2024-03-10 17:36:22 +01:00
|
|
|
/*
|
|
|
|
|
* 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 { useNavigate } from 'react-router-dom';
|
2024-04-14 15:50:12 +02:00
|
|
|
import Box from '@mui/material/Box';
|
2024-04-03 22:34:48 +02:00
|
|
|
import { useEffect, useMemo, useState } from 'react';
|
2024-03-10 17:36:22 +01:00
|
|
|
import DialogContent from '@mui/material/DialogContent';
|
2024-04-03 22:34:48 +02:00
|
|
|
import { useTranslation } from 'react-i18next';
|
2024-03-10 17:36:22 +01:00
|
|
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
2024-04-29 15:29:33 +02:00
|
|
|
import { EmptyViewAbsoluteCentered } from '@/components/util/EmptyViewAbsoluteCentered.tsx';
|
2024-03-10 17:36:22 +01:00
|
|
|
import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder.tsx';
|
|
|
|
|
import { Trackers } from '@/lib/data/Trackers.ts';
|
|
|
|
|
import { TrackerCard, TrackerMode } from '@/components/tracker/TrackerCard.tsx';
|
|
|
|
|
import { TManga } from '@/typings.ts';
|
2024-04-03 22:34:48 +02:00
|
|
|
import { makeToast } from '@/components/util/Toast.tsx';
|
2024-04-27 22:14:42 +02:00
|
|
|
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
|
2024-07-04 22:00:39 +02:00
|
|
|
import { GetTrackersBindQuery } from '@/lib/graphql/generated/graphql.ts';
|
|
|
|
|
import { GET_TRACKERS_BIND } from '@/lib/graphql/queries/TrackerQuery.ts';
|
2024-03-10 17:36:22 +01:00
|
|
|
|
|
|
|
|
const getTrackerMode = (id: number, trackersInUse: number[], searchModeForTracker?: number): TrackerMode => {
|
|
|
|
|
if (id === searchModeForTracker) {
|
|
|
|
|
return TrackerMode.SEARCH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (trackersInUse.includes(id)) {
|
|
|
|
|
return TrackerMode.INFO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TrackerMode.UNTRACKED;
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-28 17:19:20 +01:00
|
|
|
export const TrackManga = ({ manga }: { manga: Pick<TManga, 'id' | 'trackRecords'> }) => {
|
2024-04-03 22:34:48 +02:00
|
|
|
const { t } = useTranslation();
|
2024-03-10 17:36:22 +01:00
|
|
|
const navigate = useNavigate();
|
|
|
|
|
|
|
|
|
|
const [searchModeForTracker, setSearchModeForTracker] = useState<number>();
|
|
|
|
|
|
2024-07-04 22:00:39 +02:00
|
|
|
const trackerList = requestManager.useGetTrackerList<GetTrackersBindQuery>(GET_TRACKERS_BIND, {
|
|
|
|
|
notifyOnNetworkStatusChange: true,
|
|
|
|
|
});
|
2024-03-10 17:36:22 +01:00
|
|
|
const mangaTrackers = manga.trackRecords.nodes;
|
|
|
|
|
|
|
|
|
|
const loggedInTrackers = Trackers.getLoggedIn(trackerList.data?.trackers.nodes ?? []);
|
|
|
|
|
const trackersInUse = Trackers.getLoggedIn(Trackers.getTrackers(mangaTrackers));
|
|
|
|
|
const trackersInUseIds = Trackers.getIds(trackersInUse);
|
|
|
|
|
|
|
|
|
|
const isSearchActive = searchModeForTracker !== undefined;
|
|
|
|
|
const OptionalDialogContent = useMemo(() => (isSearchActive ? Box : DialogContent), [isSearchActive]);
|
|
|
|
|
|
2024-04-03 22:34:48 +02:00
|
|
|
useEffect(() => {
|
|
|
|
|
Promise.all(manga.trackRecords.nodes.map((trackRecord) => requestManager.fetchTrackBind(trackRecord.id))).catch(
|
|
|
|
|
() => makeToast(t('tracking.error.label.could_not_fetch_track_info'), 'error'),
|
|
|
|
|
);
|
|
|
|
|
}, [manga.id]);
|
|
|
|
|
|
2024-03-10 17:36:22 +01:00
|
|
|
const trackerComponents = useMemo(
|
|
|
|
|
() =>
|
|
|
|
|
loggedInTrackers.map((tracker) => {
|
|
|
|
|
const mode = getTrackerMode(tracker.id, trackersInUseIds, searchModeForTracker);
|
|
|
|
|
const trackRecord = Trackers.getTrackRecordFor(tracker, manga.trackRecords.nodes);
|
|
|
|
|
|
|
|
|
|
const isSearchForTracker = mode === TrackerMode.SEARCH;
|
|
|
|
|
if (isSearchActive && !isSearchForTracker) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<TrackerCard
|
|
|
|
|
key={tracker.id}
|
|
|
|
|
tracker={tracker}
|
|
|
|
|
mangaId={manga.id}
|
|
|
|
|
trackRecord={trackRecord}
|
|
|
|
|
mode={mode}
|
|
|
|
|
setSearchMode={(id) => setSearchModeForTracker(id)}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
}),
|
|
|
|
|
[trackersInUseIds, searchModeForTracker, manga.id],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (trackerList.error) {
|
2024-04-27 22:14:42 +02:00
|
|
|
return (
|
2024-04-29 15:29:33 +02:00
|
|
|
<EmptyViewAbsoluteCentered
|
2024-04-27 22:14:42 +02:00
|
|
|
message={t('global.error.label.failed_to_load_data')}
|
|
|
|
|
messageExtra={trackerList.error.message}
|
|
|
|
|
retry={() => trackerList.refetch().catch(defaultPromiseErrorHandler('TrackManga::refetch'))}
|
|
|
|
|
/>
|
|
|
|
|
);
|
2024-03-10 17:36:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (trackerList.loading) {
|
|
|
|
|
return <LoadingPlaceholder />;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!loggedInTrackers) {
|
|
|
|
|
navigate('/settings/trackingSettings');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isSearchActive) {
|
|
|
|
|
return (
|
2024-03-29 16:54:53 +01:00
|
|
|
<OptionalDialogContent
|
|
|
|
|
sx={{
|
|
|
|
|
padding: 0,
|
|
|
|
|
// MUI adds a bottom padding to the last child of type CardContent which can only be removed via actual css styling
|
|
|
|
|
// do it here, so it is done in one place for all track related CardContent components
|
|
|
|
|
'.MuiPaper-root .MuiCardContent-root': { paddingBottom: '0' },
|
|
|
|
|
}}
|
|
|
|
|
>
|
2024-03-10 17:36:22 +01:00
|
|
|
{trackerComponents}
|
|
|
|
|
</OptionalDialogContent>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return trackerComponents;
|
|
|
|
|
};
|