iOS: search results show the line where the body match was found - #28
Open
cjbest wants to merge 6 commits into
Open
iOS: search results show the line where the body match was found#28cjbest wants to merge 6 commits into
cjbest wants to merge 6 commits into
Conversation
When the search query matches a note's body (rather than its title), the row's context line now shows the actual line of the document where the match was found — not the static second-line preview. Title-only matches keep using the regular preview, since the title itself is the match indicator. - search(_:) now returns [SearchHit] (note + optional snippet) instead of [Note]. Snippet is the trimmed line containing the first body match, capped at 140 chars with an ellipsis if longer. - bodyCache stores original-case strings so snippets render with the source's casing (matching is still case-insensitive via range(of: options:.caseInsensitive)). - NoteRow takes a `searchSnippet:` override that replaces note.preview when present. - 3 new tests cover snippet line extraction, case preservation, and long-line truncation. Existing search tests updated for the new return type. 27 unit + 4 UI = 31 green.
Two follow-ups on PR #28: - Pre-window the snippet so a match deep in a long line is visible: if the match is more than ~18 chars from the start of the trimmed line, drop everything before that and prepend a "…". The row's lineLimit(1) then truncates the trailing end (with a "…" if we capped it at 200 chars). Two new tests pin both branches. - Dismiss search when selectedNote changes via .onChange. Without it, the .searchable bar persisted into the editor's chrome and the editor's .toolbar(.hidden) didn't take effect. Initially tried a simultaneousGesture on the NavigationLink — that broke navigation in UI tests because the gesture stole the tap. .onChange reacts after the selection lands, no gesture conflict. 29 unit + 4 UI = 33 green.
- NoteRow builds an AttributedString from the snippet and bolds the span matching the query (with primary color, so it stands out a bit more against the .secondary surrounding text). - Switch .searchable to the isPresented: form. Setting it to false in .onChange(of: selectedNote) actually collapses the search bar — the previous dismissSearch() call only removed focus, leaving the bar visible in the navigation chrome of the pushed editor. - Fold the SearchableNoteList back into NoteListView's `list` since we no longer need the dismissSearch environment access.
Two related fixes addressing the same root cause: SwiftUI's .toolbar(.hidden, for: .navigationBar) doesn't fully take effect when the parent view has .searchable applied — the back chevron leaks through, leaving a bar with a back button visible on the editor. - EditorChrome.viewWillAppear now calls setNavigationBarHidden(true) imperatively on the underlying UINavigationController. This is the reliable hammer that overrides the parent searchable's chrome. - Drop the previous isPresented: $isSearchPresented hack on .searchable along with the onChange that flipped it to false on selection. That worked around the wrong problem and broke the back-trip: the search bar collapsed but the query stayed populated, so the user saw filtered results with no way to clear or edit. Now the search bar persists across navigation in the standard way — go forward, read a note, swipe back, search bar still showing your query.
The webview kept restoring whatever file was last open by reading localStorage on mount, which was the right behaviour for HMR and page reloads but wrong for a real app launch. Use sessionStorage as the discriminator: it survives reloads and HMR but gets wiped when the webview is destroyed (app quit), so its absence on mount is a reliable signal that this is a cold launch. When that happens, drop any stale registration for this window label and start blank. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a new section under Shortcuts showing the notes list and editor side-by-side, captured from iPhone 17 Pro with the device bezel. The screenshots are reproducible via testCaptureReadmeScreenshots in DriftUITests, which seeds four fake notes, navigates to each state, and synchronises with a host-side screencapture orchestrator via marker files in /tmp. XCUIScreen.screenshot() gives only the device display; the bezel comes from screencapturing the Simulator window. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
When you type a query that matches a note's body, the little context line in each result row now shows the actual line of the document where the match is — not the generic second-line preview.
Implementation:
🤖 Generated with Claude Code