45 lines
1.2 KiB
TypeScript
45 lines
1.2 KiB
TypeScript
'use client';
|
|
|
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
|
|
type Typer = { userId: string; userName: string; expiresAt: number };
|
|
|
|
export function useChatTyping(currentUserId?: string) {
|
|
const [typers, setTypers] = useState<Typer[]>([]);
|
|
const timerRef = useRef<number | null>(null);
|
|
|
|
const pruneTypers = useCallback(() => {
|
|
const now = Date.now();
|
|
setTypers((current) => current.filter((item) => item.expiresAt > now));
|
|
}, []);
|
|
|
|
const registerTyper = useCallback(
|
|
(userId: string, userName: string) => {
|
|
if (!userId || userId === currentUserId) return;
|
|
const expiresAt = Date.now() + 3000;
|
|
setTypers((current) => {
|
|
const without = current.filter((item) => item.userId !== userId);
|
|
return [...without, { userId, userName, expiresAt }];
|
|
});
|
|
},
|
|
[currentUserId]
|
|
);
|
|
|
|
const clearTypers = useCallback(() => {
|
|
setTypers([]);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
timerRef.current = window.setInterval(pruneTypers, 500);
|
|
return () => {
|
|
if (timerRef.current) window.clearInterval(timerRef.current);
|
|
};
|
|
}, [pruneTypers]);
|
|
|
|
return {
|
|
typers: typers.map(({ userId, userName }) => ({ userId, userName })),
|
|
registerTyper,
|
|
clearTypers
|
|
};
|
|
}
|