Add "auto webtoon mode" option to reader

This commit is contained in:
schroda
2024-12-26 17:15:50 +01:00
parent cfd5b78488
commit 33e184ba18
13 changed files with 184 additions and 24 deletions

View File

@@ -8,7 +8,7 @@
import { MangaStatus } from '@/lib/graphql/generated/graphql.ts';
import { TranslationKey } from '@/Base.types.ts';
import { MangaAction, MangaIdInfo } from '@/modules/manga/Manga.types.ts';
import { MangaAction, MangaIdInfo, MangaType } from '@/modules/manga/Manga.types.ts';
export const FALLBACK_MANGA: MangaIdInfo = { id: -1 };
@@ -101,3 +101,46 @@ export const actionToTranslationKey: {
error: 'manga.action.track.add.label.error',
},
};
export const SOURCES_BY_MANGA_TYPE: Record<MangaType, string[]> = {
[MangaType.MANGA]: [],
[MangaType.COMIC]: [],
[MangaType.WEBTOON]: ['mangatoon', 'manmanga', 'toomics', 'webcomics', 'webtoons', 'webtoon'],
[MangaType.MANHWA]: [
'hiperdex',
'hmanhwa',
'instamanhwa',
'manhwa18',
'manhwa68',
'manhwa365',
'manhwahentaime',
'manhwamanga',
'manhwatop',
'manhwa',
'manytoon',
'manwha',
'readmanhwa',
'skymanga',
'toonily',
'webtoonxyz',
],
[MangaType.MANHUA]: [
'1st kiss manhua',
'hero manhua',
'manhuabox',
'manhuaus',
'manhuas',
'manhuas',
'readmanhua',
'wuxiaworld',
'manhua',
],
};
export const MANGA_TAGS_BY_MANGA_TYPE: Record<MangaType, string[]> = {
[MangaType.MANGA]: ['manga'],
[MangaType.COMIC]: ['comic'],
[MangaType.WEBTOON]: ['webtoon', 'long strip'],
[MangaType.MANHWA]: ['manhwa'],
[MangaType.MANHUA]: ['manhua'],
};

View File

