Merge branch 'main' into terry-wallet-login
Some checks failed
Deploy Staging (terry-wallet-login) / deploy (push) Failing after 31s

# Conflicts:
#	src/components/messageStream/MessageStream.tsx
This commit is contained in:
TerryM
2026-06-03 14:42:07 +08:00
20 changed files with 410 additions and 19 deletions

View File

@@ -2,6 +2,7 @@ import { useI18n } from "../../../i18n";
import type { Post } from "../../../types/post";
import { ALBUM_GAP, ALBUM_MAX_HEIGHT } from "../../../constants/media";
import { AttachmentDownloadPill } from "../AttachmentDownloadPill";
import { AttachmentFilenameLabel } from "../AttachmentFilenameLabel";
import { BubbleImage } from "../BubbleImage";
import { useImageRatios } from "../hooks/useImageRatios";
import { useLightbox } from "../overlays/ImageLightbox";
@@ -19,6 +20,7 @@ export function AlbumBubble({ post }: { post: Post }) {
const text = postDisplayText(post, lang);
const visible = images.slice(0, MAX_VISIBLE);
const extra = images.length - MAX_VISIBLE;
const showFilename = post.categorySlug === "official-assets";
const sources = visible.map(
(att) => att.thumbnailUrl ?? att.thumbUrl ?? att.url,
@@ -90,6 +92,9 @@ export function AlbumBubble({ post }: { post: Post }) {
adaptive
/>
) : null}
{!isLastSlot && showFilename ? (
<AttachmentFilenameLabel attachment={att} />
) : null}
</div>
);
})}

View File

@@ -4,5 +4,11 @@ import { SingleImageFrame } from "./SingleImageFrame";
export function ImageBubble({ post }: { post: Post }) {
const att = post.attachments[0];
if (!att) return null;
return <SingleImageFrame postId={post.id} attachment={att} />;
return (
<SingleImageFrame
postId={post.id}
attachment={att}
showFilename={post.categorySlug === "official-assets"}
/>
);
}

View File

@@ -12,7 +12,12 @@ export function ImageWithTextBubble({ post }: { post: Post }) {
if (!att) return null;
return (
<div className="flex flex-col">
<SingleImageFrame postId={post.id} attachment={att} text={text} />
<SingleImageFrame
postId={post.id}
attachment={att}
text={text}
showFilename={post.categorySlug === "official-assets"}
/>
{text ? (
<CollapsibleText
wrapperClassName="px-4 pt-3"

View File

@@ -1,5 +1,6 @@
import type { Attachment } from "../../../types/post";
import { AttachmentDownloadPill } from "../AttachmentDownloadPill";
import { AttachmentFilenameLabel } from "../AttachmentFilenameLabel";
import { useLightbox } from "../overlays/ImageLightbox";
import { AdaptiveImageFrame } from "./AdaptiveImageFrame";
@@ -11,10 +12,13 @@ export function SingleImageFrame({
postId,
attachment,
text,
showFilename = false,
}: {
postId: string;
attachment: Attachment;
text?: string;
/** Show the source filename pinned bottom-left (used for 官方物料 cards). */
showFilename?: boolean;
}) {
const { openLightbox } = useLightbox();
return (
@@ -29,6 +33,9 @@ export function SingleImageFrame({
ariaLabel="View image"
>
<AttachmentDownloadPill postId={postId} attachment={attachment} />
{showFilename ? (
<AttachmentFilenameLabel attachment={attachment} />
) : null}
</AdaptiveImageFrame>
);
}

View File

@@ -5,6 +5,7 @@ import { createPortal } from "react-dom";
import { useI18n } from "../../../i18n";
import type { Attachment, Post } from "../../../types/post";
import { AttachmentDownloadPill } from "../AttachmentDownloadPill";
import { AttachmentFilenameLabel } from "../AttachmentFilenameLabel";
import { MessageInlineVideo } from "../MessageInlineVideo";
import {
useShouldUseMobilePreview,
@@ -57,12 +58,15 @@ function VideoAttachmentCard({
compact = false,
overlayCount,
onMoreClick,
showFilename = false,
}: {
postId: string;
attachment: Attachment;
compact?: boolean;
overlayCount?: number;
onMoreClick?: () => void;
/** Show the source filename pinned bottom-left (used for 官方物料 cards). */
showFilename?: boolean;
}) {
const { openVideo } = useVideoPlayer();
const [playing, setPlaying] = useState(false);
@@ -117,6 +121,9 @@ function VideoAttachmentCard({
leadingLabel={duration}
/>
) : null}
{!overlayCount && showFilename ? (
<AttachmentFilenameLabel attachment={attachment} />
) : null}
{overlayCount ? (
<button
type="button"
@@ -324,6 +331,7 @@ export function VideoBubble({ post }: { post: Post }) {
const [listOpen, setListOpen] = useState(false);
const videos = post.attachments.filter(isVideoAttachment);
const text = postDisplayText(post, lang);
const showFilename = post.categorySlug === "official-assets";
if (!videos.length) return null;
if (videos.length >= 2) {
@@ -349,6 +357,7 @@ export function VideoBubble({ post }: { post: Post }) {
compact
overlayCount={isLastSlot ? extra : undefined}
onMoreClick={() => setListOpen(true)}
showFilename={showFilename}
/>
</div>
);
@@ -379,7 +388,11 @@ export function VideoBubble({ post }: { post: Post }) {
return (
<div className="flex flex-col">
<VideoAttachmentCard postId={post.id} attachment={videos[0]} />
<VideoAttachmentCard
postId={post.id}
attachment={videos[0]}
showFilename={showFilename}
/>
{text ? (
<CollapsibleText
wrapperClassName="px-4 pt-3"