23 Commits

Author SHA1 Message Date
Arkadiusz Fal
1157eef201 Fix macOS native styling for search toolbar pickers and view options
The content type segmented picker rendered as a Liquid-Glass pill instead
of a native macOS segmented control. Wrapping a `.segmented` Picker in
`.opacity`/`.disabled`/`.accessibilityHidden`/`.fixedSize` (used to keep
toolbar items mounted-but-invisible for stable layout) inserts a hosting
layer that makes the toolbar fall back to the pill rendering.

- SearchView: filters button and content type picker are now always
  visible on macOS, rendered bare so `.segmented` keeps native styling.
- SearchView: don't reset the content type to .video on submit on macOS,
  so a pre-selected type (e.g. Playlists) is preserved (iOS unchanged).
- InstanceBrowseView: same pill fix, rendering the tab / content type
  pickers bare via conditional `if` instead of opacity-masking.
- ViewOptionsSheet / MediaBrowserViewOptionsSheet: use `.formStyle(.grouped)`
  for native macOS form styling in the options popover.
2026-06-15 08:07:40 +02:00
Arkadiusz Fal
77720ccea1 Pin view options button to leading toolbar edge on macOS
Place the view options control on the leading (`.navigation`) edge on
macOS so it is consistently the first/leftmost toolbar button across all
views, instead of sitting on the right next to the search field in
search views and on the left in non-search views.

Each affected view gains a computed `viewOptionsPlacement` (`.navigation`
on macOS, `.primaryAction` elsewhere) so iOS/iPadOS/tvOS keep the
button trailing. Search-style views (Search, InstanceBrowse) declare the
view options item first so it renders left of the search-filters button;
their flexible spacer is kept to right-pin the search field. Channel's
fixed spacer between view options and the channel menu is now iOS-only.
2026-06-14 16:03:10 +02:00
Arkadiusz Fal
4cda0bbc7a Move instance browse pickers into macOS toolbar
The Popular/Trending tab picker now lives in the toolbar (principal
placement) instead of inline above the content. Once a search is
submitted it swaps to the search content type picker, with the search
filters button alongside it as a popover, matching the global Search
view. Items stay mounted invisible on macOS 26 so the toolbar layout
stays stable while typing.
2026-06-12 21:04:30 +02:00
Arkadiusz Fal
7ecd408f89 Pin search bar to right of macOS toolbar in list views
Match the global Search view by pinning the searchable field and
trailing buttons to the right edge on macOS 26 via a flexible
ToolbarSpacer at .primaryAction. Applied to History, Bookmarks,
Manage Channels, Downloads, Instance Browse, and PeerTube Explore.

In History, the clear-history item moves from .automatic to
.primaryAction so it groups with the other trailing controls.
2026-06-12 09:54:24 +02:00
Arkadiusz Fal
271aff86b5 Present view options and search filters as popovers on macOS
Plain-Form sheets rendered as columns-style content floating inside
oversized fixed frames on macOS. Anchor these panels to their toolbar
buttons as popovers instead, sized to content; iOS/tvOS keep sheets.

- Search and PeerTube explore filters apply live (Cancel never
  reverted anything anyway) and dismiss on outside click
- Subscriptions/Manage Channels "Subscriptions Data" opens as a sheet
  from the popover's onDisappear via a pending flag, since presenting
  while the popover dismisses gets swallowed
