Files
PTT-Live/DESKTOP-APP.md
T
benoit 955bfdfe07 feat: activer boutons Groupes et ajouter export logs/config desktop
- Onglet Groupes : boutons Modifier et Supprimer fonctionnels via délégation
  d'événements et data-attributes ; slugify() côté client synchronisé avec
  le serveur ; classe CSS btn-danger pour Supprimer
- Export logs : bouton "Exporter JSON" dans l'onglet Logs (filtre niveau actif)
- Export/Import config.yaml : section dédiée dans Configuration avec dialog
  système (backup automatique .bak avant import) via IPC Electron
  (config:export / config:import dans main.js + preload.js)
2026-07-01 13:21:59 +02:00

439 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PTT Live - Application Desktop Server
Application Electron pour gérer le serveur PTT Live avec interface graphique complète.
## 📸 Aperçu
L'application desktop intègre :
-**Dashboard temps réel** : stats, utilisateurs, QR Code (généré côté Main Process, sans dépendance CDN)
-**HTTPS automatique** : certificats locaux mkcert installés au premier lancement
-**Configuration audio** : sélection devices, sample rate, bitrate
-**Gestion groupes** : CRUD complet avec API
-**Monitoring** : VU-mètres temps réel via WebSocket, logs filtrables
-**Contrôle serveur** : démarrage manuel/arrêt avec feedback visuel
---
## 🚀 Démarrage Rapide
```bash
# Depuis la racine du projet
./start-desktop.sh
# OU manuellement
cd electron
npm start
```
Au premier lancement, l'app configure automatiquement les certificats HTTPS locaux (mkcert) — voir [HTTPS et certificats](#-https-et-certificats). Le serveur PTT Live **ne démarre pas automatiquement** : cliquez sur "Démarrer" dans le dashboard pour le lancer.
---
## 📦 Installation
Les dépendances sont déjà installées. Si nécessaire :
```bash
cd electron
npm install
```
---
## 🎯 Utilisation
### 1. Dashboard
**Stats temps réel** :
- Uptime serveur
- Nombre d'utilisateurs connectés
- Groupes actifs
- Total connexions
**QR Code** :
- Généré côté Main Process (lib `qrcode`, pas de CDN externe — fonctionne sans accès Internet sur le WiFi d'un événement)
- IP réseau détectée par le Main Process (même logique que pour les certificats mkcert)
- URL construite à partir du protocole/port réels du serveur (HTTPS par défaut)
- Scanner depuis smartphone pour connexion rapide
- Bouton copier URL
- Placeholder visuel tant que le serveur est arrêté ou qu'aucun QR code n'a été généré
**Utilisateurs** :
- Liste en temps réel
- Groupe de chaque utilisateur
- Heure de connexion
### 2. Configuration Audio
**Périphériques** :
- Sélection input/output depuis dropdown auto-détecté
- Support macOS (CoreAudio), Linux (JACK/PipeWire)
- Appliquer instantanément (bridge audio rechargé)
**Paramètres** :
- Sample Rate : 44.1 / 48 / 96 kHz
- Bitrate par défaut : 32-320 kbps
- Jitter Buffer : 20-100 ms
### 3. Gestion Groupes
- **Créer** : bouton " Nouveau groupe"
- **Modifier** : depuis la liste (nom, bitrate)
- **Supprimer** : confirmation requise
- Sauvegardé automatiquement dans `config.yaml`
### 4. Monitoring
**VU-Mètres** :
- Niveaux audio par canal (input/output) et par groupe
- Temps réel via WebSocket (`/audio-levels`, même port que l'API)
- Reconnexion automatique si la connexion WebSocket tombe
### 5. Logs
- Logs serveur en temps réel
- Filtrage par niveau (error/warn/info/debug)
- Bouton "Effacer"
- Format timestamp + niveau + message
---
## 🏗️ Architecture Technique
```
┌─────────────────────────────────────────────────┐
│ ELECTRON APP (Desktop) │
│ │
│ ┌───────────────────────────────────────────┐ │
│ │ MAIN PROCESS (Node.js) │ │
│ │ │ │
│ │ • spawn server/index.js │ │
│ │ • IPC handlers (start/stop/status) │ │
│ │ • Tray icon (macOS/Linux) │ │
│ │ • Logs forwarding → Renderer │ │
│ └───────────────────────────────────────────┘ │
│ ↕ IPC │
│ ┌───────────────────────────────────────────┐ │
│ │ RENDERER PROCESS (Frontend) │ │
│ │ │ │
│ │ • HTML/CSS/JS (pas de framework) │ │
│ │ • Fetch API REST :3000/admin/* │ │
│ │ • WebSocket audio levels (live) │ │
│ │ • QR Code (data URL via IPC) │ │
│ └───────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
↕ HTTPS (127.0.0.1, certs mkcert)
┌─────────────────────────────────────────────────┐
│ SERVEUR PTT LIVE (spawned) │
│ │
│ • LiveKit Server (binaire Go) :7880 │
│ • Audio Bridge Manager │
│ • API REST Express :3000 (HTTPS) │
│ • Proxy HTTP + WS → LiveKit (/livekit/*) │
│ • WebSocket Audio Levels (/audio-levels) │
└─────────────────────────────────────────────────┘
```
Le proxy `/livekit/*` (http-proxy natif) permet aux clients de joindre LiveKit via le même port/certificat HTTPS que l'API, sans exposer le port 7880 séparément. Le serveur Express dispatch lui-même les événements `upgrade` (un seul listener) entre le proxy LiveKit et le WebSocket audio-levels, qui partagent le même port.
---
## 🔌 API Consommées
L'interface desktop utilise toutes les routes admin existantes :
| Endpoint | Méthode | Usage |
|----------|---------|-------|
| `/admin/stats` | GET | Dashboard metrics |
| `/admin/users` | GET | Liste utilisateurs |
| `/admin/groups` | GET | Liste groupes |
| `/admin/groups` | POST | Créer groupe |
| `/admin/groups/:id` | PUT | Modifier groupe |
| `/admin/groups/:id` | DELETE | Supprimer groupe |
| `/admin/config` | GET | Config complète |
| `/admin/config/audio` | PUT | Mettre à jour audio |
| `/admin/audio/devices` | GET | Énumérer devices |
| `/admin/audio/device` | POST | Sélectionner device |
| `/admin/devices/list` | GET | Auto-détection (macOS/Linux) |
| `/admin/logs` | GET | Logs serveur |
| `/health` | GET | Health check |
| `/livekit/*` | ALL | Proxy HTTP vers LiveKit Server (port 7880) |
WebSocket :
- `wss://127.0.0.1:3000/audio-levels` → VU-mètres temps réel
- `wss://127.0.0.1:3000/livekit/*` → Proxy WebSocket signaling LiveKit (clients PWA)
---
## 🔒 HTTPS et certificats
L'app est en HTTPS par défaut (`ENABLE_HTTPS=false` pour revenir en HTTP explicitement).
### Setup automatique (premier lancement)
Au premier démarrage, si `certs/localhost.pem` et `certs/localhost-key.pem` sont absents, `electron/setup-helper.js` :
1. Installe `mkcert` automatiquement (Homebrew sur macOS, téléchargement direct sur Linux)
2. Installe la CA locale (`mkcert -install`) dans le trousseau système
3. Détecte l'IP réseau et génère les certificats pour `localhost`, `127.0.0.1` et cette IP
4. Affiche des dialogs de progression/erreur (avec fallback manuel `./setup-certificates.sh`)
### Points d'attention
- **127.0.0.1, pas localhost** : le serveur écoute en IPv4 (`host: 0.0.0.0`), mais le Node embarqué par Electron peut résoudre `localhost` en IPv6 (`::1`) en priorité. `main.js` et `preload.js` utilisent donc `127.0.0.1` pour tous les appels internes (ping, health check) afin d'éviter des échecs silencieux.
- **Ping interne et `rejectUnauthorized`** : le module `https` de Node ne lit pas le trousseau système où mkcert installe sa CA (contrairement à Safari/Chrome/Electron renderer) ; `pingServer()` passe donc `rejectUnauthorized: false` pour son propre ping local.
- **Proxy LiveKit en HTTPS** : LiveKit Server local tourne en HTTP brut (port 7880) ; le proxy Express (`http-proxy`) fait le pont HTTPS ↔ HTTP côté clients.
---
## 📦 Build pour Distribution
### macOS
```bash
cd electron
npm run build:mac
```
Génère :
- `dist/mac/PTT Live Server.app`
- `dist/PTT Live Server-0.3.0.dmg`
### Linux
```bash
cd electron
npm run build:linux
```
Génère :
- `dist/PTT Live Server-0.3.0.deb`
- `dist/PTT Live Server-0.3.0.AppImage`
### Tester le build
```bash
# macOS
open dist/mac/PTT\ Live\ Server.app
# Linux
./dist/PTT\ Live\ Server-0.3.0.AppImage
```
---
## 🎨 Personnalisation
### Icônes
Placer les icônes dans `electron/assets/` :
```
electron/assets/
├── icon.icns # macOS (512x512 minimum)
├── icon.png # Linux (512x512)
└── tray-icon.png # Tray 22x22 ou 44x44 (retina)
```
Générer icônes depuis PNG :
```bash
# macOS .icns
iconutil -c icns assets/icon.iconset
# Linux .png
convert icon.png -resize 512x512 assets/icon.png
```
### Thème
Modifier `electron/ui/styles.css` :
```css
:root {
--bg-primary: #1a1a1a;
--accent-primary: #4a9eff;
/* ... */
}
```
---
## 🐛 Debug
### DevTools
Ouvrir automatiquement en mode dev :
```bash
cd electron
npm run dev
```
Ou manuellement dans `main.js` :
```javascript
mainWindow.webContents.openDevTools();
```
### Logs Console
**Main Process** :
```javascript
console.log('[Main]', ...); // Terminal qui a lancé npm start
```
**Renderer Process** :
```javascript
console.log('[Renderer]', ...); // DevTools → Console
```
**Serveur PTT Live** :
```javascript
// Transmis au Renderer via IPC
window.electronAPI.server.onLog((log) => {
console.log('[Serveur]', log);
});
```
### Erreurs courantes
**Port 3000 déjà utilisé** :
```bash
# Tuer le process
lsof -i :3000
kill -9 <PID>
# OU changer de port
PORT=3001 npm start
```
**Serveur ne démarre pas** :
- Vérifier que `server/index.js` existe
- Vérifier permissions LiveKit binaire
- Voir logs dans DevTools console
**Certificats SSL manquants / setup mkcert échoue** :
- Exécuter manuellement : `./setup-certificates.sh`
- Ou installer mkcert : https://github.com/FiloSottile/mkcert puis `mkcert -install`
- Vérifier la présence de `certs/localhost.pem` et `certs/localhost-key.pem`
**Statut serveur affiché à tort comme "arrêté"** :
- Vérifier que le ping utilise bien `127.0.0.1` (pas `localhost`, qui peut résoudre en IPv6 alors que le serveur n'écoute qu'en IPv4)
- En HTTPS, le ping interne ignore volontairement les erreurs de certificat (`rejectUnauthorized: false`) puisque Node ne lit pas le trousseau système où mkcert installe sa CA
**QR Code ne s'affiche pas** :
- Vérifier que le serveur tourne (le QR code est réinitialisé tant qu'il est arrêté)
- Le QR code est généré côté Main Process (IPC `qrcode:generate`), pas de dépendance réseau/CDN
---
## 🚧 TODO / Améliorations
### Priorité haute
- [x] **WebSocket VU-mètres** : implémenter connexion `/audio-levels`
- [ ] **Vraies icônes** : icns/png pour macOS/Linux
- [ ] **Tray icon** : avec menu contextuel fonctionnel
### Priorité moyenne
- [ ] **Graphiques monitoring** : Chart.js pour latence/bande passante
- [x] **Export logs** : bouton télécharger JSON (filtre niveau appliqué)
- [ ] **Matrice routing** : interface graphique drag & drop
- [x] **Export & import config** : bouton télécharger YAML et charger config (backup auto .bak)
### Priorité basse
- [ ] **Thème toggle** : dark/light mode
- [ ] **Auto-update** : electron-updater pour mises à jour
### Technique
- [ ] **Tests** : Spectron ou Playwright pour Electron
- [ ] **CI/CD** : GitHub Actions pour builds automatiques
- [ ] **Signature code** : macOS notarization + Linux AppImage signature
---
## 📝 Notes de Développement
### Structure Fichiers
```
electron/
├── main.js # Main Process
│ # - Spawn serveur
│ # - IPC handlers
│ # - Window management
│ # - Setup SSL au premier lancement
├── preload.js # IPC Bridge sécurisé
│ # - contextBridge
│ # - Expose electronAPI
├── setup-helper.js # Installation auto mkcert + génération certificats
│ # - Détection IP réseau
├── package.json # Config Electron + electron-builder
└── ui/ # Renderer Process (Frontend)
├── index.html # Structure UI
├── styles.css # Styles (dark theme)
└── app.js # Logic frontend (QR code reçu via IPC en data URL)
```
### Communication IPC
**Renderer → Main** :
```javascript
// Depuis ui/app.js
const result = await window.electronAPI.server.start();
```
**Main → Renderer** :
```javascript
// Depuis main.js
mainWindow.webContents.send('server:status', { running: true });
// Écouté dans ui/app.js
window.electronAPI.server.onStatus((data) => {
console.log('Status:', data);
});
```
### Sécurité
-**contextIsolation: true** : isole Node.js du renderer
-**nodeIntegration: false** : pas d'accès Node direct
-**preload.js** : whitelist API exposées via contextBridge
- ⚠️ **CSP manquant** : ajouter Content-Security-Policy en prod
---
## 🤝 Contribution
L'app desktop est modulaire et extensible :
1. **Ajouter une vue** : créer `<div id="view-xxx">` dans `index.html`
2. **Ajouter un handler IPC** : `ipcMain.handle()` dans `main.js`
3. **Exposer au renderer** : `contextBridge.exposeInMainWorld()` dans `preload.js`
4. **Appeler l'API** : fetch dans `ui/app.js`
---
## 📚 Ressources
- **Electron Docs** : https://www.electronjs.org/docs
- **electron-builder** : https://www.electron.build
- **LiveKit Server API** : https://docs.livekit.io
- **QR Code.js** : https://github.com/soldair/node-qrcode
---
## 📄 Licence
Même licence que PTT Live (MIT)
---
**Version** : 0.3.0
**Dernière mise à jour** : 2026-06-30