callix-dialer-widget 2.6.0 → 2.8.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/WIDGET-README.md +38 -17
- package/dist-widget/callix-dialer.css +1 -1
- package/dist-widget/callix-dialer.es.js +799 -109
- package/dist-widget/callix-dialer.es.js.map +1 -1
- package/dist-widget/callix-dialer.umd.js +1 -1
- package/dist-widget/callix-dialer.umd.js.map +1 -1
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
|
|
|
6
6
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
7
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
8
8
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
9
|
-
import React, { createContext, useMemo,
|
|
9
|
+
import React, { createContext, useMemo, useRef, useEffect, useSyncExternalStore, useCallback, useContext, useState, forwardRef, useLayoutEffect, useId, useImperativeHandle, StrictMode } from "react";
|
|
10
10
|
import require$$0$2, { createPortal } from "react-dom";
|
|
11
11
|
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
12
12
|
function getAugmentedNamespace(n) {
|
|
@@ -43725,6 +43725,13 @@ function requireClientSdkReact() {
|
|
|
43725
43725
|
return clientSdkReact;
|
|
43726
43726
|
}
|
|
43727
43727
|
var clientSdkReactExports = requireClientSdkReact();
|
|
43728
|
+
class EngineAccessError extends Error {
|
|
43729
|
+
constructor(code, message) {
|
|
43730
|
+
super(message);
|
|
43731
|
+
this.code = code;
|
|
43732
|
+
this.name = "EngineAccessError";
|
|
43733
|
+
}
|
|
43734
|
+
}
|
|
43728
43735
|
class EngineSignal {
|
|
43729
43736
|
constructor(value) {
|
|
43730
43737
|
this.value = value;
|
|
@@ -43791,7 +43798,8 @@ class EngineClient {
|
|
|
43791
43798
|
outputMuted: false,
|
|
43792
43799
|
outputVolume: 100,
|
|
43793
43800
|
transcript: INITIAL_TRANSCRIPT,
|
|
43794
|
-
sessionLost: null
|
|
43801
|
+
sessionLost: null,
|
|
43802
|
+
rejected: null
|
|
43795
43803
|
};
|
|
43796
43804
|
}
|
|
43797
43805
|
// ------------------------------------------------------------------ store
|
|
@@ -43824,7 +43832,16 @@ class EngineClient {
|
|
|
43824
43832
|
if (this.ws !== ws) return;
|
|
43825
43833
|
this.reconnectDelay = RECONNECT_MIN_MS;
|
|
43826
43834
|
this.setState({ wsState: "open" });
|
|
43827
|
-
const
|
|
43835
|
+
const sessionToken = !this.session && this.options.sessionToken ? this.options.sessionToken() : null;
|
|
43836
|
+
const hello = {
|
|
43837
|
+
type: "hello",
|
|
43838
|
+
role: "tab",
|
|
43839
|
+
agentId: this.agentId,
|
|
43840
|
+
...this.options.token ? { token: this.options.token } : {},
|
|
43841
|
+
...sessionToken ? { sessionToken } : {},
|
|
43842
|
+
label: this.options.label ?? "Discador",
|
|
43843
|
+
...this.session ? { session: this.session } : {}
|
|
43844
|
+
};
|
|
43828
43845
|
this.send(hello);
|
|
43829
43846
|
this.log("conectado ao host do motor");
|
|
43830
43847
|
};
|
|
@@ -43871,18 +43888,30 @@ class EngineClient {
|
|
|
43871
43888
|
for (const waiter of this.viewWaiters.splice(0)) clearTimeout(waiter.timer);
|
|
43872
43889
|
this.setState({ wsState: "closed", tabId: null, engaged: false });
|
|
43873
43890
|
}
|
|
43874
|
-
/**
|
|
43875
|
-
|
|
43876
|
-
|
|
43891
|
+
/**
|
|
43892
|
+
* A view atual, ou a próxima que o host mandar (welcome/view). Com `accept`, espera uma
|
|
43893
|
+
* view que passe no filtro (ex.: motor subindo depois de entregar a sessão). Rejeita com
|
|
43894
|
+
* `EngineAccessError` se o host recusou esta aba (`rejected`).
|
|
43895
|
+
*/
|
|
43896
|
+
waitForView(timeoutMs = 15e3, accept, options) {
|
|
43897
|
+
const rejected = this.state.rejected;
|
|
43898
|
+
if (rejected) return Promise.reject(new EngineAccessError(rejected.code, rejected.message));
|
|
43899
|
+
if (!(options == null ? void 0 : options.fresh) && this.state.view && this.state.tabId && (!accept || accept(this.state.view))) return Promise.resolve(this.state.view);
|
|
43877
43900
|
return new Promise((resolve, reject) => {
|
|
43878
43901
|
const timer = setTimeout(() => {
|
|
43879
43902
|
const index = this.viewWaiters.findIndex((w) => w.timer === timer);
|
|
43880
43903
|
if (index >= 0) this.viewWaiters.splice(index, 1);
|
|
43881
43904
|
reject(new Error("o motor não respondeu"));
|
|
43882
43905
|
}, timeoutMs);
|
|
43883
|
-
this.viewWaiters.push({ resolve, timer });
|
|
43906
|
+
this.viewWaiters.push({ resolve, reject, accept, timer });
|
|
43884
43907
|
});
|
|
43885
43908
|
}
|
|
43909
|
+
rejectWaiters(error2) {
|
|
43910
|
+
for (const waiter of this.viewWaiters.splice(0)) {
|
|
43911
|
+
clearTimeout(waiter.timer);
|
|
43912
|
+
waiter.reject(error2);
|
|
43913
|
+
}
|
|
43914
|
+
}
|
|
43886
43915
|
send(message) {
|
|
43887
43916
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) this.ws.send(JSON.stringify(message));
|
|
43888
43917
|
}
|
|
@@ -43890,7 +43919,7 @@ class EngineClient {
|
|
|
43890
43919
|
switch (message.type) {
|
|
43891
43920
|
case "welcome": {
|
|
43892
43921
|
if (Array.isArray(message.iceServers) && message.iceServers.length > 0) this.iceServers = message.iceServers;
|
|
43893
|
-
this.setState({ tabId: message.tabId });
|
|
43922
|
+
this.setState({ tabId: message.tabId, rejected: null });
|
|
43894
43923
|
this.applyView(message.view);
|
|
43895
43924
|
this.log(`sou a aba ${message.tabId}`);
|
|
43896
43925
|
if (this.options.autoEngage !== false && message.view.engagedTabId !== message.tabId) this.engage();
|
|
@@ -43908,6 +43937,19 @@ class EngineClient {
|
|
|
43908
43937
|
void this.onSignal(message.payload);
|
|
43909
43938
|
break;
|
|
43910
43939
|
case "error":
|
|
43940
|
+
if (message.code === "unauthorized") {
|
|
43941
|
+
this.setState({ lastError: message.message, rejected: { code: message.code, message: message.message } });
|
|
43942
|
+
this.session = null;
|
|
43943
|
+
this.reconnectDelay = RECONNECT_MAX_MS;
|
|
43944
|
+
this.log(`acesso recusado pelo host: ${message.message}`);
|
|
43945
|
+
this.rejectWaiters(new EngineAccessError(message.code, message.message));
|
|
43946
|
+
break;
|
|
43947
|
+
}
|
|
43948
|
+
if (message.code === "session-changed") {
|
|
43949
|
+
this.session = null;
|
|
43950
|
+
this.log("a sessão deste agente foi trocada por um login novo; reconectando com a credencial atual");
|
|
43951
|
+
break;
|
|
43952
|
+
}
|
|
43911
43953
|
this.setState({ lastError: message.message });
|
|
43912
43954
|
this.log(`erro do host: ${message.message}`);
|
|
43913
43955
|
break;
|
|
@@ -43945,6 +43987,10 @@ class EngineClient {
|
|
|
43945
43987
|
if (call && typeof call.muted === "boolean" && call.muted !== this.state.inputMuted && call.state !== "ended") patch.inputMuted = call.muted;
|
|
43946
43988
|
this.setState(patch);
|
|
43947
43989
|
for (const waiter of this.viewWaiters.splice(0)) {
|
|
43990
|
+
if (waiter.accept && !waiter.accept(view)) {
|
|
43991
|
+
this.viewWaiters.push(waiter);
|
|
43992
|
+
continue;
|
|
43993
|
+
}
|
|
43948
43994
|
clearTimeout(waiter.timer);
|
|
43949
43995
|
waiter.resolve(view);
|
|
43950
43996
|
}
|
|
@@ -43957,10 +44003,24 @@ class EngineClient {
|
|
|
43957
44003
|
};
|
|
43958
44004
|
}
|
|
43959
44005
|
// ------------------------------------------------------------------ sessão e comandos
|
|
43960
|
-
/**
|
|
44006
|
+
/**
|
|
44007
|
+
* Modo sdk: o widget fez login no back-end e entrega a sessão ao host. Com a conexão
|
|
44008
|
+
* aberta manda `session`; recusada ou caída, reconecta agora apresentando a sessão no hello
|
|
44009
|
+
* (é assim que um login novo substitui a sessão de outro navegador).
|
|
44010
|
+
*/
|
|
43961
44011
|
setSession(session) {
|
|
43962
44012
|
this.session = session;
|
|
43963
|
-
this.
|
|
44013
|
+
this.setState({ rejected: null, sessionLost: null });
|
|
44014
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
44015
|
+
this.send({ type: "session", session });
|
|
44016
|
+
return;
|
|
44017
|
+
}
|
|
44018
|
+
if (this.reconnectTimer) {
|
|
44019
|
+
clearTimeout(this.reconnectTimer);
|
|
44020
|
+
this.reconnectTimer = null;
|
|
44021
|
+
}
|
|
44022
|
+
this.reconnectDelay = RECONNECT_MIN_MS;
|
|
44023
|
+
this.connect();
|
|
43964
44024
|
}
|
|
43965
44025
|
engage() {
|
|
43966
44026
|
this.send({ type: "engage" });
|
|
@@ -52376,6 +52436,8 @@ function FloatingDialer({
|
|
|
52376
52436
|
sessionStatus = null,
|
|
52377
52437
|
loginConfirmation = null,
|
|
52378
52438
|
onCancelLoginConfirmation,
|
|
52439
|
+
onTakeOverSession,
|
|
52440
|
+
onLogoutAllTabs,
|
|
52379
52441
|
variant = "default",
|
|
52380
52442
|
portalTarget = null
|
|
52381
52443
|
}) {
|
|
@@ -52728,7 +52790,9 @@ function FloatingDialer({
|
|
|
52728
52790
|
error: sessionError,
|
|
52729
52791
|
statusMessage: sessionStatus,
|
|
52730
52792
|
confirmation: loginConfirmation,
|
|
52731
|
-
onCancelConfirmation: onCancelLoginConfirmation
|
|
52793
|
+
onCancelConfirmation: onCancelLoginConfirmation,
|
|
52794
|
+
onTakeOver: onTakeOverSession,
|
|
52795
|
+
onLogoutAll: onLogoutAllTabs
|
|
52732
52796
|
}
|
|
52733
52797
|
);
|
|
52734
52798
|
if (isMiniMode) {
|
|
@@ -52864,7 +52928,7 @@ function FloatingDialer({
|
|
|
52864
52928
|
}
|
|
52865
52929
|
);
|
|
52866
52930
|
}
|
|
52867
|
-
function LoginForm({ defaultValue, onSubmit, isLoading, error: error2, statusMessage, confirmation, onCancelConfirmation }) {
|
|
52931
|
+
function LoginForm({ defaultValue, onSubmit, isLoading, error: error2, statusMessage, confirmation, onCancelConfirmation, onTakeOver, onLogoutAll }) {
|
|
52868
52932
|
const [value, setValue] = useState(defaultValue);
|
|
52869
52933
|
const [touched, setTouched] = useState(false);
|
|
52870
52934
|
useEffect(() => {
|
|
@@ -52895,8 +52959,41 @@ function LoginForm({ defaultValue, onSubmit, isLoading, error: error2, statusMes
|
|
|
52895
52959
|
}
|
|
52896
52960
|
);
|
|
52897
52961
|
}
|
|
52962
|
+
if (confirmation == null ? void 0 : confirmation.elsewhere) {
|
|
52963
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: tw`space-y-4`, "data-login-state": "elsewhere", children: [
|
|
52964
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: tw`space-y-2 text-center`, children: [
|
|
52965
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: tw`text-[11px] font-semibold uppercase tracking-wide text-slate-500`, children: "Discador ativo em outra aba" }),
|
|
52966
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: tw`inline-flex items-center gap-2 rounded-full border border-slate-200 bg-slate-50 px-3 py-1 text-sm font-semibold text-slate-800`, children: [
|
|
52967
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(FiUser, { className: tw`text-primary` }),
|
|
52968
|
+
confirmation.username
|
|
52969
|
+
] })
|
|
52970
|
+
] }),
|
|
52971
|
+
error2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: tw`text-center text-xs text-red-500`, children: error2 }),
|
|
52972
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
52973
|
+
"button",
|
|
52974
|
+
{
|
|
52975
|
+
type: "button",
|
|
52976
|
+
id: "takeOverBtn",
|
|
52977
|
+
onClick: () => onTakeOver == null ? void 0 : onTakeOver(),
|
|
52978
|
+
className: tw`flex w-full items-center justify-center gap-2 rounded-xl bg-primary px-4 py-2 text-white shadow-lg transition hover:bg-primaryDark`,
|
|
52979
|
+
children: "Usar o discador nesta aba"
|
|
52980
|
+
}
|
|
52981
|
+
),
|
|
52982
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
52983
|
+
"button",
|
|
52984
|
+
{
|
|
52985
|
+
type: "button",
|
|
52986
|
+
id: "logoutAllBtn",
|
|
52987
|
+
onClick: () => onLogoutAll == null ? void 0 : onLogoutAll(),
|
|
52988
|
+
className: tw`w-full text-center text-xs font-semibold text-red-500 transition hover:text-red-600`,
|
|
52989
|
+
children: "Sair em todas as abas"
|
|
52990
|
+
}
|
|
52991
|
+
),
|
|
52992
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: tw`text-center text-[11px] text-slate-400`, children: "O Callix aceita uma conexão por usuário: você já está conectado em outra aba deste navegador e pode continuar por lá." })
|
|
52993
|
+
] });
|
|
52994
|
+
}
|
|
52898
52995
|
if (confirmation) {
|
|
52899
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: tw`space-y-4`, children: [
|
|
52996
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: tw`space-y-4`, "data-login-state": "choose", children: [
|
|
52900
52997
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: tw`space-y-2 text-center`, children: [
|
|
52901
52998
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: tw`text-[11px] font-semibold uppercase tracking-wide text-slate-500`, children: "Entrar como" }),
|
|
52902
52999
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: tw`inline-flex items-center gap-2 rounded-full border border-slate-200 bg-slate-50 px-3 py-1 text-sm font-semibold text-slate-800`, children: [
|
|
@@ -52905,10 +53002,12 @@ function LoginForm({ defaultValue, onSubmit, isLoading, error: error2, statusMes
|
|
|
52905
53002
|
] })
|
|
52906
53003
|
] }),
|
|
52907
53004
|
error2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: tw`text-center text-xs text-red-500`, children: error2 }),
|
|
53005
|
+
!error2 && confirmation.note && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: tw`text-center text-xs text-slate-500`, children: confirmation.note }),
|
|
52908
53006
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
52909
53007
|
"button",
|
|
52910
53008
|
{
|
|
52911
53009
|
type: "button",
|
|
53010
|
+
id: "loginConfirmBtn",
|
|
52912
53011
|
onClick: () => void onSubmit(confirmation.username),
|
|
52913
53012
|
className: tw`flex w-full items-center justify-center gap-2 rounded-xl bg-primary px-4 py-2 text-white shadow-lg transition hover:bg-primaryDark`,
|
|
52914
53013
|
children: "Entrar"
|
|
@@ -52923,7 +53022,7 @@ function LoginForm({ defaultValue, onSubmit, isLoading, error: error2, statusMes
|
|
|
52923
53022
|
children: "Usar outro usuário"
|
|
52924
53023
|
}
|
|
52925
53024
|
),
|
|
52926
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: tw`text-center text-[11px] text-slate-400`, children: "
|
|
53025
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: tw`text-center text-[11px] text-slate-400`, children: "Ao entrar, todas as abas abertas passam a usar o discador. Vai usar o Callix web? Então não entre aqui: nada é conectado sem a sua confirmação." })
|
|
52927
53026
|
] });
|
|
52928
53027
|
}
|
|
52929
53028
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("form", { className: tw`space-y-4`, onSubmit: handleSubmit, children: [
|
|
@@ -58427,6 +58526,8 @@ function MobileDialerLogin({
|
|
|
58427
58526
|
sessionStatus,
|
|
58428
58527
|
loginConfirmation,
|
|
58429
58528
|
onCancelLoginConfirmation,
|
|
58529
|
+
onTakeOverSession,
|
|
58530
|
+
onLogoutAllTabs,
|
|
58430
58531
|
density
|
|
58431
58532
|
}) {
|
|
58432
58533
|
const [loginInput, setLoginInput] = useState(username ?? "");
|
|
@@ -58463,19 +58564,33 @@ function MobileDialerLogin({
|
|
|
58463
58564
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "login-spinner", "aria-hidden": "true" }),
|
|
58464
58565
|
loadingUser && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "login-loading-user", children: loadingUser }),
|
|
58465
58566
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "login-status", children: sessionStatus || "Conectando..." })
|
|
58466
|
-
] }) : showConfirmation && loginConfirmation ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "login-confirm", children: [
|
|
58567
|
+
] }) : showConfirmation && loginConfirmation ? loginConfirmation.elsewhere ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "login-confirm", "data-login-state": "elsewhere", children: [
|
|
58568
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "login-confirm-label", children: "Discador ativo em outra aba" }),
|
|
58569
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "login-user-chip", children: [
|
|
58570
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("i", { className: "fas fa-user-check", "aria-hidden": "true" }),
|
|
58571
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: loginConfirmation.username })
|
|
58572
|
+
] }),
|
|
58573
|
+
sessionError && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "input-error", children: sessionError }),
|
|
58574
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", className: "login-confirm-btn login-confirm-btn-blue", id: "takeOverBtn", onClick: () => onTakeOverSession == null ? void 0 : onTakeOverSession(), children: [
|
|
58575
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("i", { className: "fas fa-arrow-down", "aria-hidden": "true" }),
|
|
58576
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Usar o discador nesta aba" })
|
|
58577
|
+
] }),
|
|
58578
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "login-secondary-btn login-secondary-danger", id: "logoutAllBtn", onClick: () => onLogoutAllTabs == null ? void 0 : onLogoutAllTabs(), children: "Sair em todas as abas" }),
|
|
58579
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "login-hint", children: "O Callix aceita uma conexão por usuário: você já está conectado em outra aba deste navegador e pode continuar por lá." })
|
|
58580
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "login-confirm", "data-login-state": "choose", children: [
|
|
58467
58581
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "login-confirm-label", children: "Entrar como" }),
|
|
58468
58582
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "login-user-chip", children: [
|
|
58469
58583
|
/* @__PURE__ */ jsxRuntimeExports.jsx("i", { className: "fas fa-user", "aria-hidden": "true" }),
|
|
58470
58584
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: loginConfirmation.username })
|
|
58471
58585
|
] }),
|
|
58472
58586
|
sessionError && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "input-error", children: sessionError }),
|
|
58473
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
58587
|
+
!sessionError && loginConfirmation.note && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "login-note", children: loginConfirmation.note }),
|
|
58588
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", className: "login-confirm-btn", id: "loginConfirmBtn", onClick: () => void submitLogin(loginConfirmation.username), children: [
|
|
58474
58589
|
/* @__PURE__ */ jsxRuntimeExports.jsx("i", { className: "fas fa-sign-in-alt", "aria-hidden": "true" }),
|
|
58475
58590
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Entrar" })
|
|
58476
58591
|
] }),
|
|
58477
58592
|
!loginConfirmation.locked && onCancelLoginConfirmation && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "login-secondary-btn", onClick: onCancelLoginConfirmation, children: "Usar outro usuário" }),
|
|
58478
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "login-hint", children: "
|
|
58593
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "login-hint", children: "Ao entrar, todas as abas abertas passam a usar o discador. Vai usar o Callix web? Então não entre aqui: nada é conectado sem a sua confirmação." })
|
|
58479
58594
|
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
58480
58595
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "phone-number-display", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
58481
58596
|
"input",
|
|
@@ -58568,6 +58683,7 @@ Gostaríamos de fazer um *diagnóstico gratuito* para te apresentar os valores r
|
|
|
58568
58683
|
}
|
|
58569
58684
|
function AuthenticatedMobileDialer({
|
|
58570
58685
|
username,
|
|
58686
|
+
onLogout,
|
|
58571
58687
|
showClientInfoModal = false,
|
|
58572
58688
|
density
|
|
58573
58689
|
}) {
|
|
@@ -59334,13 +59450,30 @@ function AuthenticatedMobileDialer({
|
|
|
59334
59450
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "pause-timer", children: pauseDurationLabel })
|
|
59335
59451
|
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "status-text", children: statusBadgeText })
|
|
59336
59452
|
] }) }),
|
|
59337
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
59338
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
59339
|
-
|
|
59340
|
-
|
|
59341
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
59342
|
-
|
|
59343
|
-
|
|
59453
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "status-actions", children: [
|
|
59454
|
+
isOnBreak ? /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "resume-btn", id: "resumeBtn", onClick: handleGoOffBreak, children: [
|
|
59455
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("i", { className: "fas fa-play" }),
|
|
59456
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Voltar" })
|
|
59457
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "pause-btn", id: "pauseBtn", onClick: () => setIsPauseModalOpen(true), children: [
|
|
59458
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("i", { className: "fas fa-pause" }),
|
|
59459
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Pausa" })
|
|
59460
|
+
] }),
|
|
59461
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
59462
|
+
"button",
|
|
59463
|
+
{
|
|
59464
|
+
type: "button",
|
|
59465
|
+
className: "logout-btn",
|
|
59466
|
+
id: "logoutBtn",
|
|
59467
|
+
title: "Sair do discador (todas as abas)",
|
|
59468
|
+
"aria-label": "Sair do discador",
|
|
59469
|
+
onClick: () => {
|
|
59470
|
+
if (typeof window !== "undefined" && !window.confirm("Sair do discador em todas as abas?")) return;
|
|
59471
|
+
onLogout();
|
|
59472
|
+
},
|
|
59473
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("i", { className: "fas fa-right-from-bracket" })
|
|
59474
|
+
}
|
|
59475
|
+
)
|
|
59476
|
+
] })
|
|
59344
59477
|
] }),
|
|
59345
59478
|
/* @__PURE__ */ jsxRuntimeExports.jsx(DialerNoticeBanner, { notice: dialerNotice, onDismiss: dismissDialerNotice, onRecheck: () => void recheckDevices(), onHeightChange: setNoticeHeight }),
|
|
59346
59479
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "phone-number-display", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -60176,6 +60309,206 @@ function AuthenticatedMiniDialer({
|
|
|
60176
60309
|
)
|
|
60177
60310
|
] });
|
|
60178
60311
|
}
|
|
60312
|
+
const PROBE_TIMEOUT_MS = 600;
|
|
60313
|
+
const TAKEOVER_GRACE_MS = 3e3;
|
|
60314
|
+
const TAKEOVER_JITTER_MS = 600;
|
|
60315
|
+
const LEADER_HEARTBEAT_MS = 3e3;
|
|
60316
|
+
const LEADER_STALE_MS = 9e3;
|
|
60317
|
+
function channelName(username) {
|
|
60318
|
+
return `callix-dialer:${username.trim().toLowerCase()}`;
|
|
60319
|
+
}
|
|
60320
|
+
function leaderKey(username) {
|
|
60321
|
+
return `callix_dialer_${username}_leader`;
|
|
60322
|
+
}
|
|
60323
|
+
const TAB_ROLE_KEY = "callix_dialer_tab_role";
|
|
60324
|
+
const BUS_FALLBACK_SUFFIX = "_bus";
|
|
60325
|
+
function newTabId() {
|
|
60326
|
+
const cryptoApi = typeof globalThis.crypto !== "undefined" ? globalThis.crypto : void 0;
|
|
60327
|
+
if (cryptoApi && "randomUUID" in cryptoApi) return cryptoApi.randomUUID().slice(0, 8);
|
|
60328
|
+
return Math.random().toString(36).slice(2, 10);
|
|
60329
|
+
}
|
|
60330
|
+
function defaultChannelFactory(name) {
|
|
60331
|
+
if (typeof BroadcastChannel === "undefined") return null;
|
|
60332
|
+
try {
|
|
60333
|
+
return new BroadcastChannel(name);
|
|
60334
|
+
} catch {
|
|
60335
|
+
return null;
|
|
60336
|
+
}
|
|
60337
|
+
}
|
|
60338
|
+
function defaultStorage() {
|
|
60339
|
+
try {
|
|
60340
|
+
return typeof localStorage !== "undefined" ? localStorage : null;
|
|
60341
|
+
} catch {
|
|
60342
|
+
return null;
|
|
60343
|
+
}
|
|
60344
|
+
}
|
|
60345
|
+
class DialerTabBus {
|
|
60346
|
+
constructor(options) {
|
|
60347
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
60348
|
+
this.storageListener = null;
|
|
60349
|
+
this.closed = false;
|
|
60350
|
+
this.username = options.username;
|
|
60351
|
+
this.tabId = options.tabId ?? newTabId();
|
|
60352
|
+
this.status = options.status;
|
|
60353
|
+
this.storage = options.storage === void 0 ? defaultStorage() : options.storage;
|
|
60354
|
+
const factory = options.channelFactory ?? defaultChannelFactory;
|
|
60355
|
+
this.channel = factory(channelName(this.username));
|
|
60356
|
+
if (this.channel) {
|
|
60357
|
+
this.channel.onmessage = (event) => this.receive(event.data);
|
|
60358
|
+
} else if (typeof window !== "undefined" && this.storage) {
|
|
60359
|
+
const key = this.fallbackKey();
|
|
60360
|
+
this.storageListener = (event) => {
|
|
60361
|
+
if (event.key !== key || !event.newValue) return;
|
|
60362
|
+
try {
|
|
60363
|
+
const parsed = JSON.parse(event.newValue);
|
|
60364
|
+
this.receive(parsed.message);
|
|
60365
|
+
} catch {
|
|
60366
|
+
}
|
|
60367
|
+
};
|
|
60368
|
+
window.addEventListener("storage", this.storageListener);
|
|
60369
|
+
}
|
|
60370
|
+
}
|
|
60371
|
+
fallbackKey() {
|
|
60372
|
+
return `callix_dialer_${this.username}${BUS_FALLBACK_SUFFIX}`;
|
|
60373
|
+
}
|
|
60374
|
+
on(listener) {
|
|
60375
|
+
this.listeners.add(listener);
|
|
60376
|
+
return () => {
|
|
60377
|
+
this.listeners.delete(listener);
|
|
60378
|
+
};
|
|
60379
|
+
}
|
|
60380
|
+
post(message) {
|
|
60381
|
+
if (this.closed) return;
|
|
60382
|
+
const full = { ...message, from: this.tabId };
|
|
60383
|
+
if (this.channel) {
|
|
60384
|
+
try {
|
|
60385
|
+
this.channel.postMessage(full);
|
|
60386
|
+
} catch {
|
|
60387
|
+
}
|
|
60388
|
+
return;
|
|
60389
|
+
}
|
|
60390
|
+
if (this.storage) {
|
|
60391
|
+
try {
|
|
60392
|
+
this.storage.setItem(this.fallbackKey(), JSON.stringify({ nonce: Math.random(), at: Date.now(), message: full }));
|
|
60393
|
+
} catch {
|
|
60394
|
+
}
|
|
60395
|
+
}
|
|
60396
|
+
}
|
|
60397
|
+
receive(data) {
|
|
60398
|
+
if (this.closed || !data || typeof data !== "object") return;
|
|
60399
|
+
const message = data;
|
|
60400
|
+
if (typeof message.type !== "string" || typeof message.from !== "string" || message.from === this.tabId) return;
|
|
60401
|
+
if (message.type === "ping") {
|
|
60402
|
+
const status = this.status();
|
|
60403
|
+
this.post({ type: "pong", role: status.role, authenticated: status.authenticated });
|
|
60404
|
+
}
|
|
60405
|
+
for (const listener of this.listeners) listener(message);
|
|
60406
|
+
}
|
|
60407
|
+
/** pergunta quem está aí; devolve as abas que responderam dentro do prazo */
|
|
60408
|
+
probe(timeoutMs = PROBE_TIMEOUT_MS) {
|
|
60409
|
+
return new Promise((resolve) => {
|
|
60410
|
+
const found = /* @__PURE__ */ new Map();
|
|
60411
|
+
const off = this.on((message) => {
|
|
60412
|
+
if (message.type === "pong") found.set(message.from, { tabId: message.from, role: message.role, authenticated: message.authenticated });
|
|
60413
|
+
});
|
|
60414
|
+
this.post({ type: "ping" });
|
|
60415
|
+
setTimeout(() => {
|
|
60416
|
+
off();
|
|
60417
|
+
resolve([...found.values()]);
|
|
60418
|
+
}, timeoutMs);
|
|
60419
|
+
});
|
|
60420
|
+
}
|
|
60421
|
+
close() {
|
|
60422
|
+
this.closed = true;
|
|
60423
|
+
this.listeners.clear();
|
|
60424
|
+
if (this.channel) {
|
|
60425
|
+
this.channel.onmessage = null;
|
|
60426
|
+
try {
|
|
60427
|
+
this.channel.close();
|
|
60428
|
+
} catch {
|
|
60429
|
+
}
|
|
60430
|
+
}
|
|
60431
|
+
if (this.storageListener && typeof window !== "undefined") {
|
|
60432
|
+
window.removeEventListener("storage", this.storageListener);
|
|
60433
|
+
this.storageListener = null;
|
|
60434
|
+
}
|
|
60435
|
+
}
|
|
60436
|
+
}
|
|
60437
|
+
function findLeader(pongs) {
|
|
60438
|
+
return pongs.find((pong) => pong.role === "leader" && pong.authenticated) ?? null;
|
|
60439
|
+
}
|
|
60440
|
+
function anyDialerTab(pongs) {
|
|
60441
|
+
return pongs.some((pong) => pong.role !== null);
|
|
60442
|
+
}
|
|
60443
|
+
function readLeader(username, storage = defaultStorage(), now = Date.now()) {
|
|
60444
|
+
if (!storage) return null;
|
|
60445
|
+
try {
|
|
60446
|
+
const raw = storage.getItem(leaderKey(username));
|
|
60447
|
+
if (!raw) return null;
|
|
60448
|
+
const parsed = JSON.parse(raw);
|
|
60449
|
+
if (typeof parsed.tabId !== "string" || typeof parsed.at !== "number") return null;
|
|
60450
|
+
if (now - parsed.at > LEADER_STALE_MS) return null;
|
|
60451
|
+
return { tabId: parsed.tabId, at: parsed.at };
|
|
60452
|
+
} catch {
|
|
60453
|
+
return null;
|
|
60454
|
+
}
|
|
60455
|
+
}
|
|
60456
|
+
function claimLeader(username, tabId, storage = defaultStorage(), now = Date.now()) {
|
|
60457
|
+
if (!storage) return true;
|
|
60458
|
+
const current = readLeader(username, storage, now);
|
|
60459
|
+
if (current && current.tabId !== tabId) return false;
|
|
60460
|
+
try {
|
|
60461
|
+
storage.setItem(leaderKey(username), JSON.stringify({ tabId, at: now }));
|
|
60462
|
+
} catch {
|
|
60463
|
+
}
|
|
60464
|
+
return true;
|
|
60465
|
+
}
|
|
60466
|
+
function releaseLeader(username, tabId, storage = defaultStorage()) {
|
|
60467
|
+
if (!storage) return;
|
|
60468
|
+
try {
|
|
60469
|
+
const raw = storage.getItem(leaderKey(username));
|
|
60470
|
+
if (!raw) return;
|
|
60471
|
+
const parsed = JSON.parse(raw);
|
|
60472
|
+
if (parsed.tabId === tabId) storage.removeItem(leaderKey(username));
|
|
60473
|
+
} catch {
|
|
60474
|
+
}
|
|
60475
|
+
}
|
|
60476
|
+
function defaultSessionStorage() {
|
|
60477
|
+
try {
|
|
60478
|
+
return typeof sessionStorage !== "undefined" ? sessionStorage : null;
|
|
60479
|
+
} catch {
|
|
60480
|
+
return null;
|
|
60481
|
+
}
|
|
60482
|
+
}
|
|
60483
|
+
function saveTabRole(username, role, storage = defaultSessionStorage()) {
|
|
60484
|
+
if (!storage) return;
|
|
60485
|
+
try {
|
|
60486
|
+
storage.setItem(TAB_ROLE_KEY, JSON.stringify({ username, role, at: Date.now() }));
|
|
60487
|
+
} catch {
|
|
60488
|
+
}
|
|
60489
|
+
}
|
|
60490
|
+
function readTabRole(username, storage = defaultSessionStorage()) {
|
|
60491
|
+
if (!storage) return null;
|
|
60492
|
+
try {
|
|
60493
|
+
const raw = storage.getItem(TAB_ROLE_KEY);
|
|
60494
|
+
if (!raw) return null;
|
|
60495
|
+
const parsed = JSON.parse(raw);
|
|
60496
|
+
if (parsed.username !== username) return null;
|
|
60497
|
+
return parsed.role === "leader" || parsed.role === "member" ? parsed.role : null;
|
|
60498
|
+
} catch {
|
|
60499
|
+
return null;
|
|
60500
|
+
}
|
|
60501
|
+
}
|
|
60502
|
+
function clearTabRole(storage = defaultSessionStorage()) {
|
|
60503
|
+
if (!storage) return;
|
|
60504
|
+
try {
|
|
60505
|
+
storage.removeItem(TAB_ROLE_KEY);
|
|
60506
|
+
} catch {
|
|
60507
|
+
}
|
|
60508
|
+
}
|
|
60509
|
+
function takeoverDelayMs(random = Math.random()) {
|
|
60510
|
+
return TAKEOVER_GRACE_MS + Math.floor(random * TAKEOVER_JITTER_MS);
|
|
60511
|
+
}
|
|
60179
60512
|
const DEFAULT_CLICK_TO_CALL_INTERVAL_MS = 4e3;
|
|
60180
60513
|
const BUSY_INTERVAL_FACTOR = 3;
|
|
60181
60514
|
const DISPATCH_COOLDOWN_MS = 6e3;
|
|
@@ -60398,7 +60731,7 @@ function ClickToCallAgent({ enabled = true, pollIntervalMs, sessionToken, onTask
|
|
|
60398
60731
|
}, [enabled, pollIntervalMs, sessionToken]);
|
|
60399
60732
|
return null;
|
|
60400
60733
|
}
|
|
60401
|
-
const WIDGET_VERSION = "2.
|
|
60734
|
+
const WIDGET_VERSION = "2.8.0";
|
|
60402
60735
|
let currentSipWebSocket = null;
|
|
60403
60736
|
function sendSipUnregisterIfPossible(ws) {
|
|
60404
60737
|
if (ws.readyState !== WebSocket.OPEN) return;
|
|
@@ -60524,9 +60857,23 @@ function useDialerConfig() {
|
|
|
60524
60857
|
return context;
|
|
60525
60858
|
}
|
|
60526
60859
|
const SdkCleanupManager = forwardRef(
|
|
60527
|
-
function SdkCleanupManager2({ children: children2 }, ref) {
|
|
60860
|
+
function SdkCleanupManager2({ children: children2, onSessionDropped }, ref) {
|
|
60528
60861
|
const operator = useCallOperator();
|
|
60529
60862
|
const controls = useCallOperatorControls();
|
|
60863
|
+
const operatorState = useCallOperatorState();
|
|
60864
|
+
const droppedRef = useRef(onSessionDropped);
|
|
60865
|
+
droppedRef.current = onSessionDropped;
|
|
60866
|
+
useCallOperatorEventListener("userSessionDropped", (data) => {
|
|
60867
|
+
var _a2;
|
|
60868
|
+
const originator = (data == null ? void 0 : data.originator) ?? null;
|
|
60869
|
+
(_a2 = droppedRef.current) == null ? void 0 : _a2.call(droppedRef, originator, describeSessionDrop(originator));
|
|
60870
|
+
});
|
|
60871
|
+
const startupError = (operatorState == null ? void 0 : operatorState.state) === "startupError" ? operatorState.error ?? null : null;
|
|
60872
|
+
useEffect(() => {
|
|
60873
|
+
var _a2;
|
|
60874
|
+
if (startupError !== "userIsAlreadyConnectedOnAnotherDevice") return;
|
|
60875
|
+
(_a2 = droppedRef.current) == null ? void 0 : _a2.call(droppedRef, "anotherDevice", describeStartupError(startupError));
|
|
60876
|
+
}, [startupError]);
|
|
60530
60877
|
useImperativeHandle(ref, () => ({
|
|
60531
60878
|
goOffline: () => {
|
|
60532
60879
|
console.log("[Callix Dialer] 📴 Chamando goOffline() para enviar SIP UNREGISTER...");
|
|
@@ -60547,16 +60894,18 @@ const SdkCleanupManager = forwardRef(
|
|
|
60547
60894
|
}
|
|
60548
60895
|
}
|
|
60549
60896
|
}), [operator, controls]);
|
|
60897
|
+
const controlsRef = useRef(controls);
|
|
60898
|
+
controlsRef.current = controls;
|
|
60550
60899
|
useEffect(() => {
|
|
60551
60900
|
return () => {
|
|
60552
60901
|
console.log("[Callix Dialer] 🔌 SdkCleanupManager desmontando, chamando goOffline()...");
|
|
60553
60902
|
try {
|
|
60554
|
-
|
|
60903
|
+
controlsRef.current.goOffline();
|
|
60555
60904
|
} catch (err) {
|
|
60556
60905
|
console.warn("[Callix Dialer] ⚠️ Erro no cleanup automático:", err);
|
|
60557
60906
|
}
|
|
60558
60907
|
};
|
|
60559
|
-
}, [
|
|
60908
|
+
}, []);
|
|
60560
60909
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: children2 });
|
|
60561
60910
|
}
|
|
60562
60911
|
);
|
|
@@ -60695,6 +61044,13 @@ const getStorageKeys = (username) => ({
|
|
|
60695
61044
|
SKIP_MANUAL_QUALIFICATION: `callix_dialer_${username}_skip_manual_qualification`
|
|
60696
61045
|
});
|
|
60697
61046
|
const LAST_USERNAME_KEY = "callix_dialer_last_username";
|
|
61047
|
+
function readStoredToken(user) {
|
|
61048
|
+
try {
|
|
61049
|
+
return localStorage.getItem(getStorageKeys(user).SESSION_TOKEN);
|
|
61050
|
+
} catch {
|
|
61051
|
+
return null;
|
|
61052
|
+
}
|
|
61053
|
+
}
|
|
60698
61054
|
async function fetchSkipQualification(domain, token) {
|
|
60699
61055
|
var _a2, _b;
|
|
60700
61056
|
try {
|
|
@@ -60724,10 +61080,35 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
60724
61080
|
const [isDisconnecting, setIsDisconnecting] = useState(false);
|
|
60725
61081
|
const presetUsername = options.presetUsername ? options.presetUsername.trim() : null;
|
|
60726
61082
|
const uiVariant = options.uiVariant ?? "default";
|
|
60727
|
-
const autoLogin = options.autoLogin === true;
|
|
60728
61083
|
const portalTarget = useMemo(() => options.portalTarget ?? containerEl ?? null, [options.portalTarget, containerEl]);
|
|
60729
|
-
const
|
|
60730
|
-
|
|
61084
|
+
const tabIdRef = useRef("");
|
|
61085
|
+
if (!tabIdRef.current) tabIdRef.current = newTabId();
|
|
61086
|
+
const [tabRole, setTabRole] = useState(null);
|
|
61087
|
+
const tabRoleRef = useRef(null);
|
|
61088
|
+
tabRoleRef.current = tabRole;
|
|
61089
|
+
const [tabDecided, setTabDecided] = useState(false);
|
|
61090
|
+
const [tabNote, setTabNote] = useState(null);
|
|
61091
|
+
const [engineWaiting, setEngineWaiting] = useState(false);
|
|
61092
|
+
const busRef = useRef(null);
|
|
61093
|
+
const takeoverTimerRef = useRef(null);
|
|
61094
|
+
const isAuthenticatedRef = useRef(false);
|
|
61095
|
+
isAuthenticatedRef.current = isAuthenticated;
|
|
61096
|
+
const isLoadingRef = useRef(false);
|
|
61097
|
+
isLoadingRef.current = isLoading;
|
|
61098
|
+
const logoffPendingRef = useRef(false);
|
|
61099
|
+
const handleLoginRef = useRef(async () => void 0);
|
|
61100
|
+
const handleLogoutRef = useRef(async () => void 0);
|
|
61101
|
+
const cancelTakeover = useCallback(() => {
|
|
61102
|
+
if (takeoverTimerRef.current) {
|
|
61103
|
+
clearTimeout(takeoverTimerRef.current);
|
|
61104
|
+
takeoverTimerRef.current = null;
|
|
61105
|
+
}
|
|
61106
|
+
}, []);
|
|
61107
|
+
useEffect(() => {
|
|
61108
|
+
if (options.autoLogin) {
|
|
61109
|
+
console.info("[Callix Dialer] autoLogin: desde a 2.7.0 o widget não cria sessão sem confirmação; ele entra sozinho só quando já existe uma conexão ativa deste usuário (outra aba ou o motor).");
|
|
61110
|
+
}
|
|
61111
|
+
}, [options.autoLogin]);
|
|
60731
61112
|
const currentSessionRef = useRef({
|
|
60732
61113
|
apiUrl: options.apiUrl || "/api/user-sdk-session",
|
|
60733
61114
|
token: null
|
|
@@ -60749,7 +61130,10 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
60749
61130
|
current == null ? void 0 : current.close();
|
|
60750
61131
|
const client2 = new EngineClient({
|
|
60751
61132
|
url: options.engineUrl ?? "",
|
|
60752
|
-
token: options.engineToken
|
|
61133
|
+
token: options.engineToken || void 0,
|
|
61134
|
+
// credencial da aba: o token da sessão do Callix guardado neste navegador (lido a cada
|
|
61135
|
+
// hello, para a reconexão depois de uma troca de sessão pegar o token novo)
|
|
61136
|
+
sessionToken: () => readStoredToken(user),
|
|
60753
61137
|
agentId: user,
|
|
60754
61138
|
label: "Discador",
|
|
60755
61139
|
log: (message) => console.log("[Callix Dialer/motor]", message)
|
|
@@ -60759,7 +61143,7 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
60759
61143
|
setError(`${notice.title}: ${notice.detail}${notice.action ? ` ${notice.action}` : ""}`);
|
|
60760
61144
|
setIsAuthenticated(false);
|
|
60761
61145
|
setSessionToken(null);
|
|
60762
|
-
|
|
61146
|
+
setTabNote(null);
|
|
60763
61147
|
});
|
|
60764
61148
|
client2.connect();
|
|
60765
61149
|
engineRef.current = client2;
|
|
@@ -60776,9 +61160,19 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
60776
61160
|
[]
|
|
60777
61161
|
);
|
|
60778
61162
|
useEffect(() => {
|
|
61163
|
+
let unloadHandled = false;
|
|
60779
61164
|
const handleBeforeUnload = () => {
|
|
60780
|
-
|
|
61165
|
+
var _a2;
|
|
61166
|
+
if (engineModeRef.current || unloadHandled) return;
|
|
61167
|
+
unloadHandled = true;
|
|
61168
|
+
setTimeout(() => {
|
|
61169
|
+
unloadHandled = false;
|
|
61170
|
+
}, 2e3);
|
|
60781
61171
|
const { apiUrl, token } = currentSessionRef.current;
|
|
61172
|
+
if (tabRoleRef.current === "leader") {
|
|
61173
|
+
(_a2 = busRef.current) == null ? void 0 : _a2.post({ type: "leaving" });
|
|
61174
|
+
if (busRef.current) releaseLeader(busRef.current.username, tabIdRef.current);
|
|
61175
|
+
}
|
|
60782
61176
|
if (token) {
|
|
60783
61177
|
const data = JSON.stringify({ logout: true });
|
|
60784
61178
|
const logoutUrl = `${apiUrl}?logout=true`;
|
|
@@ -60797,8 +61191,10 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
60797
61191
|
}
|
|
60798
61192
|
};
|
|
60799
61193
|
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
61194
|
+
window.addEventListener("pagehide", handleBeforeUnload);
|
|
60800
61195
|
return () => {
|
|
60801
61196
|
window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
61197
|
+
window.removeEventListener("pagehide", handleBeforeUnload);
|
|
60802
61198
|
};
|
|
60803
61199
|
}, []);
|
|
60804
61200
|
useEffect(() => {
|
|
@@ -60836,8 +61232,257 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
60836
61232
|
setUsername(presetUsername);
|
|
60837
61233
|
}
|
|
60838
61234
|
}, [presetUsername, username]);
|
|
61235
|
+
const engineDomain = useCallback(
|
|
61236
|
+
() => options.domain || new URL(options.apiUrl || "/api/user-sdk-session", window.location.href).host,
|
|
61237
|
+
[options.domain, options.apiUrl]
|
|
61238
|
+
);
|
|
61239
|
+
const enterEngine = useCallback(async (user, domain, token) => {
|
|
61240
|
+
if (token) {
|
|
61241
|
+
const skip = await fetchSkipQualification(domain, token);
|
|
61242
|
+
if (skip !== null) {
|
|
61243
|
+
setSkipManualQualification(skip);
|
|
61244
|
+
try {
|
|
61245
|
+
localStorage.setItem(getStorageKeys(user).SKIP_MANUAL_QUALIFICATION, String(skip));
|
|
61246
|
+
} catch {
|
|
61247
|
+
}
|
|
61248
|
+
}
|
|
61249
|
+
}
|
|
61250
|
+
try {
|
|
61251
|
+
localStorage.setItem(LAST_USERNAME_KEY, user);
|
|
61252
|
+
if (token) {
|
|
61253
|
+
const STORAGE_KEYS = getStorageKeys(user);
|
|
61254
|
+
localStorage.setItem(STORAGE_KEYS.SESSION_TOKEN, token);
|
|
61255
|
+
localStorage.setItem(STORAGE_KEYS.DOMAIN, domain);
|
|
61256
|
+
localStorage.setItem(STORAGE_KEYS.TIMESTAMP, Date.now().toString());
|
|
61257
|
+
}
|
|
61258
|
+
} catch {
|
|
61259
|
+
}
|
|
61260
|
+
setSessionToken(token);
|
|
61261
|
+
setCallixDomain(domain);
|
|
61262
|
+
setUsername(user);
|
|
61263
|
+
setIsAuthenticated(true);
|
|
61264
|
+
setError(null);
|
|
61265
|
+
setTabNote(null);
|
|
61266
|
+
setProviderKey(Date.now());
|
|
61267
|
+
}, []);
|
|
61268
|
+
const joinEngine = useCallback(
|
|
61269
|
+
async (user) => {
|
|
61270
|
+
setIsLoading(true);
|
|
61271
|
+
setError(null);
|
|
61272
|
+
setLoginStatus("Entrando na sessão do motor...");
|
|
61273
|
+
try {
|
|
61274
|
+
await enterEngine(user, engineDomain(), readStoredToken(user));
|
|
61275
|
+
console.log("[Callix Dialer] Conectado ao motor como", user);
|
|
61276
|
+
} catch (err) {
|
|
61277
|
+
console.error("[Callix Dialer] Erro ao entrar na sessão do motor:", err);
|
|
61278
|
+
setError(err instanceof Error ? err.message : "Erro ao conectar ao motor");
|
|
61279
|
+
} finally {
|
|
61280
|
+
setIsLoading(false);
|
|
61281
|
+
setLoginStatus(null);
|
|
61282
|
+
}
|
|
61283
|
+
},
|
|
61284
|
+
[enterEngine, engineDomain]
|
|
61285
|
+
);
|
|
61286
|
+
useEffect(() => {
|
|
61287
|
+
if (!engineMode || !username || isRestoringSession) return;
|
|
61288
|
+
const user = username;
|
|
61289
|
+
const client2 = ensureEngine(user);
|
|
61290
|
+
setEngineWaiting(!client2.getState().view);
|
|
61291
|
+
const fallback = setTimeout(() => setEngineWaiting(false), 15e3);
|
|
61292
|
+
let joining = false;
|
|
61293
|
+
let rejectedNote = false;
|
|
61294
|
+
const sync = () => {
|
|
61295
|
+
const { view, sessionLost, rejected } = client2.getState();
|
|
61296
|
+
if (!rejected && rejectedNote) {
|
|
61297
|
+
rejectedNote = false;
|
|
61298
|
+
setTabNote(null);
|
|
61299
|
+
}
|
|
61300
|
+
if (rejected) {
|
|
61301
|
+
rejectedNote = true;
|
|
61302
|
+
setEngineWaiting(false);
|
|
61303
|
+
if (isLoadingRef.current) return;
|
|
61304
|
+
if (isAuthenticatedRef.current) {
|
|
61305
|
+
console.log("[Callix Dialer] o motor recusou esta aba: a sessão do agente foi trocada por um login em outro lugar");
|
|
61306
|
+
setIsAuthenticated(false);
|
|
61307
|
+
setSessionToken(null);
|
|
61308
|
+
setCallixDomain(null);
|
|
61309
|
+
}
|
|
61310
|
+
setTabNote(rejected.message);
|
|
61311
|
+
return;
|
|
61312
|
+
}
|
|
61313
|
+
if (!view) return;
|
|
61314
|
+
setEngineWaiting(false);
|
|
61315
|
+
if (view.engine === "stopped" || view.engine === "crashed") logoffPendingRef.current = false;
|
|
61316
|
+
const hasSession = (view.engine === "running" || view.engine === "starting") && !sessionLost;
|
|
61317
|
+
if (hasSession && !logoffPendingRef.current && !isAuthenticatedRef.current && !isLoadingRef.current && !joining) {
|
|
61318
|
+
joining = true;
|
|
61319
|
+
console.log("[Callix Dialer] o motor já segura a sessão deste agente; entrando por aqui também");
|
|
61320
|
+
void joinEngine(user).finally(() => {
|
|
61321
|
+
joining = false;
|
|
61322
|
+
});
|
|
61323
|
+
} else if (view.engine === "stopped" && isAuthenticatedRef.current && !isLoadingRef.current) {
|
|
61324
|
+
console.log("[Callix Dialer] o motor desligou (Sair em outra aba ou servidor reiniciado); voltando à tela de login");
|
|
61325
|
+
setIsAuthenticated(false);
|
|
61326
|
+
setSessionToken(null);
|
|
61327
|
+
setCallixDomain(null);
|
|
61328
|
+
setTabNote("O discador foi encerrado em outra aba ou o motor foi reiniciado.");
|
|
61329
|
+
}
|
|
61330
|
+
};
|
|
61331
|
+
sync();
|
|
61332
|
+
const off = client2.subscribe(sync);
|
|
61333
|
+
return () => {
|
|
61334
|
+
off();
|
|
61335
|
+
clearTimeout(fallback);
|
|
61336
|
+
};
|
|
61337
|
+
}, [engineMode, username, isRestoringSession, ensureEngine, joinEngine]);
|
|
61338
|
+
const scheduleTakeoverRef = useRef(null);
|
|
61339
|
+
useEffect(() => {
|
|
61340
|
+
if (engineMode || !username) {
|
|
61341
|
+
setTabDecided(true);
|
|
61342
|
+
return;
|
|
61343
|
+
}
|
|
61344
|
+
setTabDecided(false);
|
|
61345
|
+
const user = username;
|
|
61346
|
+
const bus = new DialerTabBus({
|
|
61347
|
+
username: user,
|
|
61348
|
+
tabId: tabIdRef.current,
|
|
61349
|
+
status: () => ({ role: tabRoleRef.current, authenticated: isAuthenticatedRef.current })
|
|
61350
|
+
});
|
|
61351
|
+
busRef.current = bus;
|
|
61352
|
+
const becomeMember = () => {
|
|
61353
|
+
if (isAuthenticatedRef.current || tabRoleRef.current === "leader") return;
|
|
61354
|
+
setTabRole("member");
|
|
61355
|
+
saveTabRole(user, "member");
|
|
61356
|
+
setTabNote(null);
|
|
61357
|
+
setError(null);
|
|
61358
|
+
setTabDecided(true);
|
|
61359
|
+
};
|
|
61360
|
+
const scheduleTakeover = () => {
|
|
61361
|
+
cancelTakeover();
|
|
61362
|
+
takeoverTimerRef.current = setTimeout(() => {
|
|
61363
|
+
takeoverTimerRef.current = null;
|
|
61364
|
+
if (tabRoleRef.current !== "member" || isAuthenticatedRef.current || isLoadingRef.current) return;
|
|
61365
|
+
const current = readLeader(user);
|
|
61366
|
+
if (current && current.tabId !== tabIdRef.current) return;
|
|
61367
|
+
if (!claimLeader(user, tabIdRef.current)) return;
|
|
61368
|
+
bus.post({ type: "claim" });
|
|
61369
|
+
console.log("[Callix Dialer] a aba com o discador fechou; esta aba assume a conexão");
|
|
61370
|
+
void handleLoginRef.current(user);
|
|
61371
|
+
}, takeoverDelayMs());
|
|
61372
|
+
};
|
|
61373
|
+
scheduleTakeoverRef.current = scheduleTakeover;
|
|
61374
|
+
const off = bus.on((message) => {
|
|
61375
|
+
switch (message.type) {
|
|
61376
|
+
case "login":
|
|
61377
|
+
case "claim":
|
|
61378
|
+
cancelTakeover();
|
|
61379
|
+
becomeMember();
|
|
61380
|
+
break;
|
|
61381
|
+
case "leaving":
|
|
61382
|
+
if (tabRoleRef.current === "member" && !isAuthenticatedRef.current) scheduleTakeover();
|
|
61383
|
+
break;
|
|
61384
|
+
case "takeover":
|
|
61385
|
+
if (tabRoleRef.current === "leader") {
|
|
61386
|
+
console.log("[Callix Dialer] outra aba pediu o discador; soltando a conexão");
|
|
61387
|
+
void handleLogoutRef.current({ broadcast: false, keepDecision: true });
|
|
61388
|
+
}
|
|
61389
|
+
break;
|
|
61390
|
+
case "logout":
|
|
61391
|
+
cancelTakeover();
|
|
61392
|
+
void handleLogoutRef.current({ broadcast: false });
|
|
61393
|
+
setTabNote("Você saiu do discador em outra aba.");
|
|
61394
|
+
break;
|
|
61395
|
+
case "dropped": {
|
|
61396
|
+
cancelTakeover();
|
|
61397
|
+
releaseLeader(user, tabIdRef.current);
|
|
61398
|
+
setTabRole(null);
|
|
61399
|
+
clearTabRole();
|
|
61400
|
+
const notice = describeSessionDrop(message.originator);
|
|
61401
|
+
setError(`${notice.title}: ${notice.detail}${notice.action ? ` ${notice.action}` : ""}`);
|
|
61402
|
+
break;
|
|
61403
|
+
}
|
|
61404
|
+
}
|
|
61405
|
+
});
|
|
61406
|
+
return () => {
|
|
61407
|
+
off();
|
|
61408
|
+
bus.close();
|
|
61409
|
+
cancelTakeover();
|
|
61410
|
+
scheduleTakeoverRef.current = null;
|
|
61411
|
+
if (busRef.current === bus) busRef.current = null;
|
|
61412
|
+
setTabDecided(false);
|
|
61413
|
+
};
|
|
61414
|
+
}, [engineMode, username, cancelTakeover]);
|
|
61415
|
+
useEffect(() => {
|
|
61416
|
+
if (engineMode || !username || isAuthenticated || tabDecided || isRestoringSession || isLoading) return;
|
|
61417
|
+
const bus = busRef.current;
|
|
61418
|
+
if (!bus) return;
|
|
61419
|
+
const user = username;
|
|
61420
|
+
const stored = readTabRole(user);
|
|
61421
|
+
if (stored === "leader") {
|
|
61422
|
+
cancelTakeover();
|
|
61423
|
+
setTabDecided(true);
|
|
61424
|
+
if (claimLeader(user, tabIdRef.current)) {
|
|
61425
|
+
bus.post({ type: "claim" });
|
|
61426
|
+
console.log("[Callix Dialer] esta aba segurava o discador antes de recarregar; reconectando");
|
|
61427
|
+
void handleLoginRef.current(user);
|
|
61428
|
+
} else {
|
|
61429
|
+
setTabRole("member");
|
|
61430
|
+
saveTabRole(user, "member");
|
|
61431
|
+
}
|
|
61432
|
+
return;
|
|
61433
|
+
}
|
|
61434
|
+
let cancelled = false;
|
|
61435
|
+
void bus.probe().then((pongs) => {
|
|
61436
|
+
var _a2;
|
|
61437
|
+
if (cancelled) return;
|
|
61438
|
+
setTabDecided(true);
|
|
61439
|
+
const leaderLock = readLeader(user);
|
|
61440
|
+
if (findLeader(pongs) || leaderLock && leaderLock.tabId !== tabIdRef.current || stored === "member" && anyDialerTab(pongs)) {
|
|
61441
|
+
setTabRole("member");
|
|
61442
|
+
saveTabRole(user, "member");
|
|
61443
|
+
} else if (stored === "member") {
|
|
61444
|
+
setTabRole("member");
|
|
61445
|
+
(_a2 = scheduleTakeoverRef.current) == null ? void 0 : _a2.call(scheduleTakeoverRef);
|
|
61446
|
+
} else {
|
|
61447
|
+
setTabRole(null);
|
|
61448
|
+
clearTabRole();
|
|
61449
|
+
}
|
|
61450
|
+
});
|
|
61451
|
+
return () => {
|
|
61452
|
+
cancelled = true;
|
|
61453
|
+
};
|
|
61454
|
+
}, [engineMode, username, isAuthenticated, tabDecided, isRestoringSession, isLoading, cancelTakeover]);
|
|
61455
|
+
useEffect(() => {
|
|
61456
|
+
if (engineMode || tabRole !== "leader" || !username) return;
|
|
61457
|
+
const user = username;
|
|
61458
|
+
claimLeader(user, tabIdRef.current);
|
|
61459
|
+
const timer = setInterval(() => claimLeader(user, tabIdRef.current), LEADER_HEARTBEAT_MS);
|
|
61460
|
+
return () => clearInterval(timer);
|
|
61461
|
+
}, [engineMode, tabRole, username]);
|
|
61462
|
+
useEffect(() => {
|
|
61463
|
+
if (engineMode || tabRole !== "member" || !username) return;
|
|
61464
|
+
const user = username;
|
|
61465
|
+
const check = () => {
|
|
61466
|
+
if (document.visibilityState !== "visible" || takeoverTimerRef.current) return;
|
|
61467
|
+
const bus = busRef.current;
|
|
61468
|
+
if (!bus) return;
|
|
61469
|
+
void bus.probe().then((pongs) => {
|
|
61470
|
+
var _a2;
|
|
61471
|
+
if (tabRoleRef.current !== "member" || isAuthenticatedRef.current || takeoverTimerRef.current) return;
|
|
61472
|
+
if (findLeader(pongs) || readLeader(user)) return;
|
|
61473
|
+
console.log("[Callix Dialer] a aba com o discador não responde; esta aba vai assumir");
|
|
61474
|
+
(_a2 = scheduleTakeoverRef.current) == null ? void 0 : _a2.call(scheduleTakeoverRef);
|
|
61475
|
+
});
|
|
61476
|
+
};
|
|
61477
|
+
document.addEventListener("visibilitychange", check);
|
|
61478
|
+
window.addEventListener("focus", check);
|
|
61479
|
+
return () => {
|
|
61480
|
+
document.removeEventListener("visibilitychange", check);
|
|
61481
|
+
window.removeEventListener("focus", check);
|
|
61482
|
+
};
|
|
61483
|
+
}, [engineMode, tabRole, username]);
|
|
60839
61484
|
const handleLogin = useCallback(async (user) => {
|
|
60840
|
-
var _a2, _b;
|
|
61485
|
+
var _a2, _b, _c, _d;
|
|
60841
61486
|
setIsLoading(true);
|
|
60842
61487
|
setError(null);
|
|
60843
61488
|
setLoginStatus("Preparando login...");
|
|
@@ -60846,17 +61491,20 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
60846
61491
|
const engineApiUrl = options.apiUrl || "/api/user-sdk-session";
|
|
60847
61492
|
try {
|
|
60848
61493
|
setLoginStatus("Conectando ao motor...");
|
|
61494
|
+
logoffPendingRef.current = false;
|
|
60849
61495
|
const client2 = ensureEngine(user);
|
|
60850
|
-
|
|
60851
|
-
|
|
60852
|
-
|
|
61496
|
+
let view = null;
|
|
61497
|
+
try {
|
|
61498
|
+
view = await client2.waitForView(15e3);
|
|
61499
|
+
} catch (err) {
|
|
61500
|
+
if (!(err instanceof EngineAccessError)) throw err;
|
|
61501
|
+
console.log("[Callix Dialer] o motor recusou a credencial desta aba; fazendo login novo que substitui a sessão de lá");
|
|
61502
|
+
}
|
|
61503
|
+
const domain = engineDomain();
|
|
61504
|
+
const engineHasSession = view !== null && (view.engine === "running" || view.engine === "starting") && !view.sessionLost;
|
|
60853
61505
|
let token = null;
|
|
60854
61506
|
if (engineHasSession) {
|
|
60855
|
-
|
|
60856
|
-
token = localStorage.getItem(getStorageKeys(user).SESSION_TOKEN);
|
|
60857
|
-
} catch {
|
|
60858
|
-
token = null;
|
|
60859
|
-
}
|
|
61507
|
+
token = readStoredToken(user);
|
|
60860
61508
|
console.log("[Callix Dialer] motor já tem a sessão do agente; entrando sem novo login");
|
|
60861
61509
|
} else {
|
|
60862
61510
|
setLoginStatus("Autenticando no Callix...");
|
|
@@ -60872,35 +61520,20 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
60872
61520
|
}
|
|
60873
61521
|
const data = await response.json();
|
|
60874
61522
|
token = data.userSessionToken;
|
|
60875
|
-
|
|
60876
|
-
setLoginStatus("Subindo o motor...");
|
|
60877
|
-
}
|
|
60878
|
-
if (token) {
|
|
60879
|
-
const skip = await fetchSkipQualification(domain, token);
|
|
60880
|
-
if (skip !== null) {
|
|
60881
|
-
setSkipManualQualification(skip);
|
|
60882
|
-
try {
|
|
60883
|
-
localStorage.setItem(getStorageKeys(user).SKIP_MANUAL_QUALIFICATION, String(skip));
|
|
60884
|
-
} catch {
|
|
60885
|
-
}
|
|
60886
|
-
}
|
|
60887
|
-
}
|
|
60888
|
-
try {
|
|
60889
|
-
localStorage.setItem(LAST_USERNAME_KEY, user);
|
|
60890
|
-
if (token) {
|
|
61523
|
+
try {
|
|
60891
61524
|
const STORAGE_KEYS = getStorageKeys(user);
|
|
61525
|
+
localStorage.setItem(LAST_USERNAME_KEY, user);
|
|
60892
61526
|
localStorage.setItem(STORAGE_KEYS.SESSION_TOKEN, token);
|
|
60893
61527
|
localStorage.setItem(STORAGE_KEYS.DOMAIN, domain);
|
|
60894
61528
|
localStorage.setItem(STORAGE_KEYS.TIMESTAMP, Date.now().toString());
|
|
61529
|
+
} catch {
|
|
60895
61530
|
}
|
|
60896
|
-
|
|
61531
|
+
client2.setSession({ domain, userSessionToken: token });
|
|
61532
|
+
setLoginStatus("Subindo o motor...");
|
|
61533
|
+
const up = await client2.waitForView(2e4, (v) => v.engine === "running" || v.engine === "starting" || Boolean(v.sessionLost), { fresh: true });
|
|
61534
|
+
if (up.sessionLost) throw new Error(up.sessionLost.message);
|
|
60897
61535
|
}
|
|
60898
|
-
|
|
60899
|
-
setCallixDomain(domain);
|
|
60900
|
-
setUsername(user);
|
|
60901
|
-
setIsAuthenticated(true);
|
|
60902
|
-
setError(null);
|
|
60903
|
-
setProviderKey(Date.now());
|
|
61536
|
+
await enterEngine(user, domain, token);
|
|
60904
61537
|
console.log("[Callix Dialer] Conectado ao motor como", user);
|
|
60905
61538
|
} catch (err) {
|
|
60906
61539
|
console.error("[Callix Dialer] Erro ao entrar pelo motor:", err);
|
|
@@ -60913,6 +61546,20 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
60913
61546
|
}
|
|
60914
61547
|
return;
|
|
60915
61548
|
}
|
|
61549
|
+
if (!claimLeader(user, tabIdRef.current)) {
|
|
61550
|
+
console.log("[Callix Dialer] outra aba já segura a conexão deste usuário; esta aba vira membro");
|
|
61551
|
+
setTabRole("member");
|
|
61552
|
+
saveTabRole(user, "member");
|
|
61553
|
+
setTabDecided(true);
|
|
61554
|
+
setUsername(user);
|
|
61555
|
+
setIsLoading(false);
|
|
61556
|
+
setLoginStatus(null);
|
|
61557
|
+
return;
|
|
61558
|
+
}
|
|
61559
|
+
(_a2 = busRef.current) == null ? void 0 : _a2.post({ type: "claim" });
|
|
61560
|
+
cancelTakeover();
|
|
61561
|
+
setTabRole("leader");
|
|
61562
|
+
saveTabRole(user, "leader");
|
|
60916
61563
|
const apiUrl = options.apiUrl || "/api/user-sdk-session";
|
|
60917
61564
|
let previousToken;
|
|
60918
61565
|
if (typeof window !== "undefined") {
|
|
@@ -61007,6 +61654,9 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
61007
61654
|
setError(null);
|
|
61008
61655
|
setProviderKey(Date.now());
|
|
61009
61656
|
console.log("[Callix Dialer] Nova providerKey gerada para forçar recriação do SDK");
|
|
61657
|
+
setTabNote(null);
|
|
61658
|
+
setTabDecided(true);
|
|
61659
|
+
(_b = busRef.current) == null ? void 0 : _b.post({ type: "login" });
|
|
61010
61660
|
try {
|
|
61011
61661
|
const configUrl = `https://${resolvedDomain}/sdk/v1/client/user-service/config`;
|
|
61012
61662
|
setLoginStatus("Carregando configurações...");
|
|
@@ -61021,7 +61671,7 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
61021
61671
|
if (configResponse.ok) {
|
|
61022
61672
|
const configData = await configResponse.json();
|
|
61023
61673
|
console.log("[Callix Dialer] 📦 Dados da config recebidos:", JSON.stringify(configData, null, 2));
|
|
61024
|
-
const shouldSkipQualification = ((
|
|
61674
|
+
const shouldSkipQualification = ((_d = (_c = configData == null ? void 0 : configData.service) == null ? void 0 : _c.outboundOptions) == null ? void 0 : _d.skipQualification) === true;
|
|
61025
61675
|
console.log("[Callix Dialer] ✅ skipQualification configurado:", shouldSkipQualification);
|
|
61026
61676
|
setSkipManualQualification(shouldSkipQualification);
|
|
61027
61677
|
if (typeof window !== "undefined") {
|
|
@@ -61055,53 +61705,52 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
61055
61705
|
setError(err instanceof Error ? err.message : "Erro ao autenticar");
|
|
61056
61706
|
setIsAuthenticated(false);
|
|
61057
61707
|
setSessionToken(null);
|
|
61708
|
+
releaseLeader(user, tabIdRef.current);
|
|
61709
|
+
setTabRole(null);
|
|
61710
|
+
clearTabRole();
|
|
61058
61711
|
} finally {
|
|
61059
61712
|
setIsLoading(false);
|
|
61060
61713
|
setLoginStatus(null);
|
|
61061
61714
|
}
|
|
61062
|
-
}, [options.apiUrl, options.domain, options.engineUrl, isAuthenticated, sessionToken, ensureEngine]);
|
|
61063
|
-
useEffect(() => {
|
|
61064
|
-
if (lastPresetRef.current !== presetUsername) {
|
|
61065
|
-
lastPresetRef.current = presetUsername;
|
|
61066
|
-
autoLoginAttemptedRef.current = false;
|
|
61067
|
-
}
|
|
61068
|
-
if (!presetUsername || !autoLogin) {
|
|
61069
|
-
return;
|
|
61070
|
-
}
|
|
61071
|
-
if (isAuthenticated || isLoading || isRestoringSession || error2 || autoLoginAttemptedRef.current) {
|
|
61072
|
-
return;
|
|
61073
|
-
}
|
|
61074
|
-
autoLoginAttemptedRef.current = true;
|
|
61075
|
-
void handleLogin(presetUsername);
|
|
61076
|
-
}, [presetUsername, autoLogin, isAuthenticated, isLoading, isRestoringSession, error2, handleLogin]);
|
|
61715
|
+
}, [options.apiUrl, options.domain, options.engineUrl, isAuthenticated, sessionToken, ensureEngine, enterEngine, engineDomain, cancelTakeover]);
|
|
61077
61716
|
useEffect(() => {
|
|
61078
|
-
|
|
61079
|
-
|
|
61080
|
-
|
|
61081
|
-
|
|
61082
|
-
|
|
61083
|
-
void
|
|
61084
|
-
}, [autoLogin, presetUsername, username, isAuthenticated, isLoading, isRestoringSession, error2, handleLogin]);
|
|
61085
|
-
const handleLogout = useCallback(async () => {
|
|
61086
|
-
var _a2;
|
|
61717
|
+
handleLoginRef.current = handleLogin;
|
|
61718
|
+
}, [handleLogin]);
|
|
61719
|
+
const handleLogout = useCallback(async (opts) => {
|
|
61720
|
+
var _a2, _b;
|
|
61721
|
+
const broadcast = (opts == null ? void 0 : opts.broadcast) !== false;
|
|
61722
|
+
const keepDecision = (opts == null ? void 0 : opts.keepDecision) === true;
|
|
61087
61723
|
const currentUsername = username;
|
|
61724
|
+
cancelTakeover();
|
|
61088
61725
|
if (options.engineUrl) {
|
|
61089
|
-
(
|
|
61090
|
-
|
|
61091
|
-
|
|
61092
|
-
|
|
61093
|
-
|
|
61094
|
-
|
|
61095
|
-
cleanupRef.current
|
|
61096
|
-
|
|
61726
|
+
if (isAuthenticatedRef.current) {
|
|
61727
|
+
logoffPendingRef.current = true;
|
|
61728
|
+
(_a2 = engineRef.current) == null ? void 0 : _a2.command({ name: "logoff" });
|
|
61729
|
+
}
|
|
61730
|
+
} else {
|
|
61731
|
+
if (broadcast) (_b = busRef.current) == null ? void 0 : _b.post({ type: "logout" });
|
|
61732
|
+
if (cleanupRef.current) {
|
|
61733
|
+
console.log("[Callix Dialer] 📴 Logout: Chamando goOffline()...");
|
|
61734
|
+
cleanupRef.current.goOffline();
|
|
61735
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
61736
|
+
console.log("[Callix Dialer] 🛑 Logout: Chamando stop()...");
|
|
61737
|
+
cleanupRef.current.stop();
|
|
61738
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
61739
|
+
}
|
|
61740
|
+
if (currentUsername) releaseLeader(currentUsername, tabIdRef.current);
|
|
61097
61741
|
}
|
|
61098
|
-
setUsername(presetUsername ?? null);
|
|
61099
61742
|
setIsAuthenticated(false);
|
|
61100
61743
|
setSessionToken(null);
|
|
61101
61744
|
setCallixDomain(null);
|
|
61102
61745
|
setError(null);
|
|
61103
|
-
|
|
61104
|
-
|
|
61746
|
+
if (keepDecision) {
|
|
61747
|
+
setTabRole("member");
|
|
61748
|
+
if (currentUsername) saveTabRole(currentUsername, "member");
|
|
61749
|
+
return;
|
|
61750
|
+
}
|
|
61751
|
+
setTabRole(null);
|
|
61752
|
+
clearTabRole();
|
|
61753
|
+
setUsername(presetUsername ?? null);
|
|
61105
61754
|
if (typeof window !== "undefined" && currentUsername) {
|
|
61106
61755
|
try {
|
|
61107
61756
|
const STORAGE_KEYS = getStorageKeys(currentUsername);
|
|
@@ -61114,14 +61763,53 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
61114
61763
|
console.warn("[Callix Dialer] Não foi possível limpar sessão:", err);
|
|
61115
61764
|
}
|
|
61116
61765
|
}
|
|
61117
|
-
}, [username, presetUsername, options.engineUrl]);
|
|
61118
|
-
|
|
61766
|
+
}, [username, presetUsername, options.engineUrl, cancelTakeover]);
|
|
61767
|
+
useEffect(() => {
|
|
61768
|
+
handleLogoutRef.current = handleLogout;
|
|
61769
|
+
}, [handleLogout]);
|
|
61770
|
+
const handleTakeOver = useCallback(async () => {
|
|
61771
|
+
const user = username;
|
|
61772
|
+
const bus = busRef.current;
|
|
61773
|
+
if (!user || !bus) return;
|
|
61774
|
+
setIsLoading(true);
|
|
61775
|
+
setError(null);
|
|
61776
|
+
setLoginStatus("Trazendo o discador para esta aba...");
|
|
61777
|
+
bus.post({ type: "takeover" });
|
|
61778
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
61779
|
+
const current = readLeader(user);
|
|
61780
|
+
if (current && current.tabId !== tabIdRef.current) {
|
|
61781
|
+
console.log("[Callix Dialer] a outra aba não soltou a conexão; continuando como membro");
|
|
61782
|
+
setIsLoading(false);
|
|
61783
|
+
setLoginStatus(null);
|
|
61784
|
+
return;
|
|
61785
|
+
}
|
|
61786
|
+
await handleLoginRef.current(user);
|
|
61787
|
+
}, [username]);
|
|
61788
|
+
const handleLogoutAll = useCallback(() => {
|
|
61789
|
+
void handleLogoutRef.current();
|
|
61790
|
+
}, []);
|
|
61791
|
+
const handleSdkSessionDropped = useCallback(
|
|
61792
|
+
(originator, notice) => {
|
|
61793
|
+
var _a2;
|
|
61794
|
+
const user = username;
|
|
61795
|
+
if (user) releaseLeader(user, tabIdRef.current);
|
|
61796
|
+
(_a2 = busRef.current) == null ? void 0 : _a2.post({ type: "dropped", originator });
|
|
61797
|
+
setTabRole(null);
|
|
61798
|
+
clearTabRole();
|
|
61799
|
+
setError(`${notice.title}: ${notice.detail}${notice.action ? ` ${notice.action}` : ""}`);
|
|
61800
|
+
setIsAuthenticated(false);
|
|
61801
|
+
setSessionToken(null);
|
|
61802
|
+
setCallixDomain(null);
|
|
61803
|
+
},
|
|
61804
|
+
[username]
|
|
61805
|
+
);
|
|
61806
|
+
const deciding = Boolean(username) && !isAuthenticated && (engineMode ? engineWaiting : !tabDecided);
|
|
61119
61807
|
const loginConfirmation = useMemo(() => {
|
|
61120
|
-
if (isAuthenticated || isLoading || isRestoringSession || isDisconnecting || !username ||
|
|
61808
|
+
if (isAuthenticated || isLoading || isRestoringSession || isDisconnecting || !username || deciding) {
|
|
61121
61809
|
return null;
|
|
61122
61810
|
}
|
|
61123
|
-
return { username, locked: Boolean(presetUsername) };
|
|
61124
|
-
}, [isAuthenticated, isLoading, isRestoringSession, isDisconnecting, username, presetUsername,
|
|
61811
|
+
return { username, locked: Boolean(presetUsername), elsewhere: !engineMode && tabRole === "member", note: tabNote };
|
|
61812
|
+
}, [isAuthenticated, isLoading, isRestoringSession, isDisconnecting, username, presetUsername, deciding, engineMode, tabRole, tabNote]);
|
|
61125
61813
|
const handleCancelLoginConfirmation = useCallback(() => {
|
|
61126
61814
|
setUsername(null);
|
|
61127
61815
|
setError(null);
|
|
@@ -61161,11 +61849,13 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
61161
61849
|
username,
|
|
61162
61850
|
onLogin: handleLogin,
|
|
61163
61851
|
onLogout: handleLogout,
|
|
61164
|
-
isLoadingSession: isLoading || isRestoringSession ||
|
|
61852
|
+
isLoadingSession: isLoading || isRestoringSession || deciding,
|
|
61165
61853
|
sessionError: error2,
|
|
61166
61854
|
sessionStatus: loginStatus,
|
|
61167
61855
|
loginConfirmation,
|
|
61168
61856
|
onCancelLoginConfirmation: handleCancelLoginConfirmation,
|
|
61857
|
+
onTakeOverSession: handleTakeOver,
|
|
61858
|
+
onLogoutAllTabs: handleLogoutAll,
|
|
61169
61859
|
variant: uiVariant,
|
|
61170
61860
|
portalTarget,
|
|
61171
61861
|
density: options.density,
|
|
@@ -61210,7 +61900,7 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
61210
61900
|
{
|
|
61211
61901
|
domain: callixDomain,
|
|
61212
61902
|
userSessionToken: sessionToken,
|
|
61213
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(SdkCleanupManager, { ref: cleanupRef, children: [
|
|
61903
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(SdkCleanupManager, { ref: cleanupRef, onSessionDropped: handleSdkSessionDropped, children: [
|
|
61214
61904
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
61215
61905
|
DialerComponent,
|
|
61216
61906
|
{
|