Commit Graph

2749 Commits

Author SHA1 Message Date
Arkadiusz Fal
38242edf0c Present instance login as full-screen cover on tvOS
The .sheet rendering on tvOS produced a tiny floating modal where the
"Sign In" title wrapped onto two lines and form fields overflowed. Use
.fullScreenCover on tvOS and wrap the login form in
TVSidebarDetailContainer so the title/icon sit in the standard 400pt
left sidebar. iOS and macOS keep the existing sheet presentation.
2026-05-06 21:44:55 +02:00
Arkadiusz Fal
411fcba037 Surface clearer error when adding a Piped frontend URL
Pointing AddRemoteServer at a Piped Vue SPA (e.g. the frontend host
rather than the API host) used to fail with a generic
"could not detect instance type" — every JSON probe got the same
index.html back. On the failure path, fetch `/` once more and look
for `<title>Piped</title>`; if matched, return a new
`pipedFrontendDetected` error that tells the user to enter the
Piped API URL instead.
2026-05-06 21:14:50 +02:00
Arkadiusz Fal
e3f4d764cc Add UI smoke test for Piped authenticated endpoints
Adds a Piped instance, logs in, and exercises the two settings flows that
hit the regressed endpoints directly — Import Subscriptions (/subscriptions)
and Import Playlists (/user/playlists). Asserts that "session is a required
parameter" never appears in the AX tree, catching the recent header-vs-query
auth regression end to end.

Promotes three tree-walking helpers (id_in_tree?, id_with_prefix_in_tree?,
label_in_tree?) onto UITest::Axe so the spec can fetch the AX tree once per
poll iteration and run all checks against it locally — roughly 6× fewer
`axe` subprocess spawns than calling element_exists? / text_visible? per
check, and a primitive other specs can reuse.
2026-05-06 20:17:28 +02:00
Arkadiusz Fal
6f8aa9a1b3 Block HTTP Basic Auth proxy for Piped sources
Piped's session token reuses the Authorization header, so a fronting basic
auth proxy can't coexist with logged-in Piped use — the two would clobber
each other's credentials on every authenticated request.

Add a supportsHTTPBasicAuthProxy capability on Instance/InstanceType (false
for Piped, true for everything else) and route it through:

- AddRemoteServerView refuses Piped if detection only succeeded behind basic
  auth, surfacing a localized "not supported" error instead of a silently
  broken instance, and hides the optional credentials section for Piped.
- EditSourceView hides the basic auth fields for Piped instances and clears
  any legacy stored credentials on save, in case a Piped source was added
  with credentials before this change.
2026-05-06 20:17:18 +02:00
Arkadiusz Fal
11841d7b41 Send Piped session token in Authorization header again
Commit aed78c13f moved the session token from the Authorization header to a
?authToken= query parameter on /subscriptions, /subscribe, /unsubscribe,
/user/playlists, and /playlists/{id}. Piped's backend only accepts the
?authToken= form on /feed; every other authenticated route reads it from
Authorization (the Java handler names the variable "session", which is why
the rejected requests returned "session is a required parameter"). Restore
the header form for those five routes and leave feed alone.
2026-05-06 20:17:09 +02:00
Arkadiusz Fal
fac297e4d6 Cache and prewarm Invidious proxy auto-detection
The proxy auto-detect path (when proxiesVideos is off) HEADed a
googlevideo URL with a 5 s timeout on every video. The verdict is a
property of the network, not the video, so the cost was paid for no
reason on videos 2..N. On a network where the CDN is blocked the full
5 s timeout was added to playback startup every single time.

Two changes:

1) ProxyDetectionCache (actor, per-instance, 10 min TTL). First miss
   pays the HEAD once and caches the verdict; subsequent videos hit
   the cache synchronously. Concurrent callers share one in-flight
   probe. The last-seen sample CDN URL is retained so future probes
   don't need a fresh URL from the current video.

2) PlayerService kicks off InvidiousAPI.prewarmProxyDetection() in
   parallel with the videoWith... API call. By the time streams come
   back, the verdict is usually already cached and proxyStreamsIfNeeded
   is a sync lookup. Cheap when there's nothing to prewarm.

