diff options
| author | Adam Malczewski <[email protected]> | 2026-04-09 20:52:18 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-04-09 20:52:18 +0900 |
| commit | b5a5ea8d300284e0f473df0e514cdc642857b03c (patch) | |
| tree | e791331edfcb3e75885a420d4f7e8bfe9a5f0506 /src/App.svelte | |
| parent | cbf41c0e495367bb3f582ea22aabdc03bd2d046d (diff) | |
| download | flashair-speedsync-b5a5ea8d300284e0f473df0e514cdc642857b03c.tar.gz flashair-speedsync-b5a5ea8d300284e0f473df0e514cdc642857b03c.zip | |
auto-polling of new photos
Diffstat (limited to 'src/App.svelte')
| -rw-r--r-- | src/App.svelte | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/src/App.svelte b/src/App.svelte index 03cd5c1..6f6ef6d 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -1,5 +1,6 @@ <script lang="ts"> import { flashair } from './lib/flashair'; + import { pollService } from './lib/flashair'; import type { FlashAirFileEntry } from './lib/flashair'; import { imageCache } from './lib/cache'; import { autoCacheService } from './lib/cache'; @@ -16,12 +17,29 @@ let isAutoCaching = $state(false); let cachedCount = $state(0); let totalCount = $state(0); + let newImagePaths = $state(new Set<string>()); + + // Wire the auto-cache service to do a poll check between each download. + // This pauses the interval during auto-caching and uses checkOnce() instead. + autoCacheService.onBetweenDownloads = async () => { + await pollService.checkOnce(); + }; + + function startAutoCacheWithPollPause(imageList: FlashAirFileEntry[]) { + pollService.pause(); + autoCacheService.start(imageList); + } $effect(() => { const unsubscribe = autoCacheService.subscribe(() => { isAutoCaching = autoCacheService.isActive; cachedCount = autoCacheService.cachedCount; totalCount = autoCacheService.totalCount; + + // When auto-caching finishes, resume the poll interval + if (!autoCacheService.isActive) { + pollService.resume(); + } }); isAutoCaching = autoCacheService.isActive; cachedCount = autoCacheService.cachedCount; @@ -33,17 +51,43 @@ document.documentElement.setAttribute('data-theme', isDark ? 'black' : 'cmyk'); }); + $effect(() => { + const unsubscribe = pollService.onNewImages((detected) => { + // Mark new paths for animation + const freshPaths = new Set(newImagePaths); + for (const img of detected) { + freshPaths.add(img.path); + } + newImagePaths = freshPaths; + + // Prepend new images (they are already sorted newest-first from listAllImages) + images = [...detected, ...images]; + + // Feed new images into auto-cache service + autoCacheService.stop(); + startAutoCacheWithPollPause(images); + + // Auto-select the newest if nothing was selected + if (selectedFile === undefined && images.length > 0) { + selectedFile = images[0]; + } + }); + return unsubscribe; + }); + async function loadAllImages() { loading = true; error = undefined; autoCacheService.stop(); + pollService.stop(); try { images = await flashair.listAllImages('/DCIM'); if (images.length > 0 && selectedFile === undefined) { selectedFile = images[0]; } + pollService.start(images); if (images.length > 0) { - autoCacheService.start(images); + startAutoCacheWithPollPause(images); } } catch (e) { error = e instanceof Error ? e.message : String(e); @@ -74,6 +118,7 @@ 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); @@ -95,12 +140,18 @@ showDeleteConfirm = false; } + function handleAnimationDone(path: string) { + const updated = new Set(newImagePaths); + updated.delete(path); + newImagePaths = updated; + } + async function clearAllCache() { autoCacheService.stop(); await imageCache.clear(); // Restart auto-caching from scratch if (images.length > 0) { - autoCacheService.start(images); + startAutoCacheWithPollPause(images); } } </script> @@ -140,7 +191,7 @@ {/if} </div> <div class="flex-1 min-h-0"> - <ImageList {images} selectedPath={selectedFile?.path} onSelect={selectImage} /> + <ImageList {images} selectedPath={selectedFile?.path} onSelect={selectImage} {newImagePaths} onAnimationDone={handleAnimationDone} /> </div> </div> </div> |
