diff options
Diffstat (limited to 'src/lib/components')
| -rw-r--r-- | src/lib/components/ImageList.svelte | 52 | ||||
| -rw-r--r-- | src/lib/components/ImagePreview.svelte | 40 |
2 files changed, 92 insertions, 0 deletions
diff --git a/src/lib/components/ImageList.svelte b/src/lib/components/ImageList.svelte new file mode 100644 index 0000000..7e6f836 --- /dev/null +++ b/src/lib/components/ImageList.svelte @@ -0,0 +1,52 @@ +<script lang="ts"> + import { flashair } from '../flashair'; + import type { FlashAirFileEntry } from '../flashair'; + + interface Props { + images: FlashAirFileEntry[]; + selectedPath: string | undefined; + onSelect: (file: FlashAirFileEntry) => void; + } + + let { images, selectedPath, onSelect }: Props = $props(); +</script> + +<div class="h-full overflow-y-auto bg-base-100"> + {#if images.length === 0} + <div class="flex items-center justify-center h-full text-base-content/50 p-4"> + <p class="text-center text-sm">No images found</p> + </div> + {:else} + <ul class="flex flex-col gap-0.5 p-1"> + {#each images as file (file.path)} + {@const thumbUrl = flashair.thumbnailUrl(file.path)} + {@const isSelected = file.path === selectedPath} + <li> + <button + class="flex items-center gap-2 w-full rounded-lg p-1.5 text-left transition-colors {isSelected + ? 'bg-primary text-primary-content' + : 'hover:bg-base-200'}" + onclick={() => onSelect(file)} + > + {#if thumbUrl} + <img + src={thumbUrl} + alt={file.filename} + class="w-12 h-12 rounded object-cover shrink-0" + loading="lazy" + /> + {:else} + <div class="w-12 h-12 rounded bg-base-300 flex items-center justify-center shrink-0"> + <span class="text-lg">🖼️</span> + </div> + {/if} + <div class="min-w-0 flex-1"> + <p class="text-xs font-medium truncate">{file.filename}</p> + <p class="text-xs opacity-60">{file.date.toLocaleString()}</p> + </div> + </button> + </li> + {/each} + </ul> + {/if} +</div> diff --git a/src/lib/components/ImagePreview.svelte b/src/lib/components/ImagePreview.svelte new file mode 100644 index 0000000..82115e7 --- /dev/null +++ b/src/lib/components/ImagePreview.svelte @@ -0,0 +1,40 @@ +<script lang="ts"> + import { flashair } from '../flashair'; + import type { FlashAirFileEntry } from '../flashair'; + + interface Props { + file: FlashAirFileEntry | undefined; + } + + let { file }: Props = $props(); + + let imageUrl = $derived(file !== undefined ? flashair.fileUrl(file.path) : undefined); + let imageLoaded = $state(false); + + $effect(() => { + if (imageUrl !== undefined) { + imageLoaded = false; + } + }); +</script> + +<div class="h-full flex items-center justify-center bg-base-300 relative"> + {#if file === undefined || imageUrl === undefined} + <div class="text-base-content/40 text-center p-8"> + <p class="text-lg">Select a photo to preview</p> + </div> + {:else} + {#key file.path} + {#if !imageLoaded} + <span class="loading loading-spinner loading-lg absolute"></span> + {/if} + <img + src={imageUrl} + alt={file.filename} + class="max-w-full max-h-full object-contain" + class:opacity-0={!imageLoaded} + onload={() => { imageLoaded = true; }} + /> + {/key} + {/if} +</div> |
