import { useTranslation } from "react-i18next"; import { Box, Typography, Button, Stack, LinearProgress, alpha, useTheme, Link, keyframes, } from "@mui/material"; import { useNavigate } from "react-router-dom"; import { CloudUploadOutlined, StorageOutlined, UpdateOutlined, DnsOutlined, SpeedOutlined, EventOutlined, LaunchOutlined, } from "@mui/icons-material"; import dayjs from "dayjs"; import parseTraffic from "@/utils/parse-traffic"; import { useMemo, useCallback, useState } from "react"; import { openWebUrl, updateProfile } from "@/services/cmds"; import { useLockFn } from "ahooks"; import { showNotice } from "@/services/noticeService"; import { EnhancedCard } from "./enhanced-card"; import { useAppData } from "@/providers/app-data-provider"; // 定义旋转动画 const round = keyframes` from { transform: rotate(0deg); } to { transform: rotate(360deg); } `; // 辅助函数解析URL和过期时间 const parseUrl = (url?: string) => { if (!url) return "-"; if (url.startsWith("http")) return new URL(url).host; return "local"; }; const parseExpire = (expire?: number) => { if (!expire) return "-"; return dayjs(expire * 1000).format("YYYY-MM-DD"); }; // 使用类型定义,而不是导入 interface ProfileExtra { upload: number; download: number; total: number; expire: number; } export interface ProfileItem { uid: string; type?: "local" | "remote" | "merge" | "script"; name?: string; desc?: string; file?: string; url?: string; updated?: number; extra?: ProfileExtra; home?: string; option?: any; } export interface HomeProfileCardProps { current: ProfileItem | null | undefined; onProfileUpdated?: () => void; } // 添加一个通用的截断样式 const truncateStyle = { maxWidth: "calc(100% - 28px)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }; // 提取独立组件减少主组件复杂度 const ProfileDetails = ({ current, onUpdateProfile, updating }: { current: ProfileItem; onUpdateProfile: () => void; updating: boolean; }) => { const { t } = useTranslation(); const theme = useTheme(); const usedTraffic = useMemo(() => { if (!current.extra) return 0; return current.extra.upload + current.extra.download; }, [current.extra]); const trafficPercentage = useMemo(() => { if (!current.extra || !current.extra.total) return 1; return Math.min( Math.round((usedTraffic * 100) / (current.extra.total + 0.01)) + 1, 100 ); }, [current.extra, usedTraffic]); return ( {current.url && ( {t("From")}: {current.home ? ( current.home && openWebUrl(current.home)} sx={{ display: "inline-flex", alignItems: "center", minWidth: 0, maxWidth: "calc(100% - 40px)", ml: 0.5 }} title={parseUrl(current.url)} > {parseUrl(current.url)} ) : ( {parseUrl(current.url)} )} )} {current.updated && ( {t("Update Time")}:{" "} {dayjs(current.updated * 1000).format("YYYY-MM-DD HH:mm")} )} {current.extra && ( <> {t("Used / Total")}:{" "} {parseTraffic(usedTraffic)} / {parseTraffic(current.extra.total)} {current.extra.expire > 0 && ( {t("Expire Time")}:{" "} {parseExpire(current.extra.expire)} )} {trafficPercentage}% )} ); }; // 提取空配置组件 const EmptyProfile = ({ onClick }: { onClick: () => void }) => { const { t } = useTranslation(); return ( {t("Import")} {t("Profiles")} {t("Click to import subscription")} ); }; export const HomeProfileCard = ({ current, onProfileUpdated }: HomeProfileCardProps) => { const { t } = useTranslation(); const navigate = useNavigate(); const { refreshAll } = useAppData(); // 更新当前订阅 const [updating, setUpdating] = useState(false); const onUpdateProfile = useLockFn(async () => { if (!current?.uid) return; setUpdating(true); try { await updateProfile(current.uid, current.option); showNotice('success', t("Update subscription successfully"), 1000); onProfileUpdated?.(); // 刷新首页数据 refreshAll(); } catch (err: any) { showNotice('error', err.message || err.toString(), 3000); } finally { setUpdating(false); } }); // 导航到订阅页面 const goToProfiles = useCallback(() => { navigate("/profile"); }, [navigate]); // 卡片标题 const cardTitle = useMemo(() => { if (!current) return t("Profiles"); if (!current.home) return current.name; return ( current.home && openWebUrl(current.home)} sx={{ 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} ); }, [current, t]); // 卡片操作按钮 const cardAction = useMemo(() => { if (!current) return null; return ( ); }, [current, goToProfiles, t]); return ( } iconColor="info" action={cardAction} > {current ? ( ) : ( )} ); };