@involvex/youtube-music-cli 0.0.36 → 0.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/dist/source/components/layouts/MainLayout.js +1 -1
- package/dist/source/components/search/SearchBar.js +1 -1
- package/dist/source/hooks/useKeyboard.d.ts +3 -1
- package/dist/source/hooks/useKeyboard.js +66 -4
- package/dist/youtube-music-cli.exe +0 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -124,7 +124,7 @@ function MainLayout() {
|
|
|
124
124
|
dispatch({ category: 'TOGGLE_PLAYER_MODE' });
|
|
125
125
|
}, [dispatch]);
|
|
126
126
|
// Global keyboard bindings
|
|
127
|
-
useKeyBinding(KEYBINDINGS.QUIT, handleQuit);
|
|
127
|
+
useKeyBinding(KEYBINDINGS.QUIT, handleQuit, { bypassBlock: true });
|
|
128
128
|
useKeyBinding(KEYBINDINGS.SEARCH, goToSearch);
|
|
129
129
|
useKeyBinding(KEYBINDINGS.PLAYLISTS, goToPlaylists);
|
|
130
130
|
useKeyBinding(KEYBINDINGS.PLUGINS, goToPlugins);
|
|
@@ -46,7 +46,7 @@ function SearchBar({ onInput, isActive = true }) {
|
|
|
46
46
|
}
|
|
47
47
|
}, [isActive, onInput]);
|
|
48
48
|
useKeyBinding(['tab'], cycleType);
|
|
49
|
-
useKeyBinding(['escape'], clearSearch);
|
|
49
|
+
useKeyBinding(['escape'], clearSearch, { bypassBlock: true });
|
|
50
50
|
useKeyboardBlocker(isActive);
|
|
51
51
|
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: theme.colors.secondary, paddingX: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: theme.colors.dim, children: "Type: " }), searchTypes.map((type, index) => (_jsxs(Text, { color: navState.searchType === type
|
|
52
52
|
? theme.colors.primary
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* This uses a centralized manager to avoid multiple useInput calls and memory leaks.
|
|
4
4
|
* Uses a ref-based approach to always call the latest handler without stale closures.
|
|
5
5
|
*/
|
|
6
|
-
export declare function useKeyBinding(keys: readonly string[], handler: () => void
|
|
6
|
+
export declare function useKeyBinding(keys: readonly string[], handler: () => void, options?: {
|
|
7
|
+
bypassBlock?: boolean;
|
|
8
|
+
}): void;
|
|
7
9
|
/**
|
|
8
10
|
* Global Keyboard Manager Component
|
|
9
11
|
* This should be rendered once at the root of the app.
|
|
@@ -10,16 +10,20 @@ const registry = new Set();
|
|
|
10
10
|
* This uses a centralized manager to avoid multiple useInput calls and memory leaks.
|
|
11
11
|
* Uses a ref-based approach to always call the latest handler without stale closures.
|
|
12
12
|
*/
|
|
13
|
-
export function useKeyBinding(keys, handler) {
|
|
13
|
+
export function useKeyBinding(keys, handler, options) {
|
|
14
14
|
const handlerRef = useRef(handler);
|
|
15
15
|
handlerRef.current = handler;
|
|
16
16
|
useEffect(() => {
|
|
17
|
-
const entry = {
|
|
17
|
+
const entry = {
|
|
18
|
+
keys,
|
|
19
|
+
handler: () => handlerRef.current(),
|
|
20
|
+
bypassBlock: options?.bypassBlock,
|
|
21
|
+
};
|
|
18
22
|
registry.add(entry);
|
|
19
23
|
return () => {
|
|
20
24
|
registry.delete(entry);
|
|
21
25
|
};
|
|
22
|
-
}, [keys]); // keys
|
|
26
|
+
}, [keys, options?.bypassBlock]); // keys and bypassBlock are deps; handlerRef is a stable ref
|
|
23
27
|
}
|
|
24
28
|
/**
|
|
25
29
|
* Global Keyboard Manager Component
|
|
@@ -30,7 +34,65 @@ export function KeyboardManager() {
|
|
|
30
34
|
useInput((input, key) => {
|
|
31
35
|
if (blockCount > 0) {
|
|
32
36
|
// When keyboard input is blocked (e.g., within a focused text input),
|
|
33
|
-
//
|
|
37
|
+
// check if any entry has bypassBlock flag and matches this key.
|
|
38
|
+
for (const entry of registry) {
|
|
39
|
+
if (entry.bypassBlock) {
|
|
40
|
+
for (const binding of entry.keys) {
|
|
41
|
+
const lowerBinding = binding.toLowerCase();
|
|
42
|
+
// Check for ESC key (most common bypass case)
|
|
43
|
+
if (lowerBinding === 'escape' && key.escape) {
|
|
44
|
+
entry.handler();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Handle other bypass keys
|
|
48
|
+
const isMatch = ((lowerBinding === 'return' || lowerBinding === 'enter') &&
|
|
49
|
+
key.return) ||
|
|
50
|
+
(lowerBinding === 'backspace' && key.backspace) ||
|
|
51
|
+
(lowerBinding === 'tab' && key.tab) ||
|
|
52
|
+
(lowerBinding === 'up' && key.upArrow) ||
|
|
53
|
+
(lowerBinding === 'down' && key.downArrow) ||
|
|
54
|
+
(lowerBinding === 'left' && key.leftArrow) ||
|
|
55
|
+
(lowerBinding === 'right' && key.rightArrow) ||
|
|
56
|
+
(lowerBinding === 'pageup' && key.pageUp) ||
|
|
57
|
+
(lowerBinding === 'pagedown' && key.pageDown) ||
|
|
58
|
+
(() => {
|
|
59
|
+
const parts = lowerBinding.split('+');
|
|
60
|
+
const hasCtrl = parts.includes('ctrl');
|
|
61
|
+
const hasMeta = parts.includes('meta') || parts.includes('alt');
|
|
62
|
+
const hasShift = parts.includes('shift');
|
|
63
|
+
const mainKey = parts[parts.length - 1];
|
|
64
|
+
if (hasCtrl && !key.ctrl)
|
|
65
|
+
return false;
|
|
66
|
+
if (hasMeta && !key.meta)
|
|
67
|
+
return false;
|
|
68
|
+
if (hasShift && !key.shift)
|
|
69
|
+
return false;
|
|
70
|
+
// Check arrow keys
|
|
71
|
+
if (mainKey === 'up' && key.upArrow)
|
|
72
|
+
return true;
|
|
73
|
+
if (mainKey === 'down' && key.downArrow)
|
|
74
|
+
return true;
|
|
75
|
+
if (mainKey === 'left' && key.leftArrow)
|
|
76
|
+
return true;
|
|
77
|
+
if (mainKey === 'right' && key.rightArrow)
|
|
78
|
+
return true;
|
|
79
|
+
// Handle '=' and '+'
|
|
80
|
+
if (mainKey === '=' && input === '=')
|
|
81
|
+
return true;
|
|
82
|
+
if (mainKey === '+' && input === '+')
|
|
83
|
+
return true;
|
|
84
|
+
if (mainKey === '+' && key.shift && input === '=')
|
|
85
|
+
return true;
|
|
86
|
+
return (input.toLowerCase() === mainKey && !key.ctrl && !key.meta);
|
|
87
|
+
})();
|
|
88
|
+
if (isMatch) {
|
|
89
|
+
entry.handler();
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// If no bypass handler matched, skip all global shortcuts
|
|
34
96
|
return;
|
|
35
97
|
}
|
|
36
98
|
// Debug logging for key presses (helps diagnose binding issues)
|
|
Binary file
|