diff --git a/components/ChatMessageBubble.tsx b/components/ChatMessageBubble.tsx index 373844d..239af57 100644 --- a/components/ChatMessageBubble.tsx +++ b/components/ChatMessageBubble.tsx @@ -1,4 +1,5 @@ import { useMedplumProfile } from "@medplum/react-hooks"; +import { Image } from "expo-image"; import { FileDown, UserRound } from "lucide-react-native"; import { useCallback, useState } from "react"; import { View } from "react-native"; @@ -7,7 +8,6 @@ import { Alert } from "react-native"; import { Avatar, AvatarImage } from "@/components/ui/avatar"; import { Button, ButtonIcon, ButtonSpinner, ButtonText } from "@/components/ui/button"; import { Icon } from "@/components/ui/icon"; -import { Image } from "@/components/ui/image"; import { Text } from "@/components/ui/text"; import type { ChatMessage } from "@/models/chat"; import type { AttachmentWithUrl } from "@/types/attachment"; @@ -73,10 +73,11 @@ export function ChatMessageBubble({ message, avatarURL }: ChatMessageBubbleProps {hasImage ? ( {`Attachment ) : ( diff --git a/components/ChatMessageList.tsx b/components/ChatMessageList.tsx index 50622f4..e07dfea 100644 --- a/components/ChatMessageList.tsx +++ b/components/ChatMessageList.tsx @@ -1,5 +1,5 @@ import { useRef } from "react"; -import { ScrollView } from "react-native-gesture-handler"; +import { FlatList, ListRenderItem } from "react-native"; import { useAvatars } from "@/hooks/useAvatars"; import type { ChatMessage } from "@/models/chat"; @@ -13,26 +13,34 @@ interface ChatMessageListProps { } export function ChatMessageList({ messages, loading }: ChatMessageListProps) { - const scrollViewRef = useRef(null); + const flatListRef = useRef(null); const { getAvatarURL } = useAvatars(messages.map((message) => message.avatarRef)); + const renderItem: ListRenderItem = ({ item: message }) => ( + + ); + return ( - message.id} className="flex-1 bg-background-50" onContentSizeChange={() => { - // Scroll to bottom when content size changes (e.g. new message)-] - scrollViewRef.current?.scrollToEnd({ animated: true }); + // Scroll to bottom when content size changes (e.g. new message) + flatListRef.current?.scrollToEnd({ animated: true }); }} - > - {messages.map((message) => ( - - ))} - {loading && } - + ListFooterComponent={loading ? : null} + showsVerticalScrollIndicator={true} + initialNumToRender={15} + maxToRenderPerBatch={10} + windowSize={5} + removeClippedSubviews + /> ); } diff --git a/components/ThreadList.tsx b/components/ThreadList.tsx index 2f9b965..509ef4c 100644 --- a/components/ThreadList.tsx +++ b/components/ThreadList.tsx @@ -137,7 +137,7 @@ export function ThreadList({ threads, getAvatarURL, onCreateThread }: ThreadList isPractitioner={isPractitioner} /> )} - showsVerticalScrollIndicator={false} + showsVerticalScrollIndicator={true} initialNumToRender={10} maxToRenderPerBatch={10} windowSize={5} diff --git a/package-lock.json b/package-lock.json index 0dc7815..b896537 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,6 +56,7 @@ "expo-file-system": "~18.0.7", "expo-font": "~13.0.2", "expo-haptics": "~14.0.0", + "expo-image": "~2.0.4", "expo-image-picker": "~16.0.4", "expo-linking": "~7.0.3", "expo-router": "~4.0.15", @@ -10197,6 +10198,23 @@ "expo": "*" } }, + "node_modules/expo-image": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/expo-image/-/expo-image-2.0.4.tgz", + "integrity": "sha512-oIVSlV/BpBJbI9Anf8RjraGJXDWSJxNKxdXkYBJ31XrQaUstOM7OmsVKjOK40ZFZHIz3rx5SBJWK5w52Uz+/bg==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*", + "react-native-web": "*" + }, + "peerDependenciesMeta": { + "react-native-web": { + "optional": true + } + } + }, "node_modules/expo-image-loader": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-5.0.0.tgz", diff --git a/package.json b/package.json index 023ff95..0759705 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,8 @@ "react-native-webview": "13.12.5", "scheduler": "^0.25.0", "tailwindcss": "^3.4.17", - "use-context-selector": "^2.0.0" + "use-context-selector": "^2.0.0", + "expo-image": "~2.0.4" }, "devDependencies": { "@babel/core": "^7.26.0",