fix ui and oauth

This commit is contained in:
LPF
2026-03-12 00:32:56 +08:00
parent 5e0c371bb9
commit e2cea0bce2
19 changed files with 674 additions and 188 deletions

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useRef, useState } from 'react';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { RefreshCw, Save } from 'lucide-react';
import { useAppContext } from '../context/AppContext';
@@ -29,6 +29,8 @@ const Providers: React.FC = () => {
const latestProviderRuntimeRef = useRef<any[]>([]);
const [displayedProviderRuntimeItems, setDisplayedProviderRuntimeItems] = useState<any[]>([]);
const [oauthAccounts, setOAuthAccounts] = useState<Record<string, Array<any>>>({});
const [oauthAccountsLoading, setOAuthAccountsLoading] = useState<Record<string, boolean>>({});
const [oauthAccountsLoaded, setOAuthAccountsLoaded] = useState<Record<string, boolean>>({});
const providerEntries = useMemo(() => {
const providers = (((cfg as any)?.models || {}) as any)?.providers || {};
@@ -77,14 +79,6 @@ const Providers: React.FC = () => {
}
}, [activeProviderName, providerEntries]);
useEffect(() => {
providerEntries.forEach(([name, p]) => {
if (['oauth', 'hybrid'].includes(String(p?.auth || ''))) {
loadOAuthAccounts(name);
}
});
}, [providerEntries]);
useEffect(() => {
if (baseline == null && cfg && Object.keys(cfg).length > 0) {
setBaseline(cloneJSON(cfg));
@@ -131,6 +125,49 @@ const Providers: React.FC = () => {
ui,
});
const loadOAuthAccountsNow = useCallback(async (name: string) => {
if (!name) return;
setOAuthAccountsLoading((prev) => ({ ...prev, [name]: true }));
try {
await loadOAuthAccounts(name);
setOAuthAccountsLoaded((prev) => ({ ...prev, [name]: true }));
} finally {
setOAuthAccountsLoading((prev) => ({ ...prev, [name]: false }));
}
}, [loadOAuthAccounts]);
useEffect(() => {
providerEntries.forEach(([name, p]) => {
if (!['oauth', 'hybrid'].includes(String(p?.auth || ''))) return;
if (oauthAccountsLoaded[name] || oauthAccountsLoading[name]) return;
void loadOAuthAccountsNow(name);
});
}, [loadOAuthAccountsNow, oauthAccountsLoaded, oauthAccountsLoading, providerEntries]);
useEffect(() => {
if (!activeProviderEntry) return;
const [name, provider] = activeProviderEntry;
if (!['oauth', 'hybrid'].includes(String(provider?.auth || ''))) return;
if (oauthAccountsLoaded[name] || oauthAccountsLoading[name]) return;
void loadOAuthAccountsNow(name);
}, [activeProviderEntry, loadOAuthAccountsNow, oauthAccountsLoaded, oauthAccountsLoading]);
useEffect(() => {
const oauthProviderNames = new Set(
providerEntries
.filter(([, provider]) => ['oauth', 'hybrid'].includes(String(provider?.auth || '')))
.map(([name]) => name),
);
setOAuthAccountsLoaded((prev) => {
const next = Object.fromEntries(Object.entries(prev).filter(([name]) => oauthProviderNames.has(name)));
return Object.keys(next).length === Object.keys(prev).length ? prev : next;
});
setOAuthAccountsLoading((prev) => {
const next = Object.fromEntries(Object.entries(prev).filter(([name]) => oauthProviderNames.has(name)));
return Object.keys(next).length === Object.keys(prev).length ? prev : next;
});
}, [providerEntries]);
const { saveConfig } = useConfigSaveAction({
cfg,
cfgRaw,
@@ -161,12 +198,13 @@ const Providers: React.FC = () => {
<RefreshCw className="w-4 h-4" />
</FixedButton>
<Button onClick={() => setShowDiff(true)} size="sm">{t('configDiffPreview')}</Button>
<FixedButton onClick={saveConfig} variant="primary" label={t('saveChanges')}>
<Save className="w-4 h-4" />
</FixedButton>
</div>
}
/>
<Button onClick={saveConfig} variant="primary" size="sm" radius="lg" gap="1">
<Save className="w-4 h-4" />
{t('saveChanges')}
</Button>
</div>
}
/>
<div className="brand-card ui-border-subtle border rounded-[30px] p-4 md:p-6 space-y-4">
<ProviderRuntimeToolbar
@@ -217,10 +255,11 @@ const Providers: React.FC = () => {
key={activeProviderEntry[0]}
name={activeProviderEntry[0]}
oauthAccounts={oauthAccounts[activeProviderEntry[0]] || []}
oauthAccountsLoading={!!oauthAccountsLoading[activeProviderEntry[0]]}
onClearOAuthCooldown={(credentialFile) => clearOAuthCooldown(activeProviderEntry[0], credentialFile)}
onDeleteOAuthAccount={(credentialFile) => deleteOAuthAccount(activeProviderEntry[0], credentialFile)}
onFieldChange={(field, value) => updateProxyField(activeProviderEntry[0], field, value)}
onLoadOAuthAccounts={() => loadOAuthAccounts(activeProviderEntry[0])}
onLoadOAuthAccounts={() => loadOAuthAccountsNow(activeProviderEntry[0])}
onRefreshOAuthAccount={(credentialFile) => refreshOAuthAccount(activeProviderEntry[0], credentialFile)}
onRemove={() => removeProxy(activeProviderEntry[0])}
onStartOAuthLogin={() => startOAuthLogin(activeProviderEntry[0], activeProviderEntry[1])}