summaryrefslogtreecommitdiffhomepage
path: root/src/lib/components/CachedThumbnail.svelte
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-04-09 19:28:44 +0900
committerAdam Malczewski <[email protected]>2026-04-09 19:28:44 +0900
commit1bfd3e50842fdd511fc89d2b5892f8d440914cca (patch)
treee8fec173a185b91ef28681e8e7030cae46bd37ee /src/lib/components/CachedThumbnail.svelte
parent2a8ecc585f6dc5c3c5f98ba3821d899807d813f8 (diff)
downloadflashair-speedsync-1bfd3e50842fdd511fc89d2b5892f8d440914cca.tar.gz
flashair-speedsync-1bfd3e50842fdd511fc89d2b5892f8d440914cca.zip
caching of images
Diffstat (limited to 'src/lib/components/CachedThumbnail.svelte')
-rw-r--r--src/lib/components/CachedThumbnail.svelte67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/lib/components/CachedThumbnail.svelte b/src/lib/components/CachedThumbnail.svelte
new file mode 100644
index 0000000..f0fe8bf
--- /dev/null
+++ b/src/lib/components/CachedThumbnail.svelte
@@ -0,0 +1,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}