42 Commits

Author SHA1 Message Date
Arkadiusz Fal
6e8835237d Add a Navigation setting to keep the tab bar on large screens
iPad and iPhone Duo users can pick Tab Bar instead of Automatic to opt
out of the sidebar layout. Switching rebuilds the navigation Settings
lives in, so the change asks for confirmation and lands on Home first.
2026-10-11 21:28:51 +02:00
Arkadiusz Fal
4770bbe3b9 Remove dead code found by Periphery on all platforms
Delete declarations that Periphery reports unused on every platform that
compiles them (iOS, macOS, tvOS), including nine views used only by their
own previews. Platform-gated code still used on another platform, device-
only MPV render paths, migration models, CloudKit record names, App
Intents metadata and unused parameters are kept.
2026-10-08 23:57:56 +02:00
Arkadiusz Fal
5ae07574cb Add URL scheme actions: play, queue, download, bookmark, subscribe, player controls
yattee://play|play-next|queue|download|bookmark|subscribe|unsubscribe?url={link}
and yattee://player/play|pause|toggle|next|previous|close|seek|rate run through
one LinkActionPerformer that reports a LinkActionResult, ready for
x-callback-url. An unencoded url= keeps its own query; only the action's own
parameters end it.

Actions that change saved state ask first through a confirmation sheet
presented by the top-most sheet host, unless the new 'Run Link Actions
Without Asking' setting is on. Download skips the question when the quality
picker will show anyway. Player commands leave sheets and the player alone.
2026-10-05 23:58:43 +02:00
Arkadiusz Fal
83895a1fd9 Reflect the video below the hinge in the tabletop layout
The iPhone Duo tabletop layout mirrors every presented frame into the
lower half, blurred and fading out, like a screen standing on a glossy
table. The render view blits a quarter-resolution copy of the display
framebuffer into a ring of IOSurface-backed buffers (no Y flip, so the
surface is already mirrored) and hands it to a CALayer hosted by
MPVReflectionView; the simulator's software renderer feeds the same
layer a flipped CGImage. Off during PiP, for audio-only streams, and
via the new Playback → Foldable → "Reflection Below Video" setting.
2026-10-01 20:59:48 +02:00
Arkadiusz Fal
1370f68c37 Rework details panel settings: pinned info, per-orientation visibility, section defaults
Pages list
- Info is pinned first and always enabled in every layout: normalized
  pages force it to the front and enabled (older presets self-correct),
  disabling it is a no-op, and any move that would displace it snaps
  back. The iOS/macOS list renders it outside the reorderable ForEach
  (no drag handle, nothing drops above it) and the editors hide its
  enabled toggle; tvOS also hides its move buttons. The "at least one
  page must stay enabled" guard and its strings are gone since Info
  always counts.
- iPhone never renders queue or comments as pages, so its Sections list
  hides them (PanelSettings.hiddenSettingsPageTypes). Reordering goes
  through moveVisiblePages, which keeps hidden entries in their stored
  slots. Comments get their own group on the Details Panel screen
  (pill mode + avatars) and the overlay hosts pass the avatars flag.

Default visibility
- "When Player Opens" is now configured per orientation
  (portraitDefaultVisibility / landscapeDefaultVisibility). The legacy
  single value is still decoded and seeds both until set individually;
  presets that never set it default to portrait Visible, landscape
  Hidden. macOS shows one picker (no portrait layout).
- "Remember Last" no longer leaks across orientations: separate
  remembered flags, written by the portrait toggles and by the wide and
  corner layouts respectively, with the old shared flag read once as a
  fallback. The corner layout seeded from the portrait resolution
  before; it now uses landscape.

Section options (iOS inline-sections hosts)
- Chapters and Related editors gain "Expanded by Default" (on by
  default). The Info editor gains a Description group with "Expanded by
  Default" (off) and a "Collapsed Lines" stepper (1–10, default 3).
  Applied when the panel appears and on each video change.
- Expanding a collapsed section scrolls its header to the top of the
  panel: PanelPageScrollView can hand its scroll proxy to page content
  and each inline section is wrapped in one anchored container.
- The portrait panel's bottom fade sized its touch blocker from a stale
  "expanded comments pill" answer that ignored collapse on scroll, so a
  collapsed section header (the last item) sat under it and could not
  be tapped. The predicate now tracks the pill's actual collapse state.
