/** * Device state collector — memory, battery, storage, network * * @module device */ import type { DeviceState } from './types.js'; // DOM type declarations for ESLint type Navigator = { onLine: boolean; connection?: { effectiveType?: string }; getBattery?: () => Promise<{ charging: boolean; level: number }>; storage?: { estimate(): Promise<{ usage?: number }> }; }; declare const navigator: Navigator; declare const performance: { memory?: { usedJSHeapSize: number } }; interface Window { addEventListener: (type: string, listener: () => void) => void; removeEventListener: (type: string, listener: () => void) => void; } declare const window: Window; /** * Collect current device state * Best-effort: some APIs may not be available in all environments */ export function collectDeviceState(): DeviceState { const state: DeviceState = { isOnline: navigator.onLine ?? true, }; // Network type (experimental API) const connection = (navigator as { connection?: { effectiveType?: string } }).connection; if (connection) { state.networkType = connection.effectiveType ?? 'unknown'; } // Battery API (experimental, not widely supported) // Note: Battery API is deprecated but still useful for diagnostics const battery = ( navigator as { getBattery?: () => Promise<{ charging: boolean; level: number }> } ).getBattery; if (battery) { // We'll return a promise, but sync API can't wait // Store last known value if available } // Memory (Chrome-only experimental) const memory = (performance as { memory?: { usedJSHeapSize: number } }).memory; if (memory) { state.memoryMB = Math.round(memory.usedJSHeapSize / 1024 / 1024); } // Storage (async, but we'll fire-and-forget) if (navigator.storage && navigator.storage.estimate) { navigator.storage .estimate() .then(estimate => { if (estimate.usage !== undefined) { state.storageMB = Math.round(estimate.usage / 1024 / 1024); } }) .catch(() => { // Ignore errors }); } return state; } /** * Subscribe to online/offline events */ export function subscribeToConnectivity(callback: (isOnline: boolean) => void): () => void { const handleOnline = () => callback(true); const handleOffline = () => callback(false); window.addEventListener('online', handleOnline); window.addEventListener('offline', handleOffline); return () => { window.removeEventListener('online', handleOnline); window.removeEventListener('offline', handleOffline); }; }