@shortkitsdk/react-native 0.2.34 → 0.2.36
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 +8 -0
- package/android/libs/shortkit-release.aar +0 -0
- package/android/src/main/java/com/shortkit/reactnative/ReactCarouselOverlayHost.kt +100 -47
- package/android/src/main/java/com/shortkit/reactnative/ReactOverlayHost.kt +54 -8
- package/android/src/main/java/com/shortkit/reactnative/ReactVideoCarouselOverlayHost.kt +240 -27
- package/android/src/main/java/com/shortkit/reactnative/ShortKitBridge.kt +151 -1
- package/android/src/main/java/com/shortkit/reactnative/ShortKitFeedView.kt +135 -6
- package/android/src/main/java/com/shortkit/reactnative/ShortKitFeedViewManager.kt +15 -0
- package/android/src/main/java/com/shortkit/reactnative/ShortKitModule.kt +21 -11
- package/android/src/main/java/com/shortkit/reactnative/ShortKitPackage.kt +0 -2
- package/android/src/test/java/com/shortkit/reactnative/ReactCarouselOverlayHostEmitTest.kt +134 -0
- package/android/src/test/java/com/shortkit/reactnative/ReactOverlayHostDragTest.kt +45 -0
- package/android/src/test/java/com/shortkit/reactnative/ReactVideoCarouselOverlayHostDragTest.kt +69 -0
- package/android/src/test/java/com/shortkit/reactnative/ReactVideoCarouselOverlayHostEmitTest.kt +144 -0
- package/android/src/test/java/com/shortkit/reactnative/ShortKitFeedViewActivePropTest.kt +57 -0
- package/ios/ReactOverlayHost.swift +10 -8
- package/ios/ReactVideoCarouselOverlayHost.swift +6 -5
- package/ios/ShortKitBridge.swift +18 -0
- package/ios/ShortKitModule.mm +5 -0
- package/ios/ShortKitPlayerNativeView.swift +36 -0
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Info.plist +2 -2
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.abi.json +1252 -82
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +28 -2
- 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 +28 -2
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/_CodeSignature/CodeResources +9 -9
- package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Info.plist +2 -2
- package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +1252 -82
- package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +28 -2
- package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +28 -2
- package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/x86_64-apple-ios-simulator.abi.json +1252 -82
- package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +28 -2
- package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +28 -2
- package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/_CodeSignature/CodeResources +17 -17
- package/ios/ShortKitWidgetNativeView.swift +30 -3
- package/ios/ShortKitWidgetNativeViewManager.mm +1 -0
- package/package.json +1 -1
- package/src/ShortKitCommands.ts +20 -0
- package/src/ShortKitFeed.tsx +21 -0
- package/src/ShortKitPlayer.tsx +20 -1
- package/src/ShortKitWidget.tsx +63 -15
- package/src/specs/NativeShortKitModule.ts +10 -0
- package/src/specs/ShortKitWidgetViewNativeComponent.ts +15 -3
- package/src/types.ts +40 -0
- package/android/src/main/java/com/shortkit/reactnative/ShortKitPlayerNativeView.kt +0 -149
- package/android/src/main/java/com/shortkit/reactnative/ShortKitPlayerViewManager.kt +0 -35
- package/android/src/main/java/com/shortkit/reactnative/ShortKitWidgetNativeView.kt +0 -149
- package/android/src/main/java/com/shortkit/reactnative/ShortKitWidgetViewManager.kt +0 -30
package/src/types.ts
CHANGED
|
@@ -32,6 +32,11 @@ export interface FeedConfig {
|
|
|
32
32
|
autoplay?: boolean;
|
|
33
33
|
filter?: FeedFilter;
|
|
34
34
|
pullToRefreshEnabled?: boolean;
|
|
35
|
+
/** Called when the modal feed presented from `<ShortKitWidget>` /
|
|
36
|
+
* `<ShortKitPlayer>` fetches content items. Use to pre-fetch your own
|
|
37
|
+
* metadata for the items shown in the modal. Mirrors the same callback
|
|
38
|
+
* on `<ShortKitFeed>` props. */
|
|
39
|
+
onDidFetchContentItems?: (items: ContentItem[]) => void;
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
export type FeedHeight =
|
|
@@ -139,6 +144,12 @@ export interface ImageCarouselItem {
|
|
|
139
144
|
export interface VideoCarouselItem {
|
|
140
145
|
id: string;
|
|
141
146
|
videos: ContentItem[];
|
|
147
|
+
/**
|
|
148
|
+
* Zero-based index of the page the carousel landed on. Mirrors
|
|
149
|
+
* `VideoCarouselInput.initialPageIndex` from the host's input. Available
|
|
150
|
+
* to overlay components for reading the active page on first paint.
|
|
151
|
+
*/
|
|
152
|
+
initialPageIndex?: number;
|
|
142
153
|
title?: string;
|
|
143
154
|
description?: string;
|
|
144
155
|
author?: string;
|
|
@@ -170,6 +181,18 @@ export interface VideoCarouselVideoInput {
|
|
|
170
181
|
export interface VideoCarouselInput {
|
|
171
182
|
id: string;
|
|
172
183
|
videos: VideoCarouselVideoInput[];
|
|
184
|
+
/**
|
|
185
|
+
* Zero-based index of the page the carousel should land on the first time
|
|
186
|
+
* it becomes visible (vertical-arrival or initial mount). Defaults to 0.
|
|
187
|
+
* Out-of-range values are clamped to a valid index.
|
|
188
|
+
*
|
|
189
|
+
* **Has no effect after the carousel is first configured.** To move the
|
|
190
|
+
* user imperatively after landing, use
|
|
191
|
+
* `useShortKitCarousel().setActiveIndex(n)`. Re-rendering with a new
|
|
192
|
+
* `initialPageIndex` on the same `id` is ignored — change the `id` to force
|
|
193
|
+
* a re-bind if you genuinely want to land on a different page.
|
|
194
|
+
*/
|
|
195
|
+
initialPageIndex?: number;
|
|
173
196
|
title?: string;
|
|
174
197
|
description?: string;
|
|
175
198
|
author?: string;
|
|
@@ -421,6 +444,23 @@ export interface ShortKitFeedProps {
|
|
|
421
444
|
index: number;
|
|
422
445
|
pageIndex: number;
|
|
423
446
|
}) => void;
|
|
447
|
+
/**
|
|
448
|
+
* Fires for the lifecycle of a video-carousel cell long-press: `began`
|
|
449
|
+
* after a short native press delay, `ended` on touch release, and
|
|
450
|
+
* `cancelled` on user finger movement past ~10pt or when the cell is
|
|
451
|
+
* recycled (e.g. by `setFeedItems`).
|
|
452
|
+
*
|
|
453
|
+
* The recognizer runs simultaneously with the carousel's horizontal pan
|
|
454
|
+
* and the feed's vertical pan — it does not block scrolling. The intended
|
|
455
|
+
* use case is Instagram-style hold-to-pause: pause playback and hide
|
|
456
|
+
* overlay chrome on `began`, restore them on `ended` / `cancelled`.
|
|
457
|
+
*/
|
|
458
|
+
onVideoCarouselCellLongPress?: (event: {
|
|
459
|
+
id: string;
|
|
460
|
+
index: number;
|
|
461
|
+
pageIndex: number;
|
|
462
|
+
state: 'began' | 'ended' | 'cancelled';
|
|
463
|
+
}) => void;
|
|
424
464
|
}
|
|
425
465
|
|
|
426
466
|
/**
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
package com.shortkit.reactnative
|
|
2
|
-
|
|
3
|
-
import android.content.Context
|
|
4
|
-
import android.view.MotionEvent
|
|
5
|
-
import android.widget.FrameLayout
|
|
6
|
-
import com.shortkit.sdk.config.PlayerClickAction
|
|
7
|
-
import com.shortkit.sdk.config.FeedConfig
|
|
8
|
-
import com.shortkit.sdk.config.PlayerConfig
|
|
9
|
-
import com.shortkit.sdk.config.VideoOverlayMode
|
|
10
|
-
import com.shortkit.sdk.model.ContentItem
|
|
11
|
-
import com.shortkit.sdk.player.ShortKitPlayerView
|
|
12
|
-
import org.json.JSONObject
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Fabric native view wrapping [ShortKitPlayerView] for use as a
|
|
16
|
-
* single-video player in React Native.
|
|
17
|
-
*/
|
|
18
|
-
class ShortKitPlayerNativeView(context: Context) : FrameLayout(context) {
|
|
19
|
-
|
|
20
|
-
private var playerView: ShortKitPlayerView? = null
|
|
21
|
-
private var configJson: String? = null
|
|
22
|
-
private var contentItemJson: String? = null
|
|
23
|
-
|
|
24
|
-
var config: String?
|
|
25
|
-
get() = configJson
|
|
26
|
-
set(value) {
|
|
27
|
-
if (value == configJson) return
|
|
28
|
-
configJson = value
|
|
29
|
-
rebuildIfNeeded()
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
var contentItem: String?
|
|
33
|
-
get() = contentItemJson
|
|
34
|
-
set(value) {
|
|
35
|
-
if (value == contentItemJson) return
|
|
36
|
-
contentItemJson = value
|
|
37
|
-
applyContentItem()
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
var active: Boolean = true
|
|
41
|
-
set(value) {
|
|
42
|
-
if (field == value) return
|
|
43
|
-
field = value
|
|
44
|
-
applyActive()
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
|
|
48
|
-
return super.onInterceptTouchEvent(ev)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
|
|
52
|
-
return super.dispatchTouchEvent(ev)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
override fun onAttachedToWindow() {
|
|
56
|
-
super.onAttachedToWindow()
|
|
57
|
-
rebuildIfNeeded()
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
override fun onDetachedFromWindow() {
|
|
61
|
-
playerView?.deactivate()
|
|
62
|
-
super.onDetachedFromWindow()
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
private fun rebuildIfNeeded() {
|
|
66
|
-
if (playerView != null) return
|
|
67
|
-
|
|
68
|
-
val sdk = ShortKitBridge.shared?.sdk ?: return
|
|
69
|
-
val playerConfig = parsePlayerConfig(configJson)
|
|
70
|
-
|
|
71
|
-
val view = ShortKitPlayerView(context).apply {
|
|
72
|
-
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
|
73
|
-
}
|
|
74
|
-
view.initialize(sdk, playerConfig)
|
|
75
|
-
addView(view)
|
|
76
|
-
playerView = view
|
|
77
|
-
|
|
78
|
-
applyContentItem()
|
|
79
|
-
if (active) view.activate()
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
private fun applyContentItem() {
|
|
83
|
-
val json = contentItemJson ?: return
|
|
84
|
-
val view = playerView ?: return
|
|
85
|
-
val item = parseContentItem(json) ?: return
|
|
86
|
-
view.configure(item)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private fun applyActive() {
|
|
90
|
-
val view = playerView ?: return
|
|
91
|
-
if (active) view.activate() else view.deactivate()
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
private fun parsePlayerConfig(json: String?): PlayerConfig {
|
|
95
|
-
if (json.isNullOrEmpty()) return PlayerConfig()
|
|
96
|
-
return try {
|
|
97
|
-
val obj = JSONObject(json)
|
|
98
|
-
PlayerConfig(
|
|
99
|
-
cornerRadius = obj.optDouble("cornerRadius", 12.0).toFloat(),
|
|
100
|
-
clickAction = when (obj.optString("clickAction", "feed")) {
|
|
101
|
-
"feed" -> PlayerClickAction.FEED
|
|
102
|
-
"mute" -> PlayerClickAction.MUTE
|
|
103
|
-
"none" -> PlayerClickAction.NONE
|
|
104
|
-
else -> PlayerClickAction.FEED
|
|
105
|
-
},
|
|
106
|
-
autoplay = obj.optBoolean("autoplay", true),
|
|
107
|
-
loop = obj.optBoolean("loop", true),
|
|
108
|
-
muteOnStart = obj.optBoolean("muteOnStart", true),
|
|
109
|
-
videoOverlay = parseOverlay(obj),
|
|
110
|
-
feedConfig = obj.optString("feedConfig", "").let { fcStr ->
|
|
111
|
-
if (fcStr.isNotEmpty()) ShortKitBridge.parseFeedConfig(fcStr, context) else FeedConfig()
|
|
112
|
-
},
|
|
113
|
-
)
|
|
114
|
-
} catch (_: Exception) {
|
|
115
|
-
PlayerConfig()
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
private fun parseOverlay(obj: JSONObject): VideoOverlayMode {
|
|
120
|
-
val overlay = obj.opt("overlay") ?: return VideoOverlayMode.None
|
|
121
|
-
if (overlay is JSONObject && overlay.optString("type") == "custom") {
|
|
122
|
-
return VideoOverlayMode.Custom {
|
|
123
|
-
ReactOverlayHost(context)
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return VideoOverlayMode.None
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
private fun parseContentItem(json: String): ContentItem? {
|
|
130
|
-
return try {
|
|
131
|
-
val obj = JSONObject(json)
|
|
132
|
-
ContentItem(
|
|
133
|
-
id = obj.getString("id"),
|
|
134
|
-
title = obj.getString("title"),
|
|
135
|
-
description = obj.optString("description", null),
|
|
136
|
-
duration = obj.getDouble("duration"),
|
|
137
|
-
streamingUrl = obj.getString("streamingUrl"),
|
|
138
|
-
thumbnailUrl = obj.getString("thumbnailUrl"),
|
|
139
|
-
captionTracks = emptyList(),
|
|
140
|
-
customMetadata = null,
|
|
141
|
-
author = obj.optString("author", null),
|
|
142
|
-
articleUrl = obj.optString("articleUrl", null),
|
|
143
|
-
commentCount = if (obj.has("commentCount")) obj.getInt("commentCount") else null,
|
|
144
|
-
)
|
|
145
|
-
} catch (_: Exception) {
|
|
146
|
-
null
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
package com.shortkit.reactnative
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.module.annotations.ReactModule
|
|
4
|
-
import com.facebook.react.uimanager.SimpleViewManager
|
|
5
|
-
import com.facebook.react.uimanager.ThemedReactContext
|
|
6
|
-
import com.facebook.react.uimanager.annotations.ReactProp
|
|
7
|
-
|
|
8
|
-
@ReactModule(name = ShortKitPlayerViewManager.REACT_CLASS)
|
|
9
|
-
class ShortKitPlayerViewManager : SimpleViewManager<ShortKitPlayerNativeView>() {
|
|
10
|
-
|
|
11
|
-
override fun getName(): String = REACT_CLASS
|
|
12
|
-
|
|
13
|
-
override fun createViewInstance(context: ThemedReactContext): ShortKitPlayerNativeView {
|
|
14
|
-
return ShortKitPlayerNativeView(context)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
@ReactProp(name = "config")
|
|
18
|
-
fun setConfig(view: ShortKitPlayerNativeView, config: String?) {
|
|
19
|
-
view.config = config
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
@ReactProp(name = "contentItem")
|
|
23
|
-
fun setContentItem(view: ShortKitPlayerNativeView, contentItem: String?) {
|
|
24
|
-
view.contentItem = contentItem
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
@ReactProp(name = "active", defaultBoolean = true)
|
|
28
|
-
fun setActive(view: ShortKitPlayerNativeView, active: Boolean) {
|
|
29
|
-
view.active = active
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
companion object {
|
|
33
|
-
const val REACT_CLASS = "ShortKitPlayerView"
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
package com.shortkit.reactnative
|
|
2
|
-
|
|
3
|
-
import android.content.Context
|
|
4
|
-
import android.widget.FrameLayout
|
|
5
|
-
import com.shortkit.sdk.config.PlayerClickAction
|
|
6
|
-
import com.shortkit.sdk.config.VideoOverlayMode
|
|
7
|
-
import com.shortkit.sdk.config.WidgetConfig
|
|
8
|
-
import com.shortkit.sdk.widget.ShortKitWidgetView
|
|
9
|
-
import com.shortkit.sdk.config.FeedConfig
|
|
10
|
-
import com.shortkit.sdk.model.FeedFilter
|
|
11
|
-
import com.shortkit.sdk.model.WidgetInput
|
|
12
|
-
import org.json.JSONArray
|
|
13
|
-
import org.json.JSONObject
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Fabric native view wrapping [ShortKitWidgetView] for use as a
|
|
17
|
-
* horizontal video carousel in React Native.
|
|
18
|
-
*
|
|
19
|
-
* Props:
|
|
20
|
-
* - `config`: JSON string with WidgetConfig values
|
|
21
|
-
* - `items`: JSON string with WidgetInput array (compact playback-ID form)
|
|
22
|
-
*/
|
|
23
|
-
class ShortKitWidgetNativeView(context: Context) : FrameLayout(context) {
|
|
24
|
-
|
|
25
|
-
private var widgetView: ShortKitWidgetView? = null
|
|
26
|
-
private var configJson: String? = null
|
|
27
|
-
private var itemsJson: String? = null
|
|
28
|
-
private var parsedConfig: WidgetConfig = WidgetConfig()
|
|
29
|
-
private var parsedItems: List<WidgetInput> = emptyList()
|
|
30
|
-
|
|
31
|
-
var config: String?
|
|
32
|
-
get() = configJson
|
|
33
|
-
set(value) {
|
|
34
|
-
if (value == configJson) return
|
|
35
|
-
configJson = value
|
|
36
|
-
parsedConfig = parseWidgetConfig(value)
|
|
37
|
-
// If widget is already built, rebuild to pick up new config.
|
|
38
|
-
if (widgetView != null) {
|
|
39
|
-
removeWidget()
|
|
40
|
-
embedWidgetIfNeeded()
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
var items: String?
|
|
45
|
-
get() = itemsJson
|
|
46
|
-
set(value) {
|
|
47
|
-
if (value == itemsJson) return
|
|
48
|
-
itemsJson = value
|
|
49
|
-
parsedItems = parseWidgetInputs(value) ?: emptyList()
|
|
50
|
-
// Post-mount update on an existing widget.
|
|
51
|
-
widgetView?.configure(parsedItems)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
override fun onAttachedToWindow() {
|
|
55
|
-
super.onAttachedToWindow()
|
|
56
|
-
embedWidgetIfNeeded()
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
override fun onDetachedFromWindow() {
|
|
60
|
-
super.onDetachedFromWindow()
|
|
61
|
-
removeWidget()
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
private fun embedWidgetIfNeeded() {
|
|
65
|
-
if (widgetView != null) return
|
|
66
|
-
val sdk = ShortKitBridge.shared?.sdk ?: return
|
|
67
|
-
|
|
68
|
-
// Pass items at initialize time so the widget never races the server
|
|
69
|
-
// fetch — analogous to the feed's `feedItems` prop wiring.
|
|
70
|
-
val view = ShortKitWidgetView(context).apply {
|
|
71
|
-
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
|
72
|
-
}
|
|
73
|
-
view.initialize(sdk, parsedConfig, parsedItems)
|
|
74
|
-
addView(view)
|
|
75
|
-
widgetView = view
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
private fun removeWidget() {
|
|
79
|
-
widgetView?.let { removeView(it) }
|
|
80
|
-
widgetView = null
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
private fun parseWidgetConfig(json: String?): WidgetConfig {
|
|
84
|
-
if (json.isNullOrEmpty()) return WidgetConfig()
|
|
85
|
-
return try {
|
|
86
|
-
val obj = JSONObject(json)
|
|
87
|
-
WidgetConfig(
|
|
88
|
-
cardCount = obj.optInt("cardCount", 3),
|
|
89
|
-
cardSpacing = obj.optDouble("cardSpacing", 8.0).toFloat(),
|
|
90
|
-
cornerRadius = obj.optDouble("cornerRadius", 12.0).toFloat(),
|
|
91
|
-
autoplay = obj.optBoolean("autoplay", true),
|
|
92
|
-
muteOnStart = obj.optBoolean("muteOnStart", true),
|
|
93
|
-
loop = obj.optBoolean("loop", true),
|
|
94
|
-
rotationInterval = obj.optLong("rotationInterval", 10_000L),
|
|
95
|
-
clickAction = when (obj.optString("clickAction", "feed")) {
|
|
96
|
-
"feed" -> PlayerClickAction.FEED
|
|
97
|
-
"mute" -> PlayerClickAction.MUTE
|
|
98
|
-
"none" -> PlayerClickAction.NONE
|
|
99
|
-
else -> PlayerClickAction.FEED
|
|
100
|
-
},
|
|
101
|
-
cardOverlay = parseOverlay(obj),
|
|
102
|
-
filter = obj.optString("filter", "").let { filterStr ->
|
|
103
|
-
if (filterStr.isNotEmpty()) ShortKitBridge.parseFeedFilterToModel(filterStr) else null
|
|
104
|
-
},
|
|
105
|
-
feedConfig = obj.optString("feedConfig", "").let { fcStr ->
|
|
106
|
-
if (fcStr.isNotEmpty()) ShortKitBridge.parseFeedConfig(fcStr, context) else FeedConfig()
|
|
107
|
-
},
|
|
108
|
-
)
|
|
109
|
-
} catch (_: Exception) {
|
|
110
|
-
WidgetConfig()
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private fun parseOverlay(obj: JSONObject): VideoOverlayMode {
|
|
115
|
-
val overlay = obj.opt("overlay") ?: return VideoOverlayMode.None
|
|
116
|
-
if (overlay is JSONObject && overlay.optString("type") == "custom") {
|
|
117
|
-
return VideoOverlayMode.Custom {
|
|
118
|
-
ReactOverlayHost(context)
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
return VideoOverlayMode.None
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Parse a JSON array of `WidgetInput` values (compact playback-ID form).
|
|
126
|
-
* Mirrors the JS `WidgetInput` type:
|
|
127
|
-
* `{ type: 'video'; playbackId: string; fallbackUrl?: string }`.
|
|
128
|
-
*/
|
|
129
|
-
private fun parseWidgetInputs(json: String?): List<WidgetInput>? {
|
|
130
|
-
if (json.isNullOrEmpty()) return null
|
|
131
|
-
return try {
|
|
132
|
-
val arr = JSONArray(json)
|
|
133
|
-
val out = mutableListOf<WidgetInput>()
|
|
134
|
-
for (i in 0 until arr.length()) {
|
|
135
|
-
val obj = arr.getJSONObject(i)
|
|
136
|
-
if (obj.optString("type") != "video") continue
|
|
137
|
-
val playbackId = obj.optString("playbackId", "")
|
|
138
|
-
if (playbackId.isEmpty()) continue
|
|
139
|
-
val fallbackUrl = if (obj.has("fallbackUrl") && !obj.isNull("fallbackUrl")) {
|
|
140
|
-
obj.getString("fallbackUrl")
|
|
141
|
-
} else null
|
|
142
|
-
out.add(WidgetInput.Video(playbackId = playbackId, fallbackUrl = fallbackUrl))
|
|
143
|
-
}
|
|
144
|
-
out
|
|
145
|
-
} catch (_: Exception) {
|
|
146
|
-
null
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
package com.shortkit.reactnative
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.module.annotations.ReactModule
|
|
4
|
-
import com.facebook.react.uimanager.SimpleViewManager
|
|
5
|
-
import com.facebook.react.uimanager.ThemedReactContext
|
|
6
|
-
import com.facebook.react.uimanager.annotations.ReactProp
|
|
7
|
-
|
|
8
|
-
@ReactModule(name = ShortKitWidgetViewManager.REACT_CLASS)
|
|
9
|
-
class ShortKitWidgetViewManager : SimpleViewManager<ShortKitWidgetNativeView>() {
|
|
10
|
-
|
|
11
|
-
override fun getName(): String = REACT_CLASS
|
|
12
|
-
|
|
13
|
-
override fun createViewInstance(context: ThemedReactContext): ShortKitWidgetNativeView {
|
|
14
|
-
return ShortKitWidgetNativeView(context)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
@ReactProp(name = "config")
|
|
18
|
-
fun setConfig(view: ShortKitWidgetNativeView, config: String?) {
|
|
19
|
-
view.config = config
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
@ReactProp(name = "items")
|
|
23
|
-
fun setItems(view: ShortKitWidgetNativeView, items: String?) {
|
|
24
|
-
view.items = items
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
companion object {
|
|
28
|
-
const val REACT_CLASS = "ShortKitWidgetView"
|
|
29
|
-
}
|
|
30
|
-
}
|