Checkpoint parent rendering, can opt for slower handling here

This commit is contained in:
Eric Bailey
2025-05-29 21:11:26 -05:00
parent 10a77f0614
commit 5ca9e05be0
3 changed files with 80 additions and 15 deletions
@@ -66,7 +66,7 @@ export function ThreadPost({
}
return (
<PostThreadItemLoaded
<ThreadPostInner
// Safeguard from clobbering per-post state below:
key={postShadow.uri}
item={item}
@@ -99,7 +99,7 @@ function PostThreadItemDeleted({hideTopBorder}: {hideTopBorder?: boolean}) {
)
}
let PostThreadItemLoaded = ({
const ThreadPostInner = memo(function ThreadPostInner({
item,
postShadow,
overrides,
@@ -114,7 +114,7 @@ let PostThreadItemLoaded = ({
}
onPostSuccess?: (data: OnPostSuccessData) => void
threadgateRecord?: AppBskyFeedThreadgate.Record
}): React.ReactNode => {
}): React.ReactNode {
const t = useTheme()
const pal = usePalette('default')
const {_} = useLingui()
@@ -305,8 +305,7 @@ let PostThreadItemLoaded = ({
</View>
</SubtleHover>
)
}
PostThreadItemLoaded = memo(PostThreadItemLoaded)
})
function SubtleHover({children}: {children: React.ReactNode}) {
const {
@@ -70,7 +70,7 @@ export function ThreadReply({
}
return (
<PostThreadItemLoaded
<ThreadReplyInner
// Safeguard from clobbering per-post state below:
key={postShadow.uri}
item={item}
@@ -103,7 +103,7 @@ function PostThreadItemDeleted({hideTopBorder}: {hideTopBorder?: boolean}) {
)
}
let PostThreadItemLoaded = ({
const ThreadReplyInner = memo(function ThreadReplyInner({
item,
postShadow,
overrides,
@@ -118,7 +118,7 @@ let PostThreadItemLoaded = ({
}
onPostSuccess?: (data: OnPostSuccessData) => void
threadgateRecord?: AppBskyFeedThreadgate.Record
}): React.ReactNode => {
}): React.ReactNode {
const t = useTheme()
const pal = usePalette('default')
const {_} = useLingui()
@@ -336,8 +336,7 @@ let PostThreadItemLoaded = ({
</View>
</View>
)
}
PostThreadItemLoaded = memo(PostThreadItemLoaded)
})
function SubtleHover({children}: {children: React.ReactNode}) {
const {
+72 -5
View File
@@ -2,6 +2,7 @@ import {useMemo, useRef, useState} from 'react'
import {useWindowDimensions, View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {runOnJS} from 'react-native-reanimated'
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
@@ -29,6 +30,9 @@ import * as Layout from '#/components/Layout'
import {ListFooter} from '#/components/Lists'
import {Text} from '#/components/Typography'
const PARENT_CHUNK_SIZE = 5
const CHILD_CHUNK_SIZE = 50
export function Inner({uri}: {uri: string | undefined}) {
const t = useTheme()
const {_} = useLingui()
@@ -144,6 +148,68 @@ export function Inner({uri}: {uri: string | undefined}) {
* scroll in onContentSizeChange instead.
*/
const [deferParents, setDeferParents] = useState(isNative)
const [maxParentCount, setMaxParentCount] = useState(PARENT_CHUNK_SIZE)
const [maxChildCount, setMaxChildCount] = useState(CHILD_CHUNK_SIZE)
const needsBumpMaxParents = useRef(false)
const onStartReached = () => {
setMaxParentCount(n => n + PARENT_CHUNK_SIZE)
// needsBumpMaxParents.current = true
}
// const bumpMaxParentsIfNeeded = () => {
// if (!isNative) {
// return
// }
// if (needsBumpMaxParents.current) {
// needsBumpMaxParents.current = false
// setMaxParentCount(n => n + PARENT_CHUNK_SIZE)
// }
// }
// const onScrollToTop = bumpMaxParentsIfNeeded
// const onMomentumEnd = () => {
// 'worklet'
// runOnJS(bumpMaxParentsIfNeeded)()
// }
const onEndReached = () => {
if (isFetching) return
setMaxChildCount(prev => prev + CHILD_CHUNK_SIZE)
}
const items = useMemo(() => {
const results: Slice[] = []
if (!data?.items) return results
let ci = 0
for (let i = 0; i < data.items.length; i++) {
const item = data.items[i]
if ('depth' in item) {
if (item.depth === 0) {
results.push(item)
if (!deferParents) {
const start = i - 1
const limit = Math.max(0, start - maxParentCount)
for (let pi = start; pi >= limit; pi--) {
results.unshift(data.items[pi])
}
}
} else if (item.depth > 0) {
if (ci <= maxChildCount) {
results.push(item)
ci++
}
}
} else {
results.push(item)
}
}
return results
}, [data, deferParents, maxParentCount, maxChildCount])
const renderItem = ({item, index}: {item: Slice; index: number}) => {
if (item.type === 'threadPost') {
if (item.depth < 0) {
@@ -273,18 +339,19 @@ export function Inner({uri}: {uri: string | undefined}) {
<PostThreadError error={error} />
) : (
<ScrollProvider
// onMomentumEnd={onMomentumEnd}
//onMomentumEnd={onMomentumEnd}
>
<List
ref={listRef}
data={data?.items || []}
data={items}
renderItem={renderItem}
keyExtractor={keyExtractor}
onContentSizeChange={onContentSizeChangeWebOnly}
// onStartReached={onStartReached}
// onEndReached={onEndReached}
onStartReached={onStartReached}
onEndReached={onEndReached}
onEndReachedThreshold={2}
// onScrollToTop={onScrollToTop}
onStartReachedThreshold={1}
//onScrollToTop={onScrollToTop}
/**
* @see https://reactnative.dev/docs/scrollview#maintainvisiblecontentposition
*/