diff options
author | Louis Chemineau <louis@chmn.me> | 2024-08-29 14:27:59 +0200 |
---|---|---|
committer | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-08-29 23:08:11 +0200 |
commit | 56e4859201d80d3ea444bc88647d96ad71b59f88 (patch) | |
tree | b307b795be9ad14a471a90fd6794a264ef181faa /apps/files/src/components/FileEntry | |
parent | 19dd32962de7a73ecc934f8e7a5340d09fd24317 (diff) | |
download | nextcloud-server-56e4859201d80d3ea444bc88647d96ad71b59f88.tar.gz nextcloud-server-56e4859201d80d3ea444bc88647d96ad71b59f88.zip |
feat: Use the blurhash in Files
Signed-off-by: Louis Chemineau <louis@chmn.me>
Diffstat (limited to 'apps/files/src/components/FileEntry')
-rw-r--r-- | apps/files/src/components/FileEntry/FileEntryPreview.vue | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/apps/files/src/components/FileEntry/FileEntryPreview.vue b/apps/files/src/components/FileEntry/FileEntryPreview.vue index 2e43338cf05..6fe7a13a968 100644 --- a/apps/files/src/components/FileEntry/FileEntryPreview.vue +++ b/apps/files/src/components/FileEntry/FileEntryPreview.vue @@ -14,16 +14,22 @@ </template> </template> - <!-- Decorative image, should not be aria documented --> - <img v-else-if="previewUrl && backgroundFailed !== true" - ref="previewImg" - alt="" - class="files-list__row-icon-preview" - :class="{'files-list__row-icon-preview--loaded': backgroundFailed === false}" - loading="lazy" - :src="previewUrl" - @error="onBackgroundError" - @load="backgroundFailed = false"> + <!-- Decorative images, should not be aria documented --> + <span v-else-if="previewUrl" class="files-list__row-icon-preview-container"> + <canvas v-if="hasBlurhash && (backgroundFailed === true || !backgroundLoaded)" + ref="canvas" + class="files-list__row-icon-blurhash" + aria-hidden="true" /> + <img v-if="backgroundFailed !== true" + ref="previewImg" + alt="" + class="files-list__row-icon-preview" + :class="{'files-list__row-icon-preview--loaded': backgroundFailed === false}" + loading="lazy" + :src="previewUrl" + @error="onBackgroundError" + @load="onBackgroundLoad"> + </span> <FileIcon v-else v-once /> @@ -58,6 +64,7 @@ import LinkIcon from 'vue-material-design-icons/Link.vue' import NetworkIcon from 'vue-material-design-icons/Network.vue' import TagIcon from 'vue-material-design-icons/Tag.vue' import PlayCircleIcon from 'vue-material-design-icons/PlayCircle.vue' +import { decode } from 'blurhash' import CollectivesIcon from './CollectivesIcon.vue' import FavoriteIcon from './FavoriteIcon.vue' @@ -107,6 +114,7 @@ export default Vue.extend({ data() { return { backgroundFailed: undefined as boolean | undefined, + backgroundLoaded: false, } }, @@ -206,6 +214,16 @@ export default Vue.extend({ return null }, + + hasBlurhash() { + return this.source.attributes['metadata-blurhash'] !== undefined + }, + }, + + mounted() { + if (this.hasBlurhash && this.$refs.canvas) { + this.drawBlurhash() + } }, methods: { @@ -213,17 +231,43 @@ export default Vue.extend({ reset() { // Reset background state to cancel any ongoing requests this.backgroundFailed = undefined + this.backgroundLoaded = false if (this.$refs.previewImg) { this.$refs.previewImg.src = '' } }, + onBackgroundLoad() { + this.backgroundFailed = false + this.backgroundLoaded = true + }, + onBackgroundError(event) { // Do not fail if we just reset the background if (event.target?.src === '') { return } this.backgroundFailed = true + this.backgroundLoaded = false + }, + + drawBlurhash() { + const canvas = this.$refs.canvas as HTMLCanvasElement + + const width = canvas.width + const height = canvas.height + + const pixels = decode(this.source.attributes['metadata-blurhash'], width, height) + + const ctx = canvas.getContext('2d') + if (ctx === null) { + logger.error('Cannot create context for blurhash canvas') + return + } + + const imageData = ctx.createImageData(width, height) + imageData.data.set(pixels) + ctx.putImageData(imageData, 0, 0) }, t, |