From 86e39c444c6e7ffba08b079aeaf5ba1141463750 Mon Sep 17 00:00:00 2001 From: Fredrik Burmester Date: Sun, 31 May 2026 09:37:08 +0200 Subject: [PATCH 1/5] fix(ios): SDK 56 / iOS 26 EAS build fixes (SwiftUICore autolink + patch-package) (#1613) --- bun.lock | 5 ---- package.json | 7 +---- .../react-native-bottom-tabs+1.2.0.patch | 27 +++++++++---------- .../react-native-ios-utilities+5.2.0.patch | 6 ++--- .../react-native-udp+4.1.7.patch | 9 +++---- plugins/with-runtime-framework-headers.js | 22 +++++++++++++++ 6 files changed, 41 insertions(+), 35 deletions(-) rename bun-patches/react-native-bottom-tabs@1.2.0.patch => patches/react-native-bottom-tabs+1.2.0.patch (69%) rename bun-patches/react-native-ios-utilities@5.2.0.patch => patches/react-native-ios-utilities+5.2.0.patch (74%) rename bun-patches/react-native-udp@4.1.7.patch => patches/react-native-udp+4.1.7.patch (62%) diff --git a/bun.lock b/bun.lock index ed6a2e46b..aa50de168 100644 --- a/bun.lock +++ b/bun.lock @@ -114,11 +114,6 @@ }, }, }, - "patchedDependencies": { - "react-native-ios-utilities@5.2.0": "bun-patches/react-native-ios-utilities@5.2.0.patch", - "react-native-udp@4.1.7": "bun-patches/react-native-udp@4.1.7.patch", - "react-native-bottom-tabs@1.2.0": "bun-patches/react-native-bottom-tabs@1.2.0.patch", - }, "packages": { "@adobe/css-tools": ["@adobe/css-tools@4.5.0", "", {}, "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q=="], diff --git a/package.json b/package.json index f7256b9a5..74bcd674d 100644 --- a/package.json +++ b/package.json @@ -162,10 +162,5 @@ }, "trustedDependencies": [ "unrs-resolver" - ], - "patchedDependencies": { - "react-native-udp@4.1.7": "bun-patches/react-native-udp@4.1.7.patch", - "react-native-bottom-tabs@1.2.0": "bun-patches/react-native-bottom-tabs@1.2.0.patch", - "react-native-ios-utilities@5.2.0": "bun-patches/react-native-ios-utilities@5.2.0.patch" - } + ] } diff --git a/bun-patches/react-native-bottom-tabs@1.2.0.patch b/patches/react-native-bottom-tabs+1.2.0.patch similarity index 69% rename from bun-patches/react-native-bottom-tabs@1.2.0.patch rename to patches/react-native-bottom-tabs+1.2.0.patch index 9483b873c..e44815ef3 100644 --- a/bun-patches/react-native-bottom-tabs@1.2.0.patch +++ b/patches/react-native-bottom-tabs+1.2.0.patch @@ -1,10 +1,7 @@ -diff --git a/node_modules/react-native-bottom-tabs/.bun-tag-b32ab1c60a5dfcf7 b/.bun-tag-b32ab1c60a5dfcf7 -new file mode 100644 -index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 -diff --git a/ios/BottomAccessoryProvider.swift b/ios/BottomAccessoryProvider.swift +diff --git a/node_modules/react-native-bottom-tabs/ios/BottomAccessoryProvider.swift b/node_modules/react-native-bottom-tabs/ios/BottomAccessoryProvider.swift index 539efee7156599e1fc795e11bf411b7dfaf12ec7..b2af39a2e6b014e9b1ae0a51b21115c19280df69 100644 ---- a/ios/BottomAccessoryProvider.swift -+++ b/ios/BottomAccessoryProvider.swift +--- a/node_modules/react-native-bottom-tabs/ios/BottomAccessoryProvider.swift ++++ b/node_modules/react-native-bottom-tabs/ios/BottomAccessoryProvider.swift @@ -8,7 +8,7 @@ import SwiftUI self.delegate = delegate } @@ -14,10 +11,10 @@ index 539efee7156599e1fc795e11bf411b7dfaf12ec7..b2af39a2e6b014e9b1ae0a51b21115c1 @available(iOS 26.0, *) public func emitPlacementChanged(_ placement: TabViewBottomAccessoryPlacement?) { var placementValue = "none" -diff --git a/ios/TabView/NewTabView.swift b/ios/TabView/NewTabView.swift +diff --git a/node_modules/react-native-bottom-tabs/ios/TabView/NewTabView.swift b/node_modules/react-native-bottom-tabs/ios/TabView/NewTabView.swift index 22c52cdf25ad0f7398d89197cb431ca8dc8e0f99..81411376e68803de8bd83515d42565cfa95daf2b 100644 ---- a/ios/TabView/NewTabView.swift -+++ b/ios/TabView/NewTabView.swift +--- a/node_modules/react-native-bottom-tabs/ios/TabView/NewTabView.swift ++++ b/node_modules/react-native-bottom-tabs/ios/TabView/NewTabView.swift @@ -78,11 +78,11 @@ struct ConditionalBottomAccessoryModifier: ViewModifier { } @@ -56,10 +53,10 @@ index 22c52cdf25ad0f7398d89197cb431ca8dc8e0f99..81411376e68803de8bd83515d42565cf } #endif + -diff --git a/ios/TabViewImpl.swift b/ios/TabViewImpl.swift +diff --git a/node_modules/react-native-bottom-tabs/ios/TabViewImpl.swift b/node_modules/react-native-bottom-tabs/ios/TabViewImpl.swift index 72938be90540ea3a483d7db9a80fb74c04d31272..277278ffdd9268a96cb09869eb1d0c0d5e6ad300 100644 ---- a/ios/TabViewImpl.swift -+++ b/ios/TabViewImpl.swift +--- a/node_modules/react-native-bottom-tabs/ios/TabViewImpl.swift ++++ b/node_modules/react-native-bottom-tabs/ios/TabViewImpl.swift @@ -281,7 +281,7 @@ extension View { @ViewBuilder @@ -69,10 +66,10 @@ index 72938be90540ea3a483d7db9a80fb74c04d31272..277278ffdd9268a96cb09869eb1d0c0d if #available(iOS 26.0, macOS 26.0, *) { if let behavior { self.tabBarMinimizeBehavior(behavior.convert()) -diff --git a/ios/TabViewProps.swift b/ios/TabViewProps.swift +diff --git a/node_modules/react-native-bottom-tabs/ios/TabViewProps.swift b/node_modules/react-native-bottom-tabs/ios/TabViewProps.swift index 9cfb29a983b34d3f84fc7a678d19ef4ff30e0325..6a5854483e66200b71722bbac12e100742222bd3 100644 ---- a/ios/TabViewProps.swift -+++ b/ios/TabViewProps.swift +--- a/node_modules/react-native-bottom-tabs/ios/TabViewProps.swift ++++ b/node_modules/react-native-bottom-tabs/ios/TabViewProps.swift @@ -6,7 +6,7 @@ internal enum MinimizeBehavior: String { case onScrollUp case onScrollDown diff --git a/bun-patches/react-native-ios-utilities@5.2.0.patch b/patches/react-native-ios-utilities+5.2.0.patch similarity index 74% rename from bun-patches/react-native-ios-utilities@5.2.0.patch rename to patches/react-native-ios-utilities+5.2.0.patch index 4659493ba..4288dfcc3 100644 --- a/bun-patches/react-native-ios-utilities@5.2.0.patch +++ b/patches/react-native-ios-utilities+5.2.0.patch @@ -1,7 +1,7 @@ -diff --git a/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift b/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift +diff --git a/node_modules/react-native-ios-utilities/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift b/node_modules/react-native-ios-utilities/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift index 09be306d5aa39337c5114c2ad6ba7513218e0751..24ff8ee2c36fef8632a7e012514fd04db9bf89fd 100644 ---- a/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift -+++ b/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift +--- a/node_modules/react-native-ios-utilities/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift ++++ b/node_modules/react-native-ios-utilities/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift @@ -25,15 +25,14 @@ public extension RCTView { return rootView.recursivelyFindSubview(whereType: targetType); }; diff --git a/bun-patches/react-native-udp@4.1.7.patch b/patches/react-native-udp+4.1.7.patch similarity index 62% rename from bun-patches/react-native-udp@4.1.7.patch rename to patches/react-native-udp+4.1.7.patch index 823acb86e..656a73aca 100644 --- a/bun-patches/react-native-udp@4.1.7.patch +++ b/patches/react-native-udp+4.1.7.patch @@ -1,10 +1,7 @@ -diff --git a/node_modules/react-native-udp/.bun-tag-ea7df8754aa4db91 b/.bun-tag-ea7df8754aa4db91 -new file mode 100644 -index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 -diff --git a/react-native-udp.podspec b/react-native-udp.podspec +diff --git a/node_modules/react-native-udp/react-native-udp.podspec b/node_modules/react-native-udp/react-native-udp.podspec index 7450cc7d0862aadfb47d796929c801a3dc423a57..fa3e42c0152ef2d87536b8c2e484f64d525e35ec 100644 ---- a/react-native-udp.podspec -+++ b/react-native-udp.podspec +--- a/node_modules/react-native-udp/react-native-udp.podspec ++++ b/node_modules/react-native-udp/react-native-udp.podspec @@ -9,7 +9,8 @@ Pod::Spec.new do |s| s.homepage = package_json["homepage"] s.license = package_json["license"] diff --git a/plugins/with-runtime-framework-headers.js b/plugins/with-runtime-framework-headers.js index 23e7d1011..8405239b8 100644 --- a/plugins/with-runtime-framework-headers.js +++ b/plugins/with-runtime-framework-headers.js @@ -39,6 +39,28 @@ function buildPatch() { " end", " end", "", + " # iOS 26 / Xcode 26: the APP target itself compiles ExpoModulesProvider.swift,", + " # which imports SwiftUI-based modules (ExpoUI, ExpoGlassEffect, GlassPoster, ExpoBlur, …).", + " # That emits a `-framework SwiftUICore` autolink into the app executable's OWN object", + " # files, so the pods-only flag above is not enough — the app's link still fails with", + " # `cannot link directly with 'SwiftUICore'`. Drop the autolink on the user app target", + " # too. Phone-only — tvOS has no SwiftUICore split and must stay untouched.", + " if ENV['EXPO_TV'] != '1'", + " installer.aggregate_targets.each do |agg|", + " next unless agg.user_project", + " agg.user_project.native_targets.each do |target|", + " target.build_configurations.each do |cfg|", + " existing = cfg.build_settings['OTHER_SWIFT_FLAGS'] || '$(inherited)'", + " existing = existing.join(' ') if existing.is_a?(Array)", + " unless existing.include?('-disable-autolink-framework -Xfrontend SwiftUICore')", + " cfg.build_settings['OTHER_SWIFT_FLAGS'] = existing + ' -Xfrontend -disable-autolink-framework -Xfrontend SwiftUICore'", + " end", + " end", + " end", + " agg.user_project.save", + " end", + " end", + "", " # Safely patch RCTThirdPartyComponentsProvider.mm to avoid startup crash on unlinked Fabric components", ' filepath = "#{installer.sandbox.root}/../build/generated/ios/ReactCodegen/RCTThirdPartyComponentsProvider.mm"', " if File.exist?(filepath)", From 692ccfdb2cc18ab1fda0a0a442aa4cfb04b950e3 Mon Sep 17 00:00:00 2001 From: Fredrik Burmester Date: Sun, 31 May 2026 09:42:09 +0200 Subject: [PATCH 2/5] fix(tvos): add arm64 UIRequiredDeviceCapabilities to Top Shelf extension App Store Connect rejected TestFlight submissions because the Top Shelf extension binary has a 64-bit slice but did not declare arm64 under UIRequiredDeviceCapabilities in its Info.plist. --- targets/StreamyfinTopShelf/Info.plist | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/targets/StreamyfinTopShelf/Info.plist b/targets/StreamyfinTopShelf/Info.plist index 184b8d3d4..592d0c719 100644 --- a/targets/StreamyfinTopShelf/Info.plist +++ b/targets/StreamyfinTopShelf/Info.plist @@ -29,6 +29,10 @@ $(MARKETING_VERSION) CFBundleVersion $(CURRENT_PROJECT_VERSION) + UIRequiredDeviceCapabilities + + arm64 + NSExtension NSExtensionPointIdentifier From d585b20f49c052e6536833feb38bfad2ab129d8c Mon Sep 17 00:00:00 2001 From: Fredrik Burmester Date: Sun, 31 May 2026 09:44:05 +0200 Subject: [PATCH 3/5] chore: version --- app.json | 4 ++-- eas.json | 8 ++++---- providers/JellyfinProvider.tsx | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app.json b/app.json index 6dee6c85a..92ca6861f 100644 --- a/app.json +++ b/app.json @@ -2,7 +2,7 @@ "expo": { "name": "Streamyfin", "slug": "streamyfin", - "version": "0.54.0", + "version": "0.54.1", "orientation": "default", "icon": "./assets/images/icon.png", "scheme": "streamyfin", @@ -36,7 +36,7 @@ "appleTeamId": "MWD5K362T8" }, "android": { - "versionCode": 93, + "versionCode": 94, "adaptiveIcon": { "foregroundImage": "./assets/images/icon-android-plain.png", "monochromeImage": "./assets/images/icon-android-themed.png", diff --git a/eas.json b/eas.json index 03f933895..3c125b629 100644 --- a/eas.json +++ b/eas.json @@ -52,14 +52,14 @@ }, "production": { "environment": "production", - "channel": "0.54.0", + "channel": "0.54.1", "android": { "image": "latest" } }, "production-apk": { "environment": "production", - "channel": "0.54.0", + "channel": "0.54.1", "android": { "buildType": "apk", "image": "latest" @@ -67,7 +67,7 @@ }, "production-apk-tv": { "environment": "production", - "channel": "0.54.0", + "channel": "0.54.1", "android": { "buildType": "apk", "image": "latest" @@ -78,7 +78,7 @@ }, "production_tv": { "environment": "production", - "channel": "0.54.0", + "channel": "0.54.1", "env": { "EXPO_TV": "1" }, diff --git a/providers/JellyfinProvider.tsx b/providers/JellyfinProvider.tsx index 7dff4b366..e6f9853ae 100644 --- a/providers/JellyfinProvider.tsx +++ b/providers/JellyfinProvider.tsx @@ -53,7 +53,7 @@ const initialApi = (() => { const id = getOrSetDeviceId(); const deviceName = getDeviceNameSync(); const jellyfinInstance = new Jellyfin({ - clientInfo: { name: "Streamyfin", version: "0.54.0" }, + clientInfo: { name: "Streamyfin", version: "0.54.1" }, deviceInfo: { name: deviceName, id, @@ -128,7 +128,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({ const id = getOrSetDeviceId(); const deviceName = getDeviceNameSync(); return new Jellyfin({ - clientInfo: { name: "Streamyfin", version: "0.54.0" }, + clientInfo: { name: "Streamyfin", version: "0.54.1" }, deviceInfo: { name: deviceName, id, @@ -162,7 +162,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({ return { authorization: `MediaBrowser Client="Streamyfin", Device=${ Platform.OS === "android" ? "Android" : "iOS" - }, DeviceId="${deviceId}", Version="0.54.0"`, + }, DeviceId="${deviceId}", Version="0.54.1"`, }; }, [deviceId]); From 6b6bfd1a893677eb2e4ea4e0471fb13d37983373 Mon Sep 17 00:00:00 2001 From: Fredrik Burmester Date: Sun, 31 May 2026 10:48:24 +0200 Subject: [PATCH 4/5] fix(player): remove white blob artifacts on vertical sliders --- components/video-player/controls/AudioSlider.tsx | 4 ++-- components/video-player/controls/BrightnessSlider.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/video-player/controls/AudioSlider.tsx b/components/video-player/controls/AudioSlider.tsx index 9f70fbba9..31c90483c 100644 --- a/components/video-player/controls/AudioSlider.tsx +++ b/components/video-player/controls/AudioSlider.tsx @@ -105,14 +105,14 @@ const AudioSlider: React.FC = ({ setVisibility }) => { maximumValue={max} thumbWidth={0} onValueChange={handleValueChange} + renderBubble={() => null} + renderThumb={() => null} containerStyle={{ borderRadius: 50, }} theme={{ minimumTrackTintColor: "#FDFDFD", maximumTrackTintColor: "#5A5A5A", - bubbleBackgroundColor: "transparent", // Hide the value bubble - bubbleTextColor: "transparent", // Hide the value text }} /> { maximumValue={max} thumbWidth={0} onValueChange={handleValueChange} + renderBubble={() => null} + renderThumb={() => null} containerStyle={{ borderRadius: 50, }} theme={{ minimumTrackTintColor: "#FDFDFD", maximumTrackTintColor: "#5A5A5A", - bubbleBackgroundColor: "transparent", // Hide the value bubble - bubbleTextColor: "transparent", // Hide the value text }} /> Date: Sun, 31 May 2026 10:50:06 +0200 Subject: [PATCH 5/5] fix(android): resolve mpv-player Kotlin smart-cast build error (#1614) --- .../src/main/java/expo/modules/mpvplayer/MPVLayerRenderer.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/mpv-player/android/src/main/java/expo/modules/mpvplayer/MPVLayerRenderer.kt b/modules/mpv-player/android/src/main/java/expo/modules/mpvplayer/MPVLayerRenderer.kt index 753bfb28f..8b6808fdb 100644 --- a/modules/mpv-player/android/src/main/java/expo/modules/mpvplayer/MPVLayerRenderer.kt +++ b/modules/mpv-player/android/src/main/java/expo/modules/mpvplayer/MPVLayerRenderer.kt @@ -715,9 +715,7 @@ class MPVLayerRenderer(private val context: Context) : MPVLib.EventObserver { // dropped), so we (re)apply here for embedded and external alike. // This is what makes a carried-over subtitle show up on the next // episode without a manual re-selection. - if (initialAudioId != null && initialAudioId > 0) { - setAudioTrack(initialAudioId) - } + initialAudioId?.let { if (it > 0) setAudioTrack(it) } initialSubtitleId?.let { setSubtitleTrack(it) } ?: disableSubtitles() if (!isReadyToSeek) {