const componentOwnerId = props.componentOwnerId; const readMessage = props.readMessage; const handleReaction = props.handleReaction; const openThread = props.openThread; const setOpenThread = props.setOpenThread; const activeChat = props.activeChat; const curbApi = props.curbApi; const accountId = props.accountId; const incomingMessages = props.incomingMessages; const updatedMessages = props.updatedMessages; const incomingThreadMessages = props.incomingThreadMessages; const updatedThreadMessages = props.updatedThreadMessages; const ContainerPadding = styled.div` display: flex; flex-direction: row; padding-top: 1rem; padding-left: 2.5rem; padding-right: 2.5rem; padding-bottom: 2.5rem; scroll-behavior: smooth; @media (min-width: 1025px) { height: calc(100vh - 241px); } @media (max-width: 1024px) { padding: 0rem; padding-top: 102px; padding-bottom: 82px; height: 100%; } scrollbar-color: black black; ::-webkit-scrollbar { width: 6px; } ::-webkit-scrollbar-thumb { background-color: black; border-radius: 6px; } ::-webkit-scrollbar-thumb:hover { background-color: black; } * { scrollbar-color: black black; } html::-webkit-scrollbar { width: 12px; } html::-webkit-scrollbar-thumb { background-color: black; border-radius: 6px; } html::-webkit-scrollbar-thumb:hover { background-color: black; } `; const Wrapper = styled.div` height: 100%; `; const [selectedParentMessage, setSelectedParentMessage] = useState(undefined); const setThread = useCallback((message) => { setOpenThread(message); }, []); const getIconFromCache = useCallback((accountId) => { const contractId = context.networkId === "mainnet" ? "social.near" : "v1.social08.testnet"; const args = { keys: [`${accountId}/profile/**`], options: {}, }; const contractMethod = "get"; const fallbackImage = "https://i.imgur.com/e8buxpa.png"; return new Promise((resolve, reject) => { Near.asyncView(contractId, contractMethod, args) .then((result) => { let url = ""; if (!Object.keys(result).length === 0) { url = fallbackImage; } const baseImageObject = result[accountId].profile.image; if (baseImageObject.url) { url = baseImageObject.url; } else if (baseImageObject.ipfs_cid) { url = `https://ipfs.near.social/ipfs/${baseImageObject.ipfs_cid}`; } else if (baseImageObject.nft) { const contractId = baseImageObject.nft.contractId; const tokenId = baseImageObject.nft.tokenId; const base_uri = Near.view(contractId, "nft_metadata").base_uri; const mediaRef = Near.view(contractId, "nft_token", { token_id: tokenId, }).metadata.media; url = `${base_uri}/${mediaRef}`; } resolve(url); }) .catch((error) => { reject(error); }); }); },[]); const renderMessage = useMemo(() => createMessageRenderer({ handleReaction, getIconFromCache, accountId, setThread, isThread: false, }) , []); const renderThreadMessage = useMemo(() => createMessageRenderer({ handleReaction, getIconFromCache, accountId, isThread: true, }) , []); const ThreadTitle = styled.div` color: #FFF; font-size: 24px; font-style: normal; font-weight: 500; line-height: 120%; `; const ThreadContainer = styled.div` position: relative; padding-right: 30px; `; const CloseButton = styled.button` position: absolute; right: 20px; top: 20px; transform: translateY(-50%); background: none; border: none; font-size: 20px; cursor: pointer; color: grey; &:hover { color: white; } `; const ThreadHeader = ({ openThread, onClose }) => ( <ThreadContainer> <ThreadTitle>Thread</ThreadTitle> <p style={{ color: 'white' }}>{openThread.text}</p> <CloseButton onClick={onClose}>×</CloseButton> </ThreadContainer> ); return ( <Wrapper> <ContainerPadding> <VirtualizedChat loadInitialMessages={() => curbApi.fetchMessages({chat: activeChat, limit: 20})} loadPrevMessages={(id) => curbApi.fetchMessages({chat: activeChat, beforeId: id, limit: 20})} incomingMessages={incomingMessages} updatedMessages={updatedMessages} onItemNewItemRender={readMessage} shouldTriggerNewItemIndicator={(message) => message.sender !== accountId} render={renderMessage} chatId={activeChat} style={{ height: "100%", width: openThread ? "75%" : "100%" }} /> {openThread && ( <div style={{display: 'flex', flexDirection: 'column', height: '100%', width: '25%', scroll: 'none' }}> <ThreadHeader openThread={openThread} onClose={() => setOpenThread(undefined)}/> <VirtualizedChat loadInitialMessages={() => curbApi.fetchMessages({chat: activeChat, limit: 20, parentMessageId: openThread.id})} loadPrevMessages={(id) => curbApi.fetchMessages({chat: activeChat, beforeId: id, limit: 20, parentMessageId: openThread.id})} incomingMessages={incomingThreadMessages} updatedMessages={updatedThreadMessages} shouldTriggerNewItemIndicator={() => false} // Never show new item indicator in thread render={renderThreadMessage} chatId={openThread.id} style={{ height: "100%", width: "100%" }} /> </div> )} </ContainerPadding> </Wrapper> );