blob: 0dc49753081c270857c867113d7f7e8886dc1d34 [file] [log] [blame]
import dayjs from 'dayjs';
import { useMemo } from 'react';
import dayOfYear from 'dayjs/plugin/dayOfYear';
import isBetween from 'dayjs/plugin/isBetween';
import { Stack } from '@mui/system';
import {
MessageCall,
MessageDate,
MessageInitial,
MessageMember,
MessageBubblesGroup,
MessageTime,
MessageMerge,
} from './Message';
dayjs.extend(dayOfYear);
dayjs.extend(isBetween);
export default function MessageList(props) {
const messagesComponents = useMemo(() => buildMessagesList(props.messages), [props.messages]);
return (
<Stack marginLeft="16px" marginRight="16px" direction="column-reverse">
{messagesComponents?.map(({ Component, id, props }) => (
<Component key={id} {...props} />
))}
</Stack>
);
}
const buildMessagesList = (messages) => {
if (messages.length == 0) {
return null;
}
const components = [];
let lastTime = dayjs.unix(messages[0].timestamp);
let lastAuthor = messages[0].author;
let messageBubblesGroup = [];
const pushMessageBubblesGroup = () => {
if (messageBubblesGroup.length == 0) {
return;
}
components.push({
id: `group-${messageBubblesGroup[0].id}`,
Component: MessageBubblesGroup,
props: { messages: messageBubblesGroup },
});
messageBubblesGroup = [];
};
const pushMessageCall = (message) => {
components.push({
id: `call-${message.id}`,
Component: MessageCall,
props: { message },
});
};
const pushMessageMember = (message) => {
components.push({
id: `member-${message.id}`,
Component: MessageMember,
props: { message },
});
};
const pushMessageMerge = (message) => {
components.push({
id: `merge-${message.id}`,
Component: MessageMerge,
props: { message },
});
};
const pushMessageTime = (message, time, hasDateOnTop = false) => {
components.push({
id: `time-${message.id}`,
Component: MessageTime,
props: { time, hasDateOnTop },
});
};
const pushMessageDate = (message, time) => {
components.push({
id: `date-${message.id}`,
Component: MessageDate,
props: { time },
});
};
const pushMessageInitial = (message) => {
components.push({
id: `initial-${message.id}`,
Component: MessageInitial,
props: { message },
});
};
messages.forEach((message) => {
// most recent messages first
switch (message.type) {
case 'text/plain':
case 'application/data-transfer+json':
if (lastAuthor != message.author) {
pushMessageBubblesGroup();
}
messageBubblesGroup.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(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 components;
};