Introduce "sources" util class
This commit is contained in:
@@ -31,6 +31,8 @@ import { translateExtensionLanguage } from '@/modules/extension/Extensions.utils
|
|||||||
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
|
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
|
||||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||||
|
import { Sources } from '@/modules/source/services/Sources.ts';
|
||||||
|
import { SourceIdInfo } from '@/modules/source/Source.types.ts';
|
||||||
|
|
||||||
type SourceLoadingState = { isLoading: boolean; hasResults: boolean; emptySearch: boolean };
|
type SourceLoadingState = { isLoading: boolean; hasResults: boolean; emptySearch: boolean };
|
||||||
type SourceToLoadingStateMap = Map<string, SourceLoadingState>;
|
type SourceToLoadingStateMap = Map<string, SourceLoadingState>;
|
||||||
@@ -62,8 +64,8 @@ const compareSourceByName = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const compareSourcesBySearchResult = (
|
const compareSourcesBySearchResult = (
|
||||||
sourceA: Pick<SourceType, 'id'>,
|
sourceA: SourceIdInfo,
|
||||||
sourceB: Pick<SourceType, 'id'>,
|
sourceB: SourceIdInfo,
|
||||||
sourceToFetchedStateMap: SourceToLoadingStateMap,
|
sourceToFetchedStateMap: SourceToLoadingStateMap,
|
||||||
): -1 | 0 | 1 => {
|
): -1 | 0 | 1 => {
|
||||||
const isSourceAFetched = !sourceToFetchedStateMap.get(sourceA.id)?.isLoading;
|
const isSourceAFetched = !sourceToFetchedStateMap.get(sourceA.id)?.isLoading;
|
||||||
@@ -101,7 +103,7 @@ const SourceSearchPreview = React.memo(
|
|||||||
}: {
|
}: {
|
||||||
source: Pick<SourceType, 'id' | 'displayName' | 'lang'>;
|
source: Pick<SourceType, 'id' | 'displayName' | 'lang'>;
|
||||||
onSearchRequestFinished: (
|
onSearchRequestFinished: (
|
||||||
source: Pick<SourceType, 'id'>,
|
source: SourceIdInfo,
|
||||||
isLoading: boolean,
|
isLoading: boolean,
|
||||||
hasResults: boolean,
|
hasResults: boolean,
|
||||||
emptySearch: boolean,
|
emptySearch: boolean,
|
||||||
@@ -217,7 +219,7 @@ export const SearchAll: React.FC = () => {
|
|||||||
|
|
||||||
const sourcesSortedByName = useMemo(() => [...sources].sort(compareSourceByName), [sources]);
|
const sourcesSortedByName = useMemo(() => [...sources].sort(compareSourceByName), [sources]);
|
||||||
const sourcesFilteredByLang = useMemo(
|
const sourcesFilteredByLang = useMemo(
|
||||||
() => sourcesSortedByName.filter((source) => shownLangs.includes(source.lang) || Number(source.id) === 0),
|
() => sourcesSortedByName.filter((source) => shownLangs.includes(source.lang) || Sources.isLocalSource(source)),
|
||||||
[sourcesSortedByName, shownLangs],
|
[sourcesSortedByName, shownLangs],
|
||||||
);
|
);
|
||||||
const sourcesFilteredByNsfw = useMemo(
|
const sourcesFilteredByNsfw = useMemo(
|
||||||
@@ -233,7 +235,7 @@ export const SearchAll: React.FC = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const updateSourceLoadingState = useCallback(
|
const updateSourceLoadingState = useCallback(
|
||||||
({ id }: Pick<SourceType, 'id'>, isLoading: boolean, hasResults: boolean, emptySearch: boolean) => {
|
({ id }: SourceIdInfo, isLoading: boolean, hasResults: boolean, emptySearch: boolean) => {
|
||||||
setSourceToLoadingStateMap((currentMap) => {
|
setSourceToLoadingStateMap((currentMap) => {
|
||||||
const mapCopy = new Map(currentMap);
|
const mapCopy = new Map(currentMap);
|
||||||
mapCopy.set(id, { isLoading, hasResults, emptySearch });
|
mapCopy.set(id, { isLoading, hasResults, emptySearch });
|
||||||
|
|||||||
@@ -153,8 +153,7 @@ function getSourceName(source?: Pick<SourceType, 'id' | 'displayName'> | null):
|
|||||||
return translate('global.label.unknown');
|
return translate('global.label.unknown');
|
||||||
}
|
}
|
||||||
|
|
||||||
const isLocalSource = Number(source.id) === 0;
|
if (Sources.isLocalSource(source)) {
|
||||||
if (isLocalSource) {
|
|
||||||
return translate('source.local_source.title');
|
return translate('source.local_source.title');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ import { extractOriginalKey, getMetadataKey } from '@/modules/metadata/Metadata.
|
|||||||
import { MangaIdInfo } from '@/modules/manga/Manga.types.ts';
|
import { MangaIdInfo } from '@/modules/manga/Manga.types.ts';
|
||||||
import { ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts';
|
import { ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts';
|
||||||
import { CategoryIdInfo } from '@/modules/category/Category.types.ts';
|
import { CategoryIdInfo } from '@/modules/category/Category.types.ts';
|
||||||
import { SourceType } from '@/lib/graphql/generated/graphql.ts';
|
|
||||||
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
||||||
import { getMetadataDeleteFunction, getMetadataUpdateFunction } from '@/modules/metadata/services/MetadataUpdater.ts';
|
import { getMetadataDeleteFunction, getMetadataUpdateFunction } from '@/modules/metadata/services/MetadataUpdater.ts';
|
||||||
|
import { SourceIdInfo } from '@/modules/source/Source.types.ts';
|
||||||
|
|
||||||
const getAppKeyPrefixForMigration = (migrationId: number): string => {
|
const getAppKeyPrefixForMigration = (migrationId: number): string => {
|
||||||
const appKeyPrefix = METADATA_MIGRATIONS.slice(0, migrationId)
|
const appKeyPrefix = METADATA_MIGRATIONS.slice(0, migrationId)
|
||||||
@@ -269,7 +269,7 @@ const commitMigratedMetadata = (
|
|||||||
| (MangaIdInfo & MetadataHolder)
|
| (MangaIdInfo & MetadataHolder)
|
||||||
| (ChapterIdInfo & MetadataHolder)
|
| (ChapterIdInfo & MetadataHolder)
|
||||||
| (CategoryIdInfo & MetadataHolder)
|
| (CategoryIdInfo & MetadataHolder)
|
||||||
| (Pick<SourceType, 'id'> & MetadataHolder)
|
| (SourceIdInfo & MetadataHolder)
|
||||||
| undefined,
|
| undefined,
|
||||||
migratedMetadata: Metadata,
|
migratedMetadata: Metadata,
|
||||||
useEffectFn: typeof useEffect = (fn: () => void) => fn(),
|
useEffectFn: typeof useEffect = (fn: () => void) => fn(),
|
||||||
@@ -334,7 +334,7 @@ export const applyMetadataMigrations = (
|
|||||||
| (MangaIdInfo & MetadataHolder)
|
| (MangaIdInfo & MetadataHolder)
|
||||||
| (ChapterIdInfo & MetadataHolder)
|
| (ChapterIdInfo & MetadataHolder)
|
||||||
| (CategoryIdInfo & MetadataHolder)
|
| (CategoryIdInfo & MetadataHolder)
|
||||||
| (Pick<SourceType, 'id'> & MetadataHolder),
|
| (SourceIdInfo & MetadataHolder),
|
||||||
useEffectFn: typeof useEffect = (fn: () => void) => fn(),
|
useEffectFn: typeof useEffect = (fn: () => void) => fn(),
|
||||||
): Metadata | undefined => {
|
): Metadata | undefined => {
|
||||||
const meta = { ...(metadataHolder?.meta ?? {}) };
|
const meta = { ...(metadataHolder?.meta ?? {}) };
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ import { MangaIdInfo } from '@/modules/manga/Manga.types.ts';
|
|||||||
|
|
||||||
import { ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts';
|
import { ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts';
|
||||||
import { CategoryIdInfo } from '@/modules/category/Category.types.ts';
|
import { CategoryIdInfo } from '@/modules/category/Category.types.ts';
|
||||||
import { SourceType } from '@/lib/graphql/generated/graphql.ts';
|
|
||||||
import { doesMetadataKeyExistIn, getMetadataKey } from '@/modules/metadata/Metadata.utils.ts';
|
import { doesMetadataKeyExistIn, getMetadataKey } from '@/modules/metadata/Metadata.utils.ts';
|
||||||
import { applyMetadataMigrations } from '@/modules/metadata/services/MetadataMigrations.ts';
|
import { applyMetadataMigrations } from '@/modules/metadata/services/MetadataMigrations.ts';
|
||||||
|
import { SourceIdInfo } from '@/modules/source/Source.types.ts';
|
||||||
|
|
||||||
const getMetadataValueFrom = <Key extends AppMetadataKeys, Value extends AllowedMetadataValueTypes>(
|
const getMetadataValueFrom = <Key extends AppMetadataKeys, Value extends AllowedMetadataValueTypes>(
|
||||||
metadata: Metadata | undefined,
|
metadata: Metadata | undefined,
|
||||||
@@ -70,7 +70,7 @@ export function getMetadataFrom<METADATA extends Partial<Metadata<AppMetadataKey
|
|||||||
): METADATA;
|
): METADATA;
|
||||||
export function getMetadataFrom<METADATA extends Partial<Metadata<AppMetadataKeys, AllowedMetadataValueTypes>>>(
|
export function getMetadataFrom<METADATA extends Partial<Metadata<AppMetadataKeys, AllowedMetadataValueTypes>>>(
|
||||||
type: 'source',
|
type: 'source',
|
||||||
metadataHolder: Pick<SourceType, 'id'> & MetadataHolder,
|
metadataHolder: SourceIdInfo & MetadataHolder,
|
||||||
metadataWithDefaultValues: METADATA,
|
metadataWithDefaultValues: METADATA,
|
||||||
prefixes?: string[],
|
prefixes?: string[],
|
||||||
useEffectFn?: typeof useEffect,
|
useEffectFn?: typeof useEffect,
|
||||||
@@ -82,7 +82,7 @@ export function getMetadataFrom<METADATA extends Partial<Metadata<AppMetadataKey
|
|||||||
| (MangaIdInfo & MetadataHolder)
|
| (MangaIdInfo & MetadataHolder)
|
||||||
| (ChapterIdInfo & MetadataHolder)
|
| (ChapterIdInfo & MetadataHolder)
|
||||||
| (CategoryIdInfo & MetadataHolder)
|
| (CategoryIdInfo & MetadataHolder)
|
||||||
| (Pick<SourceType, 'id'> & MetadataHolder),
|
| (SourceIdInfo & MetadataHolder),
|
||||||
metadataWithDefaultValues: METADATA,
|
metadataWithDefaultValues: METADATA,
|
||||||
prefixes?: string[],
|
prefixes?: string[],
|
||||||
useEffectFn: typeof useEffect = (fn: () => void) => fn(),
|
useEffectFn: typeof useEffect = (fn: () => void) => fn(),
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import { SourceType } from '@/lib/graphql/generated/graphql.ts';
|
|
||||||
import { ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts';
|
import { ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts';
|
||||||
import { CategoryIdInfo } from '@/modules/category/Category.types.ts';
|
import { CategoryIdInfo } from '@/modules/category/Category.types.ts';
|
||||||
import {
|
import {
|
||||||
@@ -21,6 +20,7 @@ import {
|
|||||||
import { MangaIdInfo } from '@/modules/manga/Manga.types.ts';
|
import { MangaIdInfo } from '@/modules/manga/Manga.types.ts';
|
||||||
import { getMetadataKey } from '@/modules/metadata/Metadata.utils.ts';
|
import { getMetadataKey } from '@/modules/metadata/Metadata.utils.ts';
|
||||||
import { convertToGqlMeta } from '@/modules/metadata/services/MetadataConverter.ts';
|
import { convertToGqlMeta } from '@/modules/metadata/services/MetadataConverter.ts';
|
||||||
|
import { SourceIdInfo } from '@/modules/source/Source.types.ts';
|
||||||
|
|
||||||
const requestUpdateMetadataValue = async (
|
const requestUpdateMetadataValue = async (
|
||||||
metadataHolder: GqlMetaHolder,
|
metadataHolder: GqlMetaHolder,
|
||||||
@@ -46,8 +46,7 @@ const requestUpdateMetadataValue = async (
|
|||||||
await requestManager.setMangaMeta((metadataHolder as MangaIdInfo).id, metadataKey, value).response;
|
await requestManager.setMangaMeta((metadataHolder as MangaIdInfo).id, metadataKey, value).response;
|
||||||
break;
|
break;
|
||||||
case 'source':
|
case 'source':
|
||||||
await requestManager.setSourceMeta((metadataHolder as Pick<SourceType, 'id'>).id, metadataKey, value)
|
await requestManager.setSourceMeta((metadataHolder as SourceIdInfo).id, metadataKey, value).response;
|
||||||
.response;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`requestUpdateMetadataValue: unknown holderType "${holderType}"`);
|
throw new Error(`requestUpdateMetadataValue: unknown holderType "${holderType}"`);
|
||||||
@@ -95,7 +94,7 @@ export const requestUpdateCategoryMetadata = async (
|
|||||||
): Promise<void[]> => requestUpdateMetadata(category, 'category', keysToValues, keyPrefixes, isMetadataKey);
|
): Promise<void[]> => requestUpdateMetadata(category, 'category', keysToValues, keyPrefixes, isMetadataKey);
|
||||||
|
|
||||||
export const requestUpdateSourceMetadata = async (
|
export const requestUpdateSourceMetadata = async (
|
||||||
source: Pick<SourceType, 'id'> & GqlMetaHolder,
|
source: SourceIdInfo & GqlMetaHolder,
|
||||||
keysToValue: MetadataKeyValuePair[],
|
keysToValue: MetadataKeyValuePair[],
|
||||||
keyPrefixes?: string[],
|
keyPrefixes?: string[],
|
||||||
isMetadataKey?: boolean,
|
isMetadataKey?: boolean,
|
||||||
@@ -108,7 +107,7 @@ export const getMetadataUpdateFunction = (
|
|||||||
| (MangaIdInfo & MetadataHolder)
|
| (MangaIdInfo & MetadataHolder)
|
||||||
| (ChapterIdInfo & MetadataHolder)
|
| (ChapterIdInfo & MetadataHolder)
|
||||||
| (CategoryIdInfo & MetadataHolder)
|
| (CategoryIdInfo & MetadataHolder)
|
||||||
| (Pick<SourceType, 'id'> & MetadataHolder),
|
| (SourceIdInfo & MetadataHolder),
|
||||||
): ((keyValuePair: MetadataKeyValuePair[], keyPrefixes?: string[], isMetadataKey?: boolean) => Promise<void[]>) => {
|
): ((keyValuePair: MetadataKeyValuePair[], keyPrefixes?: string[], isMetadataKey?: boolean) => Promise<void[]>) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'global':
|
case 'global':
|
||||||
@@ -135,7 +134,7 @@ export const getMetadataUpdateFunction = (
|
|||||||
return (...args) =>
|
return (...args) =>
|
||||||
requestUpdateSourceMetadata(
|
requestUpdateSourceMetadata(
|
||||||
{
|
{
|
||||||
id: (metadataHolder as Pick<SourceType, 'id'>).id,
|
id: (metadataHolder as SourceIdInfo).id,
|
||||||
meta: convertToGqlMeta(metadataHolder.meta),
|
meta: convertToGqlMeta(metadataHolder.meta),
|
||||||
},
|
},
|
||||||
...args,
|
...args,
|
||||||
@@ -168,7 +167,7 @@ export const requestDeleteMetadataValue = async (
|
|||||||
await requestManager.deleteMangaMeta((metadataHolder as MangaIdInfo).id, metadataKey).response;
|
await requestManager.deleteMangaMeta((metadataHolder as MangaIdInfo).id, metadataKey).response;
|
||||||
break;
|
break;
|
||||||
case 'source':
|
case 'source':
|
||||||
await requestManager.deleteSourceMeta((metadataHolder as Pick<SourceType, 'id'>).id, metadataKey).response;
|
await requestManager.deleteSourceMeta((metadataHolder as SourceIdInfo).id, metadataKey).response;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`requestDeleteMetadataValue: unknown holderType "${holderType}"`);
|
throw new Error(`requestDeleteMetadataValue: unknown holderType "${holderType}"`);
|
||||||
@@ -215,7 +214,7 @@ export const requestDeleteCategoryMetadata = async (
|
|||||||
): Promise<void[]> => requestDeleteMetadata(category, 'category', keys, keyPrefixes, isMetadataKey);
|
): Promise<void[]> => requestDeleteMetadata(category, 'category', keys, keyPrefixes, isMetadataKey);
|
||||||
|
|
||||||
export const requestDeleteSourceMetadata = async (
|
export const requestDeleteSourceMetadata = async (
|
||||||
source: Pick<SourceType, 'id'> & GqlMetaHolder,
|
source: SourceIdInfo & GqlMetaHolder,
|
||||||
keys: AppMetadataKeys[],
|
keys: AppMetadataKeys[],
|
||||||
keyPrefixes?: string[],
|
keyPrefixes?: string[],
|
||||||
isMetadataKey?: boolean,
|
isMetadataKey?: boolean,
|
||||||
@@ -228,7 +227,7 @@ export const getMetadataDeleteFunction = (
|
|||||||
| (MangaIdInfo & MetadataHolder)
|
| (MangaIdInfo & MetadataHolder)
|
||||||
| (ChapterIdInfo & MetadataHolder)
|
| (ChapterIdInfo & MetadataHolder)
|
||||||
| (CategoryIdInfo & MetadataHolder)
|
| (CategoryIdInfo & MetadataHolder)
|
||||||
| (Pick<SourceType, 'id'> & MetadataHolder),
|
| (SourceIdInfo & MetadataHolder),
|
||||||
): ((metadataToDelete: AppMetadataKeys[], keyPrefixes?: string[], isMetadataKey?: boolean) => Promise<void[]>) => {
|
): ((metadataToDelete: AppMetadataKeys[], keyPrefixes?: string[], isMetadataKey?: boolean) => Promise<void[]>) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'global':
|
case 'global':
|
||||||
@@ -255,7 +254,7 @@ export const getMetadataDeleteFunction = (
|
|||||||
return (...args) =>
|
return (...args) =>
|
||||||
requestDeleteSourceMetadata(
|
requestDeleteSourceMetadata(
|
||||||
{
|
{
|
||||||
id: (metadataHolder as Pick<SourceType, 'id'>).id,
|
id: (metadataHolder as SourceIdInfo).id,
|
||||||
meta: convertToGqlMeta(metadataHolder.meta),
|
meta: convertToGqlMeta(metadataHolder.meta),
|
||||||
},
|
},
|
||||||
...args,
|
...args,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
GetSourceBrowseQuery,
|
GetSourceBrowseQuery,
|
||||||
GetSourceSettingsQuery,
|
GetSourceSettingsQuery,
|
||||||
SourcePreferenceChangeInput,
|
SourcePreferenceChangeInput,
|
||||||
|
SourceType,
|
||||||
} from '@/lib/graphql/generated/graphql.ts';
|
} from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
export interface IPos {
|
export interface IPos {
|
||||||
@@ -57,3 +58,5 @@ export type MultiSelectListPreferenceProps = PreferenceProps &
|
|||||||
|
|
||||||
export type EditTextPreferenceProps = PreferenceProps &
|
export type EditTextPreferenceProps = PreferenceProps &
|
||||||
ExtractByKeyValue<SourcePreferences, '__typename', 'EditTextPreference'>;
|
ExtractByKeyValue<SourcePreferences, '__typename', 'EditTextPreference'>;
|
||||||
|
|
||||||
|
export type SourceIdInfo = Pick<SourceType, 'id'>;
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ export const SourceCard: React.FC<IProps> = (props: IProps) => {
|
|||||||
|
|
||||||
const isMobileWidth = MediaQuery.useIsMobileWidth();
|
const isMobileWidth = MediaQuery.useIsMobileWidth();
|
||||||
|
|
||||||
|
const { source, showSourceRepo } = props;
|
||||||
const {
|
const {
|
||||||
source: {
|
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
lang,
|
lang,
|
||||||
@@ -45,12 +45,9 @@ export const SourceCard: React.FC<IProps> = (props: IProps) => {
|
|||||||
supportsLatest,
|
supportsLatest,
|
||||||
isNsfw,
|
isNsfw,
|
||||||
extension: { repo },
|
extension: { repo },
|
||||||
},
|
} = source;
|
||||||
showSourceRepo,
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
const isLocalSource = Number(id) === 0;
|
const sourceName = Sources.isLocalSource(source) ? t('source.local_source.title') : name;
|
||||||
const sourceName = isLocalSource ? t('source.local_source.title') : name;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import {
|
|||||||
GetSourceBrowseQueryVariables,
|
GetSourceBrowseQueryVariables,
|
||||||
GetSourceMangasFetchMutation,
|
GetSourceMangasFetchMutation,
|
||||||
GetSourceMangasFetchMutationVariables,
|
GetSourceMangasFetchMutationVariables,
|
||||||
SourceType,
|
|
||||||
} from '@/lib/graphql/generated/graphql.ts';
|
} from '@/lib/graphql/generated/graphql.ts';
|
||||||
import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts';
|
import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts';
|
||||||
import { useLocalStorage, useSessionStorage } from '@/modules/core/hooks/useStorage.tsx';
|
import { useLocalStorage, useSessionStorage } from '@/modules/core/hooks/useStorage.tsx';
|
||||||
@@ -44,7 +43,7 @@ import { createUpdateSourceMetadata, useGetSourceMetadata } from '@/modules/sour
|
|||||||
import { makeToast } from '@/modules/core/utils/Toast.ts';
|
import { makeToast } from '@/modules/core/utils/Toast.ts';
|
||||||
import { GET_SOURCE_BROWSE } from '@/lib/graphql/queries/SourceQuery.ts';
|
import { GET_SOURCE_BROWSE } from '@/lib/graphql/queries/SourceQuery.ts';
|
||||||
import { TranslationKey } from '@/Base.types.ts';
|
import { TranslationKey } from '@/Base.types.ts';
|
||||||
import { IPos } from '@/modules/source/Source.types.ts';
|
import { IPos, SourceIdInfo } from '@/modules/source/Source.types.ts';
|
||||||
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
||||||
import { EmptyView } from '@/modules/core/components/placeholder/EmptyView.tsx';
|
import { EmptyView } from '@/modules/core/components/placeholder/EmptyView.tsx';
|
||||||
import { EmptyViewAbsoluteCentered } from '@/modules/core/components/placeholder/EmptyViewAbsoluteCentered.tsx';
|
import { EmptyViewAbsoluteCentered } from '@/modules/core/components/placeholder/EmptyViewAbsoluteCentered.tsx';
|
||||||
@@ -53,8 +52,9 @@ import { GridLayout } from '@/modules/core/Core.types.ts';
|
|||||||
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
|
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
|
||||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||||
|
import { Sources } from '@/modules/source/services/Sources.ts';
|
||||||
|
|
||||||
const DEFAULT_SOURCE: Pick<SourceType, 'id'> = { id: '-1' };
|
const DEFAULT_SOURCE: SourceIdInfo = { id: '-1' };
|
||||||
|
|
||||||
const ContentTypeMenu = styled('div')(({ theme }) => ({
|
const ContentTypeMenu = styled('div')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@@ -332,7 +332,7 @@ export function SourceMangas() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const message = !isLoading ? t(SOURCE_CONTENT_TYPE_TO_ERROR_MSG_KEY[contentType]) : undefined;
|
const message = !isLoading ? t(SOURCE_CONTENT_TYPE_TO_ERROR_MSG_KEY[contentType]) : undefined;
|
||||||
const isLocalSource = sourceId === '0';
|
const isLocalSource = sourceId === Sources.LOCAL_SOURCE_ID;
|
||||||
const messageExtra = isLocalSource ? (
|
const messageExtra = isLocalSource ? (
|
||||||
<>
|
<>
|
||||||
<span>{t('source.local_source.label.checkout')} </span>
|
<span>{t('source.local_source.label.checkout')} </span>
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ import { translateExtensionLanguage } from '@/modules/extension/Extensions.utils
|
|||||||
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
|
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
|
||||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||||
|
import { Sources as SourceService } from '@/modules/source/services/Sources.ts';
|
||||||
|
|
||||||
function sourceToLangList(sources: Pick<SourceType, 'id' | 'lang'>[]) {
|
function sourceToLangList(sources: Pick<SourceType, 'id' | 'lang'>[]) {
|
||||||
const result = new Set<string>();
|
const result = new Set<string>();
|
||||||
|
|
||||||
sources.forEach((source) => {
|
sources.forEach((source) => {
|
||||||
const isLocalSource = Number(source.id) === 0;
|
const lang = SourceService.isLocalSource(source) ? DefaultLanguage.OTHER : source.lang;
|
||||||
const lang = isLocalSource ? DefaultLanguage.OTHER : source.lang;
|
|
||||||
|
|
||||||
result.add(lang);
|
result.add(lang);
|
||||||
});
|
});
|
||||||
@@ -46,8 +46,7 @@ function groupByLang<Source extends Pick<SourceType, 'id' | 'name' | 'lang'>>(
|
|||||||
const result: Record<string, Source[]> = {};
|
const result: Record<string, Source[]> = {};
|
||||||
|
|
||||||
sources.forEach((source) => {
|
sources.forEach((source) => {
|
||||||
const isLocalSource = Number(source.id) === 0;
|
const lang = SourceService.isLocalSource(source) ? DefaultLanguage.OTHER : source.lang;
|
||||||
const lang = isLocalSource ? DefaultLanguage.OTHER : source.lang;
|
|
||||||
|
|
||||||
result[lang] ??= [];
|
result[lang] ??= [];
|
||||||
result[lang].push(source);
|
result[lang].push(source);
|
||||||
@@ -146,7 +145,7 @@ export function Sources() {
|
|||||||
.filter((source) => {
|
.filter((source) => {
|
||||||
const isLangOther = lang === DefaultLanguage.OTHER;
|
const isLangOther = lang === DefaultLanguage.OTHER;
|
||||||
if (isLangOther) {
|
if (isLangOther) {
|
||||||
const isLocalSource = Number(source.id) === 0;
|
const isLocalSource = SourceService.isLocalSource(source);
|
||||||
const isLangShown = shownLangs.includes(lang);
|
const isLangShown = shownLangs.includes(lang);
|
||||||
|
|
||||||
const isLangOtherSourceShown = isLangShown || isLocalSource;
|
const isLangOtherSourceShown = isLangShown || isLocalSource;
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ import { useEffect, useMemo } from 'react';
|
|||||||
import { jsonSaveParse } from '@/lib/HelperFunctions.ts';
|
import { jsonSaveParse } from '@/lib/HelperFunctions.ts';
|
||||||
import { requestUpdateSourceMetadata } from '@/modules/metadata/services/MetadataUpdater.ts';
|
import { requestUpdateSourceMetadata } from '@/modules/metadata/services/MetadataUpdater.ts';
|
||||||
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
||||||
import { SourceType } from '@/lib/graphql/generated/graphql.ts';
|
import { ISourceMetadata, SourceIdInfo, SourceMetadataKeys } from '@/modules/source/Source.types.ts';
|
||||||
import { ISourceMetadata, SourceMetadataKeys } from '@/modules/source/Source.types.ts';
|
|
||||||
import { convertFromGqlMeta } from '@/modules/metadata/services/MetadataConverter.ts';
|
import { convertFromGqlMeta } from '@/modules/metadata/services/MetadataConverter.ts';
|
||||||
import { getMetadataFrom } from '@/modules/metadata/services/MetadataReader.ts';
|
import { getMetadataFrom } from '@/modules/metadata/services/MetadataReader.ts';
|
||||||
import {
|
import {
|
||||||
@@ -39,10 +38,7 @@ const convertGqlMetadataToAppMetadata = (
|
|||||||
savedSearches: jsonSaveParse<ISourceMetadata['savedSearches']>(metadata.savedSearches as string) ?? undefined,
|
savedSearches: jsonSaveParse<ISourceMetadata['savedSearches']>(metadata.savedSearches as string) ?? undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const getMetadata = (
|
const getMetadata = (metaHolder: SourceIdInfo & GqlMetaHolder, useEffectFn?: typeof useEffect): ISourceMetadata =>
|
||||||
metaHolder: Pick<SourceType, 'id'> & GqlMetaHolder,
|
|
||||||
useEffectFn?: typeof useEffect,
|
|
||||||
): ISourceMetadata =>
|
|
||||||
convertGqlMetadataToAppMetadata(
|
convertGqlMetadataToAppMetadata(
|
||||||
getMetadataFrom(
|
getMetadataFrom(
|
||||||
'source',
|
'source',
|
||||||
@@ -53,10 +49,9 @@ const getMetadata = (
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
export const getSourceMetadata = (metaHolder: Pick<SourceType, 'id'> & GqlMetaHolder): ISourceMetadata =>
|
export const getSourceMetadata = (metaHolder: SourceIdInfo & GqlMetaHolder): ISourceMetadata => getMetadata(metaHolder);
|
||||||
getMetadata(metaHolder);
|
|
||||||
|
|
||||||
export const useGetSourceMetadata = (metaHolder: Pick<SourceType, 'id'> & GqlMetaHolder): ISourceMetadata => {
|
export const useGetSourceMetadata = (metaHolder: SourceIdInfo & GqlMetaHolder): ISourceMetadata => {
|
||||||
const metadata = getMetadata(metaHolder, useEffect);
|
const metadata = getMetadata(metaHolder, useEffect);
|
||||||
return useMemo(() => metadata, [metaHolder]);
|
return useMemo(() => metadata, [metaHolder]);
|
||||||
};
|
};
|
||||||
@@ -65,7 +60,7 @@ export const updateSourceMetadata = async <
|
|||||||
MetadataKeys extends SourceMetadataKeys = SourceMetadataKeys,
|
MetadataKeys extends SourceMetadataKeys = SourceMetadataKeys,
|
||||||
MetadataKey extends MetadataKeys = MetadataKeys,
|
MetadataKey extends MetadataKeys = MetadataKeys,
|
||||||
>(
|
>(
|
||||||
source: Pick<SourceType, 'id'> & GqlMetaHolder,
|
source: SourceIdInfo & GqlMetaHolder,
|
||||||
metadataKey: MetadataKey,
|
metadataKey: MetadataKey,
|
||||||
value: ISourceMetadata[MetadataKey],
|
value: ISourceMetadata[MetadataKey],
|
||||||
): Promise<void[]> =>
|
): Promise<void[]> =>
|
||||||
@@ -75,7 +70,7 @@ export const updateSourceMetadata = async <
|
|||||||
|
|
||||||
export const createUpdateSourceMetadata =
|
export const createUpdateSourceMetadata =
|
||||||
<Settings extends SourceMetadataKeys>(
|
<Settings extends SourceMetadataKeys>(
|
||||||
source: Pick<SourceType, 'id'> & GqlMetaHolder,
|
source: SourceIdInfo & GqlMetaHolder,
|
||||||
handleError: (error: any) => void = defaultPromiseErrorHandler('createUpdateSourceMetadata'),
|
handleError: (error: any) => void = defaultPromiseErrorHandler('createUpdateSourceMetadata'),
|
||||||
): ((...args: OmitFirst<Parameters<typeof updateSourceMetadata<Settings>>>) => Promise<void | void[]>) =>
|
): ((...args: OmitFirst<Parameters<typeof updateSourceMetadata<Settings>>>) => Promise<void | void[]>) =>
|
||||||
(metadataKey, value) =>
|
(metadataKey, value) =>
|
||||||
|
|||||||
17
src/modules/source/services/Sources.ts
Normal file
17
src/modules/source/services/Sources.ts
Normal 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 { SourceIdInfo } from '@/modules/source/Source.types.ts';
|
||||||
|
|
||||||
|
export class Sources {
|
||||||
|
static readonly LOCAL_SOURCE_ID = '0';
|
||||||
|
|
||||||
|
static isLocalSource(source: SourceIdInfo): boolean {
|
||||||
|
return source.id === Sources.LOCAL_SOURCE_ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user