Files
nessar d53efb4be6 feat: rewrite the companion interface with Vue 3 and Vite (#14)
Move the interface sources to web/ (Vue 3 single-file components, a
reactive store, framework-free modules) and assemble them with Vite into
fixed asset names under the gitignored src/Compagnon/Web/, embedded in
the single plugin DLL. Templates are precompiled, no router or Pinia is
added and no inline script is emitted, so the script-src 'self' policy
still holds.

Extract the delicate logic - position estimation with its freshness
bounds and seeded window, history selection, help overlap, subtitle
validation and ASS cleanup, saved connection parsing - into modules
tested without a browser by node:test, injecting the clocks.

Build the interface in scripts/package.sh before the C# compile, bump
the plugin to 0.7.0, switch npm run typecheck to vue-tsc and document the
Vite dev proxy flow in the README.

Prove parity with the untouched end-to-end suite: 34 tests on the
disposable server with and without the /jellyfin prefix, stable gap
within 330 ms and seek recovery within 789 ms against the burnt-in
timecode. Record the decision in docs/adr/0003 and the evidence in
docs/validation/issue-14.md.
2026-09-18 14:21:04 +02:00

3.4 KiB
Raw Permalink Blame History

Validation de la réécriture de l'interface — Vue 3 + Vite

Protocole

Paquet 0.7.0, Jellyfin Server 12.0.0 (image figée dans tests/run.sh), Jellyfin Web de cette image, Chromium 149.0.7827.55, Playwright 1.61.1, Node.js 24.18.0, Vue 3.5.24, Vite 7.3.6, TypeScript 5.9.3. Compagnon de 375 × 812 pixels, hébergement sans préfixe puis suite complète sous /jellyfin.

npm run typecheck
npm run test:unit
bash tests/run.sh

Aucun test de la suite existante n'a été modifié : history, bilingual, quick-connect, recovery et installed sont ceux du dépôt, seule la référence à l'archive dans tests/run.sh suit la version 0.7.0.

Architecture livrée

L'interface vit dans web/ : composants monofichiers Vue assemblés par Vite, écrits en TypeScript, sans router ni Pinia. La logique délicate est extraite dans web/src/lib/ — estimation de position, fraîcheur des observations, sélection de l'historique, chevauchement de l'aide, validation et nettoyage des pistes, lecture de la connexion conservée — et testée sans navigateur par node:test avec des horloges injectées. Le magasin réactif (web/src/store.ts) reste une transposition des flux de l'ancien app.js : mêmes gardes de génération, mêmes bornes, mêmes messages.

La construction produit des noms fixes (index.html, app.js, style.css) dans src/Compagnon/Web/, dossier généré et ignoré par Git, embarqué tel quel dans le DLL. scripts/package.sh construit l'interface puis compile C#. L'index généré ne contient aucun script en ligne, compatible avec la CSP script-src 'self' du contrôleur. Le bundle pèse 75,85 kB (29,65 kB compressés).

Résultats

Exécution complète du 18 septembre 2026 :

Vérification Résultat
npm run typecheck (vue-tsc) 0 erreur
npm run test:unit 21 tests sur 21
npm audit 0 vulnérabilité
Compilation C# Release 0 erreur, 0 avertissement
bash tests/run.sh 34 tests sur 34, 131,4 s

Les contrôles installés passent avec et sans préfixe /jellyfin. La parité DOM est vérifiée par la suite existante : identifiants et classes (#status, #details, #history .main-block, .help-block, #sessions, #tracks, #help-tracks), libellés accessibles, focus après approbation, à l'expiration d'un code et à la déconnexion, options de pistes identiques entre les deux sélecteurs.

Les mesures de synchronisation contre le timecode incrusté restent dans les objectifs : écart maximal 330 ms en lecture stable à 1× (seuil 500 ms) et recalage après déplacement de 789 ms (seuil deux secondes), soit stablePass et seekPass vrais. Les extractions SRT, WebVTT et ASS restent du même ordre que le lot #5.

Limites

  • Aucun changement visuel : la refonte demandée reste un lot séparé (#15). Vite minifie la feuille servie (748 octets au lieu de 907), règles identiques.
  • La suite de tests de navigateur sert les fichiers générés depuis src/Compagnon/Web/ : exécuter un test sans npm run build préalable sert un dossier vide.
  • Le bundle d'interface est plus lourd que le script écrit à la main (75,85 kB contre 26,9 kB) ; il est mis en cache par le navigateur et la page reste publique, sans donnée supplémentaire exposée.
  • Les navigateurs antérieurs à AbortSignal.any restent hors périmètre, comme avant la réécriture.