Use gql for "mangas" I - get manga
This commit is contained in:
@@ -10,14 +10,15 @@ import FavoriteIcon from '@mui/icons-material/Favorite';
|
|||||||
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
|
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
|
||||||
import PublicIcon from '@mui/icons-material/Public';
|
import PublicIcon from '@mui/icons-material/Public';
|
||||||
import { styled } from '@mui/material/styles';
|
import { styled } from '@mui/material/styles';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { mutate } from 'swr';
|
import { mutate } from 'swr';
|
||||||
import { t as translate } from 'i18next';
|
import { t as translate } from 'i18next';
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
import { IManga, ISource } from '@/typings';
|
import { ISource } from '@/typings';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import requestManager from '@/lib/requests/RequestManager.ts';
|
||||||
import makeToast from '@/components/util/Toast';
|
import makeToast from '@/components/util/Toast';
|
||||||
|
import { MangaType } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
const DetailsWrapper = styled('div')(({ theme }) => ({
|
const DetailsWrapper = styled('div')(({ theme }) => ({
|
||||||
width: '100%',
|
width: '100%',
|
||||||
@@ -125,11 +126,36 @@ const Genres = styled('div')(() => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const OpenSourceButton = ({ url }: { url?: string | null }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const button = useMemo(
|
||||||
|
() => (
|
||||||
|
<Button disabled={!!url} startIcon={<PublicIcon />} size="large">
|
||||||
|
{t('global.button.open_site')}
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
[url],
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a href={url} target="_blank" rel="noreferrer">
|
||||||
|
<Button startIcon={<PublicIcon />} size="large">
|
||||||
|
{t('global.button.open_site')}
|
||||||
|
</Button>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
manga: IManga;
|
manga: MangaType;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSourceName(source: ISource) {
|
function getSourceName(source?: ISource | null) {
|
||||||
if (!source) {
|
if (!source) {
|
||||||
return translate('global.label.unknown');
|
return translate('global.label.unknown');
|
||||||
}
|
}
|
||||||
@@ -137,7 +163,7 @@ function getSourceName(source: ISource) {
|
|||||||
return source.displayName ?? source.id;
|
return source.displayName ?? source.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getValueOrUnknown(val: string) {
|
function getValueOrUnknown(val?: string | null) {
|
||||||
return val || 'UNKNOWN';
|
return val || 'UNKNOWN';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +195,9 @@ const MangaDetails: React.FC<IProps> = ({ manga }) => {
|
|||||||
<TopContentWrapper>
|
<TopContentWrapper>
|
||||||
<ThumbnailMetadataWrapper>
|
<ThumbnailMetadataWrapper>
|
||||||
<Thumbnail>
|
<Thumbnail>
|
||||||
<img src={requestManager.getValidImgUrlFor(manga.thumbnailUrl)} alt="Manga Thumbnail" />
|
{manga.thumbnailUrl && (
|
||||||
|
<img src={requestManager.getValidImgUrlFor(manga.thumbnailUrl)} alt="Manga Thumbnail" />
|
||||||
|
)}
|
||||||
</Thumbnail>
|
</Thumbnail>
|
||||||
<Metadata>
|
<Metadata>
|
||||||
<h1>{manga.title}</h1>
|
<h1>{manga.title}</h1>
|
||||||
@@ -195,11 +223,7 @@ const MangaDetails: React.FC<IProps> = ({ manga }) => {
|
|||||||
{manga.inLibrary ? t('manga.button.in_library') : t('manga.button.add_to_library')}
|
{manga.inLibrary ? t('manga.button.in_library') : t('manga.button.add_to_library')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<a href={manga.realUrl} target="_blank" rel="noreferrer">
|
<OpenSourceButton url={manga.realUrl} />
|
||||||
<Button startIcon={<PublicIcon />} size="large">
|
|
||||||
{t('global.button.open_site')}
|
|
||||||
</Button>
|
|
||||||
</a>
|
|
||||||
</MangaButtonsContainer>
|
</MangaButtonsContainer>
|
||||||
</TopContentWrapper>
|
</TopContentWrapper>
|
||||||
<BottomContentWrapper>
|
<BottomContentWrapper>
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ import {
|
|||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { IManga } from '@/typings';
|
|
||||||
import CategorySelect from '@/components/navbar/action/CategorySelect';
|
import CategorySelect from '@/components/navbar/action/CategorySelect';
|
||||||
|
import { MangaType } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
manga: IManga;
|
manga: MangaType;
|
||||||
onRefresh: () => any;
|
onRefresh: () => any;
|
||||||
refreshing: boolean;
|
refreshing: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const useRefreshManga = (mangaId: string) => {
|
|||||||
const handleRefresh = useCallback(async () => {
|
const handleRefresh = useCallback(async () => {
|
||||||
setFetchingOnline(true);
|
setFetchingOnline(true);
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
requestManager.getManga(mangaId, true).response.then((res) => {
|
requestManager.getMangaFetch(mangaId).response.then((res) => {
|
||||||
mutate(`${RequestManager.API_VERSION}manga/${mangaId}`, res, { revalidate: false });
|
mutate(`${RequestManager.API_VERSION}manga/${mangaId}`, res, { revalidate: false });
|
||||||
}),
|
}),
|
||||||
requestManager.getMangaChapters(mangaId, true).response.then((res) =>
|
requestManager.getMangaChapters(mangaId, true).response.then((res) =>
|
||||||
|
|||||||
@@ -24,8 +24,9 @@ import ListItemText from '@mui/material/ListItemText';
|
|||||||
import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction';
|
import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction';
|
||||||
import Collapse from '@mui/material/Collapse';
|
import Collapse from '@mui/material/Collapse';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ChapterOffset, IChapter, IManga, IMangaCard, IReaderSettings } from '@/typings';
|
import { ChapterOffset, IChapter, IReaderSettings } from '@/typings';
|
||||||
import ReaderSettingsOptions from '@/components/reader/ReaderSettingsOptions';
|
import ReaderSettingsOptions from '@/components/reader/ReaderSettingsOptions';
|
||||||
|
import { MangaType } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
const Root = styled('div')(({ theme }) => ({
|
const Root = styled('div')(({ theme }) => ({
|
||||||
top: 0,
|
top: 0,
|
||||||
@@ -114,7 +115,7 @@ const OpenDrawerButton = styled(IconButton)(({ theme }) => ({
|
|||||||
interface IProps {
|
interface IProps {
|
||||||
settings: IReaderSettings;
|
settings: IReaderSettings;
|
||||||
setSettingValue: (key: keyof IReaderSettings, value: string | boolean) => void;
|
setSettingValue: (key: keyof IReaderSettings, value: string | boolean) => void;
|
||||||
manga: IManga | IMangaCard;
|
manga: Pick<MangaType, 'id'>;
|
||||||
chapter: IChapter;
|
chapter: IChapter;
|
||||||
curPage: number;
|
curPage: number;
|
||||||
scrollToPage: (page: number) => void;
|
scrollToPage: (page: number) => void;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ function getRandomErrorFace() {
|
|||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
message: string;
|
message: string;
|
||||||
messageExtra?: JSX.Element;
|
messageExtra?: JSX.Element | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function EmptyView({ message, messageExtra }: IProps) {
|
export default function EmptyView({ message, messageExtra }: IProps) {
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ import {
|
|||||||
GetExtensionsQueryVariables,
|
GetExtensionsQueryVariables,
|
||||||
GetGlobalMetadatasQuery,
|
GetGlobalMetadatasQuery,
|
||||||
GetGlobalMetadatasQueryVariables,
|
GetGlobalMetadatasQueryVariables,
|
||||||
|
GetMangaFetchMutation,
|
||||||
|
GetMangaFetchMutationVariables,
|
||||||
|
GetMangaQuery,
|
||||||
|
GetMangaQueryVariables,
|
||||||
GetSourceQuery,
|
GetSourceQuery,
|
||||||
GetSourceQueryVariables,
|
GetSourceQueryVariables,
|
||||||
GetSourcesQuery,
|
GetSourcesQuery,
|
||||||
@@ -125,7 +129,12 @@ import {
|
|||||||
UPDATE_EXTENSION,
|
UPDATE_EXTENSION,
|
||||||
} from '@/lib/graphql/mutations/ExtensionMutation.ts';
|
} from '@/lib/graphql/mutations/ExtensionMutation.ts';
|
||||||
import { GET_SOURCE, GET_SOURCES } from '@/lib/graphql/queries/SourceQuery.ts';
|
import { GET_SOURCE, GET_SOURCES } from '@/lib/graphql/queries/SourceQuery.ts';
|
||||||
import { SET_MANGA_METADATA, UPDATE_MANGA, UPDATE_MANGA_CATEGORIES } from '@/lib/graphql/mutations/MangaMutation.ts';
|
import {
|
||||||
|
GET_MANGA_FETCH,
|
||||||
|
SET_MANGA_METADATA,
|
||||||
|
UPDATE_MANGA,
|
||||||
|
UPDATE_MANGA_CATEGORIES,
|
||||||
|
} from '@/lib/graphql/mutations/MangaMutation.ts';
|
||||||
import { GET_MANGA, GET_MANGAS } from '@/lib/graphql/queries/MangaQuery.ts';
|
import { GET_MANGA, GET_MANGAS } from '@/lib/graphql/queries/MangaQuery.ts';
|
||||||
import { GET_CATEGORIES, GET_CATEGORY, GET_CATEGORY_MANGAS } from '@/lib/graphql/queries/CategoryQuery.ts';
|
import { GET_CATEGORIES, GET_CATEGORY, GET_CATEGORY_MANGAS } from '@/lib/graphql/queries/CategoryQuery.ts';
|
||||||
import { GET_SOURCE_MANGAS_FETCH } from '@/lib/graphql/mutations/SourceMutation.ts';
|
import { GET_SOURCE_MANGAS_FETCH } from '@/lib/graphql/mutations/SourceMutation.ts';
|
||||||
@@ -712,27 +721,28 @@ export class RequestManager {
|
|||||||
|
|
||||||
public useGetManga(
|
public useGetManga(
|
||||||
mangaId: number | string,
|
mangaId: number | string,
|
||||||
{ doOnlineFetch, ...swrOptions }: SWROptions<IManga> & RequestOption = {},
|
options?: QueryHookOptions<GetMangaQuery, GetMangaQueryVariables>,
|
||||||
): AbortableSWRResponse<IManga> {
|
): AbortableApolloUseQueryResponse<GetMangaQuery, GetMangaQueryVariables> {
|
||||||
const onlineFetch = doOnlineFetch ? '?onlineFetch=true' : '';
|
return this.doRequestNew(GQLMethod.USE_QUERY, GET_MANGA, { id: Number(mangaId) }, options);
|
||||||
return this.doRequest(HttpMethod.SWR_GET, `manga/${mangaId}${onlineFetch}`, {
|
|
||||||
swrOptions,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getManga(mangaId: number | string, doOnlineFetch?: boolean): AbortableAxiosResponse<IManga> {
|
public getMangaFetch(
|
||||||
const onlineFetch = doOnlineFetch ? '?onlineFetch=true' : '';
|
|
||||||
return this.doRequest(HttpMethod.GET, `manga/${mangaId}${onlineFetch}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
public useGetFullManga(
|
|
||||||
mangaId: number | string,
|
mangaId: number | string,
|
||||||
{ doOnlineFetch, ...swrOptions }: SWROptions<IManga> & RequestOption = {},
|
options?: MutationOptions<GetMangaFetchMutation, GetMangaFetchMutationVariables>,
|
||||||
): AbortableSWRResponse<IManga> {
|
): AbortableApolloMutationResponse<GetMangaFetchMutation> {
|
||||||
const onlineFetch = doOnlineFetch ? '?onlineFetch=true' : '';
|
return this.doRequestNew<GetMangaFetchMutation, GetMangaFetchMutationVariables>(
|
||||||
return this.doRequest(HttpMethod.SWR_GET, `manga/${mangaId}/full${onlineFetch}`, {
|
GQLMethod.MUTATION,
|
||||||
swrOptions,
|
GET_MANGA_FETCH,
|
||||||
});
|
{
|
||||||
|
input: {
|
||||||
|
id: Number(mangaId),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
refetchQueries: [GET_MANGA, GET_MANGAS],
|
||||||
|
...options,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getMangaThumbnailUrl(mangaId: number): string {
|
public getMangaThumbnailUrl(mangaId: number): string {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { CircularProgress, IconButton, Stack, Tooltip, Box } from '@mui/material
|
|||||||
import React, { useContext, useEffect, useRef } from 'react';
|
import React, { useContext, useEffect, useRef } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
import { isNetworkRequestInFlight } from '@apollo/client/core/networkStatus';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import requestManager from '@/lib/requests/RequestManager.ts';
|
||||||
import NavbarContext, { useSetDefaultBackTo } from '@/components/context/NavbarContext';
|
import NavbarContext, { useSetDefaultBackTo } from '@/components/context/NavbarContext';
|
||||||
import ChapterList from '@/components/manga/ChapterList';
|
import ChapterList from '@/components/manga/ChapterList';
|
||||||
@@ -19,8 +20,9 @@ import MangaDetails from '@/components/manga/MangaDetails';
|
|||||||
import MangaToolbarMenu from '@/components/manga/MangaToolbarMenu';
|
import MangaToolbarMenu from '@/components/manga/MangaToolbarMenu';
|
||||||
import EmptyView from '@/components/util/EmptyView';
|
import EmptyView from '@/components/util/EmptyView';
|
||||||
import LoadingPlaceholder from '@/components/util/LoadingPlaceholder';
|
import LoadingPlaceholder from '@/components/util/LoadingPlaceholder';
|
||||||
|
import { MangaType } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
const AUTOFETCH_AGE = 60 * 60 * 24; // 24 hours
|
const AUTOFETCH_AGE = 1000 * 60 * 60 * 24; // 24 hours
|
||||||
|
|
||||||
const Manga: React.FC = () => {
|
const Manga: React.FC = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -29,21 +31,26 @@ const Manga: React.FC = () => {
|
|||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
const autofetchedRef = useRef(false);
|
const autofetchedRef = useRef(false);
|
||||||
|
|
||||||
const { data: manga, error, isLoading, isValidating, mutate } = requestManager.useGetManga(id);
|
const { data, error, loading: isLoading, networkStatus, refetch } = requestManager.useGetManga(id);
|
||||||
|
const isValidating = isNetworkRequestInFlight(networkStatus);
|
||||||
|
const manga = data?.manga as MangaType | undefined;
|
||||||
|
|
||||||
const [refresh, { loading: refreshing }] = useRefreshManga(id);
|
const [refresh, { loading: refreshing }] = useRefreshManga(id);
|
||||||
useSetDefaultBackTo('library');
|
useSetDefaultBackTo('library');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Automatically fetch manga from source if data is older then 24 hours
|
// Automatically fetch manga from source if data is older then 24 hours OR manga is not initialized yet
|
||||||
// Automatic fetch is done only once, to prevent issues when server does
|
// Automatic fetch is done only once, to prevent issues when server does
|
||||||
// not update age for some reason (ie. error on source side)
|
// not update age for some reason (ie. error on source side)
|
||||||
if (manga == null) return;
|
if (manga == null) return;
|
||||||
if (
|
|
||||||
manga.inLibrary &&
|
const isOutdated =
|
||||||
(manga.age > AUTOFETCH_AGE || manga.chaptersAge > AUTOFETCH_AGE) &&
|
Date.now() - Number(manga.lastFetchedAt) * 1000 > AUTOFETCH_AGE ||
|
||||||
autofetchedRef.current === false
|
Date.now() - Number(manga.chaptersLastFetchedAt) * 1000 > AUTOFETCH_AGE;
|
||||||
) {
|
const refetchBecauseOutdated = manga.inLibrary && isOutdated;
|
||||||
|
|
||||||
|
const doFetch = !autofetchedRef.current && (refetchBecauseOutdated || !manga.initialized);
|
||||||
|
if (doFetch) {
|
||||||
autofetchedRef.current = true;
|
autofetchedRef.current = true;
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
@@ -67,7 +74,7 @@ const Manga: React.FC = () => {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<IconButton onClick={() => mutate()}>
|
<IconButton onClick={() => refetch()}>
|
||||||
<Warning color="error" />
|
<Warning color="error" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -80,7 +87,7 @@ const Manga: React.FC = () => {
|
|||||||
{manga && <MangaToolbarMenu manga={manga} onRefresh={refresh} refreshing={refreshing} />}
|
{manga && <MangaToolbarMenu manga={manga} onRefresh={refresh} refreshing={refreshing} />}
|
||||||
</Stack>,
|
</Stack>,
|
||||||
);
|
);
|
||||||
}, [t, error, isValidating, refreshing, mutate, manga, refresh]);
|
}, [t, error, isValidating, refreshing, manga, refresh]);
|
||||||
|
|
||||||
if (error && !manga) {
|
if (error && !manga) {
|
||||||
return <EmptyView message={t('manga.error.label.request_failure')} messageExtra={error.message ?? error} />;
|
return <EmptyView message={t('manga.error.label.request_failure')} messageExtra={error.message ?? error} />;
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import CircularProgress from '@mui/material/CircularProgress';
|
import CircularProgress from '@mui/material/CircularProgress';
|
||||||
import { useCallback, useContext, useEffect, useState } from 'react';
|
import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||||
import { useLocation, useNavigate, useParams } from 'react-router-dom';
|
import { useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ChapterOffset, IChapter, IManga, IMangaCard, IReaderSettings, ReaderType, TranslationKey } from '@/typings';
|
import { ChapterOffset, IChapter, IReaderSettings, ReaderType, TranslationKey } from '@/typings';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import requestManager from '@/lib/requests/RequestManager.ts';
|
||||||
import {
|
import {
|
||||||
checkAndHandleMissingStoredReaderSettings,
|
checkAndHandleMissingStoredReaderSettings,
|
||||||
@@ -27,6 +27,7 @@ import VerticalPager from '@/components/reader/pager/VerticalPager';
|
|||||||
import ReaderNavBar from '@/components/navbar/ReaderNavBar';
|
import ReaderNavBar from '@/components/navbar/ReaderNavBar';
|
||||||
import NavbarContext from '@/components/context/NavbarContext';
|
import NavbarContext from '@/components/context/NavbarContext';
|
||||||
import makeToast from '@/components/util/Toast';
|
import makeToast from '@/components/util/Toast';
|
||||||
|
import { MangaType } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
const isDupChapter = async (chapterIndex: number, currentChapter: IChapter) => {
|
const isDupChapter = async (chapterIndex: number, currentChapter: IChapter) => {
|
||||||
const nextChapter = await requestManager.getChapter(currentChapter.mangaId, chapterIndex).response;
|
const nextChapter = await requestManager.getChapter(currentChapter.mangaId, chapterIndex).response;
|
||||||
@@ -93,17 +94,22 @@ export default function Reader() {
|
|||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
const { chapterIndex, mangaId } = useParams<{ chapterIndex: string; mangaId: string }>();
|
const { chapterIndex, mangaId } = useParams<{ chapterIndex: string; mangaId: string }>();
|
||||||
const {
|
|
||||||
data: manga = {
|
const initialManga = useMemo(
|
||||||
id: +mangaId,
|
() =>
|
||||||
title: '',
|
({
|
||||||
thumbnailUrl: '',
|
id: +mangaId,
|
||||||
genre: [],
|
title: '',
|
||||||
inLibraryAt: 0,
|
thumbnailUrl: '',
|
||||||
lastReadAt: 0,
|
genre: [],
|
||||||
} as IMangaCard | IManga,
|
inLibraryAt: 0,
|
||||||
isLoading: isMangaLoading,
|
lastReadAt: 0,
|
||||||
} = requestManager.useGetManga(mangaId);
|
}) as unknown as MangaType,
|
||||||
|
[mangaId],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data, loading: isMangaLoading } = requestManager.useGetManga(mangaId);
|
||||||
|
const manga = (data?.manga as MangaType) ?? initialManga;
|
||||||
const { data: chapter = initialChapter, isLoading: isChapterLoading } = requestManager.useGetChapter(
|
const { data: chapter = initialChapter, isLoading: isChapterLoading } = requestManager.useGetChapter(
|
||||||
mangaId,
|
mangaId,
|
||||||
chapterIndex,
|
chapterIndex,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { Box } from '@mui/material';
|
|||||||
import CircularProgress from '@mui/material/CircularProgress';
|
import CircularProgress from '@mui/material/CircularProgress';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { IReaderSettings } from '@/typings';
|
import { IReaderSettings } from '@/typings';
|
||||||
import { requestUpdateServerMetadata } from '@/util/metadata';
|
import { convertToGqlMeta, requestUpdateServerMetadata } from '@/util/metadata';
|
||||||
import {
|
import {
|
||||||
checkAndHandleMissingStoredReaderSettings,
|
checkAndHandleMissingStoredReaderSettings,
|
||||||
getDefaultSettings,
|
getDefaultSettings,
|
||||||
@@ -34,7 +34,7 @@ export default function DefaultReaderSettings() {
|
|||||||
useSetDefaultBackTo('settings');
|
useSetDefaultBackTo('settings');
|
||||||
|
|
||||||
const setSettingValue = (key: keyof IReaderSettings, value: string | boolean) => {
|
const setSettingValue = (key: keyof IReaderSettings, value: string | boolean) => {
|
||||||
requestUpdateServerMetadata(metadata ?? {}, [[key, value]]).catch(() =>
|
requestUpdateServerMetadata(convertToGqlMeta(metadata)! ?? {}, [[key, value]]).catch(() =>
|
||||||
makeToast(t('reader.settings.error.label.failed_to_save_settings'), 'warning'),
|
makeToast(t('reader.settings.error.label.failed_to_save_settings'), 'warning'),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -54,7 +54,11 @@ export default function DefaultReaderSettings() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkAndHandleMissingStoredReaderSettings({ meta: metadata }, 'server', getDefaultSettings()).catch(() => {});
|
checkAndHandleMissingStoredReaderSettings(
|
||||||
|
{ meta: convertToGqlMeta(metadata)! },
|
||||||
|
'server',
|
||||||
|
getDefaultSettings(),
|
||||||
|
).catch(() => {});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReaderSettingsOptions
|
<ReaderSettingsOptions
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import ListItemIcon from '@mui/material/ListItemIcon';
|
|||||||
import SearchIcon from '@mui/icons-material/Search';
|
import SearchIcon from '@mui/icons-material/Search';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { SearchMetadataKeys } from '@/typings';
|
import { SearchMetadataKeys } from '@/typings';
|
||||||
import { requestUpdateServerMetadata } from '@/util/metadata';
|
import { convertToGqlMeta, requestUpdateServerMetadata } from '@/util/metadata';
|
||||||
import { useSearchSettings } from '@/util/searchSettings';
|
import { useSearchSettings } from '@/util/searchSettings';
|
||||||
import makeToast from '@/components/util/Toast';
|
import makeToast from '@/components/util/Toast';
|
||||||
import { useSetDefaultBackTo } from '@/components/context/NavbarContext';
|
import { useSetDefaultBackTo } from '@/components/context/NavbarContext';
|
||||||
@@ -24,7 +24,7 @@ export default function SearchSettings() {
|
|||||||
useSetDefaultBackTo('settings');
|
useSetDefaultBackTo('settings');
|
||||||
|
|
||||||
const setSettingValue = (key: SearchMetadataKeys, value: boolean) => {
|
const setSettingValue = (key: SearchMetadataKeys, value: boolean) => {
|
||||||
requestUpdateServerMetadata(metadata ?? {}, [[key, value]]).catch(() =>
|
requestUpdateServerMetadata(convertToGqlMeta(metadata)! ?? {}, [[key, value]]).catch(() =>
|
||||||
makeToast(t('search.error.label.failed_to_save_settings'), 'warning'),
|
makeToast(t('search.error.label.failed_to_save_settings'), 'warning'),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { OverridableComponent } from '@mui/material/OverridableComponent';
|
|||||||
import { SvgIconTypeMap } from '@mui/material/SvgIcon/SvgIcon';
|
import { SvgIconTypeMap } from '@mui/material/SvgIcon/SvgIcon';
|
||||||
import { ParseKeys } from 'i18next';
|
import { ParseKeys } from 'i18next';
|
||||||
import { Location } from 'react-router-dom';
|
import { Location } from 'react-router-dom';
|
||||||
import { ExtensionType } from '@/lib/graphql/generated/graphql.ts';
|
import { ExtensionType, MangaType, MetaType } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
type GenericLocation<State = any> = Omit<Location, 'state'> & { state?: State };
|
type GenericLocation<State = any> = Omit<Location, 'state'> & { state?: State };
|
||||||
|
|
||||||
@@ -77,6 +77,8 @@ export type Metadata<Keys extends string = string, Values = string> = {
|
|||||||
[key in Keys]: Values;
|
[key in Keys]: Values;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type GqlMetaHolder = { meta?: MetaType[] };
|
||||||
|
|
||||||
export type MetadataHolder<Keys extends string = string, Values = string> = {
|
export type MetadataHolder<Keys extends string = string, Values = string> = {
|
||||||
meta?: Metadata<Keys, Values>;
|
meta?: Metadata<Keys, Values>;
|
||||||
};
|
};
|
||||||
@@ -236,7 +238,7 @@ export interface IReaderProps {
|
|||||||
curPage: number;
|
curPage: number;
|
||||||
initialPage: number;
|
initialPage: number;
|
||||||
settings: IReaderSettings;
|
settings: IReaderSettings;
|
||||||
manga: IMangaCard | IManga;
|
manga: MangaType;
|
||||||
chapter: IChapter | IPartialChapter;
|
chapter: IChapter | IPartialChapter;
|
||||||
nextChapter: () => void;
|
nextChapter: () => void;
|
||||||
prevChapter: () => void;
|
prevChapter: () => void;
|
||||||
|
|||||||
@@ -6,21 +6,17 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { mutate } from 'swr';
|
|
||||||
import {
|
import {
|
||||||
AllowedMetadataValueTypes,
|
AllowedMetadataValueTypes,
|
||||||
AppMetadataKeys,
|
AppMetadataKeys,
|
||||||
ICategory,
|
GqlMetaHolder,
|
||||||
IManga,
|
|
||||||
IMangaCard,
|
|
||||||
IMangaChapter,
|
|
||||||
IMetadataMigration,
|
IMetadataMigration,
|
||||||
Metadata,
|
Metadata,
|
||||||
MetadataHolder,
|
MetadataHolder,
|
||||||
MetadataKeyValuePair,
|
MetadataKeyValuePair,
|
||||||
} from '@/typings';
|
} from '@/typings';
|
||||||
import requestManager, { RequestManager } from '@/lib/requests/RequestManager.ts';
|
import requestManager from '@/lib/requests/RequestManager.ts';
|
||||||
import { MetaType } from '@/lib/graphql/generated/graphql.ts';
|
import { CategoryType, ChapterType, MangaType, MetaType } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
const APP_METADATA_KEY_PREFIX = 'webUI_';
|
const APP_METADATA_KEY_PREFIX = 'webUI_';
|
||||||
|
|
||||||
@@ -118,6 +114,27 @@ const convertValueFromMetadata = <T extends AllowedMetadataValueTypes = AllowedM
|
|||||||
return value as T;
|
return value as T;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const convertFromGqlMeta = (gqlMetadata?: MetaType[]): Metadata | undefined => {
|
||||||
|
if (!gqlMetadata) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const metadata: Metadata = {};
|
||||||
|
gqlMetadata.forEach(({ key, value }) => {
|
||||||
|
metadata[key] = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return metadata;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const convertToGqlMeta = (metadata?: Metadata): MetaType[] | undefined => {
|
||||||
|
if (!metadata) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.entries(metadata).map(([key, value]) => ({ key, value }));
|
||||||
|
};
|
||||||
|
|
||||||
const getAppMetadataFrom = (meta: Metadata, appPrefix: string = APP_METADATA_KEY_PREFIX): Metadata => {
|
const getAppMetadataFrom = (meta: Metadata, appPrefix: string = APP_METADATA_KEY_PREFIX): Metadata => {
|
||||||
const appMetadata: Metadata = {};
|
const appMetadata: Metadata = {};
|
||||||
|
|
||||||
@@ -277,6 +294,8 @@ export const getMetadataFrom = <METADATA extends Partial<Metadata<AppMetadataKey
|
|||||||
return appMetadata;
|
return appMetadata;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const wrapMetadataWithMetaKey = (wrap: boolean, metadata: Metadata): MetadataHolder => {
|
const wrapMetadataWithMetaKey = (wrap: boolean, metadata: Metadata): MetadataHolder => {
|
||||||
if (wrap) {
|
if (wrap) {
|
||||||
return {
|
return {
|
||||||
@@ -294,85 +313,54 @@ const wrapMetadataWithMetaKey = (wrap: boolean, metadata: Metadata): MetadataHol
|
|||||||
type MetadataHolderType = 'manga' | 'chapter' | 'category' | 'global';
|
type MetadataHolderType = 'manga' | 'chapter' | 'category' | 'global';
|
||||||
|
|
||||||
export const requestUpdateMetadataValue = async (
|
export const requestUpdateMetadataValue = async (
|
||||||
metadataHolder: MetadataHolder,
|
metadataHolder: GqlMetaHolder,
|
||||||
holderType: MetadataHolderType,
|
holderType: MetadataHolderType,
|
||||||
key: AppMetadataKeys,
|
key: AppMetadataKeys,
|
||||||
value: AllowedMetadataValueTypes,
|
value: AllowedMetadataValueTypes,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const metadataKey = getMetadataKey(key);
|
const metadataKey = getMetadataKey(key);
|
||||||
const mutatedMetadata = {
|
|
||||||
...metadataHolder.meta,
|
|
||||||
[metadataKey]: `${value}`,
|
|
||||||
};
|
|
||||||
|
|
||||||
let endpoint: string;
|
|
||||||
switch (holderType) {
|
switch (holderType) {
|
||||||
case 'category':
|
case 'category':
|
||||||
endpoint = `category/${(metadataHolder as ICategory).id}/meta`;
|
await requestManager.setCategoryMeta((metadataHolder as CategoryType).id, metadataKey, value).response;
|
||||||
await requestManager.setCategoryMeta((metadataHolder as ICategory).id, metadataKey, value).response;
|
|
||||||
break;
|
break;
|
||||||
case 'chapter':
|
case 'chapter':
|
||||||
// eslint-disable-next-line no-case-declarations
|
await requestManager.setChapterMeta((metadataHolder as ChapterType).id, metadataKey, value).response;
|
||||||
const { manga, chapter } = metadataHolder as IMangaChapter;
|
|
||||||
endpoint = `manga/${manga.id}/chapter/${chapter.index}/meta`;
|
|
||||||
await requestManager.setChapterMeta(chapter.id, metadataKey, value).response;
|
|
||||||
break;
|
break;
|
||||||
case 'global':
|
case 'global':
|
||||||
endpoint = 'meta';
|
|
||||||
await requestManager.setGlobalMetadata(metadataKey, value).response;
|
await requestManager.setGlobalMetadata(metadataKey, value).response;
|
||||||
break;
|
break;
|
||||||
case 'manga':
|
case 'manga':
|
||||||
endpoint = `manga/${(metadataHolder as IManga).id}/meta`;
|
await requestManager.setMangaMeta((metadataHolder as MangaType).id, metadataKey, value).response;
|
||||||
await requestManager.setMangaMeta((metadataHolder as IManga).id, metadataKey, value).response;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`requestUpdateMetadataValue: unknown holderType "${holderType}"`);
|
throw new Error(`requestUpdateMetadataValue: unknown holderType "${holderType}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const urlToMutate = `${RequestManager.API_VERSION}${endpoint}`;
|
|
||||||
mutate(
|
|
||||||
urlToMutate,
|
|
||||||
{ ...metadataHolder, ...wrapMetadataWithMetaKey(holderType !== 'global', mutatedMetadata) },
|
|
||||||
{ revalidate: false },
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const requestUpdateMetadata = async (
|
export const requestUpdateMetadata = async (
|
||||||
metadataHolder: MetadataHolder,
|
metadataHolder: GqlMetaHolder,
|
||||||
holderType: MetadataHolderType,
|
holderType: MetadataHolderType,
|
||||||
keysToValues: [AppMetadataKeys, AllowedMetadataValueTypes][],
|
keysToValues: [AppMetadataKeys, AllowedMetadataValueTypes][],
|
||||||
): Promise<void[]> =>
|
): Promise<void[]> =>
|
||||||
Promise.all(keysToValues.map(([key, value]) => requestUpdateMetadataValue(metadataHolder, holderType, key, value)));
|
Promise.all(keysToValues.map(([key, value]) => requestUpdateMetadataValue(metadataHolder, holderType, key, value)));
|
||||||
|
|
||||||
export const requestUpdateServerMetadata = async (
|
export const requestUpdateServerMetadata = async (
|
||||||
serverMetadata: Metadata,
|
serverMetadata: MetaType[],
|
||||||
keysToValues: MetadataKeyValuePair[],
|
keysToValues: MetadataKeyValuePair[],
|
||||||
): Promise<void[]> => requestUpdateMetadata({ meta: serverMetadata }, 'global', keysToValues);
|
): Promise<void[]> => requestUpdateMetadata({ meta: serverMetadata }, 'global', keysToValues);
|
||||||
|
|
||||||
export const requestUpdateMangaMetadata = async (
|
export const requestUpdateMangaMetadata = async (
|
||||||
manga: IMangaCard | IManga,
|
manga: MangaType,
|
||||||
keysToValues: MetadataKeyValuePair[],
|
keysToValues: MetadataKeyValuePair[],
|
||||||
): Promise<void[]> => requestUpdateMetadata(manga, 'manga', keysToValues);
|
): Promise<void[]> => requestUpdateMetadata(manga, 'manga', keysToValues);
|
||||||
|
|
||||||
export const requestUpdateChapterMetadata = async (
|
export const requestUpdateChapterMetadata = async (
|
||||||
mangaChapter: IMangaChapter,
|
chapter: ChapterType,
|
||||||
keysToValues: MetadataKeyValuePair[],
|
keysToValues: MetadataKeyValuePair[],
|
||||||
): Promise<void[]> => requestUpdateMetadata(mangaChapter.chapter, 'chapter', keysToValues);
|
): Promise<void[]> => requestUpdateMetadata(chapter, 'chapter', keysToValues);
|
||||||
|
|
||||||
export const requestUpdateCategoryMetadata = async (
|
export const requestUpdateCategoryMetadata = async (
|
||||||
category: ICategory,
|
category: CategoryType,
|
||||||
keysToValues: MetadataKeyValuePair[],
|
keysToValues: MetadataKeyValuePair[],
|
||||||
): Promise<void[]> => requestUpdateMetadata(category, 'category', keysToValues);
|
): Promise<void[]> => requestUpdateMetadata(category, 'category', keysToValues);
|
||||||
|
|
||||||
export const convertGqlMetadata = (gqlMetadata?: MetaType[]): Metadata | undefined => {
|
|
||||||
if (!gqlMetadata) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const metadata: Metadata = {};
|
|
||||||
gqlMetadata.forEach(({ key, value }) => {
|
|
||||||
metadata[key] = value;
|
|
||||||
});
|
|
||||||
|
|
||||||
return metadata;
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -6,14 +6,15 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { IManga, Metadata, MetadataHolder, IReaderSettings, MetadataKeyValuePair } from '@/typings';
|
import { Metadata, IReaderSettings, MetadataKeyValuePair, GqlMetaHolder } from '@/typings';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import requestManager from '@/lib/requests/RequestManager.ts';
|
||||||
import {
|
import {
|
||||||
convertGqlMetadata,
|
convertFromGqlMeta,
|
||||||
getMetadataFrom,
|
getMetadataFrom,
|
||||||
requestUpdateMangaMetadata,
|
requestUpdateMangaMetadata,
|
||||||
requestUpdateServerMetadata,
|
requestUpdateServerMetadata,
|
||||||
} from '@/util/metadata';
|
} from '@/util/metadata';
|
||||||
|
import { MangaType, MetaType } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
type UndefinedReaderSettings = {
|
type UndefinedReaderSettings = {
|
||||||
[setting in keyof IReaderSettings]: IReaderSettings[setting] | undefined;
|
[setting in keyof IReaderSettings]: IReaderSettings[setting] | undefined;
|
||||||
@@ -42,10 +43,10 @@ export const getReaderSettingsFromMetadata = (
|
|||||||
): IReaderSettings => getReaderSettingsWithDefaultValueFallback(meta, defaultSettings, applyMetadataMigration);
|
): IReaderSettings => getReaderSettingsWithDefaultValueFallback(meta, defaultSettings, applyMetadataMigration);
|
||||||
|
|
||||||
export const getReaderSettingsFor = (
|
export const getReaderSettingsFor = (
|
||||||
{ meta }: MetadataHolder,
|
{ meta }: GqlMetaHolder = {},
|
||||||
defaultSettings?: IReaderSettings,
|
defaultSettings?: IReaderSettings,
|
||||||
applyMetadataMigration?: boolean,
|
applyMetadataMigration?: boolean,
|
||||||
): IReaderSettings => getReaderSettingsFromMetadata(meta, defaultSettings, applyMetadataMigration);
|
): IReaderSettings => getReaderSettingsFromMetadata(convertFromGqlMeta(meta), defaultSettings, applyMetadataMigration);
|
||||||
|
|
||||||
export const useDefaultReaderSettings = (): {
|
export const useDefaultReaderSettings = (): {
|
||||||
metadata?: Metadata;
|
metadata?: Metadata;
|
||||||
@@ -53,7 +54,7 @@ export const useDefaultReaderSettings = (): {
|
|||||||
loading: boolean;
|
loading: boolean;
|
||||||
} => {
|
} => {
|
||||||
const { data, loading } = requestManager.useGetGlobalMeta();
|
const { data, loading } = requestManager.useGetGlobalMeta();
|
||||||
const metadata = convertGqlMetadata(data?.metas.nodes);
|
const metadata = convertFromGqlMeta(data?.metas.nodes);
|
||||||
const settings = getReaderSettingsWithDefaultValueFallback<IReaderSettings>(metadata);
|
const settings = getReaderSettingsWithDefaultValueFallback<IReaderSettings>(metadata);
|
||||||
|
|
||||||
return { metadata, settings, loading };
|
return { metadata, settings, loading };
|
||||||
@@ -67,11 +68,12 @@ export const useDefaultReaderSettings = (): {
|
|||||||
* @param defaultSettings
|
* @param defaultSettings
|
||||||
*/
|
*/
|
||||||
export const checkAndHandleMissingStoredReaderSettings = async (
|
export const checkAndHandleMissingStoredReaderSettings = async (
|
||||||
metadataHolder: IManga | MetadataHolder,
|
metadataHolder: Required<GqlMetaHolder> | MetaType[],
|
||||||
metadataHolderType: 'manga' | 'server',
|
metadataHolderType: 'manga' | 'server',
|
||||||
defaultSettings: IReaderSettings,
|
defaultSettings: IReaderSettings,
|
||||||
): Promise<void | void[]> => {
|
): Promise<void | void[]> => {
|
||||||
const meta = metadataHolder.meta ?? (metadataHolder as Metadata);
|
const getMeta = () => (Array.isArray(metadataHolder) ? metadataHolder : metadataHolder.meta);
|
||||||
|
const meta = convertFromGqlMeta(getMeta())!;
|
||||||
const settingsToCheck = getReaderSettingsWithDefaultValueFallback(
|
const settingsToCheck = getReaderSettingsWithDefaultValueFallback(
|
||||||
meta,
|
meta,
|
||||||
{
|
{
|
||||||
@@ -85,7 +87,7 @@ export const checkAndHandleMissingStoredReaderSettings = async (
|
|||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
const newSettings = getReaderSettingsFor({ meta }, defaultSettings);
|
const newSettings = getReaderSettingsFor({ meta: getMeta() }, defaultSettings);
|
||||||
|
|
||||||
const undefinedSettings = Object.entries(settingsToCheck).filter((setting) => setting[1] === undefined);
|
const undefinedSettings = Object.entries(settingsToCheck).filter((setting) => setting[1] === undefined);
|
||||||
|
|
||||||
@@ -101,9 +103,9 @@ export const checkAndHandleMissingStoredReaderSettings = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (metadataHolderType === 'manga') {
|
if (metadataHolderType === 'manga') {
|
||||||
await requestUpdateMangaMetadata(metadataHolder as IManga, settingsToUpdate);
|
await requestUpdateMangaMetadata(metadataHolder as MangaType, settingsToUpdate);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await requestUpdateServerMetadata(meta, settingsToUpdate);
|
await requestUpdateServerMetadata(metadataHolder as MetaType[], settingsToUpdate);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import { Metadata, ISearchSettings } from '@/typings';
|
import { Metadata, ISearchSettings } from '@/typings';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import requestManager from '@/lib/requests/RequestManager.ts';
|
||||||
import { convertGqlMetadata, getMetadataFrom } from '@/util/metadata';
|
import { convertFromGqlMeta, getMetadataFrom } from '@/util/metadata';
|
||||||
|
|
||||||
export const getDefaultSettings = (): ISearchSettings => ({
|
export const getDefaultSettings = (): ISearchSettings => ({
|
||||||
ignoreFilters: false,
|
ignoreFilters: false,
|
||||||
@@ -25,7 +25,7 @@ export const useSearchSettings = (): {
|
|||||||
loading: boolean;
|
loading: boolean;
|
||||||
} => {
|
} => {
|
||||||
const { data, loading } = requestManager.useGetGlobalMeta();
|
const { data, loading } = requestManager.useGetGlobalMeta();
|
||||||
const metadata = convertGqlMetadata(data?.metas.nodes);
|
const metadata = convertFromGqlMeta(data?.metas.nodes);
|
||||||
const settings = getSearchSettingsWithDefaultValueFallback(metadata);
|
const settings = getSearchSettingsWithDefaultValueFallback(metadata);
|
||||||
|
|
||||||
return { metadata, settings, loading };
|
return { metadata, settings, loading };
|
||||||
|
|||||||
Reference in New Issue
Block a user