@stream-io/video-react-native-sdk 1.20.14 → 1.20.16
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/CHANGELOG.md +21 -0
- package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt +7 -15
- package/dist/commonjs/version.js +1 -1
- package/dist/module/version.js +1 -1
- package/dist/typescript/version.d.ts +1 -1
- package/ios/StreamVideoReactNative-Bridging-Header.h +1 -2
- package/ios/StreamVideoReactNative.h +1 -0
- package/ios/StreamVideoReactNative.m +90 -94
- package/package.json +4 -4
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
## [1.20.16](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-react-native-sdk-1.20.15...@stream-io/video-react-native-sdk-1.20.16) (2025-09-18)
|
|
6
|
+
|
|
7
|
+
### Dependency Updates
|
|
8
|
+
|
|
9
|
+
- `@stream-io/noise-cancellation-react-native` updated to version `0.2.4`
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
- android RN module compilation error on RN 0.81 ([#1924](https://github.com/GetStream/stream-video-js/issues/1924)) ([b02294c](https://github.com/GetStream/stream-video-js/commit/b02294c8bb85795ff5ac5fed2195e26d7e1f11a4)), closes [#1921](https://github.com/GetStream/stream-video-js/issues/1921)
|
|
14
|
+
|
|
15
|
+
## [1.20.15](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-react-native-sdk-1.20.14...@stream-io/video-react-native-sdk-1.20.15) (2025-09-17)
|
|
16
|
+
|
|
17
|
+
### Dependency Updates
|
|
18
|
+
|
|
19
|
+
- `@stream-io/video-client` updated to version `1.31.0`
|
|
20
|
+
- `@stream-io/video-react-bindings` updated to version `1.8.3`
|
|
21
|
+
|
|
22
|
+
### Bug Fixes
|
|
23
|
+
|
|
24
|
+
- screenshot for iOS was broken on old arch on interop layer ([#1923](https://github.com/GetStream/stream-video-js/issues/1923)) ([9b3134b](https://github.com/GetStream/stream-video-js/commit/9b3134bb6f6380551af4c3a0a69274eada2f8d94))
|
|
25
|
+
|
|
5
26
|
## [1.20.14](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-react-native-sdk-1.20.13...@stream-io/video-react-native-sdk-1.20.14) (2025-09-16)
|
|
6
27
|
|
|
7
28
|
### Dependency Updates
|
|
@@ -38,6 +38,8 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) :
|
|
|
38
38
|
return NAME
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
private val mPowerManager = reactApplicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager
|
|
42
|
+
|
|
41
43
|
private var thermalStatusListener: PowerManager.OnThermalStatusChangedListener? = null
|
|
42
44
|
|
|
43
45
|
private var batteryChargingStateReceiver = object : BroadcastReceiver() {
|
|
@@ -147,8 +149,6 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) :
|
|
|
147
149
|
fun startThermalStatusUpdates(promise: Promise) {
|
|
148
150
|
try {
|
|
149
151
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
150
|
-
val powerManager =
|
|
151
|
-
reactApplicationContext.getSystemService(ReactApplicationContext.POWER_SERVICE) as PowerManager
|
|
152
152
|
|
|
153
153
|
val listener = PowerManager.OnThermalStatusChangedListener { status ->
|
|
154
154
|
val thermalStatus = when (status) {
|
|
@@ -168,7 +168,7 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) :
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
thermalStatusListener = listener
|
|
171
|
-
|
|
171
|
+
mPowerManager.addThermalStatusListener(listener)
|
|
172
172
|
// Get initial status
|
|
173
173
|
currentThermalState(promise)
|
|
174
174
|
} else {
|
|
@@ -182,12 +182,10 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) :
|
|
|
182
182
|
@ReactMethod
|
|
183
183
|
fun stopThermalStatusUpdates() {
|
|
184
184
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
185
|
-
val powerManager =
|
|
186
|
-
reactApplicationContext.getSystemService(ReactApplicationContext.POWER_SERVICE) as PowerManager
|
|
187
185
|
// Store the current listener in a local val for safe null checking
|
|
188
186
|
val currentListener = thermalStatusListener
|
|
189
187
|
if (currentListener != null) {
|
|
190
|
-
|
|
188
|
+
mPowerManager.removeThermalStatusListener(currentListener)
|
|
191
189
|
thermalStatusListener = null
|
|
192
190
|
}
|
|
193
191
|
}
|
|
@@ -197,9 +195,7 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) :
|
|
|
197
195
|
fun currentThermalState(promise: Promise) {
|
|
198
196
|
try {
|
|
199
197
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
200
|
-
val
|
|
201
|
-
reactApplicationContext.getSystemService(ReactApplicationContext.POWER_SERVICE) as PowerManager
|
|
202
|
-
val status = powerManager.currentThermalStatus
|
|
198
|
+
val status = mPowerManager.currentThermalStatus
|
|
203
199
|
val thermalStatus = when (status) {
|
|
204
200
|
PowerManager.THERMAL_STATUS_NONE -> "NONE"
|
|
205
201
|
PowerManager.THERMAL_STATUS_LIGHT -> "LIGHT"
|
|
@@ -228,9 +224,7 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) :
|
|
|
228
224
|
}
|
|
229
225
|
|
|
230
226
|
private fun sendPowerModeEvent() {
|
|
231
|
-
val
|
|
232
|
-
reactApplicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager
|
|
233
|
-
val isLowPowerMode = powerManager.isPowerSaveMode
|
|
227
|
+
val isLowPowerMode = mPowerManager.isPowerSaveMode
|
|
234
228
|
reactApplicationContext
|
|
235
229
|
.getJSModule(RCTDeviceEventEmitter::class.java)
|
|
236
230
|
.emit("isLowPowerModeEnabled", isLowPowerMode)
|
|
@@ -239,9 +233,7 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) :
|
|
|
239
233
|
@ReactMethod
|
|
240
234
|
fun isLowPowerModeEnabled(promise: Promise) {
|
|
241
235
|
try {
|
|
242
|
-
|
|
243
|
-
reactApplicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager
|
|
244
|
-
promise.resolve(powerManager.isPowerSaveMode)
|
|
236
|
+
promise.resolve(mPowerManager.isPowerSaveMode)
|
|
245
237
|
} catch (e: Exception) {
|
|
246
238
|
promise.reject("ERROR", e.message)
|
|
247
239
|
}
|
package/dist/commonjs/version.js
CHANGED
package/dist/module/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = '1.20.
|
|
1
|
+
export const version = '1.20.16';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "1.20.
|
|
1
|
+
export declare const version = "1.20.16";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
#import <React/
|
|
1
|
+
#import <React/RCTBridge.h>
|
|
2
2
|
#import <React/RCTViewManager.h>
|
|
3
3
|
#import <React/RCTEventEmitter.h>
|
|
4
4
|
#import <React/RCTLog.h>
|
|
5
5
|
#import <React/RCTUIManager.h>
|
|
6
6
|
#import <React/RCTView.h>
|
|
7
|
-
#import <React/RCTBridge.h>
|
|
8
7
|
#import <React/UIView+React.h>
|
|
9
8
|
|
|
10
9
|
#import <WebRTC/RTCCVPixelBuffer.h>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
#import <React/
|
|
1
|
+
#import <React/RCTBridge.h>
|
|
2
2
|
#import <React/RCTEventEmitter.h>
|
|
3
3
|
#import <React/RCTUIManager.h>
|
|
4
|
+
#import <React/RCTUIManagerUtils.h>
|
|
4
5
|
#import <UIKit/UIKit.h>
|
|
5
6
|
#import "StreamVideoReactNative.h"
|
|
6
7
|
#import "WebRTCModule.h"
|
|
@@ -29,13 +30,11 @@ void broadcastNotificationCallback(CFNotificationCenterRef center,
|
|
|
29
30
|
bool hasListeners;
|
|
30
31
|
CFNotificationCenterRef _notificationCenter;
|
|
31
32
|
}
|
|
32
|
-
RCT_EXPORT_MODULE();
|
|
33
33
|
|
|
34
|
-
//
|
|
35
|
-
#ifdef RCT_NEW_ARCH_ENABLED
|
|
34
|
+
// necessary for addUIBlock usage https://github.com/facebook/react-native/issues/50800#issuecomment-2823327307
|
|
36
35
|
@synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED;
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
|
|
37
|
+
RCT_EXPORT_MODULE();
|
|
39
38
|
|
|
40
39
|
+(BOOL)requiresMainQueueSetup {
|
|
41
40
|
return NO;
|
|
@@ -178,7 +177,7 @@ RCT_EXPORT_METHOD(currentThermalState:(RCTPromiseResolveBlock)resolve rejecter:(
|
|
|
178
177
|
+(void)registerIncomingCall:(NSString *)cid uuid:(NSString *)uuid {
|
|
179
178
|
[StreamVideoReactNative initializeSharedDictionaries];
|
|
180
179
|
dispatch_sync(_dictionaryQueue, ^{
|
|
181
|
-
|
|
180
|
+
|
|
182
181
|
#ifdef DEBUG
|
|
183
182
|
NSLog(@"registerIncomingCall cid:%@ -> uuid:%@",cid,uuid);
|
|
184
183
|
#endif
|
|
@@ -210,7 +209,7 @@ RCT_EXPORT_METHOD(getIncomingCallCid:(NSString *)uuid
|
|
|
210
209
|
dispatch_sync(_dictionaryQueue, ^{
|
|
211
210
|
NSString *lowercaseUUID = [uuid lowercaseString];
|
|
212
211
|
NSString *foundCid = _incomingCallCidsByUUID[lowercaseUUID];
|
|
213
|
-
|
|
212
|
+
|
|
214
213
|
if (foundCid) {
|
|
215
214
|
resolve(foundCid);
|
|
216
215
|
} else {
|
|
@@ -230,7 +229,7 @@ RCT_EXPORT_METHOD(removeIncomingCall:(NSString *)cid
|
|
|
230
229
|
#ifdef DEBUG
|
|
231
230
|
NSLog(@"removeIncomingCall cid:%@ -> uuid:%@",cid,uuid);
|
|
232
231
|
#endif
|
|
233
|
-
|
|
232
|
+
|
|
234
233
|
[_incomingCallUUIDsByCallID removeObjectForKey:cid];
|
|
235
234
|
[_incomingCallCidsByUUID removeObjectForKey:uuid];
|
|
236
235
|
resolve(@YES);
|
|
@@ -245,95 +244,92 @@ RCT_EXPORT_METHOD(captureRef:(nonnull NSNumber *)reactTag
|
|
|
245
244
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
246
245
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
247
246
|
{
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
if (!view) {
|
|
259
|
-
reject(RCTErrorUnspecified, [NSString stringWithFormat:@"No view found with reactTag: %@", reactTag], nil);
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// Get capture options
|
|
264
|
-
NSString *format = options[@"format"] ? [options[@"format"] lowercaseString] : @"png";
|
|
265
|
-
CGFloat quality = options[@"quality"] ? [options[@"quality"] floatValue] : 1.0;
|
|
266
|
-
NSNumber *width = options[@"width"];
|
|
267
|
-
NSNumber *height = options[@"height"];
|
|
268
|
-
|
|
269
|
-
// Determine the size to render
|
|
270
|
-
CGSize size;
|
|
271
|
-
CGRect bounds = view.bounds;
|
|
272
|
-
if (width && height) {
|
|
273
|
-
size = CGSizeMake([width floatValue], [height floatValue]);
|
|
274
|
-
} else {
|
|
275
|
-
size = bounds.size;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// Abort if size is invalid
|
|
279
|
-
if (size.width <= 0 || size.height <= 0) {
|
|
280
|
-
reject(@"INVALID_SIZE", @"View has invalid size", nil);
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Begin image context with appropriate scale
|
|
285
|
-
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
|
|
286
|
-
|
|
287
|
-
// Calculate scaling if needed
|
|
288
|
-
CGRect drawRect = bounds;
|
|
289
|
-
if (width && height) {
|
|
290
|
-
CGFloat scaleX = size.width / bounds.size.width;
|
|
291
|
-
CGFloat scaleY = size.height / bounds.size.height;
|
|
292
|
-
|
|
293
|
-
// Apply transform to context for scaling if dimensions differ
|
|
294
|
-
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
295
|
-
if (context) {
|
|
296
|
-
CGContextTranslateCTM(context, 0, size.height);
|
|
297
|
-
CGContextScaleCTM(context, scaleX, -scaleY);
|
|
298
|
-
drawRect = CGRectMake(0, 0, bounds.size.width, bounds.size.height);
|
|
247
|
+
// It seems that due to how UIBlocks work with uiManager, we need to call the methods in UIManagerQueue
|
|
248
|
+
// for the blocks to be dispatched before the batch is completed
|
|
249
|
+
dispatch_async(RCTGetUIManagerQueue(), ^{
|
|
250
|
+
[self.viewRegistry_DEPRECATED addUIBlock:^(RCTViewRegistry *viewRegistry) {
|
|
251
|
+
UIView *view = [viewRegistry viewForReactTag:reactTag];
|
|
252
|
+
|
|
253
|
+
if (!view) {
|
|
254
|
+
reject(RCTErrorUnspecified, [NSString stringWithFormat:@"No view found with reactTag: %@", reactTag], nil);
|
|
255
|
+
return;
|
|
299
256
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
257
|
+
|
|
258
|
+
// Get capture options
|
|
259
|
+
NSString *format = options[@"format"] ? [options[@"format"] lowercaseString] : @"png";
|
|
260
|
+
CGFloat quality = options[@"quality"] ? [options[@"quality"] floatValue] : 1.0;
|
|
261
|
+
NSNumber *width = options[@"width"];
|
|
262
|
+
NSNumber *height = options[@"height"];
|
|
263
|
+
|
|
264
|
+
// Determine the size to render
|
|
265
|
+
CGSize size;
|
|
266
|
+
CGRect bounds = view.bounds;
|
|
267
|
+
if (width && height) {
|
|
268
|
+
size = CGSizeMake([width floatValue], [height floatValue]);
|
|
269
|
+
} else {
|
|
270
|
+
size = bounds.size;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Abort if size is invalid
|
|
274
|
+
if (size.width <= 0 || size.height <= 0) {
|
|
275
|
+
reject(@"INVALID_SIZE", @"View has invalid size", nil);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Begin image context with appropriate scale
|
|
280
|
+
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
|
|
281
|
+
|
|
282
|
+
// Calculate scaling if needed
|
|
283
|
+
CGRect drawRect = bounds;
|
|
284
|
+
if (width && height) {
|
|
285
|
+
CGFloat scaleX = size.width / bounds.size.width;
|
|
286
|
+
CGFloat scaleY = size.height / bounds.size.height;
|
|
287
|
+
|
|
288
|
+
// Apply transform to context for scaling if dimensions differ
|
|
289
|
+
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
290
|
+
if (context) {
|
|
291
|
+
CGContextTranslateCTM(context, 0, size.height);
|
|
292
|
+
CGContextScaleCTM(context, scaleX, -scaleY);
|
|
293
|
+
drawRect = CGRectMake(0, 0, bounds.size.width, bounds.size.height);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
BOOL success = [view drawViewHierarchyInRect:drawRect afterScreenUpdates:YES];
|
|
298
|
+
|
|
299
|
+
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
|
300
|
+
UIGraphicsEndImageContext();
|
|
301
|
+
|
|
302
|
+
if (!success || !image) {
|
|
303
|
+
reject(@"CAPTURE_FAILED", @"Failed to capture view as image", nil);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Convert to base64 string based on format
|
|
308
|
+
NSString *base64;
|
|
309
|
+
if ([format isEqualToString:@"jpg"] || [format isEqualToString:@"jpeg"]) {
|
|
310
|
+
NSData *imageData = UIImageJPEGRepresentation(image, quality);
|
|
311
|
+
base64 = [imageData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
|
|
312
|
+
} else {
|
|
313
|
+
// Default to PNG
|
|
314
|
+
NSData *imageData = UIImagePNGRepresentation(image);
|
|
315
|
+
base64 = [imageData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (base64) {
|
|
319
|
+
resolve(base64);
|
|
320
|
+
} else {
|
|
321
|
+
reject(@"ENCODING_FAILED", @"Failed to encode image to base64", nil);
|
|
322
|
+
}
|
|
323
|
+
}];
|
|
324
|
+
});
|
|
329
325
|
}
|
|
330
326
|
|
|
331
327
|
RCT_EXPORT_METHOD(getBatteryState:(RCTPromiseResolveBlock)resolve
|
|
332
|
-
|
|
328
|
+
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
333
329
|
UIDeviceBatteryState batteryState = [UIDevice currentDevice].batteryState;
|
|
334
330
|
BOOL isCharging = (batteryState == UIDeviceBatteryStateCharging ||
|
|
335
|
-
|
|
336
|
-
|
|
331
|
+
batteryState == UIDeviceBatteryStateFull);
|
|
332
|
+
|
|
337
333
|
resolve(@{
|
|
338
334
|
@"charging": @(isCharging),
|
|
339
335
|
@"level": @(round([UIDevice currentDevice].batteryLevel * 100))
|
|
@@ -343,8 +339,8 @@ RCT_EXPORT_METHOD(getBatteryState:(RCTPromiseResolveBlock)resolve
|
|
|
343
339
|
-(void)batteryStateDidChange:(NSNotification *)notification {
|
|
344
340
|
UIDeviceBatteryState batteryState = [UIDevice currentDevice].batteryState;
|
|
345
341
|
BOOL isCharging = (batteryState == UIDeviceBatteryStateCharging ||
|
|
346
|
-
|
|
347
|
-
|
|
342
|
+
batteryState == UIDeviceBatteryStateFull);
|
|
343
|
+
|
|
348
344
|
[self sendEventWithName:@"chargingStateChanged" body:@{
|
|
349
345
|
@"charging": @(isCharging),
|
|
350
346
|
@"level": @(round([UIDevice currentDevice].batteryLevel * 100))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stream-io/video-react-native-sdk",
|
|
3
|
-
"version": "1.20.
|
|
3
|
+
"version": "1.20.16",
|
|
4
4
|
"description": "Stream Video SDK for React Native",
|
|
5
5
|
"author": "https://getstream.io",
|
|
6
6
|
"homepage": "https://getstream.io/video/docs/react-native/",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"!**/.*"
|
|
46
46
|
],
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@stream-io/video-client": "1.
|
|
49
|
-
"@stream-io/video-react-bindings": "1.8.
|
|
48
|
+
"@stream-io/video-client": "1.31.0",
|
|
49
|
+
"@stream-io/video-react-bindings": "1.8.3",
|
|
50
50
|
"intl-pluralrules": "2.0.1",
|
|
51
51
|
"lodash.merge": "^4.6.2",
|
|
52
52
|
"react-native-url-polyfill": "1.3.0",
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
"@react-native-firebase/app": "^22.1.0",
|
|
126
126
|
"@react-native-firebase/messaging": "^22.1.0",
|
|
127
127
|
"@react-native/babel-preset": "^0.79.2",
|
|
128
|
-
"@stream-io/noise-cancellation-react-native": "^0.2.
|
|
128
|
+
"@stream-io/noise-cancellation-react-native": "^0.2.4",
|
|
129
129
|
"@stream-io/react-native-webrtc": "125.4.3",
|
|
130
130
|
"@stream-io/video-filters-react-native": "^0.6.3",
|
|
131
131
|
"@testing-library/jest-native": "^5.4.3",
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '1.20.
|
|
1
|
+
export const version = '1.20.16';
|