/** Fetches devices + live sessions; polls when tab visible. */ const POLL_MS = 1500 const EMPTY_RESPONSE = Object.freeze({ devices: [], liveSessions: [] }) export function useCameras(options = {}) { const { poll: enablePoll = true } = options const { data, refresh } = useAsyncData( 'cameras', () => $fetch('/api/cameras').catch(() => EMPTY_RESPONSE), { default: () => EMPTY_RESPONSE }, ) const devices = computed(() => Object.freeze([...(data.value?.devices ?? [])])) const liveSessions = computed(() => Object.freeze([...(data.value?.liveSessions ?? [])])) const cameras = computed(() => Object.freeze([...devices.value, ...liveSessions.value])) 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', () => { document.visibilityState === 'visible' ? (startPolling(), refresh()) : stopPolling() }) if (document.visibilityState === 'visible') startPolling() }) onBeforeUnmount(stopPolling) return Object.freeze({ data, devices, liveSessions, cameras, refresh, startPolling, stopPolling }) }