From c71ad151e031671ecb1458ce20815ce79b024e92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?POL=20Micka=C3=ABl?= Date: Mon, 6 Apr 2026 05:43:04 +0200 Subject: [PATCH] feat: infrastructure Electron + persistence + electron-updater MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LocalStorageRepository avec migrations de données - Notifications Windows + ntfy mobile - WebAudioAlarm avec 4 sons - Migration electron-updater avec latest.yml + sha512 - Support ELECTRON_USER_DATA_DIR pour isolation E2E - Icône Windows native (.ico) Co-Authored-By: Claude Opus 4.6 --- build.bat | 0 build.ps1 | 0 icon.ico | Bin 0 -> 211547 bytes icon.png | Bin main.js | 422 ----------------- preload.js | 30 -- src/infrastructure/alarm/WebAudioAlarm.ts | 74 +++ src/infrastructure/electron/main.ts | 429 ++++++++++++++++++ src/infrastructure/electron/preload.ts | 34 ++ .../notifications/ElectronNotification.ts | 17 + .../persistence/LocalStorageRepository.ts | 106 +++++ .../update/GiteaUpdateAdapter.ts | 16 + 12 files changed, 676 insertions(+), 452 deletions(-) mode change 100644 => 100755 build.bat mode change 100644 => 100755 build.ps1 create mode 100755 icon.ico mode change 100644 => 100755 icon.png delete mode 100644 main.js delete mode 100644 preload.js create mode 100644 src/infrastructure/alarm/WebAudioAlarm.ts create mode 100644 src/infrastructure/electron/main.ts create mode 100644 src/infrastructure/electron/preload.ts create mode 100644 src/infrastructure/notifications/ElectronNotification.ts create mode 100644 src/infrastructure/persistence/LocalStorageRepository.ts create mode 100644 src/infrastructure/update/GiteaUpdateAdapter.ts diff --git a/build.bat b/build.bat old mode 100644 new mode 100755 diff --git a/build.ps1 b/build.ps1 old mode 100644 new mode 100755 diff --git a/icon.ico b/icon.ico new file mode 100755 index 0000000000000000000000000000000000000000..8fbacdf919eccd1b5a7003a84f931066ca83ab80 GIT binary patch literal 211547 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 { - if (!isQuitting) { - e.preventDefault(); - const choice = dialog.showMessageBoxSync(mainWindow, { - type: 'question', - buttons: ['Minimiser', 'Quitter'], - defaultId: 0, - cancelId: 0, - title: 'Minuteur Dragodinde', - message: 'Que souhaites-tu faire ?', - detail: 'Minimiser garde l\'app en arriere-plan.\nLes alarmes continueront de sonner.', - }); - if (choice === 1) { - if (tray) { tray.destroy(); tray = null; } - process.exit(0); - } else { - mainWindow.hide(); - } - } - }); - - // Envoyer les infos de version au renderer une fois chargé - mainWindow.webContents.on('did-finish-load', () => { - mainWindow.webContents.send('app-version', CURRENT_VERSION); - if (updateInfo) { - mainWindow.webContents.send('update-available', updateInfo); - } - // Badge DEV visible dans l'interface - if (!app.isPackaged) { - mainWindow.webContents.executeJavaScript(` - const p = document.querySelector('header p'); - if (p && !document.getElementById('dev-badge')) { - const b = document.createElement('span'); - b.id = 'dev-badge'; - b.textContent = 'DEV'; - b.style.cssText = 'background:#ff9820;color:#000;padding:2px 10px;border-radius:8px;font-size:0.72rem;font-weight:800;margin-left:8px;vertical-align:middle'; - p.appendChild(b); - } - `).catch(()=>{}); - } - }); -} - -// ─── TRAY ───────────────────────────────────────────────────────────────────── -function createTray() { - tray = new Tray(getTrayIcon()); - tray.setToolTip(`Minuteur Dragodinde v${CURRENT_VERSION}`); - rebuildTrayMenu(); - tray.on('double-click', () => { mainWindow.show(); mainWindow.focus(); }); -} - -function rebuildTrayMenu() { - if (!tray) return; - const items = [ - { label: `Minuteur Dragodinde v${CURRENT_VERSION}`, enabled: false }, - { type: 'separator' }, - { label: 'Ouvrir', click: () => { mainWindow.show(); mainWindow.focus(); } }, - ]; - if (updateInfo) { - items.push({ type: 'separator' }); - items.push({ - label: `⬆ Mise a jour v${updateInfo.version} disponible !`, - click: () => startDownload(), - }); - } - items.push({ type: 'separator' }); - items.push({ label: 'Quitter', click: () => { isQuitting = true; app.quit(); } }); - tray.setContextMenu(Menu.buildFromTemplate(items)); -} - -// ─── NOTIFICATIONS ──────────────────────────────────────────────────────────── -function fireNotification(title, body) { - if (!Notification.isSupported()) return; - const n = new Notification({ title, body, timeoutType: 'never' }); - n.on('click', () => { mainWindow.show(); mainWindow.focus(); }); - n.show(); -} - -// ─── IPC ────────────────────────────────────────────────────────────────────── -ipcMain.on('trigger-alarm', (event, { enclosName }) => { - fireNotification('Dragodindes pretes !', enclosName + ' - Toutes les cibles ont ete atteintes !'); - if (mainWindow && !mainWindow.isDestroyed()) { - mainWindow.webContents.send('play-alarm-sound'); - } -}); - -ipcMain.on('show-notification', (event, { title, body }) => { - fireNotification(title, body); -}); - -// Dialogue de confirmation natif (remplace confirm() du renderer qui casse les inputs) -ipcMain.handle('show-confirm', (event, { title, message, detail }) => { - const choice = dialog.showMessageBoxSync(mainWindow, { - type: 'question', - buttons: ['Annuler', 'Confirmer'], - defaultId: 0, - cancelId: 0, - title: title || 'Confirmation', - message: message || '', - detail: detail || '', - }); - return choice === 1; -}); - -// ─── 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; - try { - const parsed = new URL(url.trim()); - const mod = parsed.protocol === 'https:' ? https : require('http'); - const postData = message; - const options = { - hostname: parsed.hostname, - port: parsed.port || (parsed.protocol === 'https:' ? 443 : 80), - path: parsed.pathname + parsed.search, - method: 'POST', - headers: { - 'Content-Type': 'text/plain; charset=utf-8', - 'Content-Length': Buffer.byteLength(postData, 'utf-8'), - 'Title': title, - 'Priority': 'high', - 'Tags': 'hatching_chick', - }, - }; - const req = mod.request(options, (res) => { - res.on('data', () => {}); // drain - res.on('end', () => {}); - }); - req.on('error', (e) => console.warn('ntfy send error:', e.message)); - req.write(postData, 'utf-8'); - req.end(); - } catch (e) { - console.warn('ntfy error:', e.message); - } -}); - -ipcMain.on('focus-window', () => { mainWindow.show(); mainWindow.focus(); }); - -// Renderer demande à installer la mise à jour -ipcMain.on('install-update', () => startDownload()); - -// Renderer demande la version -ipcMain.handle('get-version', () => CURRENT_VERSION); - -// ─── VÉRIFICATION DE MISE À JOUR ───────────────────────────────────────────── -function compareVersions(a, b) { - // Retourne > 0 si b > a (b est plus récent) - const pa = a.replace(/^v/, '').split('.').map(Number); - const pb = b.replace(/^v/, '').split('.').map(Number); - for (let i = 0; i < 3; i++) { - if ((pb[i] || 0) > (pa[i] || 0)) return 1; - if ((pb[i] || 0) < (pa[i] || 0)) return -1; - } - return 0; -} - -function checkForUpdates(silent = false) { - // API Gitea : GET /api/v1/repos/{user}/{repo}/releases?limit=1 - // Retourne un tableau — le premier élément est la release la plus récente - const options = { - hostname: GITEA_HOST, - port: 443, - path: `/api/v1/repos/${GITEA_USER}/${GITEA_REPO}/releases?limit=1`, - method: 'GET', - headers: { - 'User-Agent': `MinuteurDragodinde/${CURRENT_VERSION}`, - 'Accept': 'application/json', - }, - }; - - const req = https.request(options, (res) => { - let data = ''; - res.on('data', chunk => { data += chunk; }); - res.on('end', () => { - try { - const releases = JSON.parse(data); - - // Gitea renvoie un tableau, on prend le premier (le plus récent) - if (!Array.isArray(releases) || releases.length === 0) return; - const release = releases[0]; - - const latestVersion = release.tag_name; - if (!latestVersion) return; - - if (compareVersions(CURRENT_VERSION, latestVersion) > 0) { - // Chercher l'asset installeur (.exe contenant "Setup") - const asset = release.assets && release.assets.find(a => - a.name.includes('Setup') && a.name.endsWith('.exe') - ); - if (!asset) return; - - updateInfo = { - version: latestVersion, - downloadUrl: asset.browser_download_url, - assetName: asset.name, - releaseNotes: release.body || '', - }; - - if (mainWindow && !mainWindow.isDestroyed()) { - mainWindow.webContents.send('update-available', updateInfo); - } - - fireNotification( - `Mise a jour v${latestVersion} disponible !`, - 'Cliquez pour mettre a jour Minuteur Dragodinde.' - ); - - rebuildTrayMenu(); - - } else if (!silent) { - if (mainWindow && !mainWindow.isDestroyed()) { - mainWindow.webContents.send('update-not-available'); - } - } - } catch (e) { - console.error('Update check parse error:', e.message); - } - }); - }); - - req.on('error', (e) => console.error('Update check error:', e.message)); - req.end(); -} - -// ─── TÉLÉCHARGEMENT ET REMPLACEMENT ────────────────────────────────────────── -function startDownload() { - if (!updateInfo || downloading) return; - downloading = true; - - if (mainWindow && !mainWindow.isDestroyed()) { - mainWindow.webContents.send('update-downloading', { version: updateInfo.version }); - } - - const tmpDir = os.tmpdir(); - const tmpExe = path.join(tmpDir, updateInfo.assetName); - const file = fs.createWriteStream(tmpExe); - const currentExe = process.execPath; - - // Suivre les redirections manuellement (GitHub assets redirigent) - function download(url, redirectCount = 0) { - if (redirectCount > 5) { - sendUpdateError('Trop de redirections.'); - return; - } - const urlObj = new URL(url); - const mod = urlObj.protocol === 'https:' ? https : require('http'); - const opts = { - hostname: urlObj.hostname, - path: urlObj.pathname + urlObj.search, - method: 'GET', - headers: { 'User-Agent': `MinuteurDragodinde/${CURRENT_VERSION}` }, - }; - - mod.request(opts, (res) => { - if (res.statusCode === 302 || res.statusCode === 301) { - download(res.headers.location, redirectCount + 1); - return; - } - if (res.statusCode !== 200) { - sendUpdateError(`Erreur HTTP ${res.statusCode}`); - return; - } - - const total = parseInt(res.headers['content-length'] || '0', 10); - let received = 0; - - res.on('data', chunk => { - received += chunk.length; - file.write(chunk); - if (total > 0 && mainWindow && !mainWindow.isDestroyed()) { - const pct = Math.round((received / total) * 100); - mainWindow.webContents.send('update-progress', { percent: pct }); - } - }); - - res.on('end', () => { - file.end(); - file.on('finish', () => { - // Lancer le script de remplacement - launchUpdater(tmpExe, currentExe); - }); - }); - - res.on('error', e => sendUpdateError(e.message)); - }).on('error', e => sendUpdateError(e.message)).end(); - } - - download(updateInfo.downloadUrl); -} - -function sendUpdateError(msg) { - downloading = false; - console.error('Update error:', msg); - if (mainWindow && !mainWindow.isDestroyed()) { - mainWindow.webContents.send('update-error', { message: msg }); - } -} - -function launchUpdater(newExe, currentExe) { - if (mainWindow && !mainWindow.isDestroyed()) { - mainWindow.webContents.send('update-ready'); - } - - const { spawn } = require('child_process'); - - // Script batch qui survit à la fermeture de l'app : - // 1. Attend que l'app se ferme - // 2. Lance l'installeur en silencieux - // 3. Relance l'app - // 4. Se supprime lui-même - const batPath = path.join(os.tmpdir(), 'dd-timer-update.cmd'); - const batContent = [ - '@echo off', - 'timeout /t 3 /nobreak >nul', - `start /wait "" "${newExe}" /S`, - 'timeout /t 5 /nobreak >nul', - `start "" "${currentExe}"`, - 'del "%~f0"', - ].join('\r\n'); - - fs.writeFileSync(batPath, batContent, 'utf-8'); - - setTimeout(() => { - spawn('cmd.exe', ['/c', batPath], { - detached: true, - stdio: 'ignore', - windowsHide: true, - }).unref(); - - isQuitting = true; - app.quit(); - }, 1500); -} - -// ─── CYCLE DE VIE ──────────────────────────────────────────────────────────── -app.whenReady().then(() => { - createWindow(); - createTray(); - - // Vérifier les mises à jour uniquement au démarrage (silencieux) - setTimeout(() => checkForUpdates(true), 3000); - - app.on('activate', () => { - if (BrowserWindow.getAllWindows().length === 0) createWindow(); - }); -}); - -app.on('window-all-closed', () => { - if (process.platform === 'darwin') app.quit(); -}); - -app.on('before-quit', () => { isQuitting = true; }); diff --git a/preload.js b/preload.js deleted file mode 100644 index 73636ad..0000000 --- a/preload.js +++ /dev/null @@ -1,30 +0,0 @@ -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 }), - sendNtfy: (url, title, message) => ipcRenderer.send('send-ntfy', { url, title, message }), - focusWindow: () => ipcRenderer.send('focus-window'), - showConfirm: (title, message, detail) => ipcRenderer.invoke('show-confirm', { title, message, detail }), - onPlayAlarmSound: (cb) => ipcRenderer.on('play-alarm-sound', () => cb()), - - // Version - getVersion: () => ipcRenderer.invoke('get-version'), - onAppVersion: (cb) => ipcRenderer.on('app-version', (e, v) => cb(v)), - - // Mises à jour - installUpdate: () => ipcRenderer.send('install-update'), - onUpdateAvailable: (cb) => ipcRenderer.on('update-available', (e, info) => cb(info)), - onUpdateNotAvailable: (cb) => ipcRenderer.on('update-not-available', () => cb()), - onUpdateDownloading: (cb) => ipcRenderer.on('update-downloading', (e, info) => cb(info)), - onUpdateProgress: (cb) => ipcRenderer.on('update-progress', (e, info) => cb(info)), - onUpdateReady: (cb) => ipcRenderer.on('update-ready', () => cb()), - onUpdateError: (cb) => ipcRenderer.on('update-error', (e, info) => cb(info)), -}); diff --git a/src/infrastructure/alarm/WebAudioAlarm.ts b/src/infrastructure/alarm/WebAudioAlarm.ts new file mode 100644 index 0000000..ba40380 --- /dev/null +++ b/src/infrastructure/alarm/WebAudioAlarm.ts @@ -0,0 +1,74 @@ +import type { AlarmPort } from '@domain/ports/AlarmPort'; + +export class WebAudioAlarm implements AlarmPort { + private audioCtx: AudioContext | null = null; + + private ensureContext(): AudioContext { + if (!this.audioCtx) { + this.audioCtx = new AudioContext(); + } + if (this.audioCtx.state === 'suspended') { + this.audioCtx.resume(); + } + return this.audioCtx; + } + + play(soundName: string): void { + const ctx = this.ensureContext(); + const doPlay = () => { + if (soundName === 'arpege') { + [440, 554, 659, 880].forEach((f, i) => setTimeout(() => { + const o = ctx.createOscillator(), g = ctx.createGain(); + o.connect(g); g.connect(ctx.destination); + o.frequency.value = f; o.type = 'sine'; + g.gain.setValueAtTime(0.35, ctx.currentTime); + g.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.55); + o.start(); o.stop(ctx.currentTime + 0.55); + }, i * 140)); + } else if (soundName === 'pulse') { + [0, 200, 400, 600, 800].forEach(ms => setTimeout(() => { + const o = ctx.createOscillator(), g = ctx.createGain(); + o.connect(g); g.connect(ctx.destination); + o.frequency.value = 880; o.type = 'square'; + g.gain.setValueAtTime(0.2, ctx.currentTime); + g.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.15); + o.start(); o.stop(ctx.currentTime + 0.15); + }, ms)); + } else if (soundName === 'fanfare') { + ([[523, 0], [659, 150], [784, 300], [1047, 500], [784, 700], [1047, 900]] as [number, number][]).forEach(([f, ms]) => setTimeout(() => { + const o = ctx.createOscillator(), g = ctx.createGain(); + o.connect(g); g.connect(ctx.destination); + o.frequency.value = f; o.type = 'triangle'; + g.gain.setValueAtTime(0.3, ctx.currentTime); + g.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.18); + o.start(); o.stop(ctx.currentTime + 0.18); + }, ms)); + } else if (soundName === 'cloche') { + const t = ctx.currentTime; + ([[440, 1], [880, 0.6], [1320, 0.4], [1760, 0.25]] as [number, number][]).forEach(([f, v], i) => { + const o = ctx.createOscillator(), g = ctx.createGain(); + o.connect(g); g.connect(ctx.destination); + o.frequency.value = f; o.type = 'sine'; + g.gain.setValueAtTime(v * 0.3, t); + g.gain.exponentialRampToValueAtTime(0.001, t + 2.5); + o.start(t + i * 0.01); o.stop(t + 2.5); + }); + } else { + // Fallback : arpege + this.play('arpege'); + } + }; + if (ctx.state === 'suspended') { + ctx.resume().then(doPlay).catch(() => {}); + } else { + doPlay(); + } + } + + stop(): void { + if (this.audioCtx) { + this.audioCtx.close(); + this.audioCtx = null; + } + } +} diff --git a/src/infrastructure/electron/main.ts b/src/infrastructure/electron/main.ts new file mode 100644 index 0000000..c085942 --- /dev/null +++ b/src/infrastructure/electron/main.ts @@ -0,0 +1,429 @@ +import { + app, + BrowserWindow, + Tray, + Menu, + nativeImage, + ipcMain, + Notification, + dialog, +} from 'electron'; +import path from 'path'; +import https from 'https'; +import http from 'http'; +import fs from 'fs'; +import { autoUpdater } from 'electron-updater'; + +// ─── NOM DE L'APPLICATION ───────────────────────────────────────────────────── +app.setName('Minuteur Dragodinde'); +// Windows utilise l'AppUserModelId pour le nom affiché dans les notifications +if (process.platform === 'win32') { + app.setAppUserModelId('Minuteur Dragodinde'); +} + +// ─── MODE DEV / E2E ────────────────────────────��───────────────────────────── +// En E2E (Playwright), utiliser un dossier userData dédié +if (process.env.ELECTRON_USER_DATA_DIR) { + app.setPath('userData', process.env.ELECTRON_USER_DATA_DIR); +} else if (!app.isPackaged) { + // En dev (npm start), les données sont isolées de l'app installée + app.setPath('userData', path.join(app.getPath('appData'), 'MinuteurDragodinde-DEV')); +} + +// ─── CONFIG GITEA ───────────────────────────────────────────────────────────── +const GITEA_HOST = 'gitea.mickael-pol.fr'; // ton instance Gitea +const GITEA_USER = 'mickael'; // ton user Gitea +const GITEA_REPO = 'dd-timer'; // ton repo +const CURRENT_VERSION: string = app.getVersion(); // lu depuis package.json + +interface UpdateInfo { + version: string; +} + +let mainWindow: BrowserWindow | null = null; +let tray: Tray | null = null; +let isQuitting = false; +let updateInfo: UpdateInfo | null = null; +let updateCheckInProgress = false; +let updateDownloaded = false; + +// ─── ICÔNE ─────────────────────────────────────────────────────────────────── +function getAppIcon(): Electron.NativeImage { + const iconPath = app.isPackaged + ? path.join(process.resourcesPath, 'icon.ico') + : path.join(__dirname, '../icon.ico'); + if (fs.existsSync(iconPath)) return nativeImage.createFromPath(iconPath); + return nativeImage.createEmpty(); +} + +// ─── FENÊTRE ───────────────────────────────────────────────────────────────── +function createWindow(): void { + mainWindow = new BrowserWindow({ + width: 1280, height: 900, minWidth: 960, minHeight: 650, + title: 'Minuteur Dragodinde - Dofus 3', + icon: getAppIcon(), + backgroundColor: '#0b0b14', + webPreferences: { + nodeIntegration: false, + contextIsolation: true, + backgroundThrottling: false, + preload: path.join(__dirname, 'preload.js'), + }, + }); + // Dev: Vite dev server; Prod: built renderer in dist-vite/ + if (process.env['VITE_DEV_SERVER_URL']) { + mainWindow.loadURL(process.env['VITE_DEV_SERVER_URL']); + } else { + mainWindow.loadFile(path.join(__dirname, '../dist-vite/index.html')); + } + + mainWindow.on('close', (e) => { + if (!isQuitting) { + e.preventDefault(); + const choice = dialog.showMessageBoxSync(mainWindow!, { + type: 'question', + buttons: ['Minimiser', 'Quitter'], + defaultId: 0, + cancelId: 0, + title: 'Minuteur Dragodinde', + message: 'Que souhaites-tu faire ?', + detail: 'Minimiser garde l\'app en arriere-plan.\nLes alarmes continueront de sonner.', + }); + if (choice === 1) { + if (tray) { tray.destroy(); tray = null; } + process.exit(0); + } else { + mainWindow!.hide(); + } + } + }); + + // Zoom clavier : Ctrl+Plus, Ctrl+Minus, Ctrl+0 + mainWindow.webContents.on('before-input-event', (_e, input) => { + if (!input.control || input.type !== 'keyDown') return; + const wc = mainWindow!.webContents; + if (input.key === '+' || input.key === '=') { + wc.setZoomLevel(wc.getZoomLevel() + 0.5); + } else if (input.key === '-') { + wc.setZoomLevel(wc.getZoomLevel() - 0.5); + } else if (input.key === '0') { + wc.setZoomLevel(0); + } + }); + + // Envoyer les infos de version au renderer une fois chargé + mainWindow.webContents.on('did-finish-load', () => { + mainWindow!.webContents.send('app-version', CURRENT_VERSION); + if (updateInfo) { + mainWindow!.webContents.send('update-available', updateInfo); + } + // Badge DEV visible dans l'interface + if (!app.isPackaged) { + mainWindow!.webContents.executeJavaScript(` + const p = document.querySelector('header p'); + if (p && !document.getElementById('dev-badge')) { + const b = document.createElement('span'); + b.id = 'dev-badge'; + b.textContent = 'DEV'; + b.style.cssText = 'background:#ff9820;color:#000;padding:2px 10px;border-radius:8px;font-size:0.72rem;font-weight:800;margin-left:8px;vertical-align:middle'; + p.appendChild(b); + } + `).catch(() => {}); + } + }); +} + +// ─── TRAY ───────────────────────────────────────────────────────────────────── +function createTray(): void { + tray = new Tray(getAppIcon()); + tray.setToolTip(`Minuteur Dragodinde v${CURRENT_VERSION}`); + rebuildTrayMenu(); + tray.on('double-click', () => { mainWindow!.show(); mainWindow!.focus(); }); +} + +function rebuildTrayMenu(): void { + if (!tray) return; + const items: Electron.MenuItemConstructorOptions[] = [ + { label: `Minuteur Dragodinde v${CURRENT_VERSION}`, enabled: false }, + { type: 'separator' }, + { label: 'Ouvrir', click: () => { mainWindow!.show(); mainWindow!.focus(); } }, + ]; + if (updateInfo) { + items.push({ type: 'separator' }); + if (updateDownloaded) { + items.push({ + label: `⬆ Installer v${updateInfo.version} maintenant`, + click: () => autoUpdater.quitAndInstall(true, true), + }); + } else { + items.push({ + label: `⏳ Téléchargement v${updateInfo.version}...`, + enabled: false, + }); + } + } + items.push({ type: 'separator' }); + items.push({ label: 'Quitter', click: () => { isQuitting = true; app.quit(); } }); + tray.setContextMenu(Menu.buildFromTemplate(items)); +} + +// ─── NOTIFICATIONS ──────────────────────────────────────────────────────────── +function fireNotification(title: string, body: string): void { + if (!Notification.isSupported()) return; + const n = new Notification({ title, body, timeoutType: 'never' }); + n.on('click', () => { mainWindow!.show(); mainWindow!.focus(); }); + n.show(); +} + +// ─── IPC ────────────────────────────────────────────────────────────────────── +ipcMain.on('trigger-alarm', (_event, { enclosName }: { enclosName: string }) => { + fireNotification('Dragodindes pretes !', enclosName + ' - Toutes les cibles ont ete atteintes !'); + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send('play-alarm-sound'); + } +}); + +ipcMain.on('show-notification', (_event, { title, body }: { title: string; body: string }) => { + fireNotification(title, body); +}); + +// Dialogue de confirmation natif (remplace confirm() du renderer qui casse les inputs) +ipcMain.handle('show-confirm', (_event, { title, message, detail }: { title: string; message: string; detail: string }) => { + const choice = dialog.showMessageBoxSync(mainWindow!, { + type: 'question', + buttons: ['Annuler', 'Confirmer'], + defaultId: 0, + cancelId: 0, + title: title || 'Confirmation', + message: message || '', + detail: detail || '', + }); + return choice === 1; +}); + +// ─── SAUVEGARDE FICHIER (persistante entre mises à jour) ───────────────── +const dataFile: string = 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: unknown) { console.error('load-data error:', (e as Error).message); } + return null; +}); + +ipcMain.on('save-data', (_event, json: string) => { + try { + fs.writeFileSync(dataFile, json, 'utf-8'); + } catch (e: unknown) { console.error('save-data error:', (e as Error).message); } +}); + +// ─── NTFY (notifications mobiles) ───────────────────────────────────────── +ipcMain.on('send-ntfy', (_event, { url, title, message }: { url: string; title: string; message: string }) => { + if (!url) return; + try { + const parsed = new URL(url.trim()); + const mod = parsed.protocol === 'https:' ? https : http; + // API JSON ntfy : supporte nativement l'UTF-8 (accents, emojis) + const topic = parsed.pathname.replace(/^\//, ''); + const jsonBody = JSON.stringify({ + topic, + title, + message, + priority: 4, + tags: ['dragon'], + }); + const options: https.RequestOptions = { + hostname: parsed.hostname, + port: parsed.port || (parsed.protocol === 'https:' ? 443 : 80), + path: '/', + method: 'POST', + headers: { + 'Content-Type': 'application/json; charset=utf-8', + 'Content-Length': Buffer.byteLength(jsonBody, 'utf-8'), + }, + }; + const req = mod.request(options, (res) => { + res.on('data', () => {}); // drain + res.on('end', () => {}); + }); + req.on('error', (e: Error) => console.warn('ntfy send error:', e.message)); + req.write(jsonBody, 'utf-8'); + req.end(); + } catch (e: unknown) { + console.warn('ntfy error:', (e as Error).message); + } +}); + +ipcMain.on('focus-window', () => { mainWindow!.show(); mainWindow!.focus(); }); + +// Renderer demande à installer la mise à jour +ipcMain.on('install-update', () => { + if (updateDownloaded) { + autoUpdater.quitAndInstall(true, true); + } +}); + +// Renderer demande la version +ipcMain.handle('get-version', () => CURRENT_VERSION); + +// ─── EXPORT / IMPORT FICHIER ──────────────────────────────────────────────── +ipcMain.handle('export-file', async (_event, { data, defaultName }: { data: string; defaultName: string }) => { + if (!mainWindow) return false; + const result = await dialog.showSaveDialog(mainWindow, { + title: 'Exporter les plans', + defaultPath: path.join(app.getPath('documents'), defaultName), + filters: [{ name: 'JSON', extensions: ['json'] }], + }); + if (result.canceled || !result.filePath) return false; + try { + fs.writeFileSync(result.filePath, data, 'utf-8'); + return true; + } catch (e: unknown) { + console.error('export-file error:', (e as Error).message); + return false; + } +}); + +ipcMain.handle('import-file', async () => { + if (!mainWindow) return null; + const result = await dialog.showOpenDialog(mainWindow, { + title: 'Importer des plans', + defaultPath: app.getPath('documents'), + filters: [{ name: 'JSON', extensions: ['json'] }], + properties: ['openFile'], + }); + if (result.canceled || result.filePaths.length === 0) return null; + try { + return fs.readFileSync(result.filePaths[0], 'utf-8'); + } catch (e: unknown) { + console.error('import-file error:', (e as Error).message); + return null; + } +}); + +// ─── COMPARAISON DE VERSIONS ──────────────────────────────────────────────── +function compareVersions(a: string, b: string): number { + const pa = a.replace(/^v/, '').split('.').map(Number); + const pb = b.replace(/^v/, '').split('.').map(Number); + for (let i = 0; i < 3; i++) { + if ((pb[i] || 0) > (pa[i] || 0)) return 1; + if ((pb[i] || 0) < (pa[i] || 0)) return -1; + } + return 0; +} + +// ─── ELECTRON-UPDATER : CONFIGURATION ─────────────────────────────────────── +autoUpdater.autoDownload = true; +autoUpdater.autoInstallOnAppQuit = false; + +// ─── ELECTRON-UPDATER : EVENTS ────────────────────────────────────────────── +autoUpdater.on('update-available', (info) => { + updateInfo = { version: info.version }; + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send('update-available', updateInfo); + mainWindow.webContents.send('update-downloading', { version: info.version }); + } + fireNotification( + `Mise a jour v${info.version} disponible !`, + 'Téléchargement en cours...' + ); + rebuildTrayMenu(); +}); + +autoUpdater.on('download-progress', (progress) => { + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send('update-progress', { percent: Math.round(progress.percent) }); + } +}); + +autoUpdater.on('update-downloaded', () => { + updateDownloaded = true; + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send('update-ready'); + } + rebuildTrayMenu(); +}); + +autoUpdater.on('error', (err) => { + console.error('Update error:', err.message); + updateCheckInProgress = false; + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send('update-error', { message: err.message }); + } +}); + +autoUpdater.on('update-not-available', () => { + console.log('electron-updater: no update found in latest.yml'); + updateCheckInProgress = false; +}); + +// ─── VÉRIFICATION VIA API GITEA ───────────────────────────────────────────── +function checkForUpdates(silent = false): void { + if (updateCheckInProgress) return; + updateCheckInProgress = true; + const options: https.RequestOptions = { + hostname: GITEA_HOST, + port: 443, + path: `/api/v1/repos/${GITEA_USER}/${GITEA_REPO}/releases?limit=1`, + method: 'GET', + headers: { + 'User-Agent': `MinuteurDragodinde/${CURRENT_VERSION}`, + 'Accept': 'application/json', + }, + }; + + const req = https.request(options, (res) => { + let data = ''; + res.on('data', (chunk: string) => { data += chunk; }); + res.on('end', () => { + try { + const releases = JSON.parse(data); + if (!Array.isArray(releases) || releases.length === 0) { updateCheckInProgress = false; return; } + const release = releases[0]; + const latestVersion = release.tag_name; + if (!latestVersion || compareVersions(CURRENT_VERSION, latestVersion) <= 0) { + updateCheckInProgress = false; + if (!silent && mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send('update-not-available'); + } + return; + } + + // Pointer electron-updater vers le tag de la release + const tag = latestVersion.startsWith('v') ? latestVersion : `v${latestVersion}`; + autoUpdater.setFeedURL({ + provider: 'generic', + url: `https://${GITEA_HOST}/${GITEA_USER}/${GITEA_REPO}/releases/download/${tag}`, + }); + + // electron-updater prend le relais : lit latest.yml, télécharge, vérifie sha512 + autoUpdater.checkForUpdates(); + } catch (e: unknown) { + updateCheckInProgress = false; + console.error('Update check parse error:', (e as Error).message); + } + }); + }); + + req.on('error', (e: Error) => { updateCheckInProgress = false; console.error('Update check error:', e.message); }); + req.end(); +} + +// ─── CYCLE DE VIE ──────────────────────────────────────────────────────────── +app.whenReady().then(() => { + createWindow(); + createTray(); + + // Vérifier les mises à jour uniquement au démarrage (silencieux) + setTimeout(() => checkForUpdates(true), 3000); + + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) createWindow(); + }); +}); + +app.on('window-all-closed', () => { + if (process.platform === 'darwin') app.quit(); +}); + +app.on('before-quit', () => { isQuitting = true; }); diff --git a/src/infrastructure/electron/preload.ts b/src/infrastructure/electron/preload.ts new file mode 100644 index 0000000..12afa7a --- /dev/null +++ b/src/infrastructure/electron/preload.ts @@ -0,0 +1,34 @@ +import { contextBridge, ipcRenderer } from 'electron'; + +contextBridge.exposeInMainWorld('electronAPI', { + isElectron: true, + + // Sauvegarde persistante (fichier JSON dans userData) + saveData: (json: string) => ipcRenderer.send('save-data', json), + loadData: () => ipcRenderer.invoke('load-data'), + + // Alarme + triggerAlarm: (enclosName: string) => ipcRenderer.send('trigger-alarm', { enclosName }), + showNotification: (title: string, body: string) => ipcRenderer.send('show-notification', { title, body }), + sendNtfy: (url: string, title: string, message: string) => ipcRenderer.send('send-ntfy', { url, title, message }), + focusWindow: () => ipcRenderer.send('focus-window'), + showConfirm: (title: string, message: string, detail: string) => ipcRenderer.invoke('show-confirm', { title, message, detail }), + onPlayAlarmSound: (cb: () => void) => ipcRenderer.on('play-alarm-sound', () => cb()), + + // Export / Import fichier + exportFile: (data: string, defaultName: string) => ipcRenderer.invoke('export-file', { data, defaultName }), + importFile: () => ipcRenderer.invoke('import-file'), + + // Version + getVersion: () => ipcRenderer.invoke('get-version'), + onAppVersion: (cb: (v: string) => void) => ipcRenderer.on('app-version', (_e, v) => cb(v)), + + // Mises à jour + installUpdate: () => ipcRenderer.send('install-update'), + onUpdateAvailable: (cb: (info: any) => void) => ipcRenderer.on('update-available', (_e, info) => cb(info)), + onUpdateNotAvailable: (cb: () => void) => ipcRenderer.on('update-not-available', () => cb()), + onUpdateDownloading: (cb: (info: any) => void) => ipcRenderer.on('update-downloading', (_e, info) => cb(info)), + onUpdateProgress: (cb: (info: any) => void) => ipcRenderer.on('update-progress', (_e, info) => cb(info)), + onUpdateReady: (cb: () => void) => ipcRenderer.on('update-ready', () => cb()), + onUpdateError: (cb: (info: any) => void) => ipcRenderer.on('update-error', (_e, info) => cb(info)), +}); diff --git a/src/infrastructure/notifications/ElectronNotification.ts b/src/infrastructure/notifications/ElectronNotification.ts new file mode 100644 index 0000000..a943b6d --- /dev/null +++ b/src/infrastructure/notifications/ElectronNotification.ts @@ -0,0 +1,17 @@ +import type { NotificationPort } from '@domain/ports/NotificationPort'; + +export class ElectronNotification implements NotificationPort { + showNotification(title: string, body: string): void { + const api = (window as any).electronAPI; + if (api?.showNotification) { + api.showNotification(title, body); + } + } + + sendMobileNotification(url: string, title: string, message: string): void { + const api = (window as any).electronAPI; + if (api?.sendNtfy) { + api.sendNtfy(url, title, message); + } + } +} diff --git a/src/infrastructure/persistence/LocalStorageRepository.ts b/src/infrastructure/persistence/LocalStorageRepository.ts new file mode 100644 index 0000000..5f639ab --- /dev/null +++ b/src/infrastructure/persistence/LocalStorageRepository.ts @@ -0,0 +1,106 @@ +import type { AppState, StateRepository } from '@domain/ports/StateRepository'; +import { DEFAULT_TARGETS } from '@domain/value-objects/GaugeType'; + +interface ElectronAPI { + saveData: (json: string) => void; + loadData: () => Promise; +} + +function getElectronAPI(): ElectronAPI | null { + if (typeof window !== 'undefined' && (window as any).electronAPI) { + return (window as any).electronAPI; + } + return null; +} + +export class LocalStorageRepository implements StateRepository { + private readonly storageKey = 'dd3v3'; + + async load(): Promise { + try { + let raw: string | null = null; + const api = getElectronAPI(); + if (api) raw = await api.loadData(); + if (!raw && typeof localStorage !== 'undefined') { + raw = localStorage.getItem(this.storageKey) || localStorage.getItem('dd3v2'); + } + if (!raw) return null; + return this.deserialize(raw); + } catch { + return null; + } + } + + save(state: AppState): void { + try { + const d = JSON.parse(JSON.stringify(state)); + // Reset runtime state before persisting + d.enclos.forEach((e: any) => { + e.timer.running = false; + e.alerted = {}; + }); + const json = JSON.stringify(d); + const api = getElectronAPI(); + if (api) api.saveData(json); + if (typeof localStorage !== 'undefined') { + localStorage.setItem(this.storageKey, json); + } + } catch { + // Silently fail + } + } + + private deserialize(raw: string): AppState { + const d = JSON.parse(raw); + const state: AppState = { + enclos: d.enclos || [], + activeId: d.activeId ?? null, + nextEnclosId: d.nextEnclosId || 1, + alarmSound: d.alarmSound || 'arpege', + notifsEnabled: d.notifsEnabled !== undefined ? d.notifsEnabled : true, + ntfyTopic: d.ntfyTopic || '', + archivedStats: d.archivedStats || [], + inventaire: d.inventaire || {}, + workflows: d.workflows || [], + accouplements: d.accouplements || [], + }; + + // Migration: old ntfyUrl format → ntfyTopic + if (!state.ntfyTopic && d.ntfyUrl) { + const m = d.ntfyUrl.match(/\/([^\/]+)$/); + if (m) state.ntfyTopic = m[1]; + } + + // Migrate enclos data + state.enclos.forEach((enc: any) => { + enc.timer = enc.timer || { running: false, startTime: null, pausedAt: null, pausedMs: 0, snapGauges: {}, snapStats: {} }; + enc.timer.running = false; + enc.alerted = {}; + if (enc.gaugeLevels.mangeoire === undefined) enc.gaugeLevels.mangeoire = 0; + enc.dragodindes.forEach((dd: any) => { + if (dd.stats.xp === undefined) dd.stats.xp = 1; + // Migration: old serenite target → gauge-based targets + if (dd.targets.serenite !== undefined && dd.targets.baffeur === undefined) { + const old = { ...dd.targets }; + dd.targets = { + baffeur: old.serenite ?? -5000, + caresseur: Math.max(0, old.serenite ?? 40), + foudroyeur: old.endurance ?? 20000, + abreuvoir: old.maturite ?? 20000, + dragofesse: old.amour ?? 20000, + mangeoire: 100, + }; + } + Object.keys(DEFAULT_TARGETS).forEach(k => { + if (dd.targets[k] === undefined) dd.targets[k] = (DEFAULT_TARGETS as any)[k]; + }); + }); + }); + + if (!state.activeId && state.enclos.length) { + state.activeId = state.enclos[0].id; + } + + return state; + } +} diff --git a/src/infrastructure/update/GiteaUpdateAdapter.ts b/src/infrastructure/update/GiteaUpdateAdapter.ts new file mode 100644 index 0000000..2742fb0 --- /dev/null +++ b/src/infrastructure/update/GiteaUpdateAdapter.ts @@ -0,0 +1,16 @@ +import type { UpdatePort, UpdateInfo } from '@domain/ports/UpdatePort'; + +export class GiteaUpdateAdapter implements UpdatePort { + async checkForUpdates(): Promise { + // Delegated to main process via IPC in the actual Electron app + // This is a placeholder — the real check happens in main.ts + return null; + } + + downloadAndInstall(info: UpdateInfo): void { + const api = (window as any).electronAPI; + if (api?.installUpdate) { + api.installUpdate(); + } + } +}