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.
215 lines
5.6 KiB
TypeScript
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
|
|
}
|
|
}
|