WIP scroll handling

This commit is contained in:
Eric Bailey
2025-05-20 21:40:40 -05:00
parent 7d4ce438ca
commit fc9d8d060a
+101 -3
View File
@@ -121,6 +121,56 @@ function useThreadPreferences() {
) )
} }
export function useControlledListScrolling({
isResetting,
}: {
isResetting: boolean
}) {
const ref = useRef<ListMethods>(null)
const layoutHeaderRef = useRef<View | null>(null)
const anchorPostRef = useRef<View | null>(null)
const didAdjustScrollWeb = useRef<boolean>(false)
if (didAdjustScrollWeb.current && isResetting) {
ref.current?.scrollToOffset({
animated: false,
offset: 0,
})
didAdjustScrollWeb.current = false
}
return {
listRef: ref,
headerRef: layoutHeaderRef,
anchorRef: anchorPostRef,
handleScrollReset() {
// only run once
// TODO need to handle this any time the query changes
if (didAdjustScrollWeb.current) {
return
}
if (!isResetting) {
// Measure synchronously to avoid a layout jump.
const anchorPost = anchorPostRef.current as any as Element
const headerNode = layoutHeaderRef.current as any as Element
if (anchorPost && headerNode) {
// get new scroll position
let pageY = anchorPost.getBoundingClientRect().top
// subtract header height
pageY -= headerNode.getBoundingClientRect().height
// don't scroll past 0
pageY = Math.max(0, pageY)
ref.current?.scrollToOffset({
animated: false,
offset: pageY,
})
didAdjustScrollWeb.current = true
}
}
}
}
}
export function Inner({uri}: {uri: string | undefined}) { export function Inner({uri}: {uri: string | undefined}) {
const t = useTheme() const t = useTheme()
const {_} = useLingui() const {_} = useLingui()
@@ -142,7 +192,7 @@ export function Inner({uri}: {uri: string | undefined}) {
Set<HiddenReplyKind> Set<HiddenReplyKind>
>(new Set()) >(new Set())
const {isFetching, isPlaceholderData, error, data, refetch, insertReplies} = const {isFetching, isPlaceholderData, error, data, refetch, insertReplies, ...rest} =
usePostThread({ usePostThread({
uri, uri,
enabled: isThreadPreferencesLoaded, enabled: isThreadPreferencesLoaded,
@@ -155,6 +205,11 @@ export function Inner({uri}: {uri: string | undefined}) {
shownHiddenReplyKinds, shownHiddenReplyKinds,
}, },
}) })
console.log({
isFetching,
isPlaceholderData,
rest,
})
const ref = useRef<ListMethods>(null) const ref = useRef<ListMethods>(null)
const layoutHeaderRef = useRef<View | null>(null) const layoutHeaderRef = useRef<View | null>(null)
@@ -286,10 +341,23 @@ export function Inner({uri}: {uri: string | undefined}) {
* list. * list.
*/ */
const didAdjustScrollWeb = useRef<boolean>(false) const didAdjustScrollWeb = useRef<boolean>(false)
/*
if (didAdjustScrollWeb.current && rest.fetchStatus === 'fetching') {
ref.current?.scrollToOffset({
animated: false,
offset: 0,
})
didAdjustScrollWeb.current = false
}
*/
const onContentSizeChangeWeb = () => { const onContentSizeChangeWeb = () => {
return
// only run once // only run once
if (didAdjustScrollWeb.current) return // TODO need to handle this any time the query changes
if (!isPlaceholderData) { if (didAdjustScrollWeb.current) {
return
}
if (rest.fetchStatus === 'idle') {
// Measure synchronously to avoid a layout jump. // Measure synchronously to avoid a layout jump.
const anchorPost = anchorPostRef.current as any as Element const anchorPost = anchorPostRef.current as any as Element
const headerNode = layoutHeaderRef.current as any as Element const headerNode = layoutHeaderRef.current as any as Element
@@ -309,6 +377,36 @@ export function Inner({uri}: {uri: string | undefined}) {
} }
} }
/**
* This works AFTER the data is in the cache, but not on initial loads
*/
const lastUpdate = useRef<number>(rest.dataUpdatedAt)
if (rest.dataUpdatedAt && rest.dataUpdatedAt !== lastUpdate.current) {
lastUpdate.current = rest.dataUpdatedAt
ref.current?.scrollToOffset({
animated: false,
offset: 0,
})
// Measure synchronously to avoid a layout jump.
const anchorPost = anchorPostRef.current as any as Element
const headerNode = layoutHeaderRef.current as any as Element
if (anchorPost && headerNode) {
// get new scroll position
let pageY = anchorPost.getBoundingClientRect().top
// subtract header height
pageY -= headerNode.getBoundingClientRect().height
// don't scroll past 0
pageY = Math.max(0, pageY)
ref.current?.scrollToOffset({
animated: false,
offset: pageY,
})
didAdjustScrollWeb.current = true
}
}
return ( return (
<> <>
<Layout.Header.Outer headerRef={layoutHeaderRef}> <Layout.Header.Outer headerRef={layoutHeaderRef}>