57 lines
1.8 KiB
Svelte
57 lines
1.8 KiB
Svelte
<script lang="ts">
|
|
import type { Account } from '$lib/mastodon/response';
|
|
|
|
interface Props {
|
|
account: Account;
|
|
}
|
|
|
|
let { account }: Props = $props();
|
|
let avatarDescription: string = $derived(`Avatar for ${account.acct}`);
|
|
let sourceSetHtml: string = $derived.by(() => {
|
|
// Sort thumbnails by file type. This is important, because the order of the srcset entries matter.
|
|
// We need the best format to be first
|
|
const formatPriority = new Map<string, number>([
|
|
['avif', 0],
|
|
['webp', 1],
|
|
['jpg', 99],
|
|
['jpeg', 99]
|
|
]);
|
|
const resizedAvatars = (account.resizedAvatars ?? []).toSorted((a, b) => {
|
|
const extensionA = a.file.split('.').pop() ?? '';
|
|
const extensionB = b.file.split('.').pop() ?? '';
|
|
const prioA = formatPriority.get(extensionA) ?? 3;
|
|
const prioB = formatPriority.get(extensionB) ?? 3;
|
|
return prioA - prioB;
|
|
});
|
|
const m = new Map<string, string[]>();
|
|
for (const resizedAvatar of resizedAvatars) {
|
|
const extension = resizedAvatar.file.split('.').pop();
|
|
const mime = extension ? `image/${extension}` : 'application/octet-stream';
|
|
const sourceSetEntry = `${resizedAvatar.file} ${resizedAvatar.sizeDescriptor}`;
|
|
m.set(mime, [...(m.get(mime) || []), sourceSetEntry]);
|
|
}
|
|
let html = '';
|
|
for (const entry of m.entries()) {
|
|
const srcset = entry[1].join(', ');
|
|
html += `<source srcset="${srcset}" type="${entry[0]}" />`;
|
|
}
|
|
return html;
|
|
});
|
|
</script>
|
|
|
|
<picture>
|
|
{@html sourceSetHtml}
|
|
<img src={account.avatar} alt={avatarDescription} loading="lazy" width="50" height="50" />
|
|
</picture>
|
|
|
|
<style>
|
|
img {
|
|
max-width: 100%;
|
|
max-height: 100%;
|
|
width: 50px;
|
|
height: 50px;
|
|
object-fit: contain;
|
|
border-radius: 3px;
|
|
}
|
|
</style>
|