feat: UX improvements, folder picker, download state & NFO support
## Settings - Folder picker pour les paths (navigation dossier côté serveur via GET /api/browse) - Paths vides par défaut, démarrage à / dans le picker - Picker accessible même sous Docker (volumes montés accessibles) - Bouton "Analyser bibliothèque" pour relancer scanMediaPath manuellement (POST /api/scan) - Toggle NFO support (téléchargement dossier GitLab Fankai Pack à l'organisation) - nfoSupport ajouté dans Settings interface + defaults ## Catalogue - Logo "Fankarr" cliquable → retour accueil - Filtres séparés en 2 groupes : état série (orange) | état téléchargement (bleu) - Groupe 1 : Toutes / Disponibles / Sans torrent - Groupe 2 : DL complet / DL partiel - Tooltip badge torrents → "X torrents téléchargeables" ## Page Série - Anti-spam boutons download : Set au lieu de string, bouton bloqué après envoi - Boutons bloqués si torrent déjà dans qBittorrent (cross-session via poll /api/downloads) - Boutons bloqués si épisode/saison déjà organisé dans la bibliothèque - Barre de progression sous épisode / saison / intégrale (poll 5s) - Badge "✓ téléchargé" à 100% à la place de la barre - Badge "dispo" en bleu, "✓ téléchargé" inline à côté de "dispo" ## Page Téléchargements - Onglets EN COURS / TERMINÉS (défaut : EN COURS) - EN COURS : downloading + paused + checking + error - TERMINÉS : seeding uniquement - Toggle "Masquer organisés" dans l'onglet TERMINÉS - Message vide adapté au contexte ## Organizer - seasonFolder : Saison N sans padding (pour matcher GitLab) - Map SERIE_TITLE_GITLAB_MAP : 9 corrections titres API → GitLab - downloadGitlabFolder : liste récursive + téléchargement NFO/images depuis fankai_pack - Appelé au début de organizeTorrent si nfoSupport activé - Paths vides par défaut dans readSettings du worker ## Backend - POST /api/scan : déclenche scanMediaPath manuellement - GET /api/browse?path= : liste les sous-dossiers d'un chemin - dispatchList : utilise client.config.category en priorité sur la catégorie globale - Catégorie configurable par client torrent (fix torrents non affichés page downloads)
This commit is contained in:
1 parent
f38a43d396
commit
693f8a96ae
9 files changed
+932
-319
No files matched your search
+29
-1
@@ -8,7 +8,7 @@ import {
|
||||
registerDriver, getDriver, getAvailableClients,
|
||||
listClients, addClient, removeClient, getClient,
|
||||
sanitizeClient, dispatchDownload, dispatchList
|
||||
} from './torrent-clients/index.js'
|
||||
} from './torrent-clients'
|
||||
import qbittorrentDriver from './torrent-clients/qbittorrent.js'
|
||||
import { organizeTorrent, autoOrganizeAll, scanMediaPath } from './organize.js'
|
||||
import { logger, readLogs, clearLogs, logsFileSize } from './logger.js'
|
||||
@@ -433,6 +433,22 @@ app.get('/api/system', requireAuth, (_req, res) => {
|
||||
res.json({ isDocker })
|
||||
})
|
||||
|
||||
app.get('/api/browse', requireAuth, (req, res) => {
|
||||
const dirPath = (req.query.path as string) || '/'
|
||||
try {
|
||||
const entries = fs.readdirSync(dirPath, { withFileTypes: true })
|
||||
const dirs = entries
|
||||
.filter(e => e.isDirectory())
|
||||
.map(e => e.name)
|
||||
.filter(n => !n.startsWith('.'))
|
||||
.sort((a, b) => a.localeCompare(b))
|
||||
const parent = dirPath === '/' ? null : path.dirname(dirPath)
|
||||
res.json({ path: dirPath, parent, dirs })
|
||||
} catch (err) {
|
||||
res.status(400).json({ error: err instanceof Error ? err.message : 'Erreur lecture dossier' })
|
||||
}
|
||||
})
|
||||
|
||||
app.get('/api/torrents/status', requireAuth, (_req, res) => {
|
||||
try {
|
||||
if (!fs.existsSync(TORRENTS_PATH)) { res.json({ exists: false, count: 0, empty: true }); return }
|
||||
@@ -459,6 +475,18 @@ app.post('/api/update', requireAuth, async (_req, res) => {
|
||||
}
|
||||
})
|
||||
|
||||
app.post('/api/scan', requireAuth, async (_req, res) => {
|
||||
try {
|
||||
const { mediaPath } = readSettings()
|
||||
const ORGANIZED_PATH = path.join(process.cwd(), 'data', 'organized.json')
|
||||
const result = await scanMediaPath(mediaPath, TORRENTS_PATH, ORGANIZED_PATH)
|
||||
logger.info('api', `Scan manuel: ${result.found} fichiers scannés, ${result.added} ajoutés`)
|
||||
res.json({ ok: true, ...result })
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: err instanceof Error ? err.message : 'Erreur inconnue' })
|
||||
}
|
||||
})
|
||||
|
||||
// ── SPA fallback (prod) — doit être après toutes les routes API ─
|
||||
if (fs.existsSync(PUBLIC_PATH)) {
|
||||
app.get('*path', (_req, res) => {
|
||||
|
||||
Reference in new issue
Block a user