- Media browser view options drop navigation chrome on macOS
2026-06-06 22:59:36 +02:00
Arkadiusz Fal
6673d478c2 Hide feed channel filter strip on tvOS
The horizontal channel chip strip looks awkward on tvOS and the focus
interaction is clunky. Drop it from the tvOS branch of InstanceBrowseView;
other platforms keep it.
2026-05-07 06:32:14 +02:00
Arkadiusz Fal
e609e48449 Add bottom padding under tvOS search/action top bars
Separates the inline search field and action button from the video
listing below on History, Bookmarks, Instance browse, and Manage
channels screens.
2026-04-18 20:38:02 +02:00
Arkadiusz Fal
6eec42241d Disable scroll clipping for tvOS video listing grids
Allows focus-scaled cards to render past scroll view bounds on History,
Bookmarks, Search, and Instance browse screens.
2026-04-18 20:38:02 +02:00
Arkadiusz Fal
281f5e0f13 Hide tvOS search type/filters until query entered
Match iOS behavior by gating the type switcher and filters menus on an
active query, and drop the .caption font so they render with the same
default button font as View Options.
2026-04-18 20:38:01 +02:00
Arkadiusz Fal
454f10b3ab Show selected content type in tvOS Type filter button
Display the current selection (All/Videos/Playlists/Channels) instead
of the static "Type" label so users can see the active filter at a
glance.
2026-04-18 20:38:01 +02:00
Arkadiusz Fal
885c478857 Increase top spacing for tvOS focus effect on first content row
Add padding above the content area so the tvOS focus highlight on the
first row isn't clipped by the search header above it.
2026-04-18 20:38:01 +02:00
Arkadiusz Fal
c3a2f7a965 Add bottom padding to tvOS search header for focus effect clearance 2026-04-18 20:38:01 +02:00
Arkadiusz Fal
5417374275 Consolidate tvOS search header: search, type, filters, view options
Reorganize the tvOS search UI into a single header row with search
field, type filter menu, combined filters menu (sort/date/duration
with reset), and view options button. Removes the separate filter
strip between search and results on tvOS.
2026-04-18 20:38:01 +02:00
Arkadiusz Fal
3c7581de1a Replace search content type segmented picker with Menu on tvOS
Unifies the filter strip on tvOS so all filters (sort, date, duration,
content type) use the same inline Menu style instead of mixing menus
with a segmented picker.
2026-04-18 20:38:01 +02:00
Arkadiusz Fal
831773a609 Replace search filters sheet with inline menus on tvOS
The filters sheet is too small and awkward on tvOS. Replace the filter
button with inline Menu pickers for Sort By, Upload Date, and Duration
directly in the filter strip. Applied to both SearchView and
InstanceBrowseView.
2026-04-18 20:38:01 +02:00
Arkadiusz Fal
5ae1fc3f29 Fix tvOS instance browse view overlapping search and navigation UI
Use inline TextField with focusSection instead of .searchable() and
.navigationTitle() on tvOS, matching the pattern in HistoryListView.
2026-04-18 20:38:01 +02:00
Arkadiusz Fal
8cd3aca96c Generalize Yattee Server credentials manager to BasicAuthCredentialsManager
Renames YatteeServerCredentialsManager → BasicAuthCredentialsManager so the
same Keychain-backed username/password storage can be reused for any instance
type that sits behind a reverse proxy requiring HTTP Basic Auth. Adds a
one-time migration that moves existing items from the legacy
'com.yattee.yatteeserver' Keychain service to 'com.yattee.basicauth',
preserving the iCloud-sync attribute. No behavior change for end users.
2026-04-18 20:38:00 +02:00
Arkadiusz Fal
f8da242968 Fix ContentUnavailableView centering on Apple TV
On tvOS, ContentUnavailableView inside a Group doesn't expand to fill
available space — it sizes to content and aligns top-leading. Add
.frame(maxWidth: .infinity, maxHeight: .infinity) to all instances
so they center correctly in their parent containers.
2026-04-18 20:38:00 +02:00
Arkadiusz Fal
e38e4cca3a Fix feed channel filter avatars showing placeholders instead of images
The filter strip was passing the Invidious instance URL as serverURL to
AvatarURLBuilder, which built a Yattee Server-style /avatar/ path that
doesn't exist on Invidious. Now passes the actual Yattee Server URL
(matching SubscriptionsView pattern) and enriches channels from
CachedChannelData as a fallback when the API doesn't return thumbnails.
2026-04-18 20:37:35 +02:00
Arkadiusz Fal
e3606dbb3a Fix Feed tab flashing ContentUnavailableView on initial load
When a cancelled load task fell through to `isLoading = false`, it
created a 1-frame gap where the empty view rendered before the
replacement task set `isLoading` back to `true`. Return early on
cancellation so the surviving task controls loading state.
2026-04-18 20:37:25 +02:00
Arkadiusz Fal
0e0922dad0 Fix pull-to-refresh scroll offset not resetting in InstanceBrowseView
Move .refreshable from the outer GeometryReader onto the ScrollView
itself so SwiftUI can properly coordinate the scroll offset bounce-back.
The ScrollView was inside an .overlay() which doesn't participate in
the parent's layout system, breaking the offset reset.

Closes #917
2026-04-18 20:37:25 +02:00
Arkadiusz Fal
11a8c79e21 Refactor views 2026-04-18 20:37:25 +02:00
Arkadiusz Fal
100df744d9 Yattee v2 rewrite 2026-04-18 20:37:24 +02:00