Files
jardin/docs/ameliorations-2026-03-22.md
2026-03-22 12:51:31 +01:00

128 lines
5.3 KiB
Markdown

# Jardin App — Améliorations récentes
> Date : **2026-03-22**
---
## 1. Conversion HEIC → PNG automatique à l'upload
**Problème :** Les photos prises avec un iPhone sont au format HEIC, non reconnu par les navigateurs web.
**Solution :** Lors de tout upload de média (route `POST /api/media/upload`), le backend détecte automatiquement le format HEIC/HEIF et le convertit en WEBP avant stockage.
**Fichiers modifiés :**
- `backend/app/routers/media.py` — détection par magic bytes + conversion via `pillow-heif`
- `backend/requirements.txt` — ajout de `pillow-heif`
- `frontend/src/views/*` — inputs file acceptent désormais `.heic,.HEIC`
**Comportement :**
- Fichier `.heic` reçu → converti en WEBP (même qualité que les autres imports)
- Miniature 300 px générée normalement
- Nom de fichier stocké en `.webp` dans la base de données
---
## 2. Redimensionnement des images de la bibliothèque
**Contexte :** Le paramètre "Largeur max des photos" dans Réglages s'appliquait uniquement aux nouvelles photos. Les photos déjà importées restaient à leur taille d'origine.
**Ajout :** Un bouton **"Appliquer à la bibliothèque"** dans la section Images des Réglages permet de redimensionner rétroactivement toutes les photos existantes.
**Règle appliquée :** Si la largeur d'une photo est **inférieure ou égale** au paramètre configuré, elle n'est **pas modifiée** (pas d'agrandissement).
**Fichiers modifiés :**
- `backend/app/routers/settings.py` — endpoint `POST /api/settings/images/resize-all`
- `frontend/src/api/settings.ts` — méthode `resizeAllImages()`
- `frontend/src/views/ReglagesView.vue` — bouton + feedback avec stats (redimensionnées / ignorées / erreurs)
**Endpoint retourne :**
```json
{ "ok": true, "redimensionnees": 42, "ignorees": 128, "erreurs": 0 }
```
---
## 3. Sauvegarde Samba (backup réseau)
**Contexte :** La sauvegarde ZIP existante ne proposait qu'un téléchargement local.
**Ajout :** Section **"Sauvegarde Samba"** dans les Réglages permettant d'envoyer automatiquement la sauvegarde vers un partage réseau Windows/NAS.
**Paramètres configurables :**
| Champ | Exemple |
|-------|---------|
| Adresse IP / nom du serveur | `192.168.1.10` ou `nas.local` |
| Partage | `Sauvegardes` |
| Sous-dossier | `jardin/backups` |
| Utilisateur | `gilles` |
| Mot de passe | *(masqué)* |
**Fichiers modifiés :**
- `backend/app/routers/settings.py` — endpoint `POST /api/settings/backup/samba` (génère le ZIP, copie via `smbclient` ou `pysmb`)
- `backend/app/models/user_settings.py` — clés `samba_*` persistées en base
- `frontend/src/api/settings.ts` — méthodes `getSambaSettings()`, `saveSambaSettings()`, `backupToSamba()`
- `frontend/src/views/ReglagesView.vue` — formulaire Samba + bouton "Envoyer la sauvegarde" + feedback
---
## 4. Restauration de sauvegarde
**Contexte :** Il était possible de créer un backup ZIP mais pas de le restaurer depuis l'interface.
**Ajout :** Bouton **"Restaurer une sauvegarde"** dans la section Sauvegarde des Réglages.
**Deux modes de restauration :**
| Mode | Comportement |
|------|-------------|
| **Écraser tout** (toggle activé, rouge) | Remplace la BDD entière + écrase tous les fichiers uploads |
| **Ajouter uniquement** (toggle désactivé, jaune) | Insère les lignes absentes (`INSERT OR IGNORE`) + copie uniquement les fichiers manquants |
**Sécurité :**
- Confirmation obligatoire avec `window.confirm()` décrivant le mode sélectionné
- Message d'avertissement "irréversible" affiché avant action
**Technique (mode écraser) :**
1. `engine.dispose()` — libère les connexions SQLAlchemy
2. `PRAGMA wal_checkpoint(TRUNCATE)` — vide le WAL SQLite
3. Copie directe du fichier `.db` depuis le ZIP
**Technique (mode ajouter) :**
- `sqlite3` natif — `INSERT OR IGNORE` table par table depuis la BDD du ZIP
- `foreign_keys=OFF` pendant la fusion pour éviter les conflits de contraintes
**Fichiers modifiés :**
- `backend/app/routers/settings.py` — helper `_merge_db_add_only()` + endpoint `POST /api/settings/backup/restore`
- `frontend/src/api/settings.ts` — méthode `restoreBackup(file, overwrite)`
- `frontend/src/views/ReglagesView.vue` — sélecteur ZIP + toggle mode + bouton ♻️ + feedback coloré
**Endpoint retourne :**
```json
{
"ok": true,
"uploads_copies": 27,
"uploads_ignores": 0,
"db_restauree": true,
"db_lignes_ajoutees": 0,
"erreurs": 0
}
```
---
## Résumé des endpoints ajoutés
| Méthode | Route | Description |
|---------|-------|-------------|
| `POST` | `/api/settings/images/resize-all` | Redimensionne toutes les images de la bibliothèque |
| `POST` | `/api/settings/backup/samba` | Envoie la sauvegarde ZIP vers un partage Samba |
| `POST` | `/api/settings/backup/restore` | Restaure un backup ZIP (écraser ou ajouter) |
---
## Dette technique restante
- Le redimensionnement "bibliothèque" tourne de façon synchrone — pour de très grandes bibliothèques (> 500 photos), envisager une tâche en arrière-plan avec progression SSE.
- La connexion Samba utilise `subprocess` + `smbclient` ou `pysmb` : tester la compatibilité avec les NAS Synology / QNAP.
- Après une restauration "écraser", les sessions utilisateurs actives travaillent toujours sur l'ancienne BDD jusqu'au prochain cycle de connexion SQLAlchemy. Un rechargement de page suffit.