From 70e411daf5dfe074da24ee810076375f6337b9e7 Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:44:31 +0900 Subject: [PATCH] [Update] Add Starting Up Animation and downloading models progress display. Backend: Move the init progressed position 4 to a little bit earlier. --- src-python/config.json | 167 ++++++++++++++++++ src-python/webui_controller.py | 4 +- src-tauri/tauri.conf.json | 4 +- src-ui/app/App.jsx | 2 - .../app/splash_component/SplashComponent.jsx | 47 +---- .../DownloadModelsContainer.jsx | 69 ++++++++ .../DownloadModelsContainer.module.scss | 63 +++++++ .../StartUpProgressContainer.jsx | 39 ++++ .../StartUpProgressContainer.module.scss | 100 +++++++++++ src-ui/assets/VRCT_now_downloading.png | Bin 0 -> 8738 bytes ...rchat_chatbox_trasnlator_transcription.png | Bin 0 -> 10259 bytes src-ui/assets/vrct_starting_up.png | Bin 0 -> 4106 bytes src-ui/logics/common/index.js | 1 + src-ui/logics/common/useInitProgress.js | 10 ++ src-ui/logics/useReceiveRoutes.js | 9 +- src-ui/store.js | 1 + 16 files changed, 465 insertions(+), 51 deletions(-) create mode 100644 src-python/config.json create mode 100644 src-ui/app/splash_component/download_models_container/DownloadModelsContainer.jsx create mode 100644 src-ui/app/splash_component/download_models_container/DownloadModelsContainer.module.scss create mode 100644 src-ui/app/splash_component/start_up_progress_container/StartUpProgressContainer.jsx create mode 100644 src-ui/app/splash_component/start_up_progress_container/StartUpProgressContainer.module.scss create mode 100644 src-ui/assets/VRCT_now_downloading.png create mode 100644 src-ui/assets/vrchat_chatbox_trasnlator_transcription.png create mode 100644 src-ui/assets/vrct_starting_up.png create mode 100644 src-ui/logics/common/useInitProgress.js diff --git a/src-python/config.json b/src-python/config.json new file mode 100644 index 00000000..9b1bcff9 --- /dev/null +++ b/src-python/config.json @@ -0,0 +1,167 @@ +{ + "SELECTED_TAB_NO": "1", + "SELECTED_TRANSLATION_ENGINES": { + "1": "CTranslate2", + "2": "CTranslate2", + "3": "CTranslate2" + }, + "SELECTED_YOUR_LANGUAGES": { + "1": { + "primary": { + "language": "Japanese", + "country": "Japan" + } + }, + "2": { + "primary": { + "language": "Japanese", + "country": "Japan" + } + }, + "3": { + "primary": { + "language": "Japanese", + "country": "Japan" + } + } + }, + "SELECTED_TARGET_LANGUAGES": { + "1": { + "primary": { + "language": "English", + "country": "United States" + }, + "secondary": { + "language": "English", + "country": "United States" + }, + "tertiary": { + "language": "English", + "country": "United States" + } + }, + "2": { + "primary": { + "language": "English", + "country": "United States" + }, + "secondary": { + "language": "English", + "country": "United States" + }, + "tertiary": { + "language": "English", + "country": "United States" + } + }, + "3": { + "primary": { + "language": "English", + "country": "United States" + }, + "secondary": { + "language": "English", + "country": "United States" + }, + "tertiary": { + "language": "English", + "country": "United States" + } + } + }, + "SELECTED_TRANSCRIPTION_ENGINE": "Google", + "MULTI_LANGUAGE_TRANSLATION": false, + "CONVERT_MESSAGE_TO_ROMAJI": false, + "CONVERT_MESSAGE_TO_HIRAGANA": false, + "MAIN_WINDOW_SIDEBAR_COMPACT_MODE": false, + "TRANSPARENCY": 100, + "UI_SCALING": 100, + "TEXTBOX_UI_SCALING": 100, + "MESSAGE_BOX_RATIO": 10, + "FONT_FAMILY": "Yu Gothic UI", + "UI_LANGUAGE": "en", + "RESTORE_MAIN_WINDOW_GEOMETRY": true, + "MAIN_WINDOW_GEOMETRY": { + "x_pos": 0, + "y_pos": 0, + "width": 870, + "height": 654 + }, + "AUTO_MIC_SELECT": true, + "SELECTED_MIC_HOST": "MME", + "SELECTED_MIC_DEVICE": "Headset Microphone (Oculus Virt", + "MIC_THRESHOLD": 300, + "MIC_AUTOMATIC_THRESHOLD": false, + "MIC_RECORD_TIMEOUT": 3, + "MIC_PHRASE_TIMEOUT": 3, + "MIC_MAX_PHRASES": 10, + "MIC_WORD_FILTER": [], + "MIC_AVG_LOGPROB": -0.8, + "MIC_NO_SPEECH_PROB": 0.6, + "AUTO_SPEAKER_SELECT": true, + "SELECTED_SPEAKER_DEVICE": "ヘッドホン (Oculus Virtual Audio Device) [Loopback]", + "SPEAKER_THRESHOLD": 300, + "SPEAKER_AUTOMATIC_THRESHOLD": false, + "SPEAKER_RECORD_TIMEOUT": 3, + "SPEAKER_PHRASE_TIMEOUT": 3, + "SPEAKER_MAX_PHRASES": 10, + "SPEAKER_AVG_LOGPROB": -0.8, + "SPEAKER_NO_SPEECH_PROB": 0.6, + "OSC_IP_ADDRESS": "127.0.0.1", + "OSC_PORT": 9000, + "AUTH_KEYS": { + "DeepL_API": null + }, + "USE_EXCLUDE_WORDS": true, + "SELECTED_TRANSLATION_COMPUTE_DEVICE": { + "device": "cpu", + "device_index": 0, + "device_name": "cpu" + }, + "SELECTED_TRANSCRIPTION_COMPUTE_DEVICE": { + "device": "cpu", + "device_index": 0, + "device_name": "cpu" + }, + "CTRANSLATE2_WEIGHT_TYPE": "small", + "WHISPER_WEIGHT_TYPE": "base", + "AUTO_CLEAR_MESSAGE_BOX": true, + "SEND_ONLY_TRANSLATED_MESSAGES": false, + "SEND_MESSAGE_BUTTON_TYPE": "show", + "OVERLAY_SMALL_LOG": false, + "OVERLAY_SMALL_LOG_SETTINGS": { + "x_pos": 0.0, + "y_pos": 0.0, + "z_pos": 0.0, + "x_rotation": 0.0, + "y_rotation": 0.0, + "z_rotation": 0.0, + "display_duration": 5, + "fadeout_duration": 2, + "opacity": 1.0, + "ui_scaling": 1.0, + "tracker": "HMD" + }, + "OVERLAY_LARGE_LOG": false, + "OVERLAY_LARGE_LOG_SETTINGS": { + "x_pos": 0.0, + "y_pos": 0.0, + "z_pos": 0.0, + "x_rotation": 0.0, + "y_rotation": 0.0, + "z_rotation": 0.0, + "display_duration": 5, + "fadeout_duration": 2, + "opacity": 1.0, + "ui_scaling": 0.015625, + "tracker": "LeftHand" + }, + "SEND_MESSAGE_TO_VRC": true, + "SEND_MESSAGE_FORMAT": "[message]", + "SEND_MESSAGE_FORMAT_WITH_T": "[message]([translation])", + "RECEIVED_MESSAGE_FORMAT": "[message]", + "RECEIVED_MESSAGE_FORMAT_WITH_T": "[message]([translation])", + "SEND_RECEIVED_MESSAGE_TO_VRC": false, + "LOGGER_FEATURE": false, + "VRC_MIC_MUTE_SYNC": false +} \ No newline at end of file diff --git a/src-python/webui_controller.py b/src-python/webui_controller.py index 139663e4..a1070aa0 100644 --- a/src-python/webui_controller.py +++ b/src-python/webui_controller.py @@ -1750,6 +1750,8 @@ class Controller: if config.LOGGER_FEATURE is True: model.startLogger() + self.initializationProgress(4) + # init OSC receive printLog("Init OSC Receive") model.startReceiveOSC() @@ -1772,8 +1774,6 @@ class Controller: if (config.OVERLAY_SMALL_LOG is True or config.OVERLAY_LARGE_LOG is True): model.startOverlay() - self.initializationProgress(4) - printLog("Update settings") self.updateConfigSettings() diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index f48c4e72..ab1e6f0a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -40,8 +40,8 @@ { "title": "VRCT", "center": true, - "width": 400, - "height": 400, + "width": 450, + "height": 220, "minWidth": 400, "minHeight": 200, "transparent": true, diff --git a/src-ui/app/App.jsx b/src-ui/app/App.jsx index dfabbafc..46edc86a 100644 --- a/src-ui/app/App.jsx +++ b/src-ui/app/App.jsx @@ -88,8 +88,6 @@ const UiLanguageController = () => { const { i18n } = useTranslation(); useEffect(() => { - console.log(currentUiLanguage.data); - i18n.changeLanguage(currentUiLanguage.data); }, [currentUiLanguage.data]); return null; diff --git a/src-ui/app/splash_component/SplashComponent.jsx b/src-ui/app/splash_component/SplashComponent.jsx index 6a665423..6de17662 100644 --- a/src-ui/app/splash_component/SplashComponent.jsx +++ b/src-ui/app/splash_component/SplashComponent.jsx @@ -1,51 +1,12 @@ -import { useState, useEffect } from "react"; - -import CircularProgress from '@mui/material/CircularProgress'; import styles from "./SplashComponent.module.scss"; -import { - useCTranslate2WeightTypeStatus, - useWhisperWeightTypeStatus, -} from "@logics_configs"; +import { StartUpProgressContainer } from "./start_up_progress_container/StartUpProgressContainer/"; +import { DownloadModelsContainer } from "./download_models_container/DownloadModelsContainer/"; export const SplashComponent = () => { - const { currentCTranslate2WeightTypeStatus } = useCTranslate2WeightTypeStatus(); - const { currentWhisperWeightTypeStatus } = useWhisperWeightTypeStatus(); - - const [circular_color, setCircularColor] = useState(""); - useEffect(() => { - const circular_color = getComputedStyle(document.documentElement).getPropertyValue("--primary_300_color"); - setCircularColor(circular_color.trim()); - }, []); - - console.log(currentCTranslate2WeightTypeStatus); - const c_translate_2 = currentCTranslate2WeightTypeStatus.data.find(d => d.id === "small"); - const whisper = currentWhisperWeightTypeStatus.data.find(d => d.id === "base"); - console.log(c_translate_2, whisper); - - - return (
- - - -
- ); -}; - -const DownloadModelsProgress = (props) => { - if (props.progress === null) return null; - const circular_progress = Math.floor(props.progress / 10) * 10; - - return( -
- -

{`${Math.round(props.progress)}%`}

+ +
); }; \ No newline at end of file diff --git a/src-ui/app/splash_component/download_models_container/DownloadModelsContainer.jsx b/src-ui/app/splash_component/download_models_container/DownloadModelsContainer.jsx new file mode 100644 index 00000000..9e3d8e67 --- /dev/null +++ b/src-ui/app/splash_component/download_models_container/DownloadModelsContainer.jsx @@ -0,0 +1,69 @@ +import styles from "./DownloadModelsContainer.module.scss"; +import vrct_logo_for_dark_mode from "@images/vrct_logo_for_dark_mode.png"; +import vrct_now_downloading from "@images/VRCT_now_downloading.png"; + +import { + useCTranslate2WeightTypeStatus, + useWhisperWeightTypeStatus, +} from "@logics_configs"; + +export const DownloadModelsContainer = () => { + const { currentCTranslate2WeightTypeStatus } = useCTranslate2WeightTypeStatus(); + const { currentWhisperWeightTypeStatus } = useWhisperWeightTypeStatus(); + + const c_translate_2 = currentCTranslate2WeightTypeStatus.data.find(d => d.id === "small"); + const whisper = currentWhisperWeightTypeStatus.data.find(d => d.id === "base"); + + if (c_translate_2.progress === null && whisper.progress === null) return null; + + return ( +
+
+ + +
+
+ + +
+
+ ); +}; + + +const DownloadModelsProgress = (props) => { + if (props.progress === null) return null; + const circular_progress = Math.floor(props.progress / 5) * 5; + + const progress_color = generateGradientColor({ + value: circular_progress, + colorStart: [242, 242, 242], // #f2f2f2 + colorEnd: [72, 164, 149], // #48a495 + }); + + return( +
+
+
+
+

{`${props.type_label}: ${Math.round(props.progress)}%`}

+
+ ); +}; + + +const generateGradientColor = ({ value, colorStart, colorEnd }) => { + const normalizedValue = Math.max(0, Math.min(100, value)) / 100; + const interpolatedColor = colorStart.map((start, i) => { + const end = colorEnd[i]; + return Math.round(start + (end - start) * normalizedValue); + }); + const hexColor = `#${interpolatedColor.map(val => val.toString(16).padStart(2, '0')).join('')}`; + return hexColor; +}; \ No newline at end of file diff --git a/src-ui/app/splash_component/download_models_container/DownloadModelsContainer.module.scss b/src-ui/app/splash_component/download_models_container/DownloadModelsContainer.module.scss new file mode 100644 index 00000000..0eabf677 --- /dev/null +++ b/src-ui/app/splash_component/download_models_container/DownloadModelsContainer.module.scss @@ -0,0 +1,63 @@ +.container { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow: hidden; + background-color: var(--dark_888_color); +} + +.progress_container { + position: absolute; + top: 77%; + left: 50%; + transform: translate(-50%, -50%); + width: 90%; + gap: 6px; + display: flex; + flex-direction: column; +} + +.labels_wrapper { + position: relative; + width: 100%; + height: 100%; +} + +.logo_img { + position: absolute; + top: 42%; + left: 50%; + width: 280px; + transform: translate(-50%, -50%); +} +.vrct_now_downloading_img { + position: absolute; + bottom: 2px; + right: 10px; + width: 300px; +} + +.progress_bar_container { + display: flex; + flex-direction: column; + gap: 2px; + justify-content: center; +} + +.progress_bar_wrapper { + background-color: var(--dark_800_color); +} + +$progress_ease: cubic-bezier(0, 1, 0.75, 1); +.progress_bar { + height: 8px; + transition: width 0.3s $progress_ease; +} + +.progress_label { + text-align: end; + font-size: 12px; + color: var(--dark_400_color); +} \ No newline at end of file diff --git a/src-ui/app/splash_component/start_up_progress_container/StartUpProgressContainer.jsx b/src-ui/app/splash_component/start_up_progress_container/StartUpProgressContainer.jsx new file mode 100644 index 00000000..93843faa --- /dev/null +++ b/src-ui/app/splash_component/start_up_progress_container/StartUpProgressContainer.jsx @@ -0,0 +1,39 @@ +import clsx from "clsx"; +import styles from "./StartUpProgressContainer.module.scss"; + +import { useInitProgress } from "@logics_common"; +import chat_white_square from "@images/chato_white_square.png"; +import vrct_explanation from "@images/vrchat_chatbox_trasnlator_transcription.png"; +import vrct_starting_up from "@images/vrct_starting_up.png"; + +export const StartUpProgressContainer = () => { + const { currentInitProgress } = useInitProgress(); + + const progress = currentInitProgress.data; + return ( +
+
+ {[...Array(4)].map((_, index) => ( +
+ {index === 3 + ? +
+ +
+ : null + } +
+ ))} +
+
+ + +
+
+ ); +}; diff --git a/src-ui/app/splash_component/start_up_progress_container/StartUpProgressContainer.module.scss b/src-ui/app/splash_component/start_up_progress_container/StartUpProgressContainer.module.scss new file mode 100644 index 00000000..23646c92 --- /dev/null +++ b/src-ui/app/splash_component/start_up_progress_container/StartUpProgressContainer.module.scss @@ -0,0 +1,100 @@ +$progress_ease: cubic-bezier(0, 1, 0.75, 1); + +.container { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow: hidden; +} + +.progress_bar_wrapper { + position: absolute; + top: 48%; + left: 50%; + transform: translate(-50%, -50%); + display: flex; + gap: 36px; +} + +.progress_bar { + width: 60px; + height: 2px; + position: relative; +} + +.progress_bar::before { + content: ""; + position: absolute; + left: 0; + top: 0; + width: 0; + height: 100%; + background-color: var(--dark_200_color); + transition: width 0.3s $progress_ease; +} + +.progress_bar.progressed::before { + width: 100%; +} + +.progress_bar:last-child::before { + background-color: var(--primary_400_color); +} + + +.chato_box { + position: relative; + top: 0; + transform: translateY(-100%); + width: 100%; + height: 8rem; + overflow: hidden; +} + +.chato_img { + position: absolute; + top: 150%; + left: 51%; + transform: translate(-50%, -50%) rotate(-90deg); + width: 2.8rem; + transition: all 0.3s $progress_ease 0.2s; +} + +.progress_bar.progressed .chato_img { + top: 50%; + transform: translate(-50%, -50%) rotate(30deg); + animation: infinite-rotation 20s linear infinite 0.5s; +} + +@keyframes infinite-rotation { + from { + transform: translate(-50%, -50%) rotate(30deg); + } + to { + transform: translate(-50%, -50%) rotate(390deg); + } +} + +.labels_wrapper { + position: relative; + width: 100%; + height: 100%; +} + +.vrct_starting_up_img { + position: absolute; + top: 68%; + left: 50%; + transform: translate(-50%, -50%); + width: 100px; + // transform: translate(-50%, 50%); +} +.vrct_explanation_img { + position: absolute; + bottom: 4px; + right: 10px; + width: 280px; + // transform: translate(-50%, 50%); +} \ No newline at end of file diff --git a/src-ui/assets/VRCT_now_downloading.png b/src-ui/assets/VRCT_now_downloading.png new file mode 100644 index 0000000000000000000000000000000000000000..1b73375a30269fcada3752390e98b0190bd98396 GIT binary patch literal 8738 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 { + const { currentInitProgress, updateInitProgress } = useStore_InitProgress(); + + return { + currentInitProgress, + updateInitProgress, + }; +}; \ No newline at end of file diff --git a/src-ui/logics/useReceiveRoutes.js b/src-ui/logics/useReceiveRoutes.js index d9c66f97..0e120d23 100644 --- a/src-ui/logics/useReceiveRoutes.js +++ b/src-ui/logics/useReceiveRoutes.js @@ -2,6 +2,7 @@ import { translator_status } from "@ui_configs"; import { arrayToObject } from "@utils"; import { + useInitProgress, useIsBackendReady, useWindow, useMessage, @@ -63,6 +64,7 @@ import { } from "@logics_configs"; export const useReceiveRoutes = () => { + const { updateInitProgress } = useInitProgress(); const { updateIsBackendReady } = useIsBackendReady(); const { restoreWindowGeometry } = useWindow(); const { updateIsMainPageCompactMode } = useIsMainPageCompactMode(); @@ -156,6 +158,7 @@ export const useReceiveRoutes = () => { const routes = { // Common "/run/feed_watchdog": () => {}, + "/run/initialization_progress": updateInitProgress, "/get/data/main_window_geometry": restoreWindowGeometry, "/set/data/main_window_geometry": () => {}, "/run/open_filepath_logs": () => console.log("Opened Directory, Message Logs"), @@ -311,8 +314,9 @@ export const useReceiveRoutes = () => { "/get/data/selectable_ctranslate2_weight_type_dict": updateDownloadedCTranslate2WeightTypeStatus, - "/run/download_ctranslate2_weight": updateDownloadProgressCTranslate2WeightTypeStatus, "/run/downloaded_ctranslate2_weight": downloadedCTranslate2WeightType, + "/run/download_ctranslate2_weight": () => {}, + "/run/download_progress_ctranslate2_weight": updateDownloadProgressCTranslate2WeightTypeStatus, // Transcription "/get/data/mic_record_timeout": updateMicRecordTimeout, @@ -370,8 +374,9 @@ export const useReceiveRoutes = () => { "/get/data/selectable_whisper_weight_type_dict": updateDownloadedWhisperWeightTypeStatus, - "/run/download_whisper_weight": updateDownloadProgressWhisperWeightTypeStatus, "/run/downloaded_whisper_weight": downloadedWhisperWeightType, + "/run/download_whisper_weight": () => {}, + "/run/download_progress_whisper_weight": updateDownloadProgressWhisperWeightTypeStatus, // VR "/get/data/overlay_small_log": updateIsEnabledOverlaySmallLog, diff --git a/src-ui/store.js b/src-ui/store.js index 7b4c64a4..4a426d0c 100644 --- a/src-ui/store.js +++ b/src-ui/store.js @@ -110,6 +110,7 @@ export const { atomInstance: Atom_MainFunctionsStateMemory, useHook: useStore_Ma }, "MainFunctionsStateMemory"); export const { atomInstance: Atom_OpenedQuickSetting, useHook: useStore_OpenedQuickSetting } = createAtomWithHook("", "OpenedQuickSetting"); export const { atomInstance: Atom_IsSoftwareUpdateAvailable, useHook: useStore_IsSoftwareUpdateAvailable } = createAtomWithHook(false, "IsSoftwareUpdateAvailable"); +export const { atomInstance: Atom_InitProgress, useHook: useStore_InitProgress } = createAtomWithHook(0, "InitProgress"); // Main Page // Functions