Update to server download subscription changes
This commit is contained in:
@@ -8,27 +8,52 @@
|
|||||||
|
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
|
const DOWNLOAD_TYPE_FIELDS = gql`
|
||||||
|
fragment DOWNLOAD_TYPE_FIELDS on DownloadType {
|
||||||
|
chapter {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
sourceOrder
|
||||||
|
isDownloaded
|
||||||
|
}
|
||||||
|
|
||||||
|
manga {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
downloadCount
|
||||||
|
}
|
||||||
|
|
||||||
|
progress
|
||||||
|
state
|
||||||
|
tries
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const DOWNLOAD_STATUS_FIELDS = gql`
|
export const DOWNLOAD_STATUS_FIELDS = gql`
|
||||||
|
${DOWNLOAD_TYPE_FIELDS}
|
||||||
|
|
||||||
fragment DOWNLOAD_STATUS_FIELDS on DownloadStatus {
|
fragment DOWNLOAD_STATUS_FIELDS on DownloadStatus {
|
||||||
state
|
state
|
||||||
|
|
||||||
queue {
|
queue {
|
||||||
chapter {
|
...DOWNLOAD_TYPE_FIELDS
|
||||||
id
|
}
|
||||||
name
|
}
|
||||||
sourceOrder
|
`;
|
||||||
isDownloaded
|
|
||||||
}
|
export const DOWNLOAD_UPDATES_FIELDS = gql`
|
||||||
|
${DOWNLOAD_TYPE_FIELDS}
|
||||||
manga {
|
|
||||||
id
|
fragment DOWNLOAD_UPDATES_FIELDS on DownloadUpdates {
|
||||||
title
|
state
|
||||||
downloadCount
|
omittedUpdates
|
||||||
}
|
|
||||||
|
updates {
|
||||||
progress
|
type
|
||||||
state
|
download {
|
||||||
tries
|
...DOWNLOAD_TYPE_FIELDS
|
||||||
|
position
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -214,14 +214,27 @@ export type DownloadStatusFieldPolicy = {
|
|||||||
queue?: FieldPolicy<any> | FieldReadFunction<any>,
|
queue?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
state?: FieldPolicy<any> | FieldReadFunction<any>
|
state?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
};
|
};
|
||||||
export type DownloadTypeKeySpecifier = ('chapter' | 'manga' | 'progress' | 'state' | 'tries' | DownloadTypeKeySpecifier)[];
|
export type DownloadTypeKeySpecifier = ('chapter' | 'manga' | 'position' | 'progress' | 'state' | 'tries' | DownloadTypeKeySpecifier)[];
|
||||||
export type DownloadTypeFieldPolicy = {
|
export type DownloadTypeFieldPolicy = {
|
||||||
chapter?: FieldPolicy<any> | FieldReadFunction<any>,
|
chapter?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
manga?: FieldPolicy<any> | FieldReadFunction<any>,
|
manga?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
position?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
progress?: FieldPolicy<any> | FieldReadFunction<any>,
|
progress?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
state?: FieldPolicy<any> | FieldReadFunction<any>,
|
state?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
tries?: FieldPolicy<any> | FieldReadFunction<any>
|
tries?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
};
|
};
|
||||||
|
export type DownloadUpdateKeySpecifier = ('download' | 'type' | DownloadUpdateKeySpecifier)[];
|
||||||
|
export type DownloadUpdateFieldPolicy = {
|
||||||
|
download?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
type?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
|
};
|
||||||
|
export type DownloadUpdatesKeySpecifier = ('initial' | 'omittedUpdates' | 'state' | 'updates' | DownloadUpdatesKeySpecifier)[];
|
||||||
|
export type DownloadUpdatesFieldPolicy = {
|
||||||
|
initial?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
omittedUpdates?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
state?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
updates?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
|
};
|
||||||
export type EdgeKeySpecifier = ('cursor' | 'node' | EdgeKeySpecifier)[];
|
export type EdgeKeySpecifier = ('cursor' | 'node' | EdgeKeySpecifier)[];
|
||||||
export type EdgeFieldPolicy = {
|
export type EdgeFieldPolicy = {
|
||||||
cursor?: FieldPolicy<any> | FieldReadFunction<any>,
|
cursor?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
@@ -822,9 +835,10 @@ export type StopDownloaderPayloadFieldPolicy = {
|
|||||||
clientMutationId?: FieldPolicy<any> | FieldReadFunction<any>,
|
clientMutationId?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
downloadStatus?: FieldPolicy<any> | FieldReadFunction<any>
|
downloadStatus?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
};
|
};
|
||||||
export type SubscriptionKeySpecifier = ('downloadChanged' | 'updateStatusChanged' | 'webUIUpdateStatusChange' | SubscriptionKeySpecifier)[];
|
export type SubscriptionKeySpecifier = ('downloadChanged' | 'downloadStatusChanged' | 'updateStatusChanged' | 'webUIUpdateStatusChange' | SubscriptionKeySpecifier)[];
|
||||||
export type SubscriptionFieldPolicy = {
|
export type SubscriptionFieldPolicy = {
|
||||||
downloadChanged?: FieldPolicy<any> | FieldReadFunction<any>,
|
downloadChanged?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
downloadStatusChanged?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
updateStatusChanged?: FieldPolicy<any> | FieldReadFunction<any>,
|
updateStatusChanged?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
webUIUpdateStatusChange?: FieldPolicy<any> | FieldReadFunction<any>
|
webUIUpdateStatusChange?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
};
|
};
|
||||||
@@ -1201,6 +1215,14 @@ export type StrictTypedTypePolicies = {
|
|||||||
keyFields?: false | DownloadTypeKeySpecifier | (() => undefined | DownloadTypeKeySpecifier),
|
keyFields?: false | DownloadTypeKeySpecifier | (() => undefined | DownloadTypeKeySpecifier),
|
||||||
fields?: DownloadTypeFieldPolicy,
|
fields?: DownloadTypeFieldPolicy,
|
||||||
},
|
},
|
||||||
|
DownloadUpdate?: Omit<TypePolicy, "fields" | "keyFields"> & {
|
||||||
|
keyFields?: false | DownloadUpdateKeySpecifier | (() => undefined | DownloadUpdateKeySpecifier),
|
||||||
|
fields?: DownloadUpdateFieldPolicy,
|
||||||
|
},
|
||||||
|
DownloadUpdates?: Omit<TypePolicy, "fields" | "keyFields"> & {
|
||||||
|
keyFields?: false | DownloadUpdatesKeySpecifier | (() => undefined | DownloadUpdatesKeySpecifier),
|
||||||
|
fields?: DownloadUpdatesFieldPolicy,
|
||||||
|
},
|
||||||
Edge?: Omit<TypePolicy, "fields" | "keyFields"> & {
|
Edge?: Omit<TypePolicy, "fields" | "keyFields"> & {
|
||||||
keyFields?: false | EdgeKeySpecifier | (() => undefined | EdgeKeySpecifier),
|
keyFields?: false | EdgeKeySpecifier | (() => undefined | EdgeKeySpecifier),
|
||||||
fields?: EdgeFieldPolicy,
|
fields?: EdgeFieldPolicy,
|
||||||
|
|||||||
@@ -467,6 +467,11 @@ export type DoubleFilterInput = {
|
|||||||
notIn?: InputMaybe<Array<Scalars['Float']['input']>>;
|
notIn?: InputMaybe<Array<Scalars['Float']['input']>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type DownloadChangedInput = {
|
||||||
|
/** Sets a max number of updates that can be contained in a download update message.Everything above this limit will be omitted and the "downloadStatus" should be re-fetched via the corresponding query. Due to the graphql subscription execution strategy not supporting batching for data loaders, the data loaders run into the n+1 problem, which can cause the server to get unresponsive until the status update has been handled. This is an issue e.g. when mass en- or dequeuing downloads. */
|
||||||
|
maxUpdates?: InputMaybe<Scalars['Int']['input']>;
|
||||||
|
};
|
||||||
|
|
||||||
export type DownloadEdge = Edge & {
|
export type DownloadEdge = Edge & {
|
||||||
__typename?: 'DownloadEdge';
|
__typename?: 'DownloadEdge';
|
||||||
cursor: Scalars['Cursor']['output'];
|
cursor: Scalars['Cursor']['output'];
|
||||||
@@ -498,11 +503,37 @@ export type DownloadType = {
|
|||||||
__typename?: 'DownloadType';
|
__typename?: 'DownloadType';
|
||||||
chapter: ChapterType;
|
chapter: ChapterType;
|
||||||
manga: MangaType;
|
manga: MangaType;
|
||||||
|
position: Scalars['Int']['output'];
|
||||||
progress: Scalars['Float']['output'];
|
progress: Scalars['Float']['output'];
|
||||||
state: DownloadState;
|
state: DownloadState;
|
||||||
tries: Scalars['Int']['output'];
|
tries: Scalars['Int']['output'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type DownloadUpdate = {
|
||||||
|
__typename?: 'DownloadUpdate';
|
||||||
|
download: DownloadType;
|
||||||
|
type: DownloadUpdateType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum DownloadUpdateType {
|
||||||
|
Dequeued = 'DEQUEUED',
|
||||||
|
Error = 'ERROR',
|
||||||
|
Finished = 'FINISHED',
|
||||||
|
Position = 'POSITION',
|
||||||
|
Progress = 'PROGRESS',
|
||||||
|
Queued = 'QUEUED'
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DownloadUpdates = {
|
||||||
|
__typename?: 'DownloadUpdates';
|
||||||
|
/** The current download queue at the time of sending initial message. Is null for all following messages */
|
||||||
|
initial?: Maybe<Array<DownloadType>>;
|
||||||
|
/** Indicates whether updates have been omitted based on the "maxUpdates" subscription variable. In case updates have been omitted, the "downloadStatus" query should be re-fetched. */
|
||||||
|
omittedUpdates: Scalars['Boolean']['output'];
|
||||||
|
state: DownloaderState;
|
||||||
|
updates: Array<DownloadUpdate>;
|
||||||
|
};
|
||||||
|
|
||||||
export enum DownloaderState {
|
export enum DownloaderState {
|
||||||
Started = 'STARTED',
|
Started = 'STARTED',
|
||||||
Stopped = 'STOPPED'
|
Stopped = 'STOPPED'
|
||||||
@@ -1415,7 +1446,7 @@ export type MutationUpdateWebUiArgs = {
|
|||||||
input: WebUiUpdateInput;
|
input: WebUiUpdateInput;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Node = CategoryMetaType | CategoryType | ChapterMetaType | ChapterType | DownloadType | ExtensionType | GlobalMetaType | MangaMetaType | MangaType | PartialSettingsType | SettingsType | SourceMetaType | SourceType | TrackRecordType | TrackerType;
|
export type Node = CategoryMetaType | CategoryType | ChapterMetaType | ChapterType | DownloadType | DownloadUpdate | ExtensionType | GlobalMetaType | MangaMetaType | MangaType | PartialSettingsType | SettingsType | SourceMetaType | SourceType | TrackRecordType | TrackerType;
|
||||||
|
|
||||||
export type NodeList = {
|
export type NodeList = {
|
||||||
/** A list of edges which contains the [T] and cursor to aid in pagination. */
|
/** A list of edges which contains the [T] and cursor to aid in pagination. */
|
||||||
@@ -2177,11 +2208,18 @@ export type StringFilterInput = {
|
|||||||
|
|
||||||
export type Subscription = {
|
export type Subscription = {
|
||||||
__typename?: 'Subscription';
|
__typename?: 'Subscription';
|
||||||
|
/** @deprecated Replaced width downloadStatusChanged, replace with downloadStatusChanged(input) */
|
||||||
downloadChanged: DownloadStatus;
|
downloadChanged: DownloadStatus;
|
||||||
|
downloadStatusChanged: DownloadUpdates;
|
||||||
updateStatusChanged: UpdateStatus;
|
updateStatusChanged: UpdateStatus;
|
||||||
webUIUpdateStatusChange: WebUiUpdateStatus;
|
webUIUpdateStatusChange: WebUiUpdateStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type SubscriptionDownloadStatusChangedArgs = {
|
||||||
|
input: DownloadChangedInput;
|
||||||
|
};
|
||||||
|
|
||||||
export type SwitchPreference = {
|
export type SwitchPreference = {
|
||||||
__typename?: 'SwitchPreference';
|
__typename?: 'SwitchPreference';
|
||||||
currentValue?: Maybe<Scalars['Boolean']['output']>;
|
currentValue?: Maybe<Scalars['Boolean']['output']>;
|
||||||
@@ -2731,8 +2769,12 @@ export type ChapterListFieldsFragment = { __typename?: 'ChapterType', fetchedAt:
|
|||||||
|
|
||||||
export type ChapterUpdateListFieldsFragment = { __typename?: 'ChapterType', fetchedAt: string, uploadDate: string, id: number, name: string, mangaId: number, scanlator?: string | null, realUrl?: string | null, sourceOrder: number, chapterNumber: number, isRead: boolean, isDownloaded: boolean, isBookmarked: boolean, manga: { __typename?: 'MangaType', id: number, title: string, thumbnailUrl?: string | null, thumbnailUrlLastFetched?: string | null, inLibrary: boolean, initialized: boolean, sourceId: string } };
|
export type ChapterUpdateListFieldsFragment = { __typename?: 'ChapterType', fetchedAt: string, uploadDate: string, id: number, name: string, mangaId: number, scanlator?: string | null, realUrl?: string | null, sourceOrder: number, chapterNumber: number, isRead: boolean, isDownloaded: boolean, isBookmarked: boolean, manga: { __typename?: 'MangaType', id: number, title: string, thumbnailUrl?: string | null, thumbnailUrlLastFetched?: string | null, inLibrary: boolean, initialized: boolean, sourceId: string } };
|
||||||
|
|
||||||
|
export type DownloadTypeFieldsFragment = { __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', id: number, name: string, sourceOrder: number, isDownloaded: boolean }, manga: { __typename?: 'MangaType', id: number, title: string, downloadCount: number } };
|
||||||
|
|
||||||
export type DownloadStatusFieldsFragment = { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', id: number, name: string, sourceOrder: number, isDownloaded: boolean }, manga: { __typename?: 'MangaType', id: number, title: string, downloadCount: number } }> };
|
export type DownloadStatusFieldsFragment = { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', id: number, name: string, sourceOrder: number, isDownloaded: boolean }, manga: { __typename?: 'MangaType', id: number, title: string, downloadCount: number } }> };
|
||||||
|
|
||||||
|
export type DownloadUpdatesFieldsFragment = { __typename?: 'DownloadUpdates', state: DownloaderState, omittedUpdates: boolean, updates: Array<{ __typename?: 'DownloadUpdate', type: DownloadUpdateType, download: { __typename?: 'DownloadType', position: number, progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', id: number, name: string, sourceOrder: number, isDownloaded: boolean }, manga: { __typename?: 'MangaType', id: number, title: string, downloadCount: number } } }> };
|
||||||
|
|
||||||
export type ExtensionListFieldsFragment = { __typename?: 'ExtensionType', pkgName: string, name: string, lang: string, versionCode: number, versionName: string, iconUrl: string, repo?: string | null, isNsfw: boolean, isInstalled: boolean, isObsolete: boolean, hasUpdate: boolean };
|
export type ExtensionListFieldsFragment = { __typename?: 'ExtensionType', pkgName: string, name: string, lang: string, versionCode: number, versionName: string, iconUrl: string, repo?: string | null, isNsfw: boolean, isInstalled: boolean, isObsolete: boolean, hasUpdate: boolean };
|
||||||
|
|
||||||
export type PageInfoFragment = { __typename?: 'PageInfo', endCursor?: string | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | null };
|
export type PageInfoFragment = { __typename?: 'PageInfo', endCursor?: string | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | null };
|
||||||
@@ -3554,10 +3596,12 @@ export type GetLastUpdateTimestampQueryVariables = Exact<{ [key: string]: never;
|
|||||||
|
|
||||||
export type GetLastUpdateTimestampQuery = { __typename?: 'Query', lastUpdateTimestamp: { __typename?: 'LastUpdateTimestampPayload', timestamp: string } };
|
export type GetLastUpdateTimestampQuery = { __typename?: 'Query', lastUpdateTimestamp: { __typename?: 'LastUpdateTimestampPayload', timestamp: string } };
|
||||||
|
|
||||||
export type DownloadStatusSubscriptionVariables = Exact<{ [key: string]: never; }>;
|
export type DownloadStatusSubscriptionVariables = Exact<{
|
||||||
|
input: DownloadChangedInput;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type DownloadStatusSubscription = { __typename?: 'Subscription', downloadChanged: { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', id: number, name: string, sourceOrder: number, isDownloaded: boolean }, manga: { __typename?: 'MangaType', id: number, title: string, downloadCount: number } }> } };
|
export type DownloadStatusSubscription = { __typename?: 'Subscription', downloadStatusChanged: { __typename?: 'DownloadUpdates', state: DownloaderState, omittedUpdates: boolean, updates: Array<{ __typename?: 'DownloadUpdate', type: DownloadUpdateType, download: { __typename?: 'DownloadType', position: number, progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', id: number, name: string, sourceOrder: number, isDownloaded: boolean }, manga: { __typename?: 'MangaType', id: number, title: string, downloadCount: number } } }> } };
|
||||||
|
|
||||||
export type WebuiUpdateSubscriptionVariables = Exact<{ [key: string]: never; }>;
|
export type WebuiUpdateSubscriptionVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
import { DOWNLOAD_STATUS_FIELDS } from '@/lib/graphql/fragments/DownloadFragments.ts';
|
import { DOWNLOAD_UPDATES_FIELDS } from '@/lib/graphql/fragments/DownloadFragments.ts';
|
||||||
|
|
||||||
export const DOWNLOAD_STATUS_SUBSCRIPTION = gql`
|
export const DOWNLOAD_STATUS_SUBSCRIPTION = gql`
|
||||||
${DOWNLOAD_STATUS_FIELDS}
|
${DOWNLOAD_UPDATES_FIELDS}
|
||||||
|
|
||||||
subscription DOWNLOAD_STATUS_SUBSCRIPTION {
|
subscription DOWNLOAD_STATUS_SUBSCRIPTION($input: DownloadChangedInput!) {
|
||||||
downloadChanged {
|
downloadStatusChanged(input: $input) {
|
||||||
...DOWNLOAD_STATUS_FIELDS
|
...DOWNLOAD_UPDATES_FIELDS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ import {
|
|||||||
DequeueChapterDownloadsMutationVariables,
|
DequeueChapterDownloadsMutationVariables,
|
||||||
DownloadStatusSubscription,
|
DownloadStatusSubscription,
|
||||||
DownloadStatusSubscriptionVariables,
|
DownloadStatusSubscriptionVariables,
|
||||||
|
DownloadUpdateType,
|
||||||
EnqueueChapterDownloadMutation,
|
EnqueueChapterDownloadMutation,
|
||||||
EnqueueChapterDownloadMutationVariables,
|
EnqueueChapterDownloadMutationVariables,
|
||||||
EnqueueChapterDownloadsMutation,
|
EnqueueChapterDownloadsMutation,
|
||||||
@@ -2777,10 +2778,11 @@ export class RequestManager {
|
|||||||
const wrappedMutate = (mutationOptions: Parameters<typeof mutate>[0]) => {
|
const wrappedMutate = (mutationOptions: Parameters<typeof mutate>[0]) => {
|
||||||
const variables = mutationOptions?.variables?.input;
|
const variables = mutationOptions?.variables?.input;
|
||||||
const cachedDownloadStatus = this.graphQLClient.client.readFragment<
|
const cachedDownloadStatus = this.graphQLClient.client.readFragment<
|
||||||
DownloadStatusSubscription['downloadChanged']
|
GetDownloadStatusQuery['downloadStatus']
|
||||||
>({
|
>({
|
||||||
id: 'DownloadStatus:{}',
|
id: 'DownloadStatus:{}',
|
||||||
fragment: DOWNLOAD_STATUS_FIELDS,
|
fragment: DOWNLOAD_STATUS_FIELDS,
|
||||||
|
fragmentName: 'DOWNLOAD_STATUS_FIELDS',
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!variables) {
|
if (!variables) {
|
||||||
@@ -2933,7 +2935,84 @@ export class RequestManager {
|
|||||||
public useDownloadSubscription(
|
public useDownloadSubscription(
|
||||||
options?: SubscriptionHookOptions<DownloadStatusSubscription, DownloadStatusSubscriptionVariables>,
|
options?: SubscriptionHookOptions<DownloadStatusSubscription, DownloadStatusSubscriptionVariables>,
|
||||||
): SubscriptionResult<DownloadStatusSubscription, DownloadStatusSubscriptionVariables> {
|
): SubscriptionResult<DownloadStatusSubscription, DownloadStatusSubscriptionVariables> {
|
||||||
return this.doRequest(GQLMethod.USE_SUBSCRIPTION, DOWNLOAD_STATUS_SUBSCRIPTION, {}, options);
|
return this.doRequest(
|
||||||
|
GQLMethod.USE_SUBSCRIPTION,
|
||||||
|
DOWNLOAD_STATUS_SUBSCRIPTION,
|
||||||
|
{ input: { maxUpdates: 30 } },
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
onData: (onDataOptions) => {
|
||||||
|
const downloadChanged = onDataOptions.data.data?.downloadStatusChanged;
|
||||||
|
|
||||||
|
const { cache } = this.graphQLClient.client;
|
||||||
|
|
||||||
|
if (downloadChanged?.omittedUpdates) {
|
||||||
|
cache.evict({ broadcast: true, fieldName: 'downloadStatus' });
|
||||||
|
cache.evict({ broadcast: true, id: 'DownloadStatus:{}' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadsToRemove =
|
||||||
|
downloadChanged?.updates
|
||||||
|
.filter((update) =>
|
||||||
|
[
|
||||||
|
DownloadUpdateType.Dequeued,
|
||||||
|
DownloadUpdateType.Finished,
|
||||||
|
DownloadUpdateType.Position,
|
||||||
|
].includes(update.type),
|
||||||
|
)
|
||||||
|
.map((update) => update.download.chapter.id) ?? [];
|
||||||
|
const downloadsToAdd =
|
||||||
|
downloadChanged?.updates
|
||||||
|
.filter((update) => update.type === DownloadUpdateType.Queued)
|
||||||
|
.map((update) => update.download) ?? [];
|
||||||
|
const downloadsToReorder =
|
||||||
|
downloadChanged?.updates
|
||||||
|
.filter((update) => update.type === DownloadUpdateType.Position)
|
||||||
|
.map((update) => update.download) ?? [];
|
||||||
|
|
||||||
|
cache.updateQuery<GetDownloadStatusQuery, GetDownloadStatusQueryVariables>(
|
||||||
|
{
|
||||||
|
query: GET_DOWNLOAD_STATUS,
|
||||||
|
variables: {},
|
||||||
|
},
|
||||||
|
(data) => {
|
||||||
|
if (!data) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const queueWithAddedDownloads = [...data.downloadStatus.queue, ...downloadsToAdd];
|
||||||
|
const queueWithoutRemovedDownloads = !downloadsToRemove.length
|
||||||
|
? queueWithAddedDownloads
|
||||||
|
: queueWithAddedDownloads.filter(
|
||||||
|
(download) => !downloadsToRemove.includes(download.chapter.id),
|
||||||
|
);
|
||||||
|
|
||||||
|
const queueWithReorderedDownloads = !downloadsToReorder.length
|
||||||
|
? queueWithoutRemovedDownloads
|
||||||
|
: (() => {
|
||||||
|
const tmpQueue = [...queueWithoutRemovedDownloads];
|
||||||
|
|
||||||
|
downloadsToReorder.forEach((download) => {
|
||||||
|
tmpQueue.splice(download.position, 0, download);
|
||||||
|
});
|
||||||
|
|
||||||
|
return tmpQueue;
|
||||||
|
})();
|
||||||
|
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
downloadStatus: {
|
||||||
|
...data.downloadStatus,
|
||||||
|
state: downloadChanged?.state ?? data.downloadStatus.state,
|
||||||
|
queue: queueWithReorderedDownloads,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public useUpdaterSubscription(
|
public useUpdaterSubscription(
|
||||||
|
|||||||
@@ -87,11 +87,16 @@ const typePolicies: StrictTypedTypePolicies = {
|
|||||||
key: args?.key,
|
key: args?.key,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
downloadStatus(_, { toReference }) {
|
downloadStatus: {
|
||||||
return toReference({
|
read(_, { toReference }) {
|
||||||
__typename: 'DownloadStatus',
|
return toReference({
|
||||||
key: {},
|
__typename: 'DownloadStatus',
|
||||||
});
|
key: {},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
merge(_, incoming) {
|
||||||
|
return incoming;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
getWebUIUpdateStatus(_, { toReference }) {
|
getWebUIUpdateStatus(_, { toReference }) {
|
||||||
return toReference({
|
return toReference({
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export const DownloadStateIndicator = ({ download }: { download: ChapterDownload
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
{isDownloading && `${Math.round(download.progress * 100)}%`}
|
{(isDownloading || isPartiallyDownloaded) && `${Math.round(download.progress * 100)}%`}
|
||||||
{!isDownloading &&
|
{!isDownloading &&
|
||||||
!isPartiallyDownloaded &&
|
!isPartiallyDownloaded &&
|
||||||
t(DOWNLOAD_STATE_TO_TRANSLATION_KEY_MAP[download.state])}
|
t(DOWNLOAD_STATE_TO_TRANSLATION_KEY_MAP[download.state])}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import { NavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.t
|
|||||||
import { LoadingPlaceholder } from '@/modules/core/components/placeholder/LoadingPlaceholder.tsx';
|
import { LoadingPlaceholder } from '@/modules/core/components/placeholder/LoadingPlaceholder.tsx';
|
||||||
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
||||||
import { ChapterDownloadStatus, ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts';
|
import { ChapterDownloadStatus, ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts';
|
||||||
import { DownloadState } from '@/lib/graphql/generated/graphql.ts';
|
import { DownloaderState, DownloadState } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
const HeightPreservingItem = ({ children, ...props }: BoxProps) => (
|
const HeightPreservingItem = ({ children, ...props }: BoxProps) => (
|
||||||
// the height is necessary to prevent the item container from collapsing, which confuses Virtuoso measurements
|
// the height is necessary to prevent the item container from collapsing, which confuses Virtuoso measurements
|
||||||
@@ -145,7 +145,7 @@ export const DownloadQueue: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const toggleQueueStatus = () => {
|
const toggleQueueStatus = () => {
|
||||||
if (status === 'STOPPED') {
|
if (status === DownloaderState.Stopped) {
|
||||||
requestManager.startDownloads();
|
requestManager.startDownloads();
|
||||||
} else {
|
} else {
|
||||||
requestManager.stopDownloads();
|
requestManager.stopDownloads();
|
||||||
@@ -162,9 +162,9 @@ export const DownloadQueue: React.FC = () => {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip title={t(status === 'STOPPED' ? 'global.button.start' : 'global.button.stop')}>
|
<Tooltip title={t(status === DownloaderState.Started ? 'global.button.start' : 'global.button.stop')}>
|
||||||
<IconButton onClick={toggleQueueStatus} size="large" disabled={isQueueEmpty} color="inherit">
|
<IconButton onClick={toggleQueueStatus} size="large" disabled={isQueueEmpty} color="inherit">
|
||||||
{status === 'STOPPED' ? <PlayArrowIcon /> : <PauseIcon />}
|
{status === DownloaderState.Stopped ? <PlayArrowIcon /> : <PauseIcon />}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</>,
|
</>,
|
||||||
@@ -220,7 +220,7 @@ export const DownloadQueue: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = async (chapter: ChapterIdInfo) => {
|
const handleDelete = async (chapter: ChapterIdInfo) => {
|
||||||
const isRunning = status === 'STARTED';
|
const isRunning = status === DownloaderState.Started;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isRunning) {
|
if (isRunning) {
|
||||||
@@ -287,9 +287,9 @@ export const DownloadQueue: React.FC = () => {
|
|||||||
components={{
|
components={{
|
||||||
Item: HeightPreservingItem,
|
Item: HeightPreservingItem,
|
||||||
}}
|
}}
|
||||||
computeItemKey={(_, item) => item.manga.id}
|
computeItemKey={(_, item) => item.chapter.id}
|
||||||
itemContent={(index, item) => (
|
itemContent={(index, item) => (
|
||||||
<Draggable draggableId={`${item.manga.id}-${item.chapter.sourceOrder}`} index={index}>
|
<Draggable draggableId={`${item.chapter.id}`} index={index}>
|
||||||
{(draggableProvided) => (
|
{(draggableProvided) => (
|
||||||
<DownloadChapterItem
|
<DownloadChapterItem
|
||||||
provided={draggableProvided}
|
provided={draggableProvided}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"uiVersion": "PREVIEW",
|
"uiVersion": "PREVIEW",
|
||||||
"serverVersion": "r1566"
|
"serverVersion": "r1611"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "v1.1.0",
|
"tag": "v1.1.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user