From 4cab597afafcbb85d95781537f79a4fbe8a0f673 Mon Sep 17 00:00:00 2001 From: Justin Ferrari Date: Wed, 1 Feb 2023 23:51:13 +0200 Subject: [PATCH] Initial UI done for the gif explorer --- package.json | 8 +- qortal-ui-core/font/MavenPro.ttf | Bin 0 -> 89520 bytes qortal-ui-core/font/material-icons.css | 16 +- qortal-ui-core/font/switch-theme.css | 4 +- qortal-ui-core/language/us.json | 5 +- qortal-ui-core/package.json | 16 +- qortal-ui-core/src/styles/switch-theme.css | 4 +- qortal-ui-plugins/package.json | 26 +- .../plugins/core/components/ChatGifs.js | 585 ------- .../core/components/ChatGifs/ChatGifs-css.js | 41 + .../core/components/ChatGifs/ChatGifs.js | 594 +++++++ .../{ => ChatGifs}/ChatGifsExplore.js | 4 +- .../plugins/core/components/ChatPage.js | 1485 +++++++++-------- .../plugins/core/components/ChatTextEditor.js | 119 +- .../core/messaging/q-chat/q-chat.src.js | 2 - 15 files changed, 1495 insertions(+), 1414 deletions(-) create mode 100644 qortal-ui-core/font/MavenPro.ttf delete mode 100644 qortal-ui-plugins/plugins/core/components/ChatGifs.js create mode 100644 qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs-css.js create mode 100644 qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs.js rename qortal-ui-plugins/plugins/core/components/{ => ChatGifs}/ChatGifsExplore.js (96%) diff --git a/package.json b/package.json index fad3cfe8..1afc154b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "qortal-ui", - "version": "2.2.4", + "version": "3.0.1", "description": "Qortal Project - decentralize the world - Data storage, communications, web hosting, decentralized trading, complete infrastructure for the future blockchain-based Internet", "keywords": [ "QORT", @@ -37,14 +37,12 @@ "os-locale": "3.0.0" }, "devDependencies": { - "electron": "22.0.2", + "electron": "22.1.0", "electron-builder": "23.6.0", "electron-packager": "17.1.1", - "eslint-plugin-lit": "1.8.0", - "eslint-plugin-wc": "1.4.0", "shelljs": "0.8.5" }, "engines": { "node": ">=16.17.1" } -} +} \ No newline at end of file diff --git a/qortal-ui-core/font/MavenPro.ttf b/qortal-ui-core/font/MavenPro.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ab146a80512bca8bc38e491987c476944706de9b GIT binary patch literal 89520 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", "license": "GPL-3.0", "dependencies": { - "@hapi/hapi": "21.2.0", + "@hapi/hapi": "21.2.1", "@hapi/inert": "7.0.0", "sass": "1.57.1" }, @@ -58,12 +58,12 @@ "@rollup/plugin-commonjs": "24.0.1", "@rollup/plugin-node-resolve": "15.0.1", "@rollup/plugin-replace": "5.0.2", - "@rollup/plugin-terser": "0.3.0", - "@vaadin/button": "23.3.5", - "@vaadin/grid": "23.3.5", - "@vaadin/icons": "23.3.5", - "@vaadin/password-field": "23.3.5", - "@vaadin/tooltip": "23.3.5", + "@rollup/plugin-terser": "0.4.0", + "@vaadin/button": "23.3.6", + "@vaadin/grid": "23.3.6", + "@vaadin/icons": "23.3.6", + "@vaadin/password-field": "23.3.6", + "@vaadin/tooltip": "23.3.6", "asmcrypto.js": "2.3.2", "bcryptjs": "2.4.3", "epml": "0.3.3", @@ -73,7 +73,7 @@ "pwa-helpers": "0.9.1", "redux": "4.2.0", "redux-thunk": "2.4.2", - "rollup": "3.10.1", + "rollup": "3.12.0", "rollup-plugin-node-globals": "1.4.0", "rollup-plugin-progress": "1.1.2", "rollup-plugin-scss": "3.0.0", diff --git a/qortal-ui-core/src/styles/switch-theme.css b/qortal-ui-core/src/styles/switch-theme.css index 72dfa151..47162c6b 100644 --- a/qortal-ui-core/src/styles/switch-theme.css +++ b/qortal-ui-core/src/styles/switch-theme.css @@ -48,6 +48,7 @@ html { --chatHeadTextActive: #080808; --group-header: #929292; --group-drop-shadow: rgb(17 17 26 / 10%) 0px 1px 0px; + --gifs-drop-shadow: #32326926 0px 2px 5px 0px, #0000000d 0px 1px 1px 0px; } html[theme="dark"] { @@ -99,5 +100,6 @@ html[theme="dark"] { --chatHeadText: #ffffff; --chatHeadTextActive: #ffffff; --group-header: #c8c8c8; - --group-drop-shadow: rgb(191 191 191 / 32%) 0px 1px 0px + --group-drop-shadow: rgb(191 191 191 / 32%) 0px 1px 0px; + --gifs-drop-shadow: 0px 2px 2px 0px hsla(0, 0%, 0%, 0.14), 0px 3px 1px -2px hsla(0, 0%, 0%, 0.12), 0px 1px 5px 0px hsla(0, 0%, 0%, 0.2); } \ No newline at end of file diff --git a/qortal-ui-plugins/package.json b/qortal-ui-plugins/package.json index f41d6d38..198b0be6 100644 --- a/qortal-ui-plugins/package.json +++ b/qortal-ui-plugins/package.json @@ -21,15 +21,16 @@ "@material/mwc-list": "0.27.0", "@material/mwc-select": "0.27.0", "@tiptap/core": "2.0.0-beta.209", + "@tiptap/extension-highlight": "2.0.0-beta.209", "@tiptap/extension-image": "2.0.0-beta.209", "@tiptap/extension-placeholder": "2.0.0-beta.209", "@tiptap/extension-underline": "2.0.0-beta.209", - "@tiptap/extension-highlight": "2.0.0-beta.209", "@tiptap/html": "2.0.0-beta.209", "@tiptap/starter-kit": "2.0.0-beta.209", "asmcrypto.js": "2.3.2", "compressorjs": "1.1.1", "emoji-picker-js": "https://github.com/Qortal/emoji-picker-js", + "localforage": "1.10.0", "prosemirror-commands": "1.5.0", "prosemirror-dropcursor": "1.6.1", "prosemirror-gapcursor": "1.3.1", @@ -40,7 +41,6 @@ "prosemirror-state": "1.4.2", "prosemirror-transform": "1.7.0", "prosemirror-view": "1.29.1", - "localforage": "1.10.0", "short-unique-id": "4.4.4" }, "devDependencies": { @@ -48,6 +48,7 @@ "@material/mwc-button": "0.27.0", "@material/mwc-checkbox": "0.27.0", "@material/mwc-dialog": "0.27.0", + "@material/mwc-fab": "0.27.0", "@material/mwc-formfield": "0.27.0", "@material/mwc-icon": "0.27.0", "@material/mwc-icon-button": "0.27.0", @@ -68,26 +69,27 @@ "@rollup/plugin-commonjs": "24.0.1", "@rollup/plugin-node-resolve": "15.0.1", "@rollup/plugin-replace": "5.0.2", - "@rollup/plugin-terser": "0.3.0", - "@vaadin/avatar": "23.3.5", - "@vaadin/button": "23.3.5", - "@vaadin/grid": "23.3.5", - "@vaadin/icons": "23.3.5", - "@vaadin/tooltip": "23.3.5", + "@rollup/plugin-terser": "0.4.0", + "@vaadin/avatar": "23.3.6", + "@vaadin/button": "23.3.6", + "@vaadin/grid": "23.3.6", + "@vaadin/icons": "23.3.6", + "@vaadin/tooltip": "23.3.6", + "@zip.js/zip.js": "^2.6.62", "epml": "0.3.3", "file-saver": "2.0.5", "highcharts": "10.3.3", "html-escaper": "3.0.3", "lit": "2.6.1", "lit-translate": "2.0.1", - "rollup": "3.10.1", + "passive-events-support": "1.0.33", + "rollup": "3.12.0", "rollup-plugin-node-globals": "1.4.0", "rollup-plugin-progress": "1.1.2", "rollup-plugin-web-worker-loader": "1.6.1", - "@zip.js/zip.js": "2.6.62", - "validator": "13.7.0" + "validator": "^13.7.0" }, "engines": { "node": ">=16.17.1" } -} \ No newline at end of file +} diff --git a/qortal-ui-plugins/plugins/core/components/ChatGifs.js b/qortal-ui-plugins/plugins/core/components/ChatGifs.js deleted file mode 100644 index 9a97986e..00000000 --- a/qortal-ui-plugins/plugins/core/components/ChatGifs.js +++ /dev/null @@ -1,585 +0,0 @@ -import { LitElement, html, css } from 'lit' -import { render } from 'lit/html.js' -import { Epml } from '../../../epml.js' -import * as zip from "@zip.js/zip.js"; -import { saveAs } from 'file-saver'; -import '@material/mwc-icon' -import ShortUniqueId from 'short-unique-id'; -import { publishData } from '../../utils/publish-image.js'; -import { get } from 'lit-translate'; - -import './ChatGifsExplore.js' -// import isAlphanumeric from 'validator/lib/isAlphanumeric'/ -const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }) - -class ChatGifs extends LitElement { - static get properties() { - return { - selectedAddress: { type: Object }, - myGifCollections: { type: Array }, - mySubscribedCollections: {type: Array}, - exploreCollections: { type: Array }, - gifsToBeAdded: { type: Array}, - webWorkerImage: {type: Object}, - mode: {type: String}, - currentCollection: {type: String}, - isLoading: {type: String}, - newCollectionName: {type: String} - } - } - - static get styles() { - return css` - - ` - } - - constructor() { - super() - this.uid = new ShortUniqueId() - 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.newCollectionName = "" - } - - async structureCollections(gifCollections){ - try { - const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]; - const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port; - const getMetaDataGifs = (gifCollections || []).map(async (collection) => { - let collectionObj = collection - try { - const metaData = await parentEpml.request('apiCall', { - url: `/arbitrary/metadata/GIF_REPOSITORY/${this.myAccountName}/${collection.identifier}` - }) - - collectionObj = { - ...collection, - gifUrls: [] - } - if(metaData.files){ - const metaDataArray = metaData.files.split(';').map((data)=> { - return `${nodeUrl}/arbitrary/GIF_REPOSITORY/${this.myAccountName}/${collection.identifier}?filepath=${data}` - }) - - - collectionObj = { - ...collection, - gifUrls: metaDataArray - } - - } - - - - } catch (error) { - console.log(error) - } - - return collectionObj - }) - return await Promise.all(getMetaDataGifs) - } catch (error) { - - } - } - - - - - async getMoreExploreGifs(){ - try { - - const getAllGifCollections = await parentEpml.request("apiCall", { - type: "api", - url: `/arbitrary/resources?service=GIF_REPOSITORY&limit=20&offset=${this.pageNumber * 20}`, - }); - - const gifCollectionWithMetaData = await this.structureCollections(getAllGifCollections) - this.exploreCollections = [...this.exploreCollections, ...gifCollectionWithMetaData] - - this.pageNumber = this.pageNumber + 1 - } catch (error) { - console.error(error) - } - } - - async getCollectionList(){ - try { - return await parentEpml.request("apiCall", { - type: "api", - url: `/lists/gifSubscribedRepos`, - }); - - } catch (error) { - - } - } - - async addCollectionToList(collection){ - try { - - const body = { - - "items": [ - collection - ] - - } - const bodyToString = JSON.stringify(body) - await parentEpml.request("apiCall", { - type: "api", - method: "POST", - url: `/lists/gifSubscribedRepos`, - body: bodyToString, - headers: { - 'Content-Type': 'application/json' - } - }) - } catch (error) { - - } - } - - async removeCollectionFromList(collection){ - try { - - const body = { - - "items": [ - collection - ] - - } - const bodyToString = JSON.stringify(body) - await parentEpml.request("apiCall", { - type: "api", - method: 'DELETE', - url: `/lists/gifSubscribedRepos`, - body: bodyToString, - headers: { - 'Content-Type': 'application/json' - } - }) - } catch (error) { - - } - } - - async getMyGifCollections(){ - const userName = await this.getName(this.selectedAddress.address); - this.myAccountName = userName - if(this.myAccountName){ - const getMyGifColloctions = await parentEpml.request('apiCall', { - url: `/arbitrary/resources?service=GIF_REPOSITORY&limit=0&name=${this.myAccountName}` - }) - - const gifCollectionWithMetaData = await this.structureCollections(getMyGifColloctions) - - console.log({gifCollectionWithMetaData}) - this.myGifCollections = gifCollectionWithMetaData - } - } - async getAllCollections(){ - this.pageNumber = 0 - // for the explore section - const getAllGifCollections = await parentEpml.request("apiCall", { - type: "api", - url: `/arbitrary/resources?service=GIF_REPOSITORY&limit=20&offset=${this.pageNumber * 20}`, - }); - const gifCollectionWithMetaData = await this.structureCollections(getAllGifCollections) - this.exploreCollections = gifCollectionWithMetaData - this.pageNumber = this.pageNumber + 1 - } - - async getSavedCollections(){ - const getCollectionList = await this.getCollectionList() - - let savedCollections = [] - const getSavedGifRepos = (getCollectionList || []).map(async (collection) => { - let splitCollection = collection.split('/') - const name = splitCollection[0] - const identifier = splitCollection[1] - try { - console.log({collection}) - const data = await parentEpml.request('apiCall', { - url: `/arbitrary/resources?service=GIF_REPOSITORY&limit=0&name=${name}&identifier=${identifier}` - }) - if(data.length > 0){ - savedCollections.push(data[0]) - } - - - - } catch (error) { - console.log(error) - } - - return collection - }) - await Promise.all(getSavedGifRepos) - const savedCollectionsWithMetaData = await this.structureCollections(savedCollections) - this.mySubscribedCollections = savedCollectionsWithMetaData - } - - - async firstUpdated() { - - - try { - this.isLoading = true - await this.getMyGifCollections() - await this.getAllCollections() - await this.getSavedCollections() - this.isLoading = false - - - } catch (error) { - this.isLoading = false - console.error(error) - } - } - - async updated(changedProperties) { - console.log({changedProperties}) - if (changedProperties && changedProperties.has('mode')) { - const mode = this.mode - console.log({mode}) - if (mode === 'myCollection') { - try { - this.isLoading = true - - await this.getMyGifCollections() - 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.isLoading = true - - await this.getSavedCollections() - this.isLoading = false - } catch (error) { - this.isLoading = false - } - - } - } - - - - } - - - - async getName (recipient) { - try { - const getNames = await parentEpml.request("apiCall", { - type: "api", - url: `/names/address/${recipient}`, - }); - - if (Array.isArray(getNames) && getNames.length > 0 ) { - return getNames[0].name - } else { - return '' - } - - } catch (error) { - return "" - } - } - - addGifs(gifs){ - console.log('gifs', gifs) - const mapGifs = gifs.map((file)=> { - return { - file, - name: file.name - } - }) - console.log({mapGifs}) - this.gifsToBeAdded = [...this.gifsToBeAdded, ...mapGifs] - console.log('this.gifsToBeAdded', this.gifsToBeAdded) - } - - async uploadGifCollection(){ - if(!this.newCollectionName){ - parentEpml.request('showSnackBar', get("chatpage.cchange27")); - return - } - - // if(!isAlphanumeric(this.newCollectionName)){ - // parentEpml.request('showSnackBar', get("chatpage.cchange27")); - // return - // } - try { - 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.cchange27")); - return - } - function blobToBase64(blob) { - return new Promise((resolve, _) => { - const reader = new FileReader(); - reader.onloadend = () => resolve(reader.result); - reader.readAsDataURL(blob); - }); - } - 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++) { - await zipWriter.add(this.gifsToBeAdded[i].name, new zip.BlobReader(this.gifsToBeAdded[i].file)); - } - - -await zipWriter.close(); -const zipFileBlob = await zipFileWriter.getData() -const blobTobase = await blobToBase64(zipFileBlob) -console.log({blobTobase}) - - if (!userName) { - parentEpml.request('showSnackBar', get("chatpage.cchange27")); - this.isLoading = false; - return; - } - const id = this.uid(); - const identifier = `gif_${id}`; -await publishData({ - registeredName: userName, - file : blobTobase.split(',')[1], - service: 'GIF_REPOSITORY', - identifier: this.newCollectionName, - parentEpml, - metaData: undefined, - uploadType: 'zip', - selectedAddress: this.selectedAddress, - worker: this.webWorkerImage, - isBase64: true - }) - - await new Promise((res)=> { - let interval = null - let stop = false - const getAnswer = async () => { - - - if (!stop) { - stop = true - try { - let myCollection = await parentEpml.request('apiCall', { - url: `/arbitrary/resources?service=GIF_REPOSITORY&limit=0&name=${userName}&identifier=${this.newCollectionName}` - }) - if (myCollection.length > 0) { - clearInterval(interval) - res() - } - } catch (error) {} - stop = false - } - } - interval = setInterval(getAnswer, 5000) - }) -saveAs(zipFileBlob, 'zipfile'); -console.log({zipFileBlob}) - } catch (error) { - console.log(error) - } - } - - setCurrentCollection(val){ - this.currentCollection = val - } - - render() { - console.log('this.currentCollection', this.currentCollection) - return html` -

