import type { ComponentType } from "react"; import type { Post } from "../../types/post"; import { TextBubble } from "./bubbles/TextBubble"; import { FileDocBubble } from "./bubbles/FileDocBubble"; import { ImageBubble } from "./bubbles/ImageBubble"; import { ImageWithTextBubble } from "./bubbles/ImageWithTextBubble"; import { AlbumBubble } from "./bubbles/AlbumBubble"; import { VideoBubble } from "./bubbles/VideoBubble"; import { LinkPreviewCard } from "./LinkPreviewCard"; import { formatDateTime } from "./utils/formatTime"; import { FavoriteButton } from "../../favorites/FavoriteButton"; export type MessageBubbleVariant = "default" | "latest"; type BubbleComponent = ComponentType<{ post: Post; variant?: MessageBubbleVariant; }>; export function pickBubble(post: Post): BubbleComponent { const a = post.attachments; if (a.length === 0) return TextBubble; if (a.length >= 2 && a.every((x) => x.kind === "image")) return AlbumBubble; const only = a[0]; if (only.kind === "video") return VideoBubble; if (only.kind === "image") { return post.text ? ImageWithTextBubble : ImageBubble; } return FileDocBubble; } export function MessageBubble({ post, fluid = false, variant = "default", onFavoriteChange, }: { post: Post; /** When true, fill the parent container instead of applying the standalone * feed max-widths. Used by the desktop 3-column masonry on the home page. */ fluid?: boolean; /** Desktop latest-updates cards follow the dedicated Figma masonry design. */ variant?: MessageBubbleVariant; onFavoriteChange?: (postId: string, favorited: boolean) => void; }) { const Bubble = pickBubble(post); const isVisual = Bubble === AlbumBubble || Bubble === VideoBubble || Bubble === ImageBubble || Bubble === ImageWithTextBubble; const isFileBubble = Bubble === FileDocBubble; const isLatestVariant = variant === "latest"; const isLatestFileCard = isLatestVariant && isFileBubble; return (
{isLatestVariant && !isFileBubble ? ( onFavoriteChange?.(post.id, favorited) } /> ) : null} {post.linkPreview ? (
) : null} {!isLatestVariant ? (
onFavoriteChange?.(post.id, favorited) } />
) : null} {isLatestVariant && !isFileBubble ? ( ) : null}
); }