From e460dbd34eed06e0d1c7e1a8dcbeab938c800527 Mon Sep 17 00:00:00 2001 From: litruv Date: Tue, 28 Jul 2026 00:40:02 +1000 Subject: [PATCH] Improve UnifiedPush reset UX: poll for endpoint and clearer status. --- .../notifications/SystemNotification.tsx | 71 ++++++++++++++----- src/app/utils/backgroundSync.ts | 13 +++- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/src/app/features/settings/notifications/SystemNotification.tsx b/src/app/features/settings/notifications/SystemNotification.tsx index 4b31548..eb21a4f 100644 --- a/src/app/features/settings/notifications/SystemNotification.tsx +++ b/src/app/features/settings/notifications/SystemNotification.tsx @@ -170,22 +170,30 @@ type PushStatus = { registered: boolean; distributor: string; endpoint: string; + distributors: string[]; }; /** Android-only section showing UnifiedPush registration status and controls. */ function AndroidPushNotifications() { const [status, setStatus] = useState(undefined); const [loading, setLoading] = useState(true); + const [lastError, setLastError] = useState(undefined); const refresh = useCallback(async () => { setLoading(true); const s = await getBackgroundSyncStatus(); + const distributors = Array.isArray(s?.distributors) + ? s.distributors + : typeof s?.distributors === 'string' && s.distributors && s.distributors !== '[]' + ? [s.distributors] + : []; setStatus( s ? { registered: s.registered, distributor: s.distributor || '', endpoint: s.endpoint || '', + distributors, } : undefined ); @@ -198,8 +206,14 @@ function AndroidPushNotifications() { const [resetState, reset] = useAsyncCallback( useCallback(async () => { - await requestResetPushRegistration(); + setLastError(undefined); + const result = await requestResetPushRegistration(); await refresh(); + if (!result.success) { + setLastError( + 'Could not register a push distributor. Install ntfy (with UnifiedPush enabled), then try Reset again.' + ); + } }, [refresh]) ); @@ -214,6 +228,36 @@ function AndroidPushNotifications() { resetState.status === AsyncStatus.Loading || pingState.status === AsyncStatus.Loading; + const statusDescription = (() => { + if (loading) return 'Loading status…'; + if (status === undefined) { + return ( + + Failed to read push status. + + ); + } + if (status.registered) { + return ( + + {`Distributor: ${status.distributor || 'unknown'}`} + + ); + } + if (status.distributors.length === 0) { + return ( + + No UnifiedPush distributor found. Install ntfy from Play Store/F-Droid and enable UnifiedPush in ntfy settings. + + ); + } + return ( + + {`Found ${status.distributors.join(', ')} but not registered yet. Tap Reset and pick ntfy.`} + + ); + })(); + return ( Android Push (UnifiedPush) @@ -226,29 +270,20 @@ function AndroidPushNotifications() { - Failed to read push status. - - ) : status.registered ? ( - <> - - {`Distributor: ${status.distributor || 'unknown'}`} + <> + {statusDescription} + {lastError ? ( + + {lastError} - - ) : ( - - Not registered. Tap "Reset" to choose a distributor app. - - ) + ) : null} + } after={loading ? : undefined} /> ('MatrixBackgroundSync'); const result = await MatrixBackgroundSync.requestDistributorSetup(); console.log('[BackgroundSync] requestDistributorSetup completed:', result); - return result ?? { success: false }; + if (!result?.success) return { success: false }; + + // Endpoint arrives asynchronously from the distributor after register(). + for (let i = 0; i < 20; i += 1) { + await new Promise((resolve) => setTimeout(resolve, 250)); + const status = await getBackgroundSyncStatus(); + if (status?.registered && status.endpoint) { + return { success: true }; + } + } + + return { success: true }; } catch (err) { console.error('[BackgroundSync] requestDistributorSetup failed:', err); return { success: false };