2026-09-26 23:50:30 +02:00
Arkadiusz Fal
4210b0ab05 Simplify the wide-layout details panel: floating-only on iPhone, side as a preset setting
iPhone landscape now uses the floating panel only, always on the right;
the pin and side-toggle buttons on the grabber are gone and the pinned
setting resolves to false on phone.

iPad and macOS default to the pinned side-by-side layout, keep the pin
button to switch to floating, and pick the panel side in the preset's
panel settings instead of an on-screen arrow. The pinned state persists
as a layout preference: closing the player or the hidden default
visibility no longer resets it.

Removes PanelAlignmentButton, the global floatingDetailsPanelSide setting
and its key, FloatingPanelSide.opposite, and the legacy
wideLayoutPanelAlignment preset field.
2026-09-26 22:48:11 +02:00
Arkadiusz Fal
a6d989c7af Add corner player layout on iPad and macOS
Preset-selected two-region layout: video in the top-left, a resizable
side column, and an optional region below the video. Pages are assigned
to regions per preset (Location picker in the page editor); the layout
falls back to the stacked widescreen layout below 900pt width, so Split
View and narrow windows degrade automatically.

- CornerPlayerLayout hosts the shared playerAreaForWidescreen builder,
  so the MPV hosting path is identical to the stacked layout
- Layout resolver in ExpandedPlayerSheet picks corner per layout pass;
  NavigationCoordinator.isCornerLayoutActive feeds the macOS window
  manager, which drops the aspect-ratio lock and auto-fit while corner
  is active (and restores them on exit, incl. fullscreen replay and
  window re-mounts)
- Side column width persisted via new cornerPanelColumnWidth setting
  (280-560pt, video column kept >= 480pt)
- Settings: layout mode picker (iPad/macOS) with automatic-fallback
  footer, per-page region picker when corner is on, region shown in
  the pages list
2026-09-21 23:52:09 +02:00
Arkadiusz Fal
c33d125553 Add details panel preset settings UI and default visibility
Phase 2 of the player panels redesign:

- New "Details Panel" screen in Player Controls settings: page
  reorder/enable list with per-page editor (info element toggles),
  and a default panel visibility picker (hidden/visible/remember).
- PlayerControlsSettingsViewModel gains panelSettings bindings with
  the usual debounced-save flow; the last enabled page cannot be
  disabled.
- Built-in presets bumped to v9 with explicit default panelSettings.
- The preset's default visibility now drives the wide-layout panel
  on player open and on entering landscape, replacing the hard
  hidden resets; "remember" restores the new detailsPanelLastVisible
  setting recorded on user toggles. Applied once per expanded player
  session (flag on NavigationCoordinator survives re-mounts).
- WideScreenPlayerLayout picks up external visibility writes so the
  async-loaded default reaches the mounted layout.
- Unit tests for PanelSettings Codable compatibility (round-trip,
  old JSON, unknown page types/discriminators/enum values); removed
  stale PlayerInfoTab tests left from Phase 1.
2026-09-21 23:25:10 +02:00
Arkadiusz Fal
5651f8d431 Add a toolbar layout for the video info actions with a configurable primary action
Layout & Navigation gains a Video Info section on iOS/macOS: the actions
(Play, Download, Share, Add to Playlist, Bookmark) can stay as inline
button rows or move to the navigation bar, where the chosen primary
action is pinned and the rest live in an ellipsis menu. The toolbar
layout with Download pinned is the new default, since the hero thumbnail
already plays the video on tap; a one-time TipKit popover on the
thumbnail points that out. tvOS keeps the existing button layout.
2026-09-20 23:52:20 +02:00
Arkadiusz Fal
629561f057 Keep the system accent color on tvOS
Views reading resolvedAccentColor directly (comment links, home
shortcuts, bookmarks, player panels) picked up accent colors synced
from iOS via iCloud. tvOS now always resolves to the system default.
2026-09-18 23:59:54 +02:00
Arkadiusz Fal
d22abf6088 Add an option to share videos via privacy frontend URLs
When enabled (the default), share links to YouTube videos point to the
active source's web watch page instead of youtube.com. Invidious serves
its frontend at the API URL; Piped uses its configured frontend URL.
Videos the active source can't serve (PeerTube, extracted sources) and
sources without a web frontend keep their original links.

