diff options
author | Hailey <me@haileyok.com> | 2024-05-10 07:49:08 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-10 07:49:08 -0700 |
commit | 1a90426026aa4fc851f61044d27fa0c1febdb715 (patch) | |
tree | 622704788c5e01ee849240a1934de798cb056611 /src | |
parent | 195c9f10456a988a7b09369e41c8a8cf6c94431f (diff) | |
download | voidsky-1a90426026aa4fc851f61044d27fa0c1febdb715.tar.zst |
[🐴] Remove extra spinner states from chat screen (#3947)
* remove extra loading states from chat * nits * fix scrolling animation to bottom * nit * move spinner to top
Diffstat (limited to 'src')
-rw-r--r-- | src/screens/Messages/Conversation/MessagesList.tsx | 26 | ||||
-rw-r--r-- | src/screens/Messages/Conversation/index.tsx | 83 | ||||
-rw-r--r-- | src/state/messages/convo/agent.ts | 2 |
3 files changed, 79 insertions, 32 deletions
diff --git a/src/screens/Messages/Conversation/MessagesList.tsx b/src/screens/Messages/Conversation/MessagesList.tsx index f99a41b7f..a92f3d50a 100644 --- a/src/screens/Messages/Conversation/MessagesList.tsx +++ b/src/screens/Messages/Conversation/MessagesList.tsx @@ -10,7 +10,7 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context' import {AppBskyRichtextFacet, RichText} from '@atproto/api' import {shortenLinks} from '#/lib/strings/rich-text-manip' -import {isIOS} from '#/platform/detection' +import {isIOS, isNative} from '#/platform/detection' import {useConvo} from '#/state/messages/convo' import {ConvoItem, ConvoStatus} from '#/state/messages/convo/types' import {useAgent} from '#/state/session' @@ -85,7 +85,7 @@ export function MessagesList() { // Instead, we use `onMomentumScrollEnd` and this value to determine if we need to start scrolling or not. const isMomentumScrolling = useSharedValue(false) - const [hasInitiallyScrolled, setHasInitiallyScrolled] = React.useState(false) + const hasInitiallyScrolled = useSharedValue(false) // Every time the content size changes, that means one of two things is happening: // 1. New messages are being added from the log or from a message you have sent @@ -101,7 +101,7 @@ export function MessagesList() { (_: number, height: number) => { // Because web does not have `maintainVisibleContentPosition` support, we will need to manually scroll to the // previous offset whenever we add new content to the previous offset whenever we add new content to the list. - if (isWeb && isAtTop.value && hasInitiallyScrolled) { + if (isWeb && isAtTop.value && hasInitiallyScrolled.value) { flatListRef.current?.scrollToOffset({ animated: false, offset: height - contentHeight.value, @@ -116,7 +116,7 @@ export function MessagesList() { } flatListRef.current?.scrollToOffset({ - animated: hasInitiallyScrolled, + animated: hasInitiallyScrolled.value, offset: height, }) isMomentumScrolling.value = true @@ -133,7 +133,7 @@ export function MessagesList() { // The check for `hasInitiallyScrolled` prevents an initial fetch on mount. FlatList triggers `onStartReached` // immediately on mount, since we are in fact at an offset of zero, so we have to ignore those initial calls. const onStartReached = useCallback(() => { - if (convo.status === ConvoStatus.Ready && hasInitiallyScrolled) { + if (convo.status === ConvoStatus.Ready && hasInitiallyScrolled.value) { convo.fetchMessageHistory() } }, [convo, hasInitiallyScrolled]) @@ -178,8 +178,8 @@ export function MessagesList() { // This number _must_ be the height of the MaybeLoader component. // We don't check for zero, because the `MaybeLoader` component is always present, even when not visible, which // adds a 50 pixel offset. - if (contentHeight.value > 50 && !hasInitiallyScrolled) { - runOnJS(setHasInitiallyScrolled)(true) + if (contentHeight.value > 50 && !hasInitiallyScrolled.value) { + hasInitiallyScrolled.value = true } }, [contentHeight.value, hasInitiallyScrolled, isAtBottom, isAtTop], @@ -228,17 +228,20 @@ export function MessagesList() { data={convo.items} renderItem={renderItem} keyExtractor={keyExtractor} + containWeb={true} + contentContainerStyle={{ + paddingHorizontal: 10, + }} disableVirtualization={true} - initialNumToRender={isWeb ? 50 : 25} - maxToRenderPerBatch={isWeb ? 50 : 25} + initialNumToRender={isNative ? 30 : 60} + maxToRenderPerBatch={isWeb ? 30 : 60} keyboardDismissMode="on-drag" keyboardShouldPersistTaps="handled" maintainVisibleContentPosition={{ minIndexForVisible: 1, }} - containWeb={true} - contentContainerStyle={{paddingHorizontal: 10}} removeClippedSubviews={false} + sideBorders={false} onContentSizeChange={onContentSizeChange} onStartReached={onStartReached} onScrollToIndexFailed={onScrollToIndexFailed} @@ -246,7 +249,6 @@ export function MessagesList() { ListHeaderComponent={ <MaybeLoader isLoading={convo.isFetchingHistory} /> } - sideBorders={false} /> </ScrollProvider> <MessageInput onSendMessage={onSendMessage} scrollToEnd={scrollToEnd} /> diff --git a/src/screens/Messages/Conversation/index.tsx b/src/screens/Messages/Conversation/index.tsx index af9064cc3..4c8cfe7ed 100644 --- a/src/screens/Messages/Conversation/index.tsx +++ b/src/screens/Messages/Conversation/index.tsx @@ -22,6 +22,7 @@ import {atoms as a, useBreakpoints, useTheme} from '#/alf' import {ConvoMenu} from '#/components/dms/ConvoMenu' import {Error} from '#/components/Error' import {ListMaybePlaceholder} from '#/components/Lists' +import {Loader} from '#/components/Loader' import {Text} from '#/components/Typography' import {ClipClopGate} from '../gate' @@ -53,20 +54,27 @@ export function MessagesConversationScreen({route}: Props) { } function Inner() { + const t = useTheme() const convo = useConvo() const {_} = useLingui() - if ( - convo.status === ConvoStatus.Uninitialized || - convo.status === ConvoStatus.Initializing - ) { - return ( - <CenteredView style={a.flex_1} sideBorders> - <Header /> - <ListMaybePlaceholder isLoading /> - </CenteredView> - ) - } + const [hasInitiallyRendered, setHasInitiallyRendered] = React.useState(false) + + // HACK: Because we need to scroll to the bottom of the list once initial items are added to the list, we also have + // to take into account that scrolling to the end of the list on native will happen asynchronously. This will cause + // a little flicker when the items are first renedered at the top and immediately scrolled to the bottom. to prevent + // this, we will wait until the first render has completed to remove the loading overlay. + React.useEffect(() => { + if ( + !hasInitiallyRendered && + convo.status === ConvoStatus.Ready && + !convo.isFetchingHistory + ) { + setTimeout(() => { + setHasInitiallyRendered(true) + }, 15) + } + }, [convo.isFetchingHistory, convo.items, convo.status, hasInitiallyRendered]) if (convo.status === ConvoStatus.Error) { return ( @@ -88,8 +96,30 @@ function Inner() { return ( <KeyboardProvider> <CenteredView style={a.flex_1} sideBorders> - <Header profile={convo.recipients[0]} /> - <MessagesList /> + <Header profile={convo.recipients?.[0]} /> + <View style={[a.flex_1]}> + {convo.status !== ConvoStatus.Ready ? ( + <ListMaybePlaceholder isLoading /> + ) : ( + <MessagesList /> + )} + {!hasInitiallyRendered && ( + <View + style={[ + a.absolute, + a.z_10, + a.w_full, + a.h_full, + a.justify_center, + a.align_center, + t.atoms.bg, + ]}> + <View style={[{marginBottom: 75}]}> + <Loader size="xl" /> + </View> + </View> + )} + </View> </CenteredView> </KeyboardProvider> ) @@ -128,7 +158,8 @@ let Header = ({ a.justify_between, a.align_start, a.gap_lg, - a.px_lg, + a.pl_xl, + a.pr_lg, a.py_sm, ]}> {!gtTablet ? ( @@ -154,12 +185,19 @@ let Header = ({ )} <View style={[a.align_center, a.gap_sm, a.flex_1]}> {profile ? ( - <> + <View style={[a.align_center]}> <PreviewableUserAvatar size={32} profile={profile} /> - <Text style={[a.text_lg, a.font_bold, a.text_center]}> + <Text + style={[a.text_lg, a.font_bold, isWeb ? a.mt_md : a.mt_sm]} + numberOfLines={1}> {profile.displayName} </Text> - </> + <Text + style={[t.atoms.text_contrast_medium, {fontSize: 15}]} + numberOfLines={1}> + @{profile.handle} + </Text> + </View> ) : ( <> <View @@ -171,10 +209,17 @@ let Header = ({ /> <View style={[ - {width: 120, height: 18}, + {width: 120, height: 16}, + a.rounded_xs, + t.atoms.bg_contrast_25, + a.mt_xs, + ]} + /> + <View + style={[ + {width: 175, height: 12}, a.rounded_xs, t.atoms.bg_contrast_25, - a.mb_2xs, ]} /> </> diff --git a/src/state/messages/convo/agent.ts b/src/state/messages/convo/agent.ts index 12e24577e..6801def75 100644 --- a/src/state/messages/convo/agent.ts +++ b/src/state/messages/convo/agent.ts @@ -554,7 +554,7 @@ export class Convo { { cursor: nextCursor, convoId: this.convoId, - limit: isNative ? 40 : 60, + limit: isNative ? 30 : 60, }, { headers: { |