Skip to content

Instantly share code, notes, and snippets.

@pachun
Created May 7, 2024 16:16
Show Gist options
  • Save pachun/a41623f4321008a7aa295b9f364b7d93 to your computer and use it in GitHub Desktop.
Save pachun/a41623f4321008a7aa295b9f364b7d93 to your computer and use it in GitHub Desktop.
import React from "react"
import {
AsyncStorage,
FlatList,
KeyboardAvoidingView,
TextInput,
TouchableOpacity,
Vibration,
View,
} from "react-native"
import * as Notifications from "expo-notifications"
import { MaterialIcons } from "@expo/vector-icons"
import Layout from "../../components/Layout"
import Header from "../../components/Header"
import Message from "../../components/Message"
import BottomSafeArea from "../../components/BottomSafeArea"
import { colors } from "../../globalStyles"
import styles from "./styles"
import api from "../../api"
const messageNotificationBelongsToThisConversation = (
messageNotification: MessageNotification,
conversation: PatientTeamMember,
) => messageNotification.patient_team_member.id === conversation.id
const newestMessagesFirst = (messages: Message[]): Message[] =>
messages.sort((m1, m2) => (m1.created_at < m2.created_at ? 1 : -1))
interface Props {
route: Route
navigation: TeamsNavigationProp
}
const Messages = ({ route, navigation }: Props) => {
const goBack = () => navigation.goBack()
const patientTeamMember = route.params.patientTeamMember
const [myTeamMemberId, setMyTeamMemberId] = React.useState<number>()
React.useEffect(() => {
const getMyTeamMemberId = async () =>
setMyTeamMemberId(
parseInt(await AsyncStorage.getItem("myTeamMemberId"), 10),
)
getMyTeamMemberId()
}, [])
const recipient =
myTeamMemberId === patientTeamMember.team_member.id
? patientTeamMember.primary_team_member
: patientTeamMember.team_member
const recipientName = React.useMemo(
() => `${recipient.first_name} ${recipient.last_name}`,
[recipient],
)
const [messageToSend, setMessageToSend] = React.useState<string>("")
const [messages, setMessages] = React.useState<Message[]>([])
const addMessage = (message: Message) =>
setMessages(newestMessagesFirst([...messages, message]))
const handleNewMessageNotification = (
notification: Notifications.Notification,
) => {
const messageNotification = notification.request.content.data
.body as MessageNotification
if (messageNotificationBelongsToThisConversation) {
Vibration.vibrate(500)
addMessage(messageNotification.message)
}
}
const listenForMessages = () => {
const listener = Notifications.addNotificationReceivedListener(
handleNewMessageNotification,
)
return () => listener.remove()
}
React.useEffect(listenForMessages, [messages])
React.useEffect(() => {
const unsubscribe = navigation.addListener("focus", async () => {
const messagesFromApi = (
await api.patientTeamMembers.messages(patientTeamMember).index()
).json
return setMessages(newestMessagesFirst(messagesFromApi))
})
return unsubscribe
}, [navigation])
const sendMessage = async () => {
const message = (
await api.patientTeamMembers
.messages(patientTeamMember)
.create(messageToSend)
).json
setMessageToSend("")
addMessage(message)
}
const showSharedTeamMember = () => {
navigation.navigate("ShowSharedTeamMember", {
patientTeamMember: patientTeamMember,
})
}
const isPrimaryTeamMember =
myTeamMemberId === patientTeamMember.primary_team_member.id
const editTeamMemberButton = {
rightItem: {
item: <MaterialIcons name="more-vert" size={35} />,
action: showSharedTeamMember,
},
}
const sentMessage = (message: Message) => message.sender_id === myTeamMemberId
return (
<Layout>
<Header
title={`${recipientName}`}
leftItem={{ item: "Stack Back Button", action: goBack }}
{...(isPrimaryTeamMember ? editTeamMemberButton : {})}
/>
<KeyboardAvoidingView
behavior="height"
style={styles.keyboardAvoidingContainer}
>
<FlatList
inverted
data={messages}
renderItem={item => (
<Message sent={sentMessage(item.item)} message={item.item} />
)}
keyExtractor={message => message.id.toString()}
style={styles.messageList}
/>
<View style={styles.messageFieldContainer}>
<TextInput
multiline
style={styles.messageField}
value={messageToSend}
onChangeText={setMessageToSend}
/>
<TouchableOpacity
style={styles.sendIconContainer}
onPress={sendMessage}
>
<MaterialIcons name="send" size={30} color={colors.primary} />
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
<BottomSafeArea />
</Layout>
)
}
export default Messages
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment