Skip to content

feat: search messages within the current thread - #1615

Open
chessing234 wants to merge 4 commits into
permissionlesstech:mainfrom
chessing234:feat/thread-message-search
Open

chessing234 wants to merge 4 commits into
permissionlesstech:mainfrom
chessing234:feat/thread-message-search

Conversation

@chessing234

@chessing234 chessing234 commented Aug 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Filters the open conversation by message body or sender nickname.

The render problem — you were right

.searchable is gone. Checking the hierarchy rather than guessing:

  • ContentView.swift builds MessageListView directly at line 539. The only occurrence of NavigationStack in that file is inside a comment (line 303) — there is no navigation ancestor, so .searchable rendered nothing in the public timeline.
  • ContentSheetViews.swift opens a NavigationStack at line 127 and presents ContentPrivateChatSheetView inside it at 131/149, so the DM sheet was the only place the field could ever have appeared.

So the feature was dead exactly where most conversation happens. Replaced with a plain search field, which has no navigation dependency and renders identically in both placements — the failure mode is eliminated by construction rather than by hoping.

The field lives inside MessageListView, so neither header needed changing and one implementation serves both call sites. It collapses to a magnifier until used, and resets on conversation switch so a stale filter never applies to a different thread.

Result cap

Search bypasses the message window, so a common term in a long thread rendered every historical match in one pass. Results are now capped at 200, keeping the newest, with a line stating how many matches were withheld — a truncated list says so rather than passing itself off as complete.

Accessibility

The label moved onto the search field itself. It had been applied to the whole ScrollView chain, which relabelled every message in the list for VoiceOver.

Catalog

Rebased onto current main with surgical additions: +930/−0, five keys, main's 93 Aug-10 keys untouched, no pre-existing entry modified. Real translations in all 30 locales at state: "translated", %lld specifiers verified preserved in each.

Verification

  • ThreadMessageSearchTests covers the cap: capped at the limit, newest kept, under-cap untouched, non-positive limit uncapped, truncation flag boundaries — plus the original filter behaviour, unchanged.
  • The filter and cap were compiled and executed standalone — 11 assertions pass, including that blank queries, case-insensitive body matches, sender matches and blank-body exclusion still behave as before.

Not run locally, and worth being blunt about: I could not produce the screenshots you asked for. This machine has Command Line Tools only, no Xcode, so I cannot build or run the app to photograph the field in either placement.

What I can offer instead is the static evidence above for why .searchable was dead, and the fact that a plain TextField in the view hierarchy has no ancestor requirement to satisfy. If you want the screenshots before this lands, say so and I will get to a machine with Xcode rather than guess.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f12d4fbd86

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread bitchat/Localizable.xcstrings Resolved
@chessing234

Copy link
Copy Markdown
Contributor Author

Addressed Codex P2 on tip: thread-search strings now cover all catalog locales.

@chessing234
chessing234 force-pushed the feat/thread-message-search branch from 12a3ff6 to 9a7acb1 Compare August 5, 2026 10:29

@jackjackbits jackjackbits left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In-thread search is worth having, but this needs render verification before anything else:

Blockers:

  1. Likely dead UI where people actually chat. .searchable(text:prompt:) requires a NavigationStack/NavigationSplitView ancestor to render, and the public-timeline MessageListView (ContentView.swift:539 at your merge-base) has none — the modifier will silently display nothing there on iOS and macOS. Only the DM sheet (which has a NavigationStack, with custom header chrome) might show it. Please attach screenshots of the search field visible in (a) the public timeline and (b) a DM thread, on iOS and macOS. If it doesn't render, this needs a manual search-field UI rather than .searchable.
  2. Catalog rewrite + translations (shared with the batch): whole-file xcstrings re-serialization would clobber main's Aug-10 catalog (93 keys) and break the coverage guard; all 3 new keys are English ×29. Rebase onto current main, surgical adds, real translations.

Also:

  • .accessibilityLabel is applied to the whole ScrollView chain — VoiceOver will relabel the entire message list, not the search affordance. Scope it to the right element.
  • Search mode disables message windowing and renders every match from full history — unbounded; consider capping or paginating results.

The ThreadMessageSearch filter itself and its unit tests are fine.

@chessing234
chessing234 force-pushed the feat/thread-message-search branch from 6717bac to 77fa81b Compare August 11, 2026 17:28
@chessing234

Copy link
Copy Markdown
Contributor Author

you were right about the render, and it's worse than "might not show": ContentView builds MessageListView directly at :539 and the only NavigationStack in that file is inside a comment at :303 — so .searchable rendered nothing in the public timeline. the DM sheet was the only place it could appear, via the NavigationStack ContentPeopleSheetView opens at :127.

so i dropped .searchable for a plain field. no navigation ancestor to satisfy, renders the same in both placements. it lives inside MessageListView so neither header changes and one implementation covers both call sites; collapses to a magnifier until used and resets on conversation switch.

capped results at 200 newest with a line saying how many were withheld — an uncapped common term was rendering every historical match in one pass. moved the accessibility label off the scrollview chain onto the field itself.

catalog rebased and done surgically, +930/-0, real translations in all 30 locales.

the screenshots i can't give you — this machine has command line tools only, no xcode, so i can't build or photograph it. the static evidence above is why i'm confident .searchable was dead, and a plain TextField has no ancestor requirement to fail. if you want the screenshots before it lands say so and i'll get to a machine with xcode rather than guess.

@chessing234

Copy link
Copy Markdown
Contributor Author

awaiting-review — searchable dropped for a plain textfield so it renders outside a navigationstack; catalog is surgical on tip.

@chessing234
chessing234 force-pushed the feat/thread-message-search branch from 77fa81b to a387154 Compare September 25, 2026 14:20
@chessing234

Copy link
Copy Markdown
Contributor Author

rebased onto main

@chessing234

Copy link
Copy Markdown
Contributor Author

manual search field replaces searchable; cap + a11y scoped. no device screenshots from this machine. ready for another look.

Split the existing PR change into a smaller reviewable piece.
Original change: feat: search messages within the current thread
Split the existing PR change into a smaller reviewable piece.
Original change: feat: search messages within the current thread
Split the existing PR change into a smaller reviewable piece.
Original change: feat: search messages within the current thread
@chessing234
chessing234 force-pushed the feat/thread-message-search branch from fac2743 to b6404ee Compare October 5, 2026 10:47
Keep the new scroll window and timeline guards when search is inactive.
Give filtered rows their own display without changing scroll state.
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