Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

fix: make AlsoLiked post buttons visually update and defer post loading

+55 -5
+30 -4
src/screens/PostThread/index.tsx
··· 153 153 const alsoLikedFeedEnabled = useAlsoLikedFeedEnabled() 154 154 const alsoLikedAnchorUri = 155 155 anchor?.type === 'threadPost' && isRoot ? anchor.value.post.uri : undefined 156 + const [deferParents, setDeferParents] = useState(true) 157 + const [alsoLikedReady, setAlsoLikedReady] = useState(false) 158 + useEffect(() => { 159 + const shouldEnable = 160 + Boolean(alsoLikedAnchorUri) && 161 + alsoLikedFeedEnabled && 162 + !thread.state.isPlaceholderData && 163 + !deferParents 164 + 165 + if (!shouldEnable) { 166 + setAlsoLikedReady(false) 167 + return 168 + } 169 + 170 + const timeout = setTimeout(() => { 171 + startTransition(() => { 172 + setAlsoLikedReady(true) 173 + }) 174 + }, 0) 175 + 176 + return () => clearTimeout(timeout) 177 + }, [ 178 + alsoLikedAnchorUri, 179 + alsoLikedFeedEnabled, 180 + deferParents, 181 + thread.state.isPlaceholderData, 182 + ]) 156 183 const alsoLiked = usePostAlsoLikedQuery(alsoLikedAnchorUri, { 157 - enabled: Boolean(alsoLikedAnchorUri) && alsoLikedFeedEnabled, 184 + enabled: alsoLikedReady, 158 185 }) 159 186 const alsoLikedPosts = useMemo(() => { 160 187 const seen = new Set<string>() ··· 188 215 * On web, `onContentSizeChange` is used to get ahead of next paint and handle 189 216 * this scrolling. 190 217 */ 191 - const [deferParents, setDeferParents] = useState(true) 192 218 /** 193 219 * Used to flag whether we should scroll to the anchor post. On a cold load, 194 220 * this is always true. And when a user changes thread parameters, we also ··· 355 381 } 356 382 if ( 357 383 alsoLikedAnchorUri && 358 - alsoLikedFeedEnabled && 384 + alsoLikedReady && 359 385 !alsoLiked.isLoading && 360 386 !alsoLiked.isFetchingNextPage && 361 387 alsoLiked.hasNextPage ··· 633 659 ListFooterComponent={ 634 660 <ThreadAlsoLiked 635 661 posts={alsoLikedPosts} 636 - enabled={Boolean(alsoLikedAnchorUri) && alsoLikedFeedEnabled} 662 + enabled={alsoLikedReady} 637 663 isLoading={alsoLiked.isLoading} 638 664 isFetchingNextPage={alsoLiked.isFetchingNextPage} 639 665 error={alsoLiked.error}
+4
src/state/cache/post-shadow.ts
··· 11 11 import {findAllPostsInQueryData as findAllPostsInBookmarksQueryData} from '#/state/queries/bookmarks/useBookmarksQuery' 12 12 import {findAllPostsInQueryData as findAllPostsInExploreFeedPreviewsQueryData} from '#/state/queries/explore-feed-previews' 13 13 import {findAllPostsInQueryData as findAllPostsInNotifsQueryData} from '#/state/queries/notifications/feed' 14 + import {findAllPostsInQueryData as findAllPostsInPostQueryData} from '#/state/queries/post' 14 15 import {findAllPostsInQueryData as findAllPostsInFeedQueryData} from '#/state/queries/post-feed' 15 16 import {findAllPostsInQueryData as findAllPostsInQuoteQueryData} from '#/state/queries/post-quotes' 16 17 import {findAllPostsInQueryData as findAllPostsInSearchQueryData} from '#/state/queries/search-posts' ··· 180 181 yield post 181 182 } 182 183 for (let post of findAllPostsInSearchQueryData(queryClient, uri)) { 184 + yield post 185 + } 186 + for (let post of findAllPostsInPostQueryData(queryClient, uri)) { 183 187 yield post 184 188 } 185 189 for (let post of findAllPostsInQuoteQueryData(queryClient, uri)) {
+11 -1
src/state/queries/post-also-liked.ts
··· 1 1 import {type AppBskyFeedDefs} from '@atproto/api' 2 - import {type InfiniteData, useInfiniteQuery} from '@tanstack/react-query' 2 + import { 3 + type InfiniteData, 4 + useInfiniteQuery, 5 + useQueryClient, 6 + } from '@tanstack/react-query' 3 7 4 8 import {STALE} from '#/state/queries' 9 + import {precachePost} from '#/state/queries/post' 5 10 import {useAgent} from '#/state/session' 6 11 import {IS_WEB} from '#/env' 7 12 ··· 93 98 opts?: {enabled?: boolean}, 94 99 ) { 95 100 const agent = useAgent() 101 + const queryClient = useQueryClient() 96 102 97 103 return useInfiniteQuery< 98 104 AlsoLikedPage, ··· 132 138 const postsByUri = new Map( 133 139 postsRes.data.posts.map(post => [post.uri, post] as const), 134 140 ) 141 + 142 + for (const post of postsRes.data.posts) { 143 + precachePost(queryClient, post.uri, post) 144 + } 135 145 136 146 return { 137 147 cursor: data.cursor,
+10
src/state/queries/post.ts
··· 57 57 queryClient.setQueryData(RQKEY(uri), post) 58 58 } 59 59 60 + export function* findAllPostsInQueryData( 61 + queryClient: QueryClient, 62 + uri: string, 63 + ): Generator<AppBskyFeedDefs.PostView, void> { 64 + const post = queryClient.getQueryData<AppBskyFeedDefs.PostView>(RQKEY(uri)) 65 + if (post) { 66 + yield post 67 + } 68 + } 69 + 60 70 export function useGetPost() { 61 71 const queryClient = useQueryClient() 62 72 const agent = useAgent()