Skip to content

Settings

The settings system has three layers:

  1. config/settings.ts — types and defaultSettings.
  2. settings-store.ts — runtime store with localStorage persistence and BroadcastChannel sync.
  3. simulator/SettingsPanel.tsx — UI to edit settings live.
config/settings.ts
export type Settings = {
wall: { width: number; height: number } // cm
controller: { position: Position; size: Size }
screens: Record<string, { position: Position; size: Size }>
simulator: { minWidth: number; minHeight: number } // px
}
  • position is { top, left } in percent of wall (0–100).
  • size is { width, height } in centimetres.
  • The controller sits at (50, 50) by default — centre of the wall.

defaultSettings is the fallback used the first time the app runs, or after Reset to defaults.

import { useSettings, setSettings, resetSettings } from '../settings-store'
  • useSettings() — React hook backed by useSyncExternalStore. Returns the current settings; re-renders on changes.
  • setSettings(next) — replaces the entire settings object, persists to localStorage, broadcasts to other windows.
  • resetSettings() — replaces with defaultSettings.

The store also reacts to BroadcastChannel messages from other windows, so opening the controller, three screens, and the simulator gives five contexts that stay in sync.

  • localStorage key: newsstand:settings
  • BroadcastChannel name: newsstand:settings

A shallow-merge on load tolerates partial saved data — adding new fields to Settings won’t break existing browsers.

The settings panel (simulator/SettingsPanel.tsx) slides in from the right when the user clicks Settings in the floating sim controls. It exposes:

  • Wall: width, height
  • Controller: position + size, with rotate
  • Screens: list with add / remove / rotate / edit each field
  • Footer: Reset to defaults (with confirmation dialog)

Every edit calls setSettings(...) directly — no save button — and propagates live to every open window.

  1. Add the field to the Settings type in config/settings.ts.
  2. Add a default to defaultSettings.
  3. Update settings-store.ts loadFromStorage if it needs explicit merging.
  4. Add a control to SettingsPanel.tsx.
  5. Consume via useSettings() wherever it’s needed.