/** * Fetches devices + live sessions (unified cameras). Optionally polls when tab is visible. */ const POLL_MS = 1500 export function useCameras(options = {}) { const { poll: enablePoll = true } = options const { data, refresh } = useAsyncData( 'cameras', () => $fetch('/api/cameras').catch(() => ({ devices: [], liveSessions: [] })), { default: () => ({ devices: [], liveSessions: [] }) }, ) const pollInterval = ref(null) function startPolling() { if (!enablePoll || pollInterval.value) return refresh() pollInterval.value = setInterval(refresh, POLL_MS) } function stopPolling() { if (pollInterval.value) { clearInterval(pollInterval.value) pollInterval.value = null } } onMounted(() => { if (typeof document === 'undefined') return document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') { startPolling() refresh() } else { stopPolling() } }) if (document.visibilityState === 'visible') startPolling() }) onBeforeUnmount(stopPolling) const devices = computed(() => data.value?.devices ?? []) const liveSessions = computed(() => data.value?.liveSessions ?? []) /** All cameras: devices first, then live sessions */ const cameras = computed(() => [...devices.value, ...liveSessions.value]) return { data, devices, liveSessions, cameras, refresh, startPolling, stopPolling } }