Browse Source

Added delete attachment UI

pull/127/head
Justin Ferrari 2 years ago
parent
commit
66f32f799a
  1. 6
      qortal-ui-core/language/us.json
  2. 22
      qortal-ui-core/package.json
  3. 22
      qortal-ui-plugins/package.json
  4. 181
      qortal-ui-plugins/plugins/core/components/ChatPage.js
  5. 10
      qortal-ui-plugins/plugins/core/components/ChatScroller-css.js
  6. 71
      qortal-ui-plugins/plugins/core/components/ChatScroller.js

6
qortal-ui-core/language/us.json

@ -574,7 +574,11 @@
"cchange65": "Uploading attachment. This may take up to one minute.", "cchange65": "Uploading attachment. This may take up to one minute.",
"cchange66": "Deleting attachment. This may take up to one minute.", "cchange66": "Deleting attachment. This may take up to one minute.",
"cchange67": "Attachment size exceeds 1 MB", "cchange67": "Attachment size exceeds 1 MB",
"cchange68": "edited" "cchange68": "edited",
"cchange69": "Are you sure you want to delete this image?",
"cchange70": "Are you sure you want to delete this attachment?",
"cchange71": "This image has been deleted",
"cchange72": "This attachment has been deleted"
}, },
"welcomepage": { "welcomepage": {
"wcchange1": "Welcome to Q-Chat", "wcchange1": "Welcome to Q-Chat",

22
qortal-ui-core/package.json

@ -1,6 +1,6 @@
{ {
"name": "qortal-ui-core", "name": "qortal-ui-core",
"version": "2.2.5", "version": "3.0.0",
"description": "Qortal Project - decentralize the world - Data storage, communications, web hosting, decentralized trading, complete infrastructure for the future blockchain-based Internet", "description": "Qortal Project - decentralize the world - Data storage, communications, web hosting, decentralized trading, complete infrastructure for the future blockchain-based Internet",
"keywords": [ "keywords": [
"QORT", "QORT",
@ -17,7 +17,7 @@
"author": "QORTAL <[email protected]>", "author": "QORTAL <[email protected]>",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@hapi/hapi": "21.1.0", "@hapi/hapi": "21.2.0",
"@hapi/inert": "7.0.0", "@hapi/inert": "7.0.0",
"sass": "1.57.1" "sass": "1.57.1"
}, },
@ -53,28 +53,28 @@
"@polymer/paper-spinner": "3.0.2", "@polymer/paper-spinner": "3.0.2",
"@polymer/paper-toast": "3.0.1", "@polymer/paper-toast": "3.0.1",
"@polymer/paper-tooltip": "3.0.1", "@polymer/paper-tooltip": "3.0.1",
"@rollup/plugin-alias": "4.0.2", "@rollup/plugin-alias": "4.0.3",
"@rollup/plugin-babel": "6.0.3", "@rollup/plugin-babel": "6.0.3",
"@rollup/plugin-commonjs": "24.0.0", "@rollup/plugin-commonjs": "24.0.1",
"@rollup/plugin-node-resolve": "15.0.1", "@rollup/plugin-node-resolve": "15.0.1",
"@rollup/plugin-replace": "5.0.2", "@rollup/plugin-replace": "5.0.2",
"@rollup/plugin-terser": "0.3.0", "@rollup/plugin-terser": "0.3.0",
"@vaadin/button": "23.3.3", "@vaadin/button": "23.3.5",
"@vaadin/grid": "23.3.3", "@vaadin/grid": "23.3.5",
"@vaadin/icons": "23.3.3", "@vaadin/icons": "23.3.5",
"@vaadin/password-field": "23.3.3", "@vaadin/password-field": "23.3.5",
"@vaadin/tooltip": "23.3.3", "@vaadin/tooltip": "23.3.5",
"asmcrypto.js": "2.3.2", "asmcrypto.js": "2.3.2",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"epml": "0.3.3", "epml": "0.3.3",
"file-saver": "2.0.5", "file-saver": "2.0.5",
"lit": "2.6.0", "lit": "2.6.1",
"lit-translate": "2.0.1", "lit-translate": "2.0.1",
"pwa-helpers": "0.9.1", "pwa-helpers": "0.9.1",
"random-sentence-generator": "0.0.8", "random-sentence-generator": "0.0.8",
"redux": "4.2.0", "redux": "4.2.0",
"redux-thunk": "2.4.2", "redux-thunk": "2.4.2",
"rollup": "3.9.1", "rollup": "3.10.1",
"rollup-plugin-node-globals": "1.4.0", "rollup-plugin-node-globals": "1.4.0",
"rollup-plugin-progress": "1.1.2", "rollup-plugin-progress": "1.1.2",
"rollup-plugin-scss": "3.0.0", "rollup-plugin-scss": "3.0.0",

22
qortal-ui-plugins/package.json

@ -1,6 +1,6 @@
{ {
"name": "qortal-ui-plugins", "name": "qortal-ui-plugins",
"version": "2.2.5", "version": "3.0.0",
"description": "Qortal Project - decentralize the world - Data storage, communications, web hosting, decentralized trading, complete infrastructure for the future blockchain-based Internet", "description": "Qortal Project - decentralize the world - Data storage, communications, web hosting, decentralized trading, complete infrastructure for the future blockchain-based Internet",
"keywords": [ "keywords": [
"QORT", "QORT",
@ -64,24 +64,24 @@
"@polymer/paper-slider": "3.0.1", "@polymer/paper-slider": "3.0.1",
"@polymer/paper-spinner": "3.0.2", "@polymer/paper-spinner": "3.0.2",
"@polymer/paper-tooltip": "3.0.1", "@polymer/paper-tooltip": "3.0.1",
"@rollup/plugin-alias": "4.0.2", "@rollup/plugin-alias": "4.0.3",
"@rollup/plugin-babel": "6.0.3", "@rollup/plugin-babel": "6.0.3",
"@rollup/plugin-commonjs": "24.0.0", "@rollup/plugin-commonjs": "24.0.1",
"@rollup/plugin-node-resolve": "15.0.1", "@rollup/plugin-node-resolve": "15.0.1",
"@rollup/plugin-replace": "5.0.2", "@rollup/plugin-replace": "5.0.2",
"@rollup/plugin-terser": "0.3.0", "@rollup/plugin-terser": "0.3.0",
"@vaadin/avatar": "23.3.3", "@vaadin/avatar": "23.3.5",
"@vaadin/button": "23.3.3", "@vaadin/button": "23.3.5",
"@vaadin/grid": "23.3.3", "@vaadin/grid": "23.3.5",
"@vaadin/icons": "23.3.3", "@vaadin/icons": "23.3.5",
"@vaadin/tooltip": "23.3.3", "@vaadin/tooltip": "23.3.5",
"epml": "0.3.3", "epml": "0.3.3",
"file-saver": "2.0.5", "file-saver": "2.0.5",
"highcharts": "10.3.2", "highcharts": "10.3.3",
"html-escaper": "3.0.3", "html-escaper": "3.0.3",
"lit": "2.6.0", "lit": "2.6.1",
"lit-translate": "2.0.1", "lit-translate": "2.0.1",
"rollup": "3.9.1", "rollup": "3.10.1",
"rollup-plugin-node-globals": "1.4.0", "rollup-plugin-node-globals": "1.4.0",
"rollup-plugin-progress": "1.1.2", "rollup-plugin-progress": "1.1.2",
"rollup-plugin-web-worker-loader": "1.6.1" "rollup-plugin-web-worker-loader": "1.6.1"

181
qortal-ui-plugins/plugins/core/components/ChatPage.js

@ -79,7 +79,9 @@ class ChatPage extends LitElement {
imageFile: { type: Object }, imageFile: { type: Object },
attachment: { type: Object }, attachment: { type: Object },
isUploadingImage: { type: Boolean }, isUploadingImage: { type: Boolean },
isDeletingImage: { type: Boolean },
isUploadingAttachment: { type: Boolean }, isUploadingAttachment: { type: Boolean },
isDeletingAttachment: { type: Boolean },
userLanguage: { type: String }, userLanguage: { type: String },
lastMessageRefVisible: { type: Boolean }, lastMessageRefVisible: { type: Boolean },
isLoadingOldMessages: { type: Boolean }, isLoadingOldMessages: { type: Boolean },
@ -1088,13 +1090,14 @@ class ChatPage extends LitElement {
</div> </div>
</div> </div>
`: ''} `: ''}
${(this.isUploadingAttachment) ? html` ${(this.isUploadingAttachment || this.isDeletingAttachment) ? html`
<div class="dialogCustom"> <div class="dialogCustom">
<div class="dialogCustomInner"> <div class="dialogCustomInner">
<div class="dialog-container-loader"> <div class="dialog-container-loader">
<div class=${`smallLoading marginLoader`}></div> <div class=${`smallLoading marginLoader`}></div>
<p> <p>
${translate("chatpage.cchange65")} ${this.isDeletingAttachment ?
translate("chatpage.cchange66") : translate("chatpage.cchange65")}
</p> </p>
</div> </div>
</div> </div>
@ -2419,56 +2422,146 @@ class ChatPage extends LitElement {
this.webWorkerFile = new WebWorkerFile(); this.webWorkerFile = new WebWorkerFile();
} }
const b64toBlob = (b64Data, contentType='', sliceSize=512) => { const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
const byteCharacters = atob(b64Data); const byteCharacters = atob(b64Data);
const byteArrays = []; const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize); const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length); const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) { for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i); byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
} }
const byteArray = new Uint8Array(byteNumbers); const blob = new Blob(byteArrays, {type: contentType});
byteArrays.push(byteArray); return blob;
} }
const blob = b64toBlob(str, 'image/png');
await new Promise(resolve => {
new Compressor(blob, {
quality: 0.6,
maxWidth: 500,
success(result) {
const file = new File([result], "name", {
type: 'image/png'
});
compressedFile = file;
resolve();
},
error(err) {
console.log(err.message);
},
})
})
try {
await publishData({
registeredName: userName,
file : compressedFile,
service: 'QCHAT_IMAGE',
identifier: identifier,
parentEpml,
metaData: undefined,
uploadType: 'file',
selectedAddress: this.selectedAddress,
worker: workerImage
})
this.isDeletingImage = false
} catch (error) {
this.isLoading = false;
return
}
typeMessage = 'edit';
let chatReference = outSideMsg.editedMessageObj.reference;
if(outSideMsg.editedMessageObj.chatReference){
chatReference = outSideMsg.editedMessageObj.chatReference;
}
const blob = new Blob(byteArrays, {type: contentType}); let message = "";
return blob; try {
} const parsedMessageObj = JSON.parse(outSideMsg.editedMessageObj.decodedMessage);
const blob = b64toBlob(str, 'image/png'); message = parsedMessageObj;
await new Promise(resolve => {
new Compressor(blob, { } catch (error) {
quality: 0.6, message = outSideMsg.editedMessageObj.decodedMessage;
maxWidth: 500, }
success(result) { const messageObject = {
const file = new File([result], "name", { ...message,
type: 'image/png' isImageDeleted: true
}); }
const stringifyMessageObject = JSON.stringify(messageObject);
compressedFile = file; this.sendMessage(stringifyMessageObject, typeMessage, chatReference);
resolve(); } else if (outSideMsg && outSideMsg.type === 'deleteAttachment') {
}, this.isDeletingAttachment = true;
error(err) { let compressedFile = ''
console.log(err.message); var str = "iVBORw0KGgoAAAANSUhEUgAAAsAAAAGMAQMAAADuk4YmAAAAA1BMVEX///+nxBvIAAAAAXRSTlMAQObYZgAAADlJREFUeF7twDEBAAAAwiD7p7bGDlgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAGJrAABgPqdWQAAAABJRU5ErkJggg==";
}, const userName = outSideMsg.name;
const identifier = outSideMsg.identifier;
if (this.webWorkerFile) {
workerAttachment = this.webWorkerFile;
} else {
this.webWorkerFile = new WebWorkerFile();
}
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
const blob = b64toBlob(str, 'image/png');
await new Promise(resolve => {
new Compressor(blob, {
quality: 0.6,
maxWidth: 500,
success(result) {
const file = new File([result], "name", {
type: 'image/png'
});
compressedFile = file;
resolve();
},
error(err) {
console.log(err.message);
},
})
}) })
})
try { try {
await publishData({ await publishData({
registeredName: userName, registeredName: userName,
file : compressedFile, file: compressedFile,
service: 'QCHAT_IMAGE', service: 'QCHAT_ATTACHMENT',
identifier: identifier, identifier: identifier,
parentEpml, parentEpml,
metaData: undefined, metaData: undefined,
uploadType: 'file', uploadType: 'file',
selectedAddress: this.selectedAddress, selectedAddress: this.selectedAddress,
worker: workerImage worker: workerAttachment
}) })
this.isDeletingImage = false this.isDeletingAttachment = false
} catch (error) { } catch (error) {
this.isLoading = false; this.isLoading = false;
return return
@ -2479,7 +2572,7 @@ class ChatPage extends LitElement {
if(outSideMsg.editedMessageObj.chatReference){ if(outSideMsg.editedMessageObj.chatReference){
chatReference = outSideMsg.editedMessageObj.chatReference; chatReference = outSideMsg.editedMessageObj.chatReference;
} }
let message = ""; let message = "";
try { try {
const parsedMessageObj = JSON.parse(outSideMsg.editedMessageObj.decodedMessage); const parsedMessageObj = JSON.parse(outSideMsg.editedMessageObj.decodedMessage);
@ -2490,13 +2583,11 @@ class ChatPage extends LitElement {
} }
const messageObject = { const messageObject = {
...message, ...message,
isImageDeleted: true isAttachmentDeleted: true
} }
const stringifyMessageObject = JSON.stringify(messageObject); const stringifyMessageObject = JSON.stringify(messageObject);
this.sendMessage(stringifyMessageObject, typeMessage, chatReference); this.sendMessage(stringifyMessageObject, typeMessage, chatReference);
} else if (outSideMsg && outSideMsg.type === 'image') {
}
else if (outSideMsg && outSideMsg.type === 'image') {
this.isUploadingImage = true; this.isUploadingImage = true;
const userName = await getName(this.selectedAddress.address); const userName = await getName(this.selectedAddress.address);
if (!userName) { if (!userName) {

10
qortal-ui-plugins/plugins/core/components/ChatScroller-css.js

@ -649,11 +649,6 @@ export const chatStyles = css`
cursor: pointer; cursor: pointer;
} }
.attachment-container:hover .download-icon::before {
background-color: rgb(161 158 158 / 41%);
}
.attachment-icon-container { .attachment-icon-container {
display: flex; display: flex;
@ -704,6 +699,11 @@ export const chatStyles = css`
background-color: transparent; background-color: transparent;
} }
.download-icon:hover::before {
background-color: rgb(161 158 158 / 41%);
}
.download-icon::before { .download-icon::before {
content: ""; content: "";
position: absolute; position: absolute;

71
qortal-ui-plugins/plugins/core/components/ChatScroller.js

@ -71,7 +71,6 @@ class ChatScroller extends LitElement {
} }
render() { render() {
console.log(4, "here");
let formattedMessages = this.messages.reduce((messageArray, message, index) => { let formattedMessages = this.messages.reduce((messageArray, message, index) => {
const lastGroupedMessage = messageArray[messageArray.length - 1]; const lastGroupedMessage = messageArray[messageArray.length - 1];
let timestamp; let timestamp;
@ -262,6 +261,7 @@ class MessageTemplate extends LitElement {
sendMessageForward: { attribute: false }, sendMessageForward: { attribute: false },
openDialogImage: { attribute: false }, openDialogImage: { attribute: false },
openDeleteImage: { type: Boolean }, openDeleteImage: { type: Boolean },
openDeleteAttachment: { type: Boolean },
isImageLoaded: { type: Boolean }, isImageLoaded: { type: Boolean },
isFirstMessage: { type: Boolean }, isFirstMessage: { type: Boolean },
isSingleMessageInGroup: { type: Boolean }, isSingleMessageInGroup: { type: Boolean },
@ -337,7 +337,6 @@ class MessageTemplate extends LitElement {
} }
render() { render() {
console.log(this.messageObj, "message object here");
const hidemsg = this.hideMessages; const hidemsg = this.hideMessages;
let message = ""; let message = "";
let messageVersion2 = "" let messageVersion2 = ""
@ -345,6 +344,7 @@ class MessageTemplate extends LitElement {
let repliedToData = null; let repliedToData = null;
let image = null; let image = null;
let isImageDeleted = false; let isImageDeleted = false;
let isAttachmentDeleted = false;
let version = 0; let version = 0;
let isForwarded = false let isForwarded = false
let isEdited = false let isEdited = false
@ -363,6 +363,7 @@ class MessageTemplate extends LitElement {
message = parsedMessageObj.messageText; message = parsedMessageObj.messageText;
repliedToData = this.messageObj.repliedToData; repliedToData = this.messageObj.repliedToData;
isImageDeleted = parsedMessageObj.isImageDeleted; isImageDeleted = parsedMessageObj.isImageDeleted;
isAttachmentDeleted = parsedMessageObj.isAttachmentDeleted;
reactions = parsedMessageObj.reactions || []; reactions = parsedMessageObj.reactions || [];
version = parsedMessageObj.version version = parsedMessageObj.version
isForwarded = parsedMessageObj.type === 'forward' isForwarded = parsedMessageObj.type === 'forward'
@ -588,16 +589,18 @@ class MessageTemplate extends LitElement {
<div <div
class=${[`image-container`, !this.isImageLoaded ? 'defaultSize' : ''].join(' ')} class=${[`image-container`, !this.isImageLoaded ? 'defaultSize' : ''].join(' ')}
style=${this.isFirstMessage && "margin-top: 10px;"}> style=${this.isFirstMessage && "margin-top: 10px;"}>
${imageHTML}<vaadin-icon ${imageHTML}
@click=${() => { <vaadin-icon
this.openDeleteImage = true; @click=${() => {
}} this.openDeleteImage = true;
class="image-delete-icon" icon="vaadin:close" slot="icon"></vaadin-icon> }}
class="image-delete-icon" icon="vaadin:close" slot="icon">
</vaadin-icon>
</div> </div>
` : image && isImageDeleted ? html` ` : image && isImageDeleted ? html`
<p class="image-deleted-msg">This image has been deleted</p> <p class="image-deleted-msg">${translate("chatpage.cchange71")}</p>
` : html``} ` : html``}
${attachment ? ${attachment && !isAttachmentDeleted ?
html` html`
<div @click=${async () => await this.downloadAttachment(attachment)} class="attachment-container"> <div @click=${async () => await this.downloadAttachment(attachment)} class="attachment-container">
<div class="attachment-icon-container"> <div class="attachment-icon-container">
@ -619,8 +622,28 @@ class MessageTemplate extends LitElement {
slot="icon" slot="icon"
class="download-icon"> class="download-icon">
</vaadin-icon> </vaadin-icon>
${this.myAddress === this.messageObj.sender
? html`
<vaadin-icon
@click=${(e) => {
e.stopPropagation();
this.openDeleteAttachment = true;
}}
class="image-delete-icon" icon="vaadin:close" slot="icon">
</vaadin-icon>
` : html``}
</div> </div>
` `
: attachment && isAttachmentDeleted ?
html`
<div class="attachment-container">
<div class="attachment-info">
<p style=${"font-style: italic;"} class="attachment-name">
${translate("chatpage.cchange72")}
</p>
</div>
</div>
`
: html``} : html``}
<div <div
id="messageContent" id="messageContent"
@ -737,7 +760,7 @@ class MessageTemplate extends LitElement {
this.openDeleteImage = false; this.openDeleteImage = false;
}}> }}>
<div class="delete-image-msg"> <div class="delete-image-msg">
<p>Are you sure you want to delete this image?</p> <p>${translate("chatpage.cchange69")}</p>
</div> </div>
<div class="modal-button-row" @click=${() => this.openDeleteImage = false}> <div class="modal-button-row" @click=${() => this.openDeleteImage = false}>
<button class="modal-button-red"> <button class="modal-button-red">
@ -755,6 +778,34 @@ class MessageTemplate extends LitElement {
</button> </button>
</div> </div>
</mwc-dialog> </mwc-dialog>
<mwc-dialog
hideActions
?open=${this.openDeleteAttachment}
@closed=${()=> {
this.openDeleteAttachment = false;
}}>
<div class="delete-image-msg">
<p>${translate("chatpage.cchange70")}</p>
</div>
<div class="modal-button-row" @click=${() => this.openDeleteAttachment = false}>
<button class="modal-button-red">
Cancel
</button>
<button
class="modal-button"
@click=${() => {
this.sendMessage({
type: 'deleteAttachment',
attachment: attachment,
name: attachment.name,
identifier: attachment.identifier,
editedMessageObj: this.messageObj,
})}
}>
Yes
</button>
</div>
</mwc-dialog>
` `
} }
} }

Loading…
Cancel
Save