@npaw/forge-react-native 9.6.1
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/LICENSE +10 -0
- package/NPAWForgeReactNative.podspec +44 -0
- package/README.md +51 -0
- package/android/build.gradle +77 -0
- package/android/src/main/AndroidManifest.xml +14 -0
- package/android/src/main/java/com/npaw/forge/reactnative/ForgeDtoMapper.java +295 -0
- package/android/src/main/java/com/npaw/forge/reactnative/ForgeInstanceRegistry.java +61 -0
- package/android/src/main/java/com/npaw/forge/reactnative/NPAWForgeModule.java +735 -0
- package/android/src/main/java/com/npaw/forge/reactnative/NPAWForgePackage.java +53 -0
- package/android/src/test/java/com/npaw/forge/reactnative/ForgeDtoMapperTest.java +133 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/Info.plist +82 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64/Headers/ForgeKernelFFI.h +17 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64/Headers/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64/Headers/module.modulemap +7 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/Headers/ForgeKernelFFI.h +17 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/Headers/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/Headers/module.modulemap +7 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64/Headers/ForgeKernelFFI.h +17 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64/Headers/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64/Headers/module.modulemap +7 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64-simulator/Headers/ForgeKernelFFI.h +17 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64-simulator/Headers/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64-simulator/Headers/module.modulemap +7 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64-simulator/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/Sources/ForgeKernelUniFFI/forge_kernel.swift +3931 -0
- package/ios/ForgeApple/Sources/ForgeKernelUniFFI/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/Sources/ForgeKernelUniFFI/forge_kernelFFI.modulemap +7 -0
- package/ios/ForgeApple/Sources/NPAWForgeAVPlayerAdapter/AVPlayerAccessLogFacts.swift +152 -0
- package/ios/ForgeApple/Sources/NPAWForgeAVPlayerAdapter/AVPlayerAdapter.swift +877 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/AttributionCapture.swift +158 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/CapturePlanGate.swift +189 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/CrashCapture.swift +120 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/ForgeAutomaticCapture.swift +639 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SectionsCapture.swift +1176 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SectionsEngine.swift +674 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SectionsMarkers.swift +105 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SectionsSwiftUI.swift +284 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SwiftUICapture.swift +44 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/AdAdapter.swift +199 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/AdSemantics.swift +136 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeApple.swift +596 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeCapturePlan.swift +297 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeClock.swift +29 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeLogging.swift +109 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeOutcome.swift +89 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeRuntime.swift +291 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeStorage.swift +70 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ManualAdReporter.swift +180 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/NPAWForge.swift +453 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/NativeUniFFIRuntime.swift +594 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/NetworkRequestRecord.swift +191 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ObjectiveCWrappers.swift +191 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/PlayerAdapter.swift +299 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/PlayerSemantics.swift +266 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/PrivacySanitizer.swift +59 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/VideoAdapter.swift +478 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/VideoOptions.swift +431 -0
- package/ios/ForgeApple/Sources/NPAWForgeNetworkCapture/ForgeNetworkCapture.swift +116 -0
- package/ios/ForgeApple/Sources/NPAWForgeNetworkCaptureObjC/NPAWForgeNetworkSwizzler.m +293 -0
- package/ios/ForgeApple/Sources/NPAWForgeNetworkCaptureObjC/include/NPAWForgeNetworkSwizzler.h +33 -0
- package/ios/ForgeModuleImpl.swift +1131 -0
- package/ios/NPAWForgeTurboModule.mm +399 -0
- package/package.json +33 -0
- package/src/ForgeAdReporter.ts +101 -0
- package/src/ForgeVideo.ts +169 -0
- package/src/NPAWForge.ts +177 -0
- package/src/capture.ts +192 -0
- package/src/events.ts +40 -0
- package/src/index.ts +37 -0
- package/src/specs/NativeNPAWForge.ts +168 -0
- package/src/types.ts +114 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) NPAW - All Rights Reserved
|
|
3
|
+
*
|
|
4
|
+
* This source code is protected under international copyright law. All rights
|
|
5
|
+
* reserved and protected by the copyright holders.
|
|
6
|
+
* This file is confidential and only available to authorized individuals with the
|
|
7
|
+
* permission of the copyright holders. If you encounter this file and do not have
|
|
8
|
+
* permission, please contact the copyright holders and delete this file.
|
|
9
|
+
*
|
|
10
|
+
*
|
|
11
|
+
* @author: Victor Soto <victor.soto@nicepeopleatwork.com>
|
|
12
|
+
* @description: Apple runtime abstraction that the Swift facade uses to reach the Rust core.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import Foundation
|
|
16
|
+
|
|
17
|
+
public struct RuntimeVideoView: Equatable {
|
|
18
|
+
public let id: Int64
|
|
19
|
+
|
|
20
|
+
public init(id: Int64) {
|
|
21
|
+
self.id = id
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public struct ForgeRecordedEvent: Equatable {
|
|
26
|
+
public let eventName: String
|
|
27
|
+
public let timestampMs: Int64
|
|
28
|
+
public let payload: [String: String]
|
|
29
|
+
public let urgent: Bool
|
|
30
|
+
public let viewKey: String?
|
|
31
|
+
|
|
32
|
+
public init(
|
|
33
|
+
eventName: String,
|
|
34
|
+
timestampMs: Int64,
|
|
35
|
+
payload: [String: String],
|
|
36
|
+
urgent: Bool = false,
|
|
37
|
+
viewKey: String? = nil
|
|
38
|
+
) {
|
|
39
|
+
self.eventName = eventName
|
|
40
|
+
self.timestampMs = timestampMs
|
|
41
|
+
self.payload = payload
|
|
42
|
+
self.urgent = urgent
|
|
43
|
+
self.viewKey = viewKey
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public protocol RuntimeContentMetadataProvider: AnyObject {
|
|
48
|
+
func metadataSnapshot(timemarkMs: Int64, elapsedRealtimeMs: Int64) -> MetadataSnapshot?
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public protocol RuntimeVideoPreSendHook: AnyObject {
|
|
52
|
+
func willSendRequest(
|
|
53
|
+
eventName: String,
|
|
54
|
+
view: RuntimeVideoView,
|
|
55
|
+
serviceName: String,
|
|
56
|
+
params: inout [String: String]
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public protocol RuntimeSessionPreSendHook: AnyObject {
|
|
61
|
+
func willSendRequest(serviceName: String, params: inout [String: String])
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public protocol ForgeRuntime: AnyObject {
|
|
65
|
+
func start() -> ForgeOutcome
|
|
66
|
+
func setLogLevel(_ level: ForgeLogLevel) -> ForgeOutcome
|
|
67
|
+
func createVideoView(timestampMs: Int64, options: VideoOptions) -> RuntimeVideoView
|
|
68
|
+
func recordEvent(_ event: ForgeRecordedEvent) -> ForgeOutcome
|
|
69
|
+
/// Records a typed identity transition (`loginSuccess`, `loginFailed`,
|
|
70
|
+
/// `logout`, `profileCreated`, `profileSelected`, `profileDeleted`). The
|
|
71
|
+
/// kernel consumes the recognized fields (`userId`, `profileId`,
|
|
72
|
+
/// `profileType`, `method`, `errorCode`, `reason`, `userType`), forwards
|
|
73
|
+
/// the rest as extra session-event params, and emits the taxonomy event.
|
|
74
|
+
func recordIdentityEvent(kind: String, timemarkMs: Int64, fields: [String: String]) -> ForgeOutcome
|
|
75
|
+
func recordApplicationForeground(_ foreground: Bool, timestampMs: Int64) -> ForgeOutcome
|
|
76
|
+
func recordNetworkEvent(_ record: NetworkRequestRecord) -> ForgeOutcome
|
|
77
|
+
func recordPlayerEvent(
|
|
78
|
+
view: RuntimeVideoView,
|
|
79
|
+
event: PlayerEvent,
|
|
80
|
+
timemarkMs: Int64,
|
|
81
|
+
elapsedRealtimeMs: Int64,
|
|
82
|
+
options: VideoOptions,
|
|
83
|
+
metadata: PlayerMetadataSnapshot
|
|
84
|
+
) -> ForgeOutcome
|
|
85
|
+
func recordAdEvent(
|
|
86
|
+
view: RuntimeVideoView,
|
|
87
|
+
event: AdEvent,
|
|
88
|
+
timemarkMs: Int64,
|
|
89
|
+
elapsedRealtimeMs: Int64,
|
|
90
|
+
options: VideoOptions,
|
|
91
|
+
metadata: AdMetadataSnapshot,
|
|
92
|
+
adapterVersion: String?
|
|
93
|
+
) -> ForgeOutcome
|
|
94
|
+
func registerContentMetadataProvider(view: RuntimeVideoView, provider: RuntimeContentMetadataProvider?) -> ForgeOutcome
|
|
95
|
+
func registerVideoPreSendHook(view: RuntimeVideoView, hook: RuntimeVideoPreSendHook?) -> ForgeOutcome
|
|
96
|
+
func registerSessionPreSendHook(_ hook: RuntimeSessionPreSendHook?) -> ForgeOutcome
|
|
97
|
+
func destroyVideoView(_ view: RuntimeVideoView) -> ForgeOutcome
|
|
98
|
+
func snapshotEvents() -> [ForgeRecordedEvent]
|
|
99
|
+
func destroy() -> ForgeOutcome
|
|
100
|
+
/// Registers (or clears with `nil`) the kernel capture-plan observer. The
|
|
101
|
+
/// latest plan is replayed to a late-registered listener when available.
|
|
102
|
+
func setCapturePlanListener(_ listener: ((ForgeCapturePlan) -> Void)?) -> ForgeOutcome
|
|
103
|
+
/// Latest kernel-emitted capture plan, or `nil` before the first emission.
|
|
104
|
+
func capturePlan() -> ForgeCapturePlan?
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/// Additive defaults so existing `ForgeRuntime` conformances (including the
|
|
108
|
+
/// non-native fallback) keep compiling; runtimes without a kernel capture
|
|
109
|
+
/// plan simply never deliver one and bindings stay on local options only.
|
|
110
|
+
public extension ForgeRuntime {
|
|
111
|
+
func setCapturePlanListener(_ listener: ((ForgeCapturePlan) -> Void)?) -> ForgeOutcome { .accepted }
|
|
112
|
+
func capturePlan() -> ForgeCapturePlan? { nil }
|
|
113
|
+
/// Additive default: runtimes without kernel identity support report the
|
|
114
|
+
/// capability gap instead of silently accepting the transition.
|
|
115
|
+
func recordIdentityEvent(kind: String, timemarkMs: Int64, fields: [String: String]) -> ForgeOutcome { .unsupportedCapability }
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public protocol ForgeRuntimeFactory: AnyObject {
|
|
119
|
+
func create(config: ForgeAppleConfig, services: ForgeAppleServices) -> ForgeRuntime
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
public final class UnavailableForgeRuntime: ForgeRuntime {
|
|
123
|
+
private let reason: String
|
|
124
|
+
|
|
125
|
+
public init(reason: String) {
|
|
126
|
+
self.reason = reason
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public func start() -> ForgeOutcome { failed() }
|
|
130
|
+
public func setLogLevel(_ level: ForgeLogLevel) -> ForgeOutcome { .accepted }
|
|
131
|
+
public func createVideoView(timestampMs: Int64, options: VideoOptions) -> RuntimeVideoView { RuntimeVideoView(id: -1) }
|
|
132
|
+
public func recordEvent(_ event: ForgeRecordedEvent) -> ForgeOutcome { failed() }
|
|
133
|
+
public func recordIdentityEvent(kind: String, timemarkMs: Int64, fields: [String: String]) -> ForgeOutcome { failed() }
|
|
134
|
+
public func recordApplicationForeground(_ foreground: Bool, timestampMs: Int64) -> ForgeOutcome { failed() }
|
|
135
|
+
public func recordNetworkEvent(_ record: NetworkRequestRecord) -> ForgeOutcome { failed() }
|
|
136
|
+
public func recordPlayerEvent(
|
|
137
|
+
view: RuntimeVideoView,
|
|
138
|
+
event: PlayerEvent,
|
|
139
|
+
timemarkMs: Int64,
|
|
140
|
+
elapsedRealtimeMs: Int64,
|
|
141
|
+
options: VideoOptions,
|
|
142
|
+
metadata: PlayerMetadataSnapshot
|
|
143
|
+
) -> ForgeOutcome { failed() }
|
|
144
|
+
public func recordAdEvent(
|
|
145
|
+
view: RuntimeVideoView,
|
|
146
|
+
event: AdEvent,
|
|
147
|
+
timemarkMs: Int64,
|
|
148
|
+
elapsedRealtimeMs: Int64,
|
|
149
|
+
options: VideoOptions,
|
|
150
|
+
metadata: AdMetadataSnapshot,
|
|
151
|
+
adapterVersion: String?
|
|
152
|
+
) -> ForgeOutcome { failed() }
|
|
153
|
+
public func registerContentMetadataProvider(view: RuntimeVideoView, provider: RuntimeContentMetadataProvider?) -> ForgeOutcome { .accepted }
|
|
154
|
+
public func registerVideoPreSendHook(view: RuntimeVideoView, hook: RuntimeVideoPreSendHook?) -> ForgeOutcome { .accepted }
|
|
155
|
+
public func registerSessionPreSendHook(_ hook: RuntimeSessionPreSendHook?) -> ForgeOutcome { .accepted }
|
|
156
|
+
public func destroyVideoView(_ view: RuntimeVideoView) -> ForgeOutcome { .accepted }
|
|
157
|
+
public func snapshotEvents() -> [ForgeRecordedEvent] { [] }
|
|
158
|
+
public func destroy() -> ForgeOutcome { .accepted }
|
|
159
|
+
|
|
160
|
+
private func failed() -> ForgeOutcome {
|
|
161
|
+
.failedWithDiagnostic(reason)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
public final class NativeForgeRuntimeFactory: ForgeRuntimeFactory {
|
|
166
|
+
public init() {}
|
|
167
|
+
|
|
168
|
+
public func create(config: ForgeAppleConfig, services: ForgeAppleServices) -> ForgeRuntime {
|
|
169
|
+
#if FORGE_HAS_UNIFFI
|
|
170
|
+
return UniFFIForgeRuntime(config: config)
|
|
171
|
+
#else
|
|
172
|
+
UnavailableForgeRuntime(reason: "native_runtime_unavailable")
|
|
173
|
+
#endif
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public final class RecordingForgeRuntime: ForgeRuntime {
|
|
178
|
+
public private(set) var events: [ForgeRecordedEvent] = []
|
|
179
|
+
public private(set) var identityEvents: [(kind: String, timemarkMs: Int64, fields: [String: String])] = []
|
|
180
|
+
public private(set) var playerEvents: [(RuntimeVideoView, PlayerEvent, PlayerMetadataSnapshot)] = []
|
|
181
|
+
public private(set) var playerEventTimestamps: [(timemarkMs: Int64, elapsedRealtimeMs: Int64)] = []
|
|
182
|
+
public private(set) var playerEventOptions: [VideoOptions] = []
|
|
183
|
+
public private(set) var adEvents: [(RuntimeVideoView, AdEvent, AdMetadataSnapshot)] = []
|
|
184
|
+
public private(set) var adEventTimestamps: [(timemarkMs: Int64, elapsedRealtimeMs: Int64)] = []
|
|
185
|
+
public private(set) var networkEvents: [NetworkRequestRecord] = []
|
|
186
|
+
public private(set) var createdVideoTimestamps: [Int64] = []
|
|
187
|
+
public private(set) var contentMetadataProviders: [Int64: RuntimeContentMetadataProvider] = [:]
|
|
188
|
+
public private(set) var videoPreSendHooks: [Int64: RuntimeVideoPreSendHook] = [:]
|
|
189
|
+
public private(set) var destroyedViewIds: [Int64] = []
|
|
190
|
+
public private(set) var capturePlanListener: ((ForgeCapturePlan) -> Void)?
|
|
191
|
+
public private(set) var latestCapturePlan: ForgeCapturePlan?
|
|
192
|
+
private var nextViewId: Int64 = 1
|
|
193
|
+
|
|
194
|
+
public init() {}
|
|
195
|
+
|
|
196
|
+
public func start() -> ForgeOutcome { .accepted }
|
|
197
|
+
public func setLogLevel(_ level: ForgeLogLevel) -> ForgeOutcome { .accepted }
|
|
198
|
+
public func createVideoView(timestampMs: Int64, options: VideoOptions) -> RuntimeVideoView {
|
|
199
|
+
createdVideoTimestamps.append(timestampMs)
|
|
200
|
+
defer { nextViewId += 1 }
|
|
201
|
+
return RuntimeVideoView(id: nextViewId)
|
|
202
|
+
}
|
|
203
|
+
public func recordEvent(_ event: ForgeRecordedEvent) -> ForgeOutcome {
|
|
204
|
+
events.append(event)
|
|
205
|
+
return .accepted
|
|
206
|
+
}
|
|
207
|
+
public func recordIdentityEvent(kind: String, timemarkMs: Int64, fields: [String: String]) -> ForgeOutcome {
|
|
208
|
+
identityEvents.append((kind, timemarkMs, fields))
|
|
209
|
+
return .accepted
|
|
210
|
+
}
|
|
211
|
+
public func recordApplicationForeground(_ foreground: Bool, timestampMs: Int64) -> ForgeOutcome {
|
|
212
|
+
events.append(
|
|
213
|
+
ForgeRecordedEvent(
|
|
214
|
+
eventName: foreground ? "raw_application_foreground" : "raw_application_background",
|
|
215
|
+
timestampMs: timestampMs,
|
|
216
|
+
payload: [:]
|
|
217
|
+
)
|
|
218
|
+
)
|
|
219
|
+
return .accepted
|
|
220
|
+
}
|
|
221
|
+
public func recordNetworkEvent(_ record: NetworkRequestRecord) -> ForgeOutcome {
|
|
222
|
+
networkEvents.append(record)
|
|
223
|
+
return .accepted
|
|
224
|
+
}
|
|
225
|
+
public func recordPlayerEvent(
|
|
226
|
+
view: RuntimeVideoView,
|
|
227
|
+
event: PlayerEvent,
|
|
228
|
+
timemarkMs: Int64,
|
|
229
|
+
elapsedRealtimeMs: Int64,
|
|
230
|
+
options: VideoOptions,
|
|
231
|
+
metadata: PlayerMetadataSnapshot
|
|
232
|
+
) -> ForgeOutcome {
|
|
233
|
+
playerEvents.append((view, event, metadata))
|
|
234
|
+
playerEventTimestamps.append((timemarkMs, elapsedRealtimeMs))
|
|
235
|
+
playerEventOptions.append(options)
|
|
236
|
+
return .accepted
|
|
237
|
+
}
|
|
238
|
+
public func recordAdEvent(
|
|
239
|
+
view: RuntimeVideoView,
|
|
240
|
+
event: AdEvent,
|
|
241
|
+
timemarkMs: Int64,
|
|
242
|
+
elapsedRealtimeMs: Int64,
|
|
243
|
+
options: VideoOptions,
|
|
244
|
+
metadata: AdMetadataSnapshot,
|
|
245
|
+
adapterVersion: String?
|
|
246
|
+
) -> ForgeOutcome {
|
|
247
|
+
adEvents.append((view, event, metadata))
|
|
248
|
+
adEventTimestamps.append((timemarkMs, elapsedRealtimeMs))
|
|
249
|
+
return .accepted
|
|
250
|
+
}
|
|
251
|
+
public func registerContentMetadataProvider(view: RuntimeVideoView, provider: RuntimeContentMetadataProvider?) -> ForgeOutcome {
|
|
252
|
+
if let provider {
|
|
253
|
+
contentMetadataProviders[view.id] = provider
|
|
254
|
+
} else {
|
|
255
|
+
contentMetadataProviders.removeValue(forKey: view.id)
|
|
256
|
+
}
|
|
257
|
+
return .accepted
|
|
258
|
+
}
|
|
259
|
+
public func registerVideoPreSendHook(view: RuntimeVideoView, hook: RuntimeVideoPreSendHook?) -> ForgeOutcome {
|
|
260
|
+
if let hook {
|
|
261
|
+
videoPreSendHooks[view.id] = hook
|
|
262
|
+
} else {
|
|
263
|
+
videoPreSendHooks.removeValue(forKey: view.id)
|
|
264
|
+
}
|
|
265
|
+
return .accepted
|
|
266
|
+
}
|
|
267
|
+
public func registerSessionPreSendHook(_ hook: RuntimeSessionPreSendHook?) -> ForgeOutcome { .accepted }
|
|
268
|
+
public func destroyVideoView(_ view: RuntimeVideoView) -> ForgeOutcome {
|
|
269
|
+
destroyedViewIds.append(view.id)
|
|
270
|
+
contentMetadataProviders.removeValue(forKey: view.id)
|
|
271
|
+
videoPreSendHooks.removeValue(forKey: view.id)
|
|
272
|
+
return .accepted
|
|
273
|
+
}
|
|
274
|
+
public func snapshotEvents() -> [ForgeRecordedEvent] { events }
|
|
275
|
+
public func destroy() -> ForgeOutcome { .accepted }
|
|
276
|
+
public func setCapturePlanListener(_ listener: ((ForgeCapturePlan) -> Void)?) -> ForgeOutcome {
|
|
277
|
+
capturePlanListener = listener
|
|
278
|
+
if let listener, let latest = latestCapturePlan {
|
|
279
|
+
listener(latest)
|
|
280
|
+
}
|
|
281
|
+
return .accepted
|
|
282
|
+
}
|
|
283
|
+
public func capturePlan() -> ForgeCapturePlan? { latestCapturePlan }
|
|
284
|
+
|
|
285
|
+
/// Test hook mirroring the native runtime's push path: stores the latest
|
|
286
|
+
/// plan and dispatches it to the registered listener.
|
|
287
|
+
public func emitCapturePlan(_ plan: ForgeCapturePlan) {
|
|
288
|
+
latestCapturePlan = plan
|
|
289
|
+
capturePlanListener?(plan)
|
|
290
|
+
}
|
|
291
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) NPAW - All Rights Reserved
|
|
3
|
+
*
|
|
4
|
+
* This source code is protected under international copyright law. All rights
|
|
5
|
+
* reserved and protected by the copyright holders.
|
|
6
|
+
* This file is confidential and only available to authorized individuals with the
|
|
7
|
+
* permission of the copyright holders. If you encounter this file and do not have
|
|
8
|
+
* permission, please contact the copyright holders and delete this file.
|
|
9
|
+
*
|
|
10
|
+
*
|
|
11
|
+
* @author: Victor Soto <victor.soto@nicepeopleatwork.com>
|
|
12
|
+
* @description: Apple storage abstraction used by the native runtime for bounded remote-config persistence.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import Foundation
|
|
16
|
+
|
|
17
|
+
public protocol ForgeStorage: AnyObject {
|
|
18
|
+
func read(_ key: String) -> String?
|
|
19
|
+
func write(_ key: String, value: String) -> ForgeOutcome
|
|
20
|
+
func delete(_ key: String) -> ForgeOutcome
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public final class MemoryStorage: ForgeStorage {
|
|
24
|
+
private var values: [String: String] = [:]
|
|
25
|
+
private let lock = NSLock()
|
|
26
|
+
|
|
27
|
+
public init() {}
|
|
28
|
+
|
|
29
|
+
public func read(_ key: String) -> String? {
|
|
30
|
+
lock.lock()
|
|
31
|
+
defer { lock.unlock() }
|
|
32
|
+
return values[key]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public func write(_ key: String, value: String) -> ForgeOutcome {
|
|
36
|
+
lock.lock()
|
|
37
|
+
defer { lock.unlock() }
|
|
38
|
+
values[key] = value
|
|
39
|
+
return .accepted
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public func delete(_ key: String) -> ForgeOutcome {
|
|
43
|
+
lock.lock()
|
|
44
|
+
defer { lock.unlock() }
|
|
45
|
+
values.removeValue(forKey: key)
|
|
46
|
+
return .accepted
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public final class UserDefaultsStorage: ForgeStorage {
|
|
51
|
+
private let defaults: UserDefaults
|
|
52
|
+
|
|
53
|
+
public init(suiteName: String = "com.npaw.forge.apple.storage") {
|
|
54
|
+
self.defaults = UserDefaults(suiteName: suiteName) ?? .standard
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public func read(_ key: String) -> String? {
|
|
58
|
+
defaults.string(forKey: key)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public func write(_ key: String, value: String) -> ForgeOutcome {
|
|
62
|
+
defaults.set(value, forKey: key)
|
|
63
|
+
return defaults.synchronize() ? .accepted : .failedWithDiagnostic("storage_write_failed")
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public func delete(_ key: String) -> ForgeOutcome {
|
|
67
|
+
defaults.removeObject(forKey: key)
|
|
68
|
+
return defaults.synchronize() ? .accepted : .failedWithDiagnostic("storage_delete_failed")
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) NPAW - All Rights Reserved
|
|
3
|
+
*
|
|
4
|
+
* This source code is protected under international copyright law. All rights
|
|
5
|
+
* reserved and protected by the copyright holders.
|
|
6
|
+
* This file is confidential and only available to authorized individuals with the
|
|
7
|
+
* permission of the copyright holders. If you encounter this file and do not have
|
|
8
|
+
* permission, please contact the copyright holders and delete this file.
|
|
9
|
+
*
|
|
10
|
+
*
|
|
11
|
+
* @author: Victor Soto <victor.soto@nicepeopleatwork.com>
|
|
12
|
+
* @description: Manual Apple ad reporting facade for adapterless video integrations.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import Foundation
|
|
16
|
+
|
|
17
|
+
public final class ManualAdReporter {
|
|
18
|
+
private weak var videoAdapter: VideoAdapter?
|
|
19
|
+
private let adapterVersion: String?
|
|
20
|
+
|
|
21
|
+
init(videoAdapter: VideoAdapter, adapterVersion: String?) {
|
|
22
|
+
self.videoAdapter = videoAdapter
|
|
23
|
+
self.adapterVersion = adapterVersion
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public func fireManifest(
|
|
27
|
+
metadata: AdMetadataSnapshot? = nil,
|
|
28
|
+
params: [String: String]? = [:],
|
|
29
|
+
timestampMs: Int64 = 0
|
|
30
|
+
) -> ForgeOutcome {
|
|
31
|
+
record(.manifest, metadata ?? adMetadataFromParams(params), timestampMs)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public func fireBreakStart(
|
|
35
|
+
metadata: AdMetadataSnapshot? = nil,
|
|
36
|
+
params: [String: String]? = [:],
|
|
37
|
+
timestampMs: Int64 = 0
|
|
38
|
+
) -> ForgeOutcome {
|
|
39
|
+
record(.breakStart, metadata ?? adMetadataFromParams(params), timestampMs)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public func fireAdInit(
|
|
43
|
+
metadata: AdMetadataSnapshot? = nil,
|
|
44
|
+
params: [String: String]? = [:],
|
|
45
|
+
timestampMs: Int64 = 0
|
|
46
|
+
) -> ForgeOutcome {
|
|
47
|
+
record(.adInit, metadata ?? adMetadataFromParams(params), timestampMs)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public func fireStart(
|
|
51
|
+
metadata: AdMetadataSnapshot? = nil,
|
|
52
|
+
params: [String: String]? = [:],
|
|
53
|
+
timestampMs: Int64 = 0
|
|
54
|
+
) -> ForgeOutcome {
|
|
55
|
+
record(.start, metadata ?? adMetadataFromParams(params), timestampMs)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public func fireJoin(
|
|
59
|
+
metadata: AdMetadataSnapshot? = nil,
|
|
60
|
+
params: [String: String]? = [:],
|
|
61
|
+
timestampMs: Int64 = 0
|
|
62
|
+
) -> ForgeOutcome {
|
|
63
|
+
record(.join, metadata ?? adMetadataFromParams(params), timestampMs)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public func firePause(
|
|
67
|
+
metadata: AdMetadataSnapshot? = nil,
|
|
68
|
+
params: [String: String]? = [:],
|
|
69
|
+
timestampMs: Int64 = 0
|
|
70
|
+
) -> ForgeOutcome {
|
|
71
|
+
record(.pause, metadata ?? adMetadataFromParams(params), timestampMs)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public func fireResume(
|
|
75
|
+
metadata: AdMetadataSnapshot? = nil,
|
|
76
|
+
params: [String: String]? = [:],
|
|
77
|
+
timestampMs: Int64 = 0
|
|
78
|
+
) -> ForgeOutcome {
|
|
79
|
+
record(.resume, metadata ?? adMetadataFromParams(params), timestampMs)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public func fireBufferBegin(
|
|
83
|
+
metadata: AdMetadataSnapshot? = nil,
|
|
84
|
+
params: [String: String]? = [:],
|
|
85
|
+
timestampMs: Int64 = 0
|
|
86
|
+
) -> ForgeOutcome {
|
|
87
|
+
record(.bufferBegin, metadata ?? adMetadataFromParams(params), timestampMs)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public func fireBufferEnd(
|
|
91
|
+
metadata: AdMetadataSnapshot? = nil,
|
|
92
|
+
params: [String: String]? = [:],
|
|
93
|
+
timestampMs: Int64 = 0
|
|
94
|
+
) -> ForgeOutcome {
|
|
95
|
+
record(.bufferEnd, metadata ?? adMetadataFromParams(params), timestampMs)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public func fireQuartile(_ quartile: Int? = nil, timestampMs: Int64 = 0) -> ForgeOutcome {
|
|
99
|
+
var metadata = AdMetadataSnapshot()
|
|
100
|
+
metadata.quartile = quartile
|
|
101
|
+
return record(.quartile, metadata, timestampMs)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public func fireClick(
|
|
105
|
+
metadata: AdMetadataSnapshot? = nil,
|
|
106
|
+
params: [String: String]? = [:],
|
|
107
|
+
timestampMs: Int64 = 0
|
|
108
|
+
) -> ForgeOutcome {
|
|
109
|
+
record(.click, metadata ?? adMetadataFromParams(params), timestampMs)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
public func fireClick(adUrl: String?) -> ForgeOutcome {
|
|
113
|
+
fireClick(params: adUrl.map { ["adUrl": $0] } ?? [:])
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public func fireSkip(timestampMs: Int64 = 0) -> ForgeOutcome {
|
|
117
|
+
record(.skip, AdMetadataSnapshot(), timestampMs)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public func fireStop(
|
|
121
|
+
metadata: AdMetadataSnapshot? = nil,
|
|
122
|
+
params: [String: String]? = [:],
|
|
123
|
+
timestampMs: Int64 = 0
|
|
124
|
+
) -> ForgeOutcome {
|
|
125
|
+
record(.stop, metadata ?? adMetadataFromParams(params), timestampMs)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public func fireError(
|
|
129
|
+
errorCode: String? = nil,
|
|
130
|
+
errorMessage: String? = nil,
|
|
131
|
+
errorMetadata: String? = nil,
|
|
132
|
+
timestampMs: Int64 = 0
|
|
133
|
+
) -> ForgeOutcome {
|
|
134
|
+
var metadata = AdMetadataSnapshot()
|
|
135
|
+
metadata.errorCode = errorCode
|
|
136
|
+
metadata.errorMessage = errorMessage
|
|
137
|
+
metadata.errorMetadata = errorMetadata
|
|
138
|
+
return record(.error, metadata, timestampMs)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public func fireFatalError(
|
|
142
|
+
errorCode: String? = nil,
|
|
143
|
+
errorMessage: String? = nil,
|
|
144
|
+
errorMetadata: String? = nil,
|
|
145
|
+
timestampMs: Int64 = 0
|
|
146
|
+
) -> ForgeOutcome {
|
|
147
|
+
var metadata = AdMetadataSnapshot()
|
|
148
|
+
metadata.errorCode = errorCode
|
|
149
|
+
metadata.errorMessage = errorMessage
|
|
150
|
+
metadata.errorMetadata = errorMetadata
|
|
151
|
+
metadata.errorLevel = "fatal"
|
|
152
|
+
return record(.fatalError, metadata, timestampMs)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public func fireBreakStop(
|
|
156
|
+
metadata: AdMetadataSnapshot? = nil,
|
|
157
|
+
params: [String: String]? = [:],
|
|
158
|
+
timestampMs: Int64 = 0
|
|
159
|
+
) -> ForgeOutcome {
|
|
160
|
+
record(.breakStop, metadata ?? adMetadataFromParams(params), timestampMs)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
public func fireDestroy(timestampMs: Int64 = 0) -> ForgeOutcome {
|
|
164
|
+
guard videoAdapter?.isDestroyed == false else { return .ignoredInvalidState }
|
|
165
|
+
return .unsupportedCapability
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private func record(_ event: AdEvent, _ metadata: AdMetadataSnapshot, _ timestampMs: Int64) -> ForgeOutcome {
|
|
169
|
+
videoAdapter?.recordAdEvent(
|
|
170
|
+
event: event,
|
|
171
|
+
timestampMs: timestampMs,
|
|
172
|
+
metadata: metadata,
|
|
173
|
+
adapterVersion: adapterVersion
|
|
174
|
+
) ?? .ignoredInvalidState
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private func adMetadataFromParams(_ params: [String: String]?) -> AdMetadataSnapshot {
|
|
178
|
+
videoAdapter?.adMetadataFromParams(params) ?? AdMetadataSnapshot()
|
|
179
|
+
}
|
|
180
|
+
}
|