[Update/bugfix] UI: Add disable/enable UI function when osc query is disabled.

Fix the error that the mic mute sync couldn't enable/disable.
This commit is contained in:
Sakamoto Shiina
2025-05-30 15:32:03 +09:00
parent ae38ed165d
commit 88cb4f72b5
16 changed files with 116 additions and 13 deletions

View File

@@ -24,6 +24,9 @@ common_error:
invalid_value_speaker_phrase_timeout: "It cannot be set lower than '{{speaker_record_timeout_label}}' with a value of 0 or more." invalid_value_speaker_phrase_timeout: "It cannot be set lower than '{{speaker_record_timeout_label}}' with a value of 0 or more."
invalid_value_speaker_max_phrase: "You can set a number equal to or greater than 0." invalid_value_speaker_max_phrase: "You can set a number equal to or greater than 0."
common_warning:
unable_to_use_osc_query: "The functions below have been automatically disabled because receiving OSC data is not possible due to OSC IP Address settings."
main_page: main_page:
translation: "Translation" translation: "Translation"
transcription_send: "Voice2Chatbox" transcription_send: "Voice2Chatbox"

View File

@@ -24,6 +24,9 @@ common_error:
invalid_value_speaker_phrase_timeout: "0 以上で 「{{speaker_record_timeout_label}}」 より小さくすることはできません。" invalid_value_speaker_phrase_timeout: "0 以上で 「{{speaker_record_timeout_label}}」 より小さくすることはできません。"
invalid_value_speaker_max_phrase: "0 以上の数値を設定できます。" invalid_value_speaker_max_phrase: "0 以上の数値を設定できます。"
common_warning:
unable_to_use_osc_query: "OSC IP Address の設定によりOSCデータの受信ができないため、以下の機能が自動的に無効になっています。"
main_page: main_page:
translation: "翻訳" translation: "翻訳"
transcription_send: "音声認識 マイク" transcription_send: "音声認識 マイク"

View File

@@ -1443,7 +1443,7 @@ class Controller:
"data": config.VRC_MIC_MUTE_SYNC "data": config.VRC_MIC_MUTE_SYNC
} }
} }
return response return response
@staticmethod @staticmethod
def setDisableVrcMicMuteSync(*args, **kwargs) -> dict: def setDisableVrcMicMuteSync(*args, **kwargs) -> dict:

View File

@@ -25,6 +25,7 @@
--error_bc_active_color: #9c3938; --error_bc_active_color: #9c3938;
--success_bc_color: #368777; --success_bc_color: #368777;
--waring_color: #cb944f; --waring_color: #cb944f;
--waring_bc_color: #cf7b1b;
--dark_basic_text_color: #f2f2f2; --dark_basic_text_color: #f2f2f2;
--dark_100_color: #f5f7fb; --dark_100_color: #f5f7fb;

View File

@@ -101,11 +101,17 @@ export const VrcMicMuteSyncContainer = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { currentEnableVrcMicMuteSync, toggleEnableVrcMicMuteSync } = useEnableVrcMicMuteSync(); const { currentEnableVrcMicMuteSync, toggleEnableVrcMicMuteSync } = useEnableVrcMicMuteSync();
const variable = {
state: currentEnableVrcMicMuteSync.state,
data: currentEnableVrcMicMuteSync.data.is_enabled,
};
return ( return (
<CheckboxContainer <CheckboxContainer
label={t("config_page.others.vrc_mic_mute_sync.label")} label={t("config_page.others.vrc_mic_mute_sync.label")}
desc={t("config_page.others.vrc_mic_mute_sync.desc")} desc={t("config_page.others.vrc_mic_mute_sync.desc")}
variable={currentEnableVrcMicMuteSync} variable={variable}
is_available={currentEnableVrcMicMuteSync.data.is_available}
toggleFunction={toggleEnableVrcMicMuteSync} toggleFunction={toggleEnableVrcMicMuteSync}
/> />
); );

View File

