diff --git a/apps/photos/src/components/pages/gallery/PreviewCard.tsx b/apps/photos/src/components/pages/gallery/PreviewCard.tsx index 8b0a4f629..8c5ace3aa 100644 --- a/apps/photos/src/components/pages/gallery/PreviewCard.tsx +++ b/apps/photos/src/components/pages/gallery/PreviewCard.tsx @@ -238,13 +238,34 @@ export default function PreviewCard(props: IProps) { }, []); useEffect(() => { - if (!file.msrc && !props.showPlaceholder) { - const main = async () => { - try { - let url; - if (thumbs.has(file.id)) { - url = thumbs.get(file.id); + const main = async () => { + try { + if (imgSrc) { + return; + } + let url: string; + // check in in-memory cache + if (thumbs.has(file.id)) { + url = thumbs.get(file.id); + } else { + // check in cacheStorage + if ( + publicCollectionGalleryContext.accessedThroughSharedURL + ) { + url; + await PublicCollectionDownloadManager.getCachedThumbnail( + file + ); } else { + url = await DownloadManager.getCachedThumbnail(file); + } + if (url) { + thumbs.set(file.id, url); + } else { + // download thumbnail + if (props.showPlaceholder) { + return; + } if ( publicCollectionGalleryContext.accessedThroughSharedURL ) { @@ -259,18 +280,18 @@ export default function PreviewCard(props: IProps) { } thumbs.set(file.id, url); } - if (!isMounted.current) { - return; - } - setImgSrc(url); - updateURL(file.id, url); - } catch (e) { - logError(e, 'preview card useEffect failed'); - // no-op } - }; - main(); - } + if (!isMounted.current) { + return; + } + setImgSrc(url); + updateURL(file.id, url); + } catch (e) { + logError(e, 'preview card useEffect failed'); + // no-op + } + }; + main(); }, [props.showPlaceholder]); const handleClick = () => { diff --git a/apps/photos/src/services/downloadManager.ts b/apps/photos/src/services/downloadManager.ts index 37dd630c9..fa4a18005 100644 --- a/apps/photos/src/services/downloadManager.ts +++ b/apps/photos/src/services/downloadManager.ts @@ -16,6 +16,7 @@ import { CacheStorageService } from './cache/cacheStorageService'; import { CACHES } from 'constants/cache'; import { Remote } from 'comlink'; import { DedicatedCryptoWorker } from 'worker/crypto.worker'; +import { LimitedCache } from 'types/cache'; class DownloadManager { private fileObjectURLPromise = new Map< @@ -24,6 +25,40 @@ class DownloadManager { >(); private thumbnailObjectURLPromise = new Map>(); + private async getThumbnailCache() { + try { + const thumbnailCache = await CacheStorageService.open( + CACHES.THUMBS + ); + return thumbnailCache; + } catch (e) { + return null; + // ignore + } + } + + public async getCachedThumbnail( + file: EnteFile, + thumbnailCache?: LimitedCache + ) { + try { + if (!thumbnailCache) { + thumbnailCache = await this.getThumbnailCache(); + } + const cacheResp: Response = await thumbnailCache?.match( + file.id.toString() + ); + + if (cacheResp) { + return URL.createObjectURL(await cacheResp.blob()); + } + return null; + } catch (e) { + logError(e, 'failed to get cached thumbnail'); + throw e; + } + } + public async getThumbnail( file: EnteFile, tokenOverride?: string, @@ -37,15 +72,13 @@ class DownloadManager { } if (!this.thumbnailObjectURLPromise.has(file.id)) { const downloadPromise = async () => { - const thumbnailCache = await CacheStorageService.open( - CACHES.THUMBS + const thumbnailCache = await this.getThumbnailCache(); + const cachedThumb = await this.getCachedThumbnail( + file, + thumbnailCache ); - - const cacheResp: Response = await thumbnailCache?.match( - file.id.toString() - ); - if (cacheResp) { - return URL.createObjectURL(await cacheResp.blob()); + if (cachedThumb) { + return cachedThumb; } const thumb = await this.downloadThumb( token, diff --git a/apps/photos/src/services/publicCollectionDownloadManager.ts b/apps/photos/src/services/publicCollectionDownloadManager.ts index 906867079..b64ec15d5 100644 --- a/apps/photos/src/services/publicCollectionDownloadManager.ts +++ b/apps/photos/src/services/publicCollectionDownloadManager.ts @@ -15,6 +15,9 @@ import { FILE_TYPE } from 'constants/file'; import { CustomError } from 'utils/error'; import QueueProcessor from './queueProcessor'; import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker'; +import { CACHES } from 'constants/cache'; +import { CacheStorageService } from './cache/cacheStorageService'; +import { LimitedCache } from 'types/cache'; class PublicCollectionDownloadManager { private fileObjectURLPromise = new Map< @@ -25,6 +28,40 @@ class PublicCollectionDownloadManager { private thumbnailDownloadRequestsProcessor = new QueueProcessor(5); + private async getThumbnailCache() { + try { + const thumbnailCache = await CacheStorageService.open( + CACHES.THUMBS + ); + return thumbnailCache; + } catch (e) { + return null; + // ignore + } + } + + public async getCachedThumbnail( + file: EnteFile, + thumbnailCache?: LimitedCache + ) { + try { + if (!thumbnailCache) { + thumbnailCache = await this.getThumbnailCache(); + } + const cacheResp: Response = await thumbnailCache?.match( + file.id.toString() + ); + + if (cacheResp) { + return URL.createObjectURL(await cacheResp.blob()); + } + return null; + } catch (e) { + logError(e, 'failed to get cached thumbnail'); + throw e; + } + } + public async getThumbnail( file: EnteFile, token: string, @@ -37,21 +74,13 @@ class PublicCollectionDownloadManager { if (!this.thumbnailObjectURLPromise.has(file.id)) { const downloadPromise = async () => { - const thumbnailCache = await (async () => { - try { - return await caches.open('thumbs'); - } catch (e) { - return null; - // ignore - } - })(); - - const cacheResp: Response = await thumbnailCache?.match( - file.id.toString() + const thumbnailCache = await this.getThumbnailCache(); + const cachedThumb = await this.getCachedThumbnail( + file, + thumbnailCache ); - - if (cacheResp) { - return URL.createObjectURL(await cacheResp.blob()); + if (cachedThumb) { + return cachedThumb; } const thumb =