Skip to content

Enter asks Discord itself, and the network's hits join the list. - #58

Merged
itz4blitz merged 1 commit into
mainfrom
feat/search-network-layer
Oct 24, 2026
Merged

itz4blitz merged 1 commit into
mainfrom
feat/search-network-layer

Conversation

@unRekable

Copy link
Copy Markdown
Collaborator

Stacked on #57 (which is stacked on #55) — merge those first. Against feat/search-hit-rows so only this slice shows.

What

The search pane's second layer, per docs/product/05-navigation.md §5: Enter asks the network itself, and its hits join the list.

  • A Space's scope asks the server's own search (/guilds/{id}/messages/search), a conversation's scope the channel's (/channels/{id}/messages/search for DMs). Everywhere still reads the cache alone — its networks (Slack whole-account, Telegram) come with a later slice, and a Discord server is only searched when it is the scope, as the spec has it.
  • The hits are mapped like the cache's and merged by conversation + message id; the cache's rows keep their cached tag, the network's speak for themselves. A line says what was searched ("Searched Discord · Moss & Lichen.") — or why nothing came, as with a server whose index is still building ("Discord search isn't ready for this server yet", Discord's 202).
  • Enter with a hit picked (arrow keys) opens it; Enter with no choice asks the network. The keyboard has both layers.
  • A late answer for words or a scope that have moved on never lands: every ask carries a shell-wide count, and every place that drops the answer drops its count with it. What the scope names follows what is open, for Space scopes too.

Pieces

  • Request::SearchNetwork in the protocol (optional keys as always, so an older frame still reads), served by routing to the account's adapter as a new Command::Search — the same reply-channel pattern as Download and Handoff. Networks that cannot search answer Unsupported, which the pane shows as words.
  • Discord's adapter gained search_messages beside the proven search_shared: the same endpoints, the same 202-indexing detection, hits mapped from the server's answer.
  • The test fake serves the text-search branch (query=) with its own hits and a 202 case; the new integration test covers Space scope, DM channel scope, and the 202 words in one pass. The shared-files search test rides the old branch unchanged.

Tests

cargo test --workspace-relevant suites green locally on Windows x64: chatd --test discord 31/31 (incl. the new test), protocol 24/24 (incl. the wire test), cargo test -p tinyclient --features gui 351/351 (incl. the merge test).

Known gaps

  • Everywhere's network layer waits for Slack's whole-account search; the pane's empty state says what it knows.
  • A network hit's sender is Discord's username (the network's own word); the pane names conversations from what it holds.

@itz4blitz itz4blitz left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Asking the network on Enter is the right shape, and the merge by conversation + message id, the 202 handling and the stale-answer count all look good. Two things need fixing before this can go near a real account, plus some smaller ones.

Must fix

  1. Wrong search parameter. adapters/discord/info.rs:341,345,346 send query=, but Discord's message search takes the words as content= (max 1024 characters). As written the words aren't applied, so the pane most likely shows the server's or channel's newest messages under "Searched Discord · …". The fake (tests/discord.rs:268) and the asserts (:2757, :2765) lock query= in too, so please switch them all to content=.
  2. Nothing limits network searches. enter_search/ask_network (gui/conversation/side.rs:598-660) send a new SearchNetwork on every Enter. That includes Enter again for the same words and scope, Enter while one is still in flight, and key auto-repeat while Enter is held. chatd forwards every one (server.rs:1427). Discord limits search tightly, and those 429s count toward refused() and the account pause. Please:
    • in the GUI, don't ask again for the same words and scope while one is in flight or once it has answered, and ignore held-key repeats;
    • in chatd, bound it per account as people search already does (SEARCH_GAP/SEARCH_AGAIN in discord/members.rs:527-548), so no client can turn Enter into a burst.

Should fix

  1. The Space id goes into the URL unchecked. info.rs:341 puts the client's Space id into /guilds/{space}/…. space_info checks state.guilds.contains_key(guild) first (info.rs:205); do the same here. The conversation path is already gated by known.
  2. Search runs on the adapter's command thread (discord.rs:987). A slow search, or a 429 wait, holds sends, edits and reactions behind it, and a search still queued after the server's 30 s answer timeout still goes to Discord. At the least, skip the call when the reply's receiver is already gone.
  3. Enter in Everywhere now does nothing. Everywhere is the switcher's and Shift-Command-F's default, and Scope::Everywhere => return applies when nothing is picked; in #55 Enter opened the first hit. Once a row is picked there's also no keyboard way back to asking the network.
  4. Wording:
    • side.rs:667 shows chatd's raw detail. An older chatd yields "chatd does not understand this request… (unknown variant search_network…)", which names chatd and a Rust value. Map errors to plain words.
    • side.rs:1096 says "The network found nothing here." even when the network refused, answered 202, or failed.
  5. How network hits join the list:
    • they aren't filtered for hidden conversations or message requests, which the cache already excludes;
    • they're appended after every cache hit regardless of date;
    • their snippet is the whole message cut to one line, so the match may not be visible (the cache's snippet is windowed around the match).
  6. NetworkFound.target (:85) is never read, which adds a new dead_code warning.
  7. The README still says the networks are not asked. After this it should say Enter asks Discord, for a server or a conversation.

Tests

The fake keys on query=. Its 202 uses code: 0 (Discord's is 110000, though any code is detected). Nothing covers a guild-channel conversation scope, an adapter answering Unsupported, the stale-answer guard, or Enter semantics; a test that repeated Enter sends one request would pin the limit down.

@unRekable
unRekable force-pushed the feat/search-network-layer branch from 426cf52 to d019000 Compare October 20, 2026 15:22
@unRekable
unRekable force-pushed the feat/search-hit-rows branch from c146e3f to 7fb3442 Compare October 20, 2026 15:22
@itz4blitz
itz4blitz force-pushed the feat/search-hit-rows branch from 7fb3442 to 6730d04 Compare October 24, 2026 16:55
@itz4blitz
itz4blitz changed the base branch from feat/search-hit-rows to main October 24, 2026 16:55
@itz4blitz
itz4blitz force-pushed the feat/search-network-layer branch from 44c19a2 to bde3dc3 Compare October 24, 2026 17:10
@itz4blitz
itz4blitz merged commit 01cdb6f into main Oct 24, 2026
3 of 6 checks passed
@itz4blitz
itz4blitz deleted the feat/search-network-layer branch October 24, 2026 17:12
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