IO-3000 Adjusted first approach at messaging WS changes.

This commit is contained in:
Patrick Fic
2024-11-19 15:52:57 -08:00
parent 289a666b6d
commit 299a675a9c
22 changed files with 1952 additions and 2570 deletions

View File

@@ -2,105 +2,90 @@ import Icon from "@ant-design/icons";
import { Tooltip } from "antd";
import i18n from "i18next";
import dayjs from "../../utils/day";
import React, { useEffect, useRef } from "react";
import React, { useRef, useEffect } from "react";
import { MdDone, MdDoneAll } from "react-icons/md";
import { AutoSizer, CellMeasurer, CellMeasurerCache, List } from "react-virtualized";
import { Virtuoso } from "react-virtuoso";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import "./chat-message-list.styles.scss";
export default function ChatMessageListComponent({ messages }) {
const virtualizedListRef = useRef(null);
const virtuosoRef = useRef(null);
const _cache = new CellMeasurerCache({
fixedWidth: true,
// minHeight: 50,
defaultHeight: 100
});
// Scroll to the bottom after a short delay when the component mounts
useEffect(() => {
const timer = setTimeout(() => {
if (virtuosoRef.current) {
virtuosoRef.current.scrollToIndex({
index: messages.length - 1,
behavior: "auto" // Instantly scroll to the bottom
});
}
}, 100); // Delay of 100ms to allow rendering
return () => clearTimeout(timer); // Cleanup the timer on unmount
}, [messages.length]); // Run only once on component mount
const scrollToBottom = (renderedrows) => {
//console.log("Scrolling to", messages.length);
// !!virtualizedListRef.current &&
// virtualizedListRef.current.scrollToRow(messages.length);
// Outstanding isue on virtualization: https://github.com/bvaughn/react-virtualized/issues/1179
//Scrolling does not work on this version of React.
};
useEffect(scrollToBottom, [messages]);
const _rowRenderer = ({ index, key, parent, style }) => {
// Scroll to the bottom after the new messages are rendered
useEffect(() => {
if (virtuosoRef.current) {
// Allow the DOM and Virtuoso to fully render the new data
setTimeout(() => {
virtuosoRef.current.scrollToIndex({
index: messages.length - 1,
align: "end", // Ensure the last message is fully visible
behavior: "smooth" // Smooth scrolling
});
}, 50); // Slight delay to ensure layout recalculates
}
}, [messages]); // Triggered when new messages are added
//TODO: Does this one need to come into the render of the method?
const renderMessage = (index) => {
const message = messages[index];
return (
<CellMeasurer cache={_cache} key={key} rowIndex={index} parent={parent}>
{({ measure, registerChild }) => (
<div
ref={registerChild}
onLoad={measure}
style={style}
className={`${messages[index].isoutbound ? "mine messages" : "yours messages"}`}
>
<div className="message msgmargin">
{MessageRender(messages[index])}
{StatusRender(messages[index].status)}
<div key={index} className={`${message.isoutbound ? "mine messages" : "yours messages"}`}>
<div className="message msgmargin">
<Tooltip title={DateTimeFormatter({ children: message.created_at })}>
<div>
{message.image_path &&
message.image_path.map((i, idx) => (
<div key={idx} style={{ display: "flex", justifyContent: "center" }}>
<a href={i} target="__blank" rel="noopener noreferrer">
<img alt="Received" className="message-img" src={i} />
</a>
</div>
))}
<div>{message.text}</div>
</div>
{messages[index].isoutbound && (
<div style={{ fontSize: 10 }}>
{i18n.t("messaging.labels.sentby", {
by: messages[index].userid,
time: dayjs(messages[index].created_at).format("MM/DD/YYYY @ hh:mm a")
})}
</div>
)}
</Tooltip>
{message.status && (
<div className="message-status">
<Icon
component={message.status === "sent" ? MdDone : message.status === "delivered" ? MdDoneAll : null}
className="message-icon"
/>
</div>
)}
</div>
{message.isoutbound && (
<div style={{ fontSize: 10 }}>
{i18n.t("messaging.labels.sentby", {
by: message.userid,
time: dayjs(message.created_at).format("MM/DD/YYYY @ hh:mm a")
})}
</div>
)}
</CellMeasurer>
</div>
);
};
return (
<div className="chat">
<AutoSizer>
{({ height, width }) => (
<List
ref={virtualizedListRef}
width={width}
height={height}
rowHeight={_cache.rowHeight}
rowRenderer={_rowRenderer}
rowCount={messages.length}
overscanRowCount={10}
estimatedRowSize={150}
scrollToIndex={messages.length}
/>
)}
</AutoSizer>
<Virtuoso
ref={virtuosoRef}
data={messages}
itemContent={(index) => renderMessage(index)}
followOutput="smooth" // Ensure smooth scrolling when new data is appended
style={{ height: "100%", width: "100%" }}
/>
</div>
);
}
const MessageRender = (message) => {
return (
<Tooltip title={DateTimeFormatter({ children: message.created_at })}>
<div>
{message.image_path &&
message.image_path.map((i, idx) => (
<div key={idx} style={{ display: "flex", justifyContent: "center" }}>
<a href={i} target="__blank">
<img alt="Received" className="message-img" src={i} />
</a>
</div>
))}
<div>{message.text}</div>
</div>
</Tooltip>
);
};
const StatusRender = (status) => {
switch (status) {
case "sent":
return <Icon component={MdDone} className="message-icon" />;
case "delivered":
return <Icon component={MdDoneAll} className="message-icon" />;
default:
return null;
}
};

View File

@@ -1,37 +1,30 @@
.message-icon {
//position: absolute;
// bottom: 0rem;
color: whitesmoke;
border: #000000;
position: absolute;
margin: 0 0.1rem;
bottom: 0.1rem;
right: 0.3rem;
z-index: 5;
}
.chat {
flex: 1;
//width: 300px;
//border: solid 1px #eee;
display: flex;
flex-direction: column;
margin: 0.8rem 0rem;
overflow: hidden; // Ensure the content scrolls correctly
}
.messages {
//margin-top: 30px;
display: flex;
flex-direction: column;
padding: 0.5rem; // Add padding to avoid edge clipping
}
.message {
border-radius: 20px;
padding: 0.25rem 0.8rem;
//margin-top: 5px;
// margin-bottom: 5px;
//display: inline-block;
.message-img {
max-width: 10rem;
@@ -56,7 +49,7 @@
position: relative;
}
.yours .message.last:before {
.yours .message:last-child:before {
content: "";
position: absolute;
z-index: 0;
@@ -68,7 +61,7 @@
border-bottom-right-radius: 15px;
}
.yours .message.last:after {
.yours .message:last-child:after {
content: "";
position: absolute;
z-index: 1;
@@ -88,12 +81,11 @@
color: white;
margin-left: 25%;
background: linear-gradient(to bottom, #00d0ea 0%, #0085d1 100%);
background-attachment: fixed;
position: relative;
padding-bottom: 0.6rem;
}
.mine .message.last:before {
.mine .message:last-child:before {
content: "";
position: absolute;
z-index: 0;
@@ -102,11 +94,10 @@
height: 20px;
width: 20px;
background: linear-gradient(to bottom, #00d0ea 0%, #0085d1 100%);
background-attachment: fixed;
border-bottom-left-radius: 15px;
}
.mine .message.last:after {
.mine .message:last-child:after {
content: "";
position: absolute;
z-index: 1;