Merge branch 'ui_refactor' into develop

This commit is contained in:
Sakamoto Shiina
2025-11-08 07:47:13 +09:00
344 changed files with 232 additions and 316 deletions

View File

@@ -9,6 +9,6 @@
<body> <body>
<div id="root"></div> <div id="root"></div>
<script type="module" src="./src-ui/app/index.jsx"></script> <script type="module" src="./src-ui/views/app/index.jsx"></script>
</body> </body>
</html> </html>

View File

@@ -17,7 +17,7 @@ import {
useAdvancedSettings, useAdvancedSettings,
} from "@logics_configs"; } from "@logics_configs";
import { ui_configs } from "../ui_configs"; import { ui_configs } from "./ui_configs";
export const _useBackendErrorHandling = () => { export const _useBackendErrorHandling = () => {
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -595,7 +595,7 @@ const buildCategoryApiFromSettings = (settings, settingsArray, Category, extraFu
return { ...api, ...extraFunctions }; return { ...api, ...extraFunctions };
}; };
const createCategoryHook = (Category) => { export const createCategoryHook = (Category) => {
return () => { return () => {
const { settings } = useSettingsLogics(SETTINGS_ARRAY, Category); const { settings } = useSettingsLogics(SETTINGS_ARRAY, Category);
const extraFunctions = useConfigFunctions(Category); const extraFunctions = useConfigFunctions(Category);
@@ -603,32 +603,3 @@ const createCategoryHook = (Category) => {
return { ...autoApi }; return { ...autoApi };
}; };
}; };
// --- 自動エクスポート: SETTINGS_ARRAY に含まれるユニークな Category ごとに use<Category> を作って export ---
// 例: Category === "Appearance" -> export const useAppearance = createCategoryHook("Appearance");
// const uniqueCategories = Array.from(new Set(SETTINGS_ARRAY.map((s) => s.Category)));
// 動的に named export を作る(静的解析を壊さないために明示的に定義)
/* eslint-disable import/prefer-default-export */
export const useAppearance = createCategoryHook("Appearance");
export const useDevice = createCategoryHook("Device");
export const useTranslation = createCategoryHook("Translation");
export const useTranscription = createCategoryHook("Transcription");
export const useVr = createCategoryHook("Vr");
export const useOthers = createCategoryHook("Others");
// export const useHotkeys = createCategoryHook("Hotkeys");
export const useAdvancedSettings = createCategoryHook("AdvancedSettings");
// If you later add other categories, you can either manually add:
// export const useDevice = createCategoryHook("Device");
// or uncomment the code below to auto-attach to module.exports (less ideal for tree-shaking).
//
// Auto-attach (not recommended for tree-shaking in bundlers):
// uniqueCategories.forEach((Category) => {
// const hookName = `use${Category}`;
// module.exports[hookName] = createCategoryHook(Category);
// });
/* eslint-enable import/prefer-default-export */

View File

@@ -201,3 +201,102 @@ export const useConfigFunctions = (Category) => {
return {}; return {};
} }
}; };
import { useState, useEffect, useCallback, useMemo } from "react";
export const useSliderLogic = ({
variable,
setterFunction,
postUpdateAction,
min,
max,
step = 1,
show_label_values = null,
marks_step,
setter_timing = "on_change_committed",
}) => {
if (marks_step === undefined) {
marks_step = step;
}
const [ui_value, setUiValue] = useState(variable);
const decimalPlaces = marks_step.toString().includes('.')
? marks_step.toString().split('.')[1].length
: 0;
const labelFormatter = useCallback((value) => {
if (show_label_values && show_label_values.length > 0) {
return show_label_values.includes(value) ? value : "";
}
return value.toFixed(decimalPlaces);
}, [show_label_values, decimalPlaces]);
const marks = useMemo(() => {
if (show_label_values === null) {
return null;
}
return createMarks(min, max, marks_step, labelFormatter);
}, [min, max, marks_step, labelFormatter, show_label_values]);
let onchangeFunction;
let onchangeCommittedFunction;
if (setter_timing === "on_change") {
onchangeFunction = useCallback((value) => {
setUiValue(value);
setterFunction(value);
}, [setterFunction]);
onchangeCommittedFunction = null;
} else if (setter_timing === "on_change_committed") {
onchangeFunction = useCallback((value) => {
setUiValue(value);
}, []);
onchangeCommittedFunction = useCallback((value) => {
setterFunction(value);
}, [setterFunction]);
} else {
console.error(`Invalid 'setter_timing' value provided to useSliderLogic. Expected 'on_change' or 'on_change_committed'. Received: ${setter_timing}`);
}
useEffect(() => {
if (variable !== ui_value) {
setUiValue(variable);
}
if (postUpdateAction) {
postUpdateAction();
}
}, [variable]);
return {
ui_value,
onchangeFunction,
onchangeCommittedFunction,
marks,
};
};
const createMarks = (min, max, marks_step = 1, labelFormatter = (value) => value) => {
const marks = [];
let variable = min;
for (let i = 0; variable <= max; i++) {
const fixedValue = parseFloat(variable.toFixed(10));
marks.push({ value: fixedValue, label: `${labelFormatter(fixedValue)}` });
variable += marks_step;
variable = parseFloat(variable.toFixed(10));
if (i > 1000) {
console.error("Loop limit exceeded (1000 iterations). createMarks()");
break;
}
}
return marks;
};

