callix-dialer-widget 2.7.0 → 2.8.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/WIDGET-README.md
CHANGED
|
@@ -119,18 +119,33 @@ CallixDialer.init({
|
|
|
119
119
|
apiUrl: 'https://callix-zeta.vercel.app/api/user-sdk-session', // continua: é onde o login é feito
|
|
120
120
|
uiVariant: 'mobile',
|
|
121
121
|
engineUrl: 'https://motor.exemplo.com', // host do motor (HTTPS; o navegador exige origem segura para o microfone)
|
|
122
|
-
engineToken: '...', // ENGINE_TAB_TOKEN do host
|
|
123
122
|
});
|
|
124
123
|
```
|
|
125
124
|
|
|
126
|
-
Também pelo HTML: `data-callix-engine-url`
|
|
125
|
+
Também pelo HTML: `data-callix-engine-url` no container. Só isso: desde a 2.8.0 o widget não
|
|
126
|
+
precisa do token do host (`engineToken`). A credencial da aba é a própria sessão do Callix que
|
|
127
|
+
o widget cria em `apiUrl` e guarda no navegador: uma aba nova ou um F5 no mesmo navegador
|
|
128
|
+
apresenta esse token e entra na sessão que o motor roda; outro navegador ou computador não o
|
|
129
|
+
tem, vê "Entrar" com o aviso de que o discador está em uso em outro lugar, e ao entrar faz um
|
|
130
|
+
login novo que substitui a sessão de lá (como o Callix web faz). O host confirma no Callix
|
|
131
|
+
toda sessão entregue antes de subir o motor com ela. `engineToken` continua aceito, mas só
|
|
132
|
+
serve para uso administrativo (página `tab/` do motor, roteiros); não o coloque em página
|
|
133
|
+
pública.
|
|
127
134
|
|
|
128
135
|
Fluxo de login no modo motor: o widget conecta ao host com o usuário; se o motor já segura
|
|
129
|
-
a sessão desse agente, entra direto. Senão, faz o login em
|
|
130
|
-
motor, que sobe o SDK no servidor.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
136
|
+
a sessão desse agente e a aba tem a credencial dela, entra direto. Senão, faz o login em
|
|
137
|
+
`apiUrl` e entrega a sessão ao motor, que sobe o SDK no servidor. No mesmo navegador o
|
|
138
|
+
widget nunca cria uma sessão por cima de uma viva (o login exclusivo do Callix derrubaria a
|
|
139
|
+
que o motor está usando); de outro navegador ele só cria depois que o agente clica em
|
|
140
|
+
Entrar, avisado de que encerra a sessão de lá. Se o Callix derrubar a sessão (login no
|
|
141
|
+
Callix web, supervisor, bloqueio), o widget volta à tela de login com o motivo e não reentra
|
|
142
|
+
sozinho.
|
|
143
|
+
|
|
144
|
+
Pausas no modo motor (2.8.1): a lista de pausas é a do serviço no Callix, trazida pela vista
|
|
145
|
+
do motor; a pausa escolhida vai no comando `pause` e o discador mostra o nome dela. Com um
|
|
146
|
+
motor anterior ao 2.8.1 a lista cai numa pausa única ("Pausa") e o motor usa a configurada
|
|
147
|
+
nele. O widget também informa a própria versão ao host, que a registra no log: é o jeito de
|
|
148
|
+
achar navegadores com um build antigo em cache.
|
|
134
149
|
|
|
135
150
|
Sem `engineUrl` nada muda: o SDK continua rodando no navegador como sempre.
|
|
136
151
|
|
|
@@ -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,17 @@ 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
|
+
...this.options.version ? { version: this.options.version } : {},
|
|
43842
|
+
...sessionToken ? { sessionToken } : {},
|
|
43843
|
+
label: this.options.label ?? "Discador",
|
|
43844
|
+
...this.session ? { session: this.session } : {}
|
|
43845
|
+
};
|
|
43828
43846
|
this.send(hello);
|
|
43829
43847
|
this.log("conectado ao host do motor");
|
|
43830
43848
|
};
|
|
@@ -43871,18 +43889,30 @@ class EngineClient {
|
|
|
43871
43889
|
for (const waiter of this.viewWaiters.splice(0)) clearTimeout(waiter.timer);
|
|
43872
43890
|
this.setState({ wsState: "closed", tabId: null, engaged: false });
|
|
43873
43891
|
}
|
|
43874
|
-
/**
|
|
43875
|
-
|
|
43876
|
-
|
|
43892
|
+
/**
|
|
43893
|
+
* A view atual, ou a próxima que o host mandar (welcome/view). Com `accept`, espera uma
|
|
43894
|
+
* view que passe no filtro (ex.: motor subindo depois de entregar a sessão). Rejeita com
|
|
43895
|
+
* `EngineAccessError` se o host recusou esta aba (`rejected`).
|
|
43896
|
+
*/
|
|
43897
|
+
waitForView(timeoutMs = 15e3, accept, options) {
|
|
43898
|
+
const rejected = this.state.rejected;
|
|
43899
|
+
if (rejected) return Promise.reject(new EngineAccessError(rejected.code, rejected.message));
|
|
43900
|
+
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
43901
|
return new Promise((resolve, reject) => {
|
|
43878
43902
|
const timer = setTimeout(() => {
|
|
43879
43903
|
const index = this.viewWaiters.findIndex((w) => w.timer === timer);
|
|
43880
43904
|
if (index >= 0) this.viewWaiters.splice(index, 1);
|
|
43881
43905
|
reject(new Error("o motor não respondeu"));
|
|
43882
43906
|
}, timeoutMs);
|
|
43883
|
-
this.viewWaiters.push({ resolve, timer });
|
|
43907
|
+
this.viewWaiters.push({ resolve, reject, accept, timer });
|
|
43884
43908
|
});
|
|
43885
43909
|
}
|
|
43910
|
+
rejectWaiters(error2) {
|
|
43911
|
+
for (const waiter of this.viewWaiters.splice(0)) {
|
|
43912
|
+
clearTimeout(waiter.timer);
|
|
43913
|
+
waiter.reject(error2);
|
|
43914
|
+
}
|
|
43915
|
+
}
|
|
43886
43916
|
send(message) {
|
|
43887
43917
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) this.ws.send(JSON.stringify(message));
|
|
43888
43918
|
}
|
|
@@ -43890,7 +43920,7 @@ class EngineClient {
|
|
|
43890
43920
|
switch (message.type) {
|
|
43891
43921
|
case "welcome": {
|
|
43892
43922
|
if (Array.isArray(message.iceServers) && message.iceServers.length > 0) this.iceServers = message.iceServers;
|
|
43893
|
-
this.setState({ tabId: message.tabId });
|
|
43923
|
+
this.setState({ tabId: message.tabId, rejected: null });
|
|
43894
43924
|
this.applyView(message.view);
|
|
43895
43925
|
this.log(`sou a aba ${message.tabId}`);
|
|
43896
43926
|
if (this.options.autoEngage !== false && message.view.engagedTabId !== message.tabId) this.engage();
|
|
@@ -43908,6 +43938,19 @@ class EngineClient {
|
|
|
43908
43938
|
void this.onSignal(message.payload);
|
|
43909
43939
|
break;
|
|
43910
43940
|
case "error":
|
|
43941
|
+
if (message.code === "unauthorized") {
|
|
43942
|
+
this.setState({ lastError: message.message, rejected: { code: message.code, message: message.message } });
|
|
43943
|
+
this.session = null;
|
|
43944
|
+
this.reconnectDelay = RECONNECT_MAX_MS;
|
|
43945
|
+
this.log(`acesso recusado pelo host: ${message.message}`);
|
|
43946
|
+
this.rejectWaiters(new EngineAccessError(message.code, message.message));
|
|
43947
|
+
break;
|
|
43948
|
+
}
|
|
43949
|
+
if (message.code === "session-changed") {
|
|
43950
|
+
this.session = null;
|
|
43951
|
+
this.log("a sessão deste agente foi trocada por um login novo; reconectando com a credencial atual");
|
|
43952
|
+
break;
|
|
43953
|
+
}
|
|
43911
43954
|
this.setState({ lastError: message.message });
|
|
43912
43955
|
this.log(`erro do host: ${message.message}`);
|
|
43913
43956
|
break;
|
|
@@ -43945,6 +43988,10 @@ class EngineClient {
|
|
|
43945
43988
|
if (call && typeof call.muted === "boolean" && call.muted !== this.state.inputMuted && call.state !== "ended") patch.inputMuted = call.muted;
|
|
43946
43989
|
this.setState(patch);
|
|
43947
43990
|
for (const waiter of this.viewWaiters.splice(0)) {
|
|
43991
|
+
if (waiter.accept && !waiter.accept(view)) {
|
|
43992
|
+
this.viewWaiters.push(waiter);
|
|
43993
|
+
continue;
|
|
43994
|
+
}
|
|
43948
43995
|
clearTimeout(waiter.timer);
|
|
43949
43996
|
waiter.resolve(view);
|
|
43950
43997
|
}
|
|
@@ -43957,10 +44004,33 @@ class EngineClient {
|
|
|
43957
44004
|
};
|
|
43958
44005
|
}
|
|
43959
44006
|
// ------------------------------------------------------------------ sessão e comandos
|
|
43960
|
-
/**
|
|
44007
|
+
/**
|
|
44008
|
+
* Modo sdk: o widget fez login no back-end e entrega a sessão ao host. Com a conexão
|
|
44009
|
+
* aberta manda `session`; recusada ou caída, reconecta agora apresentando a sessão no hello
|
|
44010
|
+
* (é assim que um login novo substitui a sessão de outro navegador).
|
|
44011
|
+
*/
|
|
43961
44012
|
setSession(session) {
|
|
43962
44013
|
this.session = session;
|
|
43963
|
-
this.
|
|
44014
|
+
this.setState({ rejected: null, sessionLost: null });
|
|
44015
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
44016
|
+
if (this.state.tabId) {
|
|
44017
|
+
this.send({ type: "session", session });
|
|
44018
|
+
return;
|
|
44019
|
+
}
|
|
44020
|
+
const stale = this.ws;
|
|
44021
|
+
this.ws = null;
|
|
44022
|
+
stale.onopen = null;
|
|
44023
|
+
stale.onmessage = null;
|
|
44024
|
+
stale.onclose = null;
|
|
44025
|
+
stale.close();
|
|
44026
|
+
this.setState({ wsState: "closed" });
|
|
44027
|
+
}
|
|
44028
|
+
if (this.reconnectTimer) {
|
|
44029
|
+
clearTimeout(this.reconnectTimer);
|
|
44030
|
+
this.reconnectTimer = null;
|
|
44031
|
+
}
|
|
44032
|
+
this.reconnectDelay = RECONNECT_MIN_MS;
|
|
44033
|
+
this.connect();
|
|
43964
44034
|
}
|
|
43965
44035
|
engage() {
|
|
43966
44036
|
this.send({ type: "engage" });
|
|
@@ -44159,6 +44229,18 @@ function useEngineState(client2) {
|
|
|
44159
44229
|
return useSyncExternalStore(client2.subscribe.bind(client2), client2.getState.bind(client2), client2.getState.bind(client2));
|
|
44160
44230
|
}
|
|
44161
44231
|
const ENGINE_BREAKS = [{ id: 0, name: "Pausa" }];
|
|
44232
|
+
function breaksFromView(view) {
|
|
44233
|
+
var _a2;
|
|
44234
|
+
const breaks = (_a2 = view == null ? void 0 : view.snapshot) == null ? void 0 : _a2.leg.breaks;
|
|
44235
|
+
return breaks && breaks.length > 0 ? breaks.map((b) => ({ id: b.id, name: b.name })) : ENGINE_BREAKS;
|
|
44236
|
+
}
|
|
44237
|
+
function currentBreakFromView(view) {
|
|
44238
|
+
var _a2;
|
|
44239
|
+
return ((_a2 = view.snapshot) == null ? void 0 : _a2.leg.break) ?? breaksFromView(view)[0];
|
|
44240
|
+
}
|
|
44241
|
+
function pauseCommand(breakId) {
|
|
44242
|
+
return typeof breakId === "number" ? { name: "pause", breakId } : { name: "pause" };
|
|
44243
|
+
}
|
|
44162
44244
|
function toCallQualification(q) {
|
|
44163
44245
|
return { id: q.id, name: q.name, isSystemQualification: false, systemQualificationType: 0 };
|
|
44164
44246
|
}
|
|
@@ -44291,7 +44373,7 @@ function operatorStateFromView(view, call) {
|
|
|
44291
44373
|
case "afterCall":
|
|
44292
44374
|
return { state: "afterCall" };
|
|
44293
44375
|
case "onBreak":
|
|
44294
|
-
return { state: "onBreak", break:
|
|
44376
|
+
return { state: "onBreak", break: currentBreakFromView(view) };
|
|
44295
44377
|
case "offline":
|
|
44296
44378
|
return { state: "offline" };
|
|
44297
44379
|
case "error":
|
|
@@ -44374,7 +44456,7 @@ function useEngineControls(client2) {
|
|
|
44374
44456
|
if (status === "onBreak") client2.command({ name: "resume" });
|
|
44375
44457
|
},
|
|
44376
44458
|
goOffline: () => void 0,
|
|
44377
|
-
enterOnBreak: () => client2.command(
|
|
44459
|
+
enterOnBreak: (breakId) => client2.command(pauseCommand(breakId)),
|
|
44378
44460
|
makeManualCall: (phoneNumber) => client2.command({ name: "dial", phone: phoneNumber }),
|
|
44379
44461
|
finishAfterCall: (data) => {
|
|
44380
44462
|
if (typeof data.qualificationId === "number") client2.command({ name: "qualify", qualificationId: data.qualificationId, result: data.result === "failure" ? "discard" : "success" });
|
|
@@ -44428,7 +44510,8 @@ const operators = /* @__PURE__ */ new WeakMap();
|
|
|
44428
44510
|
function engineOperator(client2) {
|
|
44429
44511
|
let operator = operators.get(client2);
|
|
44430
44512
|
if (!operator) {
|
|
44431
|
-
const breaks = new EngineSignal(
|
|
44513
|
+
const breaks = new EngineSignal(breaksFromView(client2.getState().view));
|
|
44514
|
+
client2.subscribe(() => breaks.set(breaksFromView(client2.getState().view)));
|
|
44432
44515
|
operator = {
|
|
44433
44516
|
breaks,
|
|
44434
44517
|
user: client2.userSignal,
|
|
@@ -44443,7 +44526,7 @@ function engineOperator(client2) {
|
|
|
44443
44526
|
var _a2, _b;
|
|
44444
44527
|
if (((_b = (_a2 = client2.getState().view) == null ? void 0 : _a2.snapshot) == null ? void 0 : _b.leg.status) === "onBreak") client2.command({ name: "resume" });
|
|
44445
44528
|
},
|
|
44446
|
-
enterOnBreak: () => client2.command(
|
|
44529
|
+
enterOnBreak: (breakId) => client2.command(pauseCommand(breakId)),
|
|
44447
44530
|
makeManualCall: (phoneNumber) => client2.command({ name: "dial", phone: phoneNumber }),
|
|
44448
44531
|
finishAfterCall: (data) => {
|
|
44449
44532
|
if (typeof data.qualificationId === "number") client2.command({ name: "qualify", qualificationId: data.qualificationId, result: data.result === "failure" ? "discard" : "success" });
|
|
@@ -58627,7 +58710,7 @@ function AuthenticatedMobileDialer({
|
|
|
58627
58710
|
showClientInfoModal = false,
|
|
58628
58711
|
density
|
|
58629
58712
|
}) {
|
|
58630
|
-
var _a2, _b, _c, _d;
|
|
58713
|
+
var _a2, _b, _c, _d, _e;
|
|
58631
58714
|
const { skipManualQualification } = useDialerConfig();
|
|
58632
58715
|
const [dialValue, setDialValue] = useState("");
|
|
58633
58716
|
const [activeScreen, setActiveScreen] = useState("dialer");
|
|
@@ -59340,11 +59423,12 @@ function AuthenticatedMobileDialer({
|
|
|
59340
59423
|
if (isOnBreak) return "paused";
|
|
59341
59424
|
return "available";
|
|
59342
59425
|
}, [isError, isOnBreak]);
|
|
59426
|
+
const activeBreakName = (operatorState == null ? void 0 : operatorState.state) === "onBreak" ? (_a2 = operatorState.break) == null ? void 0 : _a2.name : void 0;
|
|
59343
59427
|
const statusBadgeText = useMemo(() => {
|
|
59344
59428
|
if (isError) return (dialerNotice == null ? void 0 : dialerNotice.source) === "device" ? dialerNotice.title : "Erro";
|
|
59345
|
-
if (isOnBreak) return currentBreakName || "Em pausa";
|
|
59429
|
+
if (isOnBreak) return currentBreakName || activeBreakName || "Em pausa";
|
|
59346
59430
|
return "Disponível";
|
|
59347
|
-
}, [dialerNotice, isError, isOnBreak, currentBreakName]);
|
|
59431
|
+
}, [dialerNotice, isError, isOnBreak, currentBreakName, activeBreakName]);
|
|
59348
59432
|
const pauseDurationLabel = useMemo(() => {
|
|
59349
59433
|
const hours = Math.floor(pauseDurationSeconds / 3600);
|
|
59350
59434
|
const minutes = Math.floor(pauseDurationSeconds % 3600 / 60).toString().padStart(2, "0");
|
|
@@ -59482,15 +59566,15 @@ function AuthenticatedMobileDialer({
|
|
|
59482
59566
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "client-card-header", children: [
|
|
59483
59567
|
/* @__PURE__ */ jsxRuntimeExports.jsx("i", { className: "fas fa-user-circle client-avatar" }),
|
|
59484
59568
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "client-main-info", children: [
|
|
59485
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-name", id: "clientName", children: findValue(contactData.finalData, ["DECISOR", "NOME", "CLIENTE", "PROSPECT"]) ?? ((
|
|
59486
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-company", id: "clientCompany", children: findValue(contactData.finalData, ["EMPRESA", "RAZAO SOCIAL", "RAZÃO SOCIAL", "RAZAO_SOCIAL"]) ?? ((
|
|
59569
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-name", id: "clientName", children: findValue(contactData.finalData, ["DECISOR", "NOME", "CLIENTE", "PROSPECT"]) ?? ((_b = callInfo.info.campaignContact) == null ? void 0 : _b.label) ?? "--" }),
|
|
59570
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-company", id: "clientCompany", children: findValue(contactData.finalData, ["EMPRESA", "RAZAO SOCIAL", "RAZÃO SOCIAL", "RAZAO_SOCIAL"]) ?? ((_c = callInfo.info.campaign) == null ? void 0 : _c.name) ?? "--" })
|
|
59487
59571
|
] })
|
|
59488
59572
|
] }),
|
|
59489
59573
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "client-card-divider" }),
|
|
59490
59574
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "client-info-list", children: [
|
|
59491
59575
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "client-info-row", children: [
|
|
59492
59576
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-info-label", children: "Socio" }),
|
|
59493
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-info-value", children: findValue(contactData.finalData, ["SOCIO", "PROSPECT", "DECISOR", "NOME", "CLIENTE"]) ?? ((
|
|
59577
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-info-value", children: findValue(contactData.finalData, ["SOCIO", "PROSPECT", "DECISOR", "NOME", "CLIENTE"]) ?? ((_d = callInfo.info.campaignContact) == null ? void 0 : _d.label) ?? "--" })
|
|
59494
59578
|
] }),
|
|
59495
59579
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "client-info-row", children: [
|
|
59496
59580
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-info-label", children: "Empresa" }),
|
|
@@ -59687,7 +59771,7 @@ function AuthenticatedMobileDialer({
|
|
|
59687
59771
|
{
|
|
59688
59772
|
isOpen: isClientInfoModalOpen,
|
|
59689
59773
|
campaignCallInfo,
|
|
59690
|
-
campaignContactPhoneId: ((
|
|
59774
|
+
campaignContactPhoneId: ((_e = currentCall == null ? void 0 : currentCall.data) == null ? void 0 : _e.campaignContactPhoneId) ?? null,
|
|
59691
59775
|
callDuration: callDurationSeconds,
|
|
59692
59776
|
isCallActive: isInCall || isConnecting,
|
|
59693
59777
|
onClose: () => setIsClientInfoModalOpen(false)
|
|
@@ -60671,7 +60755,7 @@ function ClickToCallAgent({ enabled = true, pollIntervalMs, sessionToken, onTask
|
|
|
60671
60755
|
}, [enabled, pollIntervalMs, sessionToken]);
|
|
60672
60756
|
return null;
|
|
60673
60757
|
}
|
|
60674
|
-
const WIDGET_VERSION = "2.
|
|
60758
|
+
const WIDGET_VERSION = "2.8.1";
|
|
60675
60759
|
let currentSipWebSocket = null;
|
|
60676
60760
|
function sendSipUnregisterIfPossible(ws) {
|
|
60677
60761
|
if (ws.readyState !== WebSocket.OPEN) return;
|
|
@@ -61070,7 +61154,11 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
61070
61154
|
current == null ? void 0 : current.close();
|
|
61071
61155
|
const client2 = new EngineClient({
|
|
61072
61156
|
url: options.engineUrl ?? "",
|
|
61073
|
-
token: options.engineToken
|
|
61157
|
+
token: options.engineToken || void 0,
|
|
61158
|
+
version: WIDGET_VERSION,
|
|
61159
|
+
// credencial da aba: o token da sessão do Callix guardado neste navegador (lido a cada
|
|
61160
|
+
// hello, para a reconexão depois de uma troca de sessão pegar o token novo)
|
|
61161
|
+
sessionToken: () => readStoredToken(user),
|
|
61074
61162
|
agentId: user,
|
|
61075
61163
|
label: "Discador",
|
|
61076
61164
|
log: (message) => console.log("[Callix Dialer/motor]", message)
|
|
@@ -61227,8 +61315,26 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
61227
61315
|
setEngineWaiting(!client2.getState().view);
|
|
61228
61316
|
const fallback = setTimeout(() => setEngineWaiting(false), 15e3);
|
|
61229
61317
|
let joining = false;
|
|
61318
|
+
let rejectedNote = false;
|
|
61230
61319
|
const sync = () => {
|
|
61231
|
-
const { view, sessionLost } = client2.getState();
|
|
61320
|
+
const { view, sessionLost, rejected } = client2.getState();
|
|
61321
|
+
if (!rejected && rejectedNote) {
|
|
61322
|
+
rejectedNote = false;
|
|
61323
|
+
setTabNote(null);
|
|
61324
|
+
}
|
|
61325
|
+
if (rejected) {
|
|
61326
|
+
rejectedNote = true;
|
|
61327
|
+
setEngineWaiting(false);
|
|
61328
|
+
if (isLoadingRef.current) return;
|
|
61329
|
+
if (isAuthenticatedRef.current) {
|
|
61330
|
+
console.log("[Callix Dialer] o motor recusou esta aba: a sessão do agente foi trocada por um login em outro lugar");
|
|
61331
|
+
setIsAuthenticated(false);
|
|
61332
|
+
setSessionToken(null);
|
|
61333
|
+
setCallixDomain(null);
|
|
61334
|
+
}
|
|
61335
|
+
setTabNote(rejected.message);
|
|
61336
|
+
return;
|
|
61337
|
+
}
|
|
61232
61338
|
if (!view) return;
|
|
61233
61339
|
setEngineWaiting(false);
|
|
61234
61340
|
if (view.engine === "stopped" || view.engine === "crashed") logoffPendingRef.current = false;
|
|
@@ -61412,9 +61518,15 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
61412
61518
|
setLoginStatus("Conectando ao motor...");
|
|
61413
61519
|
logoffPendingRef.current = false;
|
|
61414
61520
|
const client2 = ensureEngine(user);
|
|
61415
|
-
|
|
61521
|
+
let view = null;
|
|
61522
|
+
try {
|
|
61523
|
+
view = await client2.waitForView(15e3);
|
|
61524
|
+
} catch (err) {
|
|
61525
|
+
if (!(err instanceof EngineAccessError)) throw err;
|
|
61526
|
+
console.log("[Callix Dialer] o motor recusou a credencial desta aba; fazendo login novo que substitui a sessão de lá");
|
|
61527
|
+
}
|
|
61416
61528
|
const domain = engineDomain();
|
|
61417
|
-
const engineHasSession = (view.engine === "running" || view.engine === "starting") && !view.sessionLost;
|
|
61529
|
+
const engineHasSession = view !== null && (view.engine === "running" || view.engine === "starting") && !view.sessionLost;
|
|
61418
61530
|
let token = null;
|
|
61419
61531
|
if (engineHasSession) {
|
|
61420
61532
|
token = readStoredToken(user);
|
|
@@ -61433,8 +61545,18 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
61433
61545
|
}
|
|
61434
61546
|
const data = await response.json();
|
|
61435
61547
|
token = data.userSessionToken;
|
|
61548
|
+
try {
|
|
61549
|
+
const STORAGE_KEYS = getStorageKeys(user);
|
|
61550
|
+
localStorage.setItem(LAST_USERNAME_KEY, user);
|
|
61551
|
+
localStorage.setItem(STORAGE_KEYS.SESSION_TOKEN, token);
|
|
61552
|
+
localStorage.setItem(STORAGE_KEYS.DOMAIN, domain);
|
|
61553
|
+
localStorage.setItem(STORAGE_KEYS.TIMESTAMP, Date.now().toString());
|
|
61554
|
+
} catch {
|
|
61555
|
+
}
|
|
61436
61556
|
client2.setSession({ domain, userSessionToken: token });
|
|
61437
61557
|
setLoginStatus("Subindo o motor...");
|
|
61558
|
+
const up = await client2.waitForView(2e4, (v) => v.engine === "running" || v.engine === "starting" || Boolean(v.sessionLost), { fresh: true });
|
|
61559
|
+
if (up.sessionLost) throw new Error(up.sessionLost.message);
|
|
61438
61560
|
}
|
|
61439
61561
|
await enterEngine(user, domain, token);
|
|
61440
61562
|
console.log("[Callix Dialer] Conectado ao motor como", user);
|