xrdwb17xu: Add the full-screen snap feed with media and quote slides on phones
This commit is contained in:
+37
-3
@@ -3,7 +3,7 @@
|
||||
// Dev-only: the real signed-in shell with fixture data and no network calls.
|
||||
// Likes, search and the composer work on local state so the panels can be
|
||||
// checked by hand. Used by src/app/dev/feed/page.tsx.
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { AppShell } from "@/components/AppShell";
|
||||
import { DiscoverRailsView } from "@/components/DiscoverRails";
|
||||
import { ExpertSearchView } from "@/components/ExpertSearch";
|
||||
@@ -31,6 +31,38 @@ export function FeedPreview() {
|
||||
const [loadingMore, setLoadingMore] = useState(false);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const list = useRef<HTMLDivElement | null>(null);
|
||||
// The list element swaps between the panel and the phone reel; paging re-attaches to it.
|
||||
const [listEl, setListEl] = useState<HTMLDivElement | null>(null);
|
||||
const listRef = useCallback((el: HTMLDivElement | null) => {
|
||||
list.current = el;
|
||||
setListEl(el);
|
||||
}, []);
|
||||
// Paging: two more fixture pages load when the sentinel scrolls into view,
|
||||
// the same way Feed pages (the observer root is the list or the phone reel).
|
||||
const sentinel = useRef<HTMLDivElement | null>(null);
|
||||
const [page, setPage] = useState(0);
|
||||
const [paging, setPaging] = useState(false);
|
||||
const hasMore = page < 2;
|
||||
useEffect(() => {
|
||||
const el = sentinel.current;
|
||||
if (!el || !hasMore || paging) return;
|
||||
const io = new IntersectionObserver((entries) => {
|
||||
if (!entries.some((e) => e.isIntersecting)) return;
|
||||
setPaging(true);
|
||||
window.setTimeout(() => {
|
||||
const next = page + 1;
|
||||
const items = FIXTURE_FEED_ITEMS.map((raw) => {
|
||||
const it = raw as { post: { id: string } };
|
||||
return { ...it, post: { ...it.post, id: `${it.post.id}-page${next}` } };
|
||||
});
|
||||
setPosts((cur) => [...cur, ...toCardPosts(items)]);
|
||||
setPage(next);
|
||||
setPaging(false);
|
||||
}, 900);
|
||||
}, { root: listEl, rootMargin: "400px" });
|
||||
io.observe(el);
|
||||
return () => io.disconnect();
|
||||
}, [hasMore, paging, page, posts.length, listEl]);
|
||||
|
||||
// The comments calls answer from the fixtures; the preview never reaches the network.
|
||||
useEffect(() => {
|
||||
@@ -91,8 +123,10 @@ export function FeedPreview() {
|
||||
<FeedView
|
||||
posts={posts}
|
||||
status="ready"
|
||||
loadingMore={loadingMore}
|
||||
listRef={list}
|
||||
loadingMore={loadingMore || paging}
|
||||
hasMore={hasMore}
|
||||
sentinelRef={sentinel}
|
||||
listRef={listRef}
|
||||
loadMoreFailed={false}
|
||||
newCount={newCount}
|
||||
onRetry={() => {}}
|
||||
|
||||
Reference in New Issue
Block a user