@kontextso/sdk-react-native 3.0.8-rc.0 → 3.1.0-rc.0
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/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/ios/KontextSDK.swift +42 -0
- package/ios/RNKontext.h +1 -0
- package/ios/RNKontext.mm +44 -2
- package/ios/SkOverlayManager.swift +49 -0
- package/package.json +1 -1
- package/src/NativeRNKontext.ts +3 -1
- package/src/context/AdsProvider.tsx +2 -2
- package/src/formats/Format.tsx +7 -0
- package/src/services/SkOverlay.ts +23 -0
package/dist/index.js
CHANGED
|
@@ -492,7 +492,7 @@ var import_react_native3 = require("react-native");
|
|
|
492
492
|
var import_react_native_device_info = __toESM(require("react-native-device-info"));
|
|
493
493
|
|
|
494
494
|
// package.json
|
|
495
|
-
var version = "3.0.
|
|
495
|
+
var version = "3.1.0-rc.0";
|
|
496
496
|
|
|
497
497
|
// src/NativeRNKontext.ts
|
|
498
498
|
var import_react_native2 = require("react-native");
|
package/dist/index.mjs
CHANGED
|
@@ -464,7 +464,7 @@ import { Appearance, Dimensions, PixelRatio, Platform } from "react-native";
|
|
|
464
464
|
import DeviceInfo from "react-native-device-info";
|
|
465
465
|
|
|
466
466
|
// package.json
|
|
467
|
-
var version = "3.0.
|
|
467
|
+
var version = "3.1.0-rc.0";
|
|
468
468
|
|
|
469
469
|
// src/NativeRNKontext.ts
|
|
470
470
|
import { TurboModuleRegistry } from "react-native";
|
package/ios/KontextSDK.swift
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
import Foundation
|
|
1
2
|
import AVFoundation
|
|
3
|
+
import StoreKit
|
|
4
|
+
import UIKit
|
|
5
|
+
import React
|
|
2
6
|
|
|
3
7
|
@objc(KontextSDK)
|
|
4
8
|
public class KontextSDK: NSObject {
|
|
5
9
|
private static let MINIMAL_VOLUME_THRESHOLD: Float = 0.0
|
|
6
10
|
|
|
11
|
+
// MARK: - Audio
|
|
12
|
+
|
|
7
13
|
@objc
|
|
8
14
|
public static func isSoundOn() -> NSNumber? {
|
|
9
15
|
let session = AVAudioSession.sharedInstance()
|
|
@@ -23,4 +29,40 @@ public class KontextSDK: NSObject {
|
|
|
23
29
|
return nil
|
|
24
30
|
}
|
|
25
31
|
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
// MARK: - SKOverlay
|
|
35
|
+
|
|
36
|
+
@objc
|
|
37
|
+
public static func presentSKOverlay(
|
|
38
|
+
_ appStoreId: String,
|
|
39
|
+
position: String,
|
|
40
|
+
dismissible: Bool,
|
|
41
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
42
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
43
|
+
) {
|
|
44
|
+
DispatchQueue.main.async {
|
|
45
|
+
do {
|
|
46
|
+
let ok = try SKOverlayManager.shared.present(
|
|
47
|
+
appStoreId: appStoreId,
|
|
48
|
+
position: position,
|
|
49
|
+
dismissible: dismissible
|
|
50
|
+
)
|
|
51
|
+
resolve(ok)
|
|
52
|
+
} catch {
|
|
53
|
+
reject("SK_OVERLAY_ERROR", error.localizedDescription, error)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@objc
|
|
59
|
+
public static func dismissSKOverlay(
|
|
60
|
+
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
61
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
62
|
+
) {
|
|
63
|
+
DispatchQueue.main.async {
|
|
64
|
+
let ok = SKOverlayManager.shared.dismiss()
|
|
65
|
+
resolve(ok)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
26
68
|
}
|
package/ios/RNKontext.h
CHANGED
package/ios/RNKontext.mm
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
RCT_EXPORT_MODULE()
|
|
6
6
|
|
|
7
7
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
8
|
+
|
|
8
9
|
- (void)isSoundOn:(RCTPromiseResolveBlock)resolve
|
|
9
10
|
reject:(RCTPromiseRejectBlock)reject {
|
|
10
11
|
NSNumber *isSoundOn = [KontextSDK isSoundOn];
|
|
@@ -16,13 +17,34 @@ RCT_EXPORT_MODULE()
|
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
// NEW: Present SKOverlay
|
|
21
|
+
- (void)presentSKOverlay:(NSString *)appStoreId
|
|
22
|
+
position:(NSString *)position
|
|
23
|
+
dismissible:(BOOL)dismissible
|
|
24
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
25
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
26
|
+
[KontextSDK presentSKOverlay:appStoreId
|
|
27
|
+
position:position
|
|
28
|
+
dismissible:dismissible
|
|
29
|
+
resolver:resolve
|
|
30
|
+
rejecter:reject];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// NEW: Dismiss SKOverlay
|
|
34
|
+
- (void)dismissSKOverlay:(RCTPromiseResolveBlock)resolve
|
|
35
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
36
|
+
[KontextSDK dismissSKOverlay:resolve rejecter:reject];
|
|
37
|
+
}
|
|
38
|
+
|
|
19
39
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
20
40
|
(const facebook::react::ObjCTurboModule::InitParams &)params {
|
|
21
41
|
return std::make_shared<facebook::react::NativeRNKontextSpecJSI>(params);
|
|
22
42
|
}
|
|
43
|
+
|
|
23
44
|
#else
|
|
24
|
-
|
|
25
|
-
|
|
45
|
+
|
|
46
|
+
RCT_EXPORT_METHOD(isSoundOn : (RCTPromiseResolveBlock)resolve
|
|
47
|
+
rejecter : (RCTPromiseRejectBlock)reject) {
|
|
26
48
|
NSNumber *isSoundOn = [KontextSDK isSoundOn];
|
|
27
49
|
|
|
28
50
|
if (isSoundOn == nil) {
|
|
@@ -31,6 +53,26 @@ RCT_EXPORT_METHOD(isSoundOn : (RCTPromiseResolveBlock)
|
|
|
31
53
|
resolve(isSoundOn);
|
|
32
54
|
}
|
|
33
55
|
}
|
|
56
|
+
|
|
57
|
+
// NEW: Present SKOverlay
|
|
58
|
+
RCT_EXPORT_METHOD(presentSKOverlay:(NSString *)appStoreId
|
|
59
|
+
position:(NSString *)position
|
|
60
|
+
dismissible:(BOOL)dismissible
|
|
61
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
62
|
+
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
63
|
+
[KontextSDK presentSKOverlay:appStoreId
|
|
64
|
+
position:position
|
|
65
|
+
dismissible:dismissible
|
|
66
|
+
resolver:resolve
|
|
67
|
+
rejecter:reject];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// NEW: Dismiss SKOverlay
|
|
71
|
+
RCT_EXPORT_METHOD(dismissSKOverlay:(RCTPromiseResolveBlock)resolve
|
|
72
|
+
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
73
|
+
[KontextSDK dismissSKOverlay:resolve rejecter:reject];
|
|
74
|
+
}
|
|
75
|
+
|
|
34
76
|
#endif
|
|
35
77
|
|
|
36
78
|
@end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import StoreKit
|
|
3
|
+
import UIKit
|
|
4
|
+
|
|
5
|
+
final class SKOverlayManager {
|
|
6
|
+
static let shared = SKOverlayManager()
|
|
7
|
+
|
|
8
|
+
func present(appStoreId: String, position: String, dismissible: Bool) throws -> Bool {
|
|
9
|
+
guard #available(iOS 14.0, *), #available(iOS 13.0, *) else { return false }
|
|
10
|
+
|
|
11
|
+
guard let scene = UIApplication.shared.connectedScenes
|
|
12
|
+
.compactMap({ $0 as? UIWindowScene })
|
|
13
|
+
.first(where: { $0.activationState == .foregroundActive || $0.activationState == .foregroundInactive })
|
|
14
|
+
else {
|
|
15
|
+
throw NSError(domain: "SKOverlay", code: 1, userInfo: [
|
|
16
|
+
NSLocalizedDescriptionKey: "No active UIWindowScene found"
|
|
17
|
+
])
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
dismiss(in: scene)
|
|
21
|
+
|
|
22
|
+
let pos: SKOverlay.Position = (position.lowercased() == "bottomraised") ? .bottomRaised : .bottom
|
|
23
|
+
|
|
24
|
+
let config = SKOverlay.AppConfiguration(appIdentifier: appStoreId, position: pos)
|
|
25
|
+
config.userDismissible = dismissible
|
|
26
|
+
|
|
27
|
+
let overlay = SKOverlay(configuration: config)
|
|
28
|
+
overlay.present(in: scene)
|
|
29
|
+
return true
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
func dismiss() -> Bool {
|
|
33
|
+
guard #available(iOS 14.0, *), #available(iOS 13.0, *) else { return false }
|
|
34
|
+
|
|
35
|
+
guard let scene = UIApplication.shared.connectedScenes
|
|
36
|
+
.compactMap({ $0 as? UIWindowScene })
|
|
37
|
+
.first(where: { $0.activationState == .foregroundActive || $0.activationState == .foregroundInactive })
|
|
38
|
+
else { return false }
|
|
39
|
+
|
|
40
|
+
dismiss(in: scene)
|
|
41
|
+
return true
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@available(iOS 14.0, *)
|
|
45
|
+
@available(iOS 13.0, *)
|
|
46
|
+
private func dismiss(in scene: UIWindowScene) {
|
|
47
|
+
SKOverlay.dismiss(in: scene)
|
|
48
|
+
}
|
|
49
|
+
}
|
package/package.json
CHANGED
package/src/NativeRNKontext.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { TurboModuleRegistry } from 'react-native'
|
|
|
3
3
|
|
|
4
4
|
export interface Spec extends TurboModule {
|
|
5
5
|
isSoundOn(): Promise<boolean>
|
|
6
|
+
presentSKOverlay(appStoreId: string, position: string, dismissible: boolean): Promise<boolean>
|
|
7
|
+
dismissSKOverlay(): Promise<boolean>
|
|
6
8
|
}
|
|
7
9
|
|
|
8
|
-
export default TurboModuleRegistry.getEnforcing<Spec>(
|
|
10
|
+
export default TurboModuleRegistry.getEnforcing<Spec>("RNKontext");
|
|
@@ -10,7 +10,7 @@ import { fetch as fetchNetworkInfo, NetInfoStateType } from '@react-native-commu
|
|
|
10
10
|
import { Appearance, Dimensions, PixelRatio, Platform } from 'react-native'
|
|
11
11
|
import DeviceInfo, { type DeviceType } from 'react-native-device-info'
|
|
12
12
|
import { version } from '../../package.json'
|
|
13
|
-
import
|
|
13
|
+
import NativeRNKontext from '../NativeRNKontext'
|
|
14
14
|
|
|
15
15
|
ErrorUtils.setGlobalHandler((error, isFatal) => {
|
|
16
16
|
if (!isFatal) {
|
|
@@ -24,7 +24,7 @@ const getDevice = async (): Promise<DeviceConfig> => {
|
|
|
24
24
|
try {
|
|
25
25
|
const powerState = await DeviceInfo.getPowerState()
|
|
26
26
|
const deviceType = DeviceInfo.getDeviceType() as DeviceType
|
|
27
|
-
const soundOn = await
|
|
27
|
+
const soundOn = await NativeRNKontext.isSoundOn()
|
|
28
28
|
const screen = Dimensions.get('screen')
|
|
29
29
|
const networkInfo = await fetchNetworkInfo()
|
|
30
30
|
|
package/src/formats/Format.tsx
CHANGED
|
@@ -296,6 +296,13 @@ const Format = ({ code, messageId, wrapper, onEvent, ...otherParams }: FormatPro
|
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
+
/*
|
|
300
|
+
* Fix for Android issue in Saylo.
|
|
301
|
+
* When the iframe is loaded, the onLoad event is sometimes called two or more times.
|
|
302
|
+
* When these events fire too quickly, the init-iframe response from the server gets discarded.
|
|
303
|
+
* As a result, our SDK doesn’t send the update-iframe event back to the server, and the stream never starts.
|
|
304
|
+
* This fix will send the update-iframe event even if the init-iframe isn’t received.
|
|
305
|
+
*/
|
|
299
306
|
useEffect(() => {
|
|
300
307
|
const interval = setInterval(() => {
|
|
301
308
|
if (messageStatusRef.current === MessageStatus.None) {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Platform } from 'react-native'
|
|
2
|
+
import NativeRNKontext from '../NativeRNKontext';
|
|
3
|
+
|
|
4
|
+
export type SKOverlayPosition = 'bottom' | 'bottomRaised';
|
|
5
|
+
|
|
6
|
+
export async function presentSKOverlay(params: {
|
|
7
|
+
appStoreId: string;
|
|
8
|
+
position?: SKOverlayPosition;
|
|
9
|
+
dismissible?: boolean;
|
|
10
|
+
}) {
|
|
11
|
+
if (Platform.OS !== 'ios') {
|
|
12
|
+
return false
|
|
13
|
+
}
|
|
14
|
+
const { appStoreId, position = 'bottom', dismissible = true } = params
|
|
15
|
+
return NativeRNKontext.presentSKOverlay(appStoreId, position, dismissible)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function dismissSKOverlay() {
|
|
19
|
+
if (Platform.OS !== 'ios') {
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
22
|
+
return NativeRNKontext.dismissSKOverlay()
|
|
23
|
+
}
|