From a80f6800d8159793d562c1c60994f5f36b2ad798 Mon Sep 17 00:00:00 2001 From: PhilReact Date: Fri, 22 Sep 2023 01:40:14 -0500 Subject: [PATCH] right side panel for imgs --- core/language/us.json | 3 +- plugins/plugins/core/components/ChatImage.js | 6 +- plugins/plugins/core/components/ChatPage.js | 55 +- .../components/ChatRightPanelResources.js | 651 ++++++++++++++++++ .../plugins/core/components/ChatScroller.js | 43 +- .../plugins/core/components/ReusableImage.js | 337 +++++++++ 6 files changed, 1039 insertions(+), 56 deletions(-) create mode 100644 plugins/plugins/core/components/ChatRightPanelResources.js create mode 100644 plugins/plugins/core/components/ReusableImage.js diff --git a/core/language/us.json b/core/language/us.json index cb820354..aec0628f 100644 --- a/core/language/us.json +++ b/core/language/us.json @@ -835,7 +835,8 @@ "cchange91": "Sending...", "cchange92": "Unread messages below", "cchange93": "Image copied to clipboard", - "cchange94": "loaded" + "cchange94": "loaded", + "cchange95": "Only my resources" }, "welcomepage": { "wcchange1": "Welcome to Q-Chat", diff --git a/plugins/plugins/core/components/ChatImage.js b/plugins/plugins/core/components/ChatImage.js index 238404ba..39aadd91 100644 --- a/plugins/plugins/core/components/ChatImage.js +++ b/plugins/plugins/core/components/ChatImage.js @@ -198,11 +198,7 @@ getMyNode(){ setTimeout(() => { isCalling = false - this.fetchResource({ - name, - service, - identifier - }) + this.fetchResource() }, 25000) return } diff --git a/plugins/plugins/core/components/ChatPage.js b/plugins/plugins/core/components/ChatPage.js index b3bae116..817be13e 100644 --- a/plugins/plugins/core/components/ChatPage.js +++ b/plugins/plugins/core/components/ChatPage.js @@ -10,6 +10,7 @@ import { inputKeyCodes } from '../../utils/keyCodes.js' import { replaceMessagesEdited } from '../../utils/replace-messages-edited.js' import { publishData } from '../../utils/publish-image.js' import { EmojiPicker } from 'emoji-picker-js' +import {ifDefined} from 'lit/directives/if-defined.js'; import * as zip from '@zip.js/zip.js' @@ -38,6 +39,7 @@ import './ChatSideNavHeads.js' import './ChatLeaveGroup.js' import './ChatGroupSettings.js' import './ChatRightPanel.js' +import './ChatRightPanelResources.js' import './ChatSearchResults.js' import '@material/mwc-button' import '@material/mwc-dialog' @@ -105,6 +107,7 @@ class ChatPage extends LitElement { groupAdmin: { type: Array }, groupMembers: { type: Array }, shifted: { type: Boolean }, + shiftedResources: {type: Boolean}, groupInfo: { type: Object }, setActiveChatHeadUrl: { attribute: false }, userFound: { type: Array }, @@ -1058,13 +1061,14 @@ class ChatPage extends LitElement { .group-nav-container { display: flex; height: 40px; - padding: 25px 5px 25px 20px; + padding: 5px; 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); + z-index: 1; } .top-bar-icon { @@ -1344,6 +1348,7 @@ class ChatPage extends LitElement { this.groupAdmin = [] this.groupMembers = [] this.shifted = false + this.shiftedResources = false this.groupInfo = {} this.pageNumber = 1 this.userFoundModalOpen = false @@ -1389,6 +1394,10 @@ class ChatPage extends LitElement { this.shifted = value === (false || true) ? value : !this.shifted this.requestUpdate() } + _toggleResources(value) { + this.shiftedResources = value === (false || true) ? value : !this.shiftedResources + this.requestUpdate() + } setOpenTipUser(props) { this.openTipUser = props @@ -1489,23 +1498,32 @@ class ChatPage extends LitElement { render() { - + console.log('this.chatId', this.chatId, this._chatId) return html`
- ${(!this.isReceipient && +this._chatId !== 0) ? - html` + style="grid-template-rows: minmax(40px, auto) minmax(6%, 92vh) minmax(40px, auto); flex: 3;"> +
+ ${this.isReceipient ? '' : +this._chatId === 0 ? html` +

Qortal General Chat

+ ` : html`

${this.groupInfo && this.groupInfo.groupName}

+ `} +
- + photo_library + ${(!this.isReceipient && +this._chatId !== 0) ? + html` + groups + ` + : ''}
- ` : null} +
${this.isLoadingMessages ? html` @@ -1949,6 +1967,24 @@ class ChatPage extends LitElement { >
+
+ this.getMoreMembers(val)} + .toggle=${(val) => this._toggleResources(val)} + .selectedAddress=${this.selectedAddress} + .groupMembers=${this.groupMembers} + .groupAdmin=${this.groupAdmin} + .leaveGroupObj=${this.groupInfo} + .setOpenPrivateMessage=${(val) => this.setOpenPrivateMessage(val)} + .setOpenTipUser=${(val) => this.setOpenTipUser(val)} + .setOpenUserInfo=${(val) => this.setOpenUserInfo(val)} + .setUserName=${(val) => this.setUserName(val)} + _chatId=${ifDefined(this._chatId)} + chatId=${this.chatId} + ?isreceipient=${this.isReceipient} + > + +
` } @@ -2901,7 +2937,7 @@ class ChatPage extends LitElement { })); let list = [...decodeMsgs] - + this.messagesRendered = { messages: list, @@ -3890,7 +3926,8 @@ class ChatPage extends LitElement { const image = this.imageFile const id = this.uid.rnd() - const identifier = `qchat_${id}` + const groupPart = this.isReceipient ? `direct_${this._chatId.slice(-15)}` : `group_${this._chatId}` + const identifier = `qchat_${groupPart}_${id}` let compressedFile = '' await new Promise(resolve => { new Compressor(image, { diff --git a/plugins/plugins/core/components/ChatRightPanelResources.js b/plugins/plugins/core/components/ChatRightPanelResources.js new file mode 100644 index 00000000..cb5f3703 --- /dev/null +++ b/plugins/plugins/core/components/ChatRightPanelResources.js @@ -0,0 +1,651 @@ +import { LitElement, html, css } from 'lit'; +import { render } from 'lit/html.js'; +import { Epml } from '../../../epml'; +import { getUserNameFromAddress } from '../../utils/getUserNameFromAddress'; +import snackbar from './snackbar.js'; +import '@material/mwc-button'; +import '@material/mwc-dialog'; +import '@polymer/paper-spinner/paper-spinner-lite.js'; +import '@polymer/paper-progress/paper-progress.js'; +import '@material/mwc-icon'; +import '@vaadin/button'; +import './WrapperModal'; +import './TipUser'; +import './UserInfo/UserInfo'; +import './ChatImage'; +import './ReusableImage'; +import { + use, + get, + translate, + translateUnsafeHTML, + registerTranslateConfig, +} from 'lit-translate'; + +const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }); + +class ChatRightPanelResources extends LitElement { + static get properties() { + return { + leaveGroupObj: { type: Object }, + error: { type: Boolean }, + chatHeads: { type: Array }, + groupAdmin: { attribute: false }, + groupMembers: { attribute: false }, + selectedHead: { type: Object }, + toggle: { attribute: false }, + getMoreMembers: { attribute: false }, + setOpenPrivateMessage: { attribute: false }, + userName: { type: String }, + walletBalance: { type: Number }, + sendMoneyLoading: { type: Boolean }, + btnDisable: { type: Boolean }, + errorMessage: { type: String }, + successMessage: { type: String }, + setOpenTipUser: { attribute: false }, + setOpenUserInfo: { attribute: false }, + setUserName: { attribute: false }, + chatId: { type: String }, + _chatId: { type: String }, + isReceipient: { type: Boolean }, + images: { type: Array }, + viewImage: { type: Boolean }, + autoView: {type: Boolean}, + onlyMyImages: {type: Boolean} + }; + } + + constructor() { + super(); + this.leaveGroupObj = {}; + this.leaveFee = 0.001; + this.error = false; + this.chatHeads = []; + this.groupAdmin = []; + this.groupMembers = []; + this.observerHandler = this.observerHandler.bind(this); + this.getMoreImages = this.getMoreImages.bind(this); + this.viewElement = ''; + this.downObserverElement = ''; + + this.sendMoneyLoading = false; + this.btnDisable = false; + this.errorMessage = ''; + this.successMessage = ''; + + this.images = []; + this.viewImage = false; + this.myName = + window.parent.reduxStore.getState().app.accountInfo.names[0].name; + this.autoView =false + this.onlyMyImages = true + } + + static get styles() { + return css` + .top-bar-icon { + cursor: pointer; + height: 18px; + width: 18px; + transition: 0.2s all; + } + + .top-bar-icon:hover { + color: var(--black); + } + + .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; + } + + .close-row { + width: 100%; + display: flex; + justify-content: flex-end; + height: 50px; + flex: 0; + align-items: center; + } + + .container-body { + width: 100%; + display: flex; + flex-direction: column; + flex-grow: 1; + overflow: auto; + margin-top: 5px; + padding: 0px 6px; + box-sizing: border-box; + } + + .container-body::-webkit-scrollbar-track { + background-color: whitesmoke; + border-radius: 7px; + } + + .container-body::-webkit-scrollbar { + width: 6px; + border-radius: 7px; + background-color: whitesmoke; + } + + .container-body::-webkit-scrollbar-thumb { + background-color: rgb(180, 176, 176); + border-radius: 7px; + transition: all 0.3s ease-in-out; + } + + .container-body::-webkit-scrollbar-thumb:hover { + background-color: rgb(148, 146, 146); + cursor: pointer; + } + + p { + color: var(--black); + margin: 0px; + padding: 0px; + word-break: break-all; + } + + .container { + display: flex; + width: 100%; + flex-direction: column; + height: 100%; + } + + .chat-right-panel-label { + font-family: Montserrat, sans-serif; + color: var(--group-header); + padding: 5px; + font-size: 13px; + user-select: none; + } + + .group-info { + display: flex; + flex-direction: column; + justify-content: flex-start; + gap: 10px; + } + + .group-name { + font-family: Raleway, sans-serif; + font-size: 20px; + color: var(--chat-bubble-msg-color); + text-align: center; + user-select: none; + } + + .group-description { + font-family: Roboto, sans-serif; + color: var(--chat-bubble-msg-color); + letter-spacing: 0.3px; + font-weight: 300; + font-size: 14px; + margin-top: 15px; + word-break: break-word; + user-select: none; + } + + .group-subheader { + font-family: Montserrat, sans-serif; + font-size: 14px; + color: var(--chat-bubble-msg-color); + } + + .group-data { + font-family: Roboto, sans-serif; + letter-spacing: 0.3px; + font-weight: 300; + font-size: 14px; + color: var(--chat-bubble-msg-color); + } + .message-myBg { + background-color: var(--chat-bubble-myBg) !important; + margin-bottom: 15px; + border-radius: 5px; + padding: 5px; + } + .message-data-name { + user-select: none; + color: #03a9f4; + margin-bottom: 5px; + } + .message-user-info { + display: flex; + justify-content: space-between; + width: 100%; + gap: 10px; + } + + .hideImg { + visibility: hidden; + } + .checkbox-row { + position: relative; + display: flex; + align-items: center; + align-content: center; + font-family: Montserrat, sans-serif; + font-weight: 600; + color: var(--black); + } + `; + } + + async getMoreImages(reset) { + try { + console.log({reset}) + if(reset){ + this.images = [] + } + const groupPart = this.isReceipient + ? `direct_${this._chatId.slice(-15)}` + : `group_${this._chatId}`; + + let offset = reset ? 0 : this.images.length; + let endpoint = `/arbitrary/resources/search?service=QCHAT_IMAGE&identifier=qchat_${groupPart}&reverse=true&limit=20&reverse=true&offset=${offset}` + if(this.onlyMyImages){ + endpoint = endpoint + `&name=${this.myName}` + } + const qchatImages = await parentEpml.request('apiCall', { + type: 'api', + url: endpoint, + }); + + let list = [] + if(reset){ + list = qchatImages + } else { + list = [...this.images, ...qchatImages] + } + + this.images = list + } catch (error) { + console.log(error); + } + } + + firstUpdated() { + this.viewElement = this.shadowRoot.getElementById('viewElement'); + this.downObserverElement = + this.shadowRoot.getElementById('downObserver'); + this.elementObserver(); + } + + async updated(changedProperties) { + console.log({ changedProperties }); + if (changedProperties && changedProperties.has('_chatId')) { + this.images = []; + this.getMoreImages(true); + } + + if (changedProperties && changedProperties.has('onlyMyImages')) { + this.getMoreImages(true) + } + } + + elementObserver() { + const options = { + root: this.viewElement, + rootMargin: '0px', + threshold: 1, + }; + // identify an element to observe + const elementToObserve = this.downObserverElement; + // passing it a callback function + const observer = new IntersectionObserver( + this.observerHandler, + options + ); + // call `observe()` on that MutationObserver instance, + // passing it the element to observe, and the options object + observer.observe(elementToObserve); + } + + observerHandler(entries) { + if (!entries[0].isIntersecting) { + return; + } else { + console.log('hello', this.images) + if (this.images.length < 20) { + return; + } + this.getMoreImages(); + } + } + + selectAuto(e) { + if (e.target.checked) { + this.autoView = false + } else { + this.autoView = true + } + } + + selectMyImages(e) { + if (e.target.checked) { + this.onlyMyImages = false + } else { + this.onlyMyImages = true + } + } + + render() { + console.log('hello resources3', this.images); + return html` + +
+
+ { + this.getMoreImages(true) + }} style="color: var(--black); cursor:pointer;">refresh + + this.toggle( + false + )} style="margin: 0px 10px" icon="vaadin:close" slot="icon"> +
+
+ + this.selectAuto(e)} ?checked=${this.autoView}> +
+
+ + this.selectMyImages(e)} ?checked=${this.onlyMyImages}> +
+
+ + ${this.images.map((image) => { + return html``; + })} +
+
+
+
+ `; + } +} + +customElements.define('chat-right-panel-resources', ChatRightPanelResources); + +class ImageParent extends LitElement { + static get properties() { + return { + leaveGroupObj: { type: Object }, + error: { type: Boolean }, + chatHeads: { type: Array }, + groupAdmin: { attribute: false }, + groupMembers: { attribute: false }, + selectedHead: { type: Object }, + toggle: { attribute: false }, + getMoreMembers: { attribute: false }, + setOpenPrivateMessage: { attribute: false }, + userName: { type: String }, + walletBalance: { type: Number }, + sendMoneyLoading: { type: Boolean }, + btnDisable: { type: Boolean }, + errorMessage: { type: String }, + successMessage: { type: String }, + setOpenTipUser: { attribute: false }, + setOpenUserInfo: { attribute: false }, + setUserName: { attribute: false }, + chatId: { type: String }, + _chatId: { type: String }, + isReceipient: { type: Boolean }, + images: { type: Array }, + viewImage: { type: Boolean }, + image: { type: Object }, + autoView: {type: Boolean} + }; + } + + constructor() { + super(); + this.leaveGroupObj = {}; + this.leaveFee = 0.001; + this.error = false; + this.chatHeads = []; + this.groupAdmin = []; + this.groupMembers = []; + this.viewElement = ''; + + this.sendMoneyLoading = false; + this.btnDisable = false; + this.errorMessage = ''; + this.successMessage = ''; + + this.images = []; + this.viewImage = false; + this.myName = + window.parent.reduxStore.getState().app.accountInfo.names[0].name; + } + + static get styles() { + return css` + .top-bar-icon { + cursor: pointer; + height: 18px; + width: 18px; + transition: 0.2s all; + } + + .top-bar-icon:hover { + color: var(--black); + } + + .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; + } + + .close-row { + width: 100%; + display: flex; + justify-content: flex-end; + height: 50px; + flex: 0; + gap: 20px; + align-items: center; + } + + .container-body { + width: 100%; + display: flex; + flex-direction: column; + flex-grow: 1; + overflow: auto; + margin-top: 5px; + padding: 0px 6px; + box-sizing: border-box; + } + + .container-body::-webkit-scrollbar-track { + background-color: whitesmoke; + border-radius: 7px; + } + + .container-body::-webkit-scrollbar { + width: 6px; + border-radius: 7px; + background-color: whitesmoke; + } + + .container-body::-webkit-scrollbar-thumb { + background-color: rgb(180, 176, 176); + border-radius: 7px; + transition: all 0.3s ease-in-out; + } + + .container-body::-webkit-scrollbar-thumb:hover { + background-color: rgb(148, 146, 146); + cursor: pointer; + } + + p { + color: var(--black); + margin: 0px; + padding: 0px; + word-break: break-all; + } + + .container { + display: flex; + width: 100%; + flex-direction: column; + height: 100%; + } + + .chat-right-panel-label { + font-family: Montserrat, sans-serif; + color: var(--group-header); + padding: 5px; + font-size: 13px; + user-select: none; + } + + .group-info { + display: flex; + flex-direction: column; + justify-content: flex-start; + gap: 10px; + } + + .group-name { + font-family: Raleway, sans-serif; + font-size: 20px; + color: var(--chat-bubble-msg-color); + text-align: center; + user-select: none; + } + + .group-description { + font-family: Roboto, sans-serif; + color: var(--chat-bubble-msg-color); + letter-spacing: 0.3px; + font-weight: 300; + font-size: 14px; + margin-top: 15px; + word-break: break-word; + user-select: none; + } + + .group-subheader { + font-family: Montserrat, sans-serif; + font-size: 14px; + color: var(--chat-bubble-msg-color); + } + + .group-data { + font-family: Roboto, sans-serif; + letter-spacing: 0.3px; + font-weight: 300; + font-size: 14px; + color: var(--chat-bubble-msg-color); + } + .message-myBg { + background-color: var(--chat-bubble-myBg) !important; + margin-bottom: 15px; + border-radius: 5px; + padding: 5px; + } + .message-data-name { + user-select: none; + color: #03a9f4; + margin-bottom: 5px; + } + .message-user-info { + display: flex; + justify-content: space-between; + width: 100%; + gap: 10px; + } + + .hideImg { + visibility: hidden; + } + .image-container { + display: flex; + } + `; + } + + firstUpdated() {} + + async updated(changedProperties) { + if (changedProperties && changedProperties.has('chatId')) { + // const autoSeeChatList = + // window.parent.reduxStore.getState().app.autoLoadImageChats; + // if (autoSeeChatList.includes(this.chatId)) { + // this.viewImage = true; + // } + } + } + + render() { + return html` + ${!this.autoView && !this.viewImage && this.myName !== this.image.name + ? html` +
+ +
{ + this.viewImage = true; + }} + class=${[`image-container`].join(' ')} + style="height: 200px" + > +
+ ${translate('chatpage.cchange40')} +
+
+
+ ` + : html``} + ${this.autoView || this.viewImage || this.myName === this.image.name + ? html` +
+ + + < +
+ ` + : ''} + `; + } +} + +customElements.define('image-parent', ImageParent); diff --git a/plugins/plugins/core/components/ChatScroller.js b/plugins/plugins/core/components/ChatScroller.js index 73f8e7e5..c19c3b41 100644 --- a/plugins/plugins/core/components/ChatScroller.js +++ b/plugins/plugins/core/components/ChatScroller.js @@ -185,44 +185,7 @@ function processText(input) { return wrapper; } -const formatMessages = (messages) => { - const formattedMessages = messages.reduce((messageArray, message) => { - const currentMessage = message; - const lastGroupedMessage = messageArray[messageArray.length - 1]; - currentMessage.firstMessageInChat = messageArray.length === 0; - - let timestamp, sender, repliedToData; - - if (lastGroupedMessage) { - timestamp = lastGroupedMessage.timestamp; - sender = lastGroupedMessage.sender; - repliedToData = lastGroupedMessage.repliedToData; - } else { - timestamp = currentMessage.timestamp; - sender = currentMessage.sender; - repliedToData = currentMessage.repliedToData; - } - - const isSameGroup = - Math.abs(timestamp - currentMessage.timestamp) < 600000 && - sender === currentMessage.sender && - !repliedToData; - - if (isSameGroup && lastGroupedMessage) { - lastGroupedMessage.messages.push(currentMessage); - } else { - messageArray.push({ - messages: [currentMessage], - ...currentMessage, - }); - } - - return messageArray; - }, []); - - return formattedMessages; -}; class ChatScroller extends LitElement { static get properties() { @@ -510,8 +473,7 @@ class ChatScroller extends LitElement { !previousMessage || !this.shouldGroupWithLastMessage(message, previousMessage) ) { - // If no previous message, or if the current message shouldn't be grouped with the previous, - // push the current group to the front of the formatted messages (since these are older messages) + if (currentMessageGroup) { this.messagesToRender.unshift(currentMessageGroup); } @@ -2207,7 +2169,7 @@ class MessageTemplate extends LitElement { toblockaddress=${this.messageObj.sender} > - { @@ -2225,7 +2187,6 @@ class MessageTemplate extends LitElement { dialogAction="cancel" class="red" @click=${() => { - MessageTemplate; this.openDialogImage = false; }} > diff --git a/plugins/plugins/core/components/ReusableImage.js b/plugins/plugins/core/components/ReusableImage.js new file mode 100644 index 00000000..9b5feb9c --- /dev/null +++ b/plugins/plugins/core/components/ReusableImage.js @@ -0,0 +1,337 @@ +import { LitElement, html, css } from 'lit'; +import { render } from 'lit/html.js'; +import { + use, + get, + translate, + translateUnsafeHTML, + registerTranslateConfig, +} from 'lit-translate'; +import axios from 'axios'; +import { RequestQueueWithPromise } from '../../utils/queue'; +import '@material/mwc-menu'; +import '@material/mwc-list/mwc-list-item.js'; +import { Epml } from '../../../epml'; +import '@material/mwc-dialog' + +const requestQueue = new RequestQueueWithPromise(5); +const requestQueue2 = new RequestQueueWithPromise(5); + +const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }); + +export class ResuableImage extends LitElement { + static get properties() { + return { + resource: { type: Object }, + isReady: { type: Boolean }, + status: { type: Object }, + missingData: {type: Boolean}, + openDialogImage: { type: Boolean }, + + }; + } + + static get styles() { + return css` + * { + --mdc-theme-text-primary-on-background: var(--black); + --mdc-dialog-max-width: 85vw; + --mdc-dialog-max-height: 95vh; + } + img { + width: 100%; + height: auto; + object-fit: contain; + border-radius: 5px; + position: relative; + } + .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: 30px; + position: relative; + text-indent: -9999em; + transform: translateZ(0px); + animation: 1.1s linear 0s infinite normal none running + loadingAnimation; + } + .imageContainer { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + } + + @-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); + } + } + `; + } + + constructor() { + super(); + this.resource = { + identifier: '', + name: '', + service: '', + }; + this.status = { + status: '', + }; + this.url = ''; + this.isReady = false; + this.nodeUrl = this.getNodeUrl(); + this.myNode = this.getMyNode(); + this.hasCalledWhenDownloaded = false; + this.isFetching = false; + this.missingData = false + this.openDialogImage = false + + this.observer = new IntersectionObserver((entries) => { + for (const entry of entries) { + if (entry.isIntersecting && this.status.status !== 'READY') { + this._fetchImage(); + // Stop observing after the image has started loading + this.observer.unobserve(this); + } + } + }); + } + getNodeUrl() { + const myNode = + window.parent.reduxStore.getState().app.nodeConfig.knownNodes[ + window.parent.reduxStore.getState().app.nodeConfig.node + ]; + + const nodeUrl = + myNode.protocol + '://' + myNode.domain + ':' + myNode.port; + return nodeUrl; + } + getMyNode() { + const myNode = + window.parent.reduxStore.getState().app.nodeConfig.knownNodes[ + window.parent.reduxStore.getState().app.nodeConfig.node + ]; + + return myNode; + } + + getApiKey() { + const myNode = + window.parent.reduxStore.getState().app.nodeConfig.knownNodes[ + window.parent.reduxStore.getState().app.nodeConfig.node + ]; + let apiKey = myNode.apiKey; + return apiKey; + } + + async fetchResource() { + try { + if (this.isFetching) return; + this.isFetching = true; + + await requestQueue2.enqueue(() => { + return axios.get( + `${this.nodeUrl}/arbitrary/resource/properties/${this.resource.service}/${this.resource.name}/${this.resource.identifier}?apiKey=${this.myNode.apiKey}` + ); + }); + this.isFetching = false; + } catch (error) { + this.isFetching = false; + } + } + + async fetchVideoUrl() { + this.fetchResource(); + this.url = `${this.nodeUrl}/arbitrary/${this.resource.service}/${this.resource.name}/${this.resource.identifier}?async=true&apiKey=${this.myNode.apiKey}`; + } + + async fetchStatus() { + let isCalling = false; + let percentLoaded = 0; + let timer = 24; + const response = await axios.get( + `${this.nodeUrl}/arbitrary/resource/status/${this.resource.service}/${this.resource.name}/${this.resource.identifier}?apiKey=${this.myNode.apiKey}` + ); + if (response && response.data && response.data.status === 'READY') { + this.status = response.data; + return; + } + const intervalId = setInterval(async () => { + if (isCalling) return; + isCalling = true; + + const data = await requestQueue.enqueue(() => { + return axios.get( + `${this.nodeUrl}/arbitrary/resource/status/${this.resource.service}/${this.resource.name}/${this.resource.identifier}?apiKey=${this.myNode.apiKey}` + ); + }); + const res = data.data; + + isCalling = false; + if (res.localChunkCount) { + if (res.percentLoaded) { + if ( + res.percentLoaded === percentLoaded && + res.percentLoaded !== 100 + ) { + timer = timer - 5; + } else { + timer = 24; + } + if (timer < 0) { + timer = 24; + isCalling = true; + this.status = { + ...res, + status: 'REFETCHING', + }; + + setTimeout(() => { + isCalling = false; + this.fetchResource(); + }, 25000); + return; + } + percentLoaded = res.percentLoaded; + } + + this.status = res; + if (this.status.status === 'DOWNLOADED') { + this.fetchResource(); + } + } + + // check if progress is 100% and clear interval if true + if (res?.status === 'READY') { + clearInterval(intervalId); + this.status = res; + this.isReady = true; + } + + if(res?.status === 'MISSING_DATA'){ + this.status = res + this.missingData = true + clearInterval(intervalId) + } + }, 5000); // 1 second interval + } + + async _fetchImage() { + try { + this.fetchVideoUrl({ + name: this.resource.name, + service: this.resource.service, + identifier: this.resource.identifier, + }); + this.fetchStatus(); + } catch (error) {} + } + + firstUpdated() { + this.observer.observe(this); + } + + showContextMenu(e) { + e.preventDefault(); + e.stopPropagation(); + + const contextMenu = this.shadowRoot.getElementById('contextMenu'); + const containerRect = e.currentTarget.getBoundingClientRect(); + + // Adjusting the positions + const adjustedX = e.clientX - containerRect.left; + const adjustedY = e.clientY - containerRect.top; + + contextMenu.style.top = `${adjustedY}px`; + contextMenu.style.left = `${adjustedX}px`; + + contextMenu.open = true; + } + + render() { + return html` +
+ ${this.status.status !== 'READY' + ? html` +
+
+

+ ${`${Math.round( + this.status.percentLoaded || 0 + ).toFixed(0)}% `}${translate( + 'chatpage.cchange94' + )} +

+
+ ` + : ''} + ${this.status.status === 'READY' + ? html` +
{ + this.openDialogImage = true; + }}> + +
+ ` + : ''} +
+ + { + this.openDialogImage = false; + }}> +
+
+ ${this.openDialogImage ? html` + + ` : ''} + +
+ { + this.openDialogImage = false; + }} + > + ${translate('general.close')} + +
+ `; + } +} + +customElements.define('reusable-image', ResuableImage);