- Frontend: flag isUploading empêche les uploads parallèles (double/triple soumission)
- Frontend: réponse 'duplicate' traitée comme un succès (toast info au lieu d'erreur)
- Frontend: message d'erreur réseau plus explicite ('serveur injoignable')
- Frontend: HTTP 409 (conflit concurrent) géré proprement
- Serveur lancé sans watcher (--no-watcher) sur Linux (dossier vide = inutile)
- Vérifie already_seen() dans la DB SQLite avant chaque upload vers Imago
- Si le hash existe déjà → retourne status=duplicate sans re-uploader
- Protège contre les doublons séquentiels (pas juste concurrents)
- Testé: 1er upload OK (ID 81), 2e upload même fichier → duplicate, 3e fichier différent → OK (ID 82)
- Backend: Mutex<HashSet> pour bloquer les uploads concurrents du même hash (409 Conflict)
- Backend: logs tracing pour tracer chaque upload entrant
- Frontend: flag isDragging pour éviter le double déclenchement click+drag
- Dépendance: ajout hex = 0.4 pour log du hash
Corrige le bug où un seul fichier uploadé générait 4 copies sur Imago.
- build.rs génère version dynamique : X.Y.Z+build.N-abc1234
- Version injectée dans l'API (IMAGOD_BUILD_VERSION) et pages HTML
- Suffixe -dirty si modifications non commitées
- replace_all_versions() consomme le suffixe build metadata
- Suppression auto-changelog — reste manuel pour contrôle qualité
- Ajout de dedup_db_path dans AppState (partagé avec le watcher)
- upload_image() calcule le SHA-256 avant upload et marque le hash
dans la DB de dédoublonnage après succès
- Le watcher voit maintenant les fichiers uploadés via le dashboard
comme 'déjà vus' → plus de doublons watcher/drag-and-drop
- Correction compilation: indentation du match upload_image
- build.rs convertit CHANGELOG.md → changelog.html et ROADMAP.md → help.html
- Injection automatique de la version Cargo.toml dans toutes les pages
- Correction du routage : /changelog et /help sans .html fonctionnent
- Templates changelog.tmpl.html et help.tmpl.html avec placeholders {{VERSION}}
- Plus jamais de désynchronisation entre .md et pages web !
- v0.2.0 affichée partout (index, changelog, help, API)
Problème: les balises <img> du navigateur ne peuvent pas envoyer
X-API-Key, donc les thumbnails étaient 404 car la clé configurée
était expirée.
Solution:
- get_thumbnail() utilise TOUJOURS la clé serveur (state.api_key)
au lieu de chercher le header utilisateur
- Mise à jour de la clé API dans imagod.toml avec la clé valide
Test: HTTP 200 sans header personnalisé ✓
Backend:
- ImagoClient::delete_image() — DELETE /api/v1/images/{id}
- ImagoClient::update_tags() — PUT /api/v1/images/{id}/tags
- Route DELETE /api/images/{id}
- Route PUT /api/images/{id}/tags
Frontend:
- Bouton 🗑️ sur chaque carte (visible au hover)
- Boîte de confirmation avant suppression
- Tags cliquables avec × pour suppression
- Bouton + tag pour ajouter un tag (Enter pour valider)
- Bouton Supprimer + tags éditables dans la modale
- Suppression + modif tags aussi dans la modale
⚠️ Nécessite redéploiement Imago pour le endpoint PUT /tags
- ImagoClient::get_thumbnail() utilise maintenant /thumbnail-url (URL signée)
- ImagoClient::get_file() utilise maintenant /download-url (URL signée)
- Fallback automatique thumbnail → fichier original si thumbnail indisponible
- Les images s'affichent dans la gallery même sans thumbnail généré
- Route POST /api/auth/validate (backend) : valide la clé contre Imago
- AppState supporte clé dynamique (X-Api-Key header utilisateur)
- Écran de login overlay avec champ clé API + validation
- Nom d'utilisateur affiché dans le header (👤 bruno) avec bouton logout
- Stockage clé + nom dans localStorage (persiste entre sessions)
- Tous les appels API incluent X-Api-Key du frontend
Backend:
- Route POST /api/upload avec multipart (axum 0.8)
- Proxy vers Imago, validation MIME, feedback JSON
Frontend:
- Zone de drop avec drag & drop (effet visuel au survol)
- Bouton Upload dans le header + FAB flottant mobile
- Support Ctrl+V (coller depuis presse-papier)
- Upload multiple, feedback toast (succès/erreur)
- Raccourci Ctrl+U pour upload
- Responsive: 2 breakpoints (768px, 400px)
- Gallery 2 colonnes sur mobile, FAB, toasts bottom
- user-scalable=no, tap-highlight transparent
- Remplace le onerror SVG data URI (cassé) par un vrai div placeholder
- Affiche 🖼️ + 'Pas d'aperçu' quand le thumbnail est indisponible
- Même fallback dans la modale detail