♻️ refactor : externaliser utilitaires string et time

- Déplacer la fonction `simpleHash` de useCoverImage.ts vers un nouveau fichier utils/string.ts
- Déplacer la logique d'analyse des durées HH:MM[:SS] vers un nouveau fichier utils/time.ts
- Créer les fonctions utilitaires `addCacheBust`, `normalizeUrl` et `truncate`
- Mettre à jour les imports dans useCoverImage.ts,useRenderers.ts
-Rendre le code plus réutilisable et maintenable
This commit is contained in:
2026-04-03 22:52:48 +02:00
parent 5d081654ef
commit bf03c56649
4 changed files with 117 additions and 38 deletions

View File

@@ -9,6 +9,7 @@
*/
import { ref, watch, computed, type Ref } from "vue";
import { imageCache, useImageCache } from "./imageCache";
import { simpleHash } from "../utils/string";
export interface CoverImageOptions {
maxRetries?: number;
@@ -44,17 +45,6 @@ export function useCoverImage(
// Computed: synchroniser avec le cache centralisé
// Note: on garde le controle local du loaded/error pour éviter les effets de bord
// Fonction de hash simple pour le cache-busting
function simpleHash(str: string): string {
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash = hash & hash;
}
return Math.abs(hash).toString(36);
}
// Génère une URL avec cache-busting
function getCacheBustedUrl(url: string, retry: number): string {
if (!forceReload && retry === 0) {

View File

@@ -8,6 +8,7 @@ import { ref, reactive, computed, toRaw, type Ref } from "vue";
import { api } from "../services/pmocontrol/api";
import { useSSE } from "./useSSE";
import { apiCache } from "./apiCache";
import { parseTimeToMs } from "../utils/time";
import type {
RendererSummary,
RendererState,
@@ -125,35 +126,14 @@ function ensureSSEInitialized() {
// Le backend envoie TOUJOURS les deux valeurs (même si null)
// Convertir rel_time (HH:MM:SS) en millisecondes
if (event.rel_time) {
const parts = event.rel_time.split(":").map(Number);
if (parts.length === 3) {
snapshot.state.position_ms =
((parts[0] ?? 0) * 3600 +
(parts[1] ?? 0) * 60 +
(parts[2] ?? 0)) *
1000;
}
} else {
// Si rel_time est null/undefined, mettre position à 0
snapshot.state.position_ms = 0;
}
const positionMs = parseTimeToMs(event.rel_time ?? null);
snapshot.state.position_ms = positionMs ?? 0;
// Convertir track_duration (HH:MM:SS) en millisecondes
if (event.track_duration) {
const parts = event.track_duration.split(":").map(Number);
if (parts.length === 3) {
snapshot.state.duration_ms =
((parts[0] ?? 0) * 3600 +
(parts[1] ?? 0) * 60 +
(parts[2] ?? 0)) *
1000;
}
} else {
// Si track_duration est null/undefined (flux continu sans durée),
// mettre duration_ms à null pour afficher "--:--"
snapshot.state.duration_ms = null;
}
const durationMs = parseTimeToMs(event.track_duration ?? null);
// Si track_duration est null/undefined (flux continu sans durée),
// mettre duration_ms à null pour afficher "--:--"
snapshot.state.duration_ms = durationMs;
// Important: Trigger reactivity en réassignant l'objet complet avec deep copy
// Le shallow copy ne suffit pas car snapshot.state est partagé entre renderers