The toggle lives in Settings > Layout & Navigation > Sharing on iOS and
macOS, and is shown only when an enabled source has a web watch page.
2026-09-18 23:57:34 +02:00
Arkadiusz Fal
5136b79f49 Let the user hide the account pickers outside Settings 2026-09-13 18:56:18 +02:00
Arkadiusz Fal
175b98097a Put the account switcher where the data is, and retire the old setting
Switching accounts was buried in Subscriptions settings behind a picker
and a confirmation dialog, and it wrote two stores that could disagree.
One shared switcher now sits in the Subscriptions and Playlists
toolbars, the macOS sidebar footer and the Settings root, and every path
goes through AppEnvironment.switchDataContext(to:) so a switch behaves
the same wherever it is made. Switching is one tap: it is reversible, so
there is nothing to confirm.

Rows come from DataContextValidator.availableContexts, name themselves
through displayName(for:), and carry a status suffix when the account is
not signed in — plus the instance host when two accounts share a name.
tvOS gets the same rows as a full-screen picker.

Subscriptions also explains itself when the selected account cannot
answer: a thin banner names the cause and says the data below is local.
This is the first consumer of the validator's unavailability, and
correctIfContextRemoved() now runs on foreground activation, where
SubscriptionAccountValidator used to auto-correct any selection it could
not immediately verify.

With the switcher reading the context directly, the legacy
subscriptionAccount setting has no readers left: the setting, its
validator, the mirror that kept it in step and the feed cache's
instance-keyed fallbacks all go. The cache invalidation the mirror also
carried stays, under its own name. AccountsManager still reads the raw
legacy key for the one-way context migration.
2026-09-03 23:59:32 +02:00
Arkadiusz Fal
262dab8f9e Skip local-only settings keys when enabling iCloud settings sync
refreshFromiCloud already skipped isLocalOnly keys, but the enable-time
paths did not: replaceWithiCloudData overwrote device-specific settings
with another device's values, and syncToiCloud uploaded local-only keys
to the ubiquitous store. Apply the same skip in both.
2026-07-15 06:33:02 +02:00
Arkadiusz Fal
06087220ef Add audio-only music mode
Persistent per-platform mode that plays only the audio track to save
bandwidth and speed up loads. When enabled, stream selection picks the
best audio-only stream (preferred language, codec, bitrate) and never
fetches the video URL; toggling mid-video reloads at the current
position using the quality-switch path (live vid=no toggling is avoided
due to A/V desync).

- Toggle row in the player quality/settings sheet on iOS, macOS and
  tvOS, next to lock controls
- New audioMode control button type (red when active) for player
  controls and mini player layouts
- Picking a video quality explicitly turns the mode off; audio track
  picks keep it on and now work while audio-only is playing
- Stream URL refresh preserves audio-only playback instead of
  resurrecting video
- Queue preloads and history entries resolved before a toggle are
  discarded so selection re-runs with the current mode
- tvOS player shows the video thumbnail instead of a black screen
  during audio-only playback
- PiP button hidden for audio-only streams
2026-07-13 19:06:01 +02:00
Arkadiusz Fal
6fed1b0ca7 Enforce theme at the window level instead of preferredColorScheme
SwiftUI's .preferredColorScheme on the root view could not revert from
dark back to light/system while a sheet was presented, and on macOS it
never applied to secondary window scenes such as Settings. The override
is now applied directly to UIKit/AppKit instead.

- SettingsManager.applyTheme sets overrideUserInterfaceStyle on every
  window of every connected scene (iOS) or NSApp.appearance (macOS);
  the theme setter calls it, so any future code path that changes the
  theme outside the setter must do the same
- AppTheme gains userInterfaceStyle / appearance mappings, with .system
  resolving to .unspecified / nil so the OS setting takes over again
- Applied on app appear for the initial launch state, and after both
  iCloud sync paths, since theme can arrive as a synced change and is
  no longer driven by SwiftUI state

Claude-Session: https://claude.ai/code/session_0154KH8RAVAvm6iVanhmoW8o
2026-07-05 21:06:43 +02:00
Arkadiusz Fal
b632f11b2f Add separate light/dark mode accent colors
Adds an option in Appearance settings to use different accent colors
in light and dark mode, with a toggle to keep a single shared color
(the default, preserving existing behavior).

- New synced settings keys: accentColorDark, customAccentColorDark,
  useSeparateDarkAccentColor; dark values fall back to the light
  selection until explicitly set, so no migration is needed
- resolvedAccentColor returns a dynamic platform color (UIColor trait
  provider / NSColor appearance provider) when the toggle is on, so
  the root tint and all direct readers adapt to light/dark
  automatically without consumer changes
- Accent Color section shows two stacked preset+custom grids with
  Light/Dark headers when enabled, extracted into AccentColorGrid;
  CustomAccentColorButton now takes bindings so the macOS color panel
  edits whichever target was last opened
