All files / apps/chatbot/src/components/MessageList index.tsx

100% Statements 7/7
100% Branches 2/2
100% Functions 4/4
100% Lines 6/6

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63                                          1x               6x   6x                           6x             12x             6x      
import React, { RefObject } from "react";
 
import { FlashList, FlashListRef } from "@shopify/flash-list";
 
import { makeStyles } from "@repo/ui/themes/makeStyles";
 
import { ThinkingIndicator } from "@/components/Indicators/ThinkingIndicator";
 
import { ChatMessage } from "@/types/chat";
 
import { MessageItem } from "./MessageItem";
 
interface MessageListProps {
  listRef: RefObject<FlashListRef<ChatMessage> | null>;
  messages: ChatMessage[];
  processingActionIds: string[];
  isThinking: boolean;
  onReset: () => void;
  handleAction: (msgId: string, actionId: string, type: "confirm" | "cancel") => void;
}
 
export const MessageList = ({
  listRef,
  messages,
  processingActionIds,
  isThinking,
  onReset,
  handleAction,
}: MessageListProps) => {
  const styles = useStyles();
 
  return (
    <FlashList
      ref={listRef}
      data={messages}
      // Without this the list inherits "never", and with the keyboard up the
      // first tap anywhere in it is spent dismissing the keyboard instead of
      // reaching the button under the finger — See More, and Confirm/Cancel on
      // a pending action, both needed pressing twice.
      keyboardShouldPersistTaps="handled"
      maintainVisibleContentPosition={{
        autoscrollToTopThreshold: 10,
        startRenderingFromBottom: false,
      }}
      renderItem={({ item }) => (
        <MessageItem
          message={item}
          processingActionIds={processingActionIds}
          onReset={onReset}
          handleAction={handleAction}
        />
      )}
      keyExtractor={(item) => String(item._id)}
      contentContainerStyle={styles.messagesContainer}
      ListFooterComponent={isThinking ? <ThinkingIndicator /> : null}
    />
  );
};
 
const useStyles = makeStyles(() => ({
  messagesContainer: { paddingTop: 16, paddingBottom: 8 },
}));