Repository navigation
Search in the pane: a live field, its scopes, and the Find keys. - #55
Conversation
|
Rendered the demo on Windows x64 (--features gui-shot, scratch daemon with --seed-demo) while reviewing this stack — six surfaces, all clean: inbox with badges and the scam tag, a conversation with image attachment / edited marker / call summaries / bot embed, the thread pane, People with call states, the Discord home with voice-channel stacks, and the account menu. No rendering defects found (fonts, avatars, keycaps, brand marks all draw correctly). Screenshots:
Happy to take more surfaces on request — this machine makes them cheap. |
itz4blitz
left a comment
There was a problem hiding this comment.
Thanks for this. The live field, scopes and Find keys read well, and the Windows true → cmd /C exit 0 change is right. A few things before it can land.
Must fix
- The switcher's "Search messages" row no longer searches (regression from main).
open_message_search(gui/conversation/side.rs:403-407) callsnew_search, which asks with empty words, then fills the field withinput.set_text(&words).set_textemits nothing (gui/input.rs:366-368: "Not an edit: nothing is emitted"), sosearch_typednever runs andpage.wordsstays empty. The field shows the words, the body says "Search the cache.", and nothing is asked until the user edits the field. Callsearch_typed(cx)afterset_text, or seedpage.wordsbeforereask_search, and please add a test for the switcher path. This is still present in #57 and #58. - README now conflicts with main. #59 merged, so please rebase. Keep your Search bullet, and keep #59's removal of "voice messages" from the not-built list.
Picker sweep race (chatd/src/blobs.rs:507-528, blobs/fetch.rs:260-266)
- Taking the idle decision under the queue lock is an improvement, but the store eviction and
remove_dir_allstill run after the lock is released. An ask, or a preview, that lands in that gap and reads the store before eviction gets a path that is then deleted. So the race is narrowed, not closed. Either do the eviction and removal while holding the decision, or give each account's picker a generation that asks and workers check. create_dir_allon every write re-createsmedia/<net>/<acct>orpick/<acct>afterforget(), a cache clear, or a picker that really closed, and the bytes are downloaded and then thrown away. Re-creating only on the retry path, or under the same generation check, would avoid that.- No test exercises the race; the only test change is raising the idle from 2 s to 5 s. The retry loop is bounded (
for last in [false, true]), so that part is fine.
Smaller
- Command-F with no conversation open sets the scope to Conversation. That chip is hidden, so no chip is lit while the search runs everywhere. Resolve it to Everywhere, as the switcher's row does.
- Closing the pane with ✕ (
close_rightthentake_in) leaves the page and field alive and doesn't return the keys to the composer. Esc does both. - An older chatd silently ignores the new
spacefield (nodeny_unknown_fields). It answers from the whole cache while "This space" is lit. That's probably acceptable since the two ship together, but worth knowing. docs/architecture.md:40's protocol table doesn't mentionspaceyet.
The stale-answer counter restarting per page, and "This conversation" not following a switch, are both fixed in #57, so it's fine for those to land as a stack.
81ef9a9 to
89f3e40
Compare
unRekable
left a comment
There was a problem hiding this comment.
Thank you for the thorough review — every point is addressed on the pushed branch (rebased on main, keeping #59's README state).
Must fix
- The switcher's row asks again.
open_message_searchnow goes throughnew_search_with(scope, &words, …), which seedspage.wordsbefore the ask — the ask carries the words from the start, andset_text(which fills the field to match) is no longer load-bearing, since it emits nothing. The seeding is its own function with a test (the_switcher_s_words_start_asked_for); a Shell-level test of the row itself would need gpui's test-support, whichcargo test --workspacedoes not build — the pure test pins the seeding the ask reads. - Rebased on main. The Search bullet kept, #59's removal of "voice messages" kept.
Picker sweep race
- Generations, as your second option. Each picker session carries a generation (
Picker { asked, generation }); the close records the generation it ends; an ask after the close opens the next one (next_generation(closed, open), always above the highest closed). A job stamps its session's generation and is dropped before its bytes are kept whenjob.picker_generation <= picker_closed(account)— so a fresh ask's file lands and a closed session's never does, whichever order the sweep's removals and the landing meet in. The store eviction stays a snapshot taken at close time, which a fresh session's landing postdates. create_dir_allis scoped to picks now (Want.pick): only a picker's directory can be removed under a live download, and only a picker's is re-made — the non-pick re-creation afterforgetor a cache clear is gone.- Tests:
a_close_ends_one_picker_generation_and_an_ask_opens_the_nextandthe_sweep_closes_only_what_stood_idle_and_a_reopened_picker_is_never_stalepin the generation bookkeeping and the staleness decision at the unit level, and the existing picker test still pins the file-level lifecycle (closed → re-asked → lands).
Smaller
- Command-F with nothing open now asks everywhere, so a chip is lit.
- The ✕ close drops the page and field in
take_in(same as Esc's branch) andclose_righttakes the window, returning the keys to the composer. - Known and accepted, as you say — the two ship together.
docs/architecture.md's table namesspaceonSearchMessagesand the newSearchNetworkrow.
#57 and #58 are rebased on this branch and carry no copy of the old behaviour.
The pane opened only from the switcher's last row, its words were text, and it asked the whole cache. The head is the field now, Command-F asks what the conversation open holds, Shift-Command-F the whole cache, and the chips switch the ask between the two and the conversation's Space, falling back to everywhere with nothing open, as the switcher's row does. SearchMessages names a Space, so an older frame still reads. Find's two items come back to the Edit menu, with their keys in the shortcut list.
…ened picker's download. A preview asked again while its picker was closing raced the removal of the directory it streams into: the download failed with a path not found, and the pane's ask went unanswered. The close now leaves a picker that re-registered, the write makes the part's directory again, and a rename that lost its directory fetches once more. The test's idle rises from 2 s to 5, so a slow or cold machine cannot overtake the last section.
… no `true`. Every Discord test spawns a no-op child before the real chatd, and asked the Unix `true` for it: on Windows that is program not found, and the whole binary failed before any test ran. Windows takes `cmd /C exit 0`.
… and the close returns the keys. The switcher's row seeds its words into the page's first ask - set_text is not an edit and emits nothing, so nothing depended on it anymore, and the seeding has its test. A picker's close ends its session's generation: a job of the closed session is dropped before its bytes are kept, an ask after the close opens the next generation, and only a picker's directory is re-made under a live download. The sweep and the generations carry their own tests. Command-F with nothing open asks everywhere, where a lit chip can name what was asked; the pane's close by its X goes with the keys to the composer, as Esc does; and the protocol table in docs/architecture.md knows the space filter.
…cus only when closing a pane.
afc49e6 to
345c650
Compare
What
The message search pane gets its own field and its scopes, per
docs/product/05-navigation.md§5 anddocs/design/polish/07-panes.md§2:Findsubmenu, with their rows in Settings' shortcut list. Chips switch the scope of a standing pane: This conversation · This space · Everywhere. A scope about nothing open falls back to everywhere, as the switcher's row does.SearchMessagesgrows an optionalspacefilter, serde-default, so an older frame still reads; the store search narrows onconversation.space.Two fixes found while testing this on Windows
trueas their placeholder child and failed before any test ran on a Windows machine without Git'susr/binon PATH. Windows takescmd /C exit 0.Tests
cargo test --workspacegreen on Windows x64 (afterprotoc29.3 and Git'sopensslon PATH, which the mediad voice tests use),cargo test -p tinyclient --features gui350 passed, the picker test repeated stable.Known gaps
title · age · snippet · cached; the spec's "network icon · space › conversation · date" context line is the next slice.Side observation, not part of this PR:
calls::a_ring_we_placed…andpolish's twelve parallel daemons against a 10 s socket deadline are timing-flaky on slow or loaded Windows machines; both pass in isolation and in CI.