mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-11-03 05:58:01 +08:00
Before optimization: - useSettings.ts: 516 lines (single monolithic hook) After optimization: - useSettingsForm.ts: 158 lines (form state management) - useDirectorySettings.ts: 297 lines (directory management) - useSettingsMetadata.ts: 95 lines (metadata management) - useSettings.ts: 215 lines (composition layer) - Total: 765 lines (+249 lines, but with clear separation of concerns) Benefits: ✅ Single Responsibility Principle: each hook focuses on one domain ✅ Testability: independent hooks are easier to unit test ✅ Reusability: specialized hooks can be reused in other components ✅ Maintainability: reduced cognitive load per file ✅ Zero breaking changes: SettingsDialog auto-adapted to new interface Technical details: - useSettingsForm: pure form state + language sync - useDirectorySettings: directory selection/reset + default value computation - useSettingsMetadata: config path + portable mode + restart flag - useSettings: composition layer + save logic + reset logic
96 lines
2.3 KiB
TypeScript
96 lines
2.3 KiB
TypeScript
import { useCallback, useEffect, useState } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { toast } from "sonner";
|
|
import { settingsApi } from "@/lib/api";
|
|
|
|
export interface UseSettingsMetadataResult {
|
|
configPath: string;
|
|
isPortable: boolean;
|
|
requiresRestart: boolean;
|
|
isLoading: boolean;
|
|
openConfigFolder: () => Promise<void>;
|
|
acknowledgeRestart: () => void;
|
|
setRequiresRestart: (value: boolean) => void;
|
|
}
|
|
|
|
/**
|
|
* useSettingsMetadata - 元数据管理
|
|
* 负责:
|
|
* - configPath(配置文件路径)
|
|
* - isPortable(便携模式)
|
|
* - requiresRestart(需要重启标志)
|
|
* - 打开配置文件夹
|
|
*/
|
|
export function useSettingsMetadata(): UseSettingsMetadataResult {
|
|
const { t } = useTranslation();
|
|
|
|
const [configPath, setConfigPath] = useState("");
|
|
const [isPortable, setIsPortable] = useState(false);
|
|
const [requiresRestart, setRequiresRestart] = useState(false);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
|
|
// 加载元数据
|
|
useEffect(() => {
|
|
let active = true;
|
|
setIsLoading(true);
|
|
|
|
const load = async () => {
|
|
try {
|
|
const [appConfigPath, portable] = await Promise.all([
|
|
settingsApi.getAppConfigPath(),
|
|
settingsApi.isPortable(),
|
|
]);
|
|
|
|
if (!active) return;
|
|
|
|
setConfigPath(appConfigPath || "");
|
|
setIsPortable(portable);
|
|
} catch (error) {
|
|
console.error(
|
|
"[useSettingsMetadata] Failed to load metadata",
|
|
error,
|
|
);
|
|
} finally {
|
|
if (active) {
|
|
setIsLoading(false);
|
|
}
|
|
}
|
|
};
|
|
|
|
void load();
|
|
return () => {
|
|
active = false;
|
|
};
|
|
}, []);
|
|
|
|
const openConfigFolder = useCallback(async () => {
|
|
try {
|
|
await settingsApi.openAppConfigFolder();
|
|
} catch (error) {
|
|
console.error(
|
|
"[useSettingsMetadata] Failed to open config folder",
|
|
error,
|
|
);
|
|
toast.error(
|
|
t("settings.openFolderFailed", {
|
|
defaultValue: "打开目录失败",
|
|
}),
|
|
);
|
|
}
|
|
}, [t]);
|
|
|
|
const acknowledgeRestart = useCallback(() => {
|
|
setRequiresRestart(false);
|
|
}, []);
|
|
|
|
return {
|
|
configPath,
|
|
isPortable,
|
|
requiresRestart,
|
|
isLoading,
|
|
openConfigFolder,
|
|
acknowledgeRestart,
|
|
setRequiresRestart,
|
|
};
|
|
}
|