feat(webreader): detect browser support for JPEG XL

This commit is contained in:
Gauthier Roebroeck 2021-12-22 21:24:22 +08:00
parent 610c51fd5d
commit 27f5ba6348
3 changed files with 49 additions and 28 deletions

View File

@ -0,0 +1,38 @@
export enum ImageFeature {
WEBP_LOSSY,
WEBP_LOSSLESS,
WEBP_ALPHA,
WEBP_ANIMATION,
JPEG_XL,
AVIF,
}
export function checkImageSupport(feature: ImageFeature, callback: (isSupported: boolean) => void) {
const img = new Image()
img.onload = function () {
callback((img.width > 0) && (img.height > 0))
}
img.onerror = function () {
callback(false)
}
switch (feature) {
case ImageFeature.WEBP_LOSSY:
img.src = 'data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA'
break
case ImageFeature.WEBP_LOSSLESS:
img.src = 'data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA=='
break
case ImageFeature.WEBP_ALPHA:
img.src = 'data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA=='
break
case ImageFeature.WEBP_ANIMATION:
img.src = 'data:image/webp;base64,UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA'
break
case ImageFeature.JPEG_XL:
img.src = 'data:image/jxl;base64,/woIELASCAgQAFwASxLFgkWAHL0xqnCBCV0qDp901Te/5QM='
break
case ImageFeature.AVIF:
img.src = 'data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A='
break
}
}

View File

@ -1,20 +0,0 @@
// check_webp_feature:
// 'feature' can be one of 'lossy', 'lossless', 'alpha' or 'animation'.
// 'callback(feature, isSupported)' will be passed back the detection result (in an asynchronous way!)
export function checkWebpFeature (feature: string, callback: (feature: string, isSupported: boolean) => void) {
const kTestImages: any = {
lossy: 'UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA',
lossless: 'UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==',
alpha: 'UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==',
animation: 'UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA',
}
const img = new Image()
img.onload = function () {
const result = (img.width > 0) && (img.height > 0)
callback(feature, result)
}
img.onerror = function () {
callback(feature, false)
}
img.src = 'data:image/webp;base64,' + kTestImages[feature]
}

View File

@ -183,7 +183,8 @@
</v-list-item>
<v-list-item>
<settings-switch v-model="alwaysFullscreen" :label="$t('bookreader.settings.always_fullscreen')" :disabled="!screenfull.isEnabled"/>
<settings-switch v-model="alwaysFullscreen" :label="$t('bookreader.settings.always_fullscreen')"
:disabled="!screenfull.isEnabled"/>
</v-list-item>
<v-subheader class="font-weight-black text-h6">{{ $t('bookreader.settings.display') }}</v-subheader>
@ -304,7 +305,7 @@ import SettingsSwitch from '@/components/SettingsSwitch.vue'
import ThumbnailExplorerDialog from '@/components/dialogs/ThumbnailExplorerDialog.vue'
import ShortcutHelpDialog from '@/components/dialogs/ShortcutHelpDialog.vue'
import {getBookTitleCompact} from '@/functions/book-title'
import {checkWebpFeature} from '@/functions/check-webp'
import {checkImageSupport, ImageFeature} from '@/functions/check-image'
import {bookPageUrl} from '@/functions/urls'
import {ReadingDirection} from '@/types/enum-books'
import Vue from 'vue'
@ -410,10 +411,11 @@ export default Vue.extend({
},
created() {
this.$vuetify.rtl = false
checkWebpFeature('lossy', (feature, isSupported) => {
if (isSupported) {
this.supportedMediaTypes.push('image/webp')
}
checkImageSupport(ImageFeature.WEBP_LOSSY, (isSupported) => {
if (isSupported) this.supportedMediaTypes.push('image/webp')
})
checkImageSupport(ImageFeature.JPEG_XL, (isSupported) => {
if (isSupported) this.supportedMediaTypes.push('image/jxl')
})
this.shortcuts = this.$_.keyBy([...shortcutsSettings, ...shortcutsSettingsPaged, ...shortcutsSettingsContinuous, ...shortcutsMenus, ...shortcutsAll], x => x.key)
window.addEventListener('keydown', this.keyPressed)
@ -615,7 +617,7 @@ export default Vue.extend({
set: function (alwaysFullscreen: boolean): void {
this.settings.alwaysFullscreen = alwaysFullscreen
this.$store.commit('setWebreaderAlwaysFullscreen', alwaysFullscreen)
if(alwaysFullscreen) this.enterFullscreen()
if (alwaysFullscreen) this.enterFullscreen()
else screenfull.isEnabled && screenfull.exit()
},
},
@ -629,7 +631,7 @@ export default Vue.extend({
else this.fullscreenIcon = 'mdi-fullscreen'
},
keyPressed(e: KeyboardEvent) {
if(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) return
if (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) return
this.shortcuts[e.key]?.execute(this)
},
async setup(bookId: string, page?: number) {
@ -872,6 +874,7 @@ export default Vue.extend({
.html-reader::-webkit-scrollbar {
display: none;
}
.html-reader {
scrollbar-width: none;
}