mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-28 07:14:40 +08:00
refactor: reorganize component and hook structure; remove unused modules
This commit is contained in:
12
src/App.tsx
12
src/App.tsx
@@ -1,12 +0,0 @@
|
||||
import Layout from "./pages/_layout";
|
||||
import { AppDataProvider } from "./providers/app-data-provider";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<AppDataProvider>
|
||||
<Layout />
|
||||
</AppDataProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
@@ -1,21 +0,0 @@
|
||||
import { Box, BoxProps } from "@mui/material";
|
||||
import React from "react";
|
||||
|
||||
interface CenterProps extends BoxProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Center: React.FC<CenterProps> = ({ children, ...props }) => {
|
||||
return (
|
||||
<Box
|
||||
display="flex"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
width="100%"
|
||||
height="100%"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -3,14 +3,14 @@ import { Divider, Stack, Typography } from "@mui/material";
|
||||
import { useMemo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { useClash } from "@/hooks/use-clash";
|
||||
import {
|
||||
useAppUptime,
|
||||
useClashConfig,
|
||||
useRulesData,
|
||||
useSystemProxyAddress,
|
||||
useSystemProxyData,
|
||||
} from "@/hooks/app-data";
|
||||
import { useClash } from "@/hooks/use-clash";
|
||||
} from "@/hooks/use-clash-data";
|
||||
|
||||
import { EnhancedCard } from "./enhanced-card";
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useMemo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { closeAllConnections } from "tauri-plugin-mihomo-api";
|
||||
|
||||
import { useClashConfig } from "@/hooks/app-data";
|
||||
import { useClashConfig } from "@/hooks/use-clash-data";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { patchClashMode } from "@/services/cmds";
|
||||
import type { TranslationKey } from "@/types/generated/i18n-keys";
|
||||
|
||||
@@ -34,7 +34,11 @@ import { useNavigate } from "react-router";
|
||||
import { delayGroup, healthcheckProxyProvider } from "tauri-plugin-mihomo-api";
|
||||
|
||||
import { EnhancedCard } from "@/components/home/enhanced-card";
|
||||
import { useClashConfig, useProxiesData, useRulesData } from "@/hooks/app-data";
|
||||
import {
|
||||
useClashConfig,
|
||||
useProxiesData,
|
||||
useRulesData,
|
||||
} from "@/hooks/use-clash-data";
|
||||
import { useProfiles } from "@/hooks/use-profiles";
|
||||
import { useProxySelection } from "@/hooks/use-proxy-selection";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
|
||||
@@ -24,7 +24,7 @@ import { useCallback, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
import { useRefreshAll } from "@/hooks/app-data";
|
||||
import { useRefreshAll } from "@/hooks/use-clash-data";
|
||||
import { openWebUrl, updateProfile } from "@/services/cmds";
|
||||
import { showNotice } from "@/services/noticeService";
|
||||
import parseTraffic from "@/utils/parse-traffic";
|
||||
|
||||
@@ -20,9 +20,9 @@ import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router";
|
||||
import useSWR from "swr";
|
||||
|
||||
import { useServiceInstaller } from "@/hooks/use-service-installer";
|
||||
import { useSystemState } from "@/hooks/use-system-state";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { useServiceInstaller } from "@/hooks/useServiceInstaller";
|
||||
import { getSystemInfo } from "@/services/cmds";
|
||||
import { showNotice } from "@/services/noticeService";
|
||||
import { checkUpdateSafe as checkUpdate } from "@/services/update";
|
||||
|
||||
@@ -22,7 +22,7 @@ import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { updateProxyProvider } from "tauri-plugin-mihomo-api";
|
||||
|
||||
import { useProxiesData, useProxyProvidersData } from "@/hooks/app-data";
|
||||
import { useProxiesData, useProxyProvidersData } from "@/hooks/use-clash-data";
|
||||
import { showNotice } from "@/services/noticeService";
|
||||
import parseTraffic from "@/utils/parse-traffic";
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ import {
|
||||
selectNodeForGroup,
|
||||
} from "tauri-plugin-mihomo-api";
|
||||
|
||||
import { useProxiesData } from "@/hooks/app-data";
|
||||
import { useProxiesData } from "@/hooks/use-clash-data";
|
||||
import { calcuProxies, updateProxyChainConfigInRuntime } from "@/services/cmds";
|
||||
import { debugLog } from "@/utils/debug";
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { Virtuoso, type VirtuosoHandle } from "react-virtuoso";
|
||||
import { delayGroup, healthcheckProxyProvider } from "tauri-plugin-mihomo-api";
|
||||
|
||||
import { useProxiesData } from "@/hooks/app-data";
|
||||
import { useProxiesData } from "@/hooks/use-clash-data";
|
||||
import { useProxySelection } from "@/hooks/use-proxy-selection";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { updateProxyChainConfigInRuntime } from "@/services/cmds";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useMemo } from "react";
|
||||
import useSWR from "swr";
|
||||
|
||||
import { useProxiesData } from "@/hooks/app-data";
|
||||
import { useProxiesData } from "@/hooks/use-clash-data";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { getRuntimeConfig } from "@/services/cmds";
|
||||
import delayManager from "@/services/delay";
|
||||
|
||||
@@ -21,7 +21,10 @@ import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { updateRuleProvider } from "tauri-plugin-mihomo-api";
|
||||
|
||||
import type { useRuleProvidersData, useRulesData } from "@/hooks/app-data";
|
||||
import type {
|
||||
useRuleProvidersData,
|
||||
useRulesData,
|
||||
} from "@/hooks/use-clash-data";
|
||||
import { showNotice } from "@/services/noticeService";
|
||||
|
||||
// 辅助组件 - 类型框
|
||||
|
||||
@@ -30,7 +30,7 @@ import {
|
||||
useClashConfig,
|
||||
useSystemProxyAddress,
|
||||
useSystemProxyData,
|
||||
} from "@/hooks/app-data";
|
||||
} from "@/hooks/use-clash-data";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import {
|
||||
getAutotemProxy,
|
||||
|
||||
@@ -16,11 +16,11 @@ import { TooltipIcon } from "@/components/base/base-tooltip-icon";
|
||||
import { GuardState } from "@/components/setting/mods/guard-state";
|
||||
import { SysproxyViewer } from "@/components/setting/mods/sysproxy-viewer";
|
||||
import { TunViewer } from "@/components/setting/mods/tun-viewer";
|
||||
import { useServiceInstaller } from "@/hooks/use-service-installer";
|
||||
import { useServiceUninstaller } from "@/hooks/use-service-uninstaller";
|
||||
import { useSystemProxyState } from "@/hooks/use-system-proxy-state";
|
||||
import { useSystemState } from "@/hooks/use-system-state";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { useServiceInstaller } from "@/hooks/useServiceInstaller";
|
||||
import { useServiceUninstaller } from "@/hooks/useServiceUninstaller";
|
||||
import { showNotice } from "@/services/noticeService";
|
||||
|
||||
interface ProxySwitchProps {
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
/**
|
||||
* 资源清理 Hook
|
||||
* 用于在组件卸载或窗口关闭时统一清理资源
|
||||
*/
|
||||
export const useCleanup = () => {
|
||||
const cleanupFnsRef = useRef<Set<() => void>>(new Set());
|
||||
|
||||
const registerCleanup = (fn: () => void) => {
|
||||
cleanupFnsRef.current.add(fn);
|
||||
return () => {
|
||||
cleanupFnsRef.current.delete(fn);
|
||||
};
|
||||
};
|
||||
|
||||
const cleanup = () => {
|
||||
cleanupFnsRef.current.forEach((fn) => {
|
||||
try {
|
||||
fn();
|
||||
} catch (error) {
|
||||
console.error("[资源清理] 清理失败:", error);
|
||||
}
|
||||
});
|
||||
cleanupFnsRef.current.clear();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
cleanup();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return { registerCleanup, cleanup };
|
||||
};
|
||||
@@ -1,74 +0,0 @@
|
||||
import { useMemo } from "react";
|
||||
|
||||
import { useClashConfig, useProxiesData } from "@/hooks/app-data";
|
||||
|
||||
// 获取当前代理节点信息的自定义Hook
|
||||
export const useCurrentProxy = () => {
|
||||
const { proxies, refreshProxy } = useProxiesData();
|
||||
const { clashConfig } = useClashConfig();
|
||||
|
||||
// 获取当前模式
|
||||
const currentMode = clashConfig?.mode?.toLowerCase() || "rule";
|
||||
|
||||
// 获取当前代理节点信息
|
||||
const currentProxyInfo = useMemo(() => {
|
||||
if (!proxies) return { currentProxy: null, primaryGroupName: null };
|
||||
|
||||
const globalGroup = proxies.global as IProxyGroupItem | undefined;
|
||||
const groups: IProxyGroupItem[] = Array.isArray(proxies.groups)
|
||||
? (proxies.groups as IProxyGroupItem[])
|
||||
: [];
|
||||
const records = (proxies.records || {}) as Record<string, IProxyItem>;
|
||||
|
||||
// 默认信息
|
||||
let primaryGroupName = "GLOBAL";
|
||||
let currentName = globalGroup?.now;
|
||||
|
||||
// 在规则模式下,寻找主要代理组(通常是第一个或者名字包含特定关键词的组)
|
||||
if (currentMode === "rule" && groups.length > 0) {
|
||||
// 查找主要的代理组(优先级:包含关键词 > 第一个非GLOBAL组)
|
||||
const primaryKeywords = [
|
||||
"auto",
|
||||
"select",
|
||||
"proxy",
|
||||
"节点选择",
|
||||
"自动选择",
|
||||
];
|
||||
const primaryGroup =
|
||||
groups.find((group) =>
|
||||
primaryKeywords.some((keyword) =>
|
||||
group.name.toLowerCase().includes(keyword.toLowerCase()),
|
||||
),
|
||||
) || groups.filter((g) => g.name !== "GLOBAL")[0];
|
||||
|
||||
if (primaryGroup) {
|
||||
primaryGroupName = primaryGroup.name;
|
||||
currentName = primaryGroup.now;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果找不到当前节点,返回null
|
||||
if (!currentName) return { currentProxy: null, primaryGroupName };
|
||||
|
||||
// 获取完整的节点信息
|
||||
const currentProxy = records[currentName] || {
|
||||
name: currentName,
|
||||
type: "Unknown",
|
||||
udp: false,
|
||||
xudp: false,
|
||||
tfo: false,
|
||||
mptcp: false,
|
||||
smux: false,
|
||||
history: [],
|
||||
};
|
||||
|
||||
return { currentProxy, primaryGroupName };
|
||||
}, [proxies, currentMode]);
|
||||
|
||||
return {
|
||||
currentProxy: currentProxyInfo.currentProxy,
|
||||
primaryGroupName: currentProxyInfo.primaryGroupName,
|
||||
mode: currentMode,
|
||||
refreshProxy,
|
||||
};
|
||||
};
|
||||
@@ -2,7 +2,7 @@ import { useLockFn } from "ahooks";
|
||||
import useSWR, { mutate } from "swr";
|
||||
import { closeAllConnections } from "tauri-plugin-mihomo-api";
|
||||
|
||||
import { useSystemProxyData } from "@/hooks/app-data";
|
||||
import { useSystemProxyData } from "@/hooks/use-clash-data";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { getAutotemProxy } from "@/services/cmds";
|
||||
|
||||
|
||||
@@ -54,10 +54,12 @@ import { useWindowDecorations } from "@/hooks/use-window";
|
||||
import { useThemeMode } from "@/services/states";
|
||||
import getSystem from "@/utils/get-system";
|
||||
|
||||
import { handleNoticeMessage } from "./_layout/notificationHandlers";
|
||||
import { useAppInitialization } from "./_layout/useAppInitialization";
|
||||
import { useLayoutEvents } from "./_layout/useLayoutEvents";
|
||||
import { useLoadingOverlay } from "./_layout/useLoadingOverlay";
|
||||
import {
|
||||
useAppInitialization,
|
||||
useLayoutEvents,
|
||||
useLoadingOverlay,
|
||||
} from "./_layout/hooks";
|
||||
import { handleNoticeMessage } from "./_layout/utils";
|
||||
import { navItems } from "./_routers";
|
||||
|
||||
import "dayjs/locale/ru";
|
||||
|
||||
3
src/pages/_layout/hooks/index.ts
Normal file
3
src/pages/_layout/hooks/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export { useAppInitialization } from "./use-app-initialization";
|
||||
export { useLayoutEvents } from "./use-layout-events";
|
||||
export { useLoadingOverlay } from "./use-loading-overlay";
|
||||
@@ -1,6 +1,8 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
import { hideInitialOverlay } from "../utils";
|
||||
|
||||
export const useAppInitialization = () => {
|
||||
const initRef = useRef(false);
|
||||
|
||||
@@ -25,6 +27,8 @@ export const useAppInitialization = () => {
|
||||
};
|
||||
|
||||
const notifyBackend = async (stage?: string) => {
|
||||
if (isCancelled) return;
|
||||
|
||||
try {
|
||||
if (stage) {
|
||||
await invoke("update_ui_stage", { stage });
|
||||
@@ -32,20 +36,16 @@ export const useAppInitialization = () => {
|
||||
await invoke("notify_ui_ready");
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`[初始化] 通知后端失败:`, err);
|
||||
console.error(`[Initialization] Failed to notify backend:`, err);
|
||||
}
|
||||
};
|
||||
|
||||
const removeLoadingOverlay = () => {
|
||||
const overlay = document.getElementById("initial-loading-overlay");
|
||||
if (overlay) {
|
||||
overlay.style.opacity = "0";
|
||||
scheduleTimeout(() => overlay.remove(), 300);
|
||||
}
|
||||
hideInitialOverlay({ schedule: scheduleTimeout });
|
||||
};
|
||||
|
||||
const performInitialization = async () => {
|
||||
if (isInitialized) return;
|
||||
if (isCancelled || isInitialized) return;
|
||||
isInitialized = true;
|
||||
|
||||
try {
|
||||
@@ -70,14 +70,18 @@ export const useAppInitialization = () => {
|
||||
await notifyBackend("ResourcesLoaded");
|
||||
await notifyBackend();
|
||||
} catch (error) {
|
||||
console.error("[初始化] 失败:", error);
|
||||
removeLoadingOverlay();
|
||||
notifyBackend().catch(console.error);
|
||||
if (!isCancelled) {
|
||||
console.error("[Initialization] Failed:", error);
|
||||
removeLoadingOverlay();
|
||||
notifyBackend().catch(console.error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const checkBackendReady = async () => {
|
||||
try {
|
||||
if (isCancelled) return;
|
||||
|
||||
await invoke("update_ui_stage", { stage: "Loading" });
|
||||
performInitialization();
|
||||
} catch {
|
||||
@@ -99,7 +103,7 @@ export const useAppInitialization = () => {
|
||||
try {
|
||||
window.clearTimeout(id);
|
||||
} catch (error) {
|
||||
console.warn("[初始化] 清理定时器失败:", error);
|
||||
console.warn("[Initialization] Failed to clear timer:", error);
|
||||
}
|
||||
});
|
||||
timers.clear();
|
||||
@@ -13,6 +13,10 @@ export const useLayoutEvents = (
|
||||
useEffect(() => {
|
||||
const unlisteners: Array<() => void> = [];
|
||||
let disposed = false;
|
||||
const revalidateKeys = (keys: readonly string[]) => {
|
||||
const keySet = new Set(keys);
|
||||
mutate((key) => typeof key === "string" && keySet.has(key));
|
||||
};
|
||||
|
||||
const register = (
|
||||
maybeUnlisten: void | (() => void) | Promise<void | (() => void)>,
|
||||
@@ -33,25 +37,31 @@ export const useLayoutEvents = (
|
||||
unlisteners.push(unlisten);
|
||||
}
|
||||
})
|
||||
.catch((error) => console.error("[事件监听] 注册失败", error));
|
||||
.catch((error) =>
|
||||
console.error("[Event Listener] Registration failed:", error),
|
||||
);
|
||||
};
|
||||
|
||||
register(
|
||||
addListener("verge://refresh-clash-config", async () => {
|
||||
mutate("getProxies");
|
||||
mutate("getVersion");
|
||||
mutate("getClashConfig");
|
||||
mutate("getProxyProviders");
|
||||
revalidateKeys([
|
||||
"getProxies",
|
||||
"getVersion",
|
||||
"getClashConfig",
|
||||
"getProxyProviders",
|
||||
]);
|
||||
}),
|
||||
);
|
||||
|
||||
register(
|
||||
addListener("verge://refresh-verge-config", () => {
|
||||
mutate("getVergeConfig");
|
||||
mutate("getSystemProxy");
|
||||
mutate("getAutotemProxy");
|
||||
mutate("getRunningMode");
|
||||
mutate("isServiceAvailable");
|
||||
revalidateKeys([
|
||||
"getVergeConfig",
|
||||
"getSystemProxy",
|
||||
"getAutotemProxy",
|
||||
"getRunningMode",
|
||||
"isServiceAvailable",
|
||||
]);
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -91,7 +101,7 @@ export const useLayoutEvents = (
|
||||
|
||||
if (errors.length > 0) {
|
||||
console.error(
|
||||
`[事件监听] 清理过程中发生 ${errors.length} 个错误:`,
|
||||
`[Event Listener] Encountered ${errors.length} errors during cleanup:`,
|
||||
errors,
|
||||
);
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
import { hideInitialOverlay } from "../utils";
|
||||
|
||||
export const useLoadingOverlay = (themeReady: boolean) => {
|
||||
const overlayRemovedRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!themeReady || overlayRemovedRef.current) return;
|
||||
|
||||
let fadeTimer: number | null = null;
|
||||
let retryTimer: number | null = null;
|
||||
let removalTimer: number | undefined;
|
||||
let retryTimer: number | undefined;
|
||||
let attempts = 0;
|
||||
const maxAttempts = 50;
|
||||
let stopped = false;
|
||||
@@ -15,19 +17,15 @@ export const useLoadingOverlay = (themeReady: boolean) => {
|
||||
const tryRemoveOverlay = () => {
|
||||
if (stopped || overlayRemovedRef.current) return;
|
||||
|
||||
const overlay = document.getElementById("initial-loading-overlay");
|
||||
if (overlay) {
|
||||
overlayRemovedRef.current = true;
|
||||
overlay.style.opacity = "0";
|
||||
overlay.style.pointerEvents = "none";
|
||||
const { removed, removalTimer: timerId } = hideInitialOverlay({
|
||||
assumeMissingAsRemoved: true,
|
||||
});
|
||||
if (typeof timerId === "number") {
|
||||
removalTimer = timerId;
|
||||
}
|
||||
|
||||
fadeTimer = window.setTimeout(() => {
|
||||
try {
|
||||
overlay.remove();
|
||||
} catch (error) {
|
||||
console.warn("[加载遮罩] 移除失败:", error);
|
||||
}
|
||||
}, 300);
|
||||
if (removed) {
|
||||
overlayRemovedRef.current = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -35,7 +33,7 @@ export const useLoadingOverlay = (themeReady: boolean) => {
|
||||
attempts += 1;
|
||||
retryTimer = window.setTimeout(tryRemoveOverlay, 100);
|
||||
} else {
|
||||
console.warn("[加载遮罩] 未找到元素");
|
||||
console.warn("[Loading Overlay] Element not found");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -43,8 +41,8 @@ export const useLoadingOverlay = (themeReady: boolean) => {
|
||||
|
||||
return () => {
|
||||
stopped = true;
|
||||
if (fadeTimer) window.clearTimeout(fadeTimer);
|
||||
if (retryTimer) window.clearTimeout(retryTimer);
|
||||
if (typeof removalTimer === "number") window.clearTimeout(removalTimer);
|
||||
if (typeof retryTimer === "number") window.clearTimeout(retryTimer);
|
||||
};
|
||||
}, [themeReady]);
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
export const useLazyDataLoad = (
|
||||
callbacks: Array<() => void>,
|
||||
delay: number = 1000,
|
||||
) => {
|
||||
const hasLoadedRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (hasLoadedRef.current) return;
|
||||
|
||||
const timer = window.setTimeout(() => {
|
||||
hasLoadedRef.current = true;
|
||||
callbacks.forEach((callback) => {
|
||||
try {
|
||||
callback();
|
||||
} catch (error) {
|
||||
console.error("[延迟加载] 执行失败:", error);
|
||||
}
|
||||
});
|
||||
}, delay);
|
||||
|
||||
return () => window.clearTimeout(timer);
|
||||
}, [callbacks, delay]);
|
||||
};
|
||||
2
src/pages/_layout/utils/index.ts
Normal file
2
src/pages/_layout/utils/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { hideInitialOverlay } from "./initial-loading-overlay";
|
||||
export { handleNoticeMessage } from "./notification-handlers";
|
||||
45
src/pages/_layout/utils/initial-loading-overlay.ts
Normal file
45
src/pages/_layout/utils/initial-loading-overlay.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
const OVERLAY_ID = "initial-loading-overlay";
|
||||
const REMOVE_DELAY = 300;
|
||||
|
||||
let overlayRemoved = false;
|
||||
|
||||
type HideOverlayOptions = {
|
||||
schedule?: (handler: () => void, delay: number) => number;
|
||||
assumeMissingAsRemoved?: boolean;
|
||||
};
|
||||
|
||||
type HideOverlayResult = {
|
||||
removed: boolean;
|
||||
removalTimer?: number;
|
||||
};
|
||||
|
||||
export const hideInitialOverlay = (
|
||||
options: HideOverlayOptions = {},
|
||||
): HideOverlayResult => {
|
||||
if (overlayRemoved) {
|
||||
return { removed: true };
|
||||
}
|
||||
|
||||
const overlay = document.getElementById(OVERLAY_ID);
|
||||
if (!overlay) {
|
||||
if (options.assumeMissingAsRemoved) {
|
||||
overlayRemoved = true;
|
||||
return { removed: true };
|
||||
}
|
||||
return { removed: false };
|
||||
}
|
||||
|
||||
overlayRemoved = true;
|
||||
overlay.dataset.hidden = "true";
|
||||
|
||||
const schedule = options.schedule ?? window.setTimeout;
|
||||
const removalTimer = schedule(() => {
|
||||
try {
|
||||
overlay.remove();
|
||||
} catch (error) {
|
||||
console.warn("[Loading Overlay] Removal failed:", error);
|
||||
}
|
||||
}, REMOVE_DELAY);
|
||||
|
||||
return { removed: true, removalTimer };
|
||||
};
|
||||
@@ -8,7 +8,7 @@ import { BaseSearchBox } from "@/components/base/base-search-box";
|
||||
import { ScrollTopButton } from "@/components/layout/scroll-top-button";
|
||||
import { ProviderButton } from "@/components/rule/provider-button";
|
||||
import RuleItem from "@/components/rule/rule-item";
|
||||
import { useRuleProvidersData, useRulesData } from "@/hooks/app-data";
|
||||
import { useRuleProvidersData, useRulesData } from "@/hooks/use-clash-data";
|
||||
import { useVisibility } from "@/hooks/use-visibility";
|
||||
|
||||
const RulesPage = () => {
|
||||
|
||||
Reference in New Issue
Block a user