@shortkitsdk/react-native 0.1.0 → 0.2.1

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.
@@ -2,6 +2,8 @@ package com.shortkit.reactnative
2
2
 
3
3
  import android.content.Context
4
4
  import android.content.ContextWrapper
5
+ import android.os.Handler
6
+ import android.os.Looper
5
7
  import android.util.Log
6
8
  import android.view.View
7
9
  import android.view.ViewGroup
@@ -36,6 +38,7 @@ class ShortKitFeedView(context: Context) : FrameLayout(context) {
36
38
 
37
39
  private var feedFragment: ShortKitFeedFragment? = null
38
40
  private var fragmentContainerId: Int = View.generateViewId()
41
+ private val handler = Handler(Looper.getMainLooper())
39
42
 
40
43
  init {
41
44
  id = fragmentContainerId
@@ -54,9 +57,12 @@ class ShortKitFeedView(context: Context) : FrameLayout(context) {
54
57
  /** Overlay for the upcoming cell (nativeID="overlay-next"). */
55
58
  private var nextOverlayView: View? = null
56
59
 
57
- /** The page index from which the current scroll gesture started. */
60
+ /** The page index used for overlay transform calculations. */
58
61
  private var currentPage: Int = 0
59
62
 
63
+ /** Deferred page update to avoid flashing stale metadata. */
64
+ private var pageUpdateRunnable: Runnable? = null
65
+
60
66
  // -----------------------------------------------------------------------
61
67
  // Lifecycle
62
68
  // -----------------------------------------------------------------------
@@ -145,6 +151,8 @@ class ShortKitFeedView(context: Context) : FrameLayout(context) {
145
151
  }
146
152
 
147
153
  private fun teardownScrollTracking() {
154
+ pageUpdateRunnable?.let { handler.removeCallbacks(it) }
155
+ pageUpdateRunnable = null
148
156
  pageChangeCallback?.let { viewPager?.unregisterOnPageChangeCallback(it) }
149
157
  pageChangeCallback = null
150
158
  viewPager = null
@@ -162,6 +170,41 @@ class ShortKitFeedView(context: Context) : FrameLayout(context) {
162
170
  val cellHeight = height.toFloat()
163
171
  if (cellHeight <= 0) return
164
172
 
173
+ // Detect page change, but DEFER updating currentPage.
174
+ //
175
+ // Why: when the scroll settles on a new page, overlay-current still
176
+ // shows the OLD page's metadata (React hasn't processed OVERLAY_ACTIVATE
177
+ // yet). If we update currentPage immediately, delta snaps to 0 and
178
+ // overlay-current becomes visible with stale data.
179
+ //
180
+ // By deferring ~80ms, overlay-next (which already shows the correct
181
+ // data via NextOverlayProvider) stays visible at y=0 while React
182
+ // processes the state update.
183
+ if (positionOffset == 0f) {
184
+ if (position != currentPage && pageUpdateRunnable == null) {
185
+ val targetPage = position
186
+ val runnable = Runnable {
187
+ currentPage = targetPage
188
+ pageUpdateRunnable = null
189
+ // Reapply overlay transforms now that currentPage is updated.
190
+ // Without this, overlay-next (static NextOverlayProvider state)
191
+ // stays visible at y=0 while overlay-current (live state) stays
192
+ // hidden — no scroll event fires to trigger handleScrollOffset.
193
+ val h = height.toFloat()
194
+ currentOverlayView?.translationY = 0f
195
+ nextOverlayView?.translationY = h
196
+ }
197
+ pageUpdateRunnable = runnable
198
+ handler.postDelayed(runnable, 80)
199
+ }
200
+ } else if (pageUpdateRunnable != null) {
201
+ // User is scrolling again — apply pending update immediately
202
+ // so transforms stay aligned for the new gesture.
203
+ handler.removeCallbacks(pageUpdateRunnable!!)
204
+ pageUpdateRunnable = null
205
+ currentPage = position
206
+ }
207
+
165
208
  // positionOffset is 0.0 when settled, approaches 1.0 during forward scroll.
166
209
  // position is the index of the page currently filling most of the screen.
167
210
  val delta: Float = if (position >= currentPage) {
@@ -172,11 +215,6 @@ class ShortKitFeedView(context: Context) : FrameLayout(context) {
172
215
  -(cellHeight - positionOffsetPixels.toFloat())
173
216
  }
174
217
 
175
- // Update currentPage when the scroll settles
176
- if (positionOffset == 0f) {
177
- currentPage = position
178
- }
179
-
180
218
  // Find the overlay views if not cached
181
219
  if (currentOverlayView == null || nextOverlayView == null) {
182
220
  findOverlayViews()
@@ -196,23 +234,40 @@ class ShortKitFeedView(context: Context) : FrameLayout(context) {
196
234
  }
197
235
 
198
236
  /**
199
- * Find the sibling RN overlay views by nativeID. In the Fabric hierarchy,
200
- * the ShortKitFeedView and the overlay containers are children of the
201
- * same parent (wrapped by ShortKitFeed.tsx with overflow: hidden).
237
+ * Find the sibling RN overlay views by nativeID.
238
+ *
239
+ * In Fabric interop, this view may be wrapped in an intermediate
240
+ * ViewGroup, so `getParent()` may not be the React `<View>` container
241
+ * from ShortKitFeed.tsx. We walk up the ancestor chain until we find
242
+ * the overlays.
202
243
  */
203
244
  private fun findOverlayViews() {
204
- val parent = parent as? ViewGroup ?: return
205
-
206
- for (i in 0 until parent.childCount) {
207
- val sibling = parent.getChildAt(i)
208
- if (sibling === this) continue
209
- if (currentOverlayView == null) {
210
- currentOverlayView = ReactFindViewUtil.findView(sibling, "overlay-current")
211
- }
212
- if (nextOverlayView == null) {
213
- nextOverlayView = ReactFindViewUtil.findView(sibling, "overlay-next")
245
+ var ancestor = parent as? ViewGroup ?: return
246
+ while (true) {
247
+ for (i in 0 until ancestor.childCount) {
248
+ val child = ancestor.getChildAt(i)
249
+ if (child === this || isOwnAncestor(child)) continue
250
+
251
+ if (currentOverlayView == null) {
252
+ currentOverlayView = ReactFindViewUtil.findView(child, "overlay-current")
253
+ }
254
+ if (nextOverlayView == null) {
255
+ nextOverlayView = ReactFindViewUtil.findView(child, "overlay-next")
256
+ }
214
257
  }
258
+ if (currentOverlayView != null && nextOverlayView != null) return
259
+ ancestor = ancestor.parent as? ViewGroup ?: return
260
+ }
261
+ }
262
+
263
+ /** Check if the given view is an ancestor of this view. */
264
+ private fun isOwnAncestor(view: View): Boolean {
265
+ var current: ViewParent? = parent
266
+ while (current != null) {
267
+ if (current === view) return true
268
+ current = current.parent
215
269
  }
270
+ return false
216
271
  }
217
272
 
218
273
  /** Recursively find the first [ViewPager2] in a view hierarchy. */
@@ -5,18 +5,18 @@ import com.facebook.react.bridge.ReactApplicationContext
5
5
  import com.facebook.react.bridge.ReactMethod
6
6
  import com.facebook.react.bridge.WritableMap
7
7
  import com.facebook.react.modules.core.DeviceEventManagerModule
8
+ import com.shortkit.CarouselImage
8
9
  import com.shortkit.ContentItem
9
10
  import com.shortkit.ContentSignal
11
+ import com.shortkit.CustomFeedItem
12
+ import com.shortkit.ImageCarouselItem
10
13
  import com.shortkit.FeedConfig
11
14
  import com.shortkit.FeedHeight
15
+ import com.shortkit.FeedSource
12
16
  import com.shortkit.FeedTransitionPhase
13
17
  import com.shortkit.JsonValue
14
- import com.shortkit.OverlayActionDelegate
15
18
  import com.shortkit.ShortKit
16
- import com.shortkit.ShortKitDelegate
17
- import com.shortkit.ShortKitError
18
19
  import com.shortkit.ShortKitPlayer
19
- import com.shortkit.SurveyOption
20
20
  import com.shortkit.VideoOverlayMode
21
21
  import com.shortkit.CarouselOverlayMode
22
22
  import com.shortkit.SurveyOverlayMode
@@ -30,8 +30,7 @@ import org.json.JSONArray
30
30
  import org.json.JSONObject
31
31
 
32
32
  class ShortKitModule(reactContext: ReactApplicationContext) :
33
- NativeShortKitModuleSpec(reactContext),
34
- ShortKitDelegate {
33
+ NativeShortKitModuleSpec(reactContext) {
35
34
 
36
35
  companion object {
37
36
  const val NAME = "ShortKitModule"
@@ -94,6 +93,7 @@ class ShortKitModule(reactContext: ReactApplicationContext) :
94
93
  override fun initialize(
95
94
  apiKey: String,
96
95
  config: String,
96
+ embedId: String?,
97
97
  clientAppName: String?,
98
98
  clientAppVersion: String?,
99
99
  customDimensions: String?
@@ -110,19 +110,27 @@ class ShortKitModule(reactContext: ReactApplicationContext) :
110
110
  context = context,
111
111
  apiKey = apiKey,
112
112
  config = feedConfig,
113
+ embedId = embedId,
113
114
  userId = null,
114
115
  adProvider = null,
115
116
  clientAppName = clientAppName,
116
117
  clientAppVersion = clientAppVersion,
117
118
  customDimensions = dims
118
119
  )
119
- sdk.delegate = this
120
- sdk.overlayActionDelegate = overlayDelegate
121
-
122
120
  this.shortKit = sdk
123
121
  shared = this
124
122
 
125
123
  subscribeToFlows(sdk.player)
124
+
125
+ sdk.delegate = object : com.shortkit.ShortKitDelegate {
126
+ override fun onContentTapped(contentId: String, index: Int) {
127
+ val params = Arguments.createMap().apply {
128
+ putString("contentId", contentId)
129
+ putInt("index", index)
130
+ }
131
+ sendEvent("onContentTapped", params)
132
+ }
133
+ }
126
134
  }
127
135
 
128
136
  @ReactMethod
@@ -220,98 +228,39 @@ class ShortKitModule(reactContext: ReactApplicationContext) :
220
228
  }
221
229
 
222
230
  // -----------------------------------------------------------------------
223
- // ShortKitDelegate
231
+ // Custom feed
224
232
  // -----------------------------------------------------------------------
225
233
 
226
- override fun onError(error: ShortKitError) {
227
- val params = Arguments.createMap().apply {
228
- when (error) {
229
- is ShortKitError.NetworkError -> {
230
- putString("code", "network_error")
231
- putString("message", error.cause?.localizedMessage ?: "Network error")
232
- }
233
- is ShortKitError.ApiError -> {
234
- putString("code", "api_error")
235
- putString("message", error.message ?: "API error")
236
- }
237
- is ShortKitError.PlayerError -> {
238
- putString("code", error.code)
239
- putString("message", error.message ?: "Player error")
240
- }
241
- is ShortKitError.ConfigError -> {
242
- putString("code", "config_error")
243
- putString("message", error.message ?: "Config error")
244
- }
245
- is ShortKitError.AuthError -> {
246
- putString("code", "auth_error")
247
- putString("message", "Invalid API key")
248
- }
249
- }
250
- }
251
- sendEvent("onError", params)
252
- }
253
-
254
- override fun onShareTapped(item: ContentItem) {
255
- val params = Arguments.createMap().apply {
256
- putString("item", serializeContentItemToJSON(item))
257
- }
258
- sendEvent("onShareTapped", params)
234
+ @ReactMethod
235
+ override fun setFeedItems(items: String) {
236
+ val parsed = parseCustomFeedItems(items) ?: return
237
+ shortKit?.setFeedItems(parsed)
259
238
  }
260
239
 
261
- override fun onSurveyResponse(surveyId: String, option: SurveyOption) {
262
- val params = Arguments.createMap().apply {
263
- putString("surveyId", surveyId)
264
- putString("optionId", option.id)
265
- putString("optionText", option.text)
266
- }
267
- sendEvent("onSurveyResponse", params)
240
+ @ReactMethod
241
+ override fun appendFeedItems(items: String) {
242
+ val parsed = parseCustomFeedItems(items) ?: return
243
+ shortKit?.appendFeedItems(parsed)
268
244
  }
269
245
 
270
- // We implement the optional delegate methods as no-ops; events are handled
271
- // via StateFlow/SharedFlow subscriptions instead.
272
- override fun onFeedReady() {}
273
- override fun onContentChanged(item: ContentItem) {}
274
- override fun onFeedEmpty() {}
275
-
276
- // -----------------------------------------------------------------------
277
- // OverlayActionDelegate (separate object to avoid signature clash with
278
- // ShortKitDelegate.onShareTapped)
279
- // -----------------------------------------------------------------------
280
-
281
- private val overlayDelegate = object : OverlayActionDelegate {
282
- override fun onReadMoreTapped(item: ContentItem) {
283
- val params = Arguments.createMap().apply {
284
- putString("item", serializeContentItemToJSON(item))
285
- }
286
- sendEvent("onArticleTapped", params)
287
- }
288
-
289
- override fun onShareTapped(item: ContentItem) {
290
- val params = Arguments.createMap().apply {
291
- putString("item", serializeContentItemToJSON(item))
292
- }
293
- sendEvent("onOverlayShareTapped", params)
294
- }
295
-
296
- override fun onCommentTapped(item: ContentItem) {
297
- val params = Arguments.createMap().apply {
298
- putString("item", serializeContentItemToJSON(item))
299
- }
300
- sendEvent("onCommentTapped", params)
301
- }
302
-
303
- override fun onSaveTapped(item: ContentItem) {
304
- val params = Arguments.createMap().apply {
305
- putString("item", serializeContentItemToJSON(item))
306
- }
307
- sendEvent("onSaveTapped", params)
308
- }
309
-
310
- override fun onLikeTapped(item: ContentItem) {
311
- val params = Arguments.createMap().apply {
312
- putString("item", serializeContentItemToJSON(item))
246
+ @ReactMethod
247
+ override fun fetchContent(limit: Double, promise: com.facebook.react.bridge.Promise) {
248
+ val sdk = shortKit
249
+ if (sdk == null) {
250
+ promise.resolve("[]")
251
+ return
252
+ }
253
+ scope?.launch {
254
+ try {
255
+ val items = sdk.fetchContent(limit.toInt())
256
+ val arr = JSONArray()
257
+ for (item in items) {
258
+ arr.put(JSONObject(serializeContentItemToJSON(item)))
259
+ }
260
+ promise.resolve(arr.toString())
261
+ } catch (e: Exception) {
262
+ promise.resolve("[]")
313
263
  }
314
- sendEvent("onLikeTapped", params)
315
264
  }
316
265
  }
317
266
 
@@ -489,6 +438,16 @@ class ShortKitModule(reactContext: ReactApplicationContext) :
489
438
  sendEvent("onPrefetchedAheadCountChanged", params)
490
439
  }
491
440
  }
441
+
442
+ // Remaining content count
443
+ newScope.launch {
444
+ player.remainingContentCount.collect { count ->
445
+ val params = Arguments.createMap().apply {
446
+ putInt("count", count)
447
+ }
448
+ sendEvent("onRemainingContentCountChanged", params)
449
+ }
450
+ }
492
451
  }
493
452
 
494
453
  // -----------------------------------------------------------------------
@@ -529,6 +488,7 @@ class ShortKitModule(reactContext: ReactApplicationContext) :
529
488
  private fun contentItemMap(item: ContentItem): WritableMap {
530
489
  return Arguments.createMap().apply {
531
490
  putString("id", item.id)
491
+ item.playbackId?.let { putString("playbackId", it) }
532
492
  putString("title", item.title)
533
493
  item.description?.let { putString("description", it) }
534
494
  putDouble("duration", item.duration)
@@ -679,13 +639,17 @@ class ShortKitModule(reactContext: ReactApplicationContext) :
679
639
  val muteOnStart = obj.optBoolean("muteOnStart", true)
680
640
  val videoOverlay = parseVideoOverlay(obj.optString("overlay", null))
681
641
 
642
+ val feedSourceStr = obj.optString("feedSource", "algorithmic")
643
+ val feedSource = if (feedSourceStr == "custom") FeedSource.CUSTOM else FeedSource.ALGORITHMIC
644
+
682
645
  FeedConfig(
683
646
  feedHeight = feedHeight,
684
647
  videoOverlay = videoOverlay,
685
648
  carouselOverlay = CarouselOverlayMode.None,
686
649
  surveyOverlay = SurveyOverlayMode.None,
687
650
  adOverlay = AdOverlayMode.None,
688
- muteOnStart = muteOnStart
651
+ muteOnStart = muteOnStart,
652
+ feedSource = feedSource
689
653
  )
690
654
  } catch (_: Exception) {
691
655
  FeedConfig()
@@ -748,6 +712,54 @@ class ShortKitModule(reactContext: ReactApplicationContext) :
748
712
  }
749
713
  }
750
714
 
715
+ private fun parseCustomFeedItems(json: String): List<CustomFeedItem>? {
716
+ return try {
717
+ val arr = JSONArray(json)
718
+ val result = mutableListOf<CustomFeedItem>()
719
+ for (i in 0 until arr.length()) {
720
+ val obj = arr.getJSONObject(i)
721
+ when (obj.optString("type")) {
722
+ "video" -> {
723
+ val playbackId = obj.optString("playbackId", null) ?: continue
724
+ result.add(CustomFeedItem.Video(playbackId))
725
+ }
726
+ "imageCarousel" -> {
727
+ val itemObj = obj.optJSONObject("item") ?: continue
728
+ val carouselItem = parseImageCarouselItem(itemObj) ?: continue
729
+ result.add(CustomFeedItem.ImageCarousel(carouselItem))
730
+ }
731
+ }
732
+ }
733
+ result.ifEmpty { null }
734
+ } catch (_: Exception) {
735
+ null
736
+ }
737
+ }
738
+
739
+ private fun parseImageCarouselItem(obj: JSONObject): ImageCarouselItem? {
740
+ val id = obj.optString("id", null) ?: return null
741
+ val imagesArr = obj.optJSONArray("images") ?: return null
742
+ val images = mutableListOf<CarouselImage>()
743
+ for (i in 0 until imagesArr.length()) {
744
+ val imgObj = imagesArr.getJSONObject(i)
745
+ images.add(CarouselImage(
746
+ url = imgObj.getString("url"),
747
+ alt = imgObj.optString("alt", null)
748
+ ))
749
+ }
750
+ return ImageCarouselItem(
751
+ id = id,
752
+ images = images,
753
+ autoScrollInterval = if (obj.has("autoScrollInterval")) obj.getDouble("autoScrollInterval") else null,
754
+ caption = obj.optString("caption", null),
755
+ title = obj.optString("title", null),
756
+ description = obj.optString("description", null),
757
+ author = obj.optString("author", null),
758
+ section = obj.optString("section", null),
759
+ articleUrl = obj.optString("articleUrl", null)
760
+ )
761
+ }
762
+
751
763
  /**
752
764
  * Parse optional custom dimensions JSON string into map.
753
765
  */
@@ -35,6 +35,10 @@ class ShortKitPackage : TurboReactPackage() {
35
35
  override fun createViewManagers(
36
36
  reactContext: ReactApplicationContext
37
37
  ): List<ViewManager<*, *>> {
38
- return listOf(ShortKitFeedViewManager())
38
+ return listOf(
39
+ ShortKitFeedViewManager(),
40
+ ShortKitPlayerViewManager(),
41
+ ShortKitWidgetViewManager(),
42
+ )
39
43
  }
40
44
  }
@@ -0,0 +1,136 @@
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.PlayerConfig
7
+ import com.shortkit.sdk.config.VideoOverlayMode
8
+ import com.shortkit.sdk.model.ContentItem
9
+ import com.shortkit.sdk.player.ShortKitPlayerView
10
+ import org.json.JSONObject
11
+
12
+ /**
13
+ * Fabric native view wrapping [ShortKitPlayerView] for use as a
14
+ * single-video player in React Native.
15
+ */
16
+ class ShortKitPlayerNativeView(context: Context) : FrameLayout(context) {
17
+
18
+ private var playerView: ShortKitPlayerView? = null
19
+ private var configJson: String? = null
20
+ private var contentItemJson: String? = null
21
+
22
+ var config: String?
23
+ get() = configJson
24
+ set(value) {
25
+ if (value == configJson) return
26
+ configJson = value
27
+ rebuildIfNeeded()
28
+ }
29
+
30
+ var contentItem: String?
31
+ get() = contentItemJson
32
+ set(value) {
33
+ if (value == contentItemJson) return
34
+ contentItemJson = value
35
+ applyContentItem()
36
+ }
37
+
38
+ var active: Boolean = true
39
+ set(value) {
40
+ if (field == value) return
41
+ field = value
42
+ applyActive()
43
+ }
44
+
45
+ override fun onAttachedToWindow() {
46
+ super.onAttachedToWindow()
47
+ rebuildIfNeeded()
48
+ }
49
+
50
+ override fun onDetachedFromWindow() {
51
+ playerView?.deactivate()
52
+ super.onDetachedFromWindow()
53
+ }
54
+
55
+ private fun rebuildIfNeeded() {
56
+ if (playerView != null) return
57
+
58
+ val sdk = ShortKitModule.shared?.sdk ?: return
59
+ val playerConfig = parsePlayerConfig(configJson)
60
+
61
+ val view = ShortKitPlayerView(context).apply {
62
+ layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
63
+ }
64
+ view.initialize(sdk, playerConfig)
65
+ addView(view)
66
+ playerView = view
67
+
68
+ applyContentItem()
69
+ if (active) view.activate()
70
+ }
71
+
72
+ private fun applyContentItem() {
73
+ val json = contentItemJson ?: return
74
+ val view = playerView ?: return
75
+ val item = parseContentItem(json) ?: return
76
+ view.configure(item)
77
+ }
78
+
79
+ private fun applyActive() {
80
+ val view = playerView ?: return
81
+ if (active) view.activate() else view.deactivate()
82
+ }
83
+
84
+ private fun parsePlayerConfig(json: String?): PlayerConfig {
85
+ if (json.isNullOrEmpty()) return PlayerConfig()
86
+ return try {
87
+ val obj = JSONObject(json)
88
+ PlayerConfig(
89
+ cornerRadius = obj.optDouble("cornerRadius", 12.0).toFloat(),
90
+ clickAction = when (obj.optString("clickAction", "feed")) {
91
+ "feed" -> PlayerClickAction.FEED
92
+ "mute" -> PlayerClickAction.MUTE
93
+ "none" -> PlayerClickAction.NONE
94
+ else -> PlayerClickAction.FEED
95
+ },
96
+ autoplay = obj.optBoolean("autoplay", true),
97
+ loop = obj.optBoolean("loop", true),
98
+ muteOnStart = obj.optBoolean("muteOnStart", true),
99
+ videoOverlay = parseOverlay(obj),
100
+ )
101
+ } catch (_: Exception) {
102
+ PlayerConfig()
103
+ }
104
+ }
105
+
106
+ private fun parseOverlay(obj: JSONObject): VideoOverlayMode {
107
+ val overlay = obj.opt("overlay") ?: return VideoOverlayMode.None
108
+ if (overlay is JSONObject && overlay.optString("type") == "custom") {
109
+ return VideoOverlayMode.Custom {
110
+ ShortKitOverlayBridge(context)
111
+ }
112
+ }
113
+ return VideoOverlayMode.None
114
+ }
115
+
116
+ private fun parseContentItem(json: String): ContentItem? {
117
+ return try {
118
+ val obj = JSONObject(json)
119
+ ContentItem(
120
+ id = obj.getString("id"),
121
+ title = obj.getString("title"),
122
+ description = obj.optString("description", null),
123
+ duration = obj.getDouble("duration"),
124
+ streamingUrl = obj.getString("streamingUrl"),
125
+ thumbnailUrl = obj.getString("thumbnailUrl"),
126
+ captionTracks = emptyList(),
127
+ customMetadata = null,
128
+ author = obj.optString("author", null),
129
+ articleUrl = obj.optString("articleUrl", null),
130
+ commentCount = if (obj.has("commentCount")) obj.getInt("commentCount") else null,
131
+ )
132
+ } catch (_: Exception) {
133
+ null
134
+ }
135
+ }
136
+ }
@@ -0,0 +1,35 @@
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
+ }