diff --git a/src/lib/requests/RequestManager.ts b/src/lib/requests/RequestManager.ts index b7dc367e..d4f75862 100644 --- a/src/lib/requests/RequestManager.ts +++ b/src/lib/requests/RequestManager.ts @@ -61,8 +61,6 @@ import { FilterChangeInput, GetAboutQuery, GetAboutQueryVariables, - GetExtensionsFetchMutation, - GetExtensionsFetchMutationVariables, GetCategoriesQuery, GetCategoriesQueryVariables, GetCategoryMangasQuery, @@ -71,6 +69,8 @@ import { GetChapterPagesFetchMutationVariables, GetChaptersQuery, GetChaptersQueryVariables, + GetExtensionsFetchMutation, + GetExtensionsFetchMutationVariables, GetExtensionsQuery, GetExtensionsQueryVariables, GetGlobalMetadatasQuery, @@ -1407,17 +1407,70 @@ export class RequestManager { ); } - public reorderCategory( - id: number, - position: number, - options?: MutationOptions, - ): AbortableApolloMutationResponse { - return this.doRequest( - GQLMethod.MUTATION, + public useReorderCategory( + options?: MutationHookOptions, + ): AbortableApolloUseMutationResponse { + const [mutate, result] = this.doRequest( + GQLMethod.USE_MUTATION, UPDATE_CATEGORY_ORDER, - { input: { id, position } }, - { refetchQueries: [GET_CATEGORIES], ...options }, + undefined, + options, ); + + const wrappedMutate = (mutateOptions: Parameters[0]) => { + const variables = mutateOptions?.variables?.input; + const cachedCategories = this.graphQLClient.client.readQuery< + GetCategoriesQuery, + GetCategoriesQueryVariables + >({ + query: GET_CATEGORIES, + variables: { orderBy: CategoryOrderBy.Order }, + })?.categories.nodes; + + if (!variables) { + throw new Error('useReorderCategory: no variables passed'); + } + + if (!cachedCategories) { + throw new Error('useReorderCategory: there are no cached results'); + } + + const movedIndex = cachedCategories.findIndex((category) => category.id === variables.id); + const newData = [...cachedCategories.map((category) => ({ ...category }))]; + const [removed] = newData.splice(movedIndex, 1); + newData.splice(variables.position, 0, removed); + removed.order = variables.position; + newData[movedIndex].order = movedIndex; + + return mutate({ + update: (cache) => { + cache.updateQuery( + { + id: cache.identify({ __typename: 'CategoryNodeList' }), + query: GET_CATEGORIES, + variables: { orderBy: CategoryOrderBy.Order }, + }, + (data) => ({ + ...data!, + categories: { + ...data!.categories, + nodes: newData, + }, + }), + ); + }, + optimisticResponse: { + __typename: 'Mutation', + updateCategoryOrder: { + __typename: 'UpdateCategoryOrderPayload', + categories: newData, + }, + }, + ...mutateOptions, + }); + }; + + return [wrappedMutate, result]; } public useGetCategoryMangas( diff --git a/src/screens/settings/Categories.tsx b/src/screens/settings/Categories.tsx index 212d54aa..c348a733 100644 --- a/src/screens/settings/Categories.tsx +++ b/src/screens/settings/Categories.tsx @@ -65,19 +65,17 @@ export default function Categories() { const [dialogOpen, setDialogOpen] = useState(false); const [dialogName, setDialogName] = useState(''); const [dialogDefault, setDialogDefault] = useState(false); + const [reorderCategory, { reset: revertReorder }] = requestManager.useReorderCategory(); const theme = useTheme(); useSetDefaultBackTo('settings'); const categoryReorder = (list: TCategory[], from: number, to: number) => { const reorderedCategory = list[from]; - const newData = [...list]; - const [removed] = newData.splice(from, 1); - newData.splice(to, 0, removed); - // TODO - update cache immediately - // mutate(categoriesEndpoint, newData, { revalidate: false }); - requestManager.reorderCategory(reorderedCategory.id, to + 1); + reorderCategory({ variables: { input: { id: reorderedCategory.id, position: to + 1 } } }).catch(() => + revertReorder(), + ); }; const onDragEnd = (result: DropResult) => {