@kontextso/sdk-react-native 2.1.0 → 2.1.1-rc.1
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/README.md +1 -1
- package/RNKontext.podspec +21 -0
- package/android/build.gradle +88 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/so/kontext/react/RNKontextModuleImpl.kt +21 -0
- package/android/src/newarch/java/so/kontext/react/RNKontextModule.kt +22 -0
- package/android/src/newarch/java/so/kontext/react/RNKontextPackage.kt +32 -0
- package/android/src/oldarch/java/so/kontext/react/RNKontextModule.kt +25 -0
- package/android/src/oldarch/java/so/kontext/react/RNKontextPacakge.kt +16 -0
- package/dist/index.js +77 -193
- package/dist/index.mjs +64 -180
- package/ios/KontextSDK.swift +26 -0
- package/ios/RNKontext.h +13 -0
- package/ios/RNKontext.mm +36 -0
- package/package.json +26 -4
- package/src/NativeRNKontext.ts +8 -0
- package/src/context/AdsProvider.tsx +60 -0
- package/src/formats/Format.tsx +263 -0
- package/src/formats/InlineAd.tsx +8 -0
- package/src/index.ts +5 -0
package/dist/index.mjs
CHANGED
|
@@ -7,7 +7,8 @@ import {
|
|
|
7
7
|
useBid,
|
|
8
8
|
useIframeUrl
|
|
9
9
|
} from "@kontextso/sdk-react";
|
|
10
|
-
import {
|
|
10
|
+
import { WebView } from "react-native-webview";
|
|
11
|
+
import { Linking, View, useWindowDimensions } from "react-native";
|
|
11
12
|
|
|
12
13
|
// ../sdk-common/dist/index.mjs
|
|
13
14
|
function makeIframeMessage(type, opts) {
|
|
@@ -27,44 +28,8 @@ function handleIframeMessage(handler, opts) {
|
|
|
27
28
|
};
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
// src/frame-webview.tsx
|
|
31
|
-
import { forwardRef } from "react";
|
|
32
|
-
import { WebView } from "react-native-webview";
|
|
33
|
-
import { jsx } from "react/jsx-runtime";
|
|
34
|
-
var FrameWebView = forwardRef(
|
|
35
|
-
({ iframeUrl, onMessage, style, onError, onLoad }, forwardedRef) => {
|
|
36
|
-
return /* @__PURE__ */ jsx(
|
|
37
|
-
WebView,
|
|
38
|
-
{
|
|
39
|
-
ref: forwardedRef,
|
|
40
|
-
source: {
|
|
41
|
-
uri: iframeUrl
|
|
42
|
-
},
|
|
43
|
-
onMessage,
|
|
44
|
-
style,
|
|
45
|
-
allowsInlineMediaPlayback: true,
|
|
46
|
-
mediaPlaybackRequiresUserAction: false,
|
|
47
|
-
javaScriptEnabled: true,
|
|
48
|
-
domStorageEnabled: true,
|
|
49
|
-
allowsFullscreenVideo: false,
|
|
50
|
-
injectedJavaScript: `
|
|
51
|
-
window.addEventListener("message", function(event) {
|
|
52
|
-
if (window.ReactNativeWebView && event.data) {
|
|
53
|
-
// ReactNativeWebView.postMessage only supports string data
|
|
54
|
-
window.ReactNativeWebView.postMessage(JSON.stringify(event.data));
|
|
55
|
-
}
|
|
56
|
-
}, false);
|
|
57
|
-
`,
|
|
58
|
-
onError,
|
|
59
|
-
onLoad
|
|
60
|
-
}
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
);
|
|
64
|
-
var frame_webview_default = FrameWebView;
|
|
65
|
-
|
|
66
31
|
// src/formats/Format.tsx
|
|
67
|
-
import {
|
|
32
|
+
import { jsx } from "react/jsx-runtime";
|
|
68
33
|
var sendMessage = (webViewRef, type, code, data) => {
|
|
69
34
|
const message = makeIframeMessage(type, {
|
|
70
35
|
data,
|
|
@@ -80,19 +45,13 @@ var Format = ({ code, messageId, wrapper, ...otherParams }) => {
|
|
|
80
45
|
const context = useContext(AdsContext);
|
|
81
46
|
const bid = useBid({ code, messageId });
|
|
82
47
|
const [height, setHeight] = useState(0);
|
|
83
|
-
const iframeUrl = useIframeUrl(context, bid, code, messageId
|
|
84
|
-
const modalUrl = iframeUrl.replace("/api/frame/", "/api/modal/");
|
|
48
|
+
const iframeUrl = useIframeUrl(context, bid, code, messageId);
|
|
85
49
|
const [showIframe, setShowIframe] = useState(false);
|
|
86
50
|
const [iframeLoaded, setIframeLoaded] = useState(false);
|
|
87
|
-
const [modalOpen, setModalOpen] = useState(false);
|
|
88
|
-
const [modalShown, setModalShown] = useState(false);
|
|
89
|
-
const [modalLoaded, setModalLoaded] = useState(false);
|
|
90
51
|
const [containerStyles, setContainerStyles] = useState({});
|
|
91
52
|
const [iframeStyles, setIframeStyles] = useState({});
|
|
92
53
|
const containerRef = useRef(null);
|
|
93
54
|
const webViewRef = useRef(null);
|
|
94
|
-
const modalWebViewRef = useRef(null);
|
|
95
|
-
const modalInitTimeoutRef = useRef(null);
|
|
96
55
|
const { height: windowHeight, width: windowWidth } = useWindowDimensions();
|
|
97
56
|
const reset = () => {
|
|
98
57
|
setHeight(0);
|
|
@@ -100,19 +59,9 @@ var Format = ({ code, messageId, wrapper, ...otherParams }) => {
|
|
|
100
59
|
setContainerStyles({});
|
|
101
60
|
setIframeStyles({});
|
|
102
61
|
setIframeLoaded(false);
|
|
103
|
-
resetModal();
|
|
104
62
|
context?.resetAll();
|
|
105
63
|
context?.captureError(new Error("Processing iframe error"));
|
|
106
64
|
};
|
|
107
|
-
const resetModal = () => {
|
|
108
|
-
if (modalInitTimeoutRef.current) {
|
|
109
|
-
clearTimeout(modalInitTimeoutRef.current);
|
|
110
|
-
modalInitTimeoutRef.current = null;
|
|
111
|
-
}
|
|
112
|
-
setModalOpen(false);
|
|
113
|
-
setModalLoaded(false);
|
|
114
|
-
setModalShown(false);
|
|
115
|
-
};
|
|
116
65
|
const debug = (name, data = {}) => {
|
|
117
66
|
context?.onDebugEventInternal?.(name, {
|
|
118
67
|
code,
|
|
@@ -128,19 +77,6 @@ var Format = ({ code, messageId, wrapper, ...otherParams }) => {
|
|
|
128
77
|
...data
|
|
129
78
|
});
|
|
130
79
|
};
|
|
131
|
-
const debugModal = (name, data = {}) => {
|
|
132
|
-
context?.onDebugEventInternal?.(name, {
|
|
133
|
-
code,
|
|
134
|
-
messageId,
|
|
135
|
-
otherParams,
|
|
136
|
-
bid,
|
|
137
|
-
modalUrl,
|
|
138
|
-
modalOpen,
|
|
139
|
-
modalShown,
|
|
140
|
-
modalLoaded,
|
|
141
|
-
...data
|
|
142
|
-
});
|
|
143
|
-
};
|
|
144
80
|
debug("format-update-state");
|
|
145
81
|
const onMessage = (event) => {
|
|
146
82
|
try {
|
|
@@ -188,10 +124,6 @@ var Format = ({ code, messageId, wrapper, ...otherParams }) => {
|
|
|
188
124
|
setContainerStyles(message.data.containerStyles);
|
|
189
125
|
setIframeStyles(message.data.iframeStyles);
|
|
190
126
|
break;
|
|
191
|
-
case "open-component-iframe":
|
|
192
|
-
setModalOpen(true);
|
|
193
|
-
modalInitTimeoutRef.current = setTimeout(resetModal, message.data.timeout ?? 5e3);
|
|
194
|
-
break;
|
|
195
127
|
}
|
|
196
128
|
},
|
|
197
129
|
{
|
|
@@ -207,53 +139,6 @@ var Format = ({ code, messageId, wrapper, ...otherParams }) => {
|
|
|
207
139
|
reset();
|
|
208
140
|
}
|
|
209
141
|
};
|
|
210
|
-
const onModalMessage = (event) => {
|
|
211
|
-
try {
|
|
212
|
-
const data = JSON.parse(event.nativeEvent.data);
|
|
213
|
-
debugModal("modal-iframe-message", {
|
|
214
|
-
message: data
|
|
215
|
-
});
|
|
216
|
-
const messageHandler = handleIframeMessage(
|
|
217
|
-
(message) => {
|
|
218
|
-
switch (message.type) {
|
|
219
|
-
case "close-component-iframe":
|
|
220
|
-
resetModal();
|
|
221
|
-
break;
|
|
222
|
-
case "init-component-iframe":
|
|
223
|
-
if (modalInitTimeoutRef.current) {
|
|
224
|
-
clearTimeout(modalInitTimeoutRef.current);
|
|
225
|
-
modalInitTimeoutRef.current = null;
|
|
226
|
-
}
|
|
227
|
-
setModalShown(true);
|
|
228
|
-
break;
|
|
229
|
-
case "error-component-iframe":
|
|
230
|
-
case "error-iframe":
|
|
231
|
-
resetModal();
|
|
232
|
-
break;
|
|
233
|
-
case "click-iframe":
|
|
234
|
-
if (message.data.url) {
|
|
235
|
-
Linking.openURL(`${context?.adServerUrl}${message.data.url}`).catch(
|
|
236
|
-
(err) => console.error("error opening url", err)
|
|
237
|
-
);
|
|
238
|
-
}
|
|
239
|
-
context?.onAdClickInternal(message.data);
|
|
240
|
-
break;
|
|
241
|
-
}
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
code,
|
|
245
|
-
component: "modal"
|
|
246
|
-
}
|
|
247
|
-
);
|
|
248
|
-
messageHandler({ data });
|
|
249
|
-
} catch (e) {
|
|
250
|
-
debugModal("modal-iframe-message-error", {
|
|
251
|
-
error: e
|
|
252
|
-
});
|
|
253
|
-
console.error("error parsing message from webview", e);
|
|
254
|
-
resetModal();
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
142
|
const paramsString = convertParamsToString(otherParams);
|
|
258
143
|
useEffect(() => {
|
|
259
144
|
if (!iframeLoaded || !context?.adServerUrl || !bid || !webViewRef.current) {
|
|
@@ -299,71 +184,57 @@ var Format = ({ code, messageId, wrapper, ...otherParams }) => {
|
|
|
299
184
|
}
|
|
300
185
|
return 0;
|
|
301
186
|
};
|
|
302
|
-
const content = /* @__PURE__ */
|
|
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
|
-
onLoad: () => {
|
|
328
|
-
debug("modal-load");
|
|
329
|
-
setModalLoaded(true);
|
|
330
|
-
}
|
|
187
|
+
const content = /* @__PURE__ */ jsx(View, { style: containerStyles, ref: containerRef, children: /* @__PURE__ */ jsx(
|
|
188
|
+
WebView,
|
|
189
|
+
{
|
|
190
|
+
ref: webViewRef,
|
|
191
|
+
source: {
|
|
192
|
+
uri: iframeUrl
|
|
193
|
+
},
|
|
194
|
+
onMessage,
|
|
195
|
+
style: {
|
|
196
|
+
height: getHeight(),
|
|
197
|
+
width: getWidth(),
|
|
198
|
+
...iframeStyles
|
|
199
|
+
},
|
|
200
|
+
allowsInlineMediaPlayback: true,
|
|
201
|
+
mediaPlaybackRequiresUserAction: false,
|
|
202
|
+
javaScriptEnabled: true,
|
|
203
|
+
domStorageEnabled: true,
|
|
204
|
+
allowsFullscreenVideo: false,
|
|
205
|
+
injectedJavaScript: `
|
|
206
|
+
function sendToLog(data) {
|
|
207
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
208
|
+
type: 'log-iframe',
|
|
209
|
+
data: data
|
|
210
|
+
}));
|
|
331
211
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
...iframeStyles
|
|
347
|
-
},
|
|
348
|
-
onError: () => {
|
|
349
|
-
debug("iframe-error");
|
|
350
|
-
reset();
|
|
351
|
-
},
|
|
352
|
-
onLoad: () => {
|
|
353
|
-
debug("iframe-load");
|
|
354
|
-
}
|
|
212
|
+
|
|
213
|
+
window.addEventListener("message", function(event) {
|
|
214
|
+
if (window.ReactNativeWebView && event.data) {
|
|
215
|
+
// ReactNativeWebView.postMessage only supports string data
|
|
216
|
+
window.ReactNativeWebView.postMessage(JSON.stringify(event.data));
|
|
217
|
+
}
|
|
218
|
+
}, false);
|
|
219
|
+
`,
|
|
220
|
+
onError: () => {
|
|
221
|
+
debug("iframe-error");
|
|
222
|
+
reset();
|
|
223
|
+
},
|
|
224
|
+
onLoad: () => {
|
|
225
|
+
debug("iframe-load");
|
|
355
226
|
}
|
|
356
|
-
|
|
357
|
-
|
|
227
|
+
}
|
|
228
|
+
) });
|
|
358
229
|
return wrapper ? wrapper(content) : content;
|
|
359
230
|
};
|
|
360
|
-
var FormatWithErrorBoundary = (props) => /* @__PURE__ */
|
|
231
|
+
var FormatWithErrorBoundary = (props) => /* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(Format, { ...props }) });
|
|
361
232
|
var Format_default = FormatWithErrorBoundary;
|
|
362
233
|
|
|
363
234
|
// src/formats/InlineAd.tsx
|
|
364
|
-
import { jsx as
|
|
235
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
365
236
|
var InlineAd = ({ code, messageId, wrapper, ...props }) => {
|
|
366
|
-
return /* @__PURE__ */
|
|
237
|
+
return /* @__PURE__ */ jsx2(Format_default, { code, messageId, wrapper, ...props });
|
|
367
238
|
};
|
|
368
239
|
var InlineAd_default = InlineAd;
|
|
369
240
|
|
|
@@ -371,7 +242,13 @@ var InlineAd_default = InlineAd;
|
|
|
371
242
|
import { AdsProviderInternal, log } from "@kontextso/sdk-react";
|
|
372
243
|
import { Platform } from "react-native";
|
|
373
244
|
import DeviceInfo from "react-native-device-info";
|
|
374
|
-
|
|
245
|
+
|
|
246
|
+
// src/NativeRNKontext.ts
|
|
247
|
+
import { TurboModuleRegistry } from "react-native";
|
|
248
|
+
var NativeRNKontext_default = TurboModuleRegistry.getEnforcing("RNKontext");
|
|
249
|
+
|
|
250
|
+
// src/context/AdsProvider.tsx
|
|
251
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
375
252
|
ErrorUtils.setGlobalHandler((error, isFatal) => {
|
|
376
253
|
if (!isFatal) {
|
|
377
254
|
log.warn(error);
|
|
@@ -379,7 +256,7 @@ ErrorUtils.setGlobalHandler((error, isFatal) => {
|
|
|
379
256
|
log.error(error);
|
|
380
257
|
}
|
|
381
258
|
});
|
|
382
|
-
var getDevice = () => {
|
|
259
|
+
var getDevice = async () => {
|
|
383
260
|
try {
|
|
384
261
|
const os = Platform.OS;
|
|
385
262
|
const systemVersion = DeviceInfo.getSystemVersion();
|
|
@@ -389,6 +266,12 @@ var getDevice = () => {
|
|
|
389
266
|
const deviceType = DeviceInfo.getDeviceType();
|
|
390
267
|
const appBundleId = DeviceInfo.getBundleId();
|
|
391
268
|
const appVersion = DeviceInfo.getVersion();
|
|
269
|
+
let soundOn = false;
|
|
270
|
+
try {
|
|
271
|
+
soundOn = await NativeRNKontext_default.isSoundOn();
|
|
272
|
+
} catch (error) {
|
|
273
|
+
log.warn("Failed to read output volume", error);
|
|
274
|
+
}
|
|
392
275
|
const rnv = Platform.constants.reactNativeVersion;
|
|
393
276
|
const reactNativeVersion = `${rnv.major}.${rnv.minor}.${rnv.patch}`;
|
|
394
277
|
return {
|
|
@@ -400,7 +283,8 @@ var getDevice = () => {
|
|
|
400
283
|
deviceId,
|
|
401
284
|
deviceType,
|
|
402
285
|
appBundleId,
|
|
403
|
-
appVersion
|
|
286
|
+
appVersion,
|
|
287
|
+
soundOn
|
|
404
288
|
};
|
|
405
289
|
} catch (error) {
|
|
406
290
|
console.error(error);
|
|
@@ -408,7 +292,7 @@ var getDevice = () => {
|
|
|
408
292
|
return {};
|
|
409
293
|
};
|
|
410
294
|
var AdsProvider = (props) => {
|
|
411
|
-
return /* @__PURE__ */
|
|
295
|
+
return /* @__PURE__ */ jsx3(AdsProviderInternal, { ...props, getDevice });
|
|
412
296
|
};
|
|
413
297
|
export {
|
|
414
298
|
AdsProvider,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import AVFoundation
|
|
2
|
+
|
|
3
|
+
@objc(KontextSDK)
|
|
4
|
+
public class KontextSDK: NSObject {
|
|
5
|
+
private static let MINIMAL_VOLUME_THRESHOLD: Float = 0.0
|
|
6
|
+
|
|
7
|
+
@objc
|
|
8
|
+
public static func isSoundOn() -> NSNumber? {
|
|
9
|
+
let session = AVAudioSession.sharedInstance()
|
|
10
|
+
|
|
11
|
+
do {
|
|
12
|
+
try session.setCategory(
|
|
13
|
+
.ambient,
|
|
14
|
+
mode: .default,
|
|
15
|
+
options: [.mixWithOthers]
|
|
16
|
+
)
|
|
17
|
+
try session.setActive(true)
|
|
18
|
+
|
|
19
|
+
return NSNumber(
|
|
20
|
+
value: session.outputVolume > MINIMAL_VOLUME_THRESHOLD
|
|
21
|
+
)
|
|
22
|
+
} catch {
|
|
23
|
+
return nil
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
package/ios/RNKontext.h
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#import "RNKontext-Swift.h"
|
|
2
|
+
|
|
3
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
4
|
+
#import <RNKontextSpec/RNKontextSpec.h>
|
|
5
|
+
|
|
6
|
+
@interface RNKontext: NSObject <NativeRNKontextSpec>
|
|
7
|
+
#else
|
|
8
|
+
#import <React/RCTBridgeModule.h>
|
|
9
|
+
|
|
10
|
+
@interface RNKontext: NSObject <RCTBridgeModule>
|
|
11
|
+
#endif
|
|
12
|
+
|
|
13
|
+
@end
|
package/ios/RNKontext.mm
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#import "RNKontext.h"
|
|
2
|
+
|
|
3
|
+
@implementation RNKontext
|
|
4
|
+
|
|
5
|
+
RCT_EXPORT_MODULE()
|
|
6
|
+
|
|
7
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
8
|
+
- (void)isSoundOn:(RCTPromiseResolveBlock)resolve
|
|
9
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
10
|
+
NSNumber *isSoundOn = [KontextSDK isSoundOn];
|
|
11
|
+
|
|
12
|
+
if (isSoundOn == nil) {
|
|
13
|
+
reject(@"soundon_error", @"Failed to read output volume", nil);
|
|
14
|
+
} else {
|
|
15
|
+
resolve(isSoundOn);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
20
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params {
|
|
21
|
+
return std::make_shared<facebook::react::NativeRNKontextSpecJSI>(params);
|
|
22
|
+
}
|
|
23
|
+
#else
|
|
24
|
+
RCT_EXPORT_METHOD(isSoundOn : (RCTPromiseResolveBlock)
|
|
25
|
+
resolve rejecter : (RCTPromiseRejectBlock)reject) {
|
|
26
|
+
NSNumber *isSoundOn = [KontextSDK isSoundOn];
|
|
27
|
+
|
|
28
|
+
if (isSoundOn == nil) {
|
|
29
|
+
reject(@"soundon_error", @"Failed to read output volume", nil);
|
|
30
|
+
} else {
|
|
31
|
+
resolve(isSoundOn);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
@end
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kontextso/sdk-react-native",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1-rc.1",
|
|
4
|
+
"description": "Kontext SDK for React Native",
|
|
4
5
|
"main": "./dist/index.js",
|
|
5
6
|
"module": "./dist/index.mjs",
|
|
6
7
|
"types": "./dist/index.d.ts",
|
|
7
8
|
"type": "commonjs",
|
|
8
9
|
"license": "Apache-2.0",
|
|
10
|
+
"author": "Kontext",
|
|
11
|
+
"homepage": "https://github.com/kontextso",
|
|
9
12
|
"scripts": {
|
|
10
13
|
"dev:js": "tsup --watch",
|
|
11
14
|
"dev": "npm-run-all dev:js",
|
|
@@ -52,10 +55,29 @@
|
|
|
52
55
|
"react-native-webview": "^13.15.0"
|
|
53
56
|
},
|
|
54
57
|
"dependencies": {
|
|
55
|
-
"@kontextso/sdk-react": "^1.2.
|
|
58
|
+
"@kontextso/sdk-react": "^1.2.3"
|
|
56
59
|
},
|
|
57
60
|
"files": [
|
|
58
61
|
"dist/*",
|
|
59
|
-
"
|
|
60
|
-
|
|
62
|
+
"src",
|
|
63
|
+
"android",
|
|
64
|
+
"ios",
|
|
65
|
+
"*.podspec",
|
|
66
|
+
"LICENSE",
|
|
67
|
+
"!ios/build",
|
|
68
|
+
"!android/build",
|
|
69
|
+
"!android/gradle",
|
|
70
|
+
"!android/gradlew",
|
|
71
|
+
"!android/gradlew.bat",
|
|
72
|
+
"!android/local.properties",
|
|
73
|
+
"!**/.*"
|
|
74
|
+
],
|
|
75
|
+
"codegenConfig": {
|
|
76
|
+
"name": "RNKontextSpec",
|
|
77
|
+
"type": "modules",
|
|
78
|
+
"jsSrcsDir": "src",
|
|
79
|
+
"android": {
|
|
80
|
+
"javaPackageName": "so.kontext.react"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
61
83
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import type { AdsProviderProps, Device } from '@kontextso/sdk-react'
|
|
4
|
+
import { AdsProviderInternal, log } from '@kontextso/sdk-react'
|
|
5
|
+
import { Platform } from 'react-native'
|
|
6
|
+
import DeviceInfo from 'react-native-device-info'
|
|
7
|
+
import KontextSDK from '../NativeRNKontext'
|
|
8
|
+
|
|
9
|
+
ErrorUtils.setGlobalHandler((error, isFatal) => {
|
|
10
|
+
if (!isFatal) {
|
|
11
|
+
log.warn(error)
|
|
12
|
+
} else {
|
|
13
|
+
log.error(error)
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const getDevice = async (): Promise<Device> => {
|
|
18
|
+
try {
|
|
19
|
+
const os = Platform.OS
|
|
20
|
+
const systemVersion = DeviceInfo.getSystemVersion()
|
|
21
|
+
const model = DeviceInfo.getModel()
|
|
22
|
+
const brand = DeviceInfo.getBrand()
|
|
23
|
+
const deviceId = DeviceInfo.getDeviceId()
|
|
24
|
+
const deviceType = DeviceInfo.getDeviceType()
|
|
25
|
+
const appBundleId = DeviceInfo.getBundleId()
|
|
26
|
+
const appVersion = DeviceInfo.getVersion()
|
|
27
|
+
|
|
28
|
+
let soundOn = false
|
|
29
|
+
try {
|
|
30
|
+
soundOn = await KontextSDK.isSoundOn()
|
|
31
|
+
} catch (error) {
|
|
32
|
+
log.warn('Failed to read output volume', error)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
console.log('soundOn', soundOn)
|
|
36
|
+
|
|
37
|
+
const rnv = Platform.constants.reactNativeVersion
|
|
38
|
+
const reactNativeVersion = `${rnv.major}.${rnv.minor}.${rnv.patch}`
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
os,
|
|
42
|
+
systemVersion,
|
|
43
|
+
reactNativeVersion,
|
|
44
|
+
model,
|
|
45
|
+
brand,
|
|
46
|
+
deviceId,
|
|
47
|
+
deviceType,
|
|
48
|
+
appBundleId,
|
|
49
|
+
appVersion,
|
|
50
|
+
soundOn,
|
|
51
|
+
}
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error(error)
|
|
54
|
+
}
|
|
55
|
+
return {}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const AdsProvider = (props: AdsProviderProps) => {
|
|
59
|
+
return <AdsProviderInternal {...props} getDevice={getDevice} />
|
|
60
|
+
}
|