chore: apply prettier formatting to component files
This commit is contained in:
@@ -146,7 +146,9 @@ const UsagePlanItem: React.FC<{ data: UsageData }> = ({ data }) => {
|
||||
{/* 总额度 */}
|
||||
{total !== undefined && (
|
||||
<>
|
||||
<span className="text-gray-500 dark:text-gray-400">{t("usage.total")}</span>
|
||||
<span className="text-gray-500 dark:text-gray-400">
|
||||
{t("usage.total")}
|
||||
</span>
|
||||
<span className="tabular-nums text-gray-600 dark:text-gray-400">
|
||||
{total === -1 ? "∞" : total.toFixed(2)}
|
||||
</span>
|
||||
@@ -157,7 +159,9 @@ const UsagePlanItem: React.FC<{ data: UsageData }> = ({ data }) => {
|
||||
{/* 已用额度 */}
|
||||
{used !== undefined && (
|
||||
<>
|
||||
<span className="text-gray-500 dark:text-gray-400">{t("usage.used")}</span>
|
||||
<span className="text-gray-500 dark:text-gray-400">
|
||||
{t("usage.used")}
|
||||
</span>
|
||||
<span className="tabular-nums text-gray-600 dark:text-gray-400">
|
||||
{used.toFixed(2)}
|
||||
</span>
|
||||
@@ -168,7 +172,9 @@ const UsagePlanItem: React.FC<{ data: UsageData }> = ({ data }) => {
|
||||
{/* 剩余额度 - 突出显示 */}
|
||||
{remaining !== undefined && (
|
||||
<>
|
||||
<span className="text-gray-500 dark:text-gray-400">{t("usage.remaining")}</span>
|
||||
<span className="text-gray-500 dark:text-gray-400">
|
||||
{t("usage.remaining")}
|
||||
</span>
|
||||
<span
|
||||
className={`font-semibold tabular-nums ${
|
||||
isExpired
|
||||
|
||||
@@ -95,7 +95,11 @@ const UsageScriptModal: React.FC<UsageScriptModalProps> = ({
|
||||
provider.meta?.usage_script || {
|
||||
enabled: false,
|
||||
language: "javascript",
|
||||
code: PRESET_TEMPLATES[t("usageScript.presetTemplate") === "预设模板" ? "通用模板" : "General"],
|
||||
code: PRESET_TEMPLATES[
|
||||
t("usageScript.presetTemplate") === "预设模板"
|
||||
? "通用模板"
|
||||
: "General"
|
||||
],
|
||||
timeout: 10,
|
||||
}
|
||||
);
|
||||
@@ -132,16 +136,24 @@ const UsageScriptModal: React.FC<UsageScriptModalProps> = ({
|
||||
return `${planInfo} ${t("usage.remaining")} ${plan.remaining} ${plan.unit}`;
|
||||
})
|
||||
.join(", ");
|
||||
toast.success(`${t("usageScript.testSuccess")}${summary}`, { duration: 3000 });
|
||||
} else {
|
||||
toast.error(`${t("usageScript.testFailed")}: ${result.error || t("endpointTest.noResult")}`, {
|
||||
duration: 5000,
|
||||
toast.success(`${t("usageScript.testSuccess")}${summary}`, {
|
||||
duration: 3000,
|
||||
});
|
||||
} else {
|
||||
toast.error(
|
||||
`${t("usageScript.testFailed")}: ${result.error || t("endpointTest.noResult")}`,
|
||||
{
|
||||
duration: 5000,
|
||||
},
|
||||
);
|
||||
}
|
||||
} catch (error: any) {
|
||||
toast.error(`${t("usageScript.testFailed")}: ${error?.message || t("common.unknown")}`, {
|
||||
duration: 5000,
|
||||
});
|
||||
toast.error(
|
||||
`${t("usageScript.testFailed")}: ${error?.message || t("common.unknown")}`,
|
||||
{
|
||||
duration: 5000,
|
||||
},
|
||||
);
|
||||
} finally {
|
||||
setTesting(false);
|
||||
}
|
||||
@@ -160,9 +172,12 @@ const UsageScriptModal: React.FC<UsageScriptModalProps> = ({
|
||||
setScript({ ...script, code: formatted.trim() });
|
||||
toast.success(t("usageScript.formatSuccess"), { duration: 1000 });
|
||||
} catch (error: any) {
|
||||
toast.error(`${t("usageScript.formatFailed")}: ${error?.message || t("jsonEditor.invalidJson")}`, {
|
||||
duration: 3000,
|
||||
});
|
||||
toast.error(
|
||||
`${t("usageScript.formatFailed")}: ${error?.message || t("jsonEditor.invalidJson")}`,
|
||||
{
|
||||
duration: 3000,
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -177,7 +192,9 @@ const UsageScriptModal: React.FC<UsageScriptModalProps> = ({
|
||||
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
|
||||
<DialogContent className="max-w-3xl max-h-[90vh] flex flex-col">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t("usageScript.title")} - {provider.name}</DialogTitle>
|
||||
<DialogTitle>
|
||||
{t("usageScript.title")} - {provider.name}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
{/* Content - Scrollable */}
|
||||
@@ -231,7 +248,7 @@ const UsageScriptModal: React.FC<UsageScriptModalProps> = ({
|
||||
<p className="mt-2 text-xs text-gray-500 dark:text-gray-400">
|
||||
{t("usageScript.variablesHint", {
|
||||
apiKey: "{{apiKey}}",
|
||||
baseUrl: "{{baseUrl}}"
|
||||
baseUrl: "{{baseUrl}}",
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
@@ -260,7 +277,9 @@ const UsageScriptModal: React.FC<UsageScriptModalProps> = ({
|
||||
|
||||
{/* 脚本说明 */}
|
||||
<div className="p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg text-sm text-gray-700 dark:text-gray-300">
|
||||
<h4 className="font-medium mb-2">{t("usageScript.scriptHelp")}</h4>
|
||||
<h4 className="font-medium mb-2">
|
||||
{t("usageScript.scriptHelp")}
|
||||
</h4>
|
||||
<div className="space-y-3 text-xs">
|
||||
<div>
|
||||
<strong>{t("usageScript.configFormat")}</strong>
|
||||
@@ -304,7 +323,12 @@ const UsageScriptModal: React.FC<UsageScriptModalProps> = ({
|
||||
<div className="text-gray-600 dark:text-gray-400">
|
||||
<strong>{t("usageScript.tips")}</strong>
|
||||
<ul className="mt-1 space-y-0.5 ml-2">
|
||||
<li>{t("usageScript.tip1", { apiKey: "{{apiKey}}", baseUrl: "{{baseUrl}}" })}</li>
|
||||
<li>
|
||||
{t("usageScript.tip1", {
|
||||
apiKey: "{{apiKey}}",
|
||||
baseUrl: "{{baseUrl}}",
|
||||
})}
|
||||
</li>
|
||||
<li>{t("usageScript.tip2")}</li>
|
||||
<li>{t("usageScript.tip3")}</li>
|
||||
</ul>
|
||||
|
||||
@@ -21,9 +21,7 @@ export function ModeToggle() {
|
||||
<Button variant="outline" size="icon" onClick={toggleTheme}>
|
||||
<Sun className="h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
<Moon className="absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||
<span className="sr-only">
|
||||
{t("common.toggleTheme")}
|
||||
</span>
|
||||
<span className="sr-only">{t("common.toggleTheme")}</span>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -143,9 +143,7 @@ export function AddProviderDialog({
|
||||
<DialogContent className="max-w-3xl max-h-[85vh] min-h-[600px] flex flex-col">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{submitLabel}</DialogTitle>
|
||||
<DialogDescription>
|
||||
{t("provider.addProviderHint")}
|
||||
</DialogDescription>
|
||||
<DialogDescription>{t("provider.addProviderHint")}</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex-1 overflow-y-auto px-6 py-4">
|
||||
|
||||
@@ -67,9 +67,7 @@ export function EditProviderDialog({
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="max-w-3xl max-h-[85vh] min-h-[600px] flex flex-col">
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
{t("provider.editProvider")}
|
||||
</DialogTitle>
|
||||
<DialogTitle>{t("provider.editProvider")}</DialogTitle>
|
||||
<DialogDescription>
|
||||
{t("provider.editProviderHint")}
|
||||
</DialogDescription>
|
||||
|
||||
@@ -29,7 +29,8 @@ export function ProviderActions({
|
||||
disabled={isCurrent}
|
||||
className={cn(
|
||||
"w-20",
|
||||
isCurrent && "bg-gray-200 text-muted-foreground hover:bg-gray-200 hover:text-muted-foreground dark:bg-gray-700 dark:hover:bg-gray-700",
|
||||
isCurrent &&
|
||||
"bg-gray-200 text-muted-foreground hover:bg-gray-200 hover:text-muted-foreground dark:bg-gray-700 dark:hover:bg-gray-700",
|
||||
)}
|
||||
>
|
||||
{isCurrent ? (
|
||||
|
||||
@@ -14,9 +14,7 @@ export function ProviderEmptyState({ onCreate }: ProviderEmptyStateProps) {
|
||||
<div className="mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-muted">
|
||||
<Users className="h-7 w-7 text-muted-foreground" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold">
|
||||
{t("provider.noProviders")}
|
||||
</h3>
|
||||
<h3 className="text-lg font-semibold">{t("provider.noProviders")}</h3>
|
||||
<p className="mt-2 max-w-sm text-sm text-muted-foreground">
|
||||
{t("provider.noProvidersDescription")}
|
||||
</p>
|
||||
|
||||
@@ -24,14 +24,9 @@ export function BasicFormFields({ form }: BasicFormFieldsProps) {
|
||||
name="name"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t("provider.name")}
|
||||
</FormLabel>
|
||||
<FormLabel>{t("provider.name")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
placeholder={t("provider.namePlaceholder")}
|
||||
/>
|
||||
<Input {...field} placeholder={t("provider.namePlaceholder")} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -43,9 +38,7 @@ export function BasicFormFields({ form }: BasicFormFieldsProps) {
|
||||
name="websiteUrl"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t("provider.websiteUrl")}
|
||||
</FormLabel>
|
||||
<FormLabel>{t("provider.websiteUrl")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} placeholder="https://" />
|
||||
</FormControl>
|
||||
|
||||
@@ -38,9 +38,7 @@ export function CommonConfigEditor({
|
||||
<>
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label htmlFor="settingsConfig">
|
||||
{t("provider.configJson")}
|
||||
</Label>
|
||||
<Label htmlFor="settingsConfig">{t("provider.configJson")}</Label>
|
||||
<div className="flex items-center gap-2">
|
||||
<label className="inline-flex items-center gap-2 text-sm text-muted-foreground cursor-pointer">
|
||||
<input
|
||||
|
||||
@@ -259,7 +259,7 @@ const EndpointSpeedTest: React.FC<EndpointSpeedTestProps> = ({
|
||||
}
|
||||
|
||||
// 明确只允许 http: 和 https:
|
||||
const allowedProtocols = ['http:', 'https:'];
|
||||
const allowedProtocols = ["http:", "https:"];
|
||||
if (!errorMsg && parsed && !allowedProtocols.includes(parsed.protocol)) {
|
||||
errorMsg = t("endpointTest.onlyHttps");
|
||||
}
|
||||
@@ -333,15 +333,20 @@ const EndpointSpeedTest: React.FC<EndpointSpeedTestProps> = ({
|
||||
try {
|
||||
await vscodeApi.removeCustomEndpoint(appType, providerId, entry.url);
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||
const errorMsg =
|
||||
error instanceof Error ? error.message : String(error);
|
||||
|
||||
// 只有"端点不存在"时才允许删除本地条目
|
||||
if (errorMsg.includes('not found') || errorMsg.includes('does not exist') || errorMsg.includes('不存在')) {
|
||||
console.warn(t('endpointTest.removeEndpointFailed'), errorMsg);
|
||||
if (
|
||||
errorMsg.includes("not found") ||
|
||||
errorMsg.includes("does not exist") ||
|
||||
errorMsg.includes("不存在")
|
||||
) {
|
||||
console.warn(t("endpointTest.removeEndpointFailed"), errorMsg);
|
||||
// 继续删除本地条目
|
||||
} else {
|
||||
// 其他错误:显示错误提示,阻止删除
|
||||
setLastError(t('endpointTest.removeFailed', { error: errorMsg }));
|
||||
setLastError(t("endpointTest.removeFailed", { error: errorMsg }));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,7 +455,11 @@ export function ProviderForm({
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form id="provider-form" onSubmit={form.handleSubmit(handleSubmit)} className="space-y-6">
|
||||
<form
|
||||
id="provider-form"
|
||||
onSubmit={form.handleSubmit(handleSubmit)}
|
||||
className="space-y-6"
|
||||
>
|
||||
{/* 预设供应商选择(仅新增模式显示) */}
|
||||
{!initialData && (
|
||||
<ProviderPresetSelector
|
||||
|
||||
@@ -114,9 +114,7 @@ export function ProviderPresetSelector({
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<FormLabel>
|
||||
{t("providerPreset.label")}
|
||||
</FormLabel>
|
||||
<FormLabel>{t("providerPreset.label")}</FormLabel>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{/* 自定义按钮 */}
|
||||
<button
|
||||
@@ -158,9 +156,7 @@ export function ProviderPresetSelector({
|
||||
});
|
||||
})}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{getCategoryHint()}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">{getCategoryHint()}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -122,10 +122,11 @@ export function useSpeedTestEndpoints({
|
||||
}
|
||||
|
||||
// 3. 编辑模式:初始数据中的 URL
|
||||
const initialCodexConfig =
|
||||
initialData?.settingsConfig as {
|
||||
config?: string;
|
||||
} | undefined;
|
||||
const initialCodexConfig = initialData?.settingsConfig as
|
||||
| {
|
||||
config?: string;
|
||||
}
|
||||
| undefined;
|
||||
const configStr = initialCodexConfig?.config ?? "";
|
||||
// 从 TOML 中提取 base_url
|
||||
const match = /base_url\s*=\s*["']([^"']+)["']/i.exec(configStr);
|
||||
|
||||
@@ -74,9 +74,7 @@ export function AboutSection({ isPortable }: AboutSectionProps) {
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("[AboutSection] Failed to open release notes", error);
|
||||
toast.error(
|
||||
t("settings.openReleaseNotesFailed"),
|
||||
);
|
||||
toast.error(t("settings.openReleaseNotesFailed"));
|
||||
}
|
||||
}, [t, updateInfo?.availableVersion, version]);
|
||||
|
||||
@@ -98,9 +96,7 @@ export function AboutSection({ isPortable }: AboutSectionProps) {
|
||||
await relaunchApp();
|
||||
} catch (error) {
|
||||
console.error("[AboutSection] Update failed", error);
|
||||
toast.error(
|
||||
t("settings.updateFailed"),
|
||||
);
|
||||
toast.error(t("settings.updateFailed"));
|
||||
try {
|
||||
await settingsApi.checkUpdates();
|
||||
} catch (fallbackError) {
|
||||
@@ -122,14 +118,11 @@ export function AboutSection({ isPortable }: AboutSectionProps) {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[AboutSection] Check update failed", error);
|
||||
toast.error(
|
||||
t("settings.checkUpdateFailed"),
|
||||
);
|
||||
toast.error(t("settings.checkUpdateFailed"));
|
||||
}
|
||||
}, [checkUpdate, hasUpdate, isPortable, resetDismiss, t, updateHandle]);
|
||||
|
||||
const displayVersion =
|
||||
version ?? t("common.unknown");
|
||||
const displayVersion = version ?? t("common.unknown");
|
||||
|
||||
return (
|
||||
<section className="space-y-4">
|
||||
|
||||
@@ -142,9 +142,7 @@ function ImportStatusMessage({
|
||||
<Loader2 className="mt-0.5 h-4 w-4 animate-spin text-muted-foreground" />
|
||||
<div>
|
||||
<p className="font-medium">{t("settings.importing")}</p>
|
||||
<p className="text-muted-foreground">
|
||||
{t("common.loading")}
|
||||
</p>
|
||||
<p className="text-muted-foreground">{t("common.loading")}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -169,17 +167,13 @@ function ImportStatusMessage({
|
||||
);
|
||||
}
|
||||
|
||||
const message =
|
||||
errorMessage ||
|
||||
t("settings.importFailed");
|
||||
const message = errorMessage || t("settings.importFailed");
|
||||
|
||||
return (
|
||||
<div className={`${baseClass} border-red-200 bg-red-100/70 text-red-600`}>
|
||||
<AlertCircle className="mt-0.5 h-4 w-4" />
|
||||
<div className="space-y-1">
|
||||
<p className="font-medium">
|
||||
{t("settings.importFailed")}
|
||||
</p>
|
||||
<p className="font-medium">{t("settings.importFailed")}</p>
|
||||
<p>{message}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -142,9 +142,7 @@ export function SettingsDialog({
|
||||
const handleRestartNow = useCallback(async () => {
|
||||
setShowRestartPrompt(false);
|
||||
if (import.meta.env.DEV) {
|
||||
toast.success(
|
||||
t("settings.devModeRestartHint"),
|
||||
);
|
||||
toast.success(t("settings.devModeRestartHint"));
|
||||
closeAfterSave();
|
||||
return;
|
||||
}
|
||||
@@ -153,9 +151,7 @@ export function SettingsDialog({
|
||||
await settingsApi.restart();
|
||||
} catch (error) {
|
||||
console.error("[SettingsDialog] Failed to restart app", error);
|
||||
toast.error(
|
||||
t("settings.restartFailed"),
|
||||
);
|
||||
toast.error(t("settings.restartFailed"));
|
||||
} finally {
|
||||
closeAfterSave();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user