'use client'; import { useCallback, useEffect, useState } from 'react'; import { useAuth } from '@/components/id/auth-provider'; import { apiFetch } from '@/lib/api'; import { AVATAR_UPDATED_EVENT } from '@/lib/avatar-events'; import { useResilientBlobUrl } from '@/hooks/use-resilient-blob-url'; interface AvatarAccessResponse { accessUrl: string; expiresAt: string; } export function useAvatarUrl(userId: string | undefined, hasAvatar: boolean | undefined, token: string | null) { const { isPinLocked, isLoading } = useAuth(); const [accessUrl, setAccessUrl] = useState(null); const [resolvingAccessUrl, setResolvingAccessUrl] = useState(false); const refreshAccessUrl = useCallback(async () => { if (!userId || !token || !hasAvatar || isPinLocked || isLoading) { setAccessUrl(null); setResolvingAccessUrl(false); return; } setResolvingAccessUrl(true); try { const response = await apiFetch(`/media/avatars/${userId}/url`, {}, token); setAccessUrl(response.accessUrl); } catch { setAccessUrl(null); } finally { setResolvingAccessUrl(false); } }, [hasAvatar, isLoading, isPinLocked, token, userId]); useEffect(() => { void refreshAccessUrl(); if (!hasAvatar) return; const timer = window.setInterval(() => { void refreshAccessUrl(); }, 14 * 60 * 1000); return () => window.clearInterval(timer); }, [hasAvatar, refreshAccessUrl]); useEffect(() => { if (!userId || !hasAvatar) return; function handleAvatarUpdated(event: Event) { const detail = (event as CustomEvent<{ userId?: string }>).detail; if (detail?.userId === userId) { void refreshAccessUrl(); } } window.addEventListener(AVATAR_UPDATED_EVENT, handleAvatarUpdated); return () => window.removeEventListener(AVATAR_UPDATED_EVENT, handleAvatarUpdated); }, [hasAvatar, refreshAccessUrl, userId]); const { blobUrl, isLoading: isLoadingBlob, hasError } = useResilientBlobUrl(accessUrl, token, { enabled: Boolean(hasAvatar && accessUrl && !isPinLocked && !isLoading), label: `аватар ${userId ?? ''}`.trim() }); const avatarUrl = blobUrl; const isAvatarLoading = Boolean(hasAvatar && (resolvingAccessUrl || isLoadingBlob || (accessUrl && !blobUrl && !hasError))); const refreshAvatarUrl = useCallback(async () => { await refreshAccessUrl(); }, [refreshAccessUrl]); return { avatarUrl, isAvatarLoading, hasAvatarError: hasError, refreshAvatarUrl }; }