Commit graph

8 commits

Author SHA1 Message Date
Local Dev
bd6aab02fe feat(theseus): profile at %APPDATA%\Theseus, extensions under extensions\
The profile folder was Electron's default from the product name
("Theseus Navigator") and add-ons lived in addons\ under it. Now:

  %APPDATA%\Theseus\extensions\          installed extensions
  %APPDATA%\Theseus\extensions-data\     per-extension storage + scratch
  %APPDATA%\Theseus\extensions-backups\  replaced copies
  %APPDATA%\Theseus\extensions-staged\   staged updates

Both moves are one-time migrations on the first start that finds the old
layout: the profile folder is renamed (same volume, instant) or copied
when a rename is refused, with the old folder left in place in that case;
the four sub-folders are renamed before the extension host first reads
them. Nothing is deleted. THESEUS_USER_DATA still overrides everything.

The host now hands each extension its data folder as api.dataDir; the
Screenshot and PDF editor add-ons used to rebuild the old path from their
own folder for scratch files (so they recreated addons-data\ after the
move) and now use the field, with versions bumped so the bundles reseed.
2026-09-21 01:55:25 +02:00
Local Dev
7b8539fb8d feat(theseus/screenshot): 0.6.4 — Polaroid sounds, trash icon, centred cluster, filename footer + open-in-folder
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.
2026-09-09 22:34:47 +02:00
Local Dev
81d276f655 feat(theseus/screenshot): 0.5.0 — sidebar-first editor, direct save/copy, sounds
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.
2026-09-09 00:56:41 +02:00
Local Dev
523832cd72 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
Local Dev
4c01ec7b7d 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
Local Dev
2e42783dfe fix(theseus/screenshot): 0.2.4 — deliver capture via addon storage, not a cross-origin file://
Blank editor + broken buttons root cause: index.js was writing the
capture to <userData>/addons-data/screenshot-scratch/<name>.png and
passing "?src=file://<that path>" to editor.html. The editor lives at
file:///<userData>/addons/screenshot/editor.html — different directory
tree under file://. Chromium's file:// origin policy treats those as
different origins and quietly refuses the <img> load, so init()'s
loadImage() rejects, the canvas never gets an image, and every tool
after that operates on a still-empty 300×150 default canvas — the
tools appear to work but produce no visible output because the base
image never landed. The sidebar version we replaced set
`previewImg.src = dataUrl` (a base64 data URL) directly, which has no
origin and just worked; the tab version regressed by adding the file
hop.

Fix keeps the scratch file for the recent-captures ring but hands
the raw capture through the add-on's per-add-on kv store
(`__pending` key). Same store, same origin scoping, no
cross-directory read: index.js writes via api.storage.set from main;
editor.js reads via window.silentmode.storage.get through the tab
preload (packaged since 0.3.27). Fallback path retained for
"openRecent" callers still passing ?src=… — those will need their
own fix in a follow-up.

Bumped to 0.2.4 and signed for the OTA endpoint — first real
independent add-on ship: no Theseus release needed to fix this,
0.3.27 installs pick up 0.2.4 via the boot-time signed-update poll.
2026-09-08 12:57:46 +02:00
Local Dev
15694195d6 feat(theseus/screenshot): full-tab editor + toolbar-menu + open-tab capabilities
Reworks the screenshot addon into the flow the user asked for: the
dock icon opens a small dropdown menu (Visible viewport / Full page /
Region…) instead of the sidebar picker, and each capture opens a
full browser tab hosting an editor.

Two new addon-host capabilities land alongside:
- toolbar-menu: the addon declares an icon + item list in its manifest;
  the chrome dock renders a button that, on click, opens a small menu
  and dispatches the selection to the addon via addon-menu-select IPC.
- open-tab: api.openTab(path) opens a browser tab whose URL is the
  addon's local file. Origin-gated per addon; the editor uses a
  dedicated addon-tab-preload for its main → renderer bridge.

Editor page (editor.html/js/css):
- Crop, arrow, rectangle, circle, freehand pen, text, blur
- Colour swatches (red / yellow / acid / white / black), 3 stroke widths
- Undo/redo command stack, zoom controls
- Save PNG (goes through the download pipeline, chip picks it up)
- Copy to clipboard via ClipboardItem
2026-09-07 00:56:57 +02:00
Local Dev
5642959eca feat(theseus/screenshot): bundled screenshot add-on (visible / full page / region)
New capture-tab capability on the addon-host, and the screenshot add-on
uses it to expose three modes in a sidebar launcher panel:

- Visible viewport: Electron's WebContents.capturePage() on the active tab
- Full scrollable page: temp-resize the tab view to document.scrollHeight,
  capturePage, restore
- Region: preload overlays a translucent selection div, tracks mousedown /
  move / up, sends the rect back; main takes the visible capture and
  crops via nativeImage.crop({x,y,width,height})

Saves land in the user's Downloads folder via session.downloadURL — same
pipeline as any file download, so the download chip picks them up.
Filename: theseus-screenshot-<host>-<ISO date>.png. JPEG option for
smaller files.

A follow-up task (task_b9608dc6) reworks this to open captures in a
full-tab editor with crop / draw / annotate / undo / copy-to-clipboard
instead of the current bare launcher.
2026-09-07 00:18:48 +02:00