Commit Graph

359 Commits

Author SHA1 Message Date
Jérémy Guillot
41c1fc5e2e fix(manga): générer le CBZ de téléchargement depuis les dossiers de pages
Les endpoints de téléchargement chapitre/volume plantaient (500 "file does
not exist") car le FileService traitait `pagesDirectory` comme un CBZ. Le
service reconstruit maintenant l'archive à la volée à partir des images du
dossier, et le nom du fichier chapitre inclut le titre du manga et le numéro.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:48:17 +02:00
848efd3327 Merge pull request 'feat(home): toolbar filtre/affichage et modale options d'affichage' (#46) from feat/home-toolbar-display-settings into main
All checks were successful
Deploy / deploy (push) Successful in 1m7s
Reviewed-on: #46
2026-03-27 16:26:33 +01:00
65eef59999 Merge branch 'main' into feat/home-toolbar-display-settings 2026-03-27 16:26:20 +01:00
ext.jeremy.guillot@maxicoffee.domains
e525c9b7bd feat(home): toolbar filtre/affichage et modale options d'affichage
- Correction du dropdown toolbar : prop align (left/right) pour éviter le débordement hors écran côté droit
- Filtre de collection par statut (all/completed/ongoing) persisté dans userPreferencesStore
- toolbarConfig rendu réactif (computed) avec isSelected sur Filter, Sort et View
- Modale Options d'affichage par vue (Grille, Overview, Table) avec toggles persistés
- Composant ToggleRow réutilisable
- Normalisation author → authors dans l'entité Manga (l'API renvoie author string)
2026-03-27 16:25:45 +01:00
8d8389377d Merge pull request 'fix(monitoring): corriger la résolution de l'ID chapitre après synchronisation MangaDex' (#45) from fix/monitoring-chapter-id-mismatch into main
All checks were successful
Deploy / deploy (push) Successful in 1m5s
Reviewed-on: #45
2026-03-27 15:04:20 +01:00
a9c5769c8e Merge branch 'main' into fix/monitoring-chapter-id-mismatch 2026-03-27 15:04:12 +01:00
ext.jeremy.guillot@maxicoffee.domains
969f4569f5 fix(monitoring): corriger la résolution de l'ID chapitre après synchronisation MangaDex
synchronizeChapters() retournait des UUID temporaires générés en mémoire. Ces UUID
n'étant jamais persistés, le Scraping domain ne pouvait pas retrouver le chapitre
(SQLSTATE 22P02 : invalid input syntax for type integer).

- ChapterSynchronizationServiceInterface : retourne float[] (numéros) au lieu de string[] (UUID)
- MangadxChapterSynchronizationService : retourne getNumber() au lieu de getId()
- RefreshMangaChaptersHandler : après save(), retrouve chaque chapitre par manga+numéro
  via findChapterByMangaIdAndNumber() pour obtenir le vrai PK integer avant de dispatcher
  ChapterReadyForScraping
