From e0118bb835f3661f9aee9582ca446f709f508e8a Mon Sep 17 00:00:00 2001 From: Ben Stull Date: Thu, 11 Jun 2026 14:38:50 -0700 Subject: [PATCH] feat(f9): webview segmented mode toggle + authorship legend + author CSS Co-Authored-By: Claude Opus 4.8 --- media/preview.css | 13 +++++++++++++ media/preview.ts | 37 +++++++++++++++++++++++++++++++------ src/trackChangesPreview.ts | 5 +++++ 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/media/preview.css b/media/preview.css index 655e29c..8bd5d59 100644 --- a/media/preview.css +++ b/media/preview.css @@ -51,3 +51,16 @@ del, .cw-removed { } pre.mermaid { text-align: center; background: transparent; } pre.mermaid[data-cw-error] { color: var(--vscode-errorForeground); } + +/* F9 authorship mode — inline author tints + block-level fence badges + toggle. */ +.cw-by-claude { background: var(--vscode-editorInfo-foreground, rgba(64, 120, 242, 0.18)); text-decoration: none; } +.cw-by-human { background: var(--vscode-gitDecoration-addedResourceForeground, rgba(46, 160, 67, 0.18)); text-decoration: none; } +.cw-blk.cw-by-claude, .cw-blk.cw-by-human, .cw-blk.cw-mixed { outline: 2px solid currentColor; outline-offset: 2px; background: transparent; } +.cw-seg { + background: transparent; color: var(--vscode-foreground); + border: 1px solid var(--vscode-panel-border); padding: 0 0.5em; cursor: pointer; font-size: 0.9em; +} +.cw-seg:first-child { border-radius: 3px 0 0 3px; } +.cw-seg:last-child { border-radius: 0 3px 3px 0; border-left: none; } +.cw-seg-on { background: var(--vscode-button-background); color: var(--vscode-button-foreground); } +#cw-legend .cw-swatch { padding: 0 0.4em; border-radius: 3px; } diff --git a/media/preview.ts b/media/preview.ts index 105f4a3..4492857 100644 --- a/media/preview.ts +++ b/media/preview.ts @@ -10,16 +10,29 @@ import mermaid from "mermaid"; // links it into the sealed shell via asWebviewUri). import "./preview.css"; +declare function acquireVsCodeApi(): { postMessage(m: unknown): void }; + interface RenderMessage { type: "render"; + mode: "changes" | "authorship"; html: string; - epoch: string; - summary: { added: number; removed: number; changed: number }; + epoch?: string; + summary?: { added: number; removed: number; changed: number }; + legend?: { claude: boolean; human: boolean }; } +const vscodeApi = acquireVsCodeApi(); const body = document.getElementById("cw-body")!; const header = document.getElementById("cw-epoch")!; const summary = document.getElementById("cw-summary")!; +const legend = document.getElementById("cw-legend")!; +const segs = Array.from(document.querySelectorAll(".cw-seg")); + +for (const seg of segs) { + seg.addEventListener("click", () => { + vscodeApi.postMessage({ type: "setMode", mode: seg.dataset.mode }); + }); +} function themeFor(): "dark" | "default" { return document.body.classList.contains("vscode-dark") || @@ -46,9 +59,21 @@ window.addEventListener("message", (event: MessageEvent) => { const msg = event.data; if (msg?.type !== "render") return; body.innerHTML = msg.html; - header.textContent = `Track changes since ${msg.epoch}`; - summary.innerHTML = - `+${msg.summary.added + msg.summary.changed} ` + - `−${msg.summary.removed + msg.summary.changed}`; + for (const seg of segs) seg.classList.toggle("cw-seg-on", seg.dataset.mode === msg.mode); + const authorship = msg.mode === "authorship"; + header.hidden = authorship; + summary.hidden = authorship; + legend.hidden = !authorship; + if (authorship) { + const parts: string[] = []; + if (msg.legend?.claude) parts.push('Claude'); + if (msg.legend?.human) parts.push('You'); + legend.innerHTML = parts.join(" ") || "no attribution yet"; + } else { + header.textContent = `Track changes since ${msg.epoch ?? ""}`; + summary.innerHTML = + `+${(msg.summary?.added ?? 0) + (msg.summary?.changed ?? 0)} ` + + `−${(msg.summary?.removed ?? 0) + (msg.summary?.changed ?? 0)}`; + } void renderMermaid(); }); diff --git a/src/trackChangesPreview.ts b/src/trackChangesPreview.ts index be3defe..e4fd7ba 100644 --- a/src/trackChangesPreview.ts +++ b/src/trackChangesPreview.ts @@ -193,8 +193,13 @@ export class TrackChangesPreviewController implements vscode.Disposable {
+
+ + +
Track changes +