/* * 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'; import Box from '@mui/material/Box'; import { useEffect, useMemo, useRef, useState } from 'react'; import DialogContent from '@mui/material/DialogContent'; import { useTranslation } from 'react-i18next'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { LoadingPlaceholder } from '@/modules/core/components/feedback/LoadingPlaceholder.tsx'; import { Trackers } from '@/modules/tracker/services/Trackers.ts'; import { TrackerCard, TrackerMode } from '@/modules/tracker/components/cards/TrackerCard.tsx'; import { makeToast } from '@/modules/core/utils/Toast.ts'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; import { GetMangaTrackRecordsQuery, GetTrackersBindQuery, MangaType } from '@/lib/graphql/generated/graphql.ts'; import { GET_TRACKERS_BIND } from '@/lib/graphql/queries/TrackerQuery.ts'; import { GET_MANGA_TRACK_RECORDS } from '@/lib/graphql/queries/MangaQuery.ts'; import { MangaIdInfo } from '@/modules/manga/Manga.types.ts'; import { AppRoutes } from '@/modules/core/AppRoute.constants.ts'; import { getErrorMessage } from '@/lib/HelperFunctions.ts'; import { EmptyView } from '@/modules/core/components/feedback/EmptyView.tsx'; 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; }; export const TrackManga = ({ manga }: { manga: MangaIdInfo & Pick }) => { const { t } = useTranslation(); const navigate = useNavigate(); const [searchModeForTracker, setSearchModeForTracker] = useState(); const trackerList = requestManager.useGetTrackerList(GET_TRACKERS_BIND, { notifyOnNetworkStatusChange: true, }); const trackers = trackerList.data?.trackers.nodes ?? []; const mangaTrackRecordsList = requestManager.useGetManga( GET_MANGA_TRACK_RECORDS, manga.id, ); const mangaTrackRecords = mangaTrackRecordsList.data?.manga.trackRecords.nodes ?? []; const loggedInTrackers = Trackers.getLoggedIn(trackers); const trackersInUse = Trackers.getLoggedIn(Trackers.getTrackers(mangaTrackRecords, trackers)); const trackersInUseIds = Trackers.getIds(trackersInUse); const isSearchActive = searchModeForTracker !== undefined; const OptionalDialogContent = useMemo(() => (isSearchActive ? Box : DialogContent), [isSearchActive]); const loading = trackerList.loading || mangaTrackRecordsList.loading; const error = trackerList.error ?? mangaTrackRecordsList.error; useEffect(() => { if (!loading && !error && !trackersInUse.length && !loggedInTrackers.length) { navigate(AppRoutes.tracker.path); } }, [loading]); const fetchedLatestTrackDataRef = useRef(false); useEffect(() => { if (!mangaTrackRecords.length || fetchedLatestTrackDataRef.current) { return; } fetchedLatestTrackDataRef.current = true; Promise.all( mangaTrackRecords.map((trackRecord) => requestManager.fetchTrackBind(trackRecord.id).response), ).catch((e) => makeToast(t('tracking.error.label.could_not_fetch_track_info'), 'error', getErrorMessage(e))); }, [mangaTrackRecords]); const trackerComponents = useMemo( () => loggedInTrackers.map((tracker) => { const mode = getTrackerMode(tracker.id, trackersInUseIds, searchModeForTracker); const trackRecord = Trackers.getTrackRecordFor(tracker, mangaTrackRecords); const isSearchForTracker = mode === TrackerMode.SEARCH; if (isSearchActive && !isSearchForTracker) { return null; } return ( setSearchModeForTracker(id)} /> ); }), [trackersInUseIds, searchModeForTracker, mangaTrackRecords], ); if (error) { return ( { if (trackerList.error) { trackerList.refetch().catch(defaultPromiseErrorHandler('TrackManga::refetch: trackerList')); } if (mangaTrackRecordsList.error) { mangaTrackRecordsList .refetch() .catch(defaultPromiseErrorHandler('TrackManga::refetch: mangaTrackRecordsList')); } }} /> ); } if (loading) { return ; } if (!isSearchActive) { return ( {trackerComponents} ); } return trackerComponents; };