import React, { useRef, useMemo, useCallback, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useLockFn } from 'ahooks'; import { useTranslation } from 'react-i18next'; import { toast } from 'sonner'; import { useProfiles } from '@/hooks/use-profiles'; import { ProfileViewer, ProfileViewerRef } from '@/components/profile/profile-viewer'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { Button } from '@/components/ui/button'; import { ChevronsUpDown, Check, PlusCircle, Menu, Wrench, AlertTriangle, Loader2 } from 'lucide-react'; import { useVerge } from '@/hooks/use-verge'; import { useSystemState } from '@/hooks/use-system-state'; import { useServiceInstaller } from '@/hooks/useServiceInstaller'; 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'; const MinimalHomePage: React.FC = () => { const { t } = useTranslation(); const navigate = useNavigate(); const [isToggling, setIsToggling] = useState(false); const { profiles, patchProfiles, activateSelected, mutateProfiles } = useProfiles(); const viewerRef = useRef(null); const profileItems = useMemo(() => { const items = profiles && Array.isArray(profiles.items) ? profiles.items : []; const allowedTypes = ["local", "remote"]; return items.filter((i: any) => i && allowedTypes.includes(i.type!)); }, [profiles]); const currentProfileName = useMemo(() => { return profileItems.find(p => p.uid === profiles?.current)?.name || profiles?.current; }, [profileItems, 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(); } }, [patchProfiles, activateSelected, mutateProfiles, t]); const handleProfileChange = useLockFn(async (uid: string) => { if (profiles?.current === uid) return; await activateProfile(uid, true); }); const { verge, patchVerge, mutateVerge } = useVerge(); const { isAdminMode, isServiceMode } = useSystemState(); const { installServiceAndRestartCore } = useServiceInstaller(); const isTunAvailable = isServiceMode || isAdminMode; const isProxyEnabled = verge?.enable_system_proxy || verge?.enable_tun_mode; const handleToggleProxy = useLockFn(async () => { const turningOn = !isProxyEnabled; setIsToggling(true); try { if (turningOn) { await patchVerge({ enable_tun_mode: true, enable_system_proxy: false }); toast.success(t('Proxy enabled')); } else { await patchVerge({ enable_tun_mode: false, enable_system_proxy: false }); toast.success(t('Proxy disabled')); } mutateVerge(); } catch (error: any) { toast.error(t('Failed to toggle proxy'), { description: error.message }); } finally { setIsToggling(false); } }); const navMenuItems = [ { label: 'Profiles', path: '/profile' }, { label: 'Settings', path: '/settings' }, { label: 'Logs', path: '/logs' }, { label: 'Proxies', path: '/proxies' }, { label: 'Connections', path: '/connections' }, { label: 'Rules', path: '/rules' }, ]; return (
{profileItems.length > 0 && (
{t("Profiles")} {profileItems.map((p) => ( handleProfileChange(p.uid)}> {p.name} {profiles?.current === p.uid && } ))} viewerRef.current?.create()}> {t("Add New Profile")}
)}
{t("Menu")} {navMenuItems.map((item) => ( navigate(item.path)}> {t(item.label)} ))}

{isProxyEnabled ? t('Connected') : t('Disconnected')}

{isToggling && (isProxyEnabled ? t('Disconnecting...') : t('Connecting...'))}

{!isTunAvailable && (
{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;