| import dayjs from "dayjs" |
| import React, { 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 |
| } |