diff --git a/img/qchat-send-message-icon.svg b/img/qchat-send-message-icon.svg new file mode 100644 index 00000000..ee6cb8bf --- /dev/null +++ b/img/qchat-send-message-icon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/qortal-ui-core/font/switch-theme.css b/qortal-ui-core/font/switch-theme.css index bb48fc95..4c65b30c 100644 --- a/qortal-ui-core/font/switch-theme.css +++ b/qortal-ui-core/font/switch-theme.css @@ -7,6 +7,7 @@ html { --border: #d0d6de; --border2: #dde2e8; --copybutton: #707584; + --chat-bubble: #efefef73; --sectxt: #576374; --vdicon: #707b8a; --tradehead: #6a6c75; @@ -17,11 +18,11 @@ html { --relaynodetxt: #646464; --menuhover: #eeeeee; --menuactive: #ebebeb; - --mainmenutext:#080808; - --mainmenutexthover:#080808; + --mainmenutext: #080808; + --mainmenutexthover: #080808; --switchbackground: #666666; --switchborder: #333333; - --sidetopbar: #ffffff; + --sidetopbar: #ffffff; --nav-selected-color: #dddddd; --nav-selected-color-text: #333333; --nav-color-active: #d1d1d1; @@ -43,6 +44,7 @@ html[theme="dark"] { --border: #0b305e; --border2: #0b305e; --copybutton: #d0d6de; + --chat-bubble: #9694941a; --sectxt: #bbc3cd; --vdicon: #d0d6de; --tradehead: #008fd5; @@ -53,11 +55,11 @@ html[theme="dark"] { --relaynodetxt: #d4d4d4; --menuhover: #008fd5; --menuactive: #008fd5; - --mainmenutext:#008fd5; - --mainmenutexthover:#0f1a2e; + --mainmenutext: #008fd5; + --mainmenutexthover: #0f1a2e; --switchbackground: #eeeeee; --switchborder: #03a9f4; - --sidetopbar: #070d19; + --sidetopbar: #070d19; --nav-selected-color: #0f1a2e; --nav-selected-color-text: #76c8f5; --nav-color-active: #d1d1d1; @@ -68,4 +70,4 @@ html[theme="dark"] { --nav-border-selected-color: #76c8f5; --error: #d50000; --background: url("/img/qortal_background_dark_.jpg"); -} +} \ No newline at end of file diff --git a/qortal-ui-core/src/styles/switch-theme.css b/qortal-ui-core/src/styles/switch-theme.css index 45fb525b..9c6c517e 100644 --- a/qortal-ui-core/src/styles/switch-theme.css +++ b/qortal-ui-core/src/styles/switch-theme.css @@ -7,6 +7,7 @@ html { --border: #d0d6de; --border2: #dde2e8; --copybutton: #707584; + --chat-bubble: #efefef73; --sectxt: #576374; --vdicon: #707b8a; --tradehead: #6a6c75; @@ -17,11 +18,11 @@ html { --relaynodetxt: #646464; --menuhover: #eeeeee; --menuactive: #ebebeb; - --mainmenutext:#080808; - --mainmenutexthover:#080808; + --mainmenutext: #080808; + --mainmenutexthover: #080808; --switchbackground: #666666; --switchborder: #333333; - --sidetopbar: #ffffff; + --sidetopbar: #ffffff; --nav-selected-color: #dddddd; --nav-selected-color-text: #333333; --nav-color-active: #d1d1d1; @@ -42,6 +43,7 @@ html[theme="dark"] { --border: #0b305e; --border2: #0b305e; --copybutton: #d0d6de; + --chat-bubble: #9694941a; --sectxt: #bbc3cd; --vdicon: #d0d6de; --tradehead: #008fd5; @@ -52,11 +54,11 @@ html[theme="dark"] { --relaynodetxt: #d4d4d4; --menuhover: #008fd5; --menuactive: #008fd5; - --mainmenutext:#008fd5; - --mainmenutexthover:#0f1a2e; + --mainmenutext: #008fd5; + --mainmenutexthover: #0f1a2e; --switchbackground: #eeeeee; --switchborder: #03a9f4; - --sidetopbar: #070d19; + --sidetopbar: #070d19; --nav-selected-color: #0f1a2e; --nav-selected-color-text: #76c8f5; --nav-color-active: #d1d1d1; @@ -66,4 +68,4 @@ html[theme="dark"] { --nav-border-color: #0b305e; --nav-border-selected-color: #76c8f5; --background: url("/img/qortal_background_dark_.jpg"); -} +} \ No newline at end of file diff --git a/qortal-ui-plugins/plugins/core/components/ChatModals.js b/qortal-ui-plugins/plugins/core/components/ChatModals.js index b7370ef3..c9daf3b4 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatModals.js +++ b/qortal-ui-plugins/plugins/core/components/ChatModals.js @@ -92,11 +92,11 @@ class ChatModals extends LitElement { // Send Private Message _sendMessage() { - this.isLoading = true + this.isLoading = true; - const recipient = this.shadowRoot.getElementById('sendTo').value - const messageBox = this.shadowRoot.getElementById('messageBox') - const messageText = messageBox.value + const recipient = this.shadowRoot.getElementById('sendTo').value; + const messageBox = this.shadowRoot.getElementById('messageBox'); + const messageText = messageBox.value; if (recipient.length === 0) { this.isLoading = false @@ -105,22 +105,21 @@ class ChatModals extends LitElement { } else { this.sendMessage() } - } + }; async sendMessage() { - this.isLoading = true - - const _recipient = this.shadowRoot.getElementById('sendTo').value - const messageBox = this.shadowRoot.getElementById('messageBox') - const messageText = messageBox.value - let recipient + this.isLoading = true; + const _recipient = this.shadowRoot.getElementById('sendTo').value; + const messageBox = this.shadowRoot.getElementById('messageBox'); + const messageText = messageBox.value; + let recipient; const validateName = async (receiverName) => { - let myRes + let myRes; let myNameRes = await parentEpml.request('apiCall', { type: 'api', url: `/names/${receiverName}` - }) + }); if (myNameRes.error === 401) { myRes = false @@ -128,7 +127,7 @@ class ChatModals extends LitElement { myRes = myNameRes } - return myRes + return myRes; } const myNameRes = await validateName(_recipient) @@ -139,7 +138,6 @@ class ChatModals extends LitElement { recipient = myNameRes.owner } - let _reference = new Uint8Array(64); window.crypto.getRandomValues(_reference); @@ -367,7 +365,11 @@ class ChatModals extends LitElement {

- ${translate('welcomepage.wcchange6')} + { + console.log("here500"); + this._sendMessage(); + } + }>${translate('welcomepage.wcchange6')} ${translate("chatpage.cchange22")}` : this.renderChatScroller(this._initialMessages)} - -
- +
+
+ ${this.isLoadingMessages ? html`

