# 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.