-
- - - - - - -${this.mode === "myCollection" && !this.currentCollection ? html` - ${this.isLoading === true ? html` -

Loading...

- ` : ''} - ${this.myGifCollections.map((collection)=> { - return html` -
-

{ - this.currentCollection = collection - }}>${collection.identifier}

- -
- ` - })} - ` : ''} - ${this.mode === "subscribedCollection" && !this.currentCollection ? html` - ${this.isLoading === true ? html` -

Loading...

- ` : ''} - ${this.mySubscribedCollections.map((collection)=> { - return html` -
-

{ - this.currentCollection = collection - }}>${collection.identifier}

- -
- ` - })} - ` : ''} - ${this.mode === "explore" && !this.currentCollection ? html` - ${this.isLoading === true ? html` -

Loading...

- ` : ''} - this.getMoreExploreGifs(val)} .exploreCollections=${this.exploreCollections} - .setCurrentCollection=${(val)=> this.setCurrentCollection(val)} - > - - ` : ''} - ${this.currentCollection && this.mode === "myCollection" ? html` - - ${this.currentCollection.gifUrls.map((gif)=> { - console.log({gif}) - - return html` - { - e.target.src = gif - }} src=${gif} style="width: 50px; height: 50px" /> - ` - })} - ` : ''} - ${this.currentCollection && this.mode === "subscribedCollection" ? html` - - ${this.currentCollection.gifUrls.map((gif)=> { - console.log({gif}) - - return html` - { - e.target.src = gif - }} src=${gif} style="width: 50px; height: 50px" /> - ` - })} - ` : ''} - ${this.currentCollection && this.mode === "explore" ? html` - - - ${this.currentCollection.gifUrls.map((gif)=> { - console.log({gif}) - - return html` - { - e.target.src = gif - }} src=${gif} style="width: 50px; height: 50px" /> - ` - })} - ` : ''} - ${this.mode === "newCollection" ? html` - - - - { - this.newCollectionName = e.target.value - })} /> -
- ${this.gifsToBeAdded.map((gif, i)=> { - console.log({gif}) - return html` -
- - { - this.gifsToBeAdded[i] = { - ...gif, - name: e.target.value - } - })} /> -
- - ` - })} -
- ` : ''} - -
-
- ` - } - - -} - -window.customElements.define('chat-gifs', ChatGifs) diff --git a/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs-css.js b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs-css.js new file mode 100644 index 00000000..11c2272b --- /dev/null +++ b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs-css.js @@ -0,0 +1,41 @@ +import { css } from 'lit' + +export const gifExplorerStyles = css` + .gif-explorer-container { + display: flex; + flex-direction: column; + justify-content: center; + width: 100%; + align-items: center; + gap: 15px; + } + + .title-row { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + } + + .gif-explorer-title { + flex: 1; + text-align: center; + font-family: Roboto, sans-serif; + letter-spacing: 0.8px; + font-size: 25px; + color: var(--chat-bubble-msg-color); + margin: 0; + } + + .explore-collections-icon { + margin-left: auto; + text-align: right; + font-size: 20px; + color: var(--chat-bubble-msg-color); + box-shadow: rgba(0, 0, 0, 0.1) 0px 20px 25px -5px, rgba(0, 0, 0, 0.04) 0px 10px 10px -5px; + padding: 5px; + background-color: var(--chat-menu-bg); + border: none; + border-radius: 12px; + } +` diff --git a/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs.js b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs.js new file mode 100644 index 00000000..4b41e11f --- /dev/null +++ b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifs.js @@ -0,0 +1,594 @@ +import { LitElement, html, css } from 'lit' +import { render } from 'lit/html.js' +import { Epml } from '../../../../epml.js' +import * as zip from "@zip.js/zip.js"; +import { saveAs } from 'file-saver'; +import '@material/mwc-icon' +import ShortUniqueId from 'short-unique-id'; +import { publishData } from '../../../utils/publish-image.js'; +import { translate, get } from 'lit-translate'; +import { gifExplorerStyles } from "./ChatGifs-css.js"; +import './ChatGifsExplore.js'; +import '@vaadin/tooltip'; + +const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }) + +class ChatGifs extends LitElement { + static get properties() { + return { + selectedAddress: { type: Object }, + myGifCollections: { type: Array }, + mySubscribedCollections: {type: Array}, + exploreCollections: { type: Array }, + gifsToBeAdded: { type: Array}, + webWorkerImage: {type: Object}, + mode: {type: String}, + currentCollection: {type: String}, + isLoading: {type: String}, + newCollectionName: {type: String} + } + } + + static styles = [gifExplorerStyles] + + constructor() { + super() + this.uid = new ShortUniqueId() + 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.newCollectionName = "" + } + + async structureCollections(gifCollections){ + try { + const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]; + const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port; + const getMetaDataGifs = (gifCollections || []).map(async (collection) => { + let collectionObj = collection + try { + const metaData = await parentEpml.request('apiCall', { + url: `/arbitrary/metadata/GIF_REPOSITORY/${this.myAccountName}/${collection.identifier}` + }) + + collectionObj = { + ...collection, + gifUrls: [] + } + if(metaData.files){ + const metaDataArray = metaData.files.map((data)=> { + return `${nodeUrl}/arbitrary/GIF_REPOSITORY/${this.myAccountName}/${collection.identifier}?filepath=${data}` + }) + + + collectionObj = { + ...collection, + gifUrls: metaDataArray + } + + } + + } catch (error) { + console.log(error) + } + + return collectionObj + }) + return await Promise.all(getMetaDataGifs) + } catch (error) { + + } + } + + async getMoreExploreGifs(){ + try { + const getAllGifCollections = await parentEpml.request("apiCall", { + type: "api", + url: `/arbitrary/resources?service=GIF_REPOSITORY&limit=20&offset=${this.pageNumber * 20}`, + }); + + const gifCollectionWithMetaData = await this.structureCollections(getAllGifCollections) + this.exploreCollections = [...this.exploreCollections, ...gifCollectionWithMetaData] + + this.pageNumber = this.pageNumber + 1 + } catch (error) { + console.error(error) + } + } + + async getCollectionList(){ + try { + return await parentEpml.request("apiCall", { + type: "api", + url: `/lists/gifSubscribedRepos`, + }); + + } catch (error) { + + } + } + + async addCollectionToList(collection){ + try { + const body = { + + "items": [ + collection + ] + + } + + const bodyToString = JSON.stringify(body) + await parentEpml.request("apiCall", { + type: "api", + method: "POST", + url: `/lists/gifSubscribedRepos`, + body: bodyToString, + headers: { + 'Content-Type': 'application/json' + } + }) + } catch (error) { + + } + } + + async removeCollectionFromList(collection){ + try { + + const body = { + + "items": [ + collection + ] + + } + const bodyToString = JSON.stringify(body) + await parentEpml.request("apiCall", { + type: "api", + method: 'DELETE', + url: `/lists/gifSubscribedRepos`, + body: bodyToString, + headers: { + 'Content-Type': 'application/json' + } + }) + } catch (error) { + + } + } + + async getMyGifCollections(){ + const userName = await this.getName(this.selectedAddress.address); + this.myAccountName = userName + if(this.myAccountName){ + const getMyGifColloctions = await parentEpml.request('apiCall', { + url: `/arbitrary/resources?service=GIF_REPOSITORY&limit=0&name=${this.myAccountName}` + }) + const gifCollectionWithMetaData = await this.structureCollections(getMyGifColloctions) + + console.log({gifCollectionWithMetaData}) + this.myGifCollections = gifCollectionWithMetaData + } + } + async getAllCollections(){ + this.pageNumber = 0 + // for the explore section + const getAllGifCollections = await parentEpml.request("apiCall", { + type: "api", + url: `/arbitrary/resources?service=GIF_REPOSITORY&limit=20&offset=${this.pageNumber * 20}`, + }); + const gifCollectionWithMetaData = await this.structureCollections(getAllGifCollections) + this.exploreCollections = gifCollectionWithMetaData + this.pageNumber = this.pageNumber + 1 + } + + async getSavedCollections(){ + const getCollectionList = await this.getCollectionList() + let savedCollections = [] + const getSavedGifRepos = (getCollectionList || []).map(async (collection) => { + let splitCollection = collection.split('/') + const name = splitCollection[0] + const identifier = splitCollection[1] + try { + console.log({collection}) + const data = await parentEpml.request('apiCall', { + url: `/arbitrary/resources?service=GIF_REPOSITORY&limit=0&name=${name}&identifier=${identifier}` + }) + if(data.length > 0){ + savedCollections.push(data[0]) + } + } catch (error) { + console.log(error) + } + return collection + }) + await Promise.all(getSavedGifRepos) + const savedCollectionsWithMetaData = await this.structureCollections(savedCollections) + this.mySubscribedCollections = 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; 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(--reactions-tooltip-bg); color: var(--chat-bubble-msg-color); text-align: center; padding: 20px 10px; border-radius: 8px; 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 + await this.getMyGifCollections() + await this.getAllCollections() + await this.getSavedCollections() + this.isLoading = false + } catch (error) { + this.isLoading = false + console.error(error) + } + } + + async updated(changedProperties) { + console.log({changedProperties}) + if (changedProperties && changedProperties.has('mode')) { + const mode = this.mode + console.log({mode}) + if (mode === 'myCollection') { + try { + this.isLoading = true + + await this.getMyGifCollections() + 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.isLoading = true + + await this.getSavedCollections() + this.isLoading = false + } catch (error) { + this.isLoading = false + } + + } + } + + + + } + + async getName (recipient) { + try { + const getNames = await parentEpml.request("apiCall", { + type: "api", + url: `/names/address/${recipient}`, + }); + + if (Array.isArray(getNames) && getNames.length > 0 ) { + return getNames[0].name + } else { + return '' + } + + } catch (error) { + return "" + } + } + + addGifs(gifs){ + console.log('gifs', gifs) + const mapGifs = gifs.map((file)=> { + return { + file, + name: file.name + } + }) + console.log({mapGifs}) + this.gifsToBeAdded = [...this.gifsToBeAdded, ...mapGifs] + console.log('this.gifsToBeAdded', this.gifsToBeAdded) + } + + async uploadGifCollection(){ + if(!this.newCollectionName){ + parentEpml.request('showSnackBar', get("chatpage.cchange27")); + return + } + + // if(!isAlphanumeric(this.newCollectionName)){ + // parentEpml.request('showSnackBar', get("chatpage.cchange27")); + // return + // } + try { + 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.cchange27")); + return + } + function blobToBase64(blob) { + return new Promise((resolve, _) => { + const reader = new FileReader(); + reader.onloadend = () => resolve(reader.result); + reader.readAsDataURL(blob); + }); + } + 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++) { + await zipWriter.add(this.gifsToBeAdded[i].name, new zip.BlobReader(this.gifsToBeAdded[i].file)); + } + + + await zipWriter.close(); + const zipFileBlob = await zipFileWriter.getData() + const blobTobase = await blobToBase64(zipFileBlob) + console.log({blobTobase}) + + if (!userName) { + parentEpml.request('showSnackBar', get("chatpage.cchange27")); + this.isLoading = false; + return; + } + const id = this.uid(); + const identifier = `gif_${id}`; + await publishData({ + registeredName: userName, + file : blobTobase.split(',')[1], + service: 'GIF_REPOSITORY', + identifier: this.newCollectionName, + parentEpml, + metaData: undefined, + uploadType: 'zip', + selectedAddress: this.selectedAddress, + worker: this.webWorkerImage, + isBase64: true + }) + + await new Promise((res)=> { + let interval = null + let stop = false + const getAnswer = async () => { + if (!stop) { + stop = true + try { + let myCollection = await parentEpml.request('apiCall', { + url: `/arbitrary/resources?service=GIF_REPOSITORY&limit=0&name=${userName}&identifier=${this.newCollectionName}` + }) + if (myCollection.length > 0) { + clearInterval(interval) + res() + } + } catch (error) {} + stop = false + } + } + interval = setInterval(getAnswer, 5000) + }) + + saveAs(zipFileBlob, 'zipfile'); + console.log({zipFileBlob}) + } catch (error) { + console.log(error) + } + } + + setCurrentCollection(val){ + this.currentCollection = val + } + + render() { + console.log('this.currentCollection', this.currentCollection) + console.log(3, "chat gifs here") + return html` +
+
+

