Implementar avatar estilo Windows Live Messenger con sistema de presencia
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 55s
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 55s
- Agregar componente MsnAvatar con marco SVG de grosor variable - Implementar degradados radiales estilo Frutiger Aero - Agregar composable usePresence con detección de inactividad - Incluir selector de estados: Online, Away, Busy, Offline - Actualizar UserHeader para usar el nuevo avatar
This commit is contained in:
124
nuxt4/app/composables/usePresence.ts
Normal file
124
nuxt4/app/composables/usePresence.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* 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<PresenceStatus, PresenceConfig> = {
|
||||
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<PresenceStatus>('userPresenceStatus', () => 'online')
|
||||
const lastActivity = useState<number>('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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user