diff --git a/index.html b/index.html index c9bab3f..0d5edff 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@ default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; - connect-src 'self' ws://autoatend.linco.work:6001 ws://localhost:6001 wss://aa.linco.work:443; + connect-src 'self' ws://localhost:3000 http://localhost:3000; "> Tela de Atendimento @@ -45,9 +45,9 @@ - + - \ No newline at end of file + diff --git a/main.js b/main.js index fa4dede..4ca51e0 100644 --- a/main.js +++ b/main.js @@ -14,7 +14,14 @@ let updateWin; const dataPath = path.join(__dirname, 'data.json'); // Caminho para o JSON (backup local) const settingsPath = path.join(app.getPath('userData'), 'settings.json'); // Caminho para as configurações -const apiUrl = 'https://autoatend.linco.work/api/v1/'; + +//! API +const apiUrl = 'http://localhost:3000/api/'; // Adaptado para NestJS +//! pusher +const pusherUrl = 'http://localhost:3000'; // Agora aponta para o Socket.io (NestJS) + +autoUpdater.autoDownload = false; +autoUpdater.autoInstallOnAppQuit = true; //? Função para ler as configurações function getSettings() { @@ -52,21 +59,15 @@ ipcMain.on('set-setting', (event, key, value) => { }); //! final de configurações -//!pusher -const pusherUrl = 'aa.linco.work'; - -autoUpdater.autoDownload = false; -autoUpdater.autoInstallOnAppQuit = true; - //impede que o app seja executado mais de uma vez const gotTheLock = app.requestSingleInstanceLock(); // Função para configurar inicialização automática function setAutoLaunch(start) { - app.setLoginItemSettings({ - openAtLogin: start, - path: app.getPath('exe'), // Aponta para o executável do seu app - }); + app.setLoginItemSettings({ + openAtLogin: start, + path: app.getPath('exe'), // Aponta para o executável do seu app + }); } // Função modificada para buscar dados da API @@ -112,7 +113,8 @@ async function getFirstData() { const token = await getAuthToken(); const colabId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('idOperator')") - const url = apiUrl + 'get-proximos/' + colabId; + const tenantId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('tenantId')") + const url = apiUrl + 'attendance/next-in-line/' + colabId; //! checa se o token e o colabId existem if (!token && !colabId) { console.warn("Token or colabId not found in localStorage. API requests will not be made."); return; } @@ -123,7 +125,8 @@ async function getFirstData() { url: url, headers: { 'Content-Type': 'application/json', - 'Authorization': 'Bearer ' + token + 'Authorization': 'Bearer ' + token, + 'x-tenant-id': tenantId } }); @@ -134,7 +137,7 @@ async function getFirstData() { response.on('end', () => { try { const parsedData = JSON.parse(rawData); - let proximos = parsedData; + let proximos = Array.isArray(parsedData) ? parsedData : []; if (response.statusCode === 200) { floatingWin.webContents.executeJavaScript("localStorage.setItem('proximos','" + JSON.stringify(proximos) + "')"); let count = proximos.length; @@ -162,7 +165,8 @@ async function getFirstData() { // Função para coletar a lista de atendimentos do servidor, vai ser chamada uma vez e a cada 30s async function getDataAndUpdateFloatingBtn() { - const proximos = JSON.parse(await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')")) ?? []; + const stored = await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')"); + const proximos = JSON.parse(stored || '[]'); let count = proximos.length; //lista a contagem no botão flutuante @@ -446,11 +450,11 @@ async function getSelectedOperator() { .then(operator => resolve(operator)) .catch(() => resolve(null)); } else if (mainWin && !mainWin.isDestroyed()) { - mainWin.webContents.executeJavaScript('localStorage.getItem("selectedOperator");') + mainWin.webContents.executeJavaScript('localStorage.getItem("authToken");') .then(operator => resolve(operator)) .catch(() => resolve(null)); } else if (floatingWin && !floatingWin.isDestroyed()) { - floatingWin.webContents.executeJavaScript('localStorage.getItem("selectedOperator");') + floatingWin.webContents.executeJavaScript('localStorage.getItem("authToken");') .then(operator => resolve(operator)) .catch(() => resolve(null)); } else { @@ -477,9 +481,8 @@ async function getSelectedOperatorId() { ipcMain.handle('get-pusher-config', async () => { // Obtenha sua chave e host de forma segura aqui (ambiente, .env, etc.) - const PUSHER_APP_KEY = process.env.PUSHER_APP_KEY || '1feb970af7708cb'; const PUSHER_HOST = process.env.PUSHER_HOST || pusherUrl; - return { appKey: PUSHER_APP_KEY, host: PUSHER_HOST }; + return { host: PUSHER_HOST }; }); ipcMain.on('update_version', async (event, arg) => { @@ -538,25 +541,25 @@ ipcMain.on('chamar-fila', async () => { // Se não houver atendimento em andamento, continua com a lógica original. const countFila = async () => { - const proximos = JSON.parse(await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')")) ?? []; + const stored = await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')"); + const proximos = JSON.parse(stored || '[]'); return proximos.length; } const requestData = async () => { - - - const colabId = await getSelectedOperatorId(); - const token = await getAuthToken('token'); - const url = apiUrl + 'chama-fila-app-colab/' + colabId; // URL de exemplo para enviar a solicitação + const token = await getAuthToken(); + const tenantId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('tenantId')") + const url = apiUrl + 'attendance/call-next/' + colabId; const request = net.request({ - method: 'GET', + method: 'POST', url: url, headers: { 'Content-Type': 'application/json', - 'Authorization': 'Bearer ' + token + 'Authorization': 'Bearer ' + token, + 'x-tenant-id': tenantId } }); @@ -570,31 +573,33 @@ ipcMain.on('chamar-fila', async () => { response.on('end', () => { try { const parsedData = JSON.parse(rawData); - if (response.statusCode === 200) { - mainWin.webContents.send('select-atend-id', parsedData.data); - if (parsedData.data && (parsedData.data.Status === 'Fila' || parsedData.data.Status === 'Chamado')) { showMainWindow(); } else - if (parsedData.data && parsedData.data.Status === 'Atendendo') { - let options2 = { - 'title': 'Precisa finalizar antes de chamar o próximo.', - 'message': 'Em andamento', - 'detail': 'Já possui um atendimento em andamento (Atendendo: ' + parsedData.data.clientName + '), continue e finalize por favor!', - 'type': 'error', - 'noLink': true, - 'buttons': ['Depois', 'Continuar'], - }; - dialog.showMessageBox(floatingWin, options2).then(result => { - if (result.response) { - mainWin.webContents.send('show-observation'); - showMainWindow(); - } else { - mainWin.hide(); + if (response.statusCode === 201 || response.statusCode === 200) { + if (parsedData) { + mainWin.webContents.send('select-atend-id', parsedData); + if (parsedData.status === 'Fila' || parsedData.status === 'Chamado') { showMainWindow(); } else + if (parsedData.status === 'Atendendo') { + let options2 = { + 'title': 'Precisa finalizar antes de chamar o próximo.', + 'message': 'Em andamento', + 'detail': 'Já possui um atendimento em andamento (Atendendo: ' + parsedData.clientName + '), continue e finalize por favor!', + 'type': 'error', + 'noLink': true, + 'buttons': ['Depois', 'Continuar'], }; - }); - } - // console.log(parsedData); + dialog.showMessageBox(floatingWin, options2).then(result => { + if (result.response) { + mainWin.webContents.send('show-observation'); + showMainWindow(); + } else { + mainWin.hide(); + }; + }); + } + } else { + mainWin.webContents.send('select-atend-id', null); + } } else { console.error(`Erro na requisição: Status code ${response.statusCode}`, parsedData); - // Lidar com o erro adequadamente, talvez enviando uma mensagem para a janela principal mainWin.webContents.send('api-error', { message: `Erro ao chamar atendimento: ${parsedData.message || 'Erro desconhecido'}` }); @@ -644,7 +649,8 @@ ipcMain.on('chamar-fila', async () => { // Ouve um pedido da janela flutuante para forçar a atualização da contagem ipcMain.on('refresh-count', async () => { if (floatingWin) { - const proximos = JSON.parse(await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')")) ?? []; + const stored = await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')"); + const proximos = JSON.parse(stored || '[]'); floatingWin.webContents.send('update-count', proximos.length); } }); @@ -658,44 +664,33 @@ ipcMain.on('select-atend-id', (itemId) => { ipcMain.on('iniciar-atendimento', async (event, itemId) => { const token = await getAuthToken(); - const colabId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('idOperator')") - //TODO inicia o atendimento o id do atendimento deve ser requisitado do backend - - const url = apiUrl + 'iniciar-atendimento/' + itemId; // URL para enviar a solicitação + const tenantId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('tenantId')") + const url = apiUrl + 'attendance/' + itemId + '/start'; // envio de uma solicitação POST com o ID do item const request = net.request({ - method: 'GET', + method: 'PATCH', url: url, headers: { 'Content-Type': 'application/json', - 'Authorization': 'Bearer ' + token + 'Authorization': 'Bearer ' + token, + 'x-tenant-id': tenantId } }); request.on('response', (response) => { - // console.log(`STATUS: ${response.statusCode}`); - // console.log(`HEADERS: ${JSON.stringify(response.headers)}`); response.on('data', (chunk) => { console.log(`BODY: ${chunk}`); }); response.on('end', () => { console.log('Solicitação concluída.'); - // Avisa a janela principal que a solicitação foi feita (opcional) - // mainWin.webContents.send('request-done', itemId); }); }); request.on('error', (error) => { console.error(`Erro na solicitação: ${error}`); - // Poderia notificar a UI sobre o erro }); - // Envia o ID como corpo da requisição (exemplo) - request.write(JSON.stringify({ id: itemId })); request.end(); - - // Não precisamos esperar a resposta para mudar a UI na janela principal - // A janela principal já mudou a UI ao enviar o evento 'next-step' }); // Ouve quando um atendimento é iniciado e notifica a janela flutuante @@ -715,19 +710,14 @@ ipcMain.on('atendimento-finalizado', () => { // Ouvir clique no botão "Salvar" ipcMain.on('save-observation', async (event, { itemId, observation }) => { - //TODO salva a observação e finaliza o atendimento - console.log(`Salvando observação para item ${itemId}: ${observation}`); const token = await getAuthToken(); - const colabId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('idOperator')") - //TODO inicia o atendimento o id do atendimento deve ser requisitado do backend - - const url = apiUrl + 'finalizar-atendimento/' + itemId; // URL de exemplo para enviar a solicitação + const tenantId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('tenantId')") + const url = apiUrl + 'attendance/' + itemId + '/finish'; const fmData = JSON.stringify({ - "colabId": colabId, - "obsAtendimento": observation + "observation": observation }); @@ -737,7 +727,8 @@ ipcMain.on('save-observation', async (event, { itemId, observation }) => { url: url, headers: { 'Content-Type': 'application/json', - 'Authorization': 'Bearer ' + token + 'Authorization': 'Bearer ' + token, + 'x-tenant-id': tenantId } }); @@ -747,13 +738,10 @@ ipcMain.on('save-observation', async (event, { itemId, observation }) => { }); response.on('end', () => { console.log('Solicitação concluída.'); - // Avisa a janela principal que a solicitação foi feita (opcional) - // mainWin.webContents.send('request-done', itemId); }); }); request.on('error', (error) => { console.error(`Erro na solicitação: ${error}`); - // Poderia notificar a UI sobre o erro }); // Envia o ID como corpo da requisição (exemplo) @@ -763,28 +751,17 @@ ipcMain.on('save-observation', async (event, { itemId, observation }) => { // Opcional: Fechar ou resetar a janela principal após salvar if (mainWin) { - mainWin.hide(); // Ou mainWin.webContents.send('reset-view'); + mainWin.hide(); } }); -// Permite que a janela flutuante seja arrastada -// REMOVA ou comente este listener inteiro: -/* -ipcMain.on('drag-float-window', (event, { offsetX, offsetY }) => { - if (floatingWin) { - const { x, y } = screen.getCursorScreenPoint(); - floatingWin.setPosition(x - offsetX, y - offsetY); - } -}); -*/ - - ipcMain.on('logout', () => { mainWin.webContents.executeJavaScript(` localStorage.removeItem("idOperator"); localStorage.removeItem("selectedOperator"); localStorage.removeItem("salaOperator"); localStorage.removeItem("servicosOperator"); + localStorage.removeItem("tenantId"); `).then(() => { // Fecha a janela main e abre a janela de operador e inicia o aplicativo mainWin.hide(); @@ -797,8 +774,7 @@ ipcMain.on('logout', () => { // Handler para login ipcMain.on('login-attempt', async (event, credentials) => { try { - // Substitua pela URL real da sua API de autenticação - const route = apiUrl + 'login'; + const route = apiUrl + 'auth/login'; const request = net.request({ method: 'POST', @@ -813,19 +789,17 @@ ipcMain.on('login-attempt', async (event, credentials) => { request.on('response', (response) => { response.on('data', (chunk) => { responseData += chunk.toString(); - console.log("Resposta da API:", responseData); // Adiciona este log para ver a resposta crua }); response.on('end', () => { try { const data = JSON.parse(responseData); - - if (data.status === 'Authorized' && data.api_key) { + if (data.access_token) { // Login bem-sucedido loginWin.webContents.executeJavaScript(` - localStorage.setItem("authToken", "${data.api_key}"); - localStorage.setItem("channel", "${data.channel}"); + localStorage.setItem("authToken", "${data.access_token}"); + localStorage.setItem("tenantId", "${data.user.tenantId}"); `).then(() => { // Fecha a janela de login e abre a de seleção de operador event.reply('login-response', { success: true }); @@ -841,7 +815,6 @@ ipcMain.on('login-attempt', async (event, credentials) => { }); } } catch (error) { - console.log("Resposta da API:", error); event.reply('login-response', { success: false, message: 'Erro ao processar resposta do servidor' @@ -858,7 +831,7 @@ ipcMain.on('login-attempt', async (event, credentials) => { }); // Envia as credenciais - request.write(JSON.stringify(credentials)); + request.write(JSON.stringify({ login: credentials.login, password: credentials.password })); request.end(); } catch (error) { event.reply('login-response', { @@ -906,10 +879,7 @@ ipcMain.handle('get-operators', async () => { }; } - // Aqui você pode fazer uma chamada à API para obter os operadores - // Por enquanto, vamos retornar alguns operadores de exemplo - // Substitua pela URL real da sua API de autenticação - const route = apiUrl + 'colabs/list'; + const route = apiUrl + 'collaborators'; return new Promise((resolve, reject) => { const request = net.request({ @@ -926,19 +896,18 @@ ipcMain.handle('get-operators', async () => { request.on('response', (response) => { response.on('data', (chunk) => { responseData += chunk.toString(); - console.log("Resposta da API:", responseData); // Adiciona este log para ver a resposta crua }); response.on('end', () => { try { const data = JSON.parse(responseData); - if (data.colabs) { - const operators = data.colabs.map(colab => ({ - id: colab.id, - name: colab.nome.toUpperCase(), - sala: colab.sala, - servicos: colab.servicos + if (Array.isArray(data)) { + const operators = data.map(colab => ({ + id: colab._id, + name: colab.name.toUpperCase(), + sala: colab.roomId?.name || 'Sala', + servicos: colab.serviceIds?.map(s => s.name).join(',') || '' })); resolve({ @@ -948,12 +917,11 @@ ipcMain.handle('get-operators', async () => { } else { reject({ success: false, - message: data.message || 'Erro ao obter a lista de colaboradores', + message: 'Erro ao obter a lista de colaboradores', operators: [] }); } } catch (error) { - console.log("Erro ao processar resposta da API:", error); reject({ success: false, message: 'Erro ao processar resposta do servidor', @@ -1069,4 +1037,4 @@ ipcMain.on('show-context-menu', (event) => { ]; const menu = Menu.buildFromTemplate(template); menu.popup({ window: floatingWin }); -}); \ No newline at end of file +}); diff --git a/package-lock.json b/package-lock.json index 2df74e0..9564afa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,19 @@ { "name": "autoatendcolab", - "version": "1.0.7", + "version": "1.1.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "autoatendcolab", - "version": "1.0.7", + "version": "1.1.5", "license": "ISC", "dependencies": { "@electron/remote": "^2.1.2", "electron-single-instance": "^0.0.2", "electron-updater": "^6.6.2", - "jquery": "^3.7.1" + "jquery": "^3.7.1", + "socket.io-client": "^4.8.3" }, "devDependencies": { "electron": "^35.2.1", @@ -952,6 +953,12 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -2041,9 +2048,10 @@ } }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -2743,6 +2751,28 @@ "once": "^1.4.0" } }, + "node_modules/engine.io-client": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.4.tgz", + "integrity": "sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.18.3", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -5029,6 +5059,34 @@ "npm": ">= 3.0.0" } }, + "node_modules/socket.io-client": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.3.tgz", + "integrity": "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/socks": { "version": "2.8.4", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", @@ -5734,6 +5792,27 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", @@ -5744,6 +5823,14 @@ "node": ">=8.0" } }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index a1a285e..07c4d22 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "@electron/remote": "^2.1.2", "electron-single-instance": "^0.0.2", "electron-updater": "^6.6.2", - "jquery": "^3.7.1" + "jquery": "^3.7.1", + "socket.io-client": "^4.8.3" }, "devDependencies": { "electron": "^35.2.1", @@ -48,4 +49,4 @@ "electron-reload": "^2.0.0-alpha.1", "nodemon": "^3.1.10" } -} \ No newline at end of file +} diff --git a/renderer.js b/renderer.js index d545fe8..c05d0eb 100644 --- a/renderer.js +++ b/renderer.js @@ -25,61 +25,47 @@ window.electronAPI.onLoadData((data) => { populateList(data[0]); }); -async function initializePusher() { +async function initializeSocket() { if (typeof window.electronAPI === 'undefined' || !window.electronAPI.getPusherConfig) { console.error('electronAPI not available or getPusherConfig method missing.'); return; } - const pusherConfig = await window.electronAPI.getPusherConfig(); - const PUSHER_APP_KEY = pusherConfig.appKey; - let host = pusherConfig.host; + const config = await window.electronAPI.getPusherConfig(); + let host = config.host; - const channelLocal = localStorage.getItem('channel'); - const colabId = localStorage.getItem('idOperator'); + const tenantId = localStorage.getItem('tenantId'); + const token = localStorage.getItem('authToken'); - //! checa se ja tem o colabId - if (channelLocal && colabId && PUSHER_APP_KEY) { - Pusher.logToConsole = true; - - var pusher = new Pusher(PUSHER_APP_KEY, { - wsHost: host, - wsPort: 80, - wssPort: 443, - forceTLS: true, - enableStats: false, - enabledTransports: ['wss', 'ws'], - cluster: 'mt1' + //! checa se ja tem o colabId e o tenantId + if (tenantId && token) { + // Conexão Socket.io adaptada do Pusher + const socket = io(host, { + auth: { token }, + extraHeaders: { 'x-tenant-id': tenantId } }); - let channel; - if (pusher.connection.state === 'connected') { - pusher.unsubscribe('chat.' + channelLocal + '_' + colabId); - } + socket.on('connect', () => { + console.log('Socket.io conectado ao host: ', host); + }); - channel = pusher.subscribe('chat.' + channelLocal + '_' + colabId); - - channel.bind('message-sent', function (r) { - let data = r.data.fila.original; - let count = data.length; - console.log(data); + // Evento que substitui o bind do Pusher + socket.on('queueUpdate', (data) => { + console.log('Atualização de fila recebida:', data); localStorage.setItem('proximos', JSON.stringify(data)); - - populateList(r.data.currentData.original); - + populateList(data); }); - pusher.connection.bind('error', function (err) { - console.error('Pusher connection error: ', err); + socket.on('error', (err) => { + console.error('Socket.io connection error: ', err); }); - console.log('Host de conexão: ', host); } else { - console.warn('User not authenticated or Pusher APP_KEY not available. Private channel not subscribed.'); + console.warn('User not authenticated or tenantId not available. WebSocket not connected.'); } } -initializePusher(); +initializeSocket(); //chama o proximo da fila ao abrir a janela de atendimentos window.electronAPI.selectAtendID((data) => { @@ -93,12 +79,12 @@ window.electronAPI.selectAtendID((data) => { showListView(); // Garante que o item selecionado (ID e Nome) seja o que veio da chamada, sobrescrevendo o da lista. - selectedItemId = data.id ?? null; + selectedItemId = data._id ?? null; selectedItemName = data.clientName ?? ''; //data.senhaGen - queueNumber.innerHTML = data ? `NA VEZ: ${data.clientName.toUpperCase()} - ${data.descricaoServico.toUpperCase()}` : 'Ninguem aguardando atendimento'; - selectedItemNameSpan.innerHTML = data ? ` ${data.clientName.toUpperCase()} [ ${data.senhaGen} ]` : 'Ninguem aguardando atendimento'; + queueNumber.innerHTML = data ? `NA VEZ: ${data.clientName.toUpperCase()}` : 'Ninguem aguardando atendimento'; + selectedItemNameSpan.innerHTML = data ? ` ${data.clientName.toUpperCase()} [ ${data.ticketNumber} ]` : 'Ninguem aguardando atendimento'; }); window.electronAPI.showObservation(() => { @@ -107,7 +93,7 @@ window.electronAPI.showObservation(() => { }); // Função para popular a lista de itens -function populateList(currentData) { +function populateList(proximos) { const atendimentoEmAndamentoId = localStorage.getItem('atendimentoAtual'); const atendimentoEmAndamentoNome = localStorage.getItem('atendimentoAtualNome'); @@ -118,25 +104,27 @@ function populateList(currentData) { return; } - let datastorage = localStorage.getItem('proximos'); + // Se não vier dados por parâmetro, tenta pegar do localStorage (fallback) + if (!Array.isArray(proximos)) { + let datastorage = localStorage.getItem('proximos'); + proximos = JSON.parse(datastorage || '[]'); + } - // Adiciona os outros itens apenas para visualização (opcional) - const proximos = JSON.parse(datastorage); itemList.innerHTML = ''; setTimeout(() => { - nextButton.disabled = !currentData; - }, 5000); + nextButton.disabled = !proximos || proximos.length === 0; + }, 1000); // Seleciona o primeiro item por padrão (ou o próximo disponível) // Aqui, vamos apenas pegar o primeiro da lista atual const itemToProcess = proximos[0]; // Pega o primeiro item if (itemToProcess) { - selectedItemId = itemToProcess.id; + selectedItemId = itemToProcess._id; selectedItemName = itemToProcess.clientName; const li = document.createElement('li'); - li.innerHTML = /*${itemToProcess.senhaGen}: */ `${itemToProcess.clientName.toUpperCase()} - ${itemToProcess.attendanceType.toUpperCase()} - ${itemToProcess.descricaoServico.toUpperCase()}`; - li.dataset.id = itemToProcess.id; // Armazena o ID no elemento + li.innerHTML = /*${itemToProcess.ticketNumber}: */ `${itemToProcess.clientName.toUpperCase()} - ${itemToProcess.ticketNumber}`; + li.dataset.id = itemToProcess._id; // Armazena o ID no elemento li.classList.add('selected'); // Marca como selecionado visualmente (precisa de CSS) itemList.appendChild(li); } else { @@ -149,8 +137,7 @@ function populateList(currentData) { // Adiciona os outros itens apenas para visualização (opcional) proximos.slice(1).forEach(item => { const li = document.createElement('li'); - //${item.senhaGen}: - li.textContent = `${item.clientName.toUpperCase()} - ${item.attendanceType.toUpperCase()} - ${item.descricaoServico.toUpperCase()}`; + li.textContent = `${item.clientName.toUpperCase()} - ${item.ticketNumber}`; itemList.appendChild(li); }); } @@ -223,5 +210,3 @@ saveButton.addEventListener('click', () => { window.location.reload(); } }); - -// Inicialmente, mostra a view da lista (estará vazia até receber dados) diff --git a/res/js/socket.io.min.js b/res/js/socket.io.min.js new file mode 100644 index 0000000..d954aaa --- /dev/null +++ b/res/js/socket.io.min.js @@ -0,0 +1,7 @@ +/*! + * Socket.IO v4.8.3 + * (c) 2014-2025 Guillermo Rauch + * Released under the MIT License. + */ +!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(t="undefined"!=typeof globalThis?globalThis:t||self).io=n()}(this,(function(){"use strict";function t(t,n){(null==n||n>t.length)&&(n=t.length);for(var i=0,r=Array(n);i=n.length?{done:!0}:{done:!1,value:n[e++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,u=!0,h=!1;return{s:function(){r=r.call(n)},n:function(){var t=r.next();return u=t.done,t},e:function(t){h=!0,s=t},f:function(){try{u||null==r.return||r.return()}finally{if(h)throw s}}}}function e(){return e=Object.assign?Object.assign.bind():function(t){for(var n=1;n1?{type:l[i],data:t.substring(1)}:{type:l[i]}:d},N=function(t,n){if(B){var i=function(t){var n,i,r,e,o,s=.75*t.length,u=t.length,h=0;"="===t[t.length-1]&&(s--,"="===t[t.length-2]&&s--);var f=new ArrayBuffer(s),c=new Uint8Array(f);for(n=0;n>4,c[h++]=(15&r)<<4|e>>2,c[h++]=(3&e)<<6|63&o;return f}(t);return C(i,n)}return{base64:!0,data:t}},C=function(t,n){return"blob"===n?t instanceof Blob?t:new Blob([t]):t instanceof ArrayBuffer?t:t.buffer},T=String.fromCharCode(30);function U(){return new TransformStream({transform:function(t,n){!function(t,n){y&&t.data instanceof Blob?t.data.arrayBuffer().then(k).then(n):b&&(t.data instanceof ArrayBuffer||w(t.data))?n(k(t.data)):g(t,!1,(function(t){p||(p=new TextEncoder),n(p.encode(t))}))}(t,(function(i){var r,e=i.length;if(e<126)r=new Uint8Array(1),new DataView(r.buffer).setUint8(0,e);else if(e<65536){r=new Uint8Array(3);var o=new DataView(r.buffer);o.setUint8(0,126),o.setUint16(1,e)}else{r=new Uint8Array(9);var s=new DataView(r.buffer);s.setUint8(0,127),s.setBigUint64(1,BigInt(e))}t.data&&"string"!=typeof t.data&&(r[0]|=128),n.enqueue(r),n.enqueue(i)}))}})}function M(t){return t.reduce((function(t,n){return t+n.length}),0)}function x(t,n){if(t[0].length===n)return t.shift();for(var i=new Uint8Array(n),r=0,e=0;e1?n-1:0),r=1;r1&&void 0!==arguments[1]?arguments[1]:{};return t+"://"+this.i()+this.o()+this.opts.path+this.u(n)},i.i=function(){var t=this.opts.hostname;return-1===t.indexOf(":")?t:"["+t+"]"},i.o=function(){return this.opts.port&&(this.opts.secure&&443!==Number(this.opts.port)||!this.opts.secure&&80!==Number(this.opts.port))?":"+this.opts.port:""},i.u=function(t){var n=function(t){var n="";for(var i in t)t.hasOwnProperty(i)&&(n.length&&(n+="&"),n+=encodeURIComponent(i)+"="+encodeURIComponent(t[i]));return n}(t);return n.length?"?"+n:""},n}(I),X=function(t){function n(){var n;return(n=t.apply(this,arguments)||this).h=!1,n}s(n,t);var r=n.prototype;return r.doOpen=function(){this.v()},r.pause=function(t){var n=this;this.readyState="pausing";var i=function(){n.readyState="paused",t()};if(this.h||!this.writable){var r=0;this.h&&(r++,this.once("pollComplete",(function(){--r||i()}))),this.writable||(r++,this.once("drain",(function(){--r||i()})))}else i()},r.v=function(){this.h=!0,this.doPoll(),this.emitReserved("poll")},r.onData=function(t){var n=this;(function(t,n){for(var i=t.split(T),r=[],e=0;e0&&void 0!==arguments[0]?arguments[0]:{};return e(t,{xd:this.xd},this.opts),new Y(tt,this.uri(),t)},n}(K);function tt(t){var n=t.xdomain;try{if("undefined"!=typeof XMLHttpRequest&&(!n||z))return new XMLHttpRequest}catch(t){}if(!n)try{return new(L[["Active"].concat("Object").join("X")])("Microsoft.XMLHTTP")}catch(t){}}var nt="undefined"!=typeof navigator&&"string"==typeof navigator.product&&"reactnative"===navigator.product.toLowerCase(),it=function(t){function n(){return t.apply(this,arguments)||this}s(n,t);var r=n.prototype;return r.doOpen=function(){var t=this.uri(),n=this.opts.protocols,i=nt?{}:_(this.opts,"agent","perMessageDeflate","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","localAddress","protocolVersion","origin","maxPayload","family","checkServerIdentity");this.opts.extraHeaders&&(i.headers=this.opts.extraHeaders);try{this.ws=this.createSocket(t,n,i)}catch(t){return this.emitReserved("error",t)}this.ws.binaryType=this.socket.binaryType,this.addEventListeners()},r.addEventListeners=function(){var t=this;this.ws.onopen=function(){t.opts.autoUnref&&t.ws.C.unref(),t.onOpen()},this.ws.onclose=function(n){return t.onClose({description:"websocket connection closed",context:n})},this.ws.onmessage=function(n){return t.onData(n.data)},this.ws.onerror=function(n){return t.onError("websocket error",n)}},r.write=function(t){var n=this;this.writable=!1;for(var i=function(){var i=t[r],e=r===t.length-1;g(i,n.supportsBinary,(function(t){try{n.doWrite(i,t)}catch(t){}e&&R((function(){n.writable=!0,n.emitReserved("drain")}),n.setTimeoutFn)}))},r=0;rMath.pow(2,21)-1){u.enqueue(d);break}e=v*Math.pow(2,32)+a.getUint32(4),r=3}else{if(M(i)t){u.enqueue(d);break}}}})}(Number.MAX_SAFE_INTEGER,t.socket.binaryType),r=n.readable.pipeThrough(i).getReader(),e=U();e.readable.pipeTo(n.writable),t.U=e.writable.getWriter();!function n(){r.read().then((function(i){var r=i.done,e=i.value;r||(t.onPacket(e),n())})).catch((function(t){}))}();var o={type:"open"};t.query.sid&&(o.data='{"sid":"'.concat(t.query.sid,'"}')),t.U.write(o).then((function(){return t.onOpen()}))}))}))},r.write=function(t){var n=this;this.writable=!1;for(var i=function(){var i=t[r],e=r===t.length-1;n.U.write(i).then((function(){e&&R((function(){n.writable=!0,n.emitReserved("drain")}),n.setTimeoutFn)}))},r=0;r8e3)throw"URI too long";var n=t,i=t.indexOf("["),r=t.indexOf("]");-1!=i&&-1!=r&&(t=t.substring(0,i)+t.substring(i,r).replace(/:/g,";")+t.substring(r,t.length));for(var e,o,s=ut.exec(t||""),u={},h=14;h--;)u[ht[h]]=s[h]||"";return-1!=i&&-1!=r&&(u.source=n,u.host=u.host.substring(1,u.host.length-1).replace(/;/g,":"),u.authority=u.authority.replace("[","").replace("]","").replace(/;/g,":"),u.ipv6uri=!0),u.pathNames=function(t,n){var i=/\/{2,9}/g,r=n.replace(i,"/").split("/");"/"!=n.slice(0,1)&&0!==n.length||r.splice(0,1);"/"==n.slice(-1)&&r.splice(r.length-1,1);return r}(0,u.path),u.queryKey=(e=u.query,o={},e.replace(/(?:^|&)([^&=]*)=?([^&]*)/g,(function(t,n,i){n&&(o[n]=i)})),o),u}var ct="function"==typeof addEventListener&&"function"==typeof removeEventListener,at=[];ct&&addEventListener("offline",(function(){at.forEach((function(t){return t()}))}),!1);var vt=function(t){function n(n,i){var r;if((r=t.call(this)||this).binaryType="arraybuffer",r.writeBuffer=[],r.M=0,r.I=-1,r.R=-1,r.L=-1,r._=1/0,n&&"object"===c(n)&&(i=n,n=null),n){var o=ft(n);i.hostname=o.host,i.secure="https"===o.protocol||"wss"===o.protocol,i.port=o.port,o.query&&(i.query=o.query)}else i.host&&(i.hostname=ft(i.host).host);return $(r,i),r.secure=null!=i.secure?i.secure:"undefined"!=typeof location&&"https:"===location.protocol,i.hostname&&!i.port&&(i.port=r.secure?"443":"80"),r.hostname=i.hostname||("undefined"!=typeof location?location.hostname:"localhost"),r.port=i.port||("undefined"!=typeof location&&location.port?location.port:r.secure?"443":"80"),r.transports=[],r.D={},i.transports.forEach((function(t){var n=t.prototype.name;r.transports.push(n),r.D[n]=t})),r.opts=e({path:"/engine.io",agent:!1,withCredentials:!1,upgrade:!0,timestampParam:"t",rememberUpgrade:!1,addTrailingSlash:!0,rejectUnauthorized:!0,perMessageDeflate:{threshold:1024},transportOptions:{},closeOnBeforeunload:!1},i),r.opts.path=r.opts.path.replace(/\/$/,"")+(r.opts.addTrailingSlash?"/":""),"string"==typeof r.opts.query&&(r.opts.query=function(t){for(var n={},i=t.split("&"),r=0,e=i.length;r1))return this.writeBuffer;for(var t,n=1,i=0;i=57344?i+=3:(r++,i+=4);return i}(t):Math.ceil(1.33*(t.byteLength||t.size))),i>0&&n>this.L)return this.writeBuffer.slice(0,i);n+=2}return this.writeBuffer},i.W=function(){var t=this;if(!this._)return!0;var n=Date.now()>this._;return n&&(this._=0,R((function(){t.F("ping timeout")}),this.setTimeoutFn)),n},i.write=function(t,n,i){return this.J("message",t,n,i),this},i.send=function(t,n,i){return this.J("message",t,n,i),this},i.J=function(t,n,i,r){if("function"==typeof n&&(r=n,n=void 0),"function"==typeof i&&(r=i,i=null),"closing"!==this.readyState&&"closed"!==this.readyState){(i=i||{}).compress=!1!==i.compress;var e={type:t,data:n,options:i};this.emitReserved("packetCreate",e),this.writeBuffer.push(e),r&&this.once("flush",r),this.flush()}},i.close=function(){var t=this,n=function(){t.F("forced close"),t.transport.close()},i=function i(){t.off("upgrade",i),t.off("upgradeError",i),n()},r=function(){t.once("upgrade",i),t.once("upgradeError",i)};return"opening"!==this.readyState&&"open"!==this.readyState||(this.readyState="closing",this.writeBuffer.length?this.once("drain",(function(){t.upgrading?r():n()})):this.upgrading?r():n()),this},i.B=function(t){if(n.priorWebsocketSuccess=!1,this.opts.tryAllTransports&&this.transports.length>1&&"opening"===this.readyState)return this.transports.shift(),this.q();this.emitReserved("error",t),this.F("transport error",t)},i.F=function(t,n){if("opening"===this.readyState||"open"===this.readyState||"closing"===this.readyState){if(this.clearTimeoutFn(this.Y),this.transport.removeAllListeners("close"),this.transport.close(),this.transport.removeAllListeners(),ct&&(this.P&&removeEventListener("beforeunload",this.P,!1),this.$)){var i=at.indexOf(this.$);-1!==i&&at.splice(i,1)}this.readyState="closed",this.id=null,this.emitReserved("close",t,n),this.writeBuffer=[],this.M=0}},n}(I);vt.protocol=4;var lt=function(t){function n(){var n;return(n=t.apply(this,arguments)||this).Z=[],n}s(n,t);var i=n.prototype;return i.onOpen=function(){if(t.prototype.onOpen.call(this),"open"===this.readyState&&this.opts.upgrade)for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{},r="object"===c(n)?n:i;return(!r.transports||r.transports&&"string"==typeof r.transports[0])&&(r.transports=(r.transports||["polling","websocket","webtransport"]).map((function(t){return st[t]})).filter((function(t){return!!t}))),t.call(this,n,r)||this}return s(n,t),n}(lt);pt.protocol;var dt="function"==typeof ArrayBuffer,yt=function(t){return"function"==typeof ArrayBuffer.isView?ArrayBuffer.isView(t):t.buffer instanceof ArrayBuffer},bt=Object.prototype.toString,wt="function"==typeof Blob||"undefined"!=typeof Blob&&"[object BlobConstructor]"===bt.call(Blob),gt="function"==typeof File||"undefined"!=typeof File&&"[object FileConstructor]"===bt.call(File);function mt(t){return dt&&(t instanceof ArrayBuffer||yt(t))||wt&&t instanceof Blob||gt&&t instanceof File}function kt(t,n){if(!t||"object"!==c(t))return!1;if(Array.isArray(t)){for(var i=0,r=t.length;i=0&&t.num1?e-1:0),s=1;s1?i-1:0),e=1;ei.l.retries&&(i.it.shift(),n&&n(t));else if(i.it.shift(),n){for(var e=arguments.length,o=new Array(e>1?e-1:0),s=1;s0&&void 0!==arguments[0]&&arguments[0];if(this.connected&&0!==this.it.length){var n=this.it[0];n.pending&&!t||(n.pending=!0,n.tryCount++,this.flags=n.flags,this.emit.apply(this,n.args))}},o.packet=function(t){t.nsp=this.nsp,this.io.ct(t)},o.onopen=function(){var t=this;"function"==typeof this.auth?this.auth((function(n){t.vt(n)})):this.vt(this.auth)},o.vt=function(t){this.packet({type:Bt.CONNECT,data:this.lt?e({pid:this.lt,offset:this.dt},t):t})},o.onerror=function(t){this.connected||this.emitReserved("connect_error",t)},o.onclose=function(t,n){this.connected=!1,delete this.id,this.emitReserved("disconnect",t,n),this.yt()},o.yt=function(){var t=this;Object.keys(this.acks).forEach((function(n){if(!t.sendBuffer.some((function(t){return String(t.id)===n}))){var i=t.acks[n];delete t.acks[n],i.withError&&i.call(t,new Error("socket has been disconnected"))}}))},o.onpacket=function(t){if(t.nsp===this.nsp)switch(t.type){case Bt.CONNECT:t.data&&t.data.sid?this.onconnect(t.data.sid,t.data.pid):this.emitReserved("connect_error",new Error("It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)"));break;case Bt.EVENT:case Bt.BINARY_EVENT:this.onevent(t);break;case Bt.ACK:case Bt.BINARY_ACK:this.onack(t);break;case Bt.DISCONNECT:this.ondisconnect();break;case Bt.CONNECT_ERROR:this.destroy();var n=new Error(t.data.message);n.data=t.data.data,this.emitReserved("connect_error",n)}},o.onevent=function(t){var n=t.data||[];null!=t.id&&n.push(this.ack(t.id)),this.connected?this.emitEvent(n):this.receiveBuffer.push(Object.freeze(n))},o.emitEvent=function(n){if(this.bt&&this.bt.length){var i,e=r(this.bt.slice());try{for(e.s();!(i=e.n()).done;){i.value.apply(this,n)}}catch(t){e.e(t)}finally{e.f()}}t.prototype.emit.apply(this,n),this.lt&&n.length&&"string"==typeof n[n.length-1]&&(this.dt=n[n.length-1])},o.ack=function(t){var n=this,i=!1;return function(){if(!i){i=!0;for(var r=arguments.length,e=new Array(r),o=0;o0&&t.jitter<=1?t.jitter:0,this.attempts=0}_t.prototype.duration=function(){var t=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var n=Math.random(),i=Math.floor(n*this.jitter*t);t=1&Math.floor(10*n)?t+i:t-i}return 0|Math.min(t,this.max)},_t.prototype.reset=function(){this.attempts=0},_t.prototype.setMin=function(t){this.ms=t},_t.prototype.setMax=function(t){this.max=t},_t.prototype.setJitter=function(t){this.jitter=t};var Dt=function(t){function n(n,i){var r,e;(r=t.call(this)||this).nsps={},r.subs=[],n&&"object"===c(n)&&(i=n,n=void 0),(i=i||{}).path=i.path||"/socket.io",r.opts=i,$(r,i),r.reconnection(!1!==i.reconnection),r.reconnectionAttempts(i.reconnectionAttempts||1/0),r.reconnectionDelay(i.reconnectionDelay||1e3),r.reconnectionDelayMax(i.reconnectionDelayMax||5e3),r.randomizationFactor(null!==(e=i.randomizationFactor)&&void 0!==e?e:.5),r.backoff=new _t({min:r.reconnectionDelay(),max:r.reconnectionDelayMax(),jitter:r.randomizationFactor()}),r.timeout(null==i.timeout?2e4:i.timeout),r.st="closed",r.uri=n;var o=i.parser||xt;return r.encoder=new o.Encoder,r.decoder=new o.Decoder,r.et=!1!==i.autoConnect,r.et&&r.open(),r}s(n,t);var i=n.prototype;return i.reconnection=function(t){return arguments.length?(this.kt=!!t,t||(this.skipReconnect=!0),this):this.kt},i.reconnectionAttempts=function(t){return void 0===t?this.At:(this.At=t,this)},i.reconnectionDelay=function(t){var n;return void 0===t?this.jt:(this.jt=t,null===(n=this.backoff)||void 0===n||n.setMin(t),this)},i.randomizationFactor=function(t){var n;return void 0===t?this.Et:(this.Et=t,null===(n=this.backoff)||void 0===n||n.setJitter(t),this)},i.reconnectionDelayMax=function(t){var n;return void 0===t?this.Ot:(this.Ot=t,null===(n=this.backoff)||void 0===n||n.setMax(t),this)},i.timeout=function(t){return arguments.length?(this.Bt=t,this):this.Bt},i.maybeReconnectOnOpen=function(){!this.ot&&this.kt&&0===this.backoff.attempts&&this.reconnect()},i.open=function(t){var n=this;if(~this.st.indexOf("open"))return this;this.engine=new pt(this.uri,this.opts);var i=this.engine,r=this;this.st="opening",this.skipReconnect=!1;var e=It(i,"open",(function(){r.onopen(),t&&t()})),o=function(i){n.cleanup(),n.st="closed",n.emitReserved("error",i),t?t(i):n.maybeReconnectOnOpen()},s=It(i,"error",o);if(!1!==this.Bt){var u=this.Bt,h=this.setTimeoutFn((function(){e(),o(new Error("timeout")),i.close()}),u);this.opts.autoUnref&&h.unref(),this.subs.push((function(){n.clearTimeoutFn(h)}))}return this.subs.push(e),this.subs.push(s),this},i.connect=function(t){return this.open(t)},i.onopen=function(){this.cleanup(),this.st="open",this.emitReserved("open");var t=this.engine;this.subs.push(It(t,"ping",this.onping.bind(this)),It(t,"data",this.ondata.bind(this)),It(t,"error",this.onerror.bind(this)),It(t,"close",this.onclose.bind(this)),It(this.decoder,"decoded",this.ondecoded.bind(this)))},i.onping=function(){this.emitReserved("ping")},i.ondata=function(t){try{this.decoder.add(t)}catch(t){this.onclose("parse error",t)}},i.ondecoded=function(t){var n=this;R((function(){n.emitReserved("packet",t)}),this.setTimeoutFn)},i.onerror=function(t){this.emitReserved("error",t)},i.socket=function(t,n){var i=this.nsps[t];return i?this.et&&!i.active&&i.connect():(i=new Lt(this,t,n),this.nsps[t]=i),i},i.wt=function(t){for(var n=0,i=Object.keys(this.nsps);n=this.At)this.backoff.reset(),this.emitReserved("reconnect_failed"),this.ot=!1;else{var i=this.backoff.duration();this.ot=!0;var r=this.setTimeoutFn((function(){n.skipReconnect||(t.emitReserved("reconnect_attempt",n.backoff.attempts),n.skipReconnect||n.open((function(i){i?(n.ot=!1,n.reconnect(),t.emitReserved("reconnect_error",i)):n.onreconnect()})))}),i);this.opts.autoUnref&&r.unref(),this.subs.push((function(){t.clearTimeoutFn(r)}))}},i.onreconnect=function(){var t=this.backoff.attempts;this.ot=!1,this.backoff.reset(),this.emitReserved("reconnect",t)},n}(I),Pt={};function $t(t,n){"object"===c(t)&&(n=t,t=void 0);var i,r=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2?arguments[2]:void 0,r=t;i=i||"undefined"!=typeof location&&location,null==t&&(t=i.protocol+"//"+i.host),"string"==typeof t&&("/"===t.charAt(0)&&(t="/"===t.charAt(1)?i.protocol+t:i.host+t),/^(https?|wss?):\/\//.test(t)||(t=void 0!==i?i.protocol+"//"+t:"https://"+t),r=ft(t)),r.port||(/^(http|ws)$/.test(r.protocol)?r.port="80":/^(http|ws)s$/.test(r.protocol)&&(r.port="443")),r.path=r.path||"/";var e=-1!==r.host.indexOf(":")?"["+r.host+"]":r.host;return r.id=r.protocol+"://"+e+":"+r.port+n,r.href=r.protocol+"://"+e+(i&&i.port===r.port?"":":"+r.port),r}(t,(n=n||{}).path||"/socket.io"),e=r.source,o=r.id,s=r.path,u=Pt[o]&&s in Pt[o].nsps;return n.forceNew||n["force new connection"]||!1===n.multiplex||u?i=new Dt(e,n):(Pt[o]||(Pt[o]=new Dt(e,n)),i=Pt[o]),r.query&&!n.query&&(n.query=r.queryKey),i.socket(r.path,n)}return e($t,{Manager:Dt,Socket:Lt,io:$t,connect:$t}),$t})); +//# sourceMappingURL=socket.io.min.js.map