@kontextso/sdk-react-native 0.0.9 → 0.0.10-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 +8 -95
- package/dist/index.d.ts +8 -95
- package/dist/index.js +723 -575
- package/dist/index.mjs +694 -545
- package/package.json +15 -12
package/dist/index.mjs
CHANGED
|
@@ -6,53 +6,130 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
// src/formats/InlineAd.tsx
|
|
9
|
-
import { useContext as useContext6, useEffect as
|
|
9
|
+
import { useContext as useContext6, useEffect as useEffect8, useState as useState7 } from "react";
|
|
10
10
|
import {
|
|
11
11
|
Image,
|
|
12
12
|
Linking as Linking3,
|
|
13
|
-
Platform
|
|
13
|
+
Platform,
|
|
14
14
|
Text as Text3,
|
|
15
15
|
TouchableOpacity as TouchableOpacity2,
|
|
16
16
|
View as View3
|
|
17
17
|
} from "react-native";
|
|
18
18
|
|
|
19
|
-
//
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
// src/context/AdsProvider.tsx
|
|
23
|
-
import React2, { useState as useState4 } from "react";
|
|
24
|
-
|
|
25
|
-
// src/hooks/useInitializeAds.tsx
|
|
19
|
+
// ../sdk-common/dist/index.mjs
|
|
20
|
+
import { useContext } from "react";
|
|
21
|
+
import React2, { useEffect as useEffect4, useState as useState4 } from "react";
|
|
26
22
|
import { useEffect, useState } from "react";
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
24
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
25
|
+
import { jsx } from "react/jsx-runtime";
|
|
26
|
+
import { useContext as useContext2, useEffect as useEffect5 } from "react";
|
|
27
|
+
var version = "0.1.12";
|
|
28
|
+
var Logger = class {
|
|
29
|
+
localLevel = "log";
|
|
30
|
+
remoteLevel = "error";
|
|
31
|
+
remoteConfig = null;
|
|
32
|
+
levels = {
|
|
33
|
+
debug: 0,
|
|
34
|
+
info: 1,
|
|
35
|
+
log: 2,
|
|
36
|
+
warn: 3,
|
|
37
|
+
error: 4,
|
|
38
|
+
silent: 5
|
|
39
|
+
};
|
|
40
|
+
setLocalLevel(level) {
|
|
41
|
+
this.localLevel = level;
|
|
42
|
+
}
|
|
43
|
+
setRemoteLevel(level) {
|
|
44
|
+
this.remoteLevel = level;
|
|
45
|
+
}
|
|
46
|
+
configureRemote(url, params) {
|
|
47
|
+
this.remoteConfig = { url, params };
|
|
48
|
+
}
|
|
49
|
+
shouldLog(level, targetLevel) {
|
|
50
|
+
if (targetLevel === "silent") {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
return this.levels[level] >= this.levels[targetLevel];
|
|
54
|
+
}
|
|
55
|
+
logToConsole(level, ...args) {
|
|
56
|
+
if (this.shouldLog(level, this.localLevel)) {
|
|
57
|
+
if (level === "silent") {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
console[level](...args);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
logToRemote(level, ...args) {
|
|
64
|
+
if (this.remoteConfig && this.shouldLog(level, this.remoteLevel)) {
|
|
65
|
+
fetch(
|
|
66
|
+
`${this.remoteConfig.url}/log`,
|
|
67
|
+
{
|
|
68
|
+
method: "POST",
|
|
69
|
+
body: JSON.stringify({
|
|
70
|
+
...this.remoteConfig.params,
|
|
71
|
+
level,
|
|
72
|
+
message: args,
|
|
73
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
).catch((e) => {
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
debug(...args) {
|
|
81
|
+
this.logToConsole("debug", ...args);
|
|
82
|
+
this.logToRemote("debug", ...args);
|
|
83
|
+
}
|
|
84
|
+
info(...args) {
|
|
85
|
+
this.logToConsole("info", ...args);
|
|
86
|
+
this.logToRemote("info", ...args);
|
|
87
|
+
}
|
|
88
|
+
log(...args) {
|
|
89
|
+
this.logToConsole("log", ...args);
|
|
90
|
+
this.logToRemote("log", ...args);
|
|
91
|
+
}
|
|
92
|
+
warn(...args) {
|
|
93
|
+
this.logToConsole("warn", ...args);
|
|
94
|
+
this.logToRemote("warn", ...args);
|
|
95
|
+
}
|
|
96
|
+
error(...args) {
|
|
97
|
+
this.logToConsole("error", ...args);
|
|
98
|
+
this.logToRemote("error", ...args);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
var log = new Logger();
|
|
102
|
+
var log_default = log;
|
|
103
|
+
var UNRETRIABLE_ERRORS = [403, 429, 404];
|
|
104
|
+
var fetchWithTimeout = async (input, init, customFetch2) => {
|
|
105
|
+
const { timeout = 16e3, ...rest } = init || {};
|
|
32
106
|
const controller = new AbortController();
|
|
33
107
|
const id = setTimeout(() => controller.abort(), timeout);
|
|
34
108
|
try {
|
|
35
|
-
const response = await fetch(input, {
|
|
36
|
-
...
|
|
109
|
+
const response = await (customFetch2 || fetch)(input, {
|
|
110
|
+
...rest,
|
|
37
111
|
signal: controller.signal
|
|
38
112
|
});
|
|
39
|
-
clearTimeout(id);
|
|
40
113
|
return response;
|
|
41
|
-
} catch (
|
|
114
|
+
} catch (err) {
|
|
115
|
+
if (controller.signal.aborted) {
|
|
116
|
+
throw new Error(`Fetch aborted after ${timeout}ms`);
|
|
117
|
+
}
|
|
118
|
+
throw err;
|
|
119
|
+
} finally {
|
|
42
120
|
clearTimeout(id);
|
|
43
|
-
throw e;
|
|
44
121
|
}
|
|
45
122
|
};
|
|
46
|
-
var fetchRetry = async (input, init, maxRetries
|
|
123
|
+
var fetchRetry = async (input, init, singleRequestTimeout, maxRetries, onRetry, customFetch2) => {
|
|
47
124
|
let retries = 0;
|
|
48
125
|
let response;
|
|
49
|
-
let
|
|
126
|
+
let lastError = null;
|
|
50
127
|
while (retries < maxRetries) {
|
|
51
128
|
try {
|
|
52
|
-
|
|
129
|
+
const requestInit = { ...init, timeout: singleRequestTimeout };
|
|
130
|
+
response = await fetchWithTimeout(input, requestInit, customFetch2);
|
|
53
131
|
if (UNRETRIABLE_ERRORS.includes(response.status)) {
|
|
54
|
-
|
|
55
|
-
break;
|
|
132
|
+
throw new Error(`Unretriable error: ${response.statusText}`);
|
|
56
133
|
}
|
|
57
134
|
if (response.ok) {
|
|
58
135
|
return response;
|
|
@@ -60,18 +137,20 @@ var fetchRetry = async (input, init, maxRetries = 3, retryPeriod = 500) => {
|
|
|
60
137
|
throw new Error(`Failed with status ${response.status}`);
|
|
61
138
|
}
|
|
62
139
|
} catch (error) {
|
|
140
|
+
log_default.debug(`Retrying ${input} ${retries} times, error: ${error}`);
|
|
63
141
|
retries++;
|
|
64
|
-
|
|
142
|
+
lastError = error;
|
|
143
|
+
onRetry?.(error, retries);
|
|
65
144
|
}
|
|
66
145
|
}
|
|
67
|
-
|
|
68
|
-
throw unretriableError;
|
|
69
|
-
}
|
|
70
|
-
throw new Error("Failed to fetch after multiple retries");
|
|
146
|
+
throw lastError || new Error("Failed to fetch after multiple retries");
|
|
71
147
|
};
|
|
72
148
|
var fixUrl = (adserverUrl, ad) => {
|
|
73
149
|
if (ad.content) {
|
|
74
|
-
ad.content = ad.content.replace(
|
|
150
|
+
ad.content = ad.content.replace(
|
|
151
|
+
"/impression/",
|
|
152
|
+
`${adserverUrl}/impression/`
|
|
153
|
+
);
|
|
75
154
|
ad.content = ad.content.replace("/ad/", `${adserverUrl}/impression/`);
|
|
76
155
|
}
|
|
77
156
|
return { ...ad, url: `${adserverUrl}${ad.url}` };
|
|
@@ -112,6 +191,16 @@ var mergeAds = ({
|
|
|
112
191
|
}
|
|
113
192
|
return ads;
|
|
114
193
|
};
|
|
194
|
+
var loadExternalCss = (serverUrl, publisherToken, visitorId) => {
|
|
195
|
+
const visitorIdSearchParam = visitorId ? `&visitorId=${visitorId}` : "";
|
|
196
|
+
const url = `${serverUrl}/sdk/styles?publisherToken=${publisherToken}&sdkVersion=${version}${visitorIdSearchParam}`;
|
|
197
|
+
const link = document.createElement("link");
|
|
198
|
+
link.rel = "stylesheet";
|
|
199
|
+
link.type = "text/css";
|
|
200
|
+
link.href = url;
|
|
201
|
+
document.head.appendChild(link);
|
|
202
|
+
return link;
|
|
203
|
+
};
|
|
115
204
|
function mergeStyles(propStyles, defaultStyles, overridingStyles) {
|
|
116
205
|
function deepMerge(target, source) {
|
|
117
206
|
if (typeof target !== "object" || typeof source !== "object") {
|
|
@@ -133,165 +222,36 @@ function mergeStyles(propStyles, defaultStyles, overridingStyles) {
|
|
|
133
222
|
mergedStyles = deepMerge(mergedStyles, overridingStyles || {});
|
|
134
223
|
return mergedStyles;
|
|
135
224
|
}
|
|
136
|
-
var
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const regex = /(\*(.*?)\*)|\[([^\]]+)\]\(([^)]+)\)/g;
|
|
140
|
-
let match;
|
|
141
|
-
while ((match = regex.exec(text)) !== null) {
|
|
142
|
-
if (match.index > start) {
|
|
143
|
-
parts.push({ text: text.substring(start, match.index), textType: "normal" });
|
|
144
|
-
}
|
|
145
|
-
if (match[1]) {
|
|
146
|
-
const themedText = match[2];
|
|
147
|
-
const innerMatches = themedText.match(/\[([^\]]+)\]\(([^)]+)\)/g);
|
|
148
|
-
if (innerMatches) {
|
|
149
|
-
let innerStart = 0;
|
|
150
|
-
innerMatches.forEach((linkMatch) => {
|
|
151
|
-
const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/;
|
|
152
|
-
const innerLink = linkMatch.match(linkRegex);
|
|
153
|
-
const linkIndex = themedText.indexOf(linkMatch, innerStart);
|
|
154
|
-
if (linkIndex > innerStart) {
|
|
155
|
-
parts.push({ text: themedText.substring(innerStart, linkIndex), textType: "themed" });
|
|
156
|
-
}
|
|
157
|
-
parts.push({ text: innerLink[1], textType: "link", url: innerLink[2] });
|
|
158
|
-
innerStart = linkIndex + linkMatch.length;
|
|
159
|
-
});
|
|
160
|
-
if (innerStart < themedText.length) {
|
|
161
|
-
parts.push({ text: themedText.substring(innerStart), textType: "themed" });
|
|
162
|
-
}
|
|
163
|
-
} else {
|
|
164
|
-
parts.push({ text: themedText, textType: "themed" });
|
|
165
|
-
}
|
|
166
|
-
} else if (match[3] && match[4]) {
|
|
167
|
-
parts.push({ text: match[3], textType: "link", url: match[4] });
|
|
168
|
-
}
|
|
169
|
-
start = match.index + match[0].length;
|
|
170
|
-
}
|
|
171
|
-
if (start < text.length) {
|
|
172
|
-
parts.push({ text: text.substring(start), textType: "normal" });
|
|
173
|
-
}
|
|
174
|
-
return parts;
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
// src/log.ts
|
|
178
|
-
var Logger = class {
|
|
179
|
-
localLevel = "log";
|
|
180
|
-
remoteLevel = "error";
|
|
181
|
-
remoteConfig = null;
|
|
182
|
-
levels = {
|
|
183
|
-
debug: 0,
|
|
184
|
-
info: 1,
|
|
185
|
-
log: 2,
|
|
186
|
-
warn: 3,
|
|
187
|
-
error: 4,
|
|
188
|
-
silent: 5
|
|
189
|
-
};
|
|
190
|
-
setLocalLevel(level) {
|
|
191
|
-
this.localLevel = level;
|
|
192
|
-
}
|
|
193
|
-
setRemoteLevel(level) {
|
|
194
|
-
this.remoteLevel = level;
|
|
195
|
-
}
|
|
196
|
-
configureRemote(url, params) {
|
|
197
|
-
this.remoteConfig = { url, params };
|
|
198
|
-
}
|
|
199
|
-
shouldLog(level, targetLevel) {
|
|
200
|
-
if (targetLevel === "silent") {
|
|
201
|
-
return false;
|
|
202
|
-
}
|
|
203
|
-
return this.levels[level] >= this.levels[targetLevel];
|
|
204
|
-
}
|
|
205
|
-
logToConsole(level, ...args) {
|
|
206
|
-
if (this.shouldLog(level, this.localLevel)) {
|
|
207
|
-
if (level === "silent") {
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
console[level](...args);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
logToRemote(level, ...args) {
|
|
214
|
-
if (this.remoteConfig && this.shouldLog(level, this.remoteLevel)) {
|
|
215
|
-
fetch(
|
|
216
|
-
`${this.remoteConfig.url}/log`,
|
|
217
|
-
{
|
|
218
|
-
method: "POST",
|
|
219
|
-
body: JSON.stringify({
|
|
220
|
-
...this.remoteConfig.params,
|
|
221
|
-
level,
|
|
222
|
-
message: args,
|
|
223
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
224
|
-
})
|
|
225
|
-
}
|
|
226
|
-
).catch((e) => {
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
debug(...args) {
|
|
231
|
-
this.logToConsole("debug", ...args);
|
|
232
|
-
this.logToRemote("debug", ...args);
|
|
233
|
-
}
|
|
234
|
-
info(...args) {
|
|
235
|
-
this.logToConsole("info", ...args);
|
|
236
|
-
this.logToRemote("info", ...args);
|
|
237
|
-
}
|
|
238
|
-
log(...args) {
|
|
239
|
-
this.logToConsole("log", ...args);
|
|
240
|
-
this.logToRemote("log", ...args);
|
|
241
|
-
}
|
|
242
|
-
warn(...args) {
|
|
243
|
-
this.logToConsole("warn", ...args);
|
|
244
|
-
this.logToRemote("warn", ...args);
|
|
245
|
-
}
|
|
246
|
-
error(...args) {
|
|
247
|
-
this.logToConsole("error", ...args);
|
|
248
|
-
this.logToRemote("error", ...args);
|
|
249
|
-
}
|
|
250
|
-
};
|
|
251
|
-
var log = new Logger();
|
|
252
|
-
var log_default = log;
|
|
253
|
-
|
|
254
|
-
// package.json
|
|
255
|
-
var version = "0.0.9";
|
|
256
|
-
|
|
257
|
-
// src/hooks/useInitializeAds.tsx
|
|
258
|
-
var RETRY_PERIOD_MS = 500;
|
|
259
|
-
var INIT_RETRIES = 3;
|
|
260
|
-
async function initialize(adServerUrl, publisherToken, userId, conversationId, legacyVisitorId, character) {
|
|
261
|
-
log_default.log("[BRAIN] init ads started");
|
|
225
|
+
var SINGLE_INIT_TIMEOUT_BUDGET_MS = 5e3;
|
|
226
|
+
async function initialise(adServerUrl, publisherToken, visitorId, userId, conversationId, legacyVisitorId, character, customFetch2) {
|
|
227
|
+
log_default.log("[Kontext] init ads started");
|
|
262
228
|
const response = await fetchRetry(
|
|
263
229
|
`${adServerUrl}/init`,
|
|
264
230
|
{
|
|
265
|
-
timeout: 1e4,
|
|
266
231
|
method: "POST",
|
|
267
232
|
body: JSON.stringify({
|
|
268
233
|
publisherToken,
|
|
269
234
|
userId,
|
|
270
|
-
visitorId
|
|
235
|
+
visitorId,
|
|
271
236
|
conversationId,
|
|
272
|
-
sdkVersion:
|
|
237
|
+
sdkVersion: version,
|
|
273
238
|
legacyVisitorId,
|
|
274
239
|
character
|
|
275
240
|
})
|
|
276
241
|
},
|
|
277
|
-
|
|
278
|
-
|
|
242
|
+
SINGLE_INIT_TIMEOUT_BUDGET_MS,
|
|
243
|
+
3,
|
|
244
|
+
() => {
|
|
245
|
+
log_default.warn("[Kontext] Reinitialising ads");
|
|
246
|
+
},
|
|
247
|
+
customFetch2
|
|
279
248
|
);
|
|
280
|
-
const {
|
|
281
|
-
sessionId,
|
|
282
|
-
enabledPlacements,
|
|
283
|
-
ads,
|
|
284
|
-
sessionDisabled,
|
|
285
|
-
streamAdServer,
|
|
286
|
-
onlyStream,
|
|
287
|
-
defaultReactNativeStyles,
|
|
288
|
-
overridingReactNativeStyles,
|
|
289
|
-
remoteLogLevel
|
|
290
|
-
} = await response.json();
|
|
249
|
+
const { sessionId, enabledPlacements, ads, sessionDisabled, streamAdServer, onlyStream, remoteLogLevel, preloadTimeout, streamTimeout, defaultReactNativeStyles, overridingReactNativeStyles } = await response.json();
|
|
291
250
|
const fixedAds = ads.map((ad) => {
|
|
292
|
-
|
|
251
|
+
const fixedAd = fixUrl(adServerUrl, ad);
|
|
252
|
+
return fixedAd;
|
|
293
253
|
});
|
|
294
|
-
log_default.log("[
|
|
254
|
+
log_default.log("[Kontext] init ads done");
|
|
295
255
|
return {
|
|
296
256
|
sessionDisabled,
|
|
297
257
|
sessionId,
|
|
@@ -299,126 +259,127 @@ async function initialize(adServerUrl, publisherToken, userId, conversationId, l
|
|
|
299
259
|
ads: fixedAds,
|
|
300
260
|
streamAdServer,
|
|
301
261
|
onlyStream,
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
262
|
+
remoteLogLevel,
|
|
263
|
+
preloadTimeout,
|
|
264
|
+
streamTimeout,
|
|
265
|
+
defaultReactNativeStyles,
|
|
266
|
+
overridingReactNativeStyles
|
|
305
267
|
};
|
|
306
268
|
}
|
|
307
269
|
function useInitializeAds({
|
|
308
270
|
adServerUrl,
|
|
309
271
|
publisherToken,
|
|
272
|
+
visitorId,
|
|
310
273
|
userId,
|
|
311
274
|
conversationId,
|
|
312
275
|
isDisabled,
|
|
313
276
|
character,
|
|
314
|
-
legacyVisitorId
|
|
277
|
+
legacyVisitorId,
|
|
278
|
+
captureError,
|
|
279
|
+
customFetch: customFetch2,
|
|
280
|
+
reactNativePropStyles
|
|
315
281
|
}) {
|
|
316
282
|
const [enabledPlacements, setEnabledPlacements] = useState([]);
|
|
317
283
|
const [ads, setAds] = useState([]);
|
|
318
284
|
const [error, setError] = useState();
|
|
319
285
|
const [streamAdServerUrl, setStreamAdServerUrl] = useState();
|
|
320
286
|
const [onlyStream, setOnlyStream] = useState(false);
|
|
287
|
+
const [preloadTimeout, setPreloadTimeout] = useState(8e3);
|
|
288
|
+
const [streamTimeout, setStreamTimeout] = useState(5e3);
|
|
289
|
+
const [reactNativeStyles, setReactNativeStyles] = useState(null);
|
|
321
290
|
const [sessionId, setSessionId] = useState();
|
|
322
|
-
const [defaultReactNativeStyles, setDefaultReactNativeStyles] = useState();
|
|
323
|
-
const [overridingReactNativeStyles, setOverridingReactNativeStyles] = useState();
|
|
324
291
|
useEffect(() => {
|
|
325
|
-
|
|
292
|
+
setSessionId(void 0);
|
|
326
293
|
log_default.configureRemote(adServerUrl, {
|
|
327
294
|
publisherToken,
|
|
328
295
|
userId,
|
|
329
|
-
visitorId
|
|
296
|
+
visitorId,
|
|
330
297
|
conversationId,
|
|
331
298
|
character
|
|
332
299
|
});
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
log_default.
|
|
336
|
-
|
|
300
|
+
if (!isDisabled && visitorId && userId) {
|
|
301
|
+
log_default.debug("[Kontext] Initalising ads.");
|
|
302
|
+
log_default.setRemoteLevel("debug");
|
|
303
|
+
initialise(
|
|
337
304
|
adServerUrl,
|
|
338
305
|
publisherToken,
|
|
306
|
+
visitorId,
|
|
339
307
|
userId,
|
|
340
308
|
conversationId,
|
|
341
309
|
legacyVisitorId,
|
|
342
|
-
character
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
})
|
|
310
|
+
character,
|
|
311
|
+
customFetch2
|
|
312
|
+
).then(({ sessionId: sessionId2, enabledPlacements: enabledPlacements2, ads: ads2, sessionDisabled, streamAdServer, onlyStream: onlyStream2, remoteLogLevel, preloadTimeout: preloadTimeout2, streamTimeout: streamTimeout2, defaultReactNativeStyles, overridingReactNativeStyles }) => {
|
|
313
|
+
log_default.configureRemote(adServerUrl, {
|
|
314
|
+
publisherToken,
|
|
315
|
+
adServerUrl,
|
|
316
|
+
visitorId,
|
|
317
|
+
userId,
|
|
318
|
+
conversationId,
|
|
319
|
+
legacyVisitorId,
|
|
320
|
+
character,
|
|
321
|
+
sessionId: sessionId2
|
|
322
|
+
});
|
|
323
|
+
if (remoteLogLevel) {
|
|
355
324
|
log_default.setRemoteLevel(remoteLogLevel || "silent");
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
if (
|
|
366
|
-
|
|
367
|
-
setEnabledPlacements(enabledPlacements2);
|
|
368
|
-
setAds(ads2);
|
|
369
|
-
setStreamAdServerUrl(streamAdServer);
|
|
370
|
-
setOnlyStream(onlyStream2);
|
|
371
|
-
setDefaultReactNativeStyles(defaultReactNativeStylesResponse);
|
|
372
|
-
setOverridingReactNativeStyles(overridingReactNativeStylesResponse);
|
|
373
|
-
} else {
|
|
374
|
-
log_default.debug("[BRAIN] Session is disabled by server.");
|
|
325
|
+
}
|
|
326
|
+
const mergedStyles = mergeStyles(reactNativePropStyles, defaultReactNativeStyles, overridingReactNativeStyles);
|
|
327
|
+
setReactNativeStyles(mergedStyles);
|
|
328
|
+
if (!sessionDisabled) {
|
|
329
|
+
setSessionId(sessionId2);
|
|
330
|
+
setEnabledPlacements(enabledPlacements2);
|
|
331
|
+
setAds(ads2);
|
|
332
|
+
setStreamAdServerUrl(streamAdServer);
|
|
333
|
+
setOnlyStream(onlyStream2);
|
|
334
|
+
if (preloadTimeout2) {
|
|
335
|
+
setPreloadTimeout(preloadTimeout2);
|
|
375
336
|
}
|
|
337
|
+
if (streamTimeout2) {
|
|
338
|
+
setStreamTimeout(streamTimeout2);
|
|
339
|
+
}
|
|
340
|
+
} else {
|
|
341
|
+
log_default.info(`[Kontext] Session is disabled. Reason: ${sessionId2}`);
|
|
342
|
+
setSessionId(null);
|
|
343
|
+
}
|
|
344
|
+
}).catch((e) => {
|
|
345
|
+
{
|
|
346
|
+
log_default.warn("[Kontext] Error initializing ads", e);
|
|
347
|
+
setError(e.toString());
|
|
348
|
+
captureError(e);
|
|
376
349
|
}
|
|
377
|
-
).catch((e) => {
|
|
378
|
-
log_default.warn("[BRAIN] Error initializing ads", e);
|
|
379
|
-
setError(e.message);
|
|
380
350
|
});
|
|
381
351
|
} else {
|
|
382
|
-
log_default.debug("[
|
|
352
|
+
log_default.debug("[Kontext] Ads are disabled.");
|
|
353
|
+
setSessionId(null);
|
|
383
354
|
}
|
|
384
|
-
}, [
|
|
385
|
-
|
|
386
|
-
publisherToken,
|
|
387
|
-
userId,
|
|
388
|
-
conversationId,
|
|
389
|
-
isDisabled
|
|
390
|
-
]);
|
|
391
|
-
return {
|
|
392
|
-
ads,
|
|
393
|
-
sessionId,
|
|
394
|
-
enabledPlacements,
|
|
395
|
-
error,
|
|
396
|
-
streamAdServerUrl,
|
|
397
|
-
onlyStream,
|
|
398
|
-
defaultReactNativeStyles,
|
|
399
|
-
overridingReactNativeStyles
|
|
400
|
-
};
|
|
355
|
+
}, [adServerUrl, publisherToken, visitorId, userId, conversationId, isDisabled]);
|
|
356
|
+
return { ads, sessionId, enabledPlacements, error, streamAdServerUrl, onlyStream, preloadTimeout, streamTimeout, reactNativeStyles };
|
|
401
357
|
}
|
|
402
|
-
|
|
403
|
-
// src/hooks/usePreloadAds.tsx
|
|
404
|
-
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
405
358
|
function usePreloadAds({
|
|
406
|
-
userId,
|
|
407
359
|
sessionId,
|
|
408
360
|
conversationId,
|
|
409
361
|
adserverUrl,
|
|
410
362
|
messages,
|
|
411
363
|
publisherToken,
|
|
412
364
|
character,
|
|
413
|
-
onlyStream
|
|
365
|
+
onlyStream,
|
|
366
|
+
captureError,
|
|
367
|
+
preloadTimeout,
|
|
368
|
+
customFetch: customFetch2
|
|
414
369
|
}) {
|
|
415
370
|
const [preloadDone, setPreloadDone] = useState2(false);
|
|
416
371
|
const [ads, setAds] = useState2([]);
|
|
417
|
-
const
|
|
372
|
+
const lastUserMessageContent = [...messages].reverse().find((m) => m.role === "user")?.content;
|
|
373
|
+
const userMessagesContent = messages.slice(-6).filter((m) => m.role === "user").map((m) => m.content).join(" ");
|
|
374
|
+
const numberOfAssistantMessagesAtTheEnd = messages.slice().reverse().filter((m) => m.role === "assistant" || m.role === "user").findIndex((m) => m.role === "user");
|
|
375
|
+
const numberOfAssistantFollowups = Math.max(
|
|
376
|
+
0,
|
|
377
|
+
numberOfAssistantMessagesAtTheEnd - 1
|
|
378
|
+
);
|
|
418
379
|
useEffect2(() => {
|
|
419
380
|
if (onlyStream) {
|
|
420
381
|
setPreloadDone(true);
|
|
421
|
-
log_default.log("[
|
|
382
|
+
log_default.log("[Kontext] skipping preload ads");
|
|
422
383
|
return;
|
|
423
384
|
}
|
|
424
385
|
async function preload() {
|
|
@@ -426,47 +387,57 @@ function usePreloadAds({
|
|
|
426
387
|
if (!sessionId) {
|
|
427
388
|
return;
|
|
428
389
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
390
|
+
if (!lastUserMessageContent) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
log_default.log("[Kontext] preload ads started");
|
|
394
|
+
const response = await fetchWithTimeout(
|
|
395
|
+
`${adserverUrl}/preload`,
|
|
396
|
+
{
|
|
397
|
+
method: "POST",
|
|
398
|
+
timeout: preloadTimeout,
|
|
399
|
+
body: JSON.stringify({
|
|
400
|
+
messages,
|
|
401
|
+
sessionId,
|
|
402
|
+
publisherToken,
|
|
403
|
+
conversationId,
|
|
404
|
+
character,
|
|
405
|
+
sdkVersion: version
|
|
406
|
+
})
|
|
407
|
+
},
|
|
408
|
+
customFetch2
|
|
409
|
+
);
|
|
410
|
+
if (!response.ok) {
|
|
411
|
+
throw new Error("Error preloading ads. Status: " + response.status);
|
|
412
|
+
}
|
|
413
|
+
const { ads: ads2 } = await response.json();
|
|
414
|
+
ads2.forEach((ad) => {
|
|
451
415
|
setAds((oldAds) => {
|
|
452
|
-
const
|
|
453
|
-
|
|
416
|
+
const fixedAd = fixUrl(adserverUrl, ad);
|
|
417
|
+
let found = false;
|
|
418
|
+
let newAds = oldAds.map((a) => {
|
|
419
|
+
if (a.code === ad.code) {
|
|
420
|
+
found = true;
|
|
421
|
+
return fixedAd;
|
|
422
|
+
}
|
|
423
|
+
return a;
|
|
424
|
+
});
|
|
425
|
+
if (!found) {
|
|
426
|
+
newAds.push(fixedAd);
|
|
427
|
+
}
|
|
428
|
+
return newAds;
|
|
454
429
|
});
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
log_default.warn("[BRAIN] Error preloading ads", e);
|
|
459
|
-
}
|
|
430
|
+
});
|
|
431
|
+
setPreloadDone(true);
|
|
432
|
+
log_default.log("[Kontext] preload ads finished");
|
|
460
433
|
}
|
|
461
|
-
preload()
|
|
462
|
-
|
|
434
|
+
preload().catch((e) => {
|
|
435
|
+
captureError(e);
|
|
436
|
+
log_default.error("[Kontext] Error preloading ads", e);
|
|
437
|
+
});
|
|
438
|
+
}, [sessionId, userMessagesContent, numberOfAssistantFollowups]);
|
|
463
439
|
return { preloadDone, ads };
|
|
464
440
|
}
|
|
465
|
-
|
|
466
|
-
// src/hooks/useStreamAds.tsx
|
|
467
|
-
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
468
|
-
|
|
469
|
-
// src/hooks/data-stream.ts
|
|
470
441
|
var textStreamPart = {
|
|
471
442
|
code: "0",
|
|
472
443
|
name: "text",
|
|
@@ -669,12 +640,7 @@ async function* readDataStream(reader, {
|
|
|
669
640
|
const concatenatedChunks = concatChunks(chunks, totalLength);
|
|
670
641
|
totalLength = 0;
|
|
671
642
|
const streamParts2 = decoder.decode(concatenatedChunks, { stream: true }).split("\n").filter((line) => line !== "").map(parseStreamPart);
|
|
672
|
-
let i = 0;
|
|
673
643
|
for (const streamPart of streamParts2) {
|
|
674
|
-
if (!(i % 5)) {
|
|
675
|
-
await new Promise((resolve) => setTimeout(resolve));
|
|
676
|
-
}
|
|
677
|
-
i++;
|
|
678
644
|
yield streamPart;
|
|
679
645
|
}
|
|
680
646
|
if (isAborted?.()) {
|
|
@@ -683,25 +649,8 @@ async function* readDataStream(reader, {
|
|
|
683
649
|
}
|
|
684
650
|
}
|
|
685
651
|
}
|
|
686
|
-
|
|
687
|
-
// src/hooks/useStreamAds.tsx
|
|
688
|
-
import { polyfill as polyfillEncoding } from "react-native-polyfill-globals/src/encoding";
|
|
689
|
-
import { polyfill as polyfillReadableStream } from "react-native-polyfill-globals/src/readable-stream";
|
|
690
|
-
import { Platform } from "react-native";
|
|
691
|
-
var patchFetch = fetch;
|
|
692
|
-
if (Platform.OS !== "web") {
|
|
693
|
-
polyfillEncoding();
|
|
694
|
-
polyfillReadableStream();
|
|
695
|
-
patchFetch = __require("react-native-fetch-api").fetch;
|
|
696
|
-
}
|
|
697
|
-
ErrorUtils.setGlobalHandler((error, isFatal) => {
|
|
698
|
-
if (!isFatal) {
|
|
699
|
-
log_default.warn(error);
|
|
700
|
-
} else {
|
|
701
|
-
log_default.error(error);
|
|
702
|
-
}
|
|
703
|
-
});
|
|
704
652
|
function useStreamAds({
|
|
653
|
+
visitorId,
|
|
705
654
|
userId,
|
|
706
655
|
sessionId,
|
|
707
656
|
conversationId,
|
|
@@ -711,7 +660,10 @@ function useStreamAds({
|
|
|
711
660
|
preloadDone,
|
|
712
661
|
enabledPlacements,
|
|
713
662
|
character,
|
|
714
|
-
publisherToken
|
|
663
|
+
publisherToken,
|
|
664
|
+
captureError,
|
|
665
|
+
streamTimeout,
|
|
666
|
+
customFetch: customFetch2
|
|
715
667
|
}) {
|
|
716
668
|
const [ads, setAds] = useState3([]);
|
|
717
669
|
const fetchStream = async (messages2, code) => {
|
|
@@ -729,43 +681,77 @@ function useStreamAds({
|
|
|
729
681
|
return newAds;
|
|
730
682
|
});
|
|
731
683
|
const body = JSON.stringify({
|
|
684
|
+
visitorId,
|
|
732
685
|
userId,
|
|
733
|
-
visitorId: userId,
|
|
734
686
|
sessionId,
|
|
735
687
|
code,
|
|
736
688
|
messages: messages2,
|
|
737
689
|
publisherToken,
|
|
738
690
|
character,
|
|
739
691
|
conversationId,
|
|
740
|
-
sdkVersion:
|
|
692
|
+
sdkVersion: version
|
|
741
693
|
});
|
|
742
694
|
try {
|
|
743
|
-
const response = await
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
695
|
+
const response = await fetchWithTimeout(
|
|
696
|
+
`${adserverUrl}/stream`,
|
|
697
|
+
{
|
|
698
|
+
method: "POST",
|
|
699
|
+
body,
|
|
700
|
+
headers: {
|
|
701
|
+
"Content-Type": "application/json"
|
|
702
|
+
},
|
|
703
|
+
timeout: streamTimeout
|
|
748
704
|
},
|
|
749
|
-
|
|
750
|
-
|
|
705
|
+
customFetch2
|
|
706
|
+
);
|
|
751
707
|
if (!response.ok) {
|
|
752
|
-
throw new Error("Error streaming ad");
|
|
708
|
+
throw new Error("Error streaming ad. Status: " + response.status);
|
|
753
709
|
}
|
|
754
710
|
if (!response.body) {
|
|
755
|
-
throw new Error("Response body is not
|
|
711
|
+
throw new Error("Response body is not readable stream");
|
|
756
712
|
}
|
|
757
|
-
|
|
758
|
-
(oldAds) =>
|
|
759
|
-
|
|
713
|
+
if (response.status === 204) {
|
|
714
|
+
setAds((oldAds) => {
|
|
715
|
+
const newAds = oldAds.map((ad) => {
|
|
716
|
+
if (ad.messageId === lastAssistantMessage.id && ad.code === code) {
|
|
717
|
+
return {
|
|
718
|
+
...ad,
|
|
719
|
+
isLoading: false,
|
|
720
|
+
isStreaming: false
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
return ad;
|
|
724
|
+
});
|
|
725
|
+
return newAds;
|
|
726
|
+
});
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
setAds((oldAds) => {
|
|
730
|
+
const newAds = oldAds.map((ad) => {
|
|
731
|
+
if (ad.messageId === lastAssistantMessage.id && ad.code === code) {
|
|
732
|
+
return {
|
|
733
|
+
...ad,
|
|
734
|
+
isLoading: false,
|
|
735
|
+
isStreaming: true
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
return ad;
|
|
739
|
+
});
|
|
740
|
+
return newAds;
|
|
741
|
+
});
|
|
760
742
|
let data = "";
|
|
761
743
|
let adData = {};
|
|
762
|
-
log_default.log(`[
|
|
744
|
+
log_default.log(`[Kontext] streaming ${code} ad started`);
|
|
745
|
+
if (!response.body) {
|
|
746
|
+
throw new Error("Response body is not readable stream");
|
|
747
|
+
}
|
|
763
748
|
const reader = response.body.getReader();
|
|
764
749
|
for await (const { type, value } of readDataStream(reader)) {
|
|
765
750
|
switch (type) {
|
|
766
|
-
case "text":
|
|
751
|
+
case "text": {
|
|
767
752
|
data += value;
|
|
768
753
|
break;
|
|
754
|
+
}
|
|
769
755
|
case "data": {
|
|
770
756
|
let val = value;
|
|
771
757
|
if (Array.isArray(val)) {
|
|
@@ -774,11 +760,12 @@ function useStreamAds({
|
|
|
774
760
|
adData = { ...adData, ...val };
|
|
775
761
|
break;
|
|
776
762
|
}
|
|
777
|
-
case "error":
|
|
763
|
+
case "error": {
|
|
778
764
|
throw new Error(`Error streaming ad ${value}`);
|
|
765
|
+
}
|
|
779
766
|
}
|
|
780
|
-
setAds(
|
|
781
|
-
|
|
767
|
+
setAds((oldAds) => {
|
|
768
|
+
const newAds = oldAds.map((ad) => {
|
|
782
769
|
if (ad.messageId === lastAssistantMessage.id && ad.code === code) {
|
|
783
770
|
const content = adData.content ?? data;
|
|
784
771
|
const newAd = fixUrl(adserverUrl, {
|
|
@@ -787,81 +774,86 @@ function useStreamAds({
|
|
|
787
774
|
isLoading: false,
|
|
788
775
|
isStreaming: true,
|
|
789
776
|
content: content.replace(
|
|
790
|
-
new RegExp(`/impression/${adData.product.id}/redirect`, "g"),
|
|
777
|
+
new RegExp(`/(ad|impression)/${adData.product.id}/redirect`, "g"),
|
|
791
778
|
`/impression/${adData.id}/redirect`
|
|
792
779
|
)
|
|
793
780
|
});
|
|
794
781
|
return newAd;
|
|
795
782
|
}
|
|
796
783
|
return ad;
|
|
797
|
-
})
|
|
798
|
-
|
|
784
|
+
});
|
|
785
|
+
return newAds;
|
|
786
|
+
});
|
|
799
787
|
}
|
|
800
|
-
setAds(
|
|
801
|
-
|
|
802
|
-
(ad
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
788
|
+
setAds((oldAds) => {
|
|
789
|
+
const newAds = oldAds.map((ad) => {
|
|
790
|
+
if (ad.messageId === lastAssistantMessage.id && ad.code === code) {
|
|
791
|
+
return {
|
|
792
|
+
...ad,
|
|
793
|
+
isStreaming: false
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
return ad;
|
|
797
|
+
});
|
|
798
|
+
return newAds;
|
|
799
|
+
});
|
|
800
|
+
log_default.log(`[Kontext] streaming ${code} ad done`);
|
|
806
801
|
} catch (e) {
|
|
807
|
-
|
|
808
|
-
|
|
802
|
+
captureError(e);
|
|
803
|
+
log_default.error("[Kontext] Error streaming ad", e);
|
|
804
|
+
setAds((oldAds) => {
|
|
805
|
+
let found = false;
|
|
806
|
+
const newAds = oldAds.map((ad) => {
|
|
807
|
+
if (ad.messageId === lastAssistantMessage.id && ad.code === code) {
|
|
808
|
+
found = true;
|
|
809
|
+
return {
|
|
810
|
+
...ad,
|
|
811
|
+
isLoading: false,
|
|
812
|
+
isStreaming: false,
|
|
813
|
+
isError: true
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
return ad;
|
|
817
|
+
});
|
|
818
|
+
if (!found) {
|
|
819
|
+
newAds.push({
|
|
820
|
+
isLoading: false,
|
|
821
|
+
isStreaming: false,
|
|
822
|
+
isError: true,
|
|
823
|
+
code
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
return newAds;
|
|
827
|
+
});
|
|
809
828
|
}
|
|
810
829
|
};
|
|
811
830
|
useEffect3(() => {
|
|
812
|
-
if (!isLoading && sessionId && messages.length >
|
|
813
|
-
|
|
814
|
-
if (
|
|
831
|
+
if (!isLoading && sessionId && messages.length > 0 && messages[messages.length - 1]?.role === "assistant" && preloadDone) {
|
|
832
|
+
for (const placement of enabledPlacements) {
|
|
833
|
+
if (placement.format === "QUERY_STREAM" || placement.format === "INLINE_AD" || placement.format === "BOX_AD") {
|
|
815
834
|
fetchStream(messages, String(placement.code));
|
|
816
835
|
}
|
|
817
|
-
}
|
|
836
|
+
}
|
|
818
837
|
}
|
|
819
|
-
}, [isLoading, preloadDone, sessionId
|
|
838
|
+
}, [isLoading, preloadDone, sessionId]);
|
|
820
839
|
return { ads };
|
|
821
840
|
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
fetch(`${adServerUrl}/error`, {
|
|
841
|
+
var DEFAULT_AD_SERVER_URL = "https://server.megabrain.co";
|
|
842
|
+
var captureErrorFn = (error, componentStack, additionalData) => {
|
|
843
|
+
const adserverUrl = additionalData?.adserverUrl || DEFAULT_AD_SERVER_URL;
|
|
844
|
+
fetch(`${adserverUrl}/error`, {
|
|
827
845
|
method: "POST",
|
|
828
846
|
body: JSON.stringify({
|
|
829
|
-
error: error
|
|
847
|
+
error: error.message,
|
|
830
848
|
stack: componentStack,
|
|
831
|
-
|
|
849
|
+
additionalData
|
|
832
850
|
})
|
|
833
851
|
}).catch((e) => {
|
|
834
|
-
log_default.
|
|
852
|
+
log_default.error(e);
|
|
853
|
+
}).finally(() => {
|
|
854
|
+
log_default.error(error, componentStack);
|
|
835
855
|
});
|
|
836
856
|
};
|
|
837
|
-
var ErrorBoundary = class extends React.Component {
|
|
838
|
-
constructor(props) {
|
|
839
|
-
super(props);
|
|
840
|
-
this.state = {
|
|
841
|
-
hasError: false
|
|
842
|
-
};
|
|
843
|
-
}
|
|
844
|
-
static getDerivedStateFromError() {
|
|
845
|
-
return {
|
|
846
|
-
hasError: true
|
|
847
|
-
};
|
|
848
|
-
}
|
|
849
|
-
componentDidCatch(error, info) {
|
|
850
|
-
const adServerUrl = this.props.adserverUrl;
|
|
851
|
-
if (adServerUrl) {
|
|
852
|
-
captureErrorFn(adServerUrl, error, info?.componentStack, this.props.reqBodyParams);
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
render() {
|
|
856
|
-
if (this.state.hasError) {
|
|
857
|
-
return this.props.fallback || null;
|
|
858
|
-
}
|
|
859
|
-
return this.props.children;
|
|
860
|
-
}
|
|
861
|
-
};
|
|
862
|
-
|
|
863
|
-
// src/context/AdsProvider.tsx
|
|
864
|
-
import { jsx } from "react/jsx-runtime";
|
|
865
857
|
var AdsContext = React2.createContext(null);
|
|
866
858
|
AdsContext.displayName = "AdsContext";
|
|
867
859
|
var VISITOR_ID_KEY = "brain-visitor-id";
|
|
@@ -874,48 +866,89 @@ var AdsProviderWithoutBoundary = ({
|
|
|
874
866
|
isDisabled,
|
|
875
867
|
character,
|
|
876
868
|
conversationId,
|
|
869
|
+
visitorId,
|
|
877
870
|
userId,
|
|
878
871
|
logLevel,
|
|
879
872
|
onAdView,
|
|
880
873
|
onAdClick,
|
|
881
|
-
|
|
874
|
+
customFetch: customFetch2,
|
|
875
|
+
reactNativePropStyles,
|
|
876
|
+
isReactNative
|
|
882
877
|
}) => {
|
|
878
|
+
const adServerUrlOrDefault = adserverUrl || DEFAULT_AD_SERVER_URL;
|
|
879
|
+
log_default.setLocalLevel(logLevel || "silent");
|
|
880
|
+
visitorId = visitorId || userId;
|
|
883
881
|
const [viewedAds, setViewedAds] = useState4([]);
|
|
884
882
|
const [clickedAds, setClickedAds] = useState4([]);
|
|
885
|
-
const
|
|
886
|
-
|
|
883
|
+
const captureError = (error) => {
|
|
884
|
+
captureErrorFn(error, error.stack, {
|
|
885
|
+
publisherToken,
|
|
886
|
+
adserverUrl,
|
|
887
|
+
conversationId,
|
|
888
|
+
character,
|
|
889
|
+
visitorId,
|
|
890
|
+
userId,
|
|
891
|
+
isLoading,
|
|
892
|
+
messages
|
|
893
|
+
});
|
|
894
|
+
};
|
|
895
|
+
const legacyVisitorId = typeof window !== "undefined" && typeof window.localStorage !== "undefined" && localStorage.getItem(VISITOR_ID_KEY) ? localStorage.getItem(VISITOR_ID_KEY) : void 0;
|
|
896
|
+
useEffect4(() => {
|
|
897
|
+
if (isReactNative) {
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
const linkElement = loadExternalCss(adServerUrlOrDefault, publisherToken, visitorId);
|
|
901
|
+
return () => {
|
|
902
|
+
try {
|
|
903
|
+
document.head.removeChild(linkElement);
|
|
904
|
+
} catch (e) {
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
}, [adServerUrlOrDefault, publisherToken, visitorId, isReactNative]);
|
|
887
908
|
const {
|
|
888
909
|
ads: initAds,
|
|
889
910
|
sessionId,
|
|
890
911
|
enabledPlacements,
|
|
891
|
-
error,
|
|
912
|
+
error: initError,
|
|
892
913
|
streamAdServerUrl,
|
|
893
914
|
onlyStream,
|
|
894
|
-
|
|
895
|
-
|
|
915
|
+
preloadTimeout,
|
|
916
|
+
streamTimeout,
|
|
917
|
+
reactNativeStyles
|
|
896
918
|
} = useInitializeAds({
|
|
897
919
|
adServerUrl: adServerUrlOrDefault,
|
|
898
920
|
publisherToken,
|
|
899
921
|
userId,
|
|
900
|
-
|
|
922
|
+
visitorId,
|
|
923
|
+
legacyVisitorId,
|
|
901
924
|
conversationId,
|
|
902
925
|
character,
|
|
903
|
-
isDisabled: !!isDisabled
|
|
926
|
+
isDisabled: !!isDisabled,
|
|
927
|
+
captureError,
|
|
928
|
+
customFetch: customFetch2,
|
|
929
|
+
reactNativePropStyles
|
|
904
930
|
});
|
|
905
|
-
const
|
|
906
|
-
const
|
|
907
|
-
|
|
931
|
+
const isInitialised = !!isDisabled || !!initError || !!sessionId || sessionId === null;
|
|
932
|
+
const {
|
|
933
|
+
preloadDone,
|
|
934
|
+
ads: preloadAds
|
|
935
|
+
} = usePreloadAds({
|
|
908
936
|
sessionId,
|
|
909
937
|
adserverUrl: adServerUrlOrDefault,
|
|
910
938
|
messages,
|
|
911
939
|
publisherToken,
|
|
912
940
|
conversationId,
|
|
913
941
|
userId,
|
|
942
|
+
visitorId,
|
|
914
943
|
character,
|
|
915
|
-
onlyStream
|
|
944
|
+
onlyStream,
|
|
945
|
+
captureError,
|
|
946
|
+
preloadTimeout,
|
|
947
|
+
customFetch: customFetch2
|
|
916
948
|
});
|
|
917
949
|
const { ads: streamAds } = useStreamAds({
|
|
918
950
|
userId,
|
|
951
|
+
visitorId,
|
|
919
952
|
sessionId,
|
|
920
953
|
adserverUrl: onlyStream && streamAdServerUrl ? streamAdServerUrl : adServerUrlOrDefault,
|
|
921
954
|
conversationId,
|
|
@@ -924,23 +957,28 @@ var AdsProviderWithoutBoundary = ({
|
|
|
924
957
|
character,
|
|
925
958
|
preloadDone,
|
|
926
959
|
enabledPlacements,
|
|
927
|
-
publisherToken
|
|
960
|
+
publisherToken,
|
|
961
|
+
captureError,
|
|
962
|
+
streamTimeout,
|
|
963
|
+
customFetch: customFetch2
|
|
928
964
|
});
|
|
929
965
|
const ads = mergeAds({ initAds, preloadAds, streamAds, viewedAds, clickedAds });
|
|
930
966
|
const markAdAsViewed = (ad) => {
|
|
931
|
-
log_default.debug("[Brain] Calling onAdView");
|
|
932
967
|
onAdView && onAdView({
|
|
933
968
|
id: ad.id,
|
|
934
969
|
code: ad.code,
|
|
935
970
|
messageId: ad.messageId,
|
|
936
971
|
content: ad.content
|
|
937
972
|
});
|
|
938
|
-
if (!ad.id)
|
|
939
|
-
|
|
973
|
+
if (!ad.id) {
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
976
|
+
if (viewedAds.includes(ad.id)) {
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
940
979
|
setViewedAds((old) => [...old, ad.id]);
|
|
941
980
|
};
|
|
942
981
|
const onAdClickInternal = (ad) => {
|
|
943
|
-
log_default.debug("[Brain] Calling onAdClick");
|
|
944
982
|
onAdClick && onAdClick({
|
|
945
983
|
id: ad.id,
|
|
946
984
|
code: ad.code,
|
|
@@ -963,81 +1001,73 @@ var AdsProviderWithoutBoundary = ({
|
|
|
963
1001
|
streamAdServerUrl,
|
|
964
1002
|
children,
|
|
965
1003
|
messages,
|
|
1004
|
+
conversationId,
|
|
966
1005
|
publisherToken,
|
|
967
1006
|
isLoading,
|
|
968
1007
|
ads,
|
|
969
1008
|
sessionId,
|
|
970
1009
|
isInitialised,
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
markAdAsViewed,
|
|
977
|
-
onlyStream,
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
};
|
|
984
|
-
var AdsProvider = ({
|
|
985
|
-
children,
|
|
986
|
-
messages,
|
|
987
|
-
publisherToken,
|
|
988
|
-
isLoading,
|
|
989
|
-
adserverUrl,
|
|
990
|
-
isDisabled,
|
|
991
|
-
character,
|
|
992
|
-
conversationId,
|
|
993
|
-
userId,
|
|
994
|
-
logLevel,
|
|
995
|
-
onAdView,
|
|
996
|
-
onAdClick,
|
|
997
|
-
...props
|
|
998
|
-
}) => {
|
|
999
|
-
const adServerUrlOrDefault = adserverUrl || "https://server.megabrain.co";
|
|
1000
|
-
return /* @__PURE__ */ jsx(
|
|
1001
|
-
ErrorBoundary,
|
|
1002
|
-
{
|
|
1003
|
-
fallback: children,
|
|
1004
|
-
adserverUrl: adServerUrlOrDefault,
|
|
1005
|
-
reqBodyParams: {
|
|
1006
|
-
publisherToken,
|
|
1007
|
-
adserverUrl,
|
|
1008
|
-
conversationId,
|
|
1009
|
-
character,
|
|
1010
|
-
userId,
|
|
1011
|
-
isLoading,
|
|
1012
|
-
messages
|
|
1013
|
-
},
|
|
1014
|
-
children: /* @__PURE__ */ jsx(
|
|
1015
|
-
AdsProviderWithoutBoundary,
|
|
1016
|
-
{
|
|
1017
|
-
children,
|
|
1018
|
-
messages,
|
|
1019
|
-
publisherToken,
|
|
1020
|
-
isLoading,
|
|
1021
|
-
adserverUrl,
|
|
1022
|
-
isDisabled,
|
|
1023
|
-
character,
|
|
1024
|
-
conversationId,
|
|
1025
|
-
userId,
|
|
1026
|
-
logLevel,
|
|
1027
|
-
onAdView,
|
|
1028
|
-
onAdClick,
|
|
1029
|
-
...props
|
|
1030
|
-
}
|
|
1031
|
-
)
|
|
1010
|
+
isDisabled,
|
|
1011
|
+
onAdClickInternal,
|
|
1012
|
+
enabledPlacements,
|
|
1013
|
+
userId,
|
|
1014
|
+
visitorId,
|
|
1015
|
+
markAdAsViewed,
|
|
1016
|
+
onlyStream,
|
|
1017
|
+
preloadTimeout,
|
|
1018
|
+
streamTimeout,
|
|
1019
|
+
reactNativeStyles
|
|
1020
|
+
},
|
|
1021
|
+
children
|
|
1032
1022
|
}
|
|
1033
1023
|
);
|
|
1034
1024
|
};
|
|
1035
|
-
|
|
1036
|
-
// src/hooks/useAdViewed.tsx
|
|
1037
|
-
import { useContext } from "react";
|
|
1038
|
-
function useAdViewed(ad) {
|
|
1025
|
+
function useAd({ code, messageId }) {
|
|
1039
1026
|
const context = useContext(AdsContext);
|
|
1040
|
-
|
|
1027
|
+
if (!context) {
|
|
1028
|
+
return null;
|
|
1029
|
+
}
|
|
1030
|
+
const ad = context.ads.find((ad2) => {
|
|
1031
|
+
if (messageId) {
|
|
1032
|
+
return ad2.code === code && ad2.messageId === messageId;
|
|
1033
|
+
}
|
|
1034
|
+
return ad2.code === code;
|
|
1035
|
+
});
|
|
1036
|
+
if (!ad) {
|
|
1037
|
+
return null;
|
|
1038
|
+
}
|
|
1039
|
+
const placement = context.enabledPlacements.find((p) => p.code === code);
|
|
1040
|
+
if (!placement) {
|
|
1041
|
+
return null;
|
|
1042
|
+
}
|
|
1043
|
+
const dependencies = placement.config.dependencies?.split(",").map((d) => d.trim()).filter((d) => d);
|
|
1044
|
+
if (!dependencies || dependencies.length === 0) {
|
|
1045
|
+
return ad;
|
|
1046
|
+
}
|
|
1047
|
+
const dependencyAds = context.enabledPlacements.filter(
|
|
1048
|
+
(p) => dependencies.includes(p.code)
|
|
1049
|
+
);
|
|
1050
|
+
if (!dependencyAds.length) {
|
|
1051
|
+
return ad;
|
|
1052
|
+
}
|
|
1053
|
+
const allAdsLoadedAndNotStreaming = dependencyAds.every((p) => {
|
|
1054
|
+
let a;
|
|
1055
|
+
if (messageId) {
|
|
1056
|
+
a = context.ads.find(
|
|
1057
|
+
(ad2) => ad2.code === p.code && ad2.messageId === messageId
|
|
1058
|
+
);
|
|
1059
|
+
} else {
|
|
1060
|
+
a = context.ads.find((ad2) => ad2.code === p.code);
|
|
1061
|
+
}
|
|
1062
|
+
return a && !a.isLoading && !a.isStreaming || a && a.isError;
|
|
1063
|
+
});
|
|
1064
|
+
if (!allAdsLoadedAndNotStreaming) {
|
|
1065
|
+
return null;
|
|
1066
|
+
}
|
|
1067
|
+
return ad;
|
|
1068
|
+
}
|
|
1069
|
+
function useAdViewed(ad, ref) {
|
|
1070
|
+
const context = useContext2(AdsContext);
|
|
1041
1071
|
const sendRequest = async () => {
|
|
1042
1072
|
if (!context?.adserverUrl || !ad?.id) {
|
|
1043
1073
|
return;
|
|
@@ -1054,43 +1084,95 @@ function useAdViewed(ad) {
|
|
|
1054
1084
|
if (!response.ok) {
|
|
1055
1085
|
throw new Error("Error sending view request");
|
|
1056
1086
|
}
|
|
1057
|
-
log_default.log("[
|
|
1087
|
+
log_default.log("[Kontext] ad marked as viewed", ad.id, ad.code);
|
|
1058
1088
|
} catch (e) {
|
|
1059
|
-
log_default.
|
|
1089
|
+
log_default.error("[Kontext] Error sending view request", e);
|
|
1060
1090
|
}
|
|
1061
1091
|
};
|
|
1062
|
-
|
|
1063
|
-
if (!ad || ad.isError || ad.isLoading || ad.isStreaming || ad.viewed
|
|
1092
|
+
useEffect5(() => {
|
|
1093
|
+
if (!ref?.current || !ad || !context?.visitorId || !context?.userId || ad.isError || ad.isLoading || ad.isStreaming || ad.viewed) {
|
|
1064
1094
|
return;
|
|
1065
1095
|
}
|
|
1066
|
-
|
|
1067
|
-
setTimeout(() => {
|
|
1068
|
-
log_default.log("[BRAIN] setting setStillMounted", ad.id, ad.code);
|
|
1069
|
-
setStillMounted(true);
|
|
1070
|
-
}, 1e3);
|
|
1071
|
-
}, [ad]);
|
|
1072
|
-
useEffect4(() => {
|
|
1073
|
-
if (stillMounted) {
|
|
1074
|
-
log_default.log("[BRAIN] sending request");
|
|
1096
|
+
if (typeof window.IntersectionObserver === "undefined") {
|
|
1075
1097
|
sendRequest();
|
|
1098
|
+
return;
|
|
1076
1099
|
}
|
|
1077
|
-
|
|
1100
|
+
const observer = new window.IntersectionObserver((entries, observer2) => {
|
|
1101
|
+
entries.forEach((entry) => {
|
|
1102
|
+
if (entry.isIntersecting) {
|
|
1103
|
+
sendRequest();
|
|
1104
|
+
observer2.unobserve(entry.target);
|
|
1105
|
+
}
|
|
1106
|
+
});
|
|
1107
|
+
});
|
|
1108
|
+
observer.observe(ref?.current);
|
|
1109
|
+
return () => {
|
|
1110
|
+
observer.disconnect();
|
|
1111
|
+
};
|
|
1112
|
+
}, [ad]);
|
|
1078
1113
|
}
|
|
1079
1114
|
|
|
1080
1115
|
// src/components/MarkdownText.tsx
|
|
1081
|
-
import { useContext as
|
|
1116
|
+
import { useContext as useContext3 } from "react";
|
|
1082
1117
|
import { Linking, Pressable, Text } from "react-native";
|
|
1118
|
+
|
|
1119
|
+
// src/utils.ts
|
|
1120
|
+
var getStyles = (context) => {
|
|
1121
|
+
return context.reactNativeStyles;
|
|
1122
|
+
};
|
|
1123
|
+
var parseMessageText = (text) => {
|
|
1124
|
+
const parts = [];
|
|
1125
|
+
let start = 0;
|
|
1126
|
+
const regex = /(\*(.*?)\*)|\[([^\]]+)\]\(([^)]+)\)/g;
|
|
1127
|
+
let match;
|
|
1128
|
+
while ((match = regex.exec(text)) !== null) {
|
|
1129
|
+
if (match.index > start) {
|
|
1130
|
+
parts.push({ text: text.substring(start, match.index), textType: "normal" });
|
|
1131
|
+
}
|
|
1132
|
+
if (match[1]) {
|
|
1133
|
+
const themedText = match[2];
|
|
1134
|
+
const innerMatches = themedText.match(/\[([^\]]+)\]\(([^)]+)\)/g);
|
|
1135
|
+
if (innerMatches) {
|
|
1136
|
+
let innerStart = 0;
|
|
1137
|
+
innerMatches.forEach((linkMatch) => {
|
|
1138
|
+
const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/;
|
|
1139
|
+
const innerLink = linkMatch.match(linkRegex);
|
|
1140
|
+
const linkIndex = themedText.indexOf(linkMatch, innerStart);
|
|
1141
|
+
if (linkIndex > innerStart) {
|
|
1142
|
+
parts.push({ text: themedText.substring(innerStart, linkIndex), textType: "themed" });
|
|
1143
|
+
}
|
|
1144
|
+
parts.push({ text: innerLink[1], textType: "link", url: innerLink[2] });
|
|
1145
|
+
innerStart = linkIndex + linkMatch.length;
|
|
1146
|
+
});
|
|
1147
|
+
if (innerStart < themedText.length) {
|
|
1148
|
+
parts.push({ text: themedText.substring(innerStart), textType: "themed" });
|
|
1149
|
+
}
|
|
1150
|
+
} else {
|
|
1151
|
+
parts.push({ text: themedText, textType: "themed" });
|
|
1152
|
+
}
|
|
1153
|
+
} else if (match[3] && match[4]) {
|
|
1154
|
+
parts.push({ text: match[3], textType: "link", url: match[4] });
|
|
1155
|
+
}
|
|
1156
|
+
start = match.index + match[0].length;
|
|
1157
|
+
}
|
|
1158
|
+
if (start < text.length) {
|
|
1159
|
+
parts.push({ text: text.substring(start), textType: "normal" });
|
|
1160
|
+
}
|
|
1161
|
+
return parts;
|
|
1162
|
+
};
|
|
1163
|
+
|
|
1164
|
+
// src/components/MarkdownText.tsx
|
|
1083
1165
|
import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
|
|
1084
1166
|
function MarkdownText({
|
|
1085
1167
|
content,
|
|
1086
1168
|
onLinkClick
|
|
1087
1169
|
}) {
|
|
1088
|
-
const context =
|
|
1170
|
+
const context = useContext3(AdsContext);
|
|
1089
1171
|
const textParts = parseMessageText(content);
|
|
1090
|
-
const styles = context?.
|
|
1172
|
+
const styles = getStyles(context)?.markdownText;
|
|
1091
1173
|
const linkClickHandler = (href) => {
|
|
1092
1174
|
onLinkClick();
|
|
1093
|
-
Linking.openURL(href).catch((err) =>
|
|
1175
|
+
Linking.openURL(href).catch((err) => log.warn("Failed to open URL:", err));
|
|
1094
1176
|
return false;
|
|
1095
1177
|
};
|
|
1096
1178
|
return /* @__PURE__ */ jsx2(Fragment, { children: textParts.map((t, i) => {
|
|
@@ -1118,17 +1200,18 @@ function MarkdownText({
|
|
|
1118
1200
|
|
|
1119
1201
|
// src/components/VideoPlayer.tsx
|
|
1120
1202
|
import { ResizeMode, Video } from "expo-av";
|
|
1121
|
-
import { useContext as
|
|
1203
|
+
import { useContext as useContext5, useEffect as useEffect7, useRef, useState as useState6 } from "react";
|
|
1122
1204
|
import { Linking as Linking2, Text as Text2, TouchableOpacity, View as View2 } from "react-native";
|
|
1123
1205
|
|
|
1124
1206
|
// src/components/VideoProgressBar.tsx
|
|
1125
|
-
import { useState as
|
|
1207
|
+
import { useState as useState5, useEffect as useEffect6, useContext as useContext4 } from "react";
|
|
1126
1208
|
import { View } from "react-native";
|
|
1127
1209
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1128
1210
|
function VideoProgressBar({ videoRef }) {
|
|
1129
|
-
const [progress, setProgress] =
|
|
1130
|
-
const
|
|
1131
|
-
|
|
1211
|
+
const [progress, setProgress] = useState5(0);
|
|
1212
|
+
const context = useContext4(AdsContext);
|
|
1213
|
+
const styles = getStyles(context)?.videoPlayer?.videoProgress;
|
|
1214
|
+
useEffect6(() => {
|
|
1132
1215
|
const interval = setInterval(() => {
|
|
1133
1216
|
if (!videoRef.current) {
|
|
1134
1217
|
return;
|
|
@@ -1162,13 +1245,14 @@ var VideoPlayer = ({
|
|
|
1162
1245
|
onLinkClick
|
|
1163
1246
|
}) => {
|
|
1164
1247
|
const videoRef = useRef(null);
|
|
1165
|
-
const [isPlaying, setIsPlaying] =
|
|
1166
|
-
const [isPaused, setIsPaused] =
|
|
1167
|
-
const [isEnded, setIsEnded] =
|
|
1168
|
-
const [showDownloadBadge, setShowDownloadBadge] =
|
|
1248
|
+
const [isPlaying, setIsPlaying] = useState6(false);
|
|
1249
|
+
const [isPaused, setIsPaused] = useState6(true);
|
|
1250
|
+
const [isEnded, setIsEnded] = useState6(false);
|
|
1251
|
+
const [showDownloadBadge, setShowDownloadBadge] = useState6(false);
|
|
1169
1252
|
const lastCallbackTimeRef = useRef(0);
|
|
1170
|
-
const
|
|
1171
|
-
|
|
1253
|
+
const context = useContext5(AdsContext);
|
|
1254
|
+
const styles = getStyles(context)?.videoPlayer;
|
|
1255
|
+
useEffect7(() => {
|
|
1172
1256
|
const interval = setInterval(() => {
|
|
1173
1257
|
if (videoRef.current) {
|
|
1174
1258
|
videoRef.current.getStatusAsync().then((status) => {
|
|
@@ -1212,7 +1296,7 @@ var VideoPlayer = ({
|
|
|
1212
1296
|
};
|
|
1213
1297
|
const handleLinkClick = (url) => {
|
|
1214
1298
|
if (url) {
|
|
1215
|
-
Linking2.openURL(url).catch((err) =>
|
|
1299
|
+
Linking2.openURL(url).catch((err) => log.warn("Failed to open URL:", err));
|
|
1216
1300
|
onLinkClick();
|
|
1217
1301
|
}
|
|
1218
1302
|
};
|
|
@@ -1250,62 +1334,15 @@ var VideoPlayer = ({
|
|
|
1250
1334
|
] });
|
|
1251
1335
|
};
|
|
1252
1336
|
|
|
1253
|
-
// src/hooks/useAd.tsx
|
|
1254
|
-
import { useContext as useContext5 } from "react";
|
|
1255
|
-
function useAd({ code, messageId }) {
|
|
1256
|
-
const context = useContext5(AdsContext);
|
|
1257
|
-
if (!context) {
|
|
1258
|
-
return null;
|
|
1259
|
-
}
|
|
1260
|
-
const ad = context.ads.find((ad2) => {
|
|
1261
|
-
if (messageId) {
|
|
1262
|
-
return ad2.code === code && ad2.messageId === messageId;
|
|
1263
|
-
}
|
|
1264
|
-
return ad2.code === code;
|
|
1265
|
-
});
|
|
1266
|
-
if (!ad) {
|
|
1267
|
-
return null;
|
|
1268
|
-
}
|
|
1269
|
-
const placement = context.enabledPlacements.find((p) => p.code === code);
|
|
1270
|
-
if (!placement) {
|
|
1271
|
-
return null;
|
|
1272
|
-
}
|
|
1273
|
-
const dependencies = placement.config.dependencies?.split(",").map((d) => d.trim()).filter((d) => d);
|
|
1274
|
-
if (!dependencies || dependencies.length === 0) {
|
|
1275
|
-
return ad;
|
|
1276
|
-
}
|
|
1277
|
-
const dependencyAds = context.enabledPlacements.filter(
|
|
1278
|
-
(p) => dependencies.includes(p.code)
|
|
1279
|
-
);
|
|
1280
|
-
if (!dependencyAds.length) {
|
|
1281
|
-
return ad;
|
|
1282
|
-
}
|
|
1283
|
-
const allAdsLoadedAndNotStreaming = dependencyAds.every((p) => {
|
|
1284
|
-
let a;
|
|
1285
|
-
if (messageId) {
|
|
1286
|
-
a = context.ads.find(
|
|
1287
|
-
(ad2) => ad2.code === p.code && ad2.messageId === messageId
|
|
1288
|
-
);
|
|
1289
|
-
} else {
|
|
1290
|
-
a = context.ads.find((ad2) => ad2.code === p.code);
|
|
1291
|
-
}
|
|
1292
|
-
return a && !a.isLoading && !a.isStreaming || a && a.isError;
|
|
1293
|
-
});
|
|
1294
|
-
if (!allAdsLoadedAndNotStreaming) {
|
|
1295
|
-
return null;
|
|
1296
|
-
}
|
|
1297
|
-
return ad;
|
|
1298
|
-
}
|
|
1299
|
-
|
|
1300
1337
|
// src/formats/InlineAd.tsx
|
|
1301
1338
|
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1302
1339
|
var InlineAd = ({ code, messageId, wrapper }) => {
|
|
1303
1340
|
const ad = useAd({ code, messageId });
|
|
1304
|
-
const [linkIncluded, setLinkIncluded] =
|
|
1341
|
+
const [linkIncluded, setLinkIncluded] = useState7(false);
|
|
1305
1342
|
const context = useContext6(AdsContext);
|
|
1306
|
-
const styles = context?.
|
|
1343
|
+
const styles = getStyles(context)?.inlineAd;
|
|
1307
1344
|
useAdViewed(ad);
|
|
1308
|
-
|
|
1345
|
+
useEffect8(() => {
|
|
1309
1346
|
if (ad?.content && !ad.isStreaming && !ad.content.match(/\[.*?\]\(.*?\)/) && !linkIncluded) {
|
|
1310
1347
|
setLinkIncluded(true);
|
|
1311
1348
|
}
|
|
@@ -1314,16 +1351,16 @@ var InlineAd = ({ code, messageId, wrapper }) => {
|
|
|
1314
1351
|
if (ad.isLoading || ad.content?.trim().toLowerCase().includes("none"))
|
|
1315
1352
|
return null;
|
|
1316
1353
|
const onProgress = (progress) => {
|
|
1317
|
-
|
|
1354
|
+
log.log(`Progress: ${progress}`);
|
|
1318
1355
|
};
|
|
1319
1356
|
const handleImageClick = (url) => {
|
|
1320
1357
|
if (url) {
|
|
1321
1358
|
context?.onAdClickInternal(ad);
|
|
1322
|
-
if (
|
|
1359
|
+
if (Platform.OS === "web") {
|
|
1323
1360
|
window.open(url, "_blank");
|
|
1324
1361
|
} else {
|
|
1325
1362
|
Linking3.openURL(url).catch(
|
|
1326
|
-
(err) =>
|
|
1363
|
+
(err) => log.warn("Failed to open URL:", err)
|
|
1327
1364
|
);
|
|
1328
1365
|
}
|
|
1329
1366
|
}
|
|
@@ -1391,10 +1428,122 @@ var InlineAd = ({ code, messageId, wrapper }) => {
|
|
|
1391
1428
|
return wrapper ? wrapper(content) : content;
|
|
1392
1429
|
};
|
|
1393
1430
|
var InlineAd_default = InlineAd;
|
|
1431
|
+
|
|
1432
|
+
// src/components/ErrorBoundary.tsx
|
|
1433
|
+
import React5 from "react";
|
|
1434
|
+
var captureErrorFn2 = (adServerUrl, error, componentStack, context) => {
|
|
1435
|
+
fetch(`${adServerUrl}/error`, {
|
|
1436
|
+
method: "POST",
|
|
1437
|
+
body: JSON.stringify({
|
|
1438
|
+
error: error?.message,
|
|
1439
|
+
stack: componentStack,
|
|
1440
|
+
context
|
|
1441
|
+
})
|
|
1442
|
+
}).catch((e) => {
|
|
1443
|
+
log.warn("Error reporting client error", e);
|
|
1444
|
+
});
|
|
1445
|
+
};
|
|
1446
|
+
var ErrorBoundary = class extends React5.Component {
|
|
1447
|
+
constructor(props) {
|
|
1448
|
+
super(props);
|
|
1449
|
+
this.state = {
|
|
1450
|
+
hasError: false
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
static getDerivedStateFromError() {
|
|
1454
|
+
return {
|
|
1455
|
+
hasError: true
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1458
|
+
componentDidCatch(error, info) {
|
|
1459
|
+
const adServerUrl = this.props.adserverUrl;
|
|
1460
|
+
if (adServerUrl) {
|
|
1461
|
+
captureErrorFn2(adServerUrl, error, info?.componentStack, this.props.reqBodyParams);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
render() {
|
|
1465
|
+
if (this.state.hasError) {
|
|
1466
|
+
return this.props.fallback || null;
|
|
1467
|
+
}
|
|
1468
|
+
return this.props.children;
|
|
1469
|
+
}
|
|
1470
|
+
};
|
|
1471
|
+
|
|
1472
|
+
// src/context/AdsProvider.tsx
|
|
1473
|
+
import { Platform as Platform2 } from "react-native";
|
|
1474
|
+
import { polyfill as polyfillEncoding } from "react-native-polyfill-globals/src/encoding";
|
|
1475
|
+
import { polyfill as polyfillReadableStream } from "react-native-polyfill-globals/src/readable-stream";
|
|
1476
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
1477
|
+
var VISITOR_ID_KEY2 = "brain-visitor-id";
|
|
1478
|
+
var customFetch = fetch;
|
|
1479
|
+
if (Platform2.OS !== "web") {
|
|
1480
|
+
polyfillEncoding();
|
|
1481
|
+
polyfillReadableStream();
|
|
1482
|
+
customFetch = __require("react-native-fetch-api").fetch;
|
|
1483
|
+
}
|
|
1484
|
+
ErrorUtils.setGlobalHandler((error, isFatal) => {
|
|
1485
|
+
if (!isFatal) {
|
|
1486
|
+
log.warn(error);
|
|
1487
|
+
} else {
|
|
1488
|
+
log.error(error);
|
|
1489
|
+
}
|
|
1490
|
+
});
|
|
1491
|
+
var AdsProvider = ({
|
|
1492
|
+
children,
|
|
1493
|
+
messages,
|
|
1494
|
+
publisherToken,
|
|
1495
|
+
isLoading,
|
|
1496
|
+
adserverUrl,
|
|
1497
|
+
isDisabled,
|
|
1498
|
+
character,
|
|
1499
|
+
conversationId,
|
|
1500
|
+
userId,
|
|
1501
|
+
logLevel,
|
|
1502
|
+
onAdView,
|
|
1503
|
+
onAdClick,
|
|
1504
|
+
styles
|
|
1505
|
+
}) => {
|
|
1506
|
+
const adServerUrlOrDefault = adserverUrl || "https://server.megabrain.co";
|
|
1507
|
+
return /* @__PURE__ */ jsx6(
|
|
1508
|
+
ErrorBoundary,
|
|
1509
|
+
{
|
|
1510
|
+
fallback: children,
|
|
1511
|
+
adserverUrl: adServerUrlOrDefault,
|
|
1512
|
+
reqBodyParams: {
|
|
1513
|
+
publisherToken,
|
|
1514
|
+
adserverUrl,
|
|
1515
|
+
conversationId,
|
|
1516
|
+
character,
|
|
1517
|
+
userId,
|
|
1518
|
+
isLoading,
|
|
1519
|
+
messages
|
|
1520
|
+
},
|
|
1521
|
+
children: /* @__PURE__ */ jsx6(
|
|
1522
|
+
AdsProviderWithoutBoundary,
|
|
1523
|
+
{
|
|
1524
|
+
children,
|
|
1525
|
+
messages,
|
|
1526
|
+
publisherToken,
|
|
1527
|
+
isLoading,
|
|
1528
|
+
adserverUrl,
|
|
1529
|
+
isDisabled,
|
|
1530
|
+
character,
|
|
1531
|
+
conversationId,
|
|
1532
|
+
userId,
|
|
1533
|
+
logLevel,
|
|
1534
|
+
onAdView,
|
|
1535
|
+
onAdClick,
|
|
1536
|
+
reactNativePropStyles: styles,
|
|
1537
|
+
customFetch,
|
|
1538
|
+
isReactNative: true
|
|
1539
|
+
}
|
|
1540
|
+
)
|
|
1541
|
+
}
|
|
1542
|
+
);
|
|
1543
|
+
};
|
|
1394
1544
|
export {
|
|
1395
|
-
AdsContext,
|
|
1396
1545
|
AdsProvider,
|
|
1397
1546
|
InlineAd_default as InlineAd,
|
|
1398
|
-
VISITOR_ID_KEY,
|
|
1547
|
+
VISITOR_ID_KEY2 as VISITOR_ID_KEY,
|
|
1399
1548
|
useAd
|
|
1400
1549
|
};
|