Commit Graph

3 Commits

Author SHA1 Message Date
Jon
baaa0b5472 Add fullscreen preview, PWA support, and connect without a button
Some checks failed
CI / build-and-deploy (push) Has been cancelled
Fullscreen: a button on the preview pane fullscreens the live view, carrying
the countdown over as an overlay - fullscreen hides the entire control column,
so without it you're left staring at a picture with no idea when the next
frame lands.

Wake lock: held from app start until you switch it off, rather than only for
the duration of a sequence. You're usually mid-setup when the display would
otherwise sleep.

PWA: manifest, icons and a service worker, so it installs to a standalone
window and runs with no network. That matters more here than for most web
apps - the camera is on a USB cable, so this is fully functional in a field
with no signal.

The worker precaches the pinned unpkg dependencies at install rather than
leaving them to the runtime cache. On a first visit the worker isn't
controlling the page yet, so the app's own imports go straight to the network
and never reach the fetch handler; without the precache it looked cached but
died offline on its imports. Our own files are network-first so a redeploy
always wins, and the version-pinned CDN files are cache-first.

Connecting: no connect button. The app reaches for the camera on load, retries
every 1.5s, and listens for USB connect events, so switching the camera on
mid-wait attaches it with no click or reload. The exception is a browser that
has never been granted access to the device: Chrome will not open its WebUSB
chooser outside a user gesture, so that case still shows a one-off prompt.
After that the permission is remembered and getDevices() finds the camera with
no interaction.

tsconfig excludes sw.js, which runs in ServiceWorkerGlobalScope and reports
every worker global as undefined when checked against the DOM lib.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QK7PKpRVoy69Fpa32R8abb
2026-08-02 09:53:24 +01:00
Jon
c293ee47d9 Fail the deploy build when a module is left off the publish list
Some checks failed
CI / build-and-deploy (push) Has been cancelled
voice.js was missing from build-dist.sh, which would have shipped a Worker
whose index.js imports a 404 - the app wouldn't have loaded at all. That's the
failure mode of an allowlist, so check it: any top-level .js not in MODULES now
fails the build instead of silently vanishing from the deploy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QK7PKpRVoy69Fpa32R8abb
2026-08-01 21:10:59 +01:00
Jon
1af4b215b2 Turn the demo app into a Canon 450D intervalometer
Some checks failed
CI / build-and-deploy (push) Has been cancelled
Replaces the gPhoto2 demo UI (live view beside the raw config tree) with a
timelapse intervalometer. The home screen carries only what changes between
runs - interval, frame count, start delay, start/stop, countdown, progress
and a log - while every camera setting moves into a settings drawer.

- intervalometer.js: schedules frames on an absolute grid (start + n *
  interval) so transfer time doesn't accumulate as drift over a long run. An
  overrun logs and fires as soon as the camera is free rather than dropping a
  frame; three consecutive failures abort.
- storage.js: frames stream into a folder via the File System Access API,
  named for capture time (20260801-172713_00001.JPG) so sorting by name is
  sorting by time. Falls back to downloads. Also holds the screen wake lock,
  since background tabs get their timers throttled.
- config-utils.js: config tree lookups, shutter speed parsing, and bulb
  capability detection (bulb toggle or Canon eosremoterelease).
- home.js: sequence controls plus a read-only exposure readout and pre-flight
  warnings when the interval can't fit the exposure and transfer.
- settings.js / index.js: app prefs and the full config tree behind a drawer.
  Config polling now only runs while that drawer is open, leaving the USB link
  to the captures during a sequence.

Live view stays up between frames and steps aside only while the shutter
fires, which is what the EOS driver requires; it recovers afterwards with
backoff instead of hammering a busy camera.

Deployed as an assets-only Cloudflare Worker. The WASM is built with pthreads
and allocates a shared WebAssembly.Memory, so _headers reproduces the COOP/COEP
pair from serve.json - without cross-origin isolation the app fails to start.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QK7PKpRVoy69Fpa32R8abb
2026-08-01 18:47:04 +01:00