@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.
Files changed (75) hide show
  1. package/ShortKitReactNative.podspec +1 -0
  2. package/android/build.gradle.kts +5 -1
  3. package/android/src/main/java/com/shortkit/reactnative/ReactCarouselOverlayHost.kt +319 -0
  4. package/android/src/main/java/com/shortkit/reactnative/ReactLoadingHost.kt +40 -0
  5. package/android/src/main/java/com/shortkit/reactnative/ReactOverlayHost.kt +559 -0
  6. package/android/src/main/java/com/shortkit/reactnative/ShortKitBridge.kt +984 -0
  7. package/android/src/main/java/com/shortkit/reactnative/ShortKitFeedView.kt +88 -220
  8. package/android/src/main/java/com/shortkit/reactnative/ShortKitFeedViewManager.kt +12 -3
  9. package/android/src/main/java/com/shortkit/reactnative/ShortKitModule.kt +123 -741
  10. package/android/src/main/java/com/shortkit/reactnative/ShortKitPlayerNativeView.kt +2 -2
  11. package/android/src/main/java/com/shortkit/reactnative/ShortKitWidgetNativeView.kt +2 -2
  12. package/ios/ReactCarouselOverlayHost.swift +177 -0
  13. package/ios/ReactLoadingHost.swift +38 -0
  14. package/ios/ReactOverlayHost.swift +458 -0
  15. package/ios/SKFabricSurfaceWrapper.h +18 -0
  16. package/ios/SKFabricSurfaceWrapper.mm +57 -0
  17. package/ios/ShortKitBridge.swift +186 -63
  18. package/ios/ShortKitFeedView.swift +62 -229
  19. package/ios/ShortKitFeedViewManager.mm +3 -2
  20. package/ios/ShortKitModule.mm +66 -37
  21. package/ios/ShortKitPlayerNativeView.swift +39 -8
  22. package/ios/ShortKitReactNative-Bridging-Header.h +2 -0
  23. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +1 -1
  24. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.abi.json +2380 -522
  25. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +39 -12
  26. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  27. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftinterface +39 -12
  28. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/ShortKitSDK +0 -0
  29. package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +1 -1
  30. package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +2380 -522
  31. package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +39 -12
  32. package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  33. package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +39 -12
  34. package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/ShortKitSDK +0 -0
  35. package/ios/ShortKitSDK.xcframework.bak/Info.plist +43 -0
  36. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +418 -0
  37. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Info.plist +16 -0
  38. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.abi.json +28917 -0
  39. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +824 -0
  40. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  41. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftinterface +824 -0
  42. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/module.modulemap +4 -0
  43. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/ShortKitSDK +0 -0
  44. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +418 -0
  45. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Info.plist +16 -0
  46. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +28917 -0
  47. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +824 -0
  48. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  49. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +824 -0
  50. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/module.modulemap +4 -0
  51. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/ShortKitSDK +0 -0
  52. package/ios/ShortKitWidgetNativeView.swift +3 -3
  53. package/package.json +1 -1
  54. package/src/ShortKitCarouselOverlaySurface.tsx +55 -0
  55. package/src/ShortKitCommands.ts +31 -0
  56. package/src/ShortKitContext.ts +6 -25
  57. package/src/ShortKitFeed.tsx +110 -41
  58. package/src/ShortKitLoadingSurface.tsx +24 -0
  59. package/src/ShortKitOverlaySurface.tsx +205 -0
  60. package/src/ShortKitPlayer.tsx +6 -7
  61. package/src/ShortKitProvider.tsx +27 -286
  62. package/src/index.ts +5 -3
  63. package/src/serialization.ts +19 -39
  64. package/src/specs/NativeShortKitModule.ts +58 -46
  65. package/src/specs/ShortKitFeedViewNativeComponent.ts +3 -2
  66. package/src/types.ts +78 -16
  67. package/src/useShortKit.ts +1 -3
  68. package/src/useShortKitPlayer.ts +7 -7
  69. package/android/src/main/java/com/shortkit/reactnative/ShortKitCarouselOverlayBridge.kt +0 -48
  70. package/android/src/main/java/com/shortkit/reactnative/ShortKitOverlayBridge.kt +0 -128
  71. package/ios/ShortKitCarouselOverlayBridge.swift +0 -219
  72. package/ios/ShortKitOverlayBridge.swift +0 -111
  73. package/src/CarouselOverlayManager.tsx +0 -70
  74. package/src/OverlayManager.tsx +0 -87
  75. package/src/useShortKitCarousel.ts +0 -29
