feat: account management overhaul + 7 issue resolutions (#147)
- Add smart JSON export/import with schema validation and deduplication - Add per-account proxy configurations (Issue #79) - Add advanced account sorting engine (Issues #126 & #99) - Add compact horizontal layout, AI credits, inline model visibility (Issues #145 & #134) - Add desktop push notifications for low quota (Issue #53) - Fix Arch Linux AUR process detection bug (Issue #117) - Default theme set to Dark Mode (it's better) - UI Polishing: Improved sort dropdown and symmetrical dialog layouts - Dev Mode: Resolved port conflicts and single-instance locks - Updated README and README.zh-CN with new features
This commit is contained in:
37 files changed
+1989
-455
No files matched your search
@@ -17,6 +17,7 @@ import { getAppVersion, getPlatform } from '@/actions/app';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { setAppLanguage } from '@/actions/language';
|
||||
import { useAppConfig } from '@/hooks/useAppConfig';
|
||||
import { useToast } from '@/components/ui/use-toast';
|
||||
import { Loader2, FolderOpen } from 'lucide-react';
|
||||
import { ModelVisibilitySettings } from '@/components/ModelVisibilitySettings';
|
||||
import { useEffect, useState } from 'react';
|
||||
@@ -27,6 +28,7 @@ function SettingsPage() {
|
||||
const { theme, setTheme } = useTheme();
|
||||
const { t, i18n } = useTranslation();
|
||||
const { config, isLoading, saveConfig } = useAppConfig();
|
||||
const { toast } = useToast();
|
||||
|
||||
// Local state for configuration editing
|
||||
const [proxyConfig, setProxyConfig] = useState<ProxyConfig | undefined>(undefined);
|
||||
@@ -297,6 +299,86 @@ function SettingsPage() {
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Notifications Card */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>{t('settings.notifications.title', 'Notifications')}</CardTitle>
|
||||
<CardDescription>
|
||||
{t(
|
||||
'settings.notifications.description',
|
||||
'Configure desktop alerts for account events.',
|
||||
)}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="flex items-center justify-between rounded-lg border p-4">
|
||||
<div className="space-y-1">
|
||||
<Label>{t('settings.notifications.quotaAlert', 'Low Quota Alerts')}</Label>
|
||||
<p className="text-xs text-gray-500">
|
||||
{t(
|
||||
'settings.notifications.quotaAlertDesc',
|
||||
'Get notified when a model quota drops below the set threshold',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
checked={config?.quota_alert_enabled || false}
|
||||
onCheckedChange={async (checked) => {
|
||||
if (config) {
|
||||
try {
|
||||
await saveConfig({ ...config, quota_alert_enabled: checked });
|
||||
} catch (err) {
|
||||
toast({
|
||||
title: t('common.error'),
|
||||
description: 'Failed to save notification settings',
|
||||
variant: 'destructive',
|
||||
});
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center justify-between rounded-lg border p-4">
|
||||
<div className="space-y-1">
|
||||
<Label>{t('settings.notifications.quotaThreshold', 'Alert Threshold')}</Label>
|
||||
<p className="text-xs text-gray-500">
|
||||
{t(
|
||||
'settings.notifications.quotaThresholdDesc',
|
||||
'Percentage below which to trigger an alert',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="number"
|
||||
min={0}
|
||||
max={100}
|
||||
value={config?.quota_alert_threshold ?? 20}
|
||||
onChange={async (e) => {
|
||||
const rawValue = e.target.value;
|
||||
const parsed = parseInt(rawValue, 10);
|
||||
if (isNaN(parsed) || parsed < 0 || parsed > 100) return;
|
||||
|
||||
if (config) {
|
||||
try {
|
||||
await saveConfig({ ...config, quota_alert_threshold: parsed });
|
||||
} catch (err) {
|
||||
toast({
|
||||
title: t('common.error'),
|
||||
description: 'Failed to save threshold setting',
|
||||
variant: 'destructive',
|
||||
});
|
||||
}
|
||||
}
|
||||
}}
|
||||
className="w-16 rounded-md border bg-transparent px-2 py-1 text-center text-sm"
|
||||
/>
|
||||
<span className="text-muted-foreground text-sm">%</span>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
|
||||
{/* --- MODELS TAB --- */}
|
||||
|
||||
Reference in new issue
Block a user