View File

@@ -1,25 +1,21 @@
// export { useDevice } from "./device/useDevice"; import { createCategoryHook } from "./config_page_setter/ui_config_setter.js";
// export { useAppearance } from "./appearance/useAppearance";
export const useAppearance = createCategoryHook("Appearance");
export const useDevice = createCategoryHook("Device");
export const useTranslation = createCategoryHook("Translation");
export const useTranscription = createCategoryHook("Transcription");
export const useVr = createCategoryHook("Vr");
export const useOthers = createCategoryHook("Others");
export const useAdvancedSettings = createCategoryHook("AdvancedSettings");
// Exceptional exports that are not part of SETTINGS_ARRAY or have custom logic.
export { useHotkeys } from "./config_page_setter/hotkeys/useHotkeys.js";
export { useSupporters } from "./config_page_setter/supporters/useSupporters.js";
export { usePlugins } from "./config_page_setter/plugins/usePlugins.js";
export { useSettingBoxScrollPosition } from "./config_page_setter/_aux/useSettingBoxScrollPosition.js";
export { export {
useAppearance, useSliderLogic,
useDevice, } from "./config_page_setter/useSettingsLogics.js";
useOthers,
useTranscription,
useTranslation,
useVr,
// useHotkeys,
useAdvancedSettings,
} from "../../ui_config_setter.js";
// export { useOthers } from "./others/useOthers";
// export { useTranscription } from "./transcription/useTranscription";
// export { useTranslation } from "./translation/useTranslation";
// export { useVr } from "./vr/useVr";
export { useHotkeys } from "./hotkeys/useHotkeys";
// export { useAdvancedSettings } from "./advanced_settings/useAdvancedSettings";
export { useSupporters } from "./supporters/useSupporters";
export { usePlugins } from "./plugins/usePlugins";
export { useSettingBoxScrollPosition } from "./useSettingBoxScrollPosition";

View File

