Skip to content

Commit

Permalink
Feature/add option to remove manga from categories when removing from…
Browse files Browse the repository at this point in the history
… library (#633)

* Optionally remove manga categories when removing them from library

* Use "Mangas::removeFromLibrary"

* Handle uncatched promises
  • Loading branch information
schroda authored Mar 2, 2024
1 parent c5a5c4b commit 8bdf035
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 13 deletions.
3 changes: 2 additions & 1 deletion src/components/chapter/ChapterActionMenuItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { MenuItem } from '@/components/menu/MenuItem.tsx';
import { IChapterWithMeta } from '@/components/chapter/ChapterList.tsx';
import { ChaptersWithMeta } from '@/lib/data/ChaptersWithMeta.ts';
import { createGetMenuItemTitle, createIsMenuItemDisabled, createShouldShowMenuItem } from '@/components/menu/util.ts';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';

type BaseProps = { onClose: () => void };

Expand Down Expand Up @@ -116,7 +117,7 @@ export const ChapterActionMenuItems = ({
Chapters.performAction(actualAction, chapter ? [chapter.id] : ChaptersWithMeta.getIds(chaptersWithMeta), {
chapters: getChapters(),
wasManuallyMarkedAsRead: true,
});
}).catch(defaultPromiseErrorHandler('ChapterActionMenuItems::performAction'));
onClose();
};

Expand Down
3 changes: 2 additions & 1 deletion src/components/chapter/ChapterList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { SelectableCollectionSelectAll } from '@/components/collection/Selectabl
import { Chapters } from '@/lib/data/Chapters.ts';
import { ChaptersWithMeta } from '@/lib/data/ChaptersWithMeta.ts';
import { ChapterActionMenuItems } from '@/components/chapter/ChapterActionMenuItems.tsx';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';

const ChapterListHeader = styled(Stack)(({ theme }) => ({
margin: 8,
Expand Down Expand Up @@ -167,7 +168,7 @@ export const ChapterList: React.FC<IProps> = ({ manga, isRefreshing }) => {
onClick={() =>
Chapters.download(
ChaptersWithMeta.getIds(ChaptersWithMeta.getNonDownloaded(chaptersWithMeta)),
)
).catch(defaultPromiseErrorHandler('ChapterList::download'))
}
>
<DownloadIcon />
Expand Down
6 changes: 1 addition & 5 deletions src/components/manga/MangaDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,7 @@ export const MangaDetails: React.FC<IProps> = ({ manga }) => {
};

const removeFromLibrary = () => {
Promise.all([requestManager.updateManga(manga.id, { updateManga: { inLibrary: false } }).response])
.then(() => makeToast(t('library.info.label.removed_from_library'), 'success'))
.catch(() => {
makeToast(t('library.error.label.remove_from_library'), 'error');
});
Mangas.removeFromLibrary([manga.id]).catch(defaultPromiseErrorHandler('MangaDetails::removeFromLibrary'));
};

return (
Expand Down
3 changes: 2 additions & 1 deletion src/components/navbar/action/CategorySelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { CheckboxInput } from '@/components/atoms/CheckboxInput.tsx';
import { useMetadataServerSettings } from '@/util/metadataServerSettings.ts';
import { convertToGqlMeta, requestUpdateServerMetadata } from '@/util/metadata.ts';
import { makeToast } from '@/components/util/Toast.tsx';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';

type BaseProps = {
open: boolean;
Expand Down Expand Up @@ -155,7 +156,7 @@ export function CategorySelect(props: Props) {
addToCategories,
removeFromCategories,
},
});
}).catch(defaultPromiseErrorHandler('CategorySelect::handleOk'));
};

