Two annotation-editor asks:
- Line tool: same drag flow as the arrow, no arrowhead. New toolbar
button between arrow and rect, shortcut L.
- Text box is resizable: swapped the single-line input for a textarea
with resize:both and a drag corner. Enter still commits, Shift+Enter
inserts a newline, blur commits. Multi-line rendering steps the
fillText baseline by 1.15x the font size per line so the baked
pixels match the live layout.
The textarea swallows its own pointer events so drag-resizing the
corner doesn't leak to the canvas underneath.
Rolling every user report from the 0.6.3 rollout into one bundle:
Sounds — the Web-Audio synth palette matches the metaphor now:
- Screenshot: Polaroid shutter — sharp metallic tick + curtain-close click
chained to a film-advance whir (band-passed noise sweeping 900→400 Hz).
- Copy: printer "chika-chika-chika" — three descending percussive noise
bursts pinned by short sine ticks. Reads as a print-head sweep.
- Discard: paper crumple — three overlapping band-limited noise beds
with per-sample random-amplitude crackle, descending centre freq. No
more descending sine "boop".
- Save: soft "photo dispensing" hiss (Polaroid ejects) + a small click.
- Both the panel and editor share the design so nothing sounds different
depending on which surface fired it.
UI polish:
- Discard button now carries a trash-can icon so it's obviously not the
same as the close-sidebar X (they both used to be plain X's).
- Toolbar drawing tools centre themselves via a new .tool-cluster
wrapper (flex:1 1 auto, justify-content:center); the Copy/Save actions
stay right-anchored via margin-left:auto on their own tgroup. Fixes
the maximized-sidebar case where the drawing groups all crowded the
left with a big empty gap before Copy/Save on the right.
- Filename moves out of the topbar into a dedicated footer strip under
the canvas board, alongside a new "Open in folder" button. The topbar
is now flex-wrap:nowrap and holds only fixed-width window controls,
so a long filename can never push discard / sound / max / close onto
a second row (the filename ellipsises instead).
- "Open in folder" invokes a new "openFolder" addon message that calls
Electron's shell.showItemInFolder() to open the OS file explorer with
the specific scratch PNG highlighted (falls back to shell.openPath()
on the scratch dir when no capture is named).
Version bump so the OTA update endpoint picks it up on the next tick.
Layout reorganisation from user's diagram:
- Copy + Save move out of the topbar into the toolbar as their own
right-anchored tgroup (margin-left:auto). On wide sidebars they sit at
the end of the drawing-tool row; when the sidebar is narrow, the
actions cluster wraps as its own row on the right instead of nudging
the drawing tools around. Toolbar switches from justify-content:center
to flex-start so the leading tool groups pack left and the actions
group can find the right edge cleanly.
- Topbar right cluster is now Discard / Sound / Maximize / Close — Copy
and Save are gone from the topbar entirely so the right edge reads
as controls-only, not action-mixed.
- Discard button (X icon, danger red on hover) throws away the current
capture — silentmode.invoke("clearRecent", {name}) removes it from the
ring and unlinks the scratch file — then navigates back to the panel.
Distinct from Back, which is non-destructive.
- Close button already existed from 0.6.1 but stays in the same
right-edge position for continuity.
Bundled but not shipped separately — parent session signs and pushes.
Four user reports from the 0.6.0 rollout:
- Text tool never committed. openTextInput placed the box correctly but
a couple of Chromium quirks stopped a normal type-Enter cycle:
focus() called synchronously right after appendChild lost the race
in some builds, and the input's own mousedown / click was bubbling
through to #base and re-firing openTextInput on every subsequent
keystroke click-through, so what looked like "nothing happens" was
actually "a new empty box spawned on top of the last one every time".
Now: focus after requestAnimationFrame, contain pointerdown / mousedown
/ click inside the input so they don't bubble to the canvas, track
the font size on the state so commit uses the same one openTextInput
measured against, and preventDefault on the base pointerdown so
Chromium doesn't reset focus back to <body>.
- Toolbar wrapped one dot at a time when the sidebar was narrow (a
lonely thin/medium/thick width would jump to a second row while the
swatches stayed above it). Toolbar items are now wrapped in
`<div class="tgroup">` per category — tools / swatches / widths /
undo-redo — with `flex: 0 0 auto`, so a whole row wraps as a unit
and lands cleanly under the previous one. `gap: 10px / row-gap: 6px`
keeps the visual grouping obvious.
- No way to close the sidebar without hunting for the dock icon. Added
an X button in the top-right of both the sidebar panel and the
editor toolbar. Both wire through a new `silentmode.sidebar.close()`
preload method that calls the existing `sidebar-close` IPC.
- Tightened the pointerdown text branch so preventDefault + explicit
focus-after-frame make the click-through races impossible.
Bundled but not shipped separately — parent session signs and pushes.
Editor:
- Crop tool restored — drag to select, marquee sits with a dashed acid
border and a dimmed backdrop for the area you'll discard, then the
topbar shows Apply crop / Cancel. Applying trims #base to the rect,
resets undo (dimensions changed), and drops back into the select tool.
Enter / Esc keyboard shortcuts while a crop is pending.
- Blur / mosaic redaction tool back — drag a rectangle, editor
downsamples that region of #base to ~12-block granularity and paints
the blocks back nearest-neighbour. Commits directly (no confirm step).
- Sidebar-window controls (Back, name, Copy, Save, Sound, Maximize)
reflow: Back + name on the left, Copy + Save + Sound + Maximize on
the right so the "put the sidebar back to normal size" affordance
lives where users expect it. Toolbar's drawing tools stay centred.
- Back arrow icon swapped from a chevron to a proper flat arrow
(line + arrowhead), matching the new browser back/forward glyphs.
Sounds — modeled on Firefox Screenshots' feedback rather than beeps:
- Shutter is now a real photoshoot click: two mirror-slaps built from a
band-passed noise burst (metallic ping) plus a very short square-wave
thud each. Sounds like a camera, not a beep.
- Copy is a two-chirp "printer feed" — filtered noise burst on top of a
sine chirp per beat, staccato ascending pair. Same shape Firefox Easy
Screenshot uses for "copied to clipboard".
- Save keeps its ascending triad; Discard keeps its descending pair;
new small ascending pair for Apply crop.
Chrome:
- Browser Back / Forward chevrons (M10 3 L5 8 L10 13 — two segments
meeting at a point, no shaft) replaced with straight-arrow glyphs
(line + arrowhead). Reads as a navigation arrow, not an angle bracket.
Bundled but not shipped separately — parent session OTA-signs and pushes.
Two things the shipped 0.5.0 got wrong:
- `.empty { display: flex }` overrode the plain `[hidden]` attribute the
init flow sets after the image draws, so the "Loading capture…" pill
stayed visible on top of the finished capture. Global rule
`[hidden] { display: none !important }` takes it out.
- Tool bar was left-aligned; older editor iterations grouped the drawing
tools / swatches / widths / undo-redo in the centre of the bar, which
read better in a narrow sidebar. Adds `.toolbar { justify-content: center }`;
the topbar's back / max / sound / name / save / copy stay edge-anchored.
Version bump so the OTA update endpoint picks it up on the next tick.
Two problems the old editor kept hitting:
- __pending drain race: opening the editor a second time (refresh, back-and-
forth navigation) found the storage entry already consumed and bailed to
a blank canvas silently.
- Cross-origin img loading: editor.html at file:///…/addons/screenshot/
loading a scratch PNG at file:///…/addons-data/ counts as cross-origin
under Chromium's file-URL policy; setting crossOrigin="anonymous" made
the load fail outright.
Rebuilt editor v2:
- Load path is idempotent: silentmode.invoke("getBytes", {name}) → addon
reads the scratch file and returns a data URL. No __pending drain, no
cross-origin trickery — data: URLs are same-origin and never taint the
canvas, so getImageData / toBlob keep working.
- Two-canvas model (#base + #over, over is pointer-events:none) so live
previews don't cost a full re-composite per mousemove.
- Tools: cursor, arrow, rect, ellipse, pen, text. 6 swatches, 3 widths,
undo / redo (25-deep). Copy + Save at the top bar. Back and Maximize
buttons in the same top bar so navigation controls stay reachable when
the toolbar wraps at narrow widths.
- Keyboard: A/R/O/P/T select tool, Esc = cursor, Ctrl+Z/Shift+Z undo/redo,
Ctrl+S save, Ctrl+C copy.
- Toast surface for save/copy/error feedback.
Sidebar panel gains a direct raw-save path so the user can copy or save the
capture without entering the editor:
- Two-row actions: [Copy] [Save] on top, [Discard] [Edit] below.
- Copy uses navigator.clipboard.write(ClipboardItem); Save uses
<a download> with a Blob URL — same path Chromium's will-download
tracker already handles, so the file lands in Downloads and the chip
updates like any other save.
Inline "clear all" confirmation replaces the native confirm() — the old
system-modal opened over the tab area (out of the sidebar's visual
context) and looked like Windows 95. Now a compact red strip appears
under the Recent header with Cancel / Delete buttons.
Sounds + a sound-on/off toggle in both surfaces:
- Web Audio oscillator-synthesized (no .wav shipped): shutter click on
capture, two-tone bloop on copy, descending pair on discard/back,
ascending triad on save.
- Preference stored in silentmode.storage under "soundOn" (default on),
shared between the panel and the editor.
Simplifications:
- Dropped the addon's "arm" onMessage handler (superseded by getBytes).
- Manifest capabilities: sidebar-panel + capture-tab (no open-tab,
no toolbar-menu).
Bundled but not shipped — parent session handles the OTA sign + push.
Two follow-ups on the light-mode acid work:
1) Every hardcoded #d6ff3d and rgba(214,255,61,X) in the browser
chrome and every addon panel now goes through var(--acid), so the
light-mode BCH-teal (#0AC18E) takes effect everywhere — not just
where var(--acid) was already used. Hex-with-alpha (#d6ff3d55 etc.)
converts to color-mix(); rgba() converts to rgb(from var(--acid)…)
for the same alpha with the current --acid hue. Chromium 128+
supports both. Files touched: chrome / settings / error / home /
approval / bchwallet / siawallet / screenshot (html + css).
Screenshot editor.js's #d6ff3d stays — that's the drawing colour
swatch, not UI chrome.
2) The Theseus button (.logo) and update chip (.upchip) become dark
BCH-navy chips (#253A49 background, #F8FDFF text) in light mode.
Previously the .logo hardcoded #d6ff3d text on a bright-acid tint —
invisible on a light toolbar. The dark chip stands out and gives
the light theme a distinct accent using the BCH secondary from
whybitcoincash.com's palette.
Two related visibility fixes:
1) Light-mode --acid → #0AC18E (Bitcoin Cash brand primary, from
whybitcoincash.com's palette per user). Direct swap from #088A66
(darkened variant) to the on-brand primary. Applied across chrome /
settings / error / home / approval / messages / bchwallet /
siawallet / screenshot editor. Dark mode's #d6ff3d is unchanged.
2) User-Agent no longer includes 'theseus-navigator/<ver>' or
'Electron/<ver>' tokens. Cloudflare's WAF was returning HTTP 503
'Service Unavailable' to any request carrying those (verified
directly against whybitcoincash.com — same URL, same headers, only
the UA differed; plain Chrome UA got 200, Theseus UA got 503).
Strip both tokens via a stockChromeUA() helper called from
applyAcceptLanguage(), which whenReady already invokes at boot.
Standard practice: Brave, Vivaldi, Slack all do the same.
Verified via CDP: navigator.userAgent now reports
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/130.0.6723.191 Safari/537.36
— indistinguishable from stock Chrome.
Prior light-mode --acid was #3a5c00 (dark olive-green) — legible but
off-brand. The Bitcoin Cash brand primary is #0AC18E (a teal-leaning
green already used in bchwallet's --bch variable). Darken it a step to
#088A66 for AA text contrast on white (~5:1) while staying in the BCH
family — the light-mode accent now reads as "Bitcoin Cash green,
darkened for legibility" instead of an arbitrary olive.
Applied across every chrome page + addon panel that carries the light
override (chrome / settings / error / home / approval / messages /
bchwallet / siawallet / screenshot editor). Dark mode's #d6ff3d
untouched.
Previous #4d7300 (0.3.10) was still too light against actual white
backgrounds — several tint fills (rgba(214,255,61,X)) and unpatched
addon panels were making the effective color feel bright green. Two
fixes bundled:
1) Bump --acid in every top-level page's light-media block from
#4d7300 to #3a5c00 — same hue, ~7:1 contrast on #ffffff (was ~5.5:1).
2) Add the missing light-media --acid override to the addon panels
that were still resolving to #d6ff3d: bchwallet/panel.html,
siawallet/panel.html, and screenshot/editor.css (was #b4e024, now
#3a5c00 to match).
Dark mode unchanged. Tint fills (rgba backgrounds at low alpha) still
stay as-is — at 8–15% opacity the specific hue barely matters and the
darker foreground now dominates.