Merge branch 'bugfix_translate' into develop

This commit is contained in:
Sakamoto Shiina
2025-02-10 03:11:25 +09:00
14 changed files with 268 additions and 91 deletions

View File

@@ -237,6 +237,15 @@ class Config:
if isinstance(value, dict): if isinstance(value, dict):
self._SELECTABLE_TRANSLATION_ENGINE_STATUS = value self._SELECTABLE_TRANSLATION_ENGINE_STATUS = value
@property
def SELECTABLE_TRANSCRIPTION_ENGINE_STATUS(self):
return self._SELECTABLE_TRANSCRIPTION_ENGINE_STATUS
@SELECTABLE_TRANSCRIPTION_ENGINE_STATUS.setter
def SELECTABLE_TRANSCRIPTION_ENGINE_STATUS(self, value):
if isinstance(value, dict):
self._SELECTABLE_TRANSCRIPTION_ENGINE_STATUS = value
# Save Json Data # Save Json Data
## Main Window ## Main Window
@property @property
@@ -977,6 +986,9 @@ class Config:
self._SELECTABLE_TRANSLATION_ENGINE_STATUS = {} self._SELECTABLE_TRANSLATION_ENGINE_STATUS = {}
for engine in self.SELECTABLE_TRANSLATION_ENGINE_LIST: for engine in self.SELECTABLE_TRANSLATION_ENGINE_LIST:
self._SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = False self._SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = False
self._SELECTABLE_TRANSCRIPTION_ENGINE_STATUS = {}
for engine in self.SELECTABLE_TRANSCRIPTION_ENGINE_LIST:
self._SELECTABLE_TRANSCRIPTION_ENGINE_STATUS[engine] = False
# Save Json Data # Save Json Data
## Main Window ## Main Window

View File