- New DarkAccentColorTests covering sync contract, default-off state,
  fallbacks, and toggle-off resolution

Claude-Session: https://claude.ai/code/session_0154KH8RAVAvm6iVanhmoW8o
2026-07-05 21:06:26 +02:00
Arkadiusz Fal
b47888fe04 Add custom accent color with system color picker
Add a Custom swatch to the appearance settings accent color grid,
backed by a hex value stored in settings (synced via iCloud like the
rest). iOS uses the native ColorPicker wheel; macOS uses a circular
swatch that opens NSColorPanel, since the SwiftUI color well looks out
of place among the circles. All accent consumers now read the resolved
color through SettingsManager.resolvedAccentColor.

The indigo preset is retired from the grid but kept in the enum, so
users who selected it keep their color until they pick another one.

Claude-Session: https://claude.ai/code/session_0154KH8RAVAvm6iVanhmoW8o
2026-07-04 23:57:59 +02:00
Arkadiusz Fal
1cd566ae29 Allow dragging the macOS player controls bar to reposition it
The glass controls capsule can now be dragged anywhere over the video.
Position is stored as a fraction of the container size so it survives
window resizes and aspect-ratio driven sheet resizes, persists across
sessions via SettingsManager, and snaps back magnetically when dropped
near the default bottom-center spot. Travel is clamped so the capsule
stays inside the player and never overlaps the top button row. A
mouseDownCanMoveWindow=false backing view keeps the window's
movable-by-background behavior from swallowing the drag.
2026-06-21 17:39:48 +02:00
Arkadiusz Fal
d7df883d6f Remove media sources as Home sections (shortcuts-only)
A media-source "section" only rendered as a full-width "Browse {name}"
link, identical for all source types and redundant with the shortcut
card. Remove it from the Available Sections add-list and clean up any
already-added media-source sections on load.

Keep HomeSectionItem.mediaSource as a decode-only case so existing saved
homeSectionOrder data (decoded all-or-nothing) still parses; strip those
entries via removeAllHomeMediaSourceSections(). Media-source shortcuts
are unchanged.
2026-06-11 20:16:00 +02:00
Arkadiusz Fal
8d556abd0b Split home shortcut card style into Layout, Color, and Palette
Decouple the two concerns that were entangled in a single card-style setting:

- Layout (Compact / Regular) now only controls positioning of the
  icon / title / subtitle / counter.
- Color (Soft / Vibrant) is a new independent setting: Soft = tinted
  background with palette-colored icon and neutral text; Vibrant =
  solid palette fill with white icon/text.
- Palette (Accent first, then Classic/Sunset/Meadow/Berry/Grape/Custom)
  now applies to both layouts and both colors, and is always shown.

Adds section headers (Layout / Color / Palette) to the style page and
fixes the Compact preview to show the count subtitle line. Default is
Regular + Soft + Accent.
2026-06-11 19:03:52 +02:00
Arkadiusz Fal
2f2e436fe2 Split macOS player mode into window toggle + floating control
Replace the three-way macOS Player Mode picker (Separate Window /
Floating Window / Inline) with a single 'Play in a separate window'
toggle in Playback settings, and move the always-on-top choice to a
pin button in the player's top bar (window mode only).

Floating was really a transient window property (NSWindow.level), not
a peer of the window/inline structural choice — so it belongs on a live
control, not in Settings. The pin state persists across sessions.

- Replace MacPlayerMode enum with macPlayerSeparateWindow /
  macPlayerFloating bool settings
- Branch runtime presentation and window level off the two bools
- Add pin.fill/pin toggle to MacOSPlayerControlsView top bar
- Update localization; drop obsolete playerMode strings and enum tests
2026-05-30 12:42:18 +02:00
Arkadiusz Fal
486024834d Add position-based colorful Home shortcut palettes
Colorful shortcut cards now color by grid position instead of shortcut
identity, so colors stay in the same slot when shortcuts are reordered.

Adds a Palette option (Classic default, plus Sunset, Meadow, Berry,
Grape) and a Custom palette with a swatch-list editor (ColorPicker + hex
fields) and a switchable comma-separated text field. Color is resolved
per position and wraps by palette length, wired via a new
homeShortcutColorfulColor environment value and a Color(hex:) extension.
2026-05-28 23:26:05 +02:00
Arkadiusz Fal
7a1af02418 Add card style option for Home shortcut cards
Adds a Style picker (Plain / Accent / Colorful) to the Customize Home
sheet, shown when the shortcuts layout is Cards. Defaults to Plain.

