@shortkitsdk/react-native 0.2.14 → 0.2.15
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/src/main/java/com/shortkit/reactnative/ShortKitBridge.kt +34 -2
- package/android/src/main/java/com/shortkit/reactnative/ShortKitModule.kt +5 -5
- package/ios/ReactCarouselOverlayHost.swift +30 -18
- package/ios/ReactOverlayHost.swift +65 -67
- package/ios/ShortKitBridge.swift +80 -20
- package/ios/ShortKitModule.mm +13 -4
- package/ios/ShortKitSDK.xcframework/Info.plist +2 -1
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +1 -0
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Info.plist +5 -1
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.abi.json +672 -97
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +15 -5
- 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 +15 -5
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/_CodeSignature/CodeResources +11 -11
- package/ios/ShortKitSDK.xcframework/{ios-arm64-simulator → ios-arm64_x86_64-simulator}/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +1 -0
- package/ios/{ShortKitSDK.xcframework.bak2/ios-arm64-simulator → ShortKitSDK.xcframework/ios-arm64_x86_64-simulator}/ShortKitSDK.framework/Info.plist +5 -1
- package/ios/{ShortKitSDK.xcframework.bak2/ios-arm64-simulator → ShortKitSDK.xcframework/ios-arm64_x86_64-simulator}/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +2488 -281
- package/ios/{ShortKitSDK.xcframework.bak2/ios-arm64-simulator → ShortKitSDK.xcframework/ios-arm64_x86_64-simulator}/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +65 -5
- package/ios/{ShortKitSDK.xcframework.bak2/ios-arm64-simulator → ShortKitSDK.xcframework/ios-arm64_x86_64-simulator}/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/{ShortKitSDK.xcframework.bak2/ios-arm64-simulator → ShortKitSDK.xcframework/ios-arm64_x86_64-simulator}/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +65 -5
- package/ios/{ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.abi.json → ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/x86_64-apple-ios-simulator.abi.json} +8233 -3592
- package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +925 -0
- package/ios/{ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc → 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 +925 -0
- 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 +212 -0
- package/ios/{ShortKitSDK.xcframework.bak2 → ShortKitSDK.xcframework.dev-backup}/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.abi.json +1838 -206
- package/ios/{ShortKitSDK.xcframework.bak2 → ShortKitSDK.xcframework.dev-backup}/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +51 -1
- package/ios/{ShortKitSDK.xcframework.bak2 → ShortKitSDK.xcframework.dev-backup}/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
- package/ios/{ShortKitSDK.xcframework.bak2 → ShortKitSDK.xcframework.dev-backup}/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftinterface +51 -1
- package/ios/ShortKitSDK.xcframework.dev-backup/ios-arm64/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/ShortKitSDK.xcframework.dev-backup/ios-arm64/ShortKitSDK.framework/_CodeSignature/CodeResources +168 -0
- package/ios/{ShortKitSDK.xcframework → ShortKitSDK.xcframework.dev-backup}/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +6 -6
- package/ios/ShortKitSDK.xcframework.dev-backup/ios-arm64-simulator/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/{ShortKitSDK.xcframework → ShortKitSDK.xcframework.dev-backup}/ios-arm64-simulator/ShortKitSDK.framework/_CodeSignature/CodeResources +2 -2
- package/package.json +1 -1
- package/src/ShortKitContext.ts +11 -0
- package/src/ShortKitFeed.tsx +20 -9
- package/src/ShortKitOverlaySurface.tsx +20 -6
- package/src/ShortKitProvider.tsx +4 -2
- package/src/ShortKitWidget.tsx +3 -3
- package/src/index.ts +1 -0
- package/src/specs/NativeShortKitModule.ts +5 -2
- package/src/types.ts +9 -2
- package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Info.plist +0 -16
- package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/module.modulemap +0 -4
- package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +0 -418
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.abi.json +0 -28917
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +0 -824
- 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 +0 -824
- 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 +0 -418
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +0 -824
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +0 -824
- package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/ShortKitSDK.xcframework.bak2/Info.plist +0 -43
- package/ios/ShortKitSDK.xcframework.bak2/ios-arm64/ShortKitSDK.framework/Info.plist +0 -16
- package/ios/ShortKitSDK.xcframework.bak2/ios-arm64/ShortKitSDK.framework/Modules/module.modulemap +0 -4
- package/ios/ShortKitSDK.xcframework.bak2/ios-arm64/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/ShortKitSDK.xcframework.bak2/ios-arm64-simulator/ShortKitSDK.framework/ShortKitSDK +0 -0
- package/ios/{ShortKitSDK.xcframework.bak2/ios-arm64-simulator → ShortKitSDK.xcframework/ios-arm64_x86_64-simulator}/ShortKitSDK.framework/Modules/module.modulemap +0 -0
- package/ios/{ShortKitSDK.xcframework.bak → ShortKitSDK.xcframework.dev-backup}/Info.plist +4 -4
- /package/ios/{ShortKitSDK.xcframework.bak2 → ShortKitSDK.xcframework.dev-backup}/ios-arm64/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +0 -0
- /package/ios/{ShortKitSDK.xcframework.bak → ShortKitSDK.xcframework.dev-backup}/ios-arm64/ShortKitSDK.framework/Info.plist +0 -0
- /package/ios/{ShortKitSDK.xcframework.bak → ShortKitSDK.xcframework.dev-backup}/ios-arm64/ShortKitSDK.framework/Modules/module.modulemap +0 -0
- /package/ios/{ShortKitSDK.xcframework.bak2 → ShortKitSDK.xcframework.dev-backup}/ios-arm64-simulator/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +0 -0
- /package/ios/{ShortKitSDK.xcframework.bak → ShortKitSDK.xcframework.dev-backup}/ios-arm64-simulator/ShortKitSDK.framework/Info.plist +0 -0
- /package/ios/{ShortKitSDK.xcframework → ShortKitSDK.xcframework.dev-backup}/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +0 -0
- /package/ios/{ShortKitSDK.xcframework → ShortKitSDK.xcframework.dev-backup}/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
- /package/ios/{ShortKitSDK.xcframework → ShortKitSDK.xcframework.dev-backup}/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +0 -0
- /package/ios/{ShortKitSDK.xcframework.bak → ShortKitSDK.xcframework.dev-backup}/ios-arm64-simulator/ShortKitSDK.framework/Modules/module.modulemap +0 -0
|
@@ -28,6 +28,7 @@ import com.shortkit.sdk.config.FeedSource
|
|
|
28
28
|
import com.shortkit.sdk.config.ScrollAxis
|
|
29
29
|
import com.shortkit.sdk.config.SurveyOverlayMode
|
|
30
30
|
import com.shortkit.sdk.config.VideoCarouselOverlayMode
|
|
31
|
+
import com.shortkit.sdk.feed.ShortKitRefreshState
|
|
31
32
|
import com.shortkit.sdk.config.VideoOverlayMode
|
|
32
33
|
import com.shortkit.sdk.feed.FeedPreload
|
|
33
34
|
import com.shortkit.sdk.feed.ShortKitFeedFragment
|
|
@@ -162,6 +163,8 @@ class ShortKitBridge(
|
|
|
162
163
|
val scrollAxisStr = obj.optString("scrollAxis", "vertical")
|
|
163
164
|
val scrollAxis = if (scrollAxisStr == "horizontal") ScrollAxis.Horizontal else ScrollAxis.Vertical
|
|
164
165
|
|
|
166
|
+
val pullToRefreshEnabled = obj.optBoolean("pullToRefreshEnabled", true)
|
|
167
|
+
|
|
165
168
|
FeedConfig(
|
|
166
169
|
feedHeight = feedHeight,
|
|
167
170
|
videoOverlay = videoOverlay,
|
|
@@ -174,6 +177,7 @@ class ShortKitBridge(
|
|
|
174
177
|
feedSource = feedSource,
|
|
175
178
|
filter = filter,
|
|
176
179
|
scrollAxis = scrollAxis,
|
|
180
|
+
pullToRefreshEnabled = pullToRefreshEnabled,
|
|
177
181
|
)
|
|
178
182
|
} catch (e: Exception) {
|
|
179
183
|
android.util.Log.e("SK:Bridge", "parseFeedConfig: EXCEPTION parsing config, returning default. json=${json.take(300)}", e)
|
|
@@ -488,6 +492,7 @@ class ShortKitBridge(
|
|
|
488
492
|
private val feedRegistry = mutableMapOf<String, WeakReference<ShortKitFeedFragment>>()
|
|
489
493
|
private val pendingOps = mutableMapOf<String, MutableList<(ShortKitFeedFragment) -> Unit>>()
|
|
490
494
|
private val pendingOpsLock = Any()
|
|
495
|
+
private var lastProgressEmitTime = 0L
|
|
491
496
|
|
|
492
497
|
/** Expose the underlying SDK for the Fabric feed view manager. */
|
|
493
498
|
val sdk: ShortKit? get() = shortKit
|
|
@@ -528,8 +533,35 @@ class ShortKitBridge(
|
|
|
528
533
|
emitEventOnMain("onContentTapped", params)
|
|
529
534
|
}
|
|
530
535
|
|
|
531
|
-
override fun
|
|
532
|
-
|
|
536
|
+
override fun onRefreshStateChanged(state: ShortKitRefreshState) {
|
|
537
|
+
// Throttle pulling events to max 1 per 16ms to avoid bridge saturation
|
|
538
|
+
if (state is ShortKitRefreshState.Pulling) {
|
|
539
|
+
val now = android.os.SystemClock.uptimeMillis()
|
|
540
|
+
if (now - lastProgressEmitTime < 16L) return
|
|
541
|
+
lastProgressEmitTime = now
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
val params = Arguments.createMap().apply {
|
|
545
|
+
when (state) {
|
|
546
|
+
is ShortKitRefreshState.Idle -> {
|
|
547
|
+
putString("status", "idle")
|
|
548
|
+
putDouble("progress", 0.0)
|
|
549
|
+
}
|
|
550
|
+
is ShortKitRefreshState.Pulling -> {
|
|
551
|
+
putString("status", "pulling")
|
|
552
|
+
putDouble("progress", state.progress.toDouble())
|
|
553
|
+
}
|
|
554
|
+
is ShortKitRefreshState.Triggered -> {
|
|
555
|
+
putString("status", "triggered")
|
|
556
|
+
putDouble("progress", 0.0)
|
|
557
|
+
}
|
|
558
|
+
is ShortKitRefreshState.Refreshing -> {
|
|
559
|
+
putString("status", "refreshing")
|
|
560
|
+
putDouble("progress", 0.0)
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
emitEventOnMain("onRefreshStateChanged", params)
|
|
533
565
|
}
|
|
534
566
|
|
|
535
567
|
override fun onFeedContentFetched(items: List<ContentItem>) {
|
|
@@ -207,11 +207,11 @@ class ShortKitModule(reactContext: ReactApplicationContext) :
|
|
|
207
207
|
@ReactMethod
|
|
208
208
|
override fun preloadFeed(configJSON: String, itemsJSON: String?, promise: Promise) {
|
|
209
209
|
val b = bridge
|
|
210
|
-
if (b
|
|
211
|
-
promise.resolve(
|
|
212
|
-
|
|
210
|
+
if (b != null) {
|
|
211
|
+
b.preloadFeed(configJSON, itemsJSON) { result -> promise.resolve(result) }
|
|
212
|
+
} else {
|
|
213
|
+
bufferOp { bridge?.preloadFeed(configJSON, itemsJSON) { result -> promise.resolve(result) } }
|
|
213
214
|
}
|
|
214
|
-
b.preloadFeed(configJSON, itemsJSON) { result -> promise.resolve(result) }
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
// -----------------------------------------------------------------
|
|
@@ -261,7 +261,7 @@ class ShortKitModule(reactContext: ReactApplicationContext) :
|
|
|
261
261
|
"onSurveyResponse" -> emitOnSurveyResponse(params)
|
|
262
262
|
"onContentTapped" -> emitOnContentTapped(params)
|
|
263
263
|
"onDismiss" -> emitOnDismiss(params)
|
|
264
|
-
"
|
|
264
|
+
"onRefreshStateChanged" -> emitOnRefreshStateChanged(params)
|
|
265
265
|
"onDidFetchContentItems" -> emitOnDidFetchContentItems(params)
|
|
266
266
|
"onFeedReady" -> emitOnFeedReady(params)
|
|
267
267
|
"onOverlayActiveChanged" -> emitOnOverlayActiveChanged(params)
|
|
@@ -37,6 +37,9 @@ import ShortKitSDK
|
|
|
37
37
|
private var isActive = false
|
|
38
38
|
private var activeImageIndex = 0
|
|
39
39
|
|
|
40
|
+
/// Serial queue for JPEG encoding + temp file writes (off main thread).
|
|
41
|
+
private static let imageWriteQueue = DispatchQueue(label: "com.shortkit.carousel-image-write", qos: .userInitiated)
|
|
42
|
+
|
|
40
43
|
/// Unique identifier for this overlay instance, used for event routing.
|
|
41
44
|
let surfaceId = UUID().uuidString
|
|
42
45
|
|
|
@@ -63,15 +66,28 @@ import ShortKitSDK
|
|
|
63
66
|
activeImageIndex = 0
|
|
64
67
|
createSurfaceIfNeeded()
|
|
65
68
|
|
|
66
|
-
// Replace remote URLs with local file URLs for any natively-cached images
|
|
69
|
+
// Replace remote URLs with local file URLs for any natively-cached images
|
|
70
|
+
// that already have a temp file on disk (fast path: FileManager.fileExists).
|
|
71
|
+
// If the native cache has the image but no temp file exists yet, use the
|
|
72
|
+
// remote URL immediately and schedule a background write so the file://
|
|
73
|
+
// URL is available on the next configure() for this image.
|
|
67
74
|
var modifiedItem = item
|
|
68
75
|
if let cachedImage {
|
|
69
76
|
var localImages: [CarouselImage] = []
|
|
70
77
|
for image in item.images {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
78
|
+
let tempURL = Self.tempFileURL(for: image.url)
|
|
79
|
+
if FileManager.default.fileExists(atPath: tempURL.path) {
|
|
80
|
+
// Fast path: temp file already written — use file:// URL
|
|
81
|
+
localImages.append(CarouselImage(url: tempURL.absoluteString, alt: image.alt))
|
|
82
|
+
} else if let uiImage = cachedImage(image.url) {
|
|
83
|
+
// Native cache hit but no temp file yet — use remote URL now,
|
|
84
|
+
// write temp file in background for next time.
|
|
85
|
+
localImages.append(image)
|
|
86
|
+
Self.imageWriteQueue.async {
|
|
87
|
+
Self.writeTempImage(uiImage, to: tempURL)
|
|
88
|
+
}
|
|
74
89
|
} else {
|
|
90
|
+
// Not cached — use remote URL
|
|
75
91
|
localImages.append(image)
|
|
76
92
|
}
|
|
77
93
|
}
|
|
@@ -124,23 +140,19 @@ import ShortKitSDK
|
|
|
124
140
|
])
|
|
125
141
|
}
|
|
126
142
|
|
|
127
|
-
///
|
|
128
|
-
private func
|
|
143
|
+
/// Deterministic temp file URL for a given remote image URL.
|
|
144
|
+
private static func tempFileURL(for remoteURL: String) -> URL {
|
|
129
145
|
let hash = remoteURL.hash
|
|
130
146
|
let fileName = "sk-carousel-\(abs(hash)).jpg"
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if FileManager.default.fileExists(atPath: fileURL.path) {
|
|
134
|
-
return fileURL.absoluteString
|
|
135
|
-
}
|
|
147
|
+
return URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(fileName)
|
|
148
|
+
}
|
|
136
149
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
150
|
+
/// JPEG-encode a UIImage and write to the given file URL.
|
|
151
|
+
/// Safe to call from any queue — no UIKit main-thread requirements.
|
|
152
|
+
private static func writeTempImage(_ image: UIImage, to fileURL: URL) {
|
|
153
|
+
guard !FileManager.default.fileExists(atPath: fileURL.path),
|
|
154
|
+
let data = image.jpegData(compressionQuality: 0.9) else { return }
|
|
155
|
+
try? data.write(to: fileURL, options: .atomic)
|
|
144
156
|
}
|
|
145
157
|
|
|
146
158
|
public func resetState() {
|
|
@@ -46,7 +46,9 @@ import ShortKitSDK
|
|
|
46
46
|
private var cachedPlaybackRate: Double = 1.0
|
|
47
47
|
private var cachedCaptionsEnabled: Bool = false
|
|
48
48
|
private var cachedActiveCue: [String: Any]? = nil
|
|
49
|
-
private var
|
|
49
|
+
private var cachedActiveCueJson: String? = nil // pre-serialized for bridge
|
|
50
|
+
private var cachedFeedScrollPhase: String? = nil // already a JSON string
|
|
51
|
+
private var isDragging: Bool = false // true while scroll phase is .dragging
|
|
50
52
|
|
|
51
53
|
// Time coalescing
|
|
52
54
|
private var cachedTime: (current: Double, duration: Double, buffered: Double) = (0, 0, 0)
|
|
@@ -137,7 +139,9 @@ import ShortKitSDK
|
|
|
137
139
|
cachedTime = (0, 0, 0)
|
|
138
140
|
cachedPlayerState = "idle"
|
|
139
141
|
cachedActiveCue = nil
|
|
142
|
+
cachedActiveCueJson = nil
|
|
140
143
|
cachedFeedScrollPhase = nil
|
|
144
|
+
isDragging = false
|
|
141
145
|
|
|
142
146
|
createSurfaceIfNeeded()
|
|
143
147
|
|
|
@@ -165,30 +169,21 @@ import ShortKitSDK
|
|
|
165
169
|
}
|
|
166
170
|
}
|
|
167
171
|
|
|
168
|
-
/// Emit all cached state as
|
|
169
|
-
/// (deferred) and
|
|
172
|
+
/// Emit all cached state as a single batched event. Called from
|
|
173
|
+
/// activatePlayback() (deferred) and on drag→settled transitions.
|
|
174
|
+
/// Uses pre-serialized JSON strings to avoid JSONSerialization on the
|
|
175
|
+
/// main thread during the swipe-settle critical path.
|
|
170
176
|
private func emitFullState() {
|
|
171
|
-
|
|
177
|
+
bridge?.emit("onOverlayFullState", body: [
|
|
172
178
|
"surfaceId": surfaceId,
|
|
173
179
|
"isActive": true,
|
|
174
180
|
"playerState": cachedPlayerState,
|
|
175
181
|
"isMuted": cachedIsMuted,
|
|
176
182
|
"playbackRate": cachedPlaybackRate,
|
|
177
183
|
"captionsEnabled": cachedCaptionsEnabled,
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
let cueJson = String(data: cueData, encoding: .utf8) {
|
|
182
|
-
body["activeCue"] = cueJson
|
|
183
|
-
} else {
|
|
184
|
-
body["activeCue"] = NSNull()
|
|
185
|
-
}
|
|
186
|
-
if let scrollPhase = cachedFeedScrollPhase {
|
|
187
|
-
body["feedScrollPhase"] = scrollPhase
|
|
188
|
-
} else {
|
|
189
|
-
body["feedScrollPhase"] = NSNull()
|
|
190
|
-
}
|
|
191
|
-
bridge?.emit("onOverlayFullState", body: body)
|
|
184
|
+
"activeCue": cachedActiveCueJson ?? NSNull(),
|
|
185
|
+
"feedScrollPhase": cachedFeedScrollPhase ?? NSNull(),
|
|
186
|
+
])
|
|
192
187
|
}
|
|
193
188
|
|
|
194
189
|
// MARK: - Surface Creation
|
|
@@ -255,17 +250,21 @@ import ShortKitSDK
|
|
|
255
250
|
// MARK: - Player Subscriptions
|
|
256
251
|
|
|
257
252
|
private func subscribeToPlayer(_ player: ShortKitPlayer) {
|
|
253
|
+
// Player state, muted, playbackRate, captionsEnabled, and activeCue
|
|
254
|
+
// are suppressed during .dragging to avoid unnecessary bridge traffic
|
|
255
|
+
// for an overlay that is scrolling off screen. emitFullState() re-syncs
|
|
256
|
+
// all cached values when the scroll settles (or on cancelled swipe).
|
|
257
|
+
|
|
258
258
|
player.playerState
|
|
259
259
|
.receive(on: DispatchQueue.main)
|
|
260
260
|
.sink { [weak self] state in
|
|
261
261
|
guard let self else { return }
|
|
262
262
|
self.cachedPlayerState = Self.playerStateString(state)
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
}
|
|
263
|
+
guard self.isActive, !self.isDragging else { return }
|
|
264
|
+
self.bridge?.emit("onOverlayPlayerStateChanged", body: [
|
|
265
|
+
"surfaceId": self.surfaceId,
|
|
266
|
+
"playerState": self.cachedPlayerState
|
|
267
|
+
])
|
|
269
268
|
}
|
|
270
269
|
.store(in: &cancellables)
|
|
271
270
|
|
|
@@ -274,12 +273,11 @@ import ShortKitSDK
|
|
|
274
273
|
.sink { [weak self] muted in
|
|
275
274
|
guard let self else { return }
|
|
276
275
|
self.cachedIsMuted = muted
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
}
|
|
276
|
+
guard self.isActive, !self.isDragging else { return }
|
|
277
|
+
self.bridge?.emit("onOverlayMutedChanged", body: [
|
|
278
|
+
"surfaceId": self.surfaceId,
|
|
279
|
+
"isMuted": self.cachedIsMuted
|
|
280
|
+
])
|
|
283
281
|
}
|
|
284
282
|
.store(in: &cancellables)
|
|
285
283
|
|
|
@@ -288,12 +286,11 @@ import ShortKitSDK
|
|
|
288
286
|
.sink { [weak self] rate in
|
|
289
287
|
guard let self else { return }
|
|
290
288
|
self.cachedPlaybackRate = Double(rate)
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
289
|
+
guard self.isActive, !self.isDragging else { return }
|
|
290
|
+
self.bridge?.emit("onOverlayPlaybackRateChanged", body: [
|
|
291
|
+
"surfaceId": self.surfaceId,
|
|
292
|
+
"playbackRate": self.cachedPlaybackRate
|
|
293
|
+
])
|
|
297
294
|
}
|
|
298
295
|
.store(in: &cancellables)
|
|
299
296
|
|
|
@@ -302,12 +299,11 @@ import ShortKitSDK
|
|
|
302
299
|
.sink { [weak self] enabled in
|
|
303
300
|
guard let self else { return }
|
|
304
301
|
self.cachedCaptionsEnabled = enabled
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}
|
|
302
|
+
guard self.isActive, !self.isDragging else { return }
|
|
303
|
+
self.bridge?.emit("onOverlayCaptionsEnabledChanged", body: [
|
|
304
|
+
"surfaceId": self.surfaceId,
|
|
305
|
+
"captionsEnabled": self.cachedCaptionsEnabled
|
|
306
|
+
])
|
|
311
307
|
}
|
|
312
308
|
.store(in: &cancellables)
|
|
313
309
|
|
|
@@ -315,30 +311,26 @@ import ShortKitSDK
|
|
|
315
311
|
.receive(on: DispatchQueue.main)
|
|
316
312
|
.sink { [weak self] cue in
|
|
317
313
|
guard let self else { return }
|
|
314
|
+
// Pre-serialize once; reused by emitFullState() and individual emission.
|
|
318
315
|
if let cue {
|
|
319
316
|
self.cachedActiveCue = [
|
|
320
317
|
"text": cue.text,
|
|
321
318
|
"startTime": cue.startTime,
|
|
322
319
|
"endTime": cue.endTime,
|
|
323
320
|
]
|
|
324
|
-
|
|
325
|
-
self.cachedActiveCue = nil
|
|
326
|
-
}
|
|
327
|
-
if self.isActive {
|
|
328
|
-
if let cached = self.cachedActiveCue,
|
|
329
|
-
let data = try? JSONSerialization.data(withJSONObject: cached),
|
|
321
|
+
if let data = try? JSONSerialization.data(withJSONObject: self.cachedActiveCue!),
|
|
330
322
|
let json = String(data: data, encoding: .utf8) {
|
|
331
|
-
self.
|
|
332
|
-
"surfaceId": self.surfaceId,
|
|
333
|
-
"activeCue": json
|
|
334
|
-
])
|
|
335
|
-
} else {
|
|
336
|
-
self.bridge?.emit("onOverlayActiveCueChanged", body: [
|
|
337
|
-
"surfaceId": self.surfaceId,
|
|
338
|
-
"activeCue": NSNull()
|
|
339
|
-
])
|
|
323
|
+
self.cachedActiveCueJson = json
|
|
340
324
|
}
|
|
325
|
+
} else {
|
|
326
|
+
self.cachedActiveCue = nil
|
|
327
|
+
self.cachedActiveCueJson = nil
|
|
341
328
|
}
|
|
329
|
+
guard self.isActive, !self.isDragging else { return }
|
|
330
|
+
self.bridge?.emit("onOverlayActiveCueChanged", body: [
|
|
331
|
+
"surfaceId": self.surfaceId,
|
|
332
|
+
"activeCue": self.cachedActiveCueJson ?? NSNull()
|
|
333
|
+
])
|
|
342
334
|
}
|
|
343
335
|
.store(in: &cancellables)
|
|
344
336
|
|
|
@@ -346,18 +338,26 @@ import ShortKitSDK
|
|
|
346
338
|
.receive(on: DispatchQueue.main)
|
|
347
339
|
.sink { [weak self] phase in
|
|
348
340
|
guard let self else { return }
|
|
341
|
+
// Pre-serialize once; reused by emitFullState() and individual emission.
|
|
349
342
|
switch phase {
|
|
350
343
|
case .dragging(let from):
|
|
351
|
-
|
|
352
|
-
if let data = try? JSONSerialization.data(withJSONObject:
|
|
344
|
+
self.isDragging = true
|
|
345
|
+
if let data = try? JSONSerialization.data(withJSONObject: ["phase": "dragging", "fromId": from]),
|
|
353
346
|
let json = String(data: data, encoding: .utf8) {
|
|
354
347
|
self.cachedFeedScrollPhase = json
|
|
355
348
|
}
|
|
356
349
|
case .settled:
|
|
357
|
-
let
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
350
|
+
let wasDragging = self.isDragging
|
|
351
|
+
self.isDragging = false
|
|
352
|
+
self.cachedFeedScrollPhase = "{\"phase\":\"settled\"}"
|
|
353
|
+
|
|
354
|
+
// Re-sync all state that was suppressed during the drag.
|
|
355
|
+
// Handles both normal swipes (new item's activatePlayback
|
|
356
|
+
// will also fire) and cancelled swipes (same item, no
|
|
357
|
+
// activatePlayback — this is the only re-sync path).
|
|
358
|
+
if wasDragging, self.isActive {
|
|
359
|
+
self.emitFullState()
|
|
360
|
+
return // fullState includes feedScrollPhase
|
|
361
361
|
}
|
|
362
362
|
}
|
|
363
363
|
if self.isActive {
|
|
@@ -372,7 +372,7 @@ import ShortKitSDK
|
|
|
372
372
|
player.time
|
|
373
373
|
.receive(on: DispatchQueue.main)
|
|
374
374
|
.sink { [weak self] time in
|
|
375
|
-
guard let self, self.isActive else { return }
|
|
375
|
+
guard let self, self.isActive, !self.isDragging else { return }
|
|
376
376
|
self.cachedTime = (time.current, time.duration, time.buffered)
|
|
377
377
|
self.timeDirty = true
|
|
378
378
|
}
|
|
@@ -424,9 +424,7 @@ import ShortKitSDK
|
|
|
424
424
|
props["playbackRate"] = cachedPlaybackRate
|
|
425
425
|
props["captionsEnabled"] = cachedCaptionsEnabled
|
|
426
426
|
|
|
427
|
-
if let
|
|
428
|
-
let cueData = try? JSONSerialization.data(withJSONObject: cue),
|
|
429
|
-
let cueJson = String(data: cueData, encoding: .utf8) {
|
|
427
|
+
if let cueJson = cachedActiveCueJson {
|
|
430
428
|
props["activeCue"] = cueJson
|
|
431
429
|
}
|
|
432
430
|
|
package/ios/ShortKitBridge.swift
CHANGED
|
@@ -17,6 +17,15 @@ import ShortKitSDK
|
|
|
17
17
|
private var shortKit: ShortKit?
|
|
18
18
|
private var cancellables = Set<AnyCancellable>()
|
|
19
19
|
private weak var delegate: ShortKitBridgeDelegateProtocol?
|
|
20
|
+
private var lastProgressEmitTime: CFTimeInterval = 0
|
|
21
|
+
|
|
22
|
+
// Time update coalescing (250ms, matching overlay timer interval)
|
|
23
|
+
private var cachedTime: (current: Double, duration: Double, buffered: Double) = (0, 0, 0)
|
|
24
|
+
private var timeCoalesceTimer: Timer?
|
|
25
|
+
private var timeDirty = false
|
|
26
|
+
|
|
27
|
+
// Scroll phase coalescing — only emit .dragging on first touch
|
|
28
|
+
private var lastEmittedScrollPhase: String = "settled"
|
|
20
29
|
|
|
21
30
|
/// Surface presenter for creating RCTFabricSurface instances in overlay hosts.
|
|
22
31
|
/// Set from ShortKitModule.mm via setSurfacePresenter: (called by RCTInstance).
|
|
@@ -116,12 +125,15 @@ import ShortKitSDK
|
|
|
116
125
|
}
|
|
117
126
|
|
|
118
127
|
subscribeToPublishers(sdk.player)
|
|
128
|
+
startTimeCoalescing()
|
|
119
129
|
sdk.delegate = self
|
|
120
130
|
}
|
|
121
131
|
|
|
122
132
|
// MARK: - Teardown
|
|
123
133
|
|
|
124
134
|
@objc public func teardown() {
|
|
135
|
+
timeCoalesceTimer?.invalidate()
|
|
136
|
+
timeCoalesceTimer = nil
|
|
125
137
|
cancellables.removeAll()
|
|
126
138
|
preloadHandles.removeAll()
|
|
127
139
|
feedRegistry.removeAll()
|
|
@@ -376,24 +388,27 @@ import ShortKitSDK
|
|
|
376
388
|
}
|
|
377
389
|
.store(in: &cancellables)
|
|
378
390
|
|
|
379
|
-
// Current item
|
|
391
|
+
// Current item — deferred to next run-loop tick so emission doesn't
|
|
392
|
+
// contend with Core Animation's commit phase during swipe settle.
|
|
380
393
|
player.currentItem
|
|
381
394
|
.receive(on: DispatchQueue.main)
|
|
382
395
|
.sink { [weak self] item in
|
|
383
396
|
guard let item else { return }
|
|
384
|
-
|
|
397
|
+
let body = Self.contentItemDict(item)
|
|
398
|
+
DispatchQueue.main.async {
|
|
399
|
+
self?.emit("onCurrentItemChanged", body: body)
|
|
400
|
+
}
|
|
385
401
|
}
|
|
386
402
|
.store(in: &cancellables)
|
|
387
403
|
|
|
388
|
-
// Time updates
|
|
404
|
+
// Time updates — coalesced at 250ms (4 events/sec) to avoid flooding
|
|
405
|
+
// the JS bridge. Matches the overlay timer interval in ReactOverlayHost.
|
|
389
406
|
player.time
|
|
390
407
|
.receive(on: DispatchQueue.main)
|
|
391
408
|
.sink { [weak self] time in
|
|
392
|
-
self
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
"buffered": time.buffered
|
|
396
|
-
])
|
|
409
|
+
guard let self else { return }
|
|
410
|
+
self.cachedTime = (time.current, time.duration, time.buffered)
|
|
411
|
+
self.timeDirty = true
|
|
397
412
|
}
|
|
398
413
|
.store(in: &cancellables)
|
|
399
414
|
|
|
@@ -458,7 +473,8 @@ import ShortKitSDK
|
|
|
458
473
|
}
|
|
459
474
|
.store(in: &cancellables)
|
|
460
475
|
|
|
461
|
-
// Feed transition
|
|
476
|
+
// Feed transition — deferred to next run-loop tick so emission doesn't
|
|
477
|
+
// contend with Core Animation's commit phase during swipe settle.
|
|
462
478
|
player.feedTransition
|
|
463
479
|
.receive(on: DispatchQueue.main)
|
|
464
480
|
.sink { [weak self] event in
|
|
@@ -473,24 +489,35 @@ import ShortKitSDK
|
|
|
473
489
|
if let to = event.to {
|
|
474
490
|
body["toItem"] = self.serializeContentItemToJSON(to)
|
|
475
491
|
}
|
|
476
|
-
|
|
492
|
+
DispatchQueue.main.async { [weak self] in
|
|
493
|
+
self?.emit("onFeedTransition", body: body)
|
|
494
|
+
}
|
|
477
495
|
}
|
|
478
496
|
.store(in: &cancellables)
|
|
479
497
|
|
|
480
|
-
// Feed scroll phase
|
|
498
|
+
// Feed scroll phase — coalesced: only emit .dragging on first touch
|
|
499
|
+
// (transition from settled), drop intermediate .dragging events. Always
|
|
500
|
+
// emit .settled. Deferred to next run-loop tick to avoid contending with
|
|
501
|
+
// Core Animation's commit phase.
|
|
481
502
|
player.feedScrollPhase
|
|
482
503
|
.receive(on: DispatchQueue.main)
|
|
483
504
|
.sink { [weak self] phase in
|
|
505
|
+
guard let self else { return }
|
|
484
506
|
switch phase {
|
|
485
507
|
case .dragging(let fromId):
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
]
|
|
508
|
+
// Only emit on transition from settled → dragging
|
|
509
|
+
guard self.lastEmittedScrollPhase != "dragging" else { return }
|
|
510
|
+
self.lastEmittedScrollPhase = "dragging"
|
|
511
|
+
let body: [String: Any] = ["phase": "dragging", "fromId": fromId]
|
|
512
|
+
DispatchQueue.main.async { [weak self] in
|
|
513
|
+
self?.emit("onFeedScrollPhase", body: body)
|
|
514
|
+
}
|
|
490
515
|
case .settled:
|
|
491
|
-
self
|
|
492
|
-
|
|
493
|
-
]
|
|
516
|
+
self.lastEmittedScrollPhase = "settled"
|
|
517
|
+
let body: [String: Any] = ["phase": "settled"]
|
|
518
|
+
DispatchQueue.main.async { [weak self] in
|
|
519
|
+
self?.emit("onFeedScrollPhase", body: body)
|
|
520
|
+
}
|
|
494
521
|
}
|
|
495
522
|
}
|
|
496
523
|
.store(in: &cancellables)
|
|
@@ -536,6 +563,21 @@ import ShortKitSDK
|
|
|
536
563
|
}
|
|
537
564
|
}
|
|
538
565
|
|
|
566
|
+
// MARK: - Time Coalescing
|
|
567
|
+
|
|
568
|
+
private func startTimeCoalescing() {
|
|
569
|
+
timeCoalesceTimer?.invalidate()
|
|
570
|
+
timeCoalesceTimer = Timer.scheduledTimer(withTimeInterval: 0.25, repeats: true) { [weak self] _ in
|
|
571
|
+
guard let self, self.timeDirty else { return }
|
|
572
|
+
self.timeDirty = false
|
|
573
|
+
self.emit("onTimeUpdate", body: [
|
|
574
|
+
"current": self.cachedTime.current,
|
|
575
|
+
"duration": self.cachedTime.duration,
|
|
576
|
+
"buffered": self.cachedTime.buffered
|
|
577
|
+
])
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
539
581
|
// MARK: - Content Item Serialization
|
|
540
582
|
|
|
541
583
|
/// Serialize a ContentItem to a JSON string for bridge transport.
|
|
@@ -658,6 +700,8 @@ import ShortKitSDK
|
|
|
658
700
|
let scrollAxisStr = obj["scrollAxis"] as? String ?? "vertical"
|
|
659
701
|
let scrollAxis: ScrollAxis = scrollAxisStr == "horizontal" ? .horizontal : .vertical
|
|
660
702
|
|
|
703
|
+
let pullToRefreshEnabled = obj["pullToRefreshEnabled"] as? Bool ?? true
|
|
704
|
+
|
|
661
705
|
return FeedConfig(
|
|
662
706
|
feedHeight: feedHeight,
|
|
663
707
|
scrollAxis: scrollAxis,
|
|
@@ -669,6 +713,7 @@ import ShortKitSDK
|
|
|
669
713
|
muteOnStart: muteOnStart,
|
|
670
714
|
autoplay: autoplay,
|
|
671
715
|
feedSource: feedSource,
|
|
716
|
+
pullToRefreshEnabled: pullToRefreshEnabled,
|
|
672
717
|
filter: filter
|
|
673
718
|
)
|
|
674
719
|
}
|
|
@@ -870,8 +915,23 @@ extension ShortKitBridge: ShortKitDelegate {
|
|
|
870
915
|
])
|
|
871
916
|
}
|
|
872
917
|
|
|
873
|
-
public func
|
|
874
|
-
|
|
918
|
+
public func shortKit(_ shortKit: ShortKit, didChangeRefreshState state: ShortKitRefreshState) {
|
|
919
|
+
let body: [String: Any]
|
|
920
|
+
switch state {
|
|
921
|
+
case .idle:
|
|
922
|
+
body = ["status": "idle", "progress": 0.0]
|
|
923
|
+
case .pulling(let progress):
|
|
924
|
+
// Throttle pulling events to max 1 per 16ms to avoid bridge saturation
|
|
925
|
+
let now = CACurrentMediaTime()
|
|
926
|
+
guard now - lastProgressEmitTime >= 0.016 else { return }
|
|
927
|
+
lastProgressEmitTime = now
|
|
928
|
+
body = ["status": "pulling", "progress": progress]
|
|
929
|
+
case .triggered:
|
|
930
|
+
body = ["status": "triggered", "progress": 0.0]
|
|
931
|
+
case .refreshing:
|
|
932
|
+
body = ["status": "refreshing", "progress": 0.0]
|
|
933
|
+
}
|
|
934
|
+
emitOnMain("onRefreshStateChanged", body: body)
|
|
875
935
|
}
|
|
876
936
|
|
|
877
937
|
public func shortKit(_ shortKit: ShortKit, didFetchContentItems items: [ContentItem]) {
|
package/ios/ShortKitModule.mm
CHANGED
|
@@ -72,7 +72,7 @@ RCT_EXPORT_MODULE(ShortKitModule)
|
|
|
72
72
|
@"onContentTapped",
|
|
73
73
|
@"onDismiss",
|
|
74
74
|
@"onFeedReady",
|
|
75
|
-
@"
|
|
75
|
+
@"onRefreshStateChanged",
|
|
76
76
|
@"onDidFetchContentItems",
|
|
77
77
|
@"onOverlayActiveChanged",
|
|
78
78
|
@"onOverlayPlayerStateChanged",
|
|
@@ -264,9 +264,18 @@ RCT_EXPORT_METHOD(preloadFeed:(NSString *)configJSON
|
|
|
264
264
|
itemsJSON:(NSString *)itemsJSON
|
|
265
265
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
266
266
|
reject:(RCTPromiseRejectBlock)reject) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
267
|
+
if (_shortKitBridge) {
|
|
268
|
+
[_shortKitBridge preloadFeed:configJSON itemsJSON:itemsJSON completion:^(NSString *uuid) {
|
|
269
|
+
resolve(uuid);
|
|
270
|
+
}];
|
|
271
|
+
} else {
|
|
272
|
+
if (!_pendingBridgeOps) _pendingBridgeOps = [NSMutableArray new];
|
|
273
|
+
[_pendingBridgeOps addObject:^{
|
|
274
|
+
[self->_shortKitBridge preloadFeed:configJSON itemsJSON:itemsJSON completion:^(NSString *uuid) {
|
|
275
|
+
resolve(uuid);
|
|
276
|
+
}];
|
|
277
|
+
}];
|
|
278
|
+
}
|
|
270
279
|
}
|
|
271
280
|
|
|
272
281
|
// MARK: - Storyboard / Seek Thumbnails
|
|
@@ -22,12 +22,13 @@
|
|
|
22
22
|
<key>BinaryPath</key>
|
|
23
23
|
<string>ShortKitSDK.framework/ShortKitSDK</string>
|
|
24
24
|
<key>LibraryIdentifier</key>
|
|
25
|
-
<string>ios-
|
|
25
|
+
<string>ios-arm64_x86_64-simulator</string>
|
|
26
26
|
<key>LibraryPath</key>
|
|
27
27
|
<string>ShortKitSDK.framework</string>
|
|
28
28
|
<key>SupportedArchitectures</key>
|
|
29
29
|
<array>
|
|
30
30
|
<string>arm64</string>
|
|
31
|
+
<string>x86_64</string>
|
|
31
32
|
</array>
|
|
32
33
|
<key>SupportedPlatform</key>
|
|
33
34
|
<string>ios</string>
|
package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h
CHANGED
|
@@ -360,6 +360,7 @@ SWIFT_CLASS("_TtC11ShortKitSDK26ShortKitFeedViewController")
|
|
|
360
360
|
- (void)scrollViewWillBeginDragging:(UIScrollView * _Nonnull)scrollView;
|
|
361
361
|
- (void)scrollViewDidEndDecelerating:(UIScrollView * _Nonnull)scrollView;
|
|
362
362
|
- (void)scrollViewDidEndDragging:(UIScrollView * _Nonnull)scrollView willDecelerate:(BOOL)decelerate;
|
|
363
|
+
- (void)scrollViewDidScrollToTop:(UIScrollView * _Nonnull)scrollView;
|
|
363
364
|
- (void)scrollViewDidScroll:(UIScrollView * _Nonnull)scrollView;
|
|
364
365
|
@end
|
|
365
366
|
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
<key>CFBundlePackageType</key>
|
|
12
12
|
<string>FMWK</string>
|
|
13
13
|
<key>CFBundleVersion</key>
|
|
14
|
-
<string>
|
|
14
|
+
<string>0.2.15</string>
|
|
15
|
+
<key>CFBundleShortVersionString</key>
|
|
16
|
+
<string>0.2.15</string>
|
|
17
|
+
<key>MinimumOSVersion</key>
|
|
18
|
+
<string>16.0</string>
|
|
15
19
|
</dict>
|
|
16
20
|
</plist>
|