Skip to content

Commit

Permalink
Refactored messages Array on client to use a Map (#341)
Browse files Browse the repository at this point in the history
* Added `id` field to `Message` type on client and server

* Error message for sending message when socket is closed

* Refactored messages state from an `Array` to a `Map`

* Removed unused import
  • Loading branch information
connor-kress authored Feb 23, 2025
1 parent ee758ce commit 5955203
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 24 deletions.
18 changes: 13 additions & 5 deletions client/app/components/chat/MessageChannel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ import Message from "./ChatMessage";
import { MessageChannelProps } from "../../types/Props";
import { TouchableOpacity } from "react-native";
import SheetModal from "./SheetModal";
import { UserProfile } from "../../types/User";

const MessageChannel: React.FC<MessageChannelProps> = ({
nearbyUsers,
messages,
}) => {
const [isModalVisible, setModalVisible] = useState(false);
const reverseMessages = [...messages].reverse();

const messagesArray = Array.from(messages.values())
.sort((a, b) => b.timestamp - a.timestamp);

const handleLongPress = () => {
setModalVisible(true);
Expand All @@ -28,11 +30,17 @@ const MessageChannel: React.FC<MessageChannelProps> = ({
contentContainerStyle={{
width: "100%",
}}
data={reverseMessages}
data={messagesArray}
renderItem={({ item }) => {
const user = nearbyUsers[item.author];
// console.log(nearbyUsers);
if (user === undefined) return null;
const user: UserProfile = nearbyUsers[item.author];
// Mock data for testing when socket server isn't working
// const user: UserProfile = { displayName: "You", profilePicture: 1 };
if (user === undefined) {
console.log(
`Message recieved from user not in nearbyUsers (${item.author})`
);
return null;
}
return (
<TouchableOpacity onLongPress={ handleLongPress }>
<Message
Expand Down
21 changes: 16 additions & 5 deletions client/app/screens/chat/ChatScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
KeyboardAvoidingView,
Platform,
View,
Text,
StyleSheet,
Dimensions,
} from "react-native";
Expand Down Expand Up @@ -35,7 +34,7 @@ const ChatScreen = () => {
// Note: To prevent complexity, all user information is grabbed from different contexts and services. If we wanted most information inside of UserContext, we would have to import contexts within contexts and have state change as certain things mount, which could cause errors that are difficult to pinpoint.

// Message loading and sending logic
const [messages, setMessages] = useState<Message[]>([]);
const [messages, setMessages] = useState<Map<string, Message>>(new Map());
const [messageContent, setMessageContent] = useState<string>("");

useEffect(() => {
Expand All @@ -50,7 +49,11 @@ const ChatScreen = () => {
);
await refreshNearbyUsers(socket);
}
setMessages((prevMessages) => [...prevMessages, message]);
setMessages((prevMessages) => {
const newMessages = new Map(prevMessages);
newMessages.set(message.id, message);
return newMessages;
});
if (ack) console.log("Server acknowledged message:", ack);
};

Expand All @@ -67,9 +70,9 @@ const ChatScreen = () => {
if (socket === null) return;

const newMessage: Message = {
id: Crypto.randomUUID(),
author: String(userAuth.userAuthInfo?.uid),
//msgId: Crypto.randomUUID(),
timestamp: -1, // timestamp will be overridden by socket server
timestamp: Date.now(), // timestamp will be overridden by server
content: { text: messageContent.trim() },
location: {
lat: Number(location?.lat),
Expand All @@ -78,9 +81,17 @@ const ChatScreen = () => {
replyTo: undefined,
reactions: {},
};
console.log(`[LOG] New message: ${newMessage.author
} - ${newMessage.content.text} (${newMessage.id})`);
sendMessage(socket, newMessage);

setMessageContent("");
// Optimistic UI update for testing when socket server isn't working
// setMessages((prevMessages) => {
// const newMessages = new Map(prevMessages);
// newMessages.set(newMessage.id, newMessage);
// return newMessages;
// });
};

return (
Expand Down
7 changes: 7 additions & 0 deletions client/app/services/SocketService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ export const sendMessage = (
socket: Socket,
message: Message,
) => {
if (!socket.connected) {
console.error(
`Cannot send message "${message.content.text}" (socket not connected)`
);
return;
}
console.log(`Sending message "${message.content.text}" on socket ${socket.id} (${socket.active})`);
socket.emit("sendMessage", message,
(ack: string) => {
console.log("sendMessage ack:", ack);
Expand Down
1 change: 1 addition & 0 deletions client/app/types/Message.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { LocationType } from "./Location";

export interface Message {
id: string,
author: string,
timestamp: number,
content: {
Expand Down
2 changes: 1 addition & 1 deletion client/app/types/Props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export type MessageProps = {

export type MessageChannelProps = {
nearbyUsers: { [uid: string]: UserProfile };
messages: Message[];
messages: Map<string, Message>;
};

export type SafeAreaWrapperProps = {
Expand Down
2 changes: 1 addition & 1 deletion server/src/socket_server/methods/send_message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const sendMessage = (
seen.add(recipient.uid);

recipient.socket.emit("message", message);
console.log("[WS] Sent message to user <" + recipient.uid + ">");
console.log(`[WS] Sent message to user <${recipient.uid}>`);
}

if (ack) ack("success");
Expand Down
25 changes: 13 additions & 12 deletions server/src/types/message.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { Location } from "../types"

export interface Message {
author: string,
timestamp: number,
content: {
text?: string,
attachment?: string,
},
location: Location,
replyTo?: string,
reactions: {
[key: string]: number,
}
}
id: string,
author: string,
timestamp: number,
content: {
text?: string,
attachment?: string,
},
location: Location,
replyTo?: string,
reactions: {
[key: string]: number,
}
}

0 comments on commit 5955203

Please sign in to comment.