This commit is contained in:
2025-12-17 19:50:55 +07:00
parent debdd66458
commit 7e7cdbcd76
10 changed files with 225 additions and 77 deletions

View File

@@ -3,6 +3,8 @@ import { usersApi } from '@/api'
// Глобальный кэш для blob URL аватарок
const avatarCache = new Map<number, string>()
// Пользователи, для которых нужно сбросить HTTP-кэш при следующем запросе
const needsCacheBust = new Set<number>()
interface UserAvatarProps {
userId: number
@@ -10,6 +12,7 @@ interface UserAvatarProps {
nickname: string
size?: 'sm' | 'md' | 'lg'
className?: string
version?: number // Для принудительного обновления при смене аватара
}
const sizeClasses = {
@@ -18,7 +21,7 @@ const sizeClasses = {
lg: 'w-24 h-24 text-xl',
}
export function UserAvatar({ userId, hasAvatar, nickname, size = 'md', className = '' }: UserAvatarProps) {
export function UserAvatar({ userId, hasAvatar, nickname, size = 'md', className = '', version = 0 }: UserAvatarProps) {
const [blobUrl, setBlobUrl] = useState<string | null>(null)
const [failed, setFailed] = useState(false)
@@ -28,16 +31,31 @@ export function UserAvatar({ userId, hasAvatar, nickname, size = 'md', className
return
}
// Проверяем кэш
const cached = avatarCache.get(userId)
if (cached) {
setBlobUrl(cached)
return
// Если version > 0, значит аватар обновился - сбрасываем кэш
const shouldBustCache = version > 0 || needsCacheBust.has(userId)
// Проверяем кэш только если не нужен bust
if (!shouldBustCache) {
const cached = avatarCache.get(userId)
if (cached) {
setBlobUrl(cached)
return
}
}
// Очищаем старый кэш если bust
if (shouldBustCache) {
const cached = avatarCache.get(userId)
if (cached) {
URL.revokeObjectURL(cached)
avatarCache.delete(userId)
}
needsCacheBust.delete(userId)
}
// Загружаем аватарку
let cancelled = false
usersApi.getAvatarUrl(userId)
usersApi.getAvatarUrl(userId, shouldBustCache)
.then(url => {
if (!cancelled) {
avatarCache.set(userId, url)
@@ -53,7 +71,7 @@ export function UserAvatar({ userId, hasAvatar, nickname, size = 'md', className
return () => {
cancelled = true
}
}, [userId, hasAvatar])
}, [userId, hasAvatar, version])
const sizeClass = sizeClasses[size]
@@ -84,4 +102,6 @@ export function clearAvatarCache(userId: number) {
URL.revokeObjectURL(cached)
avatarCache.delete(userId)
}
// Помечаем, что при следующем запросе нужно сбросить HTTP-кэш браузера
needsCacheBust.add(userId)
}