From cb4e5f289ab6517b7d97772b0c7d91e2c80d7921 Mon Sep 17 00:00:00 2001 From: Justin Ferrari Date: Tue, 14 Feb 2023 23:18:59 +0200 Subject: [PATCH] Completed UI functionality of GIFS --- qortal-ui-core/language/us.json | 46 +- .../core/components/ChatGifs/ChatGifs-css.js | 44 ++ .../core/components/ChatGifs/ChatGifs.js | 441 +++++++++++------- .../ChatGifs/ChatGifsExplore-css.js | 73 +++ .../components/ChatGifs/ChatGifsExplore.js | 122 ++++- .../plugins/core/components/ChatPage.js | 32 +- .../plugins/core/components/ChatScroller.js | 122 ++++- .../plugins/core/components/ChatTextEditor.js | 21 +- .../plugins/core/components/ImageComponent.js | 39 +- 9 files changed, 699 insertions(+), 241 deletions(-) diff --git a/qortal-ui-core/language/us.json b/qortal-ui-core/language/us.json index 1b3e31f7..16cf7867 100644 --- a/qortal-ui-core/language/us.json +++ b/qortal-ui-core/language/us.json @@ -572,23 +572,35 @@ "cchange63": "Enter Enabled", "cchange64": "Enter Disabled", "cchange65": "Please enter a recipient", - "cchange66": "Cannot fetch replied-to message. Message is too old.", - "cchange80": "Gif Explorer", - "cchange81": "Explore Collections", - "cchange82": "My Collections", - "cchange83": "Subscribed Collections", - "cchange84": "Upload your gif files", - "cchange85": "File should be .Gif", - "cchange86": "Upload Collection", - "cchange87": "A collection name is required!", - "cchange88": "Collection Name", - "cchange89": "Gif Collection Uploaded Successfully!", - "cchange90": "Gifs uploading, please wait...", - "cchange91": "Something went wrong! Please try changing tabs and coming back.", - "cchange92": "You currently have no collections.", - "cchange93": "You currently have no subscribed collections.", - "cchange94": "Error fetching image. Retrying...", - "cchange95": "Failed to fetch image! Please visit another collection and try again!" + "cchange66": "Cannot fetch replied-to message. Message is too old." + }, + "gifs": { + "gchange1": "Gif Explorer", + "gchange2": "Explore Collections", + "gchange3": "My Collections", + "gchange4": "Subscribed Collections", + "gchange5": "Upload your gif files", + "gchange6": "File should be .Gif", + "gchange7": "Upload Collection", + "gchange8": "A collection name is required!", + "gchange9": "Collection Name", + "gchange10": "Gif Collection Uploaded Successfully!", + "gchange11": "Gifs uploading, please wait...", + "gchange12": "Something went wrong! Please try changing tabs and coming back.", + "gchange13": "You currently have no collections.", + "gchange14": "You currently have no subscribed collections.", + "gchange15": "Error fetching GIF. Retrying...", + "gchange16": "Failed to fetch GIF! Please visit another collection and try again!", + "gchange17": "Subscribe to this collection", + "gchange18": "Searching for collections...", + "gchange19": "No collections found!", + "gchange20": "Subscribed to collection successfully!", + "gchange21": "Unsubscribed to collection successfully!", + "gchange22": "Unsubscribe from this collection", + "gchange23": "Your gif collection cannot contain two gifs with the same name!", + "gchange24": "This collection name is already taken. Try another name!", + "gchange25": "GIF (click to view)", + "gchange26": "A name is needed to access and send GIF files" }, "welcomepage": { "wcchange1": "Welcome to Q-Chat", diff --git a/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs-css.js b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs-css.js index 5a9fd29a..7f68de4f 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs-css.js +++ b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs-css.js @@ -462,10 +462,54 @@ background-color: #03a8f475; .gifs-loading-message { font-family: Montserrat, sans-serif; font-size: 20px; + font-weight: 600; color: var(--chat-bubble-msg-color); margin: 0 0 10px 0; text-align: center; user-select: none; } +.subscribe-button { + position: absolute; + bottom: 3px; + left: 50%; + transform: translateX(-50%); + font-family: Raleway, sans-serif; + font-weight: 500; + font-size: 14px; + background-color: var(--mdc-theme-primary); + border: none; + border-radius: 8px; + outline: none; + padding: 5px 10px; + transition: all 0.3s cubic-bezier(0.5, 1, 0.89, 1); +} + +.subscribe-button:hover { + cursor: pointer; + box-shadow: 0px 3px 4px 0px hsla(0,0%,0%,0.14), 0px 3px 3px -2px hsla(0,0%,0%,0.12), 0px 1px 8px 0px hsla(0,0%,0%,0.2); +} + +.unsubscribe-button { + position: absolute; + width: max-content; + bottom: 3px; + left: 50%; + transform: translateX(-50%); + font-family: Raleway, sans-serif; + font-weight: 500; + font-size: 14px; + background-color: #f44336; + border: none; + border-radius: 8px; + outline: none; + padding: 5px 10px; + transition: all 0.3s cubic-bezier(0.5, 1, 0.89, 1); +} + +.unsubscribe-button:hover { + cursor: pointer; + box-shadow: 0px 3px 4px 0px hsla(0,0%,0%,0.14), 0px 3px 3px -2px hsla(0,0%,0%,0.12), 0px 1px 8px 0px hsla(0,0%,0%,0.2); +} + `; diff --git a/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs.js b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs.js index 28fa84ea..3fa66eba 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs.js +++ b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs.js @@ -28,6 +28,10 @@ currentCollection: {type: String}, isLoading: {type: String}, newCollectionName: {type: String}, editor: {type: Object}, +isSubscribed: { type: Boolean }, +setGifsLoading: { attribute: false }, +sendMessage: { attribute: false }, +setOpenGifModal: { attribute: false } }; } @@ -36,22 +40,133 @@ editor: {type: Object}, constructor() { super(); this.uid = new ShortUniqueId(); - this.selectedAddress = - window.parent.reduxStore.getState().app.selectedAddress; + this.selectedAddress = window.parent.reduxStore.getState().app.selectedAddress; this.myGifCollections = []; this.mySubscribedCollections = []; this.exploreCollections = []; this.myAccountName = ''; this.gifsToBeAdded = []; - // mode can be 'myCollection', 'newCollection', 'explore', 'subscribedCollection' this.mode = 'myCollection'; this.currentCollection = null; this.pageNumber = 0; this.isLoading = false; + this.isSubscribed = false; this.newCollectionName = ''; + this.getAllCollections = this.getAllCollections.bind(this); } + async firstUpdated() { + const tooltip = this.shadowRoot.querySelector('vaadin-tooltip'); + const overlay = tooltip.shadowRoot.querySelector( + 'vaadin-tooltip-overlay' + ); + overlay.shadowRoot.getElementById('overlay').style.cssText = + 'background-color: transparent; border-radius: 10px; box-shadow: rgb(50 50 93 / 25%) 0px 2px 5px -1px, rgb(0 0 0 / 30%) 0px 1px 3px -1px'; + overlay.shadowRoot.getElementById('content').style.cssText = + 'background-color: var(--gif-tooltip-bg); color: var(--chat-bubble-msg-color); text-align: center; padding: 20px 10px; font-family: Roboto, sans-serif; letter-spacing: 0.3px; font-weight: 300; font-size: 13.5px; transition: all 0.3s ease-in-out;'; + + try { + this.isLoading = true; + const myCollections = await this.getMyGifCollections(); + const savedCollections = await this.getSavedCollections(); + const allCollections = await this.getAllCollections(); + + if (!Array.isArray(myCollections) && !Array.isArray(savedCollections)) { + parentEpml.request('showSnackBar', get('gifs.gchange12')); + return; + } + + await new Promise((res) => { + setTimeout(() => { + res(); + }, 1000) + }); + this.myGifCollections = myCollections; + this.mySubscribedCollections = savedCollections; + this.exploreCollections = allCollections; + } catch (error) { + console.error(error); + } finally { + this.isLoading = false; + } + } + + async updated(changedProperties) { + if (changedProperties && changedProperties.has('mode')) { + const mode = this.mode; + if (mode === 'myCollection') { + try { + this.myGifCollections = []; + this.isLoading = true; + const collections = await this.getMyGifCollections(); + await new Promise((res) => { + setTimeout(() => { + res(); + }, 1000) + }); + this.myGifCollections = collections; + } catch (error) { + console.error(error); + } finally { + this.isLoading = false; + } + } + + if (mode === 'explore') { + try { + this.exploreCollections = []; + this.isLoading = true; + const allCollections = await this.getAllCollections(); + await new Promise((res) => { + setTimeout(() => { + res(); + }, 1000) + }); + this.exploreCollections = allCollections; + } catch (error) { + console.error(error); + } finally { + this.isLoading = false; + } + } + if (mode === 'subscribedCollection') { + try { + this.mySubscribedCollections = []; + this.isLoading = true; + const savedCollections = await this.getSavedCollections(); + await new Promise((res) => { + setTimeout(() => { + res(); + }, 1000) + }); + this.mySubscribedCollections = savedCollections; + } catch (error) { + console.error(error); + } finally { + this.isLoading = false; + } + } + } + + if (changedProperties && changedProperties.has('currentCollection')) { + if (this.mode === 'explore') { + console.log(this.mySubscribedCollections, "subbed collections here"); + const subbedCollection = this.mySubscribedCollections.find((collection) => ((collection.name === this.currentCollection.name) && (collection.identifier === this.currentCollection.identifier))); + console.log({subbedCollection}); + if (subbedCollection) { + this.isSubscribed = true; + } else { + this.isSubscribed = false; + } + } + } + } + async structureCollections(gifCollections) { + const userName = await this.getName(this.selectedAddress.address); + if (!userName) { + return; + } try { const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[ @@ -73,7 +188,12 @@ editor: {type: Object}, }; if (metaData.files) { const metaDataArray = metaData.files.map((data) => { - return `${nodeUrl}/arbitrary/GIF_REPOSITORY/${this.myAccountName}/${collection.identifier}?filepath=${data}`; + return { + url: `${nodeUrl}/arbitrary/GIF_REPOSITORY/${this.myAccountName}/${collection.identifier}?filepath=${data}`, + filePath: data, + identifier: collection.identifier, + name: this.myAccountName + }; }); collectionObj = { @@ -190,8 +310,8 @@ editor: {type: Object}, const gifCollectionWithMetaData = await this.structureCollections( getAllGifCollections ); - this.exploreCollections = gifCollectionWithMetaData; this.pageNumber = this.pageNumber + 1; + return gifCollectionWithMetaData; } async getSavedCollections() { @@ -222,90 +342,6 @@ editor: {type: Object}, return savedCollectionsWithMetaData; } - async firstUpdated() { - const tooltip = this.shadowRoot.querySelector('vaadin-tooltip'); - const overlay = tooltip.shadowRoot.querySelector( - 'vaadin-tooltip-overlay' - ); - overlay.shadowRoot.getElementById('overlay').style.cssText = - 'background-color: transparent; border-radius: 10px; box-shadow: rgb(50 50 93 / 25%) 0px 2px 5px -1px, rgb(0 0 0 / 30%) 0px 1px 3px -1px'; - overlay.shadowRoot.getElementById('content').style.cssText = - 'background-color: var(--gif-tooltip-bg); color: var(--chat-bubble-msg-color); text-align: center; padding: 20px 10px; font-family: Roboto, sans-serif; letter-spacing: 0.3px; font-weight: 300; font-size: 13.5px; transition: all 0.3s ease-in-out;'; - - try { - this.isLoading = true; - const myCollections = await this.getMyGifCollections(); - const savedCollections = await this.getSavedCollections(); - - if (!Array.isArray(myCollections) && !Array.isArray(savedCollections)) { - parentEpml.request('showSnackBar', get('chatpage.cchange91')); - return; - } - - await new Promise((res) => { - setTimeout(() => { - res(); - }, 1000) - }); - this.myGifCollections = myCollections; - this.mySubscribedCollections = savedCollections; - await this.getAllCollections(); - this.isLoading = false; - } catch (error) { - this.isLoading = false; - console.error(error); - } - } - - async updated(changedProperties) { - if (changedProperties && changedProperties.has('mode')) { - const mode = this.mode; - if (mode === 'myCollection') { - try { - this.myGifCollections = []; - this.isLoading = true; - const collections = await this.getMyGifCollections(); - await new Promise((res) => { - setTimeout(() => { - res(); - }, 1000) - }); - this.myGifCollections = collections; - this.isLoading = false; - } catch (error) { - this.isLoading = false; - } - } - - if (mode === 'explore') { - try { - this.isLoading = true; - - await this.getAllCollections(); - this.isLoading = false; - } catch (error) { - this.isLoading = false; - } - } - if (mode === 'subscribedCollection') { - try { - this.mySubscribedCollections = []; - this.isLoading = true; - const savedCollections = await this.getSavedCollections(); - await new Promise((res) => { - setTimeout(() => { - res(); - }, 1000) - }); - this.mySubscribedCollections = savedCollections; - this.isLoading = false; - } catch (error) { - this.isLoading = false; - } - } - } - } - async getName(recipient) { try { const getNames = await parentEpml.request('apiCall', { @@ -323,6 +359,26 @@ editor: {type: Object}, } } + removeDotGIF(arr) { + return arr.map(obj => { + const newObj = { ...obj }; + if (newObj.hasOwnProperty('name') && newObj.name.endsWith('.gif')) { + newObj.name = newObj.name.slice(0, -4); + } + return newObj; + }); + } + + addDotGIF(arr) { + return arr.map(obj => { + const newObj = { ...obj }; + if (newObj.hasOwnProperty('name') && !newObj.name.endsWith('.gif')) { + newObj.name += '.gif'; + } + return newObj; + }); + } + addGifs(gifs) { const mapGifs = gifs.map((file) => { return { @@ -330,28 +386,59 @@ editor: {type: Object}, name: file.name, }; }); - this.gifsToBeAdded = [...this.gifsToBeAdded, ...mapGifs]; + const removedExtensions = this.removeDotGIF(mapGifs); + this.gifsToBeAdded = [...this.gifsToBeAdded, ...removedExtensions]; } async uploadGifCollection() { if (!this.newCollectionName) { - parentEpml.request('showSnackBar', get('chatpage.cchange87')); + parentEpml.request('showSnackBar', get('gifs.gchange8')); return; } try { this.setGifsLoading(true); this.isLoading = true; - const userName = await this.getName(this.selectedAddress.address); - const doesNameExist = await parentEpml.request('apiCall', { + const userName = await this.getName(this.selectedAddress.address); + const doesNameExist = await parentEpml.request('apiCall', { url: `/arbitrary/resources?service=GIF_REPOSITORY&limit=0&name=${userName}&identifier=${this.newCollectionName}`, }); - if (doesNameExist.length !== 0) { - parentEpml.request('showSnackBar', get('chatpage.cchange87')); - this.isLoading = false; - this.setGifsLoading(false); + if (!userName) { + parentEpml.request('showSnackBar', get('chatpage.cchange27')); + this.setGifsLoading(false); + this.isLoading = false; return; } + + if (doesNameExist.length !== 0) { + parentEpml.request('showSnackBar', get('gifs.gchange24')); + this.isLoading = false; + this.setGifsLoading(false); + return; + } + + function validateDuplicateGifNames(arr) { + let names = []; + for (let i = 0; i < arr.length; i++) { + if (names.includes(arr[i].name)) { + return false; + } + names.push(arr[i].name); + } + return true; + } + + let result = validateDuplicateGifNames(this.gifsToBeAdded); + + if (!result) { + parentEpml.request('showSnackBar', get('gifs.gchange23')); + this.isLoading = false; + this.setGifsLoading(false); + return; + } + + const addedGifExtensionsArr = this.addDotGIF(this.gifsToBeAdded); + function blobToBase64(blob) { return new Promise((resolve, _) => { const reader = new FileReader(); @@ -360,37 +447,24 @@ editor: {type: Object}, }); } const zipFileWriter = new zip.BlobWriter('application/zip'); - // Creates a TextReader object storing the text of the entry to add in the zip - // (i.e. "Hello world!"). - const helloWorldReader = new zip.TextReader('Hello world!'); - - // Creates a ZipWriter object writing data via `zipFileWriter`, adds the entry - // "hello.txt" containing the text "Hello world!" via `helloWorldReader`, and - // closes the writer. const zipWriter = new zip.ZipWriter(zipFileWriter, { bufferedWrite: true, }); - for (let i = 0; i < this.gifsToBeAdded.length; i++) { + for (let i = 0; i < addedGifExtensionsArr.length; i++) { await zipWriter.add( - this.gifsToBeAdded[i].name, - new zip.BlobReader(this.gifsToBeAdded[i].file) + addedGifExtensionsArr[i].name, + new zip.BlobReader(addedGifExtensionsArr[i].file) ); } await zipWriter.close(); + const zipFileBlob = await zipFileWriter.getData(); + const blobTobase = await blobToBase64(zipFileBlob); - if (!userName) { - parentEpml.request('showSnackBar', get('chatpage.cchange27')); - this.setGifsLoading(false); - this.isLoading = false; - return; - } - const id = this.uid(); - const identifier = `gif_${id}`; await publishData({ registeredName: userName, file: blobTobase.split(',')[1], @@ -421,21 +495,30 @@ editor: {type: Object}, clearInterval(interval); res(); } - } catch (error) {} + } catch (error) { + console.error(error); + this.isLoading = false; + this.setGifsLoading(false); + this.mode = 'myCollection'; + this.gifsToBeAdded = []; + this.newCollectionName = ''; + parentEpml.request('showSnackBar', get('gifs.gchange12')); + } stop = false; } }; interval = setInterval(getAnswer, 5000); }); saveAs(zipFileBlob, 'zipfile'); - this.isLoading = false; - this.setGifsLoading(false); - this.mode = 'myCollection'; - this.gifsToBeAdded = []; - this.newCollectionName = ''; - parentEpml.request('showSnackBar', get('chatpage.cchange89')); + this.isLoading = false; + this.setGifsLoading(false); + this.mode = 'myCollection'; + this.gifsToBeAdded = []; + this.newCollectionName = ''; + parentEpml.request('showSnackBar', get('gifs.gchange10')); } catch (error) { console.log(error); + parentEpml.request('showSnackBar', get('gifs.gchange12')); } } @@ -448,15 +531,36 @@ editor: {type: Object}, this.gifsToBeAdded = []; } + async subscribeToCollection() { + await this.addCollectionToList( + `${this.currentCollection.name}/${this.currentCollection.identifier}` + ); + parentEpml.request('showSnackBar', get('gifs.gchange20')); + this.isSubscribed = true; + const savedCollections = await this.getSavedCollections(); + this.mySubscribedCollections = savedCollections; + } + + async unsubscribeToCollection() { + await this.removeCollectionFromList( + `${this.currentCollection.name}/${this.currentCollection.identifier}` + ); + parentEpml.request('showSnackBar', get('gifs.gchange21')); + this.isSubscribed = false; + const savedCollections = await this.getSavedCollections(); + this.mySubscribedCollections = savedCollections; + } + render() { + console.log(8, "chat gifs here"); console.log('this.currentCollection', this.currentCollection); - console.log(31, 'chat gifs here'); return html`

${translate( - 'chatpage.cchange80' + 'gifs.gchange1' )}

+ text=${get('gifs.gchange2')}>
- ${translate('chatpage.cchange82')} + ${translate('gifs.gchange3')}
- ${translate('chatpage.cchange83')} + ${translate('gifs.gchange4')}
@@ -563,7 +668,7 @@ editor: {type: Object}, : ''} ${(this.myGifCollections.length === 0 && !this.isLoading) ? ( html` -
${translate('chatpage.cchange92')}
+
${translate('gifs.gchange13')}
` ) : ( html` @@ -590,7 +695,7 @@ editor: {type: Object}, : ''} ${(this.mySubscribedCollections.length === 0 && !this.isLoading) ? ( html` -
${translate('chatpage.cchange93')}
+
${translate('gifs.gchange14')}
` ) : ( html` @@ -614,10 +719,14 @@ editor: {type: Object}, ${this.mode === 'explore' && !this.currentCollection ? html` ${this.isLoading === true - ? html`
` - : ''} -
+ ` + : html` + + this.getAllCollections(val)} .getMoreExploreGifs=${(val) => this.getMoreExploreGifs(val)} .exploreCollections=${this @@ -625,6 +734,8 @@ editor: {type: Object}, .setCurrentCollection=${(val) => this.setCurrentCollection(val)} > + ` + } ` : '' } @@ -634,8 +745,10 @@ editor: {type: Object}, ${this.currentCollection.gifUrls.map((gif) => { return html` this.sendMessage(val)} + .setOpenGifModal=${(val) => this.setOpenGifModal(val)} .class=${'gif-image'} - .url=${gif} + .gif=${gif} .alt=${'gif-image'}> `; @@ -651,8 +764,10 @@ editor: {type: Object}, ${this.currentCollection.gifUrls.map((gif) => { return html` this.sendMessage(val)} + .setOpenGifModal=${(val) => this.setOpenGifModal(val)} .class=${'gif-image'} - .url=${gif} + .gif=${gif} .alt=${'gif-image'}> `; @@ -662,28 +777,38 @@ editor: {type: Object}, : '' } ${this.currentCollection && this.mode === 'explore' - ? html` - + ? html` +
${this.currentCollection.gifUrls.map((gif) => { - return html` - { - e.target.src = gif; - }} - src=${gif} - style="width: 50px; height: 50px" - /> + this.sendMessage(val)} + .setOpenGifModal=${(val) => this.setOpenGifModal(val)} + .class=${'gif-image'} + .gif=${gif} + .alt=${'gif-image'}> + `; })} +
+ ${this.isSubscribed ? ( + html` + + ` + ) : ( + html` + + ` + )} ` : '' } @@ -692,10 +817,10 @@ editor: {type: Object},

