convert Message and MessageList to Typescript
Change-Id: Idbca1335dccbf910c2e1715769ff46c575472d00
diff --git a/client/src/components/MessageList.tsx b/client/src/components/MessageList.tsx
new file mode 100644
index 0000000..6c3c8bf
--- /dev/null
+++ b/client/src/components/MessageList.tsx
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+import { Stack } from '@mui/system';
+import dayjs, { Dayjs } from 'dayjs';
+import dayOfYear from 'dayjs/plugin/dayOfYear';
+import isBetween from 'dayjs/plugin/isBetween';
+import { Account, ConversationMember, Message } from 'jami-web-common';
+import { ReactNode, useMemo } from 'react';
+
+import {
+ MessageBubblesGroup,
+ MessageCall,
+ MessageDate,
+ MessageInitial,
+ MessageMember,
+ MessageMerge,
+ MessageTime,
+} from './Message';
+
+dayjs.extend(dayOfYear);
+dayjs.extend(isBetween);
+
+interface MessageListProps {
+ account: Account;
+ members: ConversationMember[];
+ messages: Message[];
+}
+
+export default function MessageList({ account, members, messages }: MessageListProps) {
+ const messageComponents = useMemo(() => buildMessagesList(account, members, messages), [account, members, messages]);
+ return <Stack direction="column-reverse">{messageComponents}</Stack>;
+}
+
+const buildMessagesList = (account: Account, members: ConversationMember[], messages: Message[]) => {
+ if (messages.length === 0) {
+ return [];
+ }
+
+ const messageComponents: ReactNode[] = [];
+ let lastTime = dayjs.unix(Number(messages[0].timestamp));
+ let lastAuthor = messages[0].author;
+ let messagesGroup: Message[] = [];
+
+ const pushMessageBubblesGroup = () => {
+ if (messagesGroup.length === 0) {
+ return;
+ }
+ const props = { account, members, messages: messagesGroup };
+ messageComponents.push(<MessageBubblesGroup key={`group-${messagesGroup[0].id}`} {...props} />);
+ messagesGroup = [];
+ };
+
+ const pushMessageCall = (message: Message) => {
+ const props = { message };
+ messageComponents.push(<MessageCall key={`call-${message.id}`} {...props} />);
+ };
+
+ const pushMessageMember = (message: Message) => {
+ const props = { message };
+ messageComponents.push(<MessageMember key={`member-${message.id}`} {...props} />);
+ };
+
+ const pushMessageMerge = (message: Message) => {
+ const props = { message };
+ messageComponents.push(<MessageMerge key={`merge-${message.id}`} {...props} />);
+ };
+
+ const pushMessageTime = (message: Message, time: Dayjs, hasDateOnTop = false) => {
+ const props = { time, hasDateOnTop };
+ messageComponents.push(<MessageTime key={`time-${message.id}`} {...props} />);
+ };
+
+ const pushMessageDate = (message: Message, time: Dayjs) => {
+ const props = { time };
+ messageComponents.push(<MessageDate key={`date-${message.id}`} {...props} />);
+ };
+
+ const pushMessageInitial = (message: Message) => {
+ const props = { message };
+ messageComponents.push(<MessageInitial key={`initial-${message.id}`} {...props} />);
+ };
+
+ messages.forEach((message) => {
+ // most recent messages first
+ switch (message.type) {
+ case 'text/plain':
+ case 'application/data-transfer+json':
+ if (lastAuthor !== message.author) {
+ pushMessageBubblesGroup();
+ }
+ messagesGroup.push(message);
+ break;
+ case 'application/call-history+json':
+ pushMessageBubblesGroup();
+ pushMessageCall(message);
+ break;
+ case 'member':
+ pushMessageBubblesGroup();
+ pushMessageMember(message);
+ break;
+ case 'merge':
+ pushMessageBubblesGroup();
+ pushMessageMerge(message);
+ break;
+ case 'initial':
+ default:
+ break;
+ }
+
+ const time = dayjs.unix(Number(message.timestamp));
+ if (message.type === 'initial') {
+ pushMessageBubblesGroup();
+ pushMessageTime(message, time, true);
+ pushMessageDate(message, time);
+ pushMessageInitial(message);
+ } else {
+ if (
+ // If the date is different
+ lastTime?.year() !== time.year() ||
+ lastTime?.dayOfYear() !== time.dayOfYear()
+ ) {
+ pushMessageBubblesGroup();
+ pushMessageTime(message, time, true);
+ pushMessageDate(message, time);
+ } else if (
+ // If more than 5 minutes have passed since the last message
+ !lastTime.isBetween(time, time?.add(5, 'minute'))
+ ) {
+ pushMessageBubblesGroup();
+ pushMessageTime(message, time);
+ }
+
+ lastTime = time;
+ lastAuthor = message.author;
+ }
+ });
+
+ return messageComponents;
+};