From 50251c4354c2b4fe9c84ffe877e6f466cf8d851d Mon Sep 17 00:00:00 2001 From: corlard3y Date: Mon, 27 May 2024 12:33:14 +0100 Subject: [PATCH] fix: add comment to empty fn --- .../chat/ChatViewList/ChatViewList.tsx | 314 +++++------------- 1 file changed, 74 insertions(+), 240 deletions(-) diff --git a/packages/uiweb/src/lib/components/chat/ChatViewList/ChatViewList.tsx b/packages/uiweb/src/lib/components/chat/ChatViewList/ChatViewList.tsx index 05d705910..05d23a046 100644 --- a/packages/uiweb/src/lib/components/chat/ChatViewList/ChatViewList.tsx +++ b/packages/uiweb/src/lib/components/chat/ChatViewList/ChatViewList.tsx @@ -25,7 +25,6 @@ import { ThemeContext } from '../theme/ThemeProvider'; // Assets // Interfaces & Types -import { IReactionsForChatMessages } from '../../../types'; import { Group, IChatViewListProps } from '../exportedTypes'; import { IChatTheme } from '../theme'; import { IChatInfoResponse } from '../types'; @@ -52,8 +51,6 @@ const CHAT_STATUS = { INVALID_CHAT: 'Invalid chatId', }; -const SCROLL_LIMIT = 25; - // Exported Interfaces & Types // Exported Functions @@ -71,16 +68,11 @@ export const ChatViewList: React.FC = (options: IChatViewLis // const [chatStatusText, setChatStatusText] = useState(''); const [messages, setMessages] = useState([]); - const [reactions, setReactions] = useState({}); - const { historyMessages, historyLoading: messageLoading } = useFetchMessageUtilities(); - const scrollRef = useRef(null); + const listInnerRef = useRef(null); const [stopPagination, setStopPagination] = useState(false); const { fetchChat } = useFetchChat(); - // keep tab on singular action id, useful to ensure only one action takes place - const [singularActionId, setSingularActionId] = useState(null); - // for stream const { chatStream, @@ -95,7 +87,7 @@ export const ChatViewList: React.FC = (options: IChatViewLis const dates = new Set(); // Primary Hook that fetches and sets ChatInfo which then fetches and sets UserInfo - // Which then calls await fetchChatMessages(); to fetch messages + // Which then calls await getMessagesCall(); to fetch messages useEffect(() => { (async () => { if (!user) return; @@ -141,143 +133,15 @@ export const ChatViewList: React.FC = (options: IChatViewLis }; }, [chatId, user]); - // When loading is done - fetch chat messages + // When loading is done useEffect(() => { if (initialized.loading) return; (async function () { - await fetchChatMessages(); + await getMessagesCall(); })(); }, [initialized.loading]); - // when chat messages are changed or chat reactions are changed - useEffect(() => { - const checkForScrollAndFetchMessages = async () => { - if ( - !initialized.loading && - scrollRef && - scrollRef?.current && - scrollRef?.current?.parentElement && - !messageLoading && - !stopPagination - ) { - console.debug( - 'UIWeb::ChatViewList::useEffect[messages, reactions]::Checking if we need to load more chats::', - messages, - reactions, - scrollRef.current.clientHeight, - SCROLL_LIMIT, - scrollRef.current.parentElement.clientHeight, - scrollRef.current.clientHeight + SCROLL_LIMIT < scrollRef.current.parentElement.clientHeight - ); - - if (scrollRef.current.clientHeight + SCROLL_LIMIT < scrollRef.current.parentElement.clientHeight) { - await fetchChatMessages(); - } - } - }; - - // new messages are loaded, calculate new top and adjust since render is done - if (scrollRef.current) { - const content = scrollRef.current; - - const oldScrollHeight = parseInt(content.getAttribute('data-old-scroll-height') || '0', 10); // Old scroll height before messages are added - const newScrollHeight = content.scrollHeight; // New scroll height after messages are added - const scrollHeightDifference = newScrollHeight - oldScrollHeight; // Calculate how much the scroll height has increased plus some variance for spinner - - // Adjust the scroll position by the difference in scroll height to maintain the same view - content.scrollTop += scrollHeightDifference; - } - - // check and fetch messages - checkForScrollAndFetchMessages(); - }, [messages]); - - // Smart Scrolling - // Scroll to bottom if user hasn't scrolled or if scroll is at bottom - // Else leave the scroll as it is - // to get scroll lock - const onScroll = async () => { - if (scrollRef.current) { - const { scrollTop, scrollHeight, clientHeight } = scrollRef.current; - - let scrollLocked = scrollRef.current.getAttribute('data-scroll-locked') === 'true' ? true : false; - const programmableScroll = scrollRef.current.getAttribute('data-programmable-scroll') === 'true' ? true : false; - const programmableScrollTop = scrollRef.current.getAttribute('data-programmable-scroll-top') || 0; - - // user has scrolled away so scroll should not be locked - if (programmableScroll === false) { - scrollLocked = false; - } - - // lock scroll if user is at bottom - if (scrollTop + clientHeight >= scrollHeight - 10) { - // add 10 for variability - scrollLocked = true; - } - - console.debug( - `UIWeb::ChatViewList::onScroll::scrollLocked ${new Date().toISOString()}`, - scrollRef.current.scrollTop, - scrollRef.current.clientHeight, - scrollRef.current.scrollHeight, - scrollLocked - ); - - // update scroll-locked attribute - scrollRef.current.setAttribute('data-scroll-locked', scrollLocked.toString()); - - if (scrollTop === 0) { - const content = scrollRef.current; - const oldScrollHeight = content.scrollHeight; // Capture the old scroll height before new messages are added - scrollRef.current.setAttribute('data-old-scroll-height', oldScrollHeight.toString()); - - await fetchChatMessages(); - } - } - }; - - // To enable smart scrolling when content height gets adjsuted - const chatContainerRef = useRef(null); - useEffect(() => { - const resizeObserver = new ResizeObserver((entries) => { - for (const entry of entries) { - const { height } = entry.contentRect; - - if (scrollRef.current && height !== 0) { - const scrollLocked = scrollRef.current.getAttribute('data-scroll-locked') === 'true' ? true : false; - - console.debug( - `UIWeb::ChatViewList::onScroll::scrollLocked Observer ${new Date().toISOString()}`, - scrollRef.current.scrollTop, - scrollRef.current.clientHeight, - scrollRef.current.scrollHeight, - scrollLocked - ); - - if (height !== 0 && scrollLocked) { - // update programmable-scroll attribute - scrollRef.current.setAttribute('data-programmable-scroll', 'true'); - scrollRef.current?.scrollTo(0, scrollRef.current?.scrollHeight); - - // update programmable-scroll attribute after timeout of 1000ms for previews to render - setTimeout(() => { - if (scrollRef.current) { - scrollRef.current.setAttribute('data-programmable-scroll', 'false'); - } - }, 1000); - } - } - } - }); - - if (chatContainerRef.current) { - resizeObserver.observe(chatContainerRef.current); - } - - return () => resizeObserver.disconnect(); // clean up - }, [chatContainerRef.current]); - // Change listtype to 'CHATS' and hidden to false when chatAcceptStream is received useEffect(() => { if (Object.keys(chatAcceptStream || {}).length > 0 && chatAcceptStream.constructor === Object) { @@ -293,6 +157,9 @@ export const ChatViewList: React.FC = (options: IChatViewLis return () => clearTimeout(timer); } + return () => { + // add comment + }; }, [chatAcceptStream, participantJoinStream]); // Change listtype to 'UINITIALIZED' and hidden to true when participantRemoveStream or participantLeaveStream is received @@ -309,12 +176,16 @@ export const ChatViewList: React.FC = (options: IChatViewLis useEffect(() => { if (Object.keys(chatStream || {}).length > 0 && chatStream.constructor === Object) { transformSteamMessage(chatStream); + // setChatStatusText(''); + scrollToBottom(); } }, [chatStream]); useEffect(() => { if (Object.keys(chatRequestStream || {}).length > 0 && chatRequestStream.constructor === Object) { transformSteamMessage(chatRequestStream); + // setChatStatusText(''); + scrollToBottom(); } }, [chatRequestStream]); @@ -327,112 +198,97 @@ export const ChatViewList: React.FC = (options: IChatViewLis const transformedMessage = transformStreamToIMessageIPFSWithCID(item); if (messages && messages.length) { const newChatViewList = appendUniqueMessages(messages, [transformedMessage], false); - filterChatMessages(newChatViewList); + setFilteredMessages(newChatViewList); } else { - filterChatMessages([transformedMessage]); + setFilteredMessages([transformedMessage]); } } }; - const fetchChatMessages = async () => { - if (user && !stopPagination && !messageLoading) { - const reference = messages && messages?.length ? messages[0].link : null; - const chatHistory = await historyMessages({ - limit: limit, - chatId: chatId, - reference, - }); + useEffect(() => { + if (messages && messages?.length && messages?.length <= limit) { + // setChatStatusText(''); + scrollToBottom(); + } + }, [messages]); - if (chatHistory && chatHistory?.length) { - const reversedChatHistory = chatHistory?.reverse(); - if (messages && messages?.length) { - const newChatViewList = appendUniqueMessages(messages, reversedChatHistory, true); - filterChatMessages(newChatViewList as IMessageIPFSWithCID[]); - } else { - filterChatMessages(reversedChatHistory as IMessageIPFSWithCID[]); - } + //methods + const scrollToBottom = () => { + requestAnimationFrame(() => { + if (listInnerRef.current) { + listInnerRef.current.scrollTop = listInnerRef.current.scrollHeight; } + }); + }; - // check and stop pagination if user is readmode and chatInfo visibility is false - if ( - (user && user.readmode() && initialized.chatInfo?.meta?.visibility === false) || - initialized.chatInfo?.meta?.group === false - ) { - // not a public group - setStopPagination(true); - } + const onScroll = async () => { + if (listInnerRef.current) { + const { scrollTop } = listInnerRef.current; + if (scrollTop === 0) { + const content = listInnerRef.current; + const curScrollPos = content.scrollTop; + const oldScroll = content.scrollHeight - content.clientHeight; + + await getMessagesCall(); - // check and stop pagination if all chats are fetched - if (!chatHistory || chatHistory?.length < limit) { - setStopPagination(true); + const newScroll = content.scrollHeight - content.clientHeight; + content.scrollTop = newScroll - oldScroll; } } }; - const processChatReactions = (messageList: Array) => { - const reactionMessages = reactions; - - for (const message of messageList) { - if (message.messageType === 'Reaction') { - const reaction = message as IMessageIPFSWithCID; + const getMessagesCall = async () => { + let reference = null; + let stopFetchingChats = false; + if (messages && messages?.length) { + reference = messages[0].link; + if (!reference) { + stopFetchingChats = true; + setStopPagination(stopFetchingChats); + } + } - // TODO: This should be present as an interface in the restapi package - const reference = (reaction as any).messageObj?.reference ?? ''; + if (user && !stopFetchingChats) { + const chatHistory = await historyMessages({ + limit: limit, + chatId: chatId, + reference, + }); - if (!reactionMessages[reference]) { - reactionMessages[reference] = []; + if (chatHistory?.length) { + const reversedChatHistory = chatHistory?.reverse(); + if (messages && messages?.length) { + const newChatViewList = appendUniqueMessages(messages, reversedChatHistory, true); + setFilteredMessages(newChatViewList as IMessageIPFSWithCID[]); + } else { + setFilteredMessages(reversedChatHistory as IMessageIPFSWithCID[]); } - // Push the reaction directly into the array - reactionMessages[reference].push(reaction); } } - - return reactionMessages; }; - const filterChatMessages = (messageList: Array) => { - // filter duplicates - const uniqueMessagesList = messageList.filter((msg) => !chatFilterList.includes(msg.cid)); + const setFilteredMessages = (messageList: Array) => { + const updatedMessageList = messageList.filter((msg) => !chatFilterList.includes(msg.cid)); - // remove reactions into reactions - const reactionMessages = processChatReactions(uniqueMessagesList); - - console.debug( - `UIWeb::ChatViewList::filterChatMessages::uniqueMessageList::${new Date().toISOString()}`, - uniqueMessagesList - ); - console.debug( - `UIWeb::ChatViewList::filterChatMessages::reactionMessages::${new Date().toISOString()}`, - reactionMessages - ); - - if (uniqueMessagesList && uniqueMessagesList.length) { - setMessages([...uniqueMessagesList]); - } - - if (reactionMessages && reactionMessages.length) { - // deep copy to update - setReactions(JSON.parse(JSON.stringify(reactionMessages))); + if (updatedMessageList && updatedMessageList.length) { + setMessages([...updatedMessageList]); } }; type RenderDataType = { chat: IMessageIPFS; dateNum: string; - uid: string; }; - const renderDate = ({ chat, dateNum, uid }: RenderDataType) => { + const renderDate = ({ chat, dateNum }: RenderDataType) => { const timestampDate = dateToFromNowDaily(chat.timestamp as number); dates.add(dateNum); return ( {timestampDate} @@ -441,15 +297,12 @@ export const ChatViewList: React.FC = (options: IChatViewLis return ( = (options: IChatViewLis e.stopPropagation(); if (!stopPagination) onScroll(); }} - onClick={() => { - // cancel any singular action - setSingularActionId(null); - }} >
= (options: IChatViewLis flexDirection="column" justifyContent="start" width="100%" - ref={chatContainerRef} blur={initialized.isHidden} > {messages && messages?.map((chat: IMessageIPFS, index: number) => { - // If message is a reaction, then skip it - if (chat?.messageType === 'Reaction') return null; - const dateNum = moment(chat.timestamp).format('L'); // TODO: This is a hack as chat.fromDID is converted with eip to match with user.account creating a bug for omnichain const position = pCAIP10ToWallet(chat.fromDID)?.toLowerCase() !== pCAIP10ToWallet(user?.account ?? '')?.toLowerCase() ? 0 : 1; - - // define zIndex, really big number minus 1 - const uid = `${999999999 - index}`; - return ( <> - {dates.has(dateNum) ? null : renderDate({ chat, dateNum, uid: uid })} + {dates.has(dateNum) ? null : renderDate({ chat, dateNum })}
- {/* TODO: Remove decryptedMessagePayload in v2 component */}
@@ -581,8 +414,9 @@ const ChatViewListCard = styled(Section)` } overscroll-behavior: contain; + scroll-behavior: smooth; `; const ChatViewListCardInner = styled(Section)` - filter: ${(props) => (props.blur ? 'blur(6px)' : 'none')}; + filter: ${(props) => (props.blur ? 'blur(12px)' : 'none')}; `;