@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
@@ -10,16 +10,14 @@ import android.view.ViewGroup
10
10
  import android.widget.FrameLayout
11
11
  import androidx.fragment.app.FragmentActivity
12
12
  import androidx.viewpager2.widget.ViewPager2
13
- import com.facebook.react.uimanager.util.ReactFindViewUtil
14
- import com.shortkit.ShortKitFeedFragment
13
+ import com.shortkit.sdk.feed.ShortKitFeedFragment
15
14
 
16
15
  /**
17
16
  * Fabric native view that embeds [ShortKitFeedFragment] using Android
18
17
  * Fragment transactions. Props are set by [ShortKitFeedViewManager].
19
18
  *
20
- * Also tracks the feed's scroll offset via [ViewPager2.OnPageChangeCallback]
21
- * and applies native translation transforms to the sibling RN overlay views
22
- * so they move with the active cell during swipe transitions.
19
+ * The native SDK owns overlay lifecycle via [ReactOverlayHost] and
20
+ * [ReactCarouselOverlayHost] this view is purely a fragment container.
23
21
  *
24
22
  * Android equivalent of iOS `ShortKitFeedView.swift`.
25
23
  */
@@ -30,44 +28,51 @@ class ShortKitFeedView(context: Context) : FrameLayout(context) {
30
28
  // -----------------------------------------------------------------------
31
29
 
32
30
  var config: String? = null
33
- var overlayType: String? = null
31
+ var feedId: String? = null
32
+ var startAtItemId: String? = null
33
+ var preloadId: String? = null
34
34
 
35
35
  // -----------------------------------------------------------------------
36
36
  // Fragment management
37
37
  // -----------------------------------------------------------------------
38
38
 
39
39
  private var feedFragment: ShortKitFeedFragment? = null
40
+ private val fragmentContainer: FrameLayout
40
41
  private var fragmentContainerId: Int = View.generateViewId()
41
42
  private val handler = Handler(Looper.getMainLooper())
42
43
 
43
44
  init {
44
- id = fragmentContainerId
45
+ // Use a child FrameLayout as the fragment container. Fabric overrides
46
+ // this view's own id, so we can't use it as the fragment container.
47
+ fragmentContainer = FrameLayout(context).apply {
48
+ id = fragmentContainerId
49
+ layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
50
+ }
51
+ addView(fragmentContainer)
45
52
  }
46
53
 
47
54
  // -----------------------------------------------------------------------
48
- // Scroll tracking
55
+ // Fabric layout workarounds
49
56
  // -----------------------------------------------------------------------
50
57
 
51
- private var viewPager: ViewPager2? = null
52
- private var pageChangeCallback: ViewPager2.OnPageChangeCallback? = null
53
-
54
- /** Video overlay for the currently active cell (nativeID="overlay-current"). */
55
- private var currentOverlayView: View? = null
56
-
57
- /** Video overlay for the upcoming cell (nativeID="overlay-next"). */
58
- private var nextOverlayView: View? = null
59
-
60
- /** Carousel overlay for the currently active cell (nativeID="carousel-overlay-current"). */
61
- private var currentCarouselOverlayView: View? = null
62
-
63
- /** Carousel overlay for the upcoming cell (nativeID="carousel-overlay-next"). */
64
- private var nextCarouselOverlayView: View? = null
58
+ /**
59
+ * Fabric intercepts requestLayout() and doesn't propagate measure/layout
60
+ * to programmatically-added children. Override to schedule a manual pass.
61
+ */
62
+ override fun requestLayout() {
63
+ super.requestLayout()
64
+ @Suppress("UNNECESSARY_SAFE_CALL")
65
+ handler?.post(layoutRunnable)
66
+ }
65
67
 
66
- /** The page index used for overlay transform calculations. */
67
- private var currentPage: Int = 0
68
+ private val layoutRunnable = Runnable {
69
+ measure(
70
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
71
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
72
+ )
73
+ layout(left, top, right, bottom)
74
+ }
68
75
 
69
- /** Deferred page update to avoid flashing stale metadata. */
70
- private var pageUpdateRunnable: Runnable? = null
71
76
 
72
77
  // -----------------------------------------------------------------------
73
78
  // Lifecycle
@@ -79,7 +84,9 @@ class ShortKitFeedView(context: Context) : FrameLayout(context) {
79
84
  }
80
85
 
81
86
  override fun onDetachedFromWindow() {
82
- teardownScrollTracking()
87
+ synchronized(ShortKitBridge.staticPendingFeedViews) {
88
+ ShortKitBridge.staticPendingFeedViews.remove(this)
89
+ }
83
90
  removeFeedFragment()
84
91
  super.onDetachedFromWindow()
85
92
  }
@@ -88,36 +95,78 @@ class ShortKitFeedView(context: Context) : FrameLayout(context) {
88
95
  // Fragment containment
89
96
  // -----------------------------------------------------------------------
90
97
 
91
- private fun embedFeedFragmentIfNeeded() {
98
+ internal fun embedFeedFragmentIfNeeded() {
92
99
  if (feedFragment != null) return
93
100
 
94
- val sdk = ShortKitModule.shared?.sdk ?: run {
95
- Log.w(TAG, "ShortKit SDK not initialized. Call ShortKitModule.initialize() first.")
101
+ val sdk = ShortKitBridge.shared?.sdk ?: run {
102
+ synchronized(ShortKitBridge.staticPendingFeedViews) {
103
+ ShortKitBridge.staticPendingFeedViews.add(this)
104
+ }
96
105
  return
97
106
  }
98
107
 
99
- val activity = getReactActivity() ?: run {
100
- Log.w(TAG, "Could not find hosting Activity.")
101
- return
108
+ val activity = getReactActivity() ?: return
109
+
110
+ val feedConfig = ShortKitBridge.parseFeedConfig(config ?: "{}", context)
111
+
112
+ preloadId?.let { id ->
113
+ ShortKitBridge.shared?.consumePreload(id)
102
114
  }
103
115
 
104
- val fragment = ShortKitFeedFragment.newInstance(sdk)
116
+ val fragment = ShortKitFeedFragment.newInstance(sdk, feedConfig)
105
117
 
106
118
  try {
107
119
  activity.supportFragmentManager
108
120
  .beginTransaction()
109
121
  .replace(fragmentContainerId, fragment)
110
122
  .commitNowAllowingStateLoss()
111
- this.feedFragment = fragment // Only assign after successful commit
112
- setupScrollTracking(fragment)
123
+ this.feedFragment = fragment
124
+
125
+ // Force an immediate layout pass on the container so the fragment's
126
+ // ViewPager2/RecyclerView gets measured and can create cells.
127
+ fragmentContainer.measure(
128
+ MeasureSpec.makeMeasureSpec(measuredWidth, MeasureSpec.EXACTLY),
129
+ MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY)
130
+ )
131
+ fragmentContainer.layout(0, 0, measuredWidth, measuredHeight)
132
+
133
+ // The SDK's deferCellSetup retries only run during the current message
134
+ // loop iteration. Since Fabric suppresses layout, ViewPager2 won't
135
+ // have cells until our Choreographer callback forces layout on the
136
+ // next frame. Schedule a delayed nudge that runs after layout settles.
137
+ handler.postDelayed({
138
+ val fragView = feedFragment?.view
139
+ val vp = if (fragView != null) findViewPager2(fragView) else findViewPager2(fragmentContainer)
140
+ if (vp != null) {
141
+ if (vp.width == 0 || vp.height == 0) {
142
+ fragView?.measure(
143
+ MeasureSpec.makeMeasureSpec(measuredWidth, MeasureSpec.EXACTLY),
144
+ MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY)
145
+ )
146
+ fragView?.layout(0, 0, measuredWidth, measuredHeight)
147
+ }
148
+ if (vp.adapter != null && vp.adapter!!.itemCount > 0) {
149
+ vp.setCurrentItem(vp.currentItem, false)
150
+ }
151
+ }
152
+ }, 200)
153
+
154
+ feedId?.let { id ->
155
+ ShortKitBridge.shared?.registerFeed(id)
156
+ ShortKitBridge.shared?.registerFeedFragment(id, fragment)
157
+ }
113
158
  } catch (e: Exception) {
114
159
  Log.e(TAG, "Failed to embed feed fragment", e)
115
160
  }
116
161
  }
117
162
 
118
163
  private fun removeFeedFragment() {
164
+ feedId?.let { id ->
165
+ ShortKitBridge.shared?.unregisterFeed(id)
166
+ ShortKitBridge.shared?.unregisterFeedFragment(id)
167
+ }
119
168
  val fragment = feedFragment ?: return
120
- feedFragment = null // Clear immediately to prevent leaks on early return
169
+ feedFragment = null
121
170
 
122
171
  try {
123
172
  val activity = getReactActivity() ?: return
@@ -126,192 +175,16 @@ class ShortKitFeedView(context: Context) : FrameLayout(context) {
126
175
  .remove(fragment)
127
176
  .commitNowAllowingStateLoss()
128
177
  } catch (e: IllegalStateException) {
129
- // Expected during Activity teardown — fragment already being destroyed
178
+ // Expected during Activity teardown
130
179
  } catch (e: Exception) {
131
180
  Log.e(TAG, "Unexpected error removing feed fragment", e)
132
181
  }
133
182
  }
134
183
 
135
184
  // -----------------------------------------------------------------------
136
- // Scroll tracking
185
+ // Helpers
137
186
  // -----------------------------------------------------------------------
138
187
 
139
- private fun setupScrollTracking(fragment: ShortKitFeedFragment) {
140
- val pager = findViewPager2(fragment.view ?: return) ?: run {
141
- Log.w(TAG, "Could not find ViewPager2 in feed fragment hierarchy.")
142
- return
143
- }
144
- viewPager = pager
145
-
146
- val callback = object : ViewPager2.OnPageChangeCallback() {
147
- override fun onPageScrolled(
148
- position: Int,
149
- positionOffset: Float,
150
- positionOffsetPixels: Int
151
- ) {
152
- handleScrollOffset(position, positionOffset, positionOffsetPixels)
153
- }
154
- }
155
- pageChangeCallback = callback
156
- pager.registerOnPageChangeCallback(callback)
157
- }
158
-
159
- private fun teardownScrollTracking() {
160
- pageUpdateRunnable?.let { handler.removeCallbacks(it) }
161
- pageUpdateRunnable = null
162
- pageChangeCallback?.let { viewPager?.unregisterOnPageChangeCallback(it) }
163
- pageChangeCallback = null
164
- viewPager = null
165
- currentOverlayView?.translationY = 0f
166
- nextOverlayView?.translationY = 0f
167
- currentCarouselOverlayView?.translationY = 0f
168
- nextCarouselOverlayView?.translationY = 0f
169
- currentOverlayView = null
170
- nextOverlayView = null
171
- currentCarouselOverlayView = null
172
- nextCarouselOverlayView = null
173
- }
174
-
175
- private fun handleScrollOffset(
176
- position: Int,
177
- positionOffset: Float,
178
- positionOffsetPixels: Int
179
- ) {
180
- val cellHeight = height.toFloat()
181
- if (cellHeight <= 0) return
182
-
183
- // Detect page change, but DEFER updating currentPage.
184
- //
185
- // Why: when the scroll settles on a new page, overlay-current still
186
- // shows the OLD page's metadata (React hasn't processed OVERLAY_ACTIVATE
187
- // yet). If we update currentPage immediately, delta snaps to 0 and
188
- // overlay-current becomes visible with stale data.
189
- //
190
- // By deferring ~80ms, overlay-next (which already shows the correct
191
- // data via NextOverlayProvider) stays visible at y=0 while React
192
- // processes the state update.
193
- if (positionOffset == 0f) {
194
- if (position != currentPage && pageUpdateRunnable == null) {
195
- val targetPage = position
196
- val runnable = Runnable {
197
- currentPage = targetPage
198
- pageUpdateRunnable = null
199
- // Reapply overlay transforms now that currentPage is updated.
200
- // Without this, overlay-next (static NextOverlayProvider state)
201
- // stays visible at y=0 while overlay-current (live state) stays
202
- // hidden — no scroll event fires to trigger handleScrollOffset.
203
- val h = height.toFloat()
204
- currentOverlayView?.translationY = 0f
205
- nextOverlayView?.translationY = h
206
- currentCarouselOverlayView?.translationY = 0f
207
- nextCarouselOverlayView?.translationY = h
208
- }
209
- pageUpdateRunnable = runnable
210
- handler.postDelayed(runnable, 80)
211
- }
212
- } else if (pageUpdateRunnable != null) {
213
- // User is scrolling again — apply pending update immediately
214
- // so transforms stay aligned for the new gesture.
215
- handler.removeCallbacks(pageUpdateRunnable!!)
216
- pageUpdateRunnable = null
217
- currentPage = position
218
- }
219
-
220
- // positionOffset is 0.0 when settled, approaches 1.0 during forward scroll.
221
- // position is the index of the page currently filling most of the screen.
222
- val delta: Float = if (position >= currentPage) {
223
- // Forward scroll (or idle)
224
- positionOffsetPixels.toFloat()
225
- } else {
226
- // Backward scroll: position dropped below currentPage
227
- -(cellHeight - positionOffsetPixels.toFloat())
228
- }
229
-
230
- // Find the overlay views if not cached
231
- if (currentOverlayView == null || nextOverlayView == null) {
232
- findOverlayViews()
233
- }
234
- if (currentCarouselOverlayView == null || nextCarouselOverlayView == null) {
235
- findCarouselOverlayViews()
236
- }
237
-
238
- // Current overlays follow the active cell
239
- currentOverlayView?.translationY = -delta
240
- currentCarouselOverlayView?.translationY = -delta
241
-
242
- // Next overlays: positioned one page ahead in the scroll direction
243
- if (delta >= 0) {
244
- // Forward scroll (or idle): next cell is below
245
- val nextY = cellHeight - delta
246
- nextOverlayView?.translationY = nextY
247
- nextCarouselOverlayView?.translationY = nextY
248
- } else {
249
- // Backward scroll: next cell is above
250
- val nextY = -cellHeight - delta
251
- nextOverlayView?.translationY = nextY
252
- nextCarouselOverlayView?.translationY = nextY
253
- }
254
- }
255
-
256
- /**
257
- * Find the sibling RN overlay views by nativeID.
258
- *
259
- * In Fabric interop, this view may be wrapped in an intermediate
260
- * ViewGroup, so `getParent()` may not be the React `<View>` container
261
- * from ShortKitFeed.tsx. We walk up the ancestor chain until we find
262
- * the overlays.
263
- */
264
- private fun findOverlayViews() {
265
- var ancestor = parent as? ViewGroup ?: return
266
- while (true) {
267
- for (i in 0 until ancestor.childCount) {
268
- val child = ancestor.getChildAt(i)
269
- if (child === this || isOwnAncestor(child)) continue
270
-
271
- if (currentOverlayView == null) {
272
- currentOverlayView = ReactFindViewUtil.findView(child, "overlay-current")
273
- }
274
- if (nextOverlayView == null) {
275
- nextOverlayView = ReactFindViewUtil.findView(child, "overlay-next")
276
- }
277
- }
278
- if (currentOverlayView != null && nextOverlayView != null) return
279
- ancestor = ancestor.parent as? ViewGroup ?: return
280
- }
281
- }
282
-
283
- /**
284
- * Find the sibling RN carousel overlay views by nativeID.
285
- */
286
- private fun findCarouselOverlayViews() {
287
- var ancestor = parent as? ViewGroup ?: return
288
- while (true) {
289
- for (i in 0 until ancestor.childCount) {
290
- val child = ancestor.getChildAt(i)
291
- if (child === this || isOwnAncestor(child)) continue
292
-
293
- if (currentCarouselOverlayView == null) {
294
- currentCarouselOverlayView = ReactFindViewUtil.findView(child, "carousel-overlay-current")
295
- }
296
- if (nextCarouselOverlayView == null) {
297
- nextCarouselOverlayView = ReactFindViewUtil.findView(child, "carousel-overlay-next")
298
- }
299
- }
300
- if (currentCarouselOverlayView != null && nextCarouselOverlayView != null) return
301
- ancestor = ancestor.parent as? ViewGroup ?: return
302
- }
303
- }
304
-
305
- /** Check if the given view is an ancestor of this view. */
306
- private fun isOwnAncestor(view: View): Boolean {
307
- var current: ViewParent? = parent
308
- while (current != null) {
309
- if (current === view) return true
310
- current = current.parent
311
- }
312
- return false
313
- }
314
-
315
188
  /** Recursively find the first [ViewPager2] in a view hierarchy. */
316
189
  private fun findViewPager2(view: View): ViewPager2? {
317
190
  if (view is ViewPager2) return view
@@ -323,13 +196,8 @@ class ShortKitFeedView(context: Context) : FrameLayout(context) {
323
196
  return null
324
197
  }
325
198
 
326
- // -----------------------------------------------------------------------
327
- // Helpers
328
- // -----------------------------------------------------------------------
329
-
330
199
  /**
331
200
  * Walk the context wrapper chain to find the hosting [FragmentActivity].
332
- * React Native's [ThemedReactContext] wraps the Activity, so we unwrap it.
333
201
  */
334
202
  private fun getReactActivity(): FragmentActivity? {
335
203
  var ctx = context
@@ -15,16 +15,25 @@ class ShortKitFeedViewManager : SimpleViewManager<ShortKitFeedView>() {
15
15
  return ShortKitFeedView(context)
16
16
  }
17
17
 
18
+ @ReactProp(name = "feedId")
19
+ fun setFeedId(view: ShortKitFeedView, feedId: String?) {
20
+ view.feedId = feedId
21
+ }
22
+
18
23
  @ReactProp(name = "config")
19
24
  fun setConfig(view: ShortKitFeedView, config: String?) {
20
25
  view.config = config
21
26
  }
22
27
 
23
- @ReactProp(name = "overlayType", defaultString = "none")
24
- fun setOverlayType(view: ShortKitFeedView, overlayType: String?) {
25
- view.overlayType = overlayType
28
+ @ReactProp(name = "startAtItemId")
29
+ fun setStartAtItemId(view: ShortKitFeedView, startAtItemId: String?) {
30
+ view.startAtItemId = startAtItemId
26
31
  }
27
32
 
33
+ @ReactProp(name = "preloadId")
34
+ fun setPreloadId(view: ShortKitFeedView, preloadId: String?) {
35
+ view.preloadId = preloadId
36
+ }
28
37
 
29
38
  companion object {
30
39
  const val REACT_CLASS = "ShortKitFeedView"