Repository navigation
fix(search): open an existing DM from a ⌘K person row without a relay open; cover hidden-DM previews - #2519
Merged
Conversation
matt2e
force-pushed
the
go-back-to-hidden-dms
branch
from
November 5, 2026 01:07
078f8c7 to
cc626e1
Compare
… DMs
New message already loads an existing DM's history inline once the chosen
recipients match it. It matches against the full session channel roster,
while Remove from Team and Hide conversation only filter the sidebar and
search. So hidden DMs of both kinds, and DMs missing from the sidebar,
already preview without any production change. A probe in the browser
fixture confirmed this for a locally hidden DM. This commit locks the
behaviour in with Vitest coverage and documents it, including in the help
guide, which had nothing on getting a hidden DM back.
Tricky cases covered (real relay session, NewMessage.recovery.test.tsx):
- Locally hidden (useHiddenDms mounted beside the page, as in Messages)
and relay-hidden (30622 snapshot) DMs both preview. Previewing never
restores either hide, calls the 41010 open or publishes. Send still
takes the confirmed open and clears the local hide.
- Exact participant set, in any order, for a 3-person group. A subset
(Zoe only, or Avery only, which matches the 1:1 instead) and a superset
(adding Kai) do not match. The preview swaps straight to the avatars.
- A held history read for the group, outlived by an edit back to the
1:1, never takes over the preview. The group shows "Loading messages…"
in place of the 1:1 timeline, then its own history when matched again.
- Recipients edited while the DM roster is still loading match the
recipients chosen when it lands, not the earlier ones.
- With directMessages.available false, history still previews, the
existing unavailable notice shows and Send stays disabled.
The test harness now answers history reads per `#h` channel, so more than
one DM can have history.
Fail-before: excluding hidden DMs from the match, subset matching, gating
the preview on `available`, and a lookup that ignores recipient edits each
fail exactly one new test. Removing `key={existing.id}` does not, because
useChannelWindow already switches snapshots by id.
Behaviour kept deliberately (all pre-existing):
- Previewing does not mark anything read. The preview mounts with
`active={false}` and `marksRead={false}`. jsdom cannot establish
reading, so this is not asserted here.
- Previewing records no ⌘K Recent visit, since only navigation opens count.
- The preview stays when the connection cannot start DMs, because reading
history needs no open capability.
- Typing never opens, creates or unhides a DM. Only Send does.
Deferred: whether the sidebar row returns without a refresh after Send
for a relay-hidden DM. The browser fixture does not model 41010 unhiding.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Matt Toohey <[email protected]>
Relay-signed DM metadata carries the NIP-29 `hidden` tag, and the channel summary exposes it as `hidden`. The ⌘K person row excluded hidden channels when looking for the viewer's existing DM, so no real DM ever matched: choosing a person whose visible DM was not already listed (for example, found by username) asked the relay to open the DM again instead of navigating to it, and on a connection that cannot start DMs the row reported an error instead of opening the hidden DM directly. Only the fixtures without the tag kept the existing test green. Drop the `hidden` exclusion; DMs are hidden from directories by design, and the sidebar-hidden check next to it already decides between a plain open and the confirmed open that restores the row. Tests: the ⌘K DM fixtures now carry the relay's `hidden` tag, which makes the existing person-row test fail before this change, and a new test covers opening a sidebar-hidden DM from a person row when this connection cannot start DMs. Entry-point audit against a local relay (block/buzz at 49fcab332): New menu > New DM and the DMs sidebar + both land in New message and preview a hidden 1:1 and hidden group with no relay writes, at 1280 px and in the 390 px layout. ⌘K person rows, the profile hover card Message action, Members > Send message and the agent Message buttons are confirmed opens that navigate to the DM and unhide it on the relay, as documented; none creates or unhides while recipients are typed. Co-Authored-By: Claude Fable 5.1 <[email protected]> Signed-off-by: Matt Toohey <[email protected]>
…oads The relay's DM visibility snapshot starts `idle` with nothing hidden, and only the sidebar's ChannelInventory refreshes it once the roster is ready. Until the first `ready` snapshot, a relay-hidden DM looked visible to the ⌘K person row, which plain-navigated to it and never sent the 41010 open that asks the relay to unhide it. When the snapshot landed, the sidebar hid the row while the user was reading the DM. The person row now plain-opens an existing DM only once visibility is `ready` and the DM is not hidden from the sidebar. While it is not ready, the row takes the confirmed open whenever this connection can start DMs, as every DM did before 73c54bdf2. A connection that cannot start DMs still opens the DM directly. Tests (SearchResults.test.tsx): - New: a DM found by username while visibility is still `idle` opens through `directMessages.open` with the person's pubkey. - The relay-hidden DM (Scooby) is now clicked through its person row too, asserting the confirmed open with Scooby's pubkey. - The existing visible-DM person-row test loads visibility first, since it asserts a plain open. NewMessage.recovery.test.tsx: the 1:1 and group 39000 fixtures carry the relay's `["hidden", ""]` and `["private", ""]` tags, so a future `!channel.hidden` in New message's match fails the preview tests. That was the fixture gap that hid the ⌘K bug fixed in 73c54bdf2. Fail-before: the old person-row condition fails the new idle-window test. Matching the person row against local hides only fails the Scooby assertion. Excluding hidden channels from New message's match fails 10 of 32 NewMessage.recovery tests. Docs: channels.md no longer says an in-app DM unhide flow is deferred. Any confirmed 41010 open, including New message Send, unhides the DM. The help guide adds that choosing the person in search is a quicker way back for a 1:1. It also says that when the connection can't start DMs, New message previews the history with Send disabled, and search opens the DM without restoring it. Validation: typecheck and lint pass. SearchResults, direct-messages, PageSearch, BestieNavigation, ShortcutSettings and identity-names consumer suites pass (241 tests). No browser journey clicks a search person row. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Matt Toohey <[email protected]>
…efreshes The ⌘K person row plain-opens an existing DM only once the relay's DM visibility snapshot is `ready`. A `loading` refresh keeps the last hidden set, which may be stale, and a failed refresh keeps it too, so either can show a relay-hidden DM as visible. Only `idle` was pinned, so changing the guard to `!== "idle"` passed every person-row test while plain-opening a hidden DM during the first `loading` read or after a failed load. A new `it.each` over `loading` and `error` stubs the visibility snapshot with nothing hidden, as the hidden-DM test does, and asserts the row calls `directMessages.open` with Alice's pubkey. The guard comment now says the guard covers every refresh and failed refresh, not only the first load. Fail-before: with the guard changed to `!== "idle"`, both new cases fail and the other person-row tests pass. Validation: the SearchResults suite (115 tests), typecheck and lint pass. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Matt Toohey <[email protected]>
matt2e
force-pushed
the
go-back-to-hidden-dms
branch
from
November 5, 2026 04:34
cc626e1 to
348573d
Compare
kazemek21
approved these changes
Nov 5, 2026
kazemek21
left a comment
Contributor
There was a problem hiding this comment.
Kyle reviewed this PR and the Nexus review-tracker notes. Approved with no comments.
Posted by Codex (gpt-6.1-sol) on behalf of kylez.
ljknight
added a commit
to ljknight/buzz-app
that referenced
this pull request
Nov 5, 2026
* origin/main: Keep /leave commands out of channel history (block#2476) fix(agents): ask before switching or closing drops unsaved edits (block#2503) fix(agents): keep the Model settings row full width (block#2577) feat(github): show a pull request's changes beside its summary (block#2492) fix(search): open an existing DM from a ⌘K person row without a relay open; cover hidden-DM previews (block#2519) feat(search): show channel type icon in search result subtitles (block#2521) test(browser): bind port-0 fixture servers where the OS assigns (block#2564) test(browser): fix six journey sync flakes from the 2026-11-04 sweep (block#2566) fix(channels): ask before Escape, Close or an outside click drops a template draft (block#2501) fix(channels): render the channel details description as linked Markdown with a label-only Edit target (block#2506) fix(agents): let Back and Forward shortcuts traverse provider dialogs (block#2509) Fix Inbox recovery after a delayed Retry (block#2496) # Conflicts: # docs/buzz-help.md
wpfleger96
added a commit
that referenced
this pull request
Nov 5, 2026
…-service * origin/main: (68 commits) fix(messages): keep decoded images across virtualized remounts (#2474) Keep /leave commands out of channel history (#2476) fix(agents): ask before switching or closing drops unsaved edits (#2503) fix(agents): keep the Model settings row full width (#2577) feat(github): show a pull request's changes beside its summary (#2492) fix(search): open an existing DM from a ⌘K person row without a relay open; cover hidden-DM previews (#2519) feat(search): show channel type icon in search result subtitles (#2521) test(browser): bind port-0 fixture servers where the OS assigns (#2564) test(browser): fix six journey sync flakes from the 2026-11-04 sweep (#2566) fix(channels): ask before Escape, Close or an outside click drops a template draft (#2501) fix(channels): render the channel details description as linked Markdown with a label-only Edit target (#2506) fix(agents): let Back and Forward shortcuts traverse provider dialogs (#2509) Fix Inbox recovery after a delayed Retry (#2496) feat(composer): optional ⌘/Ctrl+Enter to send (#2331) test: use keyboard activation for reply caret setup (#2557) test: settle member search before invitation expansion (#2532) test(agent-command): isolate the copied executable writer (#2537) test(sidebar): wait for the rolled-back row to leave Starred before collapsing Work (#2574) test(browser): click timeline rows only after the timeline settles (#2560) ci: split Vitest across six shards so 3/4 stops hitting the job cap (#2571) ... # Conflicts: # src/app/Settings.tsx # src/bundled/goose/sessions.test.ts
agude-sq
added a commit
to agude-sq/buzz-app
that referenced
this pull request
Nov 5, 2026
* origin/main: (43 commits) feat(settings): follow the system clock and let people hide message times (block#2440) feat(plugins): repository access rules for Git imports (block#2484) feat(desktop): add Settings to the macOS app menu (block#2594) Preserve and renew external app approval (block#2464) fix(direct-messages): show verified identity in new message recipient search (block#2585) Offer plugin updates from the Buzz shell (block#2491) fix(messages): keep decoded images across virtualized remounts (block#2474) Keep /leave commands out of channel history (block#2476) fix(agents): ask before switching or closing drops unsaved edits (block#2503) fix(agents): keep the Model settings row full width (block#2577) feat(github): show a pull request's changes beside its summary (block#2492) fix(search): open an existing DM from a ⌘K person row without a relay open; cover hidden-DM previews (block#2519) feat(search): show channel type icon in search result subtitles (block#2521) test(browser): bind port-0 fixture servers where the OS assigns (block#2564) test(browser): fix six journey sync flakes from the 2026-11-04 sweep (block#2566) fix(channels): ask before Escape, Close or an outside click drops a template draft (block#2501) fix(channels): render the channel details description as linked Markdown with a label-only Edit target (block#2506) fix(agents): let Back and Forward shortcuts traverse provider dialogs (block#2509) Fix Inbox recovery after a delayed Retry (block#2496) feat(composer): optional ⌘/Ctrl+Enter to send (block#2331) ... # Conflicts: # docs/buzz-help.md
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.
Summary
The ⌘K person row looks for the viewer's existing DM with that person before deciding how to open it. The lookup excluded
channel.hidden, buthiddenis the NIP-29 tag the relay puts on every DM's metadata, so no real DM ever matched. Every pick took the confirmed41010open, even for a DM that was already visible in the sidebar.SearchResults.tsxnow drops that exclusion. A person row plain-navigates to an existing DM only when the relay's DM visibility snapshot isreadyand the DM is not hidden from the sidebar. A locally or relay-hidden DM still takes the confirmed open, and so does any DM while visibility isidle,loadingorerror, because the DM might be hidden. Unhiding works as it does on main.Why it matters
["hidden", ""]and["private", ""]tags, so a filter onchannel.hiddenfails the tests instead of passing against untagged fixtures.Not changed
New message already loads a hidden DM's history inline once the chosen recipients exactly match its participants, on main. That covers 1:1 and group DMs, and both local hides (Remove from Team) and relay hides (Hide conversation). This PR only adds tests and docs for that behaviour. Previewing still never opens, unhides, marks read or publishes. Only Send does.
Tests
src/app/shell/SearchResults.test.tsxidleopens throughdirectMessages.openwith the person's pubkey.it.each(["loading", "error"])asserts the same confirmed open while visibility is refreshing or has failed.hiddentag.src/features/direct-messages/NewMessage.recovery.test.tsx(real relay session)directMessages.availablefalse, history still previews and Send stays disabled.#hchannel. The 1:1 and group 39000 fixtures carryhiddenandprivatetags.Fail-before checks:
!channel.hiddenexclusion fails the existing visible-DM person-row test.idletest.!== "idle"fails bothloadinganderrorcases.availableor ignoring recipient edits each fail one new test.Validation: typecheck and lint pass. The SearchResults suite (115 tests) passes, as do the direct-messages, PageSearch, BestieNavigation, ShortcutSettings and identity-names consumer suites. No browser journey clicks a search person row.
Not checked here: whether a relay-hidden DM's sidebar row comes back without a refresh after Send. The browser fixture does not model
41010unhiding.Docs
docs/channels.md: Starting a direct message now says how New message previews an existing DM, including a hidden one. The DM visibility section no longer says an in-app unhide flow is deferred. Any confirmed41010open, including New message Send, unhides the DM.docs/buzz-help.md: a new Hidden DMs entry covers getting a hidden DM back through New message or search. It also covers what happens when the connection can't start DMs.🤖 Generated with Claude Code