Consolidate List props a bit (#2216)

zio/stable
dan 2023-12-21 22:56:45 +00:00 committed by GitHub
parent 987c543727
commit bc31da47fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 123 additions and 177 deletions

View File

@ -1,12 +1,5 @@
import React from 'react' import React from 'react'
import { import {Dimensions, StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
Dimensions,
RefreshControl,
StyleProp,
StyleSheet,
View,
ViewStyle,
} from 'react-native'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {List, ListRef} from '../util/List' import {List, ListRef} from '../util/List'
import {FeedSourceCardLoaded} from './FeedSourceCard' import {FeedSourceCardLoaded} from './FeedSourceCard'
@ -180,22 +173,14 @@ export const ProfileFeedgens = React.forwardRef<
data={items} data={items}
keyExtractor={(item: any) => item._reactKey || item.uri} keyExtractor={(item: any) => item._reactKey || item.uri}
renderItem={renderItemInner} renderItem={renderItemInner}
refreshControl={ refreshing={isPTRing}
<RefreshControl onRefresh={onRefresh}
refreshing={isPTRing} headerOffset={headerOffset}
onRefresh={onRefresh}
tintColor={pal.colors.text}
titleColor={pal.colors.text}
progressViewOffset={headerOffset}
/>
}
contentContainerStyle={{ contentContainerStyle={{
minHeight: Dimensions.get('window').height * 1.5, minHeight: Dimensions.get('window').height * 1.5,
}} }}
style={{paddingTop: headerOffset}}
indicatorStyle={theme.colorScheme === 'dark' ? 'white' : 'black'} indicatorStyle={theme.colorScheme === 'dark' ? 'white' : 'black'}
removeClippedSubviews={true} removeClippedSubviews={true}
contentOffset={{x: 0, y: headerOffset * -1}}
// @ts-ignore our .web version only -prf // @ts-ignore our .web version only -prf
desktopFixedHeight desktopFixedHeight
onEndReached={onEndReached} onEndReached={onEndReached}

View File

@ -2,7 +2,6 @@ import React from 'react'
import { import {
ActivityIndicator, ActivityIndicator,
Dimensions, Dimensions,
RefreshControl,
StyleProp, StyleProp,
View, View,
ViewStyle, ViewStyle,
@ -15,7 +14,6 @@ import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
import {ProfileCard} from '../profile/ProfileCard' import {ProfileCard} from '../profile/ProfileCard'
import {Button} from '../util/forms/Button' import {Button} from '../util/forms/Button'
import {useAnalytics} from 'lib/analytics/analytics' import {useAnalytics} from 'lib/analytics/analytics'
import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {useListMembersQuery} from '#/state/queries/list-members' import {useListMembersQuery} from '#/state/queries/list-members'
import {logger} from '#/logger' import {logger} from '#/logger'
@ -51,7 +49,6 @@ export function ListMembers({
headerOffset?: number headerOffset?: number
desktopFixedHeightOffset?: number desktopFixedHeightOffset?: number
}) { }) {
const pal = usePalette('default')
const {track} = useAnalytics() const {track} = useAnalytics()
const [isRefreshing, setIsRefreshing] = React.useState(false) const [isRefreshing, setIsRefreshing] = React.useState(false)
const {isMobile} = useWebMediaQueries() const {isMobile} = useWebMediaQueries()
@ -215,24 +212,16 @@ export function ListMembers({
renderItem={renderItem} renderItem={renderItem}
ListHeaderComponent={renderHeader} ListHeaderComponent={renderHeader}
ListFooterComponent={Footer} ListFooterComponent={Footer}
refreshControl={ refreshing={isRefreshing}
<RefreshControl onRefresh={onRefresh}
refreshing={isRefreshing} headerOffset={headerOffset}
onRefresh={onRefresh}
tintColor={pal.colors.text}
titleColor={pal.colors.text}
progressViewOffset={headerOffset}
/>
}
contentContainerStyle={{ contentContainerStyle={{
minHeight: Dimensions.get('window').height * 1.5, minHeight: Dimensions.get('window').height * 1.5,
}} }}
style={{paddingTop: headerOffset}}
onScrolledDownChange={onScrolledDownChange} onScrolledDownChange={onScrolledDownChange}
onEndReached={onEndReached} onEndReached={onEndReached}
onEndReachedThreshold={0.6} onEndReachedThreshold={0.6}
removeClippedSubviews={true} removeClippedSubviews={true}
contentOffset={{x: 0, y: headerOffset * -1}}
// @ts-ignore our .web version only -prf // @ts-ignore our .web version only -prf
desktopFixedHeight={desktopFixedHeightOffset || true} desktopFixedHeight={desktopFixedHeightOffset || true}
/> />

View File

@ -119,31 +119,51 @@ export function MyLists({
[error, onRefresh, renderItem, pal], [error, onRefresh, renderItem, pal],
) )
const FlatListCom = inline ? RNFlatList : List if (inline) {
return ( return (
<View testID={testID} style={style}> <View testID={testID} style={style}>
{items.length > 0 && ( {items.length > 0 && (
<FlatListCom <RNFlatList
testID={testID ? `${testID}-flatlist` : undefined} testID={testID ? `${testID}-flatlist` : undefined}
data={items} data={items}
keyExtractor={item => (item.uri ? item.uri : item._reactKey)} keyExtractor={item => (item.uri ? item.uri : item._reactKey)}
renderItem={renderItemInner} renderItem={renderItemInner}
refreshControl={ refreshControl={
<RefreshControl <RefreshControl
refreshing={isPTRing} refreshing={isPTRing}
onRefresh={onRefresh} onRefresh={onRefresh}
tintColor={pal.colors.text} tintColor={pal.colors.text}
titleColor={pal.colors.text} titleColor={pal.colors.text}
/> />
} }
contentContainerStyle={[s.contentContainer]} contentContainerStyle={[s.contentContainer]}
removeClippedSubviews={true} removeClippedSubviews={true}
// @ts-ignore our .web version only -prf // @ts-ignore our .web version only -prf
desktopFixedHeight desktopFixedHeight
/> />
)} )}
</View> </View>
) )
} else {
return (
<View testID={testID} style={style}>
{items.length > 0 && (
<List
testID={testID ? `${testID}-flatlist` : undefined}
data={items}
keyExtractor={item => (item.uri ? item.uri : item._reactKey)}
renderItem={renderItemInner}
refreshing={isPTRing}
onRefresh={onRefresh}
contentContainerStyle={[s.contentContainer]}
removeClippedSubviews={true}
// @ts-ignore our .web version only -prf
desktopFixedHeight
/>
)}
</View>
)
}
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({

View File

@ -1,12 +1,5 @@
import React from 'react' import React from 'react'
import { import {Dimensions, StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
Dimensions,
RefreshControl,
StyleProp,
StyleSheet,
View,
ViewStyle,
} from 'react-native'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {List, ListRef} from '../util/List' import {List, ListRef} from '../util/List'
import {ListCard} from './ListCard' import {ListCard} from './ListCard'
@ -182,22 +175,14 @@ export const ProfileLists = React.forwardRef<SectionRef, ProfileListsProps>(
data={items} data={items}
keyExtractor={(item: any) => item._reactKey} keyExtractor={(item: any) => item._reactKey}
renderItem={renderItemInner} renderItem={renderItemInner}
refreshControl={ refreshing={isPTRing}
<RefreshControl onRefresh={onRefresh}
refreshing={isPTRing} headerOffset={headerOffset}
onRefresh={onRefresh}
tintColor={pal.colors.text}
titleColor={pal.colors.text}
progressViewOffset={headerOffset}
/>
}
contentContainerStyle={{ contentContainerStyle={{
minHeight: Dimensions.get('window').height * 1.5, minHeight: Dimensions.get('window').height * 1.5,
}} }}
style={{paddingTop: headerOffset}}
indicatorStyle={theme.colorScheme === 'dark' ? 'white' : 'black'} indicatorStyle={theme.colorScheme === 'dark' ? 'white' : 'black'}
removeClippedSubviews={true} removeClippedSubviews={true}
contentOffset={{x: 0, y: headerOffset * -1}}
// @ts-ignore our .web version only -prf // @ts-ignore our .web version only -prf
desktopFixedHeight desktopFixedHeight
onEndReached={onEndReached} onEndReached={onEndReached}

View File

@ -1,13 +1,12 @@
import React from 'react' import React from 'react'
import {CenteredView} from '../util/Views' import {CenteredView} from '../util/Views'
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native' import {ActivityIndicator, StyleSheet, View} from 'react-native'
import {FeedItem} from './FeedItem' import {FeedItem} from './FeedItem'
import {NotificationFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' import {NotificationFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
import {ErrorMessage} from '../util/error/ErrorMessage' import {ErrorMessage} from '../util/error/ErrorMessage'
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn' import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
import {EmptyState} from '../util/EmptyState' import {EmptyState} from '../util/EmptyState'
import {s} from 'lib/styles' import {s} from 'lib/styles'
import {usePalette} from 'lib/hooks/usePalette'
import {useNotificationFeedQuery} from '#/state/queries/notifications/feed' import {useNotificationFeedQuery} from '#/state/queries/notifications/feed'
import {useUnreadNotificationsApi} from '#/state/queries/notifications/unread' import {useUnreadNotificationsApi} from '#/state/queries/notifications/unread'
import {logger} from '#/logger' import {logger} from '#/logger'
@ -30,7 +29,6 @@ export function Feed({
onScrolledDownChange: (isScrolledDown: boolean) => void onScrolledDownChange: (isScrolledDown: boolean) => void
ListHeaderComponent?: () => JSX.Element ListHeaderComponent?: () => JSX.Element
}) { }) {
const pal = usePalette('default')
const [isPTRing, setIsPTRing] = React.useState(false) const [isPTRing, setIsPTRing] = React.useState(false)
const moderationOpts = useModerationOpts() const moderationOpts = useModerationOpts()
@ -152,14 +150,8 @@ export function Feed({
renderItem={renderItem} renderItem={renderItem}
ListHeaderComponent={ListHeaderComponent} ListHeaderComponent={ListHeaderComponent}
ListFooterComponent={FeedFooter} ListFooterComponent={FeedFooter}
refreshControl={ refreshing={isPTRing}
<RefreshControl onRefresh={onRefresh}
refreshing={isPTRing}
onRefresh={onRefresh}
tintColor={pal.colors.text}
titleColor={pal.colors.text}
/>
}
onEndReached={onEndReached} onEndReached={onEndReached}
onEndReachedThreshold={0.6} onEndReachedThreshold={0.6}
onScrolledDownChange={onScrolledDownChange} onScrolledDownChange={onScrolledDownChange}

View File

@ -1,18 +1,16 @@
import React, {useCallback, useMemo, useState} from 'react' import React, {useCallback, useMemo, useState} from 'react'
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native' import {ActivityIndicator, StyleSheet, View} from 'react-native'
import {AppBskyFeedGetLikes as GetLikes} from '@atproto/api' import {AppBskyFeedGetLikes as GetLikes} from '@atproto/api'
import {CenteredView} from '../util/Views' import {CenteredView} from '../util/Views'
import {List} from '../util/List' import {List} from '../util/List'
import {ErrorMessage} from '../util/error/ErrorMessage' import {ErrorMessage} from '../util/error/ErrorMessage'
import {ProfileCardWithFollowBtn} from '../profile/ProfileCard' import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
import {usePalette} from 'lib/hooks/usePalette'
import {logger} from '#/logger' import {logger} from '#/logger'
import {useResolveUriQuery} from '#/state/queries/resolve-uri' import {useResolveUriQuery} from '#/state/queries/resolve-uri'
import {usePostLikedByQuery} from '#/state/queries/post-liked-by' import {usePostLikedByQuery} from '#/state/queries/post-liked-by'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
export function PostLikedBy({uri}: {uri: string}) { export function PostLikedBy({uri}: {uri: string}) {
const pal = usePalette('default')
const [isPTRing, setIsPTRing] = useState(false) const [isPTRing, setIsPTRing] = useState(false)
const { const {
data: resolvedUri, data: resolvedUri,
@ -88,14 +86,8 @@ export function PostLikedBy({uri}: {uri: string}) {
<List <List
data={likes} data={likes}
keyExtractor={item => item.actor.did} keyExtractor={item => item.actor.did}
refreshControl={ refreshing={isPTRing}
<RefreshControl onRefresh={onRefresh}
refreshing={isPTRing}
onRefresh={onRefresh}
tintColor={pal.colors.text}
titleColor={pal.colors.text}
/>
}
onEndReached={onEndReached} onEndReached={onEndReached}
renderItem={renderItem} renderItem={renderItem}
initialNumToRender={15} initialNumToRender={15}

View File

@ -1,18 +1,16 @@
import React, {useMemo, useCallback, useState} from 'react' import React, {useMemo, useCallback, useState} from 'react'
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native' import {ActivityIndicator, StyleSheet, View} from 'react-native'
import {AppBskyActorDefs as ActorDefs} from '@atproto/api' import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
import {CenteredView} from '../util/Views' import {CenteredView} from '../util/Views'
import {List} from '../util/List' import {List} from '../util/List'
import {ProfileCardWithFollowBtn} from '../profile/ProfileCard' import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
import {ErrorMessage} from '../util/error/ErrorMessage' import {ErrorMessage} from '../util/error/ErrorMessage'
import {usePalette} from 'lib/hooks/usePalette'
import {logger} from '#/logger' import {logger} from '#/logger'
import {useResolveUriQuery} from '#/state/queries/resolve-uri' import {useResolveUriQuery} from '#/state/queries/resolve-uri'
import {usePostRepostedByQuery} from '#/state/queries/post-reposted-by' import {usePostRepostedByQuery} from '#/state/queries/post-reposted-by'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
export function PostRepostedBy({uri}: {uri: string}) { export function PostRepostedBy({uri}: {uri: string}) {
const pal = usePalette('default')
const [isPTRing, setIsPTRing] = useState(false) const [isPTRing, setIsPTRing] = useState(false)
const { const {
data: resolvedUri, data: resolvedUri,
@ -89,14 +87,8 @@ export function PostRepostedBy({uri}: {uri: string}) {
<List <List
data={repostedBy} data={repostedBy}
keyExtractor={item => item.did} keyExtractor={item => item.did}
refreshControl={ refreshing={isPTRing}
<RefreshControl onRefresh={onRefresh}
refreshing={isPTRing}
onRefresh={onRefresh}
tintColor={pal.colors.text}
titleColor={pal.colors.text}
/>
}
onEndReached={onEndReached} onEndReached={onEndReached}
renderItem={renderItem} renderItem={renderItem}
initialNumToRender={15} initialNumToRender={15}

View File

@ -2,7 +2,6 @@ import React, {useEffect, useRef} from 'react'
import { import {
ActivityIndicator, ActivityIndicator,
Pressable, Pressable,
RefreshControl,
StyleSheet, StyleSheet,
TouchableOpacity, TouchableOpacity,
View, View,
@ -349,14 +348,8 @@ function PostThreadLoaded({
} }
keyExtractor={item => item._reactKey} keyExtractor={item => item._reactKey}
renderItem={renderItem} renderItem={renderItem}
refreshControl={ refreshing={isPTRing}
<RefreshControl onRefresh={onPTR}
refreshing={isPTRing}
onRefresh={onPTR}
tintColor={pal.colors.text}
titleColor={pal.colors.text}
/>
}
onContentSizeChange={onContentSizeChange} onContentSizeChange={onContentSizeChange}
style={s.hContentRegion} style={s.hContentRegion}
// @ts-ignore our .web version only -prf // @ts-ignore our .web version only -prf

View File

@ -3,7 +3,6 @@ import {
ActivityIndicator, ActivityIndicator,
AppState, AppState,
Dimensions, Dimensions,
RefreshControl,
StyleProp, StyleProp,
StyleSheet, StyleSheet,
View, View,
@ -16,7 +15,6 @@ import {FeedErrorMessage} from './FeedErrorMessage'
import {FeedSlice} from './FeedSlice' import {FeedSlice} from './FeedSlice'
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn' import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
import {useAnalytics} from 'lib/analytics/analytics' import {useAnalytics} from 'lib/analytics/analytics'
import {usePalette} from 'lib/hooks/usePalette'
import {useTheme} from 'lib/ThemeContext' import {useTheme} from 'lib/ThemeContext'
import {logger} from '#/logger' import {logger} from '#/logger'
import { import {
@ -74,7 +72,6 @@ let Feed = ({
ListHeaderComponent?: () => JSX.Element ListHeaderComponent?: () => JSX.Element
extraData?: any extraData?: any
}): React.ReactNode => { }): React.ReactNode => {
const pal = usePalette('default')
const theme = useTheme() const theme = useTheme()
const {track} = useAnalytics() const {track} = useAnalytics()
const queryClient = useQueryClient() const queryClient = useQueryClient()
@ -294,25 +291,17 @@ let Feed = ({
renderItem={renderItem} renderItem={renderItem}
ListFooterComponent={FeedFooter} ListFooterComponent={FeedFooter}
ListHeaderComponent={ListHeaderComponent} ListHeaderComponent={ListHeaderComponent}
refreshControl={ refreshing={isPTRing}
<RefreshControl onRefresh={onRefresh}
refreshing={isPTRing} headerOffset={headerOffset}
onRefresh={onRefresh}
tintColor={pal.colors.text}
titleColor={pal.colors.text}
progressViewOffset={headerOffset}
/>
}
contentContainerStyle={{ contentContainerStyle={{
minHeight: Dimensions.get('window').height * 1.5, minHeight: Dimensions.get('window').height * 1.5,
}} }}
style={{paddingTop: headerOffset}}
onScrolledDownChange={onScrolledDownChange} onScrolledDownChange={onScrolledDownChange}
indicatorStyle={theme.colorScheme === 'dark' ? 'white' : 'black'} indicatorStyle={theme.colorScheme === 'dark' ? 'white' : 'black'}
onEndReached={onEndReached} onEndReached={onEndReached}
onEndReachedThreshold={2} // number of posts left to trigger load more onEndReachedThreshold={2} // number of posts left to trigger load more
removeClippedSubviews={true} removeClippedSubviews={true}
contentOffset={{x: 0, y: headerOffset * -1}}
extraData={extraData} extraData={extraData}
// @ts-ignore our .web version only -prf // @ts-ignore our .web version only -prf
desktopFixedHeight={ desktopFixedHeight={

View File

@ -1,18 +1,16 @@
import React from 'react' import React from 'react'
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native' import {ActivityIndicator, StyleSheet, View} from 'react-native'
import {AppBskyActorDefs as ActorDefs} from '@atproto/api' import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
import {CenteredView} from '../util/Views' import {CenteredView} from '../util/Views'
import {List} from '../util/List' import {List} from '../util/List'
import {ErrorMessage} from '../util/error/ErrorMessage' import {ErrorMessage} from '../util/error/ErrorMessage'
import {ProfileCardWithFollowBtn} from './ProfileCard' import {ProfileCardWithFollowBtn} from './ProfileCard'
import {usePalette} from 'lib/hooks/usePalette'
import {useProfileFollowersQuery} from '#/state/queries/profile-followers' import {useProfileFollowersQuery} from '#/state/queries/profile-followers'
import {useResolveDidQuery} from '#/state/queries/resolve-uri' import {useResolveDidQuery} from '#/state/queries/resolve-uri'
import {logger} from '#/logger' import {logger} from '#/logger'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
export function ProfileFollowers({name}: {name: string}) { export function ProfileFollowers({name}: {name: string}) {
const pal = usePalette('default')
const [isPTRing, setIsPTRing] = React.useState(false) const [isPTRing, setIsPTRing] = React.useState(false)
const { const {
data: resolvedDid, data: resolvedDid,
@ -90,14 +88,8 @@ export function ProfileFollowers({name}: {name: string}) {
<List <List
data={followers} data={followers}
keyExtractor={item => item.did} keyExtractor={item => item.did}
refreshControl={ refreshing={isPTRing}
<RefreshControl onRefresh={onRefresh}
refreshing={isPTRing}
onRefresh={onRefresh}
tintColor={pal.colors.text}
titleColor={pal.colors.text}
/>
}
onEndReached={onEndReached} onEndReached={onEndReached}
renderItem={renderItem} renderItem={renderItem}
initialNumToRender={15} initialNumToRender={15}

View File

@ -1,18 +1,16 @@
import React from 'react' import React from 'react'
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native' import {ActivityIndicator, StyleSheet, View} from 'react-native'
import {AppBskyActorDefs as ActorDefs} from '@atproto/api' import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
import {CenteredView} from '../util/Views' import {CenteredView} from '../util/Views'
import {List} from '../util/List' import {List} from '../util/List'
import {ErrorMessage} from '../util/error/ErrorMessage' import {ErrorMessage} from '../util/error/ErrorMessage'
import {ProfileCardWithFollowBtn} from './ProfileCard' import {ProfileCardWithFollowBtn} from './ProfileCard'
import {usePalette} from 'lib/hooks/usePalette'
import {useProfileFollowsQuery} from '#/state/queries/profile-follows' import {useProfileFollowsQuery} from '#/state/queries/profile-follows'
import {useResolveDidQuery} from '#/state/queries/resolve-uri' import {useResolveDidQuery} from '#/state/queries/resolve-uri'
import {logger} from '#/logger' import {logger} from '#/logger'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
export function ProfileFollows({name}: {name: string}) { export function ProfileFollows({name}: {name: string}) {
const pal = usePalette('default')
const [isPTRing, setIsPTRing] = React.useState(false) const [isPTRing, setIsPTRing] = React.useState(false)
const { const {
data: resolvedDid, data: resolvedDid,
@ -90,14 +88,8 @@ export function ProfileFollows({name}: {name: string}) {
<List <List
data={follows} data={follows}
keyExtractor={item => item.did} keyExtractor={item => item.did}
refreshControl={ refreshing={isPTRing}
<RefreshControl onRefresh={onRefresh}
refreshing={isPTRing}
onRefresh={onRefresh}
tintColor={pal.colors.text}
titleColor={pal.colors.text}
/>
}
onEndReached={onEndReached} onEndReached={onEndReached}
renderItem={renderItem} renderItem={renderItem}
initialNumToRender={15} initialNumToRender={15}

View File

@ -1,27 +1,42 @@
import React, {memo, startTransition} from 'react' import React, {memo, startTransition} from 'react'
import {FlatListProps} from 'react-native' import {FlatListProps, RefreshControl} from 'react-native'
import {FlatList_INTERNAL} from './Views' import {FlatList_INTERNAL} from './Views'
import {addStyle} from 'lib/styles'
import {useScrollHandlers} from '#/lib/ScrollContext' import {useScrollHandlers} from '#/lib/ScrollContext'
import {runOnJS, useSharedValue} from 'react-native-reanimated' import {runOnJS, useSharedValue} from 'react-native-reanimated'
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED' import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
import {usePalette} from '#/lib/hooks/usePalette'
export type ListMethods = FlatList_INTERNAL export type ListMethods = FlatList_INTERNAL
export type ListProps<ItemT> = Omit< export type ListProps<ItemT> = Omit<
FlatListProps<ItemT>, FlatListProps<ItemT>,
'onScroll' // Use ScrollContext instead. | 'onScroll' // Use ScrollContext instead.
| 'refreshControl' // Pass refreshing and/or onRefresh instead.
| 'contentOffset' // Pass headerOffset instead.
> & { > & {
onScrolledDownChange?: (isScrolledDown: boolean) => void onScrolledDownChange?: (isScrolledDown: boolean) => void
headerOffset?: number
refreshing?: boolean
onRefresh?: () => void
} }
export type ListRef = React.MutableRefObject<FlatList_INTERNAL | null> export type ListRef = React.MutableRefObject<FlatList_INTERNAL | null>
const SCROLLED_DOWN_LIMIT = 200 const SCROLLED_DOWN_LIMIT = 200
function ListImpl<ItemT>( function ListImpl<ItemT>(
{onScrolledDownChange, ...props}: ListProps<ItemT>, {
onScrolledDownChange,
refreshing,
onRefresh,
headerOffset,
style,
...props
}: ListProps<ItemT>,
ref: React.Ref<ListMethods>, ref: React.Ref<ListMethods>,
) { ) {
const isScrolledDown = useSharedValue(false) const isScrolledDown = useSharedValue(false)
const contextScrollHandlers = useScrollHandlers() const contextScrollHandlers = useScrollHandlers()
const pal = usePalette('default')
function handleScrolledDownChange(didScrollDown: boolean) { function handleScrolledDownChange(didScrollDown: boolean) {
startTransition(() => { startTransition(() => {
@ -49,12 +64,36 @@ function ListImpl<ItemT>(
}, },
}) })
let refreshControl
if (refreshing !== undefined || onRefresh !== undefined) {
refreshControl = (
<RefreshControl
refreshing={refreshing ?? false}
onRefresh={onRefresh}
tintColor={pal.colors.text}
titleColor={pal.colors.text}
progressViewOffset={headerOffset}
/>
)
}
let contentOffset
if (headerOffset != null) {
style = addStyle(style, {
paddingTop: headerOffset,
})
contentOffset = {x: 0, y: headerOffset * -1}
}
return ( return (
<FlatList_INTERNAL <FlatList_INTERNAL
{...props} {...props}
scrollIndicatorInsets={{right: 1}} scrollIndicatorInsets={{right: 1}}
contentOffset={contentOffset}
refreshControl={refreshControl}
onScroll={scrollHandler} onScroll={scrollHandler}
scrollEventThrottle={1} scrollEventThrottle={1}
style={style}
ref={ref} ref={ref}
/> />
) )

View File

@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import {ActivityIndicator, StyleSheet, View, RefreshControl} from 'react-native' import {ActivityIndicator, StyleSheet, View} from 'react-native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
import {ViewHeader} from 'view/com/util/ViewHeader' import {ViewHeader} from 'view/com/util/ViewHeader'
@ -487,14 +487,8 @@ export function FeedsScreen(_props: Props) {
keyExtractor={item => item.key} keyExtractor={item => item.key}
contentContainerStyle={styles.contentContainer} contentContainerStyle={styles.contentContainer}
renderItem={renderItem} renderItem={renderItem}
refreshControl={ refreshing={isPTR}
<RefreshControl onRefresh={isUserSearching ? undefined : onPullToRefresh}
refreshing={isPTR}
onRefresh={isUserSearching ? undefined : onPullToRefresh}
tintColor={pal.colors.text}
titleColor={pal.colors.text}
/>
}
initialNumToRender={10} initialNumToRender={10}
onEndReached={onEndReached} onEndReached={onEndReached}
// @ts-ignore our .web version only -prf // @ts-ignore our .web version only -prf

View File

@ -3,7 +3,6 @@ import {
View, View,
StyleSheet, StyleSheet,
ActivityIndicator, ActivityIndicator,
RefreshControl,
TextInput, TextInput,
Pressable, Pressable,
Platform, Platform,
@ -185,7 +184,6 @@ type SearchResultSlice =
function SearchScreenPostResults({query}: {query: string}) { function SearchScreenPostResults({query}: {query: string}) {
const {_} = useLingui() const {_} = useLingui()
const pal = usePalette('default')
const [isPTR, setIsPTR] = React.useState(false) const [isPTR, setIsPTR] = React.useState(false)
const { const {
isFetched, isFetched,
@ -254,14 +252,8 @@ function SearchScreenPostResults({query}: {query: string}) {
} }
}} }}
keyExtractor={item => item.key} keyExtractor={item => item.key}
refreshControl={ refreshing={isPTR}
<RefreshControl onRefresh={onPullToRefresh}
refreshing={isPTR}
onRefresh={onPullToRefresh}
tintColor={pal.colors.text}
titleColor={pal.colors.text}
/>
}
onEndReached={onEndReached} onEndReached={onEndReached}
// @ts-ignore web only -prf // @ts-ignore web only -prf
desktopFixedHeight desktopFixedHeight