61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
// UserActivityTracker.tsx
|
|
|
|
'use client'
|
|
|
|
import { useEffect, useRef } from 'react'
|
|
import { useSession } from 'next-auth/react'
|
|
|
|
type Presence = 'online' | 'away' | 'offline'
|
|
|
|
export default function UserActivityTracker() {
|
|
const { data: session } = useSession()
|
|
const lastActivityRef = useRef<number>(Date.now())
|
|
const prevStatusRef = useRef<Presence>('offline')
|
|
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null)
|
|
|
|
useEffect(() => {
|
|
if (!session?.user?.steamId) return
|
|
|
|
const markActive = () => { lastActivityRef.current = Date.now() }
|
|
|
|
const tick = () => {
|
|
const diffMs = Date.now() - lastActivityRef.current
|
|
const nextStatus: Presence = diffMs < 30_000 ? 'online' : 'away'
|
|
|
|
if (nextStatus !== prevStatusRef.current) {
|
|
prevStatusRef.current = nextStatus
|
|
fetch(nextStatus === 'online' ? '/api/user/activity' : '/api/user/away', { method: 'POST' })
|
|
.catch(() => {})
|
|
}
|
|
}
|
|
|
|
// Initial online
|
|
prevStatusRef.current = 'away'
|
|
markActive()
|
|
tick()
|
|
|
|
intervalRef.current = setInterval(tick, 5_000)
|
|
|
|
// Activity Events
|
|
window.addEventListener('mousemove', markActive)
|
|
window.addEventListener('keydown', markActive)
|
|
window.addEventListener('touchstart', markActive)
|
|
document.addEventListener('visibilitychange', () => {
|
|
if (!document.hidden) markActive()
|
|
})
|
|
|
|
return () => {
|
|
window.removeEventListener('mousemove', markActive)
|
|
window.removeEventListener('keydown', markActive)
|
|
window.removeEventListener('touchstart', markActive)
|
|
document.removeEventListener('visibilitychange', () => {
|
|
if (!document.hidden) markActive()
|
|
})
|
|
|
|
if (intervalRef.current) clearInterval(intervalRef.current)
|
|
}
|
|
}, [session?.user?.steamId])
|
|
|
|
return null
|
|
}
|