Skip to content

feat(sliding-sync): rewrite MSC4186 sliding sync to match Element Web approach#101

Open
Just-Insane wants to merge 6 commits intoSableClient:devfrom
Just-Insane:feat/sliding-sync
Open

feat(sliding-sync): rewrite MSC4186 sliding sync to match Element Web approach#101
Just-Insane wants to merge 6 commits intoSableClient:devfrom
Just-Insane:feat/sliding-sync

Conversation

@Just-Insane
Copy link
Contributor

@Just-Insane Just-Insane commented Mar 9, 2026

Rewrites the sliding sync implementation to more closely match how Element Web handles MSC4186 simplified sliding sync. The classic sync path (startClassicSync) is not modified.

Sliding sync improvements (slidingSync.ts, initMatrix.ts)

  • Room list sorted by notification level, then recency, then name (matching Element Web ordering)
  • include_old_rooms added so tombstoned rooms pass predecessor state to their replacements
  • Active-room custom subscription: the focused room receives timeline_limit=50; all other rooms use the default list subscription
  • SlidingSyncManager.subscribeToRoom() / unsubscribeFromRoom() API for per-room subscription lifecycle
  • getSlidingSyncManager() exported from initMatrix
  • useSlidingSyncActiveRoom hook + SlidingSyncActiveRoomSubscriber component to wire the active room into the sliding sync subscription

Presence extension (slidingSync.ts)

  • Implements a custom MSC4186 ExtensionPresence and registers it with the SlidingSync object
  • Without this, the SDK's SlidingSyncSdk only auto-registers ExtensionToDevice and ExtensionAccountData, so extensions.presence.events payloads from the server were silently discarded — components using useUserPresence would always show stale/default presence
  • The extension maps raw events through client.getEventMapper(), calls user.setPresenceEvent() to update User state, and emits ClientEvent.Event — matching the classic sync presence path exactly
  • SlidingSyncManager.setPresenceEnabled() exposes an enable/disable toggle (consumed by the presence toggle in feat(presence): presence status setting #108)

Timeline reliability (RoomTimeline.tsx, ClientNonUIFeatures.tsx)

  • Always reinitialise the timeline room on TimelineRefresh events (previously guarded by a stale liveTimeline reference check)
  • Fixes a silent hang where the room timeline stops updating after a sliding sync reconnect

Note: This branch currently contains a few unrelated commits (Docker build fix, notification delivery bugs, in-app bug report) that were included before the branch was scoped. These will be cleaned up / rebased out.

@Just-Insane Just-Insane requested a review from a team March 9, 2026 20:47
@Just-Insane Just-Insane marked this pull request as draft March 9, 2026 21:14
@Just-Insane Just-Insane marked this pull request as ready for review March 9, 2026 21:34
@Just-Insane Just-Insane force-pushed the feat/sliding-sync branch 2 times, most recently from bc369dc to 9ad69ac Compare March 9, 2026 22:14
@Just-Insane Just-Insane changed the title feat(sliding-sync): full MSC4186 simplified sliding sync support feat(sliding-sync): rewrite MSC4186 sliding sync to match Element Web approach Mar 9, 2026
@Just-Insane Just-Insane force-pushed the feat/sliding-sync branch 2 times, most recently from 6f03387 to 049dea2 Compare March 9, 2026 23:14
Evie Gauthier added 6 commits March 9, 2026 21:39
- Sort lists by notification level, recency, then name
- Add include_old_rooms for tombstoned room predecessor state
- Active-room custom subscription (timeline_limit=50) for the viewed room
- SlidingSyncManager.subscribeToRoom / unsubscribeFromRoom
- Export getSlidingSyncManager from initMatrix
- useSlidingSyncActiveRoom hook + SlidingSyncActiveRoomSubscriber component
- No changes to the classic sync path (startClassicSync / buildClient)
Register a custom MSC4186 presence extension with the SlidingSync object so
that m.presence events delivered via extensions.presence.events are processed
into the SDK's User model on every poll.

Without this, the SlidingSync object only auto-registers ExtensionToDevice and
ExtensionAccountData (via SlidingSyncSdk), so presence payloads from the server
were silently discarded. Components using useUserPresence (Profile, MembersDrawer,
UserRoomProfile, UserHero, Presence) would always show stale/default presence.

The extension follows the same path as regular /sync: map raw events through
client.getEventMapper(), call user.setPresenceEvent() to update User state and
emit UserEvent.Presence, UserEvent.CurrentlyActive, UserEvent.LastPresenceTs,
then emit ClientEvent.Event on the client.
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