@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
@@ -11,6 +11,7 @@ Pod::Spec.new do |s|
11
11
  s.platforms = { :ios => "16.0" }
12
12
  s.source = { :git => "https://github.com/shortkit/shortkit.git", :tag => "v#{s.version}" }
13
13
  s.source_files = "ios/*.{h,m,mm,cpp,swift}"
14
+ s.public_header_files = "ios/ShortKitModule.h", "ios/SKFabricSurfaceWrapper.h"
14
15
  s.requires_arc = true
15
16
 
16
17
  # When the vendored XCFramework is present (npm published package), use it.
@@ -1,6 +1,7 @@
1
1
  plugins {
2
2
  id("com.android.library")
3
3
  id("org.jetbrains.kotlin.android")
4
+ id("org.jetbrains.kotlin.plugin.serialization")
4
5
  id("com.facebook.react")
5
6
  }
6
7
 
@@ -30,5 +31,8 @@ android {
30
31
 
31
32
  dependencies {
32
33
  implementation("com.facebook.react:react-android")
33
- implementation("dev.shortkit:shortkit:0.1.0")
34
+ implementation("dev.shortkit:shortkit:0.2.6")
35
+ implementation("androidx.viewpager2:viewpager2:1.1.0")
36
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
37
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
34
38
  }
@@ -0,0 +1,319 @@
1
+ package com.shortkit.reactnative
2
+
3
+ import android.content.Context
4
+ import android.graphics.Bitmap
5
+ import android.os.Bundle
6
+ import android.widget.FrameLayout
7
+ import com.facebook.react.ReactApplication
8
+ import com.facebook.react.bridge.Arguments
9
+ import com.facebook.react.interfaces.fabric.ReactSurface
10
+ import com.facebook.react.runtime.ReactSurfaceImpl
11
+ import com.shortkit.sdk.model.CarouselImage
12
+ import com.shortkit.sdk.model.ImageCarouselItem
13
+ import com.shortkit.sdk.overlay.CarouselOverlay
14
+ import kotlinx.serialization.encodeToString
15
+ import kotlinx.serialization.json.Json
16
+ import java.io.File
17
+ import java.io.FileOutputStream
18
+
19
+ /**
20
+ * A [FrameLayout] that conforms to [CarouselOverlay] and hosts a React Native
21
+ * Fabric [ReactSurface] for rendering the developer's React carousel overlay
22
+ * component inside a feed cell.
23
+ *
24
+ * Unlike [ReactOverlayHost], this does not subscribe to player state (carousels
25
+ * are image-based). It pushes [ImageCarouselItem] data as surface properties.
26
+ *
27
+ * Android equivalent of `react_native_sdk/ios/ReactCarouselOverlayHost.swift`.
28
+ */
29
+ class ReactCarouselOverlayHost(context: Context) : FrameLayout(context), CarouselOverlay {
30
+
31
+ private companion object {
32
+ const val TAG = "SK:CarouselHost"
33
+ }
34
+
35
+ // ------------------------------------------------------------------
36
+ // Configuration
37
+ // ------------------------------------------------------------------
38
+
39
+ /** Suffix for the surface module name (e.g. "news" -> "ShortKitCarouselOverlay_news"). */
40
+ var carouselOverlayName: String = "Default"
41
+
42
+ // ------------------------------------------------------------------
43
+ // State
44
+ // ------------------------------------------------------------------
45
+
46
+ private var surface: ReactSurface? = null
47
+ private var pendingProps: Bundle? = null
48
+
49
+ // ------------------------------------------------------------------
50
+ // Fabric layout workaround
51
+ // ------------------------------------------------------------------
52
+
53
+ private val layoutHandler = android.os.Handler(android.os.Looper.getMainLooper())
54
+
55
+ override fun requestLayout() {
56
+ super.requestLayout()
57
+ @Suppress("UNNECESSARY_SAFE_CALL")
58
+ layoutHandler?.post {
59
+ measure(
60
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
61
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
62
+ )
63
+ layout(left, top, right, bottom)
64
+ }
65
+ }
66
+
67
+ // ------------------------------------------------------------------
68
+ // Init
69
+ // ------------------------------------------------------------------
70
+
71
+ init {
72
+ setBackgroundColor(android.graphics.Color.TRANSPARENT)
73
+ }
74
+
75
+ // ------------------------------------------------------------------
76
+ // Surface warmup
77
+ // ------------------------------------------------------------------
78
+
79
+ /**
80
+ * Eagerly create the Fabric surface so it's mounted and ready before
81
+ * the cell scrolls into view. Called from the overlay factory closure
82
+ * at pool creation time — mirrors iOS ReactCarouselOverlayHost.prepareSurface().
83
+ */
84
+ fun prepareSurface() {
85
+ createSurfaceIfNeeded()
86
+
87
+ // Pre-measure the host and surface view to screen dimensions so they
88
+ // have non-zero size before being attached to a cell. This prevents
89
+ // the black flash that occurs when the host is added at 0x0 and needs
90
+ // an async layout pass to become visible.
91
+ val displayW = context.resources.displayMetrics.widthPixels
92
+ val displayH = context.resources.displayMetrics.heightPixels
93
+ val wSpec = MeasureSpec.makeMeasureSpec(displayW, MeasureSpec.EXACTLY)
94
+ val hSpec = MeasureSpec.makeMeasureSpec(displayH, MeasureSpec.EXACTLY)
95
+ measure(wSpec, hSpec)
96
+ layout(0, 0, displayW, displayH)
97
+ measureAndLayoutSurfaceView(displayW, displayH)
98
+ }
99
+
100
+ // ------------------------------------------------------------------
101
+ // CarouselOverlay — native image cache
102
+ // ------------------------------------------------------------------
103
+
104
+ /** Injected by the SDK's PrefetchManager. Returns a cached Bitmap or null. */
105
+ override var cachedImage: ((String) -> Bitmap?)? = null
106
+
107
+ // ------------------------------------------------------------------
108
+ // CarouselOverlay
109
+ // ------------------------------------------------------------------
110
+
111
+ override fun configure(item: ImageCarouselItem) {
112
+ // Replace remote URLs with local file:// URLs for any natively-cached images.
113
+ val modifiedItem = cachedImage?.let { lookup ->
114
+ val localImages = item.images.map { image ->
115
+ val bitmap = lookup(image.url)
116
+ if (bitmap != null) {
117
+ val localUrl = writeTempImage(bitmap, image.url)
118
+ if (localUrl != null) {
119
+ CarouselImage(url = localUrl, alt = image.alt)
120
+ } else {
121
+ image
122
+ }
123
+ } else {
124
+ image
125
+ }
126
+ }
127
+ ImageCarouselItem(
128
+ id = item.id,
129
+ images = localImages,
130
+ caption = item.caption,
131
+ title = item.title,
132
+ description = item.description,
133
+ author = item.author,
134
+ section = item.section,
135
+ articleUrl = item.articleUrl
136
+ )
137
+ } ?: item
138
+
139
+ val json = Json.encodeToString(modifiedItem)
140
+ val bundle = Bundle().apply {
141
+ putString("item", json)
142
+ }
143
+
144
+ val s = surface
145
+ if (s != null && s.isRunning) {
146
+ // Surface already running (cell reuse) — update props in place
147
+ (s as? ReactSurfaceImpl)?.updateInitProps(bundle)
148
+ } else if (s != null && !s.isRunning) {
149
+ // Surface pre-created by prepareSurface() but not started yet.
150
+ // Set props THEN start — the JS component mounts once with correct data.
151
+ (s as? ReactSurfaceImpl)?.updateInitProps(bundle)
152
+ s.start()
153
+ } else {
154
+ // No surface at all — create with item as initial props
155
+ pendingProps = bundle
156
+ createSurfaceIfNeeded()
157
+ }
158
+
159
+ // Pre-size the surface view NOW — before the overlay is attached to a cell.
160
+ // This eliminates the black flash: when the cell displays the overlay, the
161
+ // surface view already has correct dimensions and rendered content.
162
+ // Use parent dimensions if attached, otherwise use display dimensions.
163
+ val parentView = parent as? android.view.View
164
+ val w = if (width > 0) width
165
+ else if (parentView != null && parentView.width > 0) parentView.width
166
+ else context.resources.displayMetrics.widthPixels
167
+ val h = if (height > 0) height
168
+ else if (parentView != null && parentView.height > 0) parentView.height
169
+ else context.resources.displayMetrics.heightPixels
170
+ measureAndLayoutSurfaceView(w, h)
171
+ }
172
+
173
+ /**
174
+ * Write a Bitmap to the temp directory as JPEG, returning a file:// URL.
175
+ * Uses a hash of the remote URL as filename to avoid duplicates.
176
+ * Matches iOS ReactCarouselOverlayHost.writeTempImage().
177
+ */
178
+ private fun writeTempImage(bitmap: Bitmap, remoteUrl: String): String? {
179
+ val hash = remoteUrl.hashCode()
180
+ val fileName = "sk-carousel-${kotlin.math.abs(hash)}.jpg"
181
+ val file = File(context.cacheDir, fileName)
182
+
183
+ // Skip if already written
184
+ if (file.exists()) return "file://${file.absolutePath}"
185
+
186
+ return try {
187
+ FileOutputStream(file).use { out ->
188
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)
189
+ }
190
+ "file://${file.absolutePath}"
191
+ } catch (e: Exception) {
192
+ android.util.Log.w(TAG, "writeTempImage failed for $remoteUrl", e)
193
+ null
194
+ }
195
+ }
196
+
197
+ override fun resetState() {
198
+ val surfaceImpl = surface as? ReactSurfaceImpl ?: return
199
+ surfaceImpl.updateInitProps(Bundle())
200
+ }
201
+
202
+ override fun fadeOutForTransition() {
203
+ ShortKitBridge.shared?.emitCarouselOverlayEvent(
204
+ "onCarouselOverlayFadeOut",
205
+ Arguments.createMap()
206
+ )
207
+ }
208
+
209
+ override fun restoreFromTransition() {
210
+ ShortKitBridge.shared?.emitCarouselOverlayEvent(
211
+ "onCarouselOverlayRestore",
212
+ Arguments.createMap()
213
+ )
214
+ }
215
+
216
+ // ------------------------------------------------------------------
217
+ // Surface Creation
218
+ // ------------------------------------------------------------------
219
+
220
+ override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
221
+ super.onSizeChanged(w, h, oldw, oldh)
222
+ if (w > 0 && h > 0) {
223
+ measureAndLayoutSurfaceView(w, h)
224
+ }
225
+ }
226
+
227
+ override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
228
+ super.onLayout(changed, left, top, right, bottom)
229
+ val w = right - left
230
+ val h = bottom - top
231
+ if (w > 0 && h > 0) {
232
+ measureAndLayoutSurfaceView(w, h)
233
+ } else {
234
+ val parentView = parent as? android.view.View
235
+ val pw = parentView?.width ?: 0
236
+ val ph = parentView?.height ?: 0
237
+ if (pw > 0 && ph > 0) {
238
+ measureAndLayoutSurfaceView(pw, ph)
239
+ }
240
+ }
241
+ }
242
+
243
+ private fun measureAndLayoutSurfaceView(w: Int, h: Int) {
244
+ val sv = surface?.view ?: return
245
+ if (sv.width == w && sv.height == h) return
246
+ val wSpec = android.view.View.MeasureSpec.makeMeasureSpec(w, android.view.View.MeasureSpec.EXACTLY)
247
+ val hSpec = android.view.View.MeasureSpec.makeMeasureSpec(h, android.view.View.MeasureSpec.EXACTLY)
248
+ sv.measure(wSpec, hSpec)
249
+ sv.layout(0, 0, w, h)
250
+ }
251
+
252
+ override fun onAttachedToWindow() {
253
+ super.onAttachedToWindow()
254
+
255
+ val parentView = parent as? android.view.View
256
+ if (parentView != null && parentView.width > 0 && parentView.height > 0 && (width == 0 || height == 0)) {
257
+ val wSpec = android.view.View.MeasureSpec.makeMeasureSpec(parentView.width, android.view.View.MeasureSpec.EXACTLY)
258
+ val hSpec = android.view.View.MeasureSpec.makeMeasureSpec(parentView.height, android.view.View.MeasureSpec.EXACTLY)
259
+ measure(wSpec, hSpec)
260
+ layout(0, 0, parentView.width, parentView.height)
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Create the surface object and attach its view, but do NOT start it yet.
266
+ * Called from prepareSurface() to warm the surface ahead of configure().
267
+ */
268
+ private fun createSurfaceIfNeeded() {
269
+ if (surface != null) return
270
+
271
+ val reactHost = (context.applicationContext as? ReactApplication)?.reactHost
272
+ if (reactHost == null) {
273
+ android.util.Log.e(TAG, "createSurface FAILED: reactHost is null")
274
+ return
275
+ }
276
+ val moduleName = "ShortKitCarouselOverlay_$carouselOverlayName"
277
+
278
+ // Pass pending props as initial props so the JS component has data on first render.
279
+ // If called from prepareSurface() (no item yet), pendingProps is null — the surface
280
+ // is created but NOT started. It will be started in configure() with real data.
281
+ val initialProps = pendingProps
282
+ pendingProps = null
283
+
284
+ val newSurface = reactHost.createSurface(context, moduleName, initialProps)
285
+ surface = newSurface
286
+
287
+ newSurface.view?.let { surfaceView ->
288
+ surfaceView.layoutParams = LayoutParams(
289
+ LayoutParams.MATCH_PARENT,
290
+ LayoutParams.MATCH_PARENT
291
+ )
292
+ addView(surfaceView)
293
+ }
294
+
295
+ // Only start if we have item data — avoids rendering a blank frame.
296
+ if (initialProps != null) {
297
+ newSurface.start()
298
+ }
299
+
300
+ // Use parent dimensions if host hasn't been laid out yet
301
+ val parentView = parent as? android.view.View
302
+ val w = if (width > 0) width else parentView?.width ?: 0
303
+ val h = if (height > 0) height else parentView?.height ?: 0
304
+ if (w > 0 && h > 0) {
305
+ measureAndLayoutSurfaceView(w, h)
306
+ }
307
+ }
308
+
309
+ // ------------------------------------------------------------------
310
+ // Cleanup
311
+ // ------------------------------------------------------------------
312
+
313
+ override fun onDetachedFromWindow() {
314
+ super.onDetachedFromWindow()
315
+ if (surface?.isRunning == true) {
316
+ surface?.stop()
317
+ }
318
+ }
319
+ }
@@ -0,0 +1,40 @@
1
+ package com.shortkit.reactnative
2
+
3
+ import android.content.Context
4
+ import android.widget.FrameLayout
5
+ import com.facebook.react.ReactApplication
6
+ import com.facebook.react.interfaces.fabric.ReactSurface
7
+
8
+ /**
9
+ * A [FrameLayout] that hosts a React Native Fabric surface for the custom
10
+ * loading component. Used as the loading view provider for the ShortKit SDK.
11
+ *
12
+ * Android equivalent of `react_native_sdk/ios/ReactLoadingHost.swift`.
13
+ */
14
+ class ReactLoadingHost(context: Context) : FrameLayout(context) {
15
+
16
+ private var surface: ReactSurface? = null
17
+
18
+ override fun onAttachedToWindow() {
19
+ super.onAttachedToWindow()
20
+ if (surface == null) {
21
+ val reactHost = (context.applicationContext as? ReactApplication)?.reactHost ?: return
22
+ val newSurface = reactHost.createSurface(context, "ShortKitLoading", null)
23
+ newSurface.view?.let { surfaceView ->
24
+ surfaceView.layoutParams = LayoutParams(
25
+ LayoutParams.MATCH_PARENT,
26
+ LayoutParams.MATCH_PARENT
27
+ )
28
+ addView(surfaceView)
29
+ }
30
+ newSurface.start()
31
+ surface = newSurface
32
+ }
33
+ }
34
+
35
+ override fun onDetachedFromWindow() {
36
+ super.onDetachedFromWindow()
37
+ surface?.stop()
38
+ surface = null
39
+ }
40
+ }