diff --git a/src-ui/app/App.jsx b/src-ui/app/App.jsx index 60a3effe..de37abf8 100644 --- a/src-ui/app/App.jsx +++ b/src-ui/app/App.jsx @@ -6,7 +6,6 @@ import { import { KeyEventController, - GlobalHotKeyController, StartPythonController, UiLanguageController, ConfigPageCloseTriggerController, @@ -33,7 +32,6 @@ export const App = () => { return (
- diff --git a/src-ui/app/_app_controllers/ConfigPageCloseTriggerController.jsx b/src-ui/app/_app_controllers/ConfigPageCloseTriggerController.jsx index 7705aecc..c04e2a1a 100644 --- a/src-ui/app/_app_controllers/ConfigPageCloseTriggerController.jsx +++ b/src-ui/app/_app_controllers/ConfigPageCloseTriggerController.jsx @@ -9,6 +9,8 @@ import { useMainFunction, } from "@logics_main"; +import { useHotkeys } from "@logics_configs"; + import { useStore_MainFunctionsStateMemory } from "@store"; export const ConfigPageCloseTriggerController = () => { @@ -27,6 +29,8 @@ export const ConfigPageCloseTriggerController = () => { volumeCheckStop_Speaker, } = useVolume(); + const { registerShortcuts, unregisterAll } = useHotkeys(); + const memorizeLatestMainFunctionsState = () => { updateMainFunctionsStateMemory({ @@ -43,9 +47,11 @@ export const ConfigPageCloseTriggerController = () => { useEffect(() => { if (currentIsOpenedConfigPage.data === true) { // When config page is opened. memorizeLatestMainFunctionsState(); + unregisterAll(); if (currentTranscriptionSendStatus.data === true) setTranscriptionSend(false); if (currentTranscriptionReceiveStatus.data === true) setTranscriptionReceive(false); } else if (currentIsOpenedConfigPage.data === false) { // When config page is closed. + registerShortcuts(); if (currentMicThresholdCheckStatus.data === true) volumeCheckStop_Mic(); if (currentSpeakerThresholdCheckStatus.data === true) volumeCheckStop_Speaker(); restoreMainFunctionState(); diff --git a/src-ui/app/_app_controllers/GlobalHotKeyController.jsx b/src-ui/app/_app_controllers/GlobalHotKeyController.jsx deleted file mode 100644 index f21a2cee..00000000 --- a/src-ui/app/_app_controllers/GlobalHotKeyController.jsx +++ /dev/null @@ -1,99 +0,0 @@ -import { appWindow } from "@tauri-apps/api/window"; -import { register, unregisterAll, isRegistered } from "@tauri-apps/api/globalShortcut"; -import { useEffect } from "react"; -import { store } from "@store"; -import { useHotkeys } from "@logics_configs"; -import { useMainFunction } from "@logics_main"; - -// 修飾キーのパースを行う関数 -const parseHotkey = (hotkeyString) => { - const keyMap = { - Ctrl: "Control", - Alt: "Alt", - Shift: "Shift", - Meta: "Super", - }; - - // 入力文字列を分解して対応するキーを再結合 - return hotkeyString - .map((key) => keyMap[key] || key) // 修飾キーをマップし、その他はそのまま - .join("+"); -}; - -export const GlobalHotKeyController = () => { - const { currentHotkeys } = useHotkeys(); - - const { - toggleTranslation, - toggleTranscriptionSend, - toggleTranscriptionReceive, - } = useMainFunction(); - - useEffect(() => { - const registerShortcuts = async () => { - try { - // 既存のショートカットをすべて解除 - await unregisterAll(); - - const hotkeyEntries = Object.entries(currentHotkeys.data); - - for (const [actionKey, hotkeyRaw] of hotkeyEntries) { - if (!hotkeyRaw) continue; - - const shortcut = parseHotkey(hotkeyRaw); - const isAlreadyRegistered = await isRegistered(shortcut); - - if (!isAlreadyRegistered) { - await register(shortcut, async () => { - console.log(`Shortcut for "${actionKey}" triggered.`); - - switch (actionKey) { - case "toggle_vrct_visibility": { - const minimized = await appWindow.isMinimized(); - if (minimized) { - appWindow.unminimize(); - await appWindow.setFocus(); - store.text_area_ref.current?.focus(); - } else { - appWindow.minimize(); - } - break; - } - case "toggle_translation": { - toggleTranslation(); - break; - } - case "toggle_transcription_send": { - toggleTranscriptionSend(); - break; - } - case "toggle_transcription_receive": { - toggleTranscriptionReceive(); - break; - } - default: { - console.warn(`No handler defined for action: ${actionKey}`); - break; - } - } - }); - console.log(`Registered global shortcut: ${shortcut} for action: ${actionKey}`); - } - } - } catch (error) { - console.error("Failed to register global shortcuts:", error); - } - }; - - registerShortcuts(); - - // クリーンアップ関数でショートカットを解除 - return () => { - unregisterAll().catch((error) => { - console.error("Failed to unregister shortcuts:", error); - }); - }; - }, [currentHotkeys.data]); // 監視対象を全体に変更 - - return null; -}; diff --git a/src-ui/app/_app_controllers/index.js b/src-ui/app/_app_controllers/index.js index 29576a84..abe6f018 100644 --- a/src-ui/app/_app_controllers/index.js +++ b/src-ui/app/_app_controllers/index.js @@ -1,5 +1,4 @@ export { KeyEventController } from "./KeyEventController"; -export { GlobalHotKeyController } from "./GlobalHotKeyController"; export { StartPythonController } from "./StartPythonController"; export { UiLanguageController } from "./UiLanguageController"; export { ConfigPageCloseTriggerController } from "./ConfigPageCloseTriggerController"; diff --git a/src-ui/logics/configs/hotkeys/useHotkeys.js b/src-ui/logics/configs/hotkeys/useHotkeys.js index 65ea3448..358dd183 100644 --- a/src-ui/logics/configs/hotkeys/useHotkeys.js +++ b/src-ui/logics/configs/hotkeys/useHotkeys.js @@ -1,9 +1,19 @@ -import { useStore_Hotkeys } from "@store"; +import { appWindow } from "@tauri-apps/api/window"; + +import { store, useStore_Hotkeys } from "@store"; import { useStdoutToPython } from "@logics/useStdoutToPython"; +import { useMainFunction } from "@logics_main"; +import { register, unregisterAll, isRegistered } from "@tauri-apps/api/globalShortcut"; export const useHotkeys = () => { const { asyncStdoutToPython } = useStdoutToPython(); const { currentHotkeys, updateHotkeys, pendingHotkeys } = useStore_Hotkeys(); + const { + toggleTranslation, + toggleTranscriptionSend, + toggleTranscriptionReceive, + } = useMainFunction(); + const getHotkeys = () => { pendingHotkeys(); @@ -17,8 +27,58 @@ export const useHotkeys = () => { ...hotkeys, }; asyncStdoutToPython("/set/data/hotkeys", send_obj); + }; + const registerShortcuts = async () => { + try { + await unregisterAll(); + const hotkeyEntries = Object.entries(currentHotkeys.data); + + for (const [actionKey, hotkeyRaw] of hotkeyEntries) { + if (!hotkeyRaw) continue; + + const shortcut = parseHotkey(hotkeyRaw); + const isAlreadyRegistered = await isRegistered(shortcut); + + if (!isAlreadyRegistered) { + await register(shortcut, async () => { + switch (actionKey) { + case "toggle_vrct_visibility": { + const minimized = await appWindow.isMinimized(); + if (minimized) { + appWindow.unminimize(); + await appWindow.setFocus(); + store.text_area_ref.current?.focus(); + } else { + appWindow.minimize(); + } + break; + } + case "toggle_translation": { + toggleTranslation(); + break; + } + case "toggle_transcription_send": { + toggleTranscriptionSend(); + break; + } + case "toggle_transcription_receive": { + toggleTranscriptionReceive(); + break; + } + default: { + console.warn(`No handler defined for action: ${actionKey}`); + break; + } + } + }); + // console.log(`Registered global shortcut: ${shortcut} for action: ${actionKey}`); + } + } + } catch (error) { + console.error("Failed to register global shortcuts:", error); + } }; return { @@ -26,5 +86,22 @@ export const useHotkeys = () => { getHotkeys, updateHotkeys, setHotkeys, + registerShortcuts, + unregisterAll, }; +}; + +// 修飾キーのパースを行う関数 +const parseHotkey = (hotkeyString) => { + const keyMap = { + Ctrl: "Control", + Alt: "Alt", + Shift: "Shift", + Meta: "Super", + }; + + + return hotkeyString + .map((key) => keyMap[key] || key) + .join("+"); }; \ No newline at end of file