[Update/TMP] tmp
This commit is contained in:
@@ -94,6 +94,7 @@ config_page:
|
||||
transcription: Transcription
|
||||
vr: VR
|
||||
others: Others
|
||||
hotkeys: Hotkeys
|
||||
advanced_settings: Advanced Settings
|
||||
supporters: Supporters
|
||||
about_vrct: About VRCT
|
||||
|
||||
@@ -1,35 +1,76 @@
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
import { register, unregisterAll, isRegistered } from "@tauri-apps/api/globalShortcut";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { store } from "@store";
|
||||
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";
|
||||
|
||||
export const GlobalHotKeyController = () => {
|
||||
const is_initialized = useRef(false);
|
||||
useEffect(() => {
|
||||
if (is_initialized.current) return;
|
||||
|
||||
const registerShortcuts = async () => {
|
||||
const shortcut = "Alt+Y";
|
||||
const is_already_registered = await isRegistered(shortcut);
|
||||
if (is_already_registered) return;
|
||||
|
||||
await register(shortcut, async () => {
|
||||
console.log("Shortcut triggered, setFocus");
|
||||
appWindow.unminimize();
|
||||
await appWindow.setFocus();
|
||||
store.text_area_ref.current?.focus();
|
||||
});
|
||||
};
|
||||
|
||||
registerShortcuts();
|
||||
is_initialized.current = true;
|
||||
|
||||
return () => {
|
||||
unregisterAll().catch((error) => {
|
||||
console.error("Failed to unregister shortcuts:", error);
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
// 修飾キーのパースを行う関数
|
||||
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();
|
||||
|
||||
useEffect(() => {
|
||||
const registerShortcuts = async () => {
|
||||
const shortcut_raw = currentHotkeys.data.toggle_active_vrct;
|
||||
console.log(shortcut_raw);
|
||||
|
||||
|
||||
if (!shortcut_raw) {
|
||||
console.warn("No hotkey defined.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 入力文字列をTauriで使える形式に変換
|
||||
const shortcut = parseHotkey(shortcut_raw);
|
||||
// const shortcut = "F9";
|
||||
|
||||
try {
|
||||
// 既存のショートカットをすべて解除
|
||||
await unregisterAll();
|
||||
|
||||
// 新しいショートカットを登録
|
||||
const isAlreadyRegistered = await isRegistered(shortcut);
|
||||
if (!isAlreadyRegistered) {
|
||||
await register(shortcut, async () => {
|
||||
console.log(`Shortcut "${shortcut}" triggered, setting focus.`);
|
||||
// const minimized = await appWindow.isMinimized();
|
||||
// if (minimized === true) {
|
||||
// appWindow.unminimize();
|
||||
// await appWindow.setFocus();
|
||||
// store.text_area_ref.current?.focus();
|
||||
// } else {
|
||||
// appWindow.minimize();
|
||||
// }
|
||||
});
|
||||
console.log(`Registered global shortcut: ${shortcut}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to register global shortcut:", error);
|
||||
}
|
||||
};
|
||||
|
||||
registerShortcuts();
|
||||
|
||||
// クリーンアップ関数でショートカットを解除
|
||||
return () => {
|
||||
unregisterAll().catch((error) => {
|
||||
console.error("Failed to unregister shortcuts:", error);
|
||||
});
|
||||
};
|
||||
}, [currentHotkeys.data.toggle_active_vrct]); // 監視対象を明確に指定
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
Others,
|
||||
AdvancedSettings,
|
||||
Vr,
|
||||
Hotkeys,
|
||||
Supporters,
|
||||
AboutVrct,
|
||||
} from "@setting_box";
|
||||
@@ -27,6 +28,8 @@ export const SettingBox = () => {
|
||||
return <Others />;
|
||||
case "vr":
|
||||
return <Vr />;
|
||||
case "hotkeys":
|
||||
return <Hotkeys />;
|
||||
case "advanced_settings":
|
||||
return <AdvancedSettings />;
|
||||
case "supporters":
|
||||
|
||||
@@ -8,16 +8,22 @@ const _Entry = forwardRef((props, ref) => {
|
||||
useImperativeHandle(ref, () => ({
|
||||
focus: () => {
|
||||
inputRef.current.focus();
|
||||
},
|
||||
blur: () => {
|
||||
inputRef.current.blur();
|
||||
}
|
||||
}));
|
||||
const input_class_names = clsx(styles.entry_input_area, {
|
||||
[styles.is_disabled]: props.is_disabled
|
||||
[styles.is_disabled]: props.is_disabled,
|
||||
});
|
||||
const input_wrapper_class_names = clsx(styles.entry_wrapper, {
|
||||
[styles.is_activated]: props.is_activated,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={styles.entry_container}>
|
||||
<div
|
||||
className={styles.entry_wrapper}
|
||||
className={input_wrapper_class_names}
|
||||
style={{width: props.width }}
|
||||
>
|
||||
<input
|
||||
@@ -25,6 +31,7 @@ const _Entry = forwardRef((props, ref) => {
|
||||
className={input_class_names}
|
||||
value={props.ui_variable === null ? "" : props.ui_variable}
|
||||
onChange={(e) => props.onChange(e)}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
background-color: var(--dark_875_color);
|
||||
border: 0.1rem solid var(--dark_750_color);
|
||||
border-radius: 0.4rem;
|
||||
&.is_activated {
|
||||
border: 0.1rem solid var(--primary_400_color);
|
||||
}
|
||||
}
|
||||
|
||||
.entry_input_area {
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
import styles from "./HotkeysEntry.module.scss";
|
||||
import { _Entry } from "../_atoms/_entry/_Entry";
|
||||
import { useState, useRef } from "react";
|
||||
|
||||
export const HotkeysEntry = (props) => {
|
||||
const [is_accepting_input, setIsAcceptingInput] = useState(false); // キー入力受付中かどうか
|
||||
const lastKeyRef = useRef(null); // 直前のキーを保持
|
||||
const [displayValue, setDisplayValue] = useState(props.value[props.hotkey_id]); // 表示用の値
|
||||
const isModifierOnlyRef = useRef(false); // 修飾キー単体かどうかのフラグ
|
||||
const entryRef = useRef(null);
|
||||
|
||||
const pressedKeys = useRef(new Set()); // 押されているキーを追跡
|
||||
const keysRef = useRef([]); // 最新のkeysを保存
|
||||
|
||||
const setHotkeys = (keys) => {
|
||||
entryRef.current.blur();
|
||||
props.setHotkeys({ [props.hotkey_id]: keys });
|
||||
};
|
||||
|
||||
const handleKeyInput = (event) => {
|
||||
const keys = [];
|
||||
const nonModifierKeys = []; // 修飾キー以外を追跡する配列
|
||||
|
||||
// 修飾キーを判定して追加(重複防止)
|
||||
if (event.ctrlKey && !keys.includes("Ctrl")) keys.push("Ctrl");
|
||||
if (event.shiftKey && !keys.includes("Shift")) keys.push("Shift");
|
||||
if (event.altKey && !keys.includes("Alt")) keys.push("Alt");
|
||||
if (event.metaKey && !keys.includes("Super")) keys.push("Super");
|
||||
|
||||
let register_key = event.key === "Meta" ? "Super" : event.key;
|
||||
// アルファベットの場合は大文字に変換
|
||||
if (/^[a-zA-Z]$/.test(register_key)) {
|
||||
register_key = register_key.toUpperCase();
|
||||
}
|
||||
|
||||
// 修飾キー以外を追加
|
||||
if (!["Control", "Shift", "Alt", "Meta"].includes(event.key)) {
|
||||
keys.push(register_key);
|
||||
nonModifierKeys.push(register_key); // 修飾キー以外のキーを追跡
|
||||
}
|
||||
|
||||
// キーが既に追跡されていない場合のみ追加
|
||||
if (!pressedKeys.current.has(register_key)) {
|
||||
pressedKeys.current.add(register_key);
|
||||
}
|
||||
|
||||
// 最新のキー構成を保存
|
||||
keysRef.current = [...keys];
|
||||
|
||||
// 表示用の値を更新
|
||||
setDisplayValue(keys.join(" + "));
|
||||
|
||||
// 修飾キー単体かどうかを更新
|
||||
isModifierOnlyRef.current = nonModifierKeys.length === 0;
|
||||
|
||||
// 修飾キーのみの場合は登録処理をスキップ
|
||||
if (isModifierOnlyRef.current) return;
|
||||
};
|
||||
|
||||
const handleKeyDown = (event) => {
|
||||
event.preventDefault(); // デフォルト動作を防ぐ
|
||||
|
||||
// 直前のキーと同じならスキップ
|
||||
const currentKey = event.key;
|
||||
if (lastKeyRef.current === currentKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastKeyRef.current = currentKey; // 今回のキーを記録
|
||||
handleKeyInput(event);
|
||||
};
|
||||
|
||||
const handleKeyUp = (event) => {
|
||||
lastKeyRef.current = null; // キーが離されたらリセット
|
||||
|
||||
// 修飾キーのみの場合でも表示は維持
|
||||
if (isModifierOnlyRef.current) {
|
||||
setDisplayValue(""); // 非修飾キーが含まれていた場合リセット
|
||||
}
|
||||
|
||||
let register_key = event.key === "Meta" ? "Super" : event.key;
|
||||
// アルファベットの場合は大文字に変換
|
||||
if (/^[a-zA-Z]$/.test(register_key)) {
|
||||
register_key = register_key.toUpperCase();
|
||||
}
|
||||
// 押されているキーから削除
|
||||
pressedKeys.current.delete(register_key);
|
||||
|
||||
// 全てのキーが放された場合
|
||||
if (pressedKeys.current.size === 0) {
|
||||
|
||||
// 修飾キーのみの場合はスキップ
|
||||
const hasNonModifierKeys = keysRef.current.some(
|
||||
(key) => !["Ctrl", "Shift", "Alt", "Super"].includes(key)
|
||||
);
|
||||
if (!hasNonModifierKeys) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 保存されたキー構成を使用して登録
|
||||
setHotkeys(keysRef.current);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleBlur = () => {
|
||||
setIsAcceptingInput(false);
|
||||
pressedKeys.current.clear();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<_Entry
|
||||
ref={entryRef}
|
||||
type="text"
|
||||
placeholder="Press hotkeys keys"
|
||||
onFocus={() => [setIsAcceptingInput(true)]}
|
||||
onBlur={handleBlur}
|
||||
onKeyDown={handleKeyDown}
|
||||
onKeyUp={handleKeyUp}
|
||||
value={displayValue} // 表示用の値を設定
|
||||
width="20rem"
|
||||
is_activated={is_accepting_input}
|
||||
readOnly
|
||||
/>
|
||||
<button
|
||||
className={styles.delete_button}
|
||||
onClick={() => [setHotkeys(null), setDisplayValue("")]}
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.delete_button {
|
||||
padding: 0.8rem;
|
||||
font-size: 1.4rem;
|
||||
background-color: var(--dark_800_color);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ export { ComputeDevice } from "./compute_device/ComputeDevice";
|
||||
export { DeeplAuthKey, OpenWebpage_DeeplAuthKey } from "./deepl_auth_key/DeeplAuthKey";
|
||||
export { DropdownMenu } from "./dropdown_menu/DropdownMenu";
|
||||
export { Entry } from "./entry/Entry";
|
||||
export { HotkeysEntry } from "./hotkeys_entry/HotkeysEntry";
|
||||
export { LabelComponent } from "./label_component/LabelComponent";
|
||||
export { RadioButton } from "./radio_button/RadioButton";
|
||||
export { SectionLabelComponent } from "./section_label_component/SectionLabelComponent";
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
Slider,
|
||||
SwitchBox,
|
||||
Entry,
|
||||
HotkeysEntry,
|
||||
RadioButton,
|
||||
OpenWebpage_DeeplAuthKey,
|
||||
DeeplAuthKey,
|
||||
@@ -75,6 +76,10 @@ export const EntryContainer = (props) => (
|
||||
<CommonContainer Component={Entry} {...props} add_break_point={false} />
|
||||
);
|
||||
|
||||
export const HotkeysEntryContainer = (props) => (
|
||||
<CommonContainer Component={HotkeysEntry} {...props} add_break_point={false} />
|
||||
);
|
||||
|
||||
export const RadioButtonContainer = (props) => (
|
||||
<CommonContainer Component={RadioButton} {...props} />
|
||||
);
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { useHotkeys } from "@logics_configs";
|
||||
import styles from "./Hotkeys.module.scss";
|
||||
import { HotkeysEntryContainer } from "../_templates/Templates";
|
||||
|
||||
export const Hotkeys = () => {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<HotkeysBoxContainer />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const HotkeysBoxContainer = () => {
|
||||
const { currentHotkeys, setHotkeys } = useHotkeys();
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<HotkeysEntryContainer
|
||||
// label={t("config_page.appearance.send_message_button_type.label")}
|
||||
label="Toggle active input box"
|
||||
hotkey_id="toggle_active_vrct"
|
||||
value={currentHotkeys.data}
|
||||
setHotkeys={setHotkeys}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
.container {
|
||||
display: flex;
|
||||
gap: 6.4rem;
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -5,5 +5,6 @@ export { Transcription } from "./transcription/Transcription";
|
||||
export { Others, VrcMicMuteSyncContainer } from "./others/Others";
|
||||
export { AdvancedSettings } from "./advanced_settings/AdvancedSettings";
|
||||
export { Vr } from "./vr/Vr";
|
||||
export { Hotkeys } from "./hotkeys/Hotkeys";
|
||||
export { AboutVrct } from "./about_vrct/AboutVrct";
|
||||
export { Supporters } from "./supporters/Supporters";
|
||||
@@ -10,6 +10,7 @@ export const SidebarSection = () => {
|
||||
<Tab tab_id="transcription" />
|
||||
<Tab tab_id="vr" />
|
||||
<Tab tab_id="others" />
|
||||
<Tab tab_id="hotkeys" />
|
||||
<Tab tab_id="advanced_settings" />
|
||||
</div>
|
||||
<div className={styles.separated_tabs_wrapper}>
|
||||
|
||||
25
src-ui/logics/configs/hotkeys/useHotkeys.js
Normal file
25
src-ui/logics/configs/hotkeys/useHotkeys.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import { useStore_Hotkeys } from "@store";
|
||||
// import { useStdoutToPython } from "@logics/useStdoutToPython";
|
||||
|
||||
export const useHotkeys = () => {
|
||||
// const { asyncStdoutToPython } = useStdoutToPython();
|
||||
const { currentHotkeys, updateHotkeys, pendingHotkeys } = useStore_Hotkeys();
|
||||
|
||||
const getHotkeys = () => {
|
||||
// pendingHotkeys();
|
||||
// asyncStdoutToPython("/get/data/osc_ip_address");
|
||||
};
|
||||
|
||||
const setHotkeys = (hotkeys) => {
|
||||
updateHotkeys(hotkeys);
|
||||
// pendingHotkeys();
|
||||
// asyncStdoutToPython("/set/data/osc_ip_address", osc_ip_address);
|
||||
};
|
||||
|
||||
return {
|
||||
currentHotkeys,
|
||||
// getHotkeys,
|
||||
updateHotkeys,
|
||||
setHotkeys,
|
||||
};
|
||||
};
|
||||
@@ -51,6 +51,8 @@ export { useOverlayShowOnlyTranslatedMessages } from "./vr/useOverlayShowOnlyTra
|
||||
export { useOverlayLargeLogSettings } from "./vr/useOverlayLargeLogSettings";
|
||||
export { useSendTextToOverlay } from "./vr/useSendTextToOverlay";
|
||||
|
||||
export { useHotkeys } from "./hotkeys/useHotkeys";
|
||||
|
||||
export { useOscIpAddress } from "./advanced_settings/useOscIpAddress";
|
||||
export { useOscPort } from "./advanced_settings/useOscPort";
|
||||
|
||||
|
||||
@@ -264,6 +264,11 @@ export const { atomInstance: Atom_EnableVrcMicMuteSync, useHook: useStore_Enable
|
||||
export const { atomInstance: Atom_EnableSendMessageToVrc, useHook: useStore_EnableSendMessageToVrc } = createAtomWithHook(true, "EnableSendMessageToVrc");
|
||||
export const { atomInstance: Atom_EnableSendReceivedMessageToVrc, useHook: useStore_EnableSendReceivedMessageToVrc } = createAtomWithHook(false, "EnableSendReceivedMessageToVrc");
|
||||
|
||||
// Hotkeys
|
||||
export const { atomInstance: Atom_Hotkeys, useHook: useStore_Hotkeys } = createAtomWithHook({
|
||||
toggle_active_vrct: null,
|
||||
}, "Hotkeys");
|
||||
|
||||
// Advanced Settings
|
||||
export const { atomInstance: Atom_OscIpAddress, useHook: useStore_OscIpAddress } = createAtomWithHook("127.0.0.1", "OscIpAddress");
|
||||
export const { atomInstance: Atom_OscPort, useHook: useStore_OscPort } = createAtomWithHook("9000", "OscPort");
|
||||
|
||||
Reference in New Issue
Block a user