${translate("chatpage.cchange22")}

` : this.renderChatScroller(this._initialMessages)} + +
hello @@ -239,18 +270,15 @@ class ChatPage extends LitElement { slot="primaryAction" dialogAction="cancel" class="red" - @click=${()=>{ - + @click=${()=> { this._sendMessage({ - type: 'image', - imageFile: this.imageFile, - caption: 'This is a caption' - - - }) + type: 'image', + imageFile: this.imageFile, + caption: 'This is a caption' + }) }} > - send + send -
-
- ${this.repliedToMessageObj && html` -
-
- -
-

${this.repliedToMessageObj.senderName ? this.repliedToMessageObj.senderName : this.repliedToMessageObj.sender}

-

${this.repliedToMessageObj.message}

+
+
+
+ ${this.repliedToMessageObj && html` +
+
+ +
+

${this.repliedToMessageObj.senderName ? this.repliedToMessageObj.senderName : this.repliedToMessageObj.sender}

+

${this.repliedToMessageObj.message}

+
+ this.closeRepliedToContainer()} + >
- this.closeRepliedToContainer()} - > -
- `} - ${this.editedMessageObj && html` -
-
- -
-

${translate("chatpage.cchange25")}

-

${this.editedMessageObj.message}

+ `} + ${this.editedMessageObj && html` +
+
+ +
+

${translate("chatpage.cchange25")}

+

${this.editedMessageObj.message}

+
+ this.closeEditMessageContainer()} + >
- this.closeEditMessageContainer()} - > -
- `} -
- - - - ${this.editedMessageObj ? ( - html` - this._sendMessage()} - > - ` - ) : html`
` - } + `} +
+ this.closeEditMessageContainer()} + > + + + + ${this.editedMessageObj ? ( + html` +
+ ${this.isLoading === false ? html` + this._sendMessage()} + > + + ` : + html` + + `} +
+ ` + ) : + html` +
+ ${this.isLoading === false ? html`send-icon` : html``} +
+ ` + } +
@@ -336,8 +386,6 @@ class ChatPage extends LitElement { async firstUpdated() { // TODO: Load and fetch messages from localstorage (maybe save messages to localstorage...) - - // this.changeLanguage(); this.emojiPickerHandler = this.shadowRoot.querySelector('.emoji-button'); this.mirrorChatInput = this.shadowRoot.getElementById('messageBox'); @@ -444,6 +492,7 @@ class ChatPage extends LitElement { parentEpml.imReady(); } + async updated(changedProperties) { if (changedProperties.has('messagesRendered')) { const chatReference1 = this.isReceipient ? 'direct' : 'group'; @@ -454,11 +503,15 @@ class ChatPage extends LitElement { } if (changedProperties && changedProperties.has('editedMessageObj')) { - this.chatEditor.insertText(this.editedMessageObj.message) } } + calculateIFrameHeight(height) { + console.log(height, "height here") + this.iframeHeight = height; + } + changeLanguage() { const checkLanguage = localStorage.getItem('qortalLanguage') @@ -501,9 +554,6 @@ class ChatPage extends LitElement { async getOldMessage(scrollElement) { - - - if (this.isReceipient) { const getInitialMessages = await parentEpml.request('apiCall', { type: 'api', @@ -630,9 +680,6 @@ class ChatPage extends LitElement { } } - // set replied to message in chat editor - - getMessageSize(message){ try { @@ -697,6 +744,8 @@ class ChatPage extends LitElement { } + // set replied to message in chat editor + setRepliedToMessageObj(messageObj) { this.repliedToMessageObj = {...messageObj}; this.editedMessageObj = null; @@ -875,9 +924,6 @@ class ChatPage extends LitElement { directSocketLink = `ws://${nodeUrl}/websockets/chat/messages?involving=${window.parent.reduxStore.getState().app.selectedAddress.address}&involving=${cid}`; } - - - const directSocket = new WebSocket(directSocketLink); // Open Connection @@ -1653,41 +1699,33 @@ class ChatPage extends LitElement { editorConfig.getMessageSize(editorConfig.mirrorElement.value) if (e.type === 'click') { - e.preventDefault(); e.stopPropagation(); } if (e.type === 'paste') { - e.preventDefault(); const item_list = await navigator.clipboard.read(); console.log({item_list}) - let image_type; // we will feed this later - const item = item_list.find( item => // choose the one item holding our image - item.types.some( type => { // does this item have our type - if( type.startsWith( 'image/' ) ) { - image_type = type; // store which kind of image type it is - return true; - } - } ) - ); - const blob = item && await item.getType( image_type ); - var file = new File([blob], "name", { - type: image_type - }); - - editorConfig.insertImage(file) - - - + let image_type; // we will feed this later + const item = item_list.find( item => // choose the one item holding our image + item.types.some( type => { // does this item have our type + if (type.startsWith( 'image/')) { + image_type = type; // store which kind of image type it is + return true; + } + }) + ); + const blob = item && await item.getType( image_type ); + var file = new File([blob], "name", { + type: image_type + }); + + editorConfig.insertImage(file) navigator.clipboard.readText().then(clipboardText => { - let escapedText = editorConfig.escape(clipboardText); - editor.insertText(escapedText); }).catch(err => { - // Fallback if everything fails... let textData = (e.originalEvent || e).clipboardData.getData('text/plain'); editor.insertText(textData); @@ -1702,7 +1740,9 @@ class ChatPage extends LitElement { } if (e.type === 'keydown') { - + console.log(editorConfig.mirrorElement.scrollHeight); + editorConfig.calculateIFrameHeight(editorConfig.editableElement.contentDocument.body.scrollHeight); + // Handle Enter if (e.keyCode === 13 && !e.shiftKey) { @@ -1783,6 +1823,7 @@ class ChatPage extends LitElement { const editorConfig = { getMessageSize: this.getMessageSize, + calculateIFrameHeight: this.calculateIFrameHeight, mirrorElement: this.mirrorChatInput, editableElement: this.chatMessageInput, sendFunc: this._sendMessage, diff --git a/qortal-ui-plugins/plugins/core/components/ChatScroller-css.js b/qortal-ui-plugins/plugins/core/components/ChatScroller-css.js index 9ef4e943..c8b45432 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatScroller-css.js +++ b/qortal-ui-plugins/plugins/core/components/ChatScroller-css.js @@ -41,7 +41,7 @@ export const chatStyles = css` ul { list-style: none; margin: 0; - padding: 20px; + padding: 20px 17px; } .last-message-ref { @@ -67,7 +67,7 @@ export const chatStyles = css` .chat-list { overflow-y: auto; overflow-x: hidden; - height: 92vh; + height: 100%; box-sizing: border-box; } @@ -79,6 +79,7 @@ export const chatStyles = css` .message-data-name { color: var(--black); + user-select: none; } .message-data-time { @@ -86,6 +87,7 @@ export const chatStyles = css` font-size: 13px; padding-left: 6px; padding-bottom: 4px; + user-select: none; } .message-data-level { @@ -93,6 +95,7 @@ export const chatStyles = css` font-size: 13px; padding-left: 8px; padding-bottom: 4px; + user-select: none; } .chat-bubble-container { @@ -102,16 +105,27 @@ export const chatStyles = css` .message-container { position: relative; + margin-bottom: 20px; + } + + .message-subcontainer { + position: relative; display: flex; + background-color: #f3f3f3; flex-grow: 0; flex-direction: column; align-items: flex-start; justify-content: center; - background-color: whitesmoke; border-radius: 5px; padding: 10px 15px; gap: 10px; - margin-bottom: 20px; + margin-bottom: 10px; + } + + .message-reactions { + background-color: transparent; + width: 100%; + margin-left: 54px; } .original-message { @@ -122,10 +136,10 @@ export const chatStyles = css` line-height: 19px; overflow-wrap: break-word; user-select: text; - font-size: 16px; + font-size: 13px; width: 90%; border-radius: 5px; - background-color: rgba(209, 209, 209, 0.79); + background-color: rgba(232, 232, 232, 0.79); padding: 8px 5px 8px 25px; white-space: nowrap; } @@ -171,12 +185,19 @@ export const chatStyles = css` float: left; } - .message-parent:hover .chat-hover { - display: block; + .message-parent { + padding: 3px; + background: rgba(245, 245, 245, 0); + transition: all 0.1s ease-in-out; + } + + .message-parent:hover { + background: var(--chat-bubble); + border-radius: 8px; } - .message-parent:hover .message-container { - filter:brightness(0.90); + .message-parent:hover .chat-hover { + display: block; } .chat-hover { @@ -193,16 +214,6 @@ export const chatStyles = css` vertical-align: bottom; object-fit: contain; } - - .my-message { - background: #d1d1d1; - border: 2px solid #eeeeee; - } - - .other-message { - background: #f1f1f1; - border: 2px solid #dedede; - } .align-left { text-align: left; @@ -324,12 +335,18 @@ export const chatStyles = css` } .reactions-bg { - background-color: #3C4048; + background-color: #d5d5d5; border-radius: 10px; - padding: 4px; - color: white; + padding: 5px; + color: black; margin-right: 10px; - cursor: pointer + transition: all 0.1s ease-in-out; + border: 0.5px solid transparent; + cursor: pointer; + } + + .reactions-bg:hover { + border: 0.5px solid #6b6969; } .image-container { diff --git a/qortal-ui-plugins/plugins/core/components/ChatScroller.js b/qortal-ui-plugins/plugins/core/components/ChatScroller.js index d2f99701..b9870e10 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatScroller.js +++ b/qortal-ui-plugins/plugins/core/components/ChatScroller.js @@ -314,59 +314,65 @@ class MessageTemplate extends LitElement {
${avatarImg}
-
- ${repliedToData && html` -
-

${repliedToData.sendName ?? repliedToData.sender}

-

${repliedToData.decodedMessage.messageText}

+
+
+ ${repliedToData && html` +
+

${repliedToData.sendName ?? repliedToData.sender}

+

${repliedToData.decodedMessage.messageText}

+
+ `} + ${image && !isImageDeleted ? html` +
+ ${imageHTML} this.sendMessage({ + type: 'delete', + name: image.name, + identifier: image.identifier, + editedMessageObj: this.messageObj, + + })} + class="image-delete-icon" icon="vaadin:close" slot="icon"> +
+ ` : html``} +
+ ${unsafeHTML(this.emojiPicker.parse(this.escapeHTML(message)))} +
- `} - ${image && !isImageDeleted ? html` -
- ${imageHTML} this.sendMessage({ - type: 'delete', - name: image.name, - identifier: image.identifier, - editedMessageObj: this.messageObj, - - })} - class="image-delete-icon" icon="vaadin:close" slot="icon"> +
+ ${reactions.map((reaction)=> { + return html` + this.sendMessage({ + type: 'reaction', + editedMessageObj: this.messageObj, + reaction: reaction.type, + })} + class="reactions-bg"> + ${reaction.type} ${reaction.qty} + ` + })}
- ` : html``} -
- ${unsafeHTML(this.emojiPicker.parse(this.escapeHTML(message)))} -
-
- ${reactions.map((reaction)=> { - return html` this.sendMessage({ - type: 'reaction', - editedMessageObj: this.messageObj, - reaction: reaction.type, - })} class="reactions-bg" >${reaction.type} ${reaction.qty}` - })} -
- this.showPrivateMessageModal()} - .showBlockUserModal=${() => this.showBlockUserModal()} - .showBlockIconFunc=${(props) => this.showBlockIconFunc(props)} - .showBlockAddressIcon=${this.showBlockAddressIcon} - .originalMessage=${{...this.messageObj, message}} - .setRepliedToMessageObj=${this.setRepliedToMessageObj} - .setEditedMessageObj=${this.setEditedMessageObj} - .focusChatEditor=${this.focusChatEditor} - .myAddress=${this.myAddress} - @blur=${() => this.showBlockIconFunc(false)} - .sendMessage=${this.sendMessage} - > - + this.showPrivateMessageModal()} + .showBlockUserModal=${() => this.showBlockUserModal()} + .showBlockIconFunc=${(props) => this.showBlockIconFunc(props)} + .showBlockAddressIcon=${this.showBlockAddressIcon} + .originalMessage=${{...this.messageObj, message}} + .setRepliedToMessageObj=${this.setRepliedToMessageObj} + .setEditedMessageObj=${this.setEditedMessageObj} + .focusChatEditor=${this.focusChatEditor} + .myAddress=${this.myAddress} + @blur=${() => this.showBlockIconFunc(false)} + .sendMessage=${this.sendMessage} + > +
+
this._textArea(e)} ?disabled=${this.isLoading} id="messageBox" placeholder="${translate("welcomepage.wcchange5")}" rows="1">

