React Native New Arch (#10980)
This commit is contained in:
@@ -39,9 +39,9 @@ export const SplashScreen = ({
|
||||
logoFill,
|
||||
logoShadow: isDarkMode
|
||||
? [
|
||||
t.atoms.shadow_md,
|
||||
{
|
||||
shadowColor: logoFill,
|
||||
shadowRadius: 8,
|
||||
shadowOpacity: 0.5,
|
||||
shadowOffset: {
|
||||
width: 0,
|
||||
@@ -93,13 +93,15 @@ export const SplashScreen = ({
|
||||
size="large"
|
||||
color={isDarkMode ? 'secondary_inverted' : 'secondary'}
|
||||
style={[
|
||||
t.atoms.shadow_md,
|
||||
{
|
||||
shadowColor: t.palette.black,
|
||||
shadowRadius: 8,
|
||||
shadowOpacity: 0.1,
|
||||
shadowOffset: {
|
||||
width: 0,
|
||||
height: 5,
|
||||
},
|
||||
elevation: 16,
|
||||
},
|
||||
]}>
|
||||
<ButtonText>
|
||||
|
||||
@@ -25,6 +25,7 @@ import {KeyboardAvoidingView} from 'react-native-keyboard-controller'
|
||||
import ProgressCircle from 'react-native-progress/Circle'
|
||||
import Animated, {
|
||||
type AnimatedRef,
|
||||
type AnimatedStyle,
|
||||
Easing,
|
||||
FadeIn,
|
||||
FadeOut,
|
||||
@@ -1794,7 +1795,7 @@ function ComposerTopBar({
|
||||
isEditingDraft: boolean
|
||||
canSaveDraft: boolean
|
||||
textLength: number
|
||||
topBarAnimatedStyle: StyleProp<ViewStyle>
|
||||
topBarAnimatedStyle: AnimatedStyle<ViewStyle>
|
||||
children?: React.ReactNode
|
||||
}) {
|
||||
const t = useTheme()
|
||||
@@ -2029,7 +2030,7 @@ function ComposerPills({
|
||||
thread: ThreadDraft
|
||||
post: PostDraft
|
||||
dispatch: (action: ComposerAction) => void
|
||||
bottomBarAnimatedStyle: StyleProp<ViewStyle>
|
||||
bottomBarAnimatedStyle: AnimatedStyle<ViewStyle>
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const media = post.embed.media
|
||||
|
||||
@@ -227,7 +227,6 @@ export function TextInput({
|
||||
allowFontScaling
|
||||
multiline
|
||||
scrollEnabled={false}
|
||||
numberOfLines={2}
|
||||
// Note: should be the default value, but as of v1.104
|
||||
// it switched to "none" on Android
|
||||
autoCapitalize="sentences"
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
import {memo, useCallback, useEffect, useMemo, useRef, useState} from 'react'
|
||||
import {
|
||||
memo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import {
|
||||
ActivityIndicator,
|
||||
AppState,
|
||||
@@ -195,6 +203,10 @@ export function getItemsForFeedback(feedRow: FeedRow): {
|
||||
}
|
||||
}
|
||||
|
||||
export type PostFeedRef = {
|
||||
refreshFeed: () => Promise<void>
|
||||
}
|
||||
|
||||
// DISABLED need to check if this is causing random feed refreshes -prf
|
||||
// const REFRESH_AFTER = STALE.HOURS.ONE
|
||||
const CHECK_LATEST_AFTER = STALE.SECONDS.THIRTY
|
||||
@@ -222,6 +234,7 @@ let PostFeed = ({
|
||||
savedFeedConfig,
|
||||
initialNumToRender: initialNumToRenderOverride,
|
||||
isVideoFeed = false,
|
||||
ref,
|
||||
}: {
|
||||
feed: FeedDescriptor
|
||||
description?: RichTextType
|
||||
@@ -246,6 +259,7 @@ let PostFeed = ({
|
||||
initialNumToRender?: number
|
||||
isVideoFeed?: boolean
|
||||
lastFetchDate?: () => number
|
||||
ref?: React.Ref<PostFeedRef>
|
||||
}): React.ReactNode => {
|
||||
const ax = useAnalytics()
|
||||
const t = useTheme()
|
||||
@@ -725,8 +739,9 @@ let PostFeed = ({
|
||||
|
||||
// events
|
||||
// =
|
||||
//
|
||||
|
||||
const onRefresh = useCallback(async () => {
|
||||
const refreshFeed = async () => {
|
||||
if (!enabled) return
|
||||
|
||||
ax.metric('feed:refresh', {
|
||||
@@ -734,24 +749,23 @@ let PostFeed = ({
|
||||
feedUrl: feed,
|
||||
reason: 'pull-to-refresh',
|
||||
})
|
||||
setIsPTRing(true)
|
||||
try {
|
||||
await truncateAndInvalidate(queryClient, RQKEY(feed, feedParams))
|
||||
onHasNew?.(false)
|
||||
} catch (err) {
|
||||
logger.error('Failed to refresh posts feed', {message: err})
|
||||
}
|
||||
}
|
||||
|
||||
const onRefresh = async () => {
|
||||
setIsPTRing(true)
|
||||
await refreshFeed()
|
||||
setIsPTRing(false)
|
||||
}, [
|
||||
ax,
|
||||
queryClient,
|
||||
setIsPTRing,
|
||||
onHasNew,
|
||||
feed,
|
||||
feedParams,
|
||||
feedType,
|
||||
enabled,
|
||||
])
|
||||
}
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
refreshFeed,
|
||||
}))
|
||||
|
||||
const onEndReached = useCallback(async () => {
|
||||
if (isFetching || !hasNextPage || isError) return
|
||||
|
||||
@@ -3,6 +3,7 @@ import {type NativeScrollEvent} from 'react-native'
|
||||
import {
|
||||
clamp,
|
||||
interpolate,
|
||||
Reanimated3DefaultSpringConfig,
|
||||
type SharedValue,
|
||||
useAnimatedStyle,
|
||||
useSharedValue,
|
||||
@@ -105,6 +106,7 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) {
|
||||
'worklet'
|
||||
headerMode.set(() =>
|
||||
withSpring(v ? 1 : 0, {
|
||||
...Reanimated3DefaultSpringConfig,
|
||||
overshootClamping: true,
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import {useCallback, useEffect, useLayoutEffect, useMemo, useRef} from 'react'
|
||||
import {ActivityIndicator, StyleSheet} from 'react-native'
|
||||
import {withSpring} from 'react-native-reanimated'
|
||||
import {
|
||||
Reanimated3DefaultSpringConfig,
|
||||
withSpring,
|
||||
} from 'react-native-reanimated'
|
||||
import {useFocusEffect} from '@react-navigation/native'
|
||||
|
||||
import {PROD_DEFAULT_FEED} from '#/lib/constants'
|
||||
@@ -147,7 +150,12 @@ function HomeScreenReady({
|
||||
const headerMode = useHomeHeaderMode()
|
||||
const showHeader = useCallback(() => {
|
||||
'worklet'
|
||||
headerMode.set(() => withSpring(0, {overshootClamping: true}))
|
||||
headerMode.set(() =>
|
||||
withSpring(0, {
|
||||
...Reanimated3DefaultSpringConfig,
|
||||
overshootClamping: true,
|
||||
}),
|
||||
)
|
||||
}, [headerMode])
|
||||
|
||||
useFocusEffect(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {useCallback, useEffect, useMemo, useRef, useState} from 'react'
|
||||
import {StyleSheet} from 'react-native'
|
||||
import {SafeAreaView} from 'react-native-safe-area-context'
|
||||
import {ScrollForwarderView} from 'react-native-scroll-forwarder/src'
|
||||
import {
|
||||
type AppBskyActorDefs,
|
||||
moderateProfile,
|
||||
@@ -36,6 +37,7 @@ import {useAgent, useSession} from '#/state/session'
|
||||
import {ProfileFeedgens} from '#/view/com/feeds/ProfileFeedgens'
|
||||
import {ProfileLists} from '#/view/com/lists/ProfileLists'
|
||||
import {PagerWithHeader} from '#/view/com/pager/PagerWithHeader'
|
||||
import {type PostFeedRef} from '#/view/com/posts/PostFeed'
|
||||
import {ErrorScreen} from '#/view/com/util/error/ErrorScreen'
|
||||
import {FAB} from '#/view/com/util/fab/FAB'
|
||||
import {type ListRef} from '#/view/com/util/List'
|
||||
@@ -53,7 +55,6 @@ import * as Layout from '#/components/Layout'
|
||||
import {ScreenHider} from '#/components/moderation/ScreenHider'
|
||||
import {ProfileStarterPacks} from '#/components/StarterPack/ProfileStarterPacks'
|
||||
import {navigate} from '#/Navigation'
|
||||
import {ExpoScrollForwarderView} from '../../../modules/expo-scroll-forwarder'
|
||||
|
||||
interface SectionRef {
|
||||
scrollToTop: () => void
|
||||
@@ -187,6 +188,7 @@ function ProfileScreenLoaded({
|
||||
enabled: !!profile.associated?.labeler,
|
||||
})
|
||||
const [currentPage, setCurrentPage] = useState(0)
|
||||
const [isRefreshing, setIsRefreshing] = useState(false)
|
||||
const {_} = useLingui()
|
||||
|
||||
const [scrollViewTag, setScrollViewTag] = useState<number | null>(null)
|
||||
@@ -353,6 +355,14 @@ function ProfileScreenLoaded({
|
||||
],
|
||||
})
|
||||
|
||||
const postFeedRef = useRef<PostFeedRef>(null)
|
||||
|
||||
const onRefresh = async () => {
|
||||
setIsRefreshing(true)
|
||||
await postFeedRef.current?.refreshFeed()
|
||||
setIsRefreshing(false)
|
||||
}
|
||||
|
||||
// rendering
|
||||
// =
|
||||
|
||||
@@ -362,7 +372,10 @@ function ProfileScreenLoaded({
|
||||
setMinimumHeight: (height: number) => void
|
||||
}) => {
|
||||
return (
|
||||
<ExpoScrollForwarderView scrollViewTag={scrollViewTag}>
|
||||
<ScrollForwarderView
|
||||
scrollViewTag={scrollViewTag}
|
||||
refreshing={isRefreshing}
|
||||
onRefresh={onRefresh}>
|
||||
<ProfileHeader
|
||||
profile={profile}
|
||||
labeler={labelerInfo}
|
||||
@@ -372,7 +385,7 @@ function ProfileScreenLoaded({
|
||||
isPlaceholderProfile={showPlaceholder}
|
||||
setMinimumHeight={setMinimumHeight}
|
||||
/>
|
||||
</ExpoScrollForwarderView>
|
||||
</ScrollForwarderView>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -440,6 +453,7 @@ function ProfileScreenLoaded({
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
postFeedRef={postFeedRef}
|
||||
/>
|
||||
)
|
||||
: null}
|
||||
|
||||
@@ -2,6 +2,11 @@ import {useContext} from 'react'
|
||||
import {DrawerGestureContext} from 'react-native-drawer-layout'
|
||||
import {Gesture, GestureDetector} from 'react-native-gesture-handler'
|
||||
|
||||
/**
|
||||
* BlockDrawerGesture must wrap the ScrollView directly - Gesture.Native()
|
||||
* only works when attached to the natively scrollable view. On the new
|
||||
* arch (Android), attaching it to a wrapper view breaks scrolling.
|
||||
*/
|
||||
export function BlockDrawerGesture({children}: {children: React.ReactNode}) {
|
||||
const drawerGesture = useContext(DrawerGestureContext) ?? Gesture.Native() // noop for web
|
||||
let scrollGesture = Gesture.Native()
|
||||
|
||||
Reference in New Issue
Block a user