Skip to content

feat: paginated offline-first search — load-more, flash fix, unified list views - #231

Closed
danieltmbr wants to merge 2 commits into
feat/search-backendfrom
feat/search-native-ui
Closed

feat: paginated offline-first search — load-more, flash fix, unified list views#231
danieltmbr wants to merge 2 commits into
feat/search-backendfrom
feat/search-native-ui

Conversation

@danieltmbr

Copy link
Copy Markdown
Owner

Summary

Builds on #230 (backend pagination). Wire up paginated search across Blog, Quotes, and Catalogue tabs:

  • Flash fix: local search runs immediately on keystroke; only the network fetch is debounced (300 ms). No more empty-screen flash while waiting.
  • Load-more: BlogModel, QuotesModel, and CatalogueModel each gain loadMore() / isLoadingMore / hasMore; a loadMoreRevision counter on CatalogueModel signals CatalogueSearchEngine to re-run local search after upserts.
  • Cursor coordinators: ReaderPosts, ReaderCatalogue, ReaderQuotes track nextCursor across search(term:) and loadMore() calls so each load-more continues the active search term.
  • Unified list views: one …List(term:) view per tab handles browse (@Query) and search (engine results) in the same view, always showing the status line and load-more cell.
  • Environment actions: CataloguePageLoadAction and QuotesPageLoadAction follow the existing action pattern for environment injection.
  • Reader target: ReaderApp wired to the new paginated loaders; QuoteSearchLoader / CatalogueSearchLoader with cursor support.

Test plan

  • Reader target builds in Xcode
  • Type in Blog search field → results appear instantly from local store, no empty flash; background fetch appends more results; scroll to bottom → load-more fetches next page
  • Same for Quotes and Catalogue tabs
  • Airplane mode → local results still appear; no crash on failed network fetch
  • Catalogue note-body match shows item + snippet; still matches after relaunch (upserted offline)

🤖 Generated with Claude Code

danieltmbr and others added 2 commits July 7, 2026 07:35
- Per-tab .searchable bars on Blog, Catalogue, and Quotes — each filters only
  its own content, respecting active language/category/source filters
- Dedicated Search tab with sectioned results (Posts / Catalogue / Quotes)
  and a scope bar; catalogue section shows note-body snippets
- CatalogueSearchEngine: @observable engine that drives catalogue results via
  CatalogueStore.search; needed because @query can't cross the
  PreviewRecord→NoteRecord UUID link
- BlogSearchAction / CatalogueSearchAction / QuotesSearchAction: environment-
  injected seams; local predicate query runs first for instant results, then
  the network search upserts and triggers a second local pass
- Detail section fix: typed sections (Song/Album/Book/…) now accept
  item: PreviewRecord and coalesce typed+preview fields so a half-materialised
  item shows a header immediately; .task fires a single-item fetch on appear
  when the typed record is absent

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…list views

Wire up the paginated backend endpoints from the previous commit into the native app:
- Blog/Quotes/Catalogue: run local search immediately on keystroke (flash fix); network
  fetch debounced 300 ms; re-run local after upsert to surface new results
- CatalogueModel/QuotesModel/BlogModel: add loadMore() + isLoadingMore + hasMore state;
  loadMoreRevision counter lets CatalogueSearchEngine re-run after network upserts
- CataloguePageLoadAction / QuotesPageLoadAction: environment-injected load-more seams
- ReaderCatalogue / ReaderQuotes: cursor-tracking coordinators that thread nextCursor
  across search() and loadMore() calls against the paginated API endpoints
- Unified list views per tab: single @Query-based browse list + search-engine-driven
  results list, each with a load-more cell and status line
- ReaderApp: wire all three tabs to the paginated loaders

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@danieltmbr

Copy link
Copy Markdown
Owner Author

Duplicate — updating PR #229's base to feat/search-backend instead.

@danieltmbr danieltmbr closed this Jul 7, 2026
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.

1 participant