about summary refs log tree commit diff
path: root/src/screens/Messages/components/MessagesList.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/screens/Messages/components/MessagesList.tsx')
-rw-r--r--src/screens/Messages/components/MessagesList.tsx134
1 files changed, 85 insertions, 49 deletions
diff --git a/src/screens/Messages/components/MessagesList.tsx b/src/screens/Messages/components/MessagesList.tsx
index e84a18a6b..b400bc578 100644
--- a/src/screens/Messages/components/MessagesList.tsx
+++ b/src/screens/Messages/components/MessagesList.tsx
@@ -1,4 +1,4 @@
-import React, {useCallback, useRef} from 'react'
+import {useCallback, useEffect, useRef, useState} from 'react'
 import {LayoutChangeEvent, View} from 'react-native'
 import {useKeyboardHandler} from 'react-native-keyboard-controller'
 import Animated, {
@@ -25,8 +25,12 @@ import {
 import {logger} from '#/logger'
 import {isNative} from '#/platform/detection'
 import {isWeb} from '#/platform/detection'
-import {isConvoActive, useConvoActive} from '#/state/messages/convo'
-import {ConvoItem, ConvoStatus} from '#/state/messages/convo/types'
+import {
+  ActiveConvoStates,
+  isConvoActive,
+  useConvoActive,
+} from '#/state/messages/convo'
+import {ConvoItem, ConvoState, ConvoStatus} from '#/state/messages/convo/types'
 import {useGetPost} from '#/state/queries/post'
 import {useAgent} from '#/state/session'
 import {useShellLayout} from '#/state/shell/shell-layout'
@@ -100,16 +104,15 @@ export function MessagesList({
 
   const flatListRef = useAnimatedRef<ListMethods>()
 
-  const [newMessagesPill, setNewMessagesPill] = React.useState({
+  const [newMessagesPill, setNewMessagesPill] = useState({
     show: false,
     startContentOffset: 0,
   })
 
-  const [emojiPickerState, setEmojiPickerState] =
-    React.useState<EmojiPickerState>({
-      isOpen: false,
-      pos: {top: 0, left: 0, right: 0, bottom: 0, nextFocusRef: null},
-    })
+  const [emojiPickerState, setEmojiPickerState] = useState<EmojiPickerState>({
+    isOpen: false,
+    pos: {top: 0, left: 0, right: 0, bottom: 0, nextFocusRef: null},
+  })
 
   // We need to keep track of when the scroll offset is at the bottom of the list to know when to scroll as new items
   // are added to the list. For example, if the user is scrolled up to 1iew older messages, we don't want to scroll to
@@ -126,8 +129,8 @@ export function MessagesList({
 
   // -- Keep track of background state and positioning for new pill
   const layoutHeight = useSharedValue(0)
-  const didBackground = React.useRef(false)
-  React.useEffect(() => {
+  const didBackground = useRef(false)
+  useEffect(() => {
     if (convoState.status === ConvoStatus.Backgrounded) {
       didBackground.current = true
     }
@@ -218,7 +221,7 @@ export function MessagesList({
     }
   }, [convoState, hasScrolled, layoutHeight])
 
-  const onScroll = React.useCallback(
+  const onScroll = useCallback(
     (e: ReanimatedScrollEvent) => {
       'worklet'
       layoutHeight.set(e.layoutMeasurement.height)
@@ -376,7 +379,7 @@ export function MessagesList({
   )
 
   // -- List layout changes (opening emoji keyboard, etc.)
-  const onListLayout = React.useCallback(
+  const onListLayout = useCallback(
     (e: LayoutChangeEvent) => {
       layoutHeight.set(e.nativeEvent.layout.height)
 
@@ -395,13 +398,17 @@ export function MessagesList({
     ],
   )
 
-  const scrollToEndOnPress = React.useCallback(() => {
+  const scrollToEndOnPress = useCallback(() => {
     flatListRef.current?.scrollToOffset({
       offset: prevContentHeight.current,
       animated: true,
     })
   }, [flatListRef])
 
+  const onOpenEmojiPicker = useCallback((pos: any) => {
+    setEmojiPickerState({isOpen: true, pos})
+  }, [])
+
   return (
     <>
       {/* Custom scroll provider so that we can use the `onScroll` event in our custom List implementation */}
@@ -440,41 +447,17 @@ export function MessagesList({
         ) : blocked ? (
           footer
         ) : (
-          isConvoActive(convoState) &&
-          !convoState.isFetchingHistory && (
-            <>
-              {convoState.items.length === 0 ? (
-                <>
-                  <ChatEmptyPill />
-                  <MessageInput
-                    onSendMessage={onSendMessage}
-                    hasEmbed={!!embedUri}
-                    setEmbed={setEmbed}
-                    openEmojiPicker={pos =>
-                      setEmojiPickerState({isOpen: true, pos})
-                    }>
-                    <MessageInputEmbed
-                      embedUri={embedUri}
-                      setEmbed={setEmbed}
-                    />
-                  </MessageInput>
-                </>
-              ) : convoState.convo.status === 'request' &&
-                !hasAcceptOverride ? (
-                <ChatStatusInfo convoState={convoState} />
-              ) : (
-                <MessageInput
-                  onSendMessage={onSendMessage}
-                  hasEmbed={!!embedUri}
-                  setEmbed={setEmbed}
-                  openEmojiPicker={pos =>
-                    setEmojiPickerState({isOpen: true, pos})
-                  }>
-                  <MessageInputEmbed embedUri={embedUri} setEmbed={setEmbed} />
-                </MessageInput>
-              )}
-            </>
-          )
+          <ConversationFooter
+            convoState={convoState}
+            hasAcceptOverride={hasAcceptOverride}>
+            <MessageInput
+              onSendMessage={onSendMessage}
+              hasEmbed={!!embedUri}
+              setEmbed={setEmbed}
+              openEmojiPicker={onOpenEmojiPicker}>
+              <MessageInputEmbed embedUri={embedUri} setEmbed={setEmbed} />
+            </MessageInput>
+          </ConversationFooter>
         )}
       </Animated.View>
 
@@ -490,3 +473,56 @@ export function MessagesList({
     </>
   )
 }
+
+type FooterState = 'loading' | 'new-chat' | 'request' | 'standard'
+
+function getFooterState(
+  convoState: ActiveConvoStates,
+  hasAcceptOverride?: boolean,
+): FooterState {
+  if (convoState.items.length === 0) {
+    if (convoState.isFetchingHistory) {
+      return 'loading'
+    } else {
+      return 'new-chat'
+    }
+  }
+
+  if (convoState.convo.status === 'request' && !hasAcceptOverride) {
+    return 'request'
+  }
+
+  return 'standard'
+}
+
+function ConversationFooter({
+  convoState,
+  hasAcceptOverride,
+  children,
+}: {
+  convoState: ConvoState
+  hasAcceptOverride?: boolean
+  children?: React.ReactNode // message input
+}) {
+  if (!isConvoActive(convoState)) {
+    return null
+  }
+
+  const footerState = getFooterState(convoState, hasAcceptOverride)
+
+  switch (footerState) {
+    case 'loading':
+      return null
+    case 'new-chat':
+      return (
+        <>
+          <ChatEmptyPill />
+          {children}
+        </>
+      )
+    case 'request':
+      return <ChatStatusInfo convoState={convoState} />
+    case 'standard':
+      return children
+  }
+}