mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-01-11 20:10:25 +00:00
ksp sub updates
This commit is contained in:
parent
a85cc93026
commit
eb6fcf639f
20 changed files with 171 additions and 1423 deletions
1
MPVKit
1
MPVKit
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 28de60c09651b8ca899d67456e02d285c92ceee2
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
//
|
|
||||||
// KSPlayerManager.m
|
|
||||||
// Nuvio
|
|
||||||
//
|
|
||||||
// Created by KSPlayer integration
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <React/RCTBridgeModule.h>
|
|
||||||
#import <React/RCTEventEmitter.h>
|
|
||||||
#import <React/RCTViewManager.h>
|
|
||||||
|
|
||||||
@interface RCT_EXTERN_MODULE (KSPlayerViewManager, RCTViewManager)
|
|
||||||
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(source, NSDictionary)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(paused, BOOL)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(volume, NSNumber)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(rate, NSNumber)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(audioTrack, NSNumber)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(textTrack, NSNumber)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(allowsExternalPlayback, BOOL)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(usesExternalPlaybackWhileExternalScreenIsActive, BOOL)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(subtitleBottomOffset, NSNumber)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(subtitleFontSize, NSNumber)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(subtitleTextColor, NSString)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(subtitleBackgroundColor, NSString)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(resizeMode, NSString)
|
|
||||||
|
|
||||||
// Event properties
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onLoad, RCTDirectEventBlock)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onProgress, RCTDirectEventBlock)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onBuffering, RCTDirectEventBlock)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onEnd, RCTDirectEventBlock)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onError, RCTDirectEventBlock)
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onBufferingProgress, RCTDirectEventBlock)
|
|
||||||
|
|
||||||
RCT_EXTERN_METHOD(seek : (nonnull NSNumber *)node toTime : (nonnull NSNumber *)
|
|
||||||
time)
|
|
||||||
RCT_EXTERN_METHOD(setSource : (nonnull NSNumber *)
|
|
||||||
node source : (nonnull NSDictionary *)source)
|
|
||||||
RCT_EXTERN_METHOD(setPaused : (nonnull NSNumber *)node paused : (BOOL)paused)
|
|
||||||
RCT_EXTERN_METHOD(setVolume : (nonnull NSNumber *)
|
|
||||||
node volume : (nonnull NSNumber *)volume)
|
|
||||||
RCT_EXTERN_METHOD(setPlaybackRate : (nonnull NSNumber *)
|
|
||||||
node rate : (nonnull NSNumber *)rate)
|
|
||||||
RCT_EXTERN_METHOD(setAudioTrack : (nonnull NSNumber *)
|
|
||||||
node trackId : (nonnull NSNumber *)trackId)
|
|
||||||
RCT_EXTERN_METHOD(setTextTrack : (nonnull NSNumber *)
|
|
||||||
node trackId : (nonnull NSNumber *)trackId)
|
|
||||||
RCT_EXTERN_METHOD(getTracks : (nonnull NSNumber *)node resolve : (
|
|
||||||
RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject)
|
|
||||||
RCT_EXTERN_METHOD(setAllowsExternalPlayback : (nonnull NSNumber *)
|
|
||||||
node allows : (BOOL)allows)
|
|
||||||
RCT_EXTERN_METHOD(setUsesExternalPlaybackWhileExternalScreenIsActive : (
|
|
||||||
nonnull NSNumber *)node uses : (BOOL)uses)
|
|
||||||
RCT_EXTERN_METHOD(getAirPlayState : (nonnull NSNumber *)node resolve : (
|
|
||||||
RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject)
|
|
||||||
RCT_EXTERN_METHOD(showAirPlayPicker : (nonnull NSNumber *)node)
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface RCT_EXTERN_MODULE (KSPlayerModule, RCTEventEmitter)
|
|
||||||
|
|
||||||
RCT_EXTERN_METHOD(getTracks : (NSNumber *)nodeTag resolve : (
|
|
||||||
RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject)
|
|
||||||
RCT_EXTERN_METHOD(getAirPlayState : (NSNumber *)nodeTag resolve : (
|
|
||||||
RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject)
|
|
||||||
RCT_EXTERN_METHOD(showAirPlayPicker : (NSNumber *)nodeTag)
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
//
|
|
||||||
// KSPlayerModule.swift
|
|
||||||
// Nuvio
|
|
||||||
//
|
|
||||||
// Created by KSPlayer integration
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import KSPlayer
|
|
||||||
import React
|
|
||||||
|
|
||||||
@objc(KSPlayerModule)
|
|
||||||
class KSPlayerModule: RCTEventEmitter {
|
|
||||||
override static func requiresMainQueueSetup() -> Bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override func supportedEvents() -> [String]! {
|
|
||||||
return [
|
|
||||||
"KSPlayer-onLoad",
|
|
||||||
"KSPlayer-onProgress",
|
|
||||||
"KSPlayer-onBuffering",
|
|
||||||
"KSPlayer-onEnd",
|
|
||||||
"KSPlayer-onError"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func getTracks(_ nodeTag: NSNumber?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
||||||
guard let nodeTag = nodeTag else {
|
|
||||||
reject("INVALID_ARGUMENT", "nodeTag must not be nil", nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let viewManager = self.bridge.module(for: KSPlayerViewManager.self) as? KSPlayerViewManager {
|
|
||||||
viewManager.getTracks(nodeTag, resolve: resolve, reject: reject)
|
|
||||||
} else {
|
|
||||||
reject("NO_VIEW_MANAGER", "KSPlayerViewManager not found", nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func getAirPlayState(_ nodeTag: NSNumber?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
||||||
guard let nodeTag = nodeTag else {
|
|
||||||
reject("INVALID_ARGUMENT", "nodeTag must not be nil", nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let viewManager = self.bridge.module(for: KSPlayerViewManager.self) as? KSPlayerViewManager {
|
|
||||||
viewManager.getAirPlayState(nodeTag, resolve: resolve, reject: reject)
|
|
||||||
} else {
|
|
||||||
reject("NO_VIEW_MANAGER", "KSPlayerViewManager not found", nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func showAirPlayPicker(_ nodeTag: NSNumber?) {
|
|
||||||
guard let nodeTag = nodeTag else {
|
|
||||||
print("[KSPlayerModule] showAirPlayPicker called with nil nodeTag")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
print("[KSPlayerModule] showAirPlayPicker called for nodeTag: \(nodeTag)")
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let viewManager = self.bridge.module(for: KSPlayerViewManager.self) as? KSPlayerViewManager {
|
|
||||||
print("[KSPlayerModule] Found KSPlayerViewManager, calling showAirPlayPicker")
|
|
||||||
viewManager.showAirPlayPicker(nodeTag)
|
|
||||||
} else {
|
|
||||||
print("[KSPlayerModule] Could not find KSPlayerViewManager")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,152 +0,0 @@
|
||||||
//
|
|
||||||
// KSPlayerViewManager.swift
|
|
||||||
// Nuvio
|
|
||||||
//
|
|
||||||
// Created by KSPlayer integration
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import KSPlayer
|
|
||||||
import React
|
|
||||||
|
|
||||||
@objc(KSPlayerViewManager)
|
|
||||||
class KSPlayerViewManager: RCTViewManager {
|
|
||||||
|
|
||||||
// Not needed for RCTViewManager-based views; events are exported via Objective-C externs in KSPlayerManager.m
|
|
||||||
override func view() -> UIView! {
|
|
||||||
let view = KSPlayerView()
|
|
||||||
view.viewManager = self
|
|
||||||
return view
|
|
||||||
}
|
|
||||||
|
|
||||||
override static func requiresMainQueueSetup() -> Bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override func constantsToExport() -> [AnyHashable : Any]! {
|
|
||||||
return [
|
|
||||||
"EventTypes": [
|
|
||||||
"onLoad": "onLoad",
|
|
||||||
"onProgress": "onProgress",
|
|
||||||
"onBuffering": "onBuffering",
|
|
||||||
"onEnd": "onEnd",
|
|
||||||
"onError": "onError",
|
|
||||||
"onBufferingProgress": "onBufferingProgress"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// No-op: events are sent via direct event blocks on the view
|
|
||||||
|
|
||||||
@objc func seek(_ node: NSNumber, toTime time: NSNumber) {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let view = self.bridge.uiManager.view(forReactTag: node) as? KSPlayerView {
|
|
||||||
view.seek(to: TimeInterval(truncating: time))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func setSource(_ node: NSNumber, source: NSDictionary) {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let view = self.bridge.uiManager.view(forReactTag: node) as? KSPlayerView {
|
|
||||||
view.setSource(source)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func setPaused(_ node: NSNumber, paused: Bool) {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let view = self.bridge.uiManager.view(forReactTag: node) as? KSPlayerView {
|
|
||||||
view.setPaused(paused)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func setVolume(_ node: NSNumber, volume: NSNumber) {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let view = self.bridge.uiManager.view(forReactTag: node) as? KSPlayerView {
|
|
||||||
view.setVolume(Float(truncating: volume))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func setPlaybackRate(_ node: NSNumber, rate: NSNumber) {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let view = self.bridge.uiManager.view(forReactTag: node) as? KSPlayerView {
|
|
||||||
view.setPlaybackRate(Float(truncating: rate))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func setAudioTrack(_ node: NSNumber, trackId: NSNumber) {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let view = self.bridge.uiManager.view(forReactTag: node) as? KSPlayerView {
|
|
||||||
view.setAudioTrack(Int(truncating: trackId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func setTextTrack(_ node: NSNumber, trackId: NSNumber) {
|
|
||||||
NSLog("[KSPlayerViewManager] setTextTrack called - node: %@, trackId: %@", node, trackId)
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
NSLog("[KSPlayerViewManager] setTextTrack on main queue - looking for view with tag: %@", node)
|
|
||||||
if let view = self.bridge.uiManager.view(forReactTag: node) as? KSPlayerView {
|
|
||||||
NSLog("[KSPlayerViewManager] Found view, calling setTextTrack(%d)", Int(truncating: trackId))
|
|
||||||
view.setTextTrack(Int(truncating: trackId))
|
|
||||||
} else {
|
|
||||||
NSLog("[KSPlayerViewManager] ERROR - Could not find KSPlayerView for tag: %@", node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func getTracks(_ node: NSNumber, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let view = self.bridge.uiManager.view(forReactTag: node) as? KSPlayerView {
|
|
||||||
let tracks = view.getAvailableTracks()
|
|
||||||
resolve(tracks)
|
|
||||||
} else {
|
|
||||||
reject("NO_VIEW", "KSPlayerView not found", nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AirPlay methods
|
|
||||||
@objc func setAllowsExternalPlayback(_ node: NSNumber, allows: Bool) {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let view = self.bridge.uiManager.view(forReactTag: node) as? KSPlayerView {
|
|
||||||
view.setAllowsExternalPlayback(allows)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func setUsesExternalPlaybackWhileExternalScreenIsActive(_ node: NSNumber, uses: Bool) {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let view = self.bridge.uiManager.view(forReactTag: node) as? KSPlayerView {
|
|
||||||
view.setUsesExternalPlaybackWhileExternalScreenIsActive(uses)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func getAirPlayState(_ node: NSNumber, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let view = self.bridge.uiManager.view(forReactTag: node) as? KSPlayerView {
|
|
||||||
let airPlayState = view.getAirPlayState()
|
|
||||||
resolve(airPlayState)
|
|
||||||
} else {
|
|
||||||
reject("NO_VIEW", "KSPlayerView not found", nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func showAirPlayPicker(_ node: NSNumber) {
|
|
||||||
print("[KSPlayerViewManager] showAirPlayPicker called for node: \(node)")
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let view = self.bridge.uiManager.view(forReactTag: node) as? KSPlayerView {
|
|
||||||
print("[KSPlayerViewManager] Found KSPlayerView, calling showAirPlayPicker")
|
|
||||||
view.showAirPlayPicker()
|
|
||||||
} else {
|
|
||||||
print("[KSPlayerViewManager] Could not find KSPlayerView for node: \(node)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -11,12 +11,12 @@
|
||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||||
2AA769395C1242F225F875AF /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E007C0BAC8C453623E81663 /* ExpoModulesProvider.swift */; };
|
2AA769395C1242F225F875AF /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E007C0BAC8C453623E81663 /* ExpoModulesProvider.swift */; };
|
||||||
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
|
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
|
||||||
72D4090694139E0DAD9B066E /* libPods-Nuvio.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 406CD0CEF46F8EAEEAD92BF7 /* libPods-Nuvio.a */; };
|
|
||||||
9FBA88F42E86ECD700892850 /* KSPlayerViewManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FBA88F32E86ECD700892850 /* KSPlayerViewManager.swift */; };
|
9FBA88F42E86ECD700892850 /* KSPlayerViewManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FBA88F32E86ECD700892850 /* KSPlayerViewManager.swift */; };
|
||||||
9FBA88F52E86ECD700892850 /* KSPlayerModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FBA88F12E86ECD700892850 /* KSPlayerModule.swift */; };
|
9FBA88F52E86ECD700892850 /* KSPlayerModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FBA88F12E86ECD700892850 /* KSPlayerModule.swift */; };
|
||||||
9FBA88F62E86ECD700892850 /* KSPlayerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FBA88F02E86ECD700892850 /* KSPlayerManager.m */; };
|
9FBA88F62E86ECD700892850 /* KSPlayerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FBA88F02E86ECD700892850 /* KSPlayerManager.m */; };
|
||||||
9FBA88F72E86ECD700892850 /* KSPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FBA88F22E86ECD700892850 /* KSPlayerView.swift */; };
|
9FBA88F72E86ECD700892850 /* KSPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FBA88F22E86ECD700892850 /* KSPlayerView.swift */; };
|
||||||
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
|
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
|
||||||
|
D66ACCC72CB69F1FF14A2585 /* libPods-Nuvio.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 436A6FCA2C83F29076E121BA /* libPods-Nuvio.a */; };
|
||||||
F11748422D0307B40044C1D9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11748412D0307B40044C1D9 /* AppDelegate.swift */; };
|
F11748422D0307B40044C1D9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11748412D0307B40044C1D9 /* AppDelegate.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
|
@ -24,16 +24,16 @@
|
||||||
13B07F961A680F5B00A75B9A /* Nuvio.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Nuvio.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
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>"; };
|
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>"; };
|
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Nuvio/Info.plist; sourceTree = "<group>"; };
|
||||||
15864A7148A4384BAA9F0B37 /* 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>"; };
|
436A6FCA2C83F29076E121BA /* libPods-Nuvio.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Nuvio.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
406CD0CEF46F8EAEEAD92BF7 /* libPods-Nuvio.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Nuvio.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
49055D6E250FAFA21141FE49 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = Nuvio/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
49055D6E250FAFA21141FE49 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = Nuvio/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||||
|
5346BAA9EF8C9C8182D4485C /* 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>"; };
|
||||||
6E007C0BAC8C453623E81663 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-Nuvio/ExpoModulesProvider.swift"; 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>"; };
|
||||||
73BB213C2E9EEAC700EC03F8 /* NuvioRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = NuvioRelease.entitlements; path = Nuvio/NuvioRelease.entitlements; sourceTree = "<group>"; };
|
73BB213C2E9EEAC700EC03F8 /* NuvioRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = NuvioRelease.entitlements; path = Nuvio/NuvioRelease.entitlements; sourceTree = "<group>"; };
|
||||||
819F6DCD44DFE0C72440FDCF /* 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>"; };
|
904B4A0A0308D3727268BA5E /* 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>"; };
|
||||||
9FBA88F02E86ECD700892850 /* KSPlayerManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KSPlayerManager.m; 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 = KSPlayerModule.swift; 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 = KSPlayerView.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 = KSPlayerViewManager.swift; sourceTree = "<group>"; };
|
9FBA88F32E86ECD700892850 /* KSPlayerViewManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ../KSPlayer/RNBridge/KSPlayerViewManager.swift; sourceTree = "<group>"; };
|
||||||
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = Nuvio/SplashScreen.storyboard; sourceTree = "<group>"; };
|
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = Nuvio/SplashScreen.storyboard; sourceTree = "<group>"; };
|
||||||
BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; };
|
BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; };
|
||||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
72D4090694139E0DAD9B066E /* libPods-Nuvio.a in Frameworks */,
|
D66ACCC72CB69F1FF14A2585 /* libPods-Nuvio.a in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -76,7 +76,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||||
406CD0CEF46F8EAEEAD92BF7 /* libPods-Nuvio.a */,
|
436A6FCA2C83F29076E121BA /* libPods-Nuvio.a */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -131,8 +131,8 @@
|
||||||
D90A3959C97EE9926C513293 /* Pods */ = {
|
D90A3959C97EE9926C513293 /* Pods */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
819F6DCD44DFE0C72440FDCF /* Pods-Nuvio.debug.xcconfig */,
|
904B4A0A0308D3727268BA5E /* Pods-Nuvio.debug.xcconfig */,
|
||||||
15864A7148A4384BAA9F0B37 /* Pods-Nuvio.release.xcconfig */,
|
5346BAA9EF8C9C8182D4485C /* Pods-Nuvio.release.xcconfig */,
|
||||||
);
|
);
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -152,15 +152,15 @@
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Nuvio" */;
|
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Nuvio" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
E060D0359630A7C0F4793812 /* [CP] Check Pods Manifest.lock */,
|
3B2D9C1D63379C2F30AC0F2B /* [CP] Check Pods Manifest.lock */,
|
||||||
99A79B70155E84EE1FB7F466 /* [Expo] Configure project */,
|
99A79B70155E84EE1FB7F466 /* [Expo] Configure project */,
|
||||||
13B07F871A680F5B00A75B9A /* Sources */,
|
13B07F871A680F5B00A75B9A /* Sources */,
|
||||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||||
9B977D89FE30470F8C59964C /* Upload Debug Symbols to Sentry */,
|
9B977D89FE30470F8C59964C /* Upload Debug Symbols to Sentry */,
|
||||||
B84E40F81DF927F34032D68B /* [CP] Embed Pods Frameworks */,
|
9F740EE07B5F97C85979C145 /* [CP] Embed Pods Frameworks */,
|
||||||
AA47AE6072D35F0490B53926 /* [CP] Copy Pods Resources */,
|
550CD54859274FE505BA4957 /* [CP] Copy Pods Resources */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
|
|
@ -234,45 +234,29 @@
|
||||||
shellPath = /bin/sh;
|
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";
|
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";
|
||||||
};
|
};
|
||||||
99A79B70155E84EE1FB7F466 /* [Expo] Configure project */ = {
|
3B2D9C1D63379C2F30AC0F2B /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
"$(SRCROOT)/.xcode.env",
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
"$(SRCROOT)/.xcode.env.local",
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
"$(SRCROOT)/Nuvio/Nuvio.entitlements",
|
|
||||||
"$(SRCROOT)/Pods/Target Support Files/Pods-Nuvio/expo-configure-project.sh",
|
|
||||||
);
|
);
|
||||||
name = "[Expo] Configure project";
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
);
|
);
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
"$(SRCROOT)/Pods/Target Support Files/Pods-Nuvio/ExpoModulesProvider.swift",
|
"$(DERIVED_FILE_DIR)/Pods-Nuvio-checkManifestLockResult.txt",
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
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";
|
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;
|
||||||
};
|
};
|
||||||
9B977D89FE30470F8C59964C /* Upload Debug Symbols to Sentry */ = {
|
550CD54859274FE505BA4957 /* [CP] Copy Pods Resources */ = {
|
||||||
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'\"`";
|
|
||||||
};
|
|
||||||
AA47AE6072D35F0490B53926 /* [CP] Copy Pods Resources */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
|
@ -384,7 +368,45 @@
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Nuvio/Pods-Nuvio-resources.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Nuvio/Pods-Nuvio-resources.sh\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
B84E40F81DF927F34032D68B /* [CP] Embed Pods Frameworks */ = {
|
99A79B70155E84EE1FB7F466 /* [Expo] Configure project */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
alwaysOutOfDate = 1;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"$(SRCROOT)/.xcode.env",
|
||||||
|
"$(SRCROOT)/.xcode.env.local",
|
||||||
|
"$(SRCROOT)/Nuvio/Nuvio.entitlements",
|
||||||
|
"$(SRCROOT)/Pods/Target Support Files/Pods-Nuvio/expo-configure-project.sh",
|
||||||
|
);
|
||||||
|
name = "[Expo] Configure project";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(SRCROOT)/Pods/Target Support Files/Pods-Nuvio/ExpoModulesProvider.swift",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
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'\"`";
|
||||||
|
};
|
||||||
|
9F740EE07B5F97C85979C145 /* [CP] Embed Pods Frameworks */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
|
@ -406,28 +428,6 @@
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Nuvio/Pods-Nuvio-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Nuvio/Pods-Nuvio-frameworks.sh\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
E060D0359630A7C0F4793812 /* [CP] Check Pods Manifest.lock */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
|
||||||
"${PODS_ROOT}/Manifest.lock",
|
|
||||||
);
|
|
||||||
name = "[CP] Check Pods Manifest.lock";
|
|
||||||
outputFileListPaths = (
|
|
||||||
);
|
|
||||||
outputPaths = (
|
|
||||||
"$(DERIVED_FILE_DIR)/Pods-Nuvio-checkManifestLockResult.txt",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
|
@ -449,7 +449,7 @@
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 819F6DCD44DFE0C72440FDCF /* Pods-Nuvio.debug.xcconfig */;
|
baseConfigurationReference = 904B4A0A0308D3727268BA5E /* Pods-Nuvio.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
|
@ -487,7 +487,7 @@
|
||||||
};
|
};
|
||||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 15864A7148A4384BAA9F0B37 /* Pods-Nuvio.release.xcconfig */;
|
baseConfigurationReference = 5346BAA9EF8C9C8182D4485C /* Pods-Nuvio.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,9 @@ target 'Nuvio' do
|
||||||
)
|
)
|
||||||
|
|
||||||
# KSPlayer dependencies
|
# KSPlayer dependencies
|
||||||
pod 'KSPlayer', :git => 'https://github.com/kingslay/KSPlayer.git', :branch => 'main'
|
# Use the local checkout so we can patch subtitle rendering (and other behaviors) without forking.
|
||||||
pod 'DisplayCriteria', :git => 'https://github.com/kingslay/KSPlayer.git', :branch => 'main', :modular_headers => true
|
pod 'KSPlayer', :path => '../KSPlayer'
|
||||||
|
pod 'DisplayCriteria', :path => '../KSPlayer', :modular_headers => true
|
||||||
pod 'FFmpegKit', :git => 'https://github.com/kingslay/FFmpegKit.git', :branch => 'main', :modular_headers => true
|
pod 'FFmpegKit', :git => 'https://github.com/kingslay/FFmpegKit.git', :branch => 'main', :modular_headers => true
|
||||||
pod 'Libass', :git => 'https://github.com/kingslay/FFmpegKit.git', :branch => 'main'
|
pod 'Libass', :git => 'https://github.com/kingslay/FFmpegKit.git', :branch => 'main'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2760,7 +2760,7 @@ PODS:
|
||||||
- Yoga (0.0.0)
|
- Yoga (0.0.0)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- DisplayCriteria (from `https://github.com/kingslay/KSPlayer.git`, branch `main`)
|
- DisplayCriteria (from `../KSPlayer`)
|
||||||
- EASClient (from `../node_modules/expo-eas-client/ios`)
|
- EASClient (from `../node_modules/expo-eas-client/ios`)
|
||||||
- EXApplication (from `../node_modules/expo-application/ios`)
|
- EXApplication (from `../node_modules/expo-application/ios`)
|
||||||
- EXConstants (from `../node_modules/expo-constants/ios`)
|
- EXConstants (from `../node_modules/expo-constants/ios`)
|
||||||
|
|
@ -2800,7 +2800,7 @@ DEPENDENCIES:
|
||||||
- FFmpegKit (from `https://github.com/kingslay/FFmpegKit.git`, branch `main`)
|
- FFmpegKit (from `https://github.com/kingslay/FFmpegKit.git`, branch `main`)
|
||||||
- hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
|
- hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
|
||||||
- ImageColors (from `../node_modules/react-native-image-colors/ios`)
|
- ImageColors (from `../node_modules/react-native-image-colors/ios`)
|
||||||
- KSPlayer (from `https://github.com/kingslay/KSPlayer.git`, branch `main`)
|
- KSPlayer (from `../KSPlayer`)
|
||||||
- Libass (from `https://github.com/kingslay/FFmpegKit.git`, branch `main`)
|
- Libass (from `https://github.com/kingslay/FFmpegKit.git`, branch `main`)
|
||||||
- lottie-react-native (from `../node_modules/lottie-react-native`)
|
- lottie-react-native (from `../node_modules/lottie-react-native`)
|
||||||
- NitroMmkv (from `../node_modules/react-native-mmkv`)
|
- NitroMmkv (from `../node_modules/react-native-mmkv`)
|
||||||
|
|
@ -2910,8 +2910,7 @@ SPEC REPOS:
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
DisplayCriteria:
|
DisplayCriteria:
|
||||||
:branch: main
|
:path: "../KSPlayer"
|
||||||
:git: https://github.com/kingslay/KSPlayer.git
|
|
||||||
EASClient:
|
EASClient:
|
||||||
:path: "../node_modules/expo-eas-client/ios"
|
:path: "../node_modules/expo-eas-client/ios"
|
||||||
EXApplication:
|
EXApplication:
|
||||||
|
|
@ -2993,8 +2992,7 @@ EXTERNAL SOURCES:
|
||||||
ImageColors:
|
ImageColors:
|
||||||
:path: "../node_modules/react-native-image-colors/ios"
|
:path: "../node_modules/react-native-image-colors/ios"
|
||||||
KSPlayer:
|
KSPlayer:
|
||||||
:branch: main
|
:path: "../KSPlayer"
|
||||||
:git: https://github.com/kingslay/KSPlayer.git
|
|
||||||
Libass:
|
Libass:
|
||||||
:branch: main
|
:branch: main
|
||||||
:git: https://github.com/kingslay/FFmpegKit.git
|
:git: https://github.com/kingslay/FFmpegKit.git
|
||||||
|
|
@ -3174,15 +3172,9 @@ EXTERNAL SOURCES:
|
||||||
:path: "../node_modules/react-native/ReactCommon/yoga"
|
:path: "../node_modules/react-native/ReactCommon/yoga"
|
||||||
|
|
||||||
CHECKOUT OPTIONS:
|
CHECKOUT OPTIONS:
|
||||||
DisplayCriteria:
|
|
||||||
:commit: a7cddd878f557afa6a1f2faad9d756949406adde
|
|
||||||
:git: https://github.com/kingslay/KSPlayer.git
|
|
||||||
FFmpegKit:
|
FFmpegKit:
|
||||||
:commit: d7048037a2eb94a3b08113fbf43aa92bdcb332d9
|
:commit: d7048037a2eb94a3b08113fbf43aa92bdcb332d9
|
||||||
:git: https://github.com/kingslay/FFmpegKit.git
|
:git: https://github.com/kingslay/FFmpegKit.git
|
||||||
KSPlayer:
|
|
||||||
:commit: a7cddd878f557afa6a1f2faad9d756949406adde
|
|
||||||
:git: https://github.com/kingslay/KSPlayer.git
|
|
||||||
Libass:
|
Libass:
|
||||||
:commit: d7048037a2eb94a3b08113fbf43aa92bdcb332d9
|
:commit: d7048037a2eb94a3b08113fbf43aa92bdcb332d9
|
||||||
:git: https://github.com/kingslay/FFmpegKit.git
|
:git: https://github.com/kingslay/FFmpegKit.git
|
||||||
|
|
@ -3332,6 +3324,6 @@ SPEC CHECKSUMS:
|
||||||
SwiftUIIntrospect: fee9aa07293ee280373a591e1824e8ddc869ba5d
|
SwiftUIIntrospect: fee9aa07293ee280373a591e1824e8ddc869ba5d
|
||||||
Yoga: 051f086b5ccf465ff2ed38a2cf5a558ae01aaaa1
|
Yoga: 051f086b5ccf465ff2ed38a2cf5a558ae01aaaa1
|
||||||
|
|
||||||
PODFILE CHECKSUM: 7c74c9cd2c7f3df7ab68b4284d9f324282e54542
|
PODFILE CHECKSUM: b884d1ff07ac4a43323bce2e2e1342592513858c
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ interface KSPlayerViewProps {
|
||||||
subtitleFontSize?: number;
|
subtitleFontSize?: number;
|
||||||
subtitleTextColor?: string;
|
subtitleTextColor?: string;
|
||||||
subtitleBackgroundColor?: string;
|
subtitleBackgroundColor?: string;
|
||||||
|
subtitleOutlineEnabled?: boolean;
|
||||||
resizeMode?: 'contain' | 'cover' | 'stretch';
|
resizeMode?: 'contain' | 'cover' | 'stretch';
|
||||||
onLoad?: (data: any) => void;
|
onLoad?: (data: any) => void;
|
||||||
onProgress?: (data: any) => void;
|
onProgress?: (data: any) => void;
|
||||||
|
|
@ -60,6 +61,7 @@ export interface KSPlayerProps {
|
||||||
subtitleFontSize?: number;
|
subtitleFontSize?: number;
|
||||||
subtitleTextColor?: string;
|
subtitleTextColor?: string;
|
||||||
subtitleBackgroundColor?: string;
|
subtitleBackgroundColor?: string;
|
||||||
|
subtitleOutlineEnabled?: boolean;
|
||||||
resizeMode?: 'contain' | 'cover' | 'stretch';
|
resizeMode?: 'contain' | 'cover' | 'stretch';
|
||||||
onLoad?: (data: any) => void;
|
onLoad?: (data: any) => void;
|
||||||
onProgress?: (data: any) => void;
|
onProgress?: (data: any) => void;
|
||||||
|
|
@ -210,6 +212,7 @@ const KSPlayer = forwardRef<KSPlayerRef, KSPlayerProps>((props, ref) => {
|
||||||
subtitleFontSize={props.subtitleFontSize}
|
subtitleFontSize={props.subtitleFontSize}
|
||||||
subtitleTextColor={props.subtitleTextColor}
|
subtitleTextColor={props.subtitleTextColor}
|
||||||
subtitleBackgroundColor={props.subtitleBackgroundColor}
|
subtitleBackgroundColor={props.subtitleBackgroundColor}
|
||||||
|
subtitleOutlineEnabled={props.subtitleOutlineEnabled}
|
||||||
resizeMode={props.resizeMode}
|
resizeMode={props.resizeMode}
|
||||||
onLoad={(e: any) => props.onLoad?.(e?.nativeEvent ?? e)}
|
onLoad={(e: any) => props.onLoad?.(e?.nativeEvent ?? e)}
|
||||||
onProgress={(e: any) => props.onProgress?.(e?.nativeEvent ?? e)}
|
onProgress={(e: any) => props.onProgress?.(e?.nativeEvent ?? e)}
|
||||||
|
|
|
||||||
|
|
@ -616,6 +616,10 @@ const KSPlayerCore: React.FC = () => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Video Surface & Pinch Zoom */}
|
{/* Video Surface & Pinch Zoom */}
|
||||||
|
{/*
|
||||||
|
For KSPlayer built-in subtitles (internal text tracks), we intentionally force background OFF.
|
||||||
|
Background styling is only supported/used for custom (external/addon) subtitles overlay.
|
||||||
|
*/}
|
||||||
<KSPlayerSurface
|
<KSPlayerSurface
|
||||||
ksPlayerRef={ksPlayerRef}
|
ksPlayerRef={ksPlayerRef}
|
||||||
uri={uri}
|
uri={uri}
|
||||||
|
|
@ -656,7 +660,20 @@ const KSPlayerCore: React.FC = () => {
|
||||||
screenHeight={screenDimensions.height}
|
screenHeight={screenDimensions.height}
|
||||||
customVideoStyles={{ width: '100%', height: '100%' }}
|
customVideoStyles={{ width: '100%', height: '100%' }}
|
||||||
subtitleTextColor={customSubs.subtitleTextColor}
|
subtitleTextColor={customSubs.subtitleTextColor}
|
||||||
subtitleBackgroundColor={customSubs.subtitleBackground ? `rgba(0,0,0,${customSubs.subtitleBgOpacity})` : 'transparent'}
|
subtitleBackgroundColor={
|
||||||
|
tracks.selectedTextTrack !== null &&
|
||||||
|
tracks.selectedTextTrack >= 0 &&
|
||||||
|
!customSubs.useCustomSubtitles
|
||||||
|
? 'rgba(0,0,0,0)'
|
||||||
|
: (customSubs.subtitleBackground ? `rgba(0,0,0,${customSubs.subtitleBgOpacity})` : 'transparent')
|
||||||
|
}
|
||||||
|
subtitleOutlineEnabled={
|
||||||
|
tracks.selectedTextTrack !== null &&
|
||||||
|
tracks.selectedTextTrack >= 0 &&
|
||||||
|
!customSubs.useCustomSubtitles
|
||||||
|
? customSubs.subtitleOutline
|
||||||
|
: false
|
||||||
|
}
|
||||||
subtitleFontSize={customSubs.subtitleSize}
|
subtitleFontSize={customSubs.subtitleSize}
|
||||||
subtitleBottomOffset={customSubs.subtitleBottomOffset}
|
subtitleBottomOffset={customSubs.subtitleBottomOffset}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ interface KSPlayerSurfaceProps {
|
||||||
subtitleBackgroundColor?: string;
|
subtitleBackgroundColor?: string;
|
||||||
subtitleFontSize?: number;
|
subtitleFontSize?: number;
|
||||||
subtitleBottomOffset?: number;
|
subtitleBottomOffset?: number;
|
||||||
|
subtitleOutlineEnabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const KSPlayerSurface: React.FC<KSPlayerSurfaceProps> = ({
|
export const KSPlayerSurface: React.FC<KSPlayerSurfaceProps> = ({
|
||||||
|
|
@ -74,7 +75,8 @@ export const KSPlayerSurface: React.FC<KSPlayerSurfaceProps> = ({
|
||||||
subtitleTextColor,
|
subtitleTextColor,
|
||||||
subtitleBackgroundColor,
|
subtitleBackgroundColor,
|
||||||
subtitleFontSize,
|
subtitleFontSize,
|
||||||
subtitleBottomOffset
|
subtitleBottomOffset,
|
||||||
|
subtitleOutlineEnabled
|
||||||
}) => {
|
}) => {
|
||||||
const pinchRef = useRef<PinchGestureHandler>(null);
|
const pinchRef = useRef<PinchGestureHandler>(null);
|
||||||
|
|
||||||
|
|
@ -146,6 +148,7 @@ export const KSPlayerSurface: React.FC<KSPlayerSurfaceProps> = ({
|
||||||
subtitleBackgroundColor={subtitleBackgroundColor}
|
subtitleBackgroundColor={subtitleBackgroundColor}
|
||||||
subtitleFontSize={subtitleFontSize}
|
subtitleFontSize={subtitleFontSize}
|
||||||
subtitleBottomOffset={subtitleBottomOffset}
|
subtitleBottomOffset={subtitleBottomOffset}
|
||||||
|
subtitleOutlineEnabled={subtitleOutlineEnabled}
|
||||||
onLoad={handleLoad}
|
onLoad={handleLoad}
|
||||||
onProgress={onProgress}
|
onProgress={onProgress}
|
||||||
onBuffering={handleBuffering}
|
onBuffering={handleBuffering}
|
||||||
|
|
|
||||||
|
|
@ -239,7 +239,8 @@ export const SubtitleModals: React.FC<SubtitleModalsProps> = ({
|
||||||
<View style={{ height: previewHeight, justifyContent: 'flex-end' }}>
|
<View style={{ height: previewHeight, justifyContent: 'flex-end' }}>
|
||||||
<View style={{ alignItems: subtitleAlign === 'center' ? 'center' : subtitleAlign === 'left' ? 'flex-start' : 'flex-end', marginBottom: Math.min(80, subtitleBottomOffset) }}>
|
<View style={{ alignItems: subtitleAlign === 'center' ? 'center' : subtitleAlign === 'left' ? 'flex-start' : 'flex-end', marginBottom: Math.min(80, subtitleBottomOffset) }}>
|
||||||
<View style={{
|
<View style={{
|
||||||
backgroundColor: subtitleBackground ? `rgba(0,0,0,${subtitleBgOpacity})` : 'transparent',
|
// Built-in (KSPlayer internal) subtitles: force background off in UI preview.
|
||||||
|
backgroundColor: isUsingInternalSubtitle ? 'transparent' : (subtitleBackground ? `rgba(0,0,0,${subtitleBgOpacity})` : 'transparent'),
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
paddingHorizontal: isCompact ? 10 : 12,
|
paddingHorizontal: isCompact ? 10 : 12,
|
||||||
paddingVertical: isCompact ? 6 : 8,
|
paddingVertical: isCompact ? 6 : 8,
|
||||||
|
|
@ -331,19 +332,21 @@ export const SubtitleModals: React.FC<SubtitleModalsProps> = ({
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{/* Show Background */}
|
{/* Background is only for CustomSubtitles (external/addon). Built-in subtitles force background OFF. */}
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
{!isUsingInternalSubtitle && (
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||||
<MaterialIcons name="layers" size={16} color="rgba(255,255,255,0.7)" />
|
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||||
<Text style={{ color: '#fff', fontWeight: '600', marginLeft: 8 }}>{t('player_ui.show_background')}</Text>
|
<MaterialIcons name="layers" size={16} color="rgba(255,255,255,0.7)" />
|
||||||
|
<Text style={{ color: '#fff', fontWeight: '600', marginLeft: 8 }}>{t('player_ui.show_background')}</Text>
|
||||||
|
</View>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{ width: isCompact ? 48 : 54, height: isCompact ? 28 : 30, backgroundColor: subtitleBackground ? 'white' : 'rgba(255,255,255,0.25)', borderRadius: 15, justifyContent: 'center', alignItems: subtitleBackground ? 'flex-end' : 'flex-start', paddingHorizontal: 3 }}
|
||||||
|
onPress={toggleSubtitleBackground}
|
||||||
|
>
|
||||||
|
<View style={{ width: 24, height: 24, backgroundColor: subtitleBackground ? 'black' : 'white', borderRadius: 12 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<TouchableOpacity
|
)}
|
||||||
style={{ width: isCompact ? 48 : 54, height: isCompact ? 28 : 30, backgroundColor: subtitleBackground ? 'white' : 'rgba(255,255,255,0.25)', borderRadius: 15, justifyContent: 'center', alignItems: subtitleBackground ? 'flex-end' : 'flex-start', paddingHorizontal: 3 }}
|
|
||||||
onPress={toggleSubtitleBackground}
|
|
||||||
>
|
|
||||||
<View style={{ width: 24, height: 24, backgroundColor: subtitleBackground ? 'black' : 'white', borderRadius: 12 }} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Advanced controls */}
|
{/* Advanced controls */}
|
||||||
|
|
@ -392,21 +395,23 @@ export const SubtitleModals: React.FC<SubtitleModalsProps> = ({
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{/* Background Opacity */}
|
{/* Background Opacity (CustomSubtitles only) */}
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
{!isUsingInternalSubtitle && (
|
||||||
<Text style={{ color: 'white', fontWeight: '600' }}>{t('player_ui.background_opacity')}</Text>
|
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||||
<View style={{ flexDirection: 'row', gap: 8, alignItems: 'center' }}>
|
<Text style={{ color: 'white', fontWeight: '600' }}>{t('player_ui.background_opacity')}</Text>
|
||||||
<TouchableOpacity onPress={() => setSubtitleBgOpacity(Math.max(0, +(subtitleBgOpacity - 0.1).toFixed(1)))} style={{ width: controlBtn.size, height: controlBtn.size, borderRadius: controlBtn.radius, backgroundColor: 'rgba(255,255,255,0.18)', alignItems: 'center', justifyContent: 'center' }}>
|
<View style={{ flexDirection: 'row', gap: 8, alignItems: 'center' }}>
|
||||||
<MaterialIcons name="remove" color="#fff" size={18} />
|
<TouchableOpacity onPress={() => setSubtitleBgOpacity(Math.max(0, +(subtitleBgOpacity - 0.1).toFixed(1)))} style={{ width: controlBtn.size, height: controlBtn.size, borderRadius: controlBtn.radius, backgroundColor: 'rgba(255,255,255,0.18)', alignItems: 'center', justifyContent: 'center' }}>
|
||||||
</TouchableOpacity>
|
<MaterialIcons name="remove" color="#fff" size={18} />
|
||||||
<View style={{ minWidth: 48, paddingHorizontal: 6, paddingVertical: 4, borderRadius: 10, backgroundColor: 'rgba(255,255,255,0.12)' }}>
|
</TouchableOpacity>
|
||||||
<Text style={{ color: 'white', textAlign: 'center', fontWeight: '700' }}>{subtitleBgOpacity.toFixed(1)}</Text>
|
<View style={{ minWidth: 48, paddingHorizontal: 6, paddingVertical: 4, borderRadius: 10, backgroundColor: 'rgba(255,255,255,0.12)' }}>
|
||||||
|
<Text style={{ color: 'white', textAlign: 'center', fontWeight: '700' }}>{subtitleBgOpacity.toFixed(1)}</Text>
|
||||||
|
</View>
|
||||||
|
<TouchableOpacity onPress={() => setSubtitleBgOpacity(Math.min(1, +(subtitleBgOpacity + 0.1).toFixed(1)))} style={{ width: controlBtn.size, height: controlBtn.size, borderRadius: controlBtn.radius, backgroundColor: 'rgba(255,255,255,0.18)', alignItems: 'center', justifyContent: 'center' }}>
|
||||||
|
<MaterialIcons name="add" color="#fff" size={18} />
|
||||||
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<TouchableOpacity onPress={() => setSubtitleBgOpacity(Math.min(1, +(subtitleBgOpacity + 0.1).toFixed(1)))} style={{ width: controlBtn.size, height: controlBtn.size, borderRadius: controlBtn.radius, backgroundColor: 'rgba(255,255,255,0.18)', alignItems: 'center', justifyContent: 'center' }}>
|
|
||||||
<MaterialIcons name="add" color="#fff" size={18} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
)}
|
||||||
{!isUsingInternalSubtitle && (
|
{!isUsingInternalSubtitle && (
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||||
<Text style={{ color: 'white', fontWeight: '600' }}>{t('player_ui.text_shadow')}</Text>
|
<Text style={{ color: 'white', fontWeight: '600' }}>{t('player_ui.text_shadow')}</Text>
|
||||||
|
|
@ -416,28 +421,43 @@ export const SubtitleModals: React.FC<SubtitleModalsProps> = ({
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{/* Outline controls (now supported for ExoPlayer internal via native patch) */}
|
{/* Outline controls (now supported for ExoPlayer internal via native patch) */}
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
{isUsingInternalSubtitle ? (
|
||||||
<Text style={{ color: 'white' }}>{t('player_ui.outline_color')}</Text>
|
// KSPlayer built-in subtitles: only expose an Outline on/off toggle (no width control).
|
||||||
<View style={{ flexDirection: 'row', gap: 8 }}>
|
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||||
{['#000000', '#FFFFFF', '#00E5FF', '#FF5C5C'].map(c => (
|
<Text style={{ color: 'white', fontWeight: '600' }}>{t('player_ui.outline')}</Text>
|
||||||
<TouchableOpacity key={c} onPress={() => setSubtitleOutlineColor(c)} style={{ width: 22, height: 22, borderRadius: 11, backgroundColor: c, borderWidth: 2, borderColor: subtitleOutlineColor === c ? '#fff' : 'rgba(255,255,255,0.3)' }} />
|
<TouchableOpacity
|
||||||
))}
|
onPress={() => setSubtitleOutline(!subtitleOutline)}
|
||||||
</View>
|
style={{ paddingHorizontal: 10, paddingVertical: 8, borderRadius: 10, backgroundColor: subtitleOutline ? 'rgba(255,255,255,0.18)' : 'rgba(255,255,255,0.08)', borderWidth: 1, borderColor: 'rgba(255,255,255,0.15)', alignItems: 'center' }}
|
||||||
</View>
|
>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
<Text style={{ color: '#fff', fontWeight: '700' }}>{subtitleOutline ? t('player_ui.on') : t('player_ui.off')}</Text>
|
||||||
<Text style={{ color: 'white' }}>{t('player_ui.outline_width')}</Text>
|
|
||||||
<View style={{ flexDirection: 'row', gap: 8, alignItems: 'center' }}>
|
|
||||||
<TouchableOpacity onPress={() => setSubtitleOutlineWidth(Math.max(0, subtitleOutlineWidth - 1))} style={{ width: controlBtn.size, height: controlBtn.size, borderRadius: controlBtn.radius, backgroundColor: 'rgba(255,255,255,0.18)', alignItems: 'center', justifyContent: 'center' }}>
|
|
||||||
<MaterialIcons name="remove" color="#fff" size={18} />
|
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<View style={{ minWidth: 42, paddingHorizontal: 6, paddingVertical: 4, borderRadius: 10, backgroundColor: 'rgba(255,255,255,0.12)' }}>
|
</View>
|
||||||
<Text style={{ color: 'white', textAlign: 'center', fontWeight: '700' }}>{subtitleOutlineWidth}</Text>
|
) : (
|
||||||
|
<>
|
||||||
|
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||||
|
<Text style={{ color: 'white' }}>{t('player_ui.outline_color')}</Text>
|
||||||
|
<View style={{ flexDirection: 'row', gap: 8 }}>
|
||||||
|
{['#000000', '#FFFFFF', '#00E5FF', '#FF5C5C'].map(c => (
|
||||||
|
<TouchableOpacity key={c} onPress={() => setSubtitleOutlineColor(c)} style={{ width: 22, height: 22, borderRadius: 11, backgroundColor: c, borderWidth: 2, borderColor: subtitleOutlineColor === c ? '#fff' : 'rgba(255,255,255,0.3)' }} />
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<TouchableOpacity onPress={() => setSubtitleOutlineWidth(subtitleOutlineWidth + 1)} style={{ width: controlBtn.size, height: controlBtn.size, borderRadius: controlBtn.radius, backgroundColor: 'rgba(255,255,255,0.18)', alignItems: 'center', justifyContent: 'center' }}>
|
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||||
<MaterialIcons name="add" color="#fff" size={18} />
|
<Text style={{ color: 'white' }}>{t('player_ui.outline_width')}</Text>
|
||||||
</TouchableOpacity>
|
<View style={{ flexDirection: 'row', gap: 8, alignItems: 'center' }}>
|
||||||
</View>
|
<TouchableOpacity onPress={() => setSubtitleOutlineWidth(Math.max(0, subtitleOutlineWidth - 1))} style={{ width: controlBtn.size, height: controlBtn.size, borderRadius: controlBtn.radius, backgroundColor: 'rgba(255,255,255,0.18)', alignItems: 'center', justifyContent: 'center' }}>
|
||||||
</View>
|
<MaterialIcons name="remove" color="#fff" size={18} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<View style={{ minWidth: 42, paddingHorizontal: 6, paddingVertical: 4, borderRadius: 10, backgroundColor: 'rgba(255,255,255,0.12)' }}>
|
||||||
|
<Text style={{ color: 'white', textAlign: 'center', fontWeight: '700' }}>{subtitleOutlineWidth}</Text>
|
||||||
|
</View>
|
||||||
|
<TouchableOpacity onPress={() => setSubtitleOutlineWidth(subtitleOutlineWidth + 1)} style={{ width: controlBtn.size, height: controlBtn.size, borderRadius: controlBtn.radius, backgroundColor: 'rgba(255,255,255,0.18)', alignItems: 'center', justifyContent: 'center' }}>
|
||||||
|
<MaterialIcons name="add" color="#fff" size={18} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
{!isUsingInternalSubtitle && (
|
{!isUsingInternalSubtitle && (
|
||||||
<View style={{ flexDirection: isCompact ? 'column' : 'row', justifyContent: 'space-between', gap: 12 }}>
|
<View style={{ flexDirection: isCompact ? 'column' : 'row', justifyContent: 'space-between', gap: 12 }}>
|
||||||
<View style={{ flex: 1 }}>
|
<View style={{ flex: 1 }}>
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,7 @@
|
||||||
"on": "تشغيل",
|
"on": "تشغيل",
|
||||||
"off": "إيقاف",
|
"off": "إيقاف",
|
||||||
"outline_color": "لون الإطار",
|
"outline_color": "لون الإطار",
|
||||||
|
"outline": "الإطار",
|
||||||
"outline_width": "عرض الإطار",
|
"outline_width": "عرض الإطار",
|
||||||
"letter_spacing": "تباعد الأحرف",
|
"letter_spacing": "تباعد الأحرف",
|
||||||
"line_height": "ارتفاع السطر",
|
"line_height": "ارتفاع السطر",
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,7 @@
|
||||||
"on": "Ein",
|
"on": "Ein",
|
||||||
"off": "Aus",
|
"off": "Aus",
|
||||||
"outline_color": "Umrandungsfarbe",
|
"outline_color": "Umrandungsfarbe",
|
||||||
|
"outline": "Umrandung",
|
||||||
"outline_width": "Umrandungsbreite",
|
"outline_width": "Umrandungsbreite",
|
||||||
"letter_spacing": "Zeichenabstand",
|
"letter_spacing": "Zeichenabstand",
|
||||||
"line_height": "Zeilenhöhe",
|
"line_height": "Zeilenhöhe",
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,7 @@
|
||||||
"on": "On",
|
"on": "On",
|
||||||
"off": "Off",
|
"off": "Off",
|
||||||
"outline_color": "Outline Color",
|
"outline_color": "Outline Color",
|
||||||
|
"outline": "Outline",
|
||||||
"outline_width": "Outline Width",
|
"outline_width": "Outline Width",
|
||||||
"letter_spacing": "Letter Spacing",
|
"letter_spacing": "Letter Spacing",
|
||||||
"line_height": "Line Height",
|
"line_height": "Line Height",
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,7 @@
|
||||||
"on": "Sí",
|
"on": "Sí",
|
||||||
"off": "No",
|
"off": "No",
|
||||||
"outline_color": "Color de contorno",
|
"outline_color": "Color de contorno",
|
||||||
|
"outline": "Contorno",
|
||||||
"outline_width": "Ancho de contorno",
|
"outline_width": "Ancho de contorno",
|
||||||
"letter_spacing": "Espaciado de letras",
|
"letter_spacing": "Espaciado de letras",
|
||||||
"line_height": "Altura de línea",
|
"line_height": "Altura de línea",
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,7 @@
|
||||||
"on": "Activé",
|
"on": "Activé",
|
||||||
"off": "Désactivé",
|
"off": "Désactivé",
|
||||||
"outline_color": "Couleur du contour",
|
"outline_color": "Couleur du contour",
|
||||||
|
"outline": "Contour",
|
||||||
"outline_width": "Largeur du contour",
|
"outline_width": "Largeur du contour",
|
||||||
"letter_spacing": "Espacement des lettres",
|
"letter_spacing": "Espacement des lettres",
|
||||||
"line_height": "Hauteur de ligne",
|
"line_height": "Hauteur de ligne",
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,7 @@
|
||||||
"on": "Attivo",
|
"on": "Attivo",
|
||||||
"off": "Disattivo",
|
"off": "Disattivo",
|
||||||
"outline_color": "Colore contorno",
|
"outline_color": "Colore contorno",
|
||||||
|
"outline": "Contorno",
|
||||||
"outline_width": "Larghezza contorno",
|
"outline_width": "Larghezza contorno",
|
||||||
"letter_spacing": "Spaziatura lettere",
|
"letter_spacing": "Spaziatura lettere",
|
||||||
"line_height": "Altezza riga",
|
"line_height": "Altezza riga",
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,7 @@
|
||||||
"on": "Ligado",
|
"on": "Ligado",
|
||||||
"off": "Desligado",
|
"off": "Desligado",
|
||||||
"outline_color": "Cor do Contorno",
|
"outline_color": "Cor do Contorno",
|
||||||
|
"outline": "Contorno",
|
||||||
"outline_width": "Largura do Contorno",
|
"outline_width": "Largura do Contorno",
|
||||||
"letter_spacing": "Espaçamento de Letras",
|
"letter_spacing": "Espaçamento de Letras",
|
||||||
"line_height": "Altura da Linha",
|
"line_height": "Altura da Linha",
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,7 @@
|
||||||
"on": "Ligado",
|
"on": "Ligado",
|
||||||
"off": "Desligado",
|
"off": "Desligado",
|
||||||
"outline_color": "Cor do Contorno",
|
"outline_color": "Cor do Contorno",
|
||||||
|
"outline": "Contorno",
|
||||||
"outline_width": "Largura do Contorno",
|
"outline_width": "Largura do Contorno",
|
||||||
"letter_spacing": "Espaçamento de Letras",
|
"letter_spacing": "Espaçamento de Letras",
|
||||||
"line_height": "Altura da Linha",
|
"line_height": "Altura da Linha",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue