blob: f0fe8bf4c7d9cd6236f46e8b163ccdf643b13cc1 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
<script lang="ts">
import { flashair } from '../flashair';
import { imageCache } from '../cache';
interface Props {
path: string;
alt: string;
}
let { path, alt }: Props = $props();
let blobUrl = $state<string | undefined>(undefined);
let rawBlobUrl: string | undefined;
$effect(() => {
const currentPath = path;
blobUrl = undefined;
void loadThumbnail(currentPath);
return () => {
if (rawBlobUrl !== undefined) {
URL.revokeObjectURL(rawBlobUrl);
rawBlobUrl = undefined;
}
};
});
async function loadThumbnail(filePath: string) {
// Try cache first
const cached = await imageCache.get('thumbnail', filePath);
if (cached !== undefined) {
const url = URL.createObjectURL(cached.blob);
rawBlobUrl = url;
blobUrl = url;
return;
}
// Fetch from card
const thumbUrl = flashair.thumbnailUrl(filePath);
if (thumbUrl === undefined) return;
try {
const { blob, meta } = await flashair.fetchThumbnail(filePath);
// Store in cache (fire-and-forget)
void imageCache.put('thumbnail', filePath, blob, meta);
const url = URL.createObjectURL(blob);
rawBlobUrl = url;
blobUrl = url;
} catch {
// Thumbnail fetch failed — show placeholder
}
}
</script>
{#if blobUrl !== undefined}
<img
src={blobUrl}
{alt}
class="w-full aspect-square rounded object-cover"
draggable="false"
/>
{:else}
<div class="w-full aspect-square rounded bg-base-300 flex items-center justify-center">
<span class="loading loading-spinner loading-sm"></span>
</div>
{/if}
|