Merge branch 'ui' into for_webui
This commit is contained in:
@@ -1,13 +1,27 @@
|
|||||||
import { useEffect, useRef } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { useStartPython } from "@logics/useStartPython";
|
import {
|
||||||
|
useWindow,
|
||||||
|
} from "@logics_common";
|
||||||
|
|
||||||
|
// import React from "react";
|
||||||
|
|
||||||
|
import {
|
||||||
|
StartPythonController,
|
||||||
|
UiLanguageController,
|
||||||
|
ConfigPageCloseTriggerController,
|
||||||
|
UiSizeController,
|
||||||
|
FontFamilyController,
|
||||||
|
TransparencyController,
|
||||||
|
} from "./_app_controllers/index.js";
|
||||||
|
|
||||||
import { WindowTitleBar } from "./window_title_bar/WindowTitleBar";
|
import { WindowTitleBar } from "./window_title_bar/WindowTitleBar";
|
||||||
import { MainPage } from "./main_page/MainPage";
|
import { MainPage } from "./main_page/MainPage";
|
||||||
import { ConfigPage } from "./config_page/ConfigPage";
|
import { ConfigPage } from "./config_page/ConfigPage";
|
||||||
import { SplashComponent } from "./splash_component/SplashComponent";
|
import { SplashComponent } from "./splash_component/SplashComponent";
|
||||||
import { UpdatingComponent } from "./updating_component/UpdatingComponent";
|
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 styles from "./App.module.scss";
|
import styles from "./App.module.scss";
|
||||||
import { useIsBackendReady, useIsSoftwareUpdating } from "@logics_common";
|
import { useIsBackendReady, useIsSoftwareUpdating } from "@logics_common";
|
||||||
|
|
||||||
@@ -18,9 +32,9 @@ export const App = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<StartPythonFacadeComponent />
|
<StartPythonController />
|
||||||
<UiLanguageController />
|
<UiLanguageController />
|
||||||
<ConfigPageCloseTrigger />
|
<ConfigPageCloseTriggerController />
|
||||||
<UiSizeController />
|
<UiSizeController />
|
||||||
<FontFamilyController />
|
<FontFamilyController />
|
||||||
<TransparencyController />
|
<TransparencyController />
|
||||||
@@ -45,6 +59,7 @@ const Contents = () => {
|
|||||||
<ConfigPage />
|
<ConfigPage />
|
||||||
<MainPage />
|
<MainPage />
|
||||||
<ModalController />
|
<ModalController />
|
||||||
|
<SnackbarController />
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<UpdatingComponent />
|
<UpdatingComponent />
|
||||||
@@ -52,153 +67,3 @@ const Contents = () => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
import {
|
|
||||||
useWindow,
|
|
||||||
useVolume,
|
|
||||||
useIsOpenedConfigPage,
|
|
||||||
} from "@logics_common";
|
|
||||||
|
|
||||||
import {
|
|
||||||
useUiLanguage,
|
|
||||||
useUiScaling,
|
|
||||||
useSelectedFontFamily,
|
|
||||||
useTransparency,
|
|
||||||
} from "@logics_configs";
|
|
||||||
|
|
||||||
import {
|
|
||||||
useMainFunction,
|
|
||||||
} from "@logics_main";
|
|
||||||
|
|
||||||
const StartPythonFacadeComponent = () => {
|
|
||||||
const { asyncStartPython } = useStartPython();
|
|
||||||
const hasRunRef = useRef(false);
|
|
||||||
const { asyncFetchFonts } = useAsyncFetchFonts();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!hasRunRef.current) {
|
|
||||||
asyncStartPython().then(() => {
|
|
||||||
startFeedingToWatchDog();
|
|
||||||
asyncFetchFonts();
|
|
||||||
}).catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return () => hasRunRef.current = true;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const UiLanguageController = () => {
|
|
||||||
const { currentUiLanguage } = useUiLanguage();
|
|
||||||
const { i18n } = useTranslation();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
i18n.changeLanguage(currentUiLanguage.data);
|
|
||||||
}, [currentUiLanguage.data]);
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
import { useStore_MainFunctionsStateMemory } from "@store";
|
|
||||||
|
|
||||||
const ConfigPageCloseTrigger = () => {
|
|
||||||
const { currentIsOpenedConfigPage } = useIsOpenedConfigPage();
|
|
||||||
const { currentMainFunctionsStateMemory, updateMainFunctionsStateMemory} = useStore_MainFunctionsStateMemory();
|
|
||||||
const {
|
|
||||||
currentTranscriptionSendStatus,
|
|
||||||
setTranscriptionSend,
|
|
||||||
currentTranscriptionReceiveStatus,
|
|
||||||
setTranscriptionReceive,
|
|
||||||
} = useMainFunction();
|
|
||||||
const {
|
|
||||||
currentMicThresholdCheckStatus,
|
|
||||||
volumeCheckStop_Mic,
|
|
||||||
currentSpeakerThresholdCheckStatus,
|
|
||||||
volumeCheckStop_Speaker,
|
|
||||||
} = useVolume();
|
|
||||||
|
|
||||||
|
|
||||||
const memorizeLatestMainFunctionsState = () => {
|
|
||||||
updateMainFunctionsStateMemory({
|
|
||||||
transcription_send: currentTranscriptionSendStatus.data,
|
|
||||||
transcription_receive: currentTranscriptionReceiveStatus.data,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const restoreMainFunctionState = () => {
|
|
||||||
if (currentMainFunctionsStateMemory.data.transcription_send === true) setTranscriptionSend(true);
|
|
||||||
if (currentMainFunctionsStateMemory.data.transcription_receive === true) setTranscriptionReceive(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (currentIsOpenedConfigPage.data === true) { // When config page is opened.
|
|
||||||
memorizeLatestMainFunctionsState();
|
|
||||||
if (currentTranscriptionSendStatus.data === true) setTranscriptionSend(false);
|
|
||||||
if (currentTranscriptionReceiveStatus.data === true) setTranscriptionReceive(false);
|
|
||||||
} else if (currentIsOpenedConfigPage.data === false) { // When config page is closed.
|
|
||||||
if (currentMicThresholdCheckStatus.data === true) volumeCheckStop_Mic();
|
|
||||||
if (currentSpeakerThresholdCheckStatus.data === true) volumeCheckStop_Speaker();
|
|
||||||
restoreMainFunctionState();
|
|
||||||
}
|
|
||||||
}, [currentIsOpenedConfigPage.data]);
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
import React from "react";
|
|
||||||
const UiSizeController = () => {
|
|
||||||
const { currentUiScaling } = useUiScaling();
|
|
||||||
const font_size = 62.5 * currentUiScaling.data / 100;
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
document.documentElement.style.setProperty("font-size", `${font_size}%`);
|
|
||||||
}, [currentUiScaling.data]);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const FontFamilyController = () => {
|
|
||||||
const { currentSelectedFontFamily } = useSelectedFontFamily();
|
|
||||||
useEffect(() => {
|
|
||||||
document.documentElement.style.setProperty("--font_family", currentSelectedFontFamily.data);
|
|
||||||
}, [currentSelectedFontFamily.data]);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
import { useStore_SelectableFontFamilyList } from "@store";
|
|
||||||
import { arrayToObject } from "@utils";
|
|
||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/tauri";
|
|
||||||
const useAsyncFetchFonts = () => {
|
|
||||||
const { updateSelectableFontFamilyList } = useStore_SelectableFontFamilyList();
|
|
||||||
const asyncFetchFonts = async () => {
|
|
||||||
try {
|
|
||||||
let fonts = await invoke("get_font_list");
|
|
||||||
fonts = fonts.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: "base" }));
|
|
||||||
updateSelectableFontFamilyList(arrayToObject(fonts));
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching fonts:", error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return { asyncFetchFonts };
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const TransparencyController = () => {
|
|
||||||
const { currentTransparency } = useTransparency();
|
|
||||||
useEffect(() => {
|
|
||||||
document.documentElement.style.setProperty("opacity", `${currentTransparency.data / 100}`);
|
|
||||||
}, [currentTransparency.data]);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
import { useStdoutToPython } from "@logics/useStdoutToPython";
|
|
||||||
const startFeedingToWatchDog = () => {
|
|
||||||
const { asyncStdoutToPython } = useStdoutToPython();
|
|
||||||
setInterval(() => {
|
|
||||||
asyncStdoutToPython("/run/feed_watchdog");
|
|
||||||
}, 20000); // 20000ミリ秒 = 20秒
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
import {
|
||||||
|
useVolume,
|
||||||
|
useIsOpenedConfigPage,
|
||||||
|
} from "@logics_common";
|
||||||
|
|
||||||
|
import {
|
||||||
|
useMainFunction,
|
||||||
|
} from "@logics_main";
|
||||||
|
|
||||||
|
import { useStore_MainFunctionsStateMemory } from "@store";
|
||||||
|
|
||||||
|
export const ConfigPageCloseTriggerController = () => {
|
||||||
|
const { currentIsOpenedConfigPage } = useIsOpenedConfigPage();
|
||||||
|
const { currentMainFunctionsStateMemory, updateMainFunctionsStateMemory} = useStore_MainFunctionsStateMemory();
|
||||||
|
const {
|
||||||
|
currentTranscriptionSendStatus,
|
||||||
|
setTranscriptionSend,
|
||||||
|
currentTranscriptionReceiveStatus,
|
||||||
|
setTranscriptionReceive,
|
||||||
|
} = useMainFunction();
|
||||||
|
const {
|
||||||
|
currentMicThresholdCheckStatus,
|
||||||
|
volumeCheckStop_Mic,
|
||||||
|
currentSpeakerThresholdCheckStatus,
|
||||||
|
volumeCheckStop_Speaker,
|
||||||
|
} = useVolume();
|
||||||
|
|
||||||
|
|
||||||
|
const memorizeLatestMainFunctionsState = () => {
|
||||||
|
updateMainFunctionsStateMemory({
|
||||||
|
transcription_send: currentTranscriptionSendStatus.data,
|
||||||
|
transcription_receive: currentTranscriptionReceiveStatus.data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const restoreMainFunctionState = () => {
|
||||||
|
if (currentMainFunctionsStateMemory.data.transcription_send === true) setTranscriptionSend(true);
|
||||||
|
if (currentMainFunctionsStateMemory.data.transcription_receive === true) setTranscriptionReceive(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (currentIsOpenedConfigPage.data === true) { // When config page is opened.
|
||||||
|
memorizeLatestMainFunctionsState();
|
||||||
|
if (currentTranscriptionSendStatus.data === true) setTranscriptionSend(false);
|
||||||
|
if (currentTranscriptionReceiveStatus.data === true) setTranscriptionReceive(false);
|
||||||
|
} else if (currentIsOpenedConfigPage.data === false) { // When config page is closed.
|
||||||
|
if (currentMicThresholdCheckStatus.data === true) volumeCheckStop_Mic();
|
||||||
|
if (currentSpeakerThresholdCheckStatus.data === true) volumeCheckStop_Speaker();
|
||||||
|
restoreMainFunctionState();
|
||||||
|
}
|
||||||
|
}, [currentIsOpenedConfigPage.data]);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
11
src-ui/app/_app_controllers/FontFamilyController.jsx
Normal file
11
src-ui/app/_app_controllers/FontFamilyController.jsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
import { useSelectedFontFamily } from "@logics_configs";
|
||||||
|
|
||||||
|
export const FontFamilyController = () => {
|
||||||
|
const { currentSelectedFontFamily } = useSelectedFontFamily();
|
||||||
|
useEffect(() => {
|
||||||
|
document.documentElement.style.setProperty("--font_family", currentSelectedFontFamily.data);
|
||||||
|
}, [currentSelectedFontFamily.data]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
48
src-ui/app/_app_controllers/StartPythonController.jsx
Normal file
48
src-ui/app/_app_controllers/StartPythonController.jsx
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { invoke } from "@tauri-apps/api/tauri";
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
import { useStartPython } from "@logics/useStartPython";
|
||||||
|
import { useStdoutToPython } from "@logics/useStdoutToPython";
|
||||||
|
|
||||||
|
import { useStore_SelectableFontFamilyList } from "@store";
|
||||||
|
import { arrayToObject } from "@utils";
|
||||||
|
|
||||||
|
export const StartPythonController = () => {
|
||||||
|
const { asyncStartPython } = useStartPython();
|
||||||
|
const hasRunRef = useRef(false);
|
||||||
|
const { asyncFetchFonts } = useAsyncFetchFonts();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!hasRunRef.current) {
|
||||||
|
asyncStartPython().then(() => {
|
||||||
|
startFeedingToWatchDogController();
|
||||||
|
asyncFetchFonts();
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return () => hasRunRef.current = true;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useAsyncFetchFonts = () => {
|
||||||
|
const { updateSelectableFontFamilyList } = useStore_SelectableFontFamilyList();
|
||||||
|
const asyncFetchFonts = async () => {
|
||||||
|
try {
|
||||||
|
let fonts = await invoke("get_font_list");
|
||||||
|
fonts = fonts.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: "base" }));
|
||||||
|
updateSelectableFontFamilyList(arrayToObject(fonts));
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching fonts:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return { asyncFetchFonts };
|
||||||
|
};
|
||||||
|
|
||||||
|
const startFeedingToWatchDogController = () => {
|
||||||
|
const { asyncStdoutToPython } = useStdoutToPython();
|
||||||
|
setInterval(() => {
|
||||||
|
asyncStdoutToPython("/run/feed_watchdog");
|
||||||
|
}, 20000); // 20000ミリ秒 = 20秒
|
||||||
|
};
|
||||||
11
src-ui/app/_app_controllers/TransparencyController.jsx
Normal file
11
src-ui/app/_app_controllers/TransparencyController.jsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
import { useTransparency } from "@logics_configs";
|
||||||
|
|
||||||
|
export const TransparencyController = () => {
|
||||||
|
const { currentTransparency } = useTransparency();
|
||||||
|
useEffect(() => {
|
||||||
|
document.documentElement.style.setProperty("opacity", `${currentTransparency.data / 100}`);
|
||||||
|
}, [currentTransparency.data]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
14
src-ui/app/_app_controllers/UiLanguageController.jsx
Normal file
14
src-ui/app/_app_controllers/UiLanguageController.jsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useUiLanguage } from "@logics_configs";
|
||||||
|
|
||||||
|
export const UiLanguageController = () => {
|
||||||
|
const { currentUiLanguage } = useUiLanguage();
|
||||||
|
const { i18n } = useTranslation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
i18n.changeLanguage(currentUiLanguage.data);
|
||||||
|
}, [currentUiLanguage.data]);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
13
src-ui/app/_app_controllers/UiSizeController.jsx
Normal file
13
src-ui/app/_app_controllers/UiSizeController.jsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
import { useUiScaling } from "@logics_configs";
|
||||||
|
|
||||||
|
export const UiSizeController = () => {
|
||||||
|
const { currentUiScaling } = useUiScaling();
|
||||||
|
const font_size = 62.5 * currentUiScaling.data / 100;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.documentElement.style.setProperty("font-size", `${font_size}%`);
|
||||||
|
}, [currentUiScaling.data]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
6
src-ui/app/_app_controllers/index.js
Normal file
6
src-ui/app/_app_controllers/index.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export { StartPythonController } from "./StartPythonController";
|
||||||
|
export { UiLanguageController } from "./UiLanguageController";
|
||||||
|
export { ConfigPageCloseTriggerController } from "./ConfigPageCloseTriggerController";
|
||||||
|
export { UiSizeController } from "./UiSizeController";
|
||||||
|
export { FontFamilyController } from "./FontFamilyController";
|
||||||
|
export { TransparencyController } from "./TransparencyController";
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import clsx from "clsx";
|
||||||
import React, { useRef, forwardRef, useImperativeHandle } from "react";
|
import React, { useRef, forwardRef, useImperativeHandle } from "react";
|
||||||
import styles from "./_Entry.module.scss";
|
import styles from "./_Entry.module.scss";
|
||||||
|
|
||||||
@@ -9,6 +10,9 @@ const _Entry = forwardRef((props, ref) => {
|
|||||||
inputRef.current.focus();
|
inputRef.current.focus();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
const input_class_names = clsx(styles.entry_input_area, {
|
||||||
|
[styles.is_disabled]: props.is_disabled
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.entry_container}>
|
<div className={styles.entry_container}>
|
||||||
@@ -18,7 +22,7 @@ const _Entry = forwardRef((props, ref) => {
|
|||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className={styles.entry_input_area}
|
className={input_class_names}
|
||||||
value={props.ui_variable === null ? "" : props.ui_variable}
|
value={props.ui_variable === null ? "" : props.ui_variable}
|
||||||
onChange={(e) => props.onChange(e)}
|
onChange={(e) => props.onChange(e)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -16,4 +16,9 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
resize: none;
|
resize: none;
|
||||||
|
color: var(--dark_basic_text_color);
|
||||||
|
&.is_disabled {
|
||||||
|
color: var(--dark_500_color);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
import styles from "./DeeplAuthKey.module.scss";
|
import styles from "./DeeplAuthKey.module.scss";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
import CircularProgress from "@mui/material/CircularProgress";
|
||||||
import ExternalLink from "@images/external_link.svg?react";
|
import ExternalLink from "@images/external_link.svg?react";
|
||||||
import { _Entry } from "../_atoms/_entry/_Entry";
|
import { _Entry } from "../_atoms/_entry/_Entry";
|
||||||
import { useState, useRef } from "react";
|
import { useState, useRef } from "react";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
export const DeeplAuthKey = (props) => {
|
export const DeeplAuthKey = (props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -22,11 +24,28 @@ export const DeeplAuthKey = (props) => {
|
|||||||
props.saveFunction();
|
props.saveFunction();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.variable === "" || props.variable === null) {
|
||||||
|
seIsEditable(true);
|
||||||
|
}
|
||||||
|
}, [props.variable]);
|
||||||
|
|
||||||
|
const is_disabled = props.state === "pending";
|
||||||
|
|
||||||
|
const save_button_class_names = clsx(styles.save_button, {
|
||||||
|
[styles.is_disabled]: is_disabled
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<div className={styles.entry_section_wrapper}>
|
<div className={styles.entry_section_wrapper}>
|
||||||
<_Entry ref={entryRef} width="30rem" onChange={onchangeEntryAuthKey} ui_variable={props.variable}/>
|
<_Entry ref={entryRef} width="30rem" onChange={onchangeEntryAuthKey} ui_variable={props.variable} is_disabled={is_disabled}/>
|
||||||
<button className={styles.save_button} onClick={saveAuthKey}>Save</button>
|
<button className={save_button_class_names} onClick={saveAuthKey}>
|
||||||
|
{is_disabled
|
||||||
|
? <CircularProgress size="1.4rem" sx={{ color: "var(--dark_basic_text_color)" }}/>
|
||||||
|
: <p className={styles.save_button_label}>Save</p>
|
||||||
|
}
|
||||||
|
</button>
|
||||||
{is_editable
|
{is_editable
|
||||||
? null
|
? null
|
||||||
:
|
:
|
||||||
|
|||||||
@@ -44,17 +44,25 @@
|
|||||||
.save_button {
|
.save_button {
|
||||||
padding: 0.8rem 1.2rem;
|
padding: 0.8rem 1.2rem;
|
||||||
background-color: var(--primary_600_color);
|
background-color: var(--primary_600_color);
|
||||||
color: var(--dark_basic_text_color);
|
|
||||||
font-size: 1.4rem;
|
|
||||||
border-radius: 0.4rem;
|
border-radius: 0.4rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
min-width: 5.4rem;
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--primary_500_color);
|
background-color: var(--primary_500_color);
|
||||||
}
|
}
|
||||||
&:active {
|
&:active {
|
||||||
background-color: var(--primary_700_color);
|
background-color: var(--primary_700_color);
|
||||||
}
|
}
|
||||||
|
&.is_disabled {
|
||||||
|
pointer-events: none;
|
||||||
|
background-color: var(--primary_800_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.save_button_label {
|
||||||
|
color: var(--dark_basic_text_color);
|
||||||
|
font-size: 1.4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.open_webpage_button_wrapper {
|
.open_webpage_button_wrapper {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
.container {
|
.container {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry_wrapper {
|
.entry_wrapper {
|
||||||
|
|||||||
@@ -98,9 +98,9 @@ const CTranslation2ComputeDevice_Box = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const DeeplAuthKey_Box = () => {
|
const DeeplAuthKey_Box = () => {
|
||||||
const [input_value, seInputValue] = useState("");
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { currentDeepLAuthKey, setDeepLAuthKey, deleteDeepLAuthKey } = useDeepLAuthKey();
|
const { currentDeepLAuthKey, setDeepLAuthKey, deleteDeepLAuthKey } = useDeepLAuthKey();
|
||||||
|
const [input_value, seInputValue] = useState(currentDeepLAuthKey.data);
|
||||||
|
|
||||||
const onChangeFunction = (value) => {
|
const onChangeFunction = (value) => {
|
||||||
seInputValue(value);
|
seInputValue(value);
|
||||||
@@ -124,6 +124,7 @@ const DeeplAuthKey_Box = () => {
|
|||||||
{translator: t("main_page.translator")}
|
{translator: t("main_page.translator")}
|
||||||
)}
|
)}
|
||||||
variable={input_value}
|
variable={input_value}
|
||||||
|
state={currentDeepLAuthKey.state}
|
||||||
onChangeFunction={onChangeFunction}
|
onChangeFunction={onChangeFunction}
|
||||||
saveFunction={saveFunction}
|
saveFunction={saveFunction}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ export const MessageContainer = () => {
|
|||||||
|
|
||||||
const asyncSetMessageBoxHeightInRem = async (data) => {
|
const asyncSetMessageBoxHeightInRem = async (data) => {
|
||||||
const minimized = await appWindow.isMinimized();
|
const minimized = await appWindow.isMinimized();
|
||||||
if (minimized === true) return; // don't save while the window is minimized.
|
if (minimized) return; // don't save while the window is minimized.
|
||||||
setMessageBoxHeightInRem(data);
|
setMessageBoxHeightInRem(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const calculateMessageBoxRatioAndHeight = () => {
|
const calculateMessageBoxRatioAndHeight = () => {
|
||||||
if (!currentIsAppliedInitMessageBoxHeight.data) {
|
if (!currentIsAppliedInitMessageBoxHeight.data) {
|
||||||
asyncSetMessageInputBoxRatio(currentMessageInputBoxRatio.data);
|
asyncSetMessageInputBoxRatio(currentMessageInputBoxRatio.data);
|
||||||
@@ -33,7 +34,7 @@ export const MessageContainer = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (log_box_ref.current && message_box_wrapper_ref.current) {
|
if (log_box_ref.current && message_box_wrapper_ref.current && container_ref.current) {
|
||||||
const container_height = container_ref.current.offsetHeight;
|
const container_height = container_ref.current.offsetHeight;
|
||||||
const container_padding_bottom = parseFloat(window.getComputedStyle(container_ref.current).paddingBottom);
|
const container_padding_bottom = parseFloat(window.getComputedStyle(container_ref.current).paddingBottom);
|
||||||
const total_height = container_height - container_padding_bottom;
|
const total_height = container_height - container_padding_bottom;
|
||||||
@@ -43,6 +44,8 @@ export const MessageContainer = () => {
|
|||||||
|
|
||||||
asyncSetMessageInputBoxRatio(message_box_ratio);
|
asyncSetMessageInputBoxRatio(message_box_ratio);
|
||||||
asyncSetMessageBoxHeightInRem(convertRatioToRem(message_box_ratio));
|
asyncSetMessageBoxHeightInRem(convertRatioToRem(message_box_ratio));
|
||||||
|
} else {
|
||||||
|
console.warn("References not ready for calculation");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -53,24 +56,26 @@ export const MessageContainer = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Note: I thought the part "1.4" is message box bottom padding + (message box separator height/2)
|
|
||||||
// but it should be fixed at 1.4. Idk why, tho.
|
|
||||||
asyncSetMessageBoxHeightInRem((position / FONT_SIZE_STANDARD) - 1.4);
|
asyncSetMessageBoxHeightInRem((position / FONT_SIZE_STANDARD) - 1.4);
|
||||||
}, [position]);
|
}, [position]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
asyncSetMessageBoxHeightInRem(convertRatioToRem(currentMessageInputBoxRatio.data));
|
asyncSetMessageBoxHeightInRem(convertRatioToRem(currentMessageInputBoxRatio.data));
|
||||||
}, [currentMessageInputBoxRatio.data]);
|
}, [currentMessageInputBoxRatio.data]);
|
||||||
|
|
||||||
const convertRatioToRem = (ratio) => {
|
const convertRatioToRem = (ratio) => {
|
||||||
|
if (!container_ref.current) return 0;
|
||||||
const container_height = container_ref.current.offsetHeight;
|
const container_height = container_ref.current.offsetHeight;
|
||||||
const container_padding_bottom = parseFloat(window.getComputedStyle(container_ref.current).paddingBottom);
|
const container_padding_bottom = parseFloat(window.getComputedStyle(container_ref.current).paddingBottom);
|
||||||
const total_height = container_height - container_padding_bottom;
|
const total_height = container_height - container_padding_bottom;
|
||||||
if (total_height === 0) return 0;
|
return total_height === 0 ? 0 : ((ratio / 100) * total_height / FONT_SIZE_STANDARD);
|
||||||
return ((ratio / 100) * total_height / FONT_SIZE_STANDARD);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
calculateMessageBoxRatioAndHeight();
|
||||||
|
updateIsAppliedInitMessageBoxHeight(true); // Ensure this happens after initial calculation
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let resizeTimeout;
|
let resizeTimeout;
|
||||||
|
|
||||||
@@ -86,10 +91,6 @@ export const MessageContainer = () => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
updateIsAppliedInitMessageBoxHeight(true);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container} ref={container_ref}>
|
<div className={styles.container} ref={container_ref}>
|
||||||
<div className={styles.log_box_resize_wrapper}
|
<div className={styles.log_box_resize_wrapper}
|
||||||
@@ -98,7 +99,7 @@ export const MessageContainer = () => {
|
|||||||
onMouseLeave={() => setIsHovered(false)}
|
onMouseLeave={() => setIsHovered(false)}
|
||||||
>
|
>
|
||||||
<LogBox />
|
<LogBox />
|
||||||
<MessageLogSettingsContainer to_visible_toggle_bar={is_hovered}/>
|
<MessageLogSettingsContainer to_visible_toggle_bar={is_hovered} />
|
||||||
</div>
|
</div>
|
||||||
<Separator {...separatorProps} onDragStart={calculateMessageBoxRatioAndHeight} />
|
<Separator {...separatorProps} onDragStart={calculateMessageBoxRatioAndHeight} />
|
||||||
<div
|
<div
|
||||||
@@ -112,10 +113,8 @@ export const MessageContainer = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Separator = ({ onDragStart, ...props }) => {
|
const Separator = ({ onDragStart, ...props }) => (
|
||||||
return (
|
|
||||||
<div tabIndex={0} className={styles.separator} {...props} onDragStart={onDragStart}>
|
<div tabIndex={0} className={styles.separator} {...props} onDragStart={onDragStart}>
|
||||||
<span className={styles.separator_line}></span>
|
<span className={styles.separator_line}></span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
|||||||
39
src-ui/app/snackbar_controller/SnackbarController.jsx
Normal file
39
src-ui/app/snackbar_controller/SnackbarController.jsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { clsx } from "clsx";
|
||||||
|
import Snackbar from "@mui/material/Snackbar";
|
||||||
|
import Slide from "@mui/material/Slide";
|
||||||
|
|
||||||
|
import styles from "./SnackbarController.module.scss";
|
||||||
|
import { useNotificationStatus } from "@logics_common";
|
||||||
|
|
||||||
|
export const SnackbarController = () => {
|
||||||
|
const { currentNotificationStatus, closeNotification } = useNotificationStatus();
|
||||||
|
|
||||||
|
const handleClose = (event, reason) => {
|
||||||
|
closeNotification(event, reason);
|
||||||
|
};
|
||||||
|
|
||||||
|
const snackbar_classname = clsx(styles.snackbar_content, {
|
||||||
|
[styles.is_success]: currentNotificationStatus.data.status === "success",
|
||||||
|
[styles.is_error]: currentNotificationStatus.data.status === "error",
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Snackbar
|
||||||
|
open={currentNotificationStatus.data.is_open}
|
||||||
|
onClose={handleClose}
|
||||||
|
TransitionComponent={SlideTransition}
|
||||||
|
key={currentNotificationStatus.data.key}
|
||||||
|
autoHideDuration={5000}
|
||||||
|
>
|
||||||
|
<div className={snackbar_classname}>
|
||||||
|
<p className={styles.snackbar_message}>{currentNotificationStatus.data.message}</p>
|
||||||
|
</div>
|
||||||
|
</Snackbar>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SlideTransition = (props) => {
|
||||||
|
return <Slide {...props} direction="up" />;
|
||||||
|
};
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
.snackbar_content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 2rem;
|
||||||
|
color: #fff;
|
||||||
|
&.is_success {
|
||||||
|
background-color: #368777;
|
||||||
|
}
|
||||||
|
&.is_error {
|
||||||
|
background-color: #bb4448;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.snackbar_message {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ export { useWindow } from "./useWindow";
|
|||||||
export { useIsOpenedConfigPage } from "./useIsOpenedConfigPage";
|
export { useIsOpenedConfigPage } from "./useIsOpenedConfigPage";
|
||||||
export { useIsSoftwareUpdateAvailable } from "./useIsSoftwareUpdateAvailable";
|
export { useIsSoftwareUpdateAvailable } from "./useIsSoftwareUpdateAvailable";
|
||||||
export { useIsSoftwareUpdating } from "./useIsSoftwareUpdating";
|
export { useIsSoftwareUpdating } from "./useIsSoftwareUpdating";
|
||||||
|
export { useNotificationStatus } from "./useNotificationStatus";
|
||||||
export { useOpenFolder } from "./useOpenFolder";
|
export { useOpenFolder } from "./useOpenFolder";
|
||||||
export { useMessage } from "./useMessage";
|
export { useMessage } from "./useMessage";
|
||||||
export { useUpdateSoftware } from "./useUpdateSoftware";
|
export { useUpdateSoftware } from "./useUpdateSoftware";
|
||||||
|
|||||||
42
src-ui/logics/common/useNotificationStatus.js
Normal file
42
src-ui/logics/common/useNotificationStatus.js
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { useStore_NotificationStatus } from "@store";
|
||||||
|
|
||||||
|
export const useNotificationStatus = () => {
|
||||||
|
const { currentNotificationStatus, updateNotificationStatus } = useStore_NotificationStatus();
|
||||||
|
|
||||||
|
const generateRandomKey = () => Math.random();
|
||||||
|
|
||||||
|
const showNotification_Error = (message) => {
|
||||||
|
updateNotificationStatus({
|
||||||
|
status: "error",
|
||||||
|
is_open: true,
|
||||||
|
key: generateRandomKey(),
|
||||||
|
message: message,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const showNotification_Success = (message) => {
|
||||||
|
updateNotificationStatus({
|
||||||
|
status: "success",
|
||||||
|
is_open: true,
|
||||||
|
key: generateRandomKey(),
|
||||||
|
message: message,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeNotification = (event, reason) => {
|
||||||
|
if (reason === "clickaway") return;
|
||||||
|
updateNotificationStatus((prev) => ({
|
||||||
|
...prev.data,
|
||||||
|
is_open: false,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
currentNotificationStatus,
|
||||||
|
updateNotificationStatus,
|
||||||
|
|
||||||
|
showNotification_Error,
|
||||||
|
showNotification_Success,
|
||||||
|
closeNotification,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -2,6 +2,9 @@ import { translator_status } from "@ui_configs";
|
|||||||
import { arrayToObject } from "@utils";
|
import { arrayToObject } from "@utils";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
useNotificationStatus,
|
||||||
|
|
||||||
|
|
||||||
useComputeMode,
|
useComputeMode,
|
||||||
useInitProgress,
|
useInitProgress,
|
||||||
useIsBackendReady,
|
useIsBackendReady,
|
||||||
@@ -167,6 +170,10 @@ export const useReceiveRoutes = () => {
|
|||||||
const { updateOscIpAddress } = useOscIpAddress();
|
const { updateOscIpAddress } = useOscIpAddress();
|
||||||
const { updateOscPort } = useOscPort();
|
const { updateOscPort } = useOscPort();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const { showNotification_Success, showNotification_Error } = useNotificationStatus();
|
||||||
|
|
||||||
const routes = {
|
const routes = {
|
||||||
// Common
|
// Common
|
||||||
"/run/feed_watchdog": () => {},
|
"/run/feed_watchdog": () => {},
|
||||||
@@ -494,6 +501,7 @@ export const useReceiveRoutes = () => {
|
|||||||
const error_route = error_routes[parsed_data.endpoint];
|
const error_route = error_routes[parsed_data.endpoint];
|
||||||
(error_route) ? error_route(parsed_data.result.data) : console.error(`Invalid endpoint: ${parsed_data.endpoint}\nresult: ${JSON.stringify(parsed_data.result)}`);
|
(error_route) ? error_route(parsed_data.result.data) : console.error(`Invalid endpoint: ${parsed_data.endpoint}\nresult: ${JSON.stringify(parsed_data.result)}`);
|
||||||
console.error(`status 400: ${JSON.stringify(parsed_data.result)}`);
|
console.error(`status 400: ${JSON.stringify(parsed_data.result)}`);
|
||||||
|
showNotification_Error(parsed_data.result.message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 348:
|
case 348:
|
||||||
|
|||||||
@@ -115,6 +115,12 @@ export const { atomInstance: Atom_IsSoftwareUpdateAvailable, useHook: useStore_I
|
|||||||
export const { atomInstance: Atom_InitProgress, useHook: useStore_InitProgress } = createAtomWithHook(0, "InitProgress");
|
export const { atomInstance: Atom_InitProgress, useHook: useStore_InitProgress } = createAtomWithHook(0, "InitProgress");
|
||||||
export const { atomInstance: Atom_IsBreakPoint, useHook: useStore_IsBreakPoint } = createAtomWithHook(false, "IsBreakPoint");
|
export const { atomInstance: Atom_IsBreakPoint, useHook: useStore_IsBreakPoint } = createAtomWithHook(false, "IsBreakPoint");
|
||||||
export const { atomInstance: Atom_IsSoftwareUpdating, useHook: useStore_IsSoftwareUpdating } = createAtomWithHook(false, "IsSoftwareUpdating");
|
export const { atomInstance: Atom_IsSoftwareUpdating, useHook: useStore_IsSoftwareUpdating } = createAtomWithHook(false, "IsSoftwareUpdating");
|
||||||
|
export const { atomInstance: Atom_NotificationStatus, useHook: useStore_NotificationStatus } = createAtomWithHook({
|
||||||
|
status: "",
|
||||||
|
is_open: false,
|
||||||
|
key: 0,
|
||||||
|
message: "",
|
||||||
|
}, "NotificationStatus");
|
||||||
|
|
||||||
// Main Page
|
// Main Page
|
||||||
// Functions
|
// Functions
|
||||||
|
|||||||
Reference in New Issue
Block a user