- Plain: current look (light accent tint + accent border)
- Accent: solid accent fill, white icon/text
- Colorful: solid fill with a fixed color per shortcut type

The filled styles use a Reminders-style layout (icon top-leading, count
top-trailing, title anchored to the bottom) with a subtle gradient sheen
over the fill color. Cards without a meaningful count (Open Link, Remote,
Subscriptions, instance content, media sources) hide the number; Remote
shows its status dot in the top-right slot instead.

Persisted via SettingsKey.homeShortcutCardStyle, mirroring the existing
homeShortcutLayout accessor.
2026-05-26 06:43:34 +02:00
Arkadiusz Fal
6dfa63c263 Remove Enable DASH setting; make DASH a last-resort format
Drop the dashEnabled toggle and its plumbing. Stream auto-selection now
keeps DASH as a candidate but ranks it strictly below progressive and
HLS formats, so DASH is only chosen when it is the only format available
(including live-stream fallback after HLS). The manual quality selector
hides DASH entirely on iOS/tvOS/macOS. Reconciles BackendSwitcher, which
previously treated HLS/DASH equally, to use the same DASH-last ranking.
2026-05-20 07:14:31 +02:00
Arkadiusz Fal
c168fbae02 Add tvOS A/V sync diagnostics on its own settings page
Surface audio-delay (±10/±100 ms) and video-sync-mode controls behind an
"A/V Sync" navigation row in Advanced settings rather than inline, keeping the
Advanced page uncluttered. Audio delay applies live to the running MPV
instance; sync mode takes effect on next playback.
2026-05-14 09:43:25 +02:00
Arkadiusz Fal
6a343311ea Add tvOS display frame rate and dynamic range matching
Lets the Apple TV switch its HDMI output to match the playing video's
frame rate and dynamic range via AVDisplayManager.preferredDisplayCriteria,
driven from MPV's container-fps and video-params/gamma. Two opt-in toggles
(default off) live under Playback → Display on tvOS; both are no-ops on
other platforms. Anchor an AVKit class symbol so the linker keeps AVKit
linked — Swift only autolinks AVFoundation here, and without AVKit the
UIWindow.avDisplayManager category isn't loaded at runtime.
2026-05-10 15:28:11 +02:00
Arkadiusz Fal
d0297a5e89 Fix tvOS MPV Options focus and Add/Edit sheet layout
Wrap pushed view in TVSidebarDetailContainer, list custom options
first so focus engages on a row, mark default options focusable so the
list scrolls. Replace toolbar-based Add/Edit sheets with padded VStacks
and inline confirm buttons. Cache customMPVOptions in @Observable
backing storage so writes refresh the list immediately.
2026-05-09 18:11:59 +02:00
Arkadiusz Fal
aabf5313fa Expose Background Playback toggle on tvOS, default off
Surfaces the existing iOS/macOS Background Playback setting in the tvOS
Playback settings, defaulting to off so audio stops when the user leaves
the app via the TV button. Pauses playback on .background/.inactive when
the toggle is off, regardless of audio route — the user's setting wins
over AirPlay/HomePod handoff. Also auto-shows the tvOS player controls
when returning to foreground so the paused state is immediately visible
and actionable.
2026-05-09 14:50:38 +02:00
Arkadiusz Fal
158d518e3a Trim comments and hoist settings read in stream filtering
Drop comments restating what the code shows; hoist allowSoftwareDecodedFormats
out of the recommendedVideoStreams filter closure so the bridge property is
read once per render instead of once per stream.
2026-05-07 18:03:34 +02:00
Arkadiusz Fal
16477641ab Add Allow Software-Decoded Formats playback setting
Lets the auto stream selector pick formats whose codec isn't hardware
decoded on the current device. Defaults off; when on, 4K VP9/AV1 can be
auto-selected on Apple TV models without those decoders. Software-decoded
streams also move into the Recommended section so the selection stays
visible without enabling advanced stream details.
2026-05-07 18:00:14 +02:00
Arkadiusz Fal
5a839da1bd Resolve URL shorteners and prompt for ambiguous description links
Tapping bit.ly/tinyurl/t.co/etc. in a description or comment previously
opened Safari even when the destination was a playable YouTube URL.
Added an opt-in "Resolve Short Links" toggle under YouTube Enhancements
(off by default) that follows the redirect on tap: if the target is a
YouTube/PeerTube/direct-media URL, open it in-app; otherwise prompt the
user before falling back to yt-dlp extraction or the browser.

