Browse Source

Fix gif not display before 100% loaded

master
AlphaX-Projects 3 months ago
parent
commit
054195c2bf
  1. 230
      plugins/plugins/core/components/ChatImageGif.js
  2. 35
      plugins/plugins/core/components/ChatScroller.js

230
plugins/plugins/core/components/ChatImageGif.js

@ -0,0 +1,230 @@
import { html, LitElement } from 'lit'
import { Epml } from '../../../epml'
import { RequestQueueWithPromise } from '../../utils/classes'
import { chatImageStyles } from './plugins-css'
import axios from 'axios'
// Multi language support
import { get, translate } from '../../../../core/translate'
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
const requestQueue = new RequestQueueWithPromise(5)
export class ChatImageGif extends LitElement {
static get properties() {
return {
resource: { type: Object },
isReady: { type: Boolean },
status: { type: Object },
setOpenDialogGif: { attribute: false }
}
}
static get styles() {
return [chatImageStyles]
}
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.observer = new IntersectionObserver(entries => {
for (const entry of entries) {
if (entry.isIntersecting && this.status.status !== 'READY') {
this.fetchGif()
this.observer.unobserve(this)
}
}
})
}
render() {
return html`
<div class=${[`image-container`, this.status.status !== 'READY' ? 'defaultSize' : '', this.status.status !== 'READY' ? 'hideImg' : '',].join(' ')}>
${this.status.status !== 'READY' ?
html`
<div style="display: flex; flex-direction: column; width:100%; height: 100%; justify-content: center; align-items: center; position: absolute;">
<div class=${`smallLoading`}></div>
<p style="color: var(--black)">${`${Math.round(this.status.percentLoaded || 0).toFixed(0)}% `}${translate('chatpage.cchange94')}</p>
</div>
`
: ''
}
${this.status.status === 'READY' ?
html`
${this.createGif(this.url)}
`
: ''
}
</div>
`
}
firstUpdated() {
this.observer.observe(this)
}
createGif(gif) {
const gifHTMLRes = new Image()
gifHTMLRes.src = gif
gifHTMLRes.style = 'max-width:45vh; max-height:40vh; border-radius: 5px; cursor: pointer;'
gifHTMLRes.onclick = () => {this.setOpenDialogGif(true);}
gifHTMLRes.onload = () => {this.isGifLoaded = true;}
gifHTMLRes.onerror = () => {
if (this.gifFetches < 4) {
setTimeout(() => {
this.gifFetches = this.gifFetches + 1
gifHTMLRes.src = gif
}, 10000)
} else {
gifHTMLRes.src = '/img/chain.png'
gifHTMLRes.style = 'max-width:45vh; max-height:20vh; border-radius: 5px; filter: opacity(0.5);'
gifHTMLRes.onclick = () => {}
this.isGifLoaded = true
}
}
return gifHTMLRes
}
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
}
async fetchResource() {
try {
if (this.isFetching) return
this.isFetching = true
await axios.get(`${this.nodeUrl}/arbitrary/resource/properties/${this.resource.service}/${this.resource.name}/${this.resource.identifier}`)
this.isFetching = false
} catch (error) {
this.isFetching = false
}
}
async fetchGifUrl() {
this.fetchResource()
this.url = `${this.nodeUrl}/arbitrary/${this.resource.service}/${this.resource.name}/${this.resource.identifier}?async=true`
}
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}`)
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}`)
})
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
}
}, 5000) // 5 second interval
}
async fetchGif() {
try {
this.fetchGifUrl({name: this.resource.name, service: this.resource.service, identifier: this.resource.identifier})
this.fetchStatus()
} catch (error) { /* empty */ }
}
shouldUpdate(changedProperties) {
if (changedProperties.has('setOpenDialogGif') && changedProperties.size === 1) {
return false
}
return true
}
// Standard functions
getApiKey() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
return myNode.apiKey
}
isEmptyArray(arr) {
if (!arr) { return true }
return arr.length === 0
}
round(number) {
return (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8)
}
}
window.customElements.define('chat-image-gif', ChatImageGif)

