BlueSky & more on desktop lazurite.stormlightlabs.org/
tauri rust typescript bluesky appview atproto solid
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 83 lines 3.5 kB view raw
1import { getReplyRootPost } from "$/lib/feeds"; 2import type { PostEngagementTab } from "$/lib/post-engagement-routes"; 3import type { FeedViewPost, PostView } from "$/lib/types"; 4import { For, Show } from "solid-js"; 5import { EmptyFeedState, FeedSkeleton, LoadingMoreIndicator } from "./FeedEmpty"; 6import { PostCard } from "./PostCard"; 7import type { FeedState } from "./types"; 8 9function FeedStatus(props: { activeFeedState: FeedState | undefined; visibleItems: FeedViewPost[] }) { 10 const loading = () => !props.activeFeedState || props.activeFeedState.loading; 11 12 return ( 13 <> 14 <Show when={loading()}> 15 <FeedSkeleton /> 16 </Show> 17 <Show when={props.activeFeedState?.error}> 18 {(message) => ( 19 <div class="rounded-3xl bg-[rgba(138,31,31,0.2)] p-4 text-sm text-error shadow-[inset_0_0_0_1px_rgba(255,128,128,0.2)]"> 20 {message()} 21 </div> 22 )} 23 </Show> 24 <Show when={!loading() && !props.activeFeedState?.error && props.visibleItems.length === 0}> 25 <EmptyFeedState /> 26 </Show> 27 </> 28 ); 29} 30 31export function FeedContent( 32 props: { 33 activeFeedId: string; 34 activeFeedState: FeedState | undefined; 35 bookmarkPendingByUri: Record<string, boolean>; 36 focusedIndex: number; 37 likePendingByUri: Record<string, boolean>; 38 likePulseUri: string | null; 39 onFocusIndex: (index: number) => void; 40 onBookmark: (post: PostView) => Promise<void> | void; 41 onLike: (post: PostView) => Promise<void> | void; 42 onOpenEngagement: (uri: string, tab: PostEngagementTab) => Promise<void> | void; 43 onOpenThread: (uri: string) => Promise<void> | void; 44 onQuote: (post: PostView) => void; 45 onReply: (post: PostView, root: PostView) => void; 46 onRepost: (post: PostView) => Promise<void> | void; 47 postRefs: Map<string, HTMLElement>; 48 repostPendingByUri: Record<string, boolean>; 49 repostPulseUri: string | null; 50 sentinelRef: (element: HTMLDivElement) => void; 51 visibleItems: FeedViewPost[]; 52 }, 53) { 54 return ( 55 <div class="grid min-w-0 gap-3" data-feed-id={props.activeFeedId}> 56 <FeedStatus activeFeedState={props.activeFeedState} visibleItems={props.visibleItems} /> 57 <For each={props.visibleItems}> 58 {(item, index) => ( 59 <PostCard 60 bookmarkPending={!!props.bookmarkPendingByUri[item.post.uri]} 61 focused={props.focusedIndex === index()} 62 item={item} 63 likePending={!!props.likePendingByUri[item.post.uri]} 64 onBookmark={() => void props.onBookmark(item.post)} 65 onFocus={() => props.onFocusIndex(index())} 66 onLike={() => void props.onLike(item.post)} 67 onOpenEngagement={(tab) => void props.onOpenEngagement(item.post.uri, tab)} 68 onOpenThread={(uri) => void props.onOpenThread(uri)} 69 onQuote={() => props.onQuote(item.post)} 70 onReply={() => props.onReply(item.post, getReplyRootPost(item))} 71 onRepost={() => void props.onRepost(item.post)} 72 post={item.post} 73 pulseLike={props.likePulseUri === item.post.uri} 74 pulseRepost={props.repostPulseUri === item.post.uri} 75 registerRef={(element) => props.postRefs.set(item.post.uri, element)} 76 repostPending={!!props.repostPendingByUri[item.post.uri]} /> 77 )} 78 </For> 79 <div ref={(element) => props.sentinelRef(element)} /> 80 <LoadingMoreIndicator loading={!!props.activeFeedState?.loadingMore} /> 81 </div> 82 ); 83}