Also added a confirmation dialog for non-shortener links that only
matched the loose .externalVideo yt-dlp fallback, so arbitrary web
pages in descriptions no longer silently kick off extraction.

Prompts live on NavigationCoordinator and are dual-hosted by YatteeApp
and ExpandedPlayerSheet so they remain visible whether or not the
expanded player is covering the main view.
2026-04-23 07:29:57 +02:00
Arkadiusz Fal
d2b6a158db Enable app icon selection on macOS 2026-04-20 21:21:18 +02:00
Arkadiusz Fal
8f00fe012f Add tvOS setting to close video with Menu button
When enabled, the Siri remote Menu button stops playback and clears the
queue instead of only collapsing the player, and the explicit top-bar
close (X) button is hidden.
2026-04-18 20:38:02 +02:00
Arkadiusz Fal
9f86ff0667 Add tvOS Top Shelf extension
Surfaces Continue Watching, Recent Feed, and Recent Bookmarks in the
Apple TV Home top shelf when Yattee is focused. Tapping a tile opens
the video via the existing yattee://video/{id} deep link.

- New YatteeTopShelf app extension target (tvOS only). LD_ENTRY_POINT is
  overridden to _NSExtensionMain; the tv-app-extension product type
  defaults to _TVExtensionMain which is for the pre-tvOS-13 legacy API
  and crashes modern TVTopShelfContentProvider subclasses at launch.
- Main app writes per-section JSON snapshots (capped at 10 items each)
  to a shared App Group UserDefaults suite after bookmark, watch-history,
  and feed-cache changes, plus an initial write on launch.
- Enabled-sections list is mirrored to the same App Group so the
  extension can respect the user's selection without touching SwiftData.
- Settings → Top Shelf (tvOS only) lets the user toggle sections.
- Deep link playback shows a loading toast while video details are
  fetched, and an error toast if no source is configured.
2026-04-18 20:38:02 +02:00
Arkadiusz Fal
9b55ee7127 Add tvOS setting for video click behavior 2026-04-18 20:38:01 +02:00
Arkadiusz Fal
eb697b7bbc Add List/Grid layout option for Home sections
Introduces a "Display sections as" picker in Home settings with List and
Grid modes. Grid renders each section as a horizontal shelf of video
cards, defaulting to Grid on tvOS and List on iOS/macOS. Per-platform
defaults are preserved via a platform-specific settings key.

On tvOS the shelf is a focus section so swiping up/down between rows of
different lengths works without getting stuck at the end of a row.
2026-04-18 20:38:01 +02:00
Arkadiusz Fal
c7942ef555 Rework tvOS player controls and settings sheet
Replace the tvOS bottom action bar with Settings / Info / Comments /
Next / Close. Settings reuses QualitySelectorView (video, audio,
subtitles, speed); Comments opens TVDetailsPanel directly on the
comments tab; Close stops playback and dismisses.

Debug button is hidden by default and can be re-enabled via a new
tvOS-only Advanced Settings > Developer toggle.

Present the settings sheet as a fullScreenCover with a centered
material card, fix the "Normal" hyphenation, and restyle row selection
throughout the quality selector on tvOS: per-row rounded backgrounds
with focus tint + stroke, vertical spacing instead of dividers, and a
focusable speed-rate menu.
2026-04-18 20:38:01 +02:00
Arkadiusz Fal
9e95a91284 Sync sidebar/tab bar/home layout per-platform via iCloud
Extends `SettingsKey.isPlatformSpecific` to cover home, tab bar, and
sidebar layout, plus player details panel and video swipe actions, so
iOS devices sync these with other iOS devices (and tvOS with tvOS,
macOS with macOS) instead of overwriting each other via the shared
iCloud key. Adds a one-shot migration that copies legacy unprefixed
values into the new platform-prefixed slots locally and in iCloud,
preserving protected-key timestamps.
2026-04-18 20:38:01 +02:00
Arkadiusz Fal
f4605e7390 Force plain list style on tvOS and hide setting from appearance
Inset/grouped list style doesn't work well with tvOS focus effects.
Always return .plain on tvOS and hide the list style picker from
appearance settings.
2026-04-18 20:38:01 +02:00
Arkadiusz Fal
7c33f7e9f3 Change default layout settings 2026-04-18 20:37:25 +02:00
Arkadiusz Fal
100df744d9 Yattee v2 rewrite 2026-04-18 20:37:24 +02:00