Fix <List> types (#6756)
* fix List and ScrollView types * add comment * rm omitting ref
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import React, {useCallback, useRef} from 'react'
|
import React, {useCallback, useRef} from 'react'
|
||||||
import {FlatList, LayoutChangeEvent, View} from 'react-native'
|
import {LayoutChangeEvent, View} from 'react-native'
|
||||||
import {
|
import {
|
||||||
KeyboardStickyView,
|
KeyboardStickyView,
|
||||||
useKeyboardHandler,
|
useKeyboardHandler,
|
||||||
@@ -33,7 +33,7 @@ import {
|
|||||||
EmojiPicker,
|
EmojiPicker,
|
||||||
EmojiPickerState,
|
EmojiPickerState,
|
||||||
} from '#/view/com/composer/text-input/web/EmojiPicker.web'
|
} from '#/view/com/composer/text-input/web/EmojiPicker.web'
|
||||||
import {List} from '#/view/com/util/List'
|
import {List, ListMethods} from '#/view/com/util/List'
|
||||||
import {ChatDisabled} from '#/screens/Messages/components/ChatDisabled'
|
import {ChatDisabled} from '#/screens/Messages/components/ChatDisabled'
|
||||||
import {MessageInput} from '#/screens/Messages/components/MessageInput'
|
import {MessageInput} from '#/screens/Messages/components/MessageInput'
|
||||||
import {MessageListError} from '#/screens/Messages/components/MessageListError'
|
import {MessageListError} from '#/screens/Messages/components/MessageListError'
|
||||||
@@ -94,7 +94,7 @@ export function MessagesList({
|
|||||||
const getPost = useGetPost()
|
const getPost = useGetPost()
|
||||||
const {embedUri, setEmbed} = useMessageEmbed()
|
const {embedUri, setEmbed} = useMessageEmbed()
|
||||||
|
|
||||||
const flatListRef = useAnimatedRef<FlatList>()
|
const flatListRef = useAnimatedRef<ListMethods>()
|
||||||
|
|
||||||
const [newMessagesPill, setNewMessagesPill] = React.useState({
|
const [newMessagesPill, setNewMessagesPill] = React.useState({
|
||||||
show: false,
|
show: false,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
|
import Animated from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
@@ -35,7 +36,7 @@ export function Layout({children}: React.PropsWithChildren<{}>) {
|
|||||||
const {gtMobile} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
const onboardDispatch = useOnboardingDispatch()
|
const onboardDispatch = useOnboardingDispatch()
|
||||||
const {state, dispatch} = React.useContext(Context)
|
const {state, dispatch} = React.useContext(Context)
|
||||||
const scrollview = React.useRef<ScrollView>(null)
|
const scrollview = React.useRef<Animated.ScrollView>(null)
|
||||||
const prevActiveStep = React.useRef<string>(state.activeStep)
|
const prevActiveStep = React.useRef<string>(state.activeStep)
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import {FlatList, ScrollView, StyleSheet, View} from 'react-native'
|
import {ScrollView, StyleSheet, View} from 'react-native'
|
||||||
import {useAnimatedRef} from 'react-native-reanimated'
|
import {useAnimatedRef} from 'react-native-reanimated'
|
||||||
|
|
||||||
import {usePalette} from '#/lib/hooks/usePalette'
|
import {usePalette} from '#/lib/hooks/usePalette'
|
||||||
@@ -11,7 +11,7 @@ import {TabBar} from './TabBar'
|
|||||||
export interface PagerWithHeaderChildParams {
|
export interface PagerWithHeaderChildParams {
|
||||||
headerHeight: number
|
headerHeight: number
|
||||||
isFocused: boolean
|
isFocused: boolean
|
||||||
scrollElRef: React.MutableRefObject<FlatList<any> | ScrollView | null>
|
scrollElRef: React.MutableRefObject<ListMethods | ScrollView | null>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PagerWithHeaderProps {
|
export interface PagerWithHeaderProps {
|
||||||
|
|||||||
+25
-13
@@ -1,6 +1,10 @@
|
|||||||
import React, {memo} from 'react'
|
import React, {memo} from 'react'
|
||||||
import {FlatListProps, RefreshControl, ViewToken} from 'react-native'
|
import {RefreshControl, ViewToken} from 'react-native'
|
||||||
import {runOnJS, useSharedValue} from 'react-native-reanimated'
|
import {
|
||||||
|
FlatListPropsWithLayout,
|
||||||
|
runOnJS,
|
||||||
|
useSharedValue,
|
||||||
|
} from 'react-native-reanimated'
|
||||||
import {updateActiveVideoViewAsync} from '@haileyok/bluesky-video'
|
import {updateActiveVideoViewAsync} from '@haileyok/bluesky-video'
|
||||||
|
|
||||||
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
||||||
@@ -13,8 +17,8 @@ import {useTheme} from '#/alf'
|
|||||||
import {FlatList_INTERNAL} from './Views'
|
import {FlatList_INTERNAL} from './Views'
|
||||||
|
|
||||||
export type ListMethods = FlatList_INTERNAL
|
export type ListMethods = FlatList_INTERNAL
|
||||||
export type ListProps<ItemT> = Omit<
|
export type ListProps<ItemT = any> = Omit<
|
||||||
FlatListProps<ItemT>,
|
FlatListPropsWithLayout<ItemT>,
|
||||||
| 'onMomentumScrollBegin' // Use ScrollContext instead.
|
| 'onMomentumScrollBegin' // Use ScrollContext instead.
|
||||||
| 'onMomentumScrollEnd' // Use ScrollContext instead.
|
| 'onMomentumScrollEnd' // Use ScrollContext instead.
|
||||||
| 'onScroll' // Use ScrollContext instead.
|
| 'onScroll' // Use ScrollContext instead.
|
||||||
@@ -22,6 +26,7 @@ export type ListProps<ItemT> = Omit<
|
|||||||
| 'onScrollEndDrag' // Use ScrollContext instead.
|
| 'onScrollEndDrag' // Use ScrollContext instead.
|
||||||
| 'refreshControl' // Pass refreshing and/or onRefresh instead.
|
| 'refreshControl' // Pass refreshing and/or onRefresh instead.
|
||||||
| 'contentOffset' // Pass headerOffset instead.
|
| 'contentOffset' // Pass headerOffset instead.
|
||||||
|
| 'progressViewOffset' // Can't be an animated value
|
||||||
> & {
|
> & {
|
||||||
onScrolledDownChange?: (isScrolledDown: boolean) => void
|
onScrolledDownChange?: (isScrolledDown: boolean) => void
|
||||||
headerOffset?: number
|
headerOffset?: number
|
||||||
@@ -32,12 +37,14 @@ export type ListProps<ItemT> = Omit<
|
|||||||
// Web only prop to contain the scroll to the container rather than the window
|
// Web only prop to contain the scroll to the container rather than the window
|
||||||
disableFullWindowScroll?: boolean
|
disableFullWindowScroll?: boolean
|
||||||
sideBorders?: boolean
|
sideBorders?: boolean
|
||||||
|
progressViewOffset?: number
|
||||||
}
|
}
|
||||||
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>(
|
let List = React.forwardRef<ListMethods, ListProps>(
|
||||||
|
(
|
||||||
{
|
{
|
||||||
onScrolledDownChange,
|
onScrolledDownChange,
|
||||||
refreshing,
|
refreshing,
|
||||||
@@ -47,9 +54,9 @@ function ListImpl<ItemT>(
|
|||||||
style,
|
style,
|
||||||
progressViewOffset,
|
progressViewOffset,
|
||||||
...props
|
...props
|
||||||
}: ListProps<ItemT>,
|
},
|
||||||
ref: React.Ref<ListMethods>,
|
ref,
|
||||||
) {
|
): React.ReactElement => {
|
||||||
const isScrolledDown = useSharedValue(false)
|
const isScrolledDown = useSharedValue(false)
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const dedupe = useDedupe(400)
|
const dedupe = useDedupe(400)
|
||||||
@@ -103,7 +110,10 @@ function ListImpl<ItemT>(
|
|||||||
return [undefined, undefined]
|
return [undefined, undefined]
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
(info: {viewableItems: Array<ViewToken>; changed: Array<ViewToken>}) => {
|
(info: {
|
||||||
|
viewableItems: Array<ViewToken>
|
||||||
|
changed: Array<ViewToken>
|
||||||
|
}) => {
|
||||||
for (const item of info.changed) {
|
for (const item of info.changed) {
|
||||||
if (item.isViewable) {
|
if (item.isViewable) {
|
||||||
onItemSeen(item.item)
|
onItemSeen(item.item)
|
||||||
@@ -151,11 +161,13 @@ function ListImpl<ItemT>(
|
|||||||
viewabilityConfig={viewabilityConfig}
|
viewabilityConfig={viewabilityConfig}
|
||||||
showsVerticalScrollIndicator={!isAndroid}
|
showsVerticalScrollIndicator={!isAndroid}
|
||||||
style={style}
|
style={style}
|
||||||
|
// @ts-expect-error FlatList_INTERNAL ref type is wrong -sfn
|
||||||
ref={ref}
|
ref={ref}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
)
|
||||||
|
List.displayName = 'List'
|
||||||
|
|
||||||
export const List = memo(React.forwardRef(ListImpl)) as <ItemT>(
|
List = memo(List)
|
||||||
props: ListProps<ItemT> & {ref?: React.Ref<ListMethods>},
|
export {List}
|
||||||
) => React.ReactElement
|
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ export const ViewSelector = React.forwardRef<
|
|||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
<FlatList_INTERNAL
|
<FlatList_INTERNAL
|
||||||
|
// @ts-expect-error FlatList_INTERNAL ref type is wrong -sfn
|
||||||
ref={flatListRef}
|
ref={flatListRef}
|
||||||
data={data}
|
data={data}
|
||||||
keyExtractor={keyExtractor}
|
keyExtractor={keyExtractor}
|
||||||
|
|||||||
Vendored
-19
@@ -1,19 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import {ViewProps} from 'react-native'
|
|
||||||
export {FlatList as FlatList_INTERNAL, ScrollView} from 'react-native'
|
|
||||||
export function CenteredView({
|
|
||||||
style,
|
|
||||||
sideBorders,
|
|
||||||
...props
|
|
||||||
}: React.PropsWithChildren<
|
|
||||||
ViewProps & {
|
|
||||||
/**
|
|
||||||
* @platform web
|
|
||||||
*/
|
|
||||||
sideBorders?: boolean
|
|
||||||
/**
|
|
||||||
* @platform web
|
|
||||||
*/
|
|
||||||
topBorder?: boolean
|
|
||||||
}
|
|
||||||
>)
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import {View} from 'react-native'
|
|
||||||
import Animated from 'react-native-reanimated'
|
|
||||||
|
|
||||||
// If you explode these into functions, don't forget to forwardRef!
|
|
||||||
export const FlatList_INTERNAL = Animated.FlatList
|
|
||||||
export const CenteredView = View
|
|
||||||
export const ScrollView = Animated.ScrollView
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {forwardRef} from 'react'
|
||||||
|
import {FlatListComponent} from 'react-native'
|
||||||
|
import {View, ViewProps} from 'react-native'
|
||||||
|
import Animated from 'react-native-reanimated'
|
||||||
|
import {FlatListPropsWithLayout} from 'react-native-reanimated'
|
||||||
|
|
||||||
|
// If you explode these into functions, don't forget to forwardRef!
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Avoid using `FlatList_INTERNAL` and use `List` where possible.
|
||||||
|
* The types are a bit wrong on `FlatList_INTERNAL`
|
||||||
|
*/
|
||||||
|
export const FlatList_INTERNAL = Animated.FlatList
|
||||||
|
export type FlatList_INTERNAL<ItemT = any> = Omit<
|
||||||
|
FlatListComponent<ItemT, FlatListPropsWithLayout<ItemT>>,
|
||||||
|
'CellRendererComponent'
|
||||||
|
>
|
||||||
|
export const ScrollView = Animated.ScrollView
|
||||||
|
export type ScrollView = typeof Animated.ScrollView
|
||||||
|
|
||||||
|
export const CenteredView = forwardRef<
|
||||||
|
View,
|
||||||
|
React.PropsWithChildren<
|
||||||
|
ViewProps & {sideBorders?: boolean; topBorder?: boolean}
|
||||||
|
>
|
||||||
|
>(function CenteredView(props, ref) {
|
||||||
|
return <View ref={ref} {...props} />
|
||||||
|
})
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {ActivityIndicator, type FlatList, StyleSheet, View} from 'react-native'
|
import {ActivityIndicator, StyleSheet, View} from 'react-native'
|
||||||
import {AppBskyFeedDefs} from '@atproto/api'
|
import {AppBskyFeedDefs} from '@atproto/api'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
@@ -25,7 +25,7 @@ import {useComposerControls} from '#/state/shell/composer'
|
|||||||
import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
|
import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
|
||||||
import {FAB} from '#/view/com/util/fab/FAB'
|
import {FAB} from '#/view/com/util/fab/FAB'
|
||||||
import {TextLink} from '#/view/com/util/Link'
|
import {TextLink} from '#/view/com/util/Link'
|
||||||
import {List} from '#/view/com/util/List'
|
import {List, ListMethods} from '#/view/com/util/List'
|
||||||
import {FeedFeedLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
|
import {FeedFeedLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
|
||||||
import {Text} from '#/view/com/util/text/Text'
|
import {Text} from '#/view/com/util/text/Text'
|
||||||
import {ViewHeader} from '#/view/com/util/ViewHeader'
|
import {ViewHeader} from '#/view/com/util/ViewHeader'
|
||||||
@@ -130,7 +130,7 @@ export function FeedsScreen(_props: Props) {
|
|||||||
error: searchError,
|
error: searchError,
|
||||||
} = useSearchPopularFeedsMutation()
|
} = useSearchPopularFeedsMutation()
|
||||||
const {hasSession} = useSession()
|
const {hasSession} = useSession()
|
||||||
const listRef = React.useRef<FlatList>(null)
|
const listRef = React.useRef<ListMethods>(null)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A search query is present. We may not have search results yet.
|
* A search query is present. We may not have search results yet.
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {FlatList, View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
|
|
||||||
import {ScrollProvider} from '#/lib/ScrollContext'
|
import {ScrollProvider} from '#/lib/ScrollContext'
|
||||||
import {List} from '#/view/com/util/List'
|
import {List, ListMethods} from '#/view/com/util/List'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import * as Toggle from '#/components/forms/Toggle'
|
import * as Toggle from '#/components/forms/Toggle'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
export function ListContained() {
|
export function ListContained() {
|
||||||
const [animated, setAnimated] = React.useState(false)
|
const [animated, setAnimated] = React.useState(false)
|
||||||
const ref = React.useRef<FlatList>(null)
|
const ref = React.useRef<ListMethods>(null)
|
||||||
|
|
||||||
const data = React.useMemo(() => {
|
const data = React.useMemo(() => {
|
||||||
return Array.from({length: 100}, (_, i) => ({
|
return Array.from({length: 100}, (_, i) => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user