refacto: réécriture des textes, messages et commentaires
This commit is contained in:
1 parent
6a3cb21adf
commit
586eccbbb3
118 files changed
+1621
-2159
No files matched your search
@@ -15,7 +15,7 @@
|
||||
</span>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm text-primary font-medium">
|
||||
{{ status.empty ? 'Catalogue non téléchargé' : `${status.count} séries disponibles` }}
|
||||
{{ status.empty ? 'Catalogue non synchronisé' : plural(status.count, 'série disponible', 'séries disponibles') }}
|
||||
</p>
|
||||
<p class="text-meta text-muted mt-0.5">
|
||||
{{ status.empty
|
||||
@@ -24,7 +24,7 @@
|
||||
</p>
|
||||
</div>
|
||||
<button @click="update" :disabled="updating" :class="status.empty ? 'btn-primary' : 'btn-secondary'" class="shrink-0">
|
||||
{{ updating ? 'Téléchargement…' : status.empty ? 'Télécharger' : 'Mettre à jour' }}
|
||||
{{ updating ? 'Synchronisation…' : status.empty ? 'Synchroniser le catalogue' : 'Synchroniser' }}
|
||||
</button>
|
||||
</section>
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm text-primary font-medium">Vous avez déjà des séries Fankai ?</p>
|
||||
<p class="text-meta text-muted mt-0.5">
|
||||
<template v-if="scanResult">{{ scanResult.found }} fichiers analysés · {{ scanResult.added }} référencés.</template>
|
||||
<template v-else>Analysez la médiathèque pour référencer les fichiers présents, sans les déplacer.</template>
|
||||
<template v-if="scanResult">{{ plural(scanResult.found, 'fichier trouvé', 'fichiers trouvés') }}, {{ plural(scanResult.added, 'ajouté', 'ajoutés') }} à la médiathèque.</template>
|
||||
<template v-else>Analysez la médiathèque pour reconnaître les épisodes déjà présents. Aucun fichier n'est déplacé.</template>
|
||||
</p>
|
||||
</div>
|
||||
<button @click="scan" :disabled="scanning || status.empty || !settings.mediaPath" class="btn-secondary shrink-0">
|
||||
@@ -45,7 +45,7 @@
|
||||
</section>
|
||||
|
||||
<p v-if="warnEmpty" class="text-body text-accent" role="alert">
|
||||
Le catalogue est encore vide. Téléchargez-le, ou cliquez à nouveau sur « Suivant » pour continuer.
|
||||
Le catalogue est encore vide. Synchronisez-le, ou cliquez à nouveau sur « Suivant » pour continuer.
|
||||
</p>
|
||||
</template>
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { Library, ScanSearch } from 'lucide-vue-next'
|
||||
import { useToast } from '@/composables/useToast'
|
||||
import { plural } from '@/utils/format'
|
||||
import type { SetupSettings } from './setup'
|
||||
|
||||
defineProps<{ settings: SetupSettings; isDocker: boolean; defaultPath: string }>()
|
||||
@@ -77,9 +78,9 @@ async function update() {
|
||||
if (res.ok) {
|
||||
status.value = { exists: true, count: data.count, empty: data.count === 0 }
|
||||
warnEmpty.value = false
|
||||
toast(`${data.count} séries chargées ✓`, 'success')
|
||||
toast(`Catalogue synchronisé : ${plural(data.count, 'série')}`, 'success')
|
||||
} else {
|
||||
toast(data.error ?? 'Erreur lors de la mise à jour', 'error')
|
||||
toast(data.error ?? 'Impossible de synchroniser le catalogue', 'error')
|
||||
}
|
||||
} catch {
|
||||
toast('Impossible de contacter le serveur', 'error')
|
||||
@@ -96,7 +97,7 @@ async function scan() {
|
||||
const data = await res.json()
|
||||
scanResult.value = { found: data.found, added: data.added }
|
||||
} else {
|
||||
toast("Erreur lors de l'analyse", 'error')
|
||||
toast("Impossible d'analyser la médiathèque", 'error')
|
||||
}
|
||||
} catch {
|
||||
toast('Impossible de contacter le serveur', 'error')
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
<!-- Clients existants -->
|
||||
<div v-if="clients.length > 0" class="flex flex-col gap-2">
|
||||
<div v-for="client in clients" :key="client.uuid" class="card flex items-center gap-3">
|
||||
<span
|
||||
@@ -25,7 +24,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Formulaire -->
|
||||
<div v-if="formOpen" class="card flex flex-col gap-4">
|
||||
<p class="text-sm font-semibold text-primary">{{ editing ? 'Modifier le client' : 'Ajouter un client' }}</p>
|
||||
<TorrentClientForm
|
||||
@@ -41,7 +39,6 @@
|
||||
<Plus :size="14" /> {{ clients.length > 0 ? 'Ajouter un autre client' : 'Ajouter un client' }}
|
||||
</button>
|
||||
|
||||
<!-- Rappel chemins -->
|
||||
<div class="flex items-start gap-3 px-4 py-3 rounded-field border border-border bg-card/50">
|
||||
<Info :size="15" class="text-muted mt-0.5 shrink-0" />
|
||||
<p class="text-meta text-muted leading-relaxed">
|
||||
@@ -58,8 +55,8 @@
|
||||
<div class="flex flex-col gap-0.5">
|
||||
<p class="text-body text-accent font-medium">Aucun client configuré</p>
|
||||
<p class="text-meta text-muted">
|
||||
Sans client, FanKarr ne pourra rien télécharger. Cliquez à nouveau sur « Suivant » pour continuer quand même,
|
||||
vous pourrez l'ajouter plus tard dans Paramètres → Clients de téléchargement.
|
||||
Sans client, FanKarr ne pourra rien télécharger. Cliquez à nouveau sur « Suivant » pour passer cette étape.
|
||||
Vous pourrez en ajouter un plus tard dans Paramètres › Clients torrent.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,23 +5,23 @@
|
||||
<SettingsToggle
|
||||
v-model="form.autoImport"
|
||||
label="Import automatique"
|
||||
description="Importe dès qu'un téléchargement est terminé, puis vérifie toutes les 5 minutes. Sinon, l'import se lance à la main depuis Activité."
|
||||
description="Importe les téléchargements terminés (vérification toutes les 5 minutes). Désactivé, vous lancez l'import depuis la page Activité."
|
||||
/>
|
||||
<SettingsToggle
|
||||
v-model="form.englishDirectory"
|
||||
label="Dossiers « Season » au lieu de « Saison »"
|
||||
description="Nomme les dossiers de saison « Season 01 » plutôt que « Saison 1 »."
|
||||
label="Dossiers de saison en anglais"
|
||||
description="« Season 01 » au lieu de « Saison 1 »."
|
||||
/>
|
||||
<SettingsToggle
|
||||
v-model="form.autoUnimportMissing"
|
||||
label="Désimporter si le fichier disparaît"
|
||||
description="Un épisode supprimé du disque est retiré de la médiathèque FanKarr au scan suivant."
|
||||
label="Retirer les épisodes supprimés du disque"
|
||||
description="À la prochaine analyse, un épisode dont le fichier a disparu est retiré de la médiathèque."
|
||||
/>
|
||||
<SettingsToggle
|
||||
v-if="settings.organizeMode === 'move'"
|
||||
v-model="form.deleteTorrentOnMove"
|
||||
label="Supprimer le torrent après déplacement"
|
||||
description="Retire automatiquement le torrent du client une fois le fichier déplacé."
|
||||
description="Le torrent ne peut plus être partagé une fois le fichier déplacé : autant le retirer du client."
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<SettingsToggle
|
||||
v-model="form.nfoSupport"
|
||||
label="Fichiers NFO et images"
|
||||
description="Télécharge NFO et visuels à côté de chaque épisode lors de l'import."
|
||||
description="Enregistre à côté de chaque épisode un fichier .nfo (titre, résumé…) et ses images."
|
||||
/>
|
||||
<div class="flex items-start gap-2.5 px-3 py-2.5 rounded-field border border-border bg-main/50 text-meta text-muted leading-relaxed">
|
||||
<Info :size="13" class="shrink-0 mt-0.5" />
|
||||
@@ -67,7 +67,7 @@ const error = ref<string | null>(null)
|
||||
async function submit(): Promise<boolean> {
|
||||
error.value = null
|
||||
if (await postSettings(form)) return true
|
||||
error.value = "Erreur lors de l'enregistrement."
|
||||
error.value = "Impossible d'enregistrer les réglages d'import."
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div class="flex flex-col gap-4">
|
||||
|
||||
<!-- Jellyfin -->
|
||||
<section class="card flex flex-col gap-4">
|
||||
<div class="flex items-start gap-3">
|
||||
<span class="w-9 h-9 rounded-full bg-accent-muted text-accent flex items-center justify-center shrink-0">
|
||||
@@ -13,7 +12,7 @@
|
||||
<span v-if="jellyfin?.test?.ok" class="pill pill-ok h-5 px-2 text-[10.5px]">Connecté</span>
|
||||
</p>
|
||||
<p class="text-meta text-muted mt-0.5 leading-relaxed">
|
||||
Permet à vos utilisateurs Jellyfin de se connecter à FanKarr et de faire des demandes depuis le plugin FanKarr Search.
|
||||
Vos utilisateurs Jellyfin se connectent à FanKarr et font leurs demandes depuis le plugin FanKarr Search.
|
||||
</p>
|
||||
</div>
|
||||
<button @click="jellyfinOpen = !jellyfinOpen" :aria-expanded="jellyfinOpen" class="btn-secondary btn-sm shrink-0">
|
||||
@@ -31,7 +30,7 @@
|
||||
{{ syncing ? 'Synchronisation…' : 'Synchroniser les utilisateurs' }}
|
||||
</button>
|
||||
<span v-if="syncResult" class="text-meta text-ok">
|
||||
{{ syncResult.created }} créé{{ syncResult.created > 1 ? 's' : '' }} · {{ syncResult.skipped }} ignoré{{ syncResult.skipped > 1 ? 's' : '' }}
|
||||
{{ plural(syncResult.created, 'créé', 'créés') }} · {{ plural(syncResult.skipped, 'déjà existant', 'déjà existants') }}
|
||||
</span>
|
||||
<span v-if="syncError" class="text-meta text-err">{{ syncError }}</span>
|
||||
</div>
|
||||
@@ -40,7 +39,6 @@
|
||||
</template>
|
||||
</section>
|
||||
|
||||
<!-- Plex -->
|
||||
<section class="card flex flex-col gap-4">
|
||||
<div class="flex items-start gap-3">
|
||||
<span class="w-9 h-9 rounded-full bg-accent-muted text-accent flex items-center justify-center shrink-0">
|
||||
@@ -53,7 +51,7 @@
|
||||
</p>
|
||||
<p class="text-meta text-muted mt-0.5 leading-relaxed">
|
||||
Crée une bibliothèque Plex sur votre médiathèque, reliée à l'agent de métadonnées Fankai.
|
||||
Requiert Plex Media Server 1.43 ou plus récent pour la configuration automatique.
|
||||
Nécessite Plex Media Server 1.43 ou plus récent pour la configuration automatique.
|
||||
</p>
|
||||
</div>
|
||||
<button @click="openPlex" :disabled="!settings.mediaPath" class="btn-secondary btn-sm shrink-0">
|
||||
@@ -63,7 +61,7 @@
|
||||
<p v-if="!settings.mediaPath" class="text-meta text-accent">Renseignez d'abord la médiathèque à l'étape Dossiers.</p>
|
||||
</section>
|
||||
|
||||
<p class="text-meta text-muted">Pas de serveur multimédia pour l'instant ? Passez cette étape, tout se configure aussi plus tard.</p>
|
||||
<p class="text-meta text-muted">Pas encore de Jellyfin ni de Plex ? Passez cette étape : vous pourrez les configurer plus tard dans les paramètres.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -76,6 +74,7 @@ import { Server, Tv } from 'lucide-vue-next'
|
||||
import JellyfinConnectionForm from '@/components/settings/JellyfinConnectionForm.vue'
|
||||
import PlexWizard from '@/components/settings/PlexWizard.vue'
|
||||
import { setupContextKey, type SetupSettings } from './setup'
|
||||
import { plural } from '@/utils/format'
|
||||
|
||||
defineProps<{ settings: SetupSettings; isDocker: boolean; defaultPath: string }>()
|
||||
|
||||
@@ -101,7 +100,7 @@ async function syncUsers() {
|
||||
const res = await fetch('/api/jellyfin/sync', { method: 'POST', credentials: 'include' })
|
||||
const data = await res.json()
|
||||
if (res.ok) syncResult.value = data
|
||||
else syncError.value = data.error ?? 'Erreur lors de la synchronisation'
|
||||
else syncError.value = data.error ?? 'Impossible de synchroniser les utilisateurs Jellyfin'
|
||||
} catch {
|
||||
syncError.value = 'Impossible de contacter le serveur'
|
||||
} finally {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
class="field"
|
||||
spellcheck="false"
|
||||
/>
|
||||
<button @click="openPicker(field.key)" class="btn-secondary shrink-0" :title="`Parcourir — ${field.label}`">
|
||||
<button @click="openPicker(field.key)" class="btn-secondary shrink-0" :title="`Choisir le dossier : ${field.label}`">
|
||||
<FolderOpen :size="14" /> <span class="hidden sm:inline">Parcourir</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -34,15 +34,14 @@
|
||||
</div>
|
||||
|
||||
<p v-if="result?.relation === 'same'" class="text-meta text-err flex items-start gap-1.5">
|
||||
<X :size="12" class="shrink-0 mt-0.5" /> La médiathèque doit être distincte du dossier de téléchargements.
|
||||
<X :size="12" class="shrink-0 mt-0.5" /> La médiathèque et le dossier des téléchargements doivent être différents.
|
||||
</p>
|
||||
<p v-else-if="result?.relation === 'nested'" class="text-meta text-accent flex items-start gap-1.5">
|
||||
<TriangleAlert :size="12" class="shrink-0 mt-0.5" />
|
||||
Un dossier est à l'intérieur de l'autre : ça fonctionne, mais le scan de la médiathèque verra aussi les téléchargements.
|
||||
L'un des dossiers est dans l'autre. C'est possible, mais l'analyse de la médiathèque trouvera aussi les téléchargements.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Mode d'import -->
|
||||
<div class="card flex flex-col gap-3">
|
||||
<label class="field-label">Mode d'import</label>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-2">
|
||||
@@ -62,7 +61,6 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Résultat du test hardlink -->
|
||||
<div v-if="result && form.organizeMode === 'hardlink'" class="text-meta">
|
||||
<p v-if="result.hardlink.tested && result.hardlink.ok" class="text-ok flex items-center gap-1.5">
|
||||
<Check :size="12" class="shrink-0" /> {{ result.hardlink.message }}
|
||||
@@ -71,7 +69,7 @@
|
||||
<p class="text-accent flex items-start gap-1.5">
|
||||
<TriangleAlert :size="12" class="shrink-0 mt-0.5" /> {{ result.hardlink.message }}
|
||||
</p>
|
||||
<p class="text-muted">Sans hardlink, FanKarr copiera les fichiers (espace disque doublé).</p>
|
||||
<p class="text-muted">Les hardlinks ne fonctionnent pas entre ces dossiers : en mode Copier, chaque fichier prendra deux fois la place.</p>
|
||||
<button @click="form.organizeMode = 'copy'" class="btn-secondary btn-sm self-start">Passer en mode Copier</button>
|
||||
</div>
|
||||
<p v-else class="text-muted">{{ result.hardlink.message }}</p>
|
||||
@@ -104,7 +102,7 @@ const fields: { key: PathKey; label: string; required: boolean; placeholder: str
|
||||
{
|
||||
key: 'completePath', label: 'Dossier des téléchargements terminés', required: false,
|
||||
placeholder: props.isDocker ? '/data/downloads' : 'D:/Torrents/complete',
|
||||
help: 'Là où votre client torrent dépose les fichiers terminés. Sert aussi à tester les hardlinks.',
|
||||
help: 'Dossier où votre client torrent place les fichiers terminés.',
|
||||
},
|
||||
{
|
||||
key: 'mediaPath', label: 'Médiathèque Fankai', required: true,
|
||||
@@ -114,9 +112,9 @@ const fields: { key: PathKey; label: string; required: boolean; placeholder: str
|
||||
]
|
||||
|
||||
const modes = [
|
||||
{ id: 'hardlink' as const, label: 'Hardlink', text: 'Aucune copie : le fichier reste en partage dans le client torrent.' },
|
||||
{ id: 'hardlink' as const, label: 'Hardlink', text: 'Le fichier apparaît dans la médiathèque sans être copié ; le client continue de le partager.' },
|
||||
{ id: 'copy' as const, label: 'Copier', text: 'Duplique le fichier. Fonctionne partout, prend deux fois la place.' },
|
||||
{ id: 'move' as const, label: 'Déplacer', text: 'Retire le fichier du client : le partage s\'arrête.' },
|
||||
{ id: 'move' as const, label: 'Déplacer', text: "Retire le fichier du client : le partage s'arrête." },
|
||||
]
|
||||
|
||||
const form = reactive({
|
||||
@@ -175,7 +173,7 @@ async function submit(): Promise<boolean> {
|
||||
if (!res.ok) { error.value = 'Corrigez les dossiers signalés avant de continuer.'; return false }
|
||||
|
||||
if (!(await postSettings({ ...form, mediaPath: res.mediaPath.resolved, completePath: res.completePath?.resolved ?? '' }))) {
|
||||
error.value = "Erreur lors de l'enregistrement."
|
||||
error.value = "Impossible d'enregistrer les dossiers."
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
@@ -21,14 +21,14 @@
|
||||
<div class="flex flex-col sm:flex-row gap-2">
|
||||
<button @click="done(true)" :disabled="finishing || !settings.mediaPath" class="btn-primary">
|
||||
<Compass :size="15" />
|
||||
{{ context.relaunch ? 'Revoir la visite guidée' : "Terminer et découvrir l'interface" }}
|
||||
{{ context.relaunch ? 'Revoir la visite guidée' : 'Terminer avec la visite guidée' }}
|
||||
</button>
|
||||
<button @click="done(false)" :disabled="finishing || !settings.mediaPath" class="btn-secondary">
|
||||
{{ context.relaunch ? 'Fermer' : 'Terminer sans la visite' }}
|
||||
</button>
|
||||
</div>
|
||||
<p v-if="!context.relaunch" class="text-meta text-muted -mt-3">
|
||||
La visite guidée présente chaque écran en une minute. Vous pourrez la relancer depuis le bouton « ? » de la barre latérale.
|
||||
La visite guidée présente les écrans principaux en une minute. Vous pourrez la relancer avec le bouton « ? ».
|
||||
</p>
|
||||
|
||||
</div>
|
||||
@@ -38,6 +38,7 @@
|
||||
import { ref, reactive, inject, onMounted } from 'vue'
|
||||
import { Check, Compass, Minus, TriangleAlert, X } from 'lucide-vue-next'
|
||||
import { checkPaths, setupContextKey, type SetupSettings, type SetupStepId } from './setup'
|
||||
import { plural } from '@/utils/format'
|
||||
|
||||
type RowState = 'loading' | 'ok' | 'warn' | 'error' | 'neutral'
|
||||
interface Row { label: string; value: string; state: RowState; step: SetupStepId }
|
||||
@@ -55,7 +56,7 @@ const stateClass: Record<RowState, string> = {
|
||||
neutral: 'bg-hover text-muted',
|
||||
}
|
||||
|
||||
const modeLabel = { hardlink: 'Hardlink', copy: 'Copie', move: 'Déplacement' }
|
||||
const modeLabel = { hardlink: 'Hardlink', copy: 'Copier', move: 'Déplacer' }
|
||||
|
||||
const row = (label: string, step: SetupStepId, value = '…', state: RowState = 'loading'): Row => ({ label, step, value, state })
|
||||
|
||||
@@ -64,11 +65,11 @@ const rows = reactive({
|
||||
mode : row("Mode d'import", 'paths'),
|
||||
client : row('Client torrent', 'client'),
|
||||
import : row('Import automatique', 'import',
|
||||
props.settings.autoImport ? 'Activé' : 'Désactivé : import manuel depuis Activité',
|
||||
props.settings.autoImport ? 'Activé' : 'Désactivé : import manuel depuis la page Activité',
|
||||
props.settings.autoImport ? 'ok' : 'neutral'),
|
||||
nfo : row('NFO et images', 'import', props.settings.nfoSupport ? 'Activés' : 'Désactivés', 'neutral'),
|
||||
nfo : row('Fichiers NFO et images', 'import', props.settings.nfoSupport ? 'Activés' : 'Désactivés', 'neutral'),
|
||||
jellyfin: row('Jellyfin', 'media-server'),
|
||||
plex : row('Plex', 'media-server', context.plexOpened ? 'Assistant Plex lancé' : 'Non configuré', 'neutral'),
|
||||
plex : row('Plex', 'media-server', context.plexOpened ? 'Assistant ouvert, non vérifié' : 'Non configuré', 'neutral'),
|
||||
catalog : row('Catalogue Fankai', 'catalog'),
|
||||
})
|
||||
|
||||
@@ -90,7 +91,7 @@ async function loadPaths() {
|
||||
set(rows.paths, 'Médiathèque non configurée', 'error')
|
||||
} else {
|
||||
set(rows.paths,
|
||||
`${s.mediaPath}${s.completePath ? ` ← ${s.completePath}` : ' · téléchargements non renseignés'}`,
|
||||
`Médiathèque : ${s.mediaPath} · ${s.completePath ? `Téléchargements : ${s.completePath}` : 'dossier des téléchargements non renseigné'}`,
|
||||
!res.ok ? 'error' : s.completePath ? 'ok' : 'warn')
|
||||
}
|
||||
|
||||
@@ -139,7 +140,7 @@ async function loadCatalog() {
|
||||
try {
|
||||
const { count, empty } = await getJson('/api/torrents/status')
|
||||
if (empty) set(rows.catalog, 'Catalogue vide', 'warn')
|
||||
else set(rows.catalog, `${count} séries disponibles`, 'ok')
|
||||
else set(rows.catalog, plural(count, 'série disponible', 'séries disponibles'), 'ok')
|
||||
} catch {
|
||||
set(rows.catalog, 'Impossible de vérifier', 'warn')
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div class="flex flex-col gap-6">
|
||||
|
||||
<!-- Fonctionnement -->
|
||||
<ol class="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
<li v-for="(item, i) in flow" :key="item.title" class="card flex gap-3">
|
||||
<span class="w-8 h-8 rounded-full bg-accent-muted text-accent flex items-center justify-center shrink-0">
|
||||
@@ -14,7 +13,6 @@
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<!-- Ce qu'on va configurer -->
|
||||
<div class="card flex flex-col gap-3">
|
||||
<p class="field-label">Au programme</p>
|
||||
<ul class="flex flex-col gap-2">
|
||||
@@ -22,14 +20,13 @@
|
||||
<Check :size="14" class="text-accent mt-0.5 shrink-0" />
|
||||
<span class="text-secondary">
|
||||
{{ item.label }}
|
||||
<span v-if="item.optional" class="text-muted text-meta">(optionnel)</span>
|
||||
<span v-if="item.optional" class="text-muted text-meta">(facultatif)</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="text-meta text-muted">Comptez environ 5 minutes.</p>
|
||||
</div>
|
||||
|
||||
<!-- Docker -->
|
||||
<div v-if="isDocker" class="flex items-start gap-3 px-4 py-3 rounded-field border border-accent/30 bg-accent-muted">
|
||||
<HardDrive :size="16" class="text-accent mt-0.5 shrink-0" />
|
||||
<div class="flex flex-col gap-1">
|
||||
@@ -54,16 +51,16 @@ defineProps<{ settings: SetupSettings; isDocker: boolean; defaultPath: string }>
|
||||
|
||||
const flow = [
|
||||
{ icon: Library, title: 'Catalogue', text: 'Toutes les séries Fankai, avec leurs torrents par épisode, saison ou intégrale.' },
|
||||
{ icon: Download, title: 'Téléchargement', text: 'Un clic envoie le torrent à votre client (qBittorrent, Transmission…).' },
|
||||
{ icon: FolderOpen, title: 'Import', text: 'Une fois terminé, le fichier est renommé et rangé par série et saison.' },
|
||||
{ icon: Download, title: 'Téléchargement', text: 'Le torrent est envoyé à votre client (qBittorrent, Transmission…).' },
|
||||
{ icon: FolderOpen, title: 'Import', text: 'Une fois le téléchargement terminé, le fichier est renommé et rangé par série et par saison.' },
|
||||
{ icon: Tv, title: 'Lecture', text: 'Jellyfin ou Plex retrouvent vos séries avec les métadonnées Fankai.' },
|
||||
]
|
||||
|
||||
const checklist = [
|
||||
{ label: 'Dossier de téléchargements et médiathèque' },
|
||||
{ label: 'Dossier des téléchargements et médiathèque' },
|
||||
{ label: 'Client torrent' },
|
||||
{ label: 'Import automatique et nommage' },
|
||||
{ label: 'Jellyfin ou Plex', optional: true },
|
||||
{ label: 'Téléchargement du catalogue' },
|
||||
{ label: 'Synchronisation du catalogue' },
|
||||
]
|
||||
</script>
|
||||
Reference in new issue
Block a user