@shortkitsdk/react-native 0.2.11 → 0.2.12
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.kts +13 -1
- package/android/src/main/java/com/shortkit/reactnative/ReactCarouselOverlayHost.kt +115 -55
- package/android/src/main/java/com/shortkit/reactnative/ReactOverlayHost.kt +67 -56
- package/android/src/main/java/com/shortkit/reactnative/ShortKitBridge.kt +71 -26
- package/android/src/main/java/com/shortkit/reactnative/ShortKitFeedView.kt +160 -35
- package/android/src/main/java/com/shortkit/reactnative/ShortKitFeedViewManager.kt +5 -0
- package/android/src/main/java/com/shortkit/reactnative/ShortKitModule.kt +43 -10
- package/android/src/main/java/com/shortkit/reactnative/ShortKitPlayerNativeView.kt +9 -0
- package/ios/ReactOverlayHost.swift +13 -27
- package/ios/ShortKitBridge.swift +36 -2
- package/ios/ShortKitFeedView.swift +24 -3
- package/ios/ShortKitModule.mm +4 -1
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.abi.json +720 -144
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +19 -5
- 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 +19 -5
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +720 -144
- package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +19 -5
- 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 +19 -5
- package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/package.json +1 -1
- package/src/ShortKitContext.ts +2 -1
- package/src/ShortKitFeed.tsx +14 -0
- package/src/ShortKitOverlaySurface.tsx +153 -45
- package/src/ShortKitPlayer.tsx +25 -3
- package/src/ShortKitProvider.tsx +4 -2
- package/src/index.ts +4 -0
- package/src/serialization.ts +1 -0
- package/src/specs/NativeShortKitModule.ts +18 -1
- package/src/types.ts +6 -0
|
@@ -169,6 +169,15 @@ public enum FeedHeight : Swift.Codable, Swift.Equatable, Swift.Sendable {
|
|
|
169
169
|
public func encode(to encoder: any Swift.Encoder) throws
|
|
170
170
|
public init(from decoder: any Swift.Decoder) throws
|
|
171
171
|
}
|
|
172
|
+
public enum ScrollAxis : Swift.String, Swift.Codable, Swift.Equatable, Swift.Sendable {
|
|
173
|
+
case vertical
|
|
174
|
+
case horizontal
|
|
175
|
+
public init?(rawValue: Swift.String)
|
|
176
|
+
public typealias RawValue = Swift.String
|
|
177
|
+
public var rawValue: Swift.String {
|
|
178
|
+
get
|
|
179
|
+
}
|
|
180
|
+
}
|
|
172
181
|
public enum FeedSource : Swift.String, Swift.Codable, Swift.Equatable, Swift.Sendable {
|
|
173
182
|
case algorithmic
|
|
174
183
|
case custom
|
|
@@ -191,6 +200,7 @@ public struct FeedFilter : Swift.Codable, Swift.Equatable, Swift.Sendable {
|
|
|
191
200
|
}
|
|
192
201
|
public struct FeedConfig : Swift.Codable {
|
|
193
202
|
public var feedHeight: ShortKitSDK.FeedHeight
|
|
203
|
+
public var scrollAxis: ShortKitSDK.ScrollAxis
|
|
194
204
|
public var videoOverlay: ShortKitSDK.VideoOverlayMode
|
|
195
205
|
public var carouselOverlay: ShortKitSDK.CarouselOverlayMode
|
|
196
206
|
public var surveyOverlay: ShortKitSDK.SurveyOverlayMode
|
|
@@ -201,7 +211,7 @@ public struct FeedConfig : Swift.Codable {
|
|
|
201
211
|
public var coldStartEnabled: Swift.Bool
|
|
202
212
|
public var filter: ShortKitSDK.FeedFilter?
|
|
203
213
|
public var preload: ShortKitSDK.FeedPreload?
|
|
204
|
-
public init(feedHeight: ShortKitSDK.FeedHeight = .fullscreen, videoOverlay: ShortKitSDK.VideoOverlayMode = .none, carouselOverlay: ShortKitSDK.CarouselOverlayMode = .none, surveyOverlay: ShortKitSDK.SurveyOverlayMode = .none, adOverlay: ShortKitSDK.AdOverlayMode = .none, muteOnStart: Swift.Bool = true, autoplay: Swift.Bool = true, feedSource: ShortKitSDK.FeedSource = .algorithmic, coldStartEnabled: Swift.Bool = false, filter: ShortKitSDK.FeedFilter? = nil, preload: ShortKitSDK.FeedPreload? = nil)
|
|
214
|
+
public init(feedHeight: ShortKitSDK.FeedHeight = .fullscreen, scrollAxis: ShortKitSDK.ScrollAxis = .vertical, videoOverlay: ShortKitSDK.VideoOverlayMode = .none, carouselOverlay: ShortKitSDK.CarouselOverlayMode = .none, surveyOverlay: ShortKitSDK.SurveyOverlayMode = .none, adOverlay: ShortKitSDK.AdOverlayMode = .none, muteOnStart: Swift.Bool = true, autoplay: Swift.Bool = true, feedSource: ShortKitSDK.FeedSource = .algorithmic, coldStartEnabled: Swift.Bool = false, filter: ShortKitSDK.FeedFilter? = nil, preload: ShortKitSDK.FeedPreload? = nil)
|
|
205
215
|
public func encode(to encoder: any Swift.Encoder) throws
|
|
206
216
|
public init(from decoder: any Swift.Decoder) throws
|
|
207
217
|
}
|
|
@@ -266,7 +276,7 @@ extension ShortKitSDK.ShortKitDelegate {
|
|
|
266
276
|
@objc deinit
|
|
267
277
|
}
|
|
268
278
|
@_Concurrency.MainActor @preconcurrency public struct ShortKitFeedView : SwiftUI.UIViewControllerRepresentable {
|
|
269
|
-
@_Concurrency.MainActor @preconcurrency public init(shortKit: ShortKitSDK.ShortKit, config: ShortKitSDK.FeedConfig)
|
|
279
|
+
@_Concurrency.MainActor @preconcurrency public init(shortKit: ShortKitSDK.ShortKit, config: ShortKitSDK.FeedConfig = FeedConfig(), onFeedReady: (() -> Swift.Void)? = nil)
|
|
270
280
|
@_Concurrency.MainActor @preconcurrency public func makeCoordinator() -> ShortKitSDK.ShortKitFeedView.Coordinator
|
|
271
281
|
@_Concurrency.MainActor @preconcurrency public func makeUIViewController(context: ShortKitSDK.ShortKitFeedView.Context) -> ShortKitSDK.ShortKitFeedViewController
|
|
272
282
|
@_Concurrency.MainActor @preconcurrency public func updateUIViewController(_ uiViewController: ShortKitSDK.ShortKitFeedViewController, context: ShortKitSDK.ShortKitFeedView.Context)
|
|
@@ -280,6 +290,7 @@ extension ShortKitSDK.ShortKitDelegate {
|
|
|
280
290
|
@objc @_hasMissingDesignatedInitializers @_Concurrency.MainActor @preconcurrency public class ShortKitFeedViewController : UIKit.UIViewController {
|
|
281
291
|
@_Concurrency.MainActor @preconcurrency public var onDismiss: (() -> Swift.Void)?
|
|
282
292
|
@_Concurrency.MainActor @preconcurrency public var onRemainingContentCountChange: ((Swift.Int) -> Swift.Void)?
|
|
293
|
+
@_Concurrency.MainActor @preconcurrency public var onFeedReady: (() -> Swift.Void)?
|
|
283
294
|
@_Concurrency.MainActor @preconcurrency public init(shortKit: ShortKitSDK.ShortKit, config: ShortKitSDK.FeedConfig, startAtItemId: Swift.String? = nil)
|
|
284
295
|
@_Concurrency.MainActor public func setFeedItems(_ items: [ShortKitSDK.FeedInput])
|
|
285
296
|
@_Concurrency.MainActor public func appendFeedItems(_ items: [ShortKitSDK.FeedInput])
|
|
@@ -289,6 +300,9 @@ extension ShortKitSDK.ShortKitDelegate {
|
|
|
289
300
|
@_Concurrency.MainActor @preconcurrency @objc override dynamic public func viewWillAppear(_ animated: Swift.Bool)
|
|
290
301
|
@_Concurrency.MainActor @preconcurrency @objc override dynamic public func viewDidAppear(_ animated: Swift.Bool)
|
|
291
302
|
@_Concurrency.MainActor @preconcurrency @objc override dynamic public func viewWillDisappear(_ animated: Swift.Bool)
|
|
303
|
+
@_Concurrency.MainActor @preconcurrency public func setBridgeManaged()
|
|
304
|
+
@_Concurrency.MainActor @preconcurrency public func activate()
|
|
305
|
+
@_Concurrency.MainActor @preconcurrency public func deactivate()
|
|
292
306
|
@_Concurrency.MainActor @preconcurrency @objc override dynamic public func viewDidDisappear(_ animated: Swift.Bool)
|
|
293
307
|
@_Concurrency.MainActor @preconcurrency @objc override dynamic public var supportedInterfaceOrientations: UIKit.UIInterfaceOrientationMask {
|
|
294
308
|
@objc get
|
|
@@ -689,9 +703,6 @@ public enum ContentSignal : Swift.Equatable, Swift.Sendable {
|
|
|
689
703
|
final public var remainingContentCount: Combine.AnyPublisher<Swift.Int, Swift.Never> {
|
|
690
704
|
get
|
|
691
705
|
}
|
|
692
|
-
final public var feedReady: Combine.AnyPublisher<Swift.Void, Swift.Never> {
|
|
693
|
-
get
|
|
694
|
-
}
|
|
695
706
|
final public var currentItemValue: ShortKitSDK.ContentItem? {
|
|
696
707
|
get
|
|
697
708
|
}
|
|
@@ -754,6 +765,7 @@ final public class ShortKit {
|
|
|
754
765
|
final public var loadingViewProvider: (() -> UIKit.UIView)?
|
|
755
766
|
public init(apiKey: Swift.String, userId: Swift.String? = nil, adProvider: (any ShortKitSDK.ShortKitAdProvider)? = nil, clientAppName: Swift.String? = nil, clientAppVersion: Swift.String? = nil, customDimensions: [Swift.String : Swift.String]? = nil, loadingViewProvider: (() -> UIKit.UIView)? = nil)
|
|
756
767
|
final public func preloadFeed(filter: ShortKitSDK.FeedFilter? = nil, limit: Swift.Int = 10) -> ShortKitSDK.FeedPreload
|
|
768
|
+
final public func preloadFeed(items: [ShortKitSDK.FeedInput]) -> ShortKitSDK.FeedPreload
|
|
757
769
|
final public func fetchContent(limit: Swift.Int = 10, filter: ShortKitSDK.FeedFilter? = nil) async throws -> [ShortKitSDK.ContentItem]
|
|
758
770
|
final public func setUserId(_ id: Swift.String)
|
|
759
771
|
final public func clearUserId()
|
|
@@ -835,6 +847,8 @@ public struct WidgetConfig {
|
|
|
835
847
|
}
|
|
836
848
|
extension ShortKitSDK.AdQuartile : Swift.Equatable {}
|
|
837
849
|
extension ShortKitSDK.AdQuartile : Swift.Hashable {}
|
|
850
|
+
extension ShortKitSDK.ScrollAxis : Swift.Hashable {}
|
|
851
|
+
extension ShortKitSDK.ScrollAxis : Swift.RawRepresentable {}
|
|
838
852
|
extension ShortKitSDK.FeedSource : Swift.Hashable {}
|
|
839
853
|
extension ShortKitSDK.FeedSource : Swift.RawRepresentable {}
|
|
840
854
|
extension ShortKitSDK.ShortKitFeedView : Swift.Sendable {}
|
|
Binary file
|
|
@@ -169,6 +169,15 @@ public enum FeedHeight : Swift.Codable, Swift.Equatable, Swift.Sendable {
|
|
|
169
169
|
public func encode(to encoder: any Swift.Encoder) throws
|
|
170
170
|
public init(from decoder: any Swift.Decoder) throws
|
|
171
171
|
}
|
|
172
|
+
public enum ScrollAxis : Swift.String, Swift.Codable, Swift.Equatable, Swift.Sendable {
|
|
173
|
+
case vertical
|
|
174
|
+
case horizontal
|
|
175
|
+
public init?(rawValue: Swift.String)
|
|
176
|
+
public typealias RawValue = Swift.String
|
|
177
|
+
public var rawValue: Swift.String {
|
|
178
|
+
get
|
|
179
|
+
}
|
|
180
|
+
}
|
|
172
181
|
public enum FeedSource : Swift.String, Swift.Codable, Swift.Equatable, Swift.Sendable {
|
|
173
182
|
case algorithmic
|
|
174
183
|
case custom
|
|
@@ -191,6 +200,7 @@ public struct FeedFilter : Swift.Codable, Swift.Equatable, Swift.Sendable {
|
|
|
191
200
|
}
|
|
192
201
|
public struct FeedConfig : Swift.Codable {
|
|
193
202
|
public var feedHeight: ShortKitSDK.FeedHeight
|
|
203
|
+
public var scrollAxis: ShortKitSDK.ScrollAxis
|
|
194
204
|
public var videoOverlay: ShortKitSDK.VideoOverlayMode
|
|
195
205
|
public var carouselOverlay: ShortKitSDK.CarouselOverlayMode
|
|
196
206
|
public var surveyOverlay: ShortKitSDK.SurveyOverlayMode
|
|
@@ -201,7 +211,7 @@ public struct FeedConfig : Swift.Codable {
|
|
|
201
211
|
public var coldStartEnabled: Swift.Bool
|
|
202
212
|
public var filter: ShortKitSDK.FeedFilter?
|
|
203
213
|
public var preload: ShortKitSDK.FeedPreload?
|
|
204
|
-
public init(feedHeight: ShortKitSDK.FeedHeight = .fullscreen, videoOverlay: ShortKitSDK.VideoOverlayMode = .none, carouselOverlay: ShortKitSDK.CarouselOverlayMode = .none, surveyOverlay: ShortKitSDK.SurveyOverlayMode = .none, adOverlay: ShortKitSDK.AdOverlayMode = .none, muteOnStart: Swift.Bool = true, autoplay: Swift.Bool = true, feedSource: ShortKitSDK.FeedSource = .algorithmic, coldStartEnabled: Swift.Bool = false, filter: ShortKitSDK.FeedFilter? = nil, preload: ShortKitSDK.FeedPreload? = nil)
|
|
214
|
+
public init(feedHeight: ShortKitSDK.FeedHeight = .fullscreen, scrollAxis: ShortKitSDK.ScrollAxis = .vertical, videoOverlay: ShortKitSDK.VideoOverlayMode = .none, carouselOverlay: ShortKitSDK.CarouselOverlayMode = .none, surveyOverlay: ShortKitSDK.SurveyOverlayMode = .none, adOverlay: ShortKitSDK.AdOverlayMode = .none, muteOnStart: Swift.Bool = true, autoplay: Swift.Bool = true, feedSource: ShortKitSDK.FeedSource = .algorithmic, coldStartEnabled: Swift.Bool = false, filter: ShortKitSDK.FeedFilter? = nil, preload: ShortKitSDK.FeedPreload? = nil)
|
|
205
215
|
public func encode(to encoder: any Swift.Encoder) throws
|
|
206
216
|
public init(from decoder: any Swift.Decoder) throws
|
|
207
217
|
}
|
|
@@ -266,7 +276,7 @@ extension ShortKitSDK.ShortKitDelegate {
|
|
|
266
276
|
@objc deinit
|
|
267
277
|
}
|
|
268
278
|
@_Concurrency.MainActor @preconcurrency public struct ShortKitFeedView : SwiftUI.UIViewControllerRepresentable {
|
|
269
|
-
@_Concurrency.MainActor @preconcurrency public init(shortKit: ShortKitSDK.ShortKit, config: ShortKitSDK.FeedConfig)
|
|
279
|
+
@_Concurrency.MainActor @preconcurrency public init(shortKit: ShortKitSDK.ShortKit, config: ShortKitSDK.FeedConfig = FeedConfig(), onFeedReady: (() -> Swift.Void)? = nil)
|
|
270
280
|
@_Concurrency.MainActor @preconcurrency public func makeCoordinator() -> ShortKitSDK.ShortKitFeedView.Coordinator
|
|
271
281
|
@_Concurrency.MainActor @preconcurrency public func makeUIViewController(context: ShortKitSDK.ShortKitFeedView.Context) -> ShortKitSDK.ShortKitFeedViewController
|
|
272
282
|
@_Concurrency.MainActor @preconcurrency public func updateUIViewController(_ uiViewController: ShortKitSDK.ShortKitFeedViewController, context: ShortKitSDK.ShortKitFeedView.Context)
|
|
@@ -280,6 +290,7 @@ extension ShortKitSDK.ShortKitDelegate {
|
|
|
280
290
|
@objc @_hasMissingDesignatedInitializers @_Concurrency.MainActor @preconcurrency public class ShortKitFeedViewController : UIKit.UIViewController {
|
|
281
291
|
@_Concurrency.MainActor @preconcurrency public var onDismiss: (() -> Swift.Void)?
|
|
282
292
|
@_Concurrency.MainActor @preconcurrency public var onRemainingContentCountChange: ((Swift.Int) -> Swift.Void)?
|
|
293
|
+
@_Concurrency.MainActor @preconcurrency public var onFeedReady: (() -> Swift.Void)?
|
|
283
294
|
@_Concurrency.MainActor @preconcurrency public init(shortKit: ShortKitSDK.ShortKit, config: ShortKitSDK.FeedConfig, startAtItemId: Swift.String? = nil)
|
|
284
295
|
@_Concurrency.MainActor public func setFeedItems(_ items: [ShortKitSDK.FeedInput])
|
|
285
296
|
@_Concurrency.MainActor public func appendFeedItems(_ items: [ShortKitSDK.FeedInput])
|
|
@@ -289,6 +300,9 @@ extension ShortKitSDK.ShortKitDelegate {
|
|
|
289
300
|
@_Concurrency.MainActor @preconcurrency @objc override dynamic public func viewWillAppear(_ animated: Swift.Bool)
|
|
290
301
|
@_Concurrency.MainActor @preconcurrency @objc override dynamic public func viewDidAppear(_ animated: Swift.Bool)
|
|
291
302
|
@_Concurrency.MainActor @preconcurrency @objc override dynamic public func viewWillDisappear(_ animated: Swift.Bool)
|
|
303
|
+
@_Concurrency.MainActor @preconcurrency public func setBridgeManaged()
|
|
304
|
+
@_Concurrency.MainActor @preconcurrency public func activate()
|
|
305
|
+
@_Concurrency.MainActor @preconcurrency public func deactivate()
|
|
292
306
|
@_Concurrency.MainActor @preconcurrency @objc override dynamic public func viewDidDisappear(_ animated: Swift.Bool)
|
|
293
307
|
@_Concurrency.MainActor @preconcurrency @objc override dynamic public var supportedInterfaceOrientations: UIKit.UIInterfaceOrientationMask {
|
|
294
308
|
@objc get
|
|
@@ -689,9 +703,6 @@ public enum ContentSignal : Swift.Equatable, Swift.Sendable {
|
|
|
689
703
|
final public var remainingContentCount: Combine.AnyPublisher<Swift.Int, Swift.Never> {
|
|
690
704
|
get
|
|
691
705
|
}
|
|
692
|
-
final public var feedReady: Combine.AnyPublisher<Swift.Void, Swift.Never> {
|
|
693
|
-
get
|
|
694
|
-
}
|
|
695
706
|
final public var currentItemValue: ShortKitSDK.ContentItem? {
|
|
696
707
|
get
|
|
697
708
|
}
|
|
@@ -754,6 +765,7 @@ final public class ShortKit {
|
|
|
754
765
|
final public var loadingViewProvider: (() -> UIKit.UIView)?
|
|
755
766
|
public init(apiKey: Swift.String, userId: Swift.String? = nil, adProvider: (any ShortKitSDK.ShortKitAdProvider)? = nil, clientAppName: Swift.String? = nil, clientAppVersion: Swift.String? = nil, customDimensions: [Swift.String : Swift.String]? = nil, loadingViewProvider: (() -> UIKit.UIView)? = nil)
|
|
756
767
|
final public func preloadFeed(filter: ShortKitSDK.FeedFilter? = nil, limit: Swift.Int = 10) -> ShortKitSDK.FeedPreload
|
|
768
|
+
final public func preloadFeed(items: [ShortKitSDK.FeedInput]) -> ShortKitSDK.FeedPreload
|
|
757
769
|
final public func fetchContent(limit: Swift.Int = 10, filter: ShortKitSDK.FeedFilter? = nil) async throws -> [ShortKitSDK.ContentItem]
|
|
758
770
|
final public func setUserId(_ id: Swift.String)
|
|
759
771
|
final public func clearUserId()
|
|
@@ -835,6 +847,8 @@ public struct WidgetConfig {
|
|
|
835
847
|
}
|
|
836
848
|
extension ShortKitSDK.AdQuartile : Swift.Equatable {}
|
|
837
849
|
extension ShortKitSDK.AdQuartile : Swift.Hashable {}
|
|
850
|
+
extension ShortKitSDK.ScrollAxis : Swift.Hashable {}
|
|
851
|
+
extension ShortKitSDK.ScrollAxis : Swift.RawRepresentable {}
|
|
838
852
|
extension ShortKitSDK.FeedSource : Swift.Hashable {}
|
|
839
853
|
extension ShortKitSDK.FeedSource : Swift.RawRepresentable {}
|
|
840
854
|
extension ShortKitSDK.ShortKitFeedView : Swift.Sendable {}
|
|
Binary file
|
package/package.json
CHANGED
package/src/ShortKitContext.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
ContentItem,
|
|
4
4
|
FeedConfig,
|
|
5
5
|
FeedFilter,
|
|
6
|
+
FeedInput,
|
|
6
7
|
PlayerTime,
|
|
7
8
|
PlayerState,
|
|
8
9
|
CaptionTrack,
|
|
@@ -45,7 +46,7 @@ export interface ShortKitContextValue {
|
|
|
45
46
|
fetchContent: (limit?: number, filter?: FeedFilter) => Promise<ContentItem[]>;
|
|
46
47
|
|
|
47
48
|
// Preload
|
|
48
|
-
preloadFeed: (config?: Partial<FeedConfig
|
|
49
|
+
preloadFeed: (config?: Partial<FeedConfig>, items?: FeedInput[]) => Promise<string>;
|
|
49
50
|
|
|
50
51
|
// Storyboard / seek thumbnails
|
|
51
52
|
prefetchStoryboard: (playbackId: string) => void;
|
package/src/ShortKitFeed.tsx
CHANGED
|
@@ -41,6 +41,7 @@ export const ShortKitFeed = forwardRef<ShortKitFeedHandle, ShortKitFeedProps>(
|
|
|
41
41
|
onRefreshRequested,
|
|
42
42
|
onDidFetchContentItems,
|
|
43
43
|
onRemainingContentCountChange,
|
|
44
|
+
onFeedReady,
|
|
44
45
|
} = props;
|
|
45
46
|
|
|
46
47
|
const context = useContext(ShortKitContext);
|
|
@@ -79,6 +80,19 @@ export const ShortKitFeed = forwardRef<ShortKitFeedHandle, ShortKitFeedProps>(
|
|
|
79
80
|
return () => subscription.remove();
|
|
80
81
|
}, [feedId, onRemainingContentCountChange]);
|
|
81
82
|
|
|
83
|
+
// Subscribe to per-feed ready event
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (!NativeShortKitModule || !onFeedReady) return;
|
|
86
|
+
|
|
87
|
+
const subscription = NativeShortKitModule.onFeedReady((event) => {
|
|
88
|
+
if (event.feedId === feedId) {
|
|
89
|
+
onFeedReady();
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return () => subscription.remove();
|
|
94
|
+
}, [feedId, onFeedReady]);
|
|
95
|
+
|
|
82
96
|
// Register overlay components before native view mounts.
|
|
83
97
|
// useLayoutEffect fires after commit but before paint — before
|
|
84
98
|
// didMoveToWindow/onAttachedToWindow on the native view.
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import React, { useEffect,
|
|
2
|
-
import { AppRegistry,
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { AppRegistry, View, Text } from 'react-native';
|
|
3
3
|
import type { OverlayProps, PlayerState, PlayerTime, FeedScrollPhase } from './types';
|
|
4
4
|
import { deserializeContentItem } from './serialization';
|
|
5
5
|
import NativeShortKitModule from './specs/NativeShortKitModule';
|
|
6
6
|
|
|
7
|
+
const SK_OVERLAY_TAG = '[ShortKit:OverlaySurface]';
|
|
8
|
+
|
|
7
9
|
// Named registry — supports different overlay components per feed
|
|
8
10
|
const _overlayRegistry = new Map<string, React.ComponentType<OverlayProps>>();
|
|
9
11
|
|
|
@@ -16,7 +18,9 @@ export function registerOverlayComponent(
|
|
|
16
18
|
name: string,
|
|
17
19
|
component: React.ComponentType<OverlayProps>,
|
|
18
20
|
) {
|
|
19
|
-
if (_overlayRegistry.has(name))
|
|
21
|
+
if (_overlayRegistry.has(name)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
20
24
|
_overlayRegistry.set(name, component);
|
|
21
25
|
|
|
22
26
|
const moduleName = `ShortKitOverlay_${name}`;
|
|
@@ -27,6 +31,47 @@ export function registerOverlayComponent(
|
|
|
27
31
|
});
|
|
28
32
|
}
|
|
29
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Error boundary that catches crashes inside the overlay component.
|
|
36
|
+
* Without this, a crash in an isolated React surface is silent on Android.
|
|
37
|
+
*/
|
|
38
|
+
class OverlayErrorBoundary extends React.Component<
|
|
39
|
+
{ surfaceId?: string; overlayName: string; children: React.ReactNode },
|
|
40
|
+
{ error: Error | null }
|
|
41
|
+
> {
|
|
42
|
+
state: { error: Error | null } = { error: null };
|
|
43
|
+
|
|
44
|
+
static getDerivedStateFromError(error: Error) {
|
|
45
|
+
return { error };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
componentDidCatch(error: Error, info: React.ErrorInfo) {
|
|
49
|
+
console.error(
|
|
50
|
+
`${SK_OVERLAY_TAG} CRASH in overlay '${this.props.overlayName}' (surfaceId=${this.props.surfaceId}):`,
|
|
51
|
+
error.message,
|
|
52
|
+
'\nComponent stack:',
|
|
53
|
+
info.componentStack,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
render() {
|
|
58
|
+
if (this.state.error) {
|
|
59
|
+
// Render a visible red indicator in __DEV__ so it's obvious
|
|
60
|
+
if (__DEV__) {
|
|
61
|
+
return (
|
|
62
|
+
<View style={{ flex: 1, backgroundColor: 'rgba(255,0,0,0.3)', justifyContent: 'center', alignItems: 'center', padding: 20 }}>
|
|
63
|
+
<Text style={{ color: 'white', fontSize: 14, textAlign: 'center' }}>
|
|
64
|
+
{`Overlay '${this.props.overlayName}' crashed:\n${this.state.error.message}`}
|
|
65
|
+
</Text>
|
|
66
|
+
</View>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
return this.props.children;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
30
75
|
/** Raw props received from native appProperties (set once per item in configure()). */
|
|
31
76
|
interface RawOverlaySurfaceProps {
|
|
32
77
|
surfaceId?: string;
|
|
@@ -47,14 +92,9 @@ interface InnerProps extends RawOverlaySurfaceProps {
|
|
|
47
92
|
/**
|
|
48
93
|
* Subscribe to a native overlay event, filtered by surfaceId.
|
|
49
94
|
*
|
|
50
|
-
* iOS and Android new arch emit events through
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* - Android: getJSModule(RCTDeviceEventEmitter).emit() — only
|
|
54
|
-
* DeviceEventEmitter.addListener() receives these events (codegen
|
|
55
|
-
* EventEmitter subscriptions do NOT receive them on Android new arch).
|
|
56
|
-
*
|
|
57
|
-
* We branch per platform to use the path that actually delivers events.
|
|
95
|
+
* Both iOS and Android (new arch) emit events through the codegen
|
|
96
|
+
* EventEmitter path (mEventEmitterCallback / JSI direct channel).
|
|
97
|
+
* We subscribe via the codegen emitter method on the TurboModule.
|
|
58
98
|
*/
|
|
59
99
|
function useOverlayEvent<T extends { surfaceId: string }>(
|
|
60
100
|
eventName: string,
|
|
@@ -66,19 +106,11 @@ function useOverlayEvent<T extends { surfaceId: string }>(
|
|
|
66
106
|
|
|
67
107
|
let sub: { remove: () => void } | undefined;
|
|
68
108
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
sub = (emitter as (cb: (e: T) => void) => { remove: () => void })((e: T) => {
|
|
75
|
-
if (e.surfaceId !== surfaceId) return;
|
|
76
|
-
handler(e);
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
// Android new arch: events come through RCTDeviceEventEmitter.emit().
|
|
81
|
-
sub = DeviceEventEmitter.addListener(eventName, (e: T) => {
|
|
109
|
+
// Both platforms: events come through the codegen EventEmitterCallback.
|
|
110
|
+
// Access the codegen emitter method by name on the TurboModule.
|
|
111
|
+
const emitter = NativeShortKitModule?.[eventName as keyof typeof NativeShortKitModule];
|
|
112
|
+
if (typeof emitter === 'function') {
|
|
113
|
+
sub = (emitter as (cb: (e: T) => void) => { remove: () => void })((e: T) => {
|
|
82
114
|
if (e.surfaceId !== surfaceId) return;
|
|
83
115
|
handler(e);
|
|
84
116
|
});
|
|
@@ -90,13 +122,24 @@ function useOverlayEvent<T extends { surfaceId: string }>(
|
|
|
90
122
|
|
|
91
123
|
function ShortKitOverlaySurfaceInner(props: InnerProps) {
|
|
92
124
|
const Component = _overlayRegistry.get(props.overlayName);
|
|
93
|
-
if (!Component)
|
|
125
|
+
if (!Component) {
|
|
126
|
+
console.error(`${SK_OVERLAY_TAG} ShortKitOverlaySurfaceInner: Component NOT FOUND in registry for '${props.overlayName}'. Registered names: [${Array.from(_overlayRegistry.keys()).join(', ')}]`);
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
94
129
|
|
|
95
|
-
const item =
|
|
96
|
-
|
|
97
|
-
[props.item],
|
|
130
|
+
const [item, setItem] = useState(() =>
|
|
131
|
+
props.item ? deserializeContentItem(props.item) : null,
|
|
98
132
|
);
|
|
99
133
|
|
|
134
|
+
// Sync item from props when surface is first mounted or remounted via updateInitProps
|
|
135
|
+
const prevPropsItemRef = React.useRef(props.item);
|
|
136
|
+
if (props.item !== prevPropsItemRef.current) {
|
|
137
|
+
prevPropsItemRef.current = props.item;
|
|
138
|
+
// Synchronous state update during render — React restarts with new state
|
|
139
|
+
// before committing, so stale frame is never painted.
|
|
140
|
+
setItem(props.item ? deserializeContentItem(props.item) : null);
|
|
141
|
+
}
|
|
142
|
+
|
|
100
143
|
const sid = props.surfaceId;
|
|
101
144
|
|
|
102
145
|
// Initialize state from surface properties (set once in configure()).
|
|
@@ -141,6 +184,24 @@ function ShortKitOverlaySurfaceInner(props: InnerProps) {
|
|
|
141
184
|
|
|
142
185
|
// --- Event subscriptions (filtered by surfaceId) ---
|
|
143
186
|
|
|
187
|
+
// Item changed via event (not updateInitProps) — triggers React DIFF
|
|
188
|
+
// instead of full remount. Uses DeviceEventEmitter because this event
|
|
189
|
+
// is not in the TurboModule spec (avoids native codegen changes).
|
|
190
|
+
useEffect(() => {
|
|
191
|
+
if (!sid) return;
|
|
192
|
+
const { DeviceEventEmitter } = require('react-native');
|
|
193
|
+
const sub = DeviceEventEmitter.addListener('onOverlayItemChanged', (e: { surfaceId: string; item: string }) => {
|
|
194
|
+
if (e.surfaceId !== sid) return;
|
|
195
|
+
const newItem = e.item ? deserializeContentItem(e.item) : null;
|
|
196
|
+
if (newItem) setItem(newItem);
|
|
197
|
+
// Reset playback state for the new item
|
|
198
|
+
setIsActive(false);
|
|
199
|
+
setPlayerState('idle' as PlayerState);
|
|
200
|
+
setTime({ current: 0, duration: 0, buffered: 0 });
|
|
201
|
+
});
|
|
202
|
+
return () => sub.remove();
|
|
203
|
+
}, [sid]);
|
|
204
|
+
|
|
144
205
|
useOverlayEvent<{ surfaceId: string; isActive: boolean }>(
|
|
145
206
|
'onOverlayActiveChanged', sid,
|
|
146
207
|
(e) => setIsActive(e.isActive),
|
|
@@ -175,31 +236,78 @@ function ShortKitOverlaySurfaceInner(props: InnerProps) {
|
|
|
175
236
|
'onOverlayFeedScrollPhaseChanged', sid,
|
|
176
237
|
(e) => {
|
|
177
238
|
try {
|
|
178
|
-
|
|
239
|
+
const next = e.feedScrollPhase ? JSON.parse(e.feedScrollPhase) : null;
|
|
240
|
+
// Stabilize object reference: only update state if the phase actually
|
|
241
|
+
// changed. Prevents unnecessary re-renders of memo'd overlay components
|
|
242
|
+
// that receive feedScrollPhase as a prop (new JSON.parse object !== old).
|
|
243
|
+
setFeedScrollPhase(prev => {
|
|
244
|
+
if (prev?.phase === next?.phase && prev?.fromId === next?.fromId) {
|
|
245
|
+
return prev;
|
|
246
|
+
}
|
|
247
|
+
return next;
|
|
248
|
+
});
|
|
179
249
|
} catch {
|
|
180
250
|
setFeedScrollPhase(null);
|
|
181
251
|
}
|
|
182
252
|
},
|
|
183
253
|
);
|
|
184
254
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
)
|
|
255
|
+
// EXPERIMENT: time updates disabled to measure impact on swipe perf
|
|
256
|
+
// useOverlayEvent<{ surfaceId: string; current: number; duration: number; buffered: number }>(
|
|
257
|
+
// 'onOverlayTimeUpdate', sid,
|
|
258
|
+
// (e) => setTime({ current: e.current, duration: e.duration, buffered: e.buffered }),
|
|
259
|
+
// );
|
|
260
|
+
|
|
261
|
+
// Batched full-state sync — replaces 7 individual events on swipe settle.
|
|
262
|
+
// All setState calls within one handler = one React render (auto-batched).
|
|
263
|
+
useOverlayEvent<{
|
|
264
|
+
surfaceId: string;
|
|
265
|
+
isActive: boolean;
|
|
266
|
+
playerState: string;
|
|
267
|
+
isMuted: boolean;
|
|
268
|
+
playbackRate: number;
|
|
269
|
+
captionsEnabled: boolean;
|
|
270
|
+
activeCue: string | null;
|
|
271
|
+
feedScrollPhase: string | null;
|
|
272
|
+
}>('onOverlayFullState', sid, (e) => {
|
|
273
|
+
setIsActive(e.isActive);
|
|
274
|
+
setPlayerState(e.playerState as PlayerState);
|
|
275
|
+
setIsMuted(e.isMuted);
|
|
276
|
+
setPlaybackRate(e.playbackRate);
|
|
277
|
+
setCaptionsEnabled(e.captionsEnabled);
|
|
278
|
+
try {
|
|
279
|
+
setActiveCue(e.activeCue ? JSON.parse(e.activeCue) : null);
|
|
280
|
+
} catch {
|
|
281
|
+
setActiveCue(null);
|
|
282
|
+
}
|
|
283
|
+
try {
|
|
284
|
+
const next = e.feedScrollPhase ? JSON.parse(e.feedScrollPhase) : null;
|
|
285
|
+
setFeedScrollPhase(prev => {
|
|
286
|
+
if (prev?.phase === next?.phase && prev?.fromId === next?.fromId) return prev;
|
|
287
|
+
return next;
|
|
288
|
+
});
|
|
289
|
+
} catch {
|
|
290
|
+
setFeedScrollPhase(null);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
189
293
|
|
|
190
|
-
if (!item)
|
|
294
|
+
if (!item) {
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
191
297
|
|
|
192
298
|
return (
|
|
193
|
-
<
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
299
|
+
<OverlayErrorBoundary surfaceId={sid} overlayName={props.overlayName}>
|
|
300
|
+
<Component
|
|
301
|
+
item={item}
|
|
302
|
+
isActive={isActive}
|
|
303
|
+
playerState={playerState}
|
|
304
|
+
time={time}
|
|
305
|
+
isMuted={isMuted}
|
|
306
|
+
playbackRate={playbackRate}
|
|
307
|
+
captionsEnabled={captionsEnabled}
|
|
308
|
+
activeCue={activeCue}
|
|
309
|
+
feedScrollPhase={feedScrollPhase}
|
|
310
|
+
/>
|
|
311
|
+
</OverlayErrorBoundary>
|
|
204
312
|
);
|
|
205
313
|
}
|
package/src/ShortKitPlayer.tsx
CHANGED
|
@@ -17,11 +17,13 @@ import ShortKitPlayerView from './specs/ShortKitPlayerViewNativeComponent';
|
|
|
17
17
|
export function ShortKitPlayer(props: ShortKitPlayerProps) {
|
|
18
18
|
const { config, contentItem, active, style } = props;
|
|
19
19
|
|
|
20
|
+
const clickAction = config?.clickAction ?? 'feed';
|
|
21
|
+
|
|
20
22
|
const serializedConfig = useMemo(() => {
|
|
21
23
|
const cfg = config ?? {};
|
|
22
24
|
return JSON.stringify({
|
|
23
25
|
cornerRadius: cfg.cornerRadius ?? 12,
|
|
24
|
-
clickAction:
|
|
26
|
+
clickAction: clickAction,
|
|
25
27
|
autoplay: cfg.autoplay ?? true,
|
|
26
28
|
loop: cfg.loop ?? true,
|
|
27
29
|
muteOnStart: cfg.muteOnStart ?? true,
|
|
@@ -31,20 +33,40 @@ export function ShortKitPlayer(props: ShortKitPlayerProps) {
|
|
|
31
33
|
: { type: 'custom' }
|
|
32
34
|
: 'none',
|
|
33
35
|
});
|
|
34
|
-
}, [config]);
|
|
36
|
+
}, [config, clickAction]);
|
|
35
37
|
|
|
36
38
|
const serializedItem = useMemo(() => {
|
|
37
39
|
if (!contentItem) return undefined;
|
|
38
40
|
return JSON.stringify(contentItem);
|
|
39
41
|
}, [contentItem]);
|
|
40
42
|
|
|
43
|
+
// When clickAction is "none", the native view should not participate in
|
|
44
|
+
// Fabric's JS-side hit testing. Without this, Fabric on Android sees the
|
|
45
|
+
// native component as the touch target and never routes the touch to a
|
|
46
|
+
// parent Pressable — even though the native view returns false from
|
|
47
|
+
// dispatchTouchEvent. iOS doesn't need this because UIKit's responder
|
|
48
|
+
// chain bubbles unhandled touches automatically.
|
|
49
|
+
//
|
|
50
|
+
// "box-none" on the container means the container View itself is
|
|
51
|
+
// transparent to touches (passes through to parent), but children can
|
|
52
|
+
// still receive touches if needed. "none" on the native view means it
|
|
53
|
+
// is fully invisible to hit testing.
|
|
54
|
+
const nativeTouchPassthrough = clickAction === 'none';
|
|
55
|
+
|
|
41
56
|
return (
|
|
42
|
-
<View
|
|
57
|
+
<View
|
|
58
|
+
style={[styles.container, style]}
|
|
59
|
+
pointerEvents={nativeTouchPassthrough ? 'box-none' : 'auto'}
|
|
60
|
+
onStartShouldSetResponder={() => {
|
|
61
|
+
return false;
|
|
62
|
+
}}
|
|
63
|
+
>
|
|
43
64
|
<ShortKitPlayerView
|
|
44
65
|
style={styles.player}
|
|
45
66
|
config={serializedConfig}
|
|
46
67
|
contentItem={serializedItem}
|
|
47
68
|
active={active}
|
|
69
|
+
pointerEvents={nativeTouchPassthrough ? 'none' : 'auto'}
|
|
48
70
|
/>
|
|
49
71
|
</View>
|
|
50
72
|
);
|
package/src/ShortKitProvider.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
ContentItem,
|
|
9
9
|
FeedConfig,
|
|
10
10
|
FeedFilter,
|
|
11
|
+
FeedInput,
|
|
11
12
|
PlayerTime,
|
|
12
13
|
PlayerState,
|
|
13
14
|
CaptionTrack,
|
|
@@ -420,10 +421,11 @@ export function ShortKitProvider({
|
|
|
420
421
|
}
|
|
421
422
|
}, []);
|
|
422
423
|
|
|
423
|
-
const preloadFeedCmd = useCallback(async (config?: Partial<FeedConfig
|
|
424
|
+
const preloadFeedCmd = useCallback(async (config?: Partial<FeedConfig>, items?: FeedInput[]): Promise<string> => {
|
|
424
425
|
if (!NativeShortKitModule) return '';
|
|
425
426
|
const configJSON = config ? serializeFeedConfig(config as FeedConfig) : '{}';
|
|
426
|
-
|
|
427
|
+
const itemsJSON = items ? JSON.stringify(items) : null;
|
|
428
|
+
return NativeShortKitModule.preloadFeed(configJSON, itemsJSON);
|
|
427
429
|
}, []);
|
|
428
430
|
|
|
429
431
|
// -----------------------------------------------------------------------
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { useShortKit } from './useShortKit';
|
|
|
7
7
|
export type {
|
|
8
8
|
FeedConfig,
|
|
9
9
|
FeedHeight,
|
|
10
|
+
ScrollAxis,
|
|
10
11
|
FeedSource,
|
|
11
12
|
OverlayConfig,
|
|
12
13
|
CarouselOverlayConfig,
|
|
@@ -42,4 +43,7 @@ export type {
|
|
|
42
43
|
StoryboardTile,
|
|
43
44
|
} from './types';
|
|
44
45
|
export { ShortKitCommands } from './ShortKitCommands';
|
|
46
|
+
export { default as NativeShortKitModule } from './specs/NativeShortKitModule';
|
|
47
|
+
export { registerOverlayComponent } from './ShortKitOverlaySurface';
|
|
48
|
+
export { registerCarouselOverlayComponent } from './ShortKitCarouselOverlaySurface';
|
|
45
49
|
export type { OverlayProps, CarouselOverlayProps } from './types';
|
package/src/serialization.ts
CHANGED
|
@@ -27,6 +27,7 @@ export function serializeFeedConfig(config: FeedConfig): string {
|
|
|
27
27
|
|
|
28
28
|
return JSON.stringify({
|
|
29
29
|
feedHeight: JSON.stringify(config.feedHeight ?? { type: 'fullscreen' }),
|
|
30
|
+
scrollAxis: config.scrollAxis ?? 'vertical',
|
|
30
31
|
overlay,
|
|
31
32
|
carouselOverlay,
|
|
32
33
|
surveyMode: JSON.stringify(config.surveyMode ?? 'none'),
|
|
@@ -108,6 +108,10 @@ type ContentTappedEvent = Readonly<{
|
|
|
108
108
|
index: Int32;
|
|
109
109
|
}>;
|
|
110
110
|
|
|
111
|
+
type FeedReadyEvent = Readonly<{
|
|
112
|
+
feedId: string;
|
|
113
|
+
}>;
|
|
114
|
+
|
|
111
115
|
// --- Overlay per-surface event payload types ---
|
|
112
116
|
|
|
113
117
|
type OverlayActiveEvent = Readonly<{
|
|
@@ -152,6 +156,17 @@ type OverlayTimeUpdateEvent = Readonly<{
|
|
|
152
156
|
buffered: Double;
|
|
153
157
|
}>;
|
|
154
158
|
|
|
159
|
+
type OverlayFullStateEvent = Readonly<{
|
|
160
|
+
surfaceId: string;
|
|
161
|
+
isActive: boolean;
|
|
162
|
+
playerState: string;
|
|
163
|
+
isMuted: boolean;
|
|
164
|
+
playbackRate: Double;
|
|
165
|
+
captionsEnabled: boolean;
|
|
166
|
+
activeCue: string;
|
|
167
|
+
feedScrollPhase: string;
|
|
168
|
+
}>;
|
|
169
|
+
|
|
155
170
|
export interface Spec extends TurboModule {
|
|
156
171
|
// --- Lifecycle ---
|
|
157
172
|
initialize(
|
|
@@ -186,7 +201,7 @@ export interface Spec extends TurboModule {
|
|
|
186
201
|
appendFeedItems(feedId: string, items: string): void;
|
|
187
202
|
fetchContent(limit: Int32, filterJSON: string | null): Promise<string>;
|
|
188
203
|
applyFilter(feedId: string, filterJSON: string | null): void;
|
|
189
|
-
preloadFeed(configJSON: string): Promise<string>;
|
|
204
|
+
preloadFeed(configJSON: string, itemsJSON: string | null): Promise<string>;
|
|
190
205
|
|
|
191
206
|
// --- Storyboard / seek thumbnails ---
|
|
192
207
|
prefetchStoryboard(playbackId: string): void;
|
|
@@ -212,6 +227,7 @@ export interface Spec extends TurboModule {
|
|
|
212
227
|
readonly onDismiss: EventEmitter<DismissEvent>;
|
|
213
228
|
readonly onRefreshRequested: EventEmitter<RefreshRequestedEvent>;
|
|
214
229
|
readonly onDidFetchContentItems: EventEmitter<DidFetchContentItemsEvent>;
|
|
230
|
+
readonly onFeedReady: EventEmitter<FeedReadyEvent>;
|
|
215
231
|
|
|
216
232
|
// --- Overlay per-surface events ---
|
|
217
233
|
readonly onOverlayActiveChanged: EventEmitter<OverlayActiveEvent>;
|
|
@@ -222,6 +238,7 @@ export interface Spec extends TurboModule {
|
|
|
222
238
|
readonly onOverlayActiveCueChanged: EventEmitter<OverlayActiveCueEvent>;
|
|
223
239
|
readonly onOverlayFeedScrollPhaseChanged: EventEmitter<OverlayFeedScrollPhaseEvent>;
|
|
224
240
|
readonly onOverlayTimeUpdate: EventEmitter<OverlayTimeUpdateEvent>;
|
|
241
|
+
readonly onOverlayFullState: EventEmitter<OverlayFullStateEvent>;
|
|
225
242
|
}
|
|
226
243
|
|
|
227
244
|
export default TurboModuleRegistry.getEnforcing<Spec>('ShortKitModule');
|