Bluesky app fork with some witchin' additions 💫

Use scroll position to gate post-created feed refresh (#9881)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

authored by samuel.fm

Claude Opus 4.6 and committed by
GitHub
9b830fd4 4ebeb94b

+19 -20
+1
CLAUDE.md
··· 24 24 yarn ios # Run on iOS 25 25 26 26 # Testing & Quality 27 + # IMPORTANT: Always use these yarn scripts, never call the underlying tools directly 27 28 yarn test # Run Jest tests 28 29 yarn lint # Run ESLint 29 30 yarn typecheck # Run TypeScript type checking
+18 -20
src/view/com/posts/PostFeed.tsx
··· 1 - import { 2 - type JSX, 3 - memo, 4 - useCallback, 5 - useEffect, 6 - useMemo, 7 - useRef, 8 - useState, 9 - } from 'react' 1 + import {memo, useCallback, useEffect, useMemo, useRef, useState} from 'react' 10 2 import { 11 3 ActivityIndicator, 12 4 AppState, ··· 220 212 scrollElRef?: ListRef 221 213 onHasNew?: (v: boolean) => void 222 214 onScrolledDownChange?: (isScrolledDown: boolean) => void 223 - renderEmptyState: () => JSX.Element 224 - renderEndOfFeed?: () => JSX.Element 215 + renderEmptyState: () => React.ReactElement 216 + renderEndOfFeed?: () => React.ReactElement 225 217 testID?: string 226 218 headerOffset?: number 227 219 progressViewOffset?: number 228 220 desktopFixedHeightOffset?: number 229 - ListHeaderComponent?: () => JSX.Element 221 + ListHeaderComponent?: () => React.ReactElement 230 222 extraData?: any 231 223 savedFeedConfig?: AppBskyActorDefs.SavedFeed 232 224 initialNumToRender?: number ··· 309 301 } 310 302 }) 311 303 304 + const isScrolledDownRef = useRef(false) 305 + const handleScrolledDownChange = (isScrolledDown: boolean) => { 306 + isScrolledDownRef.current = isScrolledDown 307 + onScrolledDownChange?.(isScrolledDown) 308 + } 309 + 312 310 const myDid = currentAccount?.did || '' 313 311 const onPostCreated = useCallback(() => { 314 312 // NOTE 315 - // only invalidate if there's 1 page 316 - // more than 1 page can trigger some UI freakouts on iOS and android 317 - // -prf 313 + // only invalidate if at the top of the feed 314 + // changing content when scrolled can trigger some UI freakouts on iOS and android 315 + // -sfn 318 316 if ( 319 - data?.pages.length === 1 && 317 + !isScrolledDownRef.current && 320 318 (feed === 'following' || 321 319 feed === `author|${myDid}|posts_and_author_threads`) 322 320 ) { 323 - queryClient.invalidateQueries({queryKey: RQKEY(feed)}) 321 + void queryClient.invalidateQueries({queryKey: RQKEY(feed)}) 324 322 } 325 - }, [queryClient, feed, data, myDid]) 323 + }, [queryClient, feed, myDid]) 326 324 useEffect(() => { 327 325 return listenPostCreated(onPostCreated) 328 326 }, [onPostCreated]) ··· 981 979 } 982 980 } 983 981 }, 984 - [feedFeedback, feed, liveNowConfig, getPostPosition], 982 + [feedFeedback, feed, liveNowConfig, getPostPosition, ax], 985 983 ) 986 984 987 985 return ( ··· 1001 999 contentContainerStyle={{ 1002 1000 minHeight: Dimensions.get('window').height * 1.5, 1003 1001 }} 1004 - onScrolledDownChange={onScrolledDownChange} 1002 + onScrolledDownChange={handleScrolledDownChange} 1005 1003 onEndReached={onEndReached} 1006 1004 onEndReachedThreshold={2} // number of posts left to trigger load more 1007 1005 removeClippedSubviews={true}