Skip to content
This repository was archived by the owner on Mar 10, 2026. It is now read-only.

fix: notification delivery bugs#252

Open
Just-Insane wants to merge 7 commits into7w1:devfrom
CloudHub-Social:fix/notification-delivery-bugs
Open

fix: notification delivery bugs#252
Just-Insane wants to merge 7 commits into7w1:devfrom
CloudHub-Social:fix/notification-delivery-bugs

Conversation

@Just-Insane
Copy link
Collaborator

Summary

Fixes several bugs in how notifications are delivered and played.

Fixes

  • Push notifications always silentresolveSilent in the service worker now always returns false, leaving sound/vibration decisions entirely to the OS and Sygnal push gateway. The in-app sound setting no longer affects push sound.
  • In-app banner not appearing on desktop — The banner was gated behind a mobileOrTablet() check. It now fires on all platforms when In-App Notifications is enabled.
  • In-app banner showing "sent an encrypted message" — Events reaching the banner are already decrypted by the SDK. isEncryptedRoom: false is now passed so the actual message body is shown when content preview is enabled.
  • Desktop OS notifications not firing when page is hidden — The OS notification block now runs before the visibilityState !== 'visible' guard (which only gates the in-app banner and audio). Notifications now fire when the browser window is minimised.
  • iOS lock screen media player after notification soundmediaSession.playbackState is cleared after a short delay following play(). If in-app media has since registered its own metadata the session is left untouched.

Changed files

File Change
src/app/pages/client/ClientNonUIFeatures.tsx Remove mobileOrTablet() gate; move OS notification block before visibility guard; pass isEncryptedRoom: false; call clearMediaSessionQuickly() after play()
src/sw.ts Remove notificationSoundEnabled from postMessage payload
src/sw/pushNotification.ts resolveSilent = () => false

Evie Gauthier added 2 commits March 8, 2026 14:37
… audio, media session)

- resolveSilent = () => false — OS/Sygnal handles push sound entirely; the
  in-app sound setting no longer affects push notification sound
- remove notificationSoundEnabled from SW postMessage payload
- move OS notification block before visibilityState guard so desktop
  notifications fire even when the browser window is minimised
- pass isEncryptedRoom:false for in-app banner preview — events are already
  decrypted by the SDK so the actual message body is always shown
- call clearMediaSessionQuickly() after play() to dismiss the iOS lock screen
  media player; only clears playbackState if no real media metadata is set
@Just-Insane Just-Insane marked this pull request as ready for review March 8, 2026 18:44
@Just-Insane Just-Insane requested a review from 7w1 as a code owner March 8, 2026 18:44
The banner placement move (ClientNonUIFeatures -> ClientLayout) belongs
in the separate fix/notification-banner PR. Keep the render here so Knip
does not report the banner files as unused on this branch.
Just-Insane pushed a commit to CloudHub-Social/sable that referenced this pull request Mar 9, 2026
Evie Gauthier added 4 commits March 9, 2026 13:12
… sound tweak

Two bugs caused by sliding sync's limited required_state (only $ME member):

1. DM badge was grey instead of green
   Synapse sends highlight_count=0 for DMs without mention; the badge only
   showed as Success (green) when highlight>0. DMs should always display
   the green badge for any unread. Fix: RoomNavItem treats direct && total>0
   as highlight for the UnreadBadge highlight prop.

2. DM OS notification was silent
   PushProcessor evaluates .m.rule.room_one_to_one by checking
   room_member_count==2, but with only m.room.member/$ME in required_state
   the member count is 1, so the rule fails. Events fall through to
   .m.rule.message (notify, no sound), leaving loudByRule=false and the
   OS notification silent:true. Fix: isLoud = loudByRule || isDM so that
   known DM rooms always produce non-silent notifications when sounds are on.
useNotificationJumper was using roomToParents.get(roomId) — the direct
parent set — which could be a subspace rather than a root-level space.
The router only recognises /space/<root-space-id>/room paths, so linking
via a subspace ID would hit JoinBeforeNavigate instead of opening the room.

Replace with the same logic as useRoomNavigate:
  getOrphanParents() walks the full hierarchy to find root-level spaces,
  guessPerfectParent() picks the best one to route through.
…p in try/catch

Two bugs caused in-app notifications to silently vanish on desktop when
the window was focused:

1. window.Notification() was called unconditionally even when the window
   had focus.  In some browsers/environments (certain Chrome versions,
   Electron, macOS DnD mode) calling the Notification constructor throws
   or is silently rejected when the tab is active.  Without a try/catch
   the uncaught exception aborted the entire RoomEvent.Timeline handler
   before setInAppBanner was ever reached — so neither the OS notification
   NOR the in-app banner appeared.  InviteNotifications already used
   try/catch for the same reason; MessageNotifications did not.

2. The OS notification was semantically wrong when focused: the in-app
   banner is the correct alert while the window is active.  Added a
   !document.hasFocus() guard to match the comment's stated intent
   ("alert when minimised or tab not active") and to prevent a duplicate
   OS+in-app banner when another window is simply on top.

Mobile is unaffected: mobileOrTablet() already gates the OS block.
The in-app banner path (visibilityState === 'visible' → setInAppBanner)
is unchanged and continues to fire correctly on both desktop (focused)
and mobile (app visible in browser).
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant