Add an intermediate List component

This commit is contained in:
Dan Abramov
2023-12-13 00:42:35 +00:00
parent 5fa43530f6
commit 7eb4ad6c29
24 changed files with 95 additions and 100 deletions
+3 -2
View File
@@ -13,7 +13,8 @@ import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed'
import {ComposeIcon2} from 'lib/icons'
import {colors, s} from 'lib/styles'
import {FlatList, View, useWindowDimensions} from 'react-native'
import {View, useWindowDimensions} from 'react-native'
import {ListMethods} from '../util/List'
import {Feed} from '../posts/Feed'
import {TextLink} from '../util/Link'
import {FAB} from '../util/fab/FAB'
@@ -54,7 +55,7 @@ export function FeedPage({
const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll()
const {screen, track} = useAnalytics()
const headerOffset = useHeaderOffset()
const scrollElRef = React.useRef<FlatList>(null)
const scrollElRef = React.useRef<ListMethods>(null)
const [hasNew, setHasNew] = React.useState(false)
const scrollToTop = React.useCallback(() => {
+4 -4
View File
@@ -1,4 +1,4 @@
import React, {MutableRefObject} from 'react'
import React from 'react'
import {
Dimensions,
RefreshControl,
@@ -8,7 +8,7 @@ import {
ViewStyle,
} from 'react-native'
import {useQueryClient} from '@tanstack/react-query'
import {FlatList} from '../util/Views'
import {List, ListRef} from '../util/List'
import {FeedSourceCardLoaded} from './FeedSourceCard'
import {ErrorMessage} from '../util/error/ErrorMessage'
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
@@ -37,7 +37,7 @@ interface SectionRef {
interface ProfileFeedgensProps {
did: string
scrollElRef: MutableRefObject<FlatList<any> | null>
scrollElRef: ListRef
onScroll?: OnScrollHandler
scrollEventThrottle?: number
headerOffset: number
@@ -188,7 +188,7 @@ export const ProfileFeedgens = React.forwardRef<
const scrollHandler = useAnimatedScrollHandler(onScroll || {})
return (
<View testID={testID} style={style}>
<FlatList
<List
testID={testID ? `${testID}-flatlist` : undefined}
ref={scrollElRef}
data={items}
+4 -4
View File
@@ -1,4 +1,4 @@
import React, {MutableRefObject} from 'react'
import React from 'react'
import {
ActivityIndicator,
Dimensions,
@@ -8,7 +8,7 @@ import {
ViewStyle,
} from 'react-native'
import {AppBskyActorDefs, AppBskyGraphDefs} from '@atproto/api'
import {FlatList} from '../util/Views'
import {List, ListRef} from '../util/List'
import {ProfileCardFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
import {ErrorMessage} from '../util/error/ErrorMessage'
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
@@ -45,7 +45,7 @@ export function ListMembers({
}: {
list: string
style?: StyleProp<ViewStyle>
scrollElRef?: MutableRefObject<FlatList<any> | null>
scrollElRef?: ListRef
onScroll: OnScrollHandler
onPressTryAgain?: () => void
renderHeader: () => JSX.Element
@@ -212,7 +212,7 @@ export function ListMembers({
const scrollHandler = useAnimatedScrollHandler(onScroll)
return (
<View testID={testID} style={style}>
<FlatList
<List
testID={testID ? `${testID}-flatlist` : undefined}
ref={scrollElRef}
data={items}
+2 -2
View File
@@ -15,7 +15,7 @@ import {ErrorMessage} from '../util/error/ErrorMessage'
import {Text} from '../util/text/Text'
import {useAnalytics} from 'lib/analytics/analytics'
import {usePalette} from 'lib/hooks/usePalette'
import {FlatList} from '../util/Views'
import {List} from '../util/List'
import {s} from 'lib/styles'
import {logger} from '#/logger'
import {Trans} from '@lingui/macro'
@@ -119,7 +119,7 @@ export function MyLists({
[error, onRefresh, renderItem, pal],
)
const FlatListCom = inline ? RNFlatList : FlatList
const FlatListCom = inline ? RNFlatList : List
return (
<View testID={testID} style={style}>
{items.length > 0 && (
+4 -4
View File
@@ -1,4 +1,4 @@
import React, {MutableRefObject} from 'react'
import React from 'react'
import {
Dimensions,
RefreshControl,
@@ -8,7 +8,7 @@ import {
ViewStyle,
} from 'react-native'
import {useQueryClient} from '@tanstack/react-query'
import {FlatList} from '../util/Views'
import {List, ListRef} from '../util/List'
import {ListCard} from './ListCard'
import {ErrorMessage} from '../util/error/ErrorMessage'
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
@@ -36,7 +36,7 @@ interface SectionRef {
interface ProfileListsProps {
did: string
scrollElRef: MutableRefObject<FlatList<any> | null>
scrollElRef: ListRef
onScroll?: OnScrollHandler
scrollEventThrottle?: number
headerOffset: number
@@ -190,7 +190,7 @@ export const ProfileLists = React.forwardRef<SectionRef, ProfileListsProps>(
const scrollHandler = useAnimatedScrollHandler(onScroll || {})
return (
<View testID={testID} style={style}>
<FlatList
<List
testID={testID ? `${testID}-flatlist` : undefined}
ref={scrollElRef}
data={items}
+5 -4
View File
@@ -1,5 +1,5 @@
import React, {MutableRefObject} from 'react'
import {CenteredView, FlatList} from '../util/Views'
import React from 'react'
import {CenteredView} from '../util/Views'
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native'
import {FeedItem} from './FeedItem'
import {NotificationFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
@@ -15,6 +15,7 @@ import {useUnreadNotificationsApi} from '#/state/queries/notifications/unread'
import {logger} from '#/logger'
import {cleanError} from '#/lib/strings/errors'
import {useModerationOpts} from '#/state/queries/preferences'
import {List, ListRef} from '../util/List'
const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'}
@@ -26,7 +27,7 @@ export function Feed({
onScroll,
ListHeaderComponent,
}: {
scrollElRef?: MutableRefObject<FlatList<any> | null>
scrollElRef?: ListRef
onPressTryAgain?: () => void
onScroll?: OnScrollHandler
ListHeaderComponent?: () => JSX.Element
@@ -146,7 +147,7 @@ export function Feed({
/>
</CenteredView>
)}
<FlatList
<List
testID="notifsFeed"
ref={scrollElRef}
data={items}
+3 -3
View File
@@ -1,7 +1,6 @@
import * as React from 'react'
import {
LayoutChangeEvent,
FlatList,
ScrollView,
StyleSheet,
View,
@@ -22,6 +21,7 @@ import {TabBar} from './TabBar'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {OnScrollHandler} from 'lib/hooks/useOnMainScroll'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
import {ListMethods} from '../util/List'
const SCROLLED_DOWN_LIMIT = 200
@@ -30,7 +30,7 @@ export interface PagerWithHeaderChildParams {
isFocused: boolean
onScroll: OnScrollHandler
isScrolledDown: boolean
scrollElRef: React.MutableRefObject<FlatList<any> | ScrollView | null>
scrollElRef: React.MutableRefObject<ListMethods | ScrollView | null>
}
export interface PagerWithHeaderProps {
@@ -331,7 +331,7 @@ function PagerItem({
isScrolledDown,
onScroll: scrollHandler,
scrollElRef: scrollElRef as React.MutableRefObject<
FlatList<any> | ScrollView | null
ListMethods | ScrollView | null
>,
})
}
+3 -2
View File
@@ -1,7 +1,8 @@
import React, {useCallback, useMemo, useState} from 'react'
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native'
import {AppBskyFeedGetLikes as GetLikes} from '@atproto/api'
import {CenteredView, FlatList} from '../util/Views'
import {CenteredView} from '../util/Views'
import {List} from '../util/List'
import {ErrorMessage} from '../util/error/ErrorMessage'
import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
import {usePalette} from 'lib/hooks/usePalette'
@@ -84,7 +85,7 @@ export function PostLikedBy({uri}: {uri: string}) {
// loaded
// =
return (
<FlatList
<List
data={likes}
keyExtractor={item => item.actor.did}
refreshControl={
+3 -2
View File
@@ -1,7 +1,8 @@
import React, {useMemo, useCallback, useState} from 'react'
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native'
import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
import {CenteredView, FlatList} from '../util/Views'
import {CenteredView} from '../util/Views'
import {List} from '../util/List'
import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
import {ErrorMessage} from '../util/error/ErrorMessage'
import {usePalette} from 'lib/hooks/usePalette'
@@ -85,7 +86,7 @@ export function PostRepostedBy({uri}: {uri: string}) {
// loaded
// =
return (
<FlatList
<List
data={repostedBy}
keyExtractor={item => item.did}
refreshControl={
+4 -3
View File
@@ -8,7 +8,8 @@ import {
View,
} from 'react-native'
import {AppBskyFeedDefs} from '@atproto/api'
import {CenteredView, FlatList} from '../util/Views'
import {CenteredView} from '../util/Views'
import {List, ListMethods} from '../util/List'
import {
FontAwesomeIcon,
FontAwesomeIconStyle,
@@ -140,7 +141,7 @@ function PostThreadLoaded({
const {_} = useLingui()
const pal = usePalette('default')
const {isTablet, isDesktop} = useWebMediaQueries()
const ref = useRef<FlatList>(null)
const ref = useRef<ListMethods>(null)
const highlightedPostRef = useRef<View | null>(null)
const needsScrollAdjustment = useRef<boolean>(
!isNative || // web always uses scroll adjustment
@@ -335,7 +336,7 @@ function PostThreadLoaded({
)
return (
<FlatList
<List
ref={ref}
data={posts}
initialNumToRender={!isNative ? posts.length : undefined}
+4 -4
View File
@@ -1,4 +1,4 @@
import React, {memo, MutableRefObject} from 'react'
import React, {memo} from 'react'
import {
ActivityIndicator,
AppState,
@@ -10,7 +10,7 @@ import {
ViewStyle,
} from 'react-native'
import {useQueryClient} from '@tanstack/react-query'
import {FlatList} from '../util/Views'
import {List, ListRef} from '../util/List'
import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
import {FeedErrorMessage} from './FeedErrorMessage'
import {FeedSlice} from './FeedSlice'
@@ -62,7 +62,7 @@ let Feed = ({
style?: StyleProp<ViewStyle>
enabled?: boolean
pollInterval?: number
scrollElRef?: MutableRefObject<FlatList<any> | null>
scrollElRef?: ListRef
onHasNew?: (v: boolean) => void
onScroll?: OnScrollHandler
scrollEventThrottle?: number
@@ -273,7 +273,7 @@ let Feed = ({
const scrollHandler = useAnimatedScrollHandler(onScroll || {})
return (
<View testID={testID} style={style}>
<FlatList
<List
testID={testID ? `${testID}-flatlist` : undefined}
ref={scrollElRef}
data={feedItems}
+3 -2
View File
@@ -1,7 +1,8 @@
import React from 'react'
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native'
import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
import {CenteredView, FlatList} from '../util/Views'
import {CenteredView} from '../util/Views'
import {List} from '../util/List'
import {ErrorMessage} from '../util/error/ErrorMessage'
import {ProfileCardWithFollowBtn} from './ProfileCard'
import {usePalette} from 'lib/hooks/usePalette'
@@ -86,7 +87,7 @@ export function ProfileFollowers({name}: {name: string}) {
// loaded
// =
return (
<FlatList
<List
data={followers}
keyExtractor={item => item.did}
refreshControl={
+3 -2
View File
@@ -1,7 +1,8 @@
import React from 'react'
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native'
import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
import {CenteredView, FlatList} from '../util/Views'
import {CenteredView} from '../util/Views'
import {List} from '../util/List'
import {ErrorMessage} from '../util/error/ErrorMessage'
import {ProfileCardWithFollowBtn} from './ProfileCard'
import {usePalette} from 'lib/hooks/usePalette'
@@ -86,7 +87,7 @@ export function ProfileFollows({name}: {name: string}) {
// loaded
// =
return (
<FlatList
<List
data={follows}
keyExtractor={item => item.did}
refreshControl={
+15
View File
@@ -0,0 +1,15 @@
import React from 'react'
import {FlatListProps} from 'react-native'
import {FlatList_INTERNAL} from './Views'
export type ListMethods = FlatList_INTERNAL
export type ListProps<ItemT> = FlatListProps<ItemT>
export type ListRef = React.MutableRefObject<FlatList_INTERNAL | null>
function ListImpl<ItemT>(props: ListProps<ItemT>, ref: React.Ref<ListMethods>) {
return <FlatList_INTERNAL {...props} ref={ref} />
}
export const List = React.forwardRef(ListImpl) as <ItemT>(
props: ListProps<ItemT> & {ref?: React.Ref<ListMethods>},
) => React.ReactElement
+2 -2
View File
@@ -6,7 +6,7 @@ import {
View,
ScrollView,
} from 'react-native'
import {FlatList} from './Views'
import {FlatList_INTERNAL} from './Views'
import {OnScrollCb} from 'lib/hooks/useOnMainScroll'
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
import {Text} from './text/Text'
@@ -110,7 +110,7 @@ export const ViewSelector = React.forwardRef<
[items],
)
return (
<FlatList
<FlatList_INTERNAL
ref={flatListRef}
data={data}
keyExtractor={keyExtractor}
+1 -1
View File
@@ -1,6 +1,6 @@
import React from 'react'
import {ViewProps} from 'react-native'
export {FlatList, ScrollView} from 'react-native'
export {FlatList as FlatList_INTERNAL, ScrollView} from 'react-native'
export function CenteredView({
style,
sideBorders,
+1 -1
View File
@@ -2,7 +2,7 @@ import React from 'react'
import {View} from 'react-native'
import Animated from 'react-native-reanimated'
export const FlatList = Animated.FlatList
export const FlatList_INTERNAL = Animated.FlatList
export const ScrollView = Animated.ScrollView
export function CenteredView(props) {
return <View {...props} />
+1 -1
View File
@@ -49,7 +49,7 @@ export function CenteredView({
return <View style={style} {...props} />
}
export const FlatList = React.forwardRef(function FlatListImpl<ItemT>(
export const FlatList_INTERNAL = React.forwardRef(function FlatListImpl<ItemT>(
{
contentContainerStyle,
style,