[Update] Config Page: Device Tab. Add dynamic energy threshold functionally and sync slider and entry component.

This commit is contained in:
Sakamoto Shiina
2024-09-12 15:43:16 +09:00
parent 166759075a
commit b12908f01f
16 changed files with 282 additions and 95 deletions

View File

@@ -35,8 +35,8 @@ const StartPythonFacadeComponent = () => {
const { getSelectedMicHost } = useSelectedMicHost();
const { getSelectedMicDevice } = useSelectedMicDevice();
const { getSelectedSpeakerDevice } = useSelectedSpeakerDevice();
const { getMicThreshold } = useMicThreshold();
const { getSpeakerThreshold } = useSpeakerThreshold();
const { getMicThreshold, getEnableAutomaticMicThreshold } = useMicThreshold();
const { getSpeakerThreshold, getEnableAutomaticSpeakerThreshold } = useSpeakerThreshold();
const { getEnableAutoClearMessageBox } = useEnableAutoClearMessageBox();
const { getSendMessageButtonType } = useSendMessageButtonType();
@@ -52,6 +52,8 @@ const StartPythonFacadeComponent = () => {
getMicThreshold();
getSpeakerThreshold();
getEnableAutomaticMicThreshold();
getEnableAutomaticSpeakerThreshold();
getEnableAutoClearMessageBox();
getSendMessageButtonType();

View File

@@ -3,14 +3,14 @@ import { useState } from "react";
import styles from "./Switchbox.module.scss";
export const Switchbox = (props) => {
const [is_turned_on, setIsTurnedOn] = useState(false);
const [is_hovered, setIsHovered] = useState(false);
const [is_mouse_down, setIsMouseDown] = useState(false);
const getClassNames = (baseClass) => clsx(baseClass, {
[styles.is_active]: (is_turned_on === true),
// [styles.is_loading]: (currentState.state === "loading"),
const is_loading = (props.variable.state === "loading");
const getClassNames = (base_class) => clsx(base_class, {
[styles.is_active]: (props.variable.data === true),
[styles.is_loading]: is_loading,
[styles.is_hovered]: is_hovered,
[styles.is_mouse_down]: is_mouse_down,
});
@@ -21,21 +21,22 @@ export const Switchbox = (props) => {
const onMouseUp = () => setIsMouseDown(false);
const toggleFunction = () => {
setIsTurnedOn(!is_turned_on);
props.toggleFunction();
};
return (
<div className={styles.switchbox_container}>
<div className={styles.switchbox_wrapper}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
onClick={toggleFunction}
<div className={getClassNames(styles.switchbox_wrapper)}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
onClick={toggleFunction}
>
<div className={getClassNames(styles.toggle_control)}>
<span className={getClassNames(styles.control)}></span>
{is_loading && <span className={styles.loader}></span>}
</div>
</div>
</div>

View File

@@ -15,6 +15,9 @@
cursor: pointer;
padding: 2rem;
height: 100%;
&.is_loading {
pointer-events: none;
}
}
.toggle_control {
@@ -22,4 +25,8 @@
display: flex;
justify-content: center;
align-items: center;
}
.loader {
@include loader(2rem, 0.2rem, right, -4rem);
}

View File

@@ -17,14 +17,26 @@ export const ThresholdComponent = (props) => {
import MicSvg from "@images/mic.svg?react";
import { useMicThreshold } from "@logics_configs/useMicThreshold";
const MicComponent = (props) => {
const { currentMicThreshold, setMicThreshold } = useMicThreshold();
const {
currentMicThreshold,
setMicThreshold,
currentEnableAutomaticMicThreshold,
} = useMicThreshold();
const [ui_threshold, setUiThreshold] = useState(currentMicThreshold);
const {volumeCheckStart_Mic, volumeCheckStop_Mic, currentMicThresholdCheckStatus } = useVolume();
const {
volumeCheckStart_Mic,
volumeCheckStop_Mic,
currentMicThresholdCheckStatus,
} = useVolume();
useEffect(() => {
setUiThreshold(currentMicThreshold);
}, [currentMicThreshold]);
if (currentEnableAutomaticMicThreshold.data === true) {
setUiThreshold("Auto");
} else {
setUiThreshold(currentMicThreshold);
}
}, [currentMicThreshold, currentEnableAutomaticMicThreshold]);
const setUiThresholdFunction = (payload_ui_threshold) => {
setUiThreshold(payload_ui_threshold);
@@ -33,6 +45,8 @@ const MicComponent = (props) => {
setMicThreshold(payload_threshold);
};
const is_disable = currentEnableAutomaticMicThreshold.data === true ? true : false;
return (
<>
<VolumeCheckButton
@@ -53,6 +67,7 @@ const MicComponent = (props) => {
ui_threshold={ui_threshold}
setUiThresholdFunction={setUiThresholdFunction}
setThresholdFunction={setThresholdFunction}
is_disable={is_disable}
/>
</>
);
@@ -60,13 +75,25 @@ const MicComponent = (props) => {
import HeadphonesSvg from "@images/headphones.svg?react";
import { useSpeakerThreshold } from "@logics_configs/useSpeakerThreshold";
const SpeakerComponent = (props) => {
const { currentSpeakerThreshold, setSpeakerThreshold } = useSpeakerThreshold();
const {
currentSpeakerThreshold,
setSpeakerThreshold,
currentEnableAutomaticSpeakerThreshold,
} = useSpeakerThreshold();
const [ui_threshold, setUiThreshold] = useState(currentSpeakerThreshold);
const {volumeCheckStart_Speaker, volumeCheckStop_Speaker, currentSpeakerThresholdCheckStatus } = useVolume();
const {
volumeCheckStart_Speaker,
volumeCheckStop_Speaker,
currentSpeakerThresholdCheckStatus,
} = useVolume();
useEffect(() => {
setUiThreshold(currentSpeakerThreshold);
}, [currentSpeakerThreshold]);
if (currentEnableAutomaticSpeakerThreshold.data === true) {
setUiThreshold("Auto");
} else {
setUiThreshold(currentSpeakerThreshold);
}
}, [currentSpeakerThreshold, currentEnableAutomaticSpeakerThreshold]);
const setUiThresholdFunction = (payload_ui_threshold) => {
setUiThreshold(payload_ui_threshold);
@@ -75,6 +102,8 @@ const SpeakerComponent = (props) => {
setSpeakerThreshold(payload_threshold);
};
const is_disable = currentEnableAutomaticSpeakerThreshold.data === true ? true : false;
return (
<>
<VolumeCheckButton
@@ -95,6 +124,7 @@ const SpeakerComponent = (props) => {
ui_threshold={ui_threshold}
setUiThresholdFunction={setUiThresholdFunction}
setThresholdFunction={setThresholdFunction}
is_disable={is_disable}
/>
</>
);

View File

@@ -1,4 +1,3 @@
import { useState } from "react";
import styles from "./SliderAndMeter.module.scss";
import {
useStore_MicVolume,
@@ -18,48 +17,56 @@ export const SliderAndMeter = (props) => {
);
};
import { useMicThreshold } from "@logics_configs/useMicThreshold";
const ThresholdVolumeMeter_Mic = (props) => {
const { currentMicVolume } = useStore_MicVolume();
const { currentEnableAutomaticMicThreshold } = useMicThreshold();
const currentVolumeVariable = Math.min(currentMicVolume.data, props.max);
const volume_width_percentage = (currentVolumeVariable / props.max) * 100;
return (
<>
<VolumeMeter volume_width_percentage={volume_width_percentage} volume={currentVolumeVariable} threshold={props.ui_threshold}/>
<input
type="range"
min={props.min}
max={props.max}
value={props.ui_threshold}
onChange={(e) => props.setUiThresholdFunction(e.target.value)}
onMouseUp={(e) => props.setThresholdFunction(e.target.value)}
className={styles.threshold_slider}
/>
{currentEnableAutomaticMicThreshold.data === false &&
<input
type="range"
min={props.min}
max={props.max}
value={props.ui_threshold}
onChange={(e) => props.setUiThresholdFunction(e.target.value)}
onMouseUp={(e) => props.setThresholdFunction(e.target.value)}
className={styles.threshold_slider}
/>
}
</>
);
};
import { useSpeakerThreshold } from "@logics_configs/useSpeakerThreshold";
const ThresholdVolumeMeter_Speaker = (props) => {
const { currentSpeakerVolume } = useStore_SpeakerVolume();
const { currentEnableAutomaticSpeakerThreshold } = useSpeakerThreshold();
const currentVolumeVariable = Math.min(currentSpeakerVolume.data, props.max);
const volume_width_percentage = (currentVolumeVariable / props.max) * 100;
return (
<>
<VolumeMeter volume_width_percentage={volume_width_percentage} volume={currentVolumeVariable} threshold={props.ui_threshold} />
<input
type="range"
min={props.min}
max={props.max}
value={props.ui_threshold}
onChange={(e) => props.setUiThresholdFunction(e.target.value)}
onMouseUp={(e) => props.setThresholdFunction(e.target.value)}
className={styles.threshold_slider}
/>
{currentEnableAutomaticSpeakerThreshold.data === false &&
<input
type="range"
min={props.min}
max={props.max}
value={props.ui_threshold}
onChange={(e) => props.setUiThresholdFunction(e.target.value)}
onMouseUp={(e) => props.setThresholdFunction(e.target.value)}
className={styles.threshold_slider}
/>
}
</>
);
};

View File

@@ -1,3 +1,4 @@
import clsx from "clsx";
import styles from "./ThresholdEntry.module.scss";
export const ThresholdEntry = (props) => {
@@ -22,9 +23,13 @@ const ThresholdEntry_Mic = (props) => {
}
};
const class_names = clsx(styles.entry_input_area, {
[styles.is_disable]: props.is_disable
});
return (
<input
className={styles.entry_input_area}
className={class_names}
onChange={onChangeFunction}
value={props.ui_threshold}
/>
@@ -40,9 +45,13 @@ const ThresholdEntry_Speaker = (props) => {
}
};
const class_names = clsx(styles.entry_input_area, {
[styles.is_disable]: props.is_disable
});
return (
<input
className={styles.entry_input_area}
className={class_names}
onChange={onChangeFunction}
value={props.ui_threshold}
/>

View File

@@ -15,4 +15,9 @@
height: 100%;
font-size: 1.4rem;
resize: none;
color: var(--dark_basic_text_color);
&.is_disable {
color: var(--dark_500_color);
pointer-events: none;
}
}

View File

@@ -38,19 +38,19 @@ export const DropdownMenuContainer = (props) => {
};
export const ThresholdContainer = (props) => {
return (
<div className={styles.threshold_container}>
<div className={styles.threshold_switch_section}>
<LabelComponent label={props.label} desc={props.desc} />
<Switchbox {...props}/>
</div>
<div className={styles.threshold_section}>
<ThresholdComponent {...props}/>
</div>
</div>
);
};
// export const ThresholdContainer = (props) => {
// return (
// <div className={styles.threshold_container}>
// <div className={styles.threshold_switch_section}>
// <LabelComponent label={props.label} desc={props.desc} />
// <Switchbox {...props}/>
// </div>
// <div className={styles.threshold_section}>
// <ThresholdComponent {...props}/>
// </div>
// </div>
// );
// };
export const useSettingBox = () => {

View File

@@ -17,25 +17,25 @@
width: 100%;
}
.threshold_container {
display: flex;
width: 100%;
flex-direction: column;
justify-content: space-between;
align-items: center;
gap: 2rem;
}
// .threshold_container {
// display: flex;
// width: 100%;
// flex-direction: column;
// justify-content: space-between;
// align-items: center;
// gap: 2rem;
// }
.threshold_switch_section {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
}
// .threshold_switch_section {
// display: flex;
// width: 100%;
// justify-content: space-between;
// align-items: center;
// }
.threshold_section {
width: 100%;
}
// .threshold_section {
// width: 100%;
// }
.deepl_auth_key_label_section {
max-width: 34rem;

View File

@@ -1,7 +1,6 @@
import { useTranslation } from "react-i18next";
import styles from "./Device.module.scss";
import {
ThresholdContainer,
useOnMouseLeaveDropdownMenu,
} from "../components/useSettingBox";
export const Device = () => {
@@ -18,16 +17,19 @@ import { useSelectedMicHost } from "@logics_configs/useSelectedMicHost";
import { useMicDeviceList } from "@logics_configs/useMicDeviceList";
import { useSelectedMicDevice } from "@logics_configs/useSelectedMicDevice";
import { useMicThreshold } from "@logics_configs/useMicThreshold";
import { LabelComponent } from "../components/label_component/LabelComponent";
import { DropdownMenu } from "../components/dropdown_menu/DropdownMenu";
import { ThresholdComponent } from "../components/threshold_component/ThresholdComponent";
import { Switchbox } from "../components/switchbox/Switchbox";
const Mic_Container = () => {
const { t } = useTranslation();
const { currentSelectedMicHost, setSelectedMicHost } = useSelectedMicHost();
const { currentMicHostList, getMicHostList } = useMicHostList();
const { onMouseLeaveFunction } = useOnMouseLeaveDropdownMenu();
const { currentEnableAutomaticMicThreshold, toggleEnableAutomaticMicThreshold } = useMicThreshold();
const selectFunction_host = (selected_data) => {
setSelectedMicHost(selected_data.selected_id);
@@ -40,6 +42,20 @@ const Mic_Container = () => {
setSelectedMicDevice(selected_data.selected_id);
};
const getLabels = () => {
if (currentEnableAutomaticMicThreshold.data === true) {
return {
label: t("config_page.mic_dynamic_energy_threshold.label_for_automatic"),
desc: t("config_page.mic_dynamic_energy_threshold.desc_for_automatic"),
};
} else {
return {
label: t("config_page.mic_dynamic_energy_threshold.label_for_manual"),
desc: t("config_page.mic_dynamic_energy_threshold.desc_for_manual"),
};
}
};
return (
<div className={styles.mic_container}>
@@ -73,13 +89,20 @@ const Mic_Container = () => {
</div>
</div>
<div className={styles.threshold_container}>
<ThresholdContainer
label={t("config_page.mic_dynamic_energy_threshold.label_for_manual")}
desc={t("config_page.mic_dynamic_energy_threshold.desc_for_manual")}
id="mic_threshold"
min="0"
max="2000"
/>
<div className={styles.threshold_switch_section}>
<LabelComponent {...getLabels()} />
<Switchbox
variable={currentEnableAutomaticMicThreshold}
toggleFunction={toggleEnableAutomaticMicThreshold}
/>
</div>
<div className={styles.threshold_section}>
<ThresholdComponent
id="mic_threshold"
min="0"
max="2000"
/>
</div>
</div>
</div>
);
@@ -87,16 +110,34 @@ const Mic_Container = () => {
import { useSpeakerDeviceList } from "@logics_configs/useSpeakerDeviceList";
import { useSelectedSpeakerDevice } from "@logics_configs/useSelectedSpeakerDevice";
import { useSpeakerThreshold } from "@logics_configs/useSpeakerThreshold";
const Speaker_Container = () => {
const { t } = useTranslation();
const { currentSelectedSpeakerDevice, setSelectedSpeakerDevice } = useSelectedSpeakerDevice();
const { currentSpeakerDeviceList, getSpeakerDeviceList } = useSpeakerDeviceList();
const { onMouseLeaveFunction } = useOnMouseLeaveDropdownMenu();
const { currentEnableAutomaticSpeakerThreshold, toggleEnableAutomaticSpeakerThreshold } = useSpeakerThreshold();
const selectFunction = (selected_data) => {
setSelectedSpeakerDevice(selected_data.selected_id);
};
const getLabels = () => {
if (currentEnableAutomaticSpeakerThreshold.data === true) {
return {
label: t("config_page.speaker_dynamic_energy_threshold.label_for_automatic"),
desc: t("config_page.speaker_dynamic_energy_threshold.desc_for_automatic"),
};
} else {
return {
label: t("config_page.speaker_dynamic_energy_threshold.label_for_manual"),
desc: t("config_page.speaker_dynamic_energy_threshold.desc_for_manual"),
};
}
};
return (
<div className={styles.speaker_container}>
<div className={styles.device_container} onMouseLeave={onMouseLeaveFunction}>
@@ -116,13 +157,20 @@ const Speaker_Container = () => {
</div>
</div>
<div className={styles.threshold_container}>
<ThresholdContainer
label={t("config_page.speaker_dynamic_energy_threshold.label_for_manual")}
desc={t("config_page.speaker_dynamic_energy_threshold.desc_for_manual")}
id="speaker_threshold"
min="0"
max="4000"
/>
<div className={styles.threshold_switch_section}>
<LabelComponent {...getLabels()}/>
<Switchbox
variable={currentEnableAutomaticSpeakerThreshold}
toggleFunction={toggleEnableAutomaticSpeakerThreshold}
/>
</div>
<div className={styles.threshold_section}>
<ThresholdComponent
id="speaker_threshold"
min="0"
max="4000"
/>
</div>
</div>
</div>
);

View File

@@ -22,6 +22,31 @@
padding: 2rem;
}
.threshold_container {
display: flex;
width: 100%;
flex-direction: column;
justify-content: space-between;
align-items: center;
gap: 2rem;
}
.threshold_switch_section {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
}
.threshold_section {
width: 100%;
}
.device_label {
font-size: 1.8rem;
color: var(--dark_basic_text_color);

View File

@@ -1,9 +1,10 @@
import { useStore_MicThreshold } from "@store";
import { useStore_MicThreshold, useStore_EnableAutomaticMicThreshold } from "@store";
import { useStdoutToPython } from "@logics/useStdoutToPython";
export const useMicThreshold = () => {
const { asyncStdoutToPython } = useStdoutToPython();
const { updateMicThreshold, currentMicThreshold } = useStore_MicThreshold();
const { updateEnableAutomaticMicThreshold, currentEnableAutomaticMicThreshold } = useStore_EnableAutomaticMicThreshold();
const getMicThreshold = () => {
asyncStdoutToPython("/config/input_mic_energy_threshold");
@@ -13,10 +14,29 @@ export const useMicThreshold = () => {
asyncStdoutToPython("/controller/callback_set_mic_energy_threshold", mic_threshold);
};
const getEnableAutomaticMicThreshold = () => {
updateEnableAutomaticMicThreshold(() => new Promise(() => {}));
asyncStdoutToPython("/config/input_mic_dynamic_energy_threshold");
};
const toggleEnableAutomaticMicThreshold = () => {
updateEnableAutomaticMicThreshold(() => new Promise(() => {}));
if (currentEnableAutomaticMicThreshold.data) {
asyncStdoutToPython("/controller/callback_disable_mic_dynamic_energy_threshold");
} else {
asyncStdoutToPython("/controller/callback_enable_mic_dynamic_energy_threshold");
}
};
return {
currentMicThreshold,
getMicThreshold,
setMicThreshold,
updateMicThreshold,
currentEnableAutomaticMicThreshold,
getEnableAutomaticMicThreshold,
toggleEnableAutomaticMicThreshold,
updateEnableAutomaticMicThreshold,
};
};

View File

@@ -1,9 +1,10 @@
import { useStore_SpeakerThreshold } from "@store";
import { useStore_SpeakerThreshold, useStore_EnableAutomaticSpeakerThreshold } from "@store";
import { useStdoutToPython } from "@logics/useStdoutToPython";
export const useSpeakerThreshold = () => {
const { asyncStdoutToPython } = useStdoutToPython();
const { updateSpeakerThreshold, currentSpeakerThreshold } = useStore_SpeakerThreshold();
const { updateEnableAutomaticSpeakerThreshold, currentEnableAutomaticSpeakerThreshold } = useStore_EnableAutomaticSpeakerThreshold();
const getSpeakerThreshold = () => {
asyncStdoutToPython("/config/input_speaker_energy_threshold");
@@ -13,10 +14,29 @@ export const useSpeakerThreshold = () => {
asyncStdoutToPython("/controller/callback_set_speaker_energy_threshold", speaker_threshold);
};
const getEnableAutomaticSpeakerThreshold = () => {
updateEnableAutomaticSpeakerThreshold(() => new Promise(() => {}));
asyncStdoutToPython("/config/input_speaker_dynamic_energy_threshold");
};
const toggleEnableAutomaticSpeakerThreshold = () => {
updateEnableAutomaticSpeakerThreshold(() => new Promise(() => {}));
if (currentEnableAutomaticSpeakerThreshold.data) {
asyncStdoutToPython("/controller/callback_disable_speaker_dynamic_energy_threshold");
} else {
asyncStdoutToPython("/controller/callback_enable_speaker_dynamic_energy_threshold");
}
};
return {
currentSpeakerThreshold,
getSpeakerThreshold,
setSpeakerThreshold,
updateSpeakerThreshold,
currentEnableAutomaticSpeakerThreshold,
getEnableAutomaticSpeakerThreshold,
toggleEnableAutomaticSpeakerThreshold,
updateEnableAutomaticSpeakerThreshold,
};
};

View File

@@ -36,8 +36,10 @@ export const useReceiveRoutes = () => {
const { updateSelectedMicDevice } = useSelectedMicDevice();
const { updateSpeakerDeviceList } = useSpeakerDeviceList();
const { updateSelectedSpeakerDevice } = useSelectedSpeakerDevice();
const { updateMicThreshold } = useMicThreshold();
const { updateSpeakerThreshold } = useSpeakerThreshold();
const { updateMicThreshold, updateEnableAutomaticMicThreshold } = useMicThreshold();
const { updateSpeakerThreshold, updateEnableAutomaticSpeakerThreshold } = useSpeakerThreshold();
const { updateEnableAutoClearMessageBox } = useEnableAutoClearMessageBox();
const { updateSendMessageButtonType } = useSendMessageButtonType();
@@ -94,6 +96,12 @@ export const useReceiveRoutes = () => {
"/config/input_speaker_energy_threshold": updateSpeakerThreshold,
"/controller/callback_set_speaker_energy_threshold": updateSpeakerThreshold,
"/config/input_mic_dynamic_energy_threshold": updateEnableAutomaticMicThreshold,
"/controller/callback_enable_mic_dynamic_energy_threshold": updateEnableAutomaticMicThreshold,
"/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,
"/controller/callback_messagebox_send": updateSentMessageLogById,
"/action/transcription_send_mic_message": addSentMessageLog,

View File

@@ -133,6 +133,8 @@ export const { atomInstance: Atom_SpeakerThresholdCheckStatus, useHook: useStore
export const { atomInstance: Atom_MicThreshold, useHook: useStore_MicThreshold } = createAtomWithHook(0, "MicThreshold");
export const { atomInstance: Atom_SpeakerThreshold, useHook: useStore_SpeakerThreshold } = createAtomWithHook(0, "SpeakerThreshold");
export const { atomInstance: Atom_EnableAutomaticMicThreshold, useHook: useStore_EnableAutomaticMicThreshold } = createAsyncAtomWithHook(false, "EnableAutomaticMicThreshold");
export const { atomInstance: Atom_EnableAutomaticSpeakerThreshold, useHook: useStore_EnableAutomaticSpeakerThreshold } = createAsyncAtomWithHook(false, "EnableAutomaticSpeakerThreshold");
export const { atomInstance: Atom_SendMessageFormat, useHook: useStore_SendMessageFormat } = createAtomWithHook({
before: "",

View File

@@ -76,6 +76,9 @@ $toggle_control_size: $toggle_height - calc($toggle_gutter * 2);
background: $toggle_control_color;
transition: left $toggle_control_speed $toggle_control_ease;
}
&.is_loading:after{
background-color: var(--dark_600_color);
}
&.is_hovered {
background-color: var(--dark_725_color);
}