/*
* 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 { Tab, Tabs } from '@mui/material';
import React, { useContext, useEffect, useState } from 'react';
import NavbarContext from 'components/context/NavbarContext';
import client from 'util/client';
import cloneObject from 'util/cloneObject';
import EmptyView from 'components/util/EmptyView';
import LoadingPlaceholder from 'components/util/LoadingPlaceholder';
import TabPanel from 'components/util/TabPanel';
import LibraryOptions from 'components/library/LibraryOptions';
import LibraryMangaGrid from 'components/library/LibraryMangaGrid';
import LibrarySearch from 'components/library/LibrarySearch';
import { useHistory, useParams } from 'react-router-dom';
interface IMangaCategory {
category: ICategory
mangas: IManga[]
isFetched: boolean
}
export default function Library() {
const { setTitle, setAction } = useContext(NavbarContext);
useEffect(() => {
setTitle('Library'); setAction(
<>
>,
);
}, []);
const { tabParamNumber } = useParams<{ tabParamNumber: string }>();
const [tabs, setTabs] = useState();
const [tabNum, setTabNum] = useState(0);
const history = useHistory();
// a hack so MangaGrid doesn't stop working. I won't change it in case
// if I do manga pagination for library..
const [lastPageNum, setLastPageNum] = useState(1);
const handleTabChange = (newTab: number) => {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
history.location.search === ''
? history.replace(`/library/${newTab}`)
: history.replace(`/library/${newTab}/${history.location.search}`);
setTabNum(newTab);
};
useEffect(() => {
client.get('/api/v1/category')
.then((response) => response.data)
.then((categories: ICategory[]) => {
const categoryTabs = categories.map((category) => ({
category,
mangas: [] as IManga[],
isFetched: false,
}));
setTabs(categoryTabs);
if (categoryTabs.length > 0) {
setTabNum(() => {
if (tabParamNumber !== undefined
&& !Number.isNaN(tabParamNumber)
&& !!categories.find((cat) => cat.order === Number(tabParamNumber))) {
return Number(tabParamNumber);
}
history.replace('/library');
return categoryTabs[0].category.order;
});
}
});
}, []);
// fetch the current tab
useEffect(() => {
if (tabs !== undefined) {
tabs.forEach((tab, index) => {
if (tab.category.order === tabNum && !tab.isFetched) {
// eslint-disable-next-line @typescript-eslint/no-shadow
client.get(`/api/v1/category/${tab.category.id}`)
.then((response) => response.data)
.then((data: IManga[]) => {
const tabsClone = cloneObject(tabs);
tabsClone[index].mangas = data;
tabsClone[index].isFetched = true;
setTabs(tabsClone);
});
}
});
}
}, [tabs?.length, tabNum]);
if (tabs === undefined) {
return ;
}
if (tabs.length === 0) {
return ;
}
let toRender;
if (tabs.length > 1) {
// eslint-disable-next-line max-len
const tabDefines = tabs.map((tab) => ());
const tabBodies = tabs.map((tab) => (
));
// Visual Hack: 160px is min-width for viewport width of >600
const scrollableTabs = window.innerWidth < tabs.length * 160;
toRender = (
<>
handleTabChange(newTab)}
indicatorColor="primary"
textColor="primary"
centered={!scrollableTabs}
variant={scrollableTabs ? 'scrollable' : 'fullWidth'}
scrollButtons
allowScrollButtonsMobile
>
{tabDefines}
{tabBodies}
>
);
} else {
const mangas = tabs.length === 1 ? tabs[0].mangas : [];
toRender = (
);
}
return toRender;
}