fix and update

This commit is contained in:
lendry
2026-07-01 22:46:04 +03:00
parent cb82544905
commit 2b88e028c6
7 changed files with 385 additions and 79 deletions

View File

@@ -15,6 +15,7 @@ import {
extractFilesFromDataTransfer,
useChatMediaComposer
} from '@/components/chat/chat-media-compose-dialog';
import { ChatImageLightbox } from '@/components/chat/chat-image-lightbox';
import { ChatEmojiContent } from '@/components/chat/chat-emoji-content';
import { ChatMessageContextMenu, ChatSelectionContextMenu, SelectableMessageWrapper } from '@/components/chat/chat-message-context-menu';
import { ChatPinnedMessageBanner } from '@/components/chat/chat-pinned-message-banner';
@@ -28,6 +29,7 @@ import { scrollToChatMessage } from '@/components/chat/replied-message-preview';
import { useFamilyOverlay } from '@/components/family/family-overlay-provider';
import { useAuth } from '@/components/id/auth-provider';
import { UserAvatar } from '@/components/id/user-avatar';
import { MediaImageSkeleton } from '@/components/ui/media-image-skeleton';
import { useToast } from '@/components/id/toast-provider';
import { useRealtime } from '@/components/notifications/realtime-provider';
import { Button } from '@/components/ui/button';
@@ -74,6 +76,8 @@ import { shouldShowChatDateSeparator } from '@/lib/chat-date-utils';
import { encryptE2EBlob, e2eKindFromMessageType } from '@/lib/e2e-chat';
import { findMemberRoom, findOrCreateMemberChat, roomDisplayLabel } from '@/lib/family-chat';
import { getE2EMessageText, useE2EChat } from '@/hooks/use-e2e-chat';
import { useChatRoomMedia } from '@/hooks/use-chat-room-media';
import { collectChatImageMessages } from '@/lib/chat-media-album';
import { cn } from '@/lib/utils';
interface PresignedUploadResponse {
@@ -87,7 +91,7 @@ function formatMessageTime(value: string) {
return new Intl.DateTimeFormat('ru-RU', { hour: '2-digit', minute: '2-digit' }).format(new Date(value));
}
function MiniChatImageMessage({ message, token }: { message: ChatMessage; token: string }) {
function MiniChatEncryptedImageMessage({ message, token, onOpen }: { message: ChatMessage; token: string; onOpen?: () => void }) {
const [src, setSrc] = useState<string | null>(null);
const [failed, setFailed] = useState(false);
const metadata = parseMessageMetadata(message.metadataJson) as { fileName?: string; width?: number; height?: number };
@@ -146,12 +150,19 @@ function MiniChatImageMessage({ message, token }: { message: ChatMessage; token:
}
return (
<img
src={src}
alt={message.content?.trim() || metadata.fileName || 'Фото в чате'}
className="max-h-[260px] w-[190px] rounded-2xl object-cover shadow-sm"
style={{ aspectRatio: metadata.width && metadata.height ? `${metadata.width} / ${metadata.height}` : undefined }}
/>
<button
type="button"
className="block overflow-hidden rounded-2xl shadow-sm"
onClick={onOpen}
disabled={!onOpen}
>
<img
src={src}
alt={message.content?.trim() || metadata.fileName || 'Фото в чате'}
className="max-h-[260px] w-[190px] object-cover"
style={{ aspectRatio: metadata.width && metadata.height ? `${metadata.width} / ${metadata.height}` : undefined }}
/>
</button>
);
}
@@ -202,6 +213,7 @@ export function MiniFamilyChat() {
const [chatToolsOpen, setChatToolsOpen] = useState(false);
const [chatToolsTab, setChatToolsTab] = useState<ChatToolsTab>('search');
const [mediaDropVisible, setMediaDropVisible] = useState(false);
const [lightboxIndex, setLightboxIndex] = useState<number | null>(null);
const mediaComposer = useChatMediaComposer();
const messagesEndRef = useRef<HTMLDivElement>(null);
const autoScrollStateRef = useRef<{ id: string | null; count: number }>({ id: null, count: 0 });
@@ -213,6 +225,13 @@ export function MiniFamilyChat() {
() => messages.filter((message) => !message.isDeleted),
[messages]
);
const chatImageMessages = useMemo(() => collectChatImageMessages(visibleMessages), [visibleMessages]);
const { mediaUrls } = useChatRoomMedia(token, activeRoom?.id ?? null, visibleMessages);
function openImageLightbox(message: ChatMessage) {
const index = chatImageMessages.findIndex((item) => item.id === message.id);
if (index >= 0) setLightboxIndex(index);
}
const pinnedMessage = useMemo(
() =>
visibleMessages
@@ -361,6 +380,7 @@ export function MiniFamilyChat() {
setMessages([]);
setBotMessages([]);
setDraft('');
setLightboxIndex(null);
exitSelectionMode();
setEmojiOpen(false);
setPollOpen(false);
@@ -1173,9 +1193,58 @@ export function MiniFamilyChat() {
);
})}
</div>
) : message.storageKey && message.type === 'IMAGE' && message.isEncrypted && token ? (
<div className="space-y-1">
<MiniChatEncryptedImageMessage
message={message}
token={token}
onOpen={() => openImageLightbox(message)}
/>
{visibleText?.trim() ? (
<div className="whitespace-pre-wrap break-words text-sm leading-relaxed">
<ChatEmojiContent content={visibleText} size={18} />
</div>
) : null}
</div>
) : message.storageKey && message.type === 'IMAGE' && token ? (
<div className="space-y-1">
<MiniChatImageMessage message={message} token={token} />
{(() => {
const media = message.storageKey ? mediaUrls[message.storageKey] : undefined;
const meta = parseMessageMetadata(message.metadataJson) as {
fileName?: string;
width?: number;
height?: number;
};
if (!media?.blobUrl || media.status === 'loading') {
const ratio =
meta.width && meta.height
? Math.max(0.65, Math.min(1.35, meta.height / meta.width))
: 0.72;
return (
<div className="w-[190px]" style={{ height: Math.round(190 * ratio) }}>
<MediaImageSkeleton className="h-full w-full min-h-0" rounded="2xl" />
</div>
);
}
return (
<button
type="button"
className="block overflow-hidden rounded-2xl shadow-sm"
onClick={() => openImageLightbox(message)}
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={media.blobUrl}
alt={message.content?.trim() || meta.fileName || 'Фото в чате'}
className="max-h-[260px] w-[190px] object-cover"
style={{
aspectRatio:
meta.width && meta.height ? `${meta.width} / ${meta.height}` : undefined
}}
/>
</button>
);
})()}
{visibleText?.trim() ? (
<div className="whitespace-pre-wrap break-words text-sm leading-relaxed">
<ChatEmojiContent content={visibleText} size={18} />
@@ -1494,6 +1563,14 @@ export function MiniFamilyChat() {
authToken={token}
onClose={() => setMiniAppUrl(null)}
/>
<ChatImageLightbox
open={lightboxIndex !== null}
images={chatImageMessages}
index={lightboxIndex ?? 0}
mediaUrls={mediaUrls}
onClose={() => setLightboxIndex(null)}
onIndexChange={setLightboxIndex}
/>
</>
);
}