diff --git a/src/components/MobileFeed.tsx b/src/components/MobileFeed.tsx index 344f88d..56de67d 100644 --- a/src/components/MobileFeed.tsx +++ b/src/components/MobileFeed.tsx @@ -82,8 +82,42 @@ function SlideMedia({ media, author }: { media: CardMedia; author: string }) { ); } +/** Several media items in one slide: a sideways scroll-snap track with a dot per item. */ +function MediaTrack({ items, author }: { items: CardMedia[]; author: string }) { + const track = useRef(null); + const [active, setActive] = useState(0); + const onScroll = () => { + const el = track.current; + if (!el) return; + const next = Math.min(items.length - 1, Math.max(0, Math.round(el.scrollLeft / Math.max(el.clientWidth, 1)))); + if (next === active) return; + setActive(next); + // A video stops when it is swiped away. + el.querySelectorAll(":scope > .slide-pane").forEach((pane, i) => { + if (i !== next) pane.querySelectorAll("video").forEach((v) => v.pause()); + }); + }; + return ( + <> +
+ {items.map((m, i) => ( +
+ +
+ ))} +
+ + + ); +} + function PostSlide({ post, index, current, p }: { post: CardPost; index: number; current: boolean; p: FeedViewProps }) { - const media = post.media.find((m) => m.kind === "video" || m.src) ?? null; + const items = post.media.filter((m) => m.kind === "video" || m.src); + const media = items[0] ?? null; const own = canDelete(post, p.feedUserId) && !!p.onDelete; // While a video plays, the author and text step aside so the native controls stay clear. const [playing, setPlaying] = useState(false); @@ -100,7 +134,7 @@ function PostSlide({ post, index, current, p }: { post: CardPost; index: number; > {media ? ( <> - + {items.length > 1 ? : }