Repository navigation
Description
Summary
Opening a message result from Desktop search can strand the user in an isolated nested-branch view instead of showing where the message belongs.
The panel displays only the matched reply and ends with:
No replies in this branch yet
Reply in thread to continue this branch
There is no visible originating channel message, no highlighted match in its parent conversation, no parent/root breadcrumb, and no action to open the complete parent thread. The composer consequently encourages the user to create another nested branch without making that consequence clear.
Steps to reproduce
- In Buzz Desktop, search for text contained in a reply inside an existing channel thread.
- Open the matching message result.
- Observe the thread panel.
Actual behavior
- The matched reply is opened as an isolated branch root.
- The originating channel/root message is not visible or highlighted.
- Earlier thread context is absent.
- No channel → root thread → matched reply breadcrumb is shown.
- There is no Open parent thread or Back to channel message action.
- The empty-branch composer invites a reply that would create another nested branch.
This makes a successfully found message practically unusable for recovering and continuing a conversation.
Expected behavior
Opening a message search result should preserve conversation context:
- open the complete parent/root thread;
- scroll to and visibly highlight the matched message;
- identify the originating channel and root message;
- provide explicit Open parent thread and/or Back to channel navigation;
- avoid presenting an empty nested-branch composer as though it were the recovered conversation.
If an isolated-branch view remains supported, it should clearly expose its parent chain and offer a one-click route to the root conversation.
Acceptance criteria
- Opening a reply from search exposes the originating channel and root thread.
- The matched message is scrolled into view and visibly highlighted.
- The user can navigate directly to the parent/root conversation.
- The UI clearly distinguishes replying to the matched message from continuing the root thread.
- Search results for top-level messages, root messages, direct replies, and nested replies have automated navigation coverage.
Related issues checked
- feat(search): query operators
from:/in:/before:/after:(backend already supports them, client never sends them) #2853 concerns search operators, not result navigation. - Missing replies in thread view after replying to non-latest messages #3799 concerns replies missing from a thread view, not loss of context when opening search results.
- Support threads (infinitely nested) #47 introduced nested threads but does not track this navigation failure.
Activity
cmyk commentedon Aug 18, 2026
Clicking a macOS notification for a direct or nested reply must open the complete parent/root thread, highlight the notified reply, and provide channel/parent navigation even when the notification payload lacks an explicit threadRootId.
Giszmo commentedon Sep 15, 2026
Reproduced on
main(051c3a2) and traced. This is the same defect as the notification case, and the open PR #7452 fixes both — but it is written and tested only as a notification fix, so the link to this issue is easy to miss.Mechanism. Search results and notifications share one navigation path:
openSearchHitWithNavigation→cacheSearchHitEvent+goChannel→ChannelRouteScreen.buildSearchHitEvent(desktop/src/app/navigation/searchHitEventCache.ts) projects a hit into aRelayEventwhose only tag is["h", channelId]— noereply tags, because the search response carries no thread root at any layer (SearchHitincrates/buzz-search/src/query.rs,SearchHitInfoindesktop/src-tauri/src/models.rs,fromRawSearchHitindesktop/src/shared/api/tauri.ts).ChannelRouteScreensplices that projection into the timeline at mount, souseChannelRouteTargetseestargetMessage.parentId === undefined, takes the root-message branch, opens the matched reply as its own thread head, and records it inhandledThreadRouteTargetRef— after which hydrating the real event can no longer repair the selection. That is the "No replies in this branch yet" panel described above.Evidence. I added a search-path regression to
desktop/tests/e2e/navigation.spec.ts— emit root → sibling → parent → nested reply into a mock channel, hold the target'sget_eventwith__BUZZ_E2E_DEFER_GET_EVENT__, search for the nested reply, click the result, release hydration, then require the root and both ancestors in the thread panel:main(051c3a2) it fails, with the thread head being the matched reply itself ("Nested searchable reply");Test case (mirrors the one in #7452)
Two parts of this report that #7452 does not cover, in case they should be split out:
fetchRouteEventreturnsnulland the tag-less projection is inserted on its own, so the isolated-branch behaviour returns. The belt-and-braces fix is to carry the thread root in the search hit itself, which would also letresolveSearchHitDestinationstop passingthreadRootId: nullfor every message hit.