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.
Follow-ups to the review of the push, keyword and identity work:
- A send that names no sender, like the List-Unsubscribe mailto: of the
unified view, fell back to the first identity in server order, which
on Stalwart 1.0 is a group's. It now takes the login's own identity,
with addresses compared regardless of case.
- Re-register creates the replacement subscription before it destroys
the old one, so at Stalwart's limit (15 per account by default) it
failed with `overQuota`. It now frees the old record's place and
tries once more.
- On 1.0 the push settings note goes by the emailpush capability alone
and ignores refusals remembered under 0.16. On 0.16 a group the user
belongs to is recognised by its identity, so a member without
calendars, contacts or files keeps the group's junk filter and is no
longer told the group sends no notifications.
- Plugin imports can no longer set Stalwart 1.0's attachment keywords,
and `keywords.discover` leaves them out.
- Batch mark-as-read showed messages the server refused as read. It now
updates only what was written and reports the rest, and thread
expansion and category-tab moves keep what a partly refused batch
did write.
- Refused read and star changes from shortcuts, the list, the viewer
and Pro tabs show "Failed to update email" instead of an unhandled
rejection. The automatic mark-as-read on opening stays quiet.
- A tag whose id predates the 128-byte limit can have its colour
changed again.
- The state-regression guard notes that a multi-node 1.0 cluster can
trip it harmlessly, at the cost of one extra full fetch.
Stalwart refuses a push subscription's whole emailPush map as
`forbidden` when it names a mailbox shared by ACL (0.16.16 and later,
and 1.0). Bulwark put every account with mailboxes in the map, so
enabling push showed raw JSON, and the background re-sync destroyed the
working subscription after its refresh was refused and dropped its key:
push stopped without a word and could not be turned back on while the
share existed. A network error, a timeout or rate limiting during the
refresh ended it the same way.
- The map holds the primary account and the accounts that list
`urn:ietf:params:jmap:emailpush`, which 1.0 leaves off ACL shares.
0.16 lists it everywhere, so a refused map narrows to the accounts
that look owned, then to the primary account, as the mobile app does.
Refused accounts are remembered under
`bulwark.push.emailPushRefused.v1.<id>`; Re-register and disable
clear the list.
- A subscription ends only when a verified replacement exists, the user
turns push off, or the server no longer has it. The old record is
destroyed after the new one is verified. A failed listing, a network
error or a refused method call leave it and its key alone.
- PushSubscription/set failures throw typed errors (`jmapSetError` for
a refused object, `jmapError` for a refused call) instead of JSON in
the message or `false`, and the client exposes `getAccountInfo`.
- Settings says that mailboxes others share don't send background
notifications, and `forbidden` and `overQuota` read as plain text in
settings and the onboarding prompt.
The re-sync effect depended on pushStatus.kind, so its own
setPushStatus({ kind: 'busy' }) re-fired the effect, whose cleanup
cancelled the in-flight enableWebPush - the push row then sat on
"Working…" forever and never updated the filter. Depend only on the
setting flip; read client/relay/status live from the recreated closure.
Flipping the setting only wrote to the store; the server-side JMAP push
filter stayed stale until the next app launch ran resyncWebPush. When push
is already enabled on the device, re-run enableWebPush on change so the
toggle takes effect without a restart.
The notification panel only ever addresses the account on screen, so
arming a browser for five accounts meant switching account five times
and answering the same permission prompt on each pass.
The browser holds a single push subscription: enabling an account
registers it against that one subscription rather than creating another.
A section in the notification settings now lists every connected account
with its current state and turns push on or off for the ones selected,
walking them against the same subscription.
A refusal at the browser level - unsupported, or permission denied -
applies to every account, so it stops the walk instead of failing each
account in turn and prompting repeatedly.