diff --git a/README.md b/README.md index 98c98a8..8cbe006 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,10 @@ dd-timer/ ## Changelog +### v1.1.2 +- πŸ’Ύ **Sauvegarde persistante** β€” les donnees sont maintenant sauvegardees dans un fichier JSON, plus de perte de statistiques apres une mise a jour +- ❌ **Dialogue de fermeture** β€” cliquer sur la croix propose de minimiser en arriere-plan ou de quitter completement + ### v1.1.1 - πŸ”§ Correction de la mise a jour automatique β€” l'app se relance maintenant toute seule apres installation - πŸ”§ Correction de l'affichage du titre des notifications ntfy (encodage base64 supprime) diff --git a/main.js b/main.js index 9274f30..1567983 100644 --- a/main.js +++ b/main.js @@ -55,12 +55,21 @@ function createWindow() { mainWindow.on('close', (e) => { if (!isQuitting) { e.preventDefault(); - mainWindow.hide(); - if (tray) tray.displayBalloon({ - iconType: 'info', + const choice = dialog.showMessageBoxSync(mainWindow, { + type: 'question', + buttons: ['Minimiser', 'Quitter'], + defaultId: 0, + cancelId: 0, title: 'Minuteur Dragodinde', - content: "Tourne en arriere-plan. Les alarmes sonneront normalement.", + message: 'Que souhaites-tu faire ?', + detail: 'Minimiser garde l\'app en arriere-plan.\nLes alarmes continueront de sonner.', }); + if (choice === 1) { + isQuitting = true; + app.quit(); + } else { + mainWindow.hide(); + } } }); @@ -133,6 +142,22 @@ ipcMain.on('show-notification', (event, { title, body }) => { fireNotification(title, body); }); +// ─── SAUVEGARDE FICHIER (persistante entre mises Γ  jour) ───────────────── +const dataFile = path.join(app.getPath('userData'), 'dd-timer-data.json'); + +ipcMain.handle('load-data', () => { + try { + if (fs.existsSync(dataFile)) return fs.readFileSync(dataFile, 'utf-8'); + } catch (e) { console.error('load-data error:', e.message); } + return null; +}); + +ipcMain.on('save-data', (event, json) => { + try { + fs.writeFileSync(dataFile, json, 'utf-8'); + } catch (e) { console.error('save-data error:', e.message); } +}); + // ─── NTFY (notifications mobiles) ───────────────────────────────────────── ipcMain.on('send-ntfy', (event, { url, title, message }) => { if (!url) return; @@ -343,8 +368,8 @@ function launchUpdater(newExe, currentExe) { const batContent = [ '@echo off', 'timeout /t 3 /nobreak >nul', - `"${newExe}" /S`, - 'timeout /t 2 /nobreak >nul', + `start /wait "" "${newExe}" /S`, + 'timeout /t 5 /nobreak >nul', `start "" "${currentExe}"`, 'del "%~f0"', ].join('\r\n'); diff --git a/package.json b/package.json index 675558b..75ec18f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "minuteur-dragodinde", - "version": "1.1.1", + "version": "1.1.2", "description": "Minuteur elevage Dragodinde Dofus 3", "main": "main.js", "author": "Mickael", diff --git a/preload.js b/preload.js index 16402a8..6549239 100644 --- a/preload.js +++ b/preload.js @@ -3,6 +3,10 @@ const { contextBridge, ipcRenderer } = require('electron'); contextBridge.exposeInMainWorld('electronAPI', { isElectron: true, + // Sauvegarde persistante (fichier JSON dans userData) + saveData: (json) => ipcRenderer.send('save-data', json), + loadData: () => ipcRenderer.invoke('load-data'), + // Alarme triggerAlarm: (enclosName) => ipcRenderer.send('trigger-alarm', { enclosName }), showNotification: (title, body) => ipcRenderer.send('show-notification', { title, body }), diff --git a/src/index.html b/src/index.html index b326d80..a172bfe 100644 --- a/src/index.html +++ b/src/index.html @@ -1052,12 +1052,18 @@ function save(){ try{ const d=JSON.parse(JSON.stringify(S)); d.enclos.forEach(e=>{e.timer.running=false;e.alerted={};}); - localStorage.setItem('dd3v3',JSON.stringify(d)); + const json=JSON.stringify(d); + // Sauvegarde fichier (persistante) + localStorage (fallback) + if(window.electronAPI?.saveData) window.electronAPI.saveData(json); + localStorage.setItem('dd3v3',json); }catch(e){} } -function load(){ +async function load(){ try{ - const raw=localStorage.getItem('dd3v3')||localStorage.getItem('dd3v2'); + // PrioritΓ© : fichier persistant > localStorage + let raw=null; + if(window.electronAPI?.loadData) raw=await window.electronAPI.loadData(); + if(!raw) raw=localStorage.getItem('dd3v3')||localStorage.getItem('dd3v2'); if(!raw)return; const d=JSON.parse(raw); S.enclos=d.enclos||[];S.activeId=d.activeId;S.nextEnclosId=d.nextEnclosId||1; @@ -2262,12 +2268,14 @@ if(window.electronAPI?.isElectron){ // ══════════════════════════════════════════ // INIT // ══════════════════════════════════════════ -load(); -if(!S.enclos.length){const e=makeEnclos(S.nextEnclosId++);S.enclos.push(e);S.activeId=e.id;} -notifGranted=typeof Notification!=='undefined'&&Notification.permission==='granted'; -render(); -if(activeEnclos()?.dragodindes.length===0)addDD(S.activeId); -requestAnimationFrame(loop); +(async()=>{ + await load(); + if(!S.enclos.length){const e=makeEnclos(S.nextEnclosId++);S.enclos.push(e);S.activeId=e.id;} + notifGranted=typeof Notification!=='undefined'&&Notification.permission==='granted'; + render(); + if(activeEnclos()?.dragodindes.length===0)addDD(S.activeId); + requestAnimationFrame(loop); +})();