Skip to content

feat(room-nav): show topic and last-message preview for rooms in the sidebar#669

Open
Just-Insane wants to merge 10 commits into
SableClient:devfrom
Just-Insane:feat/room-message-preview
Open

feat(room-nav): show topic and last-message preview for rooms in the sidebar#669
Just-Insane wants to merge 10 commits into
SableClient:devfrom
Just-Insane:feat/room-message-preview

Conversation

@Just-Insane
Copy link
Copy Markdown
Contributor

Description

Extends the room navigation sidebar so that non-DM rooms also display a topic or last-message preview beneath the room name — mirroring the DM list preview added in #666.

  • useRoomLastMessage — new hook that scans the live timeline in reverse to find the most recent visible message event (skipping reactions, redactions, and state events) and returns a human-readable preview string. Handles encrypted events (updates when decryption resolves), sender prefixing, and common content types (text, attachments, stickers, polls, etc.).
  • Sidebar integrationSpaceItems and the home-room list pass the preview down to each NavItem component.
  • Sliding sync fixLIST_TIMELINE_LIMIT increased from 1 to 5. With only 1 event, the SDK's eventShouldLiveIn() drops reactions and edits from the live timeline (their parent event is absent in the single-event batch), leaving the timeline empty. Fetching 5 events ensures the parent is almost always present so previews work for unvisited rooms.

Fixes #

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings

AI disclosure:

  • Partially AI assisted (clarify which code was AI assisted and briefly explain what it does).

useRoomLastMessage.ts — the reverse-scan loop and event-type dispatch table were drafted with AI assistance and then reviewed against the Matrix spec and existing hook patterns in the codebase. The sliding-sync LIST_TIMELINE_LIMIT diagnosis and fix were done manually after investigating the SDK's eventShouldLiveIn() behaviour.

@Just-Insane Just-Insane requested review from 7w1 and hazre as code owners April 12, 2026 16:12
@Just-Insane Just-Insane deleted the feat/room-message-preview branch April 12, 2026 19:33
@Just-Insane Just-Insane restored the feat/room-message-preview branch April 12, 2026 19:41
@Just-Insane Just-Insane reopened this Apr 12, 2026
Copilot AI review requested due to automatic review settings April 14, 2026 02:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds room-topic and last-message previews to room entries in the sidebar (Home + Spaces) by introducing a new live-timeline scanning hook, and adjusts Sliding Sync list timeline limits so enough events are available to compute previews reliably.

Changes:

  • Add useRoomLastMessage hook to derive a sender-prefixed “last message” preview from the live timeline (including encrypted placeholder + decryption updates).
  • Wire new preview toggles through settings and into RoomNavItem for Home/Space/Direct sidebars.
  • Increase Sliding Sync LIST_TIMELINE_LIMIT from 1 → 5 to avoid empty timelines when only relations are returned.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
src/client/slidingSync.ts Raises list timeline limit to ensure previews can find a parent message when relations are present.
src/app/state/settings.ts Adds settings flags for DM/room topic/message previews and defaults.
src/app/pages/client/space/Space.tsx Passes room preview settings down to room nav items in Spaces.
src/app/pages/client/home/Home.tsx Passes room preview settings down to room nav items in Home.
src/app/pages/client/direct/Direct.tsx Adds DM message preview setting plumbing to DM list rendering.
src/app/hooks/useRoomLastMessage.ts New hook computing last-message preview from live timeline with decryption updates.
src/app/features/settings/cosmetics/Themes.tsx Adds UI toggles for DM message preview, room topic preview, and room message preview.
src/app/features/room-nav/RoomNavItem.tsx Displays topic/last-message preview under room names based on new settings.
.changeset/room-message-preview.md Changeset entry for the room-nav preview feature.
.changeset/feat-dm-message-preview.md Changeset entry for DM preview feature (scope may not match PR metadata).
test.txt Appears unrelated scratch file.
run_diffs.sh Appears to be a local developer utility script.
presence_info.txt Appears to be local debug/output data.
output.txt Appears to be local debug/output data.
branches.txt Appears to be local debug/output data.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/app/hooks/useRoomLastMessage.ts Outdated
Comment on lines +62 to +95
export function useRoomLastMessage(
room: Room | undefined,
mx: MatrixClient | undefined
): string | undefined {
const [text, setText] = useState<string | undefined>(() =>
room && mx ? getLastMessageText(room, mx) : undefined
);

useEffect(() => {
if (!room || !mx) {
setText(undefined);
return undefined;
}
setText(getLastMessageText(room, mx));

const update = () => setText(getLastMessageText(room, mx));
room.on(RoomEventEnum.Timeline, update);
room.on(RoomEventEnum.LocalEchoUpdated, update);

// Re-check when any event in this room is decrypted (encrypted → plaintext).
const onDecrypted = (ev: MatrixEvent) => {
if (ev.getRoomId() === room.roomId) update();
};
mx.on(MatrixEventEvent.Decrypted, onDecrypted);

return () => {
room.off(RoomEventEnum.Timeline, update);
room.off(RoomEventEnum.LocalEchoUpdated, update);
mx.off(MatrixEventEvent.Decrypted, onDecrypted);
};
}, [room, mx]);

return text;
}
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hook is new behavior that affects sidebar rendering and has several edge cases (replies, edits, redactions, encrypted→decrypted transitions). The repo already uses Vitest for hook-level tests; adding focused unit tests for useRoomLastMessage (e.g., skipping edits/reactions, trimming reply fallback, updating on decryption) would help prevent regressions.

