ENGLISH·COURSE API
    Preparing search index...
    • Client hook: the seek step the learner chose, and the way to change it.

      Parameters

      • Optionalstorage: Storage

        Overrides the browser's localStorage; tests inject a fake here instead of monkey-patching the global

      Returns { stepSeconds: 3 | 5 | 10; choose: (seconds: 3 | 5 | 10) => void }

      The step in force, in seconds, and choose to change it

      How far a double tap on the video skips is a preference of the player's chrome, not learner data. That is why it is stored here rather than behind a domain port the way playback position, continue-watching and completion are: no use case reasons about it, and the domain would gain an interface nothing in the domain calls. What it does keep from those adapters is the learning-english: key namespace and the rule that storage which is absent, denied or corrupt degrades to the default instead of throwing.

      Two consumers in one tree need the same answer — PlaybackGestures and SeekStepMenu — and a second tab can change it underneath both. A module-level subscriber set plus useSyncExternalStore serves all three without a context provider: a write notifies the subscribers directly (the storage event does not fire in the tab that wrote), and the event covers the other tabs.

      getServerSnapshot returns the default, so the server's HTML and the hydration render agree by construction; React compares the two snapshots once hydration commits and re-renders with the stored one itself, which is why nothing here has to nudge it. For that one commit the step is the default even for a learner who chose ten seconds; no gesture can land in it, and the menu reads the same store, so it can never show a step the gestures do not have.