diff --git a/qortal-ui-core/font/KoHo.ttf b/qortal-ui-core/font/KoHo.ttf new file mode 100644 index 00000000..72841e9d Binary files /dev/null and b/qortal-ui-core/font/KoHo.ttf differ diff --git a/qortal-ui-core/font/Livvic.ttf b/qortal-ui-core/font/Livvic.ttf new file mode 100644 index 00000000..f477b285 Binary files /dev/null and b/qortal-ui-core/font/Livvic.ttf differ diff --git a/qortal-ui-core/font/Montserrat.ttf b/qortal-ui-core/font/Montserrat.ttf new file mode 100644 index 00000000..656db666 Binary files /dev/null and b/qortal-ui-core/font/Montserrat.ttf differ diff --git a/qortal-ui-core/font/material-icons.css b/qortal-ui-core/font/material-icons.css index 2270c09d..422f0fa1 100644 --- a/qortal-ui-core/font/material-icons.css +++ b/qortal-ui-core/font/material-icons.css @@ -2,19 +2,42 @@ font-family: 'Material Icons'; font-style: normal; font-weight: 400; - src: url(MaterialIcons-Regular.eot); /* For IE6-8 */ + src: url(MaterialIcons-Regular.eot); + /* For IE6-8 */ src: local('Material Icons'), - local('MaterialIcons-Regular'), - url(MaterialIcons-Regular.woff2) format('woff2'), - url(MaterialIcons-Regular.woff) format('woff'), - url(MaterialIcons-Regular.ttf) format('truetype'); + local('MaterialIcons-Regular'), + url(MaterialIcons-Regular.woff2) format('woff2'), + url(MaterialIcons-Regular.woff) format('woff'), + url(MaterialIcons-Regular.ttf) format('truetype'); +} + +@font-face { + font-family: 'Montserrat'; + src: local('Montserrat'), + local('Montserrat'), + url(Montserrat.ttf) format('truetype'); +} + +@font-face { + font-family: 'KoHo'; + src: local('KoHo'), + local('KoHo'), + url(KoHo.ttf) format('truetype'); +} + +@font-face { + font-family: 'Livvic'; + src: local('Livvic'), + local('Livvic'), + url(Livvic.ttf) format('truetype'); } .material-icons { font-family: 'Material Icons'; font-weight: normal; font-style: normal; - font-size: 24px; /* Preferred icon size */ + font-size: 24px; + /* Preferred icon size */ display: inline-block; line-height: 1; text-transform: none; @@ -33,4 +56,4 @@ /* Support for IE. */ font-feature-settings: 'liga'; -} +} \ No newline at end of file diff --git a/qortal-ui-core/language/us.json b/qortal-ui-core/language/us.json index c2bc9565..265fd645 100644 --- a/qortal-ui-core/language/us.json +++ b/qortal-ui-core/language/us.json @@ -465,8 +465,8 @@ "cchange3": "Blocked Users", "cchange4": "New Message", "cchange5": "(Click to scroll down)", - "cchange6": "Type the name or address of who you want to chat with to send a private message!", - "cchange7": "Name / Address", + "cchange6": "Type the name or address of who you want to chat with to send a private message! You can validate the person's name by clicking on the book icon.", + "cchange7": "Username / Address", "cchange8": "Message...", "cchange9": "Send", "cchange10": "Blocked Users List", @@ -478,7 +478,7 @@ "cchange16": "Successfully unblocked this user.", "cchange17": "Error occurred when trying to unblock this user. Please try again!", "cchange18": "unblock", - "cchange19": "Invalid Name / Address, Check the name / address and retry...", + "cchange19": "Invalid Username / Address, Check the name / address and retry...", "cchange20": "Message Sent Successfully!", "cchange21": "Sending failed, Please retry...", "cchange22": "Loading Messages...", @@ -492,7 +492,11 @@ "cchange30": "Uploading image. This may take up to one minute.", "cchange31": "Deleting image. This may take up to one minute.", "cchange33": "Cancel", - "cchange34": "This chat message is using an older message version and cannot use this feature." + "cchange34": "This chat message is using an older message version and cannot use this feature.", + "cchange35": "Error when trying to fetch the user's name. Please try again!", + "cchange36": "Search Results", + "cchange37": "No Results Found", + "cchange38": "User Verified" }, "welcomepage": { "wcchange1": "Welcome to Q-Chat", @@ -521,7 +525,7 @@ "bcchange13": "Reaction", "bcchange14": "Forward", "bcchange15": "Message Forwarded", - "bcchange16": "Choose recipient", + "bcchange16": "Choose Recipient or Search for One Below", "bcchange17": "FORWARDED" }, "grouppage": { diff --git a/qortal-ui-plugins/plugins/core/components/ChatPage.js b/qortal-ui-plugins/plugins/core/components/ChatPage.js index fbb48b94..9e33352c 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatPage.js +++ b/qortal-ui-plugins/plugins/core/components/ChatPage.js @@ -14,19 +14,19 @@ import './ChatScroller.js'; import './LevelFounder.js'; import './NameMenu.js'; import './TimeAgo.js'; -import './ChatTextEditor'; -import './WrapperModal'; +import './ChatTextEditor.js'; +import './WrapperModal.js'; import './ChatSelect.js' +import './ChatSeachResults.js'; import '@polymer/paper-spinner/paper-spinner-lite.js'; import '@material/mwc-button'; import '@material/mwc-dialog'; import '@material/mwc-icon'; import { replaceMessagesEdited } from '../../utils/replace-messages-edited.js'; import { publishData } from '../../utils/publish-image.js'; +import { EmojiPicker } from 'emoji-picker-js'; import WebWorker from 'web-worker:./computePowWorker.js'; import WebWorkerImage from 'web-worker:./computePowWorkerImage.js'; -import { EmojiPicker } from 'emoji-picker-js'; - // const messagesCache = localForage.createInstance({ // name: "messages-cache", @@ -67,469 +67,585 @@ class ChatPage extends LitElement { chatEditorNewChat: { type: Object }, userLanguage: { type: String }, lastMessageRefVisible: { type: Boolean }, - isLoadingOldMessages: {type: Boolean}, + isLoadingOldMessages: { type: Boolean }, isEditMessageOpen: { type: Boolean }, - webSocket: {attribute: false}, - chatHeads: {type: Array}, - forwardActiveChatHeadUrl: {type: String}, - openForwardOpen: {type: Boolean} + webSocket: { attribute: false }, + chatHeads: { type: Array }, + forwardActiveChatHeadUrl: { type: Object }, + openForwardOpen: {type: Boolean }, + userFound: { type: Array }, + userFoundModalOpen: { type: Boolean }, } } static get styles() { - return css` - html { - scroll-behavior: smooth; - } - - .chat-head-container { - display: flex; - justify-content: flex-start; - flex-direction: column; - height: 50vh; - overflow-y: auto; - width: 100%; - } - - .chat-container { - display: grid; - grid-template-rows: minmax(6%, 92vh) minmax(40px, auto); - max-height: 100%; - } - - .chat-text-area { - display: flex; - position: relative; - justify-content: center; - min-height: 60px; - max-height: 100%; - } - - .chat-text-area .typing-area { - display: flex; - flex-direction: column; - width: 98%; - box-sizing: border-box; - margin-bottom: 8px; - border: 1px solid var(--chat-bubble-bg); - border-radius: 10px; - background: var(--chat-bubble-bg); - } - - .chat-text-area .typing-area textarea { - display: none; - } - - .chat-text-area .typing-area .chat-editor { - display: flex; - max-height: -webkit-fill-available; - width: 100%; - border-color: transparent; - margin: 0; - padding: 0; - border: none; - } - - .repliedTo-container { - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - padding: 10px 10px 8px 10px; - } - - .repliedTo-subcontainer { - display: flex; - flex-direction: row; - align-items: center; - gap: 15px; - width: 100%; - } - - .repliedTo-message { - display: flex; - flex-direction: column; - gap: 5px; - width: 100%; - } - - .senderName { - margin: 0; - color: var(--mdc-theme-primary); - font-weight: bold; - user-select: none; - } - - .original-message { - color: var(--chat-bubble-msg-color); - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - margin: 0; - width: 800px; - } - - .reply-icon { - width: 20px; - color: var(--mdc-theme-primary); - } - - .close-icon { - color: #676b71; - width: 18px; - transition: all 0.1s ease-in-out; - } - - .close-icon:hover { - cursor: pointer; - color: #494c50; - } - - .chat-text-area .typing-area .chatbar { - position: relative; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - height: auto; - padding: 5px 5px 5px 7px; - overflow-y: hidden; - } - - .chatbar-container { - width: 100%; - display: flex; - height: auto; - overflow: hidden; - } - - .chat-text-area .typing-area .emoji-button { - width: 45px; - height: 40px; - padding-top: 4px; - border: none; - outline: none; - background: transparent; - cursor: pointer; - max-height: 40px; - color: var(--black); - } - - .emoji-button-caption { - width: 45px; - height: 40px; - padding-top: 4px; - border: none; - outline: none; - background: transparent; - cursor: pointer; - max-height: 40px; - color: var(--black); - } - - .caption-container { - width: 100%; - display: flex; - height: auto; - overflow: hidden; - justify-content: center; - background-color: var(--white); - padding: 5px; - border-radius: 1px; - } - - .chatbar-caption { - font-family: Roboto, sans-serif; - width: 70%; - margin-right: 10px; - outline: none; - align-items: center; - font-size: 18px; - resize: none; - border-top: 0; - border-right: 0; - border-left: 0; - border-bottom: 1px solid #cac8c8; - padding: 3px; - } - - .message-size-container { - display: flex; - justify-content: flex-end; - width: 100%; - } - - .message-size { - font-family: Roboto, sans-serif; - font-size: 12px; - color: black; - } - - .lds-grid { - width: 120px; - height: 120px; - position: absolute; - left: 50%; - top: 40%; - } - - .lds-grid div { - position: absolute; - width: 34px; - height: 34px; - border-radius: 50%; - background: #03a9f4; - animation: lds-grid 1.2s linear infinite; - } - - .lds-grid div:nth-child(1) { - top: 4px; - left: 4px; - animation-delay: 0s; - } - - .lds-grid div:nth-child(2) { - top: 4px; - left: 48px; - animation-delay: -0.4s; - } - - .lds-grid div:nth-child(3) { - top: 4px; - left: 90px; - animation-delay: -0.8s; - } - - .lds-grid div:nth-child(4) { - top: 50px; - left: 4px; - animation-delay: -0.4s; - } - - .lds-grid div:nth-child(5) { - top: 50px; - left: 48px; - animation-delay: -0.8s; - } - - .lds-grid div:nth-child(6) { - top: 50px; - left: 90px; - animation-delay: -1.2s; - } - - .lds-grid div:nth-child(7) { - top: 95px; - left: 4px; - animation-delay: -0.8s; - } - - .lds-grid div:nth-child(8) { - top: 95px; - left: 48px; - animation-delay: -1.2s; - } - - .lds-grid div:nth-child(9) { - top: 95px; - left: 90px; - animation-delay: -1.6s; - } - - @keyframes lds-grid { - 0%, 100% { - opacity: 1; - } - 50% { - opacity: 0.5; - } - } - - .float-left { - float: left; - } - - img { - border-radius: 25%; - } - - .dialogCustom { - position: fixed; - z-index: 10000; - display: flex; - justify-content: center; - flex-direction: column; - align-items: center; - top: 10px; - right: 20px; - user-select: none; - } - - .dialogCustom p { - color: var(--black) - } - - .dialogCustomInner { - min-width: 300px; - height: 40px; - background-color: var(--white); - box-shadow: rgb(119 119 119 / 32%) 0px 4px 12px; - padding: 10px; - border-radius: 4px; - } - - .dialogCustomInner ul { - padding-left: 0px - } - .dialogCustomInner li { - margin-bottom: 10px; - } - - .marginLoader { - margin-right: 8px; - } - - .smallLoading, - .smallLoading:after { - border-radius: 50%; - width: 2px; - height: 2px; - } - - .smallLoading { - border-width: 0.8em; - border-style: solid; - border-color: rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2) - rgba(3, 169, 244, 0.2) rgb(3, 169, 244); - font-size: 10px; - position: relative; - text-indent: -9999em; - transform: translateZ(0px); - animation: 1.1s linear 0s infinite normal none running loadingAnimation; - } - - @-webkit-keyframes loadingAnimation { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @keyframes loadingAnimation { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - /* Add Image Modal Dialog Styling */ - - .dialog-container { - position: relative; - display: flex; - align-items: center; - flex-direction: column; - padding: 0 10px; - gap: 10px; - height: 100%; - } - - .dialog-container-title { - color: var(--black); - font-size: 18px; - } - - .dialog-container-loader { - position: relative; - display: flex; - align-items: center; - padding: 0 10px; - gap: 10px; - height: 100%; - } - - .dialog-image { - width: 100%; - max-height: 300px; - border-radius: 0; - object-fit: contain; - } - - .last-message-ref { - position: absolute; - font-size: 18px; - top: -40px; - right: 30px; - width: 50; - height: 50; - z-index: 5; - color: black; - background-color: white; - border-radius: 50%; - transition: all 0.1s ease-in-out; - } - - .last-message-ref:hover { - cursor: pointer; - transform: scale(1.1); - } - - .arrow-down-icon { - transform: scale(1.15); - } - - .modal-button-row { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - } + return css` + html { + scroll-behavior: smooth; + } - .modal-button { - font-family: Roboto, sans-serif; - font-size: 16px; - color: var(--mdc-theme-primary); - background-color: transparent; - padding: 8px 10px; - border-radius: 5px; - border: none; - transition: all 0.3s ease-in-out; - } + .chat-head-container { + display: flex; + justify-content: flex-start; + flex-direction: column; + height: 50vh; + overflow-y: auto; + overflow-x: hidden; + width: 100%; + } + + .chat-container { + display: grid; + grid-template-rows: minmax(6%, 92vh) minmax(40px, auto); + max-height: 100%; + } + + .chat-text-area { + display: flex; + position: relative; + justify-content: center; + min-height: 60px; + max-height: 100%; + } + + .chat-text-area .typing-area { + display: flex; + flex-direction: column; + width: 98%; + box-sizing: border-box; + margin-bottom: 8px; + border: 1px solid var(--chat-bubble-bg); + border-radius: 10px; + background: var(--chat-bubble-bg); + } + + .chat-text-area .typing-area textarea { + display: none; + } + + .chat-text-area .typing-area .chat-editor { + display: flex; + max-height: -webkit-fill-available; + width: 100%; + border-color: transparent; + margin: 0; + padding: 0; + border: none; + } + + .repliedTo-container { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 10px 10px 8px 10px; + } + + .repliedTo-subcontainer { + display: flex; + flex-direction: row; + align-items: center; + gap: 15px; + width: 100%; + } + + .repliedTo-message { + display: flex; + flex-direction: column; + gap: 5px; + width: 100%; + } + + .senderName { + margin: 0; + color: var(--mdc-theme-primary); + font-weight: bold; + user-select: none; + } + + .original-message { + color: var(--chat-bubble-msg-color); + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + margin: 0; + width: 800px; + } + + .reply-icon { + width: 20px; + color: var(--mdc-theme-primary); + } + + .close-icon { + color: #676b71; + width: 18px; + transition: all 0.1s ease-in-out; + } + + .close-icon:hover { + cursor: pointer; + color: #494c50; + } + + .chat-text-area .typing-area .chatbar { + position: relative; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: auto; + padding: 5px 5px 5px 7px; + overflow-y: hidden; + } + + .chatbar-container { + width: 100%; + display: flex; + height: auto; + overflow: hidden; + } + + .chat-text-area .typing-area .emoji-button { + width: 45px; + height: 40px; + padding-top: 4px; + border: none; + outline: none; + background: transparent; + cursor: pointer; + max-height: 40px; + color: var(--black); + } + + .emoji-button-caption { + width: 45px; + height: 40px; + padding-top: 4px; + border: none; + outline: none; + background: transparent; + cursor: pointer; + max-height: 40px; + color: var(--black); + } + + .caption-container { + width: 100%; + display: flex; + height: auto; + overflow: hidden; + justify-content: center; + background-color: var(--white); + padding: 5px; + border-radius: 1px; + } + + .chatbar-caption { + font-family: Roboto, sans-serif; + width: 70%; + margin-right: 10px; + outline: none; + align-items: center; + font-size: 18px; + resize: none; + border-top: 0; + border-right: 0; + border-left: 0; + border-bottom: 1px solid #cac8c8; + padding: 3px; + } + + .message-size-container { + display: flex; + justify-content: flex-end; + width: 100%; + } + + .message-size { + font-family: Roboto, sans-serif; + font-size: 12px; + color: black; + } + + .lds-grid { + width: 120px; + height: 120px; + position: absolute; + left: 50%; + top: 40%; + } + + .lds-grid div { + position: absolute; + width: 34px; + height: 34px; + border-radius: 50%; + background: #03a9f4; + animation: lds-grid 1.2s linear infinite; + } + + .lds-grid div:nth-child(1) { + top: 4px; + left: 4px; + animation-delay: 0s; + } - .modal-button-red { - font-family: Roboto, sans-serif; - font-size: 16px; - color: #F44336; - background-color: transparent; - padding: 8px 10px; - border-radius: 5px; - border: none; - transition: all 0.3s ease-in-out; - } + .lds-grid div:nth-child(2) { + top: 4px; + left: 48px; + animation-delay: -0.4s; + } + + .lds-grid div:nth-child(3) { + top: 4px; + left: 90px; + animation-delay: -0.8s; + } + + .lds-grid div:nth-child(4) { + top: 50px; + left: 4px; + animation-delay: -0.4s; + } + + .lds-grid div:nth-child(5) { + top: 50px; + left: 48px; + animation-delay: -0.8s; + } + + .lds-grid div:nth-child(6) { + top: 50px; + left: 90px; + animation-delay: -1.2s; + } + + .lds-grid div:nth-child(7) { + top: 95px; + left: 4px; + animation-delay: -0.8s; + } + + .lds-grid div:nth-child(8) { + top: 95px; + left: 48px; + animation-delay: -1.2s; + } + + .lds-grid div:nth-child(9) { + top: 95px; + left: 90px; + animation-delay: -1.6s; + } + + @keyframes lds-grid { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } +} + + .float-left { + float: left; + } + + img { + border-radius: 25%; + } + + .dialogCustom { + position: fixed; + z-index: 10000; + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + top: 10px; + right: 20px; + user-select: none; + } + + .dialogCustom p { + color: var(--black) + } + + .dialogCustomInner { + min-width: 300px; + height: 40px; + background-color: var(--white); + box-shadow: rgb(119 119 119 / 32%) 0px 4px 12px; + padding: 10px; + border-radius: 4px; + } + + .dialogCustomInner ul { + padding-left: 0px + } + + .dialogCustomInner li { + margin-bottom: 10px; + } + + .marginLoader { + margin-right: 8px; + } + + .smallLoading, + .smallLoading:after { + border-radius: 50%; + width: 2px; + height: 2px; + } + + .smallLoading { + border-width: 0.8em; + border-style: solid; + border-color: rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2) + rgba(3, 169, 244, 0.2) rgb(3, 169, 244); + font-size: 10px; + position: relative; + text-indent: -9999em; + transform: translateZ(0px); + animation: 1.1s linear 0s infinite normal none running loadingAnimation; + } + + @-webkit-keyframes loadingAnimation { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } + } - .modal-button-red:hover { - cursor: pointer; - background-color: #f4433663; - } + @keyframes loadingAnimation { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } + } + + /* Add Image Modal Dialog Styling */ + + .dialog-container { + position: relative; + display: flex; + align-items: center; + flex-direction: column; + padding: 0 10px; + gap: 10px; + height: 100%; + } + + .dialog-container-title { + font-family: Montserrat; + color: var(--black); + font-size: 20px; + margin: 15px 0 0 0; + } + + .divider { + height: 1px; + background-color: var(--chat-bubble-msg-color); + user-select: none; + width: 70%; + margin-bottom: 20px; + } + + .dialog-container-loader { + position: relative; + display: flex; + align-items: center; + padding: 0 10px; + gap: 10px; + height: 100%; + } + + .dialog-image { + width: 100%; + max-height: 300px; + border-radius: 0; + object-fit: contain; + } + + .last-message-ref { + position: absolute; + font-size: 18px; + top: -40px; + right: 30px; + width: 50; + height: 50; + z-index: 5; + color: black; + background-color: white; + border-radius: 50%; + transition: all 0.1s ease-in-out; +} - .modal-button:hover { - cursor: pointer; - background-color: #03a8f475; - } - ` - } + .last-message-ref:hover { + cursor: pointer; + transform: scale(1.1); + } + + .arrow-down-icon { + transform: scale(1.15); + } + + .modal-button-row { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + } + + .modal-button { + font-family: Roboto, sans-serif; + font-size: 16px; + color: var(--mdc-theme-primary); + background-color: transparent; + padding: 8px 10px; + border-radius: 5px; + border: none; + transition: all 0.3s ease-in-out; + } + + .modal-button-red { + font-family: Roboto, sans-serif; + font-size: 16px; + color: #F44336; + background-color: transparent; + padding: 8px 10px; + border-radius: 5px; + border: none; + transition: all 0.3s ease-in-out; + } + + .modal-button-red:hover { + cursor: pointer; + background-color: #f4433663; + } + + .modal-button:hover { + cursor: pointer; + background-color: #03a8f475; + } + + .name-input { + width: 100%; + margin-bottom: 15px; + outline: 0; + border-width: 0 0 2px; + border-color: var(--mdc-theme-primary); + background-color: transparent; + padding: 10px; + font-family: Roboto, sans-serif; + font-size: 15px; + color: var(--chat-bubble-msg-color); + } + + .name-input::selection { + background-color: var(--mdc-theme-primary); + color: white; + } + + .name-input::placeholder { + opacity: 0.9; + color: var(--black); + } + + .search-results-div { + position: absolute; + top: 25px; + right: 25px; + } + + .search-field { + width: 100%; + position: relative; + margin-bottom: 5px; + } + + .search-icon { + position: absolute; + right: 3px; + top: 0; + color: var(--chat-bubble-msg-color); + transition: all 0.3s ease-in-out; + background: none; + border-radius: 50%; + padding: 6px 3px; + font-size: 21px; + } + + .search-icon:hover { + cursor: pointer; + background: #d7d7d75c; + } + + .user-verified { + position: absolute; + top: 0; + right: 5px; + display: flex; + align-items: center; + gap: 10px; + color: #04aa2e; + font-size: 13px; + } + + .user-selected { + display: flex; + justify-content: space-between; + align-items: center; + margin: 0; + box-shadow: rgb(0 0 0 / 16%) 0px 3px 6px, rgb(0 0 0 / 23%) 0px 3px 6px; + padding: 18px 20px; + color: var(--chat-bubble-msg-color); + border-radius: 5px; + background-color: #ececec96; + } + + .user-selected-name { + font-family: Roboto, sans-serif; + margin: 0; + font-size: 16px; + } + + .forwarding-container { + display: flex; + gap: 15px; + } + + .user-selected-forwarding { + font-family: Livvic, sans-serif; + margin: 0; + font-size: 16px; + } + + .close-forwarding { + color: #676b71; + width: 14px; + transition: all 0.1s ease-in-out; + } + + .close-forwarding:hover { + cursor: pointer; + color: #4e5054; + } +` +} constructor() { super() - this.changeMsgInput = this.changeMsgInput.bind(this) this.getOldMessage = this.getOldMessage.bind(this) this._sendMessage = this._sendMessage.bind(this) this.insertImage = this.insertImage.bind(this) @@ -570,11 +686,17 @@ class ChatPage extends LitElement { boxShadow: 'rgba(4, 4, 5, 0.15) 0px 0px 0px 1px, rgba(0, 0, 0, 0.24) 0px 8px 16px 0px' }); this.openForwardOpen = false + this.userFoundModalOpen = false + this.userFound = [] + this.forwardActiveChatHeadUrl = { + url: "", + name: "", + selected: false + } } - - render() { + console.log(25, 'here'); return html`
@@ -651,9 +773,7 @@ class ChatPage extends LitElement { .chatEditor=${this.chatEditor} .imageFile=${this.imageFile} .insertImage=${this.insertImage} - .chatMessageInput=${this.chatMessageInput} .editedMessageObj=${this.editedMessageObj} - .mirrorChatInput=${this.mirrorChatInput} ?isLoading=${this.isLoading} ?isLoadingMessages=${this.isLoadingMessages} ?isEditMessageOpen=${this.isEditMessageOpen}> @@ -676,9 +796,9 @@ class ChatPage extends LitElement {
`: ''} { - this.chatEditorNewChat.resetValue() - this.removeImage() + .onClickFunc=${() => { + this.chatEditorNewChat.resetValue(); + this.removeImage(); } } style=${(this.imageFile && !this.isUploadingImage) ? "display: block" : "display: none"}>
@@ -705,14 +825,15 @@ class ChatPage extends LitElement {
{ - this.openForwardOpen = false - this.forwardActiveChatHeadUrl = "" + .onClickFunc=${() => { + this.openForwardOpen = false; + this.forwardActiveChatHeadUrl = {}; + this.chatEditor.enable(); + this.requestUpdate(); } } style=${this.openForwardOpen ? "display: block" : "display: none"}>
@@ -737,18 +860,88 @@ class ChatPage extends LitElement {

${translate("blockpage.bcchange16")}

+
- ${this.chatHeads.map((item)=> { - return html` { - this.forwardActiveChatHeadUrl = val - }} chatInfo=${JSON.stringify(item)}>` - })} -
+
+ { + this.forwardActiveChatHeadUrl = {}; + this.requestUpdate(); + } + } + /> + ${this.forwardActiveChatHeadUrl.selected ? ( + html` +
+

${translate("chatpage.cchange38")}

+ +
+ ` + ) : ( + html` + + + ` + )} +
+ ${this.forwardActiveChatHeadUrl.selected ? ( + html` +
+

+ ${this.forwardActiveChatHeadUrl.name} +

+
+

+ Forwarding... +

+ { + this.userFound = []; + this.forwardActiveChatHeadUrl = {}; + this.requestUpdate(); + this.shadowRoot.getElementById("sendTo").value = ""; + }}> + +
+
+ ` + ) : ( + html` + ${this.chatHeads.map((item) => { + return html` + { + this.forwardActiveChatHeadUrl = { + ...this.forwardActiveChatHeadUrl, + url: val + }; + this.userFound = []; + }} + chatInfo=${JSON.stringify(item)}> + ` + })} + ` + )} +
- +
+ { + this.forwardActiveChatHeadUrl = { + ...this.forwardActiveChatHeadUrl, + url: `direct/${result.owner}`, + name: result.name, + selected: true + }; + this.userFound = []; + this.userFoundModalOpen = false; + }} + .closeFunc=${() => { + this.userFoundModalOpen = false; + this.userFound = []; + }} + .searchResults=${this.userFound} + ?isOpen=${this.userFoundModalOpen} + ?loading=${this.isLoading}> + +
+ ` } + async userSearch() { + const nameValue = this.shadowRoot.getElementById('sendTo').value; + if (!nameValue) { + this.userFound = []; + this.userFoundModalOpen = true; + return; + } + try { + const result = await parentEpml.request('apiCall', { + type: 'api', + url: `/names/${nameValue}` + }) + if (result.error === 401) { + this.userFound = []; + } else { + this.userFound = [ + ...this.userFound, + result, + ]; + } + this.userFoundModalOpen = true; + } catch (error) { + console.error(error); + let err4string = get("chatpage.cchange35"); + parentEpml.request('showSnackBar', `${err4string}`) + } + } + setForwardProperties(forwardedMessage){ this.openForwardOpen = true this.forwardedMessage = forwardedMessage } - - async sendForwardMessage(){ - let parsedMessageObj = {} - let publicKey = { - hasPubKey: false, - key: '' - } + + async sendForwardMessage() { + let parsedMessageObj = {}; try { parsedMessageObj = JSON.parse(this.forwardedMessage); - - } catch (error) { - parsedMessageObj = {} - } - - try { - const res = await parentEpml.request('apiCall', { - type: 'api', - url: `/addresses/publickey/${this.forwardChatId}` - }) - if (res.error === 102) { - publicKey.key = '' - publicKey.hasPubKey = false - } else if (res !== false) { - publicKey.key = res - publicKey.hasPubKey = true - } else { - publicKey.key = '' - publicKey.hasPubKey = false - } - } catch (error) { - + } + catch (error) { + parsedMessageObj = {}; } try { @@ -812,17 +1031,10 @@ class ChatPage extends LitElement { type: 'forward' } delete message.reactions - const stringifyMessageObject = JSON.stringify(message) - this.sendMessage(stringifyMessageObject, undefined, '', true, { - isReceipient: true, - chatId: 'Qdxha59Cm1Ty4QkKMBWPnKrNigcDCDk6eq', - publicKey: { - hasPubKey: false, - key: '' - } - }) + const stringifyMessageObject = JSON.stringify(message); + this.sendMessage(stringifyMessageObject, undefined, '', true) } catch (error) { - console.log({error}) + console.log({error}); } } @@ -842,9 +1054,6 @@ class ChatPage extends LitElement { if (file.type.includes('image')) { this.imageFile = file; this.chatEditor.disable(); - // this.changeMsgInput('newChat') - // this.initChatEditor(); - // this.chatEditor.disable(); return; } parentEpml.request('showSnackBar', get("chatpage.cchange28")); @@ -955,10 +1164,20 @@ class ChatPage extends LitElement { } } + if (changedProperties && changedProperties.has('chatId') && changedProperties.get('chatId')) { await this.initUpdate() } + + if (changedProperties && changedProperties.has('openForwardOpen')) { + if (this.openForwardOpen === true) { + this.chatEditor.disable(); + } + } + if (changedProperties && changedProperties.has('forwardActiveChatHeadUrl')) { + console.log(this.forwardActiveChatHeadUrl, "forwardActiveChatHeadUrl here"); + } } async renderPlaceholder() { @@ -1454,7 +1673,7 @@ class ChatPage extends LitElement { } async _sendMessage(outSideMsg) { - + console.log(outSideMsg); // have params to determine if it's a reply or not // have variable to determine if it's a response, holds signature in constructor // need original message signature @@ -1698,35 +1917,31 @@ class ChatPage extends LitElement { users: [this.selectedAddress.address] }] } - const messageObject = { ...message, reactions - } const stringifyMessageObject = JSON.stringify(messageObject) this.sendMessage(stringifyMessageObject, typeMessage, chatReference); - } else if (/^\s*$/.test(trimmedMessage)) { this.isLoading = false; this.chatEditor.enable(); - this.chatEditorNewChat.enable() + this.chatEditorNewChat.enable(); } else if (this.repliedToMessageObj) { - let chatReference = this.repliedToMessageObj.reference - + let chatReference = this.repliedToMessageObj.reference; if(this.repliedToMessageObj.chatReference){ - chatReference = this.repliedToMessageObj.chatReference + chatReference = this.repliedToMessageObj.chatReference; } - typeMessage = 'reply' + typeMessage = 'reply'; const messageObject = { messageText: trimmedMessage, images: [''], repliedTo: chatReference, version: 1 } - const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage ); + const stringifyMessageObject = JSON.stringify(messageObject); + this.sendMessage(stringifyMessageObject, typeMessage); } else if (this.editedMessageObj) { typeMessage = 'edit' let chatReference = this.editedMessageObj.reference @@ -1762,7 +1977,7 @@ class ChatPage extends LitElement { } } - async sendMessage(messageText, typeMessage, chatReference, isForward, forwardParams) { + async sendMessage(messageText, typeMessage, chatReference, isForward) { this.isLoading = true; let _reference = new Uint8Array(64); @@ -1811,19 +2026,67 @@ class ChatPage extends LitElement { }; const sendForwardRequest = async () => { - const { publicKey } = forwardParams + let publicKey = { + hasPubKey: false, + key: '' + }; - const isRecipient = this.forwardActiveChatHeadUrl.includes('direct') === true ? true : false; + if (this.forwardActiveChatHeadUrl.url) { + const activeChatHeadAddress = this.forwardActiveChatHeadUrl.url.split('/')[1] + try { + const res = await parentEpml.request('apiCall', { + type: 'api', + url: `/addresses/publickey/${activeChatHeadAddress}` + }) + + if (res.error === 102) { + publicKey.key = '' + publicKey.hasPubKey = false + } else if (res !== false) { + publicKey.key = res + publicKey.hasPubKey = true + } else { + publicKey.key = '' + publicKey.hasPubKey = false + } + } catch (error) { + console.error(error); + } + } + + if (!this.forwardActiveChatHeadUrl && this.shadowRoot.getElementById("sendTo").value !== "") { + try { + const res = await parentEpml.request('apiCall', { + type: 'api', + url: `/addresses/publickey/${this.shadowRoot.getElementById("sendTo").value}` + }) + if (res.error === 102) { + publicKey.key = '' + publicKey.hasPubKey = false + } else if (res !== false) { + publicKey.key = res + publicKey.hasPubKey = true + } else { + publicKey.key = '' + publicKey.hasPubKey = false + } + } catch (error) { + console.error(error); + } + } + + const isRecipient = this.forwardActiveChatHeadUrl.url.includes('direct') === true ? true : false; - const chatId = this.forwardActiveChatHeadUrl.split('/')[1]; - this.openForwardOpen = false + const recipientAddress = this.forwardActiveChatHeadUrl.url.split('/')[1]; + this.openForwardOpen = false; + this.chatEditor.enable(); if (isRecipient === true) { let chatResponse = await parentEpml.request('chat', { type: 18, nonce: this.selectedAddress.nonce, params: { timestamp: Date.now(), - recipient: chatId, + recipient: recipientAddress, recipientPublicKey: publicKey.key, hasChatReference: 0, chatReference: "", @@ -1842,7 +2105,7 @@ class ChatPage extends LitElement { nonce: this.selectedAddress.nonce, params: { timestamp: Date.now(), - groupID: Number(chatId), + groupID: Number(recipientAddress), hasReceipient: 0, hasChatReference: 0, chatReference: chatReference, @@ -1910,9 +2173,9 @@ class ChatPage extends LitElement { this.forwardActiveChatHeadUrl = "" }; - if(isForward){ + if (isForward) { sendForwardRequest(); - return + return; } sendMessageRequest(); } diff --git a/qortal-ui-plugins/plugins/core/components/ChatSeachResults.js b/qortal-ui-plugins/plugins/core/components/ChatSeachResults.js new file mode 100644 index 00000000..2fdf8422 --- /dev/null +++ b/qortal-ui-plugins/plugins/core/components/ChatSeachResults.js @@ -0,0 +1,66 @@ +import { LitElement, html } from 'lit'; +import { render } from 'lit/html.js'; +import { chatSearchResultsStyles } from './ChatSearchResults-css.js' +import { translate } from 'lit-translate'; +export class ChatSearchResults extends LitElement { + static get properties() { + return { + onClickFunc: { attribute: false }, + closeFunc: { attribute: false }, + searchResults: { type: Array }, + isOpen: { type: Boolean }, + loading: { type: Boolean } + } + } + + static styles = [chatSearchResultsStyles] + + render() { + return html` +
+ this.closeFunc()} + icon="vaadin:close-small" + slot="icon" + class="close-icon" + > + + ${this.loading ? ( + html` +
+ +
+ ` + ) : ( + html` +

${translate("chatpage.cchange36")}

+
+
+ ${this.searchResults.length === 0 ? ( + html`

${translate("chatpage.cchange37")}

` + ) : ( + html` + ${this.searchResults.map((result) => { + return ( + html` +
{ + this.shadowRoot.querySelector(".chat-result-card").classList.add("active"); + this.onClickFunc(result); + }}> +

+ ${result.name} +

+
+ ` + )} + )} + ` + )} +
+ ` + )} +
+ `; + } +} +customElements.define('chat-search-results', ChatSearchResults); diff --git a/qortal-ui-plugins/plugins/core/components/ChatSearchResults-css.js b/qortal-ui-plugins/plugins/core/components/ChatSearchResults-css.js new file mode 100644 index 00000000..4cff99f5 --- /dev/null +++ b/qortal-ui-plugins/plugins/core/components/ChatSearchResults-css.js @@ -0,0 +1,120 @@ +import { css } from 'lit' + +export const chatSearchResultsStyles = css` + .chat-results-card { + position: relative; + padding: 25px 20px; + box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px; + width: 300px; + min-height: 200px; + height: auto; + border-radius: 5px; + background-color: var(--white); + } + + .chat-result-header { + color: var(--chat-bubble-msg-color); + font-size: 18px; + font-family: Montserrat, sans-serif; + text-align: center; + margin: 0 0 10px 0; + user-select: none; + } + + .divider { + height: 1px; + background: var(--chat-bubble-msg-color); + margin: 0 40px; + user-select: none; + } + + .no-results { + font-family: Roboto, sans-serif; + font-weight: 300; + letter-spacing: 0.3px; + font-size: 16px; + color: var(--chat-bubble-msg-color); + text-align: center; + margin: 20px 0 0 0; + user-select: none; + } + + .chat-result-container { + height: 200px; + overflow-y: auto; + padding: 0 10px; + } + + .chat-result-container::-webkit-scrollbar-track { + background-color: whitesmoke; + border-radius: 7px; + } + + .chat-result-container::-webkit-scrollbar { + width: 6px; + border-radius: 7px; + background-color: whitesmoke; + } + + .chat-result-container::-webkit-scrollbar-thumb { + background-color: rgb(180, 176, 176); + border-radius: 7px; + transition: all 0.3s ease-in-out; + } + + .chat-result-container::-webkit-scrollbar-thumb:hover { + background-color: rgb(148, 146, 146); + cursor: pointer; + } + + .chat-result-card { + padding: 12px; + margin-bottom: 15px; + margin-top: 15px; + transition: all 0.2s ease-in-out; + box-shadow: none; + } + + .chat-result-card:active { + background-color: #09b814; + } + + .chat-result-card:hover { + cursor: pointer; + border: none; + border-radius: 4px; + box-sizing: border-box; + -webkit-box-shadow: rgba(132, 132, 132, 40%) 0px 0px 6px -1px; + box-shadow: rgba(132, 132, 132, 40%) 0px 0px 6px -1px; + } + + .chat-result { + font-family: Roboto, sans-serif; + font-weight: 300; + letter-spacing: 0.3px; + font-size: 15px; + color: var(--chat-bubble-msg-color); + margin: 0; + user-select: none; + } + + .spinner-container { + display: flex; + width: 100%; + justify-content: center + } + + .close-icon { + position: absolute; + top: 5px; + right: 5px; + color: var(--chat-bubble-msg-color); + font-size: 14px; + transition: all 0.1s ease-in-out; + } + + .close-icon:hover { + cursor: pointer; + font-size: 15px; + } +` \ No newline at end of file diff --git a/qortal-ui-plugins/plugins/core/components/ChatSelect.js b/qortal-ui-plugins/plugins/core/components/ChatSelect.js index be069a2b..67fb3a0f 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatSelect.js +++ b/qortal-ui-plugins/plugins/core/components/ChatSelect.js @@ -57,6 +57,10 @@ class ChatSelect extends LitElement { color: #92959e; } + .name { + user-select: none; + } + .clearfix:after { visibility: hidden; display: block; @@ -122,13 +126,60 @@ class ChatSelect extends LitElement { } return html` -
  • this.getUrl(this.chatInfo.url)} class="clearfix ${this.activeChatHeadUrl === this.chatInfo.url ? 'active' : ''}"> - ${this.isImageLoaded ? html`${avatarImg}` : html`` } - ${!this.isImageLoaded && !this.chatInfo.name && !this.chatInfo.groupName ? html`account_circle` : html`` } - ${!this.isImageLoaded && this.chatInfo.name ? html`
    ${this.chatInfo.name.charAt(0)}
    `: ''} - ${!this.isImageLoaded && this.chatInfo.groupName ? html`
    ${this.chatInfo.groupName.charAt(0)}
    `: ''} +
  • this.getUrl(this.chatInfo.url)} + class="clearfix ${this.activeChatHeadUrl === this.chatInfo.url ? 'active' : ''}"> + ${this.isImageLoaded ? html`${avatarImg}` : html``} + ${!this.isImageLoaded && !this.chatInfo.name && !this.chatInfo.groupName ? html`account_circle` : + html`` + } + ${!this.isImageLoaded && this.chatInfo.name ? + html` +
    + ${this.chatInfo.name.charAt(0)} +
    `: + ''} + ${!this.isImageLoaded && this.chatInfo.groupName ? + html` +
    + ${this.chatInfo.groupName.charAt(0)} +
    `: + ''}
    -
    ${this.chatInfo.groupName ? this.chatInfo.groupName : this.chatInfo.name !== undefined ? this.chatInfo.name : this.chatInfo.address.substr(0, 15)}
    +
    + + ${this.chatInfo.groupName ? + this.chatInfo.groupName : + this.chatInfo.name !== undefined ? this.chatInfo.name : + this.chatInfo.address.substr(0, 15)} + +
  • ` diff --git a/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js b/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js index 6bd01d0c..dfc572bc 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js +++ b/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js @@ -172,11 +172,14 @@ class ChatTextEditor extends LitElement { } return html`
    -
    { - this.preventUserSendingImage(e) - }}> +
    { + this.preventUserSendingImage(e) + }}> +
    ${this.isLoading === false ? html`
    { - this.removeImage() + this.onClickFunc(); }}>