Move core files into new folder

This commit is contained in:
schroda
2024-10-05 16:09:34 +02:00
parent 996bb62888
commit 23a86a77f0
173 changed files with 514 additions and 481 deletions

61
src/lib/AppStorage.ts Normal file
View File

@@ -0,0 +1,61 @@
/*
* 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/.
*/
// eslint-disable-next-line max-classes-per-file
export class Storage {
constructor(private readonly storage: typeof window.localStorage) {}
parseValue<T>(value: string | null, defaultValue: T): T {
if (value === null) {
return defaultValue;
}
return JSON.parse(value);
}
getItem(key: string): string | null {
return this.storage.getItem(key);
}
getItemParsed<T>(key: string, defaultValue: T): T {
return this.parseValue(this.getItem(key), defaultValue);
}
setItem(key: string, value: unknown, emitEvent: boolean = true): void {
const fireEvent = (valueToStore: string | undefined) => {
if (!emitEvent) {
return;
}
window.dispatchEvent(
new StorageEvent('storage', {
key,
oldValue: this.getItem(key),
newValue: valueToStore,
}),
);
};
if (value === undefined) {
this.storage.removeItem(key);
fireEvent(undefined);
return;
}
const valueToStore = JSON.stringify(value);
this.storage.setItem(key, valueToStore);
fireEvent(valueToStore);
}
}
export class AppStorage {
static readonly local: Storage = new Storage(window.localStorage);
static readonly session: Storage = new Storage(window.sessionStorage);
}

View File

@@ -0,0 +1,16 @@
/*
* 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/.
*/
export const defaultPromiseErrorHandler = (name: string) => (error: any) => {
if (process.env.NODE_ENV === 'production') {
return;
}
// eslint-disable-next-line no-console
console.error(`${name} failed due to`, error);
};

View File

@@ -0,0 +1,15 @@
/*
* 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/.
*/
export const jsonSaveParse = <T = any>(...args: Parameters<typeof JSON.parse>): T | null => {
try {
return JSON.parse(...args);
} catch (e) {
return null;
}
};

802
src/lib/IsoLanguages.ts Normal file
View File

