Snapshot: alpha-2026-9

This commit is contained in:
j3d1 2026-09-02 21:40:28 +02:00
parent 9acf5a97e2
commit d00b5c7961
241 changed files with 85546 additions and 2409 deletions

View file

@ -0,0 +1,111 @@
<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>