From e3e6c664b547666a367c96062523753699fdeb90 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Fri, 10 Apr 2026 02:34:58 +0900 Subject: add auto-show image toggle, ui niceness, more complete readme --- README.md | 32 ++++++++++++++ src/App.svelte | 76 +++++----------------------------- src/lib/components/ImagePreview.svelte | 6 +-- 3 files changed, 45 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index 23a9a21..127d78b 100644 --- a/README.md +++ b/README.md @@ -102,3 +102,35 @@ The fastest way to iterate: ``` Accessible at `http://flashair/speedsync/index.html` when connected to the FlashAir WiFi. + +--- + +## UI Guide + +### Layout + +The app uses a two-panel layout: + +- **Left panel** — Full-size image preview with pinch-to-zoom and pan support. Background is always solid black. +- **Right panel** — Scrollable thumbnail list sorted newest-first. Shows a cache progress indicator (`cached/total`) and a status dot (pulsing when auto-caching is active). + +### Floating Action Button (FAB) + +A flower-style FAB in the bottom-right corner opens to reveal action buttons: + +| Icon | Color | Action | +|---|---|---| +| ☰ (hamburger) | Secondary | Opens/closes the FAB menu | +| ↓ (download arrow) | Primary | Saves the currently selected photo to your device | +| 👁 (eye) / 👁‍🗨 (eye-slash) | Accent (on) / Neutral (off) | **Auto-show new images** — when enabled, automatically switches the preview to the newest photo as it arrives from the camera | +| ✕ (clear box) | Warning | Clears the local image cache and restarts background pre-caching | +| ℹ (info) | Info | Toggles the cache debug overlay | +| ☀/🌙 (sun/moon) | Secondary | Toggles between light (CMYK) and dark (Black) themes | + +### Automatic polling + +The app polls the FlashAir card every 1.5 seconds for new photos. When a new photo is detected: + +1. It appears at the top of the thumbnail list with a reveal animation +2. Background pre-caching restarts to include the new image +3. If **Auto-show new images** is enabled, the preview switches to the new photo immediately diff --git a/src/App.svelte b/src/App.svelte index 7a634cc..5fa63a7 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -13,8 +13,7 @@ let loading = $state(false); let error = $state(undefined); let isDark = $state(false); - let deleting = $state(false); - let showDeleteConfirm = $state(false); + let showNewImage = $state(false); let isAutoCaching = $state(false); let cachedCount = $state(0); let totalCount = $state(0); @@ -68,8 +67,8 @@ autoCacheService.stop(); startAutoCacheWithPollPause(images); - // Auto-select the newest if nothing was selected - if (selectedFile === undefined && images.length > 0) { + // Auto-select the newest if nothing was selected, or if showNewImage is on + if ((showNewImage || selectedFile === undefined) && images.length > 0) { selectedFile = images[0]; } }); @@ -102,45 +101,6 @@ selectedFile = file; } - function requestDelete() { - if (selectedFile === undefined) return; - showDeleteConfirm = true; - } - - async function confirmDelete() { - showDeleteConfirm = false; - if (selectedFile === undefined) return; - - const fileToDelete = selectedFile; - deleting = true; - try { - await flashair.deleteFile(fileToDelete.path); - // Remove from cache and auto-cache queue - void imageCache.delete('thumbnail', fileToDelete.path); - void imageCache.delete('full', fileToDelete.path); - autoCacheService.removeImage(fileToDelete.path); - pollService.removeKnownPath(fileToDelete.path); - // Remove from list and select next image - const idx = images.findIndex((f) => f.path === fileToDelete.path); - images = images.filter((f) => f.path !== fileToDelete.path); - if (images.length === 0) { - selectedFile = undefined; - } else if (idx >= images.length) { - selectedFile = images[images.length - 1]; - } else { - selectedFile = images[idx]; - } - } catch (e) { - error = `Delete failed: ${e instanceof Error ? e.message : String(e)}`; - } finally { - deleting = false; - } - } - - function cancelDelete() { - showDeleteConfirm = false; - } - function handleAnimationDone(path: string) { const updated = new Set(newImagePaths); updated.delete(path); @@ -251,13 +211,16 @@ {/if} - - @@ -287,23 +250,6 @@ - -{#if showDeleteConfirm && selectedFile !== undefined} - - - - -{/if} - {#if showDebug} {/if} diff --git a/src/lib/components/ImagePreview.svelte b/src/lib/components/ImagePreview.svelte index 22b40da..78677f7 100644 --- a/src/lib/components/ImagePreview.svelte +++ b/src/lib/components/ImagePreview.svelte @@ -438,7 +438,7 @@
@@ -453,7 +453,7 @@
{:else} {#if downloading && progress < 1} -
+
@@ -463,7 +463,6 @@
{/if} {#if fullObjectUrl !== undefined} - {#key fullObjectUrl} {file.filename} - {/key} {:else if showThumbnail}