Skip to content

Commit

Permalink
feat!: improve post's media retry logic
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Might break iOS devices, have to test
  • Loading branch information
AlejandroAkbal committed Aug 26, 2020
1 parent 45137f7 commit ceaa55c
Showing 1 changed file with 152 additions and 75 deletions.
227 changes: 152 additions & 75 deletions components/pages/posts/content/PostMedia.vue
Original file line number Diff line number Diff line change
@@ -1,39 +1,43 @@
<template>
<div>
<!-- if media is an Image -->
<img
v-if="post.media_type === 'image'"
:src="mediaResolutionChooser().url"
:loading="settings.lazyLoading.value ? 'lazy' : 'auto'"
:class="{
'post-animation opacity-0': settings.animations.value,
'opacity-100': settings.animations.value && mediaLoaded,
}"
:alt="'Image ' + post.id"
class="w-full h-auto"
:height="mediaResolutionChooser().height"
:width="mediaResolutionChooser().width"
@load="mediaLoaded = true"
referrerpolicy="no-referrer"
@error="retryToLoadMedia($event)"
/>

<!-- if its a Video -->
<video
v-else-if="post.media_type === 'video'"
:controls="settings.videoControls.value"
:alt="'Video ' + post.id"
class="w-full h-auto"
preload="none"
:poster="post.preview_file.url"
loop
playsinline
>
<source :src="post.high_res_file.url" @error="retryToLoadMedia($event)" />
Your browser doesnt support HTML5 video.
</video>

<p v-else class="text-center text-default-text">Unknown media type</p>
<template v-else-if="isImage">
<!-- if media is an Image -->
<img
:src="mediaResolutionChooser.url"
:loading="settings.lazyLoading.value ? 'lazy' : 'auto'"
:class="{
'post-animation opacity-0': settings.animations.value,
'opacity-100': hasMediaLoaded && settings.animations.value,
}"
:alt="'Image ' + post.id"
class="w-full h-auto"
:height="mediaResolutionChooser.height"
:width="mediaResolutionChooser.width"
referrerpolicy="no-referrer"
@load="hasMediaLoaded = true"
@error="retryToLoadManager($event)"
/>
</template>

<template v-else-if="isVideo">
<!-- if its a Video -->
<video
:controls="settings.videoControls.value"
:alt="'Video ' + post.id"
class="w-full h-auto"
preload="none"
:poster="post.preview_file.url"
loop
playsinline
>
<source
:src="mediaResolutionChooser.url"
@error="retryToLoadManager($event)"
/>
Your browser doesnt support HTML5 video.
</video>
</template>

</div>
</template>

Expand All @@ -54,81 +58,154 @@ export default {
data() {
return {
mediaLoaded: false,
retryCount: 0,
hasMediaLoaded: false,
retryLogic: {
count: 0,
tried: {
proxy: false,
extraSlash: false,
proxyWithExtraSlash: false,
},
},
}
},
computed: {
...mapState(['general']),
...mapState('user', ['settings']),
isImage() {
return this.post.media_type === 'image'
},
isVideo() {
return this.post.media_type === 'video'
},
mediaResolutionChooser() {
// Always return high res file if its a video
if (this.isVideo) return this.post.high_res_file
// Return full image if its setting is enabled OR if low resolution file doesnt exist
if (this.settings.fullSizeImages.value || !this.post.low_res_file.url) {
return this.post.high_res_file
}
// Return low res file
else {
return this.post.low_res_file
}
},
},
methods: {
retryToLoadMedia(event) {
// console.log(event.target, this.retryCount)
retryToLoadManager(event) {
// console.log('Media source: ', event.target.src)
const isVideo = event.target.parentElement.nodeName === 'VIDEO'
if (this.showError) {
console.debug('Error set, dont try to load image anymore')
return
}
// If browser is offline return
if (this.$nuxt.isOffline) return
if (this.$nuxt.isOffline) {
console.debug('Browser offline, dont try to load image anymore')
this.showError = true
return
}
// Proxy images if they fail to load
if (this.retryCount === 0) {
console.debug('Proxifying media')
// Proxy URL
if (!this.retryLogic.tried.proxy) {
console.debug('Proxying media')
event.target.src = this.general.CORSProxyURL + '?q=' + event.target.src
event.target.src = this.addProxyToURL(this.mediaResolutionChooser.url)
if (isVideo) {
if (this.isVideo) {
console.debug('Reloading data and playing video')
event.target.parentElement.load()
event.target.parentElement.play()
this.reloadVideoElement(event.target.parentElement)
}
this.retryCount++
this.retryLogic.tried.proxy = true
}
// If we have not reached the limit
else if (this.retryCount < this.settings.imgRetry.value) {
const originalImgSrc = event.target.src
// Add extra slash to URL
else if (!this.retryLogic.tried.extraSlash) {
console.debug('Adding extra slash')
event.target.src = ''
event.target.src = originalImgSrc
event.target.src = this.addExtraSlashToURL(
this.mediaResolutionChooser.url
)
// console.log(this.retryCount, originalImgSrc)
if (this.isVideo) {
console.debug('Reloading data and playing video')
this.reloadVideoElement(event.target.parentElement)
}
this.retryCount++
this.retryLogic.tried.extraSlash = true
}
// Load error image
else {
// console.log('Cant load the image')
// Proxy URL with extra slash
else if (!this.retryLogic.tried.proxyWithExtraSlash) {
console.debug('Proxying media with extra slash')
// Set error image
if (isVideo) {
event.target.parentElement.poster = require('~/assets/img/utils/error.png')
} else {
event.target.src = require('~/assets/img/utils/error.png')
event.target.src = this.addProxyToURL(
this.addExtraSlashToURL(this.mediaResolutionChooser.url)
)
if (this.isVideo) {
console.debug('Reloading data and playing video')
this.reloadVideoElement(event.target.parentElement)
}
// Stop retrying // This doesnt do anything
event.target.onerror = null
this.retryLogic.tried.proxyWithExtraSlash = true
}
},
mediaResolutionChooser() {
// Return full image if its setting is enabled OR if low resolution file doesnt exist
if (this.settings.fullSizeImages.value || !this.post.low_res_file.url) {
return this.post.high_res_file
// Retry to load it
else if (this.retryLogic.count < this.settings.imgRetry.value) {
console.debug(`Retry ${this.retryLogic.count} to load the media`)
event.target.src = ''
event.target.src = this.mediaResolutionChooser.url
if (this.isVideo) {
console.debug('Reloading data and playing video')
this.reloadVideoElement(event.target.parentElement)
}
this.retryLogic.count++
}
// Return low res file
// At last, show error
else {
return this.post.low_res_file
console.debug("Can't load media")
this.showError = true
}
},
reloadVideoElement(videoElement) {
videoElement.load()
videoElement.play()
},
addProxyToURL(url) {
return this.general.CORSProxyURL + '?q=' + url
},
addExtraSlashToURL(url) {
const currentURL = new URL(url)
/* console.log({
original: currentURL.toString(),
modified: currentURLWithExtraSlash,
}) */
return currentURL
.toString()
.replace(currentURL.hostname, currentURL.hostname + '/')
},
},
}
</script>
Expand Down

0 comments on commit ceaa55c

Please sign in to comment.