feat(frontend): give a cached view a lifecycle and a keyboard owner
`index.ts` caches primary views and hides them with a class so scrollTop survives navigation. Nothing else was told: `disconnectedCallback` never fires for one, so everything written to clean up there never cleans up. The worst case was not a leak — pressing `s` on Settings skipped two albums out of the Autotag queue, and `a` on that same live handler rewrites tags on disk. - `utils/view-lifecycle.ts` is the missing half: `viewActivated` / `viewDeactivated`, with `listenWhileActive`, `intervalWhileActive` and `whileActive` torn down on the way out, and an off-screen view that does not render. `registerViewAware` gives a shared reactive controller the same treatment, because a controller cannot know whether its host is a cached view — `ContextMenuController` bound three document listeners in `hostConnected`, which for a cached host is "forever". - `services/shortcut-scope.ts` publishes the ambient scope. Resolving scope from focus alone was not enough: this app is driven with the mouse, focus sits on `<body>`, and a focus-only rule would have made the panel keys work only after a click landed inside the panel. - Global bindings yield to a focused control that owns the key — button, select, slider, checkbox, menu, grid row, or anything inside an open dialog — so the unmodified single-key bindings stop stealing Space and the arrows. - `utils/roving-grid.ts` gives a card grid one tab stop moved with the arrows, since a card per tab stop makes a library-length tab sequence.
This commit is contained in:
@@ -14,8 +14,10 @@ export interface ShortcutsState {
|
||||
|
||||
type Subscriber = () => void;
|
||||
|
||||
/** Panel scope prefixes for scope-aware lookups. */
|
||||
const PANEL_PREFIXES = ['tracklist.'] as const;
|
||||
/** Panel scope prefixes for scope-aware lookups. An action with one of
|
||||
* these prefixes is only ever resolved inside its own panel, so it can
|
||||
* reuse a key the global table also binds. */
|
||||
const PANEL_PREFIXES = ['tracklist.', 'autotag.'] as const;
|
||||
|
||||
/**
|
||||
* ShortcutsStore holds the current keyboard shortcut bindings
|
||||
|
||||
Reference in New Issue
Block a user