Files
glchat/web/src/lib/hooks.ts
T

53 lines
1.9 KiB
TypeScript
Raw Normal View History

import { useEffect, useState } from 'react';
import { useQuery, type UseQueryResult } from '@tanstack/react-query';
import { fetchInstance, instanceQueryKey } from '@/api/instance';
import { fetchCurrentUser, currentUserQueryKey } from '@/api/users';
import type { InstanceInfo, User } from '@/api/types';
/** Текущий пользователь: единственный источник правды о сессии (cookie). */
export function useCurrentUser(): UseQueryResult<User> {
return useQuery({
queryKey: currentUserQueryKey,
queryFn: ({ signal }) => fetchCurrentUser(signal),
retry: false,
staleTime: 30_000,
});
}
export function useInstance(): UseQueryResult<InstanceInfo> {
return useQuery({
queryKey: instanceQueryKey,
queryFn: ({ signal }) => fetchInstance(signal),
staleTime: 60_000,
});
}
/**
* Активно ли окно: вкладка видима и окно в фокусе.
*
* Нужен для отметки прочтения — `POST /ack` уходит только когда пользователь
* действительно смотрит на комнату.
*/
export function useWindowActive(): boolean {
const [active, setActive] = useState(
() => typeof document === 'undefined' || document.visibilityState !== 'hidden',
);
useEffect(() => {
const onFocus = (): void => setActive(true);
const onBlur = (): void => setActive(false);
const onVisibility = (): void => setActive(document.visibilityState !== 'hidden');
window.addEventListener('focus', onFocus);
window.addEventListener('blur', onBlur);
document.addEventListener('visibilitychange', onVisibility);
return () => {
window.removeEventListener('focus', onFocus);
window.removeEventListener('blur', onBlur);
document.removeEventListener('visibilitychange', onVisibility);
};
}, []);
return active;
}