@@ -2,7 +2,7 @@ import * as common from "@logics_common";
import * as main from "@logics_main"; import * as main from "@logics_main";
import * as configs from "@logics_configs"; import * as configs from "@logics_configs";
import { _useBackendErrorHandling } from "./_useBackendErrorHandling"; import { _useBackendErrorHandling } from "./_useBackendErrorHandling";
import { SETTINGS_ARRAY } from "../ui_config_setter"; import { SETTINGS_ARRAY } from "./configs/config_page_setter/ui_config_setter";
export const STATIC_ROUTE_META_LIST = [ export const STATIC_ROUTE_META_LIST = [
// Common // Common

View File

@@ -3,8 +3,27 @@ import styles from "./Slider.module.scss";
import MUI_Slider from "@mui/material/Slider"; import MUI_Slider from "@mui/material/Slider";
import clsx from "clsx"; import clsx from "clsx";
import { useSliderLogic } from "@logics_configs";
export const Slider = (props) => { export const Slider = (props) => {
const location = props.valueLabelDisplayLocation || "top"; const location = props.valueLabelDisplayLocation || "top";
const {
ui_value,
onchangeFunction,
onchangeCommittedFunction,
marks
} = useSliderLogic({
variable: props.variable,
setterFunction: props.setterFunction,
setter_timing: props.setter_timing,
postUpdateAction: props.postUpdateAction,
min: props.min,
max: props.max,
step: props.step,
show_label_values: props.show_label_values,
marks_step: props.marks_step,
});
const sliderSx = { const sliderSx = {
color: "var(--dark_700_color)", color: "var(--dark_700_color)",
@@ -86,13 +105,13 @@ export const Slider = (props) => {
aria-label="Default" aria-label="Default"
// valueLabelDisplay="on" // valueLabelDisplay="on"
valueLabelDisplay={props.valueLabelDisplay ? props.valueLabelDisplay : "auto"} valueLabelDisplay={props.valueLabelDisplay ? props.valueLabelDisplay : "auto"}
value={props.variable} value={ui_value}
step={props.step} step={props.step == null ? null : Number(props.step)}
min={Number(props.min)} min={Number(props.min)}
max={Number(props.max)} max={Number(props.max)}
onChange={(_e, value) => props.onchangeFunction(value)} onChange={(_e, value) => onchangeFunction(value)}
onChangeCommitted={(_e, value) => onChangeCommitted={(_e, value) =>
props.onchangeCommittedFunction ? props.onchangeCommittedFunction(value) : null onchangeCommittedFunction ? onchangeCommittedFunction(value) : null
} }
onMouseEnter={(event) => onMouseEnter={(event) =>
props.onMouseEnterFunction ? props.onMouseEnterFunction(event) : null props.onMouseEnterFunction ? props.onMouseEnterFunction(event) : null
@@ -100,10 +119,10 @@ export const Slider = (props) => {
onMouseLeave={(event) => onMouseLeave={(event) =>
props.onMouseLeaveFunction ? props.onMouseLeaveFunction(event) : null props.onMouseLeaveFunction ? props.onMouseLeaveFunction(event) : null
} }
marks={props.marks} marks={marks}
track={props.track} track={props.track === undefined ? false : props.track}
orientation={props.orientation} orientation={props.orientation}
valueLabelFormat={`${props.valueLabelFormat ? props.valueLabelFormat : props.variable}`} valueLabelFormat={`${props.valueLabelFormat ? props.valueLabelFormat : ui_value}`}
sx={sliderSx} sx={sliderSx}
/> />
</div> </div>

View File

@@ -19,7 +19,7 @@ import {
WordFilterListToggleComponent, WordFilterListToggleComponent,
DownloadModels, DownloadModels,
MessageFormat, MessageFormat,
} from "../_components/"; } from "../_components";
import { Checkbox } from "@common_components"; import { Checkbox } from "@common_components";
const LabeledContainer = ({ children, label, desc, custom_class_name }) => ( const LabeledContainer = ({ children, label, desc, custom_class_name }) => (

View File

@@ -15,7 +15,7 @@ import {
import { import {
SectionLabelComponent, SectionLabelComponent,
} from "../_components/"; } from "../_components";
import OpenFolderSvg from "@images/open_folder.svg?react"; import OpenFolderSvg from "@images/open_folder.svg?react";
import HelpSvg from "@images/help.svg?react"; import HelpSvg from "@images/help.svg?react";

View File

@@ -56,42 +56,16 @@ const UiScalingContainer = () => {
const { currentUiScaling, setUiScaling } = useAppearance(); const { currentUiScaling, setUiScaling } = useAppearance();
const { asyncUpdateBreakPoint } = useWindow(); const { asyncUpdateBreakPoint } = useWindow();
const [ui_ui_scaling, setUiUiScaling] = useState(currentUiScaling.data);
const onchangeFunction = (value) => {
setUiUiScaling(value);
};
const onchangeCommittedFunction = (value) => {
setUiScaling(value);
};
useEffect(() => {
setUiUiScaling(currentUiScaling.data);
asyncUpdateBreakPoint();
}, [currentUiScaling.data]);
// [Duplicated]
const createMarks = (min, max) => {
const marks = [];
for (let value = min; value <= max; value += 10) {
const label = ([50,70,90,110,130,150,170,190].includes(value)) ? "" : value;
marks.push({ value, label: `${label}` });
}
return marks;
};
const marks = createMarks(40, 200);
return ( return (
<SliderContainer <SliderContainer
label={t("config_page.appearance.ui_size.label") + " (%)"} label={t("config_page.appearance.ui_size.label") + " (%)"}
min="40" variable={currentUiScaling.data}
max="200" setterFunction={setUiScaling}
onchangeCommittedFunction={onchangeCommittedFunction} postUpdateAction={asyncUpdateBreakPoint}
onchangeFunction={onchangeFunction} min={40}
variable={ui_ui_scaling} max={200}
marks={marks} step={10}
step={null} show_label_values={[40, 60, 80, 100, 120, 140, 160, 180, 200]}
track={false}
/> />
); );
}; };
@@ -100,41 +74,16 @@ const UiScalingContainer = () => {
export const MessageLogUiScalingContainer = () => { export const MessageLogUiScalingContainer = () => {
const { t } = useI18n(); const { t } = useI18n();
const { currentMessageLogUiScaling, setMessageLogUiScaling } = useAppearance(); const { currentMessageLogUiScaling, setMessageLogUiScaling } = useAppearance();
const [ui_message_log_ui_scaling, setUiMessageLogUiScaling] = useState(currentMessageLogUiScaling.data);
const onchangeFunction = (value) => {
setUiMessageLogUiScaling(value);
};
const onchangeCommittedFunction = (value) => {
setMessageLogUiScaling(value);
};
useEffect(() => {
setUiMessageLogUiScaling(currentMessageLogUiScaling.data);
}, [currentMessageLogUiScaling.data]);
// [Duplicated]
const createMarks = (min, max) => {
const marks = [];
for (let value = min; value <= max; value += 10) {
const label = ([50,70,90,110,130,150,170,190].includes(value)) ? "" : value;
marks.push({ value, label: `${label}` });
}
return marks;
};
const marks = createMarks(40, 200);
return ( return (
<SliderContainer <SliderContainer
label={t("config_page.appearance.textbox_ui_size.label") + " (%)"} label={t("config_page.appearance.textbox_ui_size.label") + " (%)"}
min="40" variable={currentMessageLogUiScaling.data}
max="200" setterFunction={setMessageLogUiScaling}
onchangeCommittedFunction={onchangeCommittedFunction} min={40}
onchangeFunction={onchangeFunction} max={200}
variable={ui_message_log_ui_scaling} step={10}
marks={marks} show_label_values={[40, 60, 80, 100, 120, 140, 160, 180, 200]}
step={null}
track={false}
/> />
); );
}; };
@@ -197,40 +146,15 @@ const FontFamilyContainer = () => {
const TransparencyContainer = () => { const TransparencyContainer = () => {
const { t } = useI18n(); const { t } = useI18n();
const { currentTransparency, setTransparency } = useAppearance(); const { currentTransparency, setTransparency } = useAppearance();
const [ui_message_log_ui_scaling, setUiTransparency] = useState(currentTransparency.data);
const onchangeFunction = (value) => {
setUiTransparency(value);
};
const onchangeCommittedFunction = (value) => {
setTransparency(value);
};
useEffect(() => {
setUiTransparency(currentTransparency.data);
}, [currentTransparency.data]);
// [Duplicated]
const createMarks = (min, max) => {
const marks = [];
for (let value = min; value <= max; value += 10) {
marks.push({ value, label: `${value}` });
}
return marks;
};
const marks = createMarks(40, 100);
return ( return (
<SliderContainer <SliderContainer
label={t("config_page.appearance.transparency.label") + " (%)"} label={t("config_page.appearance.transparency.label") + " (%)"}
min="40" variable={currentTransparency.data}
max="100" setterFunction={setTransparency}
onchangeCommittedFunction={onchangeCommittedFunction} min={40}
onchangeFunction={onchangeFunction} max={100}
variable={ui_message_log_ui_scaling} step={10}
marks={marks}
step={null}
track={false}
/> />
); );
}; };

View File

@@ -16,7 +16,7 @@ import {
DropdownMenu, DropdownMenu,
ThresholdComponent, ThresholdComponent,
SwitchBox, SwitchBox,
} from "../_components/"; } from "../_components";
export const Device = () => { export const Device = () => {
return ( return (

Some files were not shown because too many files have changed in this diff Show More