diff --git a/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte b/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte
index 2b55ea57b2..740cf784b7 100644
--- a/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte
+++ b/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte
@@ -1,6 +1,6 @@
@@ -131,3 +151,45 @@
{/if}
+
+
+ {#if assetInteraction.selectionActive}
+
+
assetInteraction.clearMultiselect()}
+ >
+
+
+
+
+
+
+ timelineManager.update(ids, (asset) => (asset.isFavorite = isFavorite))}
+ >
+
+
+
+
+
+ timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
+ />
+ {#if $preferences.tags.enabled}
+
+ {/if}
+ timelineManager.removeAssets(assetIds)}
+ onUndoDelete={(assets) => timelineManager.upsertAssets(assets)}
+ />
+
+
+
+
+ {/if}
+
diff --git a/web/src/service-worker/broadcast-channel.ts b/web/src/service-worker/broadcast-channel.ts
index ae6f1e1be6..62f90bbcc5 100644
--- a/web/src/service-worker/broadcast-channel.ts
+++ b/web/src/service-worker/broadcast-channel.ts
@@ -1,7 +1,8 @@
-import { handleCancel, handlePreload } from './request';
+import { handleCancel, handleIsUrlCached, handlePreload } from './request';
+
+export const broadcast = new BroadcastChannel('immich');
export const installBroadcastChannelListener = () => {
- const broadcast = new BroadcastChannel('immich');
// eslint-disable-next-line unicorn/prefer-add-event-listener
broadcast.onmessage = (event) => {
if (!event.data) {
@@ -20,6 +21,15 @@ export const installBroadcastChannelListener = () => {
handleCancel(url);
break;
}
+
+ case 'isImageUrlCached': {
+ void handleIsUrlCached(url);
+ break;
+ }
}
};
};
+
+export const replyIsImageUrlCached = (url: string, isImageUrlCached: boolean) => {
+ broadcast.postMessage({ type: 'isImageUrlCachedReply', url, isImageUrlCached });
+};
diff --git a/web/src/service-worker/cache.ts b/web/src/service-worker/cache.ts
index f91d8366ea..8ddf3e6ec2 100644
--- a/web/src/service-worker/cache.ts
+++ b/web/src/service-worker/cache.ts
@@ -30,7 +30,11 @@ export const put = async (key: string, response: Response) => {
return;
}
- cache.put(key, response.clone());
+ try {
+ await cache.put(key, response.clone());
+ } catch (error) {
+ console.error('Ignoring error during cache put', error);
+ }
};
export const prune = async () => {
diff --git a/web/src/service-worker/request.ts b/web/src/service-worker/request.ts
index aeb63be899..a5189fd548 100644
--- a/web/src/service-worker/request.ts
+++ b/web/src/service-worker/request.ts
@@ -1,3 +1,4 @@
+import { replyIsImageUrlCached } from './broadcast-channel';
import { get, put } from './cache';
const pendingRequests = new Map
();
@@ -44,7 +45,7 @@ export const handleRequest = async (request: URL | Request) => {
const response = await fetch(request, { signal: cancelToken.signal });
assertResponse(response);
- put(cacheKey, response);
+ await put(cacheKey, response);
return response;
} catch (error) {
@@ -71,3 +72,9 @@ export const handleCancel = (url: URL) => {
pendingRequest.abort();
pendingRequests.delete(cacheKey);
};
+
+export const handleIsUrlCached = async (url: URL) => {
+ const cacheKey = getCacheKey(url);
+ const isImageUrlCached = !!(await get(cacheKey));
+ replyIsImageUrlCached(url.pathname + url.search + url.hash, isImageUrlCached);
+};