diff --git a/qortal-ui-plugins/plugins/core/components/ChatGifs.js b/qortal-ui-plugins/plugins/core/components/ChatGifs.js
new file mode 100644
index 00000000..3ddb8017
--- /dev/null
+++ b/qortal-ui-plugins/plugins/core/components/ChatGifs.js
@@ -0,0 +1,276 @@
+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';
+
+const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
+
+class ChatGifs extends LitElement {
+ static get properties() {
+ return {
+ selectedAddress: { type: Object },
+ myGifCollections: { type: Array },
+ gifsToBeAdded: { type: Array},
+ webWorkerImage: {type: Object},
+ mode: {type: String},
+ currentCollection: {type: String}
+ }
+ }
+
+ static get styles() {
+ return css`
+
+ `
+ }
+
+ constructor() {
+ super()
+ this.uid = new ShortUniqueId()
+ this.selectedAddress = window.parent.reduxStore.getState().app.selectedAddress
+ this.myGifCollections = []
+ this.myAccountName = ''
+ this.gifsToBeAdded = []
+ // mode can be 'myCollection', 'newCollection', 'explore', 'subscribedCollection'
+ this.mode = "myCollection"
+ this.currentCollection = null
+ }
+
+ async firstUpdated() {
+
+
+ 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 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 getMetaDataGifs = (getMyGifColloctions || []).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.description){
+ const metaDataArray = metaData.description.split(';').map((data)=> {
+ return `${nodeUrl}/arbitrary/GIF_REPOSITORY/${this.myAccountName}/${collection.identifier}?filepath=${data}`
+ })
+ const listOfGifs = [`${nodeUrl}/arbitrary/GIF_REPOSITORY/Phil/gif_pmBEwm?filepath=giphy (1).gif`, `${nodeUrl}/arbitrary/GIF_REPOSITORY/Phil/gif_pmBEwm?filepath=giphy (3).gif`]
+
+ collectionObj = {
+ ...collection,
+ gifUrls: metaDataArray
+ }
+
+ }
+
+
+
+ } catch (error) {
+ console.log(error)
+ }
+
+ return collectionObj
+ })
+ const gifCollectionWithMetaData = await Promise.all(getMetaDataGifs)
+ console.log({gifCollectionWithMetaData})
+ this.myGifCollections = gifCollectionWithMetaData
+ }
+
+ } catch (error) {
+
+ }
+ }
+
+ 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(){
+ try {
+ 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})
+const userName = await this.getName(this.selectedAddress.address);
+ 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: identifier,
+ parentEpml,
+ metaData: undefined,
+ uploadType: 'zip',
+ selectedAddress: this.selectedAddress,
+ worker: this.webWorkerImage,
+ isBase64: true,
+ metaData: `description=${this.gifsToBeAdded.map((gif)=> gif.name).join(';')}`
+ })
+saveAs(zipFileBlob, 'zipfile');
+console.log({zipFileBlob})
+ } catch (error) {
+ console.log(error)
+ }
+ }
+
+ render() {
+
+ return html`
+
+
+
+
+
+
+
+
+${this.mode === "myCollection" && !this.currentCollection ? html`
+ ${this.myGifCollections.map((collection)=> {
+ return html`
+
+
{
+ this.currentCollection = collection
+ }}>${collection.identifier}
+
+
+ `
+ })}
+ ` : ''}
+ ${this.currentCollection ? 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.addGifs(Array.from(e.target.files));
+ const filePickerInput = this.shadowRoot.getElementById('file-picker-gif')
+ if(filePickerInput){
+ filePickerInput.value = ""
+ }
+ }
+ }"
+ id="file-picker-gif"
+ ?multiple=${true}
+ class="file-picker-input-gif" type="file" name="myGif" accept="image/gif" />
+
+
+
+ ${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/ChatPage.js b/qortal-ui-plugins/plugins/core/components/ChatPage.js
index 0ade923f..5ebc0247 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 localForage from "localforage";
registerTranslateConfig({
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
@@ -106,7 +106,7 @@ class ChatPage extends LitElement {
selectedHead: { type: Object },
userName: { type: String },
goToRepliedMessage: {attribute: false},
- gifsToBeAdded: { type: Array}
+ openGifModal: {type: Boolean}
}
}
@@ -894,7 +894,12 @@ class ChatPage extends LitElement {
this.currentEditor = '_chatEditorDOM'
this.initialChat = this.initialChat.bind(this)
this.isEnabledChatEnter = true
- this.gifsToBeAdded = []
+ this.openGifModal = false
+ }
+
+ setOpenGifModal(value){
+ console.log({value})
+ this.openGifModal = value
}
_toggle(value) {
@@ -1104,6 +1109,7 @@ console.log({zipFileBlob})
.repliedToMessageObj=${this.repliedToMessageObj}
.toggleEnableChatEnter=${this.toggleEnableChatEnter}
?isEnabledChatEnter=${this.isEnabledChatEnter}
+ .setOpenGifModal=${(val)=> this.setOpenGifModal(val)}
>
@@ -1124,6 +1130,15 @@ console.log({zipFileBlob})
`: ''}
+
+ {
+ this.setOpenGifModal(false)
+ // this.removeImage();
+ }}
+ style=${this.openGifModal ? "visibility:visible;z-index:50" : "visibility: hidden;z-index:-100"}>
+
+
{
this.removeImage();
@@ -1174,34 +1189,7 @@ console.log({zipFileBlob})
-
- {
- // this.removeImage();
- }}
- style=${true ? "visibility:visible;z-index:50" : "visibility: hidden;z-index:-100"}>
-
-
-
- {
- this.addGifs(e.target.files);
- const filePickerInput = this.shadowRoot.getElementById('file-picker-gif')
- if(filePickerInput){
- filePickerInput.value = ""
- }
- }
- }"
- id="file-picker-gif"
- ?multiple=${true}
- class="file-picker-input-gif" type="file" name="myGif" accept="image/gif" />
-
-
-
-
-
+
${translate("chatpage.cchange41")}
@@ -1511,7 +1499,7 @@ console.log({zipFileBlob})
}
initialChat(e) {
- if (this.editor && !this.editor.isFocused && this.currentEditor === '_chatEditorDOM' && !this.openForwardOpen && !this.openTipUser) {
+ 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 cc371fa4..70a7d068 100644
--- a/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js
+++ b/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js
@@ -29,7 +29,8 @@ class ChatTextEditor extends LitElement {
reflect: true
},
toggleEnableChatEnter: {attribute: false},
- isEnabledChatEnter: {type: Boolean}
+ isEnabledChatEnter: {type: Boolean},
+ setOpenGifModal: {attribute: false}
}
}
@@ -461,6 +462,13 @@ class ChatTextEditor extends LitElement {
+ ${this.setOpenGifModal ?
+ html`
+
+ `
+ : ''}
${this.editedMessageObj ? (
html`
diff --git a/qortal-ui-plugins/plugins/utils/publish-image.js b/qortal-ui-plugins/plugins/utils/publish-image.js
index 5835aa33..ed8e2a64 100644
--- a/qortal-ui-plugins/plugins/utils/publish-image.js
+++ b/qortal-ui-plugins/plugins/utils/publish-image.js
@@ -17,7 +17,8 @@ export const publishData = async ({
uploadType,
selectedAddress,
worker,
- isBase64
+ isBase64,
+ metaData
}) => {
const validateName = async (receiverName) => {
let nameRes = await parentEpml.request("apiCall", {
@@ -131,7 +132,13 @@ export const publishData = async ({
let uploadDataUrl = `/arbitrary/${service}/${registeredName}${urlSuffix}?apiKey=${getApiKey()}`
if (identifier != null && identifier.trim().length > 0) {
uploadDataUrl = `/arbitrary/${service}/${registeredName}/${identifier}${urlSuffix}?apiKey=${getApiKey()}`
+
+ if(metaData){
+ uploadDataUrl = `/arbitrary/${service}/${registeredName}/${identifier}${urlSuffix}?${metaData}&apiKey=${getApiKey()}`
+
+ }
}
+
let uploadDataRes = await parentEpml.request("apiCall", {
type: "api",
method: "POST",