From ff3b4e593420c85930f9a7809eb56a84033df084 Mon Sep 17 00:00:00 2001 From: VPS 4 Builder Date: Sun, 31 May 2026 05:12:07 +0200 Subject: [PATCH] =?UTF-8?q?fix(client):=20notifica=C3=A7=C3=A3o=20Wasabi?= =?UTF-8?q?=20+=20ordem=20de=20envio=20mais=20recente=20primeiro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Item 2 — Notificação de erro do Wasabi: - client-monitor.js: notifyWasabiError() envia evento IPC 'wasabi-error' ao processo Electron em dois cenários: falha no Direct Upload e Wasabi indisponível no servidor. Throttle de 60s para não inundar o usuário. - index.js: trata 'wasabi-error' no handler IPC do monitorProcess e exibe tray.displayBalloon com iconType 'error'. Item 5 — Ordem de envio (mais novas primeiro): - executarSincronizacaoLocal: após filtrar imagens, ordena por mtime DESC antes de enfileirar — dentista recebe primeiro as imagens do atendimento atual em vez de receber em ordem arbitrária do filesystem. Co-Authored-By: Claude Sonnet 4.6 --- client-monitor.js | 21 ++++++++++++++++++++- index.js | 8 ++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/client-monitor.js b/client-monitor.js index 52e13c9..f31fae9 100644 --- a/client-monitor.js +++ b/client-monitor.js @@ -1157,7 +1157,13 @@ async function executarSincronizacaoLocal() { try { const arquivos = fs.readdirSync(pastaImagensSensor); - const imagens = arquivos.filter(file => /\.(png|jpg|jpeg)$/i.test(file)); + // Ordenar da mais recente para a mais antiga (mtime DESC) para que o + // dentista receba primeiro as imagens do atendimento atual. + const imagens = arquivos + .filter(file => /\.(png|jpg|jpeg)$/i.test(file)) + .map(file => ({ file, mtime: fs.statSync(path.join(pastaImagensSensor, file)).mtime.getTime() })) + .sort((a, b) => b.mtime - a.mtime) + .map(({ file }) => file); addLog(`🔎 Encontradas ${imagens.length} imagens locais no total. Verificando pendências com o servidor...`); let processadas = 0; @@ -1301,6 +1307,17 @@ function lookupPatientInfo(fileName) { return null; } +// Notifica o processo Electron (index.js) de erro no Wasabi via IPC. +// Throttle de 60s para não inundar o usuário num backlog grande. +let lastWasabiErrorNotifyAt = 0; +function notifyWasabiError(message) { + if (!process.send) return; + const now = Date.now(); + if (now - lastWasabiErrorNotifyAt < 60000) return; + lastWasabiErrorNotifyAt = now; + process.send({ event: 'wasabi-error', message }); +} + // Enviar imagem para o servidor via Socket.IO e aguardar confirmação function sendImageToServer(filePath, isBacklog, bypassCache = false) { return new Promise(async (resolve, reject) => { @@ -1440,10 +1457,12 @@ function sendImageToServer(filePath, isBacklog, bypassCache = false) { } catch (uploadErr) { addLog(`❌ Falha no Direct Upload: ${uploadErr.message}. Tentando via VPS...`); + notifyWasabiError(`Falha no upload direto ao Wasabi: ${uploadErr.message}. Usando envio via VPS como alternativa.`); fallbackUpload(); } } else { addLog(`ℹ️ Wasabi não disponível no servidor. Usando envio padrão via VPS.`); + notifyWasabiError(`Wasabi indisponível no servidor. Imagens sendo enviadas via VPS (mais lento).`); fallbackUpload(); } }); diff --git a/index.js b/index.js index e89a7ed..449eb73 100644 --- a/index.js +++ b/index.js @@ -341,6 +341,14 @@ function startMonitorProcess() { } catch (e) { monitorProcess.send({ event: 'resize-result', id: message.id, success: false, error: e.message }); } + } else if (message && message.event === 'wasabi-error') { + if (tray) { + tray.displayBalloon({ + title: 'ScoreOdonto — Falha no Armazenamento', + content: message.message || 'Erro ao comunicar com o Wasabi.', + iconType: 'error' + }); + } } });