about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorHailey <me@haileyok.com>2024-05-10 07:49:08 -0700
committerGitHub <noreply@github.com>2024-05-10 07:49:08 -0700
commit1a90426026aa4fc851f61044d27fa0c1febdb715 (patch)
tree622704788c5e01ee849240a1934de798cb056611 /src
parent195c9f10456a988a7b09369e41c8a8cf6c94431f (diff)
downloadvoidsky-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.tsx26
-rw-r--r--src/screens/Messages/Conversation/index.tsx83
-rw-r--r--src/state/messages/convo/agent.ts2
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: {