Adds a "Start in fullscreen" toggle to the Settings → System panel,
addressing the desktop request in feedBack-desktop#97: users want the
app to launch fullscreen without hitting the OS hotkey every time.
The block ships hidden and is gated exactly like the App-updates block:
setupWindowOptions() only unhides + wires it when the feedBack-desktop
bridge exposes window.feedBackDesktop.window.{getStartFullscreen,
setStartFullscreen}. Web/Docker builds have no such bridge, so the
section never appears there. Persistence lives desktop-side because
only the Electron main process can read the pref at window-creation
time — core just proxies through the bridge.
The desktop bridge + launch behaviour land in a follow-up
feedBack-desktop PR.
Signed-off-by: gionnibgud <gionnibgud@gmail.com>
22 declarations, 446 lines. app.js 4,218 -> 3,772. Bodies VERBATIM.
Settings load/save, the AV-offset nudge, the default-arrangement pin, the instrument pathway,
and the app-update channel.
━━━ INTERFACE WIDTH 1, AND IT GOT THERE BY DRAWING THE BOUNDARY IN THE RIGHT PLACE ━━━
app.js calls loadSettings() and nothing else.
The first cut was NOT clean: _defaultArrangement was written from OUTSIDE the cluster, and an
imported binding is READ-ONLY, so that one write would have forced a setter or a state
container — as it did for the player (player-state.js) and the library (library-state.js).
But the writers were saveSettings and pinCurrentArrangementDefault, which ARE settings
functions. Widening the slice to include them left ZERO outside writes. Every export is now a
plain read-only import and no container is needed.
Worth naming, because I reached for a container twice before: the fix for "this binding is
written from outside" is sometimes a container, and sometimes it just means the boundary is in
the wrong place. Measure the writers before you build machinery.
━━━ handleSliderInput STAYS A HOST HOOK, DELIBERATELY ━━━
It lives in settings now (it is a settings control), but player-controls.js must NOT import it:
this module already imports player-controls (_applyMastery, _autoplayExitEnabled, …), so a
direct back-import would close a cycle. player-controls keeps reading it through the host seam,
and app.js — the root, which imports both — wires it. That is exactly what the seam is for, and
the contract test proves the wiring survived.
VERIFIED. A/B against origin/main in two browsers: the window contract, the settings screen
rendering, the AV-offset and default-arrangement controls present, and a real `input` event
dispatched on a slider — which is the path that goes through the host seam. IDENTICAL, zero
page errors.
node 1045, pytest 2425, ESLint 0 (no-cycle clean), host contract 2/2, Codex 0.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>