From 024db4358b4d5aab701301005396c4efd7466c67 Mon Sep 17 00:00:00 2001
From: GyDi <zzzgydi@gmail.com>
Date: Wed, 14 Dec 2022 15:07:51 +0800
Subject: [PATCH] feat: auto proxy layout column

---
 src/components/proxy/proxy-groups.tsx       |  1 +
 src/components/proxy/proxy-item-mini.tsx    | 72 ++++++++++-----------
 src/components/proxy/proxy-render.tsx       |  3 +-
 src/components/proxy/use-render-list.ts     | 16 ++++-
 src/components/proxy/use-window-width.ts    | 16 +++++
 src/components/setting/mods/misc-viewer.tsx |  3 +
 6 files changed, 70 insertions(+), 41 deletions(-)
 create mode 100644 src/components/proxy/use-window-width.ts

diff --git a/src/components/proxy/proxy-groups.tsx b/src/components/proxy/proxy-groups.tsx
index e852391..8386b53 100644
--- a/src/components/proxy/proxy-groups.tsx
+++ b/src/components/proxy/proxy-groups.tsx
@@ -118,6 +118,7 @@ export const ProxyGroups = (props: Props) => {
       ref={virtuosoRef}
       style={{ height: "100%" }}
       totalCount={renderList.length}
+      increaseViewportBy={256}
       itemContent={(index) => (
         <ProxyRender
           key={renderList[index].key}
diff --git a/src/components/proxy/proxy-item-mini.tsx b/src/components/proxy/proxy-item-mini.tsx
index 3e82c9e..68fcb61 100644
--- a/src/components/proxy/proxy-item-mini.tsx
+++ b/src/components/proxy/proxy-item-mini.tsx
@@ -1,14 +1,7 @@
 import { useEffect, useState } from "react";
 import { useLockFn } from "ahooks";
 import { CheckCircleOutlineRounded } from "@mui/icons-material";
-import {
-  alpha,
-  Box,
-  ListItemButton,
-  ListItemIcon,
-  ListItemText,
-  styled,
-} from "@mui/material";
+import { alpha, Box, ListItemButton, styled, Typography } from "@mui/material";
 import { BaseLoading } from "@/components/base";
 import delayManager from "@/services/delay";
 
@@ -52,7 +45,7 @@ export const ProxyItemMini = (props: Props) => {
       selected={selected}
       onClick={() => onClick?.(proxy.name)}
       sx={[
-        { borderRadius: 1, pl: 1.5, pr: 1 },
+        { height: 56, borderRadius: 1, pl: 1.5, pr: 1 },
         ({ palette: { mode, primary } }) => {
           const bgcolor =
             mode === "light"
@@ -61,45 +54,48 @@ export const ProxyItemMini = (props: Props) => {
           const color = mode === "light" ? primary.main : primary.light;
           const showDelay = delay > 0;
 
+          const shadowColor =
+            mode === "light" ? "rgba(0,0,0,0.04)" : "rgba(255,255,255,0.08)";
+
           return {
             "&:hover .the-check": { display: !showDelay ? "block" : "none" },
             "&:hover .the-delay": { display: showDelay ? "block" : "none" },
             "&:hover .the-icon": { display: "none" },
-            "&.Mui-selected": { bgcolor },
+            "&.Mui-selected": { bgcolor, boxShadow: `0 0 0 1px ${bgcolor}` },
             "&.Mui-selected .MuiListItemText-secondary": { color },
+            boxShadow: `0 0 0 1px ${shadowColor}`,
           };
         },
       ]}
     >
-      <ListItemText
-        title={proxy.name}
-        secondary={
-          <div>
-            <div
-              style={{
-                textOverflow: "ellipsis",
-                wordBreak: "break-all",
-                overflow: "hidden",
-                whiteSpace: showType ? "nowrap" : "inherit",
-              }}
-            >
-              {proxy.name}
-            </div>
-
-            {showType && (
-              <>
-                {!!proxy.provider && (
-                  <TypeBox component="span">{proxy.provider}</TypeBox>
-                )}
-                <TypeBox component="span">{proxy.type}</TypeBox>
-                {proxy.udp && <TypeBox component="span">UDP</TypeBox>}
-              </>
+      <Box title={proxy.name} sx={{ overflow: "hidden" }}>
+        <Typography
+          variant="body2"
+          component="div"
+          color="text.secondary"
+          sx={{
+            display: "block",
+            textOverflow: "ellipsis",
+            wordBreak: "break-all",
+            overflow: "hidden",
+            whiteSpace: "nowrap",
+          }}
+        >
+          {proxy.name}
+        </Typography>
+
+        {showType && (
+          <Box sx={{ display: "flex", flexWrap: "nowrap", flex: "none" }}>
+            {!!proxy.provider && (
+              <TypeBox component="span">{proxy.provider}</TypeBox>
             )}
-          </div>
-        }
-      />
+            <TypeBox component="span">{proxy.type}</TypeBox>
+            {proxy.udp && <TypeBox component="span">UDP</TypeBox>}
+          </Box>
+        )}
+      </Box>
 
-      <ListItemIcon sx={{ justifyContent: "flex-end", color: "primary.main" }}>
+      <Box sx={{ ml: 0.5, justifyContent: "flex-end", color: "primary.main" }}>
         {delay === -2 && (
           <Widget>
             <BaseLoading />
@@ -158,7 +154,7 @@ export const ProxyItemMini = (props: Props) => {
             sx={{ fontSize: 16 }}
           />
         )}
-      </ListItemIcon>
+      </Box>
     </ListItemButton>
   );
 };
diff --git a/src/components/proxy/proxy-render.tsx b/src/components/proxy/proxy-render.tsx
index b5f50d0..f0d197f 100644
--- a/src/components/proxy/proxy-render.tsx
+++ b/src/components/proxy/proxy-render.tsx
@@ -110,6 +110,7 @@ export const ProxyRender = (props: RenderProps) => {
     return (
       <Box
         sx={{
+          height: 56,
           display: "grid",
           gap: 1,
           pl: indent ? 4 : 2,
@@ -123,7 +124,7 @@ export const ProxyRender = (props: RenderProps) => {
             key={item.key + proxy.name}
             groupName={group.name}
             proxy={proxy!}
-            selected={group.now === proxy?.name}
+            selected={group.now === proxy.name}
             showType={headState?.showType}
             onClick={() => onChangeProxy(group, proxy!)}
           />
diff --git a/src/components/proxy/use-render-list.ts b/src/components/proxy/use-render-list.ts
index 22fc96d..1753b01 100644
--- a/src/components/proxy/use-render-list.ts
+++ b/src/components/proxy/use-render-list.ts
@@ -3,6 +3,7 @@ import { useEffect, useMemo } from "react";
 import { getProxies } from "@/services/api";
 import { useVerge } from "@/hooks/use-verge";
 import { filterSort } from "./use-filter-sort";
+import { useWindowWidth } from "./use-window-width";
 import {
   useHeadStateNew,
   DEFAULT_STATE,
@@ -28,7 +29,18 @@ export const useRenderList = (mode: string) => {
   );
 
   const { verge } = useVerge();
-  const col = verge?.proxy_layout_column || 1;
+  const { width } = useWindowWidth();
+
+  let col = verge?.proxy_layout_column || 1;
+
+  // 自适应
+  if (col === 6) {
+    if (width > 1450) col = 5;
+    else if (width > 1024) col = 4;
+    else if (width > 900) col = 3;
+    else if (width >= 600) col = 2;
+    else col = 1;
+  }
 
   const [headStates, setHeadState] = useHeadStateNew();
 
@@ -80,7 +92,7 @@ export const useRenderList = (mode: string) => {
           return ret.concat(
             groupList(proxies, col).map((proxyCol) => ({
               type: 4,
-              key: `col-${group.name}`,
+              key: `col-${group.name}-${proxyCol[0].name}`,
               group,
               headState,
               col,
diff --git a/src/components/proxy/use-window-width.ts b/src/components/proxy/use-window-width.ts
new file mode 100644
index 0000000..d1de3c3
--- /dev/null
+++ b/src/components/proxy/use-window-width.ts
@@ -0,0 +1,16 @@
+import { useEffect, useState } from "react";
+
+export const useWindowWidth = () => {
+  const [width, setWidth] = useState(() => document.body.clientWidth);
+
+  useEffect(() => {
+    const handleResize = () => setWidth(document.body.clientWidth);
+
+    window.addEventListener("resize", handleResize);
+    return () => {
+      window.removeEventListener("resize", handleResize);
+    };
+  }, []);
+
+  return { width };
+};
diff --git a/src/components/setting/mods/misc-viewer.tsx b/src/components/setting/mods/misc-viewer.tsx
index 02a0692..d438537 100644
--- a/src/components/setting/mods/misc-viewer.tsx
+++ b/src/components/setting/mods/misc-viewer.tsx
@@ -99,6 +99,9 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
               }));
             }}
           >
+            <MenuItem value={6} key={6}>
+              Auto
+            </MenuItem>
             {[1, 2, 3, 4, 5].map((i) => (
               <MenuItem value={i} key={i}>
                 {i}
-- 
GitLab