webui: bring back the old per-file diff view as an option
Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: s46e7d05cb0615b8fk
diff --git a/webui/src/web-components/sketch-diff2-view.ts b/webui/src/web-components/sketch-diff2-view.ts
index e13948e..72be0aa 100644
--- a/webui/src/web-components/sketch-diff2-view.ts
+++ b/webui/src/web-components/sketch-diff2-view.ts
@@ -158,6 +158,12 @@
@state()
private error: string | null = null;
+ @state()
+ private selectedFile: string = ""; // Empty string means "All files"
+
+ @state()
+ private viewMode: "all" | "single" = "all";
+
static styles = css`
:host {
display: flex;
@@ -189,6 +195,23 @@
gap: 12px;
}
+ .file-selector {
+ min-width: 200px;
+ padding: 8px 12px;
+ border: 1px solid var(--border-color, #ccc);
+ border-radius: 4px;
+ background-color: var(--background-color, #fff);
+ font-family: var(--font-family, system-ui, sans-serif);
+ font-size: 14px;
+ cursor: pointer;
+ }
+
+ .file-selector:focus {
+ outline: none;
+ border-color: var(--accent-color, #007acc);
+ box-shadow: 0 0 0 2px var(--accent-color-light, rgba(0, 122, 204, 0.2));
+ }
+
sketch-diff-range-picker {
flex: 1;
min-width: 400px; /* Ensure minimum width for range picker */
@@ -385,6 +408,22 @@
/* Ensure Monaco view takes full container space */
flex: 1;
}
+
+ /* Single file view styles */
+ .single-file-view {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ min-height: 0;
+ }
+
+ .single-file-monaco {
+ flex: 1;
+ width: 100%;
+ height: 100%;
+ min-height: 0;
+ }
`;
@property({ attribute: false, type: Object })
@@ -515,6 +554,7 @@
.gitService="${this.gitService}"
@range-change="${this.handleRangeChange}"
></sketch-diff-range-picker>
+ ${this.renderFileSelector()}
</div>
</div>
</div>
@@ -525,6 +565,29 @@
`;
}
+ renderFileSelector() {
+ if (this.files.length === 0) {
+ return html``;
+ }
+
+ return html`
+ <select
+ class="file-selector"
+ .value="${this.selectedFile}"
+ @change="${this.handleFileSelection}"
+ >
+ <option value="">All files (${this.files.length})</option>
+ ${this.files.map(
+ (file) => html`
+ <option value="${file.path}">
+ ${this.getFileDisplayName(file)}
+ </option>
+ `,
+ )}
+ </select>
+ `;
+ }
+
renderDiffContent() {
if (this.loading) {
return html`<div class="loading">Loading diff...</div>`;
@@ -538,6 +601,12 @@
return html`<sketch-diff-empty-view></sketch-diff-empty-view>`;
}
+ // Render single file view if a specific file is selected
+ if (this.selectedFile && this.viewMode === "single") {
+ return this.renderSingleFileView();
+ }
+
+ // Render multi-file view
return html`
<div class="multi-file-diff-container">
${this.files.map((file, index) => this.renderFileDiff(file, index))}
@@ -581,6 +650,8 @@
} else {
// No files to display - reset the view to initial state
this.selectedFilePath = "";
+ this.selectedFile = "";
+ this.viewMode = "all";
this.fileContents.clear();
this.fileExpandStates.clear();
}
@@ -591,6 +662,8 @@
this.files = [];
// Reset the view to initial state
this.selectedFilePath = "";
+ this.selectedFile = "";
+ this.viewMode = "all";
this.fileContents.clear();
this.fileExpandStates.clear();
} finally {
@@ -902,6 +975,61 @@
}
/**
+ * Handle file selection change from the dropdown
+ */
+ handleFileSelection(event: Event) {
+ const selectElement = event.target as HTMLSelectElement;
+ const selectedValue = selectElement.value;
+
+ this.selectedFile = selectedValue;
+ this.viewMode = selectedValue ? "single" : "all";
+
+ // Force re-render
+ this.requestUpdate();
+ }
+
+ /**
+ * Get display name for file in the selector
+ */
+ getFileDisplayName(file: GitDiffFile): string {
+ const status = this.getFileStatusText(file.status);
+ const pathInfo = this.getPathInfo(file);
+ return `${status}: ${pathInfo}`;
+ }
+
+ /**
+ * Render single file view with full-screen Monaco editor
+ */
+ renderSingleFileView() {
+ const selectedFileData = this.files.find(f => f.path === this.selectedFile);
+ if (!selectedFileData) {
+ return html`<div class="error">Selected file not found</div>`;
+ }
+
+ const content = this.fileContents.get(this.selectedFile);
+ if (!content) {
+ return html`<div class="loading">Loading ${this.selectedFile}...</div>`;
+ }
+
+ return html`
+ <div class="single-file-view">
+ <sketch-monaco-view
+ class="single-file-monaco"
+ .originalCode="${content.original}"
+ .modifiedCode="${content.modified}"
+ .originalFilename="${selectedFileData.path}"
+ .modifiedFilename="${selectedFileData.path}"
+ ?readOnly="${!content.editable}"
+ ?editable-right="${content.editable}"
+ @monaco-comment="${this.handleMonacoComment}"
+ @monaco-save="${this.handleMonacoSave}"
+ data-file-path="${selectedFileData.path}"
+ ></sketch-monaco-view>
+ </div>
+ `;
+ }
+
+ /**
* Refresh the diff view by reloading commits and diff data
*
* This is called when the Monaco diff tab is activated to ensure: