@kontextso/sdk-react-native 3.0.7-rc.2 → 4.0.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.d.mts +167 -4
- package/dist/index.d.ts +167 -4
- package/dist/index.js +468 -615
- package/dist/index.mjs +466 -612
- package/package.json +7 -9
- package/src/AbstractStream.ts +141 -0
- package/src/Configuration.ts +129 -0
- package/src/InlineAd.tsx +168 -0
- package/src/KontextAds.ts +40 -0
- package/src/Logger.ts +95 -0
- package/src/NativeStream.ts +20 -0
- package/src/Preload.ts +150 -0
- package/src/Session.ts +104 -0
- package/src/index.ts +2 -4
- package/src/utils/device.ts +89 -0
- package/src/utils/request.ts +73 -0
- package/src/utils/sdk.ts +16 -0
- package/src/utils/validation.ts +59 -0
- package/android/build.gradle +0 -88
- package/android/gradle.properties +0 -5
- package/android/src/main/AndroidManifest.xml +0 -2
- package/android/src/main/java/so/kontext/react/RNKontextModuleImpl.kt +0 -21
- package/android/src/newarch/java/so/kontext/react/RNKontextModule.kt +0 -22
- package/android/src/newarch/java/so/kontext/react/RNKontextPackage.kt +0 -32
- package/android/src/oldarch/java/so/kontext/react/RNKontextModule.kt +0 -25
- package/android/src/oldarch/java/so/kontext/react/RNKontextPacakge.kt +0 -16
- package/ios/KontextSDK.swift +0 -26
- package/ios/RNKontext.h +0 -13
- package/ios/RNKontext.mm +0 -36
- package/src/__tests__/util.test.ts +0 -9
- package/src/context/AdsProvider.tsx +0 -119
- package/src/formats/Format.tsx +0 -591
- package/src/formats/InlineAd.tsx +0 -8
- package/src/frame-webview.tsx +0 -43
package/dist/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,21 +15,13 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/index.ts
|
|
31
21
|
var index_exports = {};
|
|
32
22
|
__export(index_exports, {
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
InlineAd: () => InlineAd,
|
|
24
|
+
KontextAds: () => KontextAds
|
|
35
25
|
});
|
|
36
26
|
module.exports = __toCommonJS(index_exports);
|
|
37
27
|
|
|
@@ -54,671 +44,534 @@ function handleIframeMessage(handler, opts) {
|
|
|
54
44
|
};
|
|
55
45
|
}
|
|
56
46
|
|
|
57
|
-
// src/
|
|
58
|
-
var import_sdk_react = require("@kontextso/sdk-react");
|
|
59
|
-
var import_react2 = require("react");
|
|
60
|
-
var import_react_native = require("react-native");
|
|
61
|
-
|
|
62
|
-
// src/frame-webview.tsx
|
|
47
|
+
// src/InlineAd.tsx
|
|
63
48
|
var import_react = require("react");
|
|
64
49
|
var import_react_native_webview = require("react-native-webview");
|
|
65
50
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
66
|
-
var
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
ref: forwardedRef,
|
|
72
|
-
source: {
|
|
73
|
-
uri: iframeUrl
|
|
74
|
-
},
|
|
75
|
-
onMessage,
|
|
76
|
-
style,
|
|
77
|
-
allowsInlineMediaPlayback: true,
|
|
78
|
-
mediaPlaybackRequiresUserAction: false,
|
|
79
|
-
javaScriptEnabled: true,
|
|
80
|
-
domStorageEnabled: true,
|
|
81
|
-
allowsFullscreenVideo: false,
|
|
82
|
-
injectedJavaScript: `
|
|
83
|
-
window.addEventListener("message", function(event) {
|
|
84
|
-
if (window.ReactNativeWebView && event.data) {
|
|
85
|
-
// ReactNativeWebView.postMessage only supports string data
|
|
86
|
-
window.ReactNativeWebView.postMessage(JSON.stringify(event.data));
|
|
87
|
-
}
|
|
88
|
-
}, false);
|
|
89
|
-
`,
|
|
90
|
-
onError,
|
|
91
|
-
onLoad
|
|
92
|
-
}
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
);
|
|
96
|
-
var frame_webview_default = FrameWebView;
|
|
97
|
-
|
|
98
|
-
// src/formats/Format.tsx
|
|
99
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
100
|
-
var sendMessage = (webViewRef, type, code, data) => {
|
|
101
|
-
const message = makeIframeMessage(type, {
|
|
102
|
-
data,
|
|
103
|
-
code
|
|
51
|
+
var getIframeUrl = (bidId, messageId, adServerUrl) => {
|
|
52
|
+
const params = new URLSearchParams({
|
|
53
|
+
code: "inlineAd",
|
|
54
|
+
messageId,
|
|
55
|
+
sdk: "sdk-react-native"
|
|
104
56
|
});
|
|
105
|
-
|
|
106
|
-
window.dispatchEvent(new MessageEvent('message', {
|
|
107
|
-
data: ${JSON.stringify(message)}
|
|
108
|
-
}));
|
|
109
|
-
`);
|
|
57
|
+
return `${adServerUrl}/api/frame/${bidId}?${params}`;
|
|
110
58
|
};
|
|
111
|
-
var
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const bid = (0, import_sdk_react.useBid)({ code, messageId });
|
|
120
|
-
const [height, setHeight] = (0, import_react2.useState)(0);
|
|
121
|
-
const cachedContent = getCachedContent(context, bid?.bidId);
|
|
122
|
-
const iframeUrl = (0, import_sdk_react.useIframeUrl)(bid, code, messageId, "sdk-react-native", otherParams.theme, cachedContent);
|
|
123
|
-
const modalUrl = iframeUrl.replace("/api/frame/", "/api/modal/");
|
|
124
|
-
const [showIframe, setShowIframe] = (0, import_react2.useState)(false);
|
|
125
|
-
const [iframeLoaded, setIframeLoaded] = (0, import_react2.useState)(false);
|
|
126
|
-
const [modalOpen, setModalOpen] = (0, import_react2.useState)(false);
|
|
127
|
-
const [modalShown, setModalShown] = (0, import_react2.useState)(false);
|
|
128
|
-
const [modalLoaded, setModalLoaded] = (0, import_react2.useState)(false);
|
|
129
|
-
const [containerStyles, setContainerStyles] = (0, import_react2.useState)({});
|
|
130
|
-
const [iframeStyles, setIframeStyles] = (0, import_react2.useState)({});
|
|
131
|
-
const containerRef = (0, import_react2.useRef)(null);
|
|
132
|
-
const webViewRef = (0, import_react2.useRef)(null);
|
|
133
|
-
const modalWebViewRef = (0, import_react2.useRef)(null);
|
|
134
|
-
const modalInitTimeoutRef = (0, import_react2.useRef)(null);
|
|
135
|
-
const isModalInitRef = (0, import_react2.useRef)(false);
|
|
136
|
-
const { height: windowHeight, width: windowWidth } = (0, import_react_native.useWindowDimensions)();
|
|
137
|
-
const keyboardHeightRef = (0, import_react2.useRef)(0);
|
|
138
|
-
const isAdViewVisible = showIframe && iframeLoaded;
|
|
139
|
-
const reset = () => {
|
|
140
|
-
setHeight(0);
|
|
141
|
-
setShowIframe(false);
|
|
142
|
-
setContainerStyles({});
|
|
143
|
-
setIframeStyles({});
|
|
144
|
-
setIframeLoaded(false);
|
|
145
|
-
resetModal();
|
|
146
|
-
context?.resetAll();
|
|
147
|
-
context?.captureError(new Error("Processing iframe error"));
|
|
148
|
-
};
|
|
149
|
-
const resetModal = () => {
|
|
150
|
-
debugModal("Format:resetModal", {
|
|
151
|
-
params: {
|
|
152
|
-
messageId,
|
|
153
|
-
code,
|
|
154
|
-
otherParams
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
if (modalInitTimeoutRef.current) {
|
|
158
|
-
debugModal("Format:resetModalTimeout", {
|
|
159
|
-
params: {
|
|
160
|
-
messageId,
|
|
161
|
-
code,
|
|
162
|
-
otherParams
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
clearTimeout(modalInitTimeoutRef.current);
|
|
166
|
-
modalInitTimeoutRef.current = null;
|
|
59
|
+
var InlineAd = ({ messageId, session, onDebugEvent }) => {
|
|
60
|
+
const [bidId, setBidId] = (0, import_react.useState)(null);
|
|
61
|
+
const webViewRef = (0, import_react.useRef)(null);
|
|
62
|
+
const postRef = (0, import_react.useRef)({});
|
|
63
|
+
const sendMessage = (webViewRef2, type, code, data) => {
|
|
64
|
+
if (postRef.current[messageId]) {
|
|
65
|
+
onDebugEvent("InlineAd: message already posted", { messageId, ref: postRef.current });
|
|
66
|
+
return;
|
|
167
67
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
setModalShown(false);
|
|
172
|
-
};
|
|
173
|
-
const debug = (name, data = {}) => {
|
|
174
|
-
context?.onDebugEventInternal?.(name, {
|
|
175
|
-
code,
|
|
176
|
-
messageId,
|
|
177
|
-
otherParams,
|
|
178
|
-
bid,
|
|
179
|
-
iframeUrl,
|
|
180
|
-
iframeLoaded,
|
|
181
|
-
showIframe,
|
|
182
|
-
height,
|
|
183
|
-
containerStyles,
|
|
184
|
-
iframeStyles,
|
|
185
|
-
...data
|
|
186
|
-
});
|
|
187
|
-
};
|
|
188
|
-
const debugModal = (name, data = {}) => {
|
|
189
|
-
context?.onDebugEventInternal?.(name, {
|
|
190
|
-
code,
|
|
191
|
-
messageId,
|
|
192
|
-
otherParams,
|
|
193
|
-
bid,
|
|
194
|
-
modalUrl,
|
|
195
|
-
modalOpen,
|
|
196
|
-
modalShown,
|
|
197
|
-
modalLoaded,
|
|
198
|
-
...data
|
|
68
|
+
const message = makeIframeMessage(type, {
|
|
69
|
+
data,
|
|
70
|
+
code
|
|
199
71
|
});
|
|
72
|
+
onDebugEvent("InlineAd: post message", { messageId, message });
|
|
73
|
+
webViewRef2.current?.injectJavaScript(`
|
|
74
|
+
window.dispatchEvent(new MessageEvent('message', {
|
|
75
|
+
data: ${JSON.stringify(message)}
|
|
76
|
+
}));
|
|
77
|
+
`);
|
|
78
|
+
postRef.current[messageId] = true;
|
|
200
79
|
};
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
80
|
+
const updateBid = (0, import_react.useCallback)(() => {
|
|
81
|
+
const bid = session.getLastBid();
|
|
82
|
+
if (!bid || bid.messageId !== messageId) {
|
|
83
|
+
setBidId(null);
|
|
84
|
+
onDebugEvent("InlineAd: no bid", { messageId, bid });
|
|
85
|
+
return;
|
|
206
86
|
}
|
|
207
|
-
|
|
87
|
+
setBidId(bid.bidId);
|
|
88
|
+
onDebugEvent("InlineAd: update bid", { messageId, bid });
|
|
89
|
+
}, [session, messageId]);
|
|
90
|
+
(0, import_react.useEffect)(() => {
|
|
91
|
+
session.setOnUpdateBids(updateBid);
|
|
92
|
+
return () => {
|
|
93
|
+
session.setOnUpdateBids(void 0);
|
|
94
|
+
onDebugEvent("InlineAd: remove update bids callback", { messageId });
|
|
95
|
+
};
|
|
96
|
+
}, [session, updateBid]);
|
|
97
|
+
(0, import_react.useEffect)(() => {
|
|
98
|
+
updateBid();
|
|
99
|
+
}, [updateBid]);
|
|
100
|
+
if (!bidId) {
|
|
101
|
+
onDebugEvent("InlineAd: no bid id", { messageId, bidId });
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
const iframeUrl = getIframeUrl(bidId, messageId, session.config.adServerUrl);
|
|
105
|
+
if (!iframeUrl) {
|
|
106
|
+
onDebugEvent("InlineAd: no iframe url", { messageId, bidId });
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
208
109
|
const onMessage = (event) => {
|
|
209
110
|
try {
|
|
210
111
|
const data = JSON.parse(event.nativeEvent.data);
|
|
211
|
-
debug("Format:iframeMessage", {
|
|
212
|
-
message: data,
|
|
213
|
-
params: { data, messageId, code, otherParams }
|
|
214
|
-
});
|
|
215
112
|
const messageHandler = handleIframeMessage(
|
|
216
113
|
(message) => {
|
|
114
|
+
onDebugEvent("InlineAd: message handler", { messageId, message, bidId });
|
|
217
115
|
switch (message.type) {
|
|
218
116
|
case "init-iframe":
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
params: {
|
|
222
|
-
code,
|
|
223
|
-
messages: context?.messages,
|
|
224
|
-
sdk: "sdk-react-native",
|
|
225
|
-
otherParams,
|
|
226
|
-
messageId
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
sendMessage(webViewRef, "update-iframe", code, {
|
|
230
|
-
messages: context?.messages,
|
|
117
|
+
sendMessage(webViewRef, "update-iframe", "inlineAd", {
|
|
118
|
+
messages: session.getMessages(),
|
|
231
119
|
sdk: "sdk-react-native",
|
|
232
|
-
otherParams,
|
|
120
|
+
otherParams: {},
|
|
233
121
|
messageId
|
|
234
122
|
});
|
|
235
123
|
break;
|
|
236
124
|
case "error-iframe":
|
|
237
|
-
reset();
|
|
238
|
-
break;
|
|
239
|
-
case "resize-iframe":
|
|
240
|
-
setHeight(message.data.height);
|
|
241
125
|
break;
|
|
242
126
|
case "click-iframe":
|
|
243
|
-
if (message.data.url) {
|
|
244
|
-
import_react_native.Linking.openURL(`${context?.adServerUrl}${message.data.url}`).catch(
|
|
245
|
-
(err) => console.error("error opening url", err)
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
context?.onAdClickInternal(message.data);
|
|
249
127
|
break;
|
|
250
128
|
case "view-iframe":
|
|
251
|
-
context?.onAdViewInternal(message.data);
|
|
252
|
-
break;
|
|
253
|
-
case "ad-done-iframe":
|
|
254
|
-
if (bid?.bidId && message.data.cachedContent) {
|
|
255
|
-
context?.cachedContentRef?.current?.set(bid.bidId, message.data.cachedContent);
|
|
256
|
-
}
|
|
257
|
-
break;
|
|
258
|
-
case "show-iframe":
|
|
259
|
-
setShowIframe(true);
|
|
260
|
-
break;
|
|
261
|
-
case "hide-iframe":
|
|
262
|
-
setShowIframe(false);
|
|
263
|
-
break;
|
|
264
|
-
case "set-styles-iframe":
|
|
265
|
-
setContainerStyles(message.data.containerStyles);
|
|
266
|
-
setIframeStyles(message.data.iframeStyles);
|
|
267
|
-
break;
|
|
268
|
-
case "open-component-iframe":
|
|
269
|
-
setModalOpen(true);
|
|
270
|
-
modalInitTimeoutRef.current = setTimeout(() => {
|
|
271
|
-
if (!isModalInitRef.current) {
|
|
272
|
-
resetModal();
|
|
273
|
-
}
|
|
274
|
-
}, message.data.timeout ?? 5e3);
|
|
275
|
-
break;
|
|
276
|
-
case "event-iframe":
|
|
277
|
-
onEvent?.(message.data);
|
|
278
|
-
context?.onAdEventInternal(message.data);
|
|
279
|
-
break;
|
|
280
|
-
}
|
|
281
|
-
},
|
|
282
|
-
{
|
|
283
|
-
code
|
|
284
|
-
}
|
|
285
|
-
);
|
|
286
|
-
messageHandler({ data });
|
|
287
|
-
} catch (e) {
|
|
288
|
-
debug("Format:iframeMessageError", {
|
|
289
|
-
params: { error: e, messageId, code, otherParams },
|
|
290
|
-
error: e
|
|
291
|
-
});
|
|
292
|
-
console.error("error parsing message from webview", e);
|
|
293
|
-
reset();
|
|
294
|
-
}
|
|
295
|
-
};
|
|
296
|
-
const onModalMessage = (event) => {
|
|
297
|
-
try {
|
|
298
|
-
const data = JSON.parse(event.nativeEvent.data);
|
|
299
|
-
debugModal("Format:modalIframeMessage", {
|
|
300
|
-
params: { data, messageId, code, otherParams },
|
|
301
|
-
message: data
|
|
302
|
-
});
|
|
303
|
-
const messageHandler = handleIframeMessage(
|
|
304
|
-
(message) => {
|
|
305
|
-
switch (message.type) {
|
|
306
|
-
case "close-component-iframe":
|
|
307
|
-
resetModal();
|
|
308
|
-
break;
|
|
309
|
-
case "init-component-iframe":
|
|
310
|
-
isModalInitRef.current = true;
|
|
311
|
-
if (modalInitTimeoutRef.current) {
|
|
312
|
-
clearTimeout(modalInitTimeoutRef.current);
|
|
313
|
-
modalInitTimeoutRef.current = null;
|
|
314
|
-
}
|
|
315
|
-
setModalShown(true);
|
|
316
|
-
break;
|
|
317
|
-
case "error-component-iframe":
|
|
318
|
-
case "error-iframe":
|
|
319
|
-
resetModal();
|
|
320
|
-
context?.captureError(new Error("Processing modal iframe error"));
|
|
321
|
-
break;
|
|
322
|
-
case "click-iframe":
|
|
323
|
-
if (message.data.url) {
|
|
324
|
-
import_react_native.Linking.openURL(`${context?.adServerUrl}${message.data.url}`).catch(
|
|
325
|
-
(err) => console.error("error opening url", err)
|
|
326
|
-
);
|
|
327
|
-
}
|
|
328
|
-
context?.onAdClickInternal(message.data);
|
|
329
129
|
break;
|
|
330
130
|
case "event-iframe":
|
|
331
|
-
onEvent?.(message.data);
|
|
332
|
-
context?.onAdEventInternal(message.data);
|
|
333
131
|
break;
|
|
334
132
|
}
|
|
335
133
|
},
|
|
336
134
|
{
|
|
337
|
-
code
|
|
338
|
-
component: "modal"
|
|
135
|
+
code: "inlineAd"
|
|
339
136
|
}
|
|
340
137
|
);
|
|
341
138
|
messageHandler({ data });
|
|
342
139
|
} catch (e) {
|
|
343
|
-
debugModal("Format:modalIframeMessageError", {
|
|
344
|
-
params: { error: e, messageId, code, otherParams },
|
|
345
|
-
error: e
|
|
346
|
-
});
|
|
347
140
|
console.error("error parsing message from webview", e);
|
|
348
|
-
|
|
141
|
+
onDebugEvent("InlineAd: error parsing message from webview", { messageId, error: e });
|
|
349
142
|
}
|
|
350
143
|
};
|
|
351
|
-
|
|
352
|
-
(0,
|
|
353
|
-
|
|
354
|
-
debug("Format:iframePostMessageNotLoaded", {
|
|
355
|
-
params: {
|
|
356
|
-
messageId,
|
|
357
|
-
iframeLoaded,
|
|
358
|
-
contextAdServerUrl: context?.adServerUrl,
|
|
359
|
-
bid,
|
|
360
|
-
code,
|
|
361
|
-
otherParams
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
return;
|
|
365
|
-
}
|
|
366
|
-
debug("Format:iframePostMessage", {
|
|
367
|
-
params: {
|
|
368
|
-
messageId,
|
|
369
|
-
otherParams,
|
|
370
|
-
code
|
|
371
|
-
}
|
|
372
|
-
});
|
|
373
|
-
sendMessage(webViewRef, "update-iframe", code, {
|
|
374
|
-
data: { otherParams },
|
|
375
|
-
code
|
|
376
|
-
});
|
|
377
|
-
}, [paramsString, iframeLoaded, context?.adServerUrl, bid, code]);
|
|
378
|
-
const checkIfInViewport = () => {
|
|
379
|
-
if (!containerRef.current) {
|
|
380
|
-
debug("Format:checkIfInViewportNoContainer", {
|
|
381
|
-
params: {
|
|
382
|
-
messageId,
|
|
383
|
-
code,
|
|
384
|
-
otherParams
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
return;
|
|
388
|
-
}
|
|
389
|
-
debug("Format:checkIfInViewportMeasure", {
|
|
390
|
-
params: {
|
|
391
|
-
windowWidth,
|
|
392
|
-
windowHeight,
|
|
393
|
-
messageId,
|
|
394
|
-
code,
|
|
395
|
-
otherParams
|
|
396
|
-
}
|
|
397
|
-
});
|
|
398
|
-
containerRef.current.measureInWindow((containerX, containerY, containerWidth, containerHeight) => {
|
|
399
|
-
sendMessage(webViewRef, "update-dimensions-iframe", code, {
|
|
400
|
-
windowWidth,
|
|
401
|
-
windowHeight,
|
|
402
|
-
containerWidth,
|
|
403
|
-
containerHeight,
|
|
404
|
-
containerX,
|
|
405
|
-
containerY,
|
|
406
|
-
keyboardHeight: keyboardHeightRef.current
|
|
407
|
-
});
|
|
408
|
-
debug("Format:checkIfInViewportMeasureSend", {
|
|
409
|
-
params: {
|
|
410
|
-
messageId,
|
|
411
|
-
code,
|
|
412
|
-
otherParams,
|
|
413
|
-
windowWidth,
|
|
414
|
-
windowHeight,
|
|
415
|
-
containerWidth,
|
|
416
|
-
containerHeight,
|
|
417
|
-
containerX,
|
|
418
|
-
containerY,
|
|
419
|
-
keyboardHeight: keyboardHeightRef.current
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
});
|
|
423
|
-
};
|
|
424
|
-
(0, import_react2.useEffect)(() => {
|
|
425
|
-
if (!isAdViewVisible) {
|
|
426
|
-
debug("Format:checkIfInViewportNotVisible", {
|
|
427
|
-
params: {
|
|
428
|
-
messageId,
|
|
429
|
-
code,
|
|
430
|
-
otherParams
|
|
431
|
-
}
|
|
432
|
-
});
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
const interval = setInterval(() => {
|
|
436
|
-
checkIfInViewport();
|
|
437
|
-
}, 250);
|
|
438
|
-
return () => {
|
|
439
|
-
clearInterval(interval);
|
|
440
|
-
debug("Format:checkIfInViewportCleanup", {
|
|
441
|
-
params: {
|
|
442
|
-
messageId,
|
|
443
|
-
code,
|
|
444
|
-
otherParams
|
|
445
|
-
}
|
|
446
|
-
});
|
|
447
|
-
};
|
|
448
|
-
}, [isAdViewVisible]);
|
|
449
|
-
(0, import_react2.useEffect)(() => {
|
|
450
|
-
const showSubscription = import_react_native.Keyboard.addListener("keyboardDidShow", (e) => {
|
|
451
|
-
debug("Format:keyboardDidShow", {
|
|
452
|
-
params: {
|
|
453
|
-
keyboardHeight: e?.endCoordinates?.height ?? 0,
|
|
454
|
-
messageId,
|
|
455
|
-
code,
|
|
456
|
-
otherParams
|
|
457
|
-
}
|
|
458
|
-
});
|
|
459
|
-
keyboardHeightRef.current = e?.endCoordinates?.height ?? 0;
|
|
460
|
-
});
|
|
461
|
-
const hideSubscription = import_react_native.Keyboard.addListener("keyboardDidHide", () => {
|
|
462
|
-
debug("Format:keyboardDidHide", {
|
|
463
|
-
params: {
|
|
464
|
-
messageId,
|
|
465
|
-
code,
|
|
466
|
-
otherParams
|
|
467
|
-
}
|
|
468
|
-
});
|
|
469
|
-
keyboardHeightRef.current = 0;
|
|
470
|
-
});
|
|
471
|
-
return () => {
|
|
472
|
-
showSubscription.remove();
|
|
473
|
-
hideSubscription.remove();
|
|
474
|
-
keyboardHeightRef.current = 0;
|
|
475
|
-
debug("Format:keyboardEffectCleanup", {
|
|
476
|
-
params: {
|
|
477
|
-
messageId,
|
|
478
|
-
code,
|
|
479
|
-
otherParams
|
|
480
|
-
}
|
|
481
|
-
});
|
|
482
|
-
};
|
|
483
|
-
}, []);
|
|
484
|
-
if (!context || !bid || !iframeUrl) {
|
|
485
|
-
debug("Format:noContextOrBidOrIframeUrl", {
|
|
486
|
-
params: {
|
|
487
|
-
context,
|
|
488
|
-
bid,
|
|
489
|
-
iframeUrl,
|
|
490
|
-
messageId,
|
|
491
|
-
code,
|
|
492
|
-
otherParams
|
|
493
|
-
}
|
|
494
|
-
});
|
|
495
|
-
return null;
|
|
496
|
-
}
|
|
497
|
-
const inlineContent = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
498
|
-
frame_webview_default,
|
|
144
|
+
onDebugEvent("InlineAd: iframe url", { messageId, iframeUrl });
|
|
145
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
146
|
+
import_react_native_webview.WebView,
|
|
499
147
|
{
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
148
|
+
source: {
|
|
149
|
+
uri: iframeUrl
|
|
150
|
+
},
|
|
503
151
|
style: {
|
|
504
|
-
height,
|
|
152
|
+
height: 300,
|
|
505
153
|
width: "100%",
|
|
506
|
-
backgroundColor: "
|
|
507
|
-
borderWidth: 0,
|
|
508
|
-
...iframeStyles
|
|
154
|
+
backgroundColor: "red"
|
|
509
155
|
},
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
156
|
+
ref: webViewRef,
|
|
157
|
+
onMessage,
|
|
158
|
+
allowsInlineMediaPlayback: true,
|
|
159
|
+
mediaPlaybackRequiresUserAction: false,
|
|
160
|
+
javaScriptEnabled: true,
|
|
161
|
+
domStorageEnabled: true,
|
|
162
|
+
allowsFullscreenVideo: false,
|
|
163
|
+
injectedJavaScript: `
|
|
164
|
+
window.addEventListener("message", function(event) {
|
|
165
|
+
if (window.ReactNativeWebView && event.data) {
|
|
166
|
+
// ReactNativeWebView.postMessage only supports string data
|
|
167
|
+
window.ReactNativeWebView.postMessage(JSON.stringify(event.data));
|
|
516
168
|
}
|
|
517
|
-
});
|
|
518
|
-
|
|
169
|
+
}, false);
|
|
170
|
+
`,
|
|
171
|
+
onError: () => {
|
|
172
|
+
onDebugEvent("InlineAd: error loading iframe", { messageId });
|
|
519
173
|
},
|
|
520
174
|
onLoad: () => {
|
|
521
|
-
|
|
522
|
-
params: {
|
|
523
|
-
messageId,
|
|
524
|
-
code,
|
|
525
|
-
otherParams
|
|
526
|
-
}
|
|
527
|
-
});
|
|
175
|
+
onDebugEvent("InlineAd: iframe loaded", { messageId });
|
|
528
176
|
}
|
|
529
177
|
}
|
|
530
178
|
);
|
|
531
|
-
const interstitialContent = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
532
|
-
import_react_native.Modal,
|
|
533
|
-
{
|
|
534
|
-
visible: modalOpen,
|
|
535
|
-
transparent: true,
|
|
536
|
-
onRequestClose: resetModal,
|
|
537
|
-
animationType: "slide",
|
|
538
|
-
statusBarTranslucent: true,
|
|
539
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
540
|
-
import_react_native.View,
|
|
541
|
-
{
|
|
542
|
-
style: {
|
|
543
|
-
flex: 1,
|
|
544
|
-
// Don't show the modal until the modal page is loaded and sends 'init-component-iframe' message back to SDK
|
|
545
|
-
...modalShown ? { opacity: 1, pointerEvents: "auto" } : { opacity: 0, pointerEvents: "none" }
|
|
546
|
-
},
|
|
547
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
548
|
-
frame_webview_default,
|
|
549
|
-
{
|
|
550
|
-
ref: modalWebViewRef,
|
|
551
|
-
iframeUrl: modalUrl,
|
|
552
|
-
onMessage: onModalMessage,
|
|
553
|
-
style: {
|
|
554
|
-
backgroundColor: "transparent",
|
|
555
|
-
height: "100%",
|
|
556
|
-
width: "100%",
|
|
557
|
-
borderWidth: 0
|
|
558
|
-
},
|
|
559
|
-
onError: () => {
|
|
560
|
-
debug("Format:modalError", {
|
|
561
|
-
params: {
|
|
562
|
-
messageId,
|
|
563
|
-
code,
|
|
564
|
-
otherParams
|
|
565
|
-
}
|
|
566
|
-
});
|
|
567
|
-
resetModal();
|
|
568
|
-
},
|
|
569
|
-
onLoad: () => {
|
|
570
|
-
debug("Format:modalLoad", {
|
|
571
|
-
params: {
|
|
572
|
-
messageId,
|
|
573
|
-
code,
|
|
574
|
-
otherParams
|
|
575
|
-
}
|
|
576
|
-
});
|
|
577
|
-
setModalLoaded(true);
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
)
|
|
581
|
-
}
|
|
582
|
-
)
|
|
583
|
-
}
|
|
584
|
-
);
|
|
585
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
586
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
587
|
-
import_react_native.View,
|
|
588
|
-
{
|
|
589
|
-
style: isAdViewVisible ? containerStyles : {
|
|
590
|
-
height: 0,
|
|
591
|
-
overflow: "hidden"
|
|
592
|
-
},
|
|
593
|
-
ref: containerRef,
|
|
594
|
-
children: wrapper ? wrapper(inlineContent) : inlineContent
|
|
595
|
-
}
|
|
596
|
-
),
|
|
597
|
-
interstitialContent
|
|
598
|
-
] });
|
|
599
179
|
};
|
|
600
|
-
var FormatWithErrorBoundary = (props) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sdk_react.ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Format, { ...props }) });
|
|
601
|
-
var Format_default = FormatWithErrorBoundary;
|
|
602
180
|
|
|
603
|
-
// src/
|
|
604
|
-
var
|
|
605
|
-
var
|
|
606
|
-
|
|
181
|
+
// src/Configuration.ts
|
|
182
|
+
var DEFAULT_AD_SERVER_URL = "https://server.megabrain.co";
|
|
183
|
+
var DEFAULT_PLACEMENT_CODE = "inlineAd";
|
|
184
|
+
var DEFAULT_LOG_LEVEL = "info";
|
|
185
|
+
var Configuration = class {
|
|
186
|
+
config;
|
|
187
|
+
constructor(config) {
|
|
188
|
+
this.config = config;
|
|
189
|
+
}
|
|
190
|
+
get publisherToken() {
|
|
191
|
+
return this.config.publisherToken;
|
|
192
|
+
}
|
|
193
|
+
get userId() {
|
|
194
|
+
return this.config.userId;
|
|
195
|
+
}
|
|
196
|
+
get conversationId() {
|
|
197
|
+
return this.config.conversationId;
|
|
198
|
+
}
|
|
199
|
+
get character() {
|
|
200
|
+
return this.config.character;
|
|
201
|
+
}
|
|
202
|
+
get placementCode() {
|
|
203
|
+
return this.config.placementCode ?? DEFAULT_PLACEMENT_CODE;
|
|
204
|
+
}
|
|
205
|
+
get variantId() {
|
|
206
|
+
return this.config.variantId;
|
|
207
|
+
}
|
|
208
|
+
get regulatory() {
|
|
209
|
+
return this.config.regulatory;
|
|
210
|
+
}
|
|
211
|
+
get logLevel() {
|
|
212
|
+
return this.config.logLevel ?? DEFAULT_LOG_LEVEL;
|
|
213
|
+
}
|
|
214
|
+
get userEmail() {
|
|
215
|
+
return this.config.userEmail;
|
|
216
|
+
}
|
|
217
|
+
get adServerUrl() {
|
|
218
|
+
return this.config.adServerUrl ?? DEFAULT_AD_SERVER_URL;
|
|
219
|
+
}
|
|
607
220
|
};
|
|
608
|
-
var InlineAd_default = InlineAd;
|
|
609
|
-
|
|
610
|
-
// src/context/AdsProvider.tsx
|
|
611
|
-
var import_sdk_react2 = require("@kontextso/sdk-react");
|
|
612
|
-
var import_netinfo = require("@react-native-community/netinfo");
|
|
613
|
-
var import_react_native3 = require("react-native");
|
|
614
|
-
var import_react_native_device_info = __toESM(require("react-native-device-info"));
|
|
615
221
|
|
|
616
|
-
//
|
|
617
|
-
var
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
222
|
+
// src/Logger.ts
|
|
223
|
+
var Logger = class {
|
|
224
|
+
localLevel = "log";
|
|
225
|
+
remoteLevel = "error";
|
|
226
|
+
remoteConfig = null;
|
|
227
|
+
levels = {
|
|
228
|
+
debug: 0,
|
|
229
|
+
info: 1,
|
|
230
|
+
log: 2,
|
|
231
|
+
warn: 3,
|
|
232
|
+
error: 4,
|
|
233
|
+
silent: 5
|
|
234
|
+
};
|
|
235
|
+
getLocalLevel() {
|
|
236
|
+
return this.localLevel;
|
|
237
|
+
}
|
|
238
|
+
setLocalLevel(level) {
|
|
239
|
+
this.localLevel = level;
|
|
240
|
+
}
|
|
241
|
+
getRemoteLevel() {
|
|
242
|
+
return this.remoteLevel;
|
|
243
|
+
}
|
|
244
|
+
setRemoteLevel(level) {
|
|
245
|
+
this.remoteLevel = level;
|
|
246
|
+
}
|
|
247
|
+
configureRemote(url, params) {
|
|
248
|
+
this.remoteConfig = { url, params };
|
|
249
|
+
}
|
|
250
|
+
shouldLog(level, targetLevel) {
|
|
251
|
+
if (targetLevel === "silent") {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
return this.levels[level] >= this.levels[targetLevel];
|
|
255
|
+
}
|
|
256
|
+
logToConsole(level, ...args) {
|
|
257
|
+
if (this.shouldLog(level, this.localLevel)) {
|
|
258
|
+
if (level === "silent") {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
console[level](...args);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
logToRemote(level, ...args) {
|
|
265
|
+
if (this.remoteConfig && this.shouldLog(level, this.remoteLevel)) {
|
|
266
|
+
fetch(`${this.remoteConfig.url}/log`, {
|
|
267
|
+
method: "POST",
|
|
268
|
+
body: JSON.stringify({
|
|
269
|
+
...this.remoteConfig.params,
|
|
270
|
+
level,
|
|
271
|
+
message: args,
|
|
272
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
273
|
+
})
|
|
274
|
+
}).catch((e) => {
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
debug(...args) {
|
|
279
|
+
this.logToConsole("debug", ...args);
|
|
280
|
+
this.logToRemote("debug", ...args);
|
|
281
|
+
}
|
|
282
|
+
info(...args) {
|
|
283
|
+
this.logToConsole("info", ...args);
|
|
284
|
+
this.logToRemote("info", ...args);
|
|
285
|
+
}
|
|
286
|
+
log(...args) {
|
|
287
|
+
this.logToConsole("log", ...args);
|
|
288
|
+
this.logToRemote("log", ...args);
|
|
289
|
+
}
|
|
290
|
+
warn(...args) {
|
|
291
|
+
this.logToConsole("warn", ...args);
|
|
292
|
+
this.logToRemote("warn", ...args);
|
|
293
|
+
}
|
|
294
|
+
error(...args) {
|
|
295
|
+
this.logToConsole("error", ...args);
|
|
296
|
+
this.logToRemote("error", ...args);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
622
299
|
|
|
623
|
-
// src/
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
300
|
+
// src/utils/request.ts
|
|
301
|
+
async function fetchWithRetry(url, options = {}) {
|
|
302
|
+
const { retry = {}, timeout, abortController: abortControllerOption, ...fetchOptions } = options;
|
|
303
|
+
const maxRetries = retry.maxRetries ?? 3;
|
|
304
|
+
const baseDelay = retry.baseDelay ?? 1e3;
|
|
305
|
+
const backoffFactor = retry.backoffFactor ?? 2;
|
|
306
|
+
const abortController = abortControllerOption || new AbortController();
|
|
307
|
+
fetchOptions.signal = abortController.signal;
|
|
308
|
+
let timeoutId = null;
|
|
309
|
+
if (timeout) {
|
|
310
|
+
timeoutId = setTimeout(() => abortController.abort("timeout"), timeout);
|
|
630
311
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
const mapDeviceTypeToHardwareType = () => {
|
|
640
|
-
switch (deviceType) {
|
|
641
|
-
case "Handset":
|
|
642
|
-
return "handset";
|
|
643
|
-
case "Tablet":
|
|
644
|
-
return "tablet";
|
|
645
|
-
case "Tv":
|
|
646
|
-
return "tv";
|
|
647
|
-
case "Desktop":
|
|
648
|
-
return "desktop";
|
|
649
|
-
default:
|
|
650
|
-
return "other";
|
|
312
|
+
let lastError = null;
|
|
313
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
314
|
+
try {
|
|
315
|
+
const response = await fetch(url, fetchOptions);
|
|
316
|
+
if (response.status >= 500 || response.status === 429) {
|
|
317
|
+
const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
318
|
+
error.status = response.status;
|
|
319
|
+
throw error;
|
|
651
320
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
// volume: Requires react-native-volume-manager
|
|
664
|
-
// outputPluggedIn: Not available without native module
|
|
665
|
-
// outputType: Not available without native module
|
|
666
|
-
},
|
|
667
|
-
network: {
|
|
668
|
-
carrier: networkInfo.type === import_netinfo.NetInfoStateType.cellular && networkInfo.details.carrier || void 0,
|
|
669
|
-
userAgent: await import_react_native_device_info.default.getUserAgent(),
|
|
670
|
-
type: [import_netinfo.NetInfoStateType.wifi, import_netinfo.NetInfoStateType.cellular, import_netinfo.NetInfoStateType.ethernet].includes(networkInfo.type) ? networkInfo.type : import_netinfo.NetInfoStateType.other,
|
|
671
|
-
detail: networkInfo.type === import_netinfo.NetInfoStateType.cellular && networkInfo.details.cellularGeneration || void 0
|
|
672
|
-
},
|
|
673
|
-
os: {
|
|
674
|
-
name: import_react_native3.Platform.OS,
|
|
675
|
-
version: import_react_native_device_info.default.getSystemVersion(),
|
|
676
|
-
locale: Intl.DateTimeFormat().resolvedOptions().locale,
|
|
677
|
-
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
678
|
-
},
|
|
679
|
-
screen: {
|
|
680
|
-
darkMode: import_react_native3.Appearance.getColorScheme() === "dark",
|
|
681
|
-
dpr: import_react_native3.PixelRatio.get(),
|
|
682
|
-
height: screen.height,
|
|
683
|
-
width: screen.width,
|
|
684
|
-
orientation: screen.width > screen.height ? "landscape" : "portrait"
|
|
685
|
-
},
|
|
686
|
-
power: {
|
|
687
|
-
batteryLevel: powerState.batteryLevel,
|
|
688
|
-
batteryState: powerState.batteryState,
|
|
689
|
-
lowPowerMode: powerState.lowPowerMode
|
|
321
|
+
return response;
|
|
322
|
+
} catch (error) {
|
|
323
|
+
if (abortController.signal.aborted) {
|
|
324
|
+
throw new Error(`Fetch aborted: ${abortController.signal.reason}`);
|
|
325
|
+
}
|
|
326
|
+
lastError = error instanceof Error ? error : new Error("Unknown error");
|
|
327
|
+
const shouldRetry = error instanceof TypeError || // Network error
|
|
328
|
+
error.status >= 500 || // Server error
|
|
329
|
+
error.status === 429;
|
|
330
|
+
if (attempt === maxRetries || !shouldRetry) {
|
|
331
|
+
break;
|
|
690
332
|
}
|
|
333
|
+
const delay = baseDelay * backoffFactor ** attempt;
|
|
334
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
335
|
+
} finally {
|
|
336
|
+
if (timeoutId) {
|
|
337
|
+
clearTimeout(timeoutId);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
throw lastError;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// src/Preload.ts
|
|
345
|
+
var Preload = class {
|
|
346
|
+
session;
|
|
347
|
+
messages = [];
|
|
348
|
+
abortController;
|
|
349
|
+
running = false;
|
|
350
|
+
bid = null;
|
|
351
|
+
constructor(session, messages) {
|
|
352
|
+
this.session = session;
|
|
353
|
+
this.abortController = new AbortController();
|
|
354
|
+
this.setMessages(messages);
|
|
355
|
+
}
|
|
356
|
+
setMessages(messages) {
|
|
357
|
+
this.messages = messages;
|
|
358
|
+
}
|
|
359
|
+
hasBid() {
|
|
360
|
+
return this.bid !== null;
|
|
361
|
+
}
|
|
362
|
+
getBid() {
|
|
363
|
+
return this.bid;
|
|
364
|
+
}
|
|
365
|
+
setBid(bid) {
|
|
366
|
+
this.bid = bid;
|
|
367
|
+
}
|
|
368
|
+
cancel() {
|
|
369
|
+
this.abortController.abort();
|
|
370
|
+
this.running = false;
|
|
371
|
+
}
|
|
372
|
+
isRunning() {
|
|
373
|
+
return this.running;
|
|
374
|
+
}
|
|
375
|
+
/*
|
|
376
|
+
private async getDevice () {
|
|
377
|
+
try {
|
|
378
|
+
return await getDevice()
|
|
379
|
+
} catch (error) {
|
|
380
|
+
this.session.logger.error('Error getting device:', error)
|
|
381
|
+
return {} as DeviceConfig
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
*/
|
|
385
|
+
async getPreloadBody() {
|
|
386
|
+
const config = this.session.config;
|
|
387
|
+
const preloadBody = {
|
|
388
|
+
messages: this.messages,
|
|
389
|
+
sessionId: this.session.getSessionId(),
|
|
390
|
+
publisherToken: config.publisherToken,
|
|
391
|
+
userId: config.userId,
|
|
392
|
+
userEmail: config.userEmail,
|
|
393
|
+
conversationId: config.conversationId,
|
|
394
|
+
character: config.character,
|
|
395
|
+
enabledPlacementCodes: [config.placementCode],
|
|
396
|
+
variantId: config.variantId,
|
|
397
|
+
regulatory: config.regulatory,
|
|
398
|
+
sdk: this.session.sdk
|
|
691
399
|
};
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
400
|
+
return preloadBody;
|
|
401
|
+
}
|
|
402
|
+
canRequestAd() {
|
|
403
|
+
if (this.session.isSessionDisabled()) {
|
|
404
|
+
return {
|
|
405
|
+
status: "error",
|
|
406
|
+
message: "Session is disabled"
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
if (!this.messages.length) {
|
|
410
|
+
return {
|
|
411
|
+
status: "error",
|
|
412
|
+
message: "No messages"
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
async requestAd() {
|
|
418
|
+
this.running = true;
|
|
419
|
+
const cannotRequestAdReason = this.canRequestAd();
|
|
420
|
+
if (cannotRequestAdReason) {
|
|
421
|
+
return cannotRequestAdReason;
|
|
422
|
+
}
|
|
423
|
+
const config = this.session.config;
|
|
424
|
+
const preloadBody = await this.getPreloadBody();
|
|
425
|
+
try {
|
|
426
|
+
const response = await fetchWithRetry(`${config.adServerUrl}/preload`, {
|
|
427
|
+
method: "POST",
|
|
428
|
+
body: JSON.stringify(preloadBody),
|
|
429
|
+
headers: {
|
|
430
|
+
"Kontextso-Is-Disabled": "0",
|
|
431
|
+
"Kontextso-Publisher-Token": config.publisherToken
|
|
432
|
+
},
|
|
433
|
+
timeout: 16e3,
|
|
434
|
+
abortController: this.abortController
|
|
435
|
+
});
|
|
436
|
+
const jsonResponse = await response.json();
|
|
437
|
+
const bid = jsonResponse.bids?.[0] ?? null;
|
|
438
|
+
if (jsonResponse.sessionId) {
|
|
439
|
+
this.session.setSessionId(jsonResponse.sessionId);
|
|
440
|
+
}
|
|
441
|
+
if (bid) {
|
|
442
|
+
this.setBid(bid);
|
|
443
|
+
}
|
|
444
|
+
this.session.updateBids();
|
|
445
|
+
return {
|
|
446
|
+
status: "success"
|
|
447
|
+
};
|
|
448
|
+
} catch (error) {
|
|
449
|
+
this.session.logger.error("Error requesting ad:", error);
|
|
450
|
+
return {
|
|
451
|
+
status: "error"
|
|
452
|
+
};
|
|
453
|
+
} finally {
|
|
454
|
+
this.running = false;
|
|
455
|
+
}
|
|
695
456
|
}
|
|
696
457
|
};
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
458
|
+
|
|
459
|
+
// src/Session.ts
|
|
460
|
+
var Session = class {
|
|
461
|
+
config;
|
|
462
|
+
logger;
|
|
463
|
+
sdk;
|
|
464
|
+
sessionId = null;
|
|
465
|
+
sessionDisabled = false;
|
|
466
|
+
messages = [];
|
|
467
|
+
bids = [];
|
|
468
|
+
onUpdateBidsCallback = null;
|
|
469
|
+
// only one preload instance is allowed at a time
|
|
470
|
+
preloadInstance = null;
|
|
471
|
+
constructor(config, { sdk }) {
|
|
472
|
+
this.config = config;
|
|
473
|
+
this.logger = new Logger();
|
|
474
|
+
this.sdk = sdk;
|
|
475
|
+
}
|
|
476
|
+
setOnUpdateBids(callback) {
|
|
477
|
+
this.onUpdateBidsCallback = callback;
|
|
478
|
+
}
|
|
479
|
+
isSessionDisabled() {
|
|
480
|
+
return this.sessionDisabled;
|
|
481
|
+
}
|
|
482
|
+
setSessionDisabled(disabled) {
|
|
483
|
+
this.sessionDisabled = disabled;
|
|
484
|
+
}
|
|
485
|
+
getSessionId() {
|
|
486
|
+
return this.sessionId;
|
|
487
|
+
}
|
|
488
|
+
setSessionId(sessionId) {
|
|
489
|
+
this.logger.info("Session ID set:", sessionId);
|
|
490
|
+
this.sessionId = sessionId;
|
|
491
|
+
}
|
|
492
|
+
addMessage(message) {
|
|
493
|
+
this.messages.push(message);
|
|
494
|
+
this.updateBids();
|
|
495
|
+
}
|
|
496
|
+
getMessages() {
|
|
497
|
+
return this.messages;
|
|
498
|
+
}
|
|
499
|
+
updateBids() {
|
|
500
|
+
if (!this.preloadInstance?.hasBid()) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
const bid = this.preloadInstance.getBid();
|
|
504
|
+
if (!bid) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
const lastMessage = this.messages[this.messages.length - 1];
|
|
508
|
+
if (!lastMessage || lastMessage.role !== "assistant") {
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
const assignedBid = this.bids.find((b) => {
|
|
512
|
+
if (b.bidId === bid?.bidId) {
|
|
513
|
+
return true;
|
|
514
|
+
}
|
|
515
|
+
if (b.messageId === lastMessage.id) {
|
|
516
|
+
return true;
|
|
517
|
+
}
|
|
518
|
+
return false;
|
|
519
|
+
});
|
|
520
|
+
if (assignedBid) {
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
this.bids.push({
|
|
524
|
+
bidId: bid.bidId,
|
|
525
|
+
messageId: lastMessage.id
|
|
526
|
+
});
|
|
527
|
+
this.onUpdateBidsCallback?.();
|
|
528
|
+
}
|
|
529
|
+
preload() {
|
|
530
|
+
if (this.preloadInstance?.isRunning()) {
|
|
531
|
+
this.preloadInstance.cancel();
|
|
532
|
+
}
|
|
533
|
+
this.preloadInstance = new Preload(this, [...this.messages]);
|
|
534
|
+
return this.preloadInstance;
|
|
535
|
+
}
|
|
536
|
+
getLastBid() {
|
|
537
|
+
return this.bids[this.bids.length - 1];
|
|
710
538
|
}
|
|
711
539
|
};
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
var
|
|
718
|
-
|
|
540
|
+
|
|
541
|
+
// src/KontextAds.ts
|
|
542
|
+
var import_react_native = require("react-native");
|
|
543
|
+
|
|
544
|
+
// package.json
|
|
545
|
+
var version = "4.0.0-rc.0";
|
|
546
|
+
|
|
547
|
+
// src/KontextAds.ts
|
|
548
|
+
var KontextAds = (config) => {
|
|
549
|
+
return {
|
|
550
|
+
createSession: (sessionConfig) => createSession({
|
|
551
|
+
...config,
|
|
552
|
+
...sessionConfig
|
|
553
|
+
})
|
|
554
|
+
};
|
|
555
|
+
};
|
|
556
|
+
var createSession = (options) => {
|
|
557
|
+
const sdk = {
|
|
558
|
+
name: "sdk-react-native",
|
|
559
|
+
platform: import_react_native.Platform.OS === "ios" ? "ios" : "android",
|
|
560
|
+
version
|
|
561
|
+
};
|
|
562
|
+
const instance = new Session(new Configuration(options), { sdk });
|
|
563
|
+
return {
|
|
564
|
+
addMessage: (message) => {
|
|
565
|
+
instance.addMessage(message);
|
|
566
|
+
if (message.role === "user") {
|
|
567
|
+
instance.preload().requestAd();
|
|
568
|
+
}
|
|
569
|
+
},
|
|
570
|
+
getInstance: () => instance
|
|
571
|
+
};
|
|
719
572
|
};
|
|
720
573
|
// Annotate the CommonJS export names for ESM import in node:
|
|
721
574
|
0 && (module.exports = {
|
|
722
|
-
|
|
723
|
-
|
|
575
|
+
InlineAd,
|
|
576
|
+
KontextAds
|
|
724
577
|
});
|