Wrap the fullscreen provider with the core suspender so it can read escExitFullscreen through useSettings instead of manually parsing core event payloads.
Addresses review feedback: the explanatory block comments in
FullscreenProvider (source-of-truth rationale, CoreTransport typing
note) were noise — the same context already lives in the PR
description and commit history. Copyright headers on the four new
files were carried over from the template at 2023; bumped to 2026.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The merge of development into this branch combined two incompatible
changes: development's new GamepadNavigation files (#882) imported
useFullscreen from the old 'stremio/common/useFullscreen' path, while
this branch removed that file in b7f7a3d2e and moved the hook to
'stremio/common/Fullscreen'. Webpack failed to resolve the module on
CI even though git auto-merged without conflict markers.
Update the single stale import in useHorizontalNavGamepadNavigation.tsx
to point at the new module. The new index.ts exports useFullscreen as
default, so the import shape is unchanged.
Verified locally with `pnpm build` (passes with only pre-existing
bundle-size warnings).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Resolves a conflict in src/App/App.js between the new GamepadProvider
(landed via #882 on development) and FullscreenProvider on this branch.
Both wrap parts of the app tree at the same point.
Resolution: nest as <GamepadProvider> > <ShortcutsProvider> >
<FullscreenProvider>. FullscreenProvider stays innermost so it remains
inside ShortcutsProvider — required for the onShortcut('fullscreen', ...)
subscription added in 35b100767. Both ShortcutsModal and GamepadModal
render as siblings inside FullscreenProvider. NavBar conflict
auto-merged cleanly (kept useFullscreen import, added gamepad-nav hook).
Lint and types clean on App.js, HorizontalNavBar.js, FullscreenProvider.tsx.
1. Player.js — Added optional chaining (gamepad?.on/gamepad?.off) to prevent null crash
2. GamepadProvider.tsx — Toast messages now use t('GAMEPAD_CONNECTED') / t('GAMEPAD_DISCONNECTED') via i18next, added keys to en-US.json
3. useVerticalNavGamepadNavigation.tsx — Fixed event.nativeEvent?.spatialNavigationPrevented → event.spatialNavigationPrevented (native DOM events don't have nativeEvent)
4. GamepadProvider.tsx — Changed connectedGamepads from useState to useRef to avoid rAF effect restart cycle, removed it from effect deps, simplified the enabled guard
shortcuts.json already declares fullscreen -> F, but the provider was
listening for KeyF on its own keydown handler in parallel — both fired
on every F press, with the canonical shortcuts dispatch going nowhere.
Subscribe via onShortcut('fullscreen', toggleFullscreen, ...) and drop
the KeyF branch (plus the now-unused inputFocused check). Escape stays
local because its action is gated on the escExitFullscreen profile
setting; F11 stays local because it's shell-only and not in
shortcuts.json.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous NewState listener fired on every change to the ctx model —
notifications, search history, library sync, streaming-server URL — and
each fire triggered a getState('ctx') round-trip to the worker just to
re-read escExitFullscreen.
Switch to the CoreEvent / SettingsUpdated channel (same pattern App.js
uses for interfaceLanguage/quitOnClose), reading the new value straight
from the event payload. Initial seed still uses getState('ctx') once
on mount.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>