Supprime les entrées available_downloads dont le series_name ne
correspond plus à aucune série existante dans books, au début de
chaque job de détection de téléchargements.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Le tri par date d'ajout utilisait updated_at qui est écrasé à chaque
rescan de l'indexer, empêchant les livres/séries récemment ajoutés
de remonter en premier. Utilise maintenant created_at qui reflète
la vraie date d'ajout.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Modale Prowlarr (page série) : remplacé le bouton qBittorrent brut
par QbittorrentDownloadButton avec suivi managé (libraryId,
seriesName, expectedVolumes) et bouton "télécharger et remplacer".
- Ajout de alwaysShowReplace pour la modale Prowlarr (toujours montrer
le bouton remplacer) vs la page downloads (seulement si allVolumes >
expectedVolumes).
- Fix parseur : les tags de version entre crochets [V2], [V3] ne sont
plus extraits comme volumes (le préfixe "v" est ignoré après "[").
- Progression qBittorrent : utilise directement le champ progress
(completed et amount_left sont non-fiables sur qBittorrent 4.3.2).
- Référence import : ne plus exclure les volumes attendus de la
recherche de référence (corrige le mauvais dossier/nommage quand
tous les volumes sont dans expected_volumes).
- allVolumes ajouté à ProwlarrRelease (backend + frontend).
- flex-wrap sur les pastilles volumes dans la modale Prowlarr.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Ajout d'un bouton "télécharger et remplacer" avec popup de
confirmation, qui passe tous les volumes du pack (pas seulement
les manquants) et replace_existing=true à l'API.
- Nouvelle colonne replace_existing dans torrent_downloads.
- Fix critique du parseur de volumes : le pass 2 mélangeait les
indices d'octets (String::find) avec les indices de caractères
(Vec<char>), causant un décalage quand le titre contenait des
caractères multi-octets (é, à...). "Tome #097" extrayait 9
au lieu de 97. Réécrit en indexation char pure.
- Le préfixe "tome" skip désormais "#" (tome #097 → 97).
- Protection intra-batch : si une destination est déjà utilisée,
le fichier garde son nom original au lieu d'écraser.
- Alerte WARN si N fichiers source donnent N/3 volumes uniques.
- Nettoyage du répertoire sl-{id} et de la catégorie qBittorrent
après import.
- Badges volumes en flex-wrap dans la page downloads.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Le bouton revient à son état initial après l'icône verte de
confirmation, permettant de relancer un téléchargement si besoin.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
L'ancienne stratégie diff avant/après échouait quand plusieurs
torrents étaient ajoutés en parallèle (le diff voyait N nouveaux
torrents et ne pouvait pas les distinguer). Les tags et savepath
ne sont pas appliqués sur qBittorrent 4.x en url-encoded.
Nouvelle approche : chaque download managé crée une catégorie
`sl-{uuid}` dans qBittorrent, puis résout le hash en filtrant
par catégorie. Le poller retente aussi la résolution par catégorie
pour les torrents avec qb_hash NULL.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
La section "available downloads" n'était jamais mise à jour après le
chargement initial car seuls les torrent downloads étaient rafraîchis.
Stocke latestFound en state React et le rafraîchit en parallèle.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Nouvelle table available_downloads (library_id, series_name) unique
comme source de vérité pour les téléchargements disponibles
- Les jobs de détection font UPSERT (ajout/mise à jour) et DELETE
(séries complètes ou sans résultat)
- Après import, mise à jour ciblée : retire les volumes importés des
releases, supprime l'entrée si plus de releases
- Migration avec import des données existantes depuis detection_results
- Endpoint latest-found simplifié : une seule query sur la table
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Essaie INDEXER_BASE_URL, puis indexer:7081 (Docker), puis
localhost:7081 (dev local) avec timeout 2s par tentative.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Endpoint GET /version sur l'indexer (sans auth)
- Le backoffice fetch la version indexer directement (INDEXER_BASE_URL)
- Grille 3 colonnes avec les 3 versions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Endpoint GET /version (sans auth) retournant la version API
- Bloc About dans l'onglet General : nom du projet, description,
versions API et Backoffice, lien GitHub
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remplace les 5 CTEs + double query (données + count) par une seule
requête avec COUNT(*) OVER() pour le total
- Calcule book_count et series_count directement depuis UNNEST, sans
re-JOIN sur les tables
- Ajoute des index GIN sur books.authors et series_metadata.authors
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Serveur : envoie toujours les données (plus de skip si identiques),
ajoute un heartbeat toutes les 15s pour garder la connexion vivante
- Client : détecte les connexions mortes (timeout 30s sans message)
et reconnecte automatiquement, reconnexion plus rapide (3s vs 5s)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Le QbittorrentProvider expose un callback onDownloadStarted qui est
appelé quand un téléchargement est lancé avec succès. Sur la page
downloads, ce callback déclenche un refresh de la liste.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Les metadata providers sont récupérés côté serveur et les providers
sans API key sont passés en prop initialHiddenProviders, supprimant
le fetch client useEffect qui causait un layout shift.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Toutes les configurations (Prowlarr, qBittorrent, Telegram, Anilist,
Komga, metadata providers, status mappings) sont maintenant récupérées
côté serveur dans page.tsx et passées en props aux cards.
Supprime ~10 fetchs client useEffect au chargement, élimine les
layout shifts et réduit le temps de rendu initial.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Les configs Prowlarr et qBittorrent sont récupérées côté serveur et
passées en props au ProwlarrSearchModal, évitant les deux fetchs
client qui causaient l'apparition tardive du bouton.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
La config qBittorrent est maintenant récupérée côté serveur et passée
en prop au QbittorrentProvider, évitant le fetch client qui causait
l'apparition tardive des boutons de téléchargement.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Après import réussi, supprime le sous-répertoire content_path dans
/downloads/ (ne touche jamais /downloads/ lui-même)
- Supprime le torrent de qBittorrent via DELETE avec deleteFiles=true
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remplace les cartes par des lignes compactes (DownloadRow) pour
réduire l'espace vertical de chaque téléchargement
- Pagination côté client (10 par page) avec navigation prev/next
- Reset automatique à la page 1 au changement de filtre
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Après import torrent, refresh automatique des métadonnées uniquement
sur la série importée (via refresh_link) au lieu d'un job complet
- Nouvel endpoint POST /metadata/refresh-link/:id pour rafraîchir un
seul lien metadata approuvé
- Bouton "Rafraîchir" dans la modale metadata (état linked) avec
spinner et confirmation visuelle
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remplace localStorage par des cookies pour la persistance des filtres.
Le proxy restaure les filtres sauvegardés côté serveur, éliminant le flash au chargement.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>