Cleanup
This commit is contained in:
@@ -6,7 +6,6 @@ import {TabBar} from './TabBar'
|
|||||||
import {usePalette} from '#/lib/hooks/usePalette'
|
import {usePalette} from '#/lib/hooks/usePalette'
|
||||||
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
||||||
import {ListMethods} from '../util/List'
|
import {ListMethods} from '../util/List'
|
||||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
|
||||||
|
|
||||||
export interface PagerWithHeaderChildParams {
|
export interface PagerWithHeaderChildParams {
|
||||||
headerHeight: number
|
headerHeight: number
|
||||||
@@ -108,6 +107,7 @@ let PagerTabBar = ({
|
|||||||
renderHeader?: () => JSX.Element
|
renderHeader?: () => JSX.Element
|
||||||
onCurrentPageSelected?: (index: number) => void
|
onCurrentPageSelected?: (index: number) => void
|
||||||
onSelect?: (index: number) => void
|
onSelect?: (index: number) => void
|
||||||
|
tabBarAnchor?: JSX.Element
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {isMobile} = useWebMediaQueries()
|
const {isMobile} = useWebMediaQueries()
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ function PostThreadLoaded({
|
|||||||
|
|
||||||
// wait for loading to finish
|
// wait for loading to finish
|
||||||
if (thread.type === 'post' && !!thread.parent) {
|
if (thread.type === 'post' && !!thread.parent) {
|
||||||
function onMeasure(pageY) {
|
function onMeasure(pageY: number) {
|
||||||
let spinnerHeight = 0
|
let spinnerHeight = 0
|
||||||
if (isDesktop) {
|
if (isDesktop) {
|
||||||
spinnerHeight = 40
|
spinnerHeight = 40
|
||||||
@@ -216,9 +216,13 @@ function PostThreadLoaded({
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
const pageY = highlightedPostRef.current.getBoundingClientRect().top
|
// Measure synchronously to avoid a layout jump.
|
||||||
|
const domNode = highlightedPostRef.current
|
||||||
|
if (domNode) {
|
||||||
|
const pageY = (domNode as any as Element).getBoundingClientRect().top
|
||||||
onMeasure(pageY)
|
onMeasure(pageY)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
needsScrollAdjustment.current = false
|
needsScrollAdjustment.current = false
|
||||||
}
|
}
|
||||||
}, [thread, isDesktop, isTabletOrMobile])
|
}, [thread, isDesktop, isTabletOrMobile])
|
||||||
|
|||||||
@@ -86,9 +86,9 @@ function ListImpl<ItemT>(
|
|||||||
return (
|
return (
|
||||||
<FlatList_INTERNAL
|
<FlatList_INTERNAL
|
||||||
{...props}
|
{...props}
|
||||||
|
scrollIndicatorInsets={{right: 1}}
|
||||||
contentOffset={contentOffset}
|
contentOffset={contentOffset}
|
||||||
refreshControl={refreshControl}
|
refreshControl={refreshControl}
|
||||||
scrollIndicatorInsets={{right: 1}}
|
|
||||||
onScroll={scrollHandler}
|
onScroll={scrollHandler}
|
||||||
scrollEventThrottle={1}
|
scrollEventThrottle={1}
|
||||||
style={style}
|
style={style}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {useScrollHandlers} from '#/lib/ScrollContext'
|
|||||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
import {batchedUpdates} from '#/lib/batchedUpdates'
|
import {batchedUpdates} from '#/lib/batchedUpdates'
|
||||||
|
|
||||||
export type ListMethods = FlatList_INTERNAL
|
export type ListMethods = any // TODO: Better types.
|
||||||
export type ListProps<ItemT> = Omit<
|
export type ListProps<ItemT> = Omit<
|
||||||
FlatListProps<ItemT>,
|
FlatListProps<ItemT>,
|
||||||
| 'onScroll' // Use ScrollContext instead.
|
| 'onScroll' // Use ScrollContext instead.
|
||||||
@@ -18,8 +18,9 @@ export type ListProps<ItemT> = Omit<
|
|||||||
headerOffset?: number
|
headerOffset?: number
|
||||||
refreshing?: boolean
|
refreshing?: boolean
|
||||||
onRefresh?: () => void
|
onRefresh?: () => void
|
||||||
|
desktopFixedHeight: any // TODO: Better types.
|
||||||
}
|
}
|
||||||
export type ListRef = React.MutableRefObject<FlatList_INTERNAL | null>
|
export type ListRef = React.MutableRefObject<any | null> // TODO: Better types.
|
||||||
|
|
||||||
function ListImpl<ItemT>(
|
function ListImpl<ItemT>(
|
||||||
{
|
{
|
||||||
@@ -27,7 +28,7 @@ function ListImpl<ItemT>(
|
|||||||
ListFooterComponent,
|
ListFooterComponent,
|
||||||
contentContainerStyle,
|
contentContainerStyle,
|
||||||
data,
|
data,
|
||||||
desktopFixedHeight, // TODO
|
desktopFixedHeight,
|
||||||
headerOffset,
|
headerOffset,
|
||||||
keyExtractor,
|
keyExtractor,
|
||||||
refreshing: _unsupportedRefreshing,
|
refreshing: _unsupportedRefreshing,
|
||||||
@@ -53,7 +54,7 @@ function ListImpl<ItemT>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let header: ListProps<ItemT>['ListHeaderComponent'] = null
|
let header: JSX.Element | null = null
|
||||||
if (ListHeaderComponent != null) {
|
if (ListHeaderComponent != null) {
|
||||||
if (typeof ListHeaderComponent === 'object') {
|
if (typeof ListHeaderComponent === 'object') {
|
||||||
header = ListHeaderComponent
|
header = ListHeaderComponent
|
||||||
@@ -63,7 +64,7 @@ function ListImpl<ItemT>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let footer: ListProps<ItemT>['ListHeaderComponent'] = null
|
let footer: JSX.Element | null = null
|
||||||
if (ListFooterComponent != null) {
|
if (ListFooterComponent != null) {
|
||||||
if (typeof ListFooterComponent === 'object') {
|
if (typeof ListFooterComponent === 'object') {
|
||||||
footer = ListFooterComponent
|
footer = ListFooterComponent
|
||||||
@@ -100,11 +101,15 @@ function ListImpl<ItemT>(
|
|||||||
behavior: animated ? 'smooth' : 'instant',
|
behavior: animated ? 'smooth' : 'instant',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
} as any), // TODO: Types.
|
} as any), // TODO: Better types.
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
|
|
||||||
const [isVisible, setIsVisible] = React.useState(false)
|
// --- onContentSizeChange ---
|
||||||
|
const containerRef = useRef(null)
|
||||||
|
useResizeObserver(containerRef, onContentSizeChange)
|
||||||
|
|
||||||
|
// --- onScroll ---
|
||||||
const handleScroll = useNonReactiveCallback(() => {
|
const handleScroll = useNonReactiveCallback(() => {
|
||||||
contextScrollHandlers.onScroll?.(
|
contextScrollHandlers.onScroll?.(
|
||||||
{
|
{
|
||||||
@@ -112,21 +117,22 @@ function ListImpl<ItemT>(
|
|||||||
x: window.scrollX,
|
x: window.scrollX,
|
||||||
y: window.scrollY,
|
y: window.scrollY,
|
||||||
},
|
},
|
||||||
// TODO
|
} as any, // TODO: Better types.
|
||||||
},
|
null as any,
|
||||||
{
|
|
||||||
/* TODO */
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
const [isParentTreeVisible, setIsParentTreeVisible] = React.useState(false)
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!isVisible) {
|
if (!isParentTreeVisible) {
|
||||||
|
// Prevents hidden tabs from firing scroll events.
|
||||||
|
// Only one list is expected to be firing these at a time.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
window.addEventListener('scroll', handleScroll)
|
window.addEventListener('scroll', handleScroll)
|
||||||
return () => window.removeEventListener('scroll', handleScroll)
|
return () => window.removeEventListener('scroll', handleScroll)
|
||||||
}, [isVisible, handleScroll])
|
}, [isParentTreeVisible, handleScroll])
|
||||||
|
|
||||||
|
// --- onScrolledDownChange ---
|
||||||
const isScrolledDown = useRef(false)
|
const isScrolledDown = useRef(false)
|
||||||
function handleAboveTheFoldVisibleChange(isAboveTheFold: boolean) {
|
function handleAboveTheFoldVisibleChange(isAboveTheFold: boolean) {
|
||||||
const didScrollDown = !isAboveTheFold
|
const didScrollDown = !isAboveTheFold
|
||||||
@@ -138,13 +144,21 @@ function ListImpl<ItemT>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const containerRef = useRef(null)
|
// --- onEndReached ---
|
||||||
useResizeObserver(containerRef, onContentSizeChange)
|
const onTailVisibilityChange = useNonReactiveCallback(
|
||||||
|
(isTailVisible: boolean) => {
|
||||||
|
if (isTailVisible) {
|
||||||
|
onEndReached?.({
|
||||||
|
distanceFromEnd: onEndReachedThreshold || 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View {...props} style={style} ref={nativeRef}>
|
<View {...props} style={style} ref={nativeRef}>
|
||||||
<Visibility
|
<Visibility
|
||||||
onVisibleChange={setIsVisible}
|
onVisibleChange={setIsParentTreeVisible}
|
||||||
style={styles.parentTreeVisibilityDetector}
|
style={styles.parentTreeVisibilityDetector}
|
||||||
/>
|
/>
|
||||||
<View
|
<View
|
||||||
@@ -172,13 +186,7 @@ function ListImpl<ItemT>(
|
|||||||
{onEndReached && (
|
{onEndReached && (
|
||||||
<Visibility
|
<Visibility
|
||||||
topMargin={(onEndReachedThreshold ?? 0) * 100 + '%'}
|
topMargin={(onEndReachedThreshold ?? 0) * 100 + '%'}
|
||||||
onVisibleChange={isVisible => {
|
onVisibleChange={onTailVisibilityChange}
|
||||||
if (isVisible) {
|
|
||||||
onEndReached?.({
|
|
||||||
distanceFromEnd: onEndReachedThreshold || 0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{footer}
|
{footer}
|
||||||
@@ -187,17 +195,25 @@ function ListImpl<ItemT>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function useResizeObserver(ref, onResize) {
|
function useResizeObserver(
|
||||||
|
ref: React.RefObject<Element>,
|
||||||
|
onResize: undefined | ((w: number, h: number) => void),
|
||||||
|
) {
|
||||||
const handleResize = useNonReactiveCallback(onResize ?? (() => {}))
|
const handleResize = useNonReactiveCallback(onResize ?? (() => {}))
|
||||||
const isActive = !!onResize
|
const isActive = !!onResize
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!isActive) {
|
if (!isActive) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const resizeObserver = new ResizeObserver(() => {
|
const resizeObserver = new ResizeObserver(entries => {
|
||||||
handleResize()
|
batchedUpdates(() => {
|
||||||
|
for (let entry of entries) {
|
||||||
|
const rect = entry.contentRect
|
||||||
|
handleResize(rect.width, rect.height)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
const node = ref.current
|
})
|
||||||
|
const node = ref.current!
|
||||||
resizeObserver.observe(node)
|
resizeObserver.observe(node)
|
||||||
return () => {
|
return () => {
|
||||||
resizeObserver.unobserve(node)
|
resizeObserver.unobserve(node)
|
||||||
|
|||||||
Reference in New Issue
Block a user