35
plugins/plugins/core/components/ChatScroller.js

@ -18,6 +18,7 @@ import './NameMenu'
import './UserInfo'
import './WrapperModal'
import './ChatImage'
import './ChatImageGif'
import '@material/mwc-button'
import '@material/mwc-dialog'
import '@material/mwc-icon'
@ -1118,15 +1119,6 @@ class MessageTemplate extends LitElement {
levelFounder = html`<level-founder checkleveladdress="${this.messageObj.sender}"></level-founder>`
if (this.messageObj.senderName) {
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 avatarUrl = `${nodeUrl}/arbitrary/THUMBNAIL/${this.messageObj.senderName}/qortal_avatar?async=true`
avatarImg = html`<img src="${avatarUrl}" style="max-width:100%; max-height:100%;" onerror="this.onerror=null; this.src='/img/incognito.png';" />`
} else {
avatarImg = html`<img src="/img/incognito.png" style="max-width:100%; max-height:100%;" onerror="this.onerror=null;" />`
}
const createGif = (gif) => {
const gifHTMLRes = new Image()
gifHTMLRes.src = gif
@ -1149,6 +1141,15 @@ class MessageTemplate extends LitElement {
return gifHTMLRes
}
if (this.messageObj.senderName) {
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 avatarUrl = `${nodeUrl}/arbitrary/THUMBNAIL/${this.messageObj.senderName}/qortal_avatar?async=true`
avatarImg = html`<img src="${avatarUrl}" style="max-width:100%; max-height:100%;" onerror="this.onerror=null; this.src='/img/incognito.png';" />`
} else {
avatarImg = html`<img src="/img/incognito.png" style="max-width:100%; max-height:100%;" onerror="this.onerror=null;" />`
}
if (image) {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
@ -1157,7 +1158,7 @@ class MessageTemplate extends LitElement {
imageHTML = html`
<chat-image
.resource=${{name: image.name, service: image.service, identifier: image.identifier}}
.setOpenDialogImage=${(val)=> this.setOpenDialogImage(val)}
.setOpenDialogImage=${(val) => this.setOpenDialogImage(val)}
>
</chat-image>
`
@ -1169,7 +1170,13 @@ class MessageTemplate extends LitElement {
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
gifUrl = `${nodeUrl}/arbitrary/${gif.service}/${gif.name}/${gif.identifier}?async=true`
if (this.viewImage || this.myAddress === this.messageObj.sender) {
gifHTML = createGif(gifUrl)
gifHTML = html`
<chat-image-gif
.resource=${{name: gif.name, service: gif.service, identifier: gif.identifier}}
.setOpenDialogGif=${(val) => this.setOpenDialogGif(val)}
>
</chat-image-gif>
`
gifHTMLDialog = createGif(gifUrl)
gifHTMLDialog.style = 'height: auto; max-height: 80vh; width: auto; max-width: 80vw; object-fit: contain; border-radius: 5px;'
}
@ -1612,7 +1619,7 @@ class MessageTemplate extends LitElement {
<mwc-dialog id="showDialogPublicKey" ?open=${this.openDialogImage} @closed=${() => {this.openDialogImage = false;}}>
<div class="dialog-header"></div>
<div class="dialog-container imageContainer">
${this.openDialogImage ? html`<img src=${imageUrl} style="height: auto; max-height: 80vh; width: auto; max-width: 80vw; object-fit: contain; border-radius: 5px;"/>` : ''}
${this.openDialogImage ? html`<img src=${imageUrl} style="height: auto; max-height: 80vh; width: auto; max-width: 80vw; object-fit: contain; border-radius: 5px;">` : ''}
</div>
<mwc-button slot="primaryAction" dialogAction="cancel" class="red" @click=${() => {this.openDialogImage = false;}}>
${translate('general.close')}
@ -1875,6 +1882,10 @@ class MessageTemplate extends LitElement {
this.openDialogImage = val
}
setOpenDialogGif(val) {
this.openDialogGif = val
}
shouldUpdate(changedProperties) {
if (changedProperties.has('messageObj')) {
return true

Loading…
Cancel
Save