@@ -6,7 +6,7 @@ import re
from device_manager import device_manager from device_manager import device_manager
from config import config from config import config
from model import model from model import model
from utils import removeLog, printLog, errorLogging from utils import removeLog, printLog, errorLogging, isConnectedNetwork
class Controller: class Controller:
def __init__(self) -> None: def __init__(self) -> None:
@@ -25,6 +25,34 @@ class Controller:
self.run = run self.run = run
# response functions # response functions
def connectedNetwork(self) -> None:
self.run(
200,
self.run_mapping["connected_network"],
True,
)
def disconnectedNetwork(self) -> None:
self.run(
200,
self.run_mapping["connected_network"],
False,
)
def enableAiModels(self) -> None:
self.run(
200,
self.run_mapping["enable_ai_models"],
True,
)
def disableAiModels(self) -> None:
self.run(
200,
self.run_mapping["enable_ai_models"],
False,
)
def updateMicHostList(self) -> None: def updateMicHostList(self) -> None:
self.run( self.run(
200, 200,
@@ -148,6 +176,7 @@ class Controller:
) )
def downloaded(self) -> None: def downloaded(self) -> None:
if model.checkTranslatorCTranslate2ModelWeight(self.weight_type) is True:
weight_type_dict = config.SELECTABLE_CTRANSLATE2_WEIGHT_TYPE_DICT weight_type_dict = config.SELECTABLE_CTRANSLATE2_WEIGHT_TYPE_DICT
weight_type_dict[self.weight_type] = True weight_type_dict[self.weight_type] = True
config.SELECTABLE_CTRANSLATE2_WEIGHT_TYPE_DICT = weight_type_dict config.SELECTABLE_CTRANSLATE2_WEIGHT_TYPE_DICT = weight_type_dict
@@ -157,6 +186,15 @@ class Controller:
self.run_mapping["downloaded_ctranslate2_weight"], self.run_mapping["downloaded_ctranslate2_weight"],
self.weight_type, self.weight_type,
) )
else:
self.run(
400,
self.run_mapping["error_ctranslate2_weight"],
{
"message":"CTranslate2 weight download error",
"data": None
},
)
class DownloadWhisper: class DownloadWhisper:
def __init__(self, run_mapping:dict, weight_type:str, run:Callable[[int, str, Any], None]) -> None: def __init__(self, run_mapping:dict, weight_type:str, run:Callable[[int, str, Any], None]) -> None:
@@ -173,6 +211,7 @@ class Controller:
) )
def downloaded(self) -> None: def downloaded(self) -> None:
if model.checkTranscriptionWhisperModelWeight(self.weight_type) is True:
weight_type_dict = config.SELECTABLE_WHISPER_WEIGHT_TYPE_DICT weight_type_dict = config.SELECTABLE_WHISPER_WEIGHT_TYPE_DICT
weight_type_dict[self.weight_type] = True weight_type_dict[self.weight_type] = True
config.SELECTABLE_WHISPER_WEIGHT_TYPE_DICT = weight_type_dict config.SELECTABLE_WHISPER_WEIGHT_TYPE_DICT = weight_type_dict
@@ -182,6 +221,15 @@ class Controller:
self.run_mapping["downloaded_whisper_weight"], self.run_mapping["downloaded_whisper_weight"],
self.weight_type, self.weight_type,
) )
else:
self.run(
400,
self.run_mapping["error_whisper_weight"],
{
"message":"Whisper weight download error",
"data": None
},
)
def micMessage(self, result: dict) -> None: def micMessage(self, result: dict) -> None:
message = result["text"] message = result["text"]
@@ -494,7 +542,10 @@ class Controller:
your_language = config.SELECTED_YOUR_LANGUAGES[config.SELECTED_TAB_NO]["1"] your_language = config.SELECTED_YOUR_LANGUAGES[config.SELECTED_TAB_NO]["1"]
for target_language in config.SELECTED_TARGET_LANGUAGES[config.SELECTED_TAB_NO].values(): for target_language in config.SELECTED_TARGET_LANGUAGES[config.SELECTED_TAB_NO].values():
if your_language["language"] == target_language["language"] and target_language["enable"] is True: if your_language["language"] == target_language["language"] and target_language["enable"] is True:
if config.SELECTABLE_TRANSLATION_ENGINE_STATUS["CTranslate2"] is True:
engines = ["CTranslate2"] engines = ["CTranslate2"]
else:
engines = []
return {"status":200, "result":engines} return {"status":200, "result":engines}
@@ -541,6 +592,11 @@ class Controller:
self.updateTranslationEngineAndEngineList() self.updateTranslationEngineAndEngineList()
return {"status":200, "result":config.SELECTED_TARGET_LANGUAGES} return {"status":200, "result":config.SELECTED_TARGET_LANGUAGES}
@staticmethod
def getTranscriptionEngines(*args, **kwargs) -> dict:
engines = [key for key, value in config.SELECTABLE_TRANSCRIPTION_ENGINE_STATUS.items() if value is True]
return {"status":200, "result":engines}
@staticmethod @staticmethod
def getSelectedTranscriptionEngine(*args, **kwargs) -> dict: def getSelectedTranscriptionEngine(*args, **kwargs) -> dict:
return {"status":200, "result":config.SELECTED_TRANSCRIPTION_ENGINE} return {"status":200, "result":config.SELECTED_TRANSCRIPTION_ENGINE}
@@ -1665,6 +1721,12 @@ class Controller:
def init(self, *args, **kwargs) -> None: def init(self, *args, **kwargs) -> None:
removeLog() removeLog()
printLog("Start Initialization") printLog("Start Initialization")
connected_network = isConnectedNetwork()
if connected_network is True:
self.connectedNetwork()
else:
self.disconnectedNetwork()
printLog(f"Connected Network: {connected_network}")
printLog("Init Translation Engine Status") printLog("Init Translation Engine Status")
for engine in config.SELECTABLE_TRANSLATION_ENGINE_LIST: for engine in config.SELECTABLE_TRANSLATION_ENGINE_LIST:
@@ -1680,11 +1742,9 @@ class Controller:
auth_keys = config.AUTH_KEYS auth_keys = config.AUTH_KEYS
auth_keys[engine] = None auth_keys[engine] = None
config.AUTH_KEYS = auth_keys config.AUTH_KEYS = auth_keys
case _:
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = True
self.initializationProgress(1) self.initializationProgress(1)
if connected_network is True:
# download CTranslate2 Model Weight # download CTranslate2 Model Weight
printLog("Download CTranslate2 Model Weight") printLog("Download CTranslate2 Model Weight")
weight_type = config.CTRANSLATE2_WEIGHT_TYPE weight_type = config.CTRANSLATE2_WEIGHT_TYPE
@@ -1708,6 +1768,37 @@ class Controller:
if isinstance(th_download_whisper, Thread): if isinstance(th_download_whisper, Thread):
th_download_whisper.join() th_download_whisper.join()
if (model.checkTranslatorCTranslate2ModelWeight(config.CTRANSLATE2_WEIGHT_TYPE) is False or
model.checkTranscriptionWhisperModelWeight(config.WHISPER_WEIGHT_TYPE) is False):
self.disableAiModels()
else:
self.enableAiModels()
for engine in config.SELECTABLE_TRANSLATION_ENGINE_LIST:
match engine:
case "CTranslate2":
if model.checkTranslatorCTranslate2ModelWeight(config.CTRANSLATE2_WEIGHT_TYPE) is True:
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = True
else:
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = False
case _:
if connected_network is True:
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = True
else:
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = False
for engine in config.SELECTABLE_TRANSCRIPTION_ENGINE_LIST:
match engine:
case "Whisper":
if model.checkTranscriptionWhisperModelWeight(config.WHISPER_WEIGHT_TYPE) is True:
config.SELECTABLE_TRANSCRIPTION_ENGINE_STATUS[engine] = True
else:
config.SELECTABLE_TRANSCRIPTION_ENGINE_STATUS[engine] = False
case _:
if connected_network is True:
config.SELECTABLE_TRANSCRIPTION_ENGINE_STATUS[engine] = True
else:
config.SELECTABLE_TRANSCRIPTION_ENGINE_STATUS[engine] = False
self.initializationProgress(2) self.initializationProgress(2)
# set Translation Engine # set Translation Engine

