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 (
}
sx={{ borderRadius: 1.5 }}
>
{t("Label-Profiles")}
);
}, [current, goToProfiles, t]);
return (
}
iconColor="info"
action={cardAction}
>
{current ? (
) : (
)}
);
};