This commit completes stage 4 of the refactoring plan, focusing on cleanup and optimization of the modernized codebase. ## Key Changes ### Code Cleanup - Remove legacy `src/lib/styles.ts` (no longer needed) - Remove old modal components (`ImportProgressModal.tsx`, `ProviderList.tsx`) - Streamline `src/lib/tauri-api.ts` from 712 lines to 17 lines (-97.6%) - Remove global `window.api` pollution - Keep only event listeners (`tauriEvents.onProviderSwitched`) - All API calls now use modular `@/lib/api/*` layer ### Type System - Clean up `src/vite-env.d.ts` (remove 156 lines of outdated types) - Remove obsolete global type declarations - All TypeScript checks pass with zero errors ### Code Formatting - Format all source files with Prettier (82 files) - Fix formatting issues in 15 files: - App.tsx and core components - MCP management components - Settings module components - Provider management components - UI components ### Documentation Updates - Update `REFACTORING_CHECKLIST.md` with stage 4 progress - Mark completed tasks in `REFACTORING_MASTER_PLAN.md` ## Impact **Code Reduction:** - Total: -1,753 lines, +384 lines (net -1,369 lines) - tauri-api.ts: 712 → 17 lines (-97.6%) - Removed styles.ts: -82 lines - Removed vite-env.d.ts declarations: -156 lines **Quality Improvements:** - ✅ Zero TypeScript errors - ✅ Zero TODO/FIXME comments - ✅ 100% Prettier compliant - ✅ Zero `window.api` references - ✅ Fully modular API layer ## Testing - [x] TypeScript compilation passes - [x] Code formatting validated - [x] No linting errors Stage 4 completion: 100% Ready for stage 5 (testing and bug fixes)
151 lines
4.3 KiB
TypeScript
151 lines
4.3 KiB
TypeScript
import { useMemo } from "react";
|
|
import { FolderSearch, Undo2 } from "lucide-react";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Button } from "@/components/ui/button";
|
|
import { useTranslation } from "react-i18next";
|
|
import type { AppType } from "@/lib/api";
|
|
import type { ResolvedDirectories } from "@/hooks/useSettings";
|
|
|
|
interface DirectorySettingsProps {
|
|
appConfigDir?: string;
|
|
resolvedDirs: ResolvedDirectories;
|
|
onAppConfigChange: (value?: string) => void;
|
|
onBrowseAppConfig: () => Promise<void>;
|
|
onResetAppConfig: () => Promise<void>;
|
|
claudeDir?: string;
|
|
codexDir?: string;
|
|
onDirectoryChange: (app: AppType, value?: string) => void;
|
|
onBrowseDirectory: (app: AppType) => Promise<void>;
|
|
onResetDirectory: (app: AppType) => Promise<void>;
|
|
}
|
|
|
|
export function DirectorySettings({
|
|
appConfigDir,
|
|
resolvedDirs,
|
|
onAppConfigChange,
|
|
onBrowseAppConfig,
|
|
onResetAppConfig,
|
|
claudeDir,
|
|
codexDir,
|
|
onDirectoryChange,
|
|
onBrowseDirectory,
|
|
onResetDirectory,
|
|
}: DirectorySettingsProps) {
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<section className="space-y-4">
|
|
<header className="space-y-1">
|
|
<h3 className="text-sm font-medium">
|
|
{t("settings.configDirectoryOverride")}
|
|
</h3>
|
|
<p className="text-xs text-muted-foreground">
|
|
{t("settings.configDirectoryDescription")}
|
|
</p>
|
|
</header>
|
|
|
|
<DirectoryInput
|
|
label={t("settings.appConfigDir")}
|
|
description={t("settings.appConfigDirDescription")}
|
|
value={appConfigDir}
|
|
resolvedValue={resolvedDirs.appConfig}
|
|
placeholder={t("settings.browsePlaceholderApp")}
|
|
onChange={onAppConfigChange}
|
|
onBrowse={onBrowseAppConfig}
|
|
onReset={onResetAppConfig}
|
|
/>
|
|
|
|
<DirectoryInput
|
|
label={t("settings.claudeConfigDir")}
|
|
description={t("settings.claudeConfigDirDescription", {
|
|
defaultValue: "覆盖 Claude 配置目录 (settings.json)。",
|
|
})}
|
|
value={claudeDir}
|
|
resolvedValue={resolvedDirs.claude}
|
|
placeholder={t("settings.browsePlaceholderClaude")}
|
|
onChange={(val) => onDirectoryChange("claude", val)}
|
|
onBrowse={() => onBrowseDirectory("claude")}
|
|
onReset={() => onResetDirectory("claude")}
|
|
/>
|
|
|
|
<DirectoryInput
|
|
label={t("settings.codexConfigDir")}
|
|
description={t("settings.codexConfigDirDescription", {
|
|
defaultValue: "覆盖 Codex 配置目录。",
|
|
})}
|
|
value={codexDir}
|
|
resolvedValue={resolvedDirs.codex}
|
|
placeholder={t("settings.browsePlaceholderCodex")}
|
|
onChange={(val) => onDirectoryChange("codex", val)}
|
|
onBrowse={() => onBrowseDirectory("codex")}
|
|
onReset={() => onResetDirectory("codex")}
|
|
/>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
interface DirectoryInputProps {
|
|
label: string;
|
|
description?: string;
|
|
value?: string;
|
|
resolvedValue: string;
|
|
placeholder?: string;
|
|
onChange: (value?: string) => void;
|
|
onBrowse: () => Promise<void>;
|
|
onReset: () => Promise<void>;
|
|
}
|
|
|
|
function DirectoryInput({
|
|
label,
|
|
description,
|
|
value,
|
|
resolvedValue,
|
|
placeholder,
|
|
onChange,
|
|
onBrowse,
|
|
onReset,
|
|
}: DirectoryInputProps) {
|
|
const { t } = useTranslation();
|
|
const displayValue = useMemo(
|
|
() => value ?? resolvedValue ?? "",
|
|
[value, resolvedValue],
|
|
);
|
|
|
|
return (
|
|
<div className="space-y-1.5">
|
|
<div className="space-y-1">
|
|
<p className="text-xs font-medium text-foreground">{label}</p>
|
|
{description ? (
|
|
<p className="text-xs text-muted-foreground">{description}</p>
|
|
) : null}
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Input
|
|
value={displayValue}
|
|
placeholder={placeholder}
|
|
className="font-mono text-xs"
|
|
onChange={(event) => onChange(event.target.value)}
|
|
/>
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
size="icon"
|
|
onClick={onBrowse}
|
|
title={t("settings.browseDirectory")}
|
|
>
|
|
<FolderSearch className="h-4 w-4" />
|
|
</Button>
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
size="icon"
|
|
onClick={onReset}
|
|
title={t("settings.resetDefault")}
|
|
>
|
|
<Undo2 className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|