fix(mail): infinite re-render in MailSettings + error handling + sync result

- Fix infinite re-render: loadAccounts had selectedAccountId in deps causing
  repeated fetches every render; use functional setState and empty deps
- Fix all error handlers in MailSettings: err?.message || err?.detail instead of String(err)
- Fix sync result handling: backend returns {synced, error?} not {success, synced_count}
- This infinite re-render was flooding the browser with requests, causing
  Network Error for SignatureManager API calls
This commit is contained in:
Agent Zero
2026-07-16 22:20:41 +02:00
parent 214814785e
commit 68a9415e99
+19 -14
View File
@@ -51,14 +51,15 @@ export function MailSettingsPage() {
try { try {
const accs = await fetchAccounts(); const accs = await fetchAccounts();
setAccounts(accs); setAccounts(accs);
if (accs.length > 0 && !selectedAccountId) { if (accs.length > 0) {
setSelectedAccountId(accs[0].id); setSelectedAccountId((prev) => prev || accs[0].id);
} }
} catch (err) { } catch (err: any) {
toast.error(err instanceof Error ? err.message : String(err)); toast.error(err?.message || err?.detail || 'Failed to load accounts');
} }
setLoading(false); setLoading(false);
}, [selectedAccountId, toast]); // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => { loadAccounts(); }, [loadAccounts]); useEffect(() => { loadAccounts(); }, [loadAccounts]);
@@ -79,8 +80,8 @@ export function MailSettingsPage() {
smtp_port: 587, smtp_port: 587,
password: '', password: '',
}); });
} catch (err) { } catch (err: any) {
toast.error(err instanceof Error ? err.message : String(err)); toast.error(err?.message || err?.detail || 'Save failed');
} finally { } finally {
setSaving(false); setSaving(false);
} }
@@ -95,8 +96,8 @@ export function MailSettingsPage() {
} else { } else {
toast.error(result.message); toast.error(result.message);
} }
} catch (err) { } catch (err: any) {
toast.error(err instanceof Error ? err.message : String(err)); toast.error(err?.message || err?.detail || 'Connection test failed');
} finally { } finally {
setTesting(null); setTesting(null);
} }
@@ -106,9 +107,13 @@ export function MailSettingsPage() {
setSyncing(accountId); setSyncing(accountId);
try { try {
const result = await triggerSync(accountId); const result = await triggerSync(accountId);
toast.success(t('mail.syncSuccess', { count: result.synced_count })); if ((result as any)?.error) {
} catch (err) { toast.error((result as any).error);
toast.error(err instanceof Error ? err.message : String(err)); } else {
toast.success(t('mail.syncSuccess'));
}
} catch (err: any) {
toast.error(err?.message || err?.detail || 'Sync failed');
} finally { } finally {
setSyncing(null); setSyncing(null);
} }
@@ -120,8 +125,8 @@ export function MailSettingsPage() {
await deleteAccount(accountId); await deleteAccount(accountId);
setAccounts((prev) => prev.filter((a) => a.id !== accountId)); setAccounts((prev) => prev.filter((a) => a.id !== accountId));
toast.success(t('mail.accountDeleted')); toast.success(t('mail.accountDeleted'));
} catch (err) { } catch (err: any) {
toast.error(err instanceof Error ? err.message : String(err)); toast.error(err?.message || err?.detail || 'Delete failed');
} }
}, [toast, t]); }, [toast, t]);