feat(09-02): add frontend keyboard shortcut service, store, and controller

- Create keyboard-shortcut-service.ts singleton with keydown listener
- Shadow DOM active element resolution for scope detection
- Text input suppression (only Escape passes through)
- Scope resolution: text-input > panel-specific > global
- Action dispatch to player/queue stores and Wails bindings
- Create shortcuts-store.ts with Wails persistence and event sync
- Create shortcuts-controller.ts for Lit component integration
- Export store and controller from store/index.ts
- Replace hardcoded Ctrl+F handler in index.ts with service
- Initialize service via import in frontend/index.ts
This commit is contained in:
2026-03-06 21:48:52 -05:00
parent 6285ca9dc4
commit 40d48151dd
5 changed files with 610 additions and 18 deletions
+3 -18
View File
@@ -13,7 +13,6 @@ import '@components/genres-view/genres-view.ts';
import '@components/genre-details/genre-details.ts';
import '@components/search-bar/search-bar.ts';
import '@components/track-details/track-details.ts';
import type { SearchBar } from '@components/search-bar/search-bar.ts';
import '@awesome.me/webawesome/dist/styles/themes/default.css';
import '@awesome.me/webawesome/dist/components/icon/icon.js';
import { setBasePath } from '@awesome.me/webawesome/dist/webawesome.js';
@@ -24,6 +23,9 @@ import * as Queue from '@go/queue/Queue';
// Importing the theme store triggers initialization: it fetches the saved
// theme from the backend and applies CSS custom properties to :root.
import '@store/theme-store';
// Importing the keyboard shortcut service triggers initialization:
// registers the document keydown listener for global shortcuts.
import './src/services/keyboard-shortcut-service';
import {
hasTrackPayload,
getDragPayload,
@@ -150,23 +152,6 @@ if (queueButton && queuePanel) {
);
}
// ---------------------------------------------------------------
// Ctrl+F to focus the search bar
// ---------------------------------------------------------------
document.addEventListener('keydown', (e: KeyboardEvent) => {
if ((e.ctrlKey || e.metaKey) && e.key === 'f') {
const bar = document.querySelector(
'search-bar',
) as SearchBar | null;
if (bar && !bar.hasAttribute('hidden')) {
e.preventDefault();
bar.focusInput();
}
}
});
// ---------------------------------------------------------------
// Request current state from the backend
// ---------------------------------------------------------------