Search
Search

Transaction: 37NYTHs...cS7j

Receiver
Status
Succeeded
Transaction Fee
0.00135 
Deposit Value
0.00864 
Gas Used
13 Tgas
Attached Gas
300 Tgas
Created
December 19, 2023 at 9:37:35am
Hash
37NYTHs6oZoEKD1pYf9oNBj1auP44wQLgjepWphpcS7j

Actions

Called method: 'set' in contract: social.near
Arguments:
{ "data": { "calimero-internal.near": { "widget": { "Calimero.Curb.Chat.MessageInput": { "": "const {\n componentOwnerId,\n selectedChat,\n sendMessage,\n openThread,\n isThread,\n isReadOnly,\n isOwner,\n isModerator,\n fetchAccounts,\n} = props;\n\nconst Container = styled.div`\n position: absolute;\n width: 100%;\n bottom: 16px;\n padding-left: 16px;\n padding-right: 16px;\n padding-top: 12px;\n padding-bottom: 12px;\n background-color: #1d1d21;\n display: flex;\n align-items: end;\n @media (min-width: 1025px) {\n gap: 8px;\n border-radius: 4px;\n }\n @media (max-width: 1024px) {\n position: fixed;\n margin: 0 !important;\n left: 0;\n right: 0;\n bottom: 0px;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n gap: 4px;\n margin: 0px;\n padding-left: 8px;\n padding-right: 8px;\n padding-bottom: 12px;\n padding-top: 12px;\n width: 100% !important;\n }\n`;\n\nconst EmojiPopupContainer = styled.div`\n position: absolute;\n bottom: 70px;\n right: 2.5rem;\n`;\n\nconst UploadPopupContainer = styled.div`\n position: absolute;\n bottom: 46px;\n left: 16px;\n @media (max-width: 1024px) {\n left: 8px;\n }\n`;\n\nconst UploadContainer = styled.div`\n background-color: #25252a;\n border-radius: 2px;\n width: fit-content;\n`;\n\nconst [showUpload, setShowUpload] = useState(false);\nconst [message, setMessage] = useState('');\n//Message is cleaned in Quill after it is returned to bos components so\n//this ref is setting value from callback to be used after sending with ENTER key\nconst messageRef = useRef(null);\nconst [uploadedFile, setUploadedFile] = useState(null);\nconst [uploadedImage, setUploadedImage] = useState(null);\nconst [emojiSelectorOpen, setEmojiSelectorOpen] = useState(false);\nconst [error, setError] = useState('');\nconst [sendFromLib, setSendFromLib] = useState(false);\n\nconst handleMessageChange = useCallback((mesage) => {\n setMessage(mesage);\n}, []);\n\nconst resetFile = useCallback(() => {\n setUploadedFile(null);\n setShowUpload(false);\n}, []);\n\nconst resetImage = useCallback(() => {\n setUploadedImage(null);\n setShowUpload(false);\n}, []);\n\nconst emptyText = /^(\\s*<p><br><\\/p>\\s*)*$/;\nconst markdownParser = (text) => {\n const toHTML = text.replace(\n /(\\b(https?:\\/\\/[^\\s<]+\\/?)\\b)|^(#####|####|###|##|#) (.*)$|(@everyone)|(@here)|(@[a-z\\d]+[-_]*[a-z\\d]+[-_]*[a-z\\d]+\\.(near|testnet))|<p><br><\\/p>(?=\\s*$)/gim,\n (\n match,\n url,\n url2,\n heading,\n text,\n everyoneMention,\n hereMention,\n validMention,\n ) => {\n if (url || url2) {\n return `<a href=\"${url || url2}\" class=\"url-link\" target=\"_blank\">${\n url || url2\n }</a>`;\n } else if (heading) {\n return text;\n } else if (everyoneMention) {\n return `<span class='mention-everyone'>@everyone</span>`;\n } else if (hereMention) {\n return `<span class='mention-here'>@here</span>`;\n } else if (validMention) {\n return `<span class='mention mention-user-${validMention\n .replace('@', '')\n .replace(/\\./g, '\\\\.')\n .replace(/_/g, '\\\\_')}'>${validMention}</span>`;\n } else {\n return '';\n }\n },\n );\n\n return toHTML;\n};\n\nconst isActive =\n (message && !emptyText.test(markdownParser(message))) ||\n uploadedImage ||\n uploadedFile;\n\nconst handleSendMessage = useCallback(\n (vmValue) => {\n const messageToSend = vmValue || message;\n if (\n (uploadedFile && !uploadedFile.file.cid) ||\n (uploadedImage && !uploadedImage.file.cid)\n ) {\n return;\n } else if (\n emptyText.test(markdownParser(messageToSend)) &&\n !uploadedImage &&\n !uploadedFile\n ) {\n handleMessageChange('');\n messageRef.current = '';\n } else {\n sendMessage(\n markdownParser(messageToSend),\n uploadedImage,\n selectedChat,\n uploadedFile,\n openThread,\n );\n resetImage();\n resetFile();\n setShowUpload(false);\n setEmojiSelectorOpen(false);\n handleMessageChange('');\n messageRef.current = '';\n }\n },\n [message, uploadedImage, uploadedFile, openThread, selectedChat],\n);\n\nuseEffect(() => {\n if (sendFromLib) {\n handleSendMessage(messageRef.current);\n setSendFromLib(false);\n }\n}, [sendFromLib]);\n\n//Hack for https://stackoverflow.com/questions/57847594/react-hooks-accessing-up-to-date-state-from-within-a-callback\n//as passed handleSendMessage to input field component use staled useState values\nconst handleSendMessageFromLib = (value) => {\n messageRef.current = value;\n setSendFromLib(true);\n};\n\nconst Wrapper = styled.div`\n flex-grow: 1;\n display: contents;\n align-items: start;\n background-color: #111111;\n`;\n\nconst FullWidthWrapper = styled.div`\n display: flow;\n flex-direction: row;\n overflow: hidden;\n align-items: start;\n width: 100%;\n`;\n\n// const IconUploadWrapper = styled.div`\n// height: 34px;\n// width: 34px;\n// padding: 8px;\n// display: flex;\n// justify-content: center;\n// border-radius: 2px;\n// align-items: center;\n// :hover {\n// background-color: #686672;\n// fill: #fff;\n// }\n// cursor: pointer;\n// fill: #686672;\n// `;\n\n// const IconUpload = ({ onClick }) => (\n// <IconUploadWrapper>\n// <svg\n// onClick={onClick}\n// xmlns=\"http://www.w3.org/2000/svg\"\n// width=\"18\"\n// height=\"18\"\n// className=\"bi bi-plus-circle\"\n// viewBox=\"0 0 16 16\"\n// >\n// <path d=\"M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z\" />\n// <path d=\"M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z\" />\n// </svg>\n// </IconUploadWrapper>\n// );\n\nconst EmojiContainer = styled.div`\n border-radius: 2px;\n margin-bottom: 4px;\n height: 26px;\n width: 26px;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 2px;\n cursor: pointer;\n\n .hidden-svg {\n visibility: hidden;\n position: absolute;\n z-index: -10;\n }\n\n .visible-svg {\n visibility: visible;\n }\n`;\n\nconst IconEmoji = () => {\n const [hovered, setHovered] = useState(false);\n\n return (\n <EmojiContainer\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n fill=\"#686672\"\n className={`bi bi-emoji-wink ${hovered ? 'hidden-svg' : 'visible-svg'}`}\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z\" />\n <path d=\"M4.285 9.567a.5.5 0 0 1 .683.183A3.498 3.498 0 0 0 8 11.5a3.498 3.498 0 0 0 3.032-1.75.5.5 0 1 1 .866.5A4.498 4.498 0 0 1 8 12.5a4.498 4.498 0 0 1-3.898-2.25.5.5 0 0 1 .183-.683zM7 6.5C7 7.328 6.552 8 6 8s-1-.672-1-1.5S5.448 5 6 5s1 .672 1 1.5zm1.757-.437a.5.5 0 0 1 .68.194.934.934 0 0 0 .813.493c.339 0 .645-.19.813-.493a.5.5 0 1 1 .874.486A1.934 1.934 0 0 1 10.25 7.75c-.73 0-1.356-.412-1.687-1.007a.5.5 0 0 1 .194-.68z\" />\n </svg>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n fill=\"#FFDD1D\"\n className={`bi bi-emoji-wink-fill ${\n hovered ? 'visible-svg' : 'hidden-svg'\n }`}\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0zM7 6.5C7 5.672 6.552 5 6 5s-1 .672-1 1.5S5.448 8 6 8s1-.672 1-1.5zM4.285 9.567a.5.5 0 0 0-.183.683A4.498 4.498 0 0 0 8 12.5a4.5 4.5 0 0 0 3.898-2.25.5.5 0 1 0-.866-.5A3.498 3.498 0 0 1 8 11.5a3.498 3.498 0 0 1-3.032-1.75.5.5 0 0 0-.683-.183zm5.152-3.31a.5.5 0 0 0-.874.486c.33.595.958 1.007 1.687 1.007.73 0 1.356-.412 1.687-1.007a.5.5 0 0 0-.874-.486.934.934 0 0 1-.813.493.934.934 0 0 1-.813-.493z\" />\n </svg>\n </EmojiContainer>\n );\n};\n\nconst IconSendSvg = styled.svg`\n margin-bottom: 8px;\n :hover {\n fill: #4e95ff;\n }\n cursor: pointer;\n`;\nconst IconSend = ({ onClick, isActive }) => (\n <IconSendSvg\n onClick={onClick}\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n fill={`${isActive ? '#4E95FF' : '#686672'}`}\n className=\"bi bi-send-fill\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M15.964.686a.5.5 0 0 0-.65-.65L.767 5.855H.766l-.452.18a.5.5 0 0 0-.082.887l.41.26.001.002 4.995 3.178 3.178 4.995.002.002.26.41a.5.5 0 0 0 .886-.083l6-15Zm-1.833 1.89L6.637 10.07l-.215-.338a.5.5 0 0 0-.154-.154l-.338-.215 7.494-7.494 1.178-.471-.47 1.178Z\" />\n </IconSendSvg>\n);\n\nconst Placeholder = styled.div`\n position: absolute;\n z-index: 10;\n bottom: ${({ placeholderPosition }) =>\n placeholderPosition && placeholderPosition};\n left: 68px;\n color: #686672;\n font-size: 16px;\n font-style: normal;\n font-weight: 400;\n line-height: 150%;\n pointer-events: none;\n @media (max-width: 1024px) {\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 150%;\n bottom: ${({ placeholderPositionMobile }) =>\n placeholderPositionMobile && placeholderPositionMobile};\n left: 56px;\n }\n`;\n\nconst getCustomStyle = (openThread) => {\n const customStyle = {\n width: 'calc(100% - 440px)',\n marginLeft: '2.5rem',\n marginRight: '2.5rem',\n };\n if (openThread && !isThread) {\n customStyle.width = 'calc(60% - 262px)';\n customStyle.marginRight = '1.25rem';\n } else if (!openThread && !isThread) {\n customStyle.width = 'calc(100% - 440px)';\n } else if (openThread && isThread) {\n customStyle.width = 'calc(40% - 212px)';\n customStyle.marginLeft = '0rem';\n customStyle.marginRight = '1.25rem';\n }\n return customStyle;\n};\n\nconst ReadOnlyField = styled.div`\n background-color: #111111;\n height: 2rem;\n border-radius: 4px;\n padding: 4px 8px 4px 8px;\n font-family: Helvetica Neue;\n font-size: 16px;\n font-style: normal;\n font-weight: 400;\n line-height: 150%;\n color: #797978;\n flex: 1;\n @media (max-width: 1024px) {\n font-size: 14px;\n display: flex;\n align-items: center;\n }\n`;\n\nlet canWriteMessage = false;\nif (isReadOnly) {\n if (isModerator || isOwner) {\n canWriteMessage = true;\n } else {\n canWriteMessage = false;\n }\n} else {\n canWriteMessage = true;\n}\n\nlet placeholderPosition = '16px';\nif (uploadedFile.file.cid) {\n placeholderPosition = '61px';\n} else if (uploadedImage.file.cid) {\n placeholderPosition = '86px';\n}\n\nconst [showAutocomplete, setShowAutocomplete] = useState(false);\n\nconst autoCompleteAccountId = (accountId) => {\n let text = message.replace(/[\\s]{0,1}@[^\\s]*$/, '');\n text = `${text} @${accountId}`.trim() + ' \\u200B';\n setMessage(text);\n setShowAutocomplete(false);\n};\n\nuseEffect(() => {\n const showAccountAutocomplete = /@[\\w][^\\s]*$/.test(message);\n setShowAutocomplete(showAccountAutocomplete);\n}, [message]);\n\nconst ImageIconSvg = () => (\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"#fff\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M15.75 12.75C15.75 13.7446 15.3549 14.6984 14.6517 15.4017C13.9484 16.1049 12.9946 16.5 12 16.5C11.0054 16.5 10.0516 16.1049 9.34835 15.4017C8.64509 14.6984 8.25 13.7446 8.25 12.75C8.25 11.7554 8.64509 10.8016 9.34835 10.0983C10.0516 9.39509 11.0054 9 12 9C12.9946 9 13.9484 9.39509 14.6517 10.0983C15.3549 10.8016 15.75 11.7554 15.75 12.75Z\"\n fill=\"white\"\n />\n <path\n d=\"M3 6C2.20435 6 1.44129 6.31607 0.87868 6.87868C0.316071 7.44129 0 8.20435 0 9V18C0 18.7956 0.316071 19.5587 0.87868 20.1213C1.44129 20.6839 2.20435 21 3 21H21C21.7956 21 22.5587 20.6839 23.1213 20.1213C23.6839 19.5587 24 18.7956 24 18V9C24 8.20435 23.6839 7.44129 23.1213 6.87868C22.5587 6.31607 21.7956 6 21 6H19.242C18.4464 5.99983 17.6835 5.68365 17.121 5.121L15.879 3.879C15.3165 3.31635 14.5536 3.00017 13.758 3H10.242C9.44641 3.00017 8.68348 3.31635 8.121 3.879L6.879 5.121C6.31652 5.68365 5.55358 5.99983 4.758 6H3ZM3.75 9C3.55109 9 3.36032 8.92098 3.21967 8.78033C3.07902 8.63968 3 8.44891 3 8.25C3 8.05109 3.07902 7.86032 3.21967 7.71967C3.36032 7.57902 3.55109 7.5 3.75 7.5C3.94891 7.5 4.13968 7.57902 4.28033 7.71967C4.42098 7.86032 4.5 8.05109 4.5 8.25C4.5 8.44891 4.42098 8.63968 4.28033 8.78033C4.13968 8.92098 3.94891 9 3.75 9ZM17.25 12.75C17.25 14.1424 16.6969 15.4777 15.7123 16.4623C14.7277 17.4469 13.3924 18 12 18C10.6076 18 9.27226 17.4469 8.28769 16.4623C7.30312 15.4777 6.75 14.1424 6.75 12.75C6.75 11.3576 7.30312 10.0223 8.28769 9.03769C9.27226 8.05312 10.6076 7.5 12 7.5C13.3924 7.5 14.7277 8.05312 15.7123 9.03769C16.6969 10.0223 17.25 11.3576 17.25 12.75Z\"\n fill=\"white\"\n />\n </svg>\n);\n\nconst FileIconSvg = () => (\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"#fff\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <g clipPath=\"url(#clip0_952_64107)\">\n <path\n d=\"M13.9395 0H6C5.20435 0 4.44129 0.316071 3.87868 0.87868C3.31607 1.44129 3 2.20435 3 3V21C3 21.7956 3.31607 22.5587 3.87868 23.1213C4.44129 23.6839 5.20435 24 6 24H18C18.7956 24 19.5587 23.6839 20.1213 23.1213C20.6839 22.5587 21 21.7956 21 21V7.0605C20.9999 6.66271 20.8418 6.28124 20.5605 6L15 0.4395C14.7188 0.158176 14.3373 8.49561e-05 13.9395 0V0ZM14.25 5.25V2.25L18.75 6.75H15.75C15.3522 6.75 14.9706 6.59196 14.6893 6.31066C14.408 6.02936 14.25 5.64782 14.25 5.25ZM9.75 8.25V9.201L10.5735 8.7255C10.6588 8.67548 10.7532 8.64283 10.8512 8.62943C10.9492 8.61603 11.0489 8.62214 11.1445 8.64743C11.2401 8.67271 11.3298 8.71665 11.4084 8.77674C11.487 8.83682 11.5529 8.91185 11.6023 8.9975C11.6518 9.08316 11.6838 9.17776 11.6966 9.27584C11.7093 9.37393 11.7025 9.47357 11.6766 9.56902C11.6507 9.66447 11.6062 9.75386 11.5456 9.83203C11.4849 9.9102 11.4095 9.97561 11.3235 10.0245L10.5 10.5L11.3235 10.9755C11.4095 11.0244 11.4849 11.0898 11.5456 11.168C11.6062 11.2461 11.6507 11.3355 11.6766 11.431C11.7025 11.5264 11.7093 11.6261 11.6966 11.7242C11.6838 11.8222 11.6518 11.9168 11.6023 12.0025C11.5529 12.0882 11.487 12.1632 11.4084 12.2233C11.3298 12.2833 11.2401 12.3273 11.1445 12.3526C11.0489 12.3779 10.9492 12.384 10.8512 12.3706C10.7532 12.3572 10.6588 12.3245 10.5735 12.2745L9.75 11.799V12.75C9.75 12.9489 9.67098 13.1397 9.53033 13.2803C9.38968 13.421 9.19891 13.5 9 13.5C8.80109 13.5 8.61032 13.421 8.46967 13.2803C8.32902 13.1397 8.25 12.9489 8.25 12.75V11.799L7.4265 12.2745C7.34117 12.3245 7.24679 12.3572 7.14879 12.3706C7.0508 12.384 6.95111 12.3779 6.85549 12.3526C6.75987 12.3273 6.67019 12.2833 6.59162 12.2233C6.51304 12.1632 6.44713 12.0882 6.39768 12.0025C6.34822 11.9168 6.3162 11.8222 6.30345 11.7242C6.2907 11.6261 6.29748 11.5264 6.32339 11.431C6.34931 11.3355 6.39385 11.2461 6.45445 11.168C6.51505 11.0898 6.59052 11.0244 6.6765 10.9755L7.5 10.5L6.6765 10.0245C6.50565 9.92434 6.38134 9.76066 6.33072 9.56919C6.2801 9.37772 6.30727 9.174 6.40629 9.00248C6.50532 8.83096 6.66817 8.70558 6.8593 8.65369C7.05043 8.6018 7.25433 8.62761 7.4265 8.7255L8.25 9.201V8.25C8.25 8.05109 8.32902 7.86032 8.46967 7.71967C8.61032 7.57902 8.80109 7.5 9 7.5C9.19891 7.5 9.38968 7.57902 9.53033 7.71967C9.67098 7.86032 9.75 8.05109 9.75 8.25ZM6.75 15H14.25C14.4489 15 14.6397 15.079 14.7803 15.2197C14.921 15.3603 15 15.5511 15 15.75C15 15.9489 14.921 16.1397 14.7803 16.2803C14.6397 16.421 14.4489 16.5 14.25 16.5H6.75C6.55109 16.5 6.36032 16.421 6.21967 16.2803C6.07902 16.1397 6 15.9489 6 15.75C6 15.5511 6.07902 15.3603 6.21967 15.2197C6.36032 15.079 6.55109 15 6.75 15ZM6.75 18H14.25C14.4489 18 14.6397 18.079 14.7803 18.2197C14.921 18.3603 15 18.5511 15 18.75C15 18.9489 14.921 19.1397 14.7803 19.2803C14.6397 19.421 14.4489 19.5 14.25 19.5H6.75C6.55109 19.5 6.36032 19.421 6.21967 19.2803C6.07902 19.1397 6 18.9489 6 18.75C6 18.5511 6.07902 18.3603 6.21967 18.2197C6.36032 18.079 6.55109 18 6.75 18Z\"\n fill=\"white\"\n />\n </g>\n <defs>\n <clipPath id=\"clip0_952_64107\">\n <rect width=\"24\" height=\"24\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n);\n\nconst ErrorContainer = styled.div`\n position: relative;\n top: 0;\n padding-top: 4px;\n padding-bottom: 4px;\n padding-left: 8px;\n display: flex;\n width: 206px;\n color: #dc3545;\n font-family: Helvetica Neue;\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 150%;\n background-color: #25252a;\n border-radius: 2px;\n`;\n\nconst filterHtml = (message, emoji) => {\n if (!message) {\n return `<p>${emoji}</p>`;\n }\n const endingsToCheck = [\n '<br>',\n '<br></p>',\n '</p>',\n '</strong>',\n '<br></li></ul>',\n '</li></ul>',\n '</em>',\n '</u>',\n '<br></li></ol>',\n '</li></ol>',\n ];\n\n for (const ending of endingsToCheck) {\n if (message.endsWith(ending)) {\n const lastIndex = message.lastIndexOf(ending);\n return message.substring(0, lastIndex) + emoji + ending;\n }\n }\n};\n\nconst addEmojiToMessage = (emoji) => {\n const text = filterHtml(message, emoji);\n setMessage(text);\n};\nconst [accountData, setAccountData] = useState([]);\n\nconst debouncedFetchUsers = (value) => {\n setTimeout(\n () =>\n fetchAccounts(value.toLowerCase()).then((users) => {\n const accounts = users.map((account) => {\n return {\n id: account.id,\n active: account.active,\n };\n });\n setAccountData(accounts);\n }),\n 500,\n );\n};\n\nuseEffect(() => {\n const term = message.split('@').pop().split('<')[0];\n if (term) {\n debouncedFetchUsers(term);\n }\n}, [showAutocomplete]);\n\nreturn (\n <>\n {canWriteMessage && (\n <Container\n style={getCustomStyle(openThread, isThread)}\n key={openThread.id}\n >\n {/* <IconUpload\n onClick={() => {\n setError('');\n if (!uploadedFile.file.cid && !uploadedImage.file.cid) {\n setEmojiSelectorOpen(false);\n setShowUpload(!showUpload);\n }\n }}\n /> */}\n <Wrapper>\n <FullWidthWrapper>\n <ChatInputField\n setValue={setMessage}\n value={message}\n handleMessageSend={handleSendMessageFromLib}\n />\n {showAutocomplete && accountData.length > 0 && (\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.Chat.AutocompleteList`}\n props={{\n componentOwnerId,\n onSelect: autoCompleteAccountId,\n accountData,\n }}\n />\n )}\n </FullWidthWrapper>\n {(!message || emptyText.test(markdownParser(message))) && (\n <Placeholder placeholderPosition={placeholderPosition}>\n {openThread && isThread\n ? `Reply in thread`\n : `Type message in ${selectedChat}`}\n </Placeholder>\n )}\n\n {uploadedFile.file.cid && (\n <>\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.Chat.MessageFileField`}\n props={{\n file: uploadedFile.file,\n resetFile,\n }}\n />\n </>\n )}\n {uploadedImage.file.cid && (\n <>\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.Chat.MessageImageField`}\n props={{\n file: uploadedImage.file,\n resetImage,\n }}\n />\n </>\n )}\n </Wrapper>\n <div onClick={() => setEmojiSelectorOpen(!emojiSelectorOpen)}>\n <IconEmoji />\n </div>\n <IconSend\n onClick={() => {\n if (isActive) {\n handleSendMessage();\n }\n }}\n isActive={isActive}\n />\n {emojiSelectorOpen && (\n <EmojiPopupContainer>\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.EmojiSelector.EmojiSelector`}\n props={{\n OnEmojiSelected: (emoji) => addEmojiToMessage(emoji),\n }}\n key={'message-input-emoji-component'}\n />\n </EmojiPopupContainer>\n )}\n {showUpload && !uploadedFile.file.cid && !uploadedImage.file.cid && (\n <UploadPopupContainer>\n {error && <ErrorContainer>{error}</ErrorContainer>}\n <UploadContainer>\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.Chat.UploadComponent`}\n props={{\n uploadedFile: uploadedImage,\n setUploadedFile: setUploadedImage,\n type: ['image/jpeg', 'image/png', 'image/gif'],\n icon: <ImageIconSvg />,\n text: 'Upload Image',\n setError: setError,\n }}\n key=\"images-component\"\n />\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.Chat.UploadComponent`}\n props={{\n uploadedFile: uploadedFile,\n setUploadedFile: setUploadedFile,\n type: ['*/*'],\n icon: <FileIconSvg />,\n text: 'Upload File',\n setError: setError,\n }}\n key=\"files-component\"\n />\n </UploadContainer>\n </UploadPopupContainer>\n )}\n </Container>\n )}\n {!canWriteMessage && (\n <Container\n style={getCustomStyle(openThread, isThread)}\n key={openThread.id}\n >\n <ReadOnlyField>\n You don&apos;t have permissions to write in this channel\n </ReadOnlyField>\n </Container>\n )}\n </>\n);\n" }, "Calimero.Curb.Chat.ChatDisplaySplit": { "": "const componentOwnerId = props.componentOwnerId;\nconst readMessage = props.readMessage;\nconst handleReaction = props.handleReaction;\nconst openThread = props.openThread;\nconst setOpenThread = props.setOpenThread;\nconst activeChat = props.activeChat;\nconst curbApi = props.curbApi;\nconst accountId = props.accountId;\nconst incomingMessages = props.incomingMessages;\nconst updatedMessages = props.updatedMessages;\nconst resetImage = props.resetImage;\nconst sendMessage = props.sendMessage;\nconst getIconFromCache = props.getIconFromCache;\nconst isThread = props.isThread;\nconst isReadOnly = props.isReadOnly;\nconst toggleEmojiSelector = props.toggleEmojiSelector;\nconst channelMeta = props.channelMeta;\nconst channelUserList = props.channelUserList;\nconst setOpenMobileReactions = props.setOpenMobileReactions;\nconst openMobileReactions = props.openMobileReactions;\nconst onMessageDeletion = props.onMessageDeletion;\nconst onEditModeRequested = props.onEditModeRequested;\nconst onEditModeCancelled = props.onEditModeCancelled;\nconst onMessageUpdated = props.onMessageUpdated;\n\nconst ContainerPadding = styled.div`\n @media (max-width: 1024px) {\n height: calc(100vh - 160px) !important;\n padding-left: 0px !important;\n padding-right: 0px !important;\n }\n scrollbar-color: black black;\n ::-webkit-scrollbar {\n width: 6px;\n }\n ::-webkit-scrollbar-thumb {\n background-color: black;\n border-radius: 6px;\n }\n ::-webkit-scrollbar-thumb:hover {\n background-color: black;\n }\n * {\n scrollbar-color: black black;\n }\n html::-webkit-scrollbar {\n width: 12px;\n }\n html::-webkit-scrollbar-thumb {\n background-color: black;\n border-radius: 6px;\n }\n html::-webkit-scrollbar-thumb:hover {\n background-color: black;\n }\n`;\n\nconst ThreadTitle = styled.div`\n color: #fff;\n font-size: 24px;\n font-style: normal;\n font-weight: 500;\n line-height: 120%;\n`;\n\nconst ThreadContainer = styled.div`\n position: relative;\n padding-bottom: 20px;\n border-bottom: 2px solid #282933;\n display: flex;\n justify-content: space-between;\n @media (max-width: 1024px) {\n margin-right: 16px;\n padding-top: 104px;\n }\n`;\n\nconst CloseSvg = styled.svg`\n fill: #777583;\n :hover {\n fill: #fff;\n }\n cursor: pointer;\n`;\n\nconst Wrapper = styled.div`\n @media (max-width: 1024px) {\n width: 100% !important;\n }\n`;\n\nconst containerPaddingStyle = {\n display: 'flex',\n flexDirection: 'row',\n paddingTop: '1rem',\n paddingLeft: '2.5rem',\n paddingRight: '2.5rem',\n paddingBottom: '2.5rem',\n scrollBehavior: 'smooth',\n height: 'calc(100vh - 241px)',\n};\nconst chatStyle = {\n height: '',\n width: '',\n};\n\nconst wrapperStyle = {\n height: '100%',\n width: '100%',\n};\n\nconst CloseButtonSvg = ({ onClose }) => (\n <CloseSvg\n onClick={onClose}\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n className=\"bi bi-x-circle\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z\" />\n <path d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z\" />\n </CloseSvg>\n);\n\nconst ThreadHeader = ({ onClose }) => (\n <ThreadContainer>\n <ThreadTitle>Thread</ThreadTitle>\n <CloseButtonSvg onClose={onClose} />\n </ThreadContainer>\n);\n\nconst loadInitialMessages = () => {\n if (isThread && openThread.id) {\n return curbApi.fetchMessages({\n chat: activeChat,\n limit: 20,\n parentMessageId: openThread.id,\n });\n }\n return curbApi.fetchMessages({ chat: activeChat, limit: 20 });\n};\n\nconst loadPrevMessages = (id) => {\n if (isThread && id) {\n return curbApi.fetchMessages({\n chat: activeChat,\n beforeId: id,\n limit: 20,\n parentMessageId: openThread.id,\n });\n }\n return curbApi.fetchMessages({ chat: activeChat, beforeId: id, limit: 20 });\n};\n\nconst setThread = useCallback((message) => {\n setOpenThread(message);\n}, []);\n\nconst isModerator = useMemo(\n () =>\n channelUserList?.some(\n (user) => user.id === accountId && user.moderator === true,\n ),\n [channelUserList, accountId],\n);\n\nconst isOwner = accountId === channelMeta.createdBy;\n\nconst renderMessage = useMemo(\n () =>\n createMessageRenderer({\n handleReaction,\n getIconFromCache,\n accountId,\n isThread,\n openMobileReactions,\n setOpenMobileReactions,\n setThread: setThread ? setThread : undefined,\n toggleEmojiSelector,\n onEditModeRequested: onEditModeRequested,\n onEditModeCancelled: onEditModeCancelled,\n onMessageUpdated: onMessageUpdated,\n editable: () => false,\n deleteable: (message) => {\n if (message.sender === accountId) {\n return true;\n }\n return isOwner || isModerator;\n },\n onDeleteMessageRequested: (message) => {\n onMessageDeletion(message);\n },\n }),\n [accountId, isOwner, isModerator, openMobileReactions],\n);\n\nif (openThread && isThread) {\n chatStyle.height = 'calc(100% - 124px)';\n chatStyle.width = '100%';\n chatStyle['overflow'] = 'hidden';\n containerPaddingStyle.flexDirection = 'column';\n containerPaddingStyle.paddingLeft = '0px';\n containerPaddingStyle.height = '100%';\n containerPaddingStyle['width'] = '100%';\n wrapperStyle.width = '100%';\n} else if (openThread && !isThread) {\n chatStyle.height = '100%';\n chatStyle.width = '100%';\n containerPaddingStyle.paddingRight = '0px';\n wrapperStyle.width = '60%';\n} else {\n chatStyle.height = '100%';\n chatStyle.width = '100%';\n chatStyle['overflow'] = 'hidden';\n}\n\nreturn (\n <Wrapper style={wrapperStyle}>\n <ContainerPadding style={containerPaddingStyle}>\n {openThread && isThread && (\n <ThreadHeader\n openThread={openThread}\n onClose={() => setOpenThread(undefined)}\n />\n )}\n <VirtualizedChat\n loadInitialMessages={loadInitialMessages}\n loadPrevMessages={loadPrevMessages}\n incomingMessages={incomingMessages}\n updatedMessages={updatedMessages}\n onItemNewItemRender={readMessage}\n shouldTriggerNewItemIndicator={(message) =>\n message.sender !== accountId\n }\n render={renderMessage}\n chatId={isThread ? openThread.id : activeChat} // re-render the chat when the chat/thread changes\n style={chatStyle}\n />\n </ContainerPadding>\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.Chat.MessageInput`}\n props={{\n componentOwnerId,\n selectedChat:\n activeChat.type === 'channel' ? activeChat.name : activeChat.id,\n sendMessage: sendMessage,\n resetImage: resetImage,\n openThread,\n isThread,\n isReadOnly,\n isOwner,\n isModerator,\n fetchAccounts: (prefix) => {\n return curbApi.fetchAccounts({ prefix });\n },\n }}\n />\n </Wrapper>\n);\n" } } } } }

Transaction Execution Plan

Convert Transaction To Receipt
Gas Burned:
2 Tgas
Tokens Burned:
0.00025 
Receipt:
Predecessor ID:
Receiver ID:
Gas Burned:
11 Tgas
Tokens Burned:
0.0011 
Called method: 'set' in contract: social.near
Arguments:
{ "data": { "calimero-internal.near": { "widget": { "Calimero.Curb.Chat.MessageInput": { "": "const {\n componentOwnerId,\n selectedChat,\n sendMessage,\n openThread,\n isThread,\n isReadOnly,\n isOwner,\n isModerator,\n fetchAccounts,\n} = props;\n\nconst Container = styled.div`\n position: absolute;\n width: 100%;\n bottom: 16px;\n padding-left: 16px;\n padding-right: 16px;\n padding-top: 12px;\n padding-bottom: 12px;\n background-color: #1d1d21;\n display: flex;\n align-items: end;\n @media (min-width: 1025px) {\n gap: 8px;\n border-radius: 4px;\n }\n @media (max-width: 1024px) {\n position: fixed;\n margin: 0 !important;\n left: 0;\n right: 0;\n bottom: 0px;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n gap: 4px;\n margin: 0px;\n padding-left: 8px;\n padding-right: 8px;\n padding-bottom: 12px;\n padding-top: 12px;\n width: 100% !important;\n }\n`;\n\nconst EmojiPopupContainer = styled.div`\n position: absolute;\n bottom: 70px;\n right: 2.5rem;\n`;\n\nconst UploadPopupContainer = styled.div`\n position: absolute;\n bottom: 46px;\n left: 16px;\n @media (max-width: 1024px) {\n left: 8px;\n }\n`;\n\nconst UploadContainer = styled.div`\n background-color: #25252a;\n border-radius: 2px;\n width: fit-content;\n`;\n\nconst [showUpload, setShowUpload] = useState(false);\nconst [message, setMessage] = useState('');\n//Message is cleaned in Quill after it is returned to bos components so\n//this ref is setting value from callback to be used after sending with ENTER key\nconst messageRef = useRef(null);\nconst [uploadedFile, setUploadedFile] = useState(null);\nconst [uploadedImage, setUploadedImage] = useState(null);\nconst [emojiSelectorOpen, setEmojiSelectorOpen] = useState(false);\nconst [error, setError] = useState('');\nconst [sendFromLib, setSendFromLib] = useState(false);\n\nconst handleMessageChange = useCallback((mesage) => {\n setMessage(mesage);\n}, []);\n\nconst resetFile = useCallback(() => {\n setUploadedFile(null);\n setShowUpload(false);\n}, []);\n\nconst resetImage = useCallback(() => {\n setUploadedImage(null);\n setShowUpload(false);\n}, []);\n\nconst emptyText = /^(\\s*<p><br><\\/p>\\s*)*$/;\nconst markdownParser = (text) => {\n const toHTML = text.replace(\n /(\\b(https?:\\/\\/[^\\s<]+\\/?)\\b)|^(#####|####|###|##|#) (.*)$|(@everyone)|(@here)|(@[a-z\\d]+[-_]*[a-z\\d]+[-_]*[a-z\\d]+\\.(near|testnet))|<p><br><\\/p>(?=\\s*$)/gim,\n (\n match,\n url,\n url2,\n heading,\n text,\n everyoneMention,\n hereMention,\n validMention,\n ) => {\n if (url || url2) {\n return `<a href=\"${url || url2}\" class=\"url-link\" target=\"_blank\">${\n url || url2\n }</a>`;\n } else if (heading) {\n return text;\n } else if (everyoneMention) {\n return `<span class='mention-everyone'>@everyone</span>`;\n } else if (hereMention) {\n return `<span class='mention-here'>@here</span>`;\n } else if (validMention) {\n return `<span class='mention mention-user-${validMention\n .replace('@', '')\n .replace(/\\./g, '\\\\.')\n .replace(/_/g, '\\\\_')}'>${validMention}</span>`;\n } else {\n return '';\n }\n },\n );\n\n return toHTML;\n};\n\nconst isActive =\n (message && !emptyText.test(markdownParser(message))) ||\n uploadedImage ||\n uploadedFile;\n\nconst handleSendMessage = useCallback(\n (vmValue) => {\n const messageToSend = vmValue || message;\n if (\n (uploadedFile && !uploadedFile.file.cid) ||\n (uploadedImage && !uploadedImage.file.cid)\n ) {\n return;\n } else if (\n emptyText.test(markdownParser(messageToSend)) &&\n !uploadedImage &&\n !uploadedFile\n ) {\n handleMessageChange('');\n messageRef.current = '';\n } else {\n sendMessage(\n markdownParser(messageToSend),\n uploadedImage,\n selectedChat,\n uploadedFile,\n openThread,\n );\n resetImage();\n resetFile();\n setShowUpload(false);\n setEmojiSelectorOpen(false);\n handleMessageChange('');\n messageRef.current = '';\n }\n },\n [message, uploadedImage, uploadedFile, openThread, selectedChat],\n);\n\nuseEffect(() => {\n if (sendFromLib) {\n handleSendMessage(messageRef.current);\n setSendFromLib(false);\n }\n}, [sendFromLib]);\n\n//Hack for https://stackoverflow.com/questions/57847594/react-hooks-accessing-up-to-date-state-from-within-a-callback\n//as passed handleSendMessage to input field component use staled useState values\nconst handleSendMessageFromLib = (value) => {\n messageRef.current = value;\n setSendFromLib(true);\n};\n\nconst Wrapper = styled.div`\n flex-grow: 1;\n display: contents;\n align-items: start;\n background-color: #111111;\n`;\n\nconst FullWidthWrapper = styled.div`\n display: flow;\n flex-direction: row;\n overflow: hidden;\n align-items: start;\n width: 100%;\n`;\n\n// const IconUploadWrapper = styled.div`\n// height: 34px;\n// width: 34px;\n// padding: 8px;\n// display: flex;\n// justify-content: center;\n// border-radius: 2px;\n// align-items: center;\n// :hover {\n// background-color: #686672;\n// fill: #fff;\n// }\n// cursor: pointer;\n// fill: #686672;\n// `;\n\n// const IconUpload = ({ onClick }) => (\n// <IconUploadWrapper>\n// <svg\n// onClick={onClick}\n// xmlns=\"http://www.w3.org/2000/svg\"\n// width=\"18\"\n// height=\"18\"\n// className=\"bi bi-plus-circle\"\n// viewBox=\"0 0 16 16\"\n// >\n// <path d=\"M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z\" />\n// <path d=\"M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z\" />\n// </svg>\n// </IconUploadWrapper>\n// );\n\nconst EmojiContainer = styled.div`\n border-radius: 2px;\n margin-bottom: 4px;\n height: 26px;\n width: 26px;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 2px;\n cursor: pointer;\n\n .hidden-svg {\n visibility: hidden;\n position: absolute;\n z-index: -10;\n }\n\n .visible-svg {\n visibility: visible;\n }\n`;\n\nconst IconEmoji = () => {\n const [hovered, setHovered] = useState(false);\n\n return (\n <EmojiContainer\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n fill=\"#686672\"\n className={`bi bi-emoji-wink ${hovered ? 'hidden-svg' : 'visible-svg'}`}\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z\" />\n <path d=\"M4.285 9.567a.5.5 0 0 1 .683.183A3.498 3.498 0 0 0 8 11.5a3.498 3.498 0 0 0 3.032-1.75.5.5 0 1 1 .866.5A4.498 4.498 0 0 1 8 12.5a4.498 4.498 0 0 1-3.898-2.25.5.5 0 0 1 .183-.683zM7 6.5C7 7.328 6.552 8 6 8s-1-.672-1-1.5S5.448 5 6 5s1 .672 1 1.5zm1.757-.437a.5.5 0 0 1 .68.194.934.934 0 0 0 .813.493c.339 0 .645-.19.813-.493a.5.5 0 1 1 .874.486A1.934 1.934 0 0 1 10.25 7.75c-.73 0-1.356-.412-1.687-1.007a.5.5 0 0 1 .194-.68z\" />\n </svg>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n fill=\"#FFDD1D\"\n className={`bi bi-emoji-wink-fill ${\n hovered ? 'visible-svg' : 'hidden-svg'\n }`}\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0zM7 6.5C7 5.672 6.552 5 6 5s-1 .672-1 1.5S5.448 8 6 8s1-.672 1-1.5zM4.285 9.567a.5.5 0 0 0-.183.683A4.498 4.498 0 0 0 8 12.5a4.5 4.5 0 0 0 3.898-2.25.5.5 0 1 0-.866-.5A3.498 3.498 0 0 1 8 11.5a3.498 3.498 0 0 1-3.032-1.75.5.5 0 0 0-.683-.183zm5.152-3.31a.5.5 0 0 0-.874.486c.33.595.958 1.007 1.687 1.007.73 0 1.356-.412 1.687-1.007a.5.5 0 0 0-.874-.486.934.934 0 0 1-.813.493.934.934 0 0 1-.813-.493z\" />\n </svg>\n </EmojiContainer>\n );\n};\n\nconst IconSendSvg = styled.svg`\n margin-bottom: 8px;\n :hover {\n fill: #4e95ff;\n }\n cursor: pointer;\n`;\nconst IconSend = ({ onClick, isActive }) => (\n <IconSendSvg\n onClick={onClick}\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n fill={`${isActive ? '#4E95FF' : '#686672'}`}\n className=\"bi bi-send-fill\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M15.964.686a.5.5 0 0 0-.65-.65L.767 5.855H.766l-.452.18a.5.5 0 0 0-.082.887l.41.26.001.002 4.995 3.178 3.178 4.995.002.002.26.41a.5.5 0 0 0 .886-.083l6-15Zm-1.833 1.89L6.637 10.07l-.215-.338a.5.5 0 0 0-.154-.154l-.338-.215 7.494-7.494 1.178-.471-.47 1.178Z\" />\n </IconSendSvg>\n);\n\nconst Placeholder = styled.div`\n position: absolute;\n z-index: 10;\n bottom: ${({ placeholderPosition }) =>\n placeholderPosition && placeholderPosition};\n left: 68px;\n color: #686672;\n font-size: 16px;\n font-style: normal;\n font-weight: 400;\n line-height: 150%;\n pointer-events: none;\n @media (max-width: 1024px) {\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 150%;\n bottom: ${({ placeholderPositionMobile }) =>\n placeholderPositionMobile && placeholderPositionMobile};\n left: 56px;\n }\n`;\n\nconst getCustomStyle = (openThread) => {\n const customStyle = {\n width: 'calc(100% - 440px)',\n marginLeft: '2.5rem',\n marginRight: '2.5rem',\n };\n if (openThread && !isThread) {\n customStyle.width = 'calc(60% - 262px)';\n customStyle.marginRight = '1.25rem';\n } else if (!openThread && !isThread) {\n customStyle.width = 'calc(100% - 440px)';\n } else if (openThread && isThread) {\n customStyle.width = 'calc(40% - 212px)';\n customStyle.marginLeft = '0rem';\n customStyle.marginRight = '1.25rem';\n }\n return customStyle;\n};\n\nconst ReadOnlyField = styled.div`\n background-color: #111111;\n height: 2rem;\n border-radius: 4px;\n padding: 4px 8px 4px 8px;\n font-family: Helvetica Neue;\n font-size: 16px;\n font-style: normal;\n font-weight: 400;\n line-height: 150%;\n color: #797978;\n flex: 1;\n @media (max-width: 1024px) {\n font-size: 14px;\n display: flex;\n align-items: center;\n }\n`;\n\nlet canWriteMessage = false;\nif (isReadOnly) {\n if (isModerator || isOwner) {\n canWriteMessage = true;\n } else {\n canWriteMessage = false;\n }\n} else {\n canWriteMessage = true;\n}\n\nlet placeholderPosition = '16px';\nif (uploadedFile.file.cid) {\n placeholderPosition = '61px';\n} else if (uploadedImage.file.cid) {\n placeholderPosition = '86px';\n}\n\nconst [showAutocomplete, setShowAutocomplete] = useState(false);\n\nconst autoCompleteAccountId = (accountId) => {\n let text = message.replace(/[\\s]{0,1}@[^\\s]*$/, '');\n text = `${text} @${accountId}`.trim() + ' \\u200B';\n setMessage(text);\n setShowAutocomplete(false);\n};\n\nuseEffect(() => {\n const showAccountAutocomplete = /@[\\w][^\\s]*$/.test(message);\n setShowAutocomplete(showAccountAutocomplete);\n}, [message]);\n\nconst ImageIconSvg = () => (\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"#fff\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M15.75 12.75C15.75 13.7446 15.3549 14.6984 14.6517 15.4017C13.9484 16.1049 12.9946 16.5 12 16.5C11.0054 16.5 10.0516 16.1049 9.34835 15.4017C8.64509 14.6984 8.25 13.7446 8.25 12.75C8.25 11.7554 8.64509 10.8016 9.34835 10.0983C10.0516 9.39509 11.0054 9 12 9C12.9946 9 13.9484 9.39509 14.6517 10.0983C15.3549 10.8016 15.75 11.7554 15.75 12.75Z\"\n fill=\"white\"\n />\n <path\n d=\"M3 6C2.20435 6 1.44129 6.31607 0.87868 6.87868C0.316071 7.44129 0 8.20435 0 9V18C0 18.7956 0.316071 19.5587 0.87868 20.1213C1.44129 20.6839 2.20435 21 3 21H21C21.7956 21 22.5587 20.6839 23.1213 20.1213C23.6839 19.5587 24 18.7956 24 18V9C24 8.20435 23.6839 7.44129 23.1213 6.87868C22.5587 6.31607 21.7956 6 21 6H19.242C18.4464 5.99983 17.6835 5.68365 17.121 5.121L15.879 3.879C15.3165 3.31635 14.5536 3.00017 13.758 3H10.242C9.44641 3.00017 8.68348 3.31635 8.121 3.879L6.879 5.121C6.31652 5.68365 5.55358 5.99983 4.758 6H3ZM3.75 9C3.55109 9 3.36032 8.92098 3.21967 8.78033C3.07902 8.63968 3 8.44891 3 8.25C3 8.05109 3.07902 7.86032 3.21967 7.71967C3.36032 7.57902 3.55109 7.5 3.75 7.5C3.94891 7.5 4.13968 7.57902 4.28033 7.71967C4.42098 7.86032 4.5 8.05109 4.5 8.25C4.5 8.44891 4.42098 8.63968 4.28033 8.78033C4.13968 8.92098 3.94891 9 3.75 9ZM17.25 12.75C17.25 14.1424 16.6969 15.4777 15.7123 16.4623C14.7277 17.4469 13.3924 18 12 18C10.6076 18 9.27226 17.4469 8.28769 16.4623C7.30312 15.4777 6.75 14.1424 6.75 12.75C6.75 11.3576 7.30312 10.0223 8.28769 9.03769C9.27226 8.05312 10.6076 7.5 12 7.5C13.3924 7.5 14.7277 8.05312 15.7123 9.03769C16.6969 10.0223 17.25 11.3576 17.25 12.75Z\"\n fill=\"white\"\n />\n </svg>\n);\n\nconst FileIconSvg = () => (\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"#fff\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <g clipPath=\"url(#clip0_952_64107)\">\n <path\n d=\"M13.9395 0H6C5.20435 0 4.44129 0.316071 3.87868 0.87868C3.31607 1.44129 3 2.20435 3 3V21C3 21.7956 3.31607 22.5587 3.87868 23.1213C4.44129 23.6839 5.20435 24 6 24H18C18.7956 24 19.5587 23.6839 20.1213 23.1213C20.6839 22.5587 21 21.7956 21 21V7.0605C20.9999 6.66271 20.8418 6.28124 20.5605 6L15 0.4395C14.7188 0.158176 14.3373 8.49561e-05 13.9395 0V0ZM14.25 5.25V2.25L18.75 6.75H15.75C15.3522 6.75 14.9706 6.59196 14.6893 6.31066C14.408 6.02936 14.25 5.64782 14.25 5.25ZM9.75 8.25V9.201L10.5735 8.7255C10.6588 8.67548 10.7532 8.64283 10.8512 8.62943C10.9492 8.61603 11.0489 8.62214 11.1445 8.64743C11.2401 8.67271 11.3298 8.71665 11.4084 8.77674C11.487 8.83682 11.5529 8.91185 11.6023 8.9975C11.6518 9.08316 11.6838 9.17776 11.6966 9.27584C11.7093 9.37393 11.7025 9.47357 11.6766 9.56902C11.6507 9.66447 11.6062 9.75386 11.5456 9.83203C11.4849 9.9102 11.4095 9.97561 11.3235 10.0245L10.5 10.5L11.3235 10.9755C11.4095 11.0244 11.4849 11.0898 11.5456 11.168C11.6062 11.2461 11.6507 11.3355 11.6766 11.431C11.7025 11.5264 11.7093 11.6261 11.6966 11.7242C11.6838 11.8222 11.6518 11.9168 11.6023 12.0025C11.5529 12.0882 11.487 12.1632 11.4084 12.2233C11.3298 12.2833 11.2401 12.3273 11.1445 12.3526C11.0489 12.3779 10.9492 12.384 10.8512 12.3706C10.7532 12.3572 10.6588 12.3245 10.5735 12.2745L9.75 11.799V12.75C9.75 12.9489 9.67098 13.1397 9.53033 13.2803C9.38968 13.421 9.19891 13.5 9 13.5C8.80109 13.5 8.61032 13.421 8.46967 13.2803C8.32902 13.1397 8.25 12.9489 8.25 12.75V11.799L7.4265 12.2745C7.34117 12.3245 7.24679 12.3572 7.14879 12.3706C7.0508 12.384 6.95111 12.3779 6.85549 12.3526C6.75987 12.3273 6.67019 12.2833 6.59162 12.2233C6.51304 12.1632 6.44713 12.0882 6.39768 12.0025C6.34822 11.9168 6.3162 11.8222 6.30345 11.7242C6.2907 11.6261 6.29748 11.5264 6.32339 11.431C6.34931 11.3355 6.39385 11.2461 6.45445 11.168C6.51505 11.0898 6.59052 11.0244 6.6765 10.9755L7.5 10.5L6.6765 10.0245C6.50565 9.92434 6.38134 9.76066 6.33072 9.56919C6.2801 9.37772 6.30727 9.174 6.40629 9.00248C6.50532 8.83096 6.66817 8.70558 6.8593 8.65369C7.05043 8.6018 7.25433 8.62761 7.4265 8.7255L8.25 9.201V8.25C8.25 8.05109 8.32902 7.86032 8.46967 7.71967C8.61032 7.57902 8.80109 7.5 9 7.5C9.19891 7.5 9.38968 7.57902 9.53033 7.71967C9.67098 7.86032 9.75 8.05109 9.75 8.25ZM6.75 15H14.25C14.4489 15 14.6397 15.079 14.7803 15.2197C14.921 15.3603 15 15.5511 15 15.75C15 15.9489 14.921 16.1397 14.7803 16.2803C14.6397 16.421 14.4489 16.5 14.25 16.5H6.75C6.55109 16.5 6.36032 16.421 6.21967 16.2803C6.07902 16.1397 6 15.9489 6 15.75C6 15.5511 6.07902 15.3603 6.21967 15.2197C6.36032 15.079 6.55109 15 6.75 15ZM6.75 18H14.25C14.4489 18 14.6397 18.079 14.7803 18.2197C14.921 18.3603 15 18.5511 15 18.75C15 18.9489 14.921 19.1397 14.7803 19.2803C14.6397 19.421 14.4489 19.5 14.25 19.5H6.75C6.55109 19.5 6.36032 19.421 6.21967 19.2803C6.07902 19.1397 6 18.9489 6 18.75C6 18.5511 6.07902 18.3603 6.21967 18.2197C6.36032 18.079 6.55109 18 6.75 18Z\"\n fill=\"white\"\n />\n </g>\n <defs>\n <clipPath id=\"clip0_952_64107\">\n <rect width=\"24\" height=\"24\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n);\n\nconst ErrorContainer = styled.div`\n position: relative;\n top: 0;\n padding-top: 4px;\n padding-bottom: 4px;\n padding-left: 8px;\n display: flex;\n width: 206px;\n color: #dc3545;\n font-family: Helvetica Neue;\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 150%;\n background-color: #25252a;\n border-radius: 2px;\n`;\n\nconst filterHtml = (message, emoji) => {\n if (!message) {\n return `<p>${emoji}</p>`;\n }\n const endingsToCheck = [\n '<br>',\n '<br></p>',\n '</p>',\n '</strong>',\n '<br></li></ul>',\n '</li></ul>',\n '</em>',\n '</u>',\n '<br></li></ol>',\n '</li></ol>',\n ];\n\n for (const ending of endingsToCheck) {\n if (message.endsWith(ending)) {\n const lastIndex = message.lastIndexOf(ending);\n return message.substring(0, lastIndex) + emoji + ending;\n }\n }\n};\n\nconst addEmojiToMessage = (emoji) => {\n const text = filterHtml(message, emoji);\n setMessage(text);\n};\nconst [accountData, setAccountData] = useState([]);\n\nconst debouncedFetchUsers = (value) => {\n setTimeout(\n () =>\n fetchAccounts(value.toLowerCase()).then((users) => {\n const accounts = users.map((account) => {\n return {\n id: account.id,\n active: account.active,\n };\n });\n setAccountData(accounts);\n }),\n 500,\n );\n};\n\nuseEffect(() => {\n const term = message.split('@').pop().split('<')[0];\n if (term) {\n debouncedFetchUsers(term);\n }\n}, [showAutocomplete]);\n\nreturn (\n <>\n {canWriteMessage && (\n <Container\n style={getCustomStyle(openThread, isThread)}\n key={openThread.id}\n >\n {/* <IconUpload\n onClick={() => {\n setError('');\n if (!uploadedFile.file.cid && !uploadedImage.file.cid) {\n setEmojiSelectorOpen(false);\n setShowUpload(!showUpload);\n }\n }}\n /> */}\n <Wrapper>\n <FullWidthWrapper>\n <ChatInputField\n setValue={setMessage}\n value={message}\n handleMessageSend={handleSendMessageFromLib}\n />\n {showAutocomplete && accountData.length > 0 && (\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.Chat.AutocompleteList`}\n props={{\n componentOwnerId,\n onSelect: autoCompleteAccountId,\n accountData,\n }}\n />\n )}\n </FullWidthWrapper>\n {(!message || emptyText.test(markdownParser(message))) && (\n <Placeholder placeholderPosition={placeholderPosition}>\n {openThread && isThread\n ? `Reply in thread`\n : `Type message in ${selectedChat}`}\n </Placeholder>\n )}\n\n {uploadedFile.file.cid && (\n <>\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.Chat.MessageFileField`}\n props={{\n file: uploadedFile.file,\n resetFile,\n }}\n />\n </>\n )}\n {uploadedImage.file.cid && (\n <>\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.Chat.MessageImageField`}\n props={{\n file: uploadedImage.file,\n resetImage,\n }}\n />\n </>\n )}\n </Wrapper>\n <div onClick={() => setEmojiSelectorOpen(!emojiSelectorOpen)}>\n <IconEmoji />\n </div>\n <IconSend\n onClick={() => {\n if (isActive) {\n handleSendMessage();\n }\n }}\n isActive={isActive}\n />\n {emojiSelectorOpen && (\n <EmojiPopupContainer>\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.EmojiSelector.EmojiSelector`}\n props={{\n OnEmojiSelected: (emoji) => addEmojiToMessage(emoji),\n }}\n key={'message-input-emoji-component'}\n />\n </EmojiPopupContainer>\n )}\n {showUpload && !uploadedFile.file.cid && !uploadedImage.file.cid && (\n <UploadPopupContainer>\n {error && <ErrorContainer>{error}</ErrorContainer>}\n <UploadContainer>\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.Chat.UploadComponent`}\n props={{\n uploadedFile: uploadedImage,\n setUploadedFile: setUploadedImage,\n type: ['image/jpeg', 'image/png', 'image/gif'],\n icon: <ImageIconSvg />,\n text: 'Upload Image',\n setError: setError,\n }}\n key=\"images-component\"\n />\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.Chat.UploadComponent`}\n props={{\n uploadedFile: uploadedFile,\n setUploadedFile: setUploadedFile,\n type: ['*/*'],\n icon: <FileIconSvg />,\n text: 'Upload File',\n setError: setError,\n }}\n key=\"files-component\"\n />\n </UploadContainer>\n </UploadPopupContainer>\n )}\n </Container>\n )}\n {!canWriteMessage && (\n <Container\n style={getCustomStyle(openThread, isThread)}\n key={openThread.id}\n >\n <ReadOnlyField>\n You don&apos;t have permissions to write in this channel\n </ReadOnlyField>\n </Container>\n )}\n </>\n);\n" }, "Calimero.Curb.Chat.ChatDisplaySplit": { "": "const componentOwnerId = props.componentOwnerId;\nconst readMessage = props.readMessage;\nconst handleReaction = props.handleReaction;\nconst openThread = props.openThread;\nconst setOpenThread = props.setOpenThread;\nconst activeChat = props.activeChat;\nconst curbApi = props.curbApi;\nconst accountId = props.accountId;\nconst incomingMessages = props.incomingMessages;\nconst updatedMessages = props.updatedMessages;\nconst resetImage = props.resetImage;\nconst sendMessage = props.sendMessage;\nconst getIconFromCache = props.getIconFromCache;\nconst isThread = props.isThread;\nconst isReadOnly = props.isReadOnly;\nconst toggleEmojiSelector = props.toggleEmojiSelector;\nconst channelMeta = props.channelMeta;\nconst channelUserList = props.channelUserList;\nconst setOpenMobileReactions = props.setOpenMobileReactions;\nconst openMobileReactions = props.openMobileReactions;\nconst onMessageDeletion = props.onMessageDeletion;\nconst onEditModeRequested = props.onEditModeRequested;\nconst onEditModeCancelled = props.onEditModeCancelled;\nconst onMessageUpdated = props.onMessageUpdated;\n\nconst ContainerPadding = styled.div`\n @media (max-width: 1024px) {\n height: calc(100vh - 160px) !important;\n padding-left: 0px !important;\n padding-right: 0px !important;\n }\n scrollbar-color: black black;\n ::-webkit-scrollbar {\n width: 6px;\n }\n ::-webkit-scrollbar-thumb {\n background-color: black;\n border-radius: 6px;\n }\n ::-webkit-scrollbar-thumb:hover {\n background-color: black;\n }\n * {\n scrollbar-color: black black;\n }\n html::-webkit-scrollbar {\n width: 12px;\n }\n html::-webkit-scrollbar-thumb {\n background-color: black;\n border-radius: 6px;\n }\n html::-webkit-scrollbar-thumb:hover {\n background-color: black;\n }\n`;\n\nconst ThreadTitle = styled.div`\n color: #fff;\n font-size: 24px;\n font-style: normal;\n font-weight: 500;\n line-height: 120%;\n`;\n\nconst ThreadContainer = styled.div`\n position: relative;\n padding-bottom: 20px;\n border-bottom: 2px solid #282933;\n display: flex;\n justify-content: space-between;\n @media (max-width: 1024px) {\n margin-right: 16px;\n padding-top: 104px;\n }\n`;\n\nconst CloseSvg = styled.svg`\n fill: #777583;\n :hover {\n fill: #fff;\n }\n cursor: pointer;\n`;\n\nconst Wrapper = styled.div`\n @media (max-width: 1024px) {\n width: 100% !important;\n }\n`;\n\nconst containerPaddingStyle = {\n display: 'flex',\n flexDirection: 'row',\n paddingTop: '1rem',\n paddingLeft: '2.5rem',\n paddingRight: '2.5rem',\n paddingBottom: '2.5rem',\n scrollBehavior: 'smooth',\n height: 'calc(100vh - 241px)',\n};\nconst chatStyle = {\n height: '',\n width: '',\n};\n\nconst wrapperStyle = {\n height: '100%',\n width: '100%',\n};\n\nconst CloseButtonSvg = ({ onClose }) => (\n <CloseSvg\n onClick={onClose}\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n className=\"bi bi-x-circle\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z\" />\n <path d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z\" />\n </CloseSvg>\n);\n\nconst ThreadHeader = ({ onClose }) => (\n <ThreadContainer>\n <ThreadTitle>Thread</ThreadTitle>\n <CloseButtonSvg onClose={onClose} />\n </ThreadContainer>\n);\n\nconst loadInitialMessages = () => {\n if (isThread && openThread.id) {\n return curbApi.fetchMessages({\n chat: activeChat,\n limit: 20,\n parentMessageId: openThread.id,\n });\n }\n return curbApi.fetchMessages({ chat: activeChat, limit: 20 });\n};\n\nconst loadPrevMessages = (id) => {\n if (isThread && id) {\n return curbApi.fetchMessages({\n chat: activeChat,\n beforeId: id,\n limit: 20,\n parentMessageId: openThread.id,\n });\n }\n return curbApi.fetchMessages({ chat: activeChat, beforeId: id, limit: 20 });\n};\n\nconst setThread = useCallback((message) => {\n setOpenThread(message);\n}, []);\n\nconst isModerator = useMemo(\n () =>\n channelUserList?.some(\n (user) => user.id === accountId && user.moderator === true,\n ),\n [channelUserList, accountId],\n);\n\nconst isOwner = accountId === channelMeta.createdBy;\n\nconst renderMessage = useMemo(\n () =>\n createMessageRenderer({\n handleReaction,\n getIconFromCache,\n accountId,\n isThread,\n openMobileReactions,\n setOpenMobileReactions,\n setThread: setThread ? setThread : undefined,\n toggleEmojiSelector,\n onEditModeRequested: onEditModeRequested,\n onEditModeCancelled: onEditModeCancelled,\n onMessageUpdated: onMessageUpdated,\n editable: () => false,\n deleteable: (message) => {\n if (message.sender === accountId) {\n return true;\n }\n return isOwner || isModerator;\n },\n onDeleteMessageRequested: (message) => {\n onMessageDeletion(message);\n },\n }),\n [accountId, isOwner, isModerator, openMobileReactions],\n);\n\nif (openThread && isThread) {\n chatStyle.height = 'calc(100% - 124px)';\n chatStyle.width = '100%';\n chatStyle['overflow'] = 'hidden';\n containerPaddingStyle.flexDirection = 'column';\n containerPaddingStyle.paddingLeft = '0px';\n containerPaddingStyle.height = '100%';\n containerPaddingStyle['width'] = '100%';\n wrapperStyle.width = '100%';\n} else if (openThread && !isThread) {\n chatStyle.height = '100%';\n chatStyle.width = '100%';\n containerPaddingStyle.paddingRight = '0px';\n wrapperStyle.width = '60%';\n} else {\n chatStyle.height = '100%';\n chatStyle.width = '100%';\n chatStyle['overflow'] = 'hidden';\n}\n\nreturn (\n <Wrapper style={wrapperStyle}>\n <ContainerPadding style={containerPaddingStyle}>\n {openThread && isThread && (\n <ThreadHeader\n openThread={openThread}\n onClose={() => setOpenThread(undefined)}\n />\n )}\n <VirtualizedChat\n loadInitialMessages={loadInitialMessages}\n loadPrevMessages={loadPrevMessages}\n incomingMessages={incomingMessages}\n updatedMessages={updatedMessages}\n onItemNewItemRender={readMessage}\n shouldTriggerNewItemIndicator={(message) =>\n message.sender !== accountId\n }\n render={renderMessage}\n chatId={isThread ? openThread.id : activeChat} // re-render the chat when the chat/thread changes\n style={chatStyle}\n />\n </ContainerPadding>\n <Widget\n src={`${componentOwnerId}/widget/Calimero.Curb.Chat.MessageInput`}\n props={{\n componentOwnerId,\n selectedChat:\n activeChat.type === 'channel' ? activeChat.name : activeChat.id,\n sendMessage: sendMessage,\n resetImage: resetImage,\n openThread,\n isThread,\n isReadOnly,\n isOwner,\n isModerator,\n fetchAccounts: (prefix) => {\n return curbApi.fetchAccounts({ prefix });\n },\n }}\n />\n </Wrapper>\n);\n" } } } } }
Empty result
No logs
Receipt:
Predecessor ID:
Gas Burned:
223 Ggas
Tokens Burned:
0 
Transferred 0.18797  to calimero-deployer.near
Empty result
No logs