From 4b71950d9920913a2a2cc9e493b23b87aad7cec1 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 8 Aug 2024 17:05:51 +0100 Subject: [PATCH] Remove unnecessary state update for reply gate (#4897) * Move mobile compose prompt to inner component * Make canReply computed * Use same clamp we use elsewhere --- src/view/com/post-thread/PostThread.tsx | 48 ++++++++++++++++++------- src/view/screens/PostThread.tsx | 42 ++-------------------- 2 files changed, 38 insertions(+), 52 deletions(-) diff --git a/src/view/com/post-thread/PostThread.tsx b/src/view/com/post-thread/PostThread.tsx index b7eaedd3..40145741 100644 --- a/src/view/com/post-thread/PostThread.tsx +++ b/src/view/com/post-thread/PostThread.tsx @@ -1,11 +1,14 @@ -import React, {useEffect, useRef} from 'react' -import {useWindowDimensions, View} from 'react-native' +import React, {useRef} from 'react' +import {StyleSheet, useWindowDimensions, View} from 'react-native' import {runOnJS} from 'react-native-reanimated' +import Animated from 'react-native-reanimated' +import {useSafeAreaInsets} from 'react-native-safe-area-context' import {AppBskyFeedDefs} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {moderatePost_wrapped as moderatePost} from '#/lib/moderatePost_wrapped' +import {clamp} from '#/lib/numbers' import {ScrollProvider} from '#/lib/ScrollContext' import {isAndroid, isNative, isWeb} from '#/platform/detection' import {useModerationOpts} from '#/state/preferences/moderation-opts' @@ -22,6 +25,7 @@ import { import {usePreferencesQuery} from '#/state/queries/preferences' import {useSession} from '#/state/session' import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender' +import {useMinimalShellFabTransform} from 'lib/hooks/useMinimalShellTransform' import {useSetTitle} from 'lib/hooks/useSetTitle' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {sanitizeDisplayName} from 'lib/strings/display-names' @@ -82,11 +86,9 @@ const keyExtractor = (item: RowItem) => { export function PostThread({ uri, - onCanReply, onPressReply, }: { uri: string | undefined - onCanReply: (canReply: boolean) => void onPressReply: () => unknown }) { const {hasSession, currentAccount} = useSession() @@ -210,14 +212,6 @@ export function PostThread({ return null }, [thread, skeleton?.highlightedPost, isThreadError, _, threadError]) - useEffect(() => { - if (error) { - onCanReply(false) - } else if (rootPost) { - onCanReply(!rootPost.viewer?.replyDisabled) - } - }, [rootPost, onCanReply, error]) - // construct content const posts = React.useMemo(() => { if (!skeleton) return [] @@ -313,6 +307,7 @@ export function PostThread({ setMaxReplies(prev => prev + 50) }, [isFetching, maxReplies, posts.length]) + const canReply = !error && rootPost && !rootPost.viewer?.replyDisabled const hasParents = skeleton?.highlightedPost?.type === 'post' && (skeleton.highlightedPost.ctx.isParentLoading || @@ -473,10 +468,30 @@ export function PostThread({ sideBorders={false} /> + {isMobile && canReply && hasSession && ( + + )} ) } +function MobileComposePrompt({onPressReply}: {onPressReply: () => unknown}) { + const safeAreaInsets = useSafeAreaInsets() + const fabMinimalShellTransform = useMinimalShellFabTransform() + return ( + + + + ) +} + function isThreadPost(v: unknown): v is ThreadPost { return !!v && typeof v === 'object' && 'type' in v && v.type === 'post' } @@ -622,3 +637,12 @@ function hasBranchingReplies(node?: ThreadNode) { } return true } + +const styles = StyleSheet.create({ + prompt: { + // @ts-ignore web-only + position: isWeb ? 'fixed' : 'absolute', + left: 0, + right: 0, + }, +}) diff --git a/src/view/screens/PostThread.tsx b/src/view/screens/PostThread.tsx index 89234c46..43dae2f1 100644 --- a/src/view/screens/PostThread.tsx +++ b/src/view/screens/PostThread.tsx @@ -1,39 +1,26 @@ import React from 'react' -import {StyleSheet, View} from 'react-native' -import Animated from 'react-native-reanimated' -import {useSafeAreaInsets} from 'react-native-safe-area-context' +import {View} from 'react-native' import {useFocusEffect} from '@react-navigation/native' import {useQueryClient} from '@tanstack/react-query' -import {clamp} from 'lodash' -import {isWeb} from '#/platform/detection' import { RQKEY as POST_THREAD_RQKEY, ThreadNode, } from '#/state/queries/post-thread' -import {useSession} from '#/state/session' import {useSetMinimalShellMode} from '#/state/shell' import {useComposerControls} from '#/state/shell/composer' -import {useMinimalShellFabTransform} from 'lib/hooks/useMinimalShellTransform' -import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types' import {makeRecordUri} from 'lib/strings/url-helpers' import {s} from 'lib/styles' -import {ComposePrompt} from 'view/com/composer/Prompt' import {PostThread as PostThreadComponent} from '../com/post-thread/PostThread' type Props = NativeStackScreenProps export function PostThreadScreen({route}: Props) { const queryClient = useQueryClient() - const {hasSession} = useSession() - const fabMinimalShellTransform = useMinimalShellFabTransform() const setMinimalShellMode = useSetMinimalShellMode() const {openComposer} = useComposerControls() - const safeAreaInsets = useSafeAreaInsets() const {name, rkey} = route.params - const {isMobile} = useWebMediaQueries() const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey) - const [canReply, setCanReply] = React.useState(false) useFocusEffect( React.useCallback(() => { @@ -67,33 +54,8 @@ export function PostThreadScreen({route}: Props) { return ( - + - {isMobile && canReply && hasSession && ( - - - - )} ) } - -const styles = StyleSheet.create({ - prompt: { - // @ts-ignore web-only - position: isWeb ? 'fixed' : 'absolute', - left: 0, - right: 0, - }, -})