forked from Qortal/qortal-ui
Merge branch 'feature/implement-logic-edit-reply-messages' of https://github.com/PhillipLangMartinez/qortal-ui into feature/implement-UI-edit-reply-messages
This commit is contained in:
commit
353cacb789
@ -489,7 +489,9 @@
|
|||||||
"cchange27": "A registered name is required to send images",
|
"cchange27": "A registered name is required to send images",
|
||||||
"cchange28": "This file is not an image",
|
"cchange28": "This file is not an image",
|
||||||
"cchange29": "Maximum message size is 1000 bytes",
|
"cchange29": "Maximum message size is 1000 bytes",
|
||||||
"cchange30": "Cancel"
|
"cchange30": "Uploading image. This may take up to one minute.",
|
||||||
|
"cchange31": "Deleting image. This may take up to one minute.",
|
||||||
|
"cchange33": "Cancel"
|
||||||
},
|
},
|
||||||
"welcomepage": {
|
"welcomepage": {
|
||||||
"wcchange1": "Welcome to Q-Chat",
|
"wcchange1": "Welcome to Q-Chat",
|
||||||
|
@ -58,8 +58,9 @@ class ChatPage extends LitElement {
|
|||||||
repliedToMessageObj: { type: Object },
|
repliedToMessageObj: { type: Object },
|
||||||
editedMessageObj: { type: Object },
|
editedMessageObj: { type: Object },
|
||||||
iframeHeight: { type: Number },
|
iframeHeight: { type: Number },
|
||||||
chatMessageSize: { type: Number },
|
chatMessageSize: { type: Number},
|
||||||
imageFile: { type: Object },
|
imageFile: {type: Object},
|
||||||
|
isUploadingImage: {type: Boolean},
|
||||||
caption: { type: String }
|
caption: { type: String }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -386,6 +387,86 @@ class ChatPage extends LitElement {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.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)
|
||||||
|
}
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialogCustomInner {
|
||||||
|
min-width: 300px;
|
||||||
|
height: 40px;
|
||||||
|
background-color: var(--white);
|
||||||
|
box-shadow: var(--mdc-dialog-box-shadow, 0px 11px 15px -7px rgba(0, 0, 0, 0.2), 0px 24px 38px 3px rgba(0, 0, 0, 0.14), 0px 9px 46px 8px rgba(0, 0, 0, 0.12));
|
||||||
|
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.6em;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.mdc-dialog .mdc-dialog__surface {
|
.mdc-dialog .mdc-dialog__surface {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
@ -530,7 +611,7 @@ class ChatPage extends LitElement {
|
|||||||
this.imageFile = null
|
this.imageFile = null
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
${translate("chatpage.cchange30")}
|
${translate("chatpage.cchange33")}
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
<mwc-button
|
<mwc-button
|
||||||
slot="primaryAction"
|
slot="primaryAction"
|
||||||
@ -654,6 +735,31 @@ class ChatPage extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
${(this.isUploadingImage || this.isDeletingImage) ? html`
|
||||||
|
<div class="dialogCustom">
|
||||||
|
<div class="dialogCustomInner">
|
||||||
|
<div class="dialog-container">
|
||||||
|
|
||||||
|
<div class="row between">
|
||||||
|
|
||||||
|
<div class=${`smallLoading marginLoader`}></div>
|
||||||
|
<p>
|
||||||
|
${this.isDeletingImage ?
|
||||||
|
translate("chatpage.cchange31") : translate("chatpage.cchange30")}
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`: ''}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
@ -1398,6 +1504,7 @@ class ChatPage extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(outSideMsg && outSideMsg.type === 'delete'){
|
if(outSideMsg && outSideMsg.type === 'delete'){
|
||||||
|
this.isDeletingImage = true
|
||||||
const userName = outSideMsg.name
|
const userName = outSideMsg.name
|
||||||
const identifier = outSideMsg.identifier
|
const identifier = outSideMsg.identifier
|
||||||
let compressedFile = ''
|
let compressedFile = ''
|
||||||
@ -1454,11 +1561,12 @@ class ChatPage extends LitElement {
|
|||||||
selectedAddress: this.selectedAddress,
|
selectedAddress: this.selectedAddress,
|
||||||
worker: new WebWorkerImage()
|
worker: new WebWorkerImage()
|
||||||
})
|
})
|
||||||
} catch (error) {
|
this.isDeletingImage = false
|
||||||
console.error(error)
|
} catch (error) {
|
||||||
this.isLoading = false;
|
console.error(error)
|
||||||
this.chatEditor.enable();
|
this.isLoading = false;
|
||||||
return
|
this.chatEditor.enable();
|
||||||
|
return
|
||||||
}
|
}
|
||||||
typeMessage = 'edit';
|
typeMessage = 'edit';
|
||||||
let chatReference = outSideMsg.editedMessageObj.reference;
|
let chatReference = outSideMsg.editedMessageObj.reference;
|
||||||
@ -1485,7 +1593,7 @@ class ChatPage extends LitElement {
|
|||||||
|
|
||||||
}
|
}
|
||||||
else if (outSideMsg && outSideMsg.type === 'image') {
|
else if (outSideMsg && outSideMsg.type === 'image') {
|
||||||
|
this.isUploadingImage = true;
|
||||||
const userName = await getName(this.selectedAddress.address);
|
const userName = await getName(this.selectedAddress.address);
|
||||||
if (!userName) {
|
if (!userName) {
|
||||||
parentEpml.request('showSnackBar', get("chatpage.cchange27"));
|
parentEpml.request('showSnackBar', get("chatpage.cchange27"));
|
||||||
@ -1520,6 +1628,7 @@ class ChatPage extends LitElement {
|
|||||||
this.chatEditor.enable();
|
this.chatEditor.enable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await publishData({
|
await publishData({
|
||||||
registeredName: userName,
|
registeredName: userName,
|
||||||
@ -1532,6 +1641,8 @@ class ChatPage extends LitElement {
|
|||||||
selectedAddress: this.selectedAddress,
|
selectedAddress: this.selectedAddress,
|
||||||
worker: new WebWorkerImage()
|
worker: new WebWorkerImage()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.isUploadingImage = false
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
|
@ -356,6 +356,10 @@ export const chatStyles = css`
|
|||||||
.image-container {
|
.image-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
.defaultSize {
|
||||||
|
width:45vh;
|
||||||
|
height:40vh
|
||||||
|
}
|
||||||
.image-delete-icon {
|
.image-delete-icon {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
@ -47,10 +47,80 @@ class ChatScroller extends LitElement {
|
|||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
console.log({messages: this.messages})
|
||||||
|
|
||||||
|
let formattedMessages = this.messages.reduce((messageArray, message)=> {
|
||||||
|
const lastGroupedMessage = messageArray[messageArray.length - 1]
|
||||||
|
let timestamp
|
||||||
|
let sender
|
||||||
|
let repliedToData
|
||||||
|
if(lastGroupedMessage){
|
||||||
|
timestamp = lastGroupedMessage.timestamp
|
||||||
|
sender = lastGroupedMessage.sender
|
||||||
|
repliedToData = lastGroupedMessage.repliedToData
|
||||||
|
}
|
||||||
|
const isSameGroup = Math.abs(timestamp - message.timestamp) < 600000 && sender === message.sender && !repliedToData
|
||||||
|
|
||||||
|
if(isSameGroup){
|
||||||
|
messageArray[messageArray.length - 1].messages = [...(messageArray[messageArray.length - 1]?.messages || []), message]
|
||||||
|
} else {
|
||||||
|
messageArray.push({
|
||||||
|
messages: [message],
|
||||||
|
...message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return messageArray
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
console.log({formattedMessages})
|
||||||
return html`
|
return html`
|
||||||
<ul id="viewElement" class="chat-list clearfix">
|
<ul id="viewElement" class="chat-list clearfix">
|
||||||
<div id="upObserver"></div>
|
<div id="upObserver"></div>
|
||||||
${repeat(
|
${formattedMessages.map((formattedMessage)=> {
|
||||||
|
|
||||||
|
return repeat(
|
||||||
|
formattedMessage.messages,
|
||||||
|
(message) => message.reference,
|
||||||
|
(message, indexMessage) => html`
|
||||||
|
<message-template
|
||||||
|
.emojiPicker=${this.emojiPicker}
|
||||||
|
.escapeHTML=${this.escapeHTML}
|
||||||
|
.messageObj=${message}
|
||||||
|
.hideMessages=${this.hideMessages}
|
||||||
|
.setRepliedToMessageObj=${this.setRepliedToMessageObj}
|
||||||
|
.setEditedMessageObj=${this.setEditedMessageObj}
|
||||||
|
.focusChatEditor=${this.focusChatEditor}
|
||||||
|
.sendMessage=${this.sendMessage}
|
||||||
|
?isfirstmessage=${indexMessage === 0}
|
||||||
|
?isSingleMessageInGroup=${formattedMessage.messages.length > 1}
|
||||||
|
>
|
||||||
|
</message-template>`
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<!-- ${repeat(
|
||||||
|
testMessages,
|
||||||
|
(testMessage)=> testMessage.signature,
|
||||||
|
(testMessage)=> {
|
||||||
|
return repeat(
|
||||||
|
testMessage.messages,
|
||||||
|
(message) => message.reference,
|
||||||
|
(message, indexMessage) => html`
|
||||||
|
<message-template
|
||||||
|
.emojiPicker=${this.emojiPicker}
|
||||||
|
.escapeHTML=${this.escapeHTML}
|
||||||
|
.messageObj=${message}
|
||||||
|
.hideMessages=${this.hideMessages}
|
||||||
|
.setRepliedToMessageObj=${this.setRepliedToMessageObj}
|
||||||
|
.setEditedMessageObj=${this.setEditedMessageObj}
|
||||||
|
.focusChatEditor=${this.focusChatEditor}
|
||||||
|
.sendMessage=${this.sendMessage}
|
||||||
|
?isfirstmessage=${indexMessage === 0}
|
||||||
|
>
|
||||||
|
</message-template>`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)} -->
|
||||||
|
<!-- ${repeat(
|
||||||
this.messages,
|
this.messages,
|
||||||
(message) => message.reference,
|
(message) => message.reference,
|
||||||
(message) => html`
|
(message) => html`
|
||||||
@ -65,7 +135,7 @@ class ChatScroller extends LitElement {
|
|||||||
.sendMessage=${this.sendMessage}
|
.sendMessage=${this.sendMessage}
|
||||||
>
|
>
|
||||||
</message-template>`
|
</message-template>`
|
||||||
)}
|
)} -->
|
||||||
<div id='downObserver'></div>
|
<div id='downObserver'></div>
|
||||||
<div class='last-message-ref'>
|
<div class='last-message-ref'>
|
||||||
<vaadin-icon class='arrow-down-icon' icon='vaadin:arrow-circle-down' slot='icon' @click=${() => {
|
<vaadin-icon class='arrow-down-icon' icon='vaadin:arrow-circle-down' slot='icon' @click=${() => {
|
||||||
@ -164,7 +234,10 @@ class MessageTemplate extends LitElement {
|
|||||||
setEditedMessageObj: { type: Function },
|
setEditedMessageObj: { type: Function },
|
||||||
focusChatEditor: { type: Function },
|
focusChatEditor: { type: Function },
|
||||||
sendMessage: { type: Function },
|
sendMessage: { type: Function },
|
||||||
openDialogImage: {type: Function}
|
openDialogImage: {type: Function},
|
||||||
|
isImageLoaded: {type: Boolean},
|
||||||
|
isFirstMessage: {type: Boolean},
|
||||||
|
isSingleMessageInGroup: {type: Boolean}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,6 +250,9 @@ class MessageTemplate extends LitElement {
|
|||||||
this.myAddress = window.parent.reduxStore.getState().app.selectedAddress.address
|
this.myAddress = window.parent.reduxStore.getState().app.selectedAddress.address
|
||||||
this.imageFetches = 0
|
this.imageFetches = 0
|
||||||
this.openDialogImage = false
|
this.openDialogImage = false
|
||||||
|
this.isImageLoaded = false
|
||||||
|
this.isFirstMessage = false
|
||||||
|
this.isSingleMessageInGroup = false
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = [chatStyles]
|
static styles = [chatStyles]
|
||||||
@ -210,12 +286,13 @@ class MessageTemplate extends LitElement {
|
|||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const hidemsg = this.hideMessages;
|
console.log('isFirst', this.isFirstMessage)
|
||||||
let message = "";
|
const hidemsg = this.hideMessages
|
||||||
let reactions = [];
|
let message = ""
|
||||||
let repliedToData = null;
|
let reactions = []
|
||||||
let image = null;
|
let repliedToData = null
|
||||||
let isImageDeleted = false;
|
let image = null
|
||||||
|
let isImageDeleted = false
|
||||||
try {
|
try {
|
||||||
const parsedMessageObj = JSON.parse(this.messageObj.decodedMessage);
|
const parsedMessageObj = JSON.parse(this.messageObj.decodedMessage);
|
||||||
message = parsedMessageObj.messageText;
|
message = parsedMessageObj.messageText;
|
||||||
@ -246,15 +323,19 @@ class MessageTemplate extends LitElement {
|
|||||||
} else {
|
} else {
|
||||||
avatarImg = html`<img src='/img/incognito.png' style="max-width:100%; max-height:100%;" onerror="this.onerror=null;" />`
|
avatarImg = html`<img src='/img/incognito.png' style="max-width:100%; max-height:100%;" onerror="this.onerror=null;" />`
|
||||||
}
|
}
|
||||||
|
|
||||||
const createImage=(imageUrl)=>{
|
const createImage=(imageUrl)=>{
|
||||||
const imageHTMLRes = new Image();
|
const imageHTMLRes = new Image();
|
||||||
imageHTMLRes.src = imageUrl;
|
imageHTMLRes.src = imageUrl;
|
||||||
imageHTMLRes.style= "max-width:45vh; max-height:40vh; border-radius: 5px; cursor: pointer";
|
imageHTMLRes.style= "max-width:45vh; max-height:40vh; border-radius: 5px; cursor: pointer";
|
||||||
imageHTMLRes.onclick= () => {
|
imageHTMLRes.onclick= () => {
|
||||||
this.openDialogImage = true
|
this.openDialogImage = true
|
||||||
};
|
}
|
||||||
imageHTMLRes.onerror = () => {
|
imageHTMLRes.onload = ()=> {
|
||||||
|
this.isImageLoaded = true
|
||||||
|
}
|
||||||
|
imageHTMLRes.onerror = ()=> {
|
||||||
|
|
||||||
console.log('inputRef', this.imageFetches)
|
console.log('inputRef', this.imageFetches)
|
||||||
if (this.imageFetches < 4) {
|
if (this.imageFetches < 4) {
|
||||||
setTimeout(()=> {
|
setTimeout(()=> {
|
||||||
@ -267,6 +348,8 @@ class MessageTemplate extends LitElement {
|
|||||||
imageHTMLRes.onclick= () => {
|
imageHTMLRes.onclick= () => {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.isImageLoaded = true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return imageHTMLRes;
|
return imageHTMLRes;
|
||||||
@ -293,6 +376,8 @@ class MessageTemplate extends LitElement {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return hideit ? html`<li class="clearfix"></li>` : html`
|
return hideit ? html`<li class="clearfix"></li>` : html`
|
||||||
<li class="clearfix message-parent">
|
<li class="clearfix message-parent">
|
||||||
<div class="message-data ${this.messageObj.sender === this.myAddress ? "" : ""}">
|
<div class="message-data ${this.messageObj.sender === this.myAddress ? "" : ""}">
|
||||||
@ -312,7 +397,7 @@ class MessageTemplate extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
`}
|
`}
|
||||||
${image && !isImageDeleted ? html`
|
${image && !isImageDeleted ? html`
|
||||||
<div class="image-container">
|
<div class=${[`image-container`, !this.isImageLoaded ? 'defaultSize' : ''].join(' ')}>
|
||||||
${imageHTML}<vaadin-icon
|
${imageHTML}<vaadin-icon
|
||||||
@click=${() => this.sendMessage({
|
@click=${() => this.sendMessage({
|
||||||
type: 'delete',
|
type: 'delete',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user