Skip to content

Commit

Permalink
WIP: Improve preview rendering logic
Browse files Browse the repository at this point in the history
Signed-off-by: Louis Chemineau <louis@chmn.me>
  • Loading branch information
artonge committed Feb 28, 2023
1 parent 5d1d87d commit 87316de
Showing 1 changed file with 69 additions and 56 deletions.
125 changes: 69 additions & 56 deletions src/components/File.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,32 @@
<div class="file__images">
<VideoIcon v-if="file.mime.includes('video')" class="video-icon" :size="64" />

<img v-if="visibility !== 'none' && canLoad && !errorNear && !loadedVisible"
ref="imgNear"
:key="`${file.basename}-near`"
:src="srcNear"
:alt="file.basename"
:aria-describedby="ariaDescription"
@load="onLoadNear"
@error="onErrorNear">

<img v-if="(visibility === 'visible' || (loadedVisible && visibility === 'near')) && canLoad && !errorVisible"
ref="imgVisible"
:key="`${file.basename}-visible`"
:src="srcVisible"
:alt="file.basename"
:aria-describedby="ariaDescription"
@load="onLoadVisible"
@error="onErrorVisible">
<template v-if="distance < 1 && canLoad">
<!-- Alway load the small preview, unless the large on is already loaded -->
<img v-if="!loadedLarge && !errorSmall"
ref="imgSmall"
:key="`${file.basename}-small`"
:src="srcSmall"
:alt="file.basename"
:aria-describedby="ariaDescription"
@load="onLoadSmall"
@error="onErrorSmall">

<!-- Load the large preview if the small on is loaded and if the image is visible by the user. -->
<img v-if="loadedLarge || ((loadedSmall || errorSmall) && distance === 0) && !errorLarge"
ref="imgLarge"
:key="`${file.basename}-large`"
:src="srcLarge"
:alt="file.basename"
:aria-describedby="ariaDescription"
@load="onLoadLarge"
@loadstart="onLoadStartLarge"
@error="onErrorLarge">
</template>
</div>

<!-- image description -->
<p :id="ariaDescription" class="file__hidden-description" :class="{show: errorNear && errorVisible}">{{ file.basename }}</p>
<p :id="ariaDescription" class="file__hidden-description" :class="{show: errorSmall && errorLarge}">{{ file.basename }}</p>
</a>

<NcCheckboxRadioSwitch v-if="allowSelection"
Expand Down Expand Up @@ -99,8 +104,8 @@ export default {
type: Boolean,
default: true,
},
visibility: {
type: String,
distance: {
type: Number,
required: true,
},
semaphore: {
Expand All @@ -111,10 +116,11 @@ export default {
data() {
return {
loadedNear: false,
loadedVisible: false,
errorNear: false,
errorVisible: false,
loadedSmall: false,
loadedLarge: false,
loadingLarge: false,
errorSmall: false,
errorLarge: false,
canLoad: false,
semaphoreSymbol: null,
isDestroyed: false,
Expand All @@ -139,45 +145,46 @@ export default {
return this.file.etag.replace('&quot;', '').replace('&quot;', '')
},
/** @return {string} */
srcVisible() {
srcLarge() {
return this.getItemURL(512)
},
/** @return {string} */
srcNear() {
srcSmall() {
return this.getItemURL(64)
},
},
async mounted() {
this.semaphoreSymbol = await this.semaphore.acquire(() => {
switch (this.visibility) {
case 'visible':
return 1
case 'near':
return 2
default:
return 3
// Wait some time before starting the image loading logic.
// This prevent loading a lot of images when the user is simply scrolling.
setTimeout(async () => {
this.semaphoreSymbol = await this.semaphore.acquire(() => this.distance, this.file.fileid)
if (this.isDestroyed) {
this.releaseSemaphore()
return
}
}, this.file.fileid)
if (this.visibility === 'none' || this.isDestroyed) {
this.releaseSemaphore()
return
}
if (this.distance === 0) {
this.canLoad = true
} else {
// Delay even more non visible images
setTimeout(async () => (this.canLoad = true), 2000)
}
this.canLoad = true
}, 1000)
},
beforeDestroy() {
this.isDestroyed = true
this.releaseSemaphore()
// cancel any pending load
if (this.$refs.imgNear !== undefined) {
this.$refs.imgNear.src = ''
if (this.$refs.imgSmall !== undefined) {
this.$refs.imgSmall.src = ''
}
if (this.$refs.srcVisible !== undefined) {
this.$refs.srcVisible.src = ''
if (this.$refs.srcLarge !== undefined) {
this.$refs.srcLarge.src = ''
}
},
Expand All @@ -186,25 +193,31 @@ export default {
this.$emit('click', this.file.fileid)
},
/** When the 'near' image is fully loaded by browser we release semaphore */
onLoadNear() {
this.loadedNear = true
this.releaseSemaphore()
onLoadSmall() {
this.loadedSmall = true
if (!this.loadingLarge) {
this.releaseSemaphore()
}
},
/** When the 'visible' image is fully loaded by browser we release semaphore */
onLoadVisible() {
this.loadedVisible = true
this.releaseSemaphore()
onLoadStartLarge() {
this.loadingLarge = true
},
onErrorNear() {
this.errorNear = true
onLoadLarge() {
this.loadedLarge = true
this.releaseSemaphore()
},
onErrorVisible() {
this.errorVisible = true
onErrorSmall() {
this.errorSmall = true
if (!this.loadingLarge) {
this.releaseSemaphore()
}
},
onErrorLarge() {
this.errorLarge = true
this.releaseSemaphore()
},
Expand Down

0 comments on commit 87316de

Please sign in to comment.