View File

@@ -8,6 +8,9 @@ from controller import Controller
from utils import printLog, printResponse, errorLogging, encodeBase64 from utils import printLog, printResponse, errorLogging, encodeBase64
run_mapping = { run_mapping = {
"connected_network":"/run/connected_network",
"enable_ai_models":"/run/enable_ai_models",
"transcription_mic":"/run/transcription_send_mic_message", "transcription_mic":"/run/transcription_send_mic_message",
"transcription_speaker":"/run/transcription_receive_speaker_message", "transcription_speaker":"/run/transcription_receive_speaker_message",
@@ -20,8 +23,10 @@ run_mapping = {
"download_progress_ctranslate2_weight":"/run/download_progress_ctranslate2_weight", "download_progress_ctranslate2_weight":"/run/download_progress_ctranslate2_weight",
"downloaded_ctranslate2_weight":"/run/downloaded_ctranslate2_weight", "downloaded_ctranslate2_weight":"/run/downloaded_ctranslate2_weight",
"error_ctranslate2_weight":"/run/error_ctranslate2_weight",
"download_progress_whisper_weight":"/run/download_progress_whisper_weight", "download_progress_whisper_weight":"/run/download_progress_whisper_weight",
"downloaded_whisper_weight":"/run/downloaded_whisper_weight", "downloaded_whisper_weight":"/run/downloaded_whisper_weight",
"error_whisper_weight":"/run/error_whisper_weight",
"selected_mic_device":"/run/selected_mic_device", "selected_mic_device":"/run/selected_mic_device",
"selected_speaker_device":"/run/selected_speaker_device", "selected_speaker_device":"/run/selected_speaker_device",
@@ -79,6 +84,7 @@ mapping = {
"/get/data/selected_target_languages": {"status": True, "variable":controller.getSelectedTargetLanguages}, "/get/data/selected_target_languages": {"status": True, "variable":controller.getSelectedTargetLanguages},
"/set/data/selected_target_languages": {"status": True, "variable":controller.setSelectedTargetLanguages}, "/set/data/selected_target_languages": {"status": True, "variable":controller.setSelectedTargetLanguages},
"/get/data/transcription_engines": {"status": False, "variable":controller.getTranscriptionEngines},
"/get/data/selected_transcription_engine": {"status": False, "variable":controller.getSelectedTranscriptionEngine}, "/get/data/selected_transcription_engine": {"status": False, "variable":controller.getSelectedTranscriptionEngine},
"/set/data/selected_transcription_engine": {"status": False, "variable":controller.setSelectedTranscriptionEngine}, "/set/data/selected_transcription_engine": {"status": False, "variable":controller.setSelectedTranscriptionEngine},

View File

@@ -1,6 +1,11 @@
from os import path as os_path from os import path as os_path
from deepl import Translator as deepl_Translator from deepl import Translator as deepl_Translator
from translators import translate_text as other_web_Translator try:
from translators import translate_text as other_web_Translator
ENABLE_TRANSLATORS = True
except Exception:
ENABLE_TRANSLATORS = False
from .translation_languages import translation_lang from .translation_languages import translation_lang
from .translation_utils import ctranslate2_weights from .translation_utils import ctranslate2_weights
@@ -18,6 +23,7 @@ class Translator():
self.ctranslate2_translator = None self.ctranslate2_translator = None
self.ctranslate2_tokenizer = None self.ctranslate2_tokenizer = None
self.is_loaded_ctranslate2_model = False self.is_loaded_ctranslate2_model = False
self.is_enable_translators = ENABLE_TRANSLATORS
def authenticationDeepLAuthKey(self, authkey): def authenticationDeepLAuthKey(self, authkey):
result = True result = True
@@ -97,6 +103,7 @@ class Translator():
source_language, target_language = self.getLanguageCode(translator_name, target_country, source_language, target_language) source_language, target_language = self.getLanguageCode(translator_name, target_country, source_language, target_language)
match translator_name: match translator_name:
case "DeepL": case "DeepL":
if self.is_enable_translators is True:
result = other_web_Translator( result = other_web_Translator(
query_text=message, query_text=message,
translator="deepl", translator="deepl",
@@ -104,6 +111,7 @@ class Translator():
to_language=target_language, to_language=target_language,
) )
case "DeepL_API": case "DeepL_API":
if self.is_enable_translators is True:
if self.deepl_client is None: if self.deepl_client is None:
result = False result = False
else: else:
@@ -113,6 +121,7 @@ class Translator():
target_lang=target_language, target_lang=target_language,
).text ).text
case "Google": case "Google":
if self.is_enable_translators is True:
result = other_web_Translator( result = other_web_Translator(
query_text=message, query_text=message,
translator="google", translator="google",
@@ -120,6 +129,7 @@ class Translator():
to_language=target_language, to_language=target_language,
) )
case "Bing": case "Bing":
if self.is_enable_translators is True:
result = other_web_Translator( result = other_web_Translator(
query_text=message, query_text=message,
translator="bing", translator="bing",
@@ -127,6 +137,7 @@ class Translator():
to_language=target_language, to_language=target_language,
) )
case "Papago": case "Papago":
if self.is_enable_translators is True:
result = other_web_Translator( result = other_web_Translator(
query_text=message, query_text=message,
translator="papago", translator="papago",

View File

@@ -6,6 +6,14 @@ import logging
from logging.handlers import RotatingFileHandler from logging.handlers import RotatingFileHandler
from ctranslate2 import get_supported_compute_types from ctranslate2 import get_supported_compute_types
import requests
def isConnectedNetwork(url="http://www.google.com", timeout=3):
try:
response = requests.get(url, timeout=timeout)
return response.status_code == 200
except requests.RequestException:
return False
def getBestComputeType(device, device_index) -> str: def getBestComputeType(device, device_index) -> str:
compute_types = get_supported_compute_types(device, device_index) compute_types = get_supported_compute_types(device, device_index)

View File

@@ -1,9 +1,5 @@
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import {
useWindow,
} from "@logics_common";
import { import {
KeyEventController, KeyEventController,
StartPythonController, StartPythonController,
@@ -23,9 +19,10 @@ import { UpdatingComponent } from "./updating_component/UpdatingComponent";
import { ModalController } from "./modal_controller/ModalController"; import { ModalController } from "./modal_controller/ModalController";
import { SnackbarController } from "./snackbar_controller/SnackbarController"; import { SnackbarController } from "./snackbar_controller/SnackbarController";
import styles from "./App.module.scss"; import styles from "./App.module.scss";
import { useIsBackendReady, useIsSoftwareUpdating } from "@logics_common"; import { useIsBackendReady, useIsSoftwareUpdating, useIsVrctAvailable, useWindow } from "@logics_common";
export const App = () => { export const App = () => {
const { currentIsVrctAvailable } = useIsVrctAvailable();
const { currentIsBackendReady } = useIsBackendReady(); const { currentIsBackendReady } = useIsBackendReady();
const { WindowGeometryController } = useWindow(); const { WindowGeometryController } = useWindow();
const { i18n } = useTranslation(); const { i18n } = useTranslation();
@@ -42,10 +39,12 @@ export const App = () => {
<TransparencyController /> <TransparencyController />
<WindowGeometryController /> <WindowGeometryController />
{currentIsBackendReady.data === false {(currentIsBackendReady.data === false || currentIsVrctAvailable.data === false)
? <SplashComponent /> ? <SplashComponent />
: <Contents key={i18n.language}/> : <Contents key={i18n.language}/>
} }
<SnackbarController />
</div> </div>
); );
}; };
@@ -61,7 +60,6 @@ const Contents = () => {
<ConfigPage /> <ConfigPage />
<MainPage /> <MainPage />
<ModalController /> <ModalController />
<SnackbarController />
</div> </div>
: :
<UpdatingComponent /> <UpdatingComponent />

View File

@@ -17,17 +17,23 @@ export const SnackbarController = () => {
[styles.is_error]: currentNotificationStatus.data.status === "error", [styles.is_error]: currentNotificationStatus.data.status === "error",
}); });
const settings = currentNotificationStatus.data;
let hide_duration = 5000;
if (settings.options?.hide_duration === null) hide_duration = null;
if (Number(settings.options?.hide_duration)) hide_duration = settings.options.hide_duration;
return ( return (
<div> <div>
<Snackbar <Snackbar
open={currentNotificationStatus.data.is_open} open={settings.is_open}
onClose={handleClose} onClose={handleClose}
TransitionComponent={SlideTransition} TransitionComponent={SlideTransition}
key={currentNotificationStatus.data.key} key={settings.key}
autoHideDuration={5000} autoHideDuration={hide_duration}
> >
<div className={snackbar_classname}> <div className={snackbar_classname}>
<p className={styles.snackbar_message}>{currentNotificationStatus.data.message}</p> <p className={styles.snackbar_message}>{settings.message}</p>
</div> </div>
</Snackbar> </Snackbar>
</div> </div>

View File

@@ -10,3 +10,5 @@ export { useOpenFolder } from "./useOpenFolder";
export { useMessage } from "./useMessage"; export { useMessage } from "./useMessage";
export { useUpdateSoftware } from "./useUpdateSoftware"; export { useUpdateSoftware } from "./useUpdateSoftware";
export { useVolume } from "./useVolume"; export { useVolume } from "./useVolume";
export { useHandleNetworkConnection } from "./useHandleNetworkConnection";
export { useIsVrctAvailable } from "./useIsVrctAvailable";

View File

@@ -0,0 +1,18 @@
import { useNotificationStatus } from "@logics_common";
export const useHandleNetworkConnection = () => {
const { showNotification_Error } = useNotificationStatus();
const handleNetworkConnection = (is_network_connected) => {
if (!is_network_connected) {
showNotification_Error("Network is not connected. Some of the function will not work.", {
hide_duration: 8000,
});
}
};
return {
handleNetworkConnection,
};
};

View File

@@ -0,0 +1,10 @@
import { useStore_IsVrctAvailable } from "@store";
export const useIsVrctAvailable = () => {
const { currentIsVrctAvailable, updateIsVrctAvailable } = useStore_IsVrctAvailable();
return {
currentIsVrctAvailable,
updateIsVrctAvailable,
};
};

View File

@@ -5,12 +5,13 @@ export const useNotificationStatus = () => {
const generateRandomKey = () => Math.random(); const generateRandomKey = () => Math.random();
const showNotification_Error = (message) => { const showNotification_Error = (message, options = {}) => {
updateNotificationStatus({ updateNotificationStatus({
status: "error", status: "error",
is_open: true, is_open: true,
key: generateRandomKey(), key: generateRandomKey(),
message: message, message: message,
options: options,
}); });
}; };
@@ -20,6 +21,7 @@ export const useNotificationStatus = () => {
is_open: true, is_open: true,
key: generateRandomKey(), key: generateRandomKey(),
message: message, message: message,
options: options,
}); });
}; };

View File

@@ -2,8 +2,9 @@ import { translator_status } from "@ui_configs";
import { arrayToObject } from "@utils"; import { arrayToObject } from "@utils";
import { import {
useIsVrctAvailable,
useNotificationStatus, useNotificationStatus,
useHandleNetworkConnection,
useComputeMode, useComputeMode,
useInitProgress, useInitProgress,
@@ -74,6 +75,7 @@ import {
} from "@logics_configs"; } from "@logics_configs";
export const useReceiveRoutes = () => { export const useReceiveRoutes = () => {
const { updateIsVrctAvailable } = useIsVrctAvailable();
const { updateComputeMode } = useComputeMode(); const { updateComputeMode } = useComputeMode();
const { updateInitProgress } = useInitProgress(); const { updateInitProgress } = useInitProgress();
const { updateIsBackendReady } = useIsBackendReady(); const { updateIsBackendReady } = useIsBackendReady();
@@ -178,16 +180,25 @@ export const useReceiveRoutes = () => {
const { showNotification_Success, showNotification_Error } = useNotificationStatus(); const { showNotification_Success, showNotification_Error } = useNotificationStatus();
const { handleNetworkConnection } = useHandleNetworkConnection();
const routes = { const routes = {
// Common // Common
"/run/feed_watchdog": () => {}, "/run/feed_watchdog": () => {},
"/run/initialization_progress": updateInitProgress, "/run/initialization_progress": updateInitProgress,
"/run/enable_ai_models": (is_ai_models_available) => {
if (is_ai_models_available === false) {
updateIsVrctAvailable(false);
showNotification_Error("AI models have not been detected. Check the network connection and restart VRCT (it will download automatically, normally).", { hide_duration: null });
}
},
"/get/data/compute_mode": updateComputeMode, "/get/data/compute_mode": updateComputeMode,
"/get/data/main_window_geometry": restoreWindowGeometry, "/get/data/main_window_geometry": restoreWindowGeometry,
"/set/data/main_window_geometry": () => {}, "/set/data/main_window_geometry": () => {},
"/run/open_filepath_logs": () => console.log("Opened Directory, Message Logs"), "/run/open_filepath_logs": () => console.log("Opened Directory, Message Logs"),
"/run/open_filepath_config_file": () => console.log("Opened Directory, Config File"), "/run/open_filepath_config_file": () => console.log("Opened Directory, Config File"),
"/run/update_software_flag": updateIsSoftwareUpdateAvailable, "/run/update_software_flag": updateIsSoftwareUpdateAvailable,
"/run/connected_network": handleNetworkConnection,
// Main Page // Main Page
// Page Controls // Page Controls
@@ -478,6 +489,7 @@ export const useReceiveRoutes = () => {
"/get/data/speaker_no_speech_prob": ()=>{}, // Not implemented on UI yet "/get/data/speaker_no_speech_prob": ()=>{}, // Not implemented on UI yet
"/get/data/convert_message_to_romaji": ()=>{}, // Not implemented on UI yet "/get/data/convert_message_to_romaji": ()=>{}, // Not implemented on UI yet
"/get/data/convert_message_to_hiragana": ()=>{}, // Not implemented on UI yet "/get/data/convert_message_to_hiragana": ()=>{}, // Not implemented on UI yet
"/get/data/transcription_engines": ()=>{}, // Not implemented on UI yet. (if ai_models has not been detected, this will be blank array[]. if the ai_models are ok but just network has not connected, it'l be only ["Whisper"])
}; };
const error_routes = { const error_routes = {

View File

@@ -106,6 +106,7 @@ const createAtomWithHook = (initialValue, base_name, options) => {
// Common // Common
export const { atomInstance: Atom_IsBackendReady, useHook: useStore_IsBackendReady } = createAtomWithHook(false, "IsBackendReady"); export const { atomInstance: Atom_IsBackendReady, useHook: useStore_IsBackendReady } = createAtomWithHook(false, "IsBackendReady");
export const { atomInstance: Atom_IsVrctAvailable, useHook: useStore_IsVrctAvailable } = createAtomWithHook(true, "IsVrctAvailable");
export const { atomInstance: Atom_ComputeMode, useHook: useStore_ComputeMode } = createAtomWithHook("", "ComputeMode"); export const { atomInstance: Atom_ComputeMode, useHook: useStore_ComputeMode } = createAtomWithHook("", "ComputeMode");
export const { atomInstance: Atom_IsOpenedConfigPage, useHook: useStore_IsOpenedConfigPage } = createAtomWithHook(false, "IsOpenedConfigPage"); export const { atomInstance: Atom_IsOpenedConfigPage, useHook: useStore_IsOpenedConfigPage } = createAtomWithHook(false, "IsOpenedConfigPage");
export const { atomInstance: Atom_MainFunctionsStateMemory, useHook: useStore_MainFunctionsStateMemory } = createAtomWithHook({ export const { atomInstance: Atom_MainFunctionsStateMemory, useHook: useStore_MainFunctionsStateMemory } = createAtomWithHook({