Search tab + sort menu fix (and tag feeds carried from #4)
Created by: jedmund
Summary
Three things rolled up: the tag-feeds work from PR #4 (which merged into claude/illust-detail-view, not main, so it needs to come along), plus a new Search tab in the main tab bar, plus a fix for the stacked-segmented-control visual collision in TagFeedView on iPadOS 26.
Search tab
-
MainTabViewgains a third tab between Home and Profile —magnifyingglassSF Symbol. TheTabView { Tab(...) }syntax already produces the iOS 26 floating pill tab bar for free (bottom on iPhone, top on iPad). -
New
SearchView—NavigationStack+.searchablein the nav bar drawer. Submitting the search replaces theNavigationPathwith a singlePixivIllust.Tagrather than appending, so five searches in a row don't leave the user five pages deep. - Empty state is a
magnifyingglassicon and a "Search for a tag" prompt. No history / trending / suggestions yet — those would each be their own feature. - Reads
isPremiumfrom@Environment(AuthSession.self)and threads it intoTagFeedViewthe same wayHomeViewdoes, so the paginatedsort=popular_descendpoint routes correctly. - Re-registers
PixivIllustandPixivIllust.Tagdestinations locally because each tab has its ownNavigationStackand destinations are per-stack.
Sort-menu redesign in TagFeedView
The .principal toolbar slot held a segmented Picker for Popular / Recent. On iPadOS 26 that sat directly under the top-placed tab bar, so two horizontal segmented-style controls ended up stacked on top of each other and read as one giant button bar. Moving sort to a Menu button in .topBarTrailing (alongside the gear) frees up the principal slot for the nav title and makes the control unambiguously a dropdown.
- The Menu wraps a
Pickerso selection renders with iOS's standard checkmark on the current mode. - Each dropdown row has a per-mode SF Symbol via a new
systemImagecomputed onTagSearchOptions.SortMode—flamefor Popular,clockfor Recent. - Toolbar button label is a fixed
arrow.up.arrow.down— users learn the shape fast and the current mode is always one tap away.
Tag feeds (from PR #4, carried along)
This diff also includes everything from PR #4 — PR #4 merged into claude/illust-detail-view rather than main, so the tag-feed commits never actually landed on main. Summary:
-
PixivEndpointsplit into.tagSearchRecent(word:timeRange:),.tagSearchPopular(word:timeRange:)(premium-gated, paginated), and.tagSearchPopularPreview(word:)(free top-30 fallback). Both/v1/search/illustcases funnel through a privatesearchIllustURLhelper. -
TagSearchOptionsmodel (sort mode + time range) withSearchTimeRangeowning the nativeduration→start_date/end_datetranslation for ranges Pixiv's duration param doesn't cover. -
MasonryFeedextracted fromHomeViewas a reusable component so both feed surfaces share one implementation. -
TagFeedViewpushes from tag pills inIllustDetailView; rebuilds itsIllustFeedViewModelononChange(of: options)with a fresh endpoint. -
TagSearchSettingsView— modal sheet with a time-range picker; footer copy switches based on premium status. -
Profile premium badge — golden-gradient pill with
crown.fillunder the user's@handlewhenis_premium == true.
Known limitations carried over
-
Black-cell-on-next-tap bug (from PR #3's follow-ups) affects any view that uses the zoom navigation transition — so
HomeView,TagFeedView, and nowSearchView → TagFeedView. Still tracked as a follow-up. - "All / male / female" demographic filter still not wired — Pixiv's tag search API doesn't expose it, and the ranking endpoint that does isn't tag-filtered. The settings sheet has a placeholder section documenting the gap.
-
Non-premium popular results capped at ~30 —
popular-previewisn't paginated. Pixiv limitation.
Test plan
-
Tap the new Search tab → empty state shows with search field. -
Type a tag name + return → pushes a TagFeedViewwith the typed term as the tag. -
Back to the search tab → type a different tag + return → previous tag feed is replaced (not stacked) in the path. -
TagFeedViewnav bar: tag name in the center, sort menu + gear on the right, no segmented control. Sort menu dropdown shows Popular (withflame) and Recent (withclock) with a checkmark on the current mode. -
On a premium account: flipping sort to Popular paginates with the current time range; flipping time range via the gear reloads correctly. -
iPad: confirm the top-placed tab bar and the tag-feed nav bar no longer look like stacked segmented controls. -
iPhone: confirm the floating bottom tab bar still has all three tabs (Home / Search / Profile) and the pill look.