@@ -10,27 +10,36 @@ import { LongPressPointerHandlers, LongPressResult } from 'use-long-press/lib/us
import { PopupState } from 'material-ui-popup-state/hooks';
import { SelectableCollectionReturnType } from '@/modules/collection/hooks/useSelectableCollection.ts';
import { useManageMangaLibraryState } from '@/modules/manga/hooks/useManageMangaLibraryState.tsx';
import { ChapterType, MangaReaderFieldsFragment, MangaType, TrackRecordType } from '@/lib/graphql/generated/graphql.ts';
import {
ChapterType,
MangaReaderFieldsFragment,
MangaType as MangaTypeGql,
Maybe,
SourceType,
TrackRecordType,
} from '@/lib/graphql/generated/graphql.ts';
import { SingleModeProps } from '@/modules/manga/components/MangaActionMenuItems.tsx';
import { IReaderSettings } from '@/modules/reader/types/Reader.types.ts';
import { GridLayout } from '@/modules/core/Core.types.ts';
export type MangaCardMode = 'default' | 'source' | 'migrate.search' | 'migrate.select' | 'duplicate';
type MangaCardBaseProps = Pick<MangaType, 'id' | 'title' | 'sourceId'> &
type MangaCardBaseProps = Pick<MangaTypeGql, 'id' | 'title' | 'sourceId'> &
Omit<SingleModeProps['manga'], 'downloadCount' | 'unreadCount' | 'chapters'> &
Partial<Pick<MangaType, 'inLibrary' | 'downloadCount' | 'unreadCount'>> & {
Partial<Pick<MangaTypeGql, 'inLibrary' | 'downloadCount' | 'unreadCount'>> & {
firstUnreadChapter?: Pick<ChapterType, 'id' | 'sourceOrder' | 'isRead'> | null;
};
export type MangaIdInfo = Pick<MangaType, 'id'>;
export type MangaChapterCountInfo = { chapters: Pick<MangaType['chapters'], 'totalCount'> };
export type MangaDownloadInfo = Pick<MangaType, 'downloadCount'> & MangaChapterCountInfo;
export type MangaUnreadInfo = Pick<MangaType, 'unreadCount'> & MangaChapterCountInfo;
export type MangaThumbnailInfo = Pick<MangaType, 'thumbnailUrl' | 'thumbnailUrlLastFetched'>;
export type MangaIdInfo = Pick<MangaTypeGql, 'id'>;
export type MangaChapterCountInfo = { chapters: Pick<MangaTypeGql['chapters'], 'totalCount'> };
export type MangaDownloadInfo = Pick<MangaTypeGql, 'downloadCount'> & MangaChapterCountInfo;
export type MangaUnreadInfo = Pick<MangaTypeGql, 'unreadCount'> & MangaChapterCountInfo;
export type MangaThumbnailInfo = Pick<MangaTypeGql, 'thumbnailUrl' | 'thumbnailUrlLastFetched'>;
export type MangaTrackRecordInfo = MangaIdInfo & {
trackRecords: { nodes: Pick<TrackRecordType, 'id' | 'trackerId'>[] };
};
export type MangaGenreInfo = Pick<MangaTypeGql, 'genre'>;
export type MangaSourceNameInfo = { source?: Maybe<Pick<SourceType, 'name'>> };
export type MigrateMode = 'copy' | 'migrate';
@@ -41,7 +50,7 @@ export interface MangaCardProps {
gridLayout?: GridLayout;
inLibraryIndicator?: boolean;
selected?: boolean | null;
handleSelection?: SelectableCollectionReturnType<MangaType['id']>['handleSelection'];
handleSelection?: SelectableCollectionReturnType<MangaTypeGql['id']>['handleSelection'];
mode?: MangaCardMode;
}
@@ -69,3 +78,11 @@ export type MangaAction =
| 'track';
export type TMangaReader = MangaReaderFieldsFragment;
export enum MangaType {
MANGA,
COMIC,
WEBTOON,
MANHWA,
MANHUA,
}

View File

@@ -28,12 +28,19 @@ import { MetadataMigrationSettings } from '@/modules/migration/Migration.types.t
import {
MangaAction,
MangaDownloadInfo,
MangaGenreInfo,
MangaIdInfo,
MangaSourceNameInfo,
MangaThumbnailInfo,
MangaType,
MangaUnreadInfo,
MigrateMode,
} from '@/modules/manga/Manga.types.ts';
import { actionToTranslationKey } from '@/modules/manga/Manga.constants.ts';
import {
actionToTranslationKey,
MANGA_TAGS_BY_MANGA_TYPE,
SOURCES_BY_MANGA_TYPE,
} from '@/modules/manga/Manga.constants.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
type MangaToMigrate = NonNullable<GetMangaToMigrateQuery['manga']>;
@@ -524,4 +531,43 @@ export class Mangas {
throw new Error(`Mangas::performAction: unknown action "${action}"`);
}
}
static getType(manga: MangaGenreInfo & MangaSourceNameInfo): MangaType {
if (Mangas.isType(manga, MangaType.MANGA)) {
return MangaType.MANGA;
}
if (Mangas.isType(manga, MangaType.COMIC)) {
return MangaType.COMIC;
}
if (Mangas.isType(manga, MangaType.WEBTOON)) {
return MangaType.WEBTOON;
}
if (Mangas.isType(manga, MangaType.MANHWA)) {
return MangaType.MANHWA;
}
if (Mangas.isType(manga, MangaType.MANHUA)) {
return MangaType.MANHUA;
}
return MangaType.MANGA;
}
static isType(manga: MangaGenreInfo & MangaSourceNameInfo, type: MangaType): boolean {
return (
manga.genre.some((genre) => MANGA_TAGS_BY_MANGA_TYPE[type].includes(genre.toLowerCase())) ||
SOURCES_BY_MANGA_TYPE[type].includes(manga.source?.name.toLowerCase() ?? '')
);
}
static isLongStripType(manga: MangaGenreInfo & MangaSourceNameInfo): boolean {
return (
Mangas.isType(manga, MangaType.WEBTOON) ||
Mangas.isType(manga, MangaType.MANHWA) ||
Mangas.isType(manga, MangaType.MANHUA)
);
}
}