feat: watcher (phase 3+6) + navigation dashboard (version, changelog, aide)

Phase 3 — Clipboard Watcher (Windows):
- clipboard.rs: détection d'images via arboard, conversion BGRA→PNG
- Gère les doublons consécutifs (même image dans le presse-papier)

Phase 6 — Watcher Loop:
- Windows: polling clipboard → hash → dédoublonnage → upload
- Linux/macOS: polling de dossier configurable (watch_dir)
- Ajout champ watch_dir dans WatcherConfig
- Client Imago cloné avant await (évite problème Send/Sync)

Dashboard:
- Badge version v0.1.0 dans le header
- Barre de navigation: Galerie / Changelog / Aide
- Pages changelog.html et help.html (chargement dynamique)
- Endpoint GET /api/version avec infos build
- Correction import delete inutilisé dans routes.rs
This commit is contained in:
2026-06-25 09:41:51 -04:00
parent 9b06df737d
commit 3bab62733d
11 changed files with 608 additions and 36 deletions
+16 -1
View File
@@ -1,7 +1,7 @@
//! Routes API REST du dashboard — proxy vers Imago v2
use axum::{
Router, routing::{get, post, put, delete},
Router, routing::{get, post, put},
extract::{Multipart, Path, Query, State},
http::HeaderMap,
response::IntoResponse,
@@ -101,6 +101,7 @@ pub fn api_routes(state: AppState) -> Router {
.route("/api/images/{id}/tags", put(update_tags))
.route("/api/images/{id}/thumbnail", get(get_thumbnail))
.route("/api/stats", get(stats))
.route("/api/version", get(version))
.with_state(state)
}
@@ -110,6 +111,20 @@ async fn health_check() -> &'static str {
"OK"
}
/// Retourne la version de l'application et des infos utiles
async fn version() -> Json<serde_json::Value> {
Json(serde_json::json!({
"version": env!("CARGO_PKG_VERSION"),
"name": env!("CARGO_PKG_NAME"),
"description": env!("CARGO_PKG_DESCRIPTION"),
"repository": env!("CARGO_PKG_REPOSITORY"),
"rustc": option_env!("RUSTC_VERSION").unwrap_or("unknown"),
"profile": if cfg!(debug_assertions) { "debug" } else { "release" },
"target_os": std::env::consts::OS,
"target_arch": std::env::consts::ARCH,
}))
}
/// Valide une clé API utilisateur contre l'API Imago.
/// Si valide, retourne le nom du client (trouvé via les images existantes).
async fn validate_api_key(