diff --git a/src/main/index.ts b/src/main/index.ts index 3efc0a508..262f00462 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -280,12 +280,12 @@ let currentRepeatMode: PlayerRepeat = PlayerRepeat.NONE; let currentSidebarCollapsed = false; let currentShuffleEnabled = false; let playbackMenuAccelerators: MenuPlaybackState['accelerators'] = {}; -let commandPaletteOpen = false; +let inputFocused = false; -ipcMain.on('command-palette-state', (_event, opened: boolean) => { - const next = !!opened; - if (commandPaletteOpen === next) return; - commandPaletteOpen = next; +ipcMain.on('input-focus-state', (_event, focused: boolean) => { + const next = !!focused; + if (inputFocused === next) return; + inputFocused = next; if (isMacOS()) { rebuildMainMenu(); } @@ -350,7 +350,7 @@ const rebuildMainMenu = () => { if (!menuBuilder || !mainWindow) return; menuBuilder.buildMenu({ - accelerators: commandPaletteOpen ? {} : playbackMenuAccelerators, + accelerators: inputFocused ? {} : playbackMenuAccelerators, playbackStatus: currentPlaybackStatus, privateMode: currentPrivateMode, repeatMode: currentRepeatMode, diff --git a/src/preload/utils.ts b/src/preload/utils.ts index a5faded1a..ed2c3c153 100644 --- a/src/preload/utils.ts +++ b/src/preload/utils.ts @@ -54,8 +54,8 @@ const forceGarbageCollection = (): boolean => { } }; -const setCommandPaletteOpen = (opened: boolean) => { - ipcRenderer.send('command-palette-state', opened); +const setInputFocused = (focused: boolean) => { + ipcRenderer.send('input-focus-state', focused); }; const rendererOpenSettings = (cb: () => void) => { @@ -105,7 +105,7 @@ export const utils = { rendererTogglePrivateMode, rendererToggleSidebar, rendererUpdateAvailable, - setCommandPaletteOpen, + setInputFocused, startPowerSaveBlocker, stopPowerSaveBlocker, }; diff --git a/src/renderer/app.tsx b/src/renderer/app.tsx index 2e6cfd02b..ba4de9028 100644 --- a/src/renderer/app.tsx +++ b/src/renderer/app.tsx @@ -93,6 +93,7 @@ const AppEffects = () => ( + ); @@ -170,3 +171,42 @@ const NativeMenuSyncEffect = () => { return null; }; + +const InputFocusEffect = () => { + useEffect(() => { + if (!isElectron()) return; + + const handleFocusIn = (e: FocusEvent) => { + const target = e.target as Element | null; + if ( + target instanceof HTMLInputElement || + target instanceof HTMLTextAreaElement || + (target instanceof HTMLElement && target.isContentEditable) + ) { + window.api?.utils?.setInputFocused?.(true); + } + }; + + const handleFocusOut = (e: FocusEvent) => { + const related = e.relatedTarget as Element | null; + if ( + related instanceof HTMLInputElement || + related instanceof HTMLTextAreaElement || + (related instanceof HTMLElement && related.isContentEditable) + ) { + return; + } + window.api?.utils?.setInputFocused?.(false); + }; + + document.addEventListener('focusin', handleFocusIn); + document.addEventListener('focusout', handleFocusOut); + + return () => { + document.removeEventListener('focusin', handleFocusIn); + document.removeEventListener('focusout', handleFocusOut); + }; + }, []); + + return null; +}; diff --git a/src/renderer/store/app.store.ts b/src/renderer/store/app.store.ts index 2da75a668..549ced89a 100644 --- a/src/renderer/store/app.store.ts +++ b/src/renderer/store/app.store.ts @@ -201,22 +201,17 @@ export const useAppStore = createWithEqualityFn()( set((state) => { state.commandPalette.opened = false; }); - window.api?.utils?.setCommandPaletteOpen?.(false); }, open: () => { set((state) => { state.commandPalette.opened = true; }); - window.api?.utils?.setCommandPaletteOpen?.(true); }, opened: false, toggle: () => { - let nextOpened = false; set((state) => { state.commandPalette.opened = !state.commandPalette.opened; - nextOpened = state.commandPalette.opened; }); - window.api?.utils?.setCommandPaletteOpen?.(nextOpened); }, }, commandPaletteSearchSectionsExpanded: {},