111 lines
No EOL
3.3 KiB
Vue
111 lines
No EOL
3.3 KiB
Vue
<template>
|
|
<img :src="image_data" :title="title || (owner + ':' + src)" :alt="alt" :class="imgClass"
|
|
:width="width" :height="height" :style="{objectFit: fit}"/>
|
|
</template>
|
|
|
|
<script>
|
|
import {mapActions, mapGetters} from "vuex";
|
|
import fileCache from "../fileCache";
|
|
|
|
export default {
|
|
name: "AuthenticatedImage",
|
|
props: {
|
|
src: {
|
|
type: String,
|
|
required: false,
|
|
default: null
|
|
},
|
|
owner: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
title: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
alt: {
|
|
type: String,
|
|
default: 'image'
|
|
},
|
|
imgClass: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
fallbackSrc: {
|
|
type: String,
|
|
default: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+CjxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjEyIiBmaWxsPSIjY2VkNGRhIi8+CjxjaXJjbGUgY3g9IjEyIiBjeT0iOS41IiByPSI0IiBmaWxsPSIjZmZmZmZmIi8+CjxwYXRoIGQ9Ik00IDIwLjJDNCAxNi4yIDcuNiAxMy41IDEyIDEzLjVzOCAyLjcgOCA2Ljd2MC4zSDR2LTAuM3oiIGZpbGw9IiNmZmZmZmYiLz4KPC9zdmc+Cg=='
|
|
},
|
|
width: {
|
|
type: [String, Number],
|
|
default: null
|
|
},
|
|
height: {
|
|
type: [String, Number],
|
|
default: null
|
|
},
|
|
fit: {
|
|
type: String,
|
|
default: 'contain'
|
|
},
|
|
refreshKey: {
|
|
type: [String, Number],
|
|
default: null
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
image_data: "",
|
|
servers: [],
|
|
lastRequestId: 0
|
|
}
|
|
},
|
|
computed: {
|
|
...mapGetters(["signAuth"])
|
|
},
|
|
methods: {
|
|
...mapActions(["getFriendServers"]),
|
|
async loadImage() {
|
|
const requestId = ++this.lastRequestId;
|
|
if (!this.src) {
|
|
if (requestId === this.lastRequestId) {
|
|
this.image_data = this.fallbackSrc;
|
|
}
|
|
return;
|
|
}
|
|
try {
|
|
// Cached by src alone: content is hash-addressed and immutable (see fileCache.js),
|
|
// so every instance showing the same file shares one fetch and blob.
|
|
const url = await fileCache.get(this.src, async () => {
|
|
this.servers = await this.getFriendServers({username: this.owner});
|
|
const response = await this.servers.getRaw(this.signAuth, this.src);
|
|
if (!response || !response.ok) {
|
|
throw new Error('failed to fetch ' + this.src);
|
|
}
|
|
return await response.blob();
|
|
});
|
|
if (requestId === this.lastRequestId) {
|
|
this.image_data = url;
|
|
}
|
|
} catch (_e) {
|
|
if (requestId === this.lastRequestId) {
|
|
this.image_data = this.fallbackSrc;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
watch: {
|
|
src() {
|
|
this.loadImage();
|
|
},
|
|
owner() {
|
|
this.loadImage();
|
|
},
|
|
refreshKey() {
|
|
this.loadImage();
|
|
}
|
|
},
|
|
mounted() {
|
|
this.loadImage();
|
|
}
|
|
}
|
|
</script> |