Merge remote-tracking branch 'justin/feature/implement-UI-edit-reply-messages' into feature/implement-logic-edit-reply-messages
This commit is contained in:
commit
1d6df0cd0f
BIN
qortal-ui-core/font/KoHo.ttf
Normal file
BIN
qortal-ui-core/font/KoHo.ttf
Normal file
Binary file not shown.
BIN
qortal-ui-core/font/Livvic.ttf
Normal file
BIN
qortal-ui-core/font/Livvic.ttf
Normal file
Binary file not shown.
BIN
qortal-ui-core/font/Montserrat.ttf
Normal file
BIN
qortal-ui-core/font/Montserrat.ttf
Normal file
Binary file not shown.
@ -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';
|
||||
}
|
||||
}
|
@ -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": {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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`
|
||||
<div class="chat-results-card" style=${this.isOpen ? "display: block;" : "display: none;"}>
|
||||
<vaadin-icon
|
||||
@click=${() => this.closeFunc()}
|
||||
icon="vaadin:close-small"
|
||||
slot="icon"
|
||||
class="close-icon"
|
||||
>
|
||||
</vaadin-icon>
|
||||
${this.loading ? (
|
||||
html`
|
||||
<div class="spinner-container">
|
||||
<paper-spinner-lite active></paper-spinner-lite>
|
||||
</div>
|
||||
`
|
||||
) : (
|
||||
html`
|
||||
<p class="chat-result-header">${translate("chatpage.cchange36")}</p>
|
||||
<div class="divider"></div>
|
||||
<div class="chat-result-container">
|
||||
${this.searchResults.length === 0 ? (
|
||||
html`<p class="no-results">${translate("chatpage.cchange37")}</p>`
|
||||
) : (
|
||||
html`
|
||||
${this.searchResults.map((result) => {
|
||||
return (
|
||||
html`
|
||||
<div class="chat-result-card" @click=${() => {
|
||||
this.shadowRoot.querySelector(".chat-result-card").classList.add("active");
|
||||
this.onClickFunc(result);
|
||||
}}>
|
||||
<p class="chat-result">
|
||||
${result.name}
|
||||
</p>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
)}
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
customElements.define('chat-search-results', ChatSearchResults);
|
@ -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;
|
||||
}
|
||||
`
|
@ -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`
|
||||
<li @click=${() => 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`<mwc-icon class="img-icon">account_circle</mwc-icon>` : html`` }
|
||||
${!this.isImageLoaded && this.chatInfo.name ? html`<div style="width:40px; height:40px; float: left; border-radius:50%; background: ${this.activeChatHeadUrl === this.chatInfo.url ? 'var(--chatHeadBgActive)' : 'var(--chatHeadBg)' }; color: ${this.activeChatHeadUrl === this.chatInfo.url ? 'var(--chatHeadTextActive)' : 'var(--chatHeadText)' }; font-weight:bold; display: flex; justify-content: center; align-items: center; text-transform: capitalize">${this.chatInfo.name.charAt(0)}</div>`: ''}
|
||||
${!this.isImageLoaded && this.chatInfo.groupName ? html`<div style="width:40px; height:40px; float: left; border-radius:50%; background: ${this.activeChatHeadUrl === this.chatInfo.url ? 'var(--chatHeadBgActive)' : 'var(--chatHeadBg)' }; color: ${this.activeChatHeadUrl === this.chatInfo.url ? 'var(--chatHeadTextActive)' : 'var(--chatHeadText)' }; font-weight:bold; display: flex; justify-content: center; align-items: center; text-transform: capitalize">${this.chatInfo.groupName.charAt(0)}</div>`: ''}
|
||||
<li
|
||||
@click=${() => 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`<mwc-icon class="img-icon">account_circle</mwc-icon>` :
|
||||
html``
|
||||
}
|
||||
${!this.isImageLoaded && this.chatInfo.name ?
|
||||
html`
|
||||
<div
|
||||
style="width:40px; height:40px; float: left; border-radius:50%; background: ${this.activeChatHeadUrl === this.chatInfo.url ?
|
||||
'var(--chatHeadBgActive)' :
|
||||
'var(--chatHeadBg)' };
|
||||
color: ${this.activeChatHeadUrl === this.chatInfo.url ?
|
||||
'var(--chatHeadTextActive)' :
|
||||
'var(--chatHeadText)'};
|
||||
font-weight:bold;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-transform: capitalize">
|
||||
${this.chatInfo.name.charAt(0)}
|
||||
</div>`:
|
||||
''}
|
||||
${!this.isImageLoaded && this.chatInfo.groupName ?
|
||||
html`
|
||||
<div
|
||||
style="width:40px;
|
||||
height:40px;
|
||||
float: left;
|
||||
border-radius:50%;
|
||||
background: ${this.activeChatHeadUrl === this.chatInfo.url ?
|
||||
'var(--chatHeadBgActive)' :
|
||||
'var(--chatHeadBg)' };
|
||||
color: ${this.activeChatHeadUrl === this.chatInfo.url ?
|
||||
'var(--chatHeadTextActive)' :
|
||||
'var(--chatHeadText)' };
|
||||
font-weight:bold;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-transform: capitalize">
|
||||
${this.chatInfo.groupName.charAt(0)}
|
||||
</div>`:
|
||||
''}
|
||||
<div class="about">
|
||||
<div class="name"><span style="float:left; padding-left: 8px; color: var(--chat-group);">${this.chatInfo.groupName ? this.chatInfo.groupName : this.chatInfo.name !== undefined ? this.chatInfo.name : this.chatInfo.address.substr(0, 15)} </span> </div>
|
||||
<div class="name">
|
||||
<span style="float:left; padding-left: 8px; color: var(--chat-group);">
|
||||
${this.chatInfo.groupName ?
|
||||
this.chatInfo.groupName :
|
||||
this.chatInfo.name !== undefined ? this.chatInfo.name :
|
||||
this.chatInfo.address.substr(0, 15)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
`
|
||||
|
@ -172,11 +172,14 @@ class ChatTextEditor extends LitElement {
|
||||
}
|
||||
return html`
|
||||
<div
|
||||
class=${["chatbar-container", this.iframeId === "newChat" ? "chatbar-caption" : ""].join(" ")}
|
||||
class=${["chatbar-container", (this.iframeId === "newChat" || this.iframeId === "privateMessage") ? "chatbar-caption" : ""].join(" ")}
|
||||
style="${scrollHeightBool ? 'align-items: flex-end' : "align-items: center"}">
|
||||
<div class="file-picker-container" @click=${(e) => {
|
||||
this.preventUserSendingImage(e)
|
||||
}}>
|
||||
<div
|
||||
style=${this.iframeId === "privateMessage" ? "display: none" : "display: block"}
|
||||
class="file-picker-container"
|
||||
@click=${(e) => {
|
||||
this.preventUserSendingImage(e)
|
||||
}}>
|
||||
<vaadin-icon
|
||||
class="paperclip-icon"
|
||||
icon="vaadin:paperclip"
|
||||
@ -223,7 +226,13 @@ class ChatTextEditor extends LitElement {
|
||||
`
|
||||
) :
|
||||
html`
|
||||
<div style="${ scrollHeightBool ? 'margin-bottom: 5px;' : "margin-bottom: 0;"} ${this.iframeId === 'newChat' ? 'display: none;' : 'display: flex;'}">
|
||||
<div
|
||||
style="${scrollHeightBool
|
||||
? 'margin-bottom: 5px;'
|
||||
: "margin-bottom: 0;"}
|
||||
${this.iframeId === 'newChat'
|
||||
? 'display: none;'
|
||||
: 'display: flex;'}">
|
||||
${this.isLoading === false ? html`
|
||||
<img
|
||||
src="/img/qchat-send-message-icon.svg"
|
||||
@ -300,7 +309,6 @@ class ChatTextEditor extends LitElement {
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
this.emojiPickerHandler = this.shadowRoot.querySelector('.emoji-button');
|
||||
this.mirrorChatInput = this.shadowRoot.getElementById('messageBox');
|
||||
this.chatMessageInput = this.shadowRoot.getElementById(this.iframeId);
|
||||
@ -361,6 +369,7 @@ class ChatTextEditor extends LitElement {
|
||||
return;
|
||||
};
|
||||
this.chatMessageSize = 0;
|
||||
this.chatEditor.updateMirror();
|
||||
this._sendMessage(props);
|
||||
}
|
||||
|
||||
@ -688,11 +697,10 @@ class ChatTextEditor extends LitElement {
|
||||
}, 0);
|
||||
res();
|
||||
})
|
||||
|
||||
// Handle Enter
|
||||
if (e.keyCode === 13 && !e.shiftKey) {
|
||||
|
||||
// Update Mirror
|
||||
editor.updateMirror();
|
||||
|
||||
if (editor.state() === 'false') return false;
|
||||
if (editorConfig.iframeId === 'newChat') {
|
||||
|
@ -5,7 +5,7 @@ import { wrapperModalStyles } from './WrapperModal-css.js'
|
||||
export class WrapperModal extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
removeImage: { type: Function },
|
||||
onClickFunc: { attribute: false },
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ export class WrapperModal extends LitElement {
|
||||
return html`
|
||||
<div>
|
||||
<div class="backdrop" @click=${() => {
|
||||
this.removeImage()
|
||||
this.onClickFunc();
|
||||
}}></div>
|
||||
<div class="modal-body">
|
||||
<slot></slot>
|
||||
|
@ -0,0 +1,82 @@
|
||||
import { Sha256 } from 'asmcrypto.js'
|
||||
|
||||
|
||||
function sbrk(size, heap){
|
||||
let brk = 512 * 1024 // stack top
|
||||
let old = brk
|
||||
brk += size
|
||||
|
||||
if (brk > heap.length)
|
||||
throw new Error('heap exhausted')
|
||||
|
||||
return old
|
||||
}
|
||||
|
||||
|
||||
|
||||
self.addEventListener('message', async e => {
|
||||
const response = await computePow(e.data.chatBytes, e.data.path, e.data.difficulty)
|
||||
postMessage(response)
|
||||
|
||||
})
|
||||
|
||||
|
||||
const memory = new WebAssembly.Memory({ initial: 256, maximum: 256 })
|
||||
const heap = new Uint8Array(memory.buffer)
|
||||
|
||||
|
||||
|
||||
const computePow = async (chatBytes, path, difficulty) => {
|
||||
|
||||
let response = null
|
||||
|
||||
await new Promise((resolve, reject)=> {
|
||||
|
||||
const _chatBytesArray = Object.keys(chatBytes).map(function (key) { return chatBytes[key]; });
|
||||
const chatBytesArray = new Uint8Array(_chatBytesArray);
|
||||
const chatBytesHash = new Sha256().process(chatBytesArray).finish().result;
|
||||
const hashPtr = sbrk(32, heap);
|
||||
const hashAry = new Uint8Array(memory.buffer, hashPtr, 32);
|
||||
hashAry.set(chatBytesHash);
|
||||
|
||||
|
||||
const workBufferLength = 8 * 1024 * 1024;
|
||||
const workBufferPtr = sbrk(workBufferLength, heap);
|
||||
|
||||
|
||||
|
||||
const importObject = {
|
||||
env: {
|
||||
memory: memory
|
||||
},
|
||||
};
|
||||
|
||||
function loadWebAssembly(filename, imports) {
|
||||
// Fetch the file and compile it
|
||||
return fetch(filename)
|
||||
.then(response => response.arrayBuffer())
|
||||
.then(buffer => WebAssembly.compile(buffer))
|
||||
.then(module => {
|
||||
|
||||
// Create the instance.
|
||||
return new WebAssembly.Instance(module, importObject);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
loadWebAssembly(path)
|
||||
.then(wasmModule => {
|
||||
response = {
|
||||
nonce : wasmModule.exports.compute2(hashPtr, workBufferPtr, workBufferLength, difficulty),
|
||||
chatBytesArray
|
||||
}
|
||||
|
||||
resolve()
|
||||
|
||||
});
|
||||
|
||||
|
||||
})
|
||||
|
||||
return response
|
||||
}
|
@ -0,0 +1,368 @@
|
||||
import { css } from 'lit'
|
||||
|
||||
export const qchatStyles = css`
|
||||
* {
|
||||
--mdc-theme-primary: rgb(3, 169, 244);
|
||||
--mdc-theme-secondary: var(--mdc-theme-primary);
|
||||
--paper-input-container-focus-color: var(--mdc-theme-primary);
|
||||
--mdc-theme-surface: var(--white);
|
||||
--mdc-dialog-content-ink-color: var(--black);
|
||||
--lumo-primary-text-color: rgb(0, 167, 245);
|
||||
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
|
||||
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
|
||||
--lumo-primary-color: hsl(199, 100%, 48%);
|
||||
--lumo-base-color: var(--white);
|
||||
--lumo-body-text-color: var(--black);
|
||||
--_lumo-grid-border-color: var(--border);
|
||||
--_lumo-grid-secondary-border-color: var(--border2);
|
||||
--mdc-dialog-min-width: 750px;
|
||||
}
|
||||
|
||||
paper-spinner-lite {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
--paper-spinner-color: var(--mdc-theme-primary);
|
||||
--paper-spinner-stroke-width: 2px;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
background: var(--white);
|
||||
}
|
||||
|
||||
.people-list {
|
||||
width: 20vw;
|
||||
float: left;
|
||||
height: 100vh;
|
||||
overflow-y: hidden;
|
||||
border-right: 3px #ddd solid;
|
||||
}
|
||||
|
||||
.people-list .blockedusers {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 20vw;
|
||||
height: 60px;
|
||||
background: var(--white);
|
||||
border-top: 1px solid var(--border);
|
||||
border-right: 3px #ddd solid;
|
||||
}
|
||||
|
||||
.people-list .search {
|
||||
padding-top: 20px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.center {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
padding-top: 12px;
|
||||
left: 50%;
|
||||
-ms-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.people-list .create-chat {
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
display: inline-block;
|
||||
padding: 14px;
|
||||
color: #fff;
|
||||
background: var(--tradehead);
|
||||
width: 100%;
|
||||
font-size: 15px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.people-list .create-chat:hover {
|
||||
opacity: .8;
|
||||
box-shadow: 0 3px 5px rgba(0, 0, 0, .2);
|
||||
}
|
||||
|
||||
.people-list ul {
|
||||
padding: 0;
|
||||
height: 85vh;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.chat {
|
||||
width: 80vw;
|
||||
height: 100vh;
|
||||
float: left;
|
||||
background: var(--white);
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
color: #434651;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.chat .new-message-bar {
|
||||
display: flex;
|
||||
flex: 0 1 auto;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0px 25px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
left: 20vw;
|
||||
right: 0;
|
||||
z-index: 5;
|
||||
background: var(--tradehead);
|
||||
color: var(--white);
|
||||
border-radius: 0 0 8px 8px;
|
||||
min-height: 25px;
|
||||
transition: opacity .15s;
|
||||
text-transform: capitalize;
|
||||
opacity: .85;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.chat .new-message-bar:hover {
|
||||
opacity: .75;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 3px 7px rgba(0, 0, 0, .2);
|
||||
}
|
||||
|
||||
.hide-new-message-bar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.chat .chat-history {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 100%;
|
||||
left: 20vw;
|
||||
border-bottom: 2px solid var(--white);
|
||||
overflow-y: hidden;
|
||||
height: 100vh;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.chat .chat-message {
|
||||
padding: 10px;
|
||||
height: 10%;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.chat .chat-message textarea {
|
||||
width: 90%;
|
||||
border: none;
|
||||
font-size: 16px;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.chat .chat-message button {
|
||||
float: right;
|
||||
color: #94c2ed;
|
||||
font-size: 16px;
|
||||
text-transform: uppercase;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
background: #f2f5f8;
|
||||
padding: 10px;
|
||||
margin-top: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.chat .chat-message button:hover {
|
||||
color: #75b1e8;
|
||||
}
|
||||
|
||||
.online,
|
||||
.offline,
|
||||
.me {
|
||||
margin-right: 3px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.clearfix:after {
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
font-size: 0;
|
||||
content: " ";
|
||||
clear: both;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.red {
|
||||
--mdc-theme-primary: red;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin:0;
|
||||
}
|
||||
|
||||
h2, h3, h4, h5 {
|
||||
color: var(--black);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: hidden !important;
|
||||
visibility: none !important;
|
||||
}
|
||||
|
||||
.details {
|
||||
display: flex;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight:600;
|
||||
font-size:12px;
|
||||
line-height: 32px;
|
||||
opacity: 0.66;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
width: 100%;
|
||||
border: none;
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
height: 120px;
|
||||
resize: none;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.dialog-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
padding: 0 10px;
|
||||
gap: 10px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.dialog-header {
|
||||
color: var(--chat-bubble-msg-color);
|
||||
}
|
||||
|
||||
.dialog-subheader {
|
||||
color: var(--chat-bubble-msg-color);
|
||||
}
|
||||
|
||||
.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%;
|
||||
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-field {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
position: absolute;
|
||||
right: 3px;
|
||||
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;
|
||||
}
|
||||
|
||||
.search-results-div {
|
||||
position: absolute;
|
||||
top: 25px;
|
||||
right: 25px;
|
||||
}
|
||||
|
||||
.user-verified {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
color: #04aa2e;
|
||||
font-size: 13px;
|
||||
}
|
||||
`
|
@ -1,22 +1,26 @@
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../../epml.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { render } from 'lit/html.js';
|
||||
import { Epml } from '../../../../epml.js';
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate';
|
||||
import { qchatStyles } from './q-chat-css.src.js'
|
||||
import WebWorker from 'web-worker:./computePowWorker.src.js';
|
||||
|
||||
registerTranslateConfig({
|
||||
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
|
||||
})
|
||||
|
||||
import '../../components/ChatWelcomePage.js'
|
||||
import '../../components/ChatHead.js'
|
||||
import '../../components/ChatPage.js'
|
||||
import snackbar from '../../components/snackbar.js'
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-dialog'
|
||||
import '@material/mwc-icon'
|
||||
import '@material/mwc-snackbar'
|
||||
import '@vaadin/grid'
|
||||
import '../../components/ChatWelcomePage.js';
|
||||
import '../../components/ChatHead.js';
|
||||
import '../../components/ChatPage.js';
|
||||
import '../../components/WrapperModal.js';
|
||||
import '../../components/ChatSeachResults.js';
|
||||
import snackbar from '../../components/snackbar.js';
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js';
|
||||
import '@material/mwc-button';
|
||||
import '@material/mwc-dialog';
|
||||
import '@material/mwc-icon';
|
||||
import '@material/mwc-snackbar';
|
||||
import '@vaadin/grid';
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
@ -35,272 +39,18 @@ class Chat extends LitElement {
|
||||
theme: { type: String, reflect: true },
|
||||
blockedUsers: { type: Array },
|
||||
blockedUserList: { type: Array },
|
||||
activeChatHeadUrl: {type: String}
|
||||
privateMessagePlaceholder: { type: String},
|
||||
chatEditor: { type: Object },
|
||||
imageFile: { type: Object },
|
||||
activeChatHeadUrl: { type: String },
|
||||
openPrivateMessage: { type: Boolean },
|
||||
userFound: { type: Array},
|
||||
userFoundModalOpen: { type: Boolean },
|
||||
userSelected: { type: Object }
|
||||
}
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
* {
|
||||
--mdc-theme-primary: rgb(3, 169, 244);
|
||||
--mdc-theme-secondary: var(--mdc-theme-primary);
|
||||
--paper-input-container-focus-color: var(--mdc-theme-primary);
|
||||
--mdc-theme-surface: var(--white);
|
||||
--mdc-dialog-content-ink-color: var(--black);
|
||||
--lumo-primary-text-color: rgb(0, 167, 245);
|
||||
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
|
||||
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
|
||||
--lumo-primary-color: hsl(199, 100%, 48%);
|
||||
--lumo-base-color: var(--white);
|
||||
--lumo-body-text-color: var(--black);
|
||||
--_lumo-grid-border-color: var(--border);
|
||||
--_lumo-grid-secondary-border-color: var(--border2);
|
||||
--mdc-dialog-min-width: 750px;
|
||||
}
|
||||
|
||||
paper-spinner-lite {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
--paper-spinner-color: var(--mdc-theme-primary);
|
||||
--paper-spinner-stroke-width: 2px;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
background: var(--white);
|
||||
}
|
||||
|
||||
.people-list {
|
||||
width: 20vw;
|
||||
float: left;
|
||||
height: 100vh;
|
||||
overflow-y: hidden;
|
||||
border-right: 3px #ddd solid;
|
||||
}
|
||||
|
||||
.people-list .blockedusers {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 20vw;
|
||||
height: 60px;
|
||||
background: var(--white);
|
||||
border-top: 1px solid var(--border);
|
||||
border-right: 3px #ddd solid;
|
||||
}
|
||||
|
||||
.people-list .search {
|
||||
padding-top: 20px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.center {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
padding-top: 12px;
|
||||
left: 50%;
|
||||
-ms-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.people-list .create-chat {
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
display: inline-block;
|
||||
padding: 14px;
|
||||
color: #fff;
|
||||
background: var(--tradehead);
|
||||
width: 100%;
|
||||
font-size: 15px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.people-list .create-chat:hover {
|
||||
opacity: .8;
|
||||
box-shadow: 0 3px 5px rgba(0, 0, 0, .2);
|
||||
}
|
||||
|
||||
.people-list ul {
|
||||
padding: 0;
|
||||
height: 85vh;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.chat {
|
||||
width: 80vw;
|
||||
height: 100vh;
|
||||
float: left;
|
||||
background: var(--white);
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
color: #434651;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.chat .new-message-bar {
|
||||
display: flex;
|
||||
flex: 0 1 auto;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0px 25px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
left: 20vw;
|
||||
right: 0;
|
||||
z-index: 5;
|
||||
background: var(--tradehead);
|
||||
color: var(--white);
|
||||
border-radius: 0 0 8px 8px;
|
||||
min-height: 25px;
|
||||
transition: opacity .15s;
|
||||
text-transform: capitalize;
|
||||
opacity: .85;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.chat .new-message-bar:hover {
|
||||
opacity: .75;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 3px 7px rgba(0, 0, 0, .2);
|
||||
}
|
||||
|
||||
.hide-new-message-bar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.chat .chat-history {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 100%;
|
||||
left: 20vw;
|
||||
border-bottom: 2px solid var(--white);
|
||||
overflow-y: hidden;
|
||||
height: 100vh;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.chat .chat-message {
|
||||
padding: 10px;
|
||||
height: 10%;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.chat .chat-message textarea {
|
||||
width: 90%;
|
||||
border: none;
|
||||
font-size: 16px;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.chat .chat-message button {
|
||||
float: right;
|
||||
color: #94c2ed;
|
||||
font-size: 16px;
|
||||
text-transform: uppercase;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
background: #f2f5f8;
|
||||
padding: 10px;
|
||||
margin-top: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.chat .chat-message button:hover {
|
||||
color: #75b1e8;
|
||||
}
|
||||
|
||||
.online,
|
||||
.offline,
|
||||
.me {
|
||||
margin-right: 3px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.clearfix:after {
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
font-size: 0;
|
||||
content: " ";
|
||||
clear: both;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.red {
|
||||
--mdc-theme-primary: red;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin:0;
|
||||
}
|
||||
|
||||
h2, h3, h4, h5 {
|
||||
color: var(--black);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: hidden !important;
|
||||
visibility: none !important;
|
||||
}
|
||||
|
||||
.details {
|
||||
display: flex;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight:600;
|
||||
font-size:12px;
|
||||
line-height: 32px;
|
||||
opacity: 0.66;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
resize: none;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
width: 100%;
|
||||
border: none;
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
height: 120px;
|
||||
resize: none;
|
||||
background: #eee;
|
||||
}
|
||||
`
|
||||
}
|
||||
static styles = [qchatStyles]
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
@ -322,15 +72,21 @@ class Chat extends LitElement {
|
||||
this.isLoading = false
|
||||
this.showNewMesssageBar = this.showNewMesssageBar.bind(this)
|
||||
this.hideNewMesssageBar = this.hideNewMesssageBar.bind(this)
|
||||
this._sendMessage = this._sendMessage.bind(this)
|
||||
this.insertImage = this.insertImage.bind(this)
|
||||
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
|
||||
this.blockedUsers = []
|
||||
this.blockedUserList = []
|
||||
this.privateMessagePlaceholder = ""
|
||||
this.imageFile = null
|
||||
this.activeChatHeadUrl = ''
|
||||
|
||||
|
||||
this.openPrivateMessage = false
|
||||
this.userFound = []
|
||||
this.userFoundModalOpen = false
|
||||
this.userSelected = {}
|
||||
}
|
||||
|
||||
async setActiveChatHeadUrl(url){
|
||||
async setActiveChatHeadUrl(url) {
|
||||
this.activeChatHeadUrl = ''
|
||||
await this.updateComplete;
|
||||
this.activeChatHeadUrl = url
|
||||
@ -341,7 +97,10 @@ class Chat extends LitElement {
|
||||
<div class="container clearfix">
|
||||
<div class="people-list" id="people-list">
|
||||
<div class="search">
|
||||
<div class="create-chat" @click=${() => this.shadowRoot.querySelector('#startChatDialog').show()}>${translate("chatpage.cchange1")}</div>
|
||||
<div class="create-chat" @click=${() => {
|
||||
this.openPrivateMessage = true;
|
||||
}}>${translate("chatpage.cchange1")}
|
||||
</div>
|
||||
</div>
|
||||
<ul class="list">
|
||||
${this.isEmptyArray(this.chatHeads) ? this.renderLoadingText() : this.renderChatHead(this.chatHeads)}
|
||||
@ -365,35 +124,109 @@ class Chat extends LitElement {
|
||||
</div>
|
||||
|
||||
<!-- Start Chatting Dialog -->
|
||||
<mwc-dialog id="startChatDialog" scrimClickAction="${this.isLoading ? '' : 'close'}">
|
||||
<div style="text-align:center">
|
||||
<h1>${translate("chatpage.cchange1")}</h1>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<p>${translate("chatpage.cchange6")}</p>
|
||||
|
||||
<textarea class="input" ?disabled=${this.isLoading} id="sendTo" placeholder="${translate("chatpage.cchange7")}" rows="1"></textarea>
|
||||
<p style="margin-bottom:0;">
|
||||
<textarea class="textarea" @keydown=${(e) => this._textArea(e)} ?disabled=${this.isLoading} id="messageBox" placeholder="${translate("chatpage.cchange8")}" rows="1"></textarea>
|
||||
</p>
|
||||
|
||||
<mwc-button
|
||||
?disabled="${this.isLoading}"
|
||||
slot="primaryAction"
|
||||
@click=${this._sendMessage}
|
||||
>
|
||||
${this.isLoading === false ? this.renderSendText() : html`<paper-spinner-lite active></paper-spinner-lite>`}
|
||||
</mwc-button>
|
||||
<mwc-button
|
||||
?disabled="${this.isLoading}"
|
||||
slot="secondaryAction"
|
||||
dialogAction="cancel"
|
||||
class="red"
|
||||
>
|
||||
${translate("general.close")}
|
||||
</mwc-button>
|
||||
</mwc-dialog>
|
||||
<wrapper-modal
|
||||
.onClickFunc=${() => {
|
||||
this.chatEditor.resetValue();
|
||||
this.openPrivateMessage = false;
|
||||
this.shadowRoot.getElementById('sendTo').value = "";
|
||||
this.userFoundModalOpen = false;
|
||||
this.userFound = [];
|
||||
} }
|
||||
style=${this.openPrivateMessage ? "display: block" : "display: none"}>
|
||||
<div style=${"position: relative"}>
|
||||
<div class="dialog-container">
|
||||
<div class="dialog-header" style="text-align: center">
|
||||
<h1>${translate("chatpage.cchange1")}</h1>
|
||||
<hr>
|
||||
</div>
|
||||
<p class="dialog-subheader">${translate("chatpage.cchange6")}</p>
|
||||
<div class="search-field">
|
||||
<input
|
||||
type="text"
|
||||
class="name-input"
|
||||
?disabled=${this.isLoading}
|
||||
id="sendTo"
|
||||
placeholder="${translate("chatpage.cchange7")}"
|
||||
value=${this.userSelected.name}
|
||||
@keypress=${() => {
|
||||
this.userSelected = {};
|
||||
this.requestUpdate();
|
||||
}}
|
||||
/>
|
||||
${this.userSelected.name ? (
|
||||
html`
|
||||
<div class="user-verified">
|
||||
<p >${translate("chatpage.cchange38")}</p>
|
||||
<vaadin-icon icon="vaadin:check-circle-o" slot="icon"></vaadin-icon>
|
||||
</div>
|
||||
`
|
||||
) : (
|
||||
html`
|
||||
<vaadin-icon
|
||||
@click=${this.userSearch}
|
||||
slot="icon"
|
||||
icon="vaadin:open-book"
|
||||
class="search-icon">
|
||||
</vaadin-icon>
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
|
||||
<chat-text-editor
|
||||
iframeId="privateMessage"
|
||||
?hasGlobalEvents=${false}
|
||||
placeholder="${translate("chatpage.cchange8")}"
|
||||
.setChatEditor=${(editor)=> this.setChatEditor(editor)}
|
||||
.chatEditor=${this.chatEditor}
|
||||
.imageFile=${this.imageFile}
|
||||
._sendMessage=${this._sendMessage}
|
||||
.insertImage=${this.insertImage}
|
||||
?isLoading=${this.isLoading}
|
||||
.isLoadingMessages=${false}
|
||||
id="messageBox"
|
||||
>
|
||||
</chat-text-editor>
|
||||
<div class="modal-button-row">
|
||||
<button
|
||||
class="modal-button-red"
|
||||
@click=${() => {
|
||||
this.chatEditor.resetValue();
|
||||
this.openPrivateMessage = false;
|
||||
}}
|
||||
?disabled="${this.isLoading}"
|
||||
>
|
||||
${translate("chatpage.cchange33")}
|
||||
</button>
|
||||
<button
|
||||
class="modal-button"
|
||||
@click=${this._sendMessage}
|
||||
?disabled="${this.isLoading}">
|
||||
${this.isLoading === false
|
||||
? this.renderSendText()
|
||||
: html`
|
||||
<paper-spinner-lite active></paper-spinner-lite>
|
||||
`}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-results-div">
|
||||
<chat-search-results
|
||||
.onClickFunc=${(result) => {
|
||||
this.userSelected = result;
|
||||
this.userFound = [];
|
||||
this.userFoundModalOpen = false;
|
||||
}}
|
||||
.closeFunc=${() => {
|
||||
this.userFoundModalOpen = false;
|
||||
this.userFound = [];
|
||||
}}
|
||||
.searchResults=${this.userFound}
|
||||
?isOpen=${this.userFoundModalOpen}
|
||||
?loading=${this.isLoading}>
|
||||
</chat-search-results>
|
||||
</div>
|
||||
</div>
|
||||
</wrapper-modal>
|
||||
|
||||
<!-- Blocked User Dialog -->
|
||||
<mwc-dialog id="blockedUserDialog">
|
||||
@ -445,9 +278,24 @@ class Chat extends LitElement {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.shadowRoot.getElementById('sendTo').addEventListener('keydown', stopKeyEventPropagation);
|
||||
const nameInput = this.shadowRoot.getElementById('sendTo');
|
||||
|
||||
nameInput.addEventListener('keydown', stopKeyEventPropagation);
|
||||
|
||||
this.shadowRoot.getElementById('messageBox').addEventListener('keydown', stopKeyEventPropagation);
|
||||
|
||||
// let typingTimer;
|
||||
// let doneTypingInterval = 3000;
|
||||
|
||||
// //on keyup, start the countdown
|
||||
// nameInput.addEventListener('keyup', () => {
|
||||
// clearTimeout(typingTimer);
|
||||
// if (nameInput.value) {
|
||||
// console.log("typing started!");
|
||||
// typingTimer = setTimeout(this.userSearch, doneTypingInterval);
|
||||
// }
|
||||
// });
|
||||
|
||||
const getDataFromURL = () => {
|
||||
let tempUrl = document.location.href
|
||||
let splitedUrl = decodeURI(tempUrl).split('?')
|
||||
@ -547,6 +395,196 @@ class Chat extends LitElement {
|
||||
parentEpml.imReady()
|
||||
}
|
||||
|
||||
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}`)
|
||||
}
|
||||
}
|
||||
|
||||
setChatEditor(editor) {
|
||||
this.chatEditor = editor;
|
||||
}
|
||||
|
||||
async _sendMessage() {
|
||||
this.isLoading = true;
|
||||
this.chatEditor.disable();
|
||||
const messageText = this.chatEditor.mirror.value;
|
||||
// Format and Sanitize Message
|
||||
const sanitizedMessage = messageText.replace(/ /gi, ' ').replace(/<br\s*[\/]?>/gi, '\n');
|
||||
const trimmedMessage = sanitizedMessage.trim();
|
||||
if (/^\s*$/.test(trimmedMessage)) {
|
||||
this.isLoading = false;
|
||||
this.chatEditor.enable();
|
||||
} else {
|
||||
const messageObject = {
|
||||
messageText: trimmedMessage,
|
||||
images: [''],
|
||||
repliedTo: '',
|
||||
version: 1
|
||||
}
|
||||
const stringifyMessageObject = JSON.stringify(messageObject)
|
||||
this.sendMessage(stringifyMessageObject);
|
||||
}
|
||||
}
|
||||
|
||||
async sendMessage(messageText) {
|
||||
this.isLoading = true;
|
||||
|
||||
const _recipient = this.shadowRoot.getElementById('sendTo').value;
|
||||
|
||||
let recipient;
|
||||
|
||||
const validateName = async (receiverName) => {
|
||||
let myRes;
|
||||
try {
|
||||
let myNameRes = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
url: `/names/${receiverName}`
|
||||
});
|
||||
if (myNameRes.error === 401) {
|
||||
myRes = false;
|
||||
} else {
|
||||
myRes = myNameRes;
|
||||
}
|
||||
return myRes;
|
||||
} catch (error) {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
const myNameRes = await validateName(_recipient);
|
||||
if (!myNameRes) {
|
||||
recipient = _recipient;
|
||||
} else {
|
||||
recipient = myNameRes.owner;
|
||||
};
|
||||
|
||||
const getAddressPublicKey = async () => {
|
||||
let isEncrypted;
|
||||
let _publicKey;
|
||||
|
||||
let addressPublicKey = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
url: `/addresses/publickey/${recipient}`
|
||||
})
|
||||
|
||||
if (addressPublicKey.error === 102) {
|
||||
_publicKey = false;
|
||||
let err4string = get("chatpage.cchange19");
|
||||
parentEpml.request('showSnackBar', `${err4string}`);
|
||||
this.chatEditor.enable();
|
||||
this.isLoading = false;
|
||||
} else if (addressPublicKey !== false) {
|
||||
isEncrypted = 1;
|
||||
_publicKey = addressPublicKey;
|
||||
sendMessageRequest(isEncrypted, _publicKey);
|
||||
} else {
|
||||
isEncrypted = 0;
|
||||
_publicKey = this.selectedAddress.address;
|
||||
sendMessageRequest(isEncrypted, _publicKey);
|
||||
}
|
||||
};
|
||||
let _reference = new Uint8Array(64);
|
||||
window.crypto.getRandomValues(_reference);
|
||||
let reference = window.parent.Base58.encode(_reference);
|
||||
const sendMessageRequest = async (isEncrypted, _publicKey) => {
|
||||
let chatResponse = await parentEpml.request('chat', {
|
||||
type: 18,
|
||||
nonce: this.selectedAddress.nonce,
|
||||
params: {
|
||||
timestamp: Date.now(),
|
||||
recipient: recipient,
|
||||
recipientPublicKey: _publicKey,
|
||||
hasChatReference: 0,
|
||||
message: messageText,
|
||||
lastReference: reference,
|
||||
proofOfWorkNonce: 0,
|
||||
isEncrypted: isEncrypted,
|
||||
isText: 1
|
||||
}
|
||||
});
|
||||
|
||||
_computePow(chatResponse);
|
||||
};
|
||||
|
||||
const _computePow = async (chatBytes) => {
|
||||
const difficulty = this.balance === 0 ? 12 : 8;
|
||||
const path = window.parent.location.origin + '/memory-pow/memory-pow.wasm.full';
|
||||
const worker = new WebWorker();
|
||||
let nonce = null;
|
||||
let chatBytesArray = null;
|
||||
await new Promise((res, rej) => {
|
||||
worker.postMessage({chatBytes, path, difficulty});
|
||||
worker.onmessage = e => {
|
||||
worker.terminate();
|
||||
chatBytesArray = e.data.chatBytesArray;
|
||||
nonce = e.data.nonce;
|
||||
res();
|
||||
}
|
||||
});
|
||||
|
||||
let _response = await parentEpml.request('sign_chat', {
|
||||
nonce: this.selectedAddress.nonce,
|
||||
chatBytesArray: chatBytesArray,
|
||||
chatNonce: nonce
|
||||
});
|
||||
|
||||
getSendChatResponse(_response);
|
||||
};
|
||||
|
||||
const getSendChatResponse = (response) => {
|
||||
if (response === true) {
|
||||
this.setActiveChatHeadUrl(`direct/${recipient}`);
|
||||
this.shadowRoot.getElementById('sendTo').value = "";
|
||||
this.openPrivateMessage = false;
|
||||
this.chatEditor.resetValue();
|
||||
} else if (response.error) {
|
||||
parentEpml.request('showSnackBar', response.message);
|
||||
} else {
|
||||
let err2string = get("chatpage.cchange21");
|
||||
parentEpml.request('showSnackBar', `${err2string}`);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
this.chatEditor.enable();
|
||||
};
|
||||
|
||||
// Exec..
|
||||
getAddressPublicKey();
|
||||
|
||||
}
|
||||
|
||||
insertImage(file) {
|
||||
if (file.type.includes('image')) {
|
||||
this.imageFile = file;
|
||||
this.chatEditor.disable();
|
||||
return;
|
||||
}
|
||||
parentEpml.request('showSnackBar', get("chatpage.cchange28"));
|
||||
}
|
||||
|
||||
renderLoadingText() {
|
||||
return html`${translate("chatpage.cchange2")}`
|
||||
}
|
||||
@ -720,7 +758,6 @@ class Chat extends LitElement {
|
||||
const compareArgs = (a, b) => {
|
||||
return b.timestamp - a.timestamp
|
||||
}
|
||||
|
||||
this.chatHeads = chatHeadMasterList.sort(compareArgs)
|
||||
}
|
||||
|
||||
@ -735,163 +772,6 @@ class Chat extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
_sendMessage() {
|
||||
|
||||
this.isLoading = true
|
||||
|
||||
const recipient = this.shadowRoot.getElementById('sendTo').value
|
||||
const messageBox = this.shadowRoot.getElementById('messageBox')
|
||||
const messageText = messageBox.value
|
||||
|
||||
if (recipient.length === 0) {
|
||||
this.isLoading = false
|
||||
} else if (messageText.length === 0) {
|
||||
this.isLoading = false
|
||||
} else {
|
||||
this.sendMessage()
|
||||
}
|
||||
}
|
||||
|
||||
async sendMessage(e) {
|
||||
|
||||
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 myNameRes = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
url: `/names/${receiverName}`
|
||||
})
|
||||
|
||||
if (myNameRes.error === 401) {
|
||||
myRes = false
|
||||
} else {
|
||||
myRes = myNameRes
|
||||
}
|
||||
return myRes
|
||||
}
|
||||
|
||||
const myNameRes = await validateName(_recipient)
|
||||
if (!myNameRes) {
|
||||
|
||||
recipient = _recipient
|
||||
} else {
|
||||
|
||||
recipient = myNameRes.owner
|
||||
}
|
||||
|
||||
let _reference = new Uint8Array(64);
|
||||
window.crypto.getRandomValues(_reference);
|
||||
|
||||
let sendTimestamp = Date.now()
|
||||
|
||||
let reference = window.parent.Base58.encode(_reference)
|
||||
|
||||
const getAddressPublicKey = async () => {
|
||||
let isEncrypted
|
||||
let _publicKey
|
||||
|
||||
let addressPublicKey = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
url: `/addresses/publickey/${recipient}`
|
||||
})
|
||||
|
||||
if (addressPublicKey.error === 102) {
|
||||
_publicKey = false
|
||||
let err4string = get("chatpage.cchange19")
|
||||
parentEpml.request('showSnackBar', `${err4string}`)
|
||||
this.isLoading = false
|
||||
} else if (addressPublicKey !== false) {
|
||||
isEncrypted = 1
|
||||
_publicKey = addressPublicKey
|
||||
sendMessageRequest(isEncrypted, _publicKey)
|
||||
} else {
|
||||
isEncrypted = 0
|
||||
_publicKey = this.selectedAddress.address
|
||||
sendMessageRequest(isEncrypted, _publicKey)
|
||||
}
|
||||
};
|
||||
|
||||
const sendMessageRequest = async (isEncrypted, _publicKey) => {
|
||||
const messageObject = {
|
||||
messageText,
|
||||
images: [''],
|
||||
repliedTo: '',
|
||||
version: 1
|
||||
}
|
||||
const stringifyMessageObject = JSON.stringify(messageObject)
|
||||
let chatResponse = await parentEpml.request('chat', {
|
||||
type: 18,
|
||||
nonce: this.selectedAddress.nonce,
|
||||
params: {
|
||||
timestamp: sendTimestamp,
|
||||
recipient: recipient,
|
||||
recipientPublicKey: _publicKey,
|
||||
hasChatReference: 0,
|
||||
message: stringifyMessageObject,
|
||||
lastReference: reference,
|
||||
proofOfWorkNonce: 0,
|
||||
isEncrypted: isEncrypted,
|
||||
isText: 1
|
||||
}
|
||||
})
|
||||
|
||||
_computePow(chatResponse)
|
||||
}
|
||||
|
||||
const _computePow = async (chatBytes) => {
|
||||
|
||||
const _chatBytesArray = Object.keys(chatBytes).map(function (key) { return chatBytes[key]; });
|
||||
const chatBytesArray = new Uint8Array(_chatBytesArray)
|
||||
const chatBytesHash = new window.parent.Sha256().process(chatBytesArray).finish().result
|
||||
const hashPtr = window.parent.sbrk(32, window.parent.heap);
|
||||
const hashAry = new Uint8Array(window.parent.memory.buffer, hashPtr, 32)
|
||||
|
||||
hashAry.set(chatBytesHash);
|
||||
|
||||
const difficulty = this.balance === 0 ? 12 : 8
|
||||
|
||||
const workBufferLength = 8 * 1024 * 1024;
|
||||
const workBufferPtr = window.parent.sbrk(workBufferLength, window.parent.heap)
|
||||
|
||||
let nonce = window.parent.computePow(hashPtr, workBufferPtr, workBufferLength, difficulty)
|
||||
|
||||
let _response = await parentEpml.request('sign_chat', {
|
||||
nonce: this.selectedAddress.nonce,
|
||||
chatBytesArray: chatBytesArray,
|
||||
chatNonce: nonce
|
||||
})
|
||||
|
||||
getSendChatResponse(_response)
|
||||
}
|
||||
|
||||
const getSendChatResponse = (response) => {
|
||||
|
||||
if (response === true) {
|
||||
messageBox.value = ""
|
||||
let err5string = get("chatpage.cchange20")
|
||||
parentEpml.request('showSnackBar', `${err5string}`)
|
||||
this.isLoading = false
|
||||
} else if (response.error) {
|
||||
parentEpml.request('showSnackBar', response.message)
|
||||
this.isLoading = false
|
||||
} else {
|
||||
let err6string = get("chatpage.cchange21")
|
||||
parentEpml.request('showSnackBar', `${err6string}`)
|
||||
this.isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
// Exec..
|
||||
getAddressPublicKey()
|
||||
}
|
||||
|
||||
_textMenu(event) {
|
||||
|
||||
const getSelectedText = () => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user