+
+
+
+
+
+
+ {t("Connections")}
+
+
+
+
+
+
+ {parseTraffic(displayData.downloadTotal)}
+
+
+
+ {parseTraffic(displayData.uploadTotal)}
-
-
-
-
-
-
- {isTableLayout ? t("List View") : t("Table View")}
-
-
-
-
-
-
-
- {isPaused ? t("Resume") : t("Pause")}
-
-
-
-
-
-
- {!isTableLayout && (
-
- )}
-
-
+
+
+
+
+
+
+ {isTableLayout ? t("List View") : t("Table View")}
+
+
+
+
+
+
+
+ {isPaused ? t("Resume") : t("Pause")}
+
+
+
-
+
-
-
- {filterConn.length === 0 ? (
-
- ) : isTableLayout ? (
-
- detailRef.current?.open(detail)}
- scrollerRef={scrollerRefCallback}
- />
-
- ) : (
-
(
- detailRef.current?.open(item)}
- />
- )}
- />
+
+ {!isTableLayout && (
+
)}
-
+
+
+
+
+
+ {filterConn.length === 0 ? (
+
+ ) : isTableLayout ? (
+
+ detailRef.current?.open(detail)}
+ scrollerRef={scrollerRefCallback}
+ />
+
+ ) : (
+
(
+ detailRef.current?.open(item)}
+ />
+ )}
+ />
+ )}
+
+
+
);
};
-export default ConnectionsPage;
\ No newline at end of file
+export default ConnectionsPage;
diff --git a/src/pages/home.tsx b/src/pages/home.tsx
index 991757b9..fe0baad3 100644
--- a/src/pages/home.tsx
+++ b/src/pages/home.tsx
@@ -1,4 +1,10 @@
-import React, {useRef, useMemo, useCallback, useState, useEffect} from "react";
+import React, {
+ useRef,
+ useMemo,
+ useCallback,
+ useState,
+ useEffect,
+} from "react";
import { useLockFn } from "ahooks";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
@@ -25,7 +31,11 @@ import {
AlertTriangle,
Loader2,
Globe,
- Send, ExternalLink, RefreshCw, ArrowDown, ArrowUp,
+ Send,
+ ExternalLink,
+ RefreshCw,
+ ArrowDown,
+ ArrowUp,
} from "lucide-react";
import { useVerge } from "@/hooks/use-verge";
import { useSystemState } from "@/hooks/use-system-state";
@@ -34,7 +44,12 @@ import { Switch } from "@/components/ui/switch";
import { ProxySelectors } from "@/components/home/proxy-selectors";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { closeAllConnections } from "@/services/api";
-import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from "@/components/ui/tooltip";
import { updateProfile } from "@/services/cmds";
import { SidebarTrigger } from "@/components/ui/sidebar";
import parseTraffic from "@/utils/parse-traffic";
@@ -48,45 +63,45 @@ const MinimalHomePage: React.FC = () => {
const [isToggling, setIsToggling] = useState(false);
const [isUpdating, setIsUpdating] = useState(false);
const { profiles, patchProfiles, activateSelected, mutateProfiles } =
- useProfiles();
+ useProfiles();
const viewerRef = useRef
(null);
const [uidToActivate, setUidToActivate] = useState(null);
const { connections } = useAppData();
const profileItems = useMemo(() => {
const items =
- profiles && Array.isArray(profiles.items) ? profiles.items : [];
+ profiles && Array.isArray(profiles.items) ? profiles.items : [];
const allowedTypes = ["local", "remote"];
return items.filter((i: any) => i && allowedTypes.includes(i.type!));
}, [profiles]);
const currentProfile = useMemo(() => {
- return profileItems.find(p => p.uid === profiles?.current);
+ return profileItems.find((p) => p.uid === profiles?.current);
}, [profileItems, profiles?.current]);
const currentProfileName = currentProfile?.name || profiles?.current;
const activateProfile = useCallback(
- async (uid: string, notifySuccess: boolean) => {
- try {
- await patchProfiles({ current: uid });
- await closeAllConnections();
- await activateSelected();
- if (notifySuccess) {
- toast.success(t("Profile Switched"));
- }
- } catch (err: any) {
- toast.error(err.message || err.toString());
- mutateProfiles();
+ async (uid: string, notifySuccess: boolean) => {
+ try {
+ await patchProfiles({ current: uid });
+ await closeAllConnections();
+ await activateSelected();
+ if (notifySuccess) {
+ toast.success(t("Profile Switched"));
}
- },
- [patchProfiles, activateSelected, mutateProfiles, t],
+ } catch (err: any) {
+ toast.error(err.message || err.toString());
+ mutateProfiles();
+ }
+ },
+ [patchProfiles, activateSelected, mutateProfiles, t],
);
useEffect(() => {
- const uidToActivate = sessionStorage.getItem('activateProfile');
- if (uidToActivate && profileItems.some(p => p.uid === uidToActivate)) {
+ const uidToActivate = sessionStorage.getItem("activateProfile");
+ if (uidToActivate && profileItems.some((p) => p.uid === uidToActivate)) {
activateProfile(uidToActivate, false);
- sessionStorage.removeItem('activateProfile');
+ sessionStorage.removeItem("activateProfile");
}
}, [profileItems, activateProfile]);
@@ -101,7 +116,7 @@ const MinimalHomePage: React.FC = () => {
const isTunAvailable = isServiceMode || isAdminMode;
const isProxyEnabled = verge?.enable_system_proxy || verge?.enable_tun_mode;
const showTunAlert =
- (verge?.primary_action ?? "tun-mode") === "tun-mode" && !isTunAvailable;
+ (verge?.primary_action ?? "tun-mode") === "tun-mode" && !isTunAvailable;
const handleToggleProxy = useLockFn(async () => {
const turningOn = !isProxyEnabled;
@@ -143,7 +158,7 @@ const MinimalHomePage: React.FC = () => {
});
const handleUpdateProfile = useLockFn(async () => {
- if (!currentProfile?.uid || currentProfile.type !== 'remote') return;
+ if (!currentProfile?.uid || currentProfile.type !== "remote") return;
setIsUpdating(true);
try {
await updateProfile(currentProfile.uid);
@@ -159,316 +174,325 @@ const MinimalHomePage: React.FC = () => {
const statusInfo = useMemo(() => {
if (isToggling) {
return {
- text: isProxyEnabled ? t('Disconnecting...') : t('Connecting...'),
- color: isProxyEnabled ? '#f59e0b' : '#84cc16',
+ text: isProxyEnabled ? t("Disconnecting...") : t("Connecting..."),
+ color: isProxyEnabled ? "#f59e0b" : "#84cc16",
isAnimating: true,
};
}
if (isProxyEnabled) {
return {
- text: t('Connected'),
- color: '#22c55e',
+ text: t("Connected"),
+ color: "#22c55e",
isAnimating: false,
};
}
return {
- text: t('Disconnected'),
- color: '#ef4444',
+ text: t("Disconnected"),
+ color: "#ef4444",
isAnimating: false,
};
}, [isToggling, isProxyEnabled, t]);
return (
-
-
-

-
-
- {isProxyEnabled && (
-
- )}
-
-
-
-
-
-
-
- {profileItems.length > 0 ? (
- <>
-
-
-
-
-
-
-
- {t("Add Profile")}
-
-
-
-
-
-
-
-
-
- {t("Profiles")}
-
- {profileItems.map((p) => (
- handleProfileChange(p.uid)}
- >
- {p.name}
- {profiles?.current === p.uid && (
-
- )}
-
- ))}
-
-
- {currentProfile?.type === 'remote' && (
-
-
-
-
-
-
- {t("Update Profile")}
-
-
-
- )}
- >
- ) : (
- <>
-
-
-
-
-
-
-
- {t("Add Profile")}
-
-
-
-
-
- >
- )}
-
-
-
-
-
-
-
-
- {currentProfile?.announce && (
-
- )}
-
-
- {statusInfo.text}
-
- {isProxyEnabled && (
-
-
-
- {parseTraffic(connections.downloadTotal)}
-
-
-
- {parseTraffic(connections.uploadTotal)}
-
-
- )}
-
-
-
-
- {showTunAlert && (
-
-
-
- {t("Attention Required")}
-
- {t("TUN requires Service Mode or Admin Mode")}
-
- {!isServiceMode && !isAdminMode && (
-
- )}
-
-
- )}
-
-
- {profileItems.length > 0 ? (
-
- ) : (
-
-
- {t("Get Started")}
-
- {t(
- "You don't have any profiles yet. Add your first one to begin.",
- )}
-
-
-
- )}
-
-
-
-
-
mutateProfiles()} />
+
+
+
+
+ {isProxyEnabled && (
+
+ )}
+
+
+
+
+
+
+
+ {profileItems.length > 0 ? (
+ <>
+
+
+
+
+
+
+
+ {t("Add Profile")}
+
+
+
+
+
+
+
+
+
+ {t("Profiles")}
+
+ {profileItems.map((p) => (
+ handleProfileChange(p.uid)}
+ >
+ {p.name}
+ {profiles?.current === p.uid && (
+
+ )}
+
+ ))}
+
+
+ {currentProfile?.type === "remote" && (
+
+
+
+
+
+
+
+ {t("Update Profile")}
+
+
+
+
+ )}
+ >
+ ) : (
+ <>
+
+
+
+
+
+
+
+ {t("Add Profile")}
+
+
+
+
+
+ >
+ )}
+
+
+
+
+
+
+
+ {currentProfile?.announce && (
+
+ )}
+
+
+ {statusInfo.text}
+
+ {isProxyEnabled && (
+
+
+
+ {parseTraffic(connections.downloadTotal)}
+
+
+
+ {parseTraffic(connections.uploadTotal)}
+
+
+ )}
+
+
+
+
+ {showTunAlert && (
+
+
+
+ {t("Attention Required")}
+
+ {t("TUN requires Service Mode or Admin Mode")}
+
+ {!isServiceMode && !isAdminMode && (
+
+ )}
+
+
+ )}
+
+
+ {profileItems.length > 0 ? (
+
+ ) : (
+
+
+ {t("Get Started")}
+
+ {t(
+ "You don't have any profiles yet. Add your first one to begin.",
+ )}
+
+
+
+ )}
+
+
+
+
+
mutateProfiles()} />
+
);
};
-export default MinimalHomePage;
\ No newline at end of file
+export default MinimalHomePage;
diff --git a/src/pages/logs.tsx b/src/pages/logs.tsx
index 2a3d1bbe..24e6154c 100644
--- a/src/pages/logs.tsx
+++ b/src/pages/logs.tsx
@@ -31,7 +31,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
-import {SidebarTrigger} from "@/components/ui/sidebar";
+import { SidebarTrigger } from "@/components/ui/sidebar";
const LogPage = () => {
const { t } = useTranslation();
diff --git a/src/pages/profiles.tsx b/src/pages/profiles.tsx
index 1c1a30c2..eff08f41 100644
--- a/src/pages/profiles.tsx
+++ b/src/pages/profiles.tsx
@@ -55,13 +55,7 @@ import {
TooltipTrigger,
} from "@/components/ui/tooltip";
-import {
- PlusCircle,
- RefreshCw,
- Zap,
- FileText,
- Loader2,
-} from "lucide-react";
+import { PlusCircle, RefreshCw, Zap, FileText, Loader2 } from "lucide-react";
import { SidebarTrigger } from "@/components/ui/sidebar";
const ProfilePage = () => {
diff --git a/src/pages/rules.tsx b/src/pages/rules.tsx
index 7df67cf5..e6e44c15 100644
--- a/src/pages/rules.tsx
+++ b/src/pages/rules.tsx
@@ -1,4 +1,10 @@
-import React, { useState, useMemo, useRef, useEffect, useCallback } from "react";
+import React, {
+ useState,
+ useMemo,
+ useRef,
+ useEffect,
+ useCallback,
+} from "react";
import { useTranslation } from "react-i18next";
import { Virtuoso, VirtuosoHandle } from "react-virtuoso";
import { useAppData } from "@/providers/app-data-provider";
diff --git a/src/services/cmds.ts b/src/services/cmds.ts
index 4b7ccb80..788557f4 100644
--- a/src/services/cmds.ts
+++ b/src/services/cmds.ts
@@ -401,6 +401,9 @@ export async function getNextUpdateTime(uid: string) {
return invoke("get_next_update_time", { uid });
}
-export async function createProfileFromShareLink(link: string, templateName: string) {
+export async function createProfileFromShareLink(
+ link: string,
+ templateName: string,
+) {
return invoke("create_profile_from_share_link", { link, templateName });
}
diff --git a/src/services/noticeService.ts b/src/services/noticeService.ts
index 2e19d7bb..3f482a76 100644
--- a/src/services/noticeService.ts
+++ b/src/services/noticeService.ts
@@ -1,25 +1,29 @@
import { toast } from "sonner";
-type NoticeType = 'success' | 'error' | 'info' | 'warning';
+type NoticeType = "success" | "error" | "info" | "warning";
-export const showNotice = (type: NoticeType, message: string, duration?: number) => {
+export const showNotice = (
+ type: NoticeType,
+ message: string,
+ duration?: number,
+) => {
const options = duration ? { duration } : {};
switch (type) {
- case 'success':
+ case "success":
toast.success(message, options);
break;
- case 'error':
+ case "error":
toast.error(message, options);
break;
- case 'info':
+ case "info":
toast.info(message, options);
break;
- case 'warning':
+ case "warning":
toast.warning(message, options);
break;
default:
toast(message, options);
break;
}
-};
\ No newline at end of file
+};