about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorHailey <me@haileyok.com>2024-05-01 11:48:19 -0700
committerGitHub <noreply@github.com>2024-05-01 11:48:19 -0700
commit6f9993ca55f0c01509c1a159b225d73f75ed8778 (patch)
treea332c2d3305aceef30f76ceabc92b0ceea56fb6e /src
parent8304ad91ac3862becca5b3f4f7fd90b8b39d1dea (diff)
downloadvoidsky-6f9993ca55f0c01509c1a159b225d73f75ed8778.tar.zst
[Clipclops] Fix list, rework structure (#3799)
* proper min index

* move keyextractor out of react

* move onSendMessage out

* don't render the flatlist conditionally

* add loader

* rework structure

* remove some unneeded logic
Diffstat (limited to 'src')
-rw-r--r--src/screens/Messages/Conversation/MessagesList.tsx100
-rw-r--r--src/screens/Messages/Conversation/index.tsx43
2 files changed, 80 insertions, 63 deletions
diff --git a/src/screens/Messages/Conversation/MessagesList.tsx b/src/screens/Messages/Conversation/MessagesList.tsx
index ca32a6d68..ec7147e3c 100644
--- a/src/screens/Messages/Conversation/MessagesList.tsx
+++ b/src/screens/Messages/Conversation/MessagesList.tsx
@@ -3,7 +3,6 @@ import {FlatList, View, ViewToken} from 'react-native'
 import {KeyboardAvoidingView} from 'react-native-keyboard-controller'
 
 import {useChat} from '#/state/messages'
-import {ChatProvider} from '#/state/messages'
 import {ConvoItem, ConvoStatus} from '#/state/messages/convo'
 import {isWeb} from 'platform/detection'
 import {MessageInput} from '#/screens/Messages/Conversation/MessageInput'
@@ -37,31 +36,20 @@ function renderItem({item}: {item: ConvoItem}) {
   return null
 }
 
-function onScrollToEndFailed() {
-  // Placeholder function. You have to give FlatList something or else it will error.
+function keyExtractor(item: ConvoItem) {
+  return item.key
 }
 
-export function MessagesList({convoId}: {convoId: string}) {
-  return (
-    <ChatProvider convoId={convoId}>
-      <MessagesListInner />
-    </ChatProvider>
-  )
+function onScrollToEndFailed() {
+  // Placeholder function. You have to give FlatList something or else it will error.
 }
 
-export function MessagesListInner() {
+export function MessagesList() {
   const chat = useChat()
   const flatListRef = useRef<FlatList>(null)
   // We use this to know if we should scroll after a new clop is added to the list
   const isAtBottom = useRef(false)
 
-  // Because the viewableItemsChanged callback won't have access to the updated state, we use a ref to store the
-  // total number of clops
-  // TODO this needs to be set to whatever the initial number of messages is
-  // const totalMessages = useRef(10)
-
-  // TODO later
-
   const [onViewableItemsChanged, viewabilityConfig] = useMemo(() => {
     return [
       (info: {viewableItems: Array<ViewToken>; changed: Array<ViewToken>}) => {
@@ -94,49 +82,59 @@ export function MessagesListInner() {
 
   const onInputBlur = useCallback(() => {}, [])
 
+  const onSendMessage = useCallback(
+    (text: string) => {
+      chat.service.sendMessage({
+        text,
+      })
+    },
+    [chat.service],
+  )
+
   return (
     <KeyboardAvoidingView
       style={{flex: 1, marginBottom: isWeb ? 20 : 85}}
       behavior="padding"
       keyboardVerticalOffset={70}
       contentContainerStyle={{flex: 1}}>
-      {chat.state.status === ConvoStatus.Ready && (
-        <FlatList
-          data={chat.state.items}
-          keyExtractor={item => item.key}
-          renderItem={renderItem}
-          contentContainerStyle={{paddingHorizontal: 10}}
-          // In the future, we might want to adjust this value. Not very concerning right now as long as we are only
-          // dealing with text. But whenever we have images or other media and things are taller, we will want to lower
-          // this...probably.
-          initialNumToRender={20}
-          // Same with the max to render per batch. Let's be safe for now though.
-          maxToRenderPerBatch={25}
-          inverted={true}
-          onEndReached={onEndReached}
-          onScrollToIndexFailed={onScrollToEndFailed}
-          onContentSizeChange={onContentSizeChange}
-          onViewableItemsChanged={onViewableItemsChanged}
-          viewabilityConfig={viewabilityConfig}
-          maintainVisibleContentPosition={{
-            minIndexForVisible: 0,
-          }}
-          ListFooterComponent={
-            <MaybeLoader isLoading={chat.state.isFetchingHistory} />
-          }
-          removeClippedSubviews={true}
-          ref={flatListRef}
-          keyboardDismissMode="none"
-        />
-      )}
+      <FlatList
+        data={
+          chat.state.status === ConvoStatus.Ready ? chat.state.items : undefined
+        }
+        keyExtractor={keyExtractor}
+        renderItem={renderItem}
+        contentContainerStyle={{paddingHorizontal: 10}}
+        // In the future, we might want to adjust this value. Not very concerning right now as long as we are only
+        // dealing with text. But whenever we have images or other media and things are taller, we will want to lower
+        // this...probably.
+        initialNumToRender={20}
+        // Same with the max to render per batch. Let's be safe for now though.
+        maxToRenderPerBatch={25}
+        inverted={true}
+        onEndReached={onEndReached}
+        onScrollToIndexFailed={onScrollToEndFailed}
+        onContentSizeChange={onContentSizeChange}
+        onViewableItemsChanged={onViewableItemsChanged}
+        viewabilityConfig={viewabilityConfig}
+        maintainVisibleContentPosition={{
+          minIndexForVisible: 1,
+        }}
+        ListFooterComponent={
+          <MaybeLoader
+            isLoading={
+              chat.state.status === ConvoStatus.Ready &&
+              chat.state.isFetchingHistory
+            }
+          />
+        }
+        removeClippedSubviews={true}
+        ref={flatListRef}
+        keyboardDismissMode="none"
+      />
 
       <View style={{paddingHorizontal: 10}}>
         <MessageInput
-          onSendMessage={text => {
-            chat.service.sendMessage({
-              text,
-            })
-          }}
+          onSendMessage={onSendMessage}
           onFocus={onInputFocus}
           onBlur={onInputBlur}
         />
diff --git a/src/screens/Messages/Conversation/index.tsx b/src/screens/Messages/Conversation/index.tsx
index 9c5fd7912..79c49f051 100644
--- a/src/screens/Messages/Conversation/index.tsx
+++ b/src/screens/Messages/Conversation/index.tsx
@@ -9,9 +9,10 @@ import {NativeStackScreenProps} from '@react-navigation/native-stack'
 
 import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types'
 import {useGate} from '#/lib/statsig/statsig'
-import {useConvoQuery} from '#/state/queries/messages/conversation'
 import {BACK_HITSLOP} from 'lib/constants'
 import {isWeb} from 'platform/detection'
+import {ChatProvider, useChat} from 'state/messages'
+import {ConvoStatus} from 'state/messages/convo'
 import {useSession} from 'state/session'
 import {UserAvatar} from 'view/com/util/UserAvatar'
 import {CenteredView} from 'view/com/util/Views'
@@ -30,33 +31,49 @@ type Props = NativeStackScreenProps<
 export function MessagesConversationScreen({route}: Props) {
   const gate = useGate()
   const convoId = route.params.conversation
+
+  if (!gate('dms')) return <ClipClopGate />
+
+  return (
+    <ChatProvider convoId={convoId}>
+      <Inner />
+    </ChatProvider>
+  )
+}
+
+function Inner() {
+  const chat = useChat()
   const {currentAccount} = useSession()
   const myDid = currentAccount?.did
 
-  const {data: chat, isError: isError} = useConvoQuery(convoId)
   const otherProfile = React.useMemo(() => {
-    return chat?.members?.find(m => m.did !== myDid)
-  }, [chat?.members, myDid])
+    if (chat.state.status !== ConvoStatus.Ready) return
+    return chat.state.convo.members.find(m => m.did !== myDid)
+  }, [chat.state, myDid])
 
-  if (!gate('dms')) return <ClipClopGate />
-
-  if (!chat || !otherProfile) {
+  // TODO whenever we have error messages, we should use them in here -hailey
+  if (chat.state.status !== ConvoStatus.Ready || !otherProfile) {
     return (
-      <CenteredView style={{flex: 1}} sideBorders>
-        <ListMaybePlaceholder isLoading={true} isError={isError} />
-      </CenteredView>
+      <ListMaybePlaceholder
+        isLoading={true}
+        isError={chat.state.status === ConvoStatus.Error}
+      />
     )
   }
 
   return (
     <CenteredView style={{flex: 1}} sideBorders>
       <Header profile={otherProfile} />
-      <MessagesList convoId={convoId} />
+      <MessagesList />
     </CenteredView>
   )
 }
 
-function Header({profile}: {profile: AppBskyActorDefs.ProfileViewBasic}) {
+let Header = ({
+  profile,
+}: {
+  profile: AppBskyActorDefs.ProfileViewBasic
+}): React.ReactNode => {
   const t = useTheme()
   const {_} = useLingui()
   const {gtTablet} = useBreakpoints()
@@ -126,3 +143,5 @@ function Header({profile}: {profile: AppBskyActorDefs.ProfileViewBasic}) {
     </View>
   )
 }
+
+Header = React.memo(Header)