Skip to content

Search tab typeahead via autocomplete endpoint

jedmund requested to merge claude/search-typeahead into main

Created by: jedmund

Summary

Tag typeahead for the Search tab. As you type, suggestions appear below the search field via /v2/search/autocomplete; tapping one immediately pushes TagFeedView for that tag (including its translated name, so the pushed screen title reads "Genshin Impact" instead of the raw Japanese).

  • PixivAutocompleteResponse (pixillate/Models/PixivAutocompleteResponse.swift) — thin envelope wrapping [PixivIllust.Tag]. Pixiv's autocomplete returns the same tag shape it embeds in illust responses, so the existing nested Tag type gets reused.
  • .searchAutocomplete(word:) endpoint case (pixillate/Networking/PixivEndpoint.swift) — hits /v2/search/autocomplete?word=<partial>&merge_plain_keyword_results=true. The merge flag folds plain-keyword matches into the same tags array so callers render one list.
  • SearchView typeahead wiring (pixillate/Views/SearchView.swift):
    • .searchSuggestions { ... } renders a row per tag — magnifyingglass icon + Japanese name + translated name in caption-size secondary text.
    • Each row is a Button that runs performSearch(using:) on tap, immediately pushing TagFeedView rather than just filling the text field.
    • scheduleSuggestions(for:) debounces 250ms and single-flight-cancels — rapidly typing "genshin" fires one request after the user pauses, not seven. Cancellation propagates into URLSession.data(for:) cooperatively so in-flight requests stop on the wire.
    • performSearch(using:) now takes an optional explicit Tag so a tapped suggestion can carry its translatedName through into TagFeedView's title.
    • Autocomplete errors are swallowed silently. If the endpoint 401s, the next api.send call triggers the normal TokenStore.forceRefresh() dance.

Known follow-ups / limitations

  • No loading indicator between keystroke and response. The 250ms debounce window is short enough that most users won't notice, but if you see it feel laggy I can add a subtle spinner row to the suggestions list.
  • No search history / recents. Every search starts from scratch. The placeholder still shows "Search for a tag" when the field is empty; a recent-searches list could render there in a follow-up.
  • iPad: .searchable with .navigationBarDrawer(displayMode: .always) pins the field under the nav bar rather than in-line with the title. If this reads weird on iPad's top-placed tab bar, we can switch to .toolbar placement.

Test plan

  • Tap the Search tab and start typing a partial tag name — suggestions appear after you pause typing (~250ms).
  • Type rapidly — only one request fires (the rest get cancelled).
  • Tap a suggestion → immediately pushes TagFeedView with the suggestion's translated name in the nav title (when Pixiv returns one).
  • Back out of the tag feed — search field still has the tag name, suggestions still visible.
  • Clear the search field — suggestions disappear, placeholder returns.
  • Submit raw text (no suggestion tapped) → still pushes TagFeedView with the raw typed term (same behavior as before).
  • Turn off Wi-Fi and type — no error UI, just silent no-suggestions (autocomplete is best-effort).

https://claude.ai/code/session_01RDp8iEpHQ3GgpvDesCBR3s

Merge request reports

Loading