perf: reduce re-renders/syncs and fix presence issues#598
Closed
Just-Insane wants to merge 7 commits intoSableClient:devfrom
Closed
perf: reduce re-renders/syncs and fix presence issues#598Just-Insane wants to merge 7 commits intoSableClient:devfrom
Just-Insane wants to merge 7 commits intoSableClient:devfrom
Conversation
- Remove RoomEvent.UnreadNotifications from ThreadReplyChip: fired on
every room message, causing N×chip re-renders and O(n_events) scans
per message when N threads are visible. ThreadEvent.NewReply/Update
and RoomEvent.Redaction already cover the relevant updates.
- Memoize VList style in RoomTimeline: was creating a new object every
render (including the frequent setTimeline spreads from edits/replies)
- Replace empty style={} with undefined in RoomView: avoids a new
object reference on every render propagating into Page
- Reset useUserPresence state on userId change: useState initializer
only runs once; stale presence data shown when navigating between
user profiles until a UserEvent.Presence fires for the new user
- Fix useUserPresence hook: when User object doesn't exist yet (before first presence event from sliding sync), fall back to subscribing at the MatrixClient level via ClientEvent.Event. ExtensionPresence emits this after creating the User object so mx.getUser(userId) is non-null by the time the handler runs. Broaden deps from [user] to [mx, userId, user] so the effect re-subscribes at User level after the re-render. - AccountSwitcherTab: wrap own user avatar in AvatarPresence to show your own online/away/busy status as a dot in the sidebar. - DirectDMsList: add presence dots to DM sidebar icons. Single DMs show the partner's actual presence (green/yellow/grey). Group DMs show a green dot when any member is online.
…ia sliding sync
Synapse MSC4186 sliding sync has no presence extension — User.presence stays at
the SDK default ('offline') and getLastActiveTs() stays 0. Without this, presence
badges only show after toggling to classic sync and back (which briefly populates
the User objects via m.presence events in the classic sync response).
Fix: if getLastActiveTs() === 0 (no presence event received yet this session),
fall back to GET /_matrix/client/v3/presence/{userId}/status and populate state
from the REST response. Live updates via UserEvent.Presence continue to work as
before for servers that do deliver presence through sync.
… avatar shows correct state
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Reduces unnecessary re-renders, fixes a stale-state bug, adds presence badges to the sidebar, and fixes button smearing inside virtual list items.
Re-render / stale state fixes:
RoomTimeline: memoize the VList inline style object ({ willChange: 'auto' }) so the same object reference is passed on every render instead of allocating a new one each time.ThreadReplyChip: remove the per-messageRoomEvent.UnreadNotificationslistener. Each chip was attaching and tearing down a listener on every events-length change, scaling O(n) with timeline length. Unread counts in thread reply chips are now read at render time from the room's unread state.useUserPresence: reset presence state whenuserIdchanges. Previously, switching between user profiles in the right panel briefly showed the previous user's presence until the new subscription resolved.Presence badges in the sidebar:
DirectDMsList: show aPresenceBadgeon each DM avatar — online/unavailable/offline for 1:1 DMs, and a green dot when at least one participant is online for group DMs.AccountSwitcherTab: show aPresenceBadgeon the own-account avatar at the bottom of the sidebar so your own presence status is always visible.AvatarPresenceplacement fix: move theAvatarPresencewrapper outsideSidebarAvatar(which usesoverflow: hidden) so the badge is not clipped.Presence data fixes for Sliding Sync:
useUserPresence— REST fallback: Synapse MSC4186 sliding sync has no presence extension, som.presenceevents are never delivered via sync andgetLastActiveTs()stays 0. The hook now falls back to a directGET /presence/{userId}/statusREST call to bootstrap presence state on first render.ClientNonUIFeatures— explicit presence PUT: Sliding sync'ssetSyncPresenceis a no-op. Now explicitly callsPUT /presence/{userId}/statuson app-visibility change so the server records the user as online/offline and own-presence REST fetches return accurate data.UI fix:
General.css.ts: extend the "suppress hover transform inside virtual list rows" CSS override to cover allbutton:hoverand[role="button"]:hoverelements inside[data-index]rows, fixing avatar/button smearing that was visible when hovering over items in the DM list.Fixes #
Type of change
Checklist:
AI disclosure:
The
UnreadNotificationslistener removal was identified through runtime profiling of O(n) listener scaling on timeline scroll. The presence badge wiring and REST fallback patterns follow existing patterns in the codebase. Memoization and presence reset are straightforward.