forked from Qortal/qortal-ui
Merge pull request #319 from AlphaX-Projects/master
Fix gif not display before 100% loaded
This commit is contained in:
commit
c828df6775
230
plugins/plugins/core/components/ChatImageGif.js
Normal file
230
plugins/plugins/core/components/ChatImageGif.js
Normal file
@ -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)
|
@ -18,6 +18,7 @@ import './NameMenu'
|
|||||||
import './UserInfo'
|
import './UserInfo'
|
||||||
import './WrapperModal'
|
import './WrapperModal'
|
||||||
import './ChatImage'
|
import './ChatImage'
|
||||||
|
import './ChatImageGif'
|
||||||
import '@material/mwc-button'
|
import '@material/mwc-button'
|
||||||
import '@material/mwc-dialog'
|
import '@material/mwc-dialog'
|
||||||
import '@material/mwc-icon'
|
import '@material/mwc-icon'
|
||||||
@ -1118,15 +1119,6 @@ class MessageTemplate extends LitElement {
|
|||||||
|
|
||||||
levelFounder = html`<level-founder checkleveladdress="${this.messageObj.sender}"></level-founder>`
|
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 createGif = (gif) => {
|
||||||
const gifHTMLRes = new Image()
|
const gifHTMLRes = new Image()
|
||||||
gifHTMLRes.src = gif
|
gifHTMLRes.src = gif
|
||||||
@ -1149,6 +1141,15 @@ class MessageTemplate extends LitElement {
|
|||||||
return gifHTMLRes
|
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) {
|
if (image) {
|
||||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
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 nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||||
@ -1157,7 +1158,7 @@ class MessageTemplate extends LitElement {
|
|||||||
imageHTML = html`
|
imageHTML = html`
|
||||||
<chat-image
|
<chat-image
|
||||||
.resource=${{name: image.name, service: image.service, identifier: image.identifier}}
|
.resource=${{name: image.name, service: image.service, identifier: image.identifier}}
|
||||||
.setOpenDialogImage=${(val)=> this.setOpenDialogImage(val)}
|
.setOpenDialogImage=${(val) => this.setOpenDialogImage(val)}
|
||||||
>
|
>
|
||||||
</chat-image>
|
</chat-image>
|
||||||
`
|
`
|
||||||
@ -1169,7 +1170,13 @@ class MessageTemplate extends LitElement {
|
|||||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||||
gifUrl = `${nodeUrl}/arbitrary/${gif.service}/${gif.name}/${gif.identifier}?async=true`
|
gifUrl = `${nodeUrl}/arbitrary/${gif.service}/${gif.name}/${gif.identifier}?async=true`
|
||||||
if (this.viewImage || this.myAddress === this.messageObj.sender) {
|
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 = createGif(gifUrl)
|
||||||
gifHTMLDialog.style = 'height: auto; max-height: 80vh; width: auto; max-width: 80vw; object-fit: contain; border-radius: 5px;'
|
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;}}>
|
<mwc-dialog id="showDialogPublicKey" ?open=${this.openDialogImage} @closed=${() => {this.openDialogImage = false;}}>
|
||||||
<div class="dialog-header"></div>
|
<div class="dialog-header"></div>
|
||||||
<div class="dialog-container imageContainer">
|
<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>
|
</div>
|
||||||
<mwc-button slot="primaryAction" dialogAction="cancel" class="red" @click=${() => {this.openDialogImage = false;}}>
|
<mwc-button slot="primaryAction" dialogAction="cancel" class="red" @click=${() => {this.openDialogImage = false;}}>
|
||||||
${translate('general.close')}
|
${translate('general.close')}
|
||||||
@ -1875,6 +1882,10 @@ class MessageTemplate extends LitElement {
|
|||||||
this.openDialogImage = val
|
this.openDialogImage = val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setOpenDialogGif(val) {
|
||||||
|
this.openDialogGif = val
|
||||||
|
}
|
||||||
|
|
||||||
shouldUpdate(changedProperties) {
|
shouldUpdate(changedProperties) {
|
||||||
if (changedProperties.has('messageObj')) {
|
if (changedProperties.has('messageObj')) {
|
||||||
return true
|
return true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user