From f74ebc1942815ca44d3640703bd3bb66023a8943 Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Fri, 13 Sep 2024 16:23:23 +0900 Subject: [PATCH] [Update] Config Page: Add Appearance Tab. Add UI Language section.(Functionally, too) --- locales/config.js | 2 +- src-ui/app/App.jsx | 16 ++++ .../setting_box/SettingBox.jsx | 4 +- .../setting_box/appearance/Appearance.jsx | 77 ++++++++++++++----- .../appearance/Appearance.module.scss | 61 +++++++++++++++ src-ui/logics/configs/useUiLanguage.js | 24 ++++++ src-ui/logics/useReceiveRoutes.js | 9 ++- src-ui/store.js | 12 ++- 8 files changed, 182 insertions(+), 23 deletions(-) create mode 100644 src-ui/app/config_page/setting_section/setting_box/appearance/Appearance.module.scss create mode 100644 src-ui/logics/configs/useUiLanguage.js diff --git a/locales/config.js b/locales/config.js index aca15b8a..0c422a21 100644 --- a/locales/config.js +++ b/locales/config.js @@ -11,7 +11,7 @@ const resources = { en: { translation: translation_en }, ja: { translation: translation_ja }, ko: { translation: translation_ko }, - zh_Hant: { translation: translation_zh_Hant }, + "zh-Hant": { translation: translation_zh_Hant }, }; i18n diff --git a/src-ui/app/App.jsx b/src-ui/app/App.jsx index c085683f..971a6cb4 100644 --- a/src-ui/app/App.jsx +++ b/src-ui/app/App.jsx @@ -10,6 +10,7 @@ export const App = () => { return (
+
@@ -25,6 +26,7 @@ import { useMicThreshold } from "@logics_configs/useMicThreshold"; import { useSpeakerThreshold } from "@logics_configs/useSpeakerThreshold"; import { useEnableAutoClearMessageBox } from "@logics_configs/useEnableAutoClearMessageBox"; import { useSendMessageButtonType } from "@logics_configs/useSendMessageButtonType"; +import { useUiLanguage } from "@logics_configs/useUiLanguage"; const StartPythonFacadeComponent = () => { const { asyncStartPython } = useStartPython(); @@ -39,12 +41,15 @@ const StartPythonFacadeComponent = () => { const { getSpeakerThreshold, getEnableAutomaticSpeakerThreshold } = useSpeakerThreshold(); const { getEnableAutoClearMessageBox } = useEnableAutoClearMessageBox(); const { getSendMessageButtonType } = useSendMessageButtonType(); + const { getUiLanguage } = useUiLanguage(); useEffect(() => { main_page.setDecorations(true); if (!hasRunRef.current) { asyncStartPython().then((result) => { + getUiLanguage(); + getSoftwareVersion(); getSelectedMicHost(); getSelectedMicDevice(); @@ -64,5 +69,16 @@ const StartPythonFacadeComponent = () => { return () => hasRunRef.current = true; }, []); + return null; +}; + +import { useTranslation } from "react-i18next"; +const UiLanguageController = () => { + const { currentUiLanguage } = useUiLanguage(); + const { i18n } = useTranslation(); + + useEffect(() => { + i18n.changeLanguage(currentUiLanguage.data); + }, [currentUiLanguage]); return null; }; \ No newline at end of file diff --git a/src-ui/app/config_page/setting_section/setting_box/SettingBox.jsx b/src-ui/app/config_page/setting_section/setting_box/SettingBox.jsx index 4e9dbb04..f293edcb 100644 --- a/src-ui/app/config_page/setting_section/setting_box/SettingBox.jsx +++ b/src-ui/app/config_page/setting_section/setting_box/SettingBox.jsx @@ -12,8 +12,8 @@ export const SettingBox = () => { return ; // case "others": // return ; - // case "appearance": - // return ; + case "appearance": + return ; // case "about_vrct": // return ; diff --git a/src-ui/app/config_page/setting_section/setting_box/appearance/Appearance.jsx b/src-ui/app/config_page/setting_section/setting_box/appearance/Appearance.jsx index 33f96c08..913c8d04 100644 --- a/src-ui/app/config_page/setting_section/setting_box/appearance/Appearance.jsx +++ b/src-ui/app/config_page/setting_section/setting_box/appearance/Appearance.jsx @@ -1,24 +1,24 @@ +import clsx from "clsx"; import { useTranslation } from "react-i18next"; -import FolderOpenSvg from "@images/folder_open.svg?react"; - +import styles from "./Appearance.module.scss"; import { useSettingBox } from "../components/useSettingBox"; import { useStore_SelectedMicDevice, useStore_MicDeviceList } from "@store"; export const Appearance = () => { const { t } = useTranslation(); - const { currentSelectedMicDevice, updateSelectedMicDevice } = useStore_SelectedMicDevice(); - const { currentMicDeviceList } = useStore_MicDeviceList(); + // const { currentSelectedMicDevice, updateSelectedMicDevice } = useStore_SelectedMicDevice(); + // const { currentMicDeviceList } = useStore_MicDeviceList(); const { DropdownMenuContainer, - SliderContainer, - CheckboxContainer, - SwitchboxContainer, - EntryContainer, - ThresholdContainer, - RadioButtonContainer, - DeeplAuthKeyContainer, - MessageFormatContainer, - WordFilterContainer, - ActionButtonContainer, + // SliderContainer, + // CheckboxContainer, + // SwitchboxContainer, + // EntryContainer, + // ThresholdContainer, + // RadioButtonContainer, + // DeeplAuthKeyContainer, + // MessageFormatContainer, + // WordFilterContainer, + // ActionButtonContainer, } = useSettingBox(); const selectFunction = (selected_data) => { @@ -34,8 +34,13 @@ export const Appearance = () => { return ( <> - - + + + + + {/* @@ -61,8 +66,44 @@ export const Appearance = () => { - {}}/> + {}}/> */} ); -}; \ No newline at end of file +}; + +import { LabelComponent } from "../components/label_component/LabelComponent"; +import { useUiLanguage } from "@logics_configs/useUiLanguage"; + +const UiLanguageContainer = () => { + const { t } = useTranslation(); + const { currentUiLanguage, setUiLanguage } = useUiLanguage(); + + const SELECTABLE_UI_LANGUAGES_DICT = { + en: "English", + ja: "日本語", + ko: "한국어", + "zh-Hant": "繁體中文", + }; + + return ( +
+ +
+ {currentUiLanguage.state === "loading" && } + {Object.entries(SELECTABLE_UI_LANGUAGES_DICT).map(([key, value]) => ( + + ))} +
+
+ ); +}; diff --git a/src-ui/app/config_page/setting_section/setting_box/appearance/Appearance.module.scss b/src-ui/app/config_page/setting_section/setting_box/appearance/Appearance.module.scss new file mode 100644 index 00000000..f2d8ab50 --- /dev/null +++ b/src-ui/app/config_page/setting_section/setting_box/appearance/Appearance.module.scss @@ -0,0 +1,61 @@ +@import "@scss_mixins"; + +.ui_language_container { + display: flex; + width: 100%; + justify-content: space-between; + align-items: center; + padding: 2rem; + border-radius: 0.6rem; +} + +.ui_language_selector_container { + display: flex; + gap: 1rem; + position: relative; +} + + + +.radio_button_wrapper { + display: flex; + align-items: center; + cursor: pointer; + gap: 0.6rem; + padding: 0.6rem 1rem; + border-radius: 0.4rem; + position: relative; + &:hover { + background-color: var(--dark_850_color); + } + &:active { + background-color: var(--dark_925_color); + } + &.is_selected { + pointer-events: none; + } +} + +input[type="radio"] { + appearance: none; + margin: 0; + width: 1.6rem; + height: 1.6rem; + border: 0.2rem solid var(--dark_600_color); + border-radius: 50%; + transition: border-color .1s ease, border-width .1s ease; + cursor: inherit; + &:checked { + border-color: var(--primary_400_color); + border-width: 0.4rem; + } +} + +.radio_button_label { + font-size: 1.4rem; + font-weight: 400; +} + +.loader { + @include loader(2rem, 0.2rem, right, -3rem); +} \ No newline at end of file diff --git a/src-ui/logics/configs/useUiLanguage.js b/src-ui/logics/configs/useUiLanguage.js new file mode 100644 index 00000000..31e134e5 --- /dev/null +++ b/src-ui/logics/configs/useUiLanguage.js @@ -0,0 +1,24 @@ +import { useStore_UiLanguage } from "@store"; +import { useStdoutToPython } from "@logics/useStdoutToPython"; + +export const useUiLanguage = () => { + const { asyncStdoutToPython } = useStdoutToPython(); + const { currentUiLanguage, updateUiLanguage } = useStore_UiLanguage(); + + const getUiLanguage = () => { + updateUiLanguage(() => new Promise(() => {})); + asyncStdoutToPython("/config/ui_language"); + }; + + const setUiLanguage = (selected_ui_language) => { + updateUiLanguage(() => new Promise(() => {})); + asyncStdoutToPython("/controller/callback_set_ui_language", selected_ui_language); + }; + + return { + currentUiLanguage, + getUiLanguage, + updateUiLanguage, + setUiLanguage, + }; +}; \ No newline at end of file diff --git a/src-ui/logics/useReceiveRoutes.js b/src-ui/logics/useReceiveRoutes.js index fe05b0b1..ce8c7665 100644 --- a/src-ui/logics/useReceiveRoutes.js +++ b/src-ui/logics/useReceiveRoutes.js @@ -15,6 +15,8 @@ import { useSpeakerThreshold } from "@logics_configs/useSpeakerThreshold"; import { useEnableAutoClearMessageBox } from "@logics_configs/useEnableAutoClearMessageBox"; import { useSendMessageButtonType } from "@logics_configs/useSendMessageButtonType"; +import { useUiLanguage } from "@logics_configs/useUiLanguage"; + export const useReceiveRoutes = () => { const { @@ -43,6 +45,8 @@ export const useReceiveRoutes = () => { const { updateEnableAutoClearMessageBox } = useEnableAutoClearMessageBox(); const { updateSendMessageButtonType } = useSendMessageButtonType(); + const { updateUiLanguage } = useUiLanguage(); + const { updateVolumeVariable_Mic, @@ -101,7 +105,10 @@ export const useReceiveRoutes = () => { "/controller/callback_disable_mic_dynamic_energy_threshold": updateEnableAutomaticMicThreshold, "/config/input_speaker_dynamic_energy_threshold": updateEnableAutomaticSpeakerThreshold, "/controller/callback_enable_speaker_dynamic_energy_threshold": updateEnableAutomaticSpeakerThreshold, - "/controller/callback_disable_speaker_dynamic_energy_threshold": updateEnableAutomaticSpeakerThreshold, + + "/config/ui_language": updateUiLanguage, + "/controller/callback_set_ui_language": updateUiLanguage, + "/controller/callback_messagebox_send": updateSentMessageLogById, "/action/transcription_send_mic_message": addSentMessageLog, diff --git a/src-ui/store.js b/src-ui/store.js index 9fc296c1..ba2127a0 100644 --- a/src-ui/store.js +++ b/src-ui/store.js @@ -96,7 +96,6 @@ const createAsyncAtomWithHook = (initialValue, base_ame) => { export const { atomInstance: Atom_SoftwareVersion, useHook: useStore_SoftwareVersion } = createAtomWithHook("-", "SoftwareVersion"); -export const { atomInstance: Atom_UiLanguage, useHook: useStore_UiLanguage } = createAtomWithHook("en", "UiLanguage"); export const { atomInstance: Atom_TranslationStatus, useHook: useStore_TranslationStatus } = createAsyncAtomWithHook(false, "TranslationStatus"); export const { atomInstance: Atom_TranscriptionSendStatus, useHook: useStore_TranscriptionSendStatus } = createAsyncAtomWithHook(false, "TranscriptionSendStatus"); export const { atomInstance: Atom_TranscriptionReceiveStatus, useHook: useStore_TranscriptionReceiveStatus } = createAsyncAtomWithHook(false, "TranscriptionReceiveStatus"); @@ -136,6 +135,17 @@ export const { atomInstance: Atom_SpeakerThreshold, useHook: useStore_SpeakerThr export const { atomInstance: Atom_EnableAutomaticMicThreshold, useHook: useStore_EnableAutomaticMicThreshold } = createAsyncAtomWithHook(false, "EnableAutomaticMicThreshold"); export const { atomInstance: Atom_EnableAutomaticSpeakerThreshold, useHook: useStore_EnableAutomaticSpeakerThreshold } = createAsyncAtomWithHook(false, "EnableAutomaticSpeakerThreshold"); + +// Appearance +export const { atomInstance: Atom_UiLanguage, useHook: useStore_UiLanguage } = createAsyncAtomWithHook("en", "UiLanguage"); + + + + + + + + export const { atomInstance: Atom_SendMessageFormat, useHook: useStore_SendMessageFormat } = createAtomWithHook({ before: "", after: "",