Skip to content

feat(pwa): badge the installed app icon with unread count (Badging API) - #934

Open
dev-hive-kazniisa wants to merge 1 commit into
bulwarkmail:mainfrom
dev-hive-kazniisa:feat/pwa-app-badge
Open

feat(pwa): badge the installed app icon with unread count (Badging API)#934
dev-hive-kazniisa wants to merge 1 commit into
bulwarkmail:mainfrom
dev-hive-kazniisa:feat/pwa-app-badge

Conversation

@dev-hive-kazniisa

Copy link
Copy Markdown
Contributor

What

Adds useAppBadge, which mirrors the existing favicon unread badge onto the installed app icon via the Badging API (navigator.setAppBadge / clearAppBadge).

Chrome, Edge and WebKit render a separate icon for an installed PWA — taskbar, dock, Home Screen, pinned app shortcut — and that icon does not react to favicon changes at all. So a user who installs Bulwark as an app currently loses the unread indicator that tab users get. A merely pinned browser tab is unaffected either way; this only touches an actually installed app.

How

  • New hook hooks/use-app-badge.ts, mounted from the same FaviconBadge component and gated by the same faviconUnreadBadge setting — no new setting, no new i18n keys.
  • Feature-detected; a no-op where the API is unavailable.
  • No unmount cleanup on purpose. The badge is scoped to the installed app/origin, not to this component or window, so clearing it on every unmount would blank another still-open window's accurate badge. A count of zero, or the setting being turned off, already clears it through the main effect.

i18n

No new keys. The existing favicon_unread_badge label/description wording in en now mentions the app icon as well, and the ru translation for that key is filled in (it was still English). Per CONTRIBUTING, the other 22 locales fall back to English for the reworded string — happy to add them in this PR or a follow-up if you'd prefer them updated now.

Tests

hooks/__tests__/use-app-badge.test.tsx (new, 9 cases) and 4 added cases in components/__tests__/favicon-badge.test.tsx — 13 passing. npm run typecheck and npm run lint clean.

Notes

Running in production on a ~280-mailbox Stalwart deployment since 2026-08-14.

Adds useAppBadge alongside the existing useFaviconBadge, mounted from the
same FaviconBadge component and gated by the same faviconUnreadBadge
setting. Targets the separate icon Chrome/Edge/WebKit show for an
installed PWA (taskbar/dock/Home Screen/pinned-app-shortcut), which does
not react to favicon changes at all - a merely pinned browser tab is
unaffected, only an actually installed app.

No unmount cleanup: the badge is scoped to the installed app/origin, not
to this component or window, so clearing on every unmount would blank
another still-open window's accurate badge. A count of zero or the
setting being off already clears it through the main effect.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant