Xcode 26.2 (the new default on macos-26) hits a SwiftPM race where
binary xcframework downloads fail with "already exists in file system".
Xcode 26.0.1 — the toolchain the last successful release ran against —
resolved the same deps cleanly. Also download the iOS platform if the
runner image only ships the platform bundled with the default Xcode,
and clear SPM cache more broadly rather than only the artifacts dir.
setup-xcode was switching to /Applications/Xcode_26.0.1.app, which on
the macos-26 runner lacks the iOS 26.0 platform SDK. The runner's
default Xcode has it bundled. Matches rewrite/v2.
The DEVELOPER_KEY_CONTENT secret is stored base64-encoded, so fastlane
needs to be told to decode it before parsing. Matches the approach on
rewrite/v2. Removes the openssl-shell-out workaround from the previous
commits, which was solving the wrong problem.
GitHub secrets store multi-line PEMs as a single line with literal "\n"
sequences. Fastlane's app_store_connect_api_key action un-escapes them
via gsub before use; the helper must do the same before writing the
temp file, otherwise openssl sees garbage.
The hosted macOS runner's OpenSSL rejects Apple's PKCS#8 .p8 key via
OpenSSL::PKey::EC.new with "invalid curve name". Shell out to system
openssl to convert the key to SEC1/traditional PEM before handing it
to fastlane's app_store_connect_api_key action.
Ref: fastlane/fastlane#20593
Commit 37c6f6abb added fi/id/ko/nl/sv to knownRegions but never registered
their .strings files, so Xcode never copied them into the app bundle and the
runtime fell back to English even when the scheme forced one of these
languages. Adds the missing PBXFileReference entries and includes them in
the Localizable.strings PBXVariantGroup.
For context, Invidious performs a type check of its configuration during
bootup, and allows the "domain" to be unspecified, in which case the API
and HTML it generates includes path-only URLs. This is valid: in these
cases we should assume that the Host for those URLs is the same as
the Host we used to access the endpoint called.
This commit adds support for servers configured in such a way, by
defaulting the host of thumbnail URLs, to that used for authentication.
Applied ZStack overlay fix to the channel menu in ChannelVideosView
where the channel name, avatar, subscriber count, and view count
would disappear when tapping the menu.
Uses the same pattern:
- Visible static label with channel info stays on screen
- Invisible Menu overlay with .opacity(0) handles interactions
- Prevents text/avatar disappearing and resizing animations
When switching from MPV to AVPlayer, prioritize HLS and stream formats over non-streamable MP4/AVC1 formats to avoid long loading times.
Changes:
- Added isFastLoadingFormat() helper to AVPlayerBackend
- Modified streamByQualityProfile to prefer fast-loading formats for AVPlayer
- Falls back to non-streamable formats only if no fast-loading option exists
- Ensures quick backend switching without waiting for metadata download
Extended the ZStack overlay fix to all iOS navigation header menus
where text labels would disappear when tapping the menu:
- HomeView: "Home" title menu
- PopularView: "Popular" title with icon menu
- TrendingView: Country/flag title menu
- PlaylistsView: Playlist title with thumbnail menu
- ChannelPlaylistView: Playlist title with thumbnail menu
- OpenVideosView: Playback mode picker menu
All menus now use the same pattern as PlaybackSettings:
- Visible static label layer in ZStack
- Invisible Menu overlay with .opacity(0)
- Prevents text disappearing and resizing animations
When tapping menus in playback settings (playback mode, quality profile,
stream, rate, captions, audio track), the selected value text would
disappear and cause unwanted resizing animations.
Implemented ZStack overlay technique for all iOS menu buttons:
- Visible static label remains on screen
- Invisible Menu overlay (.opacity(0)) handles tap interactions
- Prevents text from disappearing when menu opens
- Eliminates resizing animations on option selection
- Add device checks in Orientation enum to prevent locking on iPad
- Hide "Lock portrait mode" setting on iPad in BrowsingSettings
- Use Constants.isIPhone for consistent device detection
AVPlayer has a fundamental limitation with MP4/AVC1 progressive downloads where the moov atom position affects playback start time. When moov is at the end of the file, AVPlayer must download the entire file before starting playback. MPV doesn't have this limitation.
This commit adds an advanced setting to optionally enable these formats in AVPlayer with appropriate warnings:
- Added new setting: "Enable non-streamable formats (MP4/AVC1)"
- Default: disabled (formats hidden, MPV handles them)
- When enabled: MP4/AVC1 formats up to 1080p appear in AVPlayer quality selector
- Resolution limit: 1080p maximum (higher resolutions can't be played properly)
- Clear warning about slow loading and 1080p limitation
- Automatic stream refresh when setting is toggled
- Full import/export support for the setting
Fixes#870 where YouTube share links incorrectly included the port number
from the user's Invidious instance URL (e.g., http://www.youtube.com:3000
instead of http://www.youtube.com).
Added defensive logic to explicitly clear the port when creating share URLs
with frontend URL strings containing "youtube.com". This ensures YouTube
share links always use the standard format without port numbers, regardless
of the user's instance configuration.
The tap-blocking overlay is only needed on iOS to dismiss the context menu
on tap. Removed it from macOS and tvOS where it was either blocking normal
interactions or not functional due to platform limitations.
Removed fixed height constraint from empty state in FavoriteItemView.
Empty sections now collapse to natural height instead of reserving
full content height (290px iOS/600px tvOS), improving space efficiency.
Improved text contrast on overlay buttons by:
- Applying foreground color directly to button labels to ensure proper override
- Using semi-transparent gray background for unfocused buttons instead of Color.secondary
- Removing accent color overrides from caption text to respect button styling
This ensures readable text in both focused (black on white) and unfocused
(white on gray) states.
Changed context menus from press-and-hold to single-press for better UX:
- Quality profile selection
- Stream quality selection
- Captions selection
- Audio track selection
Updated ControlsOverlayButton to support tap actions via new onSelect parameter.
Replaced .contextMenu modifiers with .alert for instant menu access on tvOS.
Removed hint text and unnecessary 80px padding as single-press is self-evident.
The captions context menu on tvOS was always empty because it relied on
an .onAppear callback that was never triggered. The captionsPicker view
with .onAppear was only rendered on iOS/macOS, not tvOS.
Changes:
- Access captions directly from player.currentVideo?.captions instead of
using a state variable populated via .onAppear
- Fix label logic to show "Disabled" when captions are available but not
selected, and "Not available" only when video has no captions
- Remove unused state variables and helper functions
Prefix caption URLs with /companion when invidiousCompanion is enabled in instance settings. This ensures captions are routed through the companion service, matching the behavior of video streams.
In fullscreen playback, swipe-down and timeline seek gestures now respect a 60pt safe zone at the top of the screen, allowing the system notification center gesture to work without triggering app gestures.
Comments at the bottom of the comments view were not accessible on iOS
without entering fullscreen mode. The issue was caused by the VideoDetails
view being offset by the player height when not in fullscreen, but the
ScrollView padding didn't account for this offset.
Changes:
- Add SafeAreaModel observer for iOS platform
- Update bottom padding to dynamically account for player height offset
and safe area insets based on fullscreen state
- When not in fullscreen: padding = player height + safe area bottom + 20
- When in fullscreen: padding = max(60, safe area bottom + 20)
This ensures all comments and video details content are fully scrollable
and visible regardless of fullscreen state.
This adds a new instance setting for Invidious that filters out videos
without duration information from feeds, popular, trending, search results,
and channel pages. This can be used to hide YouTube Shorts.
The setting is labeled as "Experimental: Hide videos without duration" and
includes an explanation that it can be used to hide shorts.
Key changes:
- Added hideVideosWithoutDuration property to Instance model
- Updated InstancesBridge to serialize/deserialize the new setting
- Added UI toggle in InstanceSettings with explanatory footer text
- Implemented filtering in InvidiousAPI for:
* Popular videos
* Trending videos
* Search results
* Subscription feed
* Channel content
- Videos accessed directly by URL are not filtered
Removed auto-focus logic that was causing keyboard show/hide loop
on iPad with docked keyboard. The keyboard was repeatedly dismissing
immediately after appearing due to interaction between keyboard
notifications, focus state changes, and view updates.
Changes:
- Removed focused state and keyboard observer from SearchModel
- Removed iOS textField reference (kept macOS only)
- Removed auto-focus logic from FocusableSearchTextField on iOS
- Cleaned up unused focus-related code
The search field now works reliably when tapped manually on iPad.
Auto-focus still works on macOS where it doesn't cause issues.