mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-23 11:07:44 +00:00
update trailer extraction
This commit is contained in:
parent
fb0805324d
commit
8f371215e9
16 changed files with 2886 additions and 692 deletions
10
app.json
10
app.json
|
|
@ -33,7 +33,15 @@
|
|||
"audio"
|
||||
],
|
||||
"LSSupportsOpeningDocumentsInPlace": true,
|
||||
"UIFileSharingEnabled": true
|
||||
"UIFileSharingEnabled": true,
|
||||
"LSApplicationQueriesSchemes": [
|
||||
"vlc",
|
||||
"vlc-x-callback",
|
||||
"infuse",
|
||||
"outplayer",
|
||||
"open-vidhub",
|
||||
"livecontainer"
|
||||
]
|
||||
},
|
||||
"bundleIdentifier": "com.nuvio.hub",
|
||||
"associatedDomains": [],
|
||||
|
|
|
|||
|
|
@ -7,5 +7,7 @@
|
|||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.widgetkit-extension</string>
|
||||
</dict>
|
||||
<key>RCTNewArchEnabled</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -7,147 +7,77 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0FFC28FB1FEA74CCFA112268 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 49055D6E250FAFA21141FE49 /* PrivacyInfo.xcprivacy */; };
|
||||
0512F937B36046F581AF6A55 /* View+applyIfPresent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65BDE00720574797863FA748 /* View+applyIfPresent.swift */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
2AA769395C1242F225F875AF /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E007C0BAC8C453623E81663 /* ExpoModulesProvider.swift */; };
|
||||
24FC08E856045AC6A95D753A /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 495FF0F91AFAF8A860B9D485 /* PrivacyInfo.xcprivacy */; };
|
||||
357A8847EA6B42B792A617D4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 348452A2DFC344C2BC70A974 /* Assets.xcassets */; };
|
||||
3A4B91216E8D486E9000CD6C /* Date+toTimerInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A20BAB83F6E40D880665E14 /* Date+toTimerInterval.swift */; };
|
||||
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
|
||||
730F1CDE2F24B27100EF7E51 /* Color+hex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8034143A77A946B5A793F967 /* Color+hex.swift */; };
|
||||
730F1CDF2F24B27100EF7E51 /* Date+toTimerInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A48D8A298DD48928E8D0A02 /* Date+toTimerInterval.swift */; };
|
||||
730F1CE02F24B27100EF7E51 /* Image+dynamic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26957CDD392E4E9390811D0D /* Image+dynamic.swift */; };
|
||||
730F1CE12F24B27100EF7E51 /* LiveActivityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F448294A36E433E924078C1 /* LiveActivityView.swift */; };
|
||||
730F1CE22F24B27100EF7E51 /* LiveActivityWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD48662BB71E4C9C9E340289 /* LiveActivityWidget.swift */; };
|
||||
730F1CE32F24B27100EF7E51 /* LiveActivityWidgetBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83D742B36224176A0AB3B25 /* LiveActivityWidgetBundle.swift */; };
|
||||
730F1CE42F24B27100EF7E51 /* View+applyIfPresent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 324373F393774A9CA40DE22E /* View+applyIfPresent.swift */; };
|
||||
730F1CE52F24B27100EF7E51 /* View+applyWidgetURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373D1473F5A74CBC9DBD108B /* View+applyWidgetURL.swift */; };
|
||||
730F1CE62F24B27100EF7E51 /* ViewHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3396D68881EF486E99FD480A /* ViewHelpers.swift */; };
|
||||
730F1CE72F24B27100EF7E51 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0F1D0037D1F24E60BDB57628 /* Assets.xcassets */; };
|
||||
9FBA88F42E86ECD700892850 /* KSPlayerViewManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FBA88F32E86ECD700892850 /* KSPlayerViewManager.swift */; };
|
||||
9FBA88F52E86ECD700892850 /* KSPlayerModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FBA88F12E86ECD700892850 /* KSPlayerModule.swift */; };
|
||||
9FBA88F62E86ECD700892850 /* KSPlayerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FBA88F02E86ECD700892850 /* KSPlayerManager.m */; };
|
||||
9FBA88F72E86ECD700892850 /* KSPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FBA88F22E86ECD700892850 /* KSPlayerView.swift */; };
|
||||
A0892AA96024D9EF7CA87A8A /* libPods-Nuvio.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 349BFD3B214640DED8541999 /* libPods-Nuvio.a */; };
|
||||
4F1568831D134295A56C0263 /* LiveActivityWidgetBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B775F1944CB4E2EB043DB23 /* LiveActivityWidgetBundle.swift */; };
|
||||
7069406A1E324608A86CC6C9 /* ViewHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D296491CC4F4406182E2A2BC /* ViewHelpers.swift */; };
|
||||
94F843501BFD40C384CBB500 /* View+applyWidgetURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AC8A8984F4495492E13EFD /* View+applyWidgetURL.swift */; };
|
||||
9BE191900481495083B7ECC1 /* Color+hex.swift in Sources */ = {isa = PBXBuildFile; fileRef = B36264437D84461BBC2BB706 /* Color+hex.swift */; };
|
||||
B3BB1BBDA8C742DC9A32EACF /* Image+dynamic.swift in Sources */ = {isa = PBXBuildFile; fileRef = F03926C841844CC38C468345 /* Image+dynamic.swift */; };
|
||||
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
|
||||
BD4FE0C298E078EA08432C75 /* libPods-Nuvio.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7206543A5AAE2788326BFBC7 /* libPods-Nuvio.a */; };
|
||||
D102CD3E3CCC4B83AC0F4DBE /* LiveActivityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3182DD61A7C04BD383DBB4B0 /* LiveActivityView.swift */; };
|
||||
DEB0D346CF964886AD06A268 /* LiveActivityWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C77B925A48A4711B3B59C6A /* LiveActivityWidget.swift */; };
|
||||
F11748422D0307B40044C1D9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11748412D0307B40044C1D9 /* AppDelegate.swift */; };
|
||||
F285A1620F5847BA863124AF /* LiveActivity.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = EF8716173E0148BD82B233B7 /* LiveActivity.appex */; };
|
||||
797799D4F9144A9E8D2AB90D /* LiveActivity.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 49DDF70A2BBD4320BBD94B1B /* LiveActivity.appex */; };
|
||||
F1924CDEBB5847D8A1AFD925 /* LiveActivity.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 37E2BF6107484CD098F81560 /* LiveActivity.appex */; };
|
||||
F4B2944DA5D06650F3B40F2A /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9B2F28305B8518622853186 /* ExpoModulesProvider.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
55A0DD628D7F4F4F88B4A001 /* PBXContainerItemProxy */ = {
|
||||
DBC6C07FF91444EEAB5F4C66 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 0EA489F2BF6143F1BA7B8485;
|
||||
remoteInfo = LiveActivity;
|
||||
};
|
||||
7A41A1F529994F0C8801F1A5 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = EFB756D21A05453EA489278C;
|
||||
remoteGlobalIDString = BB0FA6CBF7FD404994DB1E52;
|
||||
remoteInfo = LiveActivity;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
13CD9594FB5C4FE4A6794089 /* Embed Foundation Extensions */ = {
|
||||
8773BA7C99F44506A4A25842 /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
797799D4F9144A9E8D2AB90D /* LiveActivity.appex in Embed Foundation Extensions */,
|
||||
F1924CDEBB5847D8A1AFD925 /* LiveActivity.appex in Embed Foundation Extensions */,
|
||||
);
|
||||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
3447F08B99D9427E99FEE18E /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
F285A1620F5847BA863124AF /* LiveActivity.appex in Embed Foundation Extensions */,
|
||||
);
|
||||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
571AD3FB23F14FC7BE6A1E44 /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
);
|
||||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
BDCAC5D772944755921F3BCF /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
);
|
||||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F1058FE7710A45FABC0689A7 /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
);
|
||||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
CC1B793274FE428D8531E950 /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
name = "Embed Foundation Extensions";
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0DFF64A670930CED5EA4DF3A /* Pods-Nuvio.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Nuvio.release.xcconfig"; path = "Target Support Files/Pods-Nuvio/Pods-Nuvio.release.xcconfig"; sourceTree = "<group>"; };
|
||||
0E13CE4BDE2F4555806AE753 /* Info.plist */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
0F1D0037D1F24E60BDB57628 /* Assets.xcassets */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
0E5AC167979645D9ADB47923 /* LiveActivity.entitlements */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = LiveActivity.entitlements; path = LiveActivity.entitlements; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* Nuvio.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Nuvio.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Nuvio/Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Nuvio/Info.plist; sourceTree = "<group>"; };
|
||||
26957CDD392E4E9390811D0D /* Image+dynamic.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; path = "Image+dynamic.swift"; sourceTree = "<group>"; };
|
||||
2DE29A8A87D24662BEFFF849 /* LiveActivity.entitlements */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; path = LiveActivity.entitlements; sourceTree = "<group>"; };
|
||||
2F448294A36E433E924078C1 /* LiveActivityView.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; path = LiveActivityView.swift; sourceTree = "<group>"; };
|
||||
324373F393774A9CA40DE22E /* View+applyIfPresent.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; path = "View+applyIfPresent.swift"; sourceTree = "<group>"; };
|
||||
3396D68881EF486E99FD480A /* ViewHelpers.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; path = ViewHelpers.swift; sourceTree = "<group>"; };
|
||||
349BFD3B214640DED8541999 /* libPods-Nuvio.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Nuvio.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
373D1473F5A74CBC9DBD108B /* View+applyWidgetURL.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; path = "View+applyWidgetURL.swift"; sourceTree = "<group>"; };
|
||||
3A48D8A298DD48928E8D0A02 /* Date+toTimerInterval.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; path = "Date+toTimerInterval.swift"; sourceTree = "<group>"; };
|
||||
49055D6E250FAFA21141FE49 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = Nuvio/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
6E007C0BAC8C453623E81663 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-Nuvio/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
||||
730F1CE82F24B29C00EF7E51 /* LiveActivityDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LiveActivityDebug.entitlements; sourceTree = "<group>"; };
|
||||
73BB213C2E9EEAC700EC03F8 /* NuvioRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = NuvioRelease.entitlements; path = Nuvio/NuvioRelease.entitlements; sourceTree = "<group>"; };
|
||||
8034143A77A946B5A793F967 /* Color+hex.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; path = "Color+hex.swift"; sourceTree = "<group>"; };
|
||||
9FBA88F02E86ECD700892850 /* KSPlayerManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ../KSPlayer/RNBridge/KSPlayerManager.m; sourceTree = "<group>"; };
|
||||
9FBA88F12E86ECD700892850 /* KSPlayerModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ../KSPlayer/RNBridge/KSPlayerModule.swift; sourceTree = "<group>"; };
|
||||
9FBA88F22E86ECD700892850 /* KSPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ../KSPlayer/RNBridge/KSPlayerView.swift; sourceTree = "<group>"; };
|
||||
9FBA88F32E86ECD700892850 /* KSPlayerViewManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ../KSPlayer/RNBridge/KSPlayerViewManager.swift; sourceTree = "<group>"; };
|
||||
A83D742B36224176A0AB3B25 /* LiveActivityWidgetBundle.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; path = LiveActivityWidgetBundle.swift; sourceTree = "<group>"; };
|
||||
1B775F1944CB4E2EB043DB23 /* LiveActivityWidgetBundle.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = LiveActivityWidgetBundle.swift; path = LiveActivityWidgetBundle.swift; sourceTree = "<group>"; };
|
||||
3182DD61A7C04BD383DBB4B0 /* LiveActivityView.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = LiveActivityView.swift; path = LiveActivityView.swift; sourceTree = "<group>"; };
|
||||
348452A2DFC344C2BC70A974 /* Assets.xcassets */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
37E2BF6107484CD098F81560 /* LiveActivity.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = undefined; name = LiveActivity.appex; path = LiveActivity.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3A20BAB83F6E40D880665E14 /* Date+toTimerInterval.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "Date+toTimerInterval.swift"; path = "Date+toTimerInterval.swift"; sourceTree = "<group>"; };
|
||||
44393AD0ABDBAED5B40D2E49 /* Pods-Nuvio.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Nuvio.release.xcconfig"; path = "Target Support Files/Pods-Nuvio/Pods-Nuvio.release.xcconfig"; sourceTree = "<group>"; };
|
||||
495FF0F91AFAF8A860B9D485 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = Nuvio/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
65BDE00720574797863FA748 /* View+applyIfPresent.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "View+applyIfPresent.swift"; path = "View+applyIfPresent.swift"; sourceTree = "<group>"; };
|
||||
7206543A5AAE2788326BFBC7 /* libPods-Nuvio.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Nuvio.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
7EC866223BB0FA7280D468BF /* Pods-Nuvio.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Nuvio.debug.xcconfig"; path = "Target Support Files/Pods-Nuvio/Pods-Nuvio.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
9C77B925A48A4711B3B59C6A /* LiveActivityWidget.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = LiveActivityWidget.swift; path = LiveActivityWidget.swift; sourceTree = "<group>"; };
|
||||
A0AC8A8984F4495492E13EFD /* View+applyWidgetURL.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "View+applyWidgetURL.swift"; path = "View+applyWidgetURL.swift"; sourceTree = "<group>"; };
|
||||
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = Nuvio/SplashScreen.storyboard; sourceTree = "<group>"; };
|
||||
AD48662BB71E4C9C9E340289 /* LiveActivityWidget.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; path = LiveActivityWidget.swift; sourceTree = "<group>"; };
|
||||
B36264437D84461BBC2BB706 /* Color+hex.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "Color+hex.swift"; path = "Color+hex.swift"; sourceTree = "<group>"; };
|
||||
B9B2F28305B8518622853186 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-Nuvio/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
||||
BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; };
|
||||
DAD634845937EAF8D64F20FC /* Pods-Nuvio.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Nuvio.debug.xcconfig"; path = "Target Support Files/Pods-Nuvio/Pods-Nuvio.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
D296491CC4F4406182E2A2BC /* ViewHelpers.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = ViewHelpers.swift; path = ViewHelpers.swift; sourceTree = "<group>"; };
|
||||
E93B94AE2F7240878D655B2F /* Info.plist */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = text.plist.xml; name = Info.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
EF8716173E0148BD82B233B7 /* LiveActivity.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; fileEncoding = 9; includeInIndex = 0; path = LiveActivity.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F03926C841844CC38C468345 /* Image+dynamic.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "Image+dynamic.swift"; path = "Image+dynamic.swift"; sourceTree = "<group>"; };
|
||||
F11748412D0307B40044C1D9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = Nuvio/AppDelegate.swift; sourceTree = "<group>"; };
|
||||
F11748442D0722820044C1D9 /* Nuvio-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "Nuvio-Bridging-Header.h"; path = "Nuvio/Nuvio-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
49DDF70A2BBD4320BBD94B1B /* LiveActivity.appex */ = {isa = PBXFileReference; name = "LiveActivity.appex"; path = "LiveActivity.appex"; sourceTree = BUILT_PRODUCTS_DIR; fileEncoding = undefined; lastKnownFileType = undefined; explicitFileType = wrapper.app-extension; includeInIndex = 0; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -155,18 +85,11 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A0892AA96024D9EF7CA87A8A /* libPods-Nuvio.a in Frameworks */,
|
||||
BD4FE0C298E078EA08432C75 /* libPods-Nuvio.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C105694FF46449959CE16947 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
A2537B59C29048BFB082D5F3 /* Embed Foundation Extensions */ = {
|
||||
2341847DAC4A41A89AA0DED2 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
|
@ -179,18 +102,13 @@
|
|||
13B07FAE1A68108700A75B9A /* Nuvio */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
73BB213C2E9EEAC700EC03F8 /* NuvioRelease.entitlements */,
|
||||
F11748412D0307B40044C1D9 /* AppDelegate.swift */,
|
||||
F11748442D0722820044C1D9 /* Nuvio-Bridging-Header.h */,
|
||||
9FBA88F02E86ECD700892850 /* KSPlayerManager.m */,
|
||||
9FBA88F12E86ECD700892850 /* KSPlayerModule.swift */,
|
||||
9FBA88F22E86ECD700892850 /* KSPlayerView.swift */,
|
||||
9FBA88F32E86ECD700892850 /* KSPlayerViewManager.swift */,
|
||||
BB2F792B24A3F905000567C9 /* Supporting */,
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */,
|
||||
49055D6E250FAFA21141FE49 /* PrivacyInfo.xcprivacy */,
|
||||
495FF0F91AFAF8A860B9D485 /* PrivacyInfo.xcprivacy */,
|
||||
);
|
||||
name = Nuvio;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -199,23 +117,28 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||
349BFD3B214640DED8541999 /* libPods-Nuvio.a */,
|
||||
7206543A5AAE2788326BFBC7 /* libPods-Nuvio.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
358C5C99C443A921C8EEDDC8 /* ExpoModulesProviders */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ECB31D9B6FF08C7E8E875650 /* Nuvio */,
|
||||
);
|
||||
name = ExpoModulesProviders;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
62B088ADB2A740DAB9E343F9 /* LiveActivity */ = {
|
||||
6BFD9CA52F844119ABE664C4 /* LiveActivity */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B36264437D84461BBC2BB706 /* Color+hex.swift */,
|
||||
3A20BAB83F6E40D880665E14 /* Date+toTimerInterval.swift */,
|
||||
F03926C841844CC38C468345 /* Image+dynamic.swift */,
|
||||
3182DD61A7C04BD383DBB4B0 /* LiveActivityView.swift */,
|
||||
9C77B925A48A4711B3B59C6A /* LiveActivityWidget.swift */,
|
||||
1B775F1944CB4E2EB043DB23 /* LiveActivityWidgetBundle.swift */,
|
||||
65BDE00720574797863FA748 /* View+applyIfPresent.swift */,
|
||||
A0AC8A8984F4495492E13EFD /* View+applyWidgetURL.swift */,
|
||||
D296491CC4F4406182E2A2BC /* ViewHelpers.swift */,
|
||||
E93B94AE2F7240878D655B2F /* Info.plist */,
|
||||
348452A2DFC344C2BC70A974 /* Assets.xcassets */,
|
||||
0E5AC167979645D9ADB47923 /* LiveActivity.entitlements */,
|
||||
);
|
||||
name = LiveActivity;
|
||||
path = LiveActivity;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
|
@ -233,14 +156,9 @@
|
|||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
||||
D90A3959C97EE9926C513293 /* Pods */,
|
||||
358C5C99C443A921C8EEDDC8 /* ExpoModulesProviders */,
|
||||
E8C72B3DF7DB40A8896F56C9 /* LiveActivity */,
|
||||
62B088ADB2A740DAB9E343F9 /* LiveActivity */,
|
||||
B9F3EB198DED443D980ADFB3 /* LiveActivity */,
|
||||
C05E525650E143FB85ED7622 /* LiveActivity */,
|
||||
D05210A39FF14E649D77F8A8 /* LiveActivity */,
|
||||
2EAF711C6AB246A0A253E404 /* LiveActivity */,
|
||||
6BFD9CA52F844119ABE664C4 /* LiveActivity */,
|
||||
94DA158AE0BA28C86D2B8468 /* Pods */,
|
||||
FD98B8AFFD47909E52F111EF /* ExpoModulesProviders */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -251,17 +169,19 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* Nuvio.app */,
|
||||
EF8716173E0148BD82B233B7 /* LiveActivity.appex */,
|
||||
49DDF70A2BBD4320BBD94B1B /* LiveActivity.appex */,
|
||||
37E2BF6107484CD098F81560 /* LiveActivity.appex */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B9F3EB198DED443D980ADFB3 /* LiveActivity */ = {
|
||||
94DA158AE0BA28C86D2B8468 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7EC866223BB0FA7280D468BF /* Pods-Nuvio.debug.xcconfig */,
|
||||
44393AD0ABDBAED5B40D2E49 /* Pods-Nuvio.release.xcconfig */,
|
||||
);
|
||||
path = LiveActivity;
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BB2F792B24A3F905000567C9 /* Supporting */ = {
|
||||
|
|
@ -273,144 +193,66 @@
|
|||
path = Nuvio/Supporting;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C05E525650E143FB85ED7622 /* LiveActivity */ = {
|
||||
E3DA69DC92F44258CBB5D7D2 /* Nuvio */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
path = LiveActivity;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D05210A39FF14E649D77F8A8 /* LiveActivity */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8034143A77A946B5A793F967 /* Color+hex.swift */,
|
||||
3A48D8A298DD48928E8D0A02 /* Date+toTimerInterval.swift */,
|
||||
26957CDD392E4E9390811D0D /* Image+dynamic.swift */,
|
||||
2F448294A36E433E924078C1 /* LiveActivityView.swift */,
|
||||
AD48662BB71E4C9C9E340289 /* LiveActivityWidget.swift */,
|
||||
A83D742B36224176A0AB3B25 /* LiveActivityWidgetBundle.swift */,
|
||||
324373F393774A9CA40DE22E /* View+applyIfPresent.swift */,
|
||||
373D1473F5A74CBC9DBD108B /* View+applyWidgetURL.swift */,
|
||||
3396D68881EF486E99FD480A /* ViewHelpers.swift */,
|
||||
0E13CE4BDE2F4555806AE753 /* Info.plist */,
|
||||
0F1D0037D1F24E60BDB57628 /* Assets.xcassets */,
|
||||
2DE29A8A87D24662BEFFF849 /* LiveActivity.entitlements */,
|
||||
);
|
||||
path = LiveActivity;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D90A3959C97EE9926C513293 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAD634845937EAF8D64F20FC /* Pods-Nuvio.debug.xcconfig */,
|
||||
0DFF64A670930CED5EA4DF3A /* Pods-Nuvio.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E8C72B3DF7DB40A8896F56C9 /* LiveActivity */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
730F1CE82F24B29C00EF7E51 /* LiveActivityDebug.entitlements */,
|
||||
);
|
||||
path = LiveActivity;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
ECB31D9B6FF08C7E8E875650 /* Nuvio */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6E007C0BAC8C453623E81663 /* ExpoModulesProvider.swift */,
|
||||
B9B2F28305B8518622853186 /* ExpoModulesProvider.swift */,
|
||||
);
|
||||
name = Nuvio;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2EAF711C6AB246A0A253E404 /* LiveActivity */ = {
|
||||
FD98B8AFFD47909E52F111EF /* ExpoModulesProviders */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8034143A77A946B5A793F967 /* Color+hex.swift */,
|
||||
3A48D8A298DD48928E8D0A02 /* Date+toTimerInterval.swift */,
|
||||
26957CDD392E4E9390811D0D /* Image+dynamic.swift */,
|
||||
2F448294A36E433E924078C1 /* LiveActivityView.swift */,
|
||||
AD48662BB71E4C9C9E340289 /* LiveActivityWidget.swift */,
|
||||
A83D742B36224176A0AB3B25 /* LiveActivityWidgetBundle.swift */,
|
||||
324373F393774A9CA40DE22E /* View+applyIfPresent.swift */,
|
||||
373D1473F5A74CBC9DBD108B /* View+applyWidgetURL.swift */,
|
||||
3396D68881EF486E99FD480A /* ViewHelpers.swift */,
|
||||
0E13CE4BDE2F4555806AE753 /* Info.plist */,
|
||||
0F1D0037D1F24E60BDB57628 /* Assets.xcassets */,
|
||||
2DE29A8A87D24662BEFFF849 /* LiveActivity.entitlements */,
|
||||
E3DA69DC92F44258CBB5D7D2 /* Nuvio */,
|
||||
);
|
||||
name = LiveActivity;
|
||||
path = LiveActivity;
|
||||
name = ExpoModulesProviders;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
0EA489F2BF6143F1BA7B8485 /* LiveActivity */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C95083D445BA485B82D2FFBC /* Build configuration list for PBXNativeTarget "LiveActivity" */;
|
||||
buildPhases = (
|
||||
6E9A0429F8E74948A82DEFF5 /* Sources */,
|
||||
C105694FF46449959CE16947 /* Frameworks */,
|
||||
1E668E0B92C34E73AECDBE1A /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = LiveActivity;
|
||||
productName = LiveActivity;
|
||||
productReference = EF8716173E0148BD82B233B7 /* LiveActivity.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
13B07F861A680F5B00A75B9A /* Nuvio */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Nuvio" */;
|
||||
buildPhases = (
|
||||
13C7A3175A582B3D4E9F198E /* [CP] Check Pods Manifest.lock */,
|
||||
99A79B70155E84EE1FB7F466 /* [Expo] Configure project */,
|
||||
08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */,
|
||||
B67FC995125067F91F480913 /* [Expo] Configure project */,
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
9B977D89FE30470F8C59964C /* Upload Debug Symbols to Sentry */,
|
||||
E043D7E00F2210228303FC0B /* [CP] Embed Pods Frameworks */,
|
||||
7F1DFB9D902E2DBC35F3FB84 /* [CP] Copy Pods Resources */,
|
||||
3447F08B99D9427E99FEE18E /* Embed Foundation Extensions */,
|
||||
BDCAC5D772944755921F3BCF /* Embed Foundation Extensions */,
|
||||
571AD3FB23F14FC7BE6A1E44 /* Embed Foundation Extensions */,
|
||||
13CD9594FB5C4FE4A6794089 /* Embed Foundation Extensions */,
|
||||
F1058FE7710A45FABC0689A7 /* Embed Foundation Extensions */,
|
||||
CC1B793274FE428D8531E950 /* Embed Foundation Extensions */,
|
||||
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */,
|
||||
7D1788E2D4EF42D9BD43136D /* Upload Debug Symbols to Sentry */,
|
||||
8773BA7C99F44506A4A25842 /* Embed Foundation Extensions */,
|
||||
0014ED4AAB03BFF76DF3B778 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
8410CAE82E604DD1A187EDA2 /* PBXTargetDependency */,
|
||||
523C5D7CB8E740A5A0BF4322 /* PBXTargetDependency */,
|
||||
65AA2578A3174CBBAFE7AF11 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Nuvio;
|
||||
productName = Nuvio;
|
||||
productReference = 13B07F961A680F5B00A75B9A /* Nuvio.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
EFB756D21A05453EA489278C /* LiveActivity */ = {
|
||||
BB0FA6CBF7FD404994DB1E52 /* LiveActivity */ = {
|
||||
isa = PBXNativeTarget;
|
||||
name = LiveActivity;
|
||||
productName = LiveActivity;
|
||||
productReference = 49DDF70A2BBD4320BBD94B1B;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
buildConfigurationList = F11E3E24512A427FB847D2F6;
|
||||
buildConfigurationList = 4D277DDAFD8E470E87E3A678 /* Build configuration list for PBXNativeTarget "LiveActivity" */;
|
||||
buildPhases = (
|
||||
784E2472974841CD88391F31 /* Embed Foundation Extensions */,
|
||||
A2537B59C29048BFB082D5F3 /* Embed Foundation Extensions */,
|
||||
B06A5B524C284D9FAFC33F3C /* Embed Foundation Extensions */,
|
||||
547FCD1068DD43D2B6E1582A /* Sources */,
|
||||
2341847DAC4A41A89AA0DED2 /* Frameworks */,
|
||||
466E6B41B3D44B44941DC4FF /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = LiveActivity;
|
||||
productName = LiveActivity;
|
||||
productReference = 37E2BF6107484CD098F81560 /* LiveActivity.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
|
|
@ -420,18 +262,15 @@
|
|||
attributes = {
|
||||
LastUpgradeCheck = 1130;
|
||||
TargetAttributes = {
|
||||
0EA489F2BF6143F1BA7B8485 = {
|
||||
DevelopmentTeam = 8QBDZ766S3;
|
||||
LastSwiftMigration = 1250;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
13B07F861A680F5B00A75B9A = {
|
||||
DevelopmentTeam = 8QBDZ766S3;
|
||||
LastSwiftMigration = 1250;
|
||||
DevelopmentTeam = "8QBDZ766S3";
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
EFB756D21A05453EA489278C = {
|
||||
BB0FA6CBF7FD404994DB1E52 = {
|
||||
LastSwiftMigration = 1250;
|
||||
DevelopmentTeam = "8QBDZ766S3";
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -449,8 +288,7 @@
|
|||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* Nuvio */,
|
||||
0EA489F2BF6143F1BA7B8485 /* LiveActivity */,
|
||||
EFB756D21A05453EA489278C /* LiveActivity */,
|
||||
BB0FA6CBF7FD404994DB1E52 /* LiveActivity */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
|
@ -463,29 +301,43 @@
|
|||
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */,
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */,
|
||||
0FFC28FB1FEA74CCFA112268 /* PrivacyInfo.xcprivacy in Resources */,
|
||||
24FC08E856045AC6A95D753A /* PrivacyInfo.xcprivacy in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
1E668E0B92C34E73AECDBE1A /* Resources */ = {
|
||||
466E6B41B3D44B44941DC4FF /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
730F1CE72F24B27100EF7E51 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B06A5B524C284D9FAFC33F3C /* Embed Foundation Extensions */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
730F1CE72F24B27100EF7E51 /* Assets.xcassets in Resources */,
|
||||
357A8847EA6B42B792A617D4 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
0014ED4AAB03BFF76DF3B778 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Nuvio/Pods-Nuvio-frameworks.sh",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/React-Core-prebuilt/React.framework/React",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/ReactNativeDependencies/ReactNativeDependencies.framework/ReactNativeDependencies",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactNativeDependencies.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Nuvio/Pods-Nuvio-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
|
|
@ -503,7 +355,7 @@
|
|||
shellPath = /bin/sh;
|
||||
shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n# Source .xcode.env.updates if it exists to allow\n# SKIP_BUNDLING to be unset if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.updates\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.updates\"\nfi\n# Source local changes to allow overrides\n# if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n/bin/sh `\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode.sh'\"` `\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n\n";
|
||||
};
|
||||
13C7A3175A582B3D4E9F198E /* [CP] Check Pods Manifest.lock */ = {
|
||||
08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
|
@ -525,7 +377,21 @@
|
|||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
7F1DFB9D902E2DBC35F3FB84 /* [CP] Copy Pods Resources */ = {
|
||||
7D1788E2D4EF42D9BD43136D /* Upload Debug Symbols to Sentry */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Upload Debug Symbols to Sentry";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh `${NODE_BINARY:-node} --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode-debug-files.sh'\"`";
|
||||
};
|
||||
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
|
@ -637,7 +503,7 @@
|
|||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Nuvio/Pods-Nuvio-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
99A79B70155E84EE1FB7F466 /* [Expo] Configure project */ = {
|
||||
B67FC995125067F91F480913 /* [Expo] Configure project */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -661,42 +527,6 @@
|
|||
shellPath = /bin/sh;
|
||||
shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-Nuvio/expo-configure-project.sh\"\n";
|
||||
};
|
||||
9B977D89FE30470F8C59964C /* Upload Debug Symbols to Sentry */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Upload Debug Symbols to Sentry";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh `${NODE_BINARY:-node} --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode-debug-files.sh'\"`";
|
||||
};
|
||||
E043D7E00F2210228303FC0B /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Nuvio/Pods-Nuvio-frameworks.sh",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/React-Core-prebuilt/React.framework/React",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/ReactNativeDependencies/ReactNativeDependencies.framework/ReactNativeDependencies",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactNativeDependencies.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Nuvio/Pods-Nuvio-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
|
|
@ -705,73 +535,46 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F11748422D0307B40044C1D9 /* AppDelegate.swift in Sources */,
|
||||
9FBA88F42E86ECD700892850 /* KSPlayerViewManager.swift in Sources */,
|
||||
9FBA88F52E86ECD700892850 /* KSPlayerModule.swift in Sources */,
|
||||
9FBA88F62E86ECD700892850 /* KSPlayerManager.m in Sources */,
|
||||
9FBA88F72E86ECD700892850 /* KSPlayerView.swift in Sources */,
|
||||
2AA769395C1242F225F875AF /* ExpoModulesProvider.swift in Sources */,
|
||||
F4B2944DA5D06650F3B40F2A /* ExpoModulesProvider.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6E9A0429F8E74948A82DEFF5 /* Sources */ = {
|
||||
547FCD1068DD43D2B6E1582A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
730F1CDE2F24B27100EF7E51 /* Color+hex.swift in Sources */,
|
||||
730F1CDF2F24B27100EF7E51 /* Date+toTimerInterval.swift in Sources */,
|
||||
730F1CE02F24B27100EF7E51 /* Image+dynamic.swift in Sources */,
|
||||
730F1CE12F24B27100EF7E51 /* LiveActivityView.swift in Sources */,
|
||||
730F1CE22F24B27100EF7E51 /* LiveActivityWidget.swift in Sources */,
|
||||
730F1CE32F24B27100EF7E51 /* LiveActivityWidgetBundle.swift in Sources */,
|
||||
730F1CE42F24B27100EF7E51 /* View+applyIfPresent.swift in Sources */,
|
||||
730F1CE52F24B27100EF7E51 /* View+applyWidgetURL.swift in Sources */,
|
||||
730F1CE62F24B27100EF7E51 /* ViewHelpers.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
784E2472974841CD88391F31 /* Embed Foundation Extensions */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
730F1CDE2F24B27100EF7E51 /* "Color+hex.swift" in Sources */,
|
||||
730F1CDF2F24B27100EF7E51 /* "Date+toTimerInterval.swift" in Sources */,
|
||||
730F1CE02F24B27100EF7E51 /* "Image+dynamic.swift" in Sources */,
|
||||
730F1CE12F24B27100EF7E51 /* LiveActivityView.swift in Sources */,
|
||||
730F1CE22F24B27100EF7E51 /* LiveActivityWidget.swift in Sources */,
|
||||
730F1CE32F24B27100EF7E51 /* LiveActivityWidgetBundle.swift in Sources */,
|
||||
730F1CE42F24B27100EF7E51 /* "View+applyIfPresent.swift" in Sources */,
|
||||
730F1CE52F24B27100EF7E51 /* "View+applyWidgetURL.swift" in Sources */,
|
||||
730F1CE62F24B27100EF7E51 /* ViewHelpers.swift in Sources */,
|
||||
9BE191900481495083B7ECC1 /* Color+hex.swift in Sources */,
|
||||
3A4B91216E8D486E9000CD6C /* Date+toTimerInterval.swift in Sources */,
|
||||
B3BB1BBDA8C742DC9A32EACF /* Image+dynamic.swift in Sources */,
|
||||
D102CD3E3CCC4B83AC0F4DBE /* LiveActivityView.swift in Sources */,
|
||||
DEB0D346CF964886AD06A268 /* LiveActivityWidget.swift in Sources */,
|
||||
4F1568831D134295A56C0263 /* LiveActivityWidgetBundle.swift in Sources */,
|
||||
0512F937B36046F581AF6A55 /* View+applyIfPresent.swift in Sources */,
|
||||
94F843501BFD40C384CBB500 /* View+applyWidgetURL.swift in Sources */,
|
||||
7069406A1E324608A86CC6C9 /* ViewHelpers.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
8410CAE82E604DD1A187EDA2 /* PBXTargetDependency */ = {
|
||||
65AA2578A3174CBBAFE7AF11 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 0EA489F2BF6143F1BA7B8485 /* LiveActivity */;
|
||||
targetProxy = 55A0DD628D7F4F4F88B4A001 /* PBXContainerItemProxy */;
|
||||
};
|
||||
523C5D7CB8E740A5A0BF4322 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = EFB756D21A05453EA489278C /* LiveActivity */;
|
||||
targetProxy = 7A41A1F529994F0C8801F1A5 /* PBXContainerItemProxy */;
|
||||
target = BB0FA6CBF7FD404994DB1E52 /* LiveActivity */;
|
||||
targetProxy = DBC6C07FF91444EEAB5F4C66 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = DAD634845937EAF8D64F20FC /* Pods-Nuvio.debug.xcconfig */;
|
||||
baseConfigurationReference = 7EC866223BB0FA7280D468BF /* Pods-Nuvio.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Nuvio/Nuvio.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = 8QBDZ766S3;
|
||||
DEVELOPMENT_TEAM = "8QBDZ766S3";
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
|
|
@ -791,27 +594,26 @@
|
|||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nuvio.hub;
|
||||
PRODUCT_NAME = "Nuvio";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
PRODUCT_NAME = Nuvio;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Nuvio/Nuvio-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 0DFF64A670930CED5EA4DF3A /* Pods-Nuvio.release.xcconfig */;
|
||||
baseConfigurationReference = 44393AD0ABDBAED5B40D2E49 /* Pods-Nuvio.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Nuvio/NuvioRelease.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CODE_SIGN_ENTITLEMENTS = Nuvio/Nuvio.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = 8QBDZ766S3;
|
||||
DEVELOPMENT_TEAM = "8QBDZ766S3";
|
||||
INFOPLIST_FILE = Nuvio/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
|
@ -826,38 +628,15 @@
|
|||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nuvio.hub;
|
||||
PRODUCT_NAME = "Nuvio";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
PRODUCT_NAME = Nuvio;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Nuvio/Nuvio-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
3DCEA1FBF99E46F58A7150CC /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = LiveActivity/LiveActivity.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 34;
|
||||
DEVELOPMENT_TEAM = 8QBDZ766S3;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = LiveActivity/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = LiveActivity;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.2;
|
||||
MARKETING_VERSION = 1.3.6;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nuvio.hub.LiveActivity;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
name = Release;
|
||||
};
|
||||
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
|
|
@ -977,70 +756,54 @@
|
|||
};
|
||||
name = Release;
|
||||
};
|
||||
E4108F64486C48E192EAA45D /* Release */ = {
|
||||
935F73C6BA4D42D1A1F36953 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = LiveActivity/LiveActivity.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 34;
|
||||
DEVELOPMENT_TEAM = 8QBDZ766S3;
|
||||
CURRENT_PROJECT_VERSION = 37;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = LiveActivity/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = LiveActivity;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.2;
|
||||
MARKETING_VERSION = 1.3.6;
|
||||
MARKETING_VERSION = 1.4.1;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nuvio.hub.LiveActivity;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
DEVELOPMENT_TEAM = "8QBDZ766S3";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DE24FDCA00464F85805C3A58 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = LiveActivity/LiveActivity.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 37;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = LiveActivity/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = LiveActivity;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.2;
|
||||
MARKETING_VERSION = 1.4.1;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nuvio.hub.LiveActivity;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
DEVELOPMENT_TEAM = "8QBDZ766S3";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
B062D46778AF40DE92953986 /* Debug */ = {
|
||||
name = Debug;
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
INFOPLIST_FILE = LiveActivity/Info.plist;
|
||||
CURRENT_PROJECT_VERSION = "37";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = "16.2";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.nuvio.hub.LiveActivity";
|
||||
GENERATE_INFOPLIST_FILE = "YES";
|
||||
INFOPLIST_KEY_CFBundleDisplayName = LiveActivity;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
MARKETING_VERSION = "1.4.1";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
CODE_SIGN_ENTITLEMENTS = "LiveActivity/LiveActivity.entitlements";
|
||||
APPLICATION_EXTENSION_API_ONLY = "YES";
|
||||
};
|
||||
};
|
||||
67617475B4F443CBBCE1A6FD /* Release */ = {
|
||||
name = Release;
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
INFOPLIST_FILE = LiveActivity/Info.plist;
|
||||
CURRENT_PROJECT_VERSION = "37";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = "16.2";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.nuvio.hub.LiveActivity";
|
||||
GENERATE_INFOPLIST_FILE = "YES";
|
||||
INFOPLIST_KEY_CFBundleDisplayName = LiveActivity;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
MARKETING_VERSION = "1.4.1";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
CODE_SIGN_ENTITLEMENTS = "LiveActivity/LiveActivity.entitlements";
|
||||
APPLICATION_EXTENSION_API_ONLY = "YES";
|
||||
};
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
|
|
@ -1053,6 +816,15 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
4D277DDAFD8E470E87E3A678 /* Build configuration list for PBXNativeTarget "LiveActivity" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
935F73C6BA4D42D1A1F36953 /* Debug */,
|
||||
DE24FDCA00464F85805C3A58 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Nuvio" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
@ -1062,24 +834,6 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C95083D445BA485B82D2FFBC /* Build configuration list for PBXNativeTarget "LiveActivity" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
3DCEA1FBF99E46F58A7150CC /* Debug */,
|
||||
E4108F64486C48E192EAA45D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F11E3E24512A427FB847D2F6 /* Build configuration list for PBXNativeTarget "LiveActivity" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
B062D46778AF40DE92953986 /* Debug */,
|
||||
67617475B4F443CBBCE1A6FD /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,15 @@
|
|||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>37</string>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>vlc</string>
|
||||
<string>vlc-x-callback</string>
|
||||
<string>infuse</string>
|
||||
<string>outplayer</string>
|
||||
<string>open-vidhub</string>
|
||||
<string>livecontainer</string>
|
||||
</array>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>12.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
|
|
|
|||
234
ios/Podfile.lock
234
ios/Podfile.lock
|
|
@ -4,14 +4,14 @@ PODS:
|
|||
- ExpoModulesCore
|
||||
- EXApplication (7.0.8):
|
||||
- ExpoModulesCore
|
||||
- EXConstants (18.0.12):
|
||||
- EXConstants (18.0.13):
|
||||
- ExpoModulesCore
|
||||
- EXJSONUtils (0.15.0)
|
||||
- EXManifests (1.0.10):
|
||||
- ExpoModulesCore
|
||||
- EXNotifications (0.32.15):
|
||||
- EXNotifications (0.32.16):
|
||||
- ExpoModulesCore
|
||||
- Expo (54.0.29):
|
||||
- Expo (54.0.33):
|
||||
- ExpoModulesCore
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
|
|
@ -207,7 +207,7 @@ PODS:
|
|||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- ExpoAsset (12.0.11):
|
||||
- ExpoAsset (12.0.12):
|
||||
- ExpoModulesCore
|
||||
- ExpoBlur (15.0.8):
|
||||
- ExpoModulesCore
|
||||
|
|
@ -223,9 +223,9 @@ PODS:
|
|||
- ExpoModulesCore
|
||||
- ExpoFileSystem (19.0.21):
|
||||
- ExpoModulesCore
|
||||
- ExpoFont (14.0.10):
|
||||
- ExpoFont (14.0.11):
|
||||
- ExpoModulesCore
|
||||
- ExpoGlassEffect (0.1.8):
|
||||
- ExpoGlassEffect (0.1.9):
|
||||
- ExpoModulesCore
|
||||
- ExpoHaptics (15.0.8):
|
||||
- ExpoModulesCore
|
||||
|
|
@ -233,7 +233,7 @@ PODS:
|
|||
- ExpoModulesCore
|
||||
- ExpoLinearGradient (15.0.8):
|
||||
- ExpoModulesCore
|
||||
- ExpoLinking (8.0.10):
|
||||
- ExpoLinking (8.0.11):
|
||||
- ExpoModulesCore
|
||||
- ExpoLiveActivity (0.4.2):
|
||||
- ExpoModulesCore
|
||||
|
|
@ -294,7 +294,7 @@ PODS:
|
|||
- ExpoWebBrowser (15.0.10):
|
||||
- ExpoModulesCore
|
||||
- EXStructuredHeaders (5.0.0)
|
||||
- EXUpdates (29.0.15):
|
||||
- EXUpdates (29.0.16):
|
||||
- EASClient
|
||||
- EXManifests
|
||||
- ExpoModulesCore
|
||||
|
|
@ -333,8 +333,9 @@ PODS:
|
|||
- hermes-engine (0.81.4):
|
||||
- hermes-engine/Pre-built (= 0.81.4)
|
||||
- hermes-engine/Pre-built (0.81.4)
|
||||
- ImageColors (2.5.1):
|
||||
- ImageColors (2.6.0):
|
||||
- ExpoModulesCore
|
||||
- SwiftDraw (~> 0.27)
|
||||
- KSPlayer (1.1.0):
|
||||
- KSPlayer/Audio (= 1.1.0)
|
||||
- KSPlayer/AVPlayer (= 1.1.0)
|
||||
|
|
@ -382,10 +383,10 @@ PODS:
|
|||
- libwebp/sharpyuv (1.5.0)
|
||||
- libwebp/webp (1.5.0):
|
||||
- libwebp/sharpyuv
|
||||
- lottie-ios (4.5.0)
|
||||
- lottie-react-native (7.3.4):
|
||||
- lottie-ios (4.6.0)
|
||||
- lottie-react-native (7.3.6):
|
||||
- hermes-engine
|
||||
- lottie-ios (= 4.5.0)
|
||||
- lottie-ios (= 4.6.0)
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
|
|
@ -406,12 +407,12 @@ PODS:
|
|||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- MMKV (2.2.4):
|
||||
- MMKVCore (~> 2.2.4)
|
||||
- MMKVCore (2.2.4)
|
||||
- NitroMmkv (4.1.0):
|
||||
- MMKV (2.3.0):
|
||||
- MMKVCore (~> 2.3.0)
|
||||
- MMKVCore (2.3.0)
|
||||
- NitroMmkv (4.2.0):
|
||||
- hermes-engine
|
||||
- MMKVCore (= 2.2.4)
|
||||
- MMKVCore (= 2.3.0)
|
||||
- NitroModules
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -434,7 +435,7 @@ PODS:
|
|||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- NitroModules (0.31.10):
|
||||
- NitroModules (0.35.0):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -1738,7 +1739,7 @@ PODS:
|
|||
- React-RCTFBReactNativeSpec
|
||||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- react-native-background-downloader (4.4.5):
|
||||
- react-native-background-downloader (4.5.3):
|
||||
- hermes-engine
|
||||
- MMKV
|
||||
- RCTRequired
|
||||
|
|
@ -1858,33 +1859,7 @@ PODS:
|
|||
- google-cast-sdk
|
||||
- PromisesObjC
|
||||
- React
|
||||
- react-native-netinfo (11.4.1):
|
||||
- React-Core
|
||||
- react-native-safe-area-context (5.6.2):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- React-Core-prebuilt
|
||||
- React-debug
|
||||
- React-Fabric
|
||||
- React-featureflags
|
||||
- React-graphics
|
||||
- React-ImageManager
|
||||
- React-jsi
|
||||
- react-native-safe-area-context/common (= 5.6.2)
|
||||
- react-native-safe-area-context/fabric (= 5.6.2)
|
||||
- React-NativeModulesApple
|
||||
- React-RCTFabric
|
||||
- React-renderercss
|
||||
- React-rendererdebug
|
||||
- React-utils
|
||||
- ReactCodegen
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- react-native-safe-area-context/common (5.6.2):
|
||||
- react-native-netinfo (12.0.1):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -1906,7 +1881,53 @@ PODS:
|
|||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- react-native-safe-area-context/fabric (5.6.2):
|
||||
- react-native-safe-area-context (5.7.0):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- React-Core-prebuilt
|
||||
- React-debug
|
||||
- React-Fabric
|
||||
- React-featureflags
|
||||
- React-graphics
|
||||
- React-ImageManager
|
||||
- React-jsi
|
||||
- react-native-safe-area-context/common (= 5.7.0)
|
||||
- react-native-safe-area-context/fabric (= 5.7.0)
|
||||
- React-NativeModulesApple
|
||||
- React-RCTFabric
|
||||
- React-renderercss
|
||||
- React-rendererdebug
|
||||
- React-utils
|
||||
- ReactCodegen
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- react-native-safe-area-context/common (5.7.0):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- React-Core-prebuilt
|
||||
- React-debug
|
||||
- React-Fabric
|
||||
- React-featureflags
|
||||
- React-graphics
|
||||
- React-ImageManager
|
||||
- React-jsi
|
||||
- React-NativeModulesApple
|
||||
- React-RCTFabric
|
||||
- React-renderercss
|
||||
- React-rendererdebug
|
||||
- React-utils
|
||||
- ReactCodegen
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- react-native-safe-area-context/fabric (5.7.0):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -1929,7 +1950,7 @@ PODS:
|
|||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- react-native-skia (2.4.14):
|
||||
- react-native-skia (2.5.1):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -1953,7 +1974,7 @@ PODS:
|
|||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- react-native-slider (5.1.1):
|
||||
- react-native-slider (5.1.2):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -1965,7 +1986,7 @@ PODS:
|
|||
- React-graphics
|
||||
- React-ImageManager
|
||||
- React-jsi
|
||||
- react-native-slider/common (= 5.1.1)
|
||||
- react-native-slider/common (= 5.1.2)
|
||||
- React-NativeModulesApple
|
||||
- React-RCTFabric
|
||||
- React-renderercss
|
||||
|
|
@ -1976,7 +1997,7 @@ PODS:
|
|||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- react-native-slider/common (5.1.1):
|
||||
- react-native-slider/common (5.1.2):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -2466,7 +2487,7 @@ PODS:
|
|||
- SDWebImageSVGCoder (~> 1.7.0)
|
||||
- SDWebImageWebPCoder (~> 0.14)
|
||||
- Yoga
|
||||
- RNGestureHandler (2.29.1):
|
||||
- RNGestureHandler (2.30.0):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -2488,7 +2509,7 @@ PODS:
|
|||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- RNReanimated (4.2.0):
|
||||
- RNReanimated (4.2.2):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -2510,10 +2531,10 @@ PODS:
|
|||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- RNReanimated/reanimated (= 4.2.0)
|
||||
- RNReanimated/reanimated (= 4.2.2)
|
||||
- RNWorklets
|
||||
- Yoga
|
||||
- RNReanimated/reanimated (4.2.0):
|
||||
- RNReanimated/reanimated (4.2.2):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -2535,10 +2556,10 @@ PODS:
|
|||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- RNReanimated/reanimated/apple (= 4.2.0)
|
||||
- RNReanimated/reanimated/apple (= 4.2.2)
|
||||
- RNWorklets
|
||||
- Yoga
|
||||
- RNReanimated/reanimated/apple (4.2.0):
|
||||
- RNReanimated/reanimated/apple (4.2.2):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -2562,7 +2583,7 @@ PODS:
|
|||
- ReactNativeDependencies
|
||||
- RNWorklets
|
||||
- Yoga
|
||||
- RNScreens (4.18.0):
|
||||
- RNScreens (4.24.0):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -2584,9 +2605,9 @@ PODS:
|
|||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- RNScreens/common (= 4.18.0)
|
||||
- RNScreens/common (= 4.24.0)
|
||||
- Yoga
|
||||
- RNScreens/common (4.18.0):
|
||||
- RNScreens/common (4.24.0):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -2609,7 +2630,7 @@ PODS:
|
|||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- RNSentry (7.7.0):
|
||||
- RNSentry (8.4.0):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -2631,9 +2652,9 @@ PODS:
|
|||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Sentry/HybridSDK (= 8.57.3)
|
||||
- Sentry (= 9.7.0)
|
||||
- Yoga
|
||||
- RNSVG (15.15.1):
|
||||
- RNSVG (15.15.3):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -2654,9 +2675,9 @@ PODS:
|
|||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- RNSVG/common (= 15.15.1)
|
||||
- RNSVG/common (= 15.15.3)
|
||||
- Yoga
|
||||
- RNSVG/common (15.15.1):
|
||||
- RNSVG/common (15.15.3):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -2700,7 +2721,7 @@ PODS:
|
|||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- RNWorklets (0.7.1):
|
||||
- RNWorklets (0.7.4):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -2722,9 +2743,9 @@ PODS:
|
|||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- RNWorklets/worklets (= 0.7.1)
|
||||
- RNWorklets/worklets (= 0.7.4)
|
||||
- Yoga
|
||||
- RNWorklets/worklets (0.7.1):
|
||||
- RNWorklets/worklets (0.7.4):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -2746,9 +2767,9 @@ PODS:
|
|||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- RNWorklets/worklets/apple (= 0.7.1)
|
||||
- RNWorklets/worklets/apple (= 0.7.4)
|
||||
- Yoga
|
||||
- RNWorklets/worklets/apple (0.7.1):
|
||||
- RNWorklets/worklets/apple (0.7.4):
|
||||
- hermes-engine
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
|
@ -2771,9 +2792,9 @@ PODS:
|
|||
- ReactCommon/turbomodule/core
|
||||
- ReactNativeDependencies
|
||||
- Yoga
|
||||
- SDWebImage (5.21.5):
|
||||
- SDWebImage/Core (= 5.21.5)
|
||||
- SDWebImage/Core (5.21.5)
|
||||
- SDWebImage (5.21.7):
|
||||
- SDWebImage/Core (= 5.21.7)
|
||||
- SDWebImage/Core (5.21.7)
|
||||
- SDWebImageAVIFCoder (0.11.1):
|
||||
- libavif/core (>= 0.11.0)
|
||||
- SDWebImage (~> 5.10)
|
||||
|
|
@ -2782,7 +2803,12 @@ PODS:
|
|||
- SDWebImageWebPCoder (0.15.0):
|
||||
- libwebp (~> 1.0)
|
||||
- SDWebImage/Core (~> 5.17)
|
||||
- Sentry/HybridSDK (8.57.3)
|
||||
- Sentry (9.7.0):
|
||||
- Sentry/Core (= 9.7.0)
|
||||
- Sentry/Core (9.7.0)
|
||||
- SwiftDraw (0.27.0):
|
||||
- SwiftDrawDOM (~> 0.27.0)
|
||||
- SwiftDrawDOM (0.27.0)
|
||||
- SwiftUIIntrospect (1.3.0)
|
||||
- Yoga (0.0.0)
|
||||
|
||||
|
|
@ -2936,6 +2962,8 @@ SPEC REPOS:
|
|||
- SDWebImageSVGCoder
|
||||
- SDWebImageWebPCoder
|
||||
- Sentry
|
||||
- SwiftDraw
|
||||
- SwiftDrawDOM
|
||||
- SwiftUIIntrospect
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
|
|
@ -3217,16 +3245,16 @@ SPEC CHECKSUMS:
|
|||
DisplayCriteria: bb0a90faf14b30848bc50ac0516340ce50164187
|
||||
EASClient: 40dd9e740684782610c49becab2643782ea1a20c
|
||||
EXApplication: 1e98d4b1dccdf30627f92917f4b2c5a53c330e5f
|
||||
EXConstants: 805f35b1b295c542ca6acce836f21a1f9ee104d5
|
||||
EXConstants: fce59a631a06c4151602843667f7cfe35f81e271
|
||||
EXJSONUtils: 1d3e4590438c3ee593684186007028a14b3686cd
|
||||
EXManifests: a8d97683e5c7a3b026ffbd58559c64dc655b747b
|
||||
EXNotifications: 983f04ad4ad879b181179e326bf220541e478386
|
||||
Expo: 8fa2204bf8483fe546b4ec87c90d3ca189afc8db
|
||||
EXNotifications: 9eec98712cc814ceff916d876cb53859003b0597
|
||||
Expo: aadbcc8c6c14ff3105a9154f1683cb1424ff0d2a
|
||||
expo-dev-client: 425ee077d6754a98cfe3a2e2410d29b440b24c9d
|
||||
expo-dev-launcher: a4f4cdef064ab1fb8621e5b8c7c457cd6e9568c3
|
||||
expo-dev-menu: 05b18812110c175814c6af0d09dd658abcc5e00d
|
||||
expo-dev-menu-interface: 600df12ea01efecdd822daaf13cc0ac091775533
|
||||
ExpoAsset: 23a958e97d3d340919fe6774db35d563241e6c03
|
||||
ExpoAsset: f867e55ceb428aab99e1e8c082b5aee7c159ea18
|
||||
ExpoBlur: b90747a3f22a8b6ceffd9cb0dc41a4184efdc656
|
||||
ExpoBrightness: 46c980463e8a54b9ce77f923c4bff0bb0c9526e0
|
||||
ExpoClipboard: b36b287d8356887844bb08ed5c84b5979bb4dd1e
|
||||
|
|
@ -3234,12 +3262,12 @@ SPEC CHECKSUMS:
|
|||
ExpoDevice: 6327c3c200816795708885adf540d26ecab83d1a
|
||||
ExpoDocumentPicker: 7cd9e71a0f66fb19eb0a586d6f26eee1284692e0
|
||||
ExpoFileSystem: 858a44267a3e6e9057e0888ad7c7cfbf55d52063
|
||||
ExpoFont: 35ac6191ed86bbf56b3ebd2d9154eda9fad5b509
|
||||
ExpoGlassEffect: 8ce45eca31f12e949e23a4ee13e2bfb59e9b0785
|
||||
ExpoFont: f543ce20a228dd702813668b1a07b46f51878d47
|
||||
ExpoGlassEffect: 93f0665d19063cb3b46bbd0a2ebea4a36b6a4e37
|
||||
ExpoHaptics: d3a6375d8dcc3a1083d003bc2298ff654fafb536
|
||||
ExpoKeepAwake: 55f75eca6499bb9e4231ebad6f3e9cb8f99c0296
|
||||
ExpoLinearGradient: 809102bdb979f590083af49f7fa4805cd931bd58
|
||||
ExpoLinking: f4c4a351523da72a6bfa7e1f4ca92aee1043a3ca
|
||||
ExpoLinking: 8f0aaf69aa56f832913030503b6263dc6f647f37
|
||||
ExpoLiveActivity: d0dd0e8e1460b6b26555b611c4826cdb1036eea2
|
||||
ExpoLocalization: d9168d5300a5b03e5e78b986124d11fb6ec3ebbd
|
||||
ExpoModulesCore: f3da4f1ab5a8375d0beafab763739dbee8446583
|
||||
|
|
@ -3249,24 +3277,24 @@ SPEC CHECKSUMS:
|
|||
ExpoSystemUI: 2ad325f361a2fcd96a464e8574e19935c461c9cc
|
||||
ExpoWebBrowser: 17b064c621789e41d4816c95c93f429b84971f52
|
||||
EXStructuredHeaders: c951e77f2d936f88637421e9588c976da5827368
|
||||
EXUpdates: f20abbc8a9f4e150656fe88126d52f52d4e7793f
|
||||
EXUpdates: f86d4af4362c2c83a7bf8531d777e9fba680e2d9
|
||||
EXUpdatesInterface: 5adf50cb41e079c861da6d9b4b954c3db9a50734
|
||||
FBLazyVector: 9e0cd874afd81d9a4d36679daca991b58b260d42
|
||||
FFmpegKit: 3885085fbbc320745838ee4c8a1f9c5e5953dab2
|
||||
google-cast-sdk: 32f65af50d164e3c475e79ad123db3cc26fbcd37
|
||||
hermes-engine: 35c763d57c9832d0eef764316ca1c4d043581394
|
||||
ImageColors: e12eb73e29bc1feaa3c228db8c174a1b25acb59d
|
||||
ImageColors: 3019b37809023d67795162135628e367d70e1766
|
||||
KSPlayer: f163ac6195f240b6fa5b8225aeb39ec811a70c62
|
||||
Libass: e88af2324e1217e3a4c8bdc675f6f23a9dfc7677
|
||||
libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7
|
||||
libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
|
||||
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
|
||||
lottie-ios: a881093fab623c467d3bce374367755c272bdd59
|
||||
lottie-react-native: cbe3d931a7c24f7891a8e8032c2bb9b2373c4b9c
|
||||
MMKV: 1a8e7dbce7f9cad02c52e1b1091d07bd843aefaf
|
||||
MMKVCore: f2dd4c9befea04277a55e84e7812f930537993df
|
||||
NitroMmkv: 4af10c70043b4c3cded3f16547627c7d9d8e3b8b
|
||||
NitroModules: a71a5ab2911caf79e45170e6e12475b5260a12d0
|
||||
lottie-ios: 8f959969761e9c45d70353667d00af0e5b9cadb3
|
||||
lottie-react-native: 6a080b2f109ef611c75c503a33ebb8ea75db0c91
|
||||
MMKV: c953dbaac0da392c24b005e763c03ce2638b4ed7
|
||||
MMKVCore: d078dce7d6586a888b2c2ef5343b6242678e3ee8
|
||||
NitroMmkv: 38dfb2983c83e9bbbb64423ff48fbeaaa097cc38
|
||||
NitroModules: ff0d24be334de628166b9ac63661c998c732de7d
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
RCTDeprecation: 7487d6dda857ccd4cb3dd6ecfccdc3170e85dcbc
|
||||
RCTRequired: 54128b7df8be566881d48c7234724a78cb9b6157
|
||||
|
|
@ -3302,16 +3330,16 @@ SPEC CHECKSUMS:
|
|||
React-logger: 7b234de35acb469ce76d6bbb0457f664d6f32f62
|
||||
React-Mapbuffer: fbe1da882a187e5898bdf125e1cc6e603d27ecae
|
||||
React-microtasksnativemodule: 76905804171d8ccbe69329fc84c57eb7934add7f
|
||||
react-native-background-downloader: 384c954ba4510de725697f7df4fd75f7c25579a2
|
||||
react-native-background-downloader: 19eb7c5a834bac72f1273ab25325c71c44953c49
|
||||
react-native-blur: 1b00ef07fe0efdc0c40b37139a5268ccad73c72d
|
||||
react-native-bottom-tabs: bcb70e4fae95fc9da0da875f7414acda26dfc551
|
||||
react-native-device-brightness: 1a997350d060c3df9f303b1df84a4f7c5cbeb924
|
||||
react-native-get-random-values: a603782b2b222a34533c66371614790282dba3f1
|
||||
react-native-google-cast: 7be68a5d0b7eeb95a5924c3ecef8d319ef6c0a44
|
||||
react-native-netinfo: cec9c4e86083cb5b6aba0e0711f563e2fbbff187
|
||||
react-native-safe-area-context: 37e680fc4cace3c0030ee46e8987d24f5d3bdab2
|
||||
react-native-skia: 268f183f849742e9da216743ee234bd7ad81c69b
|
||||
react-native-slider: f954578344106f0a732a4358ce3a3e11015eb6e1
|
||||
react-native-netinfo: 7e0b1936e928fa8ddb60da9e572a33767db7805f
|
||||
react-native-safe-area-context: ae7587b95fb580d1800c5b0b2a7bd48c2868e67a
|
||||
react-native-skia: 6a51463f8391c82f675f490c8078135925285a8f
|
||||
react-native-slider: 8b9a218d1a3e526146a170cb6133be9cda23e70e
|
||||
react-native-video: bca076cfff2a3e749fc63b3ac88118e1d8ee2689
|
||||
React-NativeModulesApple: a9464983ccc0f66f45e93558671f60fc7536e438
|
||||
React-oscompat: 73db7dbc80edef36a9d6ed3c6c4e1724ead4236d
|
||||
|
|
@ -3346,18 +3374,20 @@ SPEC CHECKSUMS:
|
|||
ReactNativeDependencies: ed6d1e64802b150399f04f1d5728ec16b437251e
|
||||
RNCPicker: c8a3584b74133464ee926224463fcc54dfdaebca
|
||||
RNFastImage: 2d36f4cfed9b2342f94f8591c8be69dd047ac67c
|
||||
RNGestureHandler: 723f29dac55e25f109d263ed65cecc4b9c4bd46a
|
||||
RNReanimated: e1c71e6e693a66b203ae98773347b625d3cc85ee
|
||||
RNScreens: 61c18865ab074f4d995ac8d7cf5060522a649d05
|
||||
RNSentry: 1d7b9fdae7a01ad8f9053335b5d44e75c39a955e
|
||||
RNSVG: cf9ae78f2edf2988242c71a6392d15ff7dd62522
|
||||
RNGestureHandler: e0d0bce5599f6120b7adf90c38d2805e2935795f
|
||||
RNReanimated: f4644326ad2bc0f5c0e52f15db316d4f5ee77a60
|
||||
RNScreens: 6cb648bdad8fe9bee9259fe144df95b6d1d5b707
|
||||
RNSentry: 4e9fc32104771fbb20c5f567eb9299fd92ea48b8
|
||||
RNSVG: 7612f5bc575eab5da3364d44abe9f0d5db2cde03
|
||||
RNVectorIcons: 4351544f100d4f12cac156a7c13399e60bab3e26
|
||||
RNWorklets: 9eb6d567fa43984e96b6924a6df504b8a15980cd
|
||||
SDWebImage: e9c98383c7572d713c1a0d7dd2783b10599b9838
|
||||
RNWorklets: eb8d899de8701d58c6a634b8468ce2a6db3113b2
|
||||
SDWebImage: e9fc87c1aab89a8ab1bbd74eba378c6f53be8abf
|
||||
SDWebImageAVIFCoder: afe194a084e851f70228e4be35ef651df0fc5c57
|
||||
SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c
|
||||
SDWebImageWebPCoder: 0e06e365080397465cc73a7a9b472d8a3bd0f377
|
||||
Sentry: c643eb180df401dd8c734c5036ddd9dd9218daa6
|
||||
Sentry: 0fe17abdc98f83a3799c02564382d8b2afabadef
|
||||
SwiftDraw: c3fb77c08081f1255f33bcc0fd3c2e00fbc9bd46
|
||||
SwiftDrawDOM: 8e7d9812af1ef6e06230e72769e97838e6c7c765
|
||||
SwiftUIIntrospect: fee9aa07293ee280373a591e1824e8ddc869ba5d
|
||||
Yoga: 051f086b5ccf465ff2ed38a2cf5a558ae01aaaa1
|
||||
|
||||
|
|
|
|||
|
|
@ -864,8 +864,19 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||
drmSessionManager,
|
||||
runningSource.getCropStartMs(),
|
||||
runningSource.getCropEndMs());
|
||||
MediaSource mediaSourceWithAds = initializeAds(videoSource, runningSource);
|
||||
MediaSource mediaSource = Objects.requireNonNullElse(mediaSourceWithAds, videoSource);
|
||||
MediaSource mergedSource = videoSource;
|
||||
if (runningSource.getAudioUri() != null) {
|
||||
MediaSource audioSource = buildMediaSource(
|
||||
runningSource.getAudioUri(),
|
||||
null,
|
||||
null,
|
||||
-1,
|
||||
-1
|
||||
);
|
||||
mergedSource = new MergingMediaSource(true, videoSource, audioSource);
|
||||
}
|
||||
MediaSource mediaSourceWithAds = initializeAds(mergedSource, runningSource);
|
||||
MediaSource mediaSource = Objects.requireNonNullElse(mediaSourceWithAds, mergedSource);
|
||||
|
||||
// wait for player to be set
|
||||
while (player == null) {
|
||||
|
|
@ -1100,8 +1111,17 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||
}
|
||||
} else if ("file".equals(uri.getScheme()) ||
|
||||
!useCache) {
|
||||
DataSource.Factory progressiveDataSourceFactory = mediaDataSourceFactory;
|
||||
String host = uri.getHost();
|
||||
if (host != null && host.contains("googlevideo.com")) {
|
||||
progressiveDataSourceFactory = DataSourceUtil.buildYoutubeChunkedDataSourceFactory(
|
||||
themedReactContext,
|
||||
bandwidthMeter,
|
||||
source.getHeaders()
|
||||
);
|
||||
}
|
||||
mediaSourceFactory = new ProgressiveMediaSource.Factory(
|
||||
mediaDataSourceFactory
|
||||
progressiveDataSourceFactory
|
||||
);
|
||||
} else {
|
||||
mediaSourceFactory = new ProgressiveMediaSource.Factory(
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
269
scripts/inspect-youtube-formats.mjs
Normal file
269
scripts/inspect-youtube-formats.mjs
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
const DEFAULT_USER_AGENT =
|
||||
'Mozilla/5.0 (Linux; Android 12; Android TV) AppleWebKit/537.36 ' +
|
||||
'(KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36';
|
||||
|
||||
const DEFAULT_HEADERS = {
|
||||
'accept-language': 'en-US,en;q=0.9',
|
||||
'user-agent': DEFAULT_USER_AGENT,
|
||||
};
|
||||
|
||||
const CLIENTS = [
|
||||
{
|
||||
key: 'android_vr',
|
||||
id: '28',
|
||||
version: '1.62.27',
|
||||
userAgent:
|
||||
'com.google.android.apps.youtube.vr.oculus/1.62.27 ' +
|
||||
'(Linux; U; Android 12; en_US; Quest 3; Build/SQ3A.220605.009.A1) gzip',
|
||||
context: {
|
||||
clientName: 'ANDROID_VR',
|
||||
clientVersion: '1.62.27',
|
||||
deviceMake: 'Oculus',
|
||||
deviceModel: 'Quest 3',
|
||||
osName: 'Android',
|
||||
osVersion: '12',
|
||||
platform: 'MOBILE',
|
||||
androidSdkVersion: 32,
|
||||
hl: 'en',
|
||||
gl: 'US',
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'android',
|
||||
id: '3',
|
||||
version: '20.10.38',
|
||||
userAgent:
|
||||
'com.google.android.youtube/20.10.38 (Linux; U; Android 14; en_US) gzip',
|
||||
context: {
|
||||
clientName: 'ANDROID',
|
||||
clientVersion: '20.10.38',
|
||||
osName: 'Android',
|
||||
osVersion: '14',
|
||||
platform: 'MOBILE',
|
||||
androidSdkVersion: 34,
|
||||
hl: 'en',
|
||||
gl: 'US',
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'ios',
|
||||
id: '5',
|
||||
version: '20.10.1',
|
||||
userAgent:
|
||||
'com.google.ios.youtube/20.10.1 (iPhone16,2; U; CPU iOS 17_4 like Mac OS X)',
|
||||
context: {
|
||||
clientName: 'IOS',
|
||||
clientVersion: '20.10.1',
|
||||
deviceModel: 'iPhone16,2',
|
||||
osName: 'iPhone',
|
||||
osVersion: '17.4.0.21E219',
|
||||
platform: 'MOBILE',
|
||||
hl: 'en',
|
||||
gl: 'US',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
function parseVideoId(input) {
|
||||
if (!input) return null;
|
||||
const trimmed = input.trim();
|
||||
if (/^[A-Za-z0-9_-]{11}$/.test(trimmed)) return trimmed;
|
||||
try {
|
||||
const url = new URL(trimmed.startsWith('http') ? trimmed : `https://${trimmed}`);
|
||||
if (url.hostname.endsWith('youtu.be')) {
|
||||
const id = url.pathname.slice(1).split('/')[0];
|
||||
if (/^[A-Za-z0-9_-]{11}$/.test(id)) return id;
|
||||
}
|
||||
const v = url.searchParams.get('v');
|
||||
if (v && /^[A-Za-z0-9_-]{11}$/.test(v)) return v;
|
||||
} catch {}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getMimeBase(mimeType = '') {
|
||||
return mimeType.split(';')[0].trim();
|
||||
}
|
||||
|
||||
function getExt(mimeType = '') {
|
||||
const base = getMimeBase(mimeType);
|
||||
if (base === 'video/mp4' || base === 'audio/mp4') return 'mp4';
|
||||
if (base.includes('webm')) return 'webm';
|
||||
if (base.includes('m4a')) return 'm4a';
|
||||
return 'other';
|
||||
}
|
||||
|
||||
function parseQualityLabel(label = '') {
|
||||
const match = label.match(/(\d{2,4})p/);
|
||||
return match ? Number.parseInt(match[1], 10) : 0;
|
||||
}
|
||||
|
||||
function videoScore(height, fps, bitrate) {
|
||||
return height * 1_000_000_000 + fps * 1_000_000 + bitrate;
|
||||
}
|
||||
|
||||
function audioScore(bitrate, sampleRate) {
|
||||
return bitrate * 1_000_000 + sampleRate;
|
||||
}
|
||||
|
||||
function sortCandidates(items) {
|
||||
return [...items].sort((a, b) => b.score - a.score);
|
||||
}
|
||||
|
||||
function isIosSafeVideo(candidate) {
|
||||
const mimeBase = getMimeBase(candidate.mimeType);
|
||||
return mimeBase === 'video/mp4';
|
||||
}
|
||||
|
||||
function isIosSafeAudio(candidate) {
|
||||
const mimeBase = getMimeBase(candidate.mimeType);
|
||||
return mimeBase === 'audio/mp4' || candidate.ext === 'm4a';
|
||||
}
|
||||
|
||||
async function fetchWatchConfig(videoId) {
|
||||
const response = await fetch(`https://www.youtube.com/watch?v=${videoId}&hl=en`, {
|
||||
headers: DEFAULT_HEADERS,
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`watch page failed: ${response.status}`);
|
||||
}
|
||||
const html = await response.text();
|
||||
return {
|
||||
apiKey: html.match(/"INNERTUBE_API_KEY":"([^"]+)"/)?.[1] ?? null,
|
||||
visitorData: html.match(/"VISITOR_DATA":"([^"]+)"/)?.[1] ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
async function fetchPlayerResponse(videoId, apiKey, visitorData, client) {
|
||||
const endpoint = apiKey
|
||||
? `https://www.youtube.com/youtubei/v1/player?key=${encodeURIComponent(apiKey)}&prettyPrint=false`
|
||||
: `https://www.youtube.com/youtubei/v1/player?prettyPrint=false`;
|
||||
|
||||
const headers = {
|
||||
...DEFAULT_HEADERS,
|
||||
'content-type': 'application/json',
|
||||
origin: 'https://www.youtube.com',
|
||||
'x-youtube-client-name': client.id,
|
||||
'x-youtube-client-version': client.version,
|
||||
'user-agent': client.userAgent,
|
||||
...(visitorData ? { 'x-goog-visitor-id': visitorData } : {}),
|
||||
};
|
||||
|
||||
const payload = {
|
||||
videoId,
|
||||
contentCheckOk: true,
|
||||
racyCheckOk: true,
|
||||
context: { client: client.context },
|
||||
playbackContext: {
|
||||
contentPlaybackContext: { html5Preference: 'HTML5_PREF_WANTS' },
|
||||
},
|
||||
};
|
||||
|
||||
const response = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`player API ${client.key} failed: ${response.status}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const input = process.argv[2];
|
||||
const videoId = parseVideoId(input);
|
||||
if (!videoId) {
|
||||
console.error('Usage: node scripts/inspect-youtube-formats.mjs <youtube-id-or-url>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { apiKey, visitorData } = await fetchWatchConfig(videoId);
|
||||
if (!apiKey) {
|
||||
throw new Error('Could not extract INNERTUBE_API_KEY');
|
||||
}
|
||||
|
||||
const adaptiveVideo = [];
|
||||
const adaptiveAudio = [];
|
||||
|
||||
for (const client of CLIENTS) {
|
||||
const data = await fetchPlayerResponse(videoId, apiKey, visitorData, client);
|
||||
const formats = data?.streamingData?.adaptiveFormats ?? [];
|
||||
|
||||
for (const f of formats) {
|
||||
if (!f.url) continue;
|
||||
const mimeBase = getMimeBase(f.mimeType);
|
||||
if (mimeBase.startsWith('video/')) {
|
||||
const height = f.height ?? parseQualityLabel(f.qualityLabel);
|
||||
const fps = f.fps ?? 0;
|
||||
const bitrate = f.bitrate ?? f.averageBitrate ?? 0;
|
||||
adaptiveVideo.push({
|
||||
client: client.key,
|
||||
mimeType: f.mimeType ?? '',
|
||||
ext: getExt(f.mimeType),
|
||||
height,
|
||||
fps,
|
||||
bitrate,
|
||||
score: videoScore(height, fps, bitrate),
|
||||
url: f.url,
|
||||
});
|
||||
} else if (mimeBase.startsWith('audio/')) {
|
||||
const bitrate = f.bitrate ?? f.averageBitrate ?? 0;
|
||||
const sampleRate = Number.parseFloat(f.audioSampleRate ?? '0') || 0;
|
||||
adaptiveAudio.push({
|
||||
client: client.key,
|
||||
mimeType: f.mimeType ?? '',
|
||||
ext: getExt(f.mimeType),
|
||||
bitrate,
|
||||
audioSampleRate: f.audioSampleRate ?? '',
|
||||
score: audioScore(bitrate, sampleRate),
|
||||
url: f.url,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const sortedVideo = sortCandidates(adaptiveVideo);
|
||||
const sortedAudio = sortCandidates(adaptiveAudio);
|
||||
const iosSafeVideo = sortedVideo.filter(isIosSafeVideo);
|
||||
const iosSafeAudio = sortedAudio.filter(isIosSafeAudio);
|
||||
|
||||
console.log(`Video ID: ${videoId}`);
|
||||
console.log('');
|
||||
console.log('Top adaptive video candidates:');
|
||||
for (const item of sortedVideo.slice(0, 8)) {
|
||||
console.log(
|
||||
`- client=${item.client} height=${item.height} fps=${item.fps} bitrate=${item.bitrate} ext=${item.ext} mime=${item.mimeType}`
|
||||
);
|
||||
}
|
||||
|
||||
console.log('');
|
||||
console.log('Top adaptive audio candidates:');
|
||||
for (const item of sortedAudio.slice(0, 12)) {
|
||||
console.log(
|
||||
`- client=${item.client} bitrate=${item.bitrate} sampleRate=${item.audioSampleRate} ext=${item.ext} mime=${item.mimeType}`
|
||||
);
|
||||
}
|
||||
|
||||
console.log('');
|
||||
console.log('Top iOS-safe video candidates:');
|
||||
for (const item of iosSafeVideo.slice(0, 8)) {
|
||||
console.log(
|
||||
`- client=${item.client} height=${item.height} fps=${item.fps} bitrate=${item.bitrate} ext=${item.ext} mime=${item.mimeType}`
|
||||
);
|
||||
}
|
||||
|
||||
console.log('');
|
||||
console.log('Top iOS-safe audio candidates:');
|
||||
for (const item of iosSafeAudio.slice(0, 8)) {
|
||||
console.log(
|
||||
`- client=${item.client} bitrate=${item.bitrate} sampleRate=${item.audioSampleRate} ext=${item.ext} mime=${item.mimeType}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error instanceof Error ? error.stack ?? error.message : String(error));
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
@ -40,7 +40,7 @@ import { logger } from '../../utils/logger';
|
|||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { useSettings } from '../../hooks/useSettings';
|
||||
import { useTrailer } from '../../contexts/TrailerContext';
|
||||
import TrailerService from '../../services/trailerService';
|
||||
import TrailerService, { TrailerPlaybackSource } from '../../services/trailerService';
|
||||
import TrailerPlayer from '../video/TrailerPlayer';
|
||||
import { useLibrary } from '../../hooks/useLibrary';
|
||||
import { useToast } from '../../contexts/ToastContext';
|
||||
|
|
@ -202,7 +202,7 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
|||
const [initialLoadComplete, setInitialLoadComplete] = useState(false);
|
||||
|
||||
// Trailer state
|
||||
const [trailerUrl, setTrailerUrl] = useState<string | null>(null);
|
||||
const [trailerSource, setTrailerSource] = useState<TrailerPlaybackSource | null>(null);
|
||||
const [trailerLoading, setTrailerLoading] = useState(false);
|
||||
const [trailerError, setTrailerError] = useState(false);
|
||||
const [trailerReady, setTrailerReady] = useState(false);
|
||||
|
|
@ -392,14 +392,14 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
|||
setTrailerShouldBePaused(false);
|
||||
|
||||
// If trailer was ready and loaded, restore the video opacity
|
||||
if (trailerReady && trailerUrl) {
|
||||
if (trailerReady && trailerSource?.videoUrl) {
|
||||
logger.info('[AppleTVHero] Screen in focus and in view - restoring trailer');
|
||||
thumbnailOpacity.value = withTiming(0, { duration: 800 });
|
||||
trailerOpacity.value = withTiming(1, { duration: 800 });
|
||||
setTrailerPlaying(true);
|
||||
}
|
||||
}
|
||||
}, [isFocused, isOutOfView, setTrailerPlaying, trailerOpacity, thumbnailOpacity, trailerReady, trailerUrl]);
|
||||
}, [isFocused, isOutOfView, setTrailerPlaying, trailerOpacity, thumbnailOpacity, trailerReady, trailerSource]);
|
||||
|
||||
// Listen to navigation events to stop trailer when navigating to other screens
|
||||
useEffect(() => {
|
||||
|
|
@ -425,7 +425,7 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
|||
|
||||
const fetchTrailer = async () => {
|
||||
if (!currentItem || !showTrailersEnabled.current) {
|
||||
setTrailerUrl(null);
|
||||
setTrailerSource(null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -448,7 +448,7 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
|||
|
||||
if (!tmdbId) {
|
||||
logger.info('[AppleTVHero] No TMDB ID for:', currentItem.name, '- skipping trailer');
|
||||
setTrailerUrl(null);
|
||||
setTrailerSource(null);
|
||||
setTrailerLoading(false);
|
||||
return;
|
||||
}
|
||||
|
|
@ -467,7 +467,7 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
|||
|
||||
if (!videosRes.ok) {
|
||||
logger.warn('[AppleTVHero] TMDB videos fetch failed:', videosRes.status);
|
||||
setTrailerUrl(null);
|
||||
setTrailerSource(null);
|
||||
setTrailerLoading(false);
|
||||
return;
|
||||
}
|
||||
|
|
@ -485,31 +485,31 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
|||
|
||||
if (!pick) {
|
||||
logger.info('[AppleTVHero] No YouTube video found for:', currentItem.name);
|
||||
setTrailerUrl(null);
|
||||
setTrailerSource(null);
|
||||
setTrailerLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info('[AppleTVHero] Extracting stream for videoId:', pick.key, currentItem.name);
|
||||
|
||||
const url = await TrailerService.getTrailerFromVideoId(
|
||||
const source = await TrailerService.getTrailerPlaybackSourceFromVideoId(
|
||||
pick.key,
|
||||
currentItem.name
|
||||
);
|
||||
|
||||
if (!alive) return;
|
||||
|
||||
if (url) {
|
||||
setTrailerUrl(url);
|
||||
if (source) {
|
||||
setTrailerSource(source);
|
||||
} else {
|
||||
logger.info('[AppleTVHero] No stream extracted for:', currentItem.name);
|
||||
setTrailerUrl(null);
|
||||
setTrailerSource(null);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!alive) return;
|
||||
logger.error('[AppleTVHero] Error fetching trailer:', error);
|
||||
setTrailerError(true);
|
||||
setTrailerUrl(null);
|
||||
setTrailerSource(null);
|
||||
} finally {
|
||||
if (alive) {
|
||||
setTrailerLoading(false);
|
||||
|
|
@ -1094,11 +1094,12 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
|||
)}
|
||||
|
||||
{/* Hidden preload trailer player */}
|
||||
{settings?.showTrailers && trailerUrl && !trailerLoading && !trailerError && !trailerPreloaded && (
|
||||
{settings?.showTrailers && trailerSource?.videoUrl && !trailerLoading && !trailerError && !trailerPreloaded && (
|
||||
<View style={[StyleSheet.absoluteFillObject, { opacity: 0, pointerEvents: 'none' }]}>
|
||||
<TrailerPlayer
|
||||
key={`preload-${trailerUrl}`}
|
||||
trailerUrl={trailerUrl}
|
||||
key={`preload-${trailerSource.videoUrl}-${trailerSource.audioUrl ?? 'no-audio'}`}
|
||||
trailerUrl={trailerSource.videoUrl}
|
||||
audioUrl={trailerSource.audioUrl}
|
||||
autoPlay={false}
|
||||
muted={true}
|
||||
style={StyleSheet.absoluteFillObject}
|
||||
|
|
@ -1112,13 +1113,14 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
|||
)}
|
||||
|
||||
{/* Visible trailer player - 60% height with 5% zoom and smooth fade */}
|
||||
{settings?.showTrailers && trailerUrl && !trailerLoading && !trailerError && trailerPreloaded && (
|
||||
{settings?.showTrailers && trailerSource?.videoUrl && !trailerLoading && !trailerError && trailerPreloaded && (
|
||||
<Animated.View style={[trailerContainerStyle, trailerParallaxStyle]}>
|
||||
<Animated.View style={trailerVideoStyle}>
|
||||
<TrailerPlayer
|
||||
key={`visible-${trailerUrl}`}
|
||||
key={`visible-${trailerSource.videoUrl}-${trailerSource.audioUrl ?? 'no-audio'}`}
|
||||
ref={trailerVideoRef}
|
||||
trailerUrl={trailerUrl}
|
||||
trailerUrl={trailerSource.videoUrl}
|
||||
audioUrl={trailerSource.audioUrl}
|
||||
autoPlay={!trailerShouldBePaused}
|
||||
muted={trailerMuted}
|
||||
style={StyleSheet.absoluteFillObject}
|
||||
|
|
@ -1168,7 +1170,7 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
|||
</View>
|
||||
|
||||
{/* Trailer control buttons (unmute and fullscreen) */}
|
||||
{settings?.showTrailers && trailerReady && trailerUrl && (
|
||||
{settings?.showTrailers && trailerReady && trailerSource?.videoUrl && (
|
||||
<Animated.View style={{
|
||||
position: 'absolute',
|
||||
top: (Platform.OS === 'android' ? 60 : 70) + insets.top,
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ import { useTrailer } from '../../contexts/TrailerContext';
|
|||
import { useTranslation } from 'react-i18next';
|
||||
import { logger } from '../../utils/logger';
|
||||
import { TMDBService } from '../../services/tmdbService';
|
||||
import TrailerService from '../../services/trailerService';
|
||||
import TrailerService, { TrailerPlaybackSource } from '../../services/trailerService';
|
||||
import TrailerPlayer from '../video/TrailerPlayer';
|
||||
import { HERO_HEIGHT, SCREEN_WIDTH as width, IS_TABLET as isTablet } from '../../constants/dimensions';
|
||||
|
||||
|
|
@ -878,7 +878,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
|||
// Image loading state with optimized management
|
||||
const [imageError, setImageError] = useState(false);
|
||||
const [imageLoaded, setImageLoaded] = useState(false);
|
||||
const [trailerUrl, setTrailerUrl] = useState<string | null>(null);
|
||||
const [trailerSource, setTrailerSource] = useState<TrailerPlaybackSource | null>(null);
|
||||
const [trailerLoading, setTrailerLoading] = useState(false);
|
||||
const [trailerError, setTrailerError] = useState(false);
|
||||
// Use persistent setting instead of local state
|
||||
|
|
@ -1188,12 +1188,12 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
|||
|
||||
logger.info('HeroSection', `Extracting stream for videoId: ${pick.key} (${metadata.name})`);
|
||||
|
||||
const url = await TrailerService.getTrailerFromVideoId(pick.key, metadata.name);
|
||||
const source = await TrailerService.getTrailerPlaybackSourceFromVideoId(pick.key, metadata.name);
|
||||
|
||||
if (!alive) return;
|
||||
|
||||
if (url) {
|
||||
setTrailerUrl(url);
|
||||
if (source) {
|
||||
setTrailerSource(source);
|
||||
logger.info('HeroSection', `Trailer loaded for ${metadata.name}`);
|
||||
} else {
|
||||
logger.info('HeroSection', `No stream extracted for ${metadata.name}`);
|
||||
|
|
@ -1508,7 +1508,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
|||
try {
|
||||
setTrailerReady(false);
|
||||
setTrailerPreloaded(false);
|
||||
setTrailerUrl(null);
|
||||
setTrailerSource(null);
|
||||
trailerOpacity.value = 0;
|
||||
thumbnailOpacity.value = 1;
|
||||
} catch (_e) { }
|
||||
|
|
@ -1614,14 +1614,15 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
|||
)}
|
||||
|
||||
{/* Single trailer player - starts hidden (opacity 0), fades in when ready */}
|
||||
{shouldLoadSecondaryData && settings?.showTrailers && trailerUrl && !trailerLoading && !trailerError && (
|
||||
{shouldLoadSecondaryData && settings?.showTrailers && trailerSource?.videoUrl && !trailerLoading && !trailerError && (
|
||||
<Animated.View style={[staticStyles.absoluteFill, {
|
||||
opacity: trailerOpacity
|
||||
}, trailerParallaxStyle]}>
|
||||
<TrailerPlayer
|
||||
key={`trailer-${trailerUrl}`}
|
||||
key={`trailer-${trailerSource.videoUrl}-${trailerSource.audioUrl ?? 'no-audio'}`}
|
||||
ref={trailerVideoRef}
|
||||
trailerUrl={trailerUrl}
|
||||
trailerUrl={trailerSource.videoUrl}
|
||||
audioUrl={trailerSource.audioUrl}
|
||||
autoPlay={globalTrailerPlaying}
|
||||
muted={trailerMuted}
|
||||
style={staticStyles.absoluteFill}
|
||||
|
|
@ -1641,7 +1642,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
|||
)}
|
||||
|
||||
{/* Trailer control buttons (unmute and fullscreen) */}
|
||||
{settings?.showTrailers && trailerReady && trailerUrl && (
|
||||
{settings?.showTrailers && trailerReady && trailerSource?.videoUrl && (
|
||||
<Animated.View style={{
|
||||
position: 'absolute',
|
||||
top: Platform.OS === 'android' ? 40 : 50,
|
||||
|
|
@ -1750,7 +1751,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
|||
)}
|
||||
|
||||
{/* AI Chat button (when trailers are disabled) */}
|
||||
{settings?.aiChatEnabled && !(settings?.showTrailers && trailerReady && trailerUrl) && (
|
||||
{settings?.aiChatEnabled && !(settings?.showTrailers && trailerReady && trailerSource?.videoUrl) && (
|
||||
<Animated.View style={{
|
||||
position: 'absolute',
|
||||
top: Platform.OS === 'android' ? 40 : 50,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { useTranslation } from 'react-i18next';
|
|||
import { useTheme } from '../../contexts/ThemeContext';
|
||||
import { useTrailer } from '../../contexts/TrailerContext';
|
||||
import { logger } from '../../utils/logger';
|
||||
import TrailerService from '../../services/trailerService';
|
||||
import TrailerService, { TrailerPlaybackSource } from '../../services/trailerService';
|
||||
import Video, { VideoRef, OnLoadData, OnProgressData } from 'react-native-video';
|
||||
|
||||
const { width, height } = Dimensions.get('window');
|
||||
|
|
@ -38,6 +38,14 @@ interface TrailerModalProps {
|
|||
contentTitle: string;
|
||||
}
|
||||
|
||||
function isUnsupportedIosMediaFormat(error: any): boolean {
|
||||
if (Platform.OS !== 'ios') return false;
|
||||
|
||||
const errorCode = error?.error?.code;
|
||||
const errorDomain = error?.error?.domain;
|
||||
return errorDomain === 'AVFoundationErrorDomain' && errorCode === -11828;
|
||||
}
|
||||
|
||||
const TrailerModal: React.FC<TrailerModalProps> = memo(({
|
||||
visible,
|
||||
onClose,
|
||||
|
|
@ -67,7 +75,7 @@ const TrailerModal: React.FC<TrailerModalProps> = memo(({
|
|||
}, [t]);
|
||||
|
||||
const videoRef = React.useRef<VideoRef>(null);
|
||||
const [trailerUrl, setTrailerUrl] = useState<string | null>(null);
|
||||
const [playbackSource, setPlaybackSource] = useState<TrailerPlaybackSource | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
|
|
@ -79,7 +87,7 @@ const TrailerModal: React.FC<TrailerModalProps> = memo(({
|
|||
loadTrailer();
|
||||
} else {
|
||||
// Reset state when modal closes
|
||||
setTrailerUrl(null);
|
||||
setPlaybackSource(null);
|
||||
setLoading(false);
|
||||
setError(null);
|
||||
setIsPlaying(false);
|
||||
|
|
@ -87,7 +95,7 @@ const TrailerModal: React.FC<TrailerModalProps> = memo(({
|
|||
}
|
||||
}, [visible, trailer]);
|
||||
|
||||
const loadTrailer = useCallback(async () => {
|
||||
const loadTrailer = useCallback(async (resetRetryCount = true) => {
|
||||
if (!trailer) return;
|
||||
|
||||
// Pause hero section trailer when modal opens
|
||||
|
|
@ -100,8 +108,10 @@ const TrailerModal: React.FC<TrailerModalProps> = memo(({
|
|||
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
setTrailerUrl(null);
|
||||
setRetryCount(0); // Reset retry count when starting fresh load
|
||||
setPlaybackSource(null);
|
||||
if (resetRetryCount) {
|
||||
setRetryCount(0);
|
||||
}
|
||||
|
||||
try {
|
||||
const youtubeUrl = `https://www.youtube.com/watch?v=${trailer.key}`;
|
||||
|
|
@ -109,14 +119,14 @@ const TrailerModal: React.FC<TrailerModalProps> = memo(({
|
|||
logger.info('TrailerModal', `Loading trailer: ${trailer.name} (${youtubeUrl})`);
|
||||
|
||||
// Use the direct YouTube URL method - much more efficient!
|
||||
const directUrl = await TrailerService.getTrailerFromYouTubeUrl(
|
||||
const source = await TrailerService.getTrailerPlaybackSourceFromYouTubeUrl(
|
||||
youtubeUrl,
|
||||
`${contentTitle} - ${trailer.name}`,
|
||||
new Date(trailer.published_at).getFullYear().toString()
|
||||
);
|
||||
|
||||
if (directUrl) {
|
||||
setTrailerUrl(directUrl);
|
||||
if (source) {
|
||||
setPlaybackSource(source);
|
||||
setIsPlaying(true);
|
||||
logger.info('TrailerModal', `Successfully loaded direct trailer URL for: ${trailer.name}`);
|
||||
} else {
|
||||
|
|
@ -159,12 +169,20 @@ const TrailerModal: React.FC<TrailerModalProps> = memo(({
|
|||
const handleVideoError = useCallback((error: any) => {
|
||||
logger.error('TrailerModal', 'Video error:', error);
|
||||
|
||||
if (isUnsupportedIosMediaFormat(error)) {
|
||||
logger.error('TrailerModal', 'Unsupported iOS trailer format:', error);
|
||||
setError('This trailer format is not supported on iOS.');
|
||||
setLoading(false);
|
||||
setIsPlaying(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (retryCount < 2) {
|
||||
logger.info('TrailerModal', `Re-extracting trailer (attempt ${retryCount + 1}/2)`);
|
||||
setRetryCount(prev => prev + 1);
|
||||
// Invalidate cache so loadTrailer gets a fresh URL, not the same bad one
|
||||
if (trailer?.key) TrailerService.invalidateCache(trailer.key);
|
||||
loadTrailer();
|
||||
loadTrailer(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -242,7 +260,9 @@ const TrailerModal: React.FC<TrailerModalProps> = memo(({
|
|||
</Text>
|
||||
<TouchableOpacity
|
||||
style={[styles.retryButton, { backgroundColor: currentTheme.colors.primary }]}
|
||||
onPress={loadTrailer}
|
||||
onPress={() => {
|
||||
void loadTrailer(true);
|
||||
}}
|
||||
>
|
||||
<Text style={styles.retryButtonText}>{t('common.try_again')}</Text>
|
||||
</TouchableOpacity>
|
||||
|
|
@ -250,21 +270,28 @@ const TrailerModal: React.FC<TrailerModalProps> = memo(({
|
|||
)}
|
||||
|
||||
{/* Render the Video as soon as we have a URL; keep spinner overlay until onLoad */}
|
||||
{trailerUrl && !error && (
|
||||
{playbackSource?.videoUrl && !error && (
|
||||
<View style={styles.playerWrapper}>
|
||||
<Video
|
||||
ref={videoRef}
|
||||
source={(() => {
|
||||
const lower = (trailerUrl || '').toLowerCase();
|
||||
const lower = playbackSource.videoUrl.toLowerCase();
|
||||
const looksLikeHls = /\.m3u8(\b|$)/.test(lower) || /hls|playlist|m3u/.test(lower);
|
||||
if (Platform.OS === 'android') {
|
||||
const headers = { 'User-Agent': 'Nuvio/1.0 (Android)' };
|
||||
if (looksLikeHls) {
|
||||
return { uri: trailerUrl, type: 'm3u8', headers } as any;
|
||||
return { uri: playbackSource.videoUrl, type: 'm3u8', headers } as any;
|
||||
}
|
||||
return { uri: trailerUrl, headers } as any;
|
||||
return {
|
||||
uri: playbackSource.videoUrl,
|
||||
headers,
|
||||
...(playbackSource.audioUrl ? { audioUri: playbackSource.audioUrl } : null),
|
||||
} as any;
|
||||
}
|
||||
return { uri: trailerUrl } as any;
|
||||
return {
|
||||
uri: playbackSource.videoUrl,
|
||||
...(playbackSource.audioUrl ? { audioUri: playbackSource.audioUrl } : null),
|
||||
} as any;
|
||||
})()}
|
||||
style={styles.player}
|
||||
controls={true}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ const isTablet = width >= 768;
|
|||
|
||||
interface TrailerPlayerProps {
|
||||
trailerUrl: string;
|
||||
audioUrl?: string | null;
|
||||
autoPlay?: boolean;
|
||||
muted?: boolean;
|
||||
onLoadStart?: () => void;
|
||||
|
|
@ -46,6 +47,7 @@ interface TrailerPlayerProps {
|
|||
|
||||
const TrailerPlayer = React.forwardRef<any, TrailerPlayerProps>(({
|
||||
trailerUrl,
|
||||
audioUrl,
|
||||
autoPlay = true,
|
||||
muted = true,
|
||||
onLoadStart,
|
||||
|
|
@ -381,9 +383,16 @@ const TrailerPlayer = React.forwardRef<any, TrailerPlayerProps>(({
|
|||
if (looksLikeHls) {
|
||||
return { uri: trailerUrl, type: 'm3u8', headers: androidHeaders } as any;
|
||||
}
|
||||
return { uri: trailerUrl, headers: androidHeaders } as any;
|
||||
return {
|
||||
uri: trailerUrl,
|
||||
headers: androidHeaders,
|
||||
...(audioUrl ? { audioUri: audioUrl } : null),
|
||||
} as any;
|
||||
}
|
||||
return { uri: trailerUrl } as any;
|
||||
return {
|
||||
uri: trailerUrl,
|
||||
...(audioUrl ? { audioUri: audioUrl } : null),
|
||||
} as any;
|
||||
})()}
|
||||
style={styles.video}
|
||||
resizeMode="cover"
|
||||
|
|
|
|||
|
|
@ -472,15 +472,12 @@ const DownloadsScreen: React.FC = () => {
|
|||
case 'infuse':
|
||||
externalPlayerUrls = [
|
||||
`infuse://x-callback-url/play?url=${streamUrl}`,
|
||||
`infuse://play?url=${streamUrl}`,
|
||||
`infuse://${streamUrl}`
|
||||
];
|
||||
break;
|
||||
|
||||
case 'vidhub':
|
||||
externalPlayerUrls = [
|
||||
`vidhub://play?url=${streamUrl}`,
|
||||
`vidhub://${streamUrl}`
|
||||
`open-vidhub://x-callback-url/open?url=${streamUrl}`,
|
||||
];
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -493,12 +493,12 @@ export const useStreamsScreen = () => {
|
|||
case 'infuse':
|
||||
externalPlayerUrls = [
|
||||
`infuse://x-callback-url/play?url=${streamUrl}`,
|
||||
`infuse://play?url=${streamUrl}`,
|
||||
`infuse://${streamUrl}`,
|
||||
];
|
||||
break;
|
||||
case 'vidhub':
|
||||
externalPlayerUrls = [`vidhub://play?url=${streamUrl}`, `vidhub://${streamUrl}`];
|
||||
externalPlayerUrls = [
|
||||
`open-vidhub://x-callback-url/open?url=${streamUrl}`,
|
||||
];
|
||||
break;
|
||||
default:
|
||||
navigateToPlayer(stream);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { logger } from '../utils/logger';
|
||||
import { Platform } from 'react-native';
|
||||
import { YouTubeExtractor } from './youtubeExtractor';
|
||||
import { YouTubeExtractionResult, YouTubeExtractor } from './youtubeExtractor';
|
||||
|
||||
export interface TrailerData {
|
||||
url: string;
|
||||
|
|
@ -8,8 +8,14 @@ export interface TrailerData {
|
|||
year: number;
|
||||
}
|
||||
|
||||
export interface TrailerPlaybackSource {
|
||||
videoUrl: string;
|
||||
audioUrl: string | null;
|
||||
quality?: string;
|
||||
}
|
||||
|
||||
interface CacheEntry {
|
||||
url: string;
|
||||
source: TrailerPlaybackSource;
|
||||
expiresAt: number;
|
||||
}
|
||||
|
||||
|
|
@ -31,6 +37,15 @@ export class TrailerService {
|
|||
title?: string,
|
||||
year?: number
|
||||
): Promise<string | null> {
|
||||
const source = await this.getTrailerPlaybackSourceFromVideoId(youtubeVideoId, title, year);
|
||||
return source?.videoUrl ?? null;
|
||||
}
|
||||
|
||||
static async getTrailerPlaybackSourceFromVideoId(
|
||||
youtubeVideoId: string,
|
||||
title?: string,
|
||||
year?: number
|
||||
): Promise<TrailerPlaybackSource | null> {
|
||||
if (!youtubeVideoId) return null;
|
||||
|
||||
logger.info('TrailerService', `getTrailerFromVideoId: ${youtubeVideoId} (${title ?? '?'} ${year ?? ''})`);
|
||||
|
|
@ -43,11 +58,12 @@ export class TrailerService {
|
|||
|
||||
try {
|
||||
const platform = Platform.OS === 'android' ? 'android' : 'ios';
|
||||
const url = await YouTubeExtractor.getBestStreamUrl(youtubeVideoId, platform);
|
||||
if (url) {
|
||||
const extracted = await YouTubeExtractor.extract(youtubeVideoId, platform);
|
||||
if (extracted) {
|
||||
const source = this.toPlaybackSource(extracted);
|
||||
logger.info('TrailerService', `Extraction succeeded for ${youtubeVideoId}`);
|
||||
this.setCache(youtubeVideoId, url);
|
||||
return url;
|
||||
this.setCache(youtubeVideoId, source);
|
||||
return source;
|
||||
}
|
||||
logger.warn('TrailerService', `Extraction returned null for ${youtubeVideoId}`);
|
||||
} catch (err) {
|
||||
|
|
@ -66,6 +82,15 @@ export class TrailerService {
|
|||
title?: string,
|
||||
year?: string
|
||||
): Promise<string | null> {
|
||||
const source = await this.getTrailerPlaybackSourceFromYouTubeUrl(youtubeUrl, title, year);
|
||||
return source?.videoUrl ?? null;
|
||||
}
|
||||
|
||||
static async getTrailerPlaybackSourceFromYouTubeUrl(
|
||||
youtubeUrl: string,
|
||||
title?: string,
|
||||
year?: string
|
||||
): Promise<TrailerPlaybackSource | null> {
|
||||
logger.info('TrailerService', `getTrailerFromYouTubeUrl: ${youtubeUrl}`);
|
||||
|
||||
const videoId = YouTubeExtractor.parseVideoId(youtubeUrl);
|
||||
|
|
@ -74,7 +99,7 @@ export class TrailerService {
|
|||
return null;
|
||||
}
|
||||
|
||||
return this.getTrailerFromVideoId(
|
||||
return this.getTrailerPlaybackSourceFromVideoId(
|
||||
videoId,
|
||||
title,
|
||||
year ? parseInt(year, 10) : undefined
|
||||
|
|
@ -135,7 +160,7 @@ export class TrailerService {
|
|||
// Private — cache
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
private static getCached(key: string): string | null {
|
||||
private static getCached(key: string): TrailerPlaybackSource | null {
|
||||
const entry = this.urlCache.get(key);
|
||||
if (!entry) return null;
|
||||
if (Date.now() > entry.expiresAt) {
|
||||
|
|
@ -144,9 +169,9 @@ export class TrailerService {
|
|||
}
|
||||
// Check the URL's own CDN expiry — googlevideo.com URLs carry an `expire`
|
||||
// param (Unix timestamp). Treat as stale if it expires within 2 minutes.
|
||||
if (entry.url.includes('googlevideo.com')) {
|
||||
if (entry.source.videoUrl.includes('googlevideo.com')) {
|
||||
try {
|
||||
const u = new URL(entry.url);
|
||||
const u = new URL(entry.source.videoUrl);
|
||||
const expire = u.searchParams.get('expire');
|
||||
if (expire) {
|
||||
const expiresAt = parseInt(expire, 10) * 1000;
|
||||
|
|
@ -158,16 +183,24 @@ export class TrailerService {
|
|||
}
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
return entry.url;
|
||||
return entry.source;
|
||||
}
|
||||
|
||||
private static setCache(key: string, url: string): void {
|
||||
this.urlCache.set(key, { url, expiresAt: Date.now() + this.CACHE_TTL_MS });
|
||||
private static setCache(key: string, source: TrailerPlaybackSource): void {
|
||||
this.urlCache.set(key, { source, expiresAt: Date.now() + this.CACHE_TTL_MS });
|
||||
if (this.urlCache.size > 100) {
|
||||
const oldest = this.urlCache.keys().next().value;
|
||||
if (oldest) this.urlCache.delete(oldest);
|
||||
}
|
||||
}
|
||||
|
||||
private static toPlaybackSource(extracted: YouTubeExtractionResult): TrailerPlaybackSource {
|
||||
return {
|
||||
videoUrl: extracted.videoUrl,
|
||||
audioUrl: extracted.audioUrl,
|
||||
quality: extracted.quality,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default TrailerService;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ const DEFAULT_HEADERS: Record<string, string> = {
|
|||
'user-agent': DEFAULT_USER_AGENT,
|
||||
};
|
||||
|
||||
const PREFERRED_ADAPTIVE_CLIENT = 'android_vr';
|
||||
const REQUEST_TIMEOUT_MS = 6000; // player API + HLS manifest requests
|
||||
const WATCH_PAGE_TIMEOUT_MS = 3000; // watch page scrape — best-effort only
|
||||
const MAX_RETRIES = 2; // retry extraction up to 2 times on total failure
|
||||
|
|
@ -182,6 +181,12 @@ function getMimeBase(mimeType?: string): string {
|
|||
return (mimeType ?? '').split(';')[0].trim();
|
||||
}
|
||||
|
||||
function getCodecs(mimeType?: string): string[] {
|
||||
const match = (mimeType ?? '').match(/codecs="([^"]+)"/i);
|
||||
if (!match) return [];
|
||||
return match[1].split(',').map(codec => codec.trim().toLowerCase()).filter(Boolean);
|
||||
}
|
||||
|
||||
function getExt(mimeType?: string): 'mp4' | 'webm' | 'm4a' | 'other' {
|
||||
const base = getMimeBase(mimeType);
|
||||
if (base === 'video/mp4' || base === 'audio/mp4') return 'mp4';
|
||||
|
|
@ -260,16 +265,6 @@ async function validateUrl(url: string, userAgent: string): Promise<boolean> {
|
|||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// android_vr preferred selection — only fall back to other clients if
|
||||
// android_vr returned zero formats (likely PO token required for others)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function filterPreferAndroidVr(items: StreamCandidate[]): StreamCandidate[] {
|
||||
const fromVr = items.filter(c => c.client === 'android_vr');
|
||||
return fromVr.length > 0 ? fromVr : items;
|
||||
}
|
||||
|
||||
function sortCandidates(items: StreamCandidate[]): StreamCandidate[] {
|
||||
return [...items].sort((a, b) => {
|
||||
if (b.score !== a.score) return b.score - a.score;
|
||||
|
|
@ -279,13 +274,39 @@ function sortCandidates(items: StreamCandidate[]): StreamCandidate[] {
|
|||
});
|
||||
}
|
||||
|
||||
function pickBestForClient(
|
||||
async function findBestValidatedCandidate(
|
||||
items: StreamCandidate[],
|
||||
preferredClient: string,
|
||||
): StreamCandidate | null {
|
||||
const fromPreferred = items.filter(c => c.client === preferredClient);
|
||||
const pool = fromPreferred.length > 0 ? fromPreferred : items;
|
||||
return sortCandidates(pool)[0] ?? null;
|
||||
userAgent: string,
|
||||
label: string,
|
||||
): Promise<StreamCandidate | null> {
|
||||
for (const candidate of sortCandidates(items)) {
|
||||
const valid = await validateUrl(candidate.url, userAgent);
|
||||
if (valid) return candidate;
|
||||
logger.warn('YouTubeExtractor', `${label} URL invalid, trying next candidate`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getHlsQualityScore(variant: HlsVariant): number {
|
||||
return variant.height * 1_000_000_000 + variant.bandwidth;
|
||||
}
|
||||
|
||||
function isIosCompatibleSeparateVideo(candidate: StreamCandidate): boolean {
|
||||
if (getMimeBase(candidate.mimeType) !== 'video/mp4') return false;
|
||||
const codecs = getCodecs(candidate.mimeType);
|
||||
if (codecs.length === 0) return true;
|
||||
return codecs.some(codec =>
|
||||
codec.startsWith('avc1') ||
|
||||
codec.startsWith('hvc1') ||
|
||||
codec.startsWith('hev1'),
|
||||
);
|
||||
}
|
||||
|
||||
function isIosCompatibleSeparateAudio(candidate: StreamCandidate): boolean {
|
||||
if (getMimeBase(candidate.mimeType) !== 'audio/mp4') return false;
|
||||
const codecs = getCodecs(candidate.mimeType);
|
||||
if (codecs.length === 0) return true;
|
||||
return codecs.some(codec => codec.startsWith('mp4a'));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -580,12 +601,8 @@ export class YouTubeExtractor {
|
|||
* Matches the Kotlin InAppYouTubeExtractor approach:
|
||||
* 1. Fetch watch page for dynamic API key + visitor data
|
||||
* 2. Try ALL clients, collect formats from all that succeed
|
||||
* 3. Pick best HLS variant (by resolution/bandwidth) as primary
|
||||
* 4. Fall back to best progressive (muxed) if no HLS
|
||||
*
|
||||
* Note: Unlike the Kotlin version, we do not return separate videoUrl/audioUrl
|
||||
* for adaptive streams — react-native-video cannot merge two sources. HLS
|
||||
* provides the best quality without needing a separate audio track.
|
||||
* 3. Prefer separate adaptive video+audio when available
|
||||
* 4. Fall back to HLS/progressive muxed sources
|
||||
*/
|
||||
static async extract(
|
||||
videoIdOrUrl: string,
|
||||
|
|
@ -650,63 +667,140 @@ export class YouTubeExtractor {
|
|||
}
|
||||
}
|
||||
|
||||
// Prefer android_vr formats exclusively — other clients may require PO tokens
|
||||
// and return URLs that 403 at the CDN level during playback
|
||||
const preferredProgressive = sortCandidates(filterPreferAndroidVr(progressive));
|
||||
const bestAdaptiveVideo = pickBestForClient(adaptiveVideo, PREFERRED_ADAPTIVE_CLIENT);
|
||||
const bestAdaptiveAudio = pickBestForClient(adaptiveAudio, PREFERRED_ADAPTIVE_CLIENT);
|
||||
const progressiveCandidates = sortCandidates(progressive);
|
||||
const adaptiveVideoCandidates = sortCandidates(adaptiveVideo);
|
||||
const adaptiveAudioCandidates = sortCandidates(adaptiveAudio);
|
||||
const compatibleAdaptiveVideoCandidates =
|
||||
effectivePlatform === 'ios'
|
||||
? adaptiveVideoCandidates.filter(isIosCompatibleSeparateVideo)
|
||||
: adaptiveVideoCandidates;
|
||||
const compatibleAdaptiveAudioCandidates =
|
||||
effectivePlatform === 'ios'
|
||||
? adaptiveAudioCandidates.filter(isIosCompatibleSeparateAudio)
|
||||
: adaptiveAudioCandidates;
|
||||
|
||||
if (bestHls) logger.info('YouTubeExtractor', `Best HLS: ${bestHls.height}p ${bestHls.bandwidth}bps`);
|
||||
if (preferredProgressive[0]) logger.info('YouTubeExtractor', `Best progressive: ${preferredProgressive[0].height}p client=${preferredProgressive[0].client}`);
|
||||
if (bestAdaptiveVideo) logger.info('YouTubeExtractor', `Best adaptive video: ${bestAdaptiveVideo.height}p client=${bestAdaptiveVideo.client}`);
|
||||
if (bestAdaptiveAudio) logger.info('YouTubeExtractor', `Best adaptive audio: ${bestAdaptiveAudio.bitrate}bps client=${bestAdaptiveAudio.client}`);
|
||||
if (progressiveCandidates[0]) logger.info('YouTubeExtractor', `Best progressive: ${progressiveCandidates[0].height}p client=${progressiveCandidates[0].client}`);
|
||||
if (adaptiveVideoCandidates[0]) logger.info('YouTubeExtractor', `Best adaptive video: ${adaptiveVideoCandidates[0].height}p client=${adaptiveVideoCandidates[0].client}`);
|
||||
if (adaptiveAudioCandidates[0]) logger.info('YouTubeExtractor', `Best adaptive audio: ${adaptiveAudioCandidates[0].bitrate}bps client=${adaptiveAudioCandidates[0].client}`);
|
||||
if (effectivePlatform === 'ios') {
|
||||
if (compatibleAdaptiveVideoCandidates[0]) {
|
||||
logger.info(
|
||||
'YouTubeExtractor',
|
||||
`Best iOS-compatible adaptive video: ${compatibleAdaptiveVideoCandidates[0].height}p client=${compatibleAdaptiveVideoCandidates[0].client} mime=${compatibleAdaptiveVideoCandidates[0].mimeType}`
|
||||
);
|
||||
}
|
||||
if (compatibleAdaptiveAudioCandidates[0]) {
|
||||
logger.info(
|
||||
'YouTubeExtractor',
|
||||
`Best iOS-compatible adaptive audio: ${compatibleAdaptiveAudioCandidates[0].bitrate}bps client=${compatibleAdaptiveAudioCandidates[0].client} mime=${compatibleAdaptiveAudioCandidates[0].mimeType}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// VR client user agent used for CDN URL validation
|
||||
const vrUserAgent = CLIENTS.find(c => c.key === 'android_vr')!.userAgent;
|
||||
|
||||
// Step 4: select final source with URL validation
|
||||
// Priority: HLS > progressive muxed
|
||||
// HLS manifests don't need validation — they're not CDN segment URLs
|
||||
if (bestHls) {
|
||||
// Return the specific best variant URL, not the master playlist.
|
||||
// Master playlist lets the player pick quality adaptively (often starts low).
|
||||
// Pinning to the best variant ensures consistent high quality playback.
|
||||
logger.info('YouTubeExtractor', `Using HLS variant: ${summarizeUrl(bestHls.url)} ${bestHls.height}p`);
|
||||
// Step 4: validate the best candidates per source type, then pick the
|
||||
// highest-quality playable result.
|
||||
const validatedAdaptiveVideo = await findBestValidatedCandidate(
|
||||
compatibleAdaptiveVideoCandidates,
|
||||
vrUserAgent,
|
||||
'Adaptive video',
|
||||
);
|
||||
const validatedAdaptiveAudio = await findBestValidatedCandidate(
|
||||
compatibleAdaptiveAudioCandidates,
|
||||
vrUserAgent,
|
||||
'Adaptive audio',
|
||||
);
|
||||
const validatedProgressive = await findBestValidatedCandidate(
|
||||
progressiveCandidates,
|
||||
vrUserAgent,
|
||||
'Progressive',
|
||||
);
|
||||
|
||||
const adaptivePlayback =
|
||||
validatedAdaptiveVideo && validatedAdaptiveAudio
|
||||
? {
|
||||
type: 'adaptive' as const,
|
||||
videoUrl: validatedAdaptiveVideo.url,
|
||||
audioUrl: validatedAdaptiveAudio.url,
|
||||
quality: `${validatedAdaptiveVideo.height}p`,
|
||||
score: validatedAdaptiveVideo.score,
|
||||
height: validatedAdaptiveVideo.height,
|
||||
audioBitrate: validatedAdaptiveAudio.bitrate,
|
||||
videoClient: validatedAdaptiveVideo.client,
|
||||
videoMimeType: validatedAdaptiveVideo.mimeType,
|
||||
videoExt: validatedAdaptiveVideo.ext,
|
||||
audioClient: validatedAdaptiveAudio.client,
|
||||
audioMimeType: validatedAdaptiveAudio.mimeType,
|
||||
audioExt: validatedAdaptiveAudio.ext,
|
||||
}
|
||||
: null;
|
||||
|
||||
const progressivePlayback = validatedProgressive
|
||||
? {
|
||||
type: 'progressive' as const,
|
||||
videoUrl: validatedProgressive.url,
|
||||
audioUrl: null,
|
||||
quality: `${validatedProgressive.height}p`,
|
||||
score: validatedProgressive.score,
|
||||
height: validatedProgressive.height,
|
||||
}
|
||||
: null;
|
||||
|
||||
const hlsPlayback = bestHls
|
||||
? {
|
||||
type: 'hls' as const,
|
||||
videoUrl: bestHls.manifestUrl,
|
||||
audioUrl: null,
|
||||
quality: `${bestHls.height}p`,
|
||||
score: getHlsQualityScore(bestHls),
|
||||
height: bestHls.height,
|
||||
bandwidth: bestHls.bandwidth,
|
||||
}
|
||||
: null;
|
||||
|
||||
const bestPlayable = [adaptivePlayback, progressivePlayback, hlsPlayback]
|
||||
.filter((candidate): candidate is NonNullable<typeof candidate> => candidate !== null)
|
||||
.sort((a, b) => b.score - a.score)[0] ?? null;
|
||||
|
||||
if (bestPlayable) {
|
||||
if (bestPlayable.type === 'adaptive') {
|
||||
logger.info(
|
||||
'YouTubeExtractor',
|
||||
`Using separate adaptive streams: video=${bestPlayable.height}p ` +
|
||||
`videoClient=${bestPlayable.videoClient} videoMime=${bestPlayable.videoMimeType} videoExt=${bestPlayable.videoExt} ` +
|
||||
`audio=${bestPlayable.audioBitrate}bps audioClient=${bestPlayable.audioClient} ` +
|
||||
`audioMime=${bestPlayable.audioMimeType} audioExt=${bestPlayable.audioExt}`
|
||||
);
|
||||
} else if (bestPlayable.type === 'progressive') {
|
||||
logger.info(
|
||||
'YouTubeExtractor',
|
||||
`Using progressive: ${summarizeUrl(bestPlayable.videoUrl)} ${bestPlayable.height}p`
|
||||
);
|
||||
} else {
|
||||
logger.info(
|
||||
'YouTubeExtractor',
|
||||
`Using HLS manifest: ${summarizeUrl(bestPlayable.videoUrl)} ${bestPlayable.height}p`
|
||||
);
|
||||
}
|
||||
return {
|
||||
videoUrl: bestHls.url,
|
||||
audioUrl: null,
|
||||
quality: `${bestHls.height}p`,
|
||||
videoUrl: bestPlayable.videoUrl,
|
||||
audioUrl: bestPlayable.audioUrl,
|
||||
quality: bestPlayable.quality,
|
||||
videoId,
|
||||
};
|
||||
}
|
||||
|
||||
// Validate progressive candidates in order, return first valid one
|
||||
for (const candidate of preferredProgressive) {
|
||||
const valid = await validateUrl(candidate.url, vrUserAgent);
|
||||
if (valid) {
|
||||
logger.info('YouTubeExtractor', `Using progressive: ${summarizeUrl(candidate.url)} ${candidate.height}p`);
|
||||
return {
|
||||
videoUrl: candidate.url,
|
||||
audioUrl: null,
|
||||
quality: `${candidate.height}p`,
|
||||
videoId,
|
||||
};
|
||||
}
|
||||
logger.warn('YouTubeExtractor', `Progressive URL invalid, trying next candidate`);
|
||||
}
|
||||
|
||||
// Last resort: video-only adaptive (no audio, but beats nothing)
|
||||
if (bestAdaptiveVideo) {
|
||||
const valid = await validateUrl(bestAdaptiveVideo.url, vrUserAgent);
|
||||
if (valid) {
|
||||
logger.warn('YouTubeExtractor', `Using video-only adaptive (no audio): ${bestAdaptiveVideo.height}p`);
|
||||
return {
|
||||
videoUrl: bestAdaptiveVideo.url,
|
||||
audioUrl: null,
|
||||
quality: `${bestAdaptiveVideo.height}p`,
|
||||
videoId,
|
||||
};
|
||||
}
|
||||
if (validatedAdaptiveVideo) {
|
||||
logger.warn('YouTubeExtractor', `Using video-only adaptive fallback (no audio): ${validatedAdaptiveVideo.height}p`);
|
||||
return {
|
||||
videoUrl: validatedAdaptiveVideo.url,
|
||||
audioUrl: null,
|
||||
quality: `${validatedAdaptiveVideo.height}p`,
|
||||
videoId,
|
||||
};
|
||||
}
|
||||
|
||||
logger.warn('YouTubeExtractor', `No playable source for videoId=${videoId}`);
|
||||
|
|
|
|||
Loading…
Reference in a new issue