blob: f6da60c6a2b59049f72170c394fa921ac575ffb2 [file] [log] [blame]
idillonbef18a52022-09-01 01:51:40 -04001import dayjs from "dayjs"
idillon08f77172022-09-13 19:14:17 -04002import React, { useEffect, useMemo } from 'react'
idillonbef18a52022-09-01 01:51:40 -04003import dayOfYear from 'dayjs/plugin/dayOfYear'
4import isBetween from 'dayjs/plugin/isBetween'
5import { Stack } from "@mui/system"
6import { MessageCall, MessageDate, MessageInitial, MessageMember, MessageBubblesGroup, MessageTime, MessageMerge } from "./Message"
7
8dayjs.extend(dayOfYear)
9dayjs.extend(isBetween)
Larbi Gharibe9af9732021-03-31 15:08:01 +010010
Adrien Béraudaf09a462021-04-15 18:02:29 -040011export default function MessageList(props) {
idillon08f77172022-09-13 19:14:17 -040012 const messagesComponents = useMemo(
13 () => buildMessagesList(props.messages),
14 [props.messages]
15 )
Adrien Béraud4e287b92021-04-24 16:15:56 -040016
17 useEffect(() => {
Adrien Béraudabba2e52021-04-24 21:39:56 -040018 if (!props.loading)
19 props.loadMore()
idillonbef18a52022-09-01 01:51:40 -040020 }, [props.conversationId])
Adrien Béraud4e287b92021-04-24 16:15:56 -040021
Adrien Béraud150b4782021-04-21 19:40:59 -040022 return (
idillonbef18a52022-09-01 01:51:40 -040023 <Stack
24 marginLeft="16px"
25 marginRight="16px"
26 direction="column-reverse"
27 >
28 {messagesComponents?.map(
29 ({Component, id, props}) => <Component key={id} {...props}/>
30 )}
31 </Stack>
Adrien Béraud150b4782021-04-21 19:40:59 -040032 )
idillonbef18a52022-09-01 01:51:40 -040033}
34
35const buildMessagesList = (messages) => {
36 if (messages.length == 0) {
37 return null;
38 }
39
40 const components = []
41 let lastTime = dayjs.unix(messages[0].timestamp)
42 let lastAuthor = messages[0].author
43 let messageBubblesGroup = []
44
45 const pushMessageBubblesGroup = () => {
46 if (messageBubblesGroup.length == 0) {
47 return
48 }
49 components.push({
50 id: `group-${messageBubblesGroup[0].id}`,
51 Component: MessageBubblesGroup,
52 props: { messages: messageBubblesGroup },
53 })
54 messageBubblesGroup = []
55 }
56
57 const pushMessageCall = (message) => {
58 components.push({
59 id: `call-${message.id}`,
60 Component: MessageCall,
61 props: { message },
62 })
63 }
64
65 const pushMessageMember = (message) => {
66 components.push({
67 id: `member-${message.id}`,
68 Component: MessageMember,
69 props: { message },
70 })
71 }
72
73 const pushMessageMerge = (message) => {
74 components.push({
75 id: `merge-${message.id}`,
76 Component: MessageMerge,
77 props: { message },
78 })
79 }
80
81 const pushMessageTime = (message, time, hasDateOnTop=false) => {
82 components.push({
83 id: `time-${message.id}`,
84 Component: MessageTime,
85 props: { time, hasDateOnTop },
86 })
87 }
88
89 const pushMessageDate = (message, time) => {
90 components.push({
91 id: `date-${message.id}`,
92 Component: MessageDate,
93 props: { time }
94 })
95 }
96
97 const pushMessageInitial = (message) => {
98 components.push({
99 id: `initial-${message.id}`,
100 Component: MessageInitial,
101 props: { message }
102 })
103 }
104
105 messages.forEach(message => { // most recent messages first
106 switch (message.type) {
107 case "text/plain":
108 case "application/data-transfer+json":
109 if (lastAuthor != message.author) {
110 pushMessageBubblesGroup()
111 }
112 messageBubblesGroup.push(message)
113 break
114 case "application/call-history+json":
115 pushMessageBubblesGroup()
116 pushMessageCall(message)
117 break
118 case "member":
119 pushMessageBubblesGroup()
120 pushMessageMember(message)
121 break
122 case "merge":
123 pushMessageBubblesGroup()
124 pushMessageMerge(message)
125 break
126 case "initial":
127 default:
128 break
129 }
130
131 const time = dayjs.unix(message.timestamp)
132 if (message.type == "initial") {
133 pushMessageBubblesGroup()
134 pushMessageTime(message, time, true)
135 pushMessageDate(message, time)
136 pushMessageInitial(message)
137 }
138 else {
139 if ( // If the date is different
140 lastTime?.year() != time.year()
141 || lastTime?.dayOfYear() != time.dayOfYear()
142 ) {
143 pushMessageBubblesGroup()
144 pushMessageTime(message, time, true)
145 pushMessageDate(message, time)
146 }
147 else if ( // If more than 5 minutes have passed since the last message
148 !lastTime.isBetween(time, time?.add(5, "minute"))
149 ) {
150 pushMessageBubblesGroup()
151 pushMessageTime(message, time)
152 }
153
154 lastTime = time
155 lastAuthor = message.author
156 }
157 })
158
159 return components
160}