refactor: auto-truncate long text on home profile card

fix: sync system proxy and TUN mode status indicators on home proxy mode card
This commit is contained in:
wonfen
2025-03-21 05:23:45 +08:00
parent a28887be8e
commit f739836891
7 changed files with 130 additions and 68 deletions

View File

@@ -31,6 +31,16 @@ export const EnhancedCard = ({
const theme = useTheme();
const isDark = theme.palette.mode === "dark";
// 统一的标题截断样式
const titleTruncateStyle = {
minWidth: 0,
maxWidth: "100%",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
display: "block"
};
return (
<Box
sx={{
@@ -52,7 +62,13 @@ export const EnhancedCard = ({
borderColor: "divider",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Box sx={{
display: "flex",
alignItems: "center",
minWidth: 0,
flex: 1,
overflow: "hidden"
}}>
<Box
sx={{
display: "flex",
@@ -62,21 +78,32 @@ export const EnhancedCard = ({
width: 38,
height: 38,
mr: 1.5,
flexShrink: 0,
backgroundColor: alpha(theme.palette[iconColor].main, 0.12),
color: theme.palette[iconColor].main,
}}
>
{icon}
</Box>
{typeof title === "string" ? (
<Typography variant="h6" fontWeight="medium" fontSize={18}>
{title}
</Typography>
) : (
title
)}
<Box sx={{ minWidth: 0, flex: 1 }}>
{typeof title === "string" ? (
<Typography
variant="h6"
fontWeight="medium"
fontSize={18}
sx={titleTruncateStyle}
title={title}
>
{title}
</Typography>
) : (
<Box sx={titleTruncateStyle}>
{title}
</Box>
)}
</Box>
</Box>
{action}
{action && <Box sx={{ ml: 2, flexShrink: 0 }}>{action}</Box>}
</Box>
<Box
sx={{

View File

@@ -35,19 +35,10 @@ const round = keyframes`
`;
// 辅助函数解析URL和过期时间
const parseUrl = (url?: string, maxLength: number = 25) => {
const parseUrl = (url?: string) => {
if (!url) return "-";
let parsedUrl = "";
if (url.startsWith("http")) {
parsedUrl = new URL(url).host;
} else {
parsedUrl = "local";
}
if (parsedUrl.length > maxLength) {
return parsedUrl.substring(0, maxLength - 3) + "...";
}
return parsedUrl;
if (url.startsWith("http")) return new URL(url).host;
return "local";
};
const parseExpire = (expire?: number) => {
@@ -81,6 +72,14 @@ export interface HomeProfileCardProps {
onProfileUpdated?: () => void;
}
// 添加一个通用的截断样式
const truncateStyle = {
maxWidth: "calc(100% - 28px)",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap"
};
// 提取独立组件减少主组件复杂度
const ProfileDetails = ({ current, onUpdateProfile, updating }: {
current: ProfileItem;
@@ -109,31 +108,55 @@ const ProfileDetails = ({ current, onUpdateProfile, updating }: {
{current.url && (
<Stack direction="row" alignItems="center" spacing={1}>
<DnsOutlined fontSize="small" color="action" />
<Typography variant="body2" color="text.secondary">
{t("From")}:{" "}
<Typography variant="body2" color="text.secondary" noWrap sx={{ display: "flex", alignItems: "center" }}>
<span style={{ flexShrink: 0 }}>{t("From")}: </span>
{current.home ? (
<Link
component="button"
fontWeight="medium"
onClick={() => current.home && openWebUrl(current.home)}
sx={{
display: "inline-flex",
alignItems: "center"
display: "inline-flex",
alignItems: "center",
minWidth: 0,
maxWidth: "calc(100% - 40px)",
ml: 0.5
}}
title={parseUrl(current.url)}
>
{parseUrl(current.url)}
<Typography
component="span"
sx={{
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
minWidth: 0,
flex: 1
}}
>
{parseUrl(current.url)}
</Typography>
<LaunchOutlined
fontSize="inherit"
sx={{ ml: 0.5, fontSize: "0.8rem", opacity: 0.7, flexShrink: 0 }}
/>
</Link>
) : (
<Box
component="span"
<Typography
component="span"
fontWeight="medium"
sx={{
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
minWidth: 0,
flex: 1,
ml: 0.5
}}
title={parseUrl(current.url)}
>
{parseUrl(current.url)}
</Box>
</Typography>
)}
</Typography>
</Stack>
@@ -285,16 +308,30 @@ export const HomeProfileCard = ({ current, onProfileUpdated }: HomeProfileCardPr
fontSize={18}
onClick={() => current.home && openWebUrl(current.home)}
sx={{
display: "inline-flex",
alignItems: "center",
color: "inherit",
textDecoration: "none",
display: "flex",
alignItems: "center",
minWidth: 0,
maxWidth: "100%",
"& > span": {
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
flex: 1
}
}}
title={current.name}
>
{current.name}
<span>{current.name}</span>
<LaunchOutlined
fontSize="inherit"
sx={{ ml: 0.5, fontSize: "0.8rem", opacity: 0.7 }}
sx={{
ml: 0.5,
fontSize: "0.8rem",
opacity: 0.7,
flexShrink: 0
}}
/>
</Link>
);

View File

@@ -24,6 +24,7 @@ import {
getAutotemProxy,
getRunningMode,
} from "@/services/cmds";
import { useVerge } from "@/hooks/use-verge";
const LOCAL_STORAGE_TAB_KEY = "clash-verge-proxy-active-tab";
@@ -151,6 +152,10 @@ export const ProxyTunCard: FC = () => {
// 获取代理状态信息
const { data: sysproxy } = useSWR("getSystemProxy", getSystemProxy);
const { data: runningMode } = useSWR("getRunningMode", getRunningMode);
const { verge } = useVerge();
// 从verge配置中获取开关状态
const { enable_system_proxy, enable_tun_mode } = verge ?? {};
// 是否以sidecar模式运行
const isSidecarMode = runningMode === "sidecar";
@@ -170,7 +175,7 @@ export const ProxyTunCard: FC = () => {
const tabDescription = useMemo(() => {
if (activeTab === "system") {
return {
text: sysproxy?.enable
text: enable_system_proxy
? t("System Proxy Enabled")
: t("System Proxy Disabled"),
tooltip: t("System Proxy Info")
@@ -179,11 +184,13 @@ export const ProxyTunCard: FC = () => {
return {
text: isSidecarMode
? t("TUN Mode Service Required")
: t("TUN Mode Intercept Info"),
: enable_tun_mode
? t("TUN Mode Enabled")
: t("TUN Mode Disabled"),
tooltip: t("Tun Mode Info")
};
}
}, [activeTab, sysproxy?.enable, isSidecarMode, t]);
}, [activeTab, enable_system_proxy, enable_tun_mode, isSidecarMode, t]);
return (
<Box sx={{ display: "flex", flexDirection: "column", width: "100%" }}>
@@ -203,13 +210,14 @@ export const ProxyTunCard: FC = () => {
onClick={() => handleTabChange("system")}
icon={ComputerRounded}
label={t("System Proxy")}
hasIndicator={sysproxy?.enable}
hasIndicator={enable_system_proxy}
/>
<TabButton
isActive={activeTab === "tun"}
onClick={() => handleTabChange("tun")}
icon={TroubleshootRounded}
label={t("Tun Mode")}
hasIndicator={enable_tun_mode && !isSidecarMode}
/>
</Stack>

View File

@@ -120,17 +120,7 @@ const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => {
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
{proxy_auto_config ? (
autoproxy?.enable ? (
<PlayCircleOutlineRounded
sx={{ color: "success.main", mr: 1.5, fontSize: 28 }}
/>
) : (
<PauseCircleOutlineRounded
sx={{ color: "text.disabled", mr: 1.5, fontSize: 28 }}
/>
)
) : sysproxy?.enable ? (
{enable_system_proxy ? (
<PlayCircleOutlineRounded
sx={{ color: "success.main", mr: 1.5, fontSize: 28 }}
/>

View File

@@ -570,7 +570,6 @@
"No": "No",
"Failed": "Failed",
"Completed": "Completed",
"Bahamut Anime": "Bahamut Anime",
"Disallowed ISP": "Disallowed ISP",
"Originals Only": "Originals Only",
"No (IP Banned By Disney+)": "No (IP Banned By Disney+)",

View File

@@ -570,7 +570,6 @@
"No": "不支持",
"Failed": "测试失败",
"Completed": "检测完成",
"Bahamut Anime": "动画疯",
"Disallowed ISP": "不允许的 ISP",
"Originals Only": "仅限原创",
"No (IP Banned By Disney+)": "不支持IP被Disney+禁止)",