theseus/bundled-addons/screenshot/panel.html

294 lines
12 KiB
HTML
Raw Normal View History

feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Screenshot</title>
<style>
:root { color-scheme: light dark;
--bg:#0e131c; --panel:#141a24; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
--btn:#1c2432; --btn-h:#242e40; --err:#ff9081; }
@media (prefers-color-scheme: light) {
:root { --bg:#f8faff; --panel:#ffffff; --line:rgba(0,0,0,.10);
--ink:#1a1f2b; --mut:#5c6577; --dim:#8a93a5;
--btn:#f0f3fa; --btn-h:#e3e8f2; --acid:#088A66; --err:#c81f0f; }
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body { background: var(--bg); color: var(--ink);
font: 13px/1.5 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
display: flex; flex-direction: column; }
header { display: flex; align-items: center; justify-content: space-between;
padding: 10px 14px; border-bottom: 1px solid var(--line);
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
background: var(--panel); gap: 8px; }
header .t { font-weight: 600; display: flex; gap: 8px; align-items: center; min-width: 0; }
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
header .t .em { font-size: 15px; }
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
header .m { color: var(--dim); font-size: 11.5px; min-height: 15px; flex: 1; text-align: right; }
header .max {
border: 1px solid var(--line); border-radius: 6px; background: var(--btn);
color: var(--ink); cursor: pointer; padding: 4px 6px; font: inherit; line-height: 0;
}
header .max:hover { background: var(--btn-h); }
header .max svg { width: 14px; height: 14px; display: block; }
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
main { flex: 1; overflow-y: auto; padding: 12px 14px; display: flex; flex-direction: column; gap: 12px; }
.modes { display: flex; gap: 6px; }
button.mode {
flex: 1; min-width: 0;
padding: 10px 6px; border: 1px solid var(--line); border-radius: 8px;
background: var(--btn); color: var(--ink); cursor: pointer;
font: inherit; text-align: center;
display: flex; flex-direction: column; align-items: center; gap: 4px;
transition: background 120ms;
}
button.mode:hover:not(:disabled) { background: var(--btn-h); }
button.mode:disabled { opacity: .5; cursor: default; }
button.mode .em { font-size: 18px; line-height: 1; }
button.mode .lbl { font-size: 11.5px; }
.prev-wrap {
border: 1px dashed var(--line); border-radius: 8px;
background:
repeating-conic-gradient(rgba(255,255,255,.02) 0% 25%, transparent 0% 50%)
50%/16px 16px;
padding: 6px; min-height: 120px;
display: flex; align-items: center; justify-content: center;
color: var(--dim); font-size: 12px; text-align: center;
}
.prev-wrap img {
max-width: 100%; max-height: 320px; border-radius: 4px; display: block;
background: #fff;
}
.meta { color: var(--dim); font-size: 11.5px; display: flex; justify-content: space-between; gap: 8px; }
.meta .host { color: var(--mut); }
.actions { display: flex; gap: 6px; }
button.act {
flex: 1; padding: 9px 10px; border: 1px solid var(--line); border-radius: 8px;
background: var(--btn); color: var(--ink); cursor: pointer; font: inherit;
}
button.act.primary { background: var(--acid); color: #101418; border-color: transparent; font-weight: 600; }
button.act:hover:not(:disabled) { background: var(--btn-h); }
button.act.primary:hover:not(:disabled) { filter: brightness(1.05); }
button.act:disabled { opacity: .45; cursor: default; }
.status { color: var(--mut); font-size: 12px; min-height: 16px; }
.status.err { color: var(--err); }
.status.ok { color: var(--acid); }
.recent { display: none; }
.recent.on { display: block; }
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
.recent .lbl { color: var(--dim); font-size: 11.5px; text-transform: uppercase; letter-spacing: .5px; margin: 4px 0 6px; display: flex; justify-content: space-between; }
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
.recent .strip { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 4px; }
.recent .tile {
flex: 0 0 auto; width: 78px; height: 52px; border-radius: 4px;
border: 1px solid var(--line); background: var(--btn);
display: flex; align-items: center; justify-content: center;
cursor: pointer; overflow: hidden; position: relative;
}
.recent .tile img { width: 100%; height: 100%; object-fit: cover; background: #fff; }
.recent .tile:hover { border-color: var(--acid); }
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
.recent .clear { background: none; border: 0; color: var(--dim); font: inherit; cursor: pointer; text-transform: none; letter-spacing: 0; }
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
.recent .clear:hover { color: var(--err); }
</style>
</head>
<body>
<header>
<div class="t"><span class="em">📸</span> <span>Screenshot</span></div>
<div class="m" id="hdr-status"></div>
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
<button class="max" id="btn-max" title="Expand the sidebar to full window width" aria-label="Expand sidebar">
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M2 6V2h4M14 6V2h-4M2 10v4h4M14 10v4h-4"/>
</svg>
</button>
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
</header>
<main>
<div class="modes">
<button class="mode" data-mode="visible" title="Capture the visible part of the current tab">
<span class="em">🖼️</span><span class="lbl">Visible</span>
</button>
<button class="mode" data-mode="full" title="Capture the entire scrollable page">
<span class="em">📄</span><span class="lbl">Full page</span>
</button>
<button class="mode" data-mode="region" title="Drag a rectangle on the page to select what to capture">
<span class="em">✂️</span><span class="lbl">Region</span>
</button>
</div>
<div class="prev-wrap" id="prev-wrap">
<span id="prev-empty">No capture yet. Pick a mode above.</span>
<img id="prev-img" alt="" hidden>
</div>
<div class="meta">
<span id="meta-size"></span>
<span class="host" id="meta-host"></span>
</div>
<div class="actions">
<button class="act" id="btn-discard" disabled>Discard</button>
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
<button class="act primary" id="btn-edit" disabled title="Edit the capture — crop, annotate, redact, save">Edit</button>
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
</div>
<div class="status" id="status"></div>
<div class="recent" id="recent">
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
<div class="lbl"><span>Recent</span>
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
<button class="clear" id="clear-recent" title="Delete every past capture">clear all</button>
</div>
<div class="strip" id="recent-strip"></div>
</div>
</main>
<script>
const $ = (id) => document.getElementById(id);
const previewImg = $("prev-img");
const previewEmpty = $("prev-empty");
const status = $("status");
const metaSize = $("meta-size");
const metaHost = $("meta-host");
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
const btnEdit = $("btn-edit");
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
const btnDiscard = $("btn-discard");
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
const btnMax = $("btn-max");
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
const hdrStatus = $("hdr-status");
const recentBox = $("recent");
const recentStrip = $("recent-strip");
const clearBtn = $("clear-recent");
let last = null; // { name, dataUrl, width, height, host, bytes, mode }
let busy = false;
const fmt = (n) => n >= 1e6 ? (n / 1e6).toFixed(1) + " MB"
: n >= 1e3 ? (n / 1e3).toFixed(0) + " KB"
: n + " B";
function setStatus(text, cls = "") {
status.textContent = text || "";
status.className = "status" + (cls ? " " + cls : "");
}
function renderPreview() {
if (!last || !last.dataUrl) {
previewImg.hidden = true; previewImg.src = "";
previewEmpty.hidden = false;
metaSize.textContent = "—";
metaHost.textContent = "";
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
btnEdit.disabled = true;
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
btnDiscard.disabled = true;
return;
}
previewImg.src = last.dataUrl;
previewImg.hidden = false;
previewEmpty.hidden = true;
metaSize.textContent = `${last.width}×${last.height} · ${fmt(last.bytes || 0)}`;
metaHost.textContent = last.host || "";
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
btnEdit.disabled = false;
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
btnDiscard.disabled = false;
}
async function refreshRecent() {
try {
const list = await window.silentmode.invoke("listRecent", {});
if (!Array.isArray(list) || list.length === 0) {
recentBox.classList.remove("on");
recentStrip.innerHTML = "";
return;
}
recentBox.classList.add("on");
recentStrip.innerHTML = list.map((r) =>
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
`<div class="tile" data-name="${r.name.replace(/"/g,"&quot;")}" title="${r.name.replace(/"/g,"&quot;")} · ${fmt(r.bytes || 0)}"></div>`
).join("");
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
for (const tile of recentStrip.querySelectorAll(".tile")) {
const name = tile.dataset.name;
try {
const b = await window.silentmode.invoke("getBytes", { name });
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
if (b && b.dataUrl) tile.innerHTML = `<img src="${b.dataUrl}" alt="">`;
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
} catch {}
tile.addEventListener("click", async () => {
try {
const b = await window.silentmode.invoke("getBytes", { name });
if (!b) return;
last = { name: b.name, dataUrl: b.dataUrl, width: 0, height: 0, host: "", bytes: b.bytes };
const im = new Image();
im.onload = () => { last.width = im.naturalWidth; last.height = im.naturalHeight; renderPreview(); };
im.src = b.dataUrl;
renderPreview();
setStatus(`Loaded ${b.name}.`, "ok");
} catch (e) {
setStatus("Couldn't load: " + (e && e.message || e), "err");
}
});
}
} catch (e) {
console.warn("refreshRecent failed:", e);
}
}
async function doCapture(mode) {
if (busy) return;
busy = true;
hdrStatus.textContent = "capturing…";
setStatus("");
if (mode === "region") setStatus("Drag on the page. Esc to cancel.");
else if (mode === "full") setStatus("Rendering full page — this can take a moment.");
for (const b of document.querySelectorAll("button.mode")) b.disabled = true;
try {
const res = await window.silentmode.invoke("capture", { mode });
if (res && res.cancelled) {
setStatus("Region capture cancelled.");
} else if (res && res.dataUrl) {
last = res;
renderPreview();
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
setStatus("Captured. Click Edit to annotate.", "ok");
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
refreshRecent();
} else {
setStatus("Nothing captured.", "err");
}
} catch (e) {
console.warn("capture failed:", e);
setStatus(String(e && e.message || e), "err");
} finally {
busy = false;
hdrStatus.textContent = "";
for (const b of document.querySelectorAll("button.mode")) b.disabled = false;
}
}
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
async function doEdit() {
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
if (!last || !last.dataUrl || busy) return;
busy = true;
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
btnEdit.disabled = true;
hdrStatus.textContent = "opening editor…";
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
try {
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
// Arm __pending with the currently-previewed capture, then navigate
// this sidebar view to editor.html — same webContents, same preload,
// so the editor keeps talking to the add-on through silentmode.*.
const armed = await window.silentmode.invoke("arm", { name: last.name });
const name = (armed && armed.name) || last.name;
location.href = "editor.html?name=" + encodeURIComponent(name);
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
} catch (e) {
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
console.warn("arm failed:", e);
setStatus("Edit failed: " + (e && e.message || e), "err");
btnEdit.disabled = !last;
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
hdrStatus.textContent = "";
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
busy = false;
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
}
}
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
async function toggleMax() {
try { await window.silentmode.sidebar.toggleMax(); }
catch (e) { console.warn("toggleMax failed:", e); }
}
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
for (const b of document.querySelectorAll("button.mode")) {
b.addEventListener("click", () => doCapture(b.dataset.mode));
}
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
btnEdit.addEventListener("click", doEdit);
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
btnDiscard.addEventListener("click", () => { last = null; renderPreview(); setStatus(""); });
feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable User report: the sidebar preview lands correctly, but the moment the editor opens in its own tab the picture is blank. Rather than chase that class of handoff race again, put the editor in the same webContents as the panel: the sidebar view navigates panel.html ↔ editor.html in place. Same document object, same silentmode.storage surface, no cross-tab __pending transfer at all. - panel.html "Edit" button now calls silentmode.invoke("arm", …) — the add-on rewrites __pending with the currently-previewed capture's bytes, and the panel does location.href = "editor.html?name=…". Sidebar view loads the editor with the same preload; editor.js's storage-based load path pulls the pending entry out and paints. - editor.html gains a "Back" arrow (returns to panel.html) and a maximize / restore icon. - discard() now navigates to panel.html instead of closeTab() — there is no tab to close. - Manifest drops the "open-tab" capability entirely (no more full-tab editor); keeps sidebar-panel + capture-tab. Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax, onMaxChange}. main.js honours them via new sidebar-maximize / -restore / -toggle-max / -is-max IPCs, remembering the pre-maximize width so a restore drops back exactly. The sidebar drag-grip auto-exits maximize mode on any user drag, so pulling the edge always lands on the pre-max value plus/minus the delta. sidebar-preload exposes the surface; chrome.html renderer is untouched — this is a per-panel affordance. Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic / undo / redo / copy / save) unchanged. Save still goes through Chromium's <a download> path, so the file lands in Downloads and appears in the download chip like any other save. Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
btnMax.addEventListener("click", toggleMax);
feat(theseus/screenshot): 0.3.0 — sidebar-first flow with explicit "open in tab" 0.3.33 still ships blank screenshots because the whole toolbar-menu → auto- open-editor path can't be made race-free: the moment the editor tab opens it becomes the active tab, and a snapshot of the editor's own tab (before its canvas has drawn from storage) is a valid-looking 24 KB all-white PNG. The lastCapturableTabId fallback I added in a279864 catches the second click, but the first click can still land on the addon-owned tab whenever the user re-triggers before setActive has settled. Rebuild the UX so this class of race can't happen at all: - Drop the toolbar-menu capability. Manifest is back to sidebar-panel + capture-tab + open-tab, so the dock icon opens the panel (never the editor directly). No dropdown, no clip-under-tab-view issue, no auto- jump into an addon-owned tab. - Sidebar has the three capture buttons + a preview <img> + a "Open in editor tab" button. The preview is fed a data:image/png URL returned straight from api.captureTab, rendered inside the sidebar's own document — same origin, no file:// cross-directory gotcha, and the user can see immediately whether the shot actually landed. - Editor.html tab opens only on an explicit "Open in editor tab" click. The addon rewrites __pending at that moment (so the editor always sees the just-selected capture even if a prior editor tab drained the entry), then api.openTab("editor.html", {name}). The editor's storage-based load path is unchanged. - Recent captures ring is kept and now exposed as a horizontal thumbnail strip in the sidebar; clicking a tile re-previews that capture and arms "Open in editor tab" for it. Editor page (editor.html/js/css) unchanged — same crop / arrow / rect / ellipse / pen / text / mosaic-redact / undo / redo / copy / save. Bundled but not shipped — leaving version bump + deploy to the parent session.
2026-09-08 20:26:48 +02:00
clearBtn.addEventListener("click", async () => {
if (!confirm("Delete every past capture?")) return;
try { await window.silentmode.invoke("clearRecent", {}); await refreshRecent(); }
catch (e) { setStatus("Clear failed: " + (e && e.message || e), "err"); }
});
refreshRecent();
</script>
</body>
</html>