Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to using classes to define Chat objects #51

Merged
merged 5 commits into from
Jan 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dfx canister call user_mgmt get_user_id '("Matt")'
dfx canister call chats create_direct_chat '(principal "lpfg6-5goq7-vn6yz-wegiu-r6goc-sxoor-wj3b2-dpyup-k6i5m-qhv5m-xae", "Hi Matt, how is it going")'
dfx canister call chats send_message '(45_292_552_032_833_753, "hello!!??")'
dfx identity use matt
dfx canister call chats list_chats
dfx canister call chats get_chats '(record { updated_since = null; message_count_for_top_chat = null })'
dfx canister call chats get_messages '(45_292_552_032_833_753, 1)'
dfx canister call chats mark_read '(45_292_552_032_833_753, 2)'
dfx canister call chats send_message '(45_292_552_032_833_753, "whats up?")'
Expand Down
6 changes: 4 additions & 2 deletions src/website/public/actions/chats/createGroupChat.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Dispatch } from "react";

import chatsService from "../../services/chats/service";
import { ChatId } from "../../model/chats";
import { ChatId, NewGroupChat } from "../../model/chats";
import { UnconfirmedMessage } from "../../model/messages";
import { UserId } from "../../model/users";
import { RootState } from "../../reducers";

Expand Down Expand Up @@ -52,7 +53,8 @@ export default function(subject: string, users: UserId[]) {
// Messages may have been added on the UI before the chat was confirmed on the back end. These messages will
// have been added to the 'chat.unconfirmedMessages' array. So we need to read the values out of this array,
// then apply the state change to confirm the chat, then send those messages using the new chatId.
const messagesToSend = getState().chatsState.chats.find(c => c.kind === "newGroup" && c.id === tempId)!.unconfirmedMessages;
const chat = getState().chatsState.chats.find(c => c instanceof NewGroupChat && c.id === tempId)!
const messagesToSend = chat.messages as UnconfirmedMessage[];

dispatch(outcomeEvent);

Expand Down
82 changes: 35 additions & 47 deletions src/website/public/actions/chats/sendMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { Dispatch } from "react";

import chatsService from "../../services/chats/service";
import { SendDirectMessageResult } from "../../services/chats/sendDirectMessage";
import { Chat, ChatId } from "../../model/chats";
import { Chat, ChatId, DirectChat, GroupChat, NewDirectChat, NewGroupChat } from "../../model/chats";
import { Option } from "../../model/common";
import { LocalMessage } from "../../model/messages";
import { UserId } from "../../model/users";
import { RootState } from "../../reducers";

Expand All @@ -12,33 +13,26 @@ export const SEND_MESSAGE_SUCCEEDED = "SEND_MESSAGE_SUCCEEDED";
export const SEND_MESSAGE_FAILED = "SEND_MESSAGE_FAILED";

export default function(chat: Chat, message: string) {
switch (chat.kind) {
case "direct":
return sendDirectMessage(chat.them, chat.chatId, message);

case "group":
return sendGroupMessage(chat.chatId, message);

case "newDirect":
return sendDirectMessage(chat.them, null, message);

case "newGroup":
return sendMessageToNewGroup(chat.id, message);
if (chat instanceof DirectChat) {
return sendDirectMessage(chat.them, chat.chatId, message);
} else if (chat instanceof GroupChat) {
return sendGroupMessage(chat.chatId, message);
} else if (chat instanceof NewDirectChat) {
return sendDirectMessage(chat.them, null, message);
} else if (chat instanceof NewGroupChat) {
return sendMessageToNewGroup(chat.id, message);
}
}

function sendDirectMessage(userId: UserId, chatId: Option<ChatId>, message: string) {
return async (dispatch: Dispatch<any>, getState: () => RootState) => {
const id = Symbol("id");

const requestEvent: SendMessageRequestedEvent = {
type: SEND_MESSAGE_REQUESTED,
payload: {
kind: "direct",
userId: userId,
chatId: chatId,
message: message,
unconfirmedMessageId: id
message: message
}
};

Expand All @@ -58,11 +52,13 @@ function sendDirectMessage(userId: UserId, chatId: Option<ChatId>, message: stri
kind: "direct",
userId: userId,
chatId: chatId ?? (response.result as SendDirectMessageResult).chatId,
sender: myUserId,
message: message,
unconfirmedMessageId: id,
confirmedMessageId: response.result.messageId,
confirmedMessageDate: response.result.date
message: {
kind: "local",
id: response.result.messageId,
date: response.result.date,
sender: myUserId,
text: message
}
}
} as SendMessageSucceededEvent;
} else {
Expand All @@ -77,15 +73,12 @@ function sendDirectMessage(userId: UserId, chatId: Option<ChatId>, message: stri

function sendGroupMessage(chatId: ChatId, message: string) {
return async (dispatch: Dispatch<any>, getState: () => RootState) => {
const id = Symbol("id");

const requestEvent: SendMessageRequestedEvent = {
type: SEND_MESSAGE_REQUESTED,
payload: {
kind: "group",
chatId: chatId,
message: message,
unconfirmedMessageId: id
message: message
}
};

Expand All @@ -102,11 +95,13 @@ function sendGroupMessage(chatId: ChatId, message: string) {
payload: {
kind: "group",
chatId: chatId,
sender: myUserId,
message: message,
unconfirmedMessageId: id,
confirmedMessageId: response.result.messageId,
confirmedMessageDate: response.result.date
message: {
kind: "local",
id: response.result.messageId,
date: response.result.date,
sender: myUserId,
text: message
}
}
} as SendMessageSucceededEvent;
} else {
Expand Down Expand Up @@ -153,15 +148,13 @@ export type SendDirectMessageRequest = {
kind: "direct",
userId: UserId,
chatId: Option<ChatId>,
message: string,
unconfirmedMessageId: Symbol
message: string
}

export type SendGroupMessageRequest = {
kind: "group",
chatId: ChatId,
message: string,
unconfirmedMessageId: Symbol
message: string
}

export type SendMessageToNewGroupRequest = {
Expand All @@ -172,20 +165,15 @@ export type SendMessageToNewGroupRequest = {

export type SendMessageSuccess = SendDirectMessageSuccess | SendGroupMessageSuccess;

export type SendDirectMessageSuccess = SendMessageSuccessCommon & {
export type SendDirectMessageSuccess = {
kind: "direct",
userId: UserId
}

export type SendGroupMessageSuccess = SendMessageSuccessCommon & {
kind: "group"
userId: UserId,
chatId: ChatId,
message: LocalMessage
}

type SendMessageSuccessCommon = {
export type SendGroupMessageSuccess = {
kind: "group",
chatId: ChatId,
sender: UserId,
message: string,
unconfirmedMessageId: Symbol,
confirmedMessageId: number,
confirmedMessageDate: Date
message: LocalMessage
}
2 changes: 1 addition & 1 deletion src/website/public/actions/chats/setupNewDirectChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export default function(username: string) {
}

function chatAlreadyExists(chats: Chat[], userId: UserId) : boolean {
const chat = chats.find(c => c.kind === "direct" && c.them === userId);
const chat = chats.find(c => "them" in c && c.them === userId);

return Boolean(chat);
}
Expand Down
19 changes: 10 additions & 9 deletions src/website/public/components/ChatList.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React from "react";
import { Option } from "../model/common";
import { RootState } from "../reducers";
import { useSelector } from "react-redux";

import { GroupChat } from "../model/chats";
import { Option } from "../model/common";
import { UserId } from "../model/users";
import { RootState } from "../reducers";

import ChatListItem from "./ChatListItem";

Expand All @@ -26,18 +28,17 @@ function ChatList() {
userId = c.them;
} else {
name = c.subject;
key = c.kind === "group" ? "G-" + c.chatId.toString() : key = "NG-" + c.subject;
key = c instanceof GroupChat ? "G-" + c.chatId.toString() : key = "NG-" + c.subject;
isGroup = true;
userId = null;
}

let latestMessageText = "";
if (c.unconfirmedMessages.length) {
latestMessageText = c.unconfirmedMessages[c.unconfirmedMessages.length - 1].text;
} else if ("confirmedMessages" in c && c.confirmedMessages.length) {
const latestMessage = c.confirmedMessages[c.confirmedMessages.length - 1];
if ("text" in latestMessage) {
latestMessageText = latestMessage.text;
for (let i = c.messages.length - 1; i >= 0; i--) {
const message = c.messages[i];
if ("text" in message) {
latestMessageText = message.text;
break;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/website/public/components/MainHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { useSelector } from "react-redux";

import { RootState } from "../reducers";
import DefaultAvatar from "./defaultAvatar";
import GroupChatIcon from "../assets/icons/groupChatIcon.svg";
Expand Down
48 changes: 21 additions & 27 deletions src/website/public/components/MessagesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import { useSelector } from "react-redux";

import { RootState } from "../reducers";
import { DirectChat } from "../model/chats";
import { Option } from "../model/common";
import { UserId } from "../model/users";

Expand Down Expand Up @@ -31,13 +32,26 @@ function MessagesList() {
let lastSeenDate: Option<Date> = null;
let lastSeenDayString: Option<string> = null;
let prevMessageSender: Option<UserId> = null;
if ("confirmedMessages" in chat) {
for (let i = 0; i < chat.confirmedMessages.length; i++) {
const message = chat.confirmedMessages[i];
if (message.kind === "remote") {
continue;
}
for (let i = 0; i < chat.messages.length; i++) {
const message = chat.messages[i];
if (message.kind === "remote") {
continue;
} else if (message.kind === "unconfirmed") {
const now = new Date();

const mergeWithPrevious: boolean =
lastSeenDate !== null &&
(prevMessageSender === null || prevMessageSender === myUserId) &&
now.getTime() - lastSeenDate.getTime() < MERGE_MESSAGES_SENT_BY_SAME_USER_WITHIN_MILLIS;

const props = {
message: message.text,
mergeWithPrevious
};
children.push(<UnconfirmedMessage key={"u-" + i} {...props} />);
prevMessageSender = myUserId;
lastSeenDate = now;
} else {
const dayString = message.date.toDateString();
if (lastSeenDayString === null || lastSeenDayString !== dayString) {
children.push(<DayChangeMarker key={dayString} date={message.date}/>);
Expand All @@ -57,7 +71,7 @@ function MessagesList() {
mergeWithPrevious
};
children.push(<MessageSentByMe key={message.id} {...props} />);
} else if (chat.kind === "direct") {
} else if (chat instanceof DirectChat) {
const props = {
message: message.text,
date: message.date,
Expand All @@ -81,26 +95,6 @@ function MessagesList() {
}
}

for (let i = 0; i < chat.unconfirmedMessages.length; i++) {
const message = chat.unconfirmedMessages[i];

const now = new Date();

const mergeWithPrevious: boolean =
lastSeenDate !== null &&
(prevMessageSender === null || prevMessageSender === myUserId) &&
now.getTime() - lastSeenDate.getTime() < MERGE_MESSAGES_SENT_BY_SAME_USER_WITHIN_MILLIS;

const props = {
message: message.text,
mergeWithPrevious
};
children.push(<UnconfirmedMessage key={"u-" + i} {...props} />);

lastSeenDate = now;
prevMessageSender = myUserId;
}

return (
<div id="messages" className="detail">
{children}
Expand Down
Loading