blob: 513af54b8bf19152b2ad37df34cfe2fb8b94a0e0 [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) {
idillonae655dd2022-10-14 18:11:02 -040038 const messagesComponents = useMemo(
39 () => buildMessagesList(props.account, props.members, props.messages),
40 [props.account, props.members, props.messages]
41 );
Adrien Béraud4e287b92021-04-24 16:15:56 -040042
Adrien Béraud150b4782021-04-21 19:40:59 -040043 return (
idillonae655dd2022-10-14 18:11:02 -040044 <Stack direction="column-reverse">
simond47ef9e2022-09-28 22:24:28 -040045 {messagesComponents?.map(({ Component, id, props }) => (
46 <Component key={id} {...props} />
47 ))}
idillonbef18a52022-09-01 01:51:40 -040048 </Stack>
simond47ef9e2022-09-28 22:24:28 -040049 );
idillonbef18a52022-09-01 01:51:40 -040050}
51
idillonae655dd2022-10-14 18:11:02 -040052const buildMessagesList = (account, members, messages) => {
idillonbef18a52022-09-01 01:51:40 -040053 if (messages.length == 0) {
54 return null;
55 }
56
simond47ef9e2022-09-28 22:24:28 -040057 const components = [];
58 let lastTime = dayjs.unix(messages[0].timestamp);
59 let lastAuthor = messages[0].author;
60 let messageBubblesGroup = [];
idillonbef18a52022-09-01 01:51:40 -040061
62 const pushMessageBubblesGroup = () => {
63 if (messageBubblesGroup.length == 0) {
simond47ef9e2022-09-28 22:24:28 -040064 return;
idillonbef18a52022-09-01 01:51:40 -040065 }
66 components.push({
67 id: `group-${messageBubblesGroup[0].id}`,
68 Component: MessageBubblesGroup,
idillonae655dd2022-10-14 18:11:02 -040069 props: { account, members, messages: messageBubblesGroup },
simond47ef9e2022-09-28 22:24:28 -040070 });
71 messageBubblesGroup = [];
72 };
idillonbef18a52022-09-01 01:51:40 -040073
74 const pushMessageCall = (message) => {
75 components.push({
76 id: `call-${message.id}`,
77 Component: MessageCall,
78 props: { message },
simond47ef9e2022-09-28 22:24:28 -040079 });
80 };
idillonbef18a52022-09-01 01:51:40 -040081
82 const pushMessageMember = (message) => {
83 components.push({
84 id: `member-${message.id}`,
85 Component: MessageMember,
86 props: { message },
simond47ef9e2022-09-28 22:24:28 -040087 });
88 };
idillonbef18a52022-09-01 01:51:40 -040089
90 const pushMessageMerge = (message) => {
91 components.push({
92 id: `merge-${message.id}`,
93 Component: MessageMerge,
94 props: { message },
simond47ef9e2022-09-28 22:24:28 -040095 });
96 };
idillonbef18a52022-09-01 01:51:40 -040097
simond47ef9e2022-09-28 22:24:28 -040098 const pushMessageTime = (message, time, hasDateOnTop = false) => {
idillonbef18a52022-09-01 01:51:40 -040099 components.push({
100 id: `time-${message.id}`,
101 Component: MessageTime,
102 props: { time, hasDateOnTop },
simond47ef9e2022-09-28 22:24:28 -0400103 });
104 };
idillonbef18a52022-09-01 01:51:40 -0400105
106 const pushMessageDate = (message, time) => {
107 components.push({
108 id: `date-${message.id}`,
109 Component: MessageDate,
simond47ef9e2022-09-28 22:24:28 -0400110 props: { time },
111 });
112 };
idillonbef18a52022-09-01 01:51:40 -0400113
114 const pushMessageInitial = (message) => {
115 components.push({
116 id: `initial-${message.id}`,
117 Component: MessageInitial,
simond47ef9e2022-09-28 22:24:28 -0400118 props: { message },
119 });
120 };
idillonbef18a52022-09-01 01:51:40 -0400121
simond47ef9e2022-09-28 22:24:28 -0400122 messages.forEach((message) => {
123 // most recent messages first
idillonbef18a52022-09-01 01:51:40 -0400124 switch (message.type) {
simond47ef9e2022-09-28 22:24:28 -0400125 case 'text/plain':
126 case 'application/data-transfer+json':
idillonbef18a52022-09-01 01:51:40 -0400127 if (lastAuthor != message.author) {
simond47ef9e2022-09-28 22:24:28 -0400128 pushMessageBubblesGroup();
idillonbef18a52022-09-01 01:51:40 -0400129 }
simond47ef9e2022-09-28 22:24:28 -0400130 messageBubblesGroup.push(message);
131 break;
132 case 'application/call-history+json':
133 pushMessageBubblesGroup();
134 pushMessageCall(message);
135 break;
136 case 'member':
137 pushMessageBubblesGroup();
138 pushMessageMember(message);
139 break;
140 case 'merge':
141 pushMessageBubblesGroup();
142 pushMessageMerge(message);
143 break;
144 case 'initial':
idillonbef18a52022-09-01 01:51:40 -0400145 default:
simond47ef9e2022-09-28 22:24:28 -0400146 break;
idillonbef18a52022-09-01 01:51:40 -0400147 }
148
simond47ef9e2022-09-28 22:24:28 -0400149 const time = dayjs.unix(message.timestamp);
150 if (message.type == 'initial') {
151 pushMessageBubblesGroup();
152 pushMessageTime(message, time, true);
153 pushMessageDate(message, time);
154 pushMessageInitial(message);
155 } else {
156 if (
157 // If the date is different
158 lastTime?.year() != time.year() ||
159 lastTime?.dayOfYear() != time.dayOfYear()
idillonbef18a52022-09-01 01:51:40 -0400160 ) {
simond47ef9e2022-09-28 22:24:28 -0400161 pushMessageBubblesGroup();
162 pushMessageTime(message, time, true);
163 pushMessageDate(message, time);
164 } else if (
165 // If more than 5 minutes have passed since the last message
166 !lastTime.isBetween(time, time?.add(5, 'minute'))
167 ) {
168 pushMessageBubblesGroup();
169 pushMessageTime(message, time);
idillonbef18a52022-09-01 01:51:40 -0400170 }
171
simond47ef9e2022-09-28 22:24:28 -0400172 lastTime = time;
173 lastAuthor = message.author;
idillonbef18a52022-09-01 01:51:40 -0400174 }
simond47ef9e2022-09-28 22:24:28 -0400175 });
idillonbef18a52022-09-01 01:51:40 -0400176
simond47ef9e2022-09-28 22:24:28 -0400177 return components;
178};