| 
					
				 | 
			
			
				@@ -1,90 +1,51 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import useSWR, { useSWRConfig } from "swr"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { useEffect, useMemo, useRef, useState } from "react"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { Virtuoso } from "react-virtuoso"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { useEffect } from "react"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { useLockFn } from "ahooks"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { Button, ButtonGroup, List, Paper } from "@mui/material"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { getClashConfig, updateConfigs, updateProxy } from "../services/api"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { getClashConfig, updateConfigs } from "../services/api"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { patchClashConfig } from "../services/cmds"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { getProxies } from "../services/api"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import BasePage from "../components/base/base-page"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import ProxyItem from "../components/proxy/proxy-item"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import ProxyGroup from "../components/proxy/proxy-group"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import ProxyGlobal from "../components/proxy/proxy-global"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const ProxyPage = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const { mutate } = useSWRConfig(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const { data: proxiesData } = useSWR("getProxies", getProxies); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const { data: clashConfig } = useSWR("getClashConfig", getClashConfig); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const [curProxy, setCurProxy] = useState<string>("DIRECT"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const curMode = clashConfig?.mode.toLowerCase(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // proxy groups 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const { groups = [] } = proxiesData ?? {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // proxies and sorted 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const filterProxies = useMemo(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!proxiesData?.proxies) return []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const list = Object.values(proxiesData.proxies); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const retList = list.filter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      (p) => !p.all?.length && p.name !== "DIRECT" && p.name !== "REJECT" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const direct = list.filter((p) => p.name === "DIRECT"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const reject = list.filter((p) => p.name === "REJECT"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return direct.concat(retList).concat(reject); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  }, [proxiesData]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const modeList = ["rule", "global", "direct"]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const asGroup = curMode === "rule" && groups.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const curMode = clashConfig?.mode.toLowerCase() ?? "direct"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const { groups = [], proxies = [] } = proxiesData ?? {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // make sure that fetch the proxies successfully 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   useEffect(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (curMode === "rule" && !groups.length) || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      (curMode === "global" && filterProxies.length < 4) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (curMode === "global" && proxies.length < 2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       setTimeout(() => mutate("getProxies"), 500); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  }, [groups, filterProxies, curMode]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // update the current proxy 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  useEffect(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (curMode === "direct") setCurProxy("DIRECT"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (curMode === "global") { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      const globalNow = proxiesData?.proxies?.GLOBAL?.now; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      setCurProxy(globalNow || "DIRECT"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  }, [curMode, proxiesData]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }, [groups, proxies, curMode]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const changeLockRef = useRef(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const onChangeMode = async (mode: string) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (changeLockRef.current) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    changeLockRef.current = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      // switch rapidly 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      await updateConfigs({ mode }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      await patchClashConfig({ mode }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      mutate("getClashConfig"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } finally { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      changeLockRef.current = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const onChangeProxy = async (name: string) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (curMode !== "global") return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    await updateProxy("GLOBAL", name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    setCurProxy(name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const onChangeMode = useLockFn(async (mode: string) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // switch rapidly 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await updateConfigs({ mode }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await patchClashConfig({ mode }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    mutate("getClashConfig"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // difference style 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const pageStyle = asGroup ? {} : { height: "100%" }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const paperStyle: any = asGroup 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const showGroup = curMode === "rule" && !!groups.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const pageStyle = showGroup ? {} : { height: "100%" }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const paperStyle: any = showGroup 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ? { mb: 0.5 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     : { py: 1, height: "100%", boxSizing: "border-box" }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     <BasePage 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       contentStyle={pageStyle} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      title={asGroup ? "Proxy Groups" : "Proxies"} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      title={showGroup ? "Proxy Groups" : "Proxies"} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       header={ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         <ButtonGroup size="small"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           {modeList.map((mode) => ( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -101,26 +62,25 @@ const ProxyPage = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     > 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       <Paper sx={{ borderRadius: 1, boxShadow: 2, ...paperStyle }}> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        {asGroup ? ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        {curMode === "rule" && !!groups.length && ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           <List> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             {groups.map((group) => ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               <ProxyGroup key={group.name} group={group} /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             ))} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           </List> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) : ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          // virtual list 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <Virtuoso 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            style={{ height: "100%" }} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            totalCount={filterProxies.length} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            itemContent={(index) => ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              <ProxyItem 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                groupName="GLOBAL" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                proxy={filterProxies[index]} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                selected={filterProxies[index].name === curProxy} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                onClick={onChangeProxy} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                sx={{ py: 0, px: 2 }} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            )} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        )} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        {((curMode === "rule" && !groups.length) || curMode === "global") && ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          <ProxyGlobal 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            groupName="GLOBAL" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            curProxy={proxiesData?.global?.now} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            proxies={proxies} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        )} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        {curMode === "direct" && ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          <ProxyGlobal 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            groupName="DIRECT" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            curProxy="DIRECT" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            proxies={[proxiesData?.direct!].filter(Boolean)} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         )} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       </Paper> 
			 |