Files
pmomusic/pmoapp/webapp/src/composables/useMediaServers.ts
Eric Coissac 86df772354 Remove unnecessary console logs
This commit removes various console.log statements that were used for debugging purposes. These logs clutter the output and provide no value in production. The changes affect multiple files including components and composables related to media control and rendering.
2026-02-21 15:23:54 +01:00

215 lines
5.6 KiB
TypeScript

/**
* Composable pour gérer les media servers
* Architecture simple : l'API est la source de vérité, SSE invalide le cache
*/
import { ref, computed } from 'vue'
import { api } from '../services/pmocontrol/api'
import { sse } from '../services/pmocontrol/sse'
import type {
MediaServerSummary,
BrowseResponse
} from '../services/pmocontrol/types'
export interface BreadcrumbItem {
id: string
title: string
}
// Cache global partagé
const serversCache = ref<Map<string, MediaServerSummary>>(new Map())
const browseCache = ref<Map<string, BrowseResponse>>(new Map())
const currentPath = ref<BreadcrumbItem[]>([])
// Timestamps
const lastFetch = {
servers: 0
}
const CACHE_DURATION_MS = 2000
// Connecter SSE une seule fois
let sseConnected = false
function ensureSSEConnected() {
if (sseConnected) return
sse.onMediaServerEvent((event) => {
const serverId = event.server_id
switch (event.type) {
case 'online':
// Ajouter au cache avec les infos disponibles
const server: MediaServerSummary = {
id: serverId,
friendly_name: event.friendly_name,
model_name: event.model_name,
online: true,
}
serversCache.value.set(serverId, server)
// Fetch la liste complète pour avoir les bonnes infos
// On ne le fait pas ici car on pourrait déclencher trop de requêtes
// La liste se mettra à jour au prochain refresh automatique
break
case 'offline':
// Marquer comme offline dans le cache
const existingServer = serversCache.value.get(serverId)
if (existingServer) {
existingServer.online = false
serversCache.value.set(serverId, existingServer)
}
// Invalider tout le cache browse de ce serveur
const keysToDelete: string[] = []
browseCache.value.forEach((_, key) => {
if (key.startsWith(serverId + '/')) {
keysToDelete.push(key)
}
})
keysToDelete.forEach(key => browseCache.value.delete(key))
break
case 'global_updated':
// Invalider tout le cache de ce serveur
const globalKeysToDelete: string[] = []
browseCache.value.forEach((_, key) => {
if (key.startsWith(serverId + '/')) {
globalKeysToDelete.push(key)
}
})
globalKeysToDelete.forEach(key => browseCache.value.delete(key))
break
case 'containers_updated':
// Invalider les containers spécifiques
event.container_ids.forEach(containerId => {
const key = `${serverId}/${containerId}`
browseCache.value.delete(key)
})
break
}
})
sseConnected = true
}
/**
* Composable principal pour gérer les media servers
*/
export function useMediaServers() {
ensureSSEConnected()
const loading = ref(false)
const error = ref<string | null>(null)
// Getters computed
const allServers = computed(() => Array.from(serversCache.value.values()))
const onlineServers = computed(() => allServers.value.filter(s => s.online))
// Fetch servers list
async function fetchServers(force = false) {
const now = Date.now()
if (!force && now - lastFetch.servers < CACHE_DURATION_MS) {
return // Cache encore valide
}
try {
loading.value = true
error.value = null
const data = await api.getServers()
serversCache.value.clear()
data.forEach(s => serversCache.value.set(s.id, s))
lastFetch.servers = now
} catch (e) {
error.value = e instanceof Error ? e.message : 'Erreur fetch servers'
console.error('[useMediaServers] Erreur fetch:', e)
} finally {
loading.value = false
}
}
// Browse container (avec cache automatique)
async function browseContainer(serverId: string, containerId: string, useCache = true) {
const key = `${serverId}/${containerId}`
// Vérifier le cache
if (useCache && browseCache.value.has(key)) {
return browseCache.value.get(key)!
}
try {
loading.value = true
error.value = null
const data = await api.browseContainer(serverId, containerId)
// Mettre en cache
browseCache.value.set(key, data)
return data
} catch (e) {
error.value = e instanceof Error ? e.message : 'Erreur browse container'
console.error(`[useMediaServers] Erreur browse ${serverId}/${containerId}:`, e)
throw e
} finally {
loading.value = false
}
}
// Getters
function getServerById(id: string) {
return serversCache.value.get(id)
}
function getBrowseCached(serverId: string, containerId: string) {
const key = `${serverId}/${containerId}`
return browseCache.value.get(key)
}
// Breadcrumb path management
function setPath(path: BreadcrumbItem[]) {
currentPath.value = path
}
function clearPath() {
currentPath.value = []
}
// Invalidation du cache
function invalidateCache(serverId: string, containerId?: string) {
if (containerId) {
// Invalider un container spécifique
const key = `${serverId}/${containerId}`
browseCache.value.delete(key)
} else {
// Invalider tous les containers d'un serveur
const keysToDelete: string[] = []
browseCache.value.forEach((_, key) => {
if (key.startsWith(serverId + '/')) {
keysToDelete.push(key)
}
})
keysToDelete.forEach(key => browseCache.value.delete(key))
}
}
return {
// État
loading,
error,
currentPath,
// Getters
allServers,
onlineServers,
getServerById,
getBrowseCached,
// Actions
fetchServers,
browseContainer,
setPath,
clearPath,
invalidateCache
}
}