blob: 0d2dc10ae0f1eba0570cf7c972ed2e692259dce6 [file] [log] [blame]
simon07b4eb02022-09-29 17:50:26 -04001import { Stack } from '@mui/system';
simond47ef9e2022-09-28 22:24:28 -04002import dayjs from 'dayjs';
simond47ef9e2022-09-28 22:24:28 -04003import dayOfYear from 'dayjs/plugin/dayOfYear';
4import isBetween from 'dayjs/plugin/isBetween';
simon07b4eb02022-09-29 17:50:26 -04005import { useMemo } from 'react';
6
simond47ef9e2022-09-28 22:24:28 -04007import {
simon07b4eb02022-09-29 17:50:26 -04008 MessageBubblesGroup,
simond47ef9e2022-09-28 22:24:28 -04009 MessageCall,
10 MessageDate,
11 MessageInitial,
12 MessageMember,
simond47ef9e2022-09-28 22:24:28 -040013 MessageMerge,
simon07b4eb02022-09-29 17:50:26 -040014 MessageTime,
simond47ef9e2022-09-28 22:24:28 -040015} from './Message';
idillonbef18a52022-09-01 01:51:40 -040016
simond47ef9e2022-09-28 22:24:28 -040017dayjs.extend(dayOfYear);
18dayjs.extend(isBetween);
Larbi Gharibe9af9732021-03-31 15:08:01 +010019
Adrien Béraudaf09a462021-04-15 18:02:29 -040020export default function MessageList(props) {
simond47ef9e2022-09-28 22:24:28 -040021 const messagesComponents = useMemo(() => buildMessagesList(props.messages), [props.messages]);
Adrien Béraud4e287b92021-04-24 16:15:56 -040022
Adrien Béraud150b4782021-04-21 19:40:59 -040023 return (
simond47ef9e2022-09-28 22:24:28 -040024 <Stack marginLeft="16px" marginRight="16px" direction="column-reverse">
25 {messagesComponents?.map(({ Component, id, props }) => (
26 <Component key={id} {...props} />
27 ))}
idillonbef18a52022-09-01 01:51:40 -040028 </Stack>
simond47ef9e2022-09-28 22:24:28 -040029 );
idillonbef18a52022-09-01 01:51:40 -040030}
31
32const buildMessagesList = (messages) => {
33 if (messages.length == 0) {
34 return null;
35 }
36
simond47ef9e2022-09-28 22:24:28 -040037 const components = [];
38 let lastTime = dayjs.unix(messages[0].timestamp);
39 let lastAuthor = messages[0].author;
40 let messageBubblesGroup = [];
idillonbef18a52022-09-01 01:51:40 -040041
42 const pushMessageBubblesGroup = () => {
43 if (messageBubblesGroup.length == 0) {
simond47ef9e2022-09-28 22:24:28 -040044 return;
idillonbef18a52022-09-01 01:51:40 -040045 }
46 components.push({
47 id: `group-${messageBubblesGroup[0].id}`,
48 Component: MessageBubblesGroup,
49 props: { messages: messageBubblesGroup },
simond47ef9e2022-09-28 22:24:28 -040050 });
51 messageBubblesGroup = [];
52 };
idillonbef18a52022-09-01 01:51:40 -040053
54 const pushMessageCall = (message) => {
55 components.push({
56 id: `call-${message.id}`,
57 Component: MessageCall,
58 props: { message },
simond47ef9e2022-09-28 22:24:28 -040059 });
60 };
idillonbef18a52022-09-01 01:51:40 -040061
62 const pushMessageMember = (message) => {
63 components.push({
64 id: `member-${message.id}`,
65 Component: MessageMember,
66 props: { message },
simond47ef9e2022-09-28 22:24:28 -040067 });
68 };
idillonbef18a52022-09-01 01:51:40 -040069
70 const pushMessageMerge = (message) => {
71 components.push({
72 id: `merge-${message.id}`,
73 Component: MessageMerge,
74 props: { message },
simond47ef9e2022-09-28 22:24:28 -040075 });
76 };
idillonbef18a52022-09-01 01:51:40 -040077
simond47ef9e2022-09-28 22:24:28 -040078 const pushMessageTime = (message, time, hasDateOnTop = false) => {
idillonbef18a52022-09-01 01:51:40 -040079 components.push({
80 id: `time-${message.id}`,
81 Component: MessageTime,
82 props: { time, hasDateOnTop },
simond47ef9e2022-09-28 22:24:28 -040083 });
84 };
idillonbef18a52022-09-01 01:51:40 -040085
86 const pushMessageDate = (message, time) => {
87 components.push({
88 id: `date-${message.id}`,
89 Component: MessageDate,
simond47ef9e2022-09-28 22:24:28 -040090 props: { time },
91 });
92 };
idillonbef18a52022-09-01 01:51:40 -040093
94 const pushMessageInitial = (message) => {
95 components.push({
96 id: `initial-${message.id}`,
97 Component: MessageInitial,
simond47ef9e2022-09-28 22:24:28 -040098 props: { message },
99 });
100 };
idillonbef18a52022-09-01 01:51:40 -0400101
simond47ef9e2022-09-28 22:24:28 -0400102 messages.forEach((message) => {
103 // most recent messages first
idillonbef18a52022-09-01 01:51:40 -0400104 switch (message.type) {
simond47ef9e2022-09-28 22:24:28 -0400105 case 'text/plain':
106 case 'application/data-transfer+json':
idillonbef18a52022-09-01 01:51:40 -0400107 if (lastAuthor != message.author) {
simond47ef9e2022-09-28 22:24:28 -0400108 pushMessageBubblesGroup();
idillonbef18a52022-09-01 01:51:40 -0400109 }
simond47ef9e2022-09-28 22:24:28 -0400110 messageBubblesGroup.push(message);
111 break;
112 case 'application/call-history+json':
113 pushMessageBubblesGroup();
114 pushMessageCall(message);
115 break;
116 case 'member':
117 pushMessageBubblesGroup();
118 pushMessageMember(message);
119 break;
120 case 'merge':
121 pushMessageBubblesGroup();
122 pushMessageMerge(message);
123 break;
124 case 'initial':
idillonbef18a52022-09-01 01:51:40 -0400125 default:
simond47ef9e2022-09-28 22:24:28 -0400126 break;
idillonbef18a52022-09-01 01:51:40 -0400127 }
128
simond47ef9e2022-09-28 22:24:28 -0400129 const time = dayjs.unix(message.timestamp);
130 if (message.type == 'initial') {
131 pushMessageBubblesGroup();
132 pushMessageTime(message, time, true);
133 pushMessageDate(message, time);
134 pushMessageInitial(message);
135 } else {
136 if (
137 // If the date is different
138 lastTime?.year() != time.year() ||
139 lastTime?.dayOfYear() != time.dayOfYear()
idillonbef18a52022-09-01 01:51:40 -0400140 ) {
simond47ef9e2022-09-28 22:24:28 -0400141 pushMessageBubblesGroup();
142 pushMessageTime(message, time, true);
143 pushMessageDate(message, time);
144 } else if (
145 // If more than 5 minutes have passed since the last message
146 !lastTime.isBetween(time, time?.add(5, 'minute'))
147 ) {
148 pushMessageBubblesGroup();
149 pushMessageTime(message, time);
idillonbef18a52022-09-01 01:51:40 -0400150 }
151
simond47ef9e2022-09-28 22:24:28 -0400152 lastTime = time;
153 lastAuthor = message.author;
idillonbef18a52022-09-01 01:51:40 -0400154 }
simond47ef9e2022-09-28 22:24:28 -0400155 });
idillonbef18a52022-09-01 01:51:40 -0400156
simond47ef9e2022-09-28 22:24:28 -0400157 return components;
158};