- ${translate("welcomepage.wcchange6")} + { + this._sendMessage(); + } + }> + ${translate("welcomepage.wcchange6")} { - let myRes + let myRes; let myNameRes = await parentEpml.request('apiCall', { type: 'api', url: `/names/${receiverName}` - }) - + }); if (myNameRes.error === 401) { - myRes = false + myRes = false; } else { - myRes = myNameRes - } + myRes = myNameRes; + }; + return myRes; + }; - return myRes - } + const myNameRes = await validateName(_recipient); - const myNameRes = await validateName(_recipient) if (!myNameRes) { - - recipient = _recipient + recipient = _recipient; } else { - - recipient = myNameRes.owner - } + recipient = myNameRes.owner; + }; let _reference = new Uint8Array(64); window.crypto.getRandomValues(_reference); - let sendTimestamp = Date.now() + let sendTimestamp = Date.now(); - let reference = window.parent.Base58.encode(_reference) + let reference = window.parent.Base58.encode(_reference); const getAddressPublicKey = async () => { - let isEncrypted - let _publicKey + let isEncrypted; + let _publicKey; let addressPublicKey = await parentEpml.request('apiCall', { type: 'api', url: `/addresses/publickey/${recipient}` }) - if (addressPublicKey.error === 102) { - _publicKey = false + _publicKey = false; // Do something here... - let err1string = get("welcomepage.wcchange7") - parentEpml.request('showSnackBar', `${err1string}`) - this.isLoading = false + let err1string = get("welcomepage.wcchange7"); + parentEpml.request('showSnackBar', `${err1string}`); + this.isLoading = false; } else if (addressPublicKey !== false) { - isEncrypted = 1 - _publicKey = addressPublicKey - sendMessageRequest(isEncrypted, _publicKey) + isEncrypted = 1; + _publicKey = addressPublicKey; + sendMessageRequest(isEncrypted, _publicKey); } else { - isEncrypted = 0 - _publicKey = this.selectedAddress.address - sendMessageRequest(isEncrypted, _publicKey) - } + isEncrypted = 0; + _publicKey = this.selectedAddress.address; + sendMessageRequest(isEncrypted, _publicKey); + }; }; const sendMessageRequest = async (isEncrypted, _publicKey) => { @@ -407,8 +405,8 @@ class ChatWelcomePage extends LitElement { images: [''], repliedTo: '', version: 1 - } - const stringifyMessageObject = JSON.stringify(messageObject) + }; + const stringifyMessageObject = JSON.stringify(messageObject); let chatResponse = await parentEpml.request('chat', { type: 18, nonce: this.selectedAddress.nonce, @@ -424,7 +422,6 @@ class ChatWelcomePage extends LitElement { isText: 1 } }) - _computePow(chatResponse) } diff --git a/qortal-ui-plugins/plugins/core/components/NameMenu.js b/qortal-ui-plugins/plugins/core/components/NameMenu.js index 9b1a9635..8e1363c6 100644 --- a/qortal-ui-plugins/plugins/core/components/NameMenu.js +++ b/qortal-ui-plugins/plugins/core/components/NameMenu.js @@ -232,7 +232,11 @@ class NameMenu extends LitElement {

- ${translate("welcomepage.wcchange6")} + { + this._sendMessage(); + } + }> + ${translate("welcomepage.wcchange6")}