mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-28 08:44:41 +08:00
103 lines
3.3 KiB
TypeScript
103 lines
3.3 KiB
TypeScript
import type { ReactNode } from "react";
|
|
import { createElement } from "react";
|
|
import { SessionMeta } from "@/types";
|
|
|
|
export const getSessionKey = (session: SessionMeta) =>
|
|
`${session.providerId}:${session.sessionId}:${session.sourcePath ?? ""}`;
|
|
|
|
export const getBaseName = (value?: string | null) => {
|
|
if (!value) return "";
|
|
const trimmed = value.trim();
|
|
if (!trimmed) return "";
|
|
const normalized = trimmed.replace(/[\\/]+$/, "");
|
|
const parts = normalized.split(/[\\/]/).filter(Boolean);
|
|
return parts[parts.length - 1] || trimmed;
|
|
};
|
|
|
|
export const formatTimestamp = (value?: number) => {
|
|
if (!value) return "";
|
|
return new Date(value).toLocaleString();
|
|
};
|
|
|
|
export const formatRelativeTime = (
|
|
value: number | undefined,
|
|
t: (key: string, options?: Record<string, unknown>) => string,
|
|
) => {
|
|
if (!value) return "";
|
|
const now = Date.now();
|
|
const diff = now - value;
|
|
const minutes = Math.floor(diff / 60000);
|
|
const hours = Math.floor(diff / 3600000);
|
|
const days = Math.floor(diff / 86400000);
|
|
|
|
if (minutes < 1) return t("sessionManager.justNow");
|
|
if (minutes < 60) return t("sessionManager.minutesAgo", { count: minutes });
|
|
if (hours < 24) return t("sessionManager.hoursAgo", { count: hours });
|
|
if (days < 7) return t("sessionManager.daysAgo", { count: days });
|
|
return new Date(value).toLocaleDateString();
|
|
};
|
|
|
|
export const getProviderLabel = (
|
|
providerId: string,
|
|
t: (key: string) => string,
|
|
) => {
|
|
const key = `apps.${providerId}`;
|
|
const translated = t(key);
|
|
return translated === key ? providerId : translated;
|
|
};
|
|
|
|
// 根据 providerId 获取对应的图标名称
|
|
export const getProviderIconName = (providerId: string) => {
|
|
if (providerId === "codex") return "openai";
|
|
if (providerId === "claude") return "claude";
|
|
if (providerId === "opencode") return "opencode";
|
|
if (providerId === "openclaw") return "openclaw";
|
|
return providerId;
|
|
};
|
|
|
|
export const getRoleTone = (role: string) => {
|
|
const normalized = role.toLowerCase();
|
|
if (normalized === "assistant") return "text-blue-500";
|
|
if (normalized === "user") return "text-emerald-500";
|
|
if (normalized === "system") return "text-amber-500";
|
|
if (normalized === "tool") return "text-purple-500";
|
|
return "text-muted-foreground";
|
|
};
|
|
|
|
export const getRoleLabel = (role: string, t: (key: string) => string) => {
|
|
const normalized = role.toLowerCase();
|
|
if (normalized === "assistant") return "AI";
|
|
if (normalized === "user") return t("sessionManager.roleUser");
|
|
if (normalized === "system") return t("sessionManager.roleSystem");
|
|
if (normalized === "tool") return t("sessionManager.roleTool");
|
|
return role;
|
|
};
|
|
|
|
export const formatSessionTitle = (session: SessionMeta) => {
|
|
return (
|
|
session.title ||
|
|
getBaseName(session.projectDir) ||
|
|
session.sessionId.slice(0, 8)
|
|
);
|
|
};
|
|
|
|
export const highlightText = (text: string, query: string): ReactNode => {
|
|
if (!query) return text;
|
|
const escaped = query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
const parts = text.split(new RegExp(`(${escaped})`, "gi"));
|
|
if (parts.length === 1) return text;
|
|
return parts.map((part, i) =>
|
|
i % 2 === 1
|
|
? createElement(
|
|
"mark",
|
|
{
|
|
key: i,
|
|
className:
|
|
"bg-yellow-200/60 dark:bg-yellow-500/30 text-inherit rounded-sm px-0.5",
|
|
},
|
|
part,
|
|
)
|
|
: part,
|
|
);
|
|
};
|