${translate("chatpage.cchange80")}

+ { + if(this.isLoading) return; + this.mode = "explore"; + }} + icon="vaadin:search" + slot="icon"> + + + +
+
+ + + + ${this.mode === "myCollection" && !this.currentCollection ? html` + ${this.isLoading === true ? html` +

Loading...

+ ` : ''} + ${this.myGifCollections.map((collection)=> { + return html` +
+

{ + this.currentCollection = collection + }}>${collection.identifier}

+ +
+ ` + })} + ` : ''} + ${this.mode === "subscribedCollection" && !this.currentCollection ? html` + ${this.isLoading === true ? html` +

Loading...

+ ` : ''} + ${this.mySubscribedCollections.map((collection)=> { + return html` +
+

{ + this.currentCollection = collection + }}>${collection.identifier}

+ +
+ ` + })} + ` : ''} + ${this.mode === "explore" && !this.currentCollection ? html` + ${this.isLoading === true ? html` +

Loading...

+ ` : ''} + this.getMoreExploreGifs(val)} .exploreCollections=${this.exploreCollections} + .setCurrentCollection=${(val)=> this.setCurrentCollection(val)} + > + + ` : ''} + ${this.currentCollection && this.mode === "myCollection" ? html` + + ${this.currentCollection.gifUrls.map((gif)=> { + console.log({gif}) + + return html` + { + e.target.src = gif + }} src=${gif} style="width: 50px; height: 50px" /> + ` + })} + ` : ''} + ${this.currentCollection && this.mode === "subscribedCollection" ? html` + + ${this.currentCollection.gifUrls.map((gif)=> { + console.log({gif}) + + return html` + { + e.target.src = gif + }} src=${gif} style="width: 50px; height: 50px" /> + ` + })} + ` : ''} + ${this.currentCollection && this.mode === "explore" ? html` + + + ${this.currentCollection.gifUrls.map((gif)=> { + console.log({gif}) + + return html` + { + e.target.src = gif + }} src=${gif} style="width: 50px; height: 50px" /> + ` + })} + ` : ''} + ${this.mode === "newCollection" ? html` + + + + { + this.newCollectionName = e.target.value + })} /> +
+ ${this.gifsToBeAdded.map((gif, i)=> { + console.log({gif}) + return html` +
+ + { + this.gifsToBeAdded[i] = { + ...gif, + name: e.target.value + } + })} /> +
+ + ` + })} +
+ ` : ''} + +
+
+ ` + } + + +} + +window.customElements.define('chat-gifs', ChatGifs) diff --git a/qortal-ui-plugins/plugins/core/components/ChatGifsExplore.js b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifsExplore.js similarity index 96% rename from qortal-ui-plugins/plugins/core/components/ChatGifsExplore.js rename to qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifsExplore.js index bbd7fc3d..b5cca445 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatGifsExplore.js +++ b/qortal-ui-plugins/plugins/core/components/ChatGifs/ChatGifsExplore.js @@ -1,11 +1,11 @@ import { LitElement, html, css } from 'lit' import { render } from 'lit/html.js' -import { Epml } from '../../../epml.js' +import { Epml } from '../../../../epml.js' import * as zip from "@zip.js/zip.js"; import { saveAs } from 'file-saver'; import '@material/mwc-icon' import ShortUniqueId from 'short-unique-id'; -import { publishData } from '../../utils/publish-image.js'; +import { publishData } from '../../../utils/publish-image.js'; const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }) diff --git a/qortal-ui-plugins/plugins/core/components/ChatPage.js b/qortal-ui-plugins/plugins/core/components/ChatPage.js index 5ebc0247..e3bf62c3 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatPage.js +++ b/qortal-ui-plugins/plugins/core/components/ChatPage.js @@ -11,7 +11,7 @@ import {unsafeHTML} from 'lit/directives/unsafe-html.js'; import { Editor, Extension } from '@tiptap/core' import * as zip from "@zip.js/zip.js"; import { saveAs } from 'file-saver'; -import './ChatGifs' +import './ChatGifs/ChatGifs.js'; // import localForage from "localforage"; registerTranslateConfig({ loader: lang => fetch(`/language/${lang}.json`).then(res => res.json()) @@ -44,10 +44,6 @@ import WebWorker from 'web-worker:./computePowWorker.js'; import WebWorkerImage from 'web-worker:./computePowWorkerImage.js'; import '@polymer/paper-dialog/paper-dialog.js' -// const messagesCache = localForage.createInstance({ -// name: "messages-cache", -// }); - const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }) class ChatPage extends LitElement { @@ -111,724 +107,748 @@ class ChatPage extends LitElement { } static get styles() { - return css` - html { - scroll-behavior: smooth; - } + return css` + html { + scroll-behavior: smooth; + } + + .chat-head-container { + display: flex; + justify-content: flex-start; + flex-direction: column; + height: 50vh; + overflow-y: auto; + overflow-x: hidden; + width: 100%; + } - .chat-head-container { + .repliedTo-container { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 10px 10px 8px 10px; + } + + .senderName { + margin: 0; + color: var(--mdc-theme-primary); + font-weight: bold; + user-select: none; + } + + .original-message { + color: var(--chat-bubble-msg-color); + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + margin: 0; + width: 800px; + } + + + .close-icon { + color: #676b71; + width: 18px; + transition: all 0.1s ease-in-out; + } + + .close-icon:hover { + cursor: pointer; + color: #494c50; + } + + .chat-text-area .typing-area .chatbar { + position: relative; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: auto; + padding: 5px 5px 5px 7px; + overflow: hidden; + } + + .chat-text-area .typing-area .emoji-button { + width: 45px; + height: 40px; + padding-top: 4px; + border: none; + outline: none; + background: transparent; + cursor: pointer; + max-height: 40px; + color: var(--black); + } + + .emoji-button-caption { + width: 45px; + height: 40px; + padding-top: 4px; + border: none; + outline: none; + background: transparent; + cursor: pointer; + max-height: 40px; + color: var(--black); + } + + .caption-container { + width: 100%; + display: flex; + height: auto; + overflow: hidden; + justify-content: center; + background-color: var(--white); + padding: 5px; + border-radius: 1px; + } + + .chatbar-caption { + font-family: Roboto, sans-serif; + width: 70%; + margin-right: 10px; + outline: none; + align-items: center; + font-size: 18px; + resize: none; + border-top: 0; + border-right: 0; + border-left: 0; + border-bottom: 1px solid #cac8c8; + padding: 3px; + } + + .message-size-container { + display: flex; + justify-content: flex-end; + width: 100%; + } + + .message-size { + font-family: Roboto, sans-serif; + font-size: 12px; + color: black; + } + + .lds-grid { + width: 120px; + height: 120px; + position: absolute; + left: 50%; + top: 40%; + } + + img { + border-radius: 25%; + } + + .dialogCustom { + position: fixed; + z-index: 10000; + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + top: 10px; + right: 20px; + user-select: none; + } + + .dialogCustomInner { + min-width: 300px; + height: 40px; + background-color: var(--white); + box-shadow: rgb(119 119 119 / 32%) 0px 4px 12px; + padding: 10px; + border-radius: 4px; + } + + .dialogCustomInner ul { + padding-left: 0px + } + + .dialogCustomInner li { + margin-bottom: 10px; + } + + .marginLoader { + margin-right: 8px; + } + + .last-message-ref { + position: absolute; + font-size: 18px; + top: -40px; + right: 30px; + width: 50; + height: 50; + z-index: 5; + color: black; + background-color: white; + border-radius: 50%; + transition: all 0.1s ease-in-out; + } + + .last-message-ref:hover { + cursor: pointer; + transform: scale(1.1); + } + + .arrow-down-icon { + transform: scale(1.15); + } + + .chat-container { + display: grid; + max-height: 100%; + } + + .chat-text-area { + display: flex; + position: relative; + justify-content: center; + min-height: 60px; + max-height: 100%; + } + + .chat-text-area .typing-area { + display: flex; + flex-direction: column; + width: 98%; + box-sizing: border-box; + margin-bottom: 8px; + border: 1px solid var(--chat-bubble-bg); + border-radius: 10px; + background: var(--chat-bubble-bg); + } + + .chat-text-area .typing-area textarea { + display: none; + } + + .chat-text-area .typing-area .chat-editor { + display: flex; + max-height: -webkit-fill-available; + width: 100%; + border-color: transparent; + margin: 0; + padding: 0; + border: none; + } + + .repliedTo-container { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 10px 10px 8px 10px; + } + + .repliedTo-subcontainer { + display: flex; + flex-direction: row; + align-items: center; + gap: 15px; + width: 100%; + } + + .repliedTo-message { + display: flex; + flex-direction: column; + gap: 5px; + width: 100%; + word-break: break-all; + text-overflow: ellipsis; + overflow: hidden; + max-height: 60px; + } + .repliedTo-message p { + margin: 0px; + padding: 0px; + } + + .repliedTo-message pre { + white-space: pre-wrap; + } + + .repliedTo-message p mark { + background-color: #ffe066; + border-radius: 0.25em; + box-decoration-break: clone; + padding: 0.125em 0; + } + + .reply-icon { + width: 20px; + color: var(--mdc-theme-primary); + } + + .close-icon { + color: #676b71; + width: 18px; + transition: all 0.1s ease-in-out; + } + + .close-icon:hover { + cursor: pointer; + color: #494c50; + } + + .chatbar-container { + width: 100%; + display: flex; + height: auto; + overflow: hidden; + } + + .lds-grid { + width: 120px; + height: 120px; + position: absolute; + left: 50%; + top: 40%; + } + + .lds-grid div { + position: absolute; + width: 34px; + height: 34px; + border-radius: 50%; + background: #03a9f4; + animation: lds-grid 1.2s linear infinite; + } + + .lds-grid div:nth-child(1) { + top: 4px; + left: 4px; + animation-delay: 0s; + } + + .lds-grid div:nth-child(2) { + top: 4px; + left: 48px; + animation-delay: -0.4s; + } + + .lds-grid div:nth-child(3) { + top: 4px; + left: 90px; + animation-delay: -0.8s; + } + + .lds-grid div:nth-child(4) { + top: 50px; + left: 4px; + animation-delay: -0.4s; + } + + .lds-grid div:nth-child(5) { + top: 50px; + left: 48px; + animation-delay: -0.8s; + } + + .lds-grid div:nth-child(6) { + top: 50px; + left: 90px; + animation-delay: -1.2s; + } + + .lds-grid div:nth-child(7) { + top: 95px; + left: 4px; + animation-delay: -0.8s; + } + + .lds-grid div:nth-child(8) { + top: 95px; + left: 48px; + animation-delay: -1.2s; + } + + .lds-grid div:nth-child(9) { + top: 95px; + left: 90px; + animation-delay: -1.6s; + } + + @keyframes lds-grid { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } + } + + .float-left { + float: left; + } + + img { + border-radius: 25%; + } + + paper-dialog.warning { + width: 50%; + max-width: 50vw; + height: 30%; + max-height: 30vh; + text-align: center; + background-color: var(--white); + color: var(--black); + border: 1px solid var(--black); + border-radius: 15px; + line-height: 1.6; + overflow-y: auto; + } + .buttons { + text-align:right; + } + + .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) + } + + .dialogCustomInner { + min-width: 300px; + height: 40px; + background-color: var(--white); + box-shadow: rgb(119 119 119 / 32%) 0px 4px 12px; + 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.8em; + 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); + } + } + + /* Add Image Modal Dialog Styling */ + + .dialog-container { + position: relative; + display: flex; + align-items: center; + flex-direction: column; + padding: 0 10px; + gap: 10px; + height: 100%; + } + + .dialog-container-title { + font-family: Montserrat; + color: var(--black); + font-size: 20px; + margin: 15px 0 0 0; + } + + .divider { + height: 1px; + background-color: var(--chat-bubble-msg-color); + user-select: none; + width: 70%; + margin-bottom: 20px; + } + + .dialog-container-loader { + position: relative; + display: flex; + align-items: center; + padding: 0 10px; + gap: 10px; + height: 100%; + } + + .dialog-image { + width: 100%; + max-height: 300px; + border-radius: 0; + object-fit: contain; + } + + .chat-right-panel { + flex: 0; + border-left: 3px solid rgb(221, 221, 221); + height: 100%; + overflow-y: auto; + background: transparent; + } + + .movedin { + flex: 1 !important; + background: transparent; + } + + .main-container { + display: flex; + height: 100%; + } + + .group-nav-container { + display: flex; + height: 40px; + padding: 25px 5px 25px 20px; + margin: 0px; + background-color: var(--chat-bubble-bg); + box-sizing: border-box; + align-items: center; + justify-content: space-between; + box-shadow: var(--group-drop-shadow); + } + + .top-bar-icon { + border-radius: 50%; + color: var(--chat-bubble-msg-color); + transition: 0.3s all ease-in-out; + padding: 5px; + background-color: transparent; + } + + .top-bar-icon:hover { + background-color: #e6e6e69b; + cursor: pointer; + color: var(--black) + } + + .group-name { + font-family: Raleway, sans-serif; + font-size: 16px; + color: var(--black); + margin:0px; + padding:0px; + } + + .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%; + margin-bottom: 15px; + 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); + box-sizing: border-box; + } + + .name-input::selection { + background-color: var(--mdc-theme-primary); + color: white; + } + + .name-input::placeholder { + opacity: 0.9; + color: var(--black); + } + + .search-results-div { + position: absolute; + top: 25px; + right: 25px; + } + + .search-field { + width: 100%; + position: relative; + margin-bottom: 5px; + } + + .search-icon { + position: absolute; + right: 3px; + top: 0; + 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; + } + + .user-verified { + position: absolute; + top: 0; + right: 5px; display: flex; - justify-content: flex-start; - flex-direction: column; - height: 50vh; - overflow-y: auto; - overflow-x: hidden; - width: 100%; - } - - .repliedTo-container { + align-items: center; + gap: 10px; + color: #04aa2e; + font-size: 13px; + } + + .user-selected { display: flex; - flex-direction: row; justify-content: space-between; align-items: center; - padding: 10px 10px 8px 10px; - } - - .senderName { margin: 0; - color: var(--mdc-theme-primary); - font-weight: bold; - user-select: none; - } - - .original-message { + box-shadow: rgb(0 0 0 / 16%) 0px 3px 6px, rgb(0 0 0 / 23%) 0px 3px 6px; + padding: 18px 20px; color: var(--chat-bubble-msg-color); - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - margin: 0; - width: 800px; - } - - - .close-icon { - color: #676b71; - width: 18px; - transition: all 0.1s ease-in-out; - } - - .close-icon:hover { - cursor: pointer; - color: #494c50; - } + border-radius: 5px; + background-color: #ececec96; + } - .chat-text-area .typing-area .chatbar { + .user-selected-name { + font-family: Roboto, sans-serif; + margin: 0; + font-size: 16px; + } + + .forwarding-container { + display: flex; + gap: 15px; + } + + .user-selected-forwarding { + font-family: Livvic, sans-serif; + margin: 0; + font-size: 16px; + } + + .close-forwarding { + color: #676b71; + width: 14px; + transition: all 0.1s ease-in-out; + } + + .close-forwarding:hover { + cursor: pointer; + color: #4e5054; + } + + .gifs-backdrop { + height: 100vh; + width: 100vw; + background: transparent; + position: fixed; + } + + .gifs-container { position: relative; display: flex; - flex-direction: column; - justify-content: center; + padding: 10px 15px; + border-radius: 12px; + box-shadow: rgba(0, 0, 0, 0.09) 0px 3px 12px; + background-color: var(--chat-menu-bg); align-items: center; - height: auto; - padding: 5px 5px 5px 7px; - overflow: hidden; - } - - .chat-text-area .typing-area .emoji-button { - width: 45px; - height: 40px; - padding-top: 4px; - border: none; - outline: none; - background: transparent; - cursor: pointer; - max-height: 40px; - color: var(--black); - } - - .emoji-button-caption { - width: 45px; - height: 40px; - padding-top: 4px; - border: none; - outline: none; - background: transparent; - cursor: pointer; - max-height: 40px; - color: var(--black); - } - - .caption-container { - width: 100%; - display: flex; - height: auto; - overflow: hidden; - justify-content: center; - background-color: var(--white); - padding: 5px; - border-radius: 1px; - } - - .chatbar-caption { - font-family: Roboto, sans-serif; - width: 70%; - margin-right: 10px; - outline: none; - align-items: center; - font-size: 18px; - resize: none; - border-top: 0; - border-right: 0; - border-left: 0; - border-bottom: 1px solid #cac8c8; - padding: 3px; - } - - .message-size-container { - display: flex; justify-content: flex-end; - width: 100%; - } - - .message-size { - font-family: Roboto, sans-serif; - font-size: 12px; - color: black; - } - - .lds-grid { - width: 120px; - height: 120px; - position: absolute; - left: 50%; - top: 40%; - } - - img { - border-radius: 25%; - } - - .dialogCustom { - position: fixed; - z-index: 10000; - display: flex; - justify-content: center; - flex-direction: column; - align-items: center; - top: 10px; - right: 20px; - user-select: none; - } - - .dialogCustomInner { - min-width: 300px; - height: 40px; - background-color: var(--white); - box-shadow: rgb(119 119 119 / 32%) 0px 4px 12px; - padding: 10px; - border-radius: 4px; - } - - .dialogCustomInner ul { - padding-left: 0px - } - - .dialogCustomInner li { - margin-bottom: 10px; - } - - .marginLoader { - margin-right: 8px; - } - - .last-message-ref { - position: absolute; - font-size: 18px; - top: -40px; - right: 30px; - width: 50; - height: 50; + width: fit-content; + justify-self: flex-end; + margin-bottom: 8px; + margin-right: 5px; + box-shadow: var(--gifs-drop-shadow); z-index: 5; - color: black; - background-color: white; - border-radius: 50%; - transition: all 0.1s ease-in-out; } - - .last-message-ref:hover { - cursor: pointer; - transform: scale(1.1); + ` } - .arrow-down-icon { - transform: scale(1.15); - } - - .chat-container { - display: grid; - max-height: 100%; - } - - .chat-text-area { - display: flex; - position: relative; - justify-content: center; - min-height: 60px; - max-height: 100%; - } - - .chat-text-area .typing-area { - display: flex; - flex-direction: column; - width: 98%; - box-sizing: border-box; - margin-bottom: 8px; - border: 1px solid var(--chat-bubble-bg); - border-radius: 10px; - background: var(--chat-bubble-bg); - } - - .chat-text-area .typing-area textarea { - display: none; - } - - .chat-text-area .typing-area .chat-editor { - display: flex; - max-height: -webkit-fill-available; - width: 100%; - border-color: transparent; - margin: 0; - padding: 0; - border: none; - } - - .repliedTo-container { - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - padding: 10px 10px 8px 10px; - } - - .repliedTo-subcontainer { - display: flex; - flex-direction: row; - align-items: center; - gap: 15px; - width: 100%; - } - - .repliedTo-message { - display: flex; - flex-direction: column; - gap: 5px; - width: 100%; - word-break: break-all; - text-overflow: ellipsis; - overflow: hidden; - max-height: 60px; - } - .repliedTo-message p { - margin: 0px; - padding: 0px; - } - - .repliedTo-message pre { - white-space: pre-wrap; - } - - .repliedTo-message p mark { - background-color: #ffe066; - border-radius: 0.25em; - box-decoration-break: clone; - padding: 0.125em 0; - } - - .reply-icon { - width: 20px; - color: var(--mdc-theme-primary); - } - - .close-icon { - color: #676b71; - width: 18px; - transition: all 0.1s ease-in-out; - } - - .close-icon:hover { - cursor: pointer; - color: #494c50; - } - - .chatbar-container { - width: 100%; - display: flex; - height: auto; - overflow: hidden; - } - - .lds-grid { - width: 120px; - height: 120px; - position: absolute; - left: 50%; - top: 40%; - } - - .lds-grid div { - position: absolute; - width: 34px; - height: 34px; - border-radius: 50%; - background: #03a9f4; - animation: lds-grid 1.2s linear infinite; - } - - .lds-grid div:nth-child(1) { - top: 4px; - left: 4px; - animation-delay: 0s; - } - - .lds-grid div:nth-child(2) { - top: 4px; - left: 48px; - animation-delay: -0.4s; - } - - .lds-grid div:nth-child(3) { - top: 4px; - left: 90px; - animation-delay: -0.8s; - } - - .lds-grid div:nth-child(4) { - top: 50px; - left: 4px; - animation-delay: -0.4s; - } - - .lds-grid div:nth-child(5) { - top: 50px; - left: 48px; - animation-delay: -0.8s; - } - - .lds-grid div:nth-child(6) { - top: 50px; - left: 90px; - animation-delay: -1.2s; - } - - .lds-grid div:nth-child(7) { - top: 95px; - left: 4px; - animation-delay: -0.8s; - } - - .lds-grid div:nth-child(8) { - top: 95px; - left: 48px; - animation-delay: -1.2s; - } - - .lds-grid div:nth-child(9) { - top: 95px; - left: 90px; - animation-delay: -1.6s; - } - - @keyframes lds-grid { - 0%, 100% { - opacity: 1; - } - 50% { - opacity: 0.5; - } -} - - .float-left { - float: left; - } - - img { - border-radius: 25%; - } - - paper-dialog.warning { - width: 50%; - max-width: 50vw; - height: 30%; - max-height: 30vh; - text-align: center; - background-color: var(--white); - color: var(--black); - border: 1px solid var(--black); - border-radius: 15px; - line-height: 1.6; - overflow-y: auto; - } - .buttons { - text-align:right; - } - - .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) - } - - .dialogCustomInner { - min-width: 300px; - height: 40px; - background-color: var(--white); - box-shadow: rgb(119 119 119 / 32%) 0px 4px 12px; - 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.8em; - 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); - } - } - - /* Add Image Modal Dialog Styling */ - - .dialog-container { - position: relative; - display: flex; - align-items: center; - flex-direction: column; - padding: 0 10px; - gap: 10px; - height: 100%; - } - - .dialog-container-title { - font-family: Montserrat; - color: var(--black); - font-size: 20px; - margin: 15px 0 0 0; - } - - .divider { - height: 1px; - background-color: var(--chat-bubble-msg-color); - user-select: none; - width: 70%; - margin-bottom: 20px; - } - - .dialog-container-loader { - position: relative; - display: flex; - align-items: center; - padding: 0 10px; - gap: 10px; - height: 100%; - } - - .dialog-image { - width: 100%; - max-height: 300px; - border-radius: 0; - object-fit: contain; - } - - .chat-right-panel { - flex: 0; - border-left: 3px solid rgb(221, 221, 221); - height: 100%; - overflow-y: auto; - background: transparent; - } - - .movedin { - flex: 1 !important; - background: transparent; - } - - .main-container { - display: flex; - height: 100%; - } - - .group-nav-container { - display: flex; - height: 40px; - padding: 25px 5px 25px 20px; - margin: 0px; - background-color: var(--chat-bubble-bg); - box-sizing: border-box; - align-items: center; - justify-content: space-between; - box-shadow: var(--group-drop-shadow); - } - - .top-bar-icon { - border-radius: 50%; - color: var(--chat-bubble-msg-color); - transition: 0.3s all ease-in-out; - padding: 5px; - background-color: transparent; - } - - .top-bar-icon:hover { - background-color: #e6e6e69b; - cursor: pointer; - color: var(--black) - } - - .group-name { - font-family: Raleway, sans-serif; - font-size: 16px; - color: var(--black); - margin:0px; - padding:0px; - } - - .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%; - margin-bottom: 15px; - 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); - box-sizing: border-box; - } - - .name-input::selection { - background-color: var(--mdc-theme-primary); - color: white; - } - - .name-input::placeholder { - opacity: 0.9; - color: var(--black); - } - - .search-results-div { - position: absolute; - top: 25px; - right: 25px; - } - - .search-field { - width: 100%; - position: relative; - margin-bottom: 5px; - } - - .search-icon { - position: absolute; - right: 3px; - top: 0; - 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; - } - - .user-verified { - position: absolute; - top: 0; - right: 5px; - display: flex; - align-items: center; - gap: 10px; - color: #04aa2e; - font-size: 13px; - } - - .user-selected { - display: flex; - justify-content: space-between; - align-items: center; - margin: 0; - box-shadow: rgb(0 0 0 / 16%) 0px 3px 6px, rgb(0 0 0 / 23%) 0px 3px 6px; - padding: 18px 20px; - color: var(--chat-bubble-msg-color); - border-radius: 5px; - background-color: #ececec96; - } - - .user-selected-name { - font-family: Roboto, sans-serif; - margin: 0; - font-size: 16px; - } - - .forwarding-container { - display: flex; - gap: 15px; - } - - .user-selected-forwarding { - font-family: Livvic, sans-serif; - margin: 0; - font-size: 16px; - } - - .close-forwarding { - color: #676b71; - width: 14px; - transition: all 0.1s ease-in-out; - } - - .close-forwarding:hover { - cursor: pointer; - color: #4e5054; - } -` -} - constructor() { super() this.getOldMessage = this.getOldMessage.bind(this) @@ -897,8 +917,8 @@ class ChatPage extends LitElement { this.openGifModal = false } + setOpenGifModal(value){ - console.log({value}) this.openGifModal = value } @@ -994,6 +1014,7 @@ console.log({zipFileBlob}) } render() { + console.log(23, "chat page here"); return html`
+ +
{ + this.editor.commands.focus("end"); + this.setOpenGifModal(false); + }} style=${this.openGifModal ? "visibility: visible; z-index: 4" : "visibility: hidden; z-index: -100"}> +
+
+ + +
+
-
@@ -1053,12 +1087,11 @@ console.log({zipFileBlob}) ` : ''} ${this.repliedToMessageObj.toString() === '2' ? html` ${unsafeHTML(generateHTML(this.repliedToMessageObj.message, [ - StarterKit, - Underline, - Highlight - // other extensions … - ]))} ` : ''} - + StarterKit, + Underline, + Highlight + // other extensions … + ]))} ` : ''}

${translate("chatpage.cchange25")}

${unsafeHTML(generateHTML(this.editedMessageObj.message, [ - StarterKit, - Underline, - Highlight - // other extensions … - ]))} + StarterKit, + Underline, + Highlight + // other extensions … + ]))}
this.setOpenGifModal(val)} > @@ -1130,15 +1164,6 @@ console.log({zipFileBlob})
`: ''} - - { - this.setOpenGifModal(false) - // this.removeImage(); - }} - style=${this.openGifModal ? "visibility:visible;z-index:50" : "visibility: hidden;z-index:-100"}> - - { this.removeImage(); @@ -1499,7 +1524,7 @@ console.log({zipFileBlob}) } initialChat(e) { - if (this.editor && !this.editor.isFocused && this.currentEditor === '_chatEditorDOM' && !this.openForwardOpen && !this.openTipUser &&!this.openGifModal) { + if (this.editor && !this.editor.isFocused && this.currentEditor === '_chatEditorDOM' && !this.openForwardOpen && !this.openTipUser && !this.openGifModal) { // WARNING: Deprecated methods from KeyBoard Event if (e.code === "Space" || e.keyCode === 32 || e.which === 32) { } else if (inputKeyCodes.includes(e.keyCode)) { diff --git a/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js b/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js index 70a7d068..5393dfc2 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js +++ b/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js @@ -30,6 +30,7 @@ class ChatTextEditor extends LitElement { }, toggleEnableChatEnter: {attribute: false}, isEnabledChatEnter: {type: Boolean}, + openGifModal: { type: Boolean }, setOpenGifModal: {attribute: false} } } @@ -361,69 +362,63 @@ class ChatTextEditor extends LitElement { return html`
- + class=${["chatbar-container", "chatbar-buttons", this.iframeId !=="_chatEditorDOM" && 'hide-styling'].join(" ")} + style="align-items: center;"> - - - - - - - + @click=${() => this.editor.chain().focus().toggleBold().run()} + ?disabled=${ + this.editor && + !this.editor.can() + .chain() + .focus() + .toggleBold() + .run() + } + class=${["chatbar-button-single", (this.editedMessageObj || this.repliedToMessageObj || this.openGifModal) && 'show-chatbar-buttons', this.editor && this.editor.isActive('bold') ? 'is-active' : ''].join(" ")}> + + + + + + +