diff --git a/client/package-lock.json b/client/package-lock.json index 4d949fe..4e52c46 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -20,7 +20,9 @@ "expo-location": "~16.1.0", "expo-status-bar": "~1.6.0", "firebase": "^10.7.1", + "moment": "^2.30.1", "nativewind": "^2.0.11", + "prettier": "^3.2.4", "react": "18.2.0", "react-dom": "18.2.0", "react-native": "0.72.6", @@ -14180,6 +14182,14 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -15699,6 +15709,21 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, + "node_modules/prettier": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", diff --git a/client/package.json b/client/package.json index 509c2fc..5955275 100644 --- a/client/package.json +++ b/client/package.json @@ -21,7 +21,9 @@ "expo-location": "~16.1.0", "expo-status-bar": "~1.6.0", "firebase": "^10.7.1", + "moment": "^2.30.1", "nativewind": "^2.0.11", + "prettier": "^3.2.4", "react": "18.2.0", "react-dom": "18.2.0", "react-native": "0.72.6", diff --git a/client/screens/Chat.js b/client/screens/Chat.js index cade573..7e90604 100644 --- a/client/screens/Chat.js +++ b/client/screens/Chat.js @@ -1,98 +1,148 @@ import React, { - useState, - useEffect, - useLayoutEffect, - useCallback - } from 'react'; - import { TouchableOpacity, Text } from 'react-native'; - import { GiftedChat } from 'react-native-gifted-chat'; - import { - collection, - addDoc, - orderBy, - query, - onSnapshot - } from 'firebase/firestore'; - import { signOut } from 'firebase/auth'; - import { auth, database } from '../firebaseConfig'; - import { useNavigation } from '@react-navigation/native'; - import { AntDesign } from '@expo/vector-icons'; + useState, + useEffect, + useLayoutEffect, + useCallback, +} from "react"; +import { TouchableOpacity, Text, View, StyleSheet } from "react-native"; +import { + GiftedChat, + Bubble, + InputToolbar, + Send, +} from "react-native-gifted-chat"; +import { + collection, + addDoc, + orderBy, + query, + onSnapshot, +} from "firebase/firestore"; +import { signOut } from "firebase/auth"; +import { auth, database } from "../firebaseConfig"; +import { useNavigation } from "@react-navigation/native"; +import { AntDesign } from "@expo/vector-icons"; +import moment from "moment"; - - export default function Chat() { - - const [messages, setMessages] = useState([]); - const navigation = useNavigation(); +export default function Chat() { + const [messages, setMessages] = useState([]); + const navigation = useNavigation(); const onSignOut = () => { - signOut(auth).catch(error => console.log('Error logging out: ', error)); - }; + signOut(auth).catch((error) => console.log("Error logging out: ", error)); + }; - useLayoutEffect(() => { - navigation.setOptions({ - headerRight: () => ( - - - - ) - }); - }, [navigation]); + useLayoutEffect(() => { + navigation.setOptions({ + headerRight: () => ( + + + + + + ), + }); + }, [navigation]); - useLayoutEffect(() => { + useLayoutEffect(() => { + const collectionRef = collection(database, "chats"); + const q = query(collectionRef, orderBy("createdAt", "desc")); - const collectionRef = collection(database, 'chats'); - const q = query(collectionRef, orderBy('createdAt', 'desc')); - - const unsubscribe = onSnapshot(q, querySnapshot => { - console.log('querySnapshot unsusbscribe'); - setMessages( - querySnapshot.docs.map(doc => ({ - _id: doc.data()._id, - createdAt: doc.data().createdAt.toDate(), - text: doc.data().text, - user: doc.data().user - })) - ); - }); + const unsubscribe = onSnapshot(q, (querySnapshot) => { + console.log("querySnapshot unsubscribe"); + setMessages( + querySnapshot.docs.map((doc) => ({ + _id: doc.data()._id, + createdAt: doc.data().createdAt.toDate(), + text: doc.data().text, + user: doc.data().user, + })) + ); + }); return unsubscribe; - }, []); + }, []); - const onSend = useCallback((messages = []) => { - setMessages(previousMessages => - GiftedChat.append(previousMessages, messages) - ); + const onSend = useCallback((messages = []) => { + setMessages((previousMessages) => + GiftedChat.append(previousMessages, messages) + ); - const { _id, createdAt, text, user } = messages[0]; - addDoc(collection(database, 'chats'), { - _id, - createdAt, - text, - user - }); - }, []); + const { _id, createdAt, text, user } = messages[0]; + addDoc(collection(database, "chats"), { + _id, + createdAt, + text, + user, + }); + }, []); - return ( - onSend(messages)} - messagesContainerStyle={{ - backgroundColor: '#fff' - }} - textInputStyle={{ - backgroundColor: '#fff', - borderRadius: 20, - }} - user={{ - _id: auth?.currentUser?.email, - avatar: 'https://i.pravatar.cc/700' - }} + const renderBubble = (props) => { + const formattedTime = moment(props.currentMessage.createdAt).format( + "h:mm A" + ); + return ( + + {props.currentMessage.text} + {formattedTime} + + ); + }; + + return ( + onSend(messages)} + messagesContainerStyle={{ + backgroundColor: "#EEE7E1", + borderRadius: 20, + }} + textInputStyle={{ + backgroundColor: "white", + borderRadius: 20, + paddingHorizontal: 12, + marginTop: 6, + borderWidth: 0.5, + borderColor: "grey", + }} + renderInputToolbar={(props) => ( + - ); + )} + renderBubble={renderBubble} + user={{ + _id: auth?.currentUser?.email, + avatar: "https://i.pravatar.cc/700", + }} + /> + ); } + +const styles = StyleSheet.create({ + bubble: { + padding: 15, + borderRadius: 15, + backgroundColor: "#f0f0f0", + }, + rightBubble: { + backgroundColor: "#EDFFE0", + }, + timeText: { + fontSize: 10, + color: "#888", + marginTop: 3, + }, +});