update
This commit is contained in:
84
apps/frontend/components/chat/chat-media-album-grid.tsx
Normal file
84
apps/frontend/components/chat/chat-media-album-grid.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
'use client';
|
||||
|
||||
import type { ChatMessage } from '@/lib/api';
|
||||
import { parseChatMediaMetadata } from '@/lib/chat-media-album';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface ChatMediaAlbumGridProps {
|
||||
messages: ChatMessage[];
|
||||
mediaUrls: Record<string, { blobUrl: string } | undefined>;
|
||||
className?: string;
|
||||
onImageClick?: (message: ChatMessage, index: number) => void;
|
||||
}
|
||||
|
||||
function tileClass(count: number, index: number) {
|
||||
if (count === 1) return 'col-span-2 row-span-2';
|
||||
if (count === 2) return 'col-span-1 row-span-2';
|
||||
if (count === 3) {
|
||||
if (index === 0) return 'col-span-1 row-span-2';
|
||||
return 'col-span-1 row-span-1';
|
||||
}
|
||||
if (count === 4) return 'col-span-1 row-span-1';
|
||||
if (count === 5) {
|
||||
if (index === 0) return 'col-span-2 row-span-2';
|
||||
return 'col-span-1 row-span-1';
|
||||
}
|
||||
if (count >= 6) {
|
||||
if (index === 0) return 'col-span-2 row-span-2';
|
||||
return 'col-span-1 row-span-1';
|
||||
}
|
||||
return 'col-span-1 row-span-1';
|
||||
}
|
||||
|
||||
export function ChatMediaAlbumGrid({ messages, mediaUrls, className, onImageClick }: ChatMediaAlbumGridProps) {
|
||||
const imageMessages = messages.filter((message) => message.type === 'IMAGE' && message.storageKey);
|
||||
const fileMessages = messages.filter((message) => message.type === 'FILE' && message.storageKey);
|
||||
const count = imageMessages.length;
|
||||
|
||||
if (!count && fileMessages.length) {
|
||||
return (
|
||||
<div className={cn('space-y-2', className)}>
|
||||
{fileMessages.map((message) => (
|
||||
<div key={message.id} className="rounded-xl bg-black/5 px-3 py-2 text-sm">
|
||||
{message.content || parseChatMediaMetadata(message.metadataJson).fileName || 'Файл'}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'grid max-w-[320px] grid-cols-2 gap-0.5 overflow-hidden rounded-2xl',
|
||||
count === 1 ? 'grid-rows-1' : count === 2 ? 'grid-rows-2' : 'grid-rows-3 auto-rows-[96px]',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{imageMessages.map((message, index) => {
|
||||
const media = message.storageKey ? mediaUrls[message.storageKey] : undefined;
|
||||
const hiddenCount = count > 6 && index === 5 ? count - 6 : 0;
|
||||
return (
|
||||
<button
|
||||
key={message.id}
|
||||
type="button"
|
||||
className={cn('relative overflow-hidden bg-[#dfe4ea]', tileClass(Math.min(count, 6), index))}
|
||||
onClick={() => onImageClick?.(message, index)}
|
||||
>
|
||||
{media?.blobUrl ? (
|
||||
// eslint-disable-next-line @next/next/no-img-element
|
||||
<img src={media.blobUrl} alt="" className="h-full w-full object-cover" />
|
||||
) : (
|
||||
<div className="flex h-full min-h-[96px] items-center justify-center text-xs text-[#667085]">…</div>
|
||||
)}
|
||||
{hiddenCount > 0 ? (
|
||||
<div className="absolute inset-0 flex items-center justify-center bg-black/45 text-2xl font-semibold text-white">
|
||||
+{hiddenCount}
|
||||
</div>
|
||||
) : null}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user