fix(mail): reactive page (refresh stats + status on scan/connect) + center donut+legend
Two small fixes blocking real "feierabend":
1. Stats-Counter veraltet nach Scan/Connect/Disconnect:
- mail.tsx hatte zwei separate Data-Sources: useMailStatus (accounts +
errors + heartbeat) und useMailStats (blockedByDay + blockedByConnection)
- onScanSuccess + onIntervalChanged + OAuth-onSuccess + disconnect-handler
refreshten nur useMailStatus → der Account-Collapsible-Counter (kommt
aus useMailStats.blockedByConnection) blieb veraltet
- Beobachtet: GMX-Scan-Button meldet "90 blockiert" als Feedback, aber
Card-Header zeigt weiter 60
- Fix: refreshAll() = refresh() + refreshStats() parallel. Alle reactive
callsites (4 Stellen) auf refreshAll umgestellt
- useMailStats hatte refresh schon exportiert (Z. 153), nur nicht
verdrahtet
2. Donut + Legend horizontal zentriert:
- vorher: alignItems center (vertikal), Legend flex:1 → linksbündig mit
Legend bis Card-Rand gestreckt
- jetzt: justifyContent center + Legend ohne flex:1 → Block in der Mitte
mit Whitespace links/rechts
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
30ed4b90b4
commit
4580a197dd
@ -255,7 +255,16 @@ export default function MailScreen() {
|
||||
useMailStatus(plan);
|
||||
const { disconnect, disconnecting } = useMailDisconnect();
|
||||
const hasAccounts = accounts.length > 0;
|
||||
const { blockedByDay, blockedByConnection } = useMailStats(hasAccounts);
|
||||
const { blockedByDay, blockedByConnection, refresh: refreshStats } = useMailStats(hasAccounts);
|
||||
|
||||
// Globaler Refresh-Handler für alle reactive-Trigger (Scan-Success,
|
||||
// Interval-Change, Connect/Disconnect): refresht beide Datenquellen
|
||||
// parallel — useMailStatus (accounts, connect-errors, heartbeat) UND
|
||||
// useMailStats (blockedByDay, blockedByConnection für Charts + Counter).
|
||||
const refreshAll = () => {
|
||||
refresh();
|
||||
refreshStats();
|
||||
};
|
||||
|
||||
const [sheetVisible, setSheetVisible] = useState(false);
|
||||
const [successVisible, setSuccessVisible] = useState(false);
|
||||
@ -290,11 +299,11 @@ export default function MailScreen() {
|
||||
await disconnect(id);
|
||||
setDisconnectingId(null);
|
||||
if (expandedAccount === id) setExpandedAccount(null);
|
||||
refresh();
|
||||
refreshAll();
|
||||
}
|
||||
|
||||
function handleConnectSuccess() {
|
||||
refresh();
|
||||
refreshAll();
|
||||
if (pendingOAuthConnectionId) {
|
||||
setOauthTitleSheetConnectionId(pendingOAuthConnectionId);
|
||||
setPendingOAuthConnectionId(null);
|
||||
@ -509,11 +518,11 @@ export default function MailScreen() {
|
||||
expanded={expandedAccount === account.id}
|
||||
onToggle={() => toggleAccount(account.id)}
|
||||
onDisconnect={handleDisconnect}
|
||||
onIntervalChanged={refresh}
|
||||
onIntervalChanged={refreshAll}
|
||||
onEditSuccess={handleConnectSuccess}
|
||||
disconnecting={disconnectingId === account.id && disconnecting}
|
||||
blockedLast30d={connStat?.count}
|
||||
onScanSuccess={refresh}
|
||||
onScanSuccess={refreshAll}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@ -533,7 +542,7 @@ export default function MailScreen() {
|
||||
connectionId={oauthTitleSheetConnectionId}
|
||||
currentTitle={null}
|
||||
onClose={() => { setOauthTitleSheetConnectionId(null); setSuccessVisible(true); }}
|
||||
onSuccess={() => { setOauthTitleSheetConnectionId(null); setSuccessVisible(true); refresh(); }}
|
||||
onSuccess={() => { setOauthTitleSheetConnectionId(null); setSuccessVisible(true); refreshAll(); }}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@ -98,14 +98,14 @@ export function MailDistributionChart({ data, hero, totalBlocked, isLegend }: Pr
|
||||
paddingBottom: 12,
|
||||
}}
|
||||
>
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 16 }}>
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 16 }}>
|
||||
<HalfDonut
|
||||
segments={segments}
|
||||
centerValue={centerValue}
|
||||
centerLabel={centerLabel}
|
||||
width={DONUT_WIDTH}
|
||||
/>
|
||||
<View style={{ flex: 1, gap: 5 }}>
|
||||
<View style={{ gap: 5 }}>
|
||||
{slices.map((slice) => (
|
||||
<LegendRow key={slice.label} slice={slice} colors={colors} />
|
||||
))}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user