Cache invalidation:
- on InstancesManager.update (URL change, proxy toggle flip)
- on InstancesManager.remove
- TTL covers the network-change case for now (no NWPathMonitor yet)
2026-05-04 08:04:55 +02:00
Arkadiusz Fal
93240b4314 Wire Yattee Server playback through /proxy/relay when proxiesVideos is on
The Sources -> Edit Source -> Proxy toggle now renders for Yattee
Server entries (supportsVideoProxying gains .yatteeServer). When the
toggle is on, playback fetches go through
videoWithProxyStreamsAndCaptionsAndStoryboards with mode .relay, so
the server returns signed /proxy/relay URLs (byte-relay, supports
HTTP Range, no on-disk caching). Downloads keep going through mode
.download so the server-side /proxy/fast/ flow continues to cache
files for repeat use.

InvidiousAPI.proxyStreamsIfNeeded early-returns for .yatteeServer
since proxying is now done at fetch time via ?proxy=true rather than
client-side host rewriting.
2026-05-04 08:01:51 +02:00
Arkadiusz Fal
73e3d8164b Keep macOS play pause control visible 2026-04-24 01:14:13 +02:00
Arkadiusz Fal
8d85749354 Show playlist title in macOS toolbar 2026-04-24 00:28:31 +02:00
Arkadiusz Fal
3b9144cd28 Fix macOS sidebar dynamic item switching 2026-04-23 23:19:39 +02:00
Arkadiusz Fal
85223894ff Improve macOS channel toolbar header 2026-04-23 23:10:37 +02:00
Arkadiusz Fal
6df80c0e79 Use user-selected accent color in Home, Subscriptions, and Downloads
Color.accentColor and .foregroundStyle(.tint) resolve to the asset
catalog accent on macOS, so Home shortcut cards, section header
links, the Subscriptions "All channels" header, and the Downloads
per-channel group headers stayed blue when the user picked a
different accent. Read the color from SettingsManager and apply it
directly, matching the pattern already used for the Play button.
2026-04-23 22:55:48 +02:00
Arkadiusz Fal
fd0eab7784 Prefetch fresh video thumbnail before swapping it into info view 2026-04-23 18:37:19 +02:00
Arkadiusz Fal
6eb215f59c fixup! Restore Settings as sidebar item on macOS 2026-04-23 18:26:21 +02:00
Arkadiusz Fal
664eeadba2 Stabilize Nuke cache key across rotating thumbnail URL tokens 2026-04-23 18:22:03 +02:00
Arkadiusz Fal
20b88a811e Use user-selected accent color for Play button tint on macOS 2026-04-23 18:07:58 +02:00
Arkadiusz Fal
a32582e171 Replace macOS video nav arrows with left/right keyboard shortcuts 2026-04-23 18:06:47 +02:00
Arkadiusz Fal
cda983651e Restore Settings as sidebar item on macOS
Remove the gear toolbar button that opened Settings as a sheet in the
NavigationSplitView sidebar column, and drop the macOS guard hiding
.settings from SidebarMainItem so it can be added to the sidebar and
rendered in the detail column like other items. The dedicated Settings
window (Cmd+,) is unchanged.
2026-04-23 18:00:42 +02:00
Arkadiusz Fal
b23dfde602 Use macOS-native styling and larger text in video info view 2026-04-23 07:58:01 +02:00
Arkadiusz Fal
e0ad43ca0b Move Integrations into main settings section above Advanced
Drop the standalone iOS section for Integrations and inline its row into
the main list right above Advanced Settings. Swap the tvOS sidebar order
so Integrations appears before Advanced as well. macOS was already
correctly ordered via SettingsSection enum declaration.
2026-04-23 07:39:03 +02:00
Arkadiusz Fal
f804cc1521 Rename YouTube Enhancements settings to Integrations
Also swap the icon to puzzlepiece.extension, which better conveys that
this section houses third-party service hookups (SponsorBlock, Return
YouTube Dislike, DeArrow, short-link resolution) rather than being
YouTube-specific.

