@bravophone/webphone 0.1.2 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -5
- package/dist/bravophone.mjs +419 -302
- package/dist/bravophone.umd.js +66 -7
- package/host/_locales/pt_BR/messages.json +1430 -0
- package/host/allowed-origins.json +8 -0
- package/host/css/bravophoneContactDialer.css +385 -0
- package/host/css/dark-theme.css +116 -0
- package/host/favicon.ico +0 -0
- package/host/fonts/Audiowide-Regular.ttf +0 -0
- package/host/fonts/Seguiemj.ttf +0 -0
- package/host/images/answer-gray.png +0 -0
- package/host/images/answer.png +0 -0
- package/host/images/auto-answer-off.png +0 -0
- package/host/images/auto-answer-on.png +0 -0
- package/host/images/avatar.png +0 -0
- package/host/images/bravophone-logo.svg +39 -0
- package/host/images/bravotech_Bravotech_logo.png +0 -0
- package/host/images/circle-green.png +0 -0
- package/host/images/circle-orange.png +0 -0
- package/host/images/circle-red.png +0 -0
- package/host/images/dialer-button-down.png +0 -0
- package/host/images/dialer-button.png +0 -0
- package/host/images/gateways/activecampaign.png +0 -0
- package/host/images/gateways/agendor.png +0 -0
- package/host/images/gateways/appfacilita.png +0 -0
- package/host/images/gateways/call-in.png +0 -0
- package/host/images/gateways/click-to-call.png +0 -0
- package/host/images/gateways/clickup.png +0 -0
- package/host/images/gateways/exactsales.png +0 -0
- package/host/images/gateways/go-high-lvl.png +0 -0
- package/host/images/gateways/groner.png +0 -0
- package/host/images/gateways/hubspot.png +0 -0
- package/host/images/gateways/kommo.png +0 -0
- package/host/images/gateways/moskit.png +0 -0
- package/host/images/gateways/nectar.png +0 -0
- package/host/images/gateways/pipedrive.png +0 -0
- package/host/images/gateways/pipefy.png +0 -0
- package/host/images/gateways/piperun.png +0 -0
- package/host/images/gateways/ploomes.png +0 -0
- package/host/images/gateways/rdstation-crm.png +0 -0
- package/host/images/gateways/salesforce.png +0 -0
- package/host/images/gateways/sharpspring.png +0 -0
- package/host/images/gateways/sunhub.png +0 -0
- package/host/images/gateways/vendfly.png +0 -0
- package/host/images/gateways/zendesk.png +0 -0
- package/host/images/gateways/zoho.png +0 -0
- package/host/images/hangup.png +0 -0
- package/host/images/hold.png +0 -0
- package/host/images/icons/logo-128-christmas-celebration.png +0 -0
- package/host/images/icons/logo-128.png +0 -0
- package/host/images/icons/logo-16-christmas-celebration.png +0 -0
- package/host/images/icons/logo-16.png +0 -0
- package/host/images/icons/logo-24-christmas-celebration.png +0 -0
- package/host/images/icons/logo-24.png +0 -0
- package/host/images/icons/logo-32-christmas-celebration.png +0 -0
- package/host/images/icons/logo-32.png +0 -0
- package/host/images/icons/logo-48-christmas-celebration.png +0 -0
- package/host/images/icons/logo-48.png +0 -0
- package/host/images/loading.gif +0 -0
- package/host/images/logo-bravotech-white.png +0 -0
- package/host/images/logo-bravotech.png +0 -0
- package/host/images/logo-inline-christmas-celebration.png +0 -0
- package/host/images/logo-inline.png +0 -0
- package/host/images/mic-off.png +0 -0
- package/host/images/mic-on.png +0 -0
- package/host/images/play.png +0 -0
- package/host/images/transfer.png +0 -0
- package/host/index.html +34 -0
- package/host/js/bravophone-noise-suppressor.js +418 -0
- package/host/js/bravophone-route-selector.js +1099 -0
- package/host/js/libwebphone.js +20 -0
- package/host/js/noise/LICENSE-web-noise-suppressor.txt +21 -0
- package/host/js/noise/rnnoise-worklet.js +13 -0
- package/host/js/noise/rnnoise.wasm +0 -0
- package/host/js/noise/rnnoise_simd.wasm +0 -0
- package/host/mock-webphone.js +195 -0
- package/host/mock.html +54 -0
- package/host/popup.js +23 -0
- package/host/shim/chrome-shim.js +287 -0
- package/host/shim/guest-bridge.js +353 -0
- package/host/shim/messages.js +13 -0
- package/host/styles/theme-fixes.css +98 -0
- package/package.json +4 -2
- package/types/index.d.ts +30 -2
package/dist/bravophone.mjs
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
const
|
|
1
|
+
const Z = 'stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"', fe = `<svg viewBox="0 0 24 24" fill="none" ${Z} aria-hidden="true">
|
|
2
2
|
<path class="bp-i-body" d="M15.6 12.8a11 11 0 0 1-4.4-4.4l1-1a1.6 1.6 0 0 0 .3-1.7c-.2-.7-.4-1.4-.5-2.2A1.6 1.6 0 0 0 10.4 2H7.9a1.6 1.6 0 0 0-1.6 1.8 15.8 15.8 0 0 0 2.4 6.9 15.6 15.6 0 0 0 4.8 4.8 15.8 15.8 0 0 0 6.9 2.4 1.6 1.6 0 0 0 1.7-1.6v-2.5a1.6 1.6 0 0 0-1.4-1.6c-.8-.1-1.5-.3-2.2-.5a1.6 1.6 0 0 0-1.7.4z"/>
|
|
3
3
|
<path class="bp-i-wave bp-i-wave-1" d="M14.5 6.2a4 4 0 0 1 3.3 3.3"/>
|
|
4
4
|
<path class="bp-i-wave bp-i-wave-2" d="M14.1 2.6a7.6 7.6 0 0 1 7.3 7.3"/>
|
|
5
|
-
</svg>`,
|
|
5
|
+
</svg>`, xe = `<svg viewBox="0 0 24 24" fill="none" ${Z} aria-hidden="true">
|
|
6
6
|
<path class="bp-i-bar bp-i-bar-1" d="M4 10v4"/>
|
|
7
7
|
<path class="bp-i-bar bp-i-bar-2" d="M8.7 6.5v11"/>
|
|
8
8
|
<path class="bp-i-bar bp-i-bar-3" d="M12 3.5v17"/>
|
|
9
9
|
<path class="bp-i-bar bp-i-bar-4" d="M15.3 6.5v11"/>
|
|
10
10
|
<path class="bp-i-bar bp-i-bar-5" d="M20 10v4"/>
|
|
11
|
-
</svg>`,
|
|
11
|
+
</svg>`, we = `<svg viewBox="0 0 24 24" fill="none" ${Z} aria-hidden="true">
|
|
12
12
|
<path class="bp-i-body" d="M4 13v-1a8 8 0 0 1 16 0v1"/>
|
|
13
13
|
<path class="bp-i-body" d="M20 14.5v2a3.5 3.5 0 0 1-3.5 3.5H13"/>
|
|
14
14
|
<rect class="bp-i-cup" x="1.6" y="12.6" width="4.4" height="6.4" rx="1.8"/>
|
|
15
15
|
<rect class="bp-i-cup" x="18" y="12.6" width="4.4" height="6.4" rx="1.8"/>
|
|
16
|
-
</svg>`,
|
|
16
|
+
</svg>`, ye = `<svg viewBox="0 0 24 24" fill="none" ${Z} aria-hidden="true">
|
|
17
17
|
<path class="bp-i-body" d="M21 11.5a8.4 8.4 0 0 1-9 8.4 9 9 0 0 1-2.9-.5L3 21.5l1.5-4.6A8.4 8.4 0 0 1 12 3.1a8.4 8.4 0 0 1 9 8.4z"/>
|
|
18
18
|
<path class="bp-i-hand" d="M14.6 14.4a6.5 6.5 0 0 1-3.2-3.2l.7-.7a1 1 0 0 0 .2-1.1 6 6 0 0 1-.3-1.2 1 1 0 0 0-1-.8H9.6a1 1 0 0 0-1 1.1 9.6 9.6 0 0 0 4.8 7.2 1 1 0 0 0 1.4-.9v-1.2a1 1 0 0 0-.8-1z"/>
|
|
19
|
-
</svg>`,
|
|
19
|
+
</svg>`, ve = `<svg viewBox="0 0 10 16" width="10" height="16" fill="currentColor" aria-hidden="true">
|
|
20
20
|
<circle cx="2.6" cy="2.6" r="1.35"/><circle cx="7.4" cy="2.6" r="1.35"/>
|
|
21
21
|
<circle cx="2.6" cy="8" r="1.35"/><circle cx="7.4" cy="8" r="1.35"/>
|
|
22
22
|
<circle cx="2.6" cy="13.4" r="1.35"/><circle cx="7.4" cy="13.4" r="1.35"/>
|
|
23
|
-
</svg>`,
|
|
24
|
-
"phone-waves":
|
|
25
|
-
waveform:
|
|
26
|
-
headset:
|
|
27
|
-
"chat-phone":
|
|
28
|
-
},
|
|
23
|
+
</svg>`, J = {
|
|
24
|
+
"phone-waves": fe,
|
|
25
|
+
waveform: xe,
|
|
26
|
+
headset: we,
|
|
27
|
+
"chat-phone": ye
|
|
28
|
+
}, ae = "phone-waves", ke = `
|
|
29
29
|
.bp-launcher-icon svg { width: 100%; height: 100%; display: block; overflow: visible; }
|
|
30
30
|
|
|
31
31
|
/* Ponto de status no canto do ícone — verde registrado, cinza sem linha. */
|
|
@@ -95,7 +95,7 @@ const K = 'stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-
|
|
|
95
95
|
.bp-i-wave, .bp-i-body, .bp-i-hand, .bp-i-bar { animation: none !important; }
|
|
96
96
|
.bp-launcher-icon { transition: none; }
|
|
97
97
|
}
|
|
98
|
-
`,
|
|
98
|
+
`, Me = `
|
|
99
99
|
:host { all: initial; }
|
|
100
100
|
* { box-sizing: border-box; }
|
|
101
101
|
|
|
@@ -227,6 +227,21 @@ const K = 'stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-
|
|
|
227
227
|
/* Uma janela docada nao se redimensiona pelas bordas coladas na viewport. */
|
|
228
228
|
.bp-root.bp-docked { border-radius: 0; }
|
|
229
229
|
|
|
230
|
+
/* ---- destaque: "a janela esta aqui" ----
|
|
231
|
+
Disparado ao clicar na aba com o webphone ja aberto. Um halo que cresce e
|
|
232
|
+
some, no lugar de um shake: em interface, tremer significa erro ou acao
|
|
233
|
+
negada (senha errada), e aqui nada deu errado. */
|
|
234
|
+
@keyframes bp-attention {
|
|
235
|
+
0% { box-shadow: 0 12px 40px rgba(0,0,0,.45), 0 0 0 0 rgba(124,108,245,.55); }
|
|
236
|
+
55% { box-shadow: 0 12px 40px rgba(0,0,0,.45), 0 0 0 12px rgba(124,108,245,0); }
|
|
237
|
+
100% { box-shadow: 0 12px 40px rgba(0,0,0,.45), 0 0 0 0 rgba(124,108,245,0); }
|
|
238
|
+
}
|
|
239
|
+
.bp-root.bp-attention { animation: bp-attention .85s ease-out 2; }
|
|
240
|
+
|
|
241
|
+
@media (prefers-reduced-motion: reduce) {
|
|
242
|
+
.bp-root.bp-attention { animation: none; outline: 2px solid #7c6cf5; outline-offset: 2px; }
|
|
243
|
+
}
|
|
244
|
+
|
|
230
245
|
/* ---- previa de encaixe (docking) ----
|
|
231
246
|
Fantasma que mostra onde a janela vai parar antes de soltar. */
|
|
232
247
|
.bp-preview {
|
|
@@ -244,7 +259,9 @@ const K = 'stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-
|
|
|
244
259
|
.bp-launcher {
|
|
245
260
|
position: fixed;
|
|
246
261
|
top: 50%;
|
|
247
|
-
|
|
262
|
+
/* Acima da janela (2147483000): a aba nunca some, e uma janela docada na
|
|
263
|
+
mesma borda a esconderia. */
|
|
264
|
+
z-index: 2147483001;
|
|
248
265
|
display: flex;
|
|
249
266
|
align-items: center;
|
|
250
267
|
gap: 0;
|
|
@@ -341,25 +358,25 @@ const K = 'stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-
|
|
|
341
358
|
.bp-launcher[data-badge]:not([data-badge=""]) { animation: none; }
|
|
342
359
|
}
|
|
343
360
|
|
|
344
|
-
${
|
|
345
|
-
`,
|
|
346
|
-
function
|
|
361
|
+
${ke}
|
|
362
|
+
`, ge = "bravophone:widget:geometry", V = 28, X = 32;
|
|
363
|
+
function Le(e) {
|
|
347
364
|
try {
|
|
348
|
-
const a = localStorage.getItem(
|
|
365
|
+
const a = localStorage.getItem(ge);
|
|
349
366
|
if (!a) return { ...e };
|
|
350
|
-
const
|
|
351
|
-
return
|
|
367
|
+
const n = JSON.parse(a);
|
|
368
|
+
return n.dock ? { ...e, ...n, ...U(n.dock, n) } : { ...e, ...n };
|
|
352
369
|
} catch (a) {
|
|
353
370
|
return { ...e };
|
|
354
371
|
}
|
|
355
372
|
}
|
|
356
|
-
function
|
|
373
|
+
function K(e) {
|
|
357
374
|
try {
|
|
358
|
-
localStorage.setItem(
|
|
375
|
+
localStorage.setItem(ge, JSON.stringify(e));
|
|
359
376
|
} catch (a) {
|
|
360
377
|
}
|
|
361
378
|
}
|
|
362
|
-
function
|
|
379
|
+
function he(e) {
|
|
363
380
|
return {
|
|
364
381
|
minWidth: e.minWidth,
|
|
365
382
|
minHeight: e.minHeight,
|
|
@@ -370,107 +387,107 @@ function se(e) {
|
|
|
370
387
|
};
|
|
371
388
|
}
|
|
372
389
|
function R(e) {
|
|
373
|
-
const a = Math.max(0, window.innerWidth - e.width),
|
|
390
|
+
const a = Math.max(0, window.innerWidth - e.width), n = Math.max(0, window.innerHeight - 40);
|
|
374
391
|
return {
|
|
375
392
|
...e,
|
|
376
393
|
x: Math.min(Math.max(0, e.x), a),
|
|
377
|
-
y: Math.min(Math.max(0, e.y),
|
|
394
|
+
y: Math.min(Math.max(0, e.y), n)
|
|
378
395
|
};
|
|
379
396
|
}
|
|
380
|
-
function
|
|
381
|
-
const
|
|
397
|
+
function U(e, a) {
|
|
398
|
+
const n = window.innerWidth, o = window.innerHeight, i = Math.round(n / 2), d = Math.round(o / 2), u = Math.min(a.width, n);
|
|
382
399
|
switch (e) {
|
|
383
400
|
case "left":
|
|
384
|
-
return { x: 0, y: 0, width: u, height:
|
|
401
|
+
return { x: 0, y: 0, width: u, height: o };
|
|
385
402
|
case "right":
|
|
386
|
-
return { x:
|
|
403
|
+
return { x: n - u, y: 0, width: u, height: o };
|
|
387
404
|
case "left-half":
|
|
388
|
-
return { x: 0, y: 0, width:
|
|
405
|
+
return { x: 0, y: 0, width: i, height: o };
|
|
389
406
|
case "right-half":
|
|
390
|
-
return { x:
|
|
407
|
+
return { x: n - i, y: 0, width: i, height: o };
|
|
391
408
|
case "top":
|
|
392
|
-
return { x: a.x, y: 0, width: u, height:
|
|
409
|
+
return { x: a.x, y: 0, width: u, height: d };
|
|
393
410
|
case "bottom":
|
|
394
|
-
return { x: a.x, y:
|
|
411
|
+
return { x: a.x, y: o - d, width: u, height: d };
|
|
395
412
|
case "top-half":
|
|
396
|
-
return { x: 0, y: 0, width:
|
|
413
|
+
return { x: 0, y: 0, width: n, height: d };
|
|
397
414
|
case "bottom-half":
|
|
398
|
-
return { x: 0, y:
|
|
415
|
+
return { x: 0, y: o - d, width: n, height: d };
|
|
399
416
|
case "max":
|
|
400
|
-
return { x: 0, y: 0, width:
|
|
417
|
+
return { x: 0, y: 0, width: n, height: o };
|
|
401
418
|
default:
|
|
402
419
|
return { x: a.x, y: a.y, width: a.width, height: a.height };
|
|
403
420
|
}
|
|
404
421
|
}
|
|
405
|
-
function
|
|
406
|
-
const
|
|
407
|
-
return (f || t) &&
|
|
422
|
+
function ze(e, a, n) {
|
|
423
|
+
const o = window.innerWidth, i = window.innerHeight, d = e <= V, u = e >= o - V, f = a <= V, t = a >= i - V;
|
|
424
|
+
return (f || t) && d ? "left-half" : (f || t) && u ? "right-half" : f ? n || "max" : t ? "bottom-half" : d ? "left" : u ? "right" : null;
|
|
408
425
|
}
|
|
409
|
-
function
|
|
410
|
-
let t = { ...
|
|
426
|
+
function Se({ root: e, handle: a, handles: n, preview: o, geometry: i, limits: d, topDock: u, onChange: f }) {
|
|
427
|
+
let t = { ...i }, g = null, p = "", c = null, h = null, x = null, w = null;
|
|
411
428
|
const z = () => {
|
|
412
429
|
e.style.left = `${t.x}px`, e.style.top = `${t.y}px`, e.style.width = `${t.width}px`, e.style.height = `${t.height}px`, e.classList.toggle("bp-docked", !!t.dock), f == null || f(t);
|
|
413
|
-
}, C = (
|
|
414
|
-
if (
|
|
415
|
-
if (!
|
|
416
|
-
|
|
430
|
+
}, C = (r) => {
|
|
431
|
+
if (o) {
|
|
432
|
+
if (!r) {
|
|
433
|
+
o.hidden = !0;
|
|
417
434
|
return;
|
|
418
435
|
}
|
|
419
|
-
|
|
436
|
+
o.hidden = !1, o.style.left = `${r.x}px`, o.style.top = `${r.y}px`, o.style.width = `${r.width}px`, o.style.height = `${r.height}px`;
|
|
420
437
|
}
|
|
421
|
-
},
|
|
422
|
-
const l =
|
|
423
|
-
let { x:
|
|
424
|
-
p.includes("e") && (
|
|
425
|
-
},
|
|
438
|
+
}, $ = (r, b) => {
|
|
439
|
+
const l = he(d);
|
|
440
|
+
let { x: v, y: S, width: E, height: H } = c;
|
|
441
|
+
p.includes("e") && (E = c.width + r), p.includes("w") && (E = c.width - r), p.includes("s") && (H = c.height + b), p.includes("n") && (H = c.height - b), E = Math.min(l.maxWidth, Math.max(l.minWidth, E)), H = Math.min(l.maxHeight, Math.max(l.minHeight, H)), p.includes("w") && (v = c.x + (c.width - E)), p.includes("n") && (S = c.y + (c.height - H)), p.includes("e") && Math.abs(v + E - window.innerWidth) <= X && (E = window.innerWidth - v), p.includes("w") && Math.abs(v) <= X && (E += v, v = 0), p.includes("s") && Math.abs(S + H - window.innerHeight) <= X && (H = window.innerHeight - S), p.includes("n") && Math.abs(S) <= X && (H += S, S = 0), t = { ...t, x: v, y: S, width: E, height: H, dock: null }, z();
|
|
442
|
+
}, j = (r, b, l, v) => {
|
|
426
443
|
if (t.dock) {
|
|
427
|
-
const
|
|
428
|
-
t = { ...t, ...
|
|
429
|
-
...
|
|
444
|
+
const S = w || { width: d.width, height: d.height }, E = h.x / Math.max(1, t.width);
|
|
445
|
+
t = { ...t, ...S, dock: null }, h = { x: Math.round(S.width * E), y: Math.min(h.y, 32) }, c = {
|
|
446
|
+
...c,
|
|
430
447
|
x: l - h.x,
|
|
431
|
-
y:
|
|
432
|
-
px:
|
|
433
|
-
py:
|
|
434
|
-
},
|
|
448
|
+
y: v - h.y,
|
|
449
|
+
px: c.px + r,
|
|
450
|
+
py: c.py + b
|
|
451
|
+
}, r = 0, b = 0;
|
|
435
452
|
}
|
|
436
|
-
t = R({ ...t, x:
|
|
437
|
-
},
|
|
438
|
-
|
|
439
|
-
},
|
|
440
|
-
l.button === 0 && (
|
|
441
|
-
},
|
|
442
|
-
if (!g || !
|
|
443
|
-
const b =
|
|
444
|
-
g === "drag" ?
|
|
445
|
-
},
|
|
453
|
+
t = R({ ...t, x: c.x + r, y: c.y + b }), z(), x = ze(l, v, u), C(x ? U(x, t) : null);
|
|
454
|
+
}, _ = () => {
|
|
455
|
+
x && (w = w || { width: t.width, height: t.height }, t = { ...t, ...U(x, t), dock: x }, z());
|
|
456
|
+
}, F = (r, b) => (l) => {
|
|
457
|
+
l.button === 0 && (r === "drag" && l.target.closest(".bp-btn") || (g = r, p = b || "", c = { px: l.clientX, py: l.clientY, ...t }, h = { x: l.clientX - t.x, y: l.clientY - t.y }, t.dock || (w = { width: t.width, height: t.height }), e.classList.add(r === "drag" ? "bp-dragging" : "bp-resizing"), l.currentTarget.setPointerCapture(l.pointerId), l.preventDefault()));
|
|
458
|
+
}, D = (r) => {
|
|
459
|
+
if (!g || !c) return;
|
|
460
|
+
const b = r.clientX - c.px, l = r.clientY - c.py;
|
|
461
|
+
g === "drag" ? j(b, l, r.clientX, r.clientY) : $(b, l);
|
|
462
|
+
}, A = (r) => {
|
|
446
463
|
if (g) {
|
|
447
|
-
e.classList.remove("bp-dragging", "bp-resizing"), C(null), g === "drag" &&
|
|
464
|
+
e.classList.remove("bp-dragging", "bp-resizing"), C(null), g === "drag" && _(), g = null, p = "", c = null, x = null;
|
|
448
465
|
try {
|
|
449
|
-
|
|
466
|
+
r.currentTarget.releasePointerCapture(r.pointerId);
|
|
450
467
|
} catch (b) {
|
|
451
468
|
}
|
|
452
|
-
|
|
469
|
+
K(t);
|
|
453
470
|
}
|
|
454
471
|
};
|
|
455
|
-
a.addEventListener("pointerdown",
|
|
456
|
-
|
|
472
|
+
a.addEventListener("pointerdown", F("drag")), a.addEventListener("pointermove", D), a.addEventListener("pointerup", A), a.addEventListener("pointercancel", A), (n || []).forEach(({ el: r, dir: b }) => {
|
|
473
|
+
r.addEventListener("pointerdown", F("resize", b)), r.addEventListener("pointermove", D), r.addEventListener("pointerup", A), r.addEventListener("pointercancel", A);
|
|
457
474
|
});
|
|
458
|
-
const
|
|
459
|
-
t = t.dock ? { ...t, ...
|
|
475
|
+
const N = () => {
|
|
476
|
+
t = t.dock ? { ...t, ...U(t.dock, t) } : R(t), z();
|
|
460
477
|
};
|
|
461
|
-
window.addEventListener("resize",
|
|
478
|
+
window.addEventListener("resize", N);
|
|
462
479
|
const G = {
|
|
463
|
-
start(
|
|
480
|
+
start(r) {
|
|
464
481
|
var b, l;
|
|
465
|
-
g = "drag",
|
|
482
|
+
g = "drag", c = { px: r.x, py: r.y, ...t }, h = { x: (b = r.cx) != null ? b : t.width / 2, y: (l = r.cy) != null ? l : 20 }, t.dock || (w = { width: t.width, height: t.height }), e.classList.add("bp-dragging");
|
|
466
483
|
},
|
|
467
|
-
move(
|
|
468
|
-
if (g !== "drag" || !
|
|
469
|
-
const b =
|
|
470
|
-
|
|
484
|
+
move(r) {
|
|
485
|
+
if (g !== "drag" || !c) return;
|
|
486
|
+
const b = r.x - c.px, l = r.y - c.py;
|
|
487
|
+
j(b, l, c.x + b + h.x, c.y + l + h.y);
|
|
471
488
|
},
|
|
472
489
|
end() {
|
|
473
|
-
g === "drag" && (e.classList.remove("bp-dragging"), C(null),
|
|
490
|
+
g === "drag" && (e.classList.remove("bp-dragging"), C(null), _(), g = null, c = null, x = null, K(t));
|
|
474
491
|
}
|
|
475
492
|
};
|
|
476
493
|
return z(), {
|
|
@@ -478,136 +495,186 @@ function ke({ root: e, handle: a, handles: i, preview: r, geometry: o, limits: s
|
|
|
478
495
|
get geometry() {
|
|
479
496
|
return { ...t };
|
|
480
497
|
},
|
|
481
|
-
set(
|
|
482
|
-
const b =
|
|
483
|
-
l.width = Math.min(b.maxWidth, Math.max(b.minWidth, l.width)), l.height = Math.min(b.maxHeight, Math.max(b.minHeight, l.height)), t = R(l), z(),
|
|
498
|
+
set(r) {
|
|
499
|
+
const b = he(d), l = { ...t, ...r, dock: null };
|
|
500
|
+
l.width = Math.min(b.maxWidth, Math.max(b.minWidth, l.width)), l.height = Math.min(b.maxHeight, Math.max(b.minHeight, l.height)), t = R(l), z(), K(t);
|
|
484
501
|
},
|
|
485
502
|
/** 'left' | 'right' | 'left-half' | 'right-half' | 'max' | 'float' */
|
|
486
|
-
dock(
|
|
487
|
-
if (!
|
|
488
|
-
const b =
|
|
503
|
+
dock(r) {
|
|
504
|
+
if (!r || r === "float") {
|
|
505
|
+
const b = w || { width: d.width, height: d.height };
|
|
489
506
|
t = R({ ...t, ...b, dock: null });
|
|
490
507
|
} else
|
|
491
|
-
t.dock || (
|
|
492
|
-
z(),
|
|
508
|
+
t.dock || (w = { width: t.width, height: t.height }), t = { ...t, ...U(r, t), dock: r };
|
|
509
|
+
z(), K(t);
|
|
493
510
|
},
|
|
494
511
|
destroy() {
|
|
495
|
-
window.removeEventListener("resize",
|
|
512
|
+
window.removeEventListener("resize", N);
|
|
496
513
|
}
|
|
497
514
|
};
|
|
498
515
|
}
|
|
499
|
-
const
|
|
500
|
-
function
|
|
501
|
-
const
|
|
502
|
-
let
|
|
516
|
+
const be = "bravophone/v1";
|
|
517
|
+
function Ee({ frame: e, origin: a, onEvent: n }) {
|
|
518
|
+
const o = /* @__PURE__ */ new Map();
|
|
519
|
+
let i = 0, d = !1;
|
|
503
520
|
const u = [], f = (g) => {
|
|
504
|
-
var
|
|
521
|
+
var c;
|
|
505
522
|
if (g.origin !== a || g.source !== e.contentWindow) return;
|
|
506
523
|
const p = g.data;
|
|
507
|
-
if (!(!p || p.protocol !==
|
|
524
|
+
if (!(!p || p.protocol !== be)) {
|
|
508
525
|
if (p.type === "ready") {
|
|
509
|
-
for (
|
|
510
|
-
|
|
526
|
+
for (d = !0; u.length; ) u.shift()();
|
|
527
|
+
n == null || n("ready", (c = p.payload) != null ? c : {});
|
|
511
528
|
return;
|
|
512
529
|
}
|
|
513
530
|
if (p.type === "reply") {
|
|
514
|
-
const h =
|
|
531
|
+
const h = o.get(p.id);
|
|
515
532
|
if (!h) return;
|
|
516
|
-
|
|
533
|
+
o.delete(p.id), clearTimeout(h.timer), p.error ? h.reject(new Error(p.error)) : h.resolve(p.payload);
|
|
517
534
|
return;
|
|
518
535
|
}
|
|
519
|
-
p.type === "event" && (
|
|
536
|
+
p.type === "event" && (n == null || n(p.name, p.payload));
|
|
520
537
|
}
|
|
521
538
|
};
|
|
522
539
|
window.addEventListener("message", f);
|
|
523
|
-
function t(g, p, { timeout:
|
|
524
|
-
return new Promise((h,
|
|
525
|
-
const
|
|
526
|
-
var
|
|
540
|
+
function t(g, p, { timeout: c = 15e3 } = {}) {
|
|
541
|
+
return new Promise((h, x) => {
|
|
542
|
+
const w = `${Date.now()}-${++i}`, z = () => {
|
|
543
|
+
var $;
|
|
527
544
|
const C = setTimeout(() => {
|
|
528
|
-
|
|
529
|
-
},
|
|
530
|
-
|
|
531
|
-
{ protocol:
|
|
545
|
+
o.delete(w), x(new Error(`Bravophone: timeout no comando "${g}"`));
|
|
546
|
+
}, c);
|
|
547
|
+
o.set(w, { resolve: h, reject: x, timer: C }), ($ = e.contentWindow) == null || $.postMessage(
|
|
548
|
+
{ protocol: be, type: "command", id: w, command: g, payload: p },
|
|
532
549
|
a
|
|
533
550
|
);
|
|
534
551
|
};
|
|
535
|
-
|
|
552
|
+
d ? z() : u.push(z);
|
|
536
553
|
});
|
|
537
554
|
}
|
|
538
555
|
return {
|
|
539
556
|
call: t,
|
|
540
557
|
get ready() {
|
|
541
|
-
return
|
|
558
|
+
return d;
|
|
542
559
|
},
|
|
543
560
|
destroy() {
|
|
544
|
-
window.removeEventListener("message", f),
|
|
561
|
+
window.removeEventListener("message", f), o.forEach(({ reject: g, timer: p }) => {
|
|
545
562
|
clearTimeout(p), g(new Error("Bravophone: widget destruído"));
|
|
546
|
-
}),
|
|
563
|
+
}), o.clear();
|
|
547
564
|
}
|
|
548
565
|
};
|
|
549
566
|
}
|
|
550
|
-
const
|
|
551
|
-
function
|
|
567
|
+
const me = "bravophone:launcher", He = 4, ie = 8;
|
|
568
|
+
function Te(e) {
|
|
552
569
|
try {
|
|
553
|
-
const a = localStorage.getItem(
|
|
570
|
+
const a = localStorage.getItem(me);
|
|
554
571
|
return a ? { ...e, ...JSON.parse(a) } : { ...e };
|
|
555
572
|
} catch (a) {
|
|
556
573
|
return { ...e };
|
|
557
574
|
}
|
|
558
575
|
}
|
|
559
|
-
function
|
|
576
|
+
function ne(e) {
|
|
560
577
|
try {
|
|
561
|
-
localStorage.setItem(
|
|
578
|
+
localStorage.setItem(me, JSON.stringify(e));
|
|
562
579
|
} catch (a) {
|
|
563
580
|
}
|
|
564
581
|
}
|
|
565
|
-
function
|
|
566
|
-
const
|
|
567
|
-
return Math.min(Math.max(
|
|
582
|
+
function q(e, a) {
|
|
583
|
+
const n = Math.max(ie, window.innerHeight - a - ie);
|
|
584
|
+
return Math.min(Math.max(ie, e), n);
|
|
568
585
|
}
|
|
569
|
-
function
|
|
570
|
-
let
|
|
586
|
+
function $e({ el: e, side: a, y: n, onOpen: o }) {
|
|
587
|
+
let i = { side: a, y: q(n, e.offsetHeight || 48) }, d = null, u = !1;
|
|
571
588
|
const f = () => {
|
|
572
|
-
e.dataset.side =
|
|
589
|
+
e.dataset.side = i.side, e.style.top = `${i.y}px`, e.style.right = i.side === "right" ? "0px" : "auto", e.style.left = i.side === "left" ? "0px" : "auto";
|
|
573
590
|
}, t = (h) => {
|
|
574
|
-
h.button === 0 && (
|
|
591
|
+
h.button === 0 && (d = { py: h.clientY, y: i.y }, u = !1, e.setPointerCapture(h.pointerId));
|
|
575
592
|
}, g = (h) => {
|
|
576
|
-
if (!
|
|
577
|
-
const
|
|
578
|
-
!u && Math.abs(
|
|
593
|
+
if (!d) return;
|
|
594
|
+
const x = h.clientY - d.py;
|
|
595
|
+
!u && Math.abs(x) < He || (u || (u = !0, e.classList.add("bp-launcher-dragging")), i.y = q(d.y + x, e.offsetHeight), f());
|
|
579
596
|
}, p = (h) => {
|
|
580
|
-
if (!
|
|
581
|
-
const
|
|
582
|
-
|
|
597
|
+
if (!d) return;
|
|
598
|
+
const x = u;
|
|
599
|
+
d = null, u = !1, e.classList.remove("bp-launcher-dragging");
|
|
583
600
|
try {
|
|
584
601
|
e.releasePointerCapture(h.pointerId);
|
|
585
|
-
} catch (
|
|
602
|
+
} catch (w) {
|
|
586
603
|
}
|
|
587
|
-
|
|
604
|
+
x ? ne(i) : o == null || o();
|
|
588
605
|
};
|
|
589
606
|
e.addEventListener("pointerdown", t), e.addEventListener("pointermove", g), e.addEventListener("pointerup", p), e.addEventListener("pointercancel", p), e.addEventListener("keydown", (h) => {
|
|
590
|
-
(h.key === "Enter" || h.key === " ") && (h.preventDefault(),
|
|
607
|
+
(h.key === "Enter" || h.key === " ") && (h.preventDefault(), o == null || o());
|
|
591
608
|
});
|
|
592
|
-
const
|
|
593
|
-
|
|
609
|
+
const c = () => {
|
|
610
|
+
i.y = q(i.y, e.offsetHeight), f();
|
|
594
611
|
};
|
|
595
|
-
return window.addEventListener("resize",
|
|
612
|
+
return window.addEventListener("resize", c), f(), {
|
|
596
613
|
get state() {
|
|
597
|
-
return { ...
|
|
614
|
+
return { ...i };
|
|
598
615
|
},
|
|
599
616
|
setSide(h) {
|
|
600
|
-
|
|
617
|
+
i.side = h, f(), ne(i);
|
|
601
618
|
},
|
|
602
619
|
moveTo(h) {
|
|
603
|
-
|
|
620
|
+
i.y = q(h, e.offsetHeight), f(), ne(i);
|
|
604
621
|
},
|
|
605
622
|
destroy() {
|
|
606
|
-
window.removeEventListener("resize",
|
|
623
|
+
window.removeEventListener("resize", c);
|
|
607
624
|
}
|
|
608
625
|
};
|
|
609
626
|
}
|
|
610
|
-
const
|
|
627
|
+
const Ie = "https://cdn.jsdelivr.net/npm";
|
|
628
|
+
function Oe(e, a = "@bravophone/webphone") {
|
|
629
|
+
return `${Ie}/${a}@${e}/host/`;
|
|
630
|
+
}
|
|
631
|
+
function We({ version: e, parentOrigin: a, token: n, base: o }) {
|
|
632
|
+
const i = o || Oe(e), d = JSON.stringify({ parentOrigin: a, token: n || null }).replace(/</g, "\\u003c");
|
|
633
|
+
return `<!doctype html>
|
|
634
|
+
<html lang="pt-BR">
|
|
635
|
+
<head>
|
|
636
|
+
<meta charset="UTF-8">
|
|
637
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
638
|
+
<title>Webphone BRAVOPHONE</title>
|
|
639
|
+
<!-- CRÍTICO no modo srcdoc. O bundle referencia as imagens por caminho
|
|
640
|
+
RELATIVO (src="images/answer.png"), fora do public_path. Sem <base>,
|
|
641
|
+
elas resolvem contra a página do integrador — o documento herda o
|
|
642
|
+
baseURI do pai — e somem todas: logo, atender, desligar, mudo, hold,
|
|
643
|
+
transferir. Com <base>, resolvem contra o CDN. -->
|
|
644
|
+
<base href="${i}">
|
|
645
|
+
<link rel="stylesheet" href="${i}css/dark-theme.css">
|
|
646
|
+
<link rel="stylesheet" href="${i}styles/theme-fixes.css">
|
|
647
|
+
<style>
|
|
648
|
+
html, body { margin: 0; height: 100%; background: #10131c; overflow: hidden; }
|
|
649
|
+
#app { height: 100%; }
|
|
650
|
+
</style>
|
|
651
|
+
<script>
|
|
652
|
+
(function () {
|
|
653
|
+
var cfg = ${d};
|
|
654
|
+
// O guest-bridge lê daqui: em srcdoc não há query string para carregar a
|
|
655
|
+
// origem do pai.
|
|
656
|
+
window.__bpParentOrigin = cfg.parentOrigin;
|
|
657
|
+
if (cfg.token) {
|
|
658
|
+
// Grava onde o bundle procura, antes dele avaliar, para a sessão já subir
|
|
659
|
+
// autenticada em vez de piscar a tela de login.
|
|
660
|
+
try { localStorage.setItem('bp.local.vxToken', JSON.stringify(cfg.token)); } catch (e) {}
|
|
661
|
+
}
|
|
662
|
+
})();
|
|
663
|
+
<\/script>
|
|
664
|
+
<script src="${i}shim/messages.js"><\/script>
|
|
665
|
+
<script src="${i}shim/chrome-shim.js"><\/script>
|
|
666
|
+
<script src="${i}js/libwebphone.js"><\/script>
|
|
667
|
+
<script src="${i}js/bravophone-route-selector.js"><\/script>
|
|
668
|
+
<script defer src="${i}popup.js"><\/script>
|
|
669
|
+
<script defer src="${i}shim/guest-bridge.js"><\/script>
|
|
670
|
+
</head>
|
|
671
|
+
<body>
|
|
672
|
+
<noscript><strong>O webphone precisa de JavaScript habilitado.</strong></noscript>
|
|
673
|
+
<div id="app"></div>
|
|
674
|
+
</body>
|
|
675
|
+
</html>`;
|
|
676
|
+
}
|
|
677
|
+
const ue = {
|
|
611
678
|
// 380x640 é a geometria da janela nativa da extensão — o layout do
|
|
612
679
|
// webphone é calibrado para ela, então é o ponto de partida aqui também.
|
|
613
680
|
width: 380,
|
|
@@ -620,196 +687,231 @@ const ce = {
|
|
|
620
687
|
maxHeight: 1400,
|
|
621
688
|
margin: 24
|
|
622
689
|
};
|
|
623
|
-
function
|
|
624
|
-
const
|
|
625
|
-
for (const [
|
|
626
|
-
|
|
627
|
-
return
|
|
690
|
+
function y(e, a = {}, n = []) {
|
|
691
|
+
const o = document.createElement(e);
|
|
692
|
+
for (const [i, d] of Object.entries(a))
|
|
693
|
+
i === "class" ? o.className = d : i === "text" ? o.textContent = d : d != null && o.setAttribute(i, d);
|
|
694
|
+
return n.forEach((i) => o.appendChild(i)), o;
|
|
628
695
|
}
|
|
629
|
-
function
|
|
696
|
+
function Ce(e) {
|
|
630
697
|
const {
|
|
631
698
|
hostUrl: a,
|
|
632
|
-
token:
|
|
633
|
-
position:
|
|
634
|
-
open:
|
|
635
|
-
launcher:
|
|
699
|
+
token: n,
|
|
700
|
+
position: o = "bottom-right",
|
|
701
|
+
open: i = !1,
|
|
702
|
+
launcher: d = !0,
|
|
636
703
|
title: u = "BRAVOPHONE",
|
|
637
|
-
// '
|
|
638
|
-
//
|
|
639
|
-
|
|
704
|
+
// 'bar' por padrão: título, indicador de estado e controles visíveis.
|
|
705
|
+
// 'none' preserva 100% da UI do webphone — sem barra, o arraste vem de
|
|
706
|
+
// dentro do iframe e só um botão de fechar aparece no hover.
|
|
707
|
+
frame: f = "bar",
|
|
640
708
|
// O que arrastar até a borda de cima faz. 'max' é o gesto universal;
|
|
641
709
|
// troque para 'top-half' se preferir as metades verticais no topo.
|
|
642
710
|
dockTop: t = "max",
|
|
643
711
|
// Lado da viewport em que a aba de abertura fica colada.
|
|
644
712
|
launcherSide: g = "right",
|
|
645
713
|
// Desenho da aba: 'phone-waves' | 'waveform' | 'headset' | 'chat-phone'
|
|
646
|
-
launcherIcon: p =
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
714
|
+
launcherIcon: p = ae,
|
|
715
|
+
// 'hosted' — o iframe navega para hostUrl (padrão)
|
|
716
|
+
// 'srcdoc' — o iframe roda na origem do site e busca o conteúdo no CDN
|
|
717
|
+
mode: c = "hosted",
|
|
718
|
+
// Base dos assets no modo srcdoc. Padrão: o CDN travado nesta versão.
|
|
719
|
+
// Serve para desenvolvimento (localhost) e para quem espelhar os assets.
|
|
720
|
+
hostBase: h,
|
|
721
|
+
version: x,
|
|
722
|
+
emit: w
|
|
723
|
+
} = e, z = c === "srcdoc", C = z ? window.location.origin : new URL(a).origin, $ = y("div", { "data-bravophone": "root" });
|
|
724
|
+
$.style.cssText = "all:initial;position:static";
|
|
725
|
+
const j = $.attachShadow({ mode: "open" });
|
|
726
|
+
j.appendChild(y("style", { text: Me }));
|
|
727
|
+
const _ = (() => {
|
|
728
|
+
var le;
|
|
729
|
+
const { width: s, height: M, margin: W } = ue, P = window.innerWidth - s - W, ce = window.innerHeight - M - W, pe = {
|
|
730
|
+
"bottom-right": { x: P, y: ce },
|
|
731
|
+
"bottom-left": { x: W, y: ce },
|
|
732
|
+
"top-right": { x: P, y: W },
|
|
733
|
+
"top-left": { x: W, y: W }
|
|
659
734
|
};
|
|
660
|
-
return R({ ...(
|
|
661
|
-
})(),
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
]),
|
|
735
|
+
return R({ ...(le = pe[o]) != null ? le : pe["bottom-right"], width: s, height: M });
|
|
736
|
+
})(), F = R(Le(_)), D = y("span", { class: "bp-status", "data-state": "connecting" }), A = y("button", { class: "bp-btn bp-btn-min", title: "Minimizar", text: "—" }), N = y("button", { class: "bp-btn bp-btn-close", title: "Fechar", text: "×" }), G = y("div", { class: "bp-header" }, [
|
|
737
|
+
D,
|
|
738
|
+
y("span", { class: "bp-title", text: u }),
|
|
739
|
+
A,
|
|
740
|
+
N
|
|
741
|
+
]), r = y("iframe", {
|
|
667
742
|
class: "bp-frame",
|
|
668
|
-
|
|
743
|
+
// allow= é obrigatório no modo hospedado (cross-origin). Em srcdoc o
|
|
744
|
+
// microfone já é herdado do topo, mas declarar não custa e documenta.
|
|
669
745
|
allow: "microphone; autoplay; clipboard-write; speaker-selection",
|
|
670
746
|
title: "Webphone BRAVOPHONE"
|
|
671
|
-
})
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
747
|
+
});
|
|
748
|
+
z ? r.setAttribute(
|
|
749
|
+
"srcdoc",
|
|
750
|
+
We({ version: x, parentOrigin: C, token: n, base: h })
|
|
751
|
+
) : r.setAttribute(
|
|
752
|
+
"src",
|
|
753
|
+
Ae(new URL(a), { token: n, embed: "1", parent: location.origin })
|
|
754
|
+
);
|
|
755
|
+
const l = ["n", "s", "w", "e", "nw", "ne", "sw", "se"].map((s) => ({
|
|
756
|
+
el: y("div", { class: `bp-h bp-h-${s}` }),
|
|
757
|
+
dir: s
|
|
758
|
+
})), v = y("div", { class: "bp-preview" });
|
|
759
|
+
v.hidden = !0;
|
|
760
|
+
const S = y("button", { class: "bp-btn bp-btn-close", title: "Fechar", text: "×" }), E = y("div", { class: "bp-overlay" }, [S]), H = y("div", { class: "bp-body" }, [r, E]), k = y("div", { class: "bp-root" }, [G, H, ...l.map((s) => s.el)]);
|
|
761
|
+
f !== "bar" && k.classList.add("bp-chromeless"), k.hidden = !i;
|
|
762
|
+
const Q = y("span", { class: "bp-launcher-icon" });
|
|
763
|
+
Q.innerHTML = J[p] || J[ae];
|
|
764
|
+
const oe = y("span", { class: "bp-launcher-grip", "aria-hidden": "true" });
|
|
765
|
+
oe.innerHTML = ve;
|
|
766
|
+
const T = y("div", {
|
|
683
767
|
class: "bp-launcher",
|
|
684
768
|
role: "button",
|
|
685
769
|
tabindex: "0",
|
|
686
770
|
title: "Abrir webphone",
|
|
687
771
|
"aria-label": "Abrir webphone"
|
|
688
772
|
}, [
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
773
|
+
oe,
|
|
774
|
+
Q,
|
|
775
|
+
y("span", { class: "bp-badge" })
|
|
692
776
|
]);
|
|
693
|
-
|
|
694
|
-
const
|
|
777
|
+
T.dataset.state = "connecting", T.hidden = !d, j.append(v, k, T), document.body.appendChild($);
|
|
778
|
+
const se = Te({
|
|
695
779
|
side: g,
|
|
696
780
|
y: Math.round(window.innerHeight / 2 - 24)
|
|
697
|
-
}),
|
|
698
|
-
el:
|
|
699
|
-
side:
|
|
700
|
-
y:
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
781
|
+
}), de = $e({
|
|
782
|
+
el: T,
|
|
783
|
+
side: se.side,
|
|
784
|
+
y: q(se.y, 48),
|
|
785
|
+
// A aba nunca some, então o clique tem dois papéis: abrir quando fechada,
|
|
786
|
+
// e localizar quando já aberta.
|
|
787
|
+
onOpen: () => O.reveal()
|
|
788
|
+
}), I = Se({
|
|
789
|
+
root: k,
|
|
790
|
+
handle: G,
|
|
791
|
+
handles: l,
|
|
792
|
+
preview: v,
|
|
793
|
+
geometry: F,
|
|
794
|
+
limits: ue,
|
|
709
795
|
topDock: t,
|
|
710
|
-
onChange: (
|
|
711
|
-
}),
|
|
712
|
-
frame:
|
|
713
|
-
origin:
|
|
714
|
-
onEvent: (
|
|
715
|
-
var
|
|
716
|
-
if (
|
|
717
|
-
})),
|
|
718
|
-
const
|
|
719
|
-
|
|
796
|
+
onChange: (s) => w("resize", { width: s.width, height: s.height, dock: s.dock || null })
|
|
797
|
+
}), ee = Ee({
|
|
798
|
+
frame: r,
|
|
799
|
+
origin: C,
|
|
800
|
+
onEvent: (s, M) => {
|
|
801
|
+
var W;
|
|
802
|
+
if (s === "ready" && (D.dataset.state = "ready", T.dataset.state = "ready", n && ee.call("auth", { token: n }).catch(() => {
|
|
803
|
+
})), s === "state") {
|
|
804
|
+
const P = (W = M == null ? void 0 : M.state) != null ? W : "ready";
|
|
805
|
+
D.dataset.state = P, T.dataset.state = P;
|
|
720
806
|
}
|
|
721
|
-
if (
|
|
722
|
-
|
|
807
|
+
if (s === "call:incoming" && (O.show(), T.dataset.badge = "1", T.dataset.state = "ringing"), s === "call:answered" && (T.dataset.state = "incall"), s === "call:ended" && (delete T.dataset.badge, T.dataset.state = "ready"), s === "drag:start") {
|
|
808
|
+
I.external.start(M);
|
|
723
809
|
return;
|
|
724
810
|
}
|
|
725
|
-
if (
|
|
726
|
-
|
|
811
|
+
if (s === "drag:move") {
|
|
812
|
+
I.external.move(M);
|
|
727
813
|
return;
|
|
728
814
|
}
|
|
729
|
-
if (
|
|
730
|
-
|
|
815
|
+
if (s === "drag:end") {
|
|
816
|
+
I.external.end();
|
|
731
817
|
return;
|
|
732
818
|
}
|
|
733
|
-
|
|
819
|
+
w(s, M);
|
|
734
820
|
}
|
|
735
821
|
});
|
|
736
|
-
let
|
|
737
|
-
const
|
|
738
|
-
el:
|
|
739
|
-
bridge:
|
|
822
|
+
let Y = !1, te = null;
|
|
823
|
+
const O = {
|
|
824
|
+
el: $,
|
|
825
|
+
bridge: ee,
|
|
740
826
|
show() {
|
|
741
|
-
|
|
827
|
+
k.hidden = !1, w("open");
|
|
742
828
|
},
|
|
743
829
|
hide() {
|
|
744
|
-
|
|
830
|
+
k.hidden = !0, w("close");
|
|
745
831
|
},
|
|
746
832
|
toggle() {
|
|
747
|
-
|
|
833
|
+
k.hidden ? O.show() : O.hide();
|
|
834
|
+
},
|
|
835
|
+
/**
|
|
836
|
+
* Traz a janela para a atenção do usuário.
|
|
837
|
+
* Fechada: abre. Aberta e fora de vista: traz de volta. Aberta e
|
|
838
|
+
* visível: um halo curto, para o olho encontrá-la.
|
|
839
|
+
*/
|
|
840
|
+
reveal() {
|
|
841
|
+
if (k.hidden) {
|
|
842
|
+
O.show();
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
const s = I.geometry;
|
|
846
|
+
(s.x + s.width < 40 || s.x > window.innerWidth - 40 || s.y > window.innerHeight - 40) && I.set({
|
|
847
|
+
x: Math.round((window.innerWidth - s.width) / 2),
|
|
848
|
+
y: Math.round((window.innerHeight - s.height) / 2)
|
|
849
|
+
}), k.classList.remove("bp-attention"), k.offsetWidth, k.classList.add("bp-attention"), clearTimeout(te), te = setTimeout(() => k.classList.remove("bp-attention"), 1800), w("reveal");
|
|
748
850
|
},
|
|
749
851
|
get isOpen() {
|
|
750
|
-
return !
|
|
852
|
+
return !k.hidden;
|
|
751
853
|
},
|
|
752
|
-
minimize(
|
|
854
|
+
minimize(s) {
|
|
753
855
|
if (f !== "bar") {
|
|
754
|
-
|
|
856
|
+
O.hide();
|
|
755
857
|
return;
|
|
756
858
|
}
|
|
757
|
-
|
|
859
|
+
Y = s != null ? s : !Y, k.classList.toggle("bp-minimized", Y), A.textContent = Y ? "▢" : "—";
|
|
758
860
|
},
|
|
759
|
-
move(
|
|
760
|
-
|
|
861
|
+
move(s, M) {
|
|
862
|
+
I.set({ x: s, y: M });
|
|
761
863
|
},
|
|
762
|
-
resize(
|
|
763
|
-
|
|
864
|
+
resize(s, M) {
|
|
865
|
+
I.set({ width: s, height: M });
|
|
764
866
|
},
|
|
765
|
-
dock(
|
|
766
|
-
|
|
867
|
+
dock(s) {
|
|
868
|
+
I.dock(s);
|
|
767
869
|
},
|
|
768
|
-
setLauncherSide(
|
|
769
|
-
|
|
870
|
+
setLauncherSide(s) {
|
|
871
|
+
de.setSide(s);
|
|
770
872
|
},
|
|
771
|
-
setLauncherIcon(
|
|
772
|
-
|
|
873
|
+
setLauncherIcon(s) {
|
|
874
|
+
Q.innerHTML = J[s] || J[ae];
|
|
773
875
|
},
|
|
774
876
|
get geometry() {
|
|
775
|
-
return
|
|
877
|
+
return I.geometry;
|
|
776
878
|
},
|
|
777
879
|
destroy() {
|
|
778
|
-
|
|
880
|
+
clearTimeout(te), ee.destroy(), I.destroy(), de.destroy(), v.remove(), $.remove();
|
|
779
881
|
}
|
|
780
882
|
};
|
|
781
|
-
return
|
|
782
|
-
}
|
|
783
|
-
function
|
|
784
|
-
const
|
|
785
|
-
for (const [
|
|
786
|
-
|
|
787
|
-
return a.token && (
|
|
788
|
-
}
|
|
789
|
-
const
|
|
790
|
-
let
|
|
791
|
-
const
|
|
792
|
-
function
|
|
793
|
-
var
|
|
794
|
-
(
|
|
883
|
+
return N.addEventListener("click", () => O.hide()), A.addEventListener("click", () => O.minimize()), S.addEventListener("click", () => O.hide()), O;
|
|
884
|
+
}
|
|
885
|
+
function Ae(e, a) {
|
|
886
|
+
const n = new URL(e.href);
|
|
887
|
+
for (const [o, i] of Object.entries(a))
|
|
888
|
+
i != null && i !== "" && n.searchParams.set(o, i);
|
|
889
|
+
return a.token && (n.searchParams.delete("token"), n.hash = `token=${encodeURIComponent(a.token)}`), n.href;
|
|
890
|
+
}
|
|
891
|
+
const Be = "https://webphone.bravophone.com/embed/";
|
|
892
|
+
let L = null;
|
|
893
|
+
const B = /* @__PURE__ */ new Map();
|
|
894
|
+
function De(e, a) {
|
|
895
|
+
var n, o;
|
|
896
|
+
(n = B.get(e)) == null || n.forEach((i) => {
|
|
795
897
|
try {
|
|
796
|
-
|
|
797
|
-
} catch (
|
|
798
|
-
console.error("[Bravophone] listener falhou:",
|
|
898
|
+
i(a);
|
|
899
|
+
} catch (d) {
|
|
900
|
+
console.error("[Bravophone] listener falhou:", d);
|
|
799
901
|
}
|
|
800
|
-
}), (
|
|
902
|
+
}), (o = B.get("*")) == null || o.forEach((i) => {
|
|
801
903
|
try {
|
|
802
|
-
|
|
803
|
-
} catch (
|
|
804
|
-
console.error("[Bravophone] listener falhou:",
|
|
904
|
+
i({ event: e, payload: a });
|
|
905
|
+
} catch (d) {
|
|
906
|
+
console.error("[Bravophone] listener falhou:", d);
|
|
805
907
|
}
|
|
806
908
|
});
|
|
807
909
|
}
|
|
808
|
-
function
|
|
809
|
-
if (!
|
|
810
|
-
return
|
|
910
|
+
function m() {
|
|
911
|
+
if (!L) throw new Error("Bravophone: chame Bravophone.init() antes.");
|
|
912
|
+
return L;
|
|
811
913
|
}
|
|
812
|
-
const
|
|
914
|
+
const re = {
|
|
813
915
|
/**
|
|
814
916
|
* Monta o webphone na página.
|
|
815
917
|
* @param {object} opts
|
|
@@ -817,102 +919,117 @@ const le = {
|
|
|
817
919
|
* @param {string} [opts.token] Token de sessão do usuário (SSO do integrador).
|
|
818
920
|
* @param {'bottom-right'|'bottom-left'|'top-right'|'top-left'} [opts.position]
|
|
819
921
|
* @param {boolean} [opts.open] Abrir já visível (padrão: false, só o launcher).
|
|
820
|
-
* @param {boolean} [opts.launcher] Exibir
|
|
922
|
+
* @param {boolean} [opts.launcher] Exibir a aba de abertura (padrão: true).
|
|
923
|
+
* @param {'hosted'|'srcdoc'} [opts.mode]
|
|
924
|
+
* 'hosted' (padrão): o iframe navega para `hostUrl`. Uma origem fixa para
|
|
925
|
+
* o CORS dos backends, mas é um iframe de terceiro.
|
|
926
|
+
* 'srcdoc': o iframe roda na origem do próprio site e busca o webphone no
|
|
927
|
+
* CDN. Some o iframe de terceiro — em troca, a origem do integrador
|
|
928
|
+
* precisa estar na allowlist de CORS dos backends.
|
|
821
929
|
*/
|
|
822
930
|
init(e = {}) {
|
|
823
|
-
if (
|
|
931
|
+
if (L) return L;
|
|
824
932
|
if (typeof window == "undefined" || !document.body)
|
|
825
933
|
throw new Error("Bravophone: init() precisa rodar no browser, após o <body> existir.");
|
|
826
|
-
return location.protocol !== "https:" && location.hostname !== "localhost" && console.warn("[Bravophone] Contexto inseguro: o microfone exige HTTPS ou localhost."),
|
|
934
|
+
return location.protocol !== "https:" && location.hostname !== "localhost" && console.warn("[Bravophone] Contexto inseguro: o microfone exige HTTPS ou localhost."), L = Ce({
|
|
935
|
+
hostUrl: Be,
|
|
936
|
+
version: re.version,
|
|
937
|
+
...e,
|
|
938
|
+
emit: De
|
|
939
|
+
}), L;
|
|
827
940
|
},
|
|
828
941
|
// ---- Controle da janela ----
|
|
829
942
|
show() {
|
|
830
|
-
|
|
943
|
+
m().show();
|
|
831
944
|
},
|
|
832
945
|
hide() {
|
|
833
|
-
|
|
946
|
+
m().hide();
|
|
834
947
|
},
|
|
835
948
|
toggle() {
|
|
836
|
-
|
|
949
|
+
m().toggle();
|
|
950
|
+
},
|
|
951
|
+
/** Abre a janela; se já estiver aberta, traz para a vista e destaca. */
|
|
952
|
+
reveal() {
|
|
953
|
+
m().reveal();
|
|
837
954
|
},
|
|
838
955
|
minimize(e) {
|
|
839
|
-
|
|
956
|
+
m().minimize(e);
|
|
840
957
|
},
|
|
841
958
|
move(e, a) {
|
|
842
|
-
|
|
959
|
+
m().move(e, a);
|
|
843
960
|
},
|
|
844
961
|
resize(e, a) {
|
|
845
|
-
|
|
962
|
+
m().resize(e, a);
|
|
846
963
|
},
|
|
847
964
|
/** 'left' | 'right' | 'left-half' | 'right-half' | 'max' | 'float' */
|
|
848
965
|
dock(e) {
|
|
849
|
-
|
|
966
|
+
m().dock(e);
|
|
850
967
|
},
|
|
851
968
|
/** Move a aba de abertura para o outro lado da viewport. */
|
|
852
969
|
setLauncherSide(e) {
|
|
853
|
-
|
|
970
|
+
m().setLauncherSide(e);
|
|
854
971
|
},
|
|
855
972
|
/** 'phone-waves' | 'waveform' | 'headset' | 'chat-phone' */
|
|
856
973
|
setLauncherIcon(e) {
|
|
857
|
-
|
|
974
|
+
m().setLauncherIcon(e);
|
|
858
975
|
},
|
|
859
976
|
get isOpen() {
|
|
860
|
-
return
|
|
977
|
+
return L ? L.isOpen : !1;
|
|
861
978
|
},
|
|
862
979
|
get geometry() {
|
|
863
|
-
return
|
|
980
|
+
return L ? L.geometry : null;
|
|
864
981
|
},
|
|
865
982
|
// ---- Telefonia ----
|
|
866
983
|
/** Disca um número. Aceita formato livre; a normalização é a mesma da extensão. */
|
|
867
984
|
call(e, a) {
|
|
868
|
-
return
|
|
985
|
+
return m().bridge.call("call", { number: e, meta: a });
|
|
869
986
|
},
|
|
870
987
|
hangup() {
|
|
871
|
-
return
|
|
988
|
+
return m().bridge.call("hangup");
|
|
872
989
|
},
|
|
873
990
|
answer() {
|
|
874
|
-
return
|
|
991
|
+
return m().bridge.call("answer");
|
|
875
992
|
},
|
|
876
993
|
/** Alterna o mudo — o bundle só expõe toggle, não aceita estado alvo. */
|
|
877
994
|
mute() {
|
|
878
|
-
return
|
|
995
|
+
return m().bridge.call("mute");
|
|
879
996
|
},
|
|
880
997
|
/** Alterna a espera. Também toggle. */
|
|
881
998
|
hold() {
|
|
882
|
-
return
|
|
999
|
+
return m().bridge.call("hold");
|
|
883
1000
|
},
|
|
884
1001
|
sendDTMF(e) {
|
|
885
|
-
return
|
|
1002
|
+
return m().bridge.call("dtmf", { tone: e });
|
|
886
1003
|
},
|
|
887
1004
|
transfer(e) {
|
|
888
|
-
return
|
|
1005
|
+
return m().bridge.call("transfer", { to: e });
|
|
889
1006
|
},
|
|
890
1007
|
getStatus() {
|
|
891
|
-
return
|
|
1008
|
+
return m().bridge.call("status");
|
|
892
1009
|
},
|
|
893
1010
|
setAuth(e) {
|
|
894
|
-
return
|
|
1011
|
+
return m().bridge.call("auth", { token: e });
|
|
895
1012
|
},
|
|
896
1013
|
logout() {
|
|
897
|
-
return
|
|
1014
|
+
return m().bridge.call("logout");
|
|
898
1015
|
},
|
|
899
1016
|
// ---- Eventos ----
|
|
900
1017
|
/** Eventos: ready, state, call:dialing, call:incoming, call:answered,
|
|
901
1018
|
* call:ended, call:failed, resize, open, close, error. */
|
|
902
1019
|
on(e, a) {
|
|
903
|
-
return
|
|
1020
|
+
return B.has(e) || B.set(e, /* @__PURE__ */ new Set()), B.get(e).add(a), () => re.off(e, a);
|
|
904
1021
|
},
|
|
905
1022
|
off(e, a) {
|
|
906
|
-
var
|
|
907
|
-
(
|
|
1023
|
+
var n;
|
|
1024
|
+
(n = B.get(e)) == null || n.delete(a);
|
|
908
1025
|
},
|
|
909
1026
|
destroy() {
|
|
910
|
-
|
|
1027
|
+
L == null || L.destroy(), L = null, B.clear();
|
|
911
1028
|
},
|
|
912
1029
|
// Substituída em build time pelo valor do package.json (ver vite.config.js).
|
|
913
|
-
version: "0.1
|
|
1030
|
+
version: "0.2.1"
|
|
914
1031
|
};
|
|
915
|
-
typeof window != "undefined" && (window.Bravophone =
|
|
1032
|
+
typeof window != "undefined" && (window.Bravophone = re);
|
|
916
1033
|
export {
|
|
917
|
-
|
|
1034
|
+
re as default
|
|
918
1035
|
};
|