2026-03-27 15:03:05 +01:00
13eac6954d Merge pull request 'fix(monitoring): ajouter le handler Symfony manquant pour CheckMonitoredMangas' (#44) from fix/monitoring-missing-symfony-handler into main
All checks were successful
Deploy / deploy (push) Successful in 1m7s
Reviewed-on: #44
2026-03-27 14:36:25 +01:00
ext.jeremy.guillot@maxicoffee.domains
7e6bacd934 fix(monitoring): ajouter le handler Symfony manquant pour CheckMonitoredMangas
Sans ce wrapper #[AsMessageHandler], Messenger ne trouvait aucun handler pour
le message CheckMonitoredMangas — le scheduler et la commande console échouaient
silencieusement avec NoHandlerForMessageException.
2026-03-27 14:35:47 +01:00
d1279c90cc Merge pull request 'fix(deploy): corriger la race condition sur le cache prod au déploiement' (#43) from fix/deploy-cache-race-condition into main
All checks were successful
Deploy / deploy (push) Successful in 1m6s
Reviewed-on: #43
2026-03-27 14:29:06 +01:00
a0729d2e6e Merge branch 'main' into fix/deploy-cache-race-condition 2026-03-27 14:28:58 +01:00
ext.jeremy.guillot@maxicoffee.domains
f47d1a245f fix(deploy): corriger la race condition sur le cache prod au déploiement
L'entrypoint faisait rm -rf var/cache/prod puis lançait FrankenPHP.
FrankenPHP compilait partiellement le container DI pendant que le script
Deployer lançait aussi cache:clear → fichiers manquants → crash.

- entrypoint.sh : ajouter cache:warmup après rm -rf, avant exec FrankenPHP
  (l'entrypoint est séquentiel, FrankenPHP ne démarre qu'une fois le cache prêt)
- deploy.php : supprimer le docker exec cache:clear devenu inutile et dangereux
2026-03-27 14:28:30 +01:00
78cc83d465 Merge pull request 'feat(monitoring): ajouter une commande console pour déclencher le monitoring manuellement' (#42) from feat/monitoring-run-command into main
Some checks failed
Deploy / deploy (push) Failing after 1m7s
Reviewed-on: #42
2026-03-27 14:23:30 +01:00
7204ea7754 Merge branch 'main' into feat/monitoring-run-command 2026-03-27 14:23:21 +01:00
ext.jeremy.guillot@maxicoffee.domains
f42b5a9cf5 feat(monitoring): ajouter une commande console pour déclencher le monitoring manuellement
Permet de tester le scheduler en prod sans attendre le cycle de 2h :
  make sf c="app:monitoring:run"
2026-03-27 14:21:05 +01:00
5edd28309f Merge pull request 'fix(monitoring): corriger le scheduler qui ne détectait plus les nouveaux chapitres' (#41) from fix/monitoring-scheduler-since-frozen into main
All checks were successful
Deploy / deploy (push) Successful in 1m8s
Reviewed-on: #41
2026-03-27 12:08:33 +01:00
ext.jeremy.guillot@maxicoffee.domains
3f08e1c899 fix(monitoring): corriger le scheduler qui ne détectait plus les nouveaux chapitres
- MonitoringSchedule : supprimer la date passée au message (était évaluée une
  seule fois au démarrage du container, rendant la requête caduque après le
  premier cycle)
- CheckMonitoredMangasHandler : calculer `since` dynamiquement à l'exécution
  (`new \DateTimeImmutable('-2 hours')`) plutôt que de dépendre du message
- AutoScrapingListener : corriger le TypeError silencieux — créer un ScrapingJob
  avant d'appeler ScrapeChapterHandler (paramètre jobId manquant)

Ajoute les tests unitaires CheckMonitoredMangasHandlerTest et AutoScrapingListenerTest.
2026-03-27 12:08:06 +01:00
214f470e77 Merge pull request 'fix(manga): afficher le titre du chapitre téléchargé individuellement' (#40) from fix/chapter-title-downloaded into main
All checks were successful
Deploy / deploy (push) Successful in 1m9s
Reviewed-on: #40
2026-03-27 11:30:16 +01:00
ext.jeremy.guillot@maxicoffee.domains
345434c25d fix(manga): afficher le titre du chapitre téléchargé individuellement
Quand un chapitre téléchargé est seul dans son groupe (volumeChapterCount === 1),
on affichait "Chapitre 42" au lieu du titre réel. La condition isVolumeGroup
s'appliquait même pour les groupes à un seul élément.

Fix : la mise en forme "Chapitres X-Y" n'est désormais appliquée que lorsque
volumeChapterCount > 1, sinon on affiche chapter.title comme pour les chapitres
non téléchargés.
2026-03-27 11:29:13 +01:00
2868772f5c Merge pull request 'fix(deploy): vider le cache prod au démarrage du conteneur' (#39) from fix/entrypoint-clear-cache into main
All checks were successful
Deploy / deploy (push) Successful in 1m9s
Reviewed-on: #39
2026-03-26 18:50:15 +01:00
a2469b6c07 Merge branch 'main' into fix/entrypoint-clear-cache 2026-03-26 18:50:08 +01:00
ext.jeremy.guillot@maxicoffee.domains
926f938c45 fix(deploy): vider le cache prod au démarrage du conteneur
Sans ce fix, les workers FrankenPHP démarrent avec l'ancien cache persisté
dans le volume Docker. Si les classes référencées (ex. EntityManagerGhost,
LazyGhostTrait) ne correspondent plus à la version déployée, les workers
crashent en boucle, rendant le conteneur instable et faisant échouer le
cache:clear lancé ensuite par Deployer (exit 137).

La suppression de var/cache/prod à l'entrypoint garantit que les workers
démarrent toujours sur un cache vierge, généré à chaud à la première requête.
2026-03-26 18:49:30 +01:00
5551d73962 Merge pull request 'fix: limiter les workers FrankenPHP et nettoyer le Dockerfile' (#38) from fix/cache-clear-oom into main
Some checks failed
Deploy / deploy (push) Failing after 35s
Reviewed-on: #38
2026-03-26 18:44:26 +01:00
395a0a16cb Merge branch 'main' into fix/cache-clear-oom 2026-03-26 18:44:17 +01:00
ext.jeremy.guillot@maxicoffee.domains
8e2e608ad9 fix: limiter les workers FrankenPHP et nettoyer le Dockerfile
- worker.Caddyfile : limiter à 2 workers FrankenPHP pour éviter l'OOM
  lors du cache:clear en prod (chaque worker charge le kernel Symfony
  complet, la valeur par défaut = nb de CPUs était trop élevée)
- Dockerfile : supprimer les COPY des assets UX (ux-live-component,
  ux-react, ux-turbo) supprimés de composer.json
2026-03-26 18:43:51 +01:00
0f80cb9fec Merge pull request 'fix(doctrine): supprimer auto_generate_proxy_classes et proxy_dir' (#37) from fix/doctrine-orm3-config into main
Some checks failed
Deploy / deploy (push) Failing after 36s
Reviewed-on: #37
2026-03-26 18:39:56 +01:00
a3477629fb Merge branch 'main' into fix/doctrine-orm3-config 2026-03-26 18:39:51 +01:00
ext.jeremy.guillot@maxicoffee.domains
cde701986e fix(doctrine): supprimer auto_generate_proxy_classes et proxy_dir
Ces options ont été supprimées de Doctrine Bundle 3.x / ORM 3.x.
Elles causaient une erreur "Unrecognized options" au cache:clear en prod.
2026-03-26 18:39:22 +01:00
b921768aef Merge pull request 'chore: supprimer les dépendances Twig/Stimulus/React/Turbo inutilisées' (#36) from chore/cleanup-unused-dependencies into main
Some checks failed
Deploy / deploy (push) Failing after 1m10s
Reviewed-on: #36
2026-03-26 18:36:11 +01:00
ext.jeremy.guillot@maxicoffee.domains
5f0178f784 chore: supprimer les dépendances Twig/Stimulus/React/Turbo inutilisées
PHP : suppression de symfony/stimulus-bundle, ux-live-component, ux-react,
ux-turbo, twig/extra-bundle et symfony/form (plus utilisés depuis la
migration vers Vue.js SPA).

npm : suppression de @hotwired/stimulus, @hotwired/turbo, react, react-dom,
alpinejs, bootstrap, daisyui, sortablejs, vuedraggable et leurs types.
Corrige l'erreur de déploiement causée par vitest@^4.1.0 (introuvable)
requis par les anciens packages @symfony/ux-react et @symfony/ux-turbo v2.33.0.
2026-03-26 18:35:40 +01:00
c610d22bd2 Merge pull request 'feature/upgrade-symfony-8' (#35) from feature/upgrade-symfony-8 into main
Some checks failed
Deploy / deploy (push) Failing after 21s
Reviewed-on: #35
2026-03-26 18:23:13 +01:00
ab2cf319ac Merge branch 'main' into feature/upgrade-symfony-8 2026-03-26 18:23:07 +01:00
ext.jeremy.guillot@maxicoffee.domains
69c6757cf8 fix: corriger l'erreur HTTP 400 sur les endpoints content-sources POST/PUT
- ContentSourceForm.vue : convertir testChapterNumber en float/null avant
  envoi (évite d'envoyer "" pour ?float, rejeté par Symfony 8 strict)
- UpsertContentSourceResource : ajouter collectDenormalizationErrors: true
  pour que les erreurs de type retournent 422 au lieu de 400 via le
  chemin input: de API Platform 4
- ContentSource entity : corriger setImageSelector(string) → setImageSelector(?string)
  cohérent avec la colonne nullable
- Ajouter les tests manquants (testChapterNumber float/null/chaîne vide)
  qui auraient détecté ces bugs plus tôt
2026-03-26 18:22:31 +01:00
ext.jeremy.guillot@maxicoffee.domains
21d8111734 fix: migrer les données manga.genres de PHP sérialisé vers JSON
La migration vers DBAL 4 a changé le type de colonne genres de
Types::ARRAY (PHP sérialisé) vers Types::JSON. Les données existantes
en base doivent être converties via preUp() avant l'ALTER TABLE.
2026-03-26 17:58:07 +01:00
ext.jeremy.guillot@maxicoffee.domains
5ed303612a feat: migrer vers Symfony 8, PHP 8.4 et les dépendances majeures associées
- PHP 8.3 → 8.4 (Dockerfile + composer.json)
- Symfony 7.0 → 8.0 (tous les composants symfony/*)
- API Platform 3.x → 4.x : migration openapiContext → openapi: new Operation(...)
- Doctrine DBAL 3 → 4 : suppression use_savepoints, replace prepare/executeQuery
- Doctrine ORM 2.x → 3.x : ClassMetadataInfo → ClassMetadata, setParameters → setParameter
- Doctrine Bundle 2.x → 3.x, Fixtures Bundle 3.x → 4.x
- zenstruck/foundry 1.x → 2.x : ModelFactory → PersistentObjectFactory, getDefaults → defaults
- phpmd/phpmd 2.x → 3.x-dev (seule version supportant Symfony 8)
- phparkitect 0.3 → 0.8 : NotDependsOnTheseNamespaces prend un array
- symfony/mercure-bundle 0.3 → 0.4, symfony/monolog-bundle 3 → 4
- Suppression de runtime/frankenphp-symfony (intégré nativement dans symfony/runtime 8)
- worker.Caddyfile : suppression de APP_RUNTIME (détection automatique Symfony 8)
- Routes errors.xml/wdt.xml/profiler.xml → .php (Symfony 8 supprime le XML)
- Types::ARRAY → Types::JSON dans Entity/Manga.php (DBAL 4 retire array type)
- Suppression de src/Schedule.php (doublon vide avec MonitoringSchedule)
- Tests : hydra:Collection → Collection, hydra:member → member (API Platform 4)
2026-03-26 17:55:12 +01:00
4e30af6a16 Merge pull request 'refactor: supprimer tout le code legacy MVC/Twig/Stimulus' (#34) from refactor/remove-legacy-code into main
All checks were successful
Deploy / deploy (push) Successful in 1m7s
Reviewed-on: #34
2026-03-26 17:01:34 +01:00
ext.jeremy.guillot@maxicoffee.domains
5a0888eb28 refactor: supprimer tout le code legacy MVC/Twig/Stimulus
Supprime toutes les couches pré-DDD pour ne garder que l'architecture
hexagonale (src/Domain/), les entités Doctrine et le front Vue.js SPA.

Supprimé :
- src/Controller/ (9 controllers Twig, garde SecurityController)
- src/Service/, src/Message/, src/MessageHandler/ (services et messages legacy)
- src/Manager/, src/Twig/, src/Form/ (UI legacy)
- src/Event/, src/EventListener/, src/EventSubscriber/QueueStatusSubscriber
- src/Client/MangadexClient.php (doublon du Domain)
- src/Interface/, src/Factory/, src/DataFixtures/, src/Scheduler/MainSchedule
- templates/ (tous sauf vue/ et base retiré — SecurityController = pur JSON)
- assets/controllers/ (20 Stimulus controllers), app.js, bootstrap.js, controllers.json

Modifié :
- config/routes.yaml : suppression du chargement des controllers legacy
- config/packages/messenger.yaml : suppression des routes legacy
- config/services.yaml : suppression des bindings legacy + entrées Domain\Import fantômes
- webpack.config.js : suppression entry 'app' et enableStimulusBridge
- src/Entity/Chapter.php : suppression #[Broadcast] (Turbo Streams legacy)

Déplacé :
- src/Factory/*.php → tests/Factory/ (namespace App\Tests\Factory)
2026-03-26 17:00:46 +01:00
d7e6bf56d0 Merge pull request 'fix(layout): corriger la barre blanche en bas sur mobile réel' (#33) from fix/mobile-dvh-viewport into main
All checks were successful
Deploy / deploy (push) Successful in 1m12s
Reviewed-on: #33
2026-03-26 16:35:29 +01:00
17d44f68e5 Merge branch 'main' into fix/mobile-dvh-viewport 2026-03-26 16:35:22 +01:00
ext.jeremy.guillot@maxicoffee.domains
90d6feee2d fix(layout): corriger la barre blanche en bas sur mobile réel
Sur un vrai appareil mobile, 100vh inclut le chrome du navigateur
(barre de navigation), ce qui cachait le contenu en bas.
- Remplace h-screen (100vh) par h-[100dvh] (dynamic viewport height)
- Ajoute viewport-fit=cover pour préparer le support safe-area iOS
2026-03-26 16:35:00 +01:00
0880a77546 Merge pull request 'fix(layout): corriger le scroll coupé sur mobile' (#32) from fix/mobile-scroll-layout into main
All checks were successful
Deploy / deploy (push) Successful in 1m12s
Reviewed-on: #32
2026-03-26 16:27:18 +01:00
ext.jeremy.guillot@maxicoffee.domains
9926da6730 fix(layout): corriger le scroll coupé sur mobile
RouterView n'avait pas de contrainte de hauteur dans le flex-col de main,
empêchant overflow-y-auto de se déclencher. Le contenu dépassait la hauteur
de main.overflow-hidden et était silencieusement tronqué sur mobile.
2026-03-26 16:25:36 +01:00
4c80aa6b42 Merge pull request 'fix(reader): corriger le scroll vers le haut bloqué en mode infini' (#31) from fix/reader-infinite-scroll-up into main
All checks were successful
Deploy / deploy (push) Successful in 1m12s
Reviewed-on: #31
2026-03-26 16:11:50 +01:00
c0307a9173 Merge branch 'main' into fix/reader-infinite-scroll-up 2026-03-26 16:11:43 +01:00
ext.jeremy.guillot@maxicoffee.domains
45f7e88024 fix(reader): corriger le scroll vers le haut bloqué en mode infini
Les IntersectionObserver utilisaient root: null (viewport) au lieu du
conteneur de scroll réel (.infinite-reader). Le rootMargin de 1000px
était donc calculé par rapport au viewport, causant un montage/démontage
des pages à des moments imprécis et des sauts de layout lors du scroll
vers le haut.

Supprime également scroll-behavior: smooth sur le conteneur, qui entrait
en conflit avec le scroll anchoring du navigateur lors des corrections de
position, donnant l'impression que le scroll redescendait tout seul.
2026-03-26 16:11:19 +01:00
507fac5b5e Merge pull request 'fix(reader): corriger le chevauchement des pages en mode scroll avec zoom' (#30) from fix/reader-zoom-overlap-mobile into main
All checks were successful
Deploy / deploy (push) Successful in 1m19s
Reviewed-on: #30
2026-03-26 15:58:06 +01:00
071e12a06c Merge branch 'main' into fix/reader-zoom-overlap-mobile 2026-03-26 15:57:51 +01:00
ext.jeremy.guillot@maxicoffee.domains
59f72339fa fix(reader): corriger le chevauchement des pages en mode scroll avec zoom
En mode scroll infini, le zoom était appliqué via transform: scale() qui
n'affecte pas le flux de mise en page. Les pages se chevauchaient visuellement
quand le zoom était modifié. Passage à la propriété CSS zoom dans les deux
modes pour un comportement de layout correct.

Met aussi à jour le calcul de hauteur des placeholders pour inclure le
facteur de zoom et éviter les sauts de layout lors du chargement paresseux.
2026-03-26 15:56:18 +01:00
3963efa986 Merge pull request 'feat(system): page Status avec endpoint API Platform et composants Vue' (#29) from feat/system-status-page into main
All checks were successful
Deploy / deploy (push) Successful in 2m33s
Reviewed-on: #29
2026-03-17 22:05:27 +01:00
ext.jeremy.guillot@maxicoffee.domains
ca8791cc0d feat(system): page Status avec endpoint API Platform et composants Vue
- Nouveau domaine System/Domain/Model/SystemStatus (value object)
- QueryHandler agrégeant métriques mangas, chapitres, jobs (global/24h/7j), stockage et sources
- Endpoint GET /api/system/status via API Platform (singleton)
- Calcul de l'espace disque par RecursiveDirectoryIterator sur public/images
- Page Vue /system/status avec 6 cards (Mangas, Chapitres, Jobs, Stockage, Sources, Système)
- Nettoyage du router : suppression des PlaceholderComponent et routes placeholder
- Sidebar : suppression des entrées sans page réelle
2026-03-17 22:04:48 +01:00