Hide the Resolve Short Links toggle on tvOS — there's no way to tap
inline description links or reach a system browser there — and tighten
the openInSystemBrowser platform guards so the iOS-only UIApplication
path isn't compiled on tvOS.
2026-04-23 07:34:31 +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
d38b781858 Sparkle is macOS only 2026-04-23 06:19:24 +02:00
Arkadiusz Fal
29900b758d Point Sparkle feed at dl.yattee.stream custom domain
Bake https://dl.yattee.stream/appcast.xml into SUFeedURL and align the
appcast template and Sparkle setup notes so the gh-pages branch (served
under the custom Cloudflare-CNAMEd domain) is the single place to look
up the feed. Domain is reserved as a generic distribution surface for
Sparkle today and AltStore / other channels later.
2026-04-23 05:50:52 +02:00
Arkadiusz Fal
b5bab10694 Strip Sparkle from App Store (Release) macOS build
Add -Wl,-dead_strip_dylibs to the Release config so the linker drops the
unused Sparkle LC_LOAD_DYLIB, and a Run Script phase that removes the
auto-embedded Sparkle.framework from the app bundle for every config
except Release-DeveloperID. Disable user script sandboxing on the Yattee
target so the rm is permitted. Release-DeveloperID keeps Sparkle linked
and embedded for the notarized Developer ID channel.
2026-04-23 05:32:42 +02:00
Arkadiusz Fal
a2a4691957 Integrate Sparkle auto-updates for macOS Developer ID builds
New Release-DeveloperID configuration gates Sparkle behind a SPARKLE
compile flag so the App Store Release build stays Sparkle-free. Adds
SPUStandardUpdaterController wrapper, Check for Updates menu command,
Advanced Settings section with beta channel toggle, and a Ruby script
plus GitHub Actions job that signs each release and publishes the
appcast to gh-pages for consumption by Sparkle and Homebrew cask.
2026-04-23 04:51:00 +02:00
Arkadiusz Fal
29c67d3276 Show app icon and version at bottom of macOS settings sidebar 2026-04-22 23:09:17 +02:00
Arkadiusz Fal
6e91069ff3 Move Add Source button to toolbar in macOS Sources settings 2026-04-22 22:06:03 +02:00
Arkadiusz Fal
397fc46629 Open Settings in a dedicated resizable macOS window 2026-04-22 21:59:34 +02:00
Arkadiusz Fal
4d45f6870e Render clickable links and timestamps in comment text
Comments now use DescriptionText.attributed so URLs become tappable
and route through the same in-app pipeline as description links, and
timestamp strings seek the player.
2026-04-22 20:53:21 +02:00
Arkadiusz Fal
b54c32edad Route YouTube links tapped in descriptions through in-app playback
Description links to YouTube videos, channels, playlists, and external
video URLs now open in Yattee instead of Safari. When a video is
already playing, tapping a video link surfaces the existing
QueueActionSheet (Play Now / Play Next / Add to Queue) — the sheet is
hosted both at the app root and inside ExpandedPlayerSheet so it
appears above whichever layer is on screen.
2026-04-22 19:00:43 +02:00
Arkadiusz Fal
3afd0bdf78 Add inline Add Source button to Sources settings on macOS 2026-04-21 06:27:31 +02:00
Arkadiusz Fal
111c3d7360 Convert Download settings to macOS-native helpers 2026-04-21 04:15:35 +02:00
Arkadiusz Fal
f873aad9b9 Apply inset list style to Home settings on macOS 2026-04-21 03:40:57 +02:00
Arkadiusz Fal
bdd9f7f489 Tighten Sidebar settings for macOS
Drop the redundant inner NavigationStack on non-tvOS (the outer detail
pane already provides one) and apply .listStyle(.inset) on macOS. Kept
as List to preserve drag-to-reorder for the main navigation section.
2026-04-21 03:37:29 +02:00
Arkadiusz Fal
b275dbd7c0 Polish Log Viewer for macOS
Convert detail and filter sheets to shared helpers, add inline Filter /
Export / Clear buttons next to the search bar (toolbar items weren't
surfacing in the settings detail pane), inline the Reset Filters button
at the bottom of the filter sheet, use a 'Close' text button, and trim
the macOS Share Sheet to just the scrollable log with a Copy button.
2026-04-21 03:31:11 +02:00
Arkadiusz Fal
22b9cb7135 Convert Legacy Data Import to macOS-native helpers 2026-04-21 02:47:08 +02:00
Arkadiusz Fal
7ff889c132 Convert Contributors, Translators, Acknowledgements to macOS-native helpers 2026-04-21 02:41:15 +02:00
Arkadiusz Fal
07a1e0f81d Convert Manage Channel Notifications list to macOS-native helpers 2026-04-21 02:19:33 +02:00
Arkadiusz Fal
79459b8f2e Rework MPV Options for macOS-native look
Convert the main view to shared SettingsFormContainer/Section helpers,
drop the DisclosureGroup in favor of a single always-visible Default
Options section with monospaced trailing values, and redesign the
Add/Edit MPV option sheets on macOS as native dialogs with a Grid
layout, clearer footers, and keyboard-shortcut actions.
2026-04-21 01:12:42 +02:00
Arkadiusz Fal
a5f8bdacfb Convert About and Device Capabilities to macOS-native helpers 2026-04-21 00:55:53 +02:00
Arkadiusz Fal
48963a9e2e Convert Advanced and Developer settings to macOS-native helpers
Extend SettingsFormSection to accept a @ViewBuilder footer for sections
with dynamic multi-line content (last background refresh, orphaned
files status). Move trailing button accessories (size, progress) out of
button labels so buttons size to their content on macOS.
2026-04-21 00:48:30 +02:00
Arkadiusz Fal
72778870e1 Convert iCloud settings to macOS-native helpers
Add FixedIconWidthLabelStyle so sync category labels align when icons
have varying glyph widths.
2026-04-21 00:36:10 +02:00
Arkadiusz Fal
f173dd1c39 Convert YouTube Enhancements settings to macOS-native helpers
Includes SponsorBlock, Return YouTube Dislike, and DeArrow sub-screens.
Extend SettingsNavigationRow with an optional trailing content slot so
rows can show enabled/disabled status next to the chevron.
2026-04-21 00:31:04 +02:00
Arkadiusz Fal
60be0f8b53 Convert Privacy settings to macOS-native helpers 2026-04-20 23:43:19 +02:00
Arkadiusz Fal
c27fb3be34 Convert Notification settings to macOS-native helpers 2026-04-20 23:36:57 +02:00
Arkadiusz Fal
9912327448 Convert Layout & Navigation settings to macOS-native helpers
Add SettingsNavigationRow helper that renders destination-pushing rows
as plain list rows with a trailing chevron on macOS, and drop the top
divider in headerless sections so they don't render a stray rule.
2026-04-20 23:34:43 +02:00
Arkadiusz Fal
bb8fb28998 Convert Appearance settings to macOS-native helpers 2026-04-20 23:21:13 +02:00
Arkadiusz Fal
14b874022b Make Playback and Subtitles settings feel native on macOS
Add shared SettingsFormContainer/SettingsFormSection helpers that mirror
the Sources screen styling (uppercase subheadline headers, divider-
bracketed cards, ScrollView + LazyVStack) on macOS while keeping the
standard Form/Section layout on iOS and tvOS.

Convert PlaybackSettingsView and SubtitlesSettingsView to the new
helpers, wrap the macOS Settings detail pane in a NavigationStack so
NavigationLink pushes (Subtitles Appearance) render in the detail
column, fold the macOS-only Player Mode + Auto-resize player controls
into the Behavior section, and drop the unused queue footer.
2026-04-20 23:01:46 +02:00
Arkadiusz Fal
fef9a07aa9 Set minimum window size on macOS 2026-04-20 22:24:58 +02:00