mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-28 08:44:41 +08:00
refactor: split useSettings hook into specialized hooks
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
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user