blob: 0dc49753081c270857c867113d7f7e8886dc1d34 [file] [log] [blame]
simond47ef9e2022-09-28 22:24:28 -04001import dayjs from 'dayjs';
2import { useMemo } from 'react';
3import dayOfYear from 'dayjs/plugin/dayOfYear';
4import isBetween from 'dayjs/plugin/isBetween';
5import { Stack } from '@mui/system';
6import {
7 MessageCall,
8 MessageDate,
9 MessageInitial,
10 MessageMember,
11 MessageBubblesGroup,
12 MessageTime,
13 MessageMerge,
14} from './Message';
idillonbef18a52022-09-01 01:51:40 -040015
simond47ef9e2022-09-28 22:24:28 -040016dayjs.extend(dayOfYear);
17dayjs.extend(isBetween);
Larbi Gharibe9af9732021-03-31 15:08:01 +010018
Adrien Béraudaf09a462021-04-15 18:02:29 -040019export default function MessageList(props) {
simond47ef9e2022-09-28 22:24:28 -040020 const messagesComponents = useMemo(() => buildMessagesList(props.messages), [props.messages]);
Adrien Béraud4e287b92021-04-24 16:15:56 -040021
Adrien Béraud150b4782021-04-21 19:40:59 -040022 return (
simond47ef9e2022-09-28 22:24:28 -040023 <Stack marginLeft="16px" marginRight="16px" direction="column-reverse">
24 {messagesComponents?.map(({ Component, id, props }) => (
25 <Component key={id} {...props} />
26 ))}
idillonbef18a52022-09-01 01:51:40 -040027 </Stack>
simond47ef9e2022-09-28 22:24:28 -040028 );
idillonbef18a52022-09-01 01:51:40 -040029}
30
31const buildMessagesList = (messages) => {
32 if (messages.length == 0) {
33 return null;
34 }
35
simond47ef9e2022-09-28 22:24:28 -040036 const components = [];
37 let lastTime = dayjs.unix(messages[0].timestamp);
38 let lastAuthor = messages[0].author;
39 let messageBubblesGroup = [];
idillonbef18a52022-09-01 01:51:40 -040040
41 const pushMessageBubblesGroup = () => {
42 if (messageBubblesGroup.length == 0) {
simond47ef9e2022-09-28 22:24:28 -040043 return;
idillonbef18a52022-09-01 01:51:40 -040044 }
45 components.push({
46 id: `group-${messageBubblesGroup[0].id}`,
47 Component: MessageBubblesGroup,
48 props: { messages: messageBubblesGroup },
simond47ef9e2022-09-28 22:24:28 -040049 });
50 messageBubblesGroup = [];
51 };
idillonbef18a52022-09-01 01:51:40 -040052
53 const pushMessageCall = (message) => {
54 components.push({
55 id: `call-${message.id}`,
56 Component: MessageCall,
57 props: { message },
simond47ef9e2022-09-28 22:24:28 -040058 });
59 };
idillonbef18a52022-09-01 01:51:40 -040060
61 const pushMessageMember = (message) => {
62 components.push({
63 id: `member-${message.id}`,
64 Component: MessageMember,
65 props: { message },
simond47ef9e2022-09-28 22:24:28 -040066 });
67 };
idillonbef18a52022-09-01 01:51:40 -040068
69 const pushMessageMerge = (message) => {
70 components.push({
71 id: `merge-${message.id}`,
72 Component: MessageMerge,
73 props: { message },
simond47ef9e2022-09-28 22:24:28 -040074 });
75 };
idillonbef18a52022-09-01 01:51:40 -040076
simond47ef9e2022-09-28 22:24:28 -040077 const pushMessageTime = (message, time, hasDateOnTop = false) => {
idillonbef18a52022-09-01 01:51:40 -040078 components.push({
79 id: `time-${message.id}`,
80 Component: MessageTime,
81 props: { time, hasDateOnTop },
simond47ef9e2022-09-28 22:24:28 -040082 });
83 };
idillonbef18a52022-09-01 01:51:40 -040084
85 const pushMessageDate = (message, time) => {
86 components.push({
87 id: `date-${message.id}`,
88 Component: MessageDate,
simond47ef9e2022-09-28 22:24:28 -040089 props: { time },
90 });
91 };
idillonbef18a52022-09-01 01:51:40 -040092
93 const pushMessageInitial = (message) => {
94 components.push({
95 id: `initial-${message.id}`,
96 Component: MessageInitial,
simond47ef9e2022-09-28 22:24:28 -040097 props: { message },
98 });
99 };
idillonbef18a52022-09-01 01:51:40 -0400100
simond47ef9e2022-09-28 22:24:28 -0400101 messages.forEach((message) => {
102 // most recent messages first
idillonbef18a52022-09-01 01:51:40 -0400103 switch (message.type) {
simond47ef9e2022-09-28 22:24:28 -0400104 case 'text/plain':
105 case 'application/data-transfer+json':
idillonbef18a52022-09-01 01:51:40 -0400106 if (lastAuthor != message.author) {
simond47ef9e2022-09-28 22:24:28 -0400107 pushMessageBubblesGroup();
idillonbef18a52022-09-01 01:51:40 -0400108 }
simond47ef9e2022-09-28 22:24:28 -0400109 messageBubblesGroup.push(message);
110 break;
111 case 'application/call-history+json':
112 pushMessageBubblesGroup();
113 pushMessageCall(message);
114 break;
115 case 'member':
116 pushMessageBubblesGroup();
117 pushMessageMember(message);
118 break;
119 case 'merge':
120 pushMessageBubblesGroup();
121 pushMessageMerge(message);
122 break;
123 case 'initial':
idillonbef18a52022-09-01 01:51:40 -0400124 default:
simond47ef9e2022-09-28 22:24:28 -0400125 break;
idillonbef18a52022-09-01 01:51:40 -0400126 }
127
simond47ef9e2022-09-28 22:24:28 -0400128 const time = dayjs.unix(message.timestamp);
129 if (message.type == 'initial') {
130 pushMessageBubblesGroup();
131 pushMessageTime(message, time, true);
132 pushMessageDate(message, time);
133 pushMessageInitial(message);
134 } else {
135 if (
136 // If the date is different
137 lastTime?.year() != time.year() ||
138 lastTime?.dayOfYear() != time.dayOfYear()
idillonbef18a52022-09-01 01:51:40 -0400139 ) {
simond47ef9e2022-09-28 22:24:28 -0400140 pushMessageBubblesGroup();
141 pushMessageTime(message, time, true);
142 pushMessageDate(message, time);
143 } else if (
144 // If more than 5 minutes have passed since the last message
145 !lastTime.isBetween(time, time?.add(5, 'minute'))
146 ) {
147 pushMessageBubblesGroup();
148 pushMessageTime(message, time);
idillonbef18a52022-09-01 01:51:40 -0400149 }
150
simond47ef9e2022-09-28 22:24:28 -0400151 lastTime = time;
152 lastAuthor = message.author;
idillonbef18a52022-09-01 01:51:40 -0400153 }
simond47ef9e2022-09-28 22:24:28 -0400154 });
idillonbef18a52022-09-01 01:51:40 -0400155
simond47ef9e2022-09-28 22:24:28 -0400156 return components;
157};