@shortkitsdk/react-native 0.2.6 → 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/ShortKitReactNative.podspec +1 -0
- package/android/build.gradle.kts +17 -1
- package/android/src/main/java/com/shortkit/reactnative/ReactCarouselOverlayHost.kt +379 -0
- package/android/src/main/java/com/shortkit/reactnative/ReactLoadingHost.kt +40 -0
- package/android/src/main/java/com/shortkit/reactnative/ReactOverlayHost.kt +570 -0
- package/android/src/main/java/com/shortkit/reactnative/ShortKitBridge.kt +1029 -0
- package/android/src/main/java/com/shortkit/reactnative/ShortKitFeedView.kt +212 -219
- package/android/src/main/java/com/shortkit/reactnative/ShortKitFeedViewManager.kt +17 -3
- package/android/src/main/java/com/shortkit/reactnative/ShortKitModule.kt +157 -742
- package/android/src/main/java/com/shortkit/reactnative/ShortKitPlayerNativeView.kt +11 -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 +444 -0
- package/ios/SKFabricSurfaceWrapper.h +18 -0
- package/ios/SKFabricSurfaceWrapper.mm +57 -0
- package/ios/ShortKitBridge.swift +220 -63
- package/ios/ShortKitFeedView.swift +82 -228
- package/ios/ShortKitFeedViewManager.mm +3 -2
- package/ios/ShortKitModule.mm +69 -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 +3683 -1249
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +56 -15
- 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 +56 -15
- 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 +3683 -1249
- package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +56 -15
- 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 +56 -15
- 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 -24
- package/src/ShortKitFeed.tsx +124 -41
- package/src/ShortKitLoadingSurface.tsx +24 -0
- package/src/ShortKitOverlaySurface.tsx +313 -0
- package/src/ShortKitPlayer.tsx +30 -9
- package/src/ShortKitProvider.tsx +28 -285
- package/src/index.ts +9 -3
- package/src/serialization.ts +20 -39
- package/src/specs/NativeShortKitModule.ts +74 -45
- package/src/specs/ShortKitFeedViewNativeComponent.ts +3 -2
- package/src/types.ts +84 -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
|
@@ -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
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}>;
|
|
92
|
+
type DismissEvent = Readonly<{}>;
|
|
93
|
+
|
|
94
|
+
type RefreshRequestedEvent = Readonly<{}>;
|
|
94
95
|
|
|
95
|
-
type
|
|
96
|
-
|
|
96
|
+
type DidFetchContentItemsEvent = Readonly<{
|
|
97
|
+
items: string; // JSON-serialized ContentItem[]
|
|
97
98
|
}>;
|
|
98
99
|
|
|
99
100
|
type SurveyResponseEvent = Readonly<{
|
|
@@ -102,50 +103,75 @@ type SurveyResponseEvent = Readonly<{
|
|
|
102
103
|
optionText: string;
|
|
103
104
|
}>;
|
|
104
105
|
|
|
105
|
-
type
|
|
106
|
-
|
|
106
|
+
type ContentTappedEvent = Readonly<{
|
|
107
|
+
contentId: string;
|
|
108
|
+
index: Int32;
|
|
107
109
|
}>;
|
|
108
110
|
|
|
109
|
-
type
|
|
110
|
-
|
|
111
|
+
type FeedReadyEvent = Readonly<{
|
|
112
|
+
feedId: string;
|
|
111
113
|
}>;
|
|
112
114
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
+
// --- Overlay per-surface event payload types ---
|
|
116
|
+
|
|
117
|
+
type OverlayActiveEvent = Readonly<{
|
|
118
|
+
surfaceId: string;
|
|
119
|
+
isActive: boolean;
|
|
115
120
|
}>;
|
|
116
121
|
|
|
117
|
-
type
|
|
118
|
-
|
|
119
|
-
|
|
122
|
+
type OverlayPlayerStateEvent = Readonly<{
|
|
123
|
+
surfaceId: string;
|
|
124
|
+
playerState: string;
|
|
120
125
|
}>;
|
|
121
126
|
|
|
122
|
-
type
|
|
123
|
-
|
|
127
|
+
type OverlayMutedEvent = Readonly<{
|
|
128
|
+
surfaceId: string;
|
|
129
|
+
isMuted: boolean;
|
|
124
130
|
}>;
|
|
125
131
|
|
|
126
|
-
type
|
|
127
|
-
|
|
132
|
+
type OverlayPlaybackRateEvent = Readonly<{
|
|
133
|
+
surfaceId: string;
|
|
134
|
+
playbackRate: Double;
|
|
128
135
|
}>;
|
|
129
136
|
|
|
130
|
-
type
|
|
137
|
+
type OverlayCaptionsEnabledEvent = Readonly<{
|
|
138
|
+
surfaceId: string;
|
|
139
|
+
captionsEnabled: boolean;
|
|
140
|
+
}>;
|
|
131
141
|
|
|
132
|
-
type
|
|
133
|
-
|
|
134
|
-
|
|
142
|
+
type OverlayActiveCueEvent = Readonly<{
|
|
143
|
+
surfaceId: string;
|
|
144
|
+
activeCue: string;
|
|
135
145
|
}>;
|
|
136
146
|
|
|
137
|
-
type
|
|
147
|
+
type OverlayFeedScrollPhaseEvent = Readonly<{
|
|
148
|
+
surfaceId: string;
|
|
149
|
+
feedScrollPhase: string;
|
|
150
|
+
}>;
|
|
138
151
|
|
|
139
|
-
type
|
|
140
|
-
|
|
141
|
-
|
|
152
|
+
type OverlayTimeUpdateEvent = Readonly<{
|
|
153
|
+
surfaceId: string;
|
|
154
|
+
current: Double;
|
|
155
|
+
duration: Double;
|
|
156
|
+
buffered: Double;
|
|
157
|
+
}>;
|
|
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;
|
|
142
168
|
}>;
|
|
143
169
|
|
|
144
170
|
export interface Spec extends TurboModule {
|
|
145
171
|
// --- Lifecycle ---
|
|
146
172
|
initialize(
|
|
147
173
|
apiKey: string,
|
|
148
|
-
|
|
174
|
+
hasLoadingView: boolean,
|
|
149
175
|
clientAppName?: string,
|
|
150
176
|
clientAppVersion?: string,
|
|
151
177
|
customDimensions?: string, // JSON-serialized Record<string, string>
|
|
@@ -171,17 +197,16 @@ export interface Spec extends TurboModule {
|
|
|
171
197
|
setMaxBitrate(bitrate: Double): void;
|
|
172
198
|
|
|
173
199
|
// --- Custom feed ---
|
|
174
|
-
setFeedItems(items: string): void;
|
|
175
|
-
appendFeedItems(items: string): void;
|
|
176
|
-
fetchContent(limit: Int32): Promise<string>;
|
|
200
|
+
setFeedItems(feedId: string, items: string): void;
|
|
201
|
+
appendFeedItems(feedId: string, items: string): void;
|
|
202
|
+
fetchContent(limit: Int32, filterJSON: string | null): Promise<string>;
|
|
203
|
+
applyFilter(feedId: string, filterJSON: string | null): void;
|
|
204
|
+
preloadFeed(configJSON: string, itemsJSON: string | null): Promise<string>;
|
|
177
205
|
|
|
178
206
|
// --- Storyboard / seek thumbnails ---
|
|
179
207
|
prefetchStoryboard(playbackId: string): void;
|
|
180
208
|
getStoryboardData(playbackId: string): Promise<string>;
|
|
181
209
|
|
|
182
|
-
// --- Overlay lifecycle ---
|
|
183
|
-
notifyOverlayReady(): void;
|
|
184
|
-
|
|
185
210
|
// --- Event emitters ---
|
|
186
211
|
readonly onPlayerStateChanged: EventEmitter<PlayerStateEvent>;
|
|
187
212
|
readonly onCurrentItemChanged: EventEmitter<CurrentItemEvent>;
|
|
@@ -197,19 +222,23 @@ export interface Spec extends TurboModule {
|
|
|
197
222
|
readonly onFormatChange: EventEmitter<FormatChangeEvent>;
|
|
198
223
|
readonly onPrefetchedAheadCountChanged: EventEmitter<PrefetchedAheadCountEvent>;
|
|
199
224
|
readonly onRemainingContentCountChanged: EventEmitter<RemainingContentCountEvent>;
|
|
200
|
-
readonly onError: EventEmitter<ErrorEvent>;
|
|
201
|
-
readonly onShareTapped: EventEmitter<ShareTappedEvent>;
|
|
202
225
|
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
226
|
readonly onContentTapped: EventEmitter<ContentTappedEvent>;
|
|
209
|
-
readonly
|
|
210
|
-
readonly
|
|
211
|
-
readonly
|
|
212
|
-
readonly
|
|
227
|
+
readonly onDismiss: EventEmitter<DismissEvent>;
|
|
228
|
+
readonly onRefreshRequested: EventEmitter<RefreshRequestedEvent>;
|
|
229
|
+
readonly onDidFetchContentItems: EventEmitter<DidFetchContentItemsEvent>;
|
|
230
|
+
readonly onFeedReady: EventEmitter<FeedReadyEvent>;
|
|
231
|
+
|
|
232
|
+
// --- Overlay per-surface events ---
|
|
233
|
+
readonly onOverlayActiveChanged: EventEmitter<OverlayActiveEvent>;
|
|
234
|
+
readonly onOverlayPlayerStateChanged: EventEmitter<OverlayPlayerStateEvent>;
|
|
235
|
+
readonly onOverlayMutedChanged: EventEmitter<OverlayMutedEvent>;
|
|
236
|
+
readonly onOverlayPlaybackRateChanged: EventEmitter<OverlayPlaybackRateEvent>;
|
|
237
|
+
readonly onOverlayCaptionsEnabledChanged: EventEmitter<OverlayCaptionsEnabledEvent>;
|
|
238
|
+
readonly onOverlayActiveCueChanged: EventEmitter<OverlayActiveCueEvent>;
|
|
239
|
+
readonly onOverlayFeedScrollPhaseChanged: EventEmitter<OverlayFeedScrollPhaseEvent>;
|
|
240
|
+
readonly onOverlayTimeUpdate: EventEmitter<OverlayTimeUpdateEvent>;
|
|
241
|
+
readonly onOverlayFullState: EventEmitter<OverlayFullStateEvent>;
|
|
213
242
|
}
|
|
214
243
|
|
|
215
244
|
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
|
-
|
|
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,29 +1,45 @@
|
|
|
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;
|
|
20
|
+
scrollAxis?: ScrollAxis;
|
|
9
21
|
overlay?: OverlayConfig;
|
|
10
22
|
carouselOverlay?: CarouselOverlayConfig;
|
|
11
23
|
surveyMode?: SurveyMode;
|
|
12
24
|
muteOnStart?: boolean;
|
|
13
25
|
feedSource?: FeedSource;
|
|
26
|
+
autoplay?: boolean;
|
|
27
|
+
filter?: FeedFilter;
|
|
14
28
|
}
|
|
15
29
|
|
|
16
30
|
export type FeedHeight =
|
|
17
31
|
| { type: 'fullscreen' }
|
|
18
32
|
| { type: 'percentage'; value: number };
|
|
19
33
|
|
|
34
|
+
export type ScrollAxis = 'vertical' | 'horizontal';
|
|
35
|
+
|
|
20
36
|
export type OverlayConfig =
|
|
21
37
|
| 'none'
|
|
22
|
-
| { type: 'custom'; component: React.ComponentType };
|
|
38
|
+
| { type: 'custom'; name: string; component: React.ComponentType<OverlayProps> };
|
|
23
39
|
|
|
24
40
|
export type CarouselOverlayConfig =
|
|
25
41
|
| 'none'
|
|
26
|
-
| { type: 'custom'; component: React.ComponentType };
|
|
42
|
+
| { type: 'custom'; name: string; component: React.ComponentType<CarouselOverlayProps> };
|
|
27
43
|
|
|
28
44
|
export type SurveyMode =
|
|
29
45
|
| 'none'
|
|
@@ -44,6 +60,7 @@ export interface ContentItem {
|
|
|
44
60
|
author?: string;
|
|
45
61
|
articleUrl?: string;
|
|
46
62
|
commentCount?: number;
|
|
63
|
+
fallbackUrl?: string;
|
|
47
64
|
}
|
|
48
65
|
|
|
49
66
|
// --- Custom Feed Types ---
|
|
@@ -56,7 +73,6 @@ export interface CarouselImage {
|
|
|
56
73
|
export interface ImageCarouselItem {
|
|
57
74
|
id: string;
|
|
58
75
|
images: CarouselImage[];
|
|
59
|
-
autoScrollInterval?: number;
|
|
60
76
|
caption?: string;
|
|
61
77
|
title?: string;
|
|
62
78
|
description?: string;
|
|
@@ -66,7 +82,7 @@ export interface ImageCarouselItem {
|
|
|
66
82
|
}
|
|
67
83
|
|
|
68
84
|
export type FeedInput =
|
|
69
|
-
| { type: 'video'; playbackId: string }
|
|
85
|
+
| { type: 'video'; playbackId: string; fallbackUrl?: string }
|
|
70
86
|
| { type: 'imageCarousel'; item: ImageCarouselItem };
|
|
71
87
|
|
|
72
88
|
export type JSONValue =
|
|
@@ -97,7 +113,10 @@ export interface StoryboardData {
|
|
|
97
113
|
export interface CaptionTrack {
|
|
98
114
|
language: string;
|
|
99
115
|
label: string;
|
|
100
|
-
|
|
116
|
+
source?: CaptionSource;
|
|
117
|
+
url?: string;
|
|
118
|
+
/** @deprecated Use `url` instead. */
|
|
119
|
+
sourceUrl?: string;
|
|
101
120
|
}
|
|
102
121
|
|
|
103
122
|
export interface PlayerTime {
|
|
@@ -148,35 +167,89 @@ export interface SurveyOption {
|
|
|
148
167
|
text: string;
|
|
149
168
|
}
|
|
150
169
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
170
|
+
// --- Overlay Props ---
|
|
171
|
+
|
|
172
|
+
/** Props passed to video overlay components rendered inside feed cells. */
|
|
173
|
+
export interface OverlayProps {
|
|
174
|
+
/** The content item for this cell. */
|
|
175
|
+
item: ContentItem;
|
|
176
|
+
/** Whether this cell is the active playback cell. */
|
|
177
|
+
isActive: boolean;
|
|
178
|
+
/** Current player state. */
|
|
179
|
+
playerState: PlayerState;
|
|
180
|
+
/** Current playback time. Only updates when isActive is true. */
|
|
181
|
+
time: PlayerTime;
|
|
182
|
+
/** Whether audio is muted. */
|
|
183
|
+
isMuted: boolean;
|
|
184
|
+
/** Current playback speed. */
|
|
185
|
+
playbackRate: number;
|
|
186
|
+
/** Whether captions are enabled. */
|
|
187
|
+
captionsEnabled: boolean;
|
|
188
|
+
/** The currently active caption cue, or null. */
|
|
189
|
+
activeCue: { text: string; startTime: number; endTime: number } | null;
|
|
190
|
+
/** Current feed scroll phase — use to fade overlay during swipes. */
|
|
191
|
+
feedScrollPhase: FeedScrollPhase | null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Props passed to carousel overlay components rendered inside feed cells. */
|
|
195
|
+
export interface CarouselOverlayProps {
|
|
196
|
+
/** The carousel item for this cell. */
|
|
197
|
+
item: ImageCarouselItem;
|
|
154
198
|
}
|
|
155
199
|
|
|
156
200
|
// --- Provider Props ---
|
|
157
201
|
|
|
158
202
|
export interface ShortKitProviderProps {
|
|
159
203
|
apiKey: string;
|
|
160
|
-
config: FeedConfig;
|
|
161
204
|
userId?: string;
|
|
162
205
|
|
|
163
206
|
clientAppName?: string;
|
|
164
207
|
clientAppVersion?: string;
|
|
165
208
|
customDimensions?: Record<string, string>;
|
|
166
209
|
children: React.ReactNode;
|
|
210
|
+
/** Custom loading view rendered while the feed loads or during filter changes.
|
|
211
|
+
* When omitted, the SDK uses a default spinner. */
|
|
212
|
+
loadingViewComponent?: React.ComponentType<{}>;
|
|
167
213
|
}
|
|
168
214
|
|
|
169
215
|
// --- Feed Component Props ---
|
|
170
216
|
|
|
171
217
|
export interface ShortKitFeedProps {
|
|
218
|
+
config?: FeedConfig;
|
|
219
|
+
preloadId?: string;
|
|
172
220
|
style?: ViewStyle;
|
|
173
|
-
|
|
174
|
-
|
|
221
|
+
/** Item ID to scroll to on initial load. */
|
|
222
|
+
startAtItemId?: string;
|
|
175
223
|
onSurveyResponse?: (surveyId: string, option: SurveyOption) => void;
|
|
176
224
|
onLoop?: (event: LoopEvent) => void;
|
|
177
225
|
onFeedTransition?: (event: FeedTransitionEvent) => void;
|
|
178
226
|
onFormatChange?: (event: FormatChangeEvent) => void;
|
|
179
227
|
onContentTapped?: (contentId: string, index: number) => void;
|
|
228
|
+
/** Called when the user dismisses the feed (swipe-down or back gesture). */
|
|
229
|
+
onDismiss?: () => void;
|
|
230
|
+
/** Called when the user pulls to refresh in custom feed mode. */
|
|
231
|
+
onRefreshRequested?: () => void;
|
|
232
|
+
/** Called when the SDK fetches content items from the algorithmic feed.
|
|
233
|
+
* Use to pre-fetch your own metadata for the given items. */
|
|
234
|
+
onDidFetchContentItems?: (items: ContentItem[]) => void;
|
|
235
|
+
/** Called when the number of remaining items in this feed changes. */
|
|
236
|
+
onRemainingContentCountChange?: (count: number) => void;
|
|
237
|
+
/** Called once when this feed has loaded content and assigned a player
|
|
238
|
+
* to the first cell. Use to dismiss a splash screen or loading overlay. */
|
|
239
|
+
onFeedReady?: () => void;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Imperative handle for per-feed-instance operations.
|
|
244
|
+
* Obtained via `ref` on `<ShortKitFeed>`.
|
|
245
|
+
*/
|
|
246
|
+
export interface ShortKitFeedHandle {
|
|
247
|
+
/** Replace all items in this feed instance. */
|
|
248
|
+
setFeedItems: (items: FeedInput[]) => void;
|
|
249
|
+
/** Append items to this feed instance. */
|
|
250
|
+
appendFeedItems: (items: FeedInput[]) => void;
|
|
251
|
+
/** Apply a content filter to this feed instance. Pass null to clear. */
|
|
252
|
+
applyFilter: (filter: FeedFilter | null) => void;
|
|
180
253
|
}
|
|
181
254
|
|
|
182
255
|
// --- Single Player Config ---
|
|
@@ -232,8 +305,6 @@ export interface ShortKitWidgetProps {
|
|
|
232
305
|
export interface ShortKitPlayerState {
|
|
233
306
|
playerState: PlayerState;
|
|
234
307
|
currentItem: ContentItem | null;
|
|
235
|
-
nextItem: ContentItem | null;
|
|
236
|
-
activeCellType: 'video' | 'carousel' | null;
|
|
237
308
|
time: PlayerTime;
|
|
238
309
|
isMuted: boolean;
|
|
239
310
|
playbackRate: number;
|
|
@@ -241,11 +312,8 @@ export interface ShortKitPlayerState {
|
|
|
241
312
|
activeCaptionTrack: CaptionTrack | null;
|
|
242
313
|
activeCue: { text: string; startTime: number; endTime: number } | null;
|
|
243
314
|
prefetchedAheadCount: number;
|
|
244
|
-
remainingContentCount: number;
|
|
245
315
|
isActive: boolean;
|
|
246
316
|
feedScrollPhase: FeedScrollPhase | null;
|
|
247
|
-
lastOverlayTap: number;
|
|
248
|
-
lastOverlayDoubleTap: { x: number; y: number; id: number } | null;
|
|
249
317
|
|
|
250
318
|
play: () => void;
|
|
251
319
|
pause: () => void;
|
package/src/useShortKit.ts
CHANGED
|
@@ -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
|
-
|
|
20
|
+
preloadFeed: context.preloadFeed,
|
|
23
21
|
};
|
|
24
22
|
}
|
package/src/useShortKitPlayer.ts
CHANGED
|
@@ -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
|
-
}
|