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

@@ -33,7 +33,7 @@ type NicknameForm = z.infer<typeof nicknameSchema>
type PasswordForm = z.infer<typeof passwordSchema>
export function ProfilePage() {
const { user, updateUser } = useAuthStore()
const { user, updateUser, avatarVersion, bumpAvatarVersion } = useAuthStore()
const toast = useToast()
// State
@@ -72,31 +72,57 @@ export function ProfilePage() {
}
}, [])
// Ref для отслеживания текущего blob URL
const avatarBlobRef = useRef<string | null>(null)
// Load avatar via API
useEffect(() => {
if (user?.id && user?.avatar_url) {
loadAvatar(user.id)
} else {
if (!user?.id || !user?.avatar_url) {
setIsLoadingAvatar(false)
return
}
let cancelled = false
const bustCache = avatarVersion > 0
setIsLoadingAvatar(true)
usersApi.getAvatarUrl(user.id, bustCache)
.then(url => {
if (cancelled) {
URL.revokeObjectURL(url)
return
}
// Очищаем старый blob URL
if (avatarBlobRef.current) {
URL.revokeObjectURL(avatarBlobRef.current)
}
avatarBlobRef.current = url
setAvatarBlobUrl(url)
})
.catch(() => {
if (!cancelled) {
setAvatarBlobUrl(null)
}
})
.finally(() => {
if (!cancelled) {
setIsLoadingAvatar(false)
}
})
return () => {
if (avatarBlobUrl) {
URL.revokeObjectURL(avatarBlobUrl)
cancelled = true
}
}, [user?.id, user?.avatar_url, avatarVersion])
// Cleanup blob URL on unmount
useEffect(() => {
return () => {
if (avatarBlobRef.current) {
URL.revokeObjectURL(avatarBlobRef.current)
}
}
}, [user?.id, user?.avatar_url])
const loadAvatar = async (userId: number) => {
setIsLoadingAvatar(true)
try {
const url = await usersApi.getAvatarUrl(userId)
setAvatarBlobUrl(url)
} catch {
setAvatarBlobUrl(null)
} finally {
setIsLoadingAvatar(false)
}
}
}, [])
// Update nickname form when user changes
useEffect(() => {
@@ -150,12 +176,10 @@ export function ProfilePage() {
const updatedUser = await usersApi.uploadAvatar(file)
updateUser({ avatar_url: updatedUser.avatar_url })
if (user?.id) {
if (avatarBlobUrl) {
URL.revokeObjectURL(avatarBlobUrl)
}
clearAvatarCache(user.id)
await loadAvatar(user.id)
}
// Bump version - это вызовет перезагрузку через useEffect
bumpAvatarVersion()
toast.success('Аватар обновлен')
} catch {
toast.error('Не удалось загрузить аватар')