✅ fix(useRenderers): résoudre les problèmes de réactivité
- Supprimer l'import obsolète `toRaw` et simplifier les mises à jour via spread - Corriger la mutation directe de `state_changed` en créant des objets immutables + appel à trigger - Ajouter `triggerQueueReactivity()` pour déclencher la réactivité sur les événements queue - Mettre à jour le doc de revue frontend pour marquer toutes les tâches comme corrigées
This commit is contained in:
@@ -525,10 +525,15 @@ fait et ce qui reste à finir.
|
||||
|
||||
---
|
||||
|
||||
## Tâches restantes
|
||||
## Tâches restantes — ✅ Toutes corrigées (commit 2026-04-06)
|
||||
|
||||
Trois problèmes résiduels ont été introduits ou laissés lors de l'implémentation du commit
|
||||
ci-dessus. Ils doivent être corrigés.
|
||||
| # | Problème résiduel | État |
|
||||
|---|-------------------|------|
|
||||
| A | `state_changed` — mutation directe sans trigger réactivité | ✅ Corrigé (spread + `triggerSnapshotReactivity()`) |
|
||||
| B | `queue_refreshing`/`queue_updated` — `queueRefreshingIds` sans trigger | ✅ Corrigé (`triggerQueueReactivity()` ajoutée et appelée) |
|
||||
| C | `toRaw` import obsolète, `position_changed` simplifié | ✅ Corrigé (`toRaw` supprimé de l'import, spread direct) |
|
||||
|
||||
---
|
||||
|
||||
### A. `useRenderers.ts` — `state_changed` : mutation directe sans déclenchement de réactivité
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* - Les snapshots complets proviennent de /renderers/{id}/full
|
||||
* - Les événements SSE ne servent qu'à déclencher un refetch.
|
||||
*/
|
||||
import { ref, shallowRef, computed, toRaw, type Ref, onUnmounted } from "vue";
|
||||
import { ref, shallowRef, computed, type Ref, onUnmounted } from "vue";
|
||||
import { api } from "../services/pmocontrol/api";
|
||||
import { useSSE } from "./useSSE";
|
||||
import { apiCache } from "./apiCache";
|
||||
@@ -41,6 +41,10 @@ function triggerLoadingReactivity() {
|
||||
loadingIds.value = new Set(loadingIds.value);
|
||||
}
|
||||
|
||||
function triggerQueueReactivity() {
|
||||
queueRefreshingIds.value = new Set(queueRefreshingIds.value);
|
||||
}
|
||||
|
||||
const loading = ref(false);
|
||||
const error = ref<string | null>(null);
|
||||
|
||||
@@ -131,9 +135,13 @@ function ensureSSEInitialized() {
|
||||
// Sinon, mettre à jour le snapshot localement selon le type d'événement
|
||||
switch (event.type) {
|
||||
case "state_changed":
|
||||
// Utiliser le guard de type pour valider le transport_state
|
||||
// Créer un nouvel objet pour déclencher la réactivité
|
||||
if (isTransportState(event.state)) {
|
||||
snapshot.state.transport_state = event.state;
|
||||
snapshots.value.set(rendererId, {
|
||||
...snapshot,
|
||||
state: { ...snapshot.state, transport_state: event.state },
|
||||
});
|
||||
triggerSnapshotReactivity();
|
||||
} else {
|
||||
console.warn(`[useRenderers] transport_state inconnu: ${event.state}`);
|
||||
}
|
||||
@@ -145,27 +153,20 @@ function ensureSSEInitialized() {
|
||||
|
||||
// Convertir rel_time (HH:MM:SS) en millisecondes
|
||||
const positionMs = parseTimeToMs(event.rel_time ?? null);
|
||||
snapshot.state.position_ms = positionMs ?? 0;
|
||||
|
||||
// Convertir track_duration (HH:MM:SS) en millisecondes
|
||||
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
|
||||
// Il faut copier state aussi pour éviter que les modifications d'un renderer
|
||||
// n'affectent les autres renderers
|
||||
// IMPORTANT: Utiliser toRaw() pour obtenir l'objet brut non-réactif avant de copier
|
||||
// sinon Vue copie les getters réactifs qui continuent à pointer vers l'objet d'origine
|
||||
const rawState = toRaw(snapshot.state);
|
||||
const newState = { ...rawState };
|
||||
const newSnapshot = {
|
||||
|
||||
// Créer un nouvel objet pour déclencher la réactivité
|
||||
snapshots.value.set(rendererId, {
|
||||
...snapshot,
|
||||
state: newState,
|
||||
};
|
||||
snapshots.value.set(rendererId, newSnapshot);
|
||||
state: {
|
||||
...snapshot.state,
|
||||
position_ms: positionMs ?? 0,
|
||||
duration_ms: durationMs,
|
||||
},
|
||||
});
|
||||
triggerSnapshotReactivity();
|
||||
break;
|
||||
|
||||
case "volume_changed":
|
||||
@@ -206,11 +207,13 @@ function ensureSSEInitialized() {
|
||||
|
||||
case "queue_refreshing":
|
||||
queueRefreshingIds.value.add(rendererId);
|
||||
triggerQueueReactivity();
|
||||
break;
|
||||
|
||||
case "queue_updated":
|
||||
snapshot.state.queue_len = event.queue_length;
|
||||
queueRefreshingIds.value.delete(rendererId);
|
||||
triggerQueueReactivity();
|
||||
// Pour la queue complète, on doit refetch
|
||||
void fetchRendererSnapshot(rendererId, { force: true });
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user