@@ -0,0 +1,802 @@
/*
* 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 { I18nResourceCode } from '@/i18n';
export type ISOLanguage = {
name: string;
nativeName: string;
};
// full list: https://github.com/meikidd/iso-639-1/blob/master/src/data.js
export const IsoLanguages: { [languageCode in I18nResourceCode]: ISOLanguage } & Record<string, ISOLanguage> = {
// #############################
// ### ###
// ### START: manually added ###
// ### ###
// #############################
'es-419': {
name: 'Spanish; Castilian',
nativeName: 'Español',
},
'pt-pt': {
name: 'Portuguese',
nativeName: 'Português (Portugal)',
},
'pt-br': {
name: 'Portuguese; Brasil',
nativeName: 'Português (Brasil)',
},
zh_Hans: {
name: 'Chinese (Simplified)',
nativeName: '中文 (HANS)',
},
zh_Hant: {
name: 'Chinese (Traditional)',
nativeName: '中文 (HANT)',
},
'zh-rhk': {
name: 'Chinese',
nativeName: '中文 (RHK)',
},
'zh-rtw': {
name: 'Chinese',
nativeName: '中文 (RTW)',
},
fil: {
name: 'Filipino',
nativeName: 'Filipino',
},
sh: {
name: 'Serbo-Croatian',
nativeName: 'srpskohrvatski',
},
'nb-NO': {
name: 'Norwegian Bokmål',
nativeName: 'Norsk bokmål',
},
// #############################
// ### ###
// ### END: manually added ###
// ### ###
// #############################
aa: {
name: 'Afar',
nativeName: 'Afaraf',
},
ab: {
name: 'Abkhaz',
nativeName: 'аҧсуа бызшәа',
},
ae: {
name: 'Avestan',
nativeName: 'avesta',
},
af: {
name: 'Afrikaans',
nativeName: 'Afrikaans',
},
ak: {
name: 'Akan',
nativeName: 'Akan',
},
am: {
name: 'Amharic',
nativeName: 'አማርኛ',
},
an: {
name: 'Aragonese',
nativeName: 'aragonés',
},
ar: {
name: 'Arabic',
nativeName: 'اَلْعَرَبِيَّةُ',
},
as: {
name: 'Assamese',
nativeName: 'অসমীয়া',
},
av: {
name: 'Avaric',
nativeName: 'авар мацӀ',
},
ay: {
name: 'Aymara',
nativeName: 'aymar aru',
},
az: {
name: 'Azerbaijani',
nativeName: 'azərbaycan dili',
},
ba: {
name: 'Bashkir',
nativeName: 'башҡорт теле',
},
be: {
name: 'Belarusian',
nativeName: 'беларуская мова',
},
bg: {
name: 'Bulgarian',
nativeName: 'български език',
},
bi: {
name: 'Bislama',
nativeName: 'Bislama',
},
bm: {
name: 'Bambara',
nativeName: 'bamanankan',
},
bn: {
name: 'Bengali',
nativeName: 'বাংলা',
},
bo: {
name: 'Tibetan',
nativeName: 'བོད་ཡིག',
},
br: {
name: 'Breton',
nativeName: 'brezhoneg',
},
bs: {
name: 'Bosnian',
nativeName: 'bosanski jezik',
},
ca: {
name: 'Catalan',
nativeName: 'Català',
},
ce: {
name: 'Chechen',
nativeName: 'нохчийн мотт',
},
ch: {
name: 'Chamorro',
nativeName: 'Chamoru',
},
co: {
name: 'Corsican',
nativeName: 'corsu',
},
cr: {
name: 'Cree',
nativeName: 'ᓀᐦᐃᔭᐍᐏᐣ',
},
cs: {
name: 'Czech',
nativeName: 'čeština',
},
cu: {
name: 'Old Church Slavonic',
nativeName: 'ѩзыкъ словѣньскъ',
},
cv: {
name: 'Chuvash',
nativeName: 'чӑваш чӗлхи',
},
cy: {
name: 'Welsh',
nativeName: 'Cymraeg',
},
da: {
name: 'Danish',
nativeName: 'Dansk',
},
de: {
name: 'German',
nativeName: 'Deutsch',
},
dv: {
name: 'Divehi',
nativeName: 'ދިވެހި',
},
dz: {
name: 'Dzongkha',
nativeName: 'རྫོང་ཁ',
},
ee: {
name: 'Ewe',
nativeName: 'Eʋegbe',
},
el: {
name: 'Greek',
nativeName: 'Ελληνικά',
},
en: {
name: 'English',
nativeName: 'English',
},
eo: {
name: 'Esperanto',
nativeName: 'Esperanto',
},
es: {
name: 'Spanish',
nativeName: 'Español',
},
et: {
name: 'Estonian',
nativeName: 'eesti',
},
eu: {
name: 'Basque',
nativeName: 'euskara',
},
fa: {
name: 'Persian',
nativeName: 'فارسی',
},
ff: {
name: 'Fula',
nativeName: 'Fulfulde',
},
fi: {
name: 'Finnish',
nativeName: 'suomi',
},
fj: {
name: 'Fijian',
nativeName: 'vosa Vakaviti',
},
fo: {
name: 'Faroese',
nativeName: 'Føroyskt',
},
fr: {
name: 'French',
nativeName: 'Français',
},
fy: {
name: 'Western Frisian',
nativeName: 'Frysk',
},
ga: {
name: 'Irish',
nativeName: 'Gaeilge',
},
gd: {
name: 'Scottish Gaelic',
nativeName: 'Gàidhlig',
},
gl: {
name: 'Galician',
nativeName: 'galego',
},
gn: {
name: 'Guaraní',
nativeName: "Avañe'ẽ",
},
gu: {
name: 'Gujarati',
nativeName: 'ગુજરાતી',
},
gv: {
name: 'Manx',
nativeName: 'Gaelg',
},
ha: {
name: 'Hausa',
nativeName: 'هَوُسَ',
},
he: {
name: 'Hebrew',
nativeName: 'עברית',
},
hi: {
name: 'Hindi',
nativeName: 'हिन्दी',
},
ho: {
name: 'Hiri Motu',
nativeName: 'Hiri Motu',
},
hr: {
name: 'Croatian',
nativeName: 'Hrvatski',
},
ht: {
name: 'Haitian',
nativeName: 'Kreyòl ayisyen',
},
hu: {
name: 'Hungarian',
nativeName: 'magyar',
},
hy: {
name: 'Armenian',
nativeName: 'Հայերեն',
},
hz: {
name: 'Herero',
nativeName: 'Otjiherero',
},
ia: {
name: 'Interlingua',
nativeName: 'Interlingua',
},
id: {
name: 'Indonesian',
nativeName: 'Bahasa Indonesia',
},
ie: {
name: 'Interlingue',
nativeName: 'Interlingue',
},
ig: {
name: 'Igbo',
nativeName: 'Asụsụ Igbo',
},
ii: {
name: 'Nuosu',
nativeName: 'ꆈꌠ꒿ Nuosuhxop',
},
ik: {
name: 'Inupiaq',
nativeName: 'Iñupiaq',
},
io: {
name: 'Ido',
nativeName: 'Ido',
},
is: {
name: 'Icelandic',
nativeName: 'Íslenska',
},
it: {
name: 'Italian',
nativeName: 'Italiano',
},
iu: {
name: 'Inuktitut',
nativeName: 'ᐃᓄᒃᑎᑐᑦ',
},
ja: {
name: 'Japanese',
nativeName: '日本語',
},
jv: {
name: 'Javanese',
nativeName: 'basa Jawa',
},
ka: {
name: 'Georgian',
nativeName: 'ქართული',
},
kg: {
name: 'Kongo',
nativeName: 'Kikongo',
},
ki: {
name: 'Kikuyu',
nativeName: 'Gĩkũyũ',
},
kj: {
name: 'Kwanyama',
nativeName: 'Kuanyama',
},
kk: {
name: 'Kazakh',
nativeName: 'қазақ тілі',
},
kl: {
name: 'Kalaallisut',
nativeName: 'kalaallisut',
},
km: {
name: 'Khmer',
nativeName: 'ខេមរភាសា',
},
kn: {
name: 'Kannada',
nativeName: 'ಕನ್ನಡ',
},
ko: {
name: 'Korean',
nativeName: '한국어',
},
kr: {
name: 'Kanuri',
nativeName: 'Kanuri',
},
ks: {
name: 'Kashmiri',
nativeName: 'कश्मीरी',
},
ku: {
name: 'Kurdish',
nativeName: 'Kurdî',
},
kv: {
name: 'Komi',
nativeName: 'коми кыв',
},
kw: {
name: 'Cornish',
nativeName: 'Kernewek',
},
ky: {
name: 'Kyrgyz',
nativeName: 'Кыргызча',
},
la: {
name: 'Latin',
nativeName: 'latine',
},
lb: {
name: 'Luxembourgish',
nativeName: 'Lëtzebuergesch',
},
lg: {
name: 'Ganda',
nativeName: 'Luganda',
},
li: {
name: 'Limburgish',
nativeName: 'Limburgs',
},
ln: {
name: 'Lingala',
nativeName: 'Lingála',
},
lo: {
name: 'Lao',
nativeName: 'ພາສາລາວ',
},
lt: {
name: 'Lithuanian',
nativeName: 'lietuvių kalba',
},
lu: {
name: 'Luba-Katanga',
nativeName: 'Kiluba',
},
lv: {
name: 'Latvian',
nativeName: 'latviešu valoda',
},
mg: {
name: 'Malagasy',
nativeName: 'fiteny malagasy',
},
mh: {
name: 'Marshallese',
nativeName: 'Kajin M̧ajeļ',
},
mi: {
name: 'Māori',
nativeName: 'te reo Māori',
},
mk: {
name: 'Macedonian',
nativeName: 'македонски јазик',
},
ml: {
name: 'Malayalam',
nativeName: 'മലയാളം',
},
mn: {
name: 'Mongolian',
nativeName: 'Монгол хэл',
},
mr: {
name: 'Marathi',
nativeName: 'मराठी',
},
ms: {
name: 'Malay',
nativeName: 'Bahasa Melayu',
},
mt: {
name: 'Maltese',
nativeName: 'Malti',
},
my: {
name: 'Burmese',
nativeName: 'ဗမာစာ',
},
na: {
name: 'Nauru',
nativeName: 'Dorerin Naoero',
},
nb: {
name: 'Norwegian Bokmål',
nativeName: 'Norsk bokmål',
},
nd: {
name: 'Northern Ndebele',
nativeName: 'isiNdebele',
},
ne: {
name: 'Nepali',
nativeName: 'नेपाली',
},
ng: {
name: 'Ndonga',
nativeName: 'Owambo',
},
nl: {
name: 'Dutch',
nativeName: 'Nederlands',
},
nn: {
name: 'Norwegian Nynorsk',
nativeName: 'Norsk nynorsk',
},
no: {
name: 'Norwegian',
nativeName: 'Norsk',
},
nr: {
name: 'Southern Ndebele',
nativeName: 'isiNdebele',
},
nv: {
name: 'Navajo',
nativeName: 'Diné bizaad',
},
ny: {
name: 'Chichewa',
nativeName: 'chiCheŵa',
},
oc: {
name: 'Occitan',
nativeName: 'occitan',
},
oj: {
name: 'Ojibwe',
nativeName: 'ᐊᓂᔑᓈᐯᒧᐎᓐ',
},
om: {
name: 'Oromo',
nativeName: 'Afaan Oromoo',
},
or: {
name: 'Oriya',
nativeName: 'ଓଡ଼ିଆ',
},
os: {
name: 'Ossetian',
nativeName: 'ирон æвзаг',
},
pa: {
name: 'Panjabi',
nativeName: 'ਪੰਜਾਬੀ',
},
pi: {
name: 'Pāli',
nativeName: 'पाऴि',
},
pl: {
name: 'Polish',
nativeName: 'Polski',
},
ps: {
name: 'Pashto',
nativeName: 'پښتو',
},
pt: {
name: 'Portuguese',
nativeName: 'Português',
},
qu: {
name: 'Quechua',
nativeName: 'Runa Simi',
// asdfasdfasdfasdf
},
rm: {
name: 'Romansh',
nativeName: 'rumantsch grischun',
},
rn: {
name: 'Kirundi',
nativeName: 'Ikirundi',
},
ro: {
name: 'Romanian',
nativeName: 'Română',
},
ru: {
name: 'Russian',
nativeName: 'Русский',
},
rw: {
name: 'Kinyarwanda',
nativeName: 'Ikinyarwanda',
},
sa: {
name: 'Sanskrit',
nativeName: 'संस्कृतम्',
},
sc: {
name: 'Sardinian',
nativeName: 'sardu',
},
sd: {
name: 'Sindhi',
nativeName: 'सिन्धी',
},
se: {
name: 'Northern Sami',
nativeName: 'Davvisámegiella',
},
sg: {
name: 'Sango',
nativeName: 'yângâ tî sängö',
},
si: {
name: 'Sinhala',
nativeName: 'සිංහල',
},
sk: {
name: 'Slovak',
nativeName: 'slovenčina',
},
sl: {
name: 'Slovenian',
nativeName: 'slovenščina',
},
sm: {
name: 'Samoan',
nativeName: "gagana fa'a Samoa",
},
sn: {
name: 'Shona',
nativeName: 'chiShona',
},
so: {
name: 'Somali',
nativeName: 'Soomaaliga',
},
sq: {
name: 'Albanian',
nativeName: 'Shqip',
},
sr: {
name: 'Serbian',
nativeName: 'српски језик',
},
ss: {
name: 'Swati',
nativeName: 'SiSwati',
},
st: {
name: 'Southern Sotho',
nativeName: 'Sesotho',
},
su: {
name: 'Sundanese',
nativeName: 'Basa Sunda',
},
sv: {
name: 'Swedish',
nativeName: 'Svenska',
},
sw: {
name: 'Swahili',
nativeName: 'Kiswahili',
},
ta: {
name: 'Tamil',
nativeName: 'தமிழ்',
},
te: {
name: 'Telugu',
nativeName: 'తెలుగు',
},
tg: {
name: 'Tajik',
nativeName: 'тоҷикӣ',
},
th: {
name: 'Thai',
nativeName: 'ไทย',
},
ti: {
name: 'Tigrinya',
nativeName: 'ትግርኛ',
},
tk: {
name: 'Turkmen',
nativeName: 'Türkmençe',
},
tl: {
name: 'Tagalog',
nativeName: 'Wikang Tagalog',
},
tn: {
name: 'Tswana',
nativeName: 'Setswana',
},
to: {
name: 'Tonga',
nativeName: 'faka Tonga',
},
tr: {
name: 'Turkish',
nativeName: 'Türkçe',
},
ts: {
name: 'Tsonga',
nativeName: 'Xitsonga',
},
tt: {
name: 'Tatar',
nativeName: 'татар теле',
},
tw: {
name: 'Twi',
nativeName: 'Twi',
},
ty: {
name: 'Tahitian',
nativeName: 'Reo Tahiti',
},
ug: {
name: 'Uyghur',
nativeName: 'ئۇيغۇرچە‎',
},
uk: {
name: 'Ukrainian',
nativeName: 'Українська',
},
ur: {
name: 'Urdu',
nativeName: 'اردو',
},
uz: {
name: 'Uzbek',
nativeName: 'Ўзбек',
},
ve: {
name: 'Venda',
nativeName: 'Tshivenḓa',
},
vi: {
name: 'Vietnamese',
nativeName: 'Tiếng Việt',
},
vo: {
name: 'Volapük',
nativeName: 'Volapük',
},
wa: {
name: 'Walloon',
nativeName: 'walon',
},
wo: {
name: 'Wolof',
nativeName: 'Wollof',
},
xh: {
name: 'Xhosa',
nativeName: 'isiXhosa',
},
yi: {
name: 'Yiddish',
nativeName: 'ייִדיש',
},
yo: {
name: 'Yoruba',
nativeName: 'Yorùbá',
},
za: {
name: 'Zhuang',
nativeName: 'Saɯ cueŋƅ',
},
zh: {
name: 'Chinese',
nativeName: '中文',
},
zu: {
name: 'Zulu',
nativeName: 'isiZulu',
},
};

78
src/lib/Languages.tsx Normal file
View File

@@ -0,0 +1,78 @@
/*
* 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 { t } from 'i18next';
import { ISOLanguage, IsoLanguages } from '@/lib/IsoLanguages.ts';
export enum DefaultLanguage {
ALL = 'all',
OTHER = 'other',
LOCAL_SOURCE = 'localsourcelang',
}
function getISOLanguage(code: string): ISOLanguage | null {
if (IsoLanguages[code]) {
return IsoLanguages[code];
}
if (IsoLanguages[code.toLocaleLowerCase()]) {
return IsoLanguages[code.toLocaleLowerCase()];
}
const whereToCut = code.indexOf('-') !== -1 ? code.indexOf('-') : code.length;
const processedCode = code.toLocaleLowerCase().substring(0, whereToCut);
if (IsoLanguages[processedCode]) {
return IsoLanguages[processedCode];
}
return null;
}
export function getLanguage(code: string): { name: string; nativeName: string } {
const isoLanguage = getISOLanguage(code);
if (isoLanguage) {
return isoLanguage;
}
return {
name: t('global.language.label.language_with_code', { code }),
nativeName: t('global.language.label.language_with_code', { code }),
};
}
export function langCodeToName(code: string): string {
return getLanguage(code).nativeName;
}
function defaultNativeLang() {
return 'en'; // TODO: infer from the browser
}
export function extensionDefaultLangs() {
return [defaultNativeLang(), DefaultLanguage.ALL];
}
export function sourceDefualtLangs() {
return [defaultNativeLang(), DefaultLanguage.LOCAL_SOURCE];
}
export function sourceForcedDefaultLangs(): string[] {
return [DefaultLanguage.LOCAL_SOURCE];
}
export const langSortCmp = (a: string, b: string) => {
// puts english first for convience
const aLang = langCodeToName(a);
const bLang = langCodeToName(b);
if (a === 'en') return -1;
if (b === 'en') return 1;
return aLang.localeCompare(bLang);
};

View File

@@ -1,31 +0,0 @@
/*
* 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 { useEffect, useState } from 'react';
import { Droppable, DroppableProps } from 'react-beautiful-dnd';
// issue: https://github.com/atlassian/react-beautiful-dnd/issues/2399
// credit for fix: https://github.com/atlassian/react-beautiful-dnd/issues/2399#issuecomment-1175638194
export function StrictModeDroppable({ children, ...props }: DroppableProps) {
const [enabled, setEnabled] = useState(false);
useEffect(() => {
const animation = requestAnimationFrame(() => setEnabled(true));
return () => {
cancelAnimationFrame(animation);
setEnabled(false);
};
}, []);
if (!enabled) {
return null;
}
return <Droppable {...props}>{children}</Droppable>;
}

View File

@@ -9,9 +9,8 @@
import { t as translate } from 'i18next';
import gql from 'graphql-tag';
import { DocumentNode } from '@apollo/client';
import { ChapterOffset, TranslationKey } from '@/typings.ts';
import { makeToast } from '@/components/util/Toast.tsx';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { makeToast } from '@/lib/ui/Toast.ts';
import { requestManager } from '@/lib/requests/requests/RequestManager.ts';
import { getMetadataServerSettings } from '@/lib/metadata/metadataServerSettings.ts';
import {
ChapterListFieldsFragment,
@@ -21,6 +20,8 @@ import {
import { CHAPTER_LIST_FIELDS } from '@/lib/graphql/fragments/ChapterFragments.ts';
import { MangaIdInfo } from '@/lib/data/Mangas.ts';
import { DirectionOffset, TranslationKey } from '@/Base.types.ts';
export type ChapterAction = 'download' | 'delete' | 'bookmark' | 'unbookmark' | 'mark_as_read' | 'mark_as_unread';
export const actionToTranslationKey: {
@@ -348,13 +349,13 @@ export class Chapters {
currentChapter: Chapter,
chapters: Chapter[],
{
offset = ChapterOffset.NEXT,
offset = DirectionOffset.NEXT,
...options
}: { offset?: ChapterOffset; onlyUnread?: boolean; skipDupe?: boolean; skipDupeChapter?: Chapter } = {},
}: { offset?: DirectionOffset; onlyUnread?: boolean; skipDupe?: boolean; skipDupeChapter?: Chapter } = {},
): Chapter | undefined {
const nextChapters = Chapters.getNextChapters(currentChapter, chapters, { offset, ...options });
const isNextChapterOffset = offset === ChapterOffset.NEXT;
const isNextChapterOffset = offset === DirectionOffset.NEXT;
const sliceStartIndex = isNextChapterOffset ? -1 : 0;
const sliceEndIndex = isNextChapterOffset ? undefined : 1;
@@ -365,15 +366,15 @@ export class Chapters {
fromChapter: Chapter,
chapters: Chapter[],
{
offset = ChapterOffset.NEXT,
offset = DirectionOffset.NEXT,
onlyUnread = false,
skipDupe = false,
skipDupeChapter = fromChapter,
}: { offset?: ChapterOffset; onlyUnread?: boolean; skipDupe?: boolean; skipDupeChapter?: Chapter } = {},
}: { offset?: DirectionOffset; onlyUnread?: boolean; skipDupe?: boolean; skipDupeChapter?: Chapter } = {},
): Chapter[] {
const fromChapterIndex = chapters.findIndex((chapter) => chapter.id === fromChapter.id);
const isNextChapterOffset = offset === ChapterOffset.NEXT;
const isNextChapterOffset = offset === DirectionOffset.NEXT;
const sliceStartIndex = isNextChapterOffset ? 0 : fromChapterIndex;
const sliceEndIndex = isNextChapterOffset ? fromChapterIndex + 1 : undefined;

View File

@@ -8,8 +8,8 @@
import { t as translate } from 'i18next';
import { DocumentNode } from '@apollo/client/core';
import { MetadataMigrationSettings, TranslationKey } from '@/typings.ts';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { MetadataMigrationSettings } from '@/typings.ts';
import { requestManager } from '@/lib/requests/requests/RequestManager.ts';
import {
ChapterConditionInput,
GetMangasBaseQuery,
@@ -25,10 +25,11 @@ import {
UpdateMangaCategoriesPatchInput,
} from '@/lib/graphql/generated/graphql.ts';
import { Chapters } from '@/lib/data/Chapters.ts';
import { makeToast } from '@/components/util/Toast.tsx';
import { makeToast } from '@/lib/ui/Toast.ts';
import { getMetadataServerSettings } from '@/lib/metadata/metadataServerSettings.ts';
import { GET_MANGAS_BASE } from '@/lib/graphql/queries/MangaQuery.ts';
import { MANGA_BASE_FIELDS } from '@/lib/graphql/fragments/MangaFragments.ts';
import { TranslationKey } from '@/Base.types.ts';
export type MangaAction =
| 'download'

View File

@@ -15,9 +15,9 @@ import {
LibraryOptions,
Metadata,
} from '@/typings.ts';
import { jsonSaveParse } from '@/util/HelperFunctions.ts';
import { jsonSaveParse } from '@/lib/HelperFunctions.ts';
import { convertFromGqlMeta, getMetadataFrom, requestUpdateCategoryMetadata } from '@/lib/metadata/metadata.ts';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
import { CategoryIdInfo } from '@/lib/data/Categories.ts';
import { GridLayout } from '@/components/context/LibraryOptionsContext.tsx';

View File

@@ -15,7 +15,7 @@ import {
MetadataHolder,
MetadataKeyValuePair,
} from '@/typings.ts';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { requestManager } from '@/lib/requests/requests/RequestManager.ts';
import { MetaType, SourceType } from '@/lib/graphql/generated/graphql.ts';
import { DEFAULT_DEVICE, getActiveDevice } from '@/util/device.ts';
import { CategoryIdInfo } from '@/lib/data/Categories.ts';

View File

@@ -15,11 +15,11 @@ import {
MetadataServerSettings,
MetadataThemeSettings,
} from '@/typings.ts';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { requestManager } from '@/lib/requests/requests/RequestManager.ts';
import { convertFromGqlMeta, getMetadataFrom, requestUpdateServerMetadata } from '@/lib/metadata/metadata.ts';
import { jsonSaveParse } from '@/util/HelperFunctions.ts';
import { jsonSaveParse } from '@/lib/HelperFunctions.ts';
import { DEFAULT_DEVICE } from '@/util/device.ts';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
import { DEFAULT_SORT_SETTINGS } from '@/screens/Migration.constants.ts';
export const getDefaultSettings = (): MetadataServerSettings => ({

View File

@@ -7,7 +7,7 @@
*/
import { Metadata, IReaderSettings, MetadataKeyValuePair, GqlMetaHolder } from '@/typings.ts';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { requestManager } from '@/lib/requests/requests/RequestManager.ts';
import {
convertFromGqlMeta,
getMetadataFrom,

View File

@@ -14,9 +14,9 @@ import {
Metadata,
SourceMetadataKeys,
} from '@/typings.ts';
import { jsonSaveParse } from '@/util/HelperFunctions.ts';
import { jsonSaveParse } from '@/lib/HelperFunctions.ts';
import { convertFromGqlMeta, getMetadataFrom, requestUpdateSourceMetadata } from '@/lib/metadata/metadata.ts';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
import { SourceType } from '@/lib/graphql/generated/graphql.ts';
const convertAppMetadataToGqlMetadata = (

View File

@@ -0,0 +1,17 @@
/*
* 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 { Location } from 'react-router-dom';
type GenericLocation<State = any> = Omit<Location, 'state'> & { state?: State };
declare module 'react-router-dom' {
export function useParams<Params extends { [K in keyof Params]: string } = {}>(): Params;
export function useLocation<State = any>(): GenericLocation<State>;
}

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { AppStorage } from '@/util/AppStorage.ts';
import { AppStorage } from '@/lib/AppStorage.ts';
export abstract class BaseClient<Client, ClientConfig, Fetcher> {
protected abstract client: Client;

View File

@@ -276,7 +276,7 @@ import {
UPDATE_LIBRARY_MANGAS,
} from '@/lib/graphql/mutations/UpdaterMutation.ts';
import { GET_LAST_UPDATE_TIMESTAMP, GET_UPDATE_STATUS } from '@/lib/graphql/queries/UpdaterQuery.ts';
import { CustomCache } from '@/lib/requests/CustomCache.ts';
import { CustomCache } from '@/lib/CustomCache.ts';
import { RESTORE_BACKUP } from '@/lib/graphql/mutations/BackupMutation.ts';
import { GET_RESTORE_STATUS, VALIDATE_BACKUP } from '@/lib/graphql/queries/BackupQuery.ts';
import { DOWNLOAD_STATUS_SUBSCRIPTION } from '@/lib/graphql/subscriptions/DownloaderSubscription.ts';
@@ -287,7 +287,7 @@ import { CLEAR_SERVER_CACHE } from '@/lib/graphql/mutations/ImageMutation.ts';
import { RESET_WEBUI_UPDATE_STATUS, UPDATE_WEBUI } from '@/lib/graphql/mutations/ServerInfoMutation.ts';
import { WEBUI_UPDATE_SUBSCRIPTION } from '@/lib/graphql/subscriptions/ServerInfoSubscription.ts';
import { GET_DOWNLOAD_STATUS } from '@/lib/graphql/queries/DownloaderQuery.ts';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
import { Queue, QueuePriority } from '@/lib/Queue.ts';
import { TRACKER_SEARCH } from '@/lib/graphql/queries/TrackerQuery.ts';
import {
@@ -305,7 +305,7 @@ import { DOWNLOAD_STATUS_FIELDS } from '@/lib/graphql/fragments/DownloadFragment
import { EXTENSION_LIST_FIELDS } from '@/lib/graphql/fragments/ExtensionFragments.ts';
import { MANGA_BASE_FIELDS, MANGA_META_FIELDS } from '@/lib/graphql/fragments/MangaFragments.ts';
import { MangaIdInfo } from '@/lib/data/Mangas.ts';
import { GLOBAL_METADATA } from '@/lib/graphql/fragments/Fragments';
import { GLOBAL_METADATA } from '@/lib/graphql/fragments/Fragments.ts';
import { CATEGORY_META_FIELDS } from '@/lib/graphql/fragments/CategoryFragments.ts';
import { SOURCE_META_FIELDS } from '@/lib/graphql/fragments/SourceFragments.ts';
import { CHAPTER_META_FIELDS } from '@/lib/graphql/fragments/ChapterFragments.ts';

View File

@@ -9,7 +9,7 @@
import { ThemeOptions } from '@mui/material/styles';
import { t as translate } from 'i18next';
import WebFont from 'webfontloader';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
import { ControlledPromise } from '@/lib/ControlledPromise.ts';
type Theme = { isCustom: boolean; getName: () => string; muiTheme: ThemeOptions };

View File

@@ -8,7 +8,7 @@
import { createRoot } from 'react-dom/client';
import { ThemeProvider } from '@mui/material/styles';
import { ConfirmDialog } from '@/components/molecules/ConfirmDialog.tsx';
import { ConfirmDialog } from '@/modules/core/components/ConfirmDialog.tsx';
import { ControlledPromise } from '@/lib/ControlledPromise.ts';
import { getCurrentTheme } from '@/theme.tsx';

View File

@@ -11,8 +11,8 @@ import { Breakpoint } from '@mui/material/styles';
import { useCallback, useState } from 'react';
import { getCurrentTheme } from '@/theme.tsx';
import { ThemeMode } from '@/components/context/ThemeModeContext.tsx';
import { AppStorage } from '@/util/AppStorage.ts';
import { useResizeObserver } from '@/util/useResizeObserver.tsx';
import { AppStorage } from '@/lib/AppStorage.ts';
import { useResizeObserver } from '@/modules/core/hooks/useResizeObserver.tsx';
export class MediaQuery {
static useIsTouchDevice(): boolean {

View File

@@ -1,18 +0,0 @@
/*
* 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/.
*/
type TupleUnion<U extends string | number | symbol, R extends any[] = []> = {
[S in U]: Exclude<U, S> extends never ? [...R, S] : TupleUnion<Exclude<U, S>, [...R, S]>;
}[U];
export const shouldForwardProp =
<TCustomProps extends Record<string, unknown>>(customProps: TupleUnion<keyof TCustomProps>) =>
(prop: string): boolean =>
// @ts-ignore - TS2589: Type instantiation is excessively deep and possibly infinite.
// this function should never be used without a strict type, thus, this error can be ignored
!customProps.includes(prop);

19
src/lib/ui/Toast.ts Normal file
View File

@@ -0,0 +1,19 @@
/*
* 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 { enqueueSnackbar, OptionsObject, SnackbarKey } from 'notistack';
export function makeToast(message: string, severity?: OptionsObject['variant']): SnackbarKey;
export function makeToast(message: string, options?: OptionsObject): SnackbarKey;
export function makeToast(message: string, options: OptionsObject['variant'] | OptionsObject = 'default'): SnackbarKey {
if (typeof options === 'string') {
return enqueueSnackbar(message, { variant: options });
}
return enqueueSnackbar(message, options);
}