@@ -77,7 +77,7 @@ const OpenVrcMicMuteSyncQuickSetting = () => {
return ( return (
<OpenQuickSettingButton <OpenQuickSettingButton
label={t("config_page.others.vrc_mic_mute_sync.label")} label={t("config_page.others.vrc_mic_mute_sync.label")}
variable={currentEnableVrcMicMuteSync.data} variable={currentEnableVrcMicMuteSync.data.is_enabled}
onClickFunction={onClickFunction} onClickFunction={onClickFunction}
/> />
); );

View File

@@ -14,6 +14,7 @@ export const SnackbarController = () => {
const snackbar_classname = clsx(styles.snackbar_content, { const snackbar_classname = clsx(styles.snackbar_content, {
[styles.is_success]: currentNotificationStatus.data.status === "success", [styles.is_success]: currentNotificationStatus.data.status === "success",
[styles.is_warning]: currentNotificationStatus.data.status === "warning",
[styles.is_error]: currentNotificationStatus.data.status === "error", [styles.is_error]: currentNotificationStatus.data.status === "error",
}); });

View File

@@ -6,6 +6,9 @@
&.is_success { &.is_success {
background-color: var(--success_bc_color); background-color: var(--success_bc_color);
} }
&.is_warning {
background-color: var(--waring_bc_color);
}
&.is_error { &.is_error {
background-color: var(--error_bc_color); background-color: var(--error_bc_color);
} }

View File

@@ -3,15 +3,16 @@ import styles from "./Checkbox.module.scss";
export const Checkbox = ({ export const Checkbox = ({
checkboxId, checkboxId,
variable, variable,
is_available = true,
toggleFunction, toggleFunction,
size = "2.8rem", size = "2.8rem",
color = "var(--primary_600_color)",
borderWidth = "0.2rem", borderWidth = "0.2rem",
padding = "2rem", padding = "2rem",
}) => { }) => {
const wrapper_class_names = clsx(styles.checkbox_wrapper, { const wrapper_class_names = clsx(styles.checkbox_wrapper, {
[styles.is_disabled]: variable.state === "pending", [styles.is_disabled]: !is_available,
[styles.is_pending]: variable.state === "pending",
}); });
return ( return (
@@ -21,7 +22,6 @@ export const Checkbox = ({
htmlFor={checkboxId} htmlFor={checkboxId}
style={{ style={{
"--checkbox-size": size, "--checkbox-size": size,
"--checkbox-color": color,
"--checkbox-border-width": borderWidth, "--checkbox-border-width": borderWidth,
"--checkbox-padding": padding, "--checkbox-padding": padding,
}} }}

View File

@@ -18,12 +18,19 @@
border: var(--checkbox-color, var(--primary_600_color)) solid var(--checkbox-border-width, 0.2rem); border: var(--checkbox-color, var(--primary_600_color)) solid var(--checkbox-border-width, 0.2rem);
} }
} }
&.is_disabled { &.is_pending {
pointer-events: none; pointer-events: none;
& .cbx { & .cbx {
border-color: var(--primary_800_color); border-color: var(--primary_800_color);
} }
} }
&.is_disabled {
pointer-events: none;
& .cbx {
filter: grayscale(100%);
border-color: var(--dark_800_color);
}
}
} }
.checkbox_wrapper .cbx { .checkbox_wrapper .cbx {

View File

@@ -11,5 +11,6 @@ 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 { useHandleNetworkConnection } from "./useHandleNetworkConnection";
export { useHandleOscQuery } from "./useHandleOscQuery";
export { useIsVrctAvailable } from "./useIsVrctAvailable"; export { useIsVrctAvailable } from "./useIsVrctAvailable";
export { useFetch } from "./useFetch"; export { useFetch } from "./useFetch";

View File

@@ -0,0 +1,44 @@
import { useTranslation } from "react-i18next";
import { useNotificationStatus } from "@logics_common";
import {
useEnableVrcMicMuteSync,
} from "@logics_configs";
export const useHandleOscQuery = () => {
const { t } = useTranslation();
const { showNotification_Warning } = useNotificationStatus();
const { updateEnableVrcMicMuteSync } = useEnableVrcMicMuteSync();
const handleOscQuery = ({is_osc_query_enabled, disabled_functions}) => {
if (!is_osc_query_enabled && disabled_functions.length > 0) {
const BASE_LABEL = t("common_warning.unable_to_use_osc_query");
let items_label = "";
for (const disabled_function of disabled_functions) {
if (disabled_function === "vrc_mic_mute_sync") {
updateEnableVrcMicMuteSync({
is_enabled: !is_osc_query_enabled,
is_available: false,
});
const item = `- ${t("config_page.others.vrc_mic_mute_sync.label")}`;
items_label = `${items_label}\n${item}`;
}
}
const label = `${BASE_LABEL}${items_label}`;
showNotification_Warning(
label,
{ hide_duration: 10000, }
);
} else if (is_osc_query_enabled) {
updateEnableVrcMicMuteSync((old_value) => ({
...old_value.data,
is_available: true,
}));
}
};
return {
handleOscQuery,
};
};

View File

@@ -5,6 +5,16 @@ export const useNotificationStatus = () => {
const generateRandomKey = () => Math.random(); const generateRandomKey = () => Math.random();
const showNotification_Warning = (message, options = {}) => {
updateNotificationStatus({
status: "warning",
is_open: true,
key: generateRandomKey(),
message: message,
options: options,
});
};
const showNotification_Error = (message, options = {}) => { const showNotification_Error = (message, options = {}) => {
updateNotificationStatus({ updateNotificationStatus({
status: "error", status: "error",
@@ -37,6 +47,7 @@ export const useNotificationStatus = () => {
currentNotificationStatus, currentNotificationStatus,
updateNotificationStatus, updateNotificationStatus,
showNotification_Warning,
showNotification_Error, showNotification_Error,
showNotification_Success, showNotification_Success,
closeNotification, closeNotification,

View File

@@ -12,7 +12,7 @@ export const useEnableVrcMicMuteSync = () => {
const toggleEnableVrcMicMuteSync = () => { const toggleEnableVrcMicMuteSync = () => {
pendingEnableVrcMicMuteSync(); pendingEnableVrcMicMuteSync();
if (currentEnableVrcMicMuteSync.data) { if (currentEnableVrcMicMuteSync.data.is_enabled) {
asyncStdoutToPython("/set/disable/vrc_mic_mute_sync"); asyncStdoutToPython("/set/disable/vrc_mic_mute_sync");
} else { } else {
asyncStdoutToPython("/set/enable/vrc_mic_mute_sync"); asyncStdoutToPython("/set/enable/vrc_mic_mute_sync");

View File

@@ -7,6 +7,7 @@ import {
useIsVrctAvailable, useIsVrctAvailable,
useNotificationStatus, useNotificationStatus,
useHandleNetworkConnection, useHandleNetworkConnection,
useHandleOscQuery,
useSoftwareVersion, useSoftwareVersion,
useComputeMode, useComputeMode,
@@ -83,6 +84,7 @@ export const useReceiveRoutes = () => {
const { updateComputeMode } = useComputeMode(); const { updateComputeMode } = useComputeMode();
const { updateInitProgress } = useInitProgress(); const { updateInitProgress } = useInitProgress();
const { updateIsBackendReady } = useIsBackendReady(); const { updateIsBackendReady } = useIsBackendReady();
const { handleOscQuery } = useHandleOscQuery();
const { restoreWindowGeometry } = useWindow(); const { restoreWindowGeometry } = useWindow();
const { updateIsMainPageCompactMode } = useIsMainPageCompactMode(); const { updateIsMainPageCompactMode } = useIsMainPageCompactMode();
const { const {
@@ -219,6 +221,12 @@ export const useReceiveRoutes = () => {
})); }));
}, },
"/run/connected_network": handleNetworkConnection, "/run/connected_network": handleNetworkConnection,
"/run/enable_osc_query": ({data, disabled_functions}) => {
handleOscQuery({
is_osc_query_enabled: data,
disabled_functions: disabled_functions,
});
},
// Main Page // Main Page
// Page Controls // Page Controls
@@ -480,9 +488,15 @@ export const useReceiveRoutes = () => {
"/set/enable/logger_feature": updateEnableAutoExportMessageLogs, "/set/enable/logger_feature": updateEnableAutoExportMessageLogs,
"/set/disable/logger_feature": updateEnableAutoExportMessageLogs, "/set/disable/logger_feature": updateEnableAutoExportMessageLogs,
"/get/data/vrc_mic_mute_sync": updateEnableVrcMicMuteSync, "/get/data/vrc_mic_mute_sync": (payload) => updateEnableVrcMicMuteSync((old_value) => {
"/set/enable/vrc_mic_mute_sync": updateEnableVrcMicMuteSync, return {...old_value.data, is_enabled: payload};
"/set/disable/vrc_mic_mute_sync": updateEnableVrcMicMuteSync, }),
"/set/enable/vrc_mic_mute_sync": (payload) => updateEnableVrcMicMuteSync((old_value) => {
return {...old_value.data, is_enabled: payload};
}),
"/set/disable/vrc_mic_mute_sync": (payload) => updateEnableVrcMicMuteSync((old_value) => {
return {...old_value.data, is_enabled: payload};
}),
"/get/data/send_message_to_vrc": updateEnableSendMessageToVrc, "/get/data/send_message_to_vrc": updateEnableSendMessageToVrc,
"/set/enable/send_message_to_vrc": updateEnableSendMessageToVrc, "/set/enable/send_message_to_vrc": updateEnableSendMessageToVrc,

View File

@@ -60,10 +60,19 @@ export const createAtomWithHook = (initialValue, base_name, options) => {
}; };
const updateAtom = (payload, options = {}) => { const updateAtom = (payload, options = {}) => {
const { remain_state = false, set_state } = options; const { remain_state = false, set_state, lock_state } = options;
setAtom((currentValue) => { setAtom((currentValue) => {
const new_state = set_state ?? (remain_state ? currentValue.state : "ok"); let new_state;
if (lock_state) {
new_state = set_state;
} else {
if (currentValue.lock_state) {
new_state = currentValue.state;
} else {
new_state = set_state ?? (remain_state ? currentValue.state : "ok");
}
}
const updated_data = typeof payload === "function" const updated_data = typeof payload === "function"
? payload(currentValue) ? payload(currentValue)