Queue image requests per source
If http protocol is h2 or newer, allow: - 5 requests per source - unlimited local source requests
This commit is contained in:
@@ -12,6 +12,7 @@ import { MangaIdInfo } from '@/features/manga/Manga.types.ts';
|
|||||||
import { ChapterSourceOrderInfo } from '@/features/chapter/Chapter.types.ts';
|
import { ChapterSourceOrderInfo } from '@/features/chapter/Chapter.types.ts';
|
||||||
import { BrowseTab } from '@/features/browse/Browse.types.ts';
|
import { BrowseTab } from '@/features/browse/Browse.types.ts';
|
||||||
import { SearchParam } from '@/base/Base.types.ts';
|
import { SearchParam } from '@/base/Base.types.ts';
|
||||||
|
import { UrlUtil } from '@/lib/UrlUtil.ts';
|
||||||
|
|
||||||
type AppRouteInfo = {
|
type AppRouteInfo = {
|
||||||
match: string;
|
match: string;
|
||||||
@@ -20,16 +21,6 @@ type AppRouteInfo = {
|
|||||||
|
|
||||||
type TAppRoutes = Record<string, AppRouteInfo & { childRoutes?: TAppRoutes }>;
|
type TAppRoutes = Record<string, AppRouteInfo & { childRoutes?: TAppRoutes }>;
|
||||||
|
|
||||||
const createParam = (name: string, value: any): string => (value ? `${name}=${encodeURIComponent(value)}` : '');
|
|
||||||
|
|
||||||
const createQueryParam = (query: string | null | undefined): string => createParam(SearchParam.QUERY, query);
|
|
||||||
|
|
||||||
const addParams = (path: string, ...params: string[]) => {
|
|
||||||
const joinedParams = params.filter(Boolean).join('&');
|
|
||||||
|
|
||||||
return `${path}${joinedParams ? `?${joinedParams}` : ''}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AppRoutes = {
|
export const AppRoutes = {
|
||||||
root: {
|
root: {
|
||||||
match: '/',
|
match: '/',
|
||||||
@@ -120,7 +111,7 @@ export const AppRoutes = {
|
|||||||
browse: {
|
browse: {
|
||||||
match: ':sourceId',
|
match: ':sourceId',
|
||||||
path: (sourceId: SourceType['id'], query?: string | null | undefined) =>
|
path: (sourceId: SourceType['id'], query?: string | null | undefined) =>
|
||||||
addParams(`/sources/${sourceId}`, createQueryParam(query)),
|
UrlUtil.addQueryParam(`/sources/${sourceId}`, query),
|
||||||
},
|
},
|
||||||
configure: {
|
configure: {
|
||||||
match: ':sourceId/configure',
|
match: ':sourceId/configure',
|
||||||
@@ -128,7 +119,7 @@ export const AppRoutes = {
|
|||||||
},
|
},
|
||||||
searchAll: {
|
searchAll: {
|
||||||
match: 'all/search',
|
match: 'all/search',
|
||||||
path: (query?: string | null | undefined) => addParams('/sources/all/search', createQueryParam(query)),
|
path: (query?: string | null | undefined) => UrlUtil.addQueryParam('/sources/all/search', query),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -162,7 +153,10 @@ export const AppRoutes = {
|
|||||||
library: {
|
library: {
|
||||||
match: 'library',
|
match: 'library',
|
||||||
path: (tab?: string, search?: string) =>
|
path: (tab?: string, search?: string) =>
|
||||||
addParams('/library', createParam(SearchParam.TAB, tab), createQueryParam(search)),
|
UrlUtil.addParams('/library', {
|
||||||
|
...UrlUtil.createTabParam(tab),
|
||||||
|
...UrlUtil.createQueryParam(search),
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
updates: {
|
updates: {
|
||||||
match: 'updates',
|
match: 'updates',
|
||||||
@@ -178,7 +172,10 @@ export const AppRoutes = {
|
|||||||
},
|
},
|
||||||
browse: {
|
browse: {
|
||||||
match: 'browse',
|
match: 'browse',
|
||||||
path: (tab?: BrowseTab) => addParams('/browse', createParam(SearchParam.TAB, tab)),
|
path: (tab?: BrowseTab) =>
|
||||||
|
UrlUtil.addParams('/browse', {
|
||||||
|
[SearchParam.TAB]: tab,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
migrate: {
|
migrate: {
|
||||||
match: 'migrate/source/:sourceId',
|
match: 'migrate/source/:sourceId',
|
||||||
@@ -188,7 +185,7 @@ export const AppRoutes = {
|
|||||||
search: {
|
search: {
|
||||||
match: 'manga/:mangaId/search',
|
match: 'manga/:mangaId/search',
|
||||||
path: (sourceId: SourceType['id'], mangaId: MangaIdInfo['id'], query?: string | null | undefined) =>
|
path: (sourceId: SourceType['id'], mangaId: MangaIdInfo['id'], query?: string | null | undefined) =>
|
||||||
addParams(`/migrate/source/${sourceId}/manga/${mangaId}/search`, createQueryParam(query)),
|
UrlUtil.addQueryParam(`/migrate/source/${sourceId}/manga/${mangaId}/search`, query),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export const ChapterHistoryCard = memo(({ chapter }: { chapter: ChapterHistoryLi
|
|||||||
<Box sx={{ display: 'flex', flexGrow: 1, gap: 1 }}>
|
<Box sx={{ display: 'flex', flexGrow: 1, gap: 1 }}>
|
||||||
<ChapterCardThumbnail
|
<ChapterCardThumbnail
|
||||||
mangaId={manga.id}
|
mangaId={manga.id}
|
||||||
|
sourceId={manga.sourceId}
|
||||||
mangaTitle={manga.title}
|
mangaTitle={manga.title}
|
||||||
thumbnailUrl={manga.thumbnailUrl}
|
thumbnailUrl={manga.thumbnailUrl}
|
||||||
thumbnailUrlLastFetched={manga.thumbnailUrlLastFetched}
|
thumbnailUrlLastFetched={manga.thumbnailUrlLastFetched}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export type MangaChapterCountInfo = { chapters: Pick<MangaTypeGql['chapters'], '
|
|||||||
export type MangaInLibraryInfo = Pick<MangaTypeGql, 'inLibrary'>;
|
export type MangaInLibraryInfo = Pick<MangaTypeGql, 'inLibrary'>;
|
||||||
export type MangaDownloadInfo = Pick<MangaTypeGql, 'downloadCount'> & MangaChapterCountInfo;
|
export type MangaDownloadInfo = Pick<MangaTypeGql, 'downloadCount'> & MangaChapterCountInfo;
|
||||||
export type MangaUnreadInfo = Pick<MangaTypeGql, 'unreadCount'> & MangaChapterCountInfo;
|
export type MangaUnreadInfo = Pick<MangaTypeGql, 'unreadCount'> & MangaChapterCountInfo;
|
||||||
export type MangaThumbnailInfo = Pick<MangaTypeGql, 'thumbnailUrl' | 'thumbnailUrlLastFetched'>;
|
export type MangaThumbnailInfo = Pick<MangaTypeGql, 'thumbnailUrl' | 'thumbnailUrlLastFetched' | 'sourceId'>;
|
||||||
export type MangaTrackRecordInfo = MangaIdInfo & {
|
export type MangaTrackRecordInfo = MangaIdInfo & {
|
||||||
trackRecords: { nodes: Pick<TrackRecordType, 'id' | 'trackerId'>[] };
|
trackRecords: { nodes: Pick<TrackRecordType, 'id' | 'trackerId'>[] };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import {
|
|||||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||||
import { assertIsDefined } from '@/base/Asserts.ts';
|
import { assertIsDefined } from '@/base/Asserts.ts';
|
||||||
import { Confirmation } from '@/base/AppAwaitableComponent.ts';
|
import { Confirmation } from '@/base/AppAwaitableComponent.ts';
|
||||||
|
import { UrlUtil } from '@/lib/UrlUtil.ts';
|
||||||
|
|
||||||
type MangaToMigrate = NonNullable<GetMangaToMigrateQuery['manga']>;
|
type MangaToMigrate = NonNullable<GetMangaToMigrateQuery['manga']>;
|
||||||
type MangaToMigrateTo = NonNullable<GetMangaToMigrateToFetchMutation['fetchManga']>['manga'];
|
type MangaToMigrateTo = NonNullable<GetMangaToMigrateToFetchMutation['fetchManga']>['manga'];
|
||||||
@@ -172,10 +173,12 @@ export class Mangas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static getThumbnailUrl(manga: Partial<MangaThumbnailInfo>): string {
|
static getThumbnailUrl(manga: Partial<MangaThumbnailInfo>): string {
|
||||||
const thumbnailUrl = manga.thumbnailUrl
|
const url = UrlUtil.addParams(manga.thumbnailUrl ?? '', {
|
||||||
? `${manga.thumbnailUrl}?fetchedAt=${manga.thumbnailUrlLastFetched}`
|
fetchedAt: manga.thumbnailUrlLastFetched,
|
||||||
: '';
|
sourceId: manga.sourceId,
|
||||||
return requestManager.getValidImgUrlFor(thumbnailUrl);
|
});
|
||||||
|
|
||||||
|
return requestManager.getValidImgUrlFor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDuplicateLibraryMangas(
|
static getDuplicateLibraryMangas(
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import {
|
|||||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import { TChapterReader } from '@/features/chapter/Chapter.types.ts';
|
import { TChapterReader } from '@/features/chapter/Chapter.types.ts';
|
||||||
import { ReaderChaptersStoreSlice } from '@/features/reader/stores/ReaderChaptersStore.ts';
|
import { ReaderChaptersStoreSlice } from '@/features/reader/stores/ReaderChaptersStore.ts';
|
||||||
|
import { getReaderStore } from '@/features/reader/stores/ReaderStore.ts';
|
||||||
|
import { UrlUtil } from '@/lib/UrlUtil.ts';
|
||||||
|
|
||||||
export const useReaderSetPagesState = (
|
export const useReaderSetPagesState = (
|
||||||
isCurrentChapter: boolean,
|
isCurrentChapter: boolean,
|
||||||
@@ -48,7 +50,10 @@ export const useReaderSetPagesState = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { pages: pagesFromResponse } = pagesPayload;
|
const { pages: pagesFromResponse } = pagesPayload;
|
||||||
const newPages = pagesFromResponse.length ? pagesFromResponse : [''];
|
const tmpPages = pagesFromResponse.length ? pagesFromResponse : [''];
|
||||||
|
const newPages = tmpPages.map((page) =>
|
||||||
|
UrlUtil.addParams(page, { sourceId: getReaderStore().manga?.sourceId }),
|
||||||
|
);
|
||||||
const initialReaderPageIndex = getInitialReaderPageIndex(resumeMode, lastPageRead ?? 0, newPages.length - 1);
|
const initialReaderPageIndex = getInitialReaderPageIndex(resumeMode, lastPageRead ?? 0, newPages.length - 1);
|
||||||
|
|
||||||
const didPagesChange = previousPageData.current !== pagesPayload?.pages;
|
const didPagesChange = previousPageData.current !== pagesPayload?.pages;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export const ChapterUpdateCard = memo(({ chapter }: { chapter: ChapterUpdateList
|
|||||||
<Box sx={{ display: 'flex', flexGrow: 1, gap: 1 }}>
|
<Box sx={{ display: 'flex', flexGrow: 1, gap: 1 }}>
|
||||||
<ChapterCardThumbnail
|
<ChapterCardThumbnail
|
||||||
mangaId={manga.id}
|
mangaId={manga.id}
|
||||||
|
sourceId={manga.sourceId}
|
||||||
mangaTitle={manga.title}
|
mangaTitle={manga.title}
|
||||||
thumbnailUrl={manga.thumbnailUrl}
|
thumbnailUrl={manga.thumbnailUrl}
|
||||||
thumbnailUrlLastFetched={manga.thumbnailUrlLastFetched}
|
thumbnailUrlLastFetched={manga.thumbnailUrlLastFetched}
|
||||||
|
|||||||
64
src/lib/SourceAwareQueue.ts
Normal file
64
src/lib/SourceAwareQueue.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Contributors to the Suwayomi project
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Queue, type QueuePriority } from '@/lib/Queue';
|
||||||
|
import { Sources } from '@/features/source/services/Sources.ts';
|
||||||
|
|
||||||
|
export class SourceAwareQueue {
|
||||||
|
private static readonly DEFAULT_ID = '__global__';
|
||||||
|
|
||||||
|
private readonly queueBySource = new Map<string, Queue>([
|
||||||
|
[SourceAwareQueue.DEFAULT_ID, new Queue(this.concurrencyPerSource)],
|
||||||
|
]);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly areConnectionsLimited: boolean,
|
||||||
|
private readonly concurrencyPerSource = 5,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
private getConcurrencyFor(sourceId: string | null): number {
|
||||||
|
const isLocalSource = sourceId === Sources.LOCAL_SOURCE_ID;
|
||||||
|
|
||||||
|
if (isLocalSource) {
|
||||||
|
return Number.MAX_SAFE_INTEGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.concurrencyPerSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getQueueFor(sourceId: string | null): Queue {
|
||||||
|
const finalSourceId = sourceId ?? SourceAwareQueue.DEFAULT_ID;
|
||||||
|
const queueKey = this.areConnectionsLimited ? SourceAwareQueue.DEFAULT_ID : finalSourceId;
|
||||||
|
|
||||||
|
if (!this.queueBySource.has(queueKey)) {
|
||||||
|
this.queueBySource.set(queueKey, new Queue(this.getConcurrencyFor(finalSourceId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.queueBySource.get(queueKey)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
enqueue<T>(sourceId: string | null, key: string, fn: () => PromiseLike<T> | T, priority?: QueuePriority) {
|
||||||
|
const queue = this.getQueueFor(sourceId);
|
||||||
|
|
||||||
|
return queue.enqueue(key, fn, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
isProcessing(sourceId: string | null, key: string): boolean {
|
||||||
|
const queue = this.getQueueFor(sourceId);
|
||||||
|
|
||||||
|
return queue.isProcessing(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear(): void {
|
||||||
|
for (const queue of this.queueBySource.values()) {
|
||||||
|
queue.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.queueBySource.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/lib/UrlUtil.ts
Normal file
45
src/lib/UrlUtil.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Contributors to the Suwayomi project
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { SearchParam } from '@/base/Base.types.ts';
|
||||||
|
|
||||||
|
export class UrlUtil {
|
||||||
|
static createParams(params: Record<SearchParam | string, string | null | undefined>): URLSearchParams {
|
||||||
|
const paramEntries = Object.entries(params).filter(
|
||||||
|
(entry): entry is [string, string] => typeof entry[1] === 'string',
|
||||||
|
);
|
||||||
|
|
||||||
|
return new URLSearchParams(paramEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
static createTabParam(tab: string | null | undefined): { [SearchParam.TAB]: string } {
|
||||||
|
return { ...this.createParams({ [SearchParam.TAB]: tab }).entries() } as unknown as {
|
||||||
|
[SearchParam.TAB]: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static createQueryParam(query: string | null | undefined): { [SearchParam.QUERY]: string } {
|
||||||
|
return { ...this.createParams({ [SearchParam.QUERY]: query }).entries() } as unknown as {
|
||||||
|
[SearchParam.QUERY]: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static addParams(path: string, params: Record<SearchParam | string, string | null | undefined>): string {
|
||||||
|
const urlParams = this.createParams(params).toString();
|
||||||
|
|
||||||
|
if (urlParams) {
|
||||||
|
return `${path}?${urlParams}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static addQueryParam(path: string, query: string | null | undefined): string {
|
||||||
|
return this.addParams(path, this.createQueryParam(query));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -315,7 +315,8 @@ import { RESET_WEBUI_UPDATE_STATUS, UPDATE_WEBUI } from '@/lib/graphql/mutations
|
|||||||
import { WEBUI_UPDATE_SUBSCRIPTION } from '@/lib/graphql/subscriptions/ServerInfoSubscription.ts';
|
import { WEBUI_UPDATE_SUBSCRIPTION } from '@/lib/graphql/subscriptions/ServerInfoSubscription.ts';
|
||||||
import { GET_DOWNLOAD_STATUS } from '@/lib/graphql/queries/DownloaderQuery.ts';
|
import { GET_DOWNLOAD_STATUS } from '@/lib/graphql/queries/DownloaderQuery.ts';
|
||||||
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
||||||
import { Queue, QueuePriority } from '@/lib/Queue.ts';
|
import { QueuePriority } from '@/lib/Queue.ts';
|
||||||
|
import { SourceAwareQueue } from '@/lib/SourceAwareQueue.ts';
|
||||||
import { TRACKER_SEARCH } from '@/lib/graphql/queries/TrackerQuery.ts';
|
import { TRACKER_SEARCH } from '@/lib/graphql/queries/TrackerQuery.ts';
|
||||||
import {
|
import {
|
||||||
TRACKER_BIND,
|
TRACKER_BIND,
|
||||||
@@ -460,14 +461,29 @@ export class RequestManager {
|
|||||||
|
|
||||||
private readonly cache = new CustomCache();
|
private readonly cache = new CustomCache();
|
||||||
|
|
||||||
private readonly imageQueue = new Queue(5);
|
private readonly imageQueue: SourceAwareQueue;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
const isHttps = typeof window !== 'undefined' && window.location.protocol === 'https:';
|
||||||
|
const isHttp2 = isHttps && this.detectHttp2();
|
||||||
|
|
||||||
|
this.imageQueue = new SourceAwareQueue(isHttp2, 5);
|
||||||
|
|
||||||
BaseClient.setTokenRefreshCompleteCallback(() => {
|
BaseClient.setTokenRefreshCompleteCallback(() => {
|
||||||
this.processQueues();
|
this.processQueues();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private detectHttp2(): boolean {
|
||||||
|
const entries = performance.getEntriesByType('navigation') as PerformanceNavigationTiming[];
|
||||||
|
|
||||||
|
if (!entries.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['h2', 'h3'].includes(entries[0].nextHopProtocol);
|
||||||
|
}
|
||||||
|
|
||||||
public getClient(): IRestClient {
|
public getClient(): IRestClient {
|
||||||
return this.restClient;
|
return this.restClient;
|
||||||
}
|
}
|
||||||
@@ -896,8 +912,8 @@ export class RequestManager {
|
|||||||
* will just cause new source image requests to be sent to the server, which then will cause the server
|
* will just cause new source image requests to be sent to the server, which then will cause the server
|
||||||
* to become really slow for image requests to the same source
|
* to become really slow for image requests to the same source
|
||||||
*/
|
*/
|
||||||
private abortImageRequest(key: string, abort: () => void): void {
|
private abortImageRequest(key: string, sourceId: string | null, abort: () => void): void {
|
||||||
if (this.imageQueue.isProcessing(key)) {
|
if (this.imageQueue.isProcessing(sourceId, key)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -936,12 +952,23 @@ export class RequestManager {
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getSourceIdFromUrl(url: string): string | null {
|
||||||
|
try {
|
||||||
|
console.log('asdf', new URL(url).searchParams.get('sourceId'));
|
||||||
|
return new URL(url).searchParams.get('sourceId');
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async maybeEnqueueImageRequest<T>(
|
private async maybeEnqueueImageRequest<T>(
|
||||||
url: string,
|
url: string,
|
||||||
request: () => Promise<T>,
|
request: () => Promise<T>,
|
||||||
priority?: QueuePriority,
|
priority?: QueuePriority,
|
||||||
ignoreQueue?: boolean,
|
ignoreQueue?: boolean,
|
||||||
): Promise<ReturnType<typeof this.imageQueue.enqueue<T>> & { fromCache?: boolean }> {
|
): Promise<ReturnType<typeof this.imageQueue.enqueue<T>> & { fromCache?: boolean }> {
|
||||||
|
const sourceId = this.getSourceIdFromUrl(url);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const isCached = await ImageCache.has(url);
|
const isCached = await ImageCache.has(url);
|
||||||
if (!!ignoreQueue || isCached) {
|
if (!!ignoreQueue || isCached) {
|
||||||
@@ -952,9 +979,9 @@ export class RequestManager {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.imageQueue.enqueue(url, request, priority);
|
return this.imageQueue.enqueue(sourceId, url, request, priority);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return this.imageQueue.enqueue(url, request, priority);
|
return this.imageQueue.enqueue(sourceId, url, request, priority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1009,7 +1036,8 @@ export class RequestManager {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
response,
|
response,
|
||||||
abortRequest: (reason?: any) => this.abortImageRequest(key, () => abortRequest(reason)),
|
abortRequest: (reason?: any) =>
|
||||||
|
this.abortImageRequest(key, this.getSourceIdFromUrl(url), () => abortRequest(reason)),
|
||||||
cleanup: () => {},
|
cleanup: () => {},
|
||||||
fromCache: !!fromCache,
|
fromCache: !!fromCache,
|
||||||
};
|
};
|
||||||
@@ -1065,7 +1093,8 @@ export class RequestManager {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
response,
|
response,
|
||||||
abortRequest: (reason?: any) => this.abortImageRequest(key, () => abortRequest(reason)),
|
abortRequest: (reason?: any) =>
|
||||||
|
this.abortImageRequest(key, this.getSourceIdFromUrl(url), () => abortRequest(reason)),
|
||||||
cleanup: () => URL.revokeObjectURL(objectUrl),
|
cleanup: () => URL.revokeObjectURL(objectUrl),
|
||||||
fromCache: !!fromCache,
|
fromCache: !!fromCache,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user