@magicfeedback/popup-sdk 1.1.8 → 1.3.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/README.md +113 -70
- package/dist/assets/assets/style.css +5 -1
- package/dist/chunk-R4B3K2ZW.mjs +176 -0
- package/dist/chunk-R4B3K2ZW.mjs.map +1 -0
- package/dist/chunk-XFA2Y6CK.mjs +197 -0
- package/dist/chunk-XFA2Y6CK.mjs.map +1 -0
- package/dist/index.d.mts +130 -14
- package/dist/index.d.ts +130 -14
- package/dist/index.js +426 -910
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +416 -44
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.d.mts +60 -8
- package/dist/react-native.d.ts +60 -8
- package/dist/react-native.js +425 -911
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +415 -45
- package/dist/react-native.mjs.map +1 -1
- package/dist/{renderPopup-EZKDMLVZ.mjs → renderPopup-NJK7Z46E.mjs} +10 -870
- package/dist/renderPopup-NJK7Z46E.mjs.map +1 -0
- package/dist/{renderPopup-PS3NJDUR.mjs → renderPopup-ZYXOUBCP.mjs} +10 -870
- package/dist/renderPopup-ZYXOUBCP.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-4UXOEIAB.mjs +0 -172
- package/dist/chunk-4UXOEIAB.mjs.map +0 -1
- package/dist/chunk-XOTM5CHX.mjs +0 -193
- package/dist/chunk-XOTM5CHX.mjs.map +0 -1
- package/dist/renderPopup-EZKDMLVZ.mjs.map +0 -1
- package/dist/renderPopup-PS3NJDUR.mjs.map +0 -1
package/dist/react-native.mjs
CHANGED
|
@@ -7,8 +7,9 @@ import {
|
|
|
7
7
|
buildSurveyIdentity,
|
|
8
8
|
createDefaultStorage,
|
|
9
9
|
sdkWarn,
|
|
10
|
-
setLogger
|
|
11
|
-
|
|
10
|
+
setLogger,
|
|
11
|
+
style_default
|
|
12
|
+
} from "./chunk-R4B3K2ZW.mjs";
|
|
12
13
|
|
|
13
14
|
// src/react-native/index.tsx
|
|
14
15
|
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
|
@@ -200,6 +201,15 @@ function resolveEnvironment(nodeEnv) {
|
|
|
200
201
|
}
|
|
201
202
|
|
|
202
203
|
// src/ui/surveyHtml.ts
|
|
204
|
+
var POSITION_MAP = {
|
|
205
|
+
center: { justifyContent: "center", alignItems: "center", padding: "0", background: "rgba(0,0,0,0.5)" },
|
|
206
|
+
bottom: { justifyContent: "center", alignItems: "flex-end", padding: "16px", background: "transparent" },
|
|
207
|
+
"bottom-right": { justifyContent: "flex-end", alignItems: "flex-end", padding: "16px", background: "transparent" },
|
|
208
|
+
"bottom-left": { justifyContent: "flex-start", alignItems: "flex-end", padding: "16px", background: "transparent" },
|
|
209
|
+
top: { justifyContent: "center", alignItems: "flex-start", padding: "16px", background: "transparent" },
|
|
210
|
+
"top-right": { justifyContent: "flex-end", alignItems: "flex-start", padding: "16px", background: "transparent" },
|
|
211
|
+
"top-left": { justifyContent: "flex-start", alignItems: "flex-start", padding: "16px", background: "transparent" }
|
|
212
|
+
};
|
|
203
213
|
function buildSurveyHtml(opts) {
|
|
204
214
|
const env = opts.env === "development" ? "dev" : "prod";
|
|
205
215
|
const version = opts.version ?? "2.2.4";
|
|
@@ -210,17 +220,141 @@ function buildSurveyHtml(opts) {
|
|
|
210
220
|
const metaJson = JSON.stringify(opts.metadata ?? []);
|
|
211
221
|
const fontFaceCss = opts.font ? buildFontFaceCss(opts.font.family, opts.font.url) : "";
|
|
212
222
|
const fontFamilyValue = opts.font ? buildFontFamilyValue(opts.font.family) : "-apple-system,system-ui,sans-serif";
|
|
223
|
+
const popupClass = opts.font?.family ? "deepdots-popup deepdots-has-font" : "deepdots-popup";
|
|
224
|
+
const isDark = opts.theme === "dark";
|
|
225
|
+
const popupBg = isDark ? "#1e1e1e" : "#fff";
|
|
226
|
+
const colorScheme = isDark ? "dark" : "light";
|
|
227
|
+
const textPrimary = isDark ? "#f0f0f0" : "#111";
|
|
228
|
+
const pos = POSITION_MAP[opts.position ?? "center"] ?? POSITION_MAP.center;
|
|
229
|
+
const backLabel = JSON.stringify(opts.actions?.back?.label ?? "Back");
|
|
230
|
+
const startLabel = JSON.stringify(opts.actions?.start?.label ?? "Start survey");
|
|
231
|
+
const completeLabel = JSON.stringify(opts.actions?.complete?.label ?? "Complete survey");
|
|
232
|
+
const submitLabel = JSON.stringify(opts.actions?.accept?.label ?? "Send");
|
|
213
233
|
return `<!DOCTYPE html><html><head>
|
|
214
234
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
215
|
-
<meta name="color-scheme" content="
|
|
216
|
-
<style
|
|
235
|
+
<meta name="color-scheme" content="${colorScheme}"/>
|
|
236
|
+
<style>
|
|
237
|
+
${style_default}
|
|
238
|
+
${fontFaceCss}
|
|
239
|
+
html,body{margin:0;padding:0;height:100%;font-family:${fontFamilyValue}}
|
|
240
|
+
body{display:flex;justify-content:${pos.justifyContent};align-items:${pos.alignItems};background:${pos.background};padding:${pos.padding};box-sizing:border-box}
|
|
241
|
+
.deepdots-popup{position:relative;display:flex;flex-direction:column;justify-content:flex-start;background:${popupBg};color-scheme:${colorScheme};border-radius:8px;padding:24px;box-shadow:0 4px 6px rgba(0,0,0,0.1);max-width:600px;width:90%;min-height:200px;box-sizing:border-box}
|
|
242
|
+
.deepdots-popup-header{display:flex;justify-content:flex-end;align-items:center;width:100%}
|
|
243
|
+
#dd-close{background:transparent;border:none;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:8px;cursor:pointer;color:${textPrimary};padding:4px}
|
|
244
|
+
.deepdots-popup-container-content{display:flex;flex-direction:column;padding:0 20px 12px 20px;max-height:80vh;overflow:hidden;box-sizing:border-box}
|
|
245
|
+
.deepdots-popup-main{display:flex;flex-direction:column;width:100%;max-height:80vh;overflow-y:auto;overflow-x:hidden;position:relative}
|
|
246
|
+
#dd-form-wrapper{width:100%;flex:1 1 auto}
|
|
247
|
+
#mf{width:100%;box-sizing:border-box;visibility:hidden}
|
|
248
|
+
.deepdots-popup-main *{max-width:100%;box-sizing:border-box}
|
|
249
|
+
#dd-logo{max-height:40px;max-width:100%;object-fit:contain}
|
|
250
|
+
.deepdots-error-hint{display:none;margin:12px 0 0 0;padding:10px 12px;border-radius:6px;background:#FEF3C7;color:#92400E;border:1px solid #FCD34D;font-size:13px}
|
|
251
|
+
.deepdots-popup-footer{display:flex;flex-direction:row-reverse;justify-content:space-between;align-items:center;gap:8px;margin-top:auto;width:100%;padding-top:16px}
|
|
252
|
+
.dd-nav-btn{display:none;border:none;padding:12px 24px;border-radius:4px;cursor:pointer;font-size:14px;box-shadow:0 2px 4px rgba(0,0,0,0.1);align-items:center;justify-content:center;text-align:center}
|
|
253
|
+
#dd-back{background:transparent;color:#333;border:1px solid #999}
|
|
254
|
+
#dd-start,#dd-complete,#dd-submit{background:#1E293B;color:#fff;border:none}
|
|
255
|
+
#dd-submit:disabled,#dd-start:disabled,#dd-back:disabled,#dd-complete:disabled{opacity:0.6;cursor:not-allowed}
|
|
256
|
+
.mf-spinner{display:none;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}
|
|
257
|
+
.mf-spinner-circle{width:28px;height:28px;border:3px solid #e0e6ed;border-top-color:#1E293B;border-radius:50%;animation:ddspin 0.9s linear infinite}
|
|
258
|
+
@keyframes ddspin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}
|
|
259
|
+
@media (max-width:640px){
|
|
260
|
+
.deepdots-popup{width:calc(100% - 24px);max-width:calc(100% - 24px);border-radius:12px}
|
|
261
|
+
.deepdots-popup-footer{flex-direction:column-reverse;gap:12px}
|
|
262
|
+
.dd-nav-btn{width:100%}
|
|
263
|
+
.magicfeedback-checkbox-container,.magicfeedback-radio-container{margin:4px 0;padding:4px 8px}
|
|
264
|
+
.magicfeedback-checkbox label,.magicfeedback-radio-container label{font-size:15px}
|
|
265
|
+
.deepdots-popup input[type="radio"]{margin:6px 0 6px 8px}
|
|
266
|
+
.deepdots-popup input[type="checkbox"]{width:16px;height:16px}
|
|
267
|
+
}
|
|
268
|
+
</style>
|
|
217
269
|
</head><body>
|
|
218
|
-
<div id="
|
|
270
|
+
<div class="${popupClass}" id="dd-popup">
|
|
271
|
+
<div class="deepdots-popup-header">
|
|
272
|
+
<button type="button" id="dd-close" aria-label="Close popup">
|
|
273
|
+
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
274
|
+
<path d="M6 6L18 18M6 18L18 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
275
|
+
</svg>
|
|
276
|
+
</button>
|
|
277
|
+
</div>
|
|
278
|
+
<div class="deepdots-popup-container-content">
|
|
279
|
+
<div class="deepdots-popup-main" id="dd-main">
|
|
280
|
+
<div id="dd-form-wrapper">
|
|
281
|
+
<div class="mf-spinner" id="dd-spinner" role="status" aria-label="Loading survey"><div class="mf-spinner-circle"></div></div>
|
|
282
|
+
<div id="mf"></div>
|
|
283
|
+
</div>
|
|
284
|
+
<div class="deepdots-error-hint" id="dd-error" role="alert" aria-live="polite"></div>
|
|
285
|
+
<div class="deepdots-popup-footer" id="dd-footer">
|
|
286
|
+
<button type="button" class="dd-nav-btn" id="dd-submit">Send</button>
|
|
287
|
+
<button type="button" class="dd-nav-btn" id="dd-back">Back</button>
|
|
288
|
+
<button type="button" class="dd-nav-btn" id="dd-complete">Complete survey</button>
|
|
289
|
+
<button type="button" class="dd-nav-btn" id="dd-start">Start survey</button>
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
</div>
|
|
293
|
+
</div>
|
|
219
294
|
<script>
|
|
220
295
|
(function(){
|
|
221
296
|
function emit(s){ try{ if(window.ReactNativeWebView){ window.ReactNativeWebView.postMessage(s); } }catch(e){} }
|
|
222
297
|
function emitJSON(n,p){ try{ emit(JSON.stringify({name:n,payload:p||{}})); }catch(e){} }
|
|
223
298
|
window.DeepdotsClose = function(){ emitJSON('popup_close'); };
|
|
299
|
+
|
|
300
|
+
var popup=document.getElementById('dd-popup');
|
|
301
|
+
var main=document.getElementById('dd-main');
|
|
302
|
+
var footer=document.getElementById('dd-footer');
|
|
303
|
+
var spinner=document.getElementById('dd-spinner');
|
|
304
|
+
var formHost=document.getElementById('mf');
|
|
305
|
+
var errorHint=document.getElementById('dd-error');
|
|
306
|
+
var backBtn=document.getElementById('dd-back');
|
|
307
|
+
var startBtn=document.getElementById('dd-start');
|
|
308
|
+
var completeBtn=document.getElementById('dd-complete');
|
|
309
|
+
var submitBtn=document.getElementById('dd-submit');
|
|
310
|
+
|
|
311
|
+
backBtn.textContent=${backLabel};
|
|
312
|
+
startBtn.textContent=${startLabel};
|
|
313
|
+
completeBtn.textContent=${completeLabel};
|
|
314
|
+
submitBtn.textContent=${submitLabel};
|
|
315
|
+
|
|
316
|
+
document.getElementById('dd-close').onclick=function(){ emitJSON('popup_close'); };
|
|
317
|
+
backBtn.onclick=function(){ if(window.DeepdotsForm && window.DeepdotsForm.back){ window.DeepdotsForm.back(); } };
|
|
318
|
+
startBtn.onclick=function(){ if(window.DeepdotsForm && window.DeepdotsForm.startForm){ window.DeepdotsForm.startForm(); } };
|
|
319
|
+
completeBtn.onclick=function(){ emitJSON('popup_close'); };
|
|
320
|
+
var surveyCompletedEmitted=false;
|
|
321
|
+
submitBtn.onclick=function(){
|
|
322
|
+
if(surveyCompletedEmitted) return;
|
|
323
|
+
if(window.DeepdotsForm && window.DeepdotsForm.send){ window.DeepdotsForm.send(); }
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
function updateButtons(state){
|
|
327
|
+
backBtn.style.display='none';
|
|
328
|
+
startBtn.style.display='none';
|
|
329
|
+
submitBtn.style.display='none';
|
|
330
|
+
completeBtn.style.display='none';
|
|
331
|
+
backBtn.style.width='';
|
|
332
|
+
startBtn.style.width='';
|
|
333
|
+
submitBtn.style.width='';
|
|
334
|
+
completeBtn.style.width='';
|
|
335
|
+
if(state==='start'){
|
|
336
|
+
startBtn.style.display='inline-flex';
|
|
337
|
+
startBtn.style.width='100%';
|
|
338
|
+
} else if(state==='in_progress_first'){
|
|
339
|
+
submitBtn.style.display='inline-flex';
|
|
340
|
+
} else if(state==='in_progress_next'){
|
|
341
|
+
backBtn.style.display='inline-flex';
|
|
342
|
+
submitBtn.style.display='inline-flex';
|
|
343
|
+
} else if(state==='completed'){
|
|
344
|
+
completeBtn.style.display='inline-flex';
|
|
345
|
+
completeBtn.style.width='100%';
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function setLoading(isLoading){
|
|
350
|
+
spinner.style.display=isLoading?'flex':'none';
|
|
351
|
+
if(!isLoading){ formHost.style.visibility='visible'; }
|
|
352
|
+
footer.style.display=isLoading?'none':'flex';
|
|
353
|
+
backBtn.disabled=isLoading; startBtn.disabled=isLoading; completeBtn.disabled=isLoading; submitBtn.disabled=isLoading;
|
|
354
|
+
if(isLoading){ updateButtons(null); }
|
|
355
|
+
}
|
|
356
|
+
setLoading(true);
|
|
357
|
+
|
|
224
358
|
var initialized=false;
|
|
225
359
|
function initMF(){
|
|
226
360
|
if(initialized || !window.magicfeedback) return initialized;
|
|
@@ -229,23 +363,85 @@ function buildSurveyHtml(opts) {
|
|
|
229
363
|
window.magicfeedback.init({ debug:false, env:'${env}' });
|
|
230
364
|
var form = window.magicfeedback.form(${sid}, ${pid}, ${profileJson}, ${metaJson});
|
|
231
365
|
window.DeepdotsForm = form;
|
|
366
|
+
var stylesInjected=false;
|
|
232
367
|
form.generate('mf', {
|
|
233
368
|
addButton:false,
|
|
234
369
|
getMetaData:true,
|
|
235
|
-
onLoadedEvent:function(){
|
|
236
|
-
|
|
370
|
+
onLoadedEvent:function(args){
|
|
371
|
+
var s=args && args.formData ? args.formData.style : null;
|
|
372
|
+
if(s && !stylesInjected){
|
|
373
|
+
stylesInjected=true;
|
|
374
|
+
if(s.boxBackgroundColor){ popup.style.background=s.boxBackgroundColor; }
|
|
375
|
+
if(s.contentAlign){ main.style.justifyContent = s.contentAlign==='center' ? 'center' : 'flex-start'; }
|
|
376
|
+
if(s.buttonPrimaryColor){
|
|
377
|
+
submitBtn.style.background=s.buttonPrimaryColor; submitBtn.style.border='none'; submitBtn.style.color='#fff';
|
|
378
|
+
startBtn.style.background=s.buttonPrimaryColor; startBtn.style.border='none'; startBtn.style.color='#fff';
|
|
379
|
+
completeBtn.style.background=s.buttonPrimaryColor; completeBtn.style.border='none'; completeBtn.style.color='#fff';
|
|
380
|
+
}
|
|
381
|
+
if(s.buttonSecondaryColor){
|
|
382
|
+
backBtn.style.background='#fff'; backBtn.style.color=s.buttonSecondaryColor; backBtn.style.border='1px solid '+s.buttonSecondaryColor;
|
|
383
|
+
}
|
|
384
|
+
if(s.logo && !document.getElementById('dd-logo')){
|
|
385
|
+
var logoImg=document.createElement('img');
|
|
386
|
+
logoImg.id='dd-logo'; logoImg.src=s.logo; logoImg.alt='Logo';
|
|
387
|
+
if(s.logoSize==='small'){ logoImg.style.maxHeight='30px'; }
|
|
388
|
+
else if(s.logoSize==='medium'){ logoImg.style.maxHeight='50px'; }
|
|
389
|
+
else if(s.logoSize==='large'){ logoImg.style.maxHeight='70px'; }
|
|
390
|
+
if(s.logoPosition==='left'){ logoImg.style.margin='0 16px 20px 0'; logoImg.style.display='block'; logoImg.style.marginLeft='0'; }
|
|
391
|
+
else if(s.logoPosition==='right'){ logoImg.style.margin='0 0 20px 16px'; logoImg.style.display='block'; logoImg.style.marginLeft='auto'; }
|
|
392
|
+
else if(s.logoPosition==='center'){ logoImg.style.margin='0 auto 20px auto'; logoImg.style.display='block'; }
|
|
393
|
+
main.insertBefore(logoImg, document.getElementById('dd-form-wrapper'));
|
|
394
|
+
}
|
|
395
|
+
if(s.startMessage && s.startMessage!==''){ updateButtons('start'); }
|
|
396
|
+
else { updateButtons('in_progress_first'); }
|
|
397
|
+
} else {
|
|
398
|
+
updateButtons('in_progress_first');
|
|
399
|
+
}
|
|
400
|
+
emitJSON('loaded');
|
|
401
|
+
setLoading(false);
|
|
402
|
+
},
|
|
403
|
+
beforeSubmitEvent:function(){
|
|
404
|
+
setLoading(true);
|
|
405
|
+
emitJSON('before_submit');
|
|
406
|
+
},
|
|
237
407
|
afterSubmitEvent:function(p){
|
|
238
|
-
|
|
239
|
-
|
|
408
|
+
var error=p && p.error ? (typeof p.error==='string' ? p.error : String(p.error)) : '';
|
|
409
|
+
if(error){
|
|
410
|
+
setLoading(false);
|
|
411
|
+
if(error.toLowerCase().indexOf('no response')!==-1){
|
|
412
|
+
errorHint.textContent='Please answer the required question to continue.';
|
|
413
|
+
errorHint.style.display='block';
|
|
414
|
+
updateButtons('in_progress_next');
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
errorHint.textContent='An error occurred while submitting. Please try again or close the popup.';
|
|
418
|
+
errorHint.style.display='block';
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
errorHint.style.display='none';
|
|
422
|
+
setLoading(false);
|
|
423
|
+
if(p && p.completed){
|
|
424
|
+
surveyCompletedEmitted=true;
|
|
425
|
+
updateButtons('completed');
|
|
426
|
+
emitJSON('survey_completed', p);
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
if(p && p.total>1 && p.progress>0 && p.progress<p.total){ updateButtons('in_progress_next'); }
|
|
430
|
+
else { updateButtons('in_progress_first'); }
|
|
431
|
+
emitJSON('after_submit', p);
|
|
240
432
|
},
|
|
241
|
-
onBackEvent:function(p){
|
|
242
|
-
|
|
243
|
-
|
|
433
|
+
onBackEvent:function(p){
|
|
434
|
+
if(p && p.progress===0){ updateButtons('in_progress_first'); }
|
|
435
|
+
else { updateButtons('in_progress_next'); }
|
|
436
|
+
emitJSON('back', p);
|
|
437
|
+
}
|
|
438
|
+
}).catch(function(e){ setLoading(false); emit('error:init'); });
|
|
439
|
+
}catch(e){ setLoading(false); emit('error:exception'); }
|
|
244
440
|
return true;
|
|
245
441
|
}
|
|
246
442
|
var s=document.createElement('script'); s.src=${JSON.stringify(cdn)}; s.async=true;
|
|
247
443
|
s.onload=function(){ initMF(); };
|
|
248
|
-
s.onerror=function(){ emit('error:load'); };
|
|
444
|
+
s.onerror=function(){ setLoading(false); emit('error:load'); };
|
|
249
445
|
document.head.appendChild(s);
|
|
250
446
|
var tries=0, t=setInterval(function(){ if(initMF()||++tries>40){ clearInterval(t); } },150);
|
|
251
447
|
})();
|
|
@@ -264,18 +460,28 @@ var ReactNativePopupRenderer = class {
|
|
|
264
460
|
}
|
|
265
461
|
init() {
|
|
266
462
|
}
|
|
267
|
-
show(surveyId, productId,
|
|
463
|
+
show(surveyId, productId, actions, emit, onClose, env = "production", userId, style, sessionId, miniService, analyticsFeedbackSessionId) {
|
|
268
464
|
this.emitFn = emit;
|
|
269
465
|
this.onCloseFn = onClose;
|
|
270
466
|
this.currentSurveyId = surveyId;
|
|
271
467
|
this.partialEmitted = false;
|
|
272
468
|
const { profile, metadata } = buildSurveyIdentity(userId ?? null, sessionId ?? null, miniService ?? null, analyticsFeedbackSessionId ?? null);
|
|
273
|
-
const html = buildSurveyHtml({
|
|
469
|
+
const html = buildSurveyHtml({
|
|
470
|
+
surveyId,
|
|
471
|
+
productId,
|
|
472
|
+
env,
|
|
473
|
+
profile,
|
|
474
|
+
metadata,
|
|
475
|
+
font: style?.font,
|
|
476
|
+
theme: style?.theme,
|
|
477
|
+
position: style?.position,
|
|
478
|
+
actions
|
|
479
|
+
});
|
|
274
480
|
if (this.options.onShow) {
|
|
275
481
|
this.options.onShow({ surveyId, productId, html });
|
|
276
482
|
} else {
|
|
277
483
|
sdkWarn(
|
|
278
|
-
"[Deepdots] ReactNativePopupRenderer
|
|
484
|
+
"[Deepdots] ReactNativePopupRenderer has no onShow: pass { onShow } to new ReactNativePopupRenderer({...}) to mount the survey WebView."
|
|
279
485
|
);
|
|
280
486
|
}
|
|
281
487
|
}
|
|
@@ -366,7 +572,7 @@ var BrowserPopupRenderer = class {
|
|
|
366
572
|
if (!this.container) return;
|
|
367
573
|
this.visible = true;
|
|
368
574
|
const container = this.container;
|
|
369
|
-
void import("./renderPopup-
|
|
575
|
+
void import("./renderPopup-ZYXOUBCP.mjs").then(({ renderPopup }) => {
|
|
370
576
|
renderPopup(container, surveyId, productId, actions, emit, onClose, env, userId, style, sessionId, miniService, analyticsFeedbackSessionId);
|
|
371
577
|
});
|
|
372
578
|
}
|
|
@@ -390,7 +596,7 @@ function createDefaultRenderer() {
|
|
|
390
596
|
// src/analytics/analytics-manager.ts
|
|
391
597
|
function createDryRunSink(log = console.log) {
|
|
392
598
|
return (payload) => log(
|
|
393
|
-
"[DeepdotsAnalytics] (dry-run \xB7
|
|
599
|
+
"[DeepdotsAnalytics] (dry-run \xB7 NOT sent \xB7 no init.analytics) POST /sdk/feedback \u2192",
|
|
394
600
|
JSON.stringify(payload, null, 2)
|
|
395
601
|
);
|
|
396
602
|
}
|
|
@@ -459,6 +665,15 @@ var AnalyticsManager = class {
|
|
|
459
665
|
this.exitMiniService(name);
|
|
460
666
|
}
|
|
461
667
|
}
|
|
668
|
+
/**
|
|
669
|
+
* Olvida lo que pertenecía al usuario anterior (user attributes + métricas) al cambiar de
|
|
670
|
+
* usuario. NO toca el buffer de eventos: el cierre de sesión ya lo vació con la identidad
|
|
671
|
+
* vieja, y lo que llegue después es del usuario nuevo.
|
|
672
|
+
*/
|
|
673
|
+
resetUserScope() {
|
|
674
|
+
this.attributes = {};
|
|
675
|
+
this.metrics = {};
|
|
676
|
+
}
|
|
462
677
|
/** Registra un evento de analítica (modelo GA: nombre + params). */
|
|
463
678
|
track(name, params) {
|
|
464
679
|
const current = this.getMiniService();
|
|
@@ -546,7 +761,7 @@ function pushKV(list, key, value) {
|
|
|
546
761
|
if (value === void 0 || value === null || value === "") return;
|
|
547
762
|
list.push({ key, value: [String(value)] });
|
|
548
763
|
}
|
|
549
|
-
function buildAnalyticsFeedbackBody(envelope, keys, feedbackSessionId) {
|
|
764
|
+
function buildAnalyticsFeedbackBody(envelope, keys, feedbackSessionId, options) {
|
|
550
765
|
const { context } = envelope;
|
|
551
766
|
const profile = [];
|
|
552
767
|
pushKV(profile, "external-user-id", envelope.userId);
|
|
@@ -597,7 +812,8 @@ function buildAnalyticsFeedbackBody(envelope, keys, feedbackSessionId) {
|
|
|
597
812
|
},
|
|
598
813
|
publicKey: keys.publicKey,
|
|
599
814
|
integration: keys.integration,
|
|
600
|
-
|
|
815
|
+
// Único marcador de cierre acordado con backend: el último lote de la sesión.
|
|
816
|
+
completed: options?.sessionEnd === true,
|
|
601
817
|
...feedbackSessionId ? { sessionId: feedbackSessionId } : {}
|
|
602
818
|
};
|
|
603
819
|
}
|
|
@@ -616,20 +832,20 @@ function createFeedbackSink(options) {
|
|
|
616
832
|
let feedbackSessionId;
|
|
617
833
|
let firstPostInFlight = null;
|
|
618
834
|
const url = `${options.baseUrl}/sdk/feedback`;
|
|
619
|
-
const post = async (body, final) => {
|
|
835
|
+
const post = async (body, final, sessionEnd = false) => {
|
|
620
836
|
const json = JSON.stringify(body);
|
|
621
837
|
const small = json.length <= KEEPALIVE_MAX_BYTES;
|
|
622
838
|
if (final && options.sendBeaconImpl && small) {
|
|
623
839
|
const payload = typeof Blob !== "undefined" ? new Blob([json], { type: "application/json" }) : json;
|
|
624
840
|
if (options.sendBeaconImpl(url, payload)) {
|
|
625
|
-
options.log?.("[DeepdotsAnalytics] flush
|
|
841
|
+
options.log?.("[DeepdotsAnalytics] final flush via sendBeacon");
|
|
626
842
|
return;
|
|
627
843
|
}
|
|
628
|
-
options.log?.("[DeepdotsAnalytics] sendBeacon
|
|
844
|
+
options.log?.("[DeepdotsAnalytics] sendBeacon rejected the batch; falling back to fetch");
|
|
629
845
|
}
|
|
630
846
|
const f = options.fetchImpl ?? (typeof fetch !== "undefined" ? fetch : void 0);
|
|
631
847
|
if (!f) {
|
|
632
|
-
options.log?.("[DeepdotsAnalytics] no fetch
|
|
848
|
+
options.log?.("[DeepdotsAnalytics] no fetch available; payload not sent", body);
|
|
633
849
|
return;
|
|
634
850
|
}
|
|
635
851
|
const res = await f(url, {
|
|
@@ -642,19 +858,20 @@ function createFeedbackSink(options) {
|
|
|
642
858
|
if (!res.ok) {
|
|
643
859
|
const detail = await safeBodyText(res);
|
|
644
860
|
if (isRetryableStatus(res.status)) {
|
|
645
|
-
throw new Error(`POST /sdk/feedback ${res.status} (
|
|
861
|
+
throw new Error(`POST /sdk/feedback ${res.status} (retryable): ${detail}`);
|
|
646
862
|
}
|
|
647
863
|
options.log?.(
|
|
648
|
-
`[DeepdotsAnalytics] POST /sdk/feedback
|
|
864
|
+
`[DeepdotsAnalytics] POST /sdk/feedback rejected with ${res.status}; batch DISCARDED:`,
|
|
649
865
|
detail
|
|
650
866
|
);
|
|
651
867
|
return;
|
|
652
868
|
}
|
|
869
|
+
if (sessionEnd) return;
|
|
653
870
|
try {
|
|
654
871
|
const data = await res.json();
|
|
655
872
|
if (data?.sessionId && data.sessionId !== feedbackSessionId) {
|
|
656
873
|
feedbackSessionId = data.sessionId;
|
|
657
|
-
options.log?.("[DeepdotsAnalytics] feedbackSessionId
|
|
874
|
+
options.log?.("[DeepdotsAnalytics] feedbackSessionId cached:", feedbackSessionId);
|
|
658
875
|
options.onSessionId?.(feedbackSessionId);
|
|
659
876
|
}
|
|
660
877
|
} catch {
|
|
@@ -662,13 +879,18 @@ function createFeedbackSink(options) {
|
|
|
662
879
|
};
|
|
663
880
|
return async (envelope, meta) => {
|
|
664
881
|
const final = meta?.final === true;
|
|
882
|
+
const sessionEnd = meta?.sessionEnd === true;
|
|
665
883
|
if (!feedbackSessionId && firstPostInFlight && !final) {
|
|
666
884
|
await firstPostInFlight;
|
|
667
885
|
}
|
|
668
|
-
const body = buildAnalyticsFeedbackBody(envelope, options.keys, feedbackSessionId);
|
|
886
|
+
const body = buildAnalyticsFeedbackBody(envelope, options.keys, feedbackSessionId, { sessionEnd });
|
|
669
887
|
options.log?.("[DeepdotsAnalytics] POST /sdk/feedback \u2192", body);
|
|
670
|
-
const sent = post(body, final);
|
|
671
|
-
if (
|
|
888
|
+
const sent = post(body, final, sessionEnd);
|
|
889
|
+
if (sessionEnd) {
|
|
890
|
+
feedbackSessionId = void 0;
|
|
891
|
+
firstPostInFlight = null;
|
|
892
|
+
options.onSessionReset?.();
|
|
893
|
+
} else if (!feedbackSessionId) {
|
|
672
894
|
firstPostInFlight = sent.then(
|
|
673
895
|
() => void 0,
|
|
674
896
|
() => void 0
|
|
@@ -1103,6 +1325,7 @@ var CrashReporter = class {
|
|
|
1103
1325
|
};
|
|
1104
1326
|
|
|
1105
1327
|
// src/analytics/messaging.ts
|
|
1328
|
+
var MESSAGE_CHANNELS = ["push", "in_app"];
|
|
1106
1329
|
function buildMessageParams(stage, o) {
|
|
1107
1330
|
const p = {
|
|
1108
1331
|
stage,
|
|
@@ -1115,6 +1338,57 @@ function buildMessageParams(stage, o) {
|
|
|
1115
1338
|
if (o.currency) p.currency = o.currency;
|
|
1116
1339
|
return { ...p, ...o.params ?? {} };
|
|
1117
1340
|
}
|
|
1341
|
+
var MAX_TRACKED_MESSAGES = 500;
|
|
1342
|
+
var MessageGuard = class {
|
|
1343
|
+
constructor(maxTrackedMessages = MAX_TRACKED_MESSAGES) {
|
|
1344
|
+
this.maxTrackedMessages = maxTrackedMessages;
|
|
1345
|
+
/** message_id → canal fijado + stages ya emitidos. El orden de inserción marca la eviction. */
|
|
1346
|
+
this.seen = /* @__PURE__ */ new Map();
|
|
1347
|
+
}
|
|
1348
|
+
evaluate(stage, options) {
|
|
1349
|
+
const channel = options.channel;
|
|
1350
|
+
if (!MESSAGE_CHANNELS.includes(channel)) {
|
|
1351
|
+
return {
|
|
1352
|
+
emit: false,
|
|
1353
|
+
reason: "invalid_channel",
|
|
1354
|
+
detail: `invalid channel "${channel}" (expected ${MESSAGE_CHANNELS.join(" | ")})`
|
|
1355
|
+
};
|
|
1356
|
+
}
|
|
1357
|
+
const entry = this.seen.get(options.id);
|
|
1358
|
+
if (!entry) {
|
|
1359
|
+
this.remember(options.id, channel, stage);
|
|
1360
|
+
return { emit: true };
|
|
1361
|
+
}
|
|
1362
|
+
if (entry.channel !== channel) {
|
|
1363
|
+
return {
|
|
1364
|
+
emit: false,
|
|
1365
|
+
reason: "channel_conflict",
|
|
1366
|
+
detail: `message_id "${options.id}" was already reported on channel "${entry.channel}"; discarding "${channel}"`
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1369
|
+
if (entry.stages.has(stage)) {
|
|
1370
|
+
return {
|
|
1371
|
+
emit: false,
|
|
1372
|
+
reason: "duplicate_stage",
|
|
1373
|
+
detail: `stage "${stage}" was already sent for message_id "${options.id}"`
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
entry.stages.add(stage);
|
|
1377
|
+
return { emit: true };
|
|
1378
|
+
}
|
|
1379
|
+
/** Olvida todo lo vigilado (nueva sesión). */
|
|
1380
|
+
reset() {
|
|
1381
|
+
this.seen.clear();
|
|
1382
|
+
}
|
|
1383
|
+
remember(id, channel, stage) {
|
|
1384
|
+
this.seen.set(id, { channel, stages: /* @__PURE__ */ new Set([stage]) });
|
|
1385
|
+
while (this.seen.size > this.maxTrackedMessages) {
|
|
1386
|
+
const oldest = this.seen.keys().next();
|
|
1387
|
+
if (oldest.done) break;
|
|
1388
|
+
this.seen.delete(oldest.value);
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
};
|
|
1118
1392
|
|
|
1119
1393
|
// src/core/deepdots-popups.ts
|
|
1120
1394
|
var EXIT_QUEUE_STORAGE_KEY = "__deepdots_exit_popup_queue__";
|
|
@@ -1156,14 +1430,24 @@ var DeepdotsPopups = class {
|
|
|
1156
1430
|
this.analyticsFlushTimer = void 0;
|
|
1157
1431
|
/** Crash & error reporting (#14–17). Null hasta init(). */
|
|
1158
1432
|
this.crashReporter = null;
|
|
1433
|
+
/** Protecciones del funnel de Messaging (#18–22). Vigencia de sesión: se reinicia en init(). */
|
|
1434
|
+
this.messageGuard = new MessageGuard();
|
|
1159
1435
|
/** Observador de navegación (Fase 2): emite page_view por el canal de analytics. */
|
|
1160
1436
|
this.navObserver = null;
|
|
1161
1437
|
/** Tiempo activo (engagement time, #8). */
|
|
1162
1438
|
this.engagement = null;
|
|
1163
1439
|
/** Atributos internos del usuario identificado → POST /sdk/popups/contact. Null si no hay userId. */
|
|
1164
1440
|
this.contact = null;
|
|
1441
|
+
/** Storage resuelto en init() (inyectado por el host o localStorage). Reusado al cambiar de usuario. */
|
|
1442
|
+
this.storage = null;
|
|
1165
1443
|
/** Marca si ya se inició la navegación manual (setScreen) — para RN sin History API. */
|
|
1166
1444
|
this.navStarted = false;
|
|
1445
|
+
/**
|
|
1446
|
+
* `true` entre `session_start` y `session_end`. Hace idempotente tanto la apertura como
|
|
1447
|
+
* el cierre (p. ej. `visibilitychange` + `pagehide` seguidos) y permite abrir una sesión
|
|
1448
|
+
* nueva al volver a foreground o al conceder el consentimiento más tarde.
|
|
1449
|
+
*/
|
|
1450
|
+
this.sessionOpen = false;
|
|
1167
1451
|
/**
|
|
1168
1452
|
* Idioma resuelto en init() (explícito > navigator.language > Intl). Única fuente de
|
|
1169
1453
|
* verdad para el context de analytics Y para la segmentación por idioma de los popups.
|
|
@@ -1175,6 +1459,11 @@ var DeepdotsPopups = class {
|
|
|
1175
1459
|
this.logger = config.logger ?? console;
|
|
1176
1460
|
setLogger(this.logger);
|
|
1177
1461
|
if (this.initialized) {
|
|
1462
|
+
const nextUserId = config.userId || void 0;
|
|
1463
|
+
if (nextUserId !== this.config?.userId) {
|
|
1464
|
+
this.setUserId(nextUserId);
|
|
1465
|
+
return;
|
|
1466
|
+
}
|
|
1178
1467
|
this.log("SDK already initialized");
|
|
1179
1468
|
return;
|
|
1180
1469
|
}
|
|
@@ -1187,6 +1476,7 @@ var DeepdotsPopups = class {
|
|
|
1187
1476
|
userId: config.userId || void 0
|
|
1188
1477
|
};
|
|
1189
1478
|
const storage = config.storage ?? createDefaultStorage();
|
|
1479
|
+
this.storage = storage;
|
|
1190
1480
|
this.tracking = new TrackingManager({
|
|
1191
1481
|
storage,
|
|
1192
1482
|
clientUserId: this.config.userId,
|
|
@@ -1214,6 +1504,9 @@ var DeepdotsPopups = class {
|
|
|
1214
1504
|
sendBeaconImpl: typeof navigator !== "undefined" && typeof navigator.sendBeacon === "function" ? (url, body) => navigator.sendBeacon(url, body) : void 0,
|
|
1215
1505
|
onSessionId: (id) => {
|
|
1216
1506
|
this.analyticsFeedbackSessionId = id;
|
|
1507
|
+
},
|
|
1508
|
+
onSessionReset: () => {
|
|
1509
|
+
this.analyticsFeedbackSessionId = void 0;
|
|
1217
1510
|
}
|
|
1218
1511
|
}) : createDryRunSink((...a) => this.logger.log(...a));
|
|
1219
1512
|
const device = config.device ?? collectDeviceInfo(config.appVersion);
|
|
@@ -1222,6 +1515,7 @@ var DeepdotsPopups = class {
|
|
|
1222
1515
|
navigator: typeof navigator !== "undefined" ? navigator : void 0,
|
|
1223
1516
|
intl: typeof Intl !== "undefined" ? Intl : void 0
|
|
1224
1517
|
});
|
|
1518
|
+
this.messageGuard.reset();
|
|
1225
1519
|
this.analytics = new AnalyticsManager({
|
|
1226
1520
|
sink: analyticsSink,
|
|
1227
1521
|
publicKey: config.analytics?.publicKey ?? this.config.apiKey,
|
|
@@ -1257,7 +1551,7 @@ var DeepdotsPopups = class {
|
|
|
1257
1551
|
this.engagement = new EngagementTracker();
|
|
1258
1552
|
this.engagement.resume();
|
|
1259
1553
|
this.setupAnalyticsFlush();
|
|
1260
|
-
this.
|
|
1554
|
+
this.openSession();
|
|
1261
1555
|
const pendingCrashes = this.crashReporter.drainPendingCrashes();
|
|
1262
1556
|
if (this.tracking?.isTrackingEnabled()) {
|
|
1263
1557
|
for (const rec of pendingCrashes) {
|
|
@@ -1289,7 +1583,9 @@ var DeepdotsPopups = class {
|
|
|
1289
1583
|
}
|
|
1290
1584
|
/** Activa/desactiva el tracking (identidad + sesión + analytics). Kill-switch del contrato §7bis. */
|
|
1291
1585
|
setTrackingEnabled(enabled) {
|
|
1586
|
+
if (!enabled) this.closeSession("tracking_disabled");
|
|
1292
1587
|
this.tracking?.setTrackingEnabled(enabled);
|
|
1588
|
+
if (enabled) this.openSession();
|
|
1293
1589
|
this.log("tracking \xB7 setTrackingEnabled:", enabled, "\xB7 session_id:", this.tracking?.getSessionId() ?? null);
|
|
1294
1590
|
}
|
|
1295
1591
|
// ───────── Analytics (canal separado del feedback, vinculado por user_id) ─────────
|
|
@@ -1359,8 +1655,18 @@ var DeepdotsPopups = class {
|
|
|
1359
1655
|
trackFunnelStep(funnel, step, taskId, params) {
|
|
1360
1656
|
this.track("deepdots_funnel_step", { funnel, step, task_id: taskId, ...params ?? {} });
|
|
1361
1657
|
}
|
|
1362
|
-
/**
|
|
1658
|
+
/**
|
|
1659
|
+
* Messaging (#18–22): registra una etapa del funnel de una notificación (push/in-app).
|
|
1660
|
+
* No-op si tracking off. El evento se descarta (con warning) si el `channel` no es válido,
|
|
1661
|
+
* si ese `(message_id, stage)` ya se emitió en la sesión, o si el `message_id` ya se reportó
|
|
1662
|
+
* en otro canal — ver `MessageGuard`.
|
|
1663
|
+
*/
|
|
1363
1664
|
trackMessage(stage, options) {
|
|
1665
|
+
const verdict = this.messageGuard.evaluate(stage, options);
|
|
1666
|
+
if (!verdict.emit) {
|
|
1667
|
+
console.warn(`[DeepdotsPopups] trackMessage discarded (${verdict.reason}): ${verdict.detail}`);
|
|
1668
|
+
return;
|
|
1669
|
+
}
|
|
1364
1670
|
this.track("deepdots_message", buildMessageParams(stage, options));
|
|
1365
1671
|
}
|
|
1366
1672
|
/**
|
|
@@ -1376,21 +1682,86 @@ var DeepdotsPopups = class {
|
|
|
1376
1682
|
this.navObserver.visit(name);
|
|
1377
1683
|
}
|
|
1378
1684
|
}
|
|
1379
|
-
/** App a foreground (RN: AppState 'active'): reanuda el engagement time. */
|
|
1685
|
+
/** App a foreground (RN: AppState 'active'): reanuda el engagement time y abre sesión nueva. */
|
|
1380
1686
|
onForeground() {
|
|
1381
1687
|
this.engagement?.resume();
|
|
1688
|
+
this.openSession();
|
|
1382
1689
|
}
|
|
1383
1690
|
/**
|
|
1384
|
-
* App a background (RN: AppState 'background'):
|
|
1385
|
-
* mini-
|
|
1691
|
+
* App a background (RN: AppState 'background'): FIN DE SESIÓN. Cierra pantalla actual
|
|
1692
|
+
* (page_view), mini-services (mini_service_exit), emite engagement + `session_end` y
|
|
1693
|
+
* envía el último lote con `completed:true`.
|
|
1694
|
+
*
|
|
1695
|
+
* Es la única señal disponible en móvil: el kill de la app (swipe) NO da callback.
|
|
1386
1696
|
*/
|
|
1387
1697
|
onBackground() {
|
|
1698
|
+
this.closeSession("background");
|
|
1699
|
+
this.engagement?.pause();
|
|
1700
|
+
}
|
|
1701
|
+
/**
|
|
1702
|
+
* Cierre EXPLÍCITO de la sesión por parte del host (logout, fin de flujo…): emite
|
|
1703
|
+
* `session_end` y envía el último lote con `completed:true`.
|
|
1704
|
+
*/
|
|
1705
|
+
endSession() {
|
|
1706
|
+
this.closeSession("manual");
|
|
1707
|
+
}
|
|
1708
|
+
/**
|
|
1709
|
+
* Cambio de usuario (login / logout / cambio de cuenta). Cierra la sesión del usuario
|
|
1710
|
+
* anterior (`session_end` con `reason: 'user_change'` + `completed:true`), cambia la
|
|
1711
|
+
* identidad y abre una sesión nueva. Sin `userId` vuelve al id anónimo del SDK.
|
|
1712
|
+
*
|
|
1713
|
+
* Equivale a llamar a `init()` otra vez con otro `userId`.
|
|
1714
|
+
*/
|
|
1715
|
+
setUserId(userId) {
|
|
1716
|
+
const next = userId || void 0;
|
|
1717
|
+
if (!this.initialized || !this.config || next === this.config.userId) return;
|
|
1718
|
+
this.closeSession("user_change");
|
|
1719
|
+
const enabled = this.tracking?.isTrackingEnabled() ?? true;
|
|
1720
|
+
const storage = this.storage ?? createDefaultStorage();
|
|
1721
|
+
this.config.userId = next;
|
|
1722
|
+
this.tracking = new TrackingManager({ storage, clientUserId: next, enabled });
|
|
1723
|
+
this.contact = next ? new ContactManager({
|
|
1724
|
+
storage,
|
|
1725
|
+
publicKey: this.config.apiKey ?? "",
|
|
1726
|
+
userId: next,
|
|
1727
|
+
post: (body) => this.postContact(body)
|
|
1728
|
+
}) : null;
|
|
1729
|
+
this.analytics?.resetUserScope();
|
|
1730
|
+
this.messageGuard.reset();
|
|
1731
|
+
this.log("tracking \xB7 user_change \xB7 user_id:", this.tracking.getUserId());
|
|
1732
|
+
this.openSession();
|
|
1733
|
+
}
|
|
1734
|
+
/**
|
|
1735
|
+
* Cierra la sesión actual: vuelca todo lo que quedaba abierto y envía el último lote
|
|
1736
|
+
* marcado con `completed:true`, para que el backend cierre el registro. El `sessionId`
|
|
1737
|
+
* cacheado se olvida → el lote siguiente abre un registro nuevo.
|
|
1738
|
+
*
|
|
1739
|
+
* Idempotente: dos cierres seguidos (p. ej. `visibilitychange` + `pagehide`) no duplican
|
|
1740
|
+
* el `session_end`.
|
|
1741
|
+
*/
|
|
1742
|
+
closeSession(reason) {
|
|
1743
|
+
if (!this.sessionOpen) return;
|
|
1744
|
+
if (!this.tracking?.isTrackingEnabled()) return;
|
|
1745
|
+
this.sessionOpen = false;
|
|
1388
1746
|
this.navObserver?.stop();
|
|
1389
1747
|
this.navStarted = false;
|
|
1390
|
-
|
|
1748
|
+
this.analytics?.exitAllMiniServices();
|
|
1391
1749
|
this.flushEngagement();
|
|
1392
|
-
this.
|
|
1393
|
-
this.flushAnalytics();
|
|
1750
|
+
this.track("deepdots_session_end", { reason });
|
|
1751
|
+
this.flushAnalytics({ final: reason === "page_hide", sessionEnd: true });
|
|
1752
|
+
this.analyticsFeedbackSessionId = void 0;
|
|
1753
|
+
this.tracking?.setSessionId(null);
|
|
1754
|
+
this.log("tracking \xB7 session_end:", reason);
|
|
1755
|
+
}
|
|
1756
|
+
/**
|
|
1757
|
+
* Abre sesión (`session_start`) si no hay una abierta y el tracking está activo. Idempotente:
|
|
1758
|
+
* se llama en init(), al volver a foreground y al conceder el consentimiento.
|
|
1759
|
+
*/
|
|
1760
|
+
openSession() {
|
|
1761
|
+
if (this.sessionOpen) return;
|
|
1762
|
+
if (!this.tracking?.isTrackingEnabled()) return;
|
|
1763
|
+
this.sessionOpen = true;
|
|
1764
|
+
this.track("deepdots_session_start", {});
|
|
1394
1765
|
}
|
|
1395
1766
|
/** Payload que se ENVIARÍA al endpoint de analytics (no envía ni vacía el buffer). */
|
|
1396
1767
|
previewAnalytics() {
|
|
@@ -1428,10 +1799,7 @@ var DeepdotsPopups = class {
|
|
|
1428
1799
|
this.analyticsFlushTimer = setInterval(() => this.flushAnalytics(), ANALYTICS_FLUSH_INTERVAL_MS);
|
|
1429
1800
|
window.addEventListener("pagehide", () => {
|
|
1430
1801
|
clearInterval(this.analyticsFlushTimer);
|
|
1431
|
-
this.
|
|
1432
|
-
if (this.tracking?.isTrackingEnabled()) this.analytics?.exitAllMiniServices();
|
|
1433
|
-
this.flushEngagement();
|
|
1434
|
-
this.flushAnalytics({ final: true });
|
|
1802
|
+
this.closeSession("page_hide");
|
|
1435
1803
|
});
|
|
1436
1804
|
document.addEventListener("visibilitychange", () => {
|
|
1437
1805
|
if (document.visibilityState === "hidden") {
|
|
@@ -1893,7 +2261,7 @@ var DeepdotsPopups = class {
|
|
|
1893
2261
|
}
|
|
1894
2262
|
if (!this.popupContainer) return;
|
|
1895
2263
|
const container = this.popupContainer;
|
|
1896
|
-
void import("./renderPopup-
|
|
2264
|
+
void import("./renderPopup-ZYXOUBCP.mjs").then(({ renderPopup }) => {
|
|
1897
2265
|
renderPopup(
|
|
1898
2266
|
container,
|
|
1899
2267
|
surveyId,
|
|
@@ -2106,7 +2474,8 @@ function setupReactNative(sdk2, config, deps = {}) {
|
|
|
2106
2474
|
if (deps.appState?.addEventListener) {
|
|
2107
2475
|
subscription = deps.appState.addEventListener("change", (state) => {
|
|
2108
2476
|
if (state === "active") sdk2.onForeground();
|
|
2109
|
-
else sdk2.onBackground();
|
|
2477
|
+
else if (state === "background") sdk2.onBackground();
|
|
2478
|
+
else sdk2.flushAnalytics();
|
|
2110
2479
|
});
|
|
2111
2480
|
}
|
|
2112
2481
|
return () => {
|
|
@@ -2152,9 +2521,10 @@ function DeepdotsProvider({ config, children }) {
|
|
|
2152
2521
|
survey ? /* @__PURE__ */ jsx(Modal, { visible: true, transparent: true, animationType: "slide", children: /* @__PURE__ */ jsx(View, { style: { flex: 1 }, children: /* @__PURE__ */ jsx(
|
|
2153
2522
|
WebView,
|
|
2154
2523
|
{
|
|
2524
|
+
style: { flex: 1 },
|
|
2155
2525
|
originWhitelist: ["*"],
|
|
2156
2526
|
javaScriptEnabled: true,
|
|
2157
|
-
source: { html: survey.html },
|
|
2527
|
+
source: { html: survey.html, baseUrl: "https://sdk.deepdots.com/" },
|
|
2158
2528
|
onMessage: (e) => rendererRef.current?.handleMessage(e.nativeEvent.data)
|
|
2159
2529
|
}
|
|
2160
2530
|
) }) }) : null
|