diff --git a/src/components/messageStream/AttachmentDownloadPill.tsx b/src/components/messageStream/AttachmentDownloadPill.tsx index 82b51d3..cf8481c 100644 --- a/src/components/messageStream/AttachmentDownloadPill.tsx +++ b/src/components/messageStream/AttachmentDownloadPill.tsx @@ -20,6 +20,14 @@ type AttachmentDownloadPillProps = { * Defaults to false (fixed 30px) for standalone images/videos. */ adaptive?: boolean; + /** + * Visual size. `sm` (default, 30 px tall) for inline tiles where space is + * tight. `lg` (44 px tall with a 24 px icon and 14 px text) for overlay + * surfaces like the image lightbox or fullscreen video player where the + * affordance can breathe and should feel touch-friendly. + * Ignored when `adaptive` is set. + */ + size?: "sm" | "lg"; }; export function AttachmentDownloadPill({ @@ -28,6 +36,7 @@ export function AttachmentDownloadPill({ leadingLabel, className = "absolute left-2 top-2", adaptive = false, + size = "sm", }: AttachmentDownloadPillProps) { const { t } = useI18n(); const { showToast } = useToast(); @@ -46,52 +55,56 @@ export function AttachmentDownloadPill({ } }; + const isLg = !adaptive && size === "lg"; + + const fontCls = adaptive + ? "text-[clamp(10px,7cqw,12px)]" + : isLg + ? "text-[14px] font-medium" + : "text-[12px]"; + + const squareCls = adaptive + ? "h-[clamp(22px,18cqw,30px)] w-[clamp(22px,18cqw,30px)]" + : isLg + ? "h-[44px] w-[44px]" + : "h-[30px] w-[30px]"; + + const iconCls = adaptive + ? "h-[clamp(13px,11cqw,18px)] w-[clamp(13px,11cqw,18px)]" + : isLg + ? "h-[22px] w-[22px]" + : "h-[18px] w-[18px]"; + + const textBoxCls = adaptive + ? "h-[clamp(22px,18cqw,30px)] px-[clamp(6px,6cqw,10px)]" + : isLg + ? "h-[44px] px-4" + : "h-[30px] px-2.5"; + return ( + ) : null} + +
e.stopPropagation()} + > + + + + {formatClock(currentTime)} + + +
+
+
+
+
+
+ + + -{formatClock(remaining)} + + + {hideFullscreen ? null : ( + + )} +
+ + ); +} diff --git a/src/components/messageStream/bubbles/VideoBubble.tsx b/src/components/messageStream/bubbles/VideoBubble.tsx index 0771fa6..e33844a 100644 --- a/src/components/messageStream/bubbles/VideoBubble.tsx +++ b/src/components/messageStream/bubbles/VideoBubble.tsx @@ -1,10 +1,11 @@ import { LoaderCircle, Play, X } from "lucide-react"; import { DownloadCloudIcon } from "../../icons/DownloadCloudIcon"; -import { useEffect, useRef, useState } from "react"; +import { useEffect, useState } from "react"; import { createPortal } from "react-dom"; import { useI18n } from "../../../i18n"; import type { Attachment, Post } from "../../../types/post"; import { AttachmentDownloadPill } from "../AttachmentDownloadPill"; +import { MessageInlineVideo } from "../MessageInlineVideo"; import { useVideoPlayer } from "../overlays/VideoPlayer"; import { autolink } from "../utils/autolink"; import { CollapsibleText } from "../CollapsibleText"; @@ -56,7 +57,6 @@ function VideoAttachmentCard({ }) { const { openVideo } = useVideoPlayer(); const [playing, setPlaying] = useState(false); - const videoRef = useRef(null); const posterUrl = attachment.posterUrl ?? attachment.thumbnailUrl; const duration = formatDuration(attachment.durationSec); const previewVideoUrl = attachment.url.includes("#") @@ -73,26 +73,11 @@ function VideoAttachmentCard({ style={compact ? undefined : { aspectRatio: videoRatio(attachment) }} > {playing && !compact ? ( - <> -
{postId ? ( - + ) : null}
diff --git a/src/components/messageStream/overlays/VideoPlayer.tsx b/src/components/messageStream/overlays/VideoPlayer.tsx index 4327752..310a64b 100644 --- a/src/components/messageStream/overlays/VideoPlayer.tsx +++ b/src/components/messageStream/overlays/VideoPlayer.tsx @@ -10,14 +10,32 @@ import { import { createPortal } from "react-dom"; import { X } from "lucide-react"; import type { Attachment } from "../../../types/post"; +import { AttachmentDownloadPill } from "../AttachmentDownloadPill"; +import { MessageInlineVideo } from "../MessageInlineVideo"; + +type OnClose = (finalTime: number) => void; type PlayerState = { attachment: Attachment; currentTime: number; + onClose?: OnClose; + /** Post the video belongs to, needed for the download pill. */ + postId?: string; } | null; type Ctx = { - openVideo: (attachment: Attachment, currentTime?: number) => void; + /** + * Open the fullscreen player. `onClose` (optional) is invoked with the + * playhead at the moment the user dismisses the overlay, so callers can + * sync the original inline `