Live-update queue list when upload status changes

Storage.updatePhoto() now fires a 'photo-updated' CustomEvent so the
queue page refreshes immediately (300ms debounce) when the sync engine
changes a photo's status, instead of waiting for the 5s poll.

Also reduces background poll to 30s (just a fallback now), and revokes
stale ObjectURLs on each rebuild to prevent memory leaks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-07 16:07:53 -06:00
parent 5105b42c46
commit 3f0b0ea2e2
3 changed files with 30 additions and 6 deletions

View File

@@ -93,7 +93,14 @@ const Storage = {
}, },
async updatePhoto(id, updates) { async updatePhoto(id, updates) {
return await this.db.photos.update(id, updates); const result = await this.db.photos.update(id, updates);
// Notify any listening UI (e.g. queue page) of the change
try {
window.dispatchEvent(new CustomEvent('photo-updated', {
detail: { id: id, updates: updates }
}));
} catch (e) { /* ignore if no window context */ }
return result;
}, },
async deletePhoto(id) { async deletePhoto(id) {

View File

@@ -1,9 +1,9 @@
// NextSnap Service Worker // NextSnap Service Worker
// Provides offline-first caching for the app shell // Provides offline-first caching for the app shell
const CACHE_VERSION = 'nextsnap-v15'; const CACHE_VERSION = 'nextsnap-v16';
const APP_SHELL_CACHE = 'nextsnap-shell-v11'; const APP_SHELL_CACHE = 'nextsnap-shell-v12';
const RUNTIME_CACHE = 'nextsnap-runtime-v11'; const RUNTIME_CACHE = 'nextsnap-runtime-v12';
// Assets to cache on install // Assets to cache on install
const APP_SHELL_ASSETS = [ const APP_SHELL_ASSETS = [

View File

@@ -411,6 +411,10 @@ async function loadQueue() {
} }
emptyState.style.display = 'none'; emptyState.style.display = 'none';
// Revoke old ObjectURLs before rebuilding to prevent memory leaks
queueList.querySelectorAll('img[src^="blob:"]').forEach(img => {
URL.revokeObjectURL(img.src);
});
queueList.innerHTML = ''; queueList.innerHTML = '';
// Show active uploads first (newest first) // Show active uploads first (newest first)
@@ -610,10 +614,23 @@ window.addEventListener('offline', () => {
document.getElementById('sync-now-btn').disabled = true; document.getElementById('sync-now-btn').disabled = true;
}); });
// Refresh queue periodically // Live updates: listen for photo status changes from the sync engine
let refreshTimer = null;
window.addEventListener('photo-updated', () => {
// Debounce: rapid status transitions (pending→uploading→verified)
// would otherwise trigger multiple full rebuilds
if (refreshTimer) clearTimeout(refreshTimer);
refreshTimer = setTimeout(() => {
refreshTimer = null;
loadQueue();
updateStats();
}, 300);
});
// Fallback: full refresh every 30s in case events are missed
setInterval(() => { setInterval(() => {
loadQueue(); loadQueue();
updateStats(); updateStats();
}, 5000); }, 30000);
</script> </script>
{% endblock %} {% endblock %}