Skip to content

fix(thread): handle notification.mark_unread event#1778

Open
TabishRiazBajwa wants to merge 1 commit into
GetStream:masterfrom
TabishRiazBajwa:thread-mark-unread-event
Open

fix(thread): handle notification.mark_unread event#1778
TabishRiazBajwa wants to merge 1 commit into
GetStream:masterfrom
TabishRiazBajwa:thread-mark-unread-event

Conversation

@TabishRiazBajwa

@TabishRiazBajwa TabishRiazBajwa commented Jun 21, 2026

Copy link
Copy Markdown

Summary

Fixes #3076

Thread currently subscribes to message.read events to keep its read state up to date, but never subscribes to notification.mark_unread events. This means that when a user marks a thread as unread, the Thread's local state never reflects it — unreadMessageCount stays stale until the thread is reloaded.

Root cause

Channel already has a working handler for notification.mark_unread (see channel.ts), and Thread already has all the state infrastructure needed (ThreadUserReadState with unreadMessageCount, lastReadAt, lastReadMessageId) — it was just never wired up to this event.

Changes

  • Added subscribeRepliesMarkUnread() to Thread, following the same .on() + filter pattern as the existing subscribeRepliesRead()
  • Registered the new subscription in registerSubscriptions()
  • Added 3 new test cases in threads.test.ts:
    • Ignores events from other threads (filtered by parent_message_id)
    • Ignores events for other users (only updates the current user's state)
    • Correctly updates unreadMessageCount, lastReadAt, and lastReadMessageId for the current user

Testing

All existing tests in threads.test.ts pass (87/87), including the 3 new ones added for this fix.

Notes

  • Did not add first_unread_message_id tracking since ThreadUserReadState doesn't currently have an equivalent field (unlike ChannelState) — happy to add this in a follow-up if desired.
  • Did not call messageReceiptsTracker, consistent with the existing subscribeRepliesRead() handler, since thread delivery receipts aren't supported yet.

CLA

  • I have signed the Stream CLA (required).
  • Code changes are tested

Description of the changes, What, Why and How?

Changelog

## Summary

Fixes #3076

`Thread` currently subscribes to `message.read` events to keep its read
state up to date, but never subscribes to `notification.mark_unread`
events. This means that when a user marks a thread as unread, the
`Thread`'s local state never reflects it — `unreadMessageCount` stays
stale until the thread is reloaded.

## Root cause

`Channel` already has a working handler for `notification.mark_unread`
(see `channel.ts`), and `Thread` already has all the state infrastructure
needed (`ThreadUserReadState` with `unreadMessageCount`, `lastReadAt`,
`lastReadMessageId`) — it was just never wired up to this event.

## Changes

- Added `subscribeRepliesMarkUnread()` to `Thread`, following the same
  `.on()` + filter pattern as the existing `subscribeRepliesRead()`
- Registered the new subscription in `registerSubscriptions()`
- Added 3 new test cases in `threads.test.ts`:
  - Ignores events from other threads (filtered by `parent_message_id`)
  - Ignores events for other users (only updates the current user's state)
  - Correctly updates `unreadMessageCount`, `lastReadAt`, and
    `lastReadMessageId` for the current user

## Testing

All existing tests in `threads.test.ts` pass (87/87), including the 3 new
ones added for this fix.

## Notes

- Did not add `first_unread_message_id` tracking since `ThreadUserReadState`
  doesn't currently have an equivalent field (unlike `ChannelState`) —
  happy to add this in a follow-up if desired.
- Did not call `messageReceiptsTracker`, consistent with the existing
  `subscribeRepliesRead()` handler, since thread delivery receipts aren't
  supported yet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant