blob: bcbcd28dd4bd3bb182155d0f263a5fc1be7c336e [file] [log] [blame]
simon26e79f72022-10-05 22:16:08 -04001/*
2 * Copyright (C) 2022 Savoir-faire Linux Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation; either version 3 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public
15 * License along with this program. If not, see
16 * <https://www.gnu.org/licenses/>.
17 */
simon07b4eb02022-09-29 17:50:26 -040018import { Stack } from '@mui/system';
simond47ef9e2022-09-28 22:24:28 -040019import dayjs from 'dayjs';
simond47ef9e2022-09-28 22:24:28 -040020import dayOfYear from 'dayjs/plugin/dayOfYear';
21import isBetween from 'dayjs/plugin/isBetween';
simon07b4eb02022-09-29 17:50:26 -040022import { useMemo } from 'react';
23
simond47ef9e2022-09-28 22:24:28 -040024import {
simon07b4eb02022-09-29 17:50:26 -040025 MessageBubblesGroup,
simond47ef9e2022-09-28 22:24:28 -040026 MessageCall,
27 MessageDate,
28 MessageInitial,
29 MessageMember,
simond47ef9e2022-09-28 22:24:28 -040030 MessageMerge,
simon07b4eb02022-09-29 17:50:26 -040031 MessageTime,
simond47ef9e2022-09-28 22:24:28 -040032} from './Message';
idillonbef18a52022-09-01 01:51:40 -040033
simond47ef9e2022-09-28 22:24:28 -040034dayjs.extend(dayOfYear);
35dayjs.extend(isBetween);
Larbi Gharibe9af9732021-03-31 15:08:01 +010036
Adrien Béraudaf09a462021-04-15 18:02:29 -040037export default function MessageList(props) {
simond47ef9e2022-09-28 22:24:28 -040038 const messagesComponents = useMemo(() => buildMessagesList(props.messages), [props.messages]);
Adrien Béraud4e287b92021-04-24 16:15:56 -040039
Adrien Béraud150b4782021-04-21 19:40:59 -040040 return (
simond47ef9e2022-09-28 22:24:28 -040041 <Stack marginLeft="16px" marginRight="16px" direction="column-reverse">
42 {messagesComponents?.map(({ Component, id, props }) => (
43 <Component key={id} {...props} />
44 ))}
idillonbef18a52022-09-01 01:51:40 -040045 </Stack>
simond47ef9e2022-09-28 22:24:28 -040046 );
idillonbef18a52022-09-01 01:51:40 -040047}
48
49const buildMessagesList = (messages) => {
50 if (messages.length == 0) {
51 return null;
52 }
53
simond47ef9e2022-09-28 22:24:28 -040054 const components = [];
55 let lastTime = dayjs.unix(messages[0].timestamp);
56 let lastAuthor = messages[0].author;
57 let messageBubblesGroup = [];
idillonbef18a52022-09-01 01:51:40 -040058
59 const pushMessageBubblesGroup = () => {
60 if (messageBubblesGroup.length == 0) {
simond47ef9e2022-09-28 22:24:28 -040061 return;
idillonbef18a52022-09-01 01:51:40 -040062 }
63 components.push({
64 id: `group-${messageBubblesGroup[0].id}`,
65 Component: MessageBubblesGroup,
66 props: { messages: messageBubblesGroup },
simond47ef9e2022-09-28 22:24:28 -040067 });
68 messageBubblesGroup = [];
69 };
idillonbef18a52022-09-01 01:51:40 -040070
71 const pushMessageCall = (message) => {
72 components.push({
73 id: `call-${message.id}`,
74 Component: MessageCall,
75 props: { message },
simond47ef9e2022-09-28 22:24:28 -040076 });
77 };
idillonbef18a52022-09-01 01:51:40 -040078
79 const pushMessageMember = (message) => {
80 components.push({
81 id: `member-${message.id}`,
82 Component: MessageMember,
83 props: { message },
simond47ef9e2022-09-28 22:24:28 -040084 });
85 };
idillonbef18a52022-09-01 01:51:40 -040086
87 const pushMessageMerge = (message) => {
88 components.push({
89 id: `merge-${message.id}`,
90 Component: MessageMerge,
91 props: { message },
simond47ef9e2022-09-28 22:24:28 -040092 });
93 };
idillonbef18a52022-09-01 01:51:40 -040094
simond47ef9e2022-09-28 22:24:28 -040095 const pushMessageTime = (message, time, hasDateOnTop = false) => {
idillonbef18a52022-09-01 01:51:40 -040096 components.push({
97 id: `time-${message.id}`,
98 Component: MessageTime,
99 props: { time, hasDateOnTop },
simond47ef9e2022-09-28 22:24:28 -0400100 });
101 };
idillonbef18a52022-09-01 01:51:40 -0400102
103 const pushMessageDate = (message, time) => {
104 components.push({
105 id: `date-${message.id}`,
106 Component: MessageDate,
simond47ef9e2022-09-28 22:24:28 -0400107 props: { time },
108 });
109 };
idillonbef18a52022-09-01 01:51:40 -0400110
111 const pushMessageInitial = (message) => {
112 components.push({
113 id: `initial-${message.id}`,
114 Component: MessageInitial,
simond47ef9e2022-09-28 22:24:28 -0400115 props: { message },
116 });
117 };
idillonbef18a52022-09-01 01:51:40 -0400118
simond47ef9e2022-09-28 22:24:28 -0400119 messages.forEach((message) => {
120 // most recent messages first
idillonbef18a52022-09-01 01:51:40 -0400121 switch (message.type) {
simond47ef9e2022-09-28 22:24:28 -0400122 case 'text/plain':
123 case 'application/data-transfer+json':
idillonbef18a52022-09-01 01:51:40 -0400124 if (lastAuthor != message.author) {
simond47ef9e2022-09-28 22:24:28 -0400125 pushMessageBubblesGroup();
idillonbef18a52022-09-01 01:51:40 -0400126 }
simond47ef9e2022-09-28 22:24:28 -0400127 messageBubblesGroup.push(message);
128 break;
129 case 'application/call-history+json':
130 pushMessageBubblesGroup();
131 pushMessageCall(message);
132 break;
133 case 'member':
134 pushMessageBubblesGroup();
135 pushMessageMember(message);
136 break;
137 case 'merge':
138 pushMessageBubblesGroup();
139 pushMessageMerge(message);
140 break;
141 case 'initial':
idillonbef18a52022-09-01 01:51:40 -0400142 default:
simond47ef9e2022-09-28 22:24:28 -0400143 break;
idillonbef18a52022-09-01 01:51:40 -0400144 }
145
simond47ef9e2022-09-28 22:24:28 -0400146 const time = dayjs.unix(message.timestamp);
147 if (message.type == 'initial') {
148 pushMessageBubblesGroup();
149 pushMessageTime(message, time, true);
150 pushMessageDate(message, time);
151 pushMessageInitial(message);
152 } else {
153 if (
154 // If the date is different
155 lastTime?.year() != time.year() ||
156 lastTime?.dayOfYear() != time.dayOfYear()
idillonbef18a52022-09-01 01:51:40 -0400157 ) {
simond47ef9e2022-09-28 22:24:28 -0400158 pushMessageBubblesGroup();
159 pushMessageTime(message, time, true);
160 pushMessageDate(message, time);
161 } else if (
162 // If more than 5 minutes have passed since the last message
163 !lastTime.isBetween(time, time?.add(5, 'minute'))
164 ) {
165 pushMessageBubblesGroup();
166 pushMessageTime(message, time);
idillonbef18a52022-09-01 01:51:40 -0400167 }
168
simond47ef9e2022-09-28 22:24:28 -0400169 lastTime = time;
170 lastAuthor = message.author;
idillonbef18a52022-09-01 01:51:40 -0400171 }
simond47ef9e2022-09-28 22:24:28 -0400172 });
idillonbef18a52022-09-01 01:51:40 -0400173
simond47ef9e2022-09-28 22:24:28 -0400174 return components;
175};