mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-01 16:12:02 +00:00
fix(settings): check push again when the user comes back to the tab
The notification settings read the push state once, when they opened. Push turned off meanwhile - in the browser's site settings, or from another tab - still showed as on until the page was reloaded. The state is now read again when the window regains focus or the tab becomes visible, unless an enable or disable is in progress or has just failed. A failed check reads as off instead of leaving the panel unchanged.
This commit is contained in:
@@ -103,6 +103,20 @@ describe('NotificationSettings - pushNotifyInboxOnly', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('checks push again when the user comes back to the tab', async () => {
|
||||
Object.defineProperty(document, 'visibilityState', { value: 'visible', configurable: true });
|
||||
const { findByText } = render(<NotificationSettings />);
|
||||
await findByText('email.inbox_only');
|
||||
const check = webPush.isWebPushEnabled as ReturnType<typeof vi.fn>;
|
||||
await waitFor(() => expect(check).toHaveBeenCalled());
|
||||
const before = check.mock.calls.length;
|
||||
|
||||
// Push may have been turned off elsewhere (site settings, another tab) meanwhile.
|
||||
await act(async () => { window.dispatchEvent(new Event('focus')); });
|
||||
|
||||
await waitFor(() => expect(check.mock.calls.length).toBeGreaterThan(before));
|
||||
});
|
||||
|
||||
it('does not re-sync when push is disabled on this device', async () => {
|
||||
(webPush.isWebPushEnabled as ReturnType<typeof vi.fn>).mockResolvedValueOnce(false);
|
||||
render(<NotificationSettings />);
|
||||
|
||||
@@ -80,16 +80,37 @@ export function NotificationSettings() {
|
||||
const activeRelayLabel =
|
||||
relayOptions.find((option) => option.url === activeRelayUrl)?.label ?? activeRelayUrl;
|
||||
|
||||
const busy = pushStatus.kind === 'busy';
|
||||
|
||||
useEffect(() => {
|
||||
if (!supported) return;
|
||||
if (!client) return;
|
||||
const accountId = client.getAccountId();
|
||||
if (!accountId) return;
|
||||
void (async () => {
|
||||
const enabled = await isWebPushEnabled(accountId);
|
||||
setPushStatus(enabled ? { kind: 'enabled' } : { kind: 'idle' });
|
||||
})();
|
||||
}, [supported, client]);
|
||||
let cancelled = false;
|
||||
const refreshStatus = async () => {
|
||||
try {
|
||||
const enabled = await isWebPushEnabled(accountId);
|
||||
if (!cancelled) {
|
||||
setPushStatus(enabled ? { kind: 'enabled' } : { kind: 'idle' });
|
||||
}
|
||||
} catch {
|
||||
if (!cancelled) setPushStatus({ kind: 'idle' });
|
||||
}
|
||||
};
|
||||
const onVisible = () => {
|
||||
if (document.visibilityState === 'visible') void refreshStatus();
|
||||
};
|
||||
if (pushStatus.kind === 'busy' || pushStatus.kind === 'error') return;
|
||||
void refreshStatus();
|
||||
window.addEventListener('focus', onVisible);
|
||||
document.addEventListener('visibilitychange', onVisible);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
window.removeEventListener('focus', onVisible);
|
||||
document.removeEventListener('visibilitychange', onVisible);
|
||||
};
|
||||
}, [supported, client, pushStatus.kind]);
|
||||
|
||||
// The device list is worth loading even when push is off on this browser -
|
||||
// revoking a stale registration left on another device is exactly what you
|
||||
@@ -108,7 +129,6 @@ export function NotificationSettings() {
|
||||
void refreshDevices();
|
||||
}, [refreshDevices]);
|
||||
|
||||
const busy = pushStatus.kind === 'busy';
|
||||
const pushEnabled = pushStatus.kind === 'enabled';
|
||||
// In the static Lite build push is off by design (no service worker, see
|
||||
// components/service-worker-registration.tsx), not a browser limitation.
|
||||
|
||||
Reference in New Issue
Block a user