Copilot uses AI. Check for mistakes.
Comment thread run_diffs.sh Outdated
Comment thread output.txt Outdated
Comment thread output.txt Outdated
Comment thread presence_info.txt Outdated
Comment thread src/client/slidingSync.ts Outdated
Comment thread test.txt Outdated
Comment thread output.txt Outdated
Comment thread .changeset/feat-dm-message-preview.md Outdated
@Just-Insane Just-Insane force-pushed the feat/room-message-preview branch from 6ded99e to 20376bf Compare April 14, 2026 04:20
@Just-Insane Just-Insane marked this pull request as draft April 17, 2026 11:55
@Just-Insane Just-Insane force-pushed the feat/room-message-preview branch 5 times, most recently from 27d4e9b to fc1733d Compare May 14, 2026 19:45
Just-Insane and others added 9 commits May 14, 2026 16:43
- Test stripReplyFallback: plain text, quoted lines, no separator, multi-line
- Test eventToPreviewText: all msg types, encrypted, sticker, reactions, edits, reply fallback
- Test getLastMessageText: You prefix, display name, userId fallback, skip reactions, empty timeline
- Test useRoomLastMessage hook: undefined room, initial render, Timeline event updates
- Export pure functions for testability
Subscribe to Decrypted events before reading current state so events
that decrypt between the initial render and listener mount are not
missed. Explicitly request decryption for the last encrypted event on
mount so rooms not yet opened (e.g. sliding-sync previews) resolve
their preview text without requiring the user to visit the room.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…croll, fix eventId drag-to-bottom, increase list timeline limit

- useTimelineSync: change auto-scroll recovery useEffect → useLayoutEffect to
  prevent one-frame flash after timeline reset
- useTimelineSync: remove premature scrollToBottom from useLiveTimelineRefresh
  (operated on pre-commit DOM with stale scrollSize)
- useTimelineSync: remove scrollToBottom + eventsLengthRef suppression from
  useLiveEventArrive; let useLayoutEffect handle scroll after React commits
- RoomTimeline: init atBottomState to false when eventId is set, and reset it
  in the eventId useEffect, so auto-scroll doesn't drag to bottom on bookmark nav
- RoomTimeline: change instant scrollToBottom to use scrollToIndex instead of
  scrollTo(scrollSize) — works correctly regardless of VList measurement state
- slidingSync: increase DEFAULT_LIST_TIMELINE_LIMIT 1→3 to reduce empty previews
  when recent events are reactions/edits/state

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Debounce useRoomLastMessage update handler (300ms) to avoid
  re-rendering every room preview on each timeline event
- Debounce Direct.tsx activityCounter (500ms) to batch DM list
  re-sorts during rapid event bursts (reactions, edits, etc.)
- Update test to account for debounced update timing

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Just-Insane Just-Insane force-pushed the feat/room-message-preview branch from fc1733d to 7ac6750 Compare May 14, 2026 20:44
@Just-Insane Just-Insane marked this pull request as ready for review May 19, 2026 23:39
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.

2 participants