element-hq / element-hq/element-web
Desktop notifications are shown twice for unencrypted highlight messages
- Dominant language
- TypeScript
- Stars
- 13.5k
- Forks
- 2.8k
- PR merge metrics
- PR metrics pending
Description
### Steps to reproduce
1. Use Element Web or Element Desktop on any platform with desktop notifications enabled.
2. Have another user (or a bot) send a plaintext (unencrypted room) message that triggers a highlight push rule for you — e.g. a message containing your display name (.m.rule.contains_display_name), a user mention (.m.rule.is_user_mention), or @room.
3. Keep the room out of focus.
### Outcome
Two identical OS notifications are shown for the single event. Expected: one.
The bug does not reproduce in encrypted rooms, and does not reproduce for non-highlight messages — that asymmetry is explained by the root cause below.
Root cause analysis (verified against element-web v1.12.22/v1.12.23, matrix-js-sdk v41.8.0)
Notifier.onEvent subscribes to RoomEvent.Timeline on the client. For an unencrypted event whose push actions are notify + tweaks.highlight, the client emits RoomEvent.Timeline twice for the same event:
1. The event is added to the room's live timeline → the room re-emits → client emits → toast 1.
2. During sync processing, processEventsForNotifs (matrix-js-sdk/src/sync.ts ~L1918) accumulates every event with notify && tweaks.highlight and adds it to the global notification timeline set (client.getNotifTimelineSet().addLiveEvent(...), sync.ts ~L1570)
with data.liveEvent = true. The SyncApi constructor re-emits RoomEvent.Timeline from that set to the client (sync.ts ~L239) → Notifier.onEvent runs again for the same event, all guards pass (it only filters thread-list timelines via threadListType !== null), → identical toast 2.
Encrypted events don't hit path 2: at sync-processing time they are still m.room.encrypted, push evaluation yields no highlight, so they are never added to the notification timeline set (decryption happens later, and nothing re-adds them).
### Operating system
Windows 11 Pro, build 26200.8655
### Application version
v1.12.23
Contributor guide
Research direction
Start with Notifier.onEvent in element-web and trace its RoomEvent.Timeline subscription, then inspect matrix-js-sdk/src/sync.ts around the cited notification-timeline handling and SyncApi re-emission. Reproduce the plaintext highlight case and verify that one event produces one OS notification without changing the encrypted or non-highlight behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100