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