[Update] Add hotkeys main functions
This commit is contained in:
@@ -258,6 +258,16 @@ config_page:
|
|||||||
label: Send Received Message To VRChat
|
label: Send Received Message To VRChat
|
||||||
desc: Send the message you received from the speaker's sound to VRChat's chatbox.
|
desc: Send the message you received from the speaker's sound to VRChat's chatbox.
|
||||||
|
|
||||||
|
hotkeys:
|
||||||
|
toggle_vrct_visibility:
|
||||||
|
label: Toggle VRCT Visibility
|
||||||
|
toggle_translation:
|
||||||
|
label: Toggle Translation
|
||||||
|
toggle_transcription_send:
|
||||||
|
label: Toggle Voice2Chatbox
|
||||||
|
toggle_transcription_receive:
|
||||||
|
label: Toggle Speaker2Log
|
||||||
|
|
||||||
advanced_settings:
|
advanced_settings:
|
||||||
osc_ip_address:
|
osc_ip_address:
|
||||||
label: OSC IP Address
|
label: OSC IP Address
|
||||||
|
|||||||
@@ -255,6 +255,10 @@ config_page:
|
|||||||
label: 受信したメッセージをVRChatに送信する
|
label: 受信したメッセージをVRChatに送信する
|
||||||
desc: スピーカーから聞き取り、文字起こしされたメッセージをVRChatに送信します。
|
desc: スピーカーから聞き取り、文字起こしされたメッセージをVRChatに送信します。
|
||||||
|
|
||||||
|
hotkeys:
|
||||||
|
toggle_vrct_visibility:
|
||||||
|
label: VRCTの最小化/アクティブ化の切り替え
|
||||||
|
|
||||||
advanced_settings:
|
advanced_settings:
|
||||||
osc_ip_address:
|
osc_ip_address:
|
||||||
label: OSC IP Address
|
label: OSC IP Address
|
||||||
|
|||||||
@@ -1040,7 +1040,10 @@ class Config:
|
|||||||
self._MIC_MAX_PHRASES = 10
|
self._MIC_MAX_PHRASES = 10
|
||||||
self._MIC_WORD_FILTER = []
|
self._MIC_WORD_FILTER = []
|
||||||
self._HOTKEYS = {
|
self._HOTKEYS = {
|
||||||
"toggle_active_vrct": None,
|
"toggle_vrct_visibility": None,
|
||||||
|
"toggle_translation": None,
|
||||||
|
"toggle_transcription_send": None,
|
||||||
|
"toggle_transcription_receive": None,
|
||||||
}
|
}
|
||||||
self._MIC_AVG_LOGPROB = -0.8
|
self._MIC_AVG_LOGPROB = -0.8
|
||||||
self._MIC_NO_SPEECH_PROB = 0.6
|
self._MIC_NO_SPEECH_PROB = 0.6
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { register, unregisterAll, isRegistered } from "@tauri-apps/api/globalSho
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { store } from "@store";
|
import { store } from "@store";
|
||||||
import { useHotkeys } from "@logics_configs";
|
import { useHotkeys } from "@logics_configs";
|
||||||
|
import { useMainFunction } from "@logics_main";
|
||||||
|
|
||||||
// 修飾キーのパースを行う関数
|
// 修飾キーのパースを行う関数
|
||||||
const parseHotkey = (hotkeyString) => {
|
const parseHotkey = (hotkeyString) => {
|
||||||
@@ -22,40 +23,65 @@ const parseHotkey = (hotkeyString) => {
|
|||||||
export const GlobalHotKeyController = () => {
|
export const GlobalHotKeyController = () => {
|
||||||
const { currentHotkeys } = useHotkeys();
|
const { currentHotkeys } = useHotkeys();
|
||||||
|
|
||||||
|
const {
|
||||||
|
toggleTranslation,
|
||||||
|
toggleTranscriptionSend,
|
||||||
|
toggleTranscriptionReceive,
|
||||||
|
} = useMainFunction();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const registerShortcuts = async () => {
|
const registerShortcuts = async () => {
|
||||||
const shortcut_raw = currentHotkeys.data.toggle_active_vrct;
|
|
||||||
console.log(shortcut_raw);
|
|
||||||
|
|
||||||
if (!shortcut_raw) {
|
|
||||||
console.warn("No hotkey defined.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const shortcut = parseHotkey(shortcut_raw);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 既存のショートカットをすべて解除
|
// 既存のショートカットをすべて解除
|
||||||
await unregisterAll();
|
await unregisterAll();
|
||||||
|
|
||||||
// 新しいショートカットを登録
|
const hotkeyEntries = Object.entries(currentHotkeys.data);
|
||||||
const isAlreadyRegistered = await isRegistered(shortcut);
|
|
||||||
if (!isAlreadyRegistered) {
|
for (const [actionKey, hotkeyRaw] of hotkeyEntries) {
|
||||||
await register(shortcut, async () => {
|
if (!hotkeyRaw) continue;
|
||||||
console.log(`Shortcut "${shortcut}" triggered, setting focus.`);
|
|
||||||
const minimized = await appWindow.isMinimized();
|
const shortcut = parseHotkey(hotkeyRaw);
|
||||||
if (minimized === true) {
|
const isAlreadyRegistered = await isRegistered(shortcut);
|
||||||
appWindow.unminimize();
|
|
||||||
await appWindow.setFocus();
|
if (!isAlreadyRegistered) {
|
||||||
store.text_area_ref.current?.focus();
|
await register(shortcut, async () => {
|
||||||
} else {
|
console.log(`Shortcut for "${actionKey}" triggered.`);
|
||||||
appWindow.minimize();
|
|
||||||
}
|
switch (actionKey) {
|
||||||
});
|
case "toggle_vrct_visibility": {
|
||||||
console.log(`Registered global shortcut: ${shortcut}`);
|
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) {
|
} catch (error) {
|
||||||
console.error("Failed to register global shortcut:", error);
|
console.error("Failed to register global shortcuts:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -67,7 +93,7 @@ export const GlobalHotKeyController = () => {
|
|||||||
console.error("Failed to unregister shortcuts:", error);
|
console.error("Failed to unregister shortcuts:", error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}, [currentHotkeys.data.toggle_active_vrct]); // 監視対象を明確に指定
|
}, [currentHotkeys.data]); // 監視対象を全体に変更
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ export const HotkeysEntry = (props) => {
|
|||||||
const init_display_value = props.value[props.hotkey_id] ? props.value[props.hotkey_id].join(" + ") : "";
|
const init_display_value = props.value[props.hotkey_id] ? props.value[props.hotkey_id].join(" + ") : "";
|
||||||
setDisplayValue(init_display_value);
|
setDisplayValue(init_display_value);
|
||||||
}, []);
|
}, []);
|
||||||
console.log(props.value[props.hotkey_id]);
|
|
||||||
|
|
||||||
|
|
||||||
const updateHotkeys = (keys) => {
|
const updateHotkeys = (keys) => {
|
||||||
entryRef.current.blur();
|
entryRef.current.blur();
|
||||||
@@ -35,9 +33,10 @@ export const HotkeysEntry = (props) => {
|
|||||||
const keys = [];
|
const keys = [];
|
||||||
const nonModifierKeys = [];
|
const nonModifierKeys = [];
|
||||||
|
|
||||||
["Ctrl", "Shift", "Alt", "Super"].forEach((modKey) => {
|
["Ctrl", "Shift", "Alt", "Meta"].forEach((modKey) => {
|
||||||
if (event[`${modKey.toLowerCase()}Key`] && !keys.includes(modKey)) {
|
if (event[`${modKey.toLowerCase()}Key`] && !keys.includes(modKey)) {
|
||||||
keys.push(modKey);
|
let register_mod_key = (modKey === "Meta") ? "Super" : modKey;
|
||||||
|
keys.push(register_mod_key);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -80,6 +79,9 @@ export const HotkeysEntry = (props) => {
|
|||||||
);
|
);
|
||||||
if (hasNonModifierKeys) {
|
if (hasNonModifierKeys) {
|
||||||
updateHotkeys(keysRef.current);
|
updateHotkeys(keysRef.current);
|
||||||
|
} else {
|
||||||
|
const display_value = props.value[props.hotkey_id] ? props.value[props.hotkey_id].join(" + ") : "";
|
||||||
|
setDisplayValue(display_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useHotkeys } from "@logics_configs";
|
import { useHotkeys } from "@logics_configs";
|
||||||
import styles from "./Hotkeys.module.scss";
|
import styles from "./Hotkeys.module.scss";
|
||||||
import { HotkeysEntryContainer } from "../_templates/Templates";
|
import { HotkeysEntryContainer } from "../_templates/Templates";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
export const Hotkeys = () => {
|
export const Hotkeys = () => {
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
@@ -11,13 +11,35 @@ export const Hotkeys = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const HotkeysBoxContainer = () => {
|
const HotkeysBoxContainer = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { currentHotkeys, setHotkeys } = useHotkeys();
|
const { currentHotkeys, setHotkeys } = useHotkeys();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<HotkeysEntryContainer
|
<HotkeysEntryContainer
|
||||||
// label={t("config_page.appearance.send_message_button_type.label")}
|
label={t("config_page.hotkeys.toggle_vrct_visibility.label")}
|
||||||
label="Toggle active input box"
|
hotkey_id="toggle_vrct_visibility"
|
||||||
hotkey_id="toggle_active_vrct"
|
value={currentHotkeys.data}
|
||||||
|
state={currentHotkeys.state}
|
||||||
|
setHotkeys={setHotkeys}
|
||||||
|
/>
|
||||||
|
<HotkeysEntryContainer
|
||||||
|
label={t("config_page.hotkeys.toggle_translation.label")}
|
||||||
|
hotkey_id="toggle_translation"
|
||||||
|
value={currentHotkeys.data}
|
||||||
|
state={currentHotkeys.state}
|
||||||
|
setHotkeys={setHotkeys}
|
||||||
|
/>
|
||||||
|
<HotkeysEntryContainer
|
||||||
|
label={t("config_page.hotkeys.toggle_transcription_send.label")}
|
||||||
|
hotkey_id="toggle_transcription_send"
|
||||||
|
value={currentHotkeys.data}
|
||||||
|
state={currentHotkeys.state}
|
||||||
|
setHotkeys={setHotkeys}
|
||||||
|
/>
|
||||||
|
<HotkeysEntryContainer
|
||||||
|
label={t("config_page.hotkeys.toggle_transcription_receive.label")}
|
||||||
|
hotkey_id="toggle_transcription_receive"
|
||||||
value={currentHotkeys.data}
|
value={currentHotkeys.data}
|
||||||
state={currentHotkeys.state}
|
state={currentHotkeys.state}
|
||||||
setHotkeys={setHotkeys}
|
setHotkeys={setHotkeys}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.container {
|
.container {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 6.4rem;
|
// gap: 6.4rem;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,7 @@ export const MessageInputBox = () => {
|
|||||||
|
|
||||||
const onSubmitFunction = (e) => {
|
const onSubmitFunction = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
appWindow.minimize();
|
// appWindow.minimize();
|
||||||
|
|
||||||
if (!currentMessageInputValue.data.trim()) return updateMessageInputValue("");
|
if (!currentMessageInputValue.data.trim()) return updateMessageInputValue("");
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,13 @@ export const useHotkeys = () => {
|
|||||||
|
|
||||||
const setHotkeys = (hotkeys) => {
|
const setHotkeys = (hotkeys) => {
|
||||||
pendingHotkeys();
|
pendingHotkeys();
|
||||||
asyncStdoutToPython("/set/data/hotkeys", hotkeys);
|
const send_obj = {
|
||||||
|
...currentHotkeys.data,
|
||||||
|
...hotkeys,
|
||||||
|
};
|
||||||
|
asyncStdoutToPython("/set/data/hotkeys", send_obj);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
useStore_TranscriptionReceiveStatus,
|
useStore_TranscriptionReceiveStatus,
|
||||||
useStore_ForegroundStatus,
|
useStore_ForegroundStatus,
|
||||||
} from "@store";
|
} from "@store";
|
||||||
|
import { useCallback } from "react";
|
||||||
import { useStdoutToPython } from "@logics/useStdoutToPython";
|
import { useStdoutToPython } from "@logics/useStdoutToPython";
|
||||||
|
|
||||||
export const useMainFunction = () => {
|
export const useMainFunction = () => {
|
||||||
@@ -40,7 +40,11 @@ export const useMainFunction = () => {
|
|||||||
asyncStdoutToPython("/set/disable/translation");
|
asyncStdoutToPython("/set/disable/translation");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const toggleTranslation = () => setTranslation(!currentTranslationStatus.data);
|
const toggleTranslation = () => {
|
||||||
|
updateTranslationStatus(prev_state => {
|
||||||
|
if (prev_state.state === "ok") setTranslation(!prev_state.data);
|
||||||
|
}, { set_state: "pending" });
|
||||||
|
};
|
||||||
|
|
||||||
const setTranscriptionSend = (to_enable) => {
|
const setTranscriptionSend = (to_enable) => {
|
||||||
pendingTranscriptionSendStatus();
|
pendingTranscriptionSendStatus();
|
||||||
@@ -50,7 +54,11 @@ export const useMainFunction = () => {
|
|||||||
asyncStdoutToPython("/set/disable/transcription_send");
|
asyncStdoutToPython("/set/disable/transcription_send");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const toggleTranscriptionSend = () => setTranscriptionSend(!currentTranscriptionSendStatus.data);
|
const toggleTranscriptionSend = () => {
|
||||||
|
updateTranscriptionSendStatus(prev_state => {
|
||||||
|
if (prev_state.state === "ok") setTranscriptionSend(!prev_state.data);
|
||||||
|
}, { set_state: "pending" });
|
||||||
|
};
|
||||||
|
|
||||||
const setTranscriptionReceive = (to_enable) => {
|
const setTranscriptionReceive = (to_enable) => {
|
||||||
pendingTranscriptionReceiveStatus();
|
pendingTranscriptionReceiveStatus();
|
||||||
@@ -60,7 +68,11 @@ export const useMainFunction = () => {
|
|||||||
asyncStdoutToPython("/set/disable/transcription_receive");
|
asyncStdoutToPython("/set/disable/transcription_receive");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const toggleTranscriptionReceive = () => setTranscriptionReceive(!currentTranscriptionReceiveStatus.data);
|
const toggleTranscriptionReceive = () => {
|
||||||
|
updateTranscriptionReceiveStatus(prev_state => {
|
||||||
|
if (prev_state.state === "ok") setTranscriptionReceive(!prev_state.data);
|
||||||
|
}, { set_state: "pending" });
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const toggleForeground = () => {
|
const toggleForeground = () => {
|
||||||
|
|||||||
@@ -55,20 +55,20 @@ const createAtomWithHook = (initialValue, base_name, options) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateAtom = (payload) => {
|
const updateAtom = (payload, options = {}) => {
|
||||||
|
const { remain_state = false, set_state } = options;
|
||||||
|
|
||||||
setAtom((currentValue) => {
|
setAtom((currentValue) => {
|
||||||
if (typeof payload === "function") {
|
const new_state = set_state ?? (remain_state ? currentValue.state : "ok");
|
||||||
const updated_data = payload(currentValue);
|
|
||||||
return {
|
const updated_data = typeof payload === "function"
|
||||||
state: "ok",
|
? payload(currentValue)
|
||||||
data: updated_data,
|
: payload;
|
||||||
};
|
|
||||||
} else {
|
return {
|
||||||
return {
|
state: new_state,
|
||||||
state: "ok",
|
data: updated_data,
|
||||||
data: payload,
|
};
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -266,7 +266,10 @@ export const { atomInstance: Atom_EnableSendReceivedMessageToVrc, useHook: useSt
|
|||||||
|
|
||||||
// Hotkeys
|
// Hotkeys
|
||||||
export const { atomInstance: Atom_Hotkeys, useHook: useStore_Hotkeys } = createAtomWithHook({
|
export const { atomInstance: Atom_Hotkeys, useHook: useStore_Hotkeys } = createAtomWithHook({
|
||||||
toggle_active_vrct: null,
|
toggle_vrct_visibility: null,
|
||||||
|
toggle_translation: null,
|
||||||
|
toggle_transcription_send: null,
|
||||||
|
toggle_transcription_receive: null,
|
||||||
}, "Hotkeys");
|
}, "Hotkeys");
|
||||||
|
|
||||||
// Advanced Settings
|
// Advanced Settings
|
||||||
|
|||||||
Reference in New Issue
Block a user