return (
Expand Down
8 changes: 8 additions & 0 deletions src/i18n/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,14 @@
}
}
},
"remove_from_library": {
"remove_from_categories": {
"label": {
"description": "Remove manga from categories when removing them from the library",
"title": "Forget manga categories"
}
}
},
"search": {
"ignore_filters": {
"label": {
Expand Down
8 changes: 7 additions & 1 deletion src/lib/data/Mangas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from '@/lib/graphql/generated/graphql.ts';
import { Chapters } from '@/lib/data/Chapters.ts';
import { makeToast } from '@/components/util/Toast.tsx';
import { getMetadataServerSettings } from '@/util/metadataServerSettings.ts';

export type MangaAction =
| 'download'
Expand Down Expand Up @@ -208,10 +209,15 @@ export class Mangas {
}

static async removeFromLibrary(mangaIds: number[]): Promise<void> {
const { removeMangaFromCategories } = await getMetadataServerSettings();
return Mangas.executeAction(
'remove_from_library',
mangaIds.length,
() => requestManager.updateMangas(mangaIds, { inLibrary: false }).response,
() =>
requestManager.updateMangas(mangaIds, {
updateMangas: { inLibrary: false },
updateMangasCategories: removeMangaFromCategories ? { clearCategories: true } : undefined,
}).response,
);
}

Expand Down
4 changes: 3 additions & 1 deletion src/lib/graphql/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2842,10 +2842,12 @@ export type UpdateMangaMutation = { __typename?: 'Mutation', updateManga: { __ty

export type UpdateMangasMutationVariables = Exact<{
input: UpdateMangasInput;
updateCategoryInput: UpdateMangasCategoriesInput;
updateCategories: Scalars['Boolean']['input'];
}>;


export type UpdateMangasMutation = { __typename?: 'Mutation', updateMangas: { __typename?: 'UpdateMangasPayload', clientMutationId?: string | null, mangas: Array<{ __typename?: 'MangaType', id: number, inLibrary: boolean, inLibraryAt: any, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', id: number, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> } }> } };
export type UpdateMangasMutation = { __typename?: 'Mutation', updateMangas: { __typename?: 'UpdateMangasPayload', clientMutationId?: string | null, mangas: Array<{ __typename?: 'MangaType', id: number, inLibrary: boolean, inLibraryAt: any, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', id: number, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> } }> }, updateMangasCategories?: { __typename?: 'UpdateMangasCategoriesPayload', mangas: Array<{ __typename?: 'MangaType', id: number, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', id: number, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> } }> } };

export type UpdateMangaCategoriesMutationVariables = Exact<{
input: UpdateMangaCategoriesInput;
Expand Down
20 changes: 19 additions & 1 deletion src/lib/graphql/mutations/MangaMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ export const UPDATE_MANGA = gql`
`;

export const UPDATE_MANGAS = gql`
mutation UPDATE_MANGAS($input: UpdateMangasInput!) {
mutation UPDATE_MANGAS(
$input: UpdateMangasInput!
$updateCategoryInput: UpdateMangasCategoriesInput!
$updateCategories: Boolean!
) {
updateMangas(input: $input) {
clientMutationId
mangas {
Expand All @@ -148,6 +152,20 @@ export const UPDATE_MANGAS = gql`
}
}
}
updateMangasCategories(input: $updateCategoryInput) @include(if: $updateCategories) {
mangas {
id
categories {
nodes {
id
mangas {
totalCount
}
}
totalCount
}
}
}
}
`;

Expand Down
8 changes: 6 additions & 2 deletions src/lib/requests/RequestManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1584,13 +1584,17 @@ export class RequestManager {

public updateMangas(
ids: number[],
patch: UpdateMangaPatchInput,
patch: { updateMangas: UpdateMangaPatchInput; updateMangasCategories?: UpdateMangaCategoriesPatchInput },
options?: MutationOptions<UpdateMangasMutation, UpdateMangasMutationVariables>,
): AbortableApolloMutationResponse<UpdateMangasMutation> {
const result = this.doRequest<UpdateMangasMutation, UpdateMangasMutationVariables>(
GQLMethod.MUTATION,
UPDATE_MANGAS,
{ input: { ids, patch } },
{
input: { ids, patch: patch.updateMangas },
updateCategoryInput: { ids, patch: patch.updateMangasCategories ?? {} },
updateCategories: !!patch.updateMangasCategories,
},
options,
);

Expand Down
13 changes: 13 additions & 0 deletions src/screens/settings/LibrarySettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,19 @@ export function LibrarySettings() {
onChange={(e) => setSettingValue('showAddToLibraryCategorySelectDialog', e.target.checked)}
/>
</ListItem>
<ListItem>
<ListItemText
primary={t('library.settings.general.remove_from_library.remove_from_categories.label.title')}
secondary={t(
'library.settings.general.remove_from_library.remove_from_categories.label.description',
)}
/>
<Switch
edge="end"
checked={settings.removeMangaFromCategories}
onChange={(e) => setSettingValue('removeMangaFromCategories', e.target.checked)}
/>
</ListItem>
</List>
<GlobalUpdateSettings />
<List
Expand Down
1 change: 1 addition & 0 deletions src/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ export type MetadataServerSettings = {
// library
showAddToLibraryCategorySelectDialog: boolean;
ignoreFilters: boolean;
removeMangaFromCategories: boolean;
};

export interface ISearchSettings {
Expand Down
1 change: 1 addition & 0 deletions src/util/metadataServerSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const getDefaultSettings = (): MetadataServerSettings => ({
// library
showAddToLibraryCategorySelectDialog: true,
ignoreFilters: false,
removeMangaFromCategories: false,
});

const getMetadataServerSettingsWithDefaultFallback = (
Expand Down

0 comments on commit 8bdf035

Please sign in to comment.