refactor: cleanup and minor improvements

- Remove unused useDarkMode hook (now using shadcn theme-provider)
- Clean up MCP components (remove redundant code)
- Add restart API to settings
- Minor type improvements
This commit is contained in:
Jason
2025-10-17 16:35:12 +08:00
parent d3f2c3c901
commit 8d6ab63648
9 changed files with 20 additions and 110 deletions

View File

@@ -57,7 +57,6 @@
"i18next": "^25.5.2",
"jsonc-parser": "^3.2.1",
"lucide-react": "^0.542.0",
"next-themes": "^0.4.6",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.65.0",

View File

@@ -1,5 +1,5 @@
import { X, Download } from "lucide-react";
import { useUpdate } from "../contexts/UpdateContext";
import { useUpdate } from "@/contexts/UpdateContext";
import { useTranslation } from "react-i18next";
interface UpdateBadgeProps {

View File

@@ -18,21 +18,11 @@ import {
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { mcpApi, type AppType } from "@/lib/api";
import { McpServer, McpServerSpec } from "../../types";
import {
mcpPresets,
getMcpPresetWithDescription,
} from "../../config/mcpPresets";
import { McpServer, McpServerSpec } from "@/types";
import { mcpPresets, getMcpPresetWithDescription } from "@/config/mcpPresets";
import McpWizardModal from "./McpWizardModal";
import {
extractErrorMessage,
translateMcpBackendError,
} from "../../utils/errorUtils";
import {
tomlToMcpServer,
extractIdFromToml,
mcpServerToToml,
} from "../../utils/tomlUtils";
import { extractErrorMessage, translateMcpBackendError } from "@/utils/errorUtils";
import { tomlToMcpServer, extractIdFromToml, mcpServerToToml } from "@/utils/tomlUtils";
import { useMcpValidation } from "./useMcpValidation";
interface McpFormModalProps {

View File

@@ -3,8 +3,8 @@ import { useTranslation } from "react-i18next";
import { Edit3, Trash2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { settingsApi } from "@/lib/api";
import { McpServer } from "../../types";
import { mcpPresets } from "../../config/mcpPresets";
import { McpServer } from "@/types";
import { mcpPresets } from "@/config/mcpPresets";
import McpToggle from "./McpToggle";
interface McpListItemProps {

View File

@@ -9,14 +9,11 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { mcpApi, type AppType } from "@/lib/api";
import { McpServer } from "../../types";
import { McpServer } from "@/types";
import McpListItem from "./McpListItem";
import McpFormModal from "./McpFormModal";
import { ConfirmDialog } from "../ConfirmDialog";
import {
extractErrorMessage,
translateMcpBackendError,
} from "../../utils/errorUtils";
import { extractErrorMessage, translateMcpBackendError } from "@/utils/errorUtils";
interface McpPanelProps {
open: boolean;

View File

@@ -9,7 +9,7 @@ import {
DialogTitle,
DialogFooter,
} from "@/components/ui/dialog";
import { McpServerSpec } from "../../types";
import { McpServerSpec } from "@/types";
interface McpWizardModalProps {
isOpen: boolean;

View File

@@ -551,7 +551,7 @@ const EndpointSpeedTest: React.FC<EndpointSpeedTestProps> = ({
className={`group flex cursor-pointer items-center justify-between px-3 py-2.5 rounded-lg border transition ${
isSelected
? "border-blue-500 bg-blue-50 dark:border-blue-500 dark:bg-blue-900/20"
: "border-gray-200 bg-white hover:border-gray-300 hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-900 dark:hover:border-gray-600 dark:hover:bg-gray-850"
: "border-gray-200 bg-white hover:border-gray-300 hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-900 dark:hover:border-gray-600 dark:hover:bg-gray-800"
}`}
>
<div className="flex min-w-0 flex-1 items-center gap-3">

View File

@@ -1,85 +0,0 @@
import { useState, useEffect } from "react";
export function useDarkMode() {
// 初始设为 false挂载后在 useEffect 中加载真实值
const [isDarkMode, setIsDarkMode] = useState<boolean>(false);
const [isInitialized, setIsInitialized] = useState(false);
const isDev = import.meta.env.DEV;
// 组件挂载后加载初始值(兼容 Tauri 环境)
useEffect(() => {
if (typeof window === "undefined") return;
try {
// 尝试读取已保存的偏好
const saved = localStorage.getItem("darkMode");
if (saved !== null) {
const savedBool = saved === "true";
setIsDarkMode(savedBool);
if (isDev)
console.log("[DarkMode] Loaded from localStorage:", savedBool);
} else {
// 回退到系统偏好
const prefersDark =
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches;
setIsDarkMode(prefersDark);
if (isDev)
console.log("[DarkMode] Using system preference:", prefersDark);
}
} catch (error) {
console.error("[DarkMode] Error loading preference:", error);
setIsDarkMode(false);
}
setIsInitialized(true);
}, []); // 仅在首次挂载时运行
// 将 dark 类应用到文档根节点
useEffect(() => {
if (!isInitialized) return;
// 添加短暂延迟以确保 Tauri 中 DOM 已就绪
const timer = setTimeout(() => {
try {
if (isDarkMode) {
document.documentElement.classList.add("dark");
if (isDev) console.log("[DarkMode] Added dark class to document");
} else {
document.documentElement.classList.remove("dark");
if (isDev) console.log("[DarkMode] Removed dark class from document");
}
// 检查类名是否已成功应用
const hasClass = document.documentElement.classList.contains("dark");
if (isDev) console.log("[DarkMode] Document has dark class:", hasClass);
} catch (error) {
console.error("[DarkMode] Error applying dark class:", error);
}
}, 0);
return () => clearTimeout(timer);
}, [isDarkMode, isInitialized]);
// 将偏好保存到 localStorage
useEffect(() => {
if (!isInitialized) return;
try {
localStorage.setItem("darkMode", isDarkMode.toString());
if (isDev) console.log("[DarkMode] Saved to localStorage:", isDarkMode);
} catch (error) {
console.error("[DarkMode] Error saving preference:", error);
}
}, [isDarkMode, isInitialized]);
const toggleDarkMode = () => {
setIsDarkMode((prev) => {
const newValue = !prev;
if (isDev) console.log("[DarkMode] Toggling from", prev, "to", newValue);
return newValue;
});
};
return { isDarkMode, toggleDarkMode };
}

View File

@@ -98,6 +98,15 @@ export const settingsApi = {
},
async openExternal(url: string): Promise<void> {
try {
const u = new URL(url);
const scheme = u.protocol.replace(":", "").toLowerCase();
if (scheme !== "http" && scheme !== "https") {
throw new Error("Unsupported URL scheme");
}
} catch {
throw new Error("Invalid URL");
}
await invoke("open_external", { url });
},
};