Bind all hotkeys in <App>

Rather than binding global hotkeys in the constructor and scoped hotkeys in
<App>, bind both in <App>, choosing the document or Webamp's DOM node as the
target. Hotkeys are unbound when the React root unmounts (on dispose()).

This means enableHotkeys: true now takes effect once Webamp renders rather
than when it is constructed.
This commit is contained in:
Jordan Eldredge committed 2026-10-15 10:19:57 -07:00
1 parent d223f8c7b1
commit e69098c9bf
2 files changed
+9 -14

No files matched your search

+8 -5
View File
@@ -32,7 +32,7 @@ interface Props {
filePickers: FilePicker[];
media: IMedia;
parentDomNode: HTMLElement;
scopedHotkeys: boolean;
enableHotkeys: boolean | "scoped";
onMount?: () => void;
}
@@ -44,7 +44,7 @@ export default function App({
filePickers,
onMount,
parentDomNode,
scopedHotkeys,
enableHotkeys,
}: Props) {
const closed = useTypedSelector(Selectors.getClosed);
const genWindowsInfo = useTypedSelector(Selectors.getGenWindows);
@@ -69,10 +69,13 @@ export default function App({
const dispatch = useTypedDispatch();
useEffect(() => {
if (scopedHotkeys) {
return bindHotkeys(dispatch as Dispatch, webampNode);
if (!enableHotkeys) {
return;
}
}, [scopedHotkeys, dispatch, webampNode]);
// Scoped hotkeys only see key events from within Webamp's DOM node.
const target = enableHotkeys === "scoped" ? webampNode : document;
return bindHotkeys(dispatch as Dispatch, target);
}, [enableHotkeys, dispatch, webampNode]);
useLayoutEffect(() => {
parentDomNode.appendChild(webampNode);
+1 -9
View File
@@ -20,7 +20,6 @@ import {
} from "./types";
import getStore from "./store";
import App from "./components/App";
import { bindHotkeys } from "./hotkeys";
import Media, { IMedia, IMediaClass } from "./media";
import * as Selectors from "./selectors";
import * as Actions from "./actionCreators";
@@ -83,7 +82,6 @@ class Webamp {
initialTracks,
initialSkin,
availableSkins,
enableHotkeys = false,
zIndex,
requireJSZip,
requireMusicMetadata,
@@ -214,12 +212,6 @@ class Webamp {
}
this.store.dispatch(Actions.setWindowLayout(options.windowLayout));
// Scoped hotkeys are bound by `<App />`, since they are attached to
// Webamp's DOM node.
if (enableHotkeys === true) {
this._disposable.add(bindHotkeys(this.store.dispatch));
}
}
/**
@@ -558,7 +550,7 @@ class Webamp {
<App
media={this.media}
filePickers={this.options.filePickers || []}
scopedHotkeys={this.options.enableHotkeys === "scoped"}
enableHotkeys={this.options.enableHotkeys ?? false}
onMount={onMount}
parentDomNode={contained ? node : document.body}
/>