From 25e3fc7808ddc103a5bf63de7530ab7431dc88b2 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Sun, 26 Jan 2025 03:51:43 +0100 Subject: [PATCH] Load images with cors allowed Without allowing cors it is e.g. not possible to extract colors from an image --- src/lib/requests/RequestManager.ts | 33 ++++++++++++++----- src/modules/core/components/SpinnerImage.tsx | 5 ++- src/modules/reader/utils/Reader.utils.ts | 1 + .../components/cards/TrackerMangaCard.tsx | 1 + 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/lib/requests/RequestManager.ts b/src/lib/requests/RequestManager.ts index 348150c7..14accf09 100644 --- a/src/lib/requests/RequestManager.ts +++ b/src/lib/requests/RequestManager.ts @@ -860,7 +860,7 @@ export class RequestManager { abort(); } - private async optionallyDecodeImage(url: string, shouldDecode?: boolean): Promise { + private async optionallyDecodeImage(url: string, shouldDecode?: boolean, allowCors?: boolean): Promise { if (!shouldDecode) { return url; } @@ -868,6 +868,10 @@ export class RequestManager { const decodePromise = new ControlledPromise(); const img = new Image(); + + if (allowCors) { + img.crossOrigin = 'anonymous'; + } img.src = url; img.onload = async () => { @@ -890,7 +894,11 @@ export class RequestManager { private fetchImageViaTag( url: string, - { priority, shouldDecode }: { priority?: QueuePriority; shouldDecode?: boolean } = {}, + { + priority, + shouldDecode, + allowCors, + }: { priority?: QueuePriority; shouldDecode?: boolean; allowCors?: boolean } = {}, ): ImageRequest { const imgRequest = new ControlledPromise(); imgRequest.promise.catch(() => {}); @@ -910,6 +918,9 @@ export class RequestManager { // throws error in case request was already aborted await Promise.race([imgRequest.promise, Promise.resolve()]); + if (allowCors) { + img.crossOrigin = 'anonymous'; + } img.src = url; img.onload = async () => { @@ -993,21 +1004,25 @@ export class RequestManager { */ public requestImage( url: string, - options: { priority?: QueuePriority; useFetchApi?: boolean; shouldDecode?: boolean } = { + options: { priority?: QueuePriority; useFetchApi?: boolean; shouldDecode?: boolean; allowCors?: boolean } = {}, + ): ImageRequest { + const finalOptions = { useFetchApi: false, shouldDecode: false, - }, - ): ImageRequest { + allowCors: true, + ...Object.fromEntries(Object.entries(options).filter(([, value]) => value !== undefined)), + }; + // on firefox images are decoded async which causes a "flicker/blinking" when they're getting visible for the first time // this is an issue especially in the reader because pages that should not be shown are rendered but // not displayed, which then causes this issue once they get displayed - const shouldDecode = !!options.shouldDecode && navigator.userAgent.toLowerCase().includes('firefox'); + const shouldDecode = finalOptions.shouldDecode && navigator.userAgent.toLowerCase().includes('firefox'); - if (options.useFetchApi) { - return this.fetchImageViaFetchApi(url, { ...options, shouldDecode }); + if (finalOptions.useFetchApi) { + return this.fetchImageViaFetchApi(url, { ...finalOptions, shouldDecode }); } - return this.fetchImageViaTag(url, { ...options, shouldDecode }); + return this.fetchImageViaTag(url, { ...finalOptions, shouldDecode }); } private doRequest( diff --git a/src/modules/core/components/SpinnerImage.tsx b/src/modules/core/components/SpinnerImage.tsx index c0230ea0..d3db5ec2 100644 --- a/src/modules/core/components/SpinnerImage.tsx +++ b/src/modules/core/components/SpinnerImage.tsx @@ -35,6 +35,7 @@ interface IProps { shouldDecode?: boolean; useFetchApi?: boolean; + allowCors?: boolean; priority?: Priority; @@ -46,6 +47,7 @@ export const SpinnerImage = forwardRef((props: IProps, imgRef: ForwardedRef {}; } - const imageRequest = requestManager.requestImage(src, { priority, shouldDecode, useFetchApi }); + const imageRequest = requestManager.requestImage(src, { priority, shouldDecode, useFetchApi, allowCors }); let cacheTimeout: NodeJS.Timeout; const fetchImage = async () => { @@ -156,6 +158,7 @@ export const SpinnerImage = forwardRef((props: IProps, imgRef: ForwardedRef