limit how much we show in ui in timelines and reset it on navigation
44 unmodified lines45464748495051525324 unmodified lines787980818283848586878889909192933 unmodified lines97989910010110210310410510610710810910411011111211311411510610710810911011111211311611711811912012112212312412512612712812913011613111811913213313413510 unmodified lines14614714814913815015115215315411 unmodified lines16616716816915817017117217317425 unmodified lines44 unmodified lines $effect(() => { selectedFeed; feedServiceDid = null; newPostsAvailable = false; displayCount = 15; loaderState.reset(); fetchFeedGenerator(client ?? viewClient, selectedFeed).then((meta) => { feedServiceDid = meta?.did ?? null; });24 unmodified lines export const clearFeed = () => { if (!userDid) return; scrollContainer?.scrollTo({ top: 0, behavior: 'smooth' }); newPostsAvailable = false; displayCount = 15; resetFeed(userDid, selectedFeed); loaderState.reset(); loadMore(); };
let displayCount = $state(15);
const feedPosts = $derived.by(() => { if (!userDid) return []; const uris = feedTimelines.get(userDid)?.get(selectedFeed) ?? []; return uris3 unmodified lines }) .filter((p): p is NonNullable<typeof p> => p !== undefined); });
const renderedPosts = $derived(feedPosts.slice(0, displayCount));
const loadMore = async () => { if (loading || !client || !userDid || !feedServiceDid) return;
loading = true; loaderState.status = 'LOADING';
try { const result = await fetchFeed(client, selectedFeed, feedServiceDid); displayCount += 10; const bufferSize = feedPosts.length - displayCount; const cursor = feedCursors.get(userDid)?.get(selectedFeed);
if (bufferSize < 5 && !cursor?.end) { const result = await fetchFeed(client, selectedFeed, feedServiceDid); if (client.user && userDid) { if (!fetchingInteractions) { scheduledFetchInteractions = false; fetchingInteractions = true; await fetchInteractionsToFeedTimelineEnd(client, userDid, selectedFeed); fetchingInteractions = false; } else { scheduledFetchInteractions = true; if (client.user && userDid) { if (!fetchingInteractions) { scheduledFetchInteractions = false; fetchingInteractions = true; await fetchInteractionsToFeedTimelineEnd(client, userDid, selectedFeed); fetchingInteractions = false; } else { scheduledFetchInteractions = true; } } console.log('feed loaded', result?.end); if (result?.end) loaderState.complete(); } else { if (cursor?.end && displayCount >= feedPosts.length) loaderState.complete(); }
loaderState.loaded(); console.log('feed loaded', result?.end); if (result?.end) loaderState.complete(); } catch (error) { loadError = `${error}`; loaderState.error(); } finally {10 unmodified lines });</script>
{#snippet feedPostsView()} {#each feedPosts as post, i (post.uri)} {#each renderedPosts as post, i (post.uri)} {@const uriParts = post.uri.split('/')} {@const postDid = uriParts[2] as Did} {@const postRkey = uriParts[4] as RecordKey} <div class="mb-1.5">11 unmodified lines postComposerState.replying = p; }} /> </div> {#if i < feedPosts.length - 1} {#if i < renderedPosts.length - 1} <div class="mx-8 mt-3 mb-4 h-px bg-linear-to-r from-(--nucleus-accent)/30 to-(--nucleus-accent2)/30" ></div> {/if}25 unmodified lines117 unmodified linesExpand all1181191201211221231241251263 unmodified lines117 unmodified linesExpand all
<GenericTimelineView {client} {threads} timelineId={`following:${userDid}`} bind:postComposerState class={className} isLoggedIn={!!(userDid || $accounts.length > 0)} canLoad={!!(client && userDid && initialDone.has(userDid))}3 unmodified lines16 unmodified lines1718192021222324253 unmodified lines29303132333435363713 unmodified lines515253545556575859606162636465666718 unmodified lines8687888980909192939495829697989910028 unmodified lines12913013113211913313413513613740 unmodified lines17817918018116818218318418518625 unmodified lines16 unmodified lines
interface Props { client?: AtpClient | null; threads: Thread[]; timelineId?: string; postComposerState: PostComposerState; class?: string; isLoggedIn?: boolean; // Controls rendering of the list vs NotLoggedIn canLoad?: boolean; // Controls whether we can actually load more data3 unmodified lines
let { client = null, threads, timelineId = undefined, postComposerState = $bindable(), class: className = '', isLoggedIn = false, canLoad = undefined,13 unmodified lines if (boundaryTime === null) return threads; return threads.filter((t) => t.newestTime <= boundaryTime!); });
let displayCount = $state(15); $effect(() => { timelineId; displayCount = 15; });
const renderedThreads = $derived(visibleThreads.slice(0, displayCount));
$effect(() => { if (threads.length > 0) { if (isAtTop) boundaryTime = threads[0].newestTime; else if (boundaryTime === null) boundaryTime = threads[0].newestTime; }18 unmodified lines loaderState.status = 'LOADING'; loadError = '';
try { await onLoadMore(); displayCount += 10; const bufferSize = visibleThreads.length - displayCount;
if (bufferSize < 5 && !isComplete) await onLoadMore();
loaderState.loaded(); if (isComplete) loaderState.complete(); if (isComplete && displayCount >= visibleThreads.length) loaderState.complete(); } catch (error) { loadError = `${error}`; loaderState.error(); } finally {28 unmodified lines </span>{/snippet}
{#snippet threadsView()} {#each visibleThreads as thread, i (thread.rootUri)} {#each renderedThreads as thread, i (thread.rootUri)} <div class="flex w-full shrink-0 {reverseChronological ? 'flex-col' : 'flex-col-reverse'}"> {#if thread.branchParentPost} {@render replyPost(thread.branchParentPost)} {/if}40 unmodified lines {/if} {/if} {/each} </div> {#if i < visibleThreads.length - 1} {#if i < renderedThreads.length - 1} <div class="mx-8 mt-3 mb-4 h-px bg-linear-to-r from-(--nucleus-accent)/30 to-(--nucleus-accent2)/30" ></div> {/if}25 unmodified lines83 unmodified lines8485868788899091923 unmodified lines83 unmodified lines
<GenericTimelineView {client} {threads} timelineId={`replies:${did}`} bind:postComposerState class={className} isLoggedIn={!!(did || $accounts.length > 0)} canLoad={!!(client && userDid && did)}3 unmodified lines917 unmodified linesExpand all91891992092192292292392492592692792892892993093193214 unmodified lines947948949950951951952953954955956957957958959960961142 unmodified linesExpand all917 unmodified linesExpand all
const feed = followingFeed.get(userDid); if (!feed || feed.size === 0) return;
let minTimestamp = Date.now() * 1000; let minTimestamp = Date.now(); let found = false;
for (const uri of feed) { const post = getPostFromUri(uri); if (post) { const ts = new Date(post.record.createdAt).getTime() * 1000; const ts = new Date(post.record.createdAt).getTime(); if (ts < minTimestamp) minTimestamp = ts; found = true; } }14 unmodified lines if (!userFeedTimelines) return; const posts = userFeedTimelines.get(feedUri); if (!posts || posts.length === 0) return;
let minTimestamp = Date.now() * 1000; let minTimestamp = Date.now(); let found = false;
for (const uri of posts) { const post = getPostFromUri(uri); if (post) { const ts = new Date(post.record.createdAt).getTime() * 1000; const ts = new Date(post.record.createdAt).getTime(); if (ts < minTimestamp) minTimestamp = ts; found = true; } }142 unmodified linesExpand all