/** * Composable para manejar el estado de presencia del usuario * Inspirado en Windows Live Messenger */ export type PresenceStatus = 'online' | 'away' | 'busy' | 'offline' interface PresenceConfig { light: string // Color para el highlight (top-left) medium: string // Color medio dark: string // Color para la sombra (bottom-right) } export const PRESENCE_COLORS: Record = { online: { light: '#CCFF99', medium: '#66CC33', dark: '#339900' }, away: { light: '#FFE699', medium: '#FFCC33', dark: '#FF9900' }, busy: { light: '#FF9999', medium: '#FF3333', dark: '#CC0000' }, offline: { light: '#CCCCCC', medium: '#999999', dark: '#666666' } } export const usePresence = () => { const status = useState('userPresenceStatus', () => 'online') const lastActivity = useState('lastActivity', () => Date.now()) // Configuración de tiempos (en milisegundos) const AWAY_TIMEOUT = 5 * 60 * 1000 // 5 minutos de inactividad = Away let inactivityTimer: NodeJS.Timeout | null = null // Actualizar última actividad const updateActivity = () => { lastActivity.value = Date.now() // Si estaba away y el usuario vuelve a estar activo, ponerlo online if (status.value === 'away') { status.value = 'online' } resetInactivityTimer() } // Resetear el timer de inactividad const resetInactivityTimer = () => { if (inactivityTimer) { clearTimeout(inactivityTimer) } // Solo en el cliente if (import.meta.client) { inactivityTimer = setTimeout(() => { // Solo cambiar a away si está online if (status.value === 'online') { status.value = 'away' } }, AWAY_TIMEOUT) } } // Cambiar estado manualmente const setStatus = (newStatus: PresenceStatus) => { status.value = newStatus // Si se cambia manualmente, resetear el timer if (newStatus === 'online') { resetInactivityTimer() } else if (inactivityTimer) { // Si se pone busy o offline manualmente, cancelar el timer de away clearTimeout(inactivityTimer) inactivityTimer = null } } // Obtener los colores del estado actual const colors = computed(() => PRESENCE_COLORS[status.value]) // Inicializar listeners de actividad (solo en cliente) const initActivityListeners = () => { if (import.meta.client) { const events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart', 'click'] events.forEach(event => { document.addEventListener(event, updateActivity, { passive: true }) }) // Iniciar el timer resetInactivityTimer() // Cleanup cuando se desmonte onUnmounted(() => { events.forEach(event => { document.removeEventListener(event, updateActivity) }) if (inactivityTimer) { clearTimeout(inactivityTimer) } }) } } return { status: readonly(status), colors, setStatus, updateActivity, initActivityListeners, PRESENCE_COLORS } }