fix and update

This commit is contained in:
lendry
2026-06-29 22:51:25 +03:00
parent 885b07d76b
commit 57cb58347b
30 changed files with 799 additions and 187 deletions

View File

@@ -4,8 +4,11 @@ import { Bot } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import { UserAvatar } from '@/components/id/user-avatar';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Skeleton } from '@/components/ui/skeleton';
import { useAuth } from '@/components/id/auth-provider';
import { ChatRoom, apiFetch } from '@/lib/api';
import { CHAT_ROOM_AVATAR_UPDATED_EVENT } from '@/lib/avatar-events';
import { useResilientBlobUrl } from '@/hooks/use-resilient-blob-url';
import { cn } from '@/lib/utils';
interface ChatRoomAvatarDisplayProps {
@@ -21,7 +24,9 @@ function sizeClass(size: 'sm' | 'md') {
}
export function ChatRoomAvatarDisplay({ room, viewerUserId, token, className, size = 'md' }: ChatRoomAvatarDisplayProps) {
const { isLoading: authLoading } = useAuth();
const [roomAvatarUrl, setRoomAvatarUrl] = useState<string | null>(null);
const [resolvingRoomAvatar, setResolvingRoomAvatar] = useState(false);
const peerMember = useMemo(
() =>
room.type === 'DIRECT' || room.type === 'E2E' || room.type === 'BOT'
@@ -31,34 +36,44 @@ export function ChatRoomAvatarDisplay({ room, viewerUserId, token, className, si
);
useEffect(() => {
if (!token || !room.hasAvatar || room.type === 'DIRECT' || room.type === 'E2E' || room.type === 'BOT') {
if (!token || authLoading || !room.hasAvatar || room.type === 'DIRECT' || room.type === 'E2E' || room.type === 'BOT') {
setRoomAvatarUrl(null);
setResolvingRoomAvatar(false);
return;
}
let cancelled = false;
setResolvingRoomAvatar(true);
apiFetch<{ accessUrl: string }>(`/media/chat/${room.id}/avatar/url`, {}, token)
.then((response) => {
if (!cancelled) setRoomAvatarUrl(response.accessUrl);
})
.catch(() => {
if (!cancelled) setRoomAvatarUrl(null);
})
.finally(() => {
if (!cancelled) setResolvingRoomAvatar(false);
});
return () => {
cancelled = true;
};
}, [room.hasAvatar, room.id, room.type, room.updatedAt, token]);
}, [authLoading, room.hasAvatar, room.id, room.type, room.updatedAt, token]);
useEffect(() => {
function handleRoomAvatarUpdated(event: Event) {
const detail = (event as CustomEvent<{ roomId?: string }>).detail;
if (detail?.roomId !== room.id || !room.hasAvatar || !token) return;
if (detail?.roomId !== room.id || !room.hasAvatar || !token || authLoading) return;
apiFetch<{ accessUrl: string }>(`/media/chat/${room.id}/avatar/url`, {}, token)
.then((response) => setRoomAvatarUrl(response.accessUrl))
.catch(() => setRoomAvatarUrl(null));
}
window.addEventListener(CHAT_ROOM_AVATAR_UPDATED_EVENT, handleRoomAvatarUpdated);
return () => window.removeEventListener(CHAT_ROOM_AVATAR_UPDATED_EVENT, handleRoomAvatarUpdated);
}, [room.hasAvatar, room.id, token]);
}, [authLoading, room.hasAvatar, room.id, token]);
const { blobUrl, isLoading: isLoadingRoomBlob } = useResilientBlobUrl(roomAvatarUrl, token, {
enabled: Boolean(room.hasAvatar && roomAvatarUrl && !authLoading),
label: `аватар чата ${room.name}`
});
if (peerMember && (room.type === 'DIRECT' || room.type === 'E2E')) {
return (
@@ -85,10 +100,22 @@ export function ChatRoomAvatarDisplay({ room, viewerUserId, token, className, si
);
}
if (room.hasAvatar && roomAvatarUrl) {
const isRoomAvatarLoading = Boolean(room.hasAvatar && (resolvingRoomAvatar || isLoadingRoomBlob || (roomAvatarUrl && !blobUrl)));
if (room.hasAvatar && isRoomAvatarLoading) {
return (
<Avatar className={cn(sizeClass(size), className)}>
<AvatarImage src={roomAvatarUrl} alt={room.name} />
<AvatarFallback className="bg-transparent p-0">
<Skeleton className="h-full w-full rounded-full" />
</AvatarFallback>
</Avatar>
);
}
if (room.hasAvatar && blobUrl) {
return (
<Avatar className={cn(sizeClass(size), className)}>
<AvatarImage src={blobUrl} alt={room.name} />
<AvatarFallback>{room.name.slice(0, 2).toUpperCase()}</AvatarFallback>
</Avatar>
);