@npaw/forge-react-native-video 9.7.1 → 9.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/android/build.gradle
CHANGED
|
@@ -25,11 +25,11 @@ def safeExtGet(prop, fallback) {
|
|
|
25
25
|
|
|
26
26
|
def forgeCoreVersion = project.hasProperty('NpawForge_forgeCoreVersion')
|
|
27
27
|
? project.property('NpawForge_forgeCoreVersion')
|
|
28
|
-
: (System.getenv('FORGE_CORE_VERSION') ?: '9.7.
|
|
28
|
+
: (System.getenv('FORGE_CORE_VERSION') ?: '9.7.3')
|
|
29
29
|
|
|
30
30
|
def forgeAdapterVersion = project.hasProperty('NpawForge_forgeAdapterVersion')
|
|
31
31
|
? project.property('NpawForge_forgeAdapterVersion')
|
|
32
|
-
: (System.getenv('FORGE_ADAPTER_VERSION') ?: '9.7.
|
|
32
|
+
: (System.getenv('FORGE_ADAPTER_VERSION') ?: '9.7.3')
|
|
33
33
|
|
|
34
34
|
android {
|
|
35
35
|
namespace 'com.npaw.forge.reactnative.video'
|
|
@@ -55,12 +55,16 @@ final class ForgeRNVPlayerPlugin: RNVAVPlayerPlugin {
|
|
|
55
55
|
override func overridePlayerAsset(source: VideoSource, asset: AVAsset) async -> OverridePlayerAssetResult? {
|
|
56
56
|
var token: String?
|
|
57
57
|
var uri: String?
|
|
58
|
+
var sawUriLabel = false
|
|
59
|
+
var sawHeadersLabel = false
|
|
58
60
|
let mirror = Mirror(reflecting: source)
|
|
59
61
|
for child in mirror.children {
|
|
60
62
|
switch child.label {
|
|
61
63
|
case "uri":
|
|
64
|
+
sawUriLabel = true
|
|
62
65
|
uri = child.value as? String ?? (child.value as? String?) ?? nil
|
|
63
66
|
case "requestHeaders":
|
|
67
|
+
sawHeadersLabel = true
|
|
64
68
|
let headers = (child.value as? [String: Any]) ?? (child.value as? [String: Any]?) ?? nil
|
|
65
69
|
if let headers {
|
|
66
70
|
for (key, value) in headers where key.lowercased() == ForgeVideoModuleImpl.tokenHeader {
|
|
@@ -71,10 +75,48 @@ final class ForgeRNVPlayerPlugin: RNVAVPlayerPlugin {
|
|
|
71
75
|
break
|
|
72
76
|
}
|
|
73
77
|
}
|
|
78
|
+
// Reflection has no compile-time contract, so a renamed field would
|
|
79
|
+
// otherwise degrade in silence: `uri` falls back to the asset URL below
|
|
80
|
+
// and playback still reports, while token correlation quietly stops.
|
|
81
|
+
// Say so once, loudly enough to be found in a device log. The CI-side
|
|
82
|
+
// guard is __tests__/rn-video-source-contract.test.ts.
|
|
83
|
+
if !sawUriLabel || !sawHeadersLabel {
|
|
84
|
+
ForgeRNVPlayerPlugin.reportReflectionDrift(sawUri: sawUriLabel, sawHeaders: sawHeadersLabel)
|
|
85
|
+
}
|
|
74
86
|
if uri == nil, let urlAsset = asset as? AVURLAsset {
|
|
75
87
|
uri = urlAsset.url.absoluteString
|
|
76
88
|
}
|
|
77
89
|
ForgeVideoModuleImpl.shared.sourceSeen(asset: asset, token: token, uri: uri)
|
|
78
90
|
return nil
|
|
79
91
|
}
|
|
92
|
+
|
|
93
|
+
/// One-shot notice that `VideoSource`'s shape no longer matches what the
|
|
94
|
+
/// reflection expects.
|
|
95
|
+
///
|
|
96
|
+
/// Reported once per process: this runs for every player item, and a
|
|
97
|
+
/// per-item log on a list screen would bury the very message it exists to
|
|
98
|
+
/// surface. Reuses the same static-lock pattern as `registerOnce`.
|
|
99
|
+
private static var reflectionDriftReported = false
|
|
100
|
+
|
|
101
|
+
private static func reportReflectionDrift(sawUri: Bool, sawHeaders: Bool) {
|
|
102
|
+
registrationLock.lock()
|
|
103
|
+
if reflectionDriftReported {
|
|
104
|
+
registrationLock.unlock()
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
reflectionDriftReported = true
|
|
108
|
+
registrationLock.unlock()
|
|
109
|
+
|
|
110
|
+
let missing = [sawUri ? nil : "uri", sawHeaders ? nil : "requestHeaders"]
|
|
111
|
+
.compactMap { $0 }
|
|
112
|
+
.joined(separator: ", ")
|
|
113
|
+
NSLog(
|
|
114
|
+
"[NPAWForge] react-native-video VideoSource no longer exposes: %@. "
|
|
115
|
+
+ "Forge reads these by reflection because they are internal upstream. "
|
|
116
|
+
+ "Playback reporting continues, but token correlation is degraded. "
|
|
117
|
+
+ "Check the installed react-native-video version against the "
|
|
118
|
+
+ "supported range (>=6.11.0 <7).",
|
|
119
|
+
missing
|
|
120
|
+
)
|
|
121
|
+
}
|
|
80
122
|
}
|
|
@@ -310,16 +310,32 @@ public final class ForgeVideoModuleImpl: NSObject {
|
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
+
/// Tears the binding down: detach the player adapter, then fire the
|
|
314
|
+
/// terminal stop.
|
|
315
|
+
///
|
|
316
|
+
/// The detach comes first deliberately. By the time this block runs,
|
|
317
|
+
/// react-native-video has already released its player - `playerRemoved`
|
|
318
|
+
/// arrives on the main thread and this hop defers a full runloop turn - so
|
|
319
|
+
/// the adapter is observing a player that is being deallocated. Detaching
|
|
320
|
+
/// first means the view is closed to it before the stop makes the view
|
|
321
|
+
/// terminal, and nothing the dying player reports afterwards can be
|
|
322
|
+
/// mistaken for a replay.
|
|
323
|
+
///
|
|
324
|
+
/// The stop still carries the final position: it never read the player
|
|
325
|
+
/// (`fireStop` builds its metadata from params), and the kernel backfills
|
|
326
|
+
/// `playhead` from the last observed position when the firing params carry
|
|
327
|
+
/// none - `backfill_stop_playhead`, added for
|
|
328
|
+
/// `apple/2026-07-13_ios-stop-playhead-zero-instead-of-final-position`.
|
|
313
329
|
private func unbindOnMain(_ binding: Binding, fireStop: Bool) {
|
|
314
330
|
let instanceId = binding.request.instanceId
|
|
315
331
|
let identifier = binding.request.identifier
|
|
316
332
|
DispatchQueue.main.async { [weak self] in
|
|
317
333
|
guard let self, let forge = self.resolveForge(instanceId) else { return }
|
|
318
334
|
guard let video = forge.getVideoAdapter(identifier: identifier) else { return }
|
|
335
|
+
_ = video.setPlayerAdapter(nil)
|
|
319
336
|
if fireStop {
|
|
320
337
|
_ = video.fireStop()
|
|
321
338
|
}
|
|
322
|
-
_ = video.setPlayerAdapter(nil)
|
|
323
339
|
}
|
|
324
340
|
}
|
|
325
341
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@npaw/forge-react-native-video",
|
|
3
|
-
"version": "9.7.
|
|
3
|
+
"version": "9.7.3",
|
|
4
4
|
"description": "react-native-video adapter glue for NPAW Forge: attaches the native Media3/AVPlayer Forge adapters to react-native-video's internal players via its native plugin API.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "Victor Soto <victor.soto@nicepeopleatwork.com>",
|
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
"src"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
|
-
"typecheck": "tsc --noEmit"
|
|
18
|
+
"typecheck": "tsc --noEmit",
|
|
19
|
+
"test": "jest"
|
|
19
20
|
},
|
|
20
21
|
"peerDependencies": {
|
|
21
|
-
"@npaw/forge-react-native": "^9.7.
|
|
22
|
+
"@npaw/forge-react-native": "^9.7.3",
|
|
22
23
|
"react": "*",
|
|
23
24
|
"react-native": "*",
|
|
24
25
|
"react-native-video": ">=6.11.0 <7"
|