@shortkitsdk/react-native 0.2.6 → 0.2.11
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/ShortKitReactNative.podspec +1 -0
- package/android/build.gradle.kts +5 -1
- package/android/src/main/java/com/shortkit/reactnative/ReactCarouselOverlayHost.kt +319 -0
- package/android/src/main/java/com/shortkit/reactnative/ReactLoadingHost.kt +40 -0
- package/android/src/main/java/com/shortkit/reactnative/ReactOverlayHost.kt +559 -0
- package/android/src/main/java/com/shortkit/reactnative/ShortKitBridge.kt +984 -0
- package/android/src/main/java/com/shortkit/reactnative/ShortKitFeedView.kt +88 -220
- package/android/src/main/java/com/shortkit/reactnative/ShortKitFeedViewManager.kt +12 -3
- package/android/src/main/java/com/shortkit/reactnative/ShortKitModule.kt +123 -741
- package/android/src/main/java/com/shortkit/reactnative/ShortKitPlayerNativeView.kt +2 -2
- package/android/src/main/java/com/shortkit/reactnative/ShortKitWidgetNativeView.kt +2 -2
- package/ios/ReactCarouselOverlayHost.swift +177 -0
- package/ios/ReactLoadingHost.swift +38 -0
- package/ios/ReactOverlayHost.swift +458 -0
- package/ios/SKFabricSurfaceWrapper.h +18 -0
- package/ios/SKFabricSurfaceWrapper.mm +57 -0
- package/ios/ShortKitBridge.swift +186 -63
- package/ios/ShortKitFeedView.swift +62 -229
- package/ios/ShortKitFeedViewManager.mm +3 -2
- package/ios/ShortKitModule.mm +66 -37
- package/ios/ShortKitPlayerNativeView.swift +39 -8
- package/ios/ShortKitReactNative-Bridging-Header.h +2 -0
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +1 -1
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.abi.json +2380 -522
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +39 -12
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftinterface +39 -12
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +1 -1
- package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +2380 -522
- package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +39 -12
- package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +39 -12
- package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/ShortKitSDK.xcframework.bak/Info.plist +43 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +418 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Info.plist +16 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.abi.json +28917 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +824 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftinterface +824 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/module.modulemap +4 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +418 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Info.plist +16 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +28917 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +824 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +824 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/module.modulemap +4 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/ShortKitWidgetNativeView.swift +3 -3
- package/package.json +1 -1
- package/src/ShortKitCarouselOverlaySurface.tsx +55 -0
- package/src/ShortKitCommands.ts +31 -0
- package/src/ShortKitContext.ts +6 -25
- package/src/ShortKitFeed.tsx +110 -41
- package/src/ShortKitLoadingSurface.tsx +24 -0
- package/src/ShortKitOverlaySurface.tsx +205 -0
- package/src/ShortKitPlayer.tsx +6 -7
- package/src/ShortKitProvider.tsx +27 -286
- package/src/index.ts +5 -3
- package/src/serialization.ts +19 -39
- package/src/specs/NativeShortKitModule.ts +58 -46
- package/src/specs/ShortKitFeedViewNativeComponent.ts +3 -2
- package/src/types.ts +78 -16
- package/src/useShortKit.ts +1 -3
- package/src/useShortKitPlayer.ts +7 -7
- package/android/src/main/java/com/shortkit/reactnative/ShortKitCarouselOverlayBridge.kt +0 -48
- package/android/src/main/java/com/shortkit/reactnative/ShortKitOverlayBridge.kt +0 -128
- package/ios/ShortKitCarouselOverlayBridge.swift +0 -219
- package/ios/ShortKitOverlayBridge.swift +0 -111
- package/src/CarouselOverlayManager.tsx +0 -70
- package/src/OverlayManager.tsx +0 -87
- package/src/useShortKitCarousel.ts +0 -29
package/ios/ShortKitBridge.swift
CHANGED
|
@@ -18,25 +18,78 @@ import ShortKitSDK
|
|
|
18
18
|
private var cancellables = Set<AnyCancellable>()
|
|
19
19
|
private weak var delegate: ShortKitBridgeDelegateProtocol?
|
|
20
20
|
|
|
21
|
+
/// Surface presenter for creating RCTFabricSurface instances in overlay hosts.
|
|
22
|
+
/// Set from ShortKitModule.mm via setSurfacePresenter: (called by RCTInstance).
|
|
23
|
+
public var surfacePresenter: AnyObject?
|
|
24
|
+
|
|
25
|
+
/// Called from ShortKitModule when RCTInstance provides the surface presenter.
|
|
26
|
+
@objc public func updateSurfacePresenter(_ presenter: AnyObject?) {
|
|
27
|
+
self.surfacePresenter = presenter
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/// Preload handles keyed by UUID, consumed by feed views via preloadId prop.
|
|
31
|
+
public var preloadHandles: [String: FeedPreload] = [:]
|
|
32
|
+
|
|
33
|
+
// MARK: - Feed Instance Registry
|
|
34
|
+
|
|
35
|
+
private struct WeakFeedRef {
|
|
36
|
+
weak var vc: ShortKitFeedViewController?
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private var feedRegistry: [String: WeakFeedRef] = [:]
|
|
40
|
+
private var pendingOps: [String: [(ShortKitFeedViewController) -> Void]] = [:]
|
|
41
|
+
|
|
42
|
+
public func registerFeed(id: String, viewController vc: ShortKitFeedViewController) {
|
|
43
|
+
feedRegistry[id] = WeakFeedRef(vc: vc)
|
|
44
|
+
|
|
45
|
+
// Wire per-feed remaining content count callback
|
|
46
|
+
vc.onRemainingContentCountChange = { [weak self] count in
|
|
47
|
+
self?.emit("onRemainingContentCountChanged", body: [
|
|
48
|
+
"feedId": id,
|
|
49
|
+
"count": count
|
|
50
|
+
])
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Replay buffered operations on the next run-loop tick so the VC's
|
|
54
|
+
// view hierarchy is fully set up after didMoveToWindow returns.
|
|
55
|
+
if let ops = pendingOps.removeValue(forKey: id) {
|
|
56
|
+
DispatchQueue.main.async { [weak vc] in
|
|
57
|
+
guard let vc = vc else { return }
|
|
58
|
+
for op in ops {
|
|
59
|
+
op(vc)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public func unregisterFeed(id: String) {
|
|
66
|
+
feedRegistry.removeValue(forKey: id)
|
|
67
|
+
// Note: pendingOps are preserved for this ID to survive detach/reattach cycles
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private func feedViewController(for id: String) -> ShortKitFeedViewController? {
|
|
71
|
+
return feedRegistry[id]?.vc
|
|
72
|
+
}
|
|
73
|
+
|
|
21
74
|
// MARK: - Init
|
|
22
75
|
|
|
23
76
|
@objc public init(
|
|
24
77
|
apiKey: String,
|
|
25
|
-
|
|
78
|
+
hasLoadingView: Bool,
|
|
26
79
|
clientAppName: String?,
|
|
27
80
|
clientAppVersion: String?,
|
|
28
81
|
customDimensions customDimensionsJSON: String?,
|
|
29
|
-
delegate: ShortKitBridgeDelegateProtocol
|
|
82
|
+
delegate: ShortKitBridgeDelegateProtocol,
|
|
83
|
+
surfacePresenter: AnyObject?
|
|
30
84
|
) {
|
|
31
85
|
self.delegate = delegate
|
|
86
|
+
self.surfacePresenter = surfacePresenter
|
|
32
87
|
super.init()
|
|
33
88
|
|
|
34
|
-
let feedConfig = Self.parseFeedConfig(configJSON)
|
|
35
89
|
let dimensions = Self.parseCustomDimensions(customDimensionsJSON)
|
|
36
90
|
|
|
37
91
|
let sdk = ShortKit(
|
|
38
92
|
apiKey: apiKey,
|
|
39
|
-
config: feedConfig,
|
|
40
93
|
clientAppName: clientAppName,
|
|
41
94
|
clientAppVersion: clientAppVersion,
|
|
42
95
|
customDimensions: dimensions
|
|
@@ -45,6 +98,14 @@ import ShortKitSDK
|
|
|
45
98
|
|
|
46
99
|
ShortKitBridge.shared = self
|
|
47
100
|
|
|
101
|
+
if hasLoadingView {
|
|
102
|
+
sdk.loadingViewProvider = { [weak self] in
|
|
103
|
+
let host = ReactLoadingHost()
|
|
104
|
+
host.surfacePresenter = self?.surfacePresenter
|
|
105
|
+
return host
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
48
109
|
subscribeToPublishers(sdk.player)
|
|
49
110
|
sdk.delegate = self
|
|
50
111
|
}
|
|
@@ -53,6 +114,9 @@ import ShortKitSDK
|
|
|
53
114
|
|
|
54
115
|
@objc public func teardown() {
|
|
55
116
|
cancellables.removeAll()
|
|
117
|
+
preloadHandles.removeAll()
|
|
118
|
+
feedRegistry.removeAll()
|
|
119
|
+
pendingOps.removeAll()
|
|
56
120
|
shortKit = nil
|
|
57
121
|
if ShortKitBridge.shared === self {
|
|
58
122
|
ShortKitBridge.shared = nil
|
|
@@ -143,17 +207,31 @@ import ShortKitSDK
|
|
|
143
207
|
|
|
144
208
|
// MARK: - Custom Feed
|
|
145
209
|
|
|
146
|
-
@objc public func setFeedItems(_ json: String) {
|
|
210
|
+
@objc public func setFeedItems(_ feedId: String, items json: String) {
|
|
147
211
|
guard let items = Self.parseFeedInputs(json) else { return }
|
|
148
|
-
|
|
149
|
-
self
|
|
212
|
+
DispatchQueue.main.async { [weak self] in
|
|
213
|
+
guard let self else { return }
|
|
214
|
+
if let vc = self.feedViewController(for: feedId) {
|
|
215
|
+
vc.setFeedItems(items)
|
|
216
|
+
} else {
|
|
217
|
+
self.pendingOps[feedId, default: []].append { vc in
|
|
218
|
+
vc.setFeedItems(items)
|
|
219
|
+
}
|
|
220
|
+
}
|
|
150
221
|
}
|
|
151
222
|
}
|
|
152
223
|
|
|
153
|
-
@objc public func appendFeedItems(_ json: String) {
|
|
224
|
+
@objc public func appendFeedItems(_ feedId: String, items json: String) {
|
|
154
225
|
guard let items = Self.parseFeedInputs(json) else { return }
|
|
155
|
-
|
|
156
|
-
self
|
|
226
|
+
DispatchQueue.main.async { [weak self] in
|
|
227
|
+
guard let self else { return }
|
|
228
|
+
if let vc = self.feedViewController(for: feedId) {
|
|
229
|
+
vc.appendFeedItems(items)
|
|
230
|
+
} else {
|
|
231
|
+
self.pendingOps[feedId, default: []].append { vc in
|
|
232
|
+
vc.appendFeedItems(items)
|
|
233
|
+
}
|
|
234
|
+
}
|
|
157
235
|
}
|
|
158
236
|
}
|
|
159
237
|
|
|
@@ -209,14 +287,25 @@ import ShortKitSDK
|
|
|
209
287
|
}
|
|
210
288
|
}
|
|
211
289
|
|
|
212
|
-
@objc public func
|
|
213
|
-
|
|
290
|
+
@objc public func applyFilter(_ feedId: String, filterJSON: String?) {
|
|
291
|
+
let filter = filterJSON.flatMap { Self.parseFeedFilter($0) }
|
|
292
|
+
DispatchQueue.main.async { [weak self] in
|
|
293
|
+
guard let self else { return }
|
|
294
|
+
if let vc = self.feedViewController(for: feedId) {
|
|
295
|
+
vc.applyFilter(filter)
|
|
296
|
+
} else {
|
|
297
|
+
self.pendingOps[feedId, default: []].append { vc in
|
|
298
|
+
vc.applyFilter(filter)
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
214
302
|
}
|
|
215
303
|
|
|
216
|
-
@objc public func fetchContent(_ limit: Int, completion: @escaping (String) -> Void) {
|
|
304
|
+
@objc public func fetchContent(_ limit: Int, filterJSON: String?, completion: @escaping (String) -> Void) {
|
|
305
|
+
let filter = filterJSON.flatMap { Self.parseFeedFilter($0) }
|
|
217
306
|
Task {
|
|
218
307
|
do {
|
|
219
|
-
let items = try await self.shortKit?.fetchContent(limit: limit) ?? []
|
|
308
|
+
let items = try await self.shortKit?.fetchContent(limit: limit, filter: filter) ?? []
|
|
220
309
|
let data = try JSONEncoder().encode(items)
|
|
221
310
|
let json = String(data: data, encoding: .utf8) ?? "[]"
|
|
222
311
|
completion(json)
|
|
@@ -226,6 +315,22 @@ import ShortKitSDK
|
|
|
226
315
|
}
|
|
227
316
|
}
|
|
228
317
|
|
|
318
|
+
@objc public func preloadFeed(_ configJSON: String, completion: @escaping (String) -> Void) {
|
|
319
|
+
let config = Self.parseFeedConfig(configJSON)
|
|
320
|
+
guard let preload = shortKit?.preloadFeed(filter: config.filter) else {
|
|
321
|
+
completion("")
|
|
322
|
+
return
|
|
323
|
+
}
|
|
324
|
+
let uuid = UUID().uuidString
|
|
325
|
+
preloadHandles[uuid] = preload
|
|
326
|
+
completion(uuid)
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/// Consume a preload handle by ID. Returns and removes the handle.
|
|
330
|
+
public func consumePreload(id: String) -> FeedPreload? {
|
|
331
|
+
return preloadHandles.removeValue(forKey: id)
|
|
332
|
+
}
|
|
333
|
+
|
|
229
334
|
// MARK: - Combine Subscriptions
|
|
230
335
|
|
|
231
336
|
private func subscribeToPublishers(_ player: ShortKitPlayer) {
|
|
@@ -382,22 +487,16 @@ import ShortKitSDK
|
|
|
382
487
|
}
|
|
383
488
|
.store(in: &cancellables)
|
|
384
489
|
|
|
385
|
-
// Remaining content count
|
|
386
|
-
player.remainingContentCount
|
|
387
|
-
.receive(on: DispatchQueue.main)
|
|
388
|
-
.sink { [weak self] count in
|
|
389
|
-
self?.emit("onRemainingContentCountChanged", body: ["count": count])
|
|
390
|
-
}
|
|
391
|
-
.store(in: &cancellables)
|
|
490
|
+
// Remaining content count — now handled per-feed via onRemainingContentCountChange callback
|
|
392
491
|
}
|
|
393
492
|
|
|
394
493
|
// MARK: - Event Emission Helpers
|
|
395
494
|
|
|
396
|
-
|
|
495
|
+
func emit(_ name: String, body: [String: Any]) {
|
|
397
496
|
delegate?.emitEvent(name, body: body)
|
|
398
497
|
}
|
|
399
498
|
|
|
400
|
-
|
|
499
|
+
func emitOnMain(_ name: String, body: [String: Any]) {
|
|
401
500
|
if Thread.isMainThread {
|
|
402
501
|
emit(name, body: body)
|
|
403
502
|
} else {
|
|
@@ -407,32 +506,6 @@ import ShortKitSDK
|
|
|
407
506
|
}
|
|
408
507
|
}
|
|
409
508
|
|
|
410
|
-
// MARK: - Overlay Lifecycle Events (called by Fabric view in Task 13)
|
|
411
|
-
|
|
412
|
-
/// Emit overlay lifecycle events from the Fabric view's overlay container.
|
|
413
|
-
public func emitOverlayEvent(_ name: String, item: ContentItem) {
|
|
414
|
-
emitOnMain(name, body: ["item": serializeContentItemToJSON(item)])
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
/// Emit a raw overlay event with an arbitrary body.
|
|
418
|
-
public func emitOverlayEvent(_ name: String, body: [String: Any]) {
|
|
419
|
-
emitOnMain(name, body: body)
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
// MARK: - Carousel Overlay Lifecycle Events
|
|
423
|
-
|
|
424
|
-
/// Emit carousel overlay lifecycle events with an ImageCarouselItem.
|
|
425
|
-
public func emitCarouselOverlayEvent(_ name: String, item: ImageCarouselItem) {
|
|
426
|
-
guard let data = try? JSONEncoder().encode(item),
|
|
427
|
-
let json = String(data: data, encoding: .utf8) else { return }
|
|
428
|
-
emitOnMain(name, body: ["item": json])
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/// Emit a raw carousel overlay event with an arbitrary body.
|
|
432
|
-
public func emitCarouselOverlayEvent(_ name: String, body: [String: Any]) {
|
|
433
|
-
emitOnMain(name, body: body)
|
|
434
|
-
}
|
|
435
|
-
|
|
436
509
|
// MARK: - Content Item Serialization
|
|
437
510
|
|
|
438
511
|
/// Serialize a ContentItem to a JSON string for bridge transport.
|
|
@@ -487,6 +560,9 @@ import ShortKitSDK
|
|
|
487
560
|
if let commentCount = item.commentCount {
|
|
488
561
|
dict["commentCount"] = commentCount
|
|
489
562
|
}
|
|
563
|
+
if let fallbackUrl = item.fallbackUrl {
|
|
564
|
+
dict["fallbackUrl"] = fallbackUrl
|
|
565
|
+
}
|
|
490
566
|
|
|
491
567
|
return dict
|
|
492
568
|
}
|
|
@@ -530,7 +606,7 @@ import ShortKitSDK
|
|
|
530
606
|
/// {"feedHeight":"{\"type\":\"fullscreen\"}","overlay":"\"none\"",
|
|
531
607
|
/// "carouselMode":"\"none\"","surveyMode":"\"none\"","muteOnStart":true}
|
|
532
608
|
/// ```
|
|
533
|
-
|
|
609
|
+
public static func parseFeedConfig(_ json: String) -> FeedConfig {
|
|
534
610
|
guard let data = json.data(using: .utf8),
|
|
535
611
|
let obj = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
|
|
536
612
|
return FeedConfig()
|
|
@@ -538,6 +614,7 @@ import ShortKitSDK
|
|
|
538
614
|
|
|
539
615
|
let feedHeight = parseFeedHeight(obj["feedHeight"] as? String)
|
|
540
616
|
let muteOnStart = obj["muteOnStart"] as? Bool ?? true
|
|
617
|
+
let autoplay = obj["autoplay"] as? Bool ?? true
|
|
541
618
|
let videoOverlay = parseVideoOverlay(obj["overlay"] as? String)
|
|
542
619
|
|
|
543
620
|
let feedSourceStr = obj["feedSource"] as? String ?? "algorithmic"
|
|
@@ -545,6 +622,8 @@ import ShortKitSDK
|
|
|
545
622
|
|
|
546
623
|
let carouselOverlay = parseCarouselOverlay(obj["carouselOverlay"] as? String)
|
|
547
624
|
|
|
625
|
+
let filter = parseFeedFilter(obj["filter"] as? String)
|
|
626
|
+
|
|
548
627
|
return FeedConfig(
|
|
549
628
|
feedHeight: feedHeight,
|
|
550
629
|
videoOverlay: videoOverlay,
|
|
@@ -552,7 +631,9 @@ import ShortKitSDK
|
|
|
552
631
|
surveyOverlay: .none,
|
|
553
632
|
adOverlay: .none,
|
|
554
633
|
muteOnStart: muteOnStart,
|
|
555
|
-
|
|
634
|
+
autoplay: autoplay,
|
|
635
|
+
feedSource: feedSource,
|
|
636
|
+
filter: filter
|
|
556
637
|
)
|
|
557
638
|
}
|
|
558
639
|
|
|
@@ -560,7 +641,7 @@ import ShortKitSDK
|
|
|
560
641
|
///
|
|
561
642
|
/// Examples:
|
|
562
643
|
/// - `"\"none\""` → `.none`
|
|
563
|
-
/// - `"{\"type\":\"custom\"}"` → `.custom {
|
|
644
|
+
/// - `"{\"type\":\"custom\"}"` → `.custom { ReactOverlayHost() }`
|
|
564
645
|
private static func parseVideoOverlay(_ json: String?) -> VideoOverlayMode {
|
|
565
646
|
guard let json,
|
|
566
647
|
let data = json.data(using: .utf8),
|
|
@@ -577,10 +658,13 @@ import ShortKitSDK
|
|
|
577
658
|
if let obj = parsed as? [String: Any],
|
|
578
659
|
let type = obj["type"] as? String,
|
|
579
660
|
type == "custom" {
|
|
661
|
+
let name = obj["name"] as? String ?? "Default"
|
|
580
662
|
return .custom { @Sendable in
|
|
581
|
-
let
|
|
582
|
-
|
|
583
|
-
|
|
663
|
+
let host = ReactOverlayHost()
|
|
664
|
+
host.surfacePresenter = ShortKitBridge.shared?.surfacePresenter
|
|
665
|
+
host.overlayModuleName = "ShortKitOverlay_\(name)"
|
|
666
|
+
host.bridge = ShortKitBridge.shared
|
|
667
|
+
return host
|
|
584
668
|
}
|
|
585
669
|
}
|
|
586
670
|
|
|
@@ -591,7 +675,7 @@ import ShortKitSDK
|
|
|
591
675
|
///
|
|
592
676
|
/// Examples:
|
|
593
677
|
/// - `"\"none\""` → `.none`
|
|
594
|
-
/// - `"{\"type\":\"custom\"}"` → `.custom {
|
|
678
|
+
/// - `"{\"type\":\"custom\",\"name\":\"news\"}"` → `.custom { ReactCarouselOverlayHost() }`
|
|
595
679
|
private static func parseCarouselOverlay(_ json: String?) -> CarouselOverlayMode {
|
|
596
680
|
guard let json,
|
|
597
681
|
let data = json.data(using: .utf8),
|
|
@@ -606,10 +690,16 @@ import ShortKitSDK
|
|
|
606
690
|
if let obj = parsed as? [String: Any],
|
|
607
691
|
let type = obj["type"] as? String,
|
|
608
692
|
type == "custom" {
|
|
693
|
+
let name = obj["name"] as? String ?? "Default"
|
|
609
694
|
return .custom { @Sendable in
|
|
610
|
-
let
|
|
611
|
-
|
|
612
|
-
|
|
695
|
+
let host = ReactCarouselOverlayHost()
|
|
696
|
+
host.surfacePresenter = ShortKitBridge.shared?.surfacePresenter
|
|
697
|
+
host.bridge = ShortKitBridge.shared
|
|
698
|
+
host.carouselOverlayModuleName = "ShortKitCarouselOverlay_\(name)"
|
|
699
|
+
// Eagerly create the RN surface so it's mounted and ready before
|
|
700
|
+
// the cell scrolls into view, matching video overlay behaviour.
|
|
701
|
+
host.prepareSurface()
|
|
702
|
+
return host
|
|
613
703
|
}
|
|
614
704
|
}
|
|
615
705
|
|
|
@@ -637,6 +727,23 @@ import ShortKitSDK
|
|
|
637
727
|
}
|
|
638
728
|
}
|
|
639
729
|
|
|
730
|
+
/// Parse a JSON string of FeedFilter from the JS bridge.
|
|
731
|
+
private static func parseFeedFilter(_ json: String?) -> FeedFilter? {
|
|
732
|
+
guard let json,
|
|
733
|
+
let data = json.data(using: .utf8),
|
|
734
|
+
let obj = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
|
|
735
|
+
return nil
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
return FeedFilter(
|
|
739
|
+
tags: obj["tags"] as? [String],
|
|
740
|
+
section: obj["section"] as? String,
|
|
741
|
+
author: obj["author"] as? String,
|
|
742
|
+
contentType: obj["contentType"] as? String,
|
|
743
|
+
metadata: obj["metadata"] as? [String: String]
|
|
744
|
+
)
|
|
745
|
+
}
|
|
746
|
+
|
|
640
747
|
/// Parse a JSON string of FeedInput[] from the JS bridge.
|
|
641
748
|
private static func parseFeedInputs(_ json: String) -> [FeedInput]? {
|
|
642
749
|
guard let data = json.data(using: .utf8),
|
|
@@ -650,7 +757,8 @@ import ShortKitSDK
|
|
|
650
757
|
switch type {
|
|
651
758
|
case "video":
|
|
652
759
|
guard let playbackId = obj["playbackId"] as? String else { continue }
|
|
653
|
-
|
|
760
|
+
let fallbackUrl = obj["fallbackUrl"] as? String
|
|
761
|
+
result.append(.video(playbackId: playbackId, fallbackUrl: fallbackUrl))
|
|
654
762
|
case "imageCarousel":
|
|
655
763
|
guard let itemData = obj["item"],
|
|
656
764
|
let itemJSON = try? JSONSerialization.data(withJSONObject: itemData),
|
|
@@ -685,10 +793,25 @@ extension ShortKitBridge: ShortKitDelegate {
|
|
|
685
793
|
"index": index
|
|
686
794
|
])
|
|
687
795
|
}
|
|
796
|
+
|
|
797
|
+
public func shortKitDidRequestRefresh(_ shortKit: ShortKit) {
|
|
798
|
+
emitOnMain("onRefreshRequested", body: [:])
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
public func shortKit(_ shortKit: ShortKit, didFetchContentItems items: [ContentItem]) {
|
|
802
|
+
Task {
|
|
803
|
+
let data = try? JSONEncoder().encode(items)
|
|
804
|
+
let json = data.flatMap { String(data: $0, encoding: .utf8) } ?? "[]"
|
|
805
|
+
self.emitOnMain("onDidFetchContentItems", body: ["items": json])
|
|
806
|
+
}
|
|
807
|
+
}
|
|
688
808
|
}
|
|
689
809
|
|
|
690
|
-
// MARK: -
|
|
810
|
+
// MARK: - Dismiss Emission
|
|
691
811
|
|
|
692
|
-
extension
|
|
693
|
-
|
|
812
|
+
extension ShortKitBridge {
|
|
813
|
+
@objc public func emitDismiss() {
|
|
814
|
+
emitOnMain("onDismiss", body: [:])
|
|
815
|
+
}
|
|
694
816
|
}
|
|
817
|
+
|