@@ -22,6 +22,7 @@ type CurrentItemEvent = Readonly<{
22
22
  author?: string;
23
23
  articleUrl?: string;
24
24
  commentCount?: Int32;
25
+ fallbackUrl?: string;
25
26
  }>;
26
27
 
27
28
  type TimeUpdateEvent = Readonly<{
@@ -84,16 +85,16 @@ type PrefetchedAheadCountEvent = Readonly<{
84
85
  }>;
85
86
 
86
87
  type RemainingContentCountEvent = Readonly<{
88
+ feedId: string;
87
89
  count: Int32;
88
90
  }>;
89
91
 
90
- type ErrorEvent = Readonly<{
91
- code: string;
92
- message: string;
93
- }>;
92
+ type DismissEvent = Readonly<{}>;
93
+
94
+ type RefreshRequestedEvent = Readonly<{}>;
94
95
 
95
- type ShareTappedEvent = Readonly<{
96
- item: string; // JSON-serialized ContentItem
96
+ type DidFetchContentItemsEvent = Readonly<{
97
+ items: string; // JSON-serialized ContentItem[]
97
98
  }>;
98
99
 
99
100
  type SurveyResponseEvent = Readonly<{
@@ -102,50 +103,60 @@ type SurveyResponseEvent = Readonly<{
102
103
  optionText: string;
103
104
  }>;
104
105
 
105
- type OverlayConfigureEvent = Readonly<{
106
- item: string; // JSON-serialized ContentItem
106
+ type ContentTappedEvent = Readonly<{
107
+ contentId: string;
108
+ index: Int32;
107
109
  }>;
108
110
 
109
- type OverlayActivateEvent = Readonly<{
110
- item: string; // JSON-serialized ContentItem
111
- }>;
111
+ // --- Overlay per-surface event payload types ---
112
112
 
113
- type OverlayResetEvent = Readonly<{
114
- item: string; // JSON-serialized ContentItem
113
+ type OverlayActiveEvent = Readonly<{
114
+ surfaceId: string;
115
+ isActive: boolean;
115
116
  }>;
116
117
 
117
- type ContentTappedEvent = Readonly<{
118
- contentId: string;
119
- index: Int32;
118
+ type OverlayPlayerStateEvent = Readonly<{
119
+ surfaceId: string;
120
+ playerState: string;
120
121
  }>;
121
122
 
122
- type CarouselOverlayConfigureEvent = Readonly<{
123
- item: string; // JSON-serialized ImageCarouselItem
123
+ type OverlayMutedEvent = Readonly<{
124
+ surfaceId: string;
125
+ isMuted: boolean;
124
126
  }>;
125
127
 
126
- type CarouselOverlayActivateEvent = Readonly<{
127
- item: string; // JSON-serialized ImageCarouselItem
128
+ type OverlayPlaybackRateEvent = Readonly<{
129
+ surfaceId: string;
130
+ playbackRate: Double;
128
131
  }>;
129
132
 
130
- type CarouselOverlayResetEvent = Readonly<{}>;
133
+ type OverlayCaptionsEnabledEvent = Readonly<{
134
+ surfaceId: string;
135
+ captionsEnabled: boolean;
136
+ }>;
131
137
 
132
- type CarouselPageChangedEvent = Readonly<{
133
- page: Int32;
134
- pageCount: Int32;
138
+ type OverlayActiveCueEvent = Readonly<{
139
+ surfaceId: string;
140
+ activeCue: string;
135
141
  }>;
136
142
 
137
- type OverlayTapEvent = Readonly<{}>;
143
+ type OverlayFeedScrollPhaseEvent = Readonly<{
144
+ surfaceId: string;
145
+ feedScrollPhase: string;
146
+ }>;
138
147
 
139
- type OverlayDoubleTapEvent = Readonly<{
140
- x: Double;
141
- y: Double;
148
+ type OverlayTimeUpdateEvent = Readonly<{
149
+ surfaceId: string;
150
+ current: Double;
151
+ duration: Double;
152
+ buffered: Double;
142
153
  }>;
143
154
 
144
155
  export interface Spec extends TurboModule {
145
156
  // --- Lifecycle ---
146
157
  initialize(
147
158
  apiKey: string,
148
- config: string, // JSON-serialized FeedConfig
159
+ hasLoadingView: boolean,
149
160
  clientAppName?: string,
150
161
  clientAppVersion?: string,
151
162
  customDimensions?: string, // JSON-serialized Record<string, string>
@@ -171,17 +182,16 @@ export interface Spec extends TurboModule {
171
182
  setMaxBitrate(bitrate: Double): void;
172
183
 
173
184
  // --- Custom feed ---
174
- setFeedItems(items: string): void;
175
- appendFeedItems(items: string): void;
176
- fetchContent(limit: Int32): Promise<string>;
185
+ setFeedItems(feedId: string, items: string): void;
186
+ appendFeedItems(feedId: string, items: string): void;
187
+ fetchContent(limit: Int32, filterJSON: string | null): Promise<string>;
188
+ applyFilter(feedId: string, filterJSON: string | null): void;
189
+ preloadFeed(configJSON: string): Promise<string>;
177
190
 
178
191
  // --- Storyboard / seek thumbnails ---
179
192
  prefetchStoryboard(playbackId: string): void;
180
193
  getStoryboardData(playbackId: string): Promise<string>;
181
194
 
182
- // --- Overlay lifecycle ---
183
- notifyOverlayReady(): void;
184
-
185
195
  // --- Event emitters ---
186
196
  readonly onPlayerStateChanged: EventEmitter<PlayerStateEvent>;
187
197
  readonly onCurrentItemChanged: EventEmitter<CurrentItemEvent>;
@@ -197,19 +207,21 @@ export interface Spec extends TurboModule {
197
207
  readonly onFormatChange: EventEmitter<FormatChangeEvent>;
198
208
  readonly onPrefetchedAheadCountChanged: EventEmitter<PrefetchedAheadCountEvent>;
199
209
  readonly onRemainingContentCountChanged: EventEmitter<RemainingContentCountEvent>;
200
- readonly onError: EventEmitter<ErrorEvent>;
201
- readonly onShareTapped: EventEmitter<ShareTappedEvent>;
202
210
  readonly onSurveyResponse: EventEmitter<SurveyResponseEvent>;
203
- readonly onOverlayConfigure: EventEmitter<OverlayConfigureEvent>;
204
- readonly onOverlayActivate: EventEmitter<OverlayActivateEvent>;
205
- readonly onOverlayReset: EventEmitter<OverlayResetEvent>;
206
- readonly onOverlayTap: EventEmitter<OverlayTapEvent>;
207
- readonly onOverlayDoubleTap: EventEmitter<OverlayDoubleTapEvent>;
208
211
  readonly onContentTapped: EventEmitter<ContentTappedEvent>;
209
- readonly onCarouselOverlayConfigure: EventEmitter<CarouselOverlayConfigureEvent>;
210
- readonly onCarouselOverlayActivate: EventEmitter<CarouselOverlayActivateEvent>;
211
- readonly onCarouselOverlayReset: EventEmitter<CarouselOverlayResetEvent>;
212
- readonly onCarouselPageChanged: EventEmitter<CarouselPageChangedEvent>;
212
+ readonly onDismiss: EventEmitter<DismissEvent>;
213
+ readonly onRefreshRequested: EventEmitter<RefreshRequestedEvent>;
214
+ readonly onDidFetchContentItems: EventEmitter<DidFetchContentItemsEvent>;
215
+
216
+ // --- Overlay per-surface events ---
217
+ readonly onOverlayActiveChanged: EventEmitter<OverlayActiveEvent>;
218
+ readonly onOverlayPlayerStateChanged: EventEmitter<OverlayPlayerStateEvent>;
219
+ readonly onOverlayMutedChanged: EventEmitter<OverlayMutedEvent>;
220
+ readonly onOverlayPlaybackRateChanged: EventEmitter<OverlayPlaybackRateEvent>;
221
+ readonly onOverlayCaptionsEnabledChanged: EventEmitter<OverlayCaptionsEnabledEvent>;
222
+ readonly onOverlayActiveCueChanged: EventEmitter<OverlayActiveCueEvent>;
223
+ readonly onOverlayFeedScrollPhaseChanged: EventEmitter<OverlayFeedScrollPhaseEvent>;
224
+ readonly onOverlayTimeUpdate: EventEmitter<OverlayTimeUpdateEvent>;
213
225
  }
214
226
 
215
227
  export default TurboModuleRegistry.getEnforcing<Spec>('ShortKitModule');
@@ -1,10 +1,11 @@
1
1
  import type { HostComponent, ViewProps } from 'react-native';
2
2
  import { codegenNativeComponent } from 'react-native';
3
- import type { WithDefault } from 'react-native/Libraries/Types/CodegenTypes';
4
3
 
5
4
  export interface NativeProps extends ViewProps {
6
5
  config: string;
7
- overlayType?: WithDefault<'none' | 'custom', 'none'>;
6
+ feedId?: string;
7
+ startAtItemId?: string;
8
+ preloadId?: string;
8
9
  }
9
10
 
10
11
  export default codegenNativeComponent<NativeProps>(
package/src/types.ts CHANGED
@@ -1,9 +1,20 @@
1
+ import type React from 'react';
1
2
  import type { ViewStyle } from 'react-native';
2
3
 
3
4
  // --- Configuration ---
4
5
 
5
6
  export type FeedSource = 'algorithmic' | 'custom';
6
7
 
8
+ export interface FeedFilter {
9
+ tags?: string[];
10
+ section?: string;
11
+ author?: string;
12
+ contentType?: string;
13
+ metadata?: Record<string, string>;
14
+ }
15
+
16
+ export type CaptionSource = 'embedded' | 'external' | 'generated';
17
+
7
18
  export interface FeedConfig {
8
19
  feedHeight?: FeedHeight;
9
20
  overlay?: OverlayConfig;
@@ -11,6 +22,8 @@ export interface FeedConfig {
11
22
  surveyMode?: SurveyMode;
12
23
  muteOnStart?: boolean;
13
24
  feedSource?: FeedSource;
25
+ autoplay?: boolean;
26
+ filter?: FeedFilter;
14
27
  }
15
28
 
16
29
  export type FeedHeight =
@@ -19,11 +32,11 @@ export type FeedHeight =
19
32
 
20
33
  export type OverlayConfig =
21
34
  | 'none'
22
- | { type: 'custom'; component: React.ComponentType };
35
+ | { type: 'custom'; name: string; component: React.ComponentType<OverlayProps> };
23
36
 
24
37
  export type CarouselOverlayConfig =
25
38
  | 'none'
26
- | { type: 'custom'; component: React.ComponentType };
39
+ | { type: 'custom'; name: string; component: React.ComponentType<CarouselOverlayProps> };
27
40
 
28
41
  export type SurveyMode =
29
42
  | 'none'
@@ -44,6 +57,7 @@ export interface ContentItem {
44
57
  author?: string;
45
58
  articleUrl?: string;
46
59
  commentCount?: number;
60
+ fallbackUrl?: string;
47
61
  }
48
62
 
49
63
  // --- Custom Feed Types ---
@@ -56,7 +70,6 @@ export interface CarouselImage {
56
70
  export interface ImageCarouselItem {
57
71
  id: string;
58
72
  images: CarouselImage[];
59
- autoScrollInterval?: number;
60
73
  caption?: string;
61
74
  title?: string;
62
75
  description?: string;
@@ -66,7 +79,7 @@ export interface ImageCarouselItem {
66
79
  }
67
80
 
68
81
  export type FeedInput =
69
- | { type: 'video'; playbackId: string }
82
+ | { type: 'video'; playbackId: string; fallbackUrl?: string }
70
83
  | { type: 'imageCarousel'; item: ImageCarouselItem };
71
84
 
72
85
  export type JSONValue =
@@ -97,7 +110,10 @@ export interface StoryboardData {
97
110
  export interface CaptionTrack {
98
111
  language: string;
99
112
  label: string;
100
- sourceUrl: string;
113
+ source?: CaptionSource;
114
+ url?: string;
115
+ /** @deprecated Use `url` instead. */
116
+ sourceUrl?: string;
101
117
  }
102
118
 
103
119
  export interface PlayerTime {
@@ -148,35 +164,86 @@ export interface SurveyOption {
148
164
  text: string;
149
165
  }
150
166
 
151
- export interface ShortKitError {
152
- code: string;
153
- message: string;
167
+ // --- Overlay Props ---
168
+
169
+ /** Props passed to video overlay components rendered inside feed cells. */
170
+ export interface OverlayProps {
171
+ /** The content item for this cell. */
172
+ item: ContentItem;
173
+ /** Whether this cell is the active playback cell. */
174
+ isActive: boolean;
175
+ /** Current player state. */
176
+ playerState: PlayerState;
177
+ /** Current playback time. Only updates when isActive is true. */
178
+ time: PlayerTime;
179
+ /** Whether audio is muted. */
180
+ isMuted: boolean;
181
+ /** Current playback speed. */
182
+ playbackRate: number;
183
+ /** Whether captions are enabled. */
184
+ captionsEnabled: boolean;
185
+ /** The currently active caption cue, or null. */
186
+ activeCue: { text: string; startTime: number; endTime: number } | null;
187
+ /** Current feed scroll phase — use to fade overlay during swipes. */
188
+ feedScrollPhase: FeedScrollPhase | null;
189
+ }
190
+
191
+ /** Props passed to carousel overlay components rendered inside feed cells. */
192
+ export interface CarouselOverlayProps {
193
+ /** The carousel item for this cell. */
194
+ item: ImageCarouselItem;
154
195
  }
155
196
 
156
197
  // --- Provider Props ---
157
198
 
158
199
  export interface ShortKitProviderProps {
159
200
  apiKey: string;
160
- config: FeedConfig;
161
201
  userId?: string;
162
202
 
163
203
  clientAppName?: string;
164
204
  clientAppVersion?: string;
165
205
  customDimensions?: Record<string, string>;
166
206
  children: React.ReactNode;
207
+ /** Custom loading view rendered while the feed loads or during filter changes.
208
+ * When omitted, the SDK uses a default spinner. */
209
+ loadingViewComponent?: React.ComponentType<{}>;
167
210
  }
168
211
 
169
212
  // --- Feed Component Props ---
170
213
 
171
214
  export interface ShortKitFeedProps {
215
+ config?: FeedConfig;
216
+ preloadId?: string;
172
217
  style?: ViewStyle;
173
- onError?: (error: ShortKitError) => void;
174
- onShareTapped?: (item: ContentItem) => void;
218
+ /** Item ID to scroll to on initial load. */
219
+ startAtItemId?: string;
175
220
  onSurveyResponse?: (surveyId: string, option: SurveyOption) => void;
176
221
  onLoop?: (event: LoopEvent) => void;
177
222
  onFeedTransition?: (event: FeedTransitionEvent) => void;
178
223
  onFormatChange?: (event: FormatChangeEvent) => void;
179
224
  onContentTapped?: (contentId: string, index: number) => void;
225
+ /** Called when the user dismisses the feed (swipe-down or back gesture). */
226
+ onDismiss?: () => void;
227
+ /** Called when the user pulls to refresh in custom feed mode. */
228
+ onRefreshRequested?: () => void;
229
+ /** Called when the SDK fetches content items from the algorithmic feed.
230
+ * Use to pre-fetch your own metadata for the given items. */
231
+ onDidFetchContentItems?: (items: ContentItem[]) => void;
232
+ /** Called when the number of remaining items in this feed changes. */
233
+ onRemainingContentCountChange?: (count: number) => void;
234
+ }
235
+
236
+ /**
237
+ * Imperative handle for per-feed-instance operations.
238
+ * Obtained via `ref` on `<ShortKitFeed>`.
239
+ */
240
+ export interface ShortKitFeedHandle {
241
+ /** Replace all items in this feed instance. */
242
+ setFeedItems: (items: FeedInput[]) => void;
243
+ /** Append items to this feed instance. */
244
+ appendFeedItems: (items: FeedInput[]) => void;
245
+ /** Apply a content filter to this feed instance. Pass null to clear. */
246
+ applyFilter: (filter: FeedFilter | null) => void;
180
247
  }
181
248
 
182
249
  // --- Single Player Config ---
@@ -232,8 +299,6 @@ export interface ShortKitWidgetProps {
232
299
  export interface ShortKitPlayerState {
233
300
  playerState: PlayerState;
234
301
  currentItem: ContentItem | null;
235
- nextItem: ContentItem | null;
236
- activeCellType: 'video' | 'carousel' | null;
237
302
  time: PlayerTime;
238
303
  isMuted: boolean;
239
304
  playbackRate: number;
@@ -241,11 +306,8 @@ export interface ShortKitPlayerState {
241
306
  activeCaptionTrack: CaptionTrack | null;
242
307
  activeCue: { text: string; startTime: number; endTime: number } | null;
243
308
  prefetchedAheadCount: number;
244
- remainingContentCount: number;
245
309
  isActive: boolean;
246
310
  feedScrollPhase: FeedScrollPhase | null;
247
- lastOverlayTap: number;
248
- lastOverlayDoubleTap: { x: number; y: number; id: number } | null;
249
311
 
250
312
  play: () => void;
251
313
  pause: () => void;
@@ -16,9 +16,7 @@ export function useShortKit() {
16
16
  return {
17
17
  setUserId: context.setUserId,
18
18
  clearUserId: context.clearUserId,
19
- setFeedItems: context.setFeedItems,
20
- appendFeedItems: context.appendFeedItems,
21
19
  fetchContent: context.fetchContent,
22
- remainingContentCount: context.remainingContentCount,
20
+ preloadFeed: context.preloadFeed,
23
21
  };
24
22
  }
@@ -7,6 +7,12 @@ import type { ShortKitPlayerState } from './types';
7
7
  *
8
8
  * Must be used within a `<ShortKitProvider>`.
9
9
  *
10
+ * **Note:** This hook is NOT available inside overlay components registered via
11
+ * `config.overlay.component` / `config.carouselOverlay.component`. Overlays run
12
+ * in isolated React surfaces and receive data via props (OverlayProps /
13
+ * CarouselOverlayProps). Use `ShortKitCommands` for imperative player control
14
+ * from overlays.
15
+ *
10
16
  * @returns Player state (playerState, currentItem, time, etc.) and
11
17
  * command functions (play, pause, seek, etc.).
12
18
  */
@@ -16,19 +22,13 @@ export function useShortKitPlayer(): ShortKitPlayerState {
16
22
  throw new Error('useShortKitPlayer must be used within a ShortKitProvider');
17
23
  }
18
24
 
19
- // Return only player-related state and commands (exclude SDK operations,
20
- // carousel state, and internal fields)
25
+ // Return only player-related state and commands (exclude SDK operations)
21
26
  const {
22
27
  setUserId: _setUserId,
23
28
  clearUserId: _clearUserId,
24
29
  setFeedItems: _setFeedItems,
25
30
  appendFeedItems: _appendFeedItems,
26
31
  fetchContent: _fetchContent,
27
- currentCarouselItem: _currentCarouselItem,
28
- nextCarouselItem: _nextCarouselItem,
29
- isCarouselActive: _isCarouselActive,
30
- _overlayConfig: _overlay,
31
- _carouselOverlayConfig: _carouselOverlay,
32
32
  ...playerState
33
33
  } = context;
34
34
 
@@ -1,48 +0,0 @@
1
- package com.shortkit.reactnative
2
-
3
- import android.content.Context
4
- import android.graphics.Color
5
- import android.widget.FrameLayout
6
- import com.facebook.react.bridge.Arguments
7
- import com.shortkit.sdk.model.ImageCarouselItem
8
- import com.shortkit.sdk.overlay.CarouselOverlay
9
- import kotlinx.serialization.encodeToString
10
- import kotlinx.serialization.json.Json
11
-
12
- /**
13
- * A transparent [FrameLayout] that implements [CarouselOverlay] and bridges
14
- * carousel overlay lifecycle calls to JS events via [ShortKitModule].
15
- *
16
- * The actual carousel overlay UI is rendered by React Native on the JS side
17
- * through the `CarouselOverlayManager` component. This view simply relays
18
- * the SDK lifecycle events so the JS carousel overlay knows when to
19
- * configure, activate, reset, etc.
20
- *
21
- * Android equivalent of iOS `ShortKitCarouselOverlayBridge.swift`.
22
- */
23
- class ShortKitCarouselOverlayBridge(context: Context) : FrameLayout(context), CarouselOverlay {
24
-
25
- init {
26
- setBackgroundColor(Color.TRANSPARENT)
27
- }
28
-
29
- override fun configure(item: ImageCarouselItem) {
30
- val json = Json.encodeToString(item)
31
- val params = Arguments.createMap().apply {
32
- putString("item", json)
33
- }
34
- ShortKitModule.shared?.emitCarouselOverlayEvent("onCarouselOverlayConfigure", params)
35
- }
36
-
37
- override fun resetState() {
38
- ShortKitModule.shared?.emitCarouselOverlayEvent("onCarouselOverlayReset", Arguments.createMap())
39
- }
40
-
41
- override fun fadeOutForTransition() {
42
- ShortKitModule.shared?.emitCarouselOverlayEvent("onCarouselOverlayFadeOut", Arguments.createMap())
43
- }
44
-
45
- override fun restoreFromTransition() {
46
- ShortKitModule.shared?.emitCarouselOverlayEvent("onCarouselOverlayRestore", Arguments.createMap())
47
- }
48
- }
@@ -1,128 +0,0 @@
1
- package com.shortkit.reactnative
2
-
3
- import android.content.Context
4
- import android.graphics.Color
5
- import android.os.Handler
6
- import android.os.Looper
7
- import android.view.GestureDetector
8
- import android.view.MotionEvent
9
- import android.widget.FrameLayout
10
- import com.facebook.react.bridge.Arguments
11
- import com.shortkit.ContentItem
12
- import com.shortkit.FeedOverlay
13
- import com.shortkit.ShortKitPlayer
14
-
15
- /**
16
- * A transparent [FrameLayout] that implements [FeedOverlay] and bridges
17
- * overlay lifecycle calls to JS events via [ShortKitModule].
18
- *
19
- * The actual overlay UI is rendered by React Native on the JS side through
20
- * the `OverlayManager` component. This view simply relays the SDK lifecycle
21
- * events so the JS overlay knows when to configure, activate, reset, etc.
22
- *
23
- * Android equivalent of iOS `ShortKitOverlayBridge.swift`.
24
- */
25
- class ShortKitOverlayBridge(context: Context) : FrameLayout(context), FeedOverlay {
26
-
27
- // -----------------------------------------------------------------------
28
- // State
29
- // -----------------------------------------------------------------------
30
-
31
- /**
32
- * Stores the last configured [ContentItem] so we can pass it with
33
- * lifecycle events that don't receive the item as a parameter.
34
- */
35
- private var currentItem: ContentItem? = null
36
-
37
- /**
38
- * Deferred configure emission — cancelled if [activatePlayback] fires
39
- * on the same message-queue iteration (handleSwipe re-configure of the
40
- * active cell, not a prefetch for the next cell).
41
- */
42
- private var pendingConfigureRunnable: Runnable? = null
43
-
44
- private val handler = Handler(Looper.getMainLooper())
45
-
46
- // -----------------------------------------------------------------------
47
- // Gestures
48
- // -----------------------------------------------------------------------
49
-
50
- private val gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
51
- override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
52
- ShortKitModule.shared?.emitOverlayEvent("onOverlayTap", Arguments.createMap())
53
- return true
54
- }
55
-
56
- override fun onDoubleTap(e: MotionEvent): Boolean {
57
- val params = Arguments.createMap().apply {
58
- putDouble("x", e.x.toDouble())
59
- putDouble("y", e.y.toDouble())
60
- }
61
- ShortKitModule.shared?.emitOverlayEvent("onOverlayDoubleTap", params)
62
- return true
63
- }
64
- })
65
-
66
- // -----------------------------------------------------------------------
67
- // Init
68
- // -----------------------------------------------------------------------
69
-
70
- init {
71
- setBackgroundColor(Color.TRANSPARENT)
72
- isClickable = true
73
- }
74
-
75
- override fun onTouchEvent(event: MotionEvent): Boolean {
76
- return gestureDetector.onTouchEvent(event) || super.onTouchEvent(event)
77
- }
78
-
79
- // -----------------------------------------------------------------------
80
- // FeedOverlay
81
- // -----------------------------------------------------------------------
82
-
83
- override fun attach(player: ShortKitPlayer) {
84
- // No-op on the native side. The JS overlay subscribes to player
85
- // state via the TurboModule's flow publishers.
86
- }
87
-
88
- override fun configure(item: ContentItem) {
89
- currentItem = item
90
-
91
- // Defer the configure event by one message-queue tick. If activatePlayback()
92
- // fires before then (handleSwipe sequence: configure → reset → activate),
93
- // the event is cancelled — preventing nextItem from being overwritten
94
- // with the current cell's data.
95
- pendingConfigureRunnable?.let { handler.removeCallbacks(it) }
96
- val runnable = Runnable {
97
- currentItem?.let { ShortKitModule.shared?.emitOverlayEvent("onOverlayConfigure", it) }
98
- pendingConfigureRunnable = null
99
- }
100
- pendingConfigureRunnable = runnable
101
- handler.post(runnable)
102
- }
103
-
104
- override fun resetPlaybackProgress() {
105
- val item = currentItem ?: return
106
- ShortKitModule.shared?.emitOverlayEvent("onOverlayReset", item)
107
- }
108
-
109
- override fun activatePlayback() {
110
- // Cancel the pending configure — it was for the current cell (part of
111
- // handleSwipe), not a prefetch for the next cell.
112
- pendingConfigureRunnable?.let { handler.removeCallbacks(it) }
113
- pendingConfigureRunnable = null
114
-
115
- val item = currentItem ?: return
116
- ShortKitModule.shared?.emitOverlayEvent("onOverlayActivate", item)
117
- }
118
-
119
- override fun fadeOutForTransition() {
120
- val item = currentItem ?: return
121
- ShortKitModule.shared?.emitOverlayEvent("onOverlayFadeOut", item)
122
- }
123
-
124
- override fun restoreFromTransition() {
125
- val item = currentItem ?: return
126
- ShortKitModule.shared?.emitOverlayEvent("onOverlayRestore", item)
127
- }
128
- }