refactor: frontend (#5068)

* refactor: setting components

* refactor: frontend

* fix: settings router
This commit is contained in:
Sline
2025-10-15 18:57:44 +08:00
committed by GitHub
parent a591ee1efc
commit 0b4403b67b
34 changed files with 1072 additions and 861 deletions

View File

@@ -133,11 +133,22 @@ export const useLogData = () => {
mutate(`$sub$${subscriptKey}`);
}, [date, subscriptKey]);
const previousLogLevel = useRef<string | undefined>(undefined);
useEffect(() => {
if (!logLevel) return;
if (!logLevel) {
previousLogLevel.current = logLevel ?? undefined;
return;
}
if (previousLogLevel.current === logLevel) {
return;
}
previousLogLevel.current = logLevel;
ws.current?.close();
setDate(Date.now());
}, [logLevel]);
}, [logLevel, setDate]);
const refreshGetClashLog = (clear = false) => {
if (clear) {

View File

@@ -1,4 +1,4 @@
import { useState, useEffect, useRef, useCallback } from "react";
import { useEffect, useRef, useCallback, useReducer } from "react";
// import { useClashInfo } from "@/hooks/use-clash";
// import { useVisibility } from "@/hooks/use-visibility";
@@ -196,12 +196,11 @@ export const useTrafficMonitorEnhanced = () => {
});
}
const [, forceUpdate] = useState({});
const [, forceRender] = useReducer((version: number) => version + 1, 0);
const cleanupRef = useRef<(() => void) | null>(null);
// 强制组件更新
const triggerUpdate = useCallback(() => {
forceUpdate({});
const bumpRenderVersion = useCallback(() => {
forceRender();
}, []);
// 注册引用计数
@@ -250,9 +249,8 @@ export const useTrafficMonitorEnhanced = () => {
}),
};
globalSampler.addDataPoint(dataPoint);
triggerUpdate();
}
}, [traffic, triggerUpdate]);
}, [traffic]);
// const { data: monitorData, error } = useSWR<ISystemMonitorOverview>(
// shouldFetch ? "getSystemMonitorOverviewSafe" : null,
@@ -328,9 +326,9 @@ export const useTrafficMonitorEnhanced = () => {
const clearData = useCallback(() => {
if (globalSampler) {
globalSampler.clear();
triggerUpdate();
bumpRenderVersion();
}
}, [triggerUpdate]);
}, [bumpRenderVersion]);
// 获取采样器统计信息
const getSamplerStats = useCallback(() => {

View File

@@ -1,7 +1,11 @@
import { useEffect, useState } from "react";
export const useVisibility = () => {
const [visible, setVisible] = useState(true);
const [visible, setVisible] = useState(() =>
typeof document === "undefined"
? true
: document.visibilityState === "visible",
);
useEffect(() => {
const handleVisibilityChange = () => {
@@ -9,16 +13,15 @@ export const useVisibility = () => {
};
const handleFocus = () => setVisible(true);
const handleClick = () => setVisible(true);
const handlePointerDown = () => setVisible(true);
handleVisibilityChange();
document.addEventListener("focus", handleFocus);
document.addEventListener("pointerdown", handleClick);
document.addEventListener("pointerdown", handlePointerDown);
document.addEventListener("visibilitychange", handleVisibilityChange);
return () => {
document.removeEventListener("focus", handleFocus);
document.removeEventListener("pointerdown", handleClick);
document.removeEventListener("pointerdown", handlePointerDown);
document.removeEventListener("visibilitychange", handleVisibilityChange);
};
}, []);

46
src/hooks/use-window.ts Normal file
View File

@@ -0,0 +1,46 @@
import { use } from "react";
import { WindowContext, type WindowContextType } from "@/providers/window";
export const useWindow = () => {
const context = use(WindowContext);
if (context === undefined) {
throw new Error("useWindow must be used within WindowProvider");
}
return context;
};
export const useWindowControls = () => {
const {
maximized,
minimize,
toggleMaximize,
close,
toggleFullscreen,
currentWindow,
} = useWindow();
return {
maximized,
minimize,
toggleMaximize,
close,
toggleFullscreen,
currentWindow,
} satisfies Pick<
WindowContextType,
| "maximized"
| "minimize"
| "toggleMaximize"
| "close"
| "toggleFullscreen"
| "currentWindow"
>;
};
export const useWindowDecorations = () => {
const { decorated, toggleDecorations, refreshDecorated } = useWindow();
return { decorated, toggleDecorations, refreshDecorated } satisfies Pick<
WindowContextType,
"decorated" | "toggleDecorations" | "refreshDecorated"
>;
};

View File

@@ -1,129 +0,0 @@
import { getCurrentWindow } from "@tauri-apps/api/window";
import { debounce } from "lodash-es";
import React, {
createContext,
useCallback,
use,
useEffect,
useState,
} from "react";
interface WindowContextType {
decorated: boolean | null;
maximized: boolean | null;
toggleDecorations: () => Promise<void>;
refreshDecorated: () => Promise<boolean>;
minimize: () => void;
close: () => void;
toggleMaximize: () => Promise<void>;
toggleFullscreen: () => Promise<void>;
currentWindow: ReturnType<typeof getCurrentWindow>;
}
const WindowContext = createContext<WindowContextType | undefined>(undefined);
export const WindowProvider: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
const currentWindow = getCurrentWindow();
const [decorated, setDecorated] = useState<boolean | null>(null);
const [maximized, setMaximized] = useState<boolean | null>(null);
const close = useCallback(() => currentWindow.close(), [currentWindow]);
const minimize = useCallback(() => currentWindow.minimize(), [currentWindow]);
useEffect(() => {
const checkMaximized = debounce(async () => {
const value = await currentWindow.isMaximized();
if (maximized !== value) {
setMaximized(value);
}
}, 100);
const unlistenResize = currentWindow.onResized(checkMaximized);
return () => {
unlistenResize.then((fn) => fn());
};
}, [currentWindow, maximized]);
const toggleMaximize = useCallback(async () => {
if (await currentWindow.isMaximized()) {
await currentWindow.unmaximize();
setMaximized(false);
} else {
await currentWindow.maximize();
setMaximized(true);
}
}, [currentWindow]);
const toggleFullscreen = useCallback(async () => {
await currentWindow.setFullscreen(!(await currentWindow.isFullscreen()));
}, [currentWindow]);
const refreshDecorated = useCallback(async () => {
const val = await currentWindow.isDecorated();
setDecorated(val);
return val;
}, [currentWindow]);
const toggleDecorations = useCallback(async () => {
const currentVal = await currentWindow.isDecorated();
await currentWindow.setDecorations(!currentVal);
setDecorated(!currentVal);
}, [currentWindow]);
useEffect(() => {
refreshDecorated();
currentWindow.setMinimizable?.(true);
}, [currentWindow, refreshDecorated]);
return (
<WindowContext
value={{
decorated,
maximized,
toggleDecorations,
refreshDecorated,
minimize,
close,
toggleMaximize,
toggleFullscreen,
currentWindow,
}}
>
{children}
</WindowContext>
);
};
export const useWindow = () => {
const context = use(WindowContext);
if (context === undefined) {
throw new Error("useWindow must be used within WindowProvider");
}
return context;
};
export const useWindowControls = () => {
const {
maximized,
minimize,
toggleMaximize,
close,
toggleFullscreen,
currentWindow,
} = useWindow();
return {
maximized,
minimize,
toggleMaximize,
close,
toggleFullscreen,
currentWindow,
};
};
export const useWindowDecorations = () => {
const { decorated, toggleDecorations, refreshDecorated } = useWindow();
return { decorated, toggleDecorations, refreshDecorated };
};