- ${translate('chatpage.cchange84')} + ${translate('gifs.gchange5')}

- ${translate('chatpage.cchange85')} + ${translate('gifs.gchange6')}

{ this.newCollectionName = @@ -793,7 +918,7 @@ editor: {type: Object}, this.uploadGifCollection(); }} > - ${translate('chatpage.cchange86')} + ${translate('gifs.gchange7')}
@@ -802,7 +927,7 @@ editor: {type: Object}, : this.mode === 'newCollection' && this.isLoading === true ? ( html`
-

${translate("chatpage.cchange90")}

+

${translate("gifs.gchange11")}

` diff --git a/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifsExplore-css.js b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifsExplore-css.js index ce80afc1..2ce632ba 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifsExplore-css.js +++ b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifsExplore-css.js @@ -61,4 +61,77 @@ opacity: 0.6; color: var(--chat-bubble-msg-color); } +.search-collection-wrapper { +display: flex; +justify-content: center; +align-items: center; +width: 100%; +position: relative; +} + +.explore-collections-icon { +position: absolute; +right: 20px; +font-size: 13px; +color: var(--chat-group); +cursor: pointer; +} + +.clear-search-icon { +position: absolute; +right: 15px; +font-size: 16px; +color: var(--chat-group); +padding: 1px; +border-radius: 50%; +background-color: transparent; +transition: all 0.3s ease-in-out; +} + +.clear-search-icon:hover { +cursor: pointer; +background-color: #e4e3e389 +} + +.gifs-loading-message { +font-family: Montserrat, sans-serif; +font-size: 20px; +font-weight: 600; +color: var(--chat-bubble-msg-color); +margin: 0 0 10px 0; +text-align: center; +user-select: none; +} + +.lds-circle { +display: flex; +align-items: center; +justify-content: center; +} + +.lds-circle > div { +display: inline-block; +width: 80px; +height: 80px; +margin: 8px; +border-radius: 50%; +background: var(--mdc-theme-primary); +animation: lds-circle 2.4s cubic-bezier(0, 0.2, 0.8, 1) infinite; +} + +@keyframes lds-circle { +0%, 100% { + animation-timing-function: cubic-bezier(0.5, 0, 1, 0.5); +} +0% { + transform: rotateY(0deg); +} +50% { + transform: rotateY(1800deg); + animation-timing-function: cubic-bezier(0, 0.5, 0.5, 1); +} +100% { + transform: rotateY(3600deg); +} +} ` diff --git a/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifsExplore.js b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifsExplore.js index 1c1eb3a9..9db3f797 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifsExplore.js +++ b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifsExplore.js @@ -7,15 +7,18 @@ import '@material/mwc-icon'; const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }); class ChatGifsExplore extends LitElement { -static get properties() { -return { -currentCollection: { type: String }, -searchCollectionName: {type: String}, -getMoreExploreGifs: { attribute: false }, -exploreCollections: { type: Array }, -setCurrentCollection: { attribute: false }, -}; -} + static get properties() { + return { + currentCollection: { type: String }, + searchCollectionName: {type: String}, + getMoreExploreGifs: { attribute: false }, + exploreCollections: { type: Array }, + setCurrentCollection: { attribute: false }, + isLoading: { type: Boolean }, + isSearched: { type: Boolean }, + getAllCollections: { attribute: false } + }; + } static styles = [chatGifsExploreStyles]; @@ -25,6 +28,8 @@ setCurrentCollection: { attribute: false }, this.downObserverElement = ''; this.viewElement = ''; this.exploreCollections = []; + this.isLoading = false; + this.isSearched = false; } elementObserver() { @@ -64,21 +69,87 @@ setCurrentCollection: { attribute: false }, this.elementObserver(); } + async searchCollections() { + this.isSearched = true; + try { + this.exploreCollections = []; + this.isLoading = true; + const response = await parentEpml.request('apiCall', { + url: `/arbitrary/resources/search?service=GIF_REPOSITORY&query=${this.searchCollectionName}&limit=0 + `, + }); + await new Promise((res) => { + setTimeout(() => { + res(); + }, 1000) + }); + this.exploreCollections = response; + } catch (error) { + console.error(error); + } finally { + this.isLoading = false; + } + } + render() { - console.log(6, "chat-gifs-explore-here"); + console.log(18, "chat-gifs-explore-here"); + console.log(this.searchCollectionName, "search collection name"); return html` -
- { - this.searchCollectionName = - e.target.value; - }} - /> -
- ${this.exploreCollections.map((collection) => { +
+
+ { + this.searchCollectionName = + e.target.value; + }} + @keyup=${async (e) => { + console.log(e.key); + if (e.key === 'Enter' && this.searchCollectionName) { + await this.searchCollections() + } + }} + /> + ${this.isSearched ? ( + html` + { + if (this.isLoading) return; + const latestCollections = await this.getAllCollections(); + this.exploreCollections = latestCollections; + this.searchCollectionName = ''; + this.isSearched = false; + }} + icon='vaadin:close-small' + slot='icon'> + + ` + ) : html` + { + if (this.isLoading || !this.searchCollectionName) return; + await this.searchCollections(); + }} + icon='vaadin:search' + slot='icon'> + + `} +
+
+ ${this.isLoading ? html` +
+

${translate('gifs.gchange18')} +

+
+
` + : this.isSearched && this.exploreCollections.length === 0 ? ( + html`

${translate('gifs.gchange19')}

` + ) : ( + html`${this.exploreCollections.map((collection) => { return html`
{ this.setCurrentCollection(collection); @@ -86,9 +157,10 @@ setCurrentCollection: { attribute: false }, ${collection.identifier}
`; - })} -
-
+ })}` + )} +
+
`; } diff --git a/qortal-ui-plugins/plugins/core/components/ChatPage.js b/qortal-ui-plugins/plugins/core/components/ChatPage.js index 61b2a1a8..25561083 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatPage.js +++ b/qortal-ui-plugins/plugins/core/components/ChatPage.js @@ -1023,7 +1023,6 @@ console.log({zipFileBlob}) } render() { - console.log(23, "chat page here"); return html`
this.setGifsLoading(val)}> + .setGifsLoading=${(val) => this.setGifsLoading(val)} + .sendMessage=${(val) => this._sendMessage(val)} + .setOpenGifModal=${(val)=> this.setOpenGifModal(val)}>
{ const lastGroupedMessage = messageArray[messageArray.length - 1]; let timestamp; @@ -269,9 +270,11 @@ class MessageTemplate extends LitElement { setEditedMessageObj: { attribute: false }, sendMessage: { attribute: false }, sendMessageForward: { attribute: false }, - openDialogImage: { attribute: false }, + openDialogImage: { type: Boolean }, + openDialogGif: { type: Boolean }, openDeleteImage: { type: Boolean }, isImageLoaded: { type: Boolean }, + isGifLoaded: { type: Boolean }, isFirstMessage: { type: Boolean }, isSingleMessageInGroup: { type: Boolean }, isLastMessageInGroup: { type: Boolean }, @@ -295,8 +298,11 @@ class MessageTemplate extends LitElement { this.showBlockAddressIcon = false this.myAddress = window.parent.reduxStore.getState().app.selectedAddress.address this.imageFetches = 0 + this.gifFetches = 0 this.openDialogImage = false + this.openDialogGif = false this.isImageLoaded = false + this.isGifLoaded = false this.isFirstMessage = false this.isSingleMessageInGroup = false this.isLastMessageInGroup = false @@ -338,19 +344,23 @@ class MessageTemplate extends LitElement { let reactions = []; let repliedToData = null; let image = null; + let gif = null; let isImageDeleted = false; let version = 0; let isForwarded = false try { const parsedMessageObj = JSON.parse(this.messageObj.decodedMessage); - if(parsedMessageObj.version.toString() === '2'){ - - messageVersion2 = generateHTML(parsedMessageObj.messageText, [ - StarterKit, - Underline, - Highlight - // other extensions … - ]) + if (parsedMessageObj.version.toString() === '2' && parsedMessageObj.messageText) { + try { + messageVersion2 = generateHTML(parsedMessageObj.messageText, [ + StarterKit, + Underline, + Highlight + // other extensions … + ]) + } catch (error) { + console.error(error); + } } message = parsedMessageObj.messageText; repliedToData = this.messageObj.repliedToData; @@ -361,13 +371,20 @@ class MessageTemplate extends LitElement { if (parsedMessageObj.images && Array.isArray(parsedMessageObj.images) && parsedMessageObj.images.length > 0) { image = parsedMessageObj.images[0]; } + if (parsedMessageObj.gifs && Array.isArray(parsedMessageObj.gifs) && parsedMessageObj.gifs.length > 0) { + gif = parsedMessageObj.gifs[0]; + } } catch (error) { + console.error(error); message = this.messageObj.decodedMessage; } let avatarImg = ''; let imageHTML = ''; let imageHTMLDialog = ''; let imageUrl = ''; + let gifHTML = ''; + let gifHTMLDialog = ''; + let gifUrl = ''; let nameMenu = ''; let levelFounder = ''; let hideit = hidemsg.includes(this.messageObj.sender); @@ -411,6 +428,33 @@ class MessageTemplate extends LitElement { }; return imageHTMLRes; } + + const createGif = (gif) => { + const gifHTMLRes = new Image(); + gifHTMLRes.src = gif; + gifHTMLRes.style= "max-width:45vh; max-height:40vh; border-radius: 5px; cursor: pointer"; + gifHTMLRes.onclick= () => { + this.openDialogGif = true; + } + gifHTMLRes.onload = () => { + this.isGifLoaded = true; + } + gifHTMLRes.onerror = () => { + if (this.gifFetches < 4) { + setTimeout(() => { + this.gifFetches = this.gifFetches + 1; + gifHTMLRes.src = gif; + }, 500); + } else { + gifHTMLRes.src = '/img/chain.png'; + gifHTMLRes.style= "max-width:45vh; max-height:20vh; border-radius: 5px; filter: opacity(0.5)"; + gifHTMLRes.onclick= () => {} + this.isGifLoaded = true + } + }; + return gifHTMLRes; + } + if (image) { const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]; const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port; @@ -421,7 +465,17 @@ class MessageTemplate extends LitElement { imageHTMLDialog = createImage(imageUrl) imageHTMLDialog.style= "height: auto; max-height: 80vh; width: auto; max-width: 80vw; object-fit: contain; border-radius: 5px"; } - + } + + if (gif) { + const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]; + const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port; + gifUrl = `${nodeUrl}/arbitrary/${gif.service}/${gif.name}/${gif.identifier}?filepath=${gif.filePath}&apiKey=${myNode.apiKey}`; + if (this.viewImage || this.myAddress === this.messageObj.sender){ + gifHTML = createGif(gifUrl); + gifHTMLDialog = createGif(gifUrl) + gifHTMLDialog.style= "height: auto; max-height: 80vh; width: auto; max-width: 80vw; object-fit: contain; border-radius: 5px"; + } } nameMenu = html` @@ -560,10 +614,9 @@ class MessageTemplate extends LitElement { }} class=${[`image-container`, !this.isImageLoaded ? 'defaultSize' : ''].join(' ')} style=${this.isFirstMessage && "margin-top: 10px;"}> -
- ${translate("chatpage.cchange40")} -
- +
+ ${translate("chatpage.cchange40")} +
` : html``} ${image && !isImageDeleted && (this.viewImage || this.myAddress === this.messageObj.sender) ? html` @@ -580,6 +633,25 @@ class MessageTemplate extends LitElement { ` : image && isImageDeleted ? html`

This image has been deleted

` : html``} + ${gif && !this.viewImage && this.myAddress !== this.messageObj.sender ? html` +
{ + this.viewImage = true + }} + class=${[`image-container`, !this.isImageLoaded ? 'defaultSize' : ''].join(' ')} + style=${this.isFirstMessage && "margin-top: 10px;"}> +
+ ${translate("gifs.gchange25")} +
+
+ ` : html``} + ${gif && (this.viewImage || this.myAddress === this.messageObj.sender) ? html` +
+ ${gifHTML} +
+ ` : html``}
+ { + this.openDialogGif = false + }}> +
+
+ ${gifHTMLDialog} +
+ { + + this.openDialogGif = false + }} + > + ${translate("general.close")} + +
${this.setOpenGifModal ? html` - ` @@ -527,14 +535,7 @@ class ChatTextEditor extends LitElement { } } - - - - - async firstUpdated() { - - - + async firstUpdated() { window.addEventListener('storage', () => { const checkTheme = localStorage.getItem('qortalTheme'); const chatbar = this.shadowRoot.querySelector('.element') diff --git a/qortal-ui-plugins/plugins/core/components/ImageComponent.js b/qortal-ui-plugins/plugins/core/components/ImageComponent.js index 7a3ae908..78f37603 100644 --- a/qortal-ui-plugins/plugins/core/components/ImageComponent.js +++ b/qortal-ui-plugins/plugins/core/components/ImageComponent.js @@ -7,11 +7,13 @@ export class ImageComponent extends LitElement { static get properties() { return { class: { type: String }, -url: { type: String }, +gif: { type: Object }, alt: { type: String }, attempts: { type: Number }, maxAttempts: { type: Number }, -error: { type: Boolean } +error: { type: Boolean }, +sendMessage: { attribute: false }, +setOpenGifModal: { attribute: false } } } @@ -54,14 +56,21 @@ constructor() { async _fetchImage() { this.attempts++; if (this.attempts > this.maxAttempts) return; - + await new Promise((res) => { + setTimeout(() => { + res(); + }, 1000) + }); try { - const response = await fetch(this.url); + const response = await fetch(this.gif.url); const data = await response.json(); console.log({data}); if (data.ok) { this.error = false; - this.url = data.src; + this.gif = { + ...this.gif, + url: data.src + }; this.requestUpdate(); } else if (!data.ok || data.error) { this.error = true; @@ -76,27 +85,35 @@ async _fetchImage() { } render() { -console.log(5, "Image Component here"); -console.log(this.url) if (this.error && this.attempts <= this.maxAttempts) { setTimeout(() => { this._fetchImage(); }, 1000); } return html` -${this.url && !this.error +${this.gif && !this.error ? html` ${this.alt} { + this.sendMessage({ + type: 'gif', + identifier: this.gif.identifier, + name: this.gif.name, + filePath: this.gif.filePath, + service: "GIF_REPOSITORY" + }) + this.setOpenGifModal(false); +}} @error=${this._fetchImage} />` : this.error && this.attempts <= this.maxAttempts ? html` -

${translate('chatpage.cchange94')}

+

${translate('gifs.gchange15')}

` : html` -

${translate('chatpage.cchange95')}

+

${translate('gifs.gchange16')}

` }` }