Refactor base app layout
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
||||
import Tab from '@mui/material/Tab';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Sources } from '@/screens/Sources';
|
||||
@@ -16,11 +16,19 @@ import { TabsWrapper } from '@/components/tabs/TabsWrapper.tsx';
|
||||
import { TabsMenu } from '@/components/tabs/TabsMenu.tsx';
|
||||
import { Migration } from '@/screens/Migration.tsx';
|
||||
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||
import { useResizeObserver } from '@/util/useResizeObserver.tsx';
|
||||
|
||||
export function Browse() {
|
||||
const { t } = useTranslation();
|
||||
const { setTitle } = useContext(NavBarContext);
|
||||
|
||||
const tabsMenuRef = useRef<HTMLDivElement | null>(null);
|
||||
const [tabsMenuHeight, setTabsMenuHeight] = useState(0);
|
||||
useResizeObserver(
|
||||
tabsMenuRef,
|
||||
useCallback(() => setTabsMenuHeight(tabsMenuRef.current!.offsetHeight), [tabsMenuRef]),
|
||||
);
|
||||
|
||||
const [tabNum, setTabNum] = useState<number>(0);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -29,7 +37,7 @@ export function Browse() {
|
||||
|
||||
return (
|
||||
<TabsWrapper>
|
||||
<TabsMenu value={tabNum} tabsCount={2} onChange={(e, newTab) => setTabNum(newTab)}>
|
||||
<TabsMenu ref={tabsMenuRef} value={tabNum} tabsCount={2} onChange={(e, newTab) => setTabNum(newTab)}>
|
||||
<Tab sx={{ textTransform: 'none' }} label={t('source.title_one')} />
|
||||
<Tab sx={{ textTransform: 'none' }} label={t('extension.title_other')} />
|
||||
<Tab sx={{ textTransform: 'none' }} label={t('migrate.title')} />
|
||||
@@ -38,7 +46,7 @@ export function Browse() {
|
||||
<Sources />
|
||||
</TabPanel>
|
||||
<TabPanel index={1} currentIndex={tabNum}>
|
||||
<Extensions />
|
||||
<Extensions tabsMenuHeight={tabsMenuHeight} />
|
||||
</TabPanel>
|
||||
<TabPanel index={2} currentIndex={tabNum}>
|
||||
<Migration />
|
||||
|
||||
@@ -39,7 +39,6 @@ import { StyledGroupHeader } from '@/components/virtuoso/StyledGroupHeader.tsx';
|
||||
import { StyledGroupItemWrapper } from '@/components/virtuoso/StyledGroupItemWrapper.tsx';
|
||||
import { EmptyViewAbsoluteCentered } from '@/components/util/EmptyViewAbsoluteCentered.tsx';
|
||||
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
|
||||
import { MediaQuery } from '@/lib/ui/MediaQuery.tsx';
|
||||
|
||||
const LANGUAGE = 0;
|
||||
const EXTENSIONS = 1;
|
||||
@@ -98,12 +97,10 @@ function getExtensionsInfo(extensions: TExtension[]): {
|
||||
};
|
||||
}
|
||||
|
||||
export function Extensions() {
|
||||
export function Extensions({ tabsMenuHeight }: { tabsMenuHeight: number }) {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useContext(NavBarContext);
|
||||
|
||||
const isMobileWidth = MediaQuery.useIsMobileWidth();
|
||||
|
||||
const {
|
||||
data: serverSettingsData,
|
||||
loading: areServerSettingsLoading,
|
||||
@@ -281,34 +278,14 @@ export function Extensions() {
|
||||
{toasts}
|
||||
{FileInputComponent}
|
||||
<StyledGroupedVirtuoso
|
||||
style={{
|
||||
// override Virtuoso default values and set them with class
|
||||
height: 'undefined',
|
||||
}}
|
||||
heightToSubtract={
|
||||
isMobileWidth
|
||||
? // desktop: TabsMenu height
|
||||
48
|
||||
: // desktop: TabsMenu height - TabsMenu bottom padding + grid item top padding
|
||||
48 + 13 - 8
|
||||
}
|
||||
heightToSubtract={tabsMenuHeight}
|
||||
overscan={window.innerHeight * 0.5}
|
||||
groupCounts={groupCounts}
|
||||
groupContent={(index) => {
|
||||
const [groupName] = filteredGroupedExtensions[index];
|
||||
|
||||
return (
|
||||
<StyledGroupHeader
|
||||
key={groupName}
|
||||
variant="h4"
|
||||
style={{
|
||||
paddingLeft: '24px',
|
||||
paddingTop: '6px',
|
||||
paddingBottom: '16px',
|
||||
fontWeight: 'bold',
|
||||
}}
|
||||
isFirstItem={index === 0}
|
||||
>
|
||||
<StyledGroupHeader key={groupName} variant="h4" isFirstItem={index === 0}>
|
||||
{translateExtensionLanguage(groupName)}
|
||||
</StyledGroupHeader>
|
||||
);
|
||||
@@ -319,7 +296,6 @@ export function Extensions() {
|
||||
return (
|
||||
<StyledGroupItemWrapper
|
||||
key={`${item.pkgName}_${item.isInstalled}_${item.isObsolete}_${item.hasUpdate}`}
|
||||
isLastItem={index === visibleExtensions.length - 1}
|
||||
>
|
||||
<ExtensionCard
|
||||
extension={item}
|
||||
|
||||
@@ -65,11 +65,8 @@ export const Migration = () => {
|
||||
|
||||
return (
|
||||
<List>
|
||||
{Object.values(migratableSources).map((migratableSource, index) => (
|
||||
<StyledGroupItemWrapper
|
||||
key={migratableSource.id}
|
||||
isLastItem={index === Object.values(migratableSources).length - 1}
|
||||
>
|
||||
{Object.values(migratableSources).map((migratableSource) => (
|
||||
<StyledGroupItemWrapper key={migratableSource.id}>
|
||||
<MigrationCard {...migratableSource} />
|
||||
</StyledGroupItemWrapper>
|
||||
))}
|
||||
|
||||
@@ -25,9 +25,9 @@ import { MangaCardProps } from '@/components/manga/MangaCard.types.tsx';
|
||||
import { EmptyView } from '@/components/util/EmptyView';
|
||||
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
|
||||
import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder.tsx';
|
||||
import { EmptyViewAbsoluteCentered } from '@/components/util/EmptyViewAbsoluteCentered.tsx';
|
||||
import { SourceType } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { BaseMangaGrid } from '@/components/source/BaseMangaGrid.tsx';
|
||||
import { EmptyViewAbsoluteCentered } from '@/components/util/EmptyViewAbsoluteCentered.tsx';
|
||||
|
||||
type SourceLoadingState = { isLoading: boolean; hasResults: boolean; emptySearch: boolean };
|
||||
type SourceToLoadingStateMap = Map<string, SourceLoadingState>;
|
||||
@@ -152,7 +152,7 @@ const SourceSearchPreview = React.memo(
|
||||
</Card>
|
||||
{errorMessage ? (
|
||||
<EmptyView
|
||||
sx={{ alignItems: 'start' }}
|
||||
sx={{ alignItems: 'start', height: undefined }}
|
||||
noFaces
|
||||
message={errorMessage}
|
||||
messageExtra={error && error.message}
|
||||
|
||||
@@ -163,7 +163,7 @@ export const Updates: React.FC = () => {
|
||||
const download = downloadForChapter(chapter);
|
||||
|
||||
return (
|
||||
<StyledGroupItemWrapper key={index} isLastItem={index === updateEntries.length - 1}>
|
||||
<StyledGroupItemWrapper key={index}>
|
||||
<Card>
|
||||
<CardActionArea
|
||||
component={Link}
|
||||
|
||||
@@ -238,11 +238,7 @@ export function Categories() {
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={dialogDefault}
|
||||
onChange={(e) => setDialogDefault(e.target.checked)}
|
||||
color="default"
|
||||
/>
|
||||
<Checkbox checked={dialogDefault} onChange={(e) => setDialogDefault(e.target.checked)} />
|
||||
}
|
||||
label={t('category.label.use_as_default_category')}
|
||||
/>
|
||||
|
||||
@@ -35,6 +35,7 @@ import { GET_MANGAS_DUPLICATES } from '@/lib/graphql/queries/MangaQuery.ts';
|
||||
import { MangaIdInfo } from '@/lib/data/Mangas.ts';
|
||||
import { BaseMangaGrid } from '@/components/source/BaseMangaGrid.tsx';
|
||||
import { IMangaGridProps } from '@/components/MangaGrid.tsx';
|
||||
import { StyledGroupItemWrapper } from '@/components/virtuoso/StyledGroupItemWrapper.tsx';
|
||||
|
||||
const findDuplicatesByTitle = <Manga extends Pick<MangaType, 'title'>>(
|
||||
libraryMangas: Manga[],
|
||||
@@ -174,10 +175,6 @@ export const LibraryDuplicates = () => {
|
||||
if (gridLayout === GridLayout.List) {
|
||||
return (
|
||||
<StyledGroupedVirtuoso
|
||||
style={{
|
||||
// override Virtuoso default values and set them with class
|
||||
height: 'undefined',
|
||||
}}
|
||||
groupCounts={mangasCountByTitle}
|
||||
groupContent={(index) => (
|
||||
<StyledGroupHeader variant="h5" isFirstItem={index === 0}>
|
||||
@@ -185,14 +182,14 @@ export const LibraryDuplicates = () => {
|
||||
</StyledGroupHeader>
|
||||
)}
|
||||
itemContent={(index) => (
|
||||
<Box key={duplicatedMangas[index].id} sx={{ px: 1, pb: 1 }}>
|
||||
<StyledGroupItemWrapper key={duplicatedMangas[index].id}>
|
||||
<MangaCard
|
||||
manga={duplicatedMangas[index] as IMangaGridProps['mangas'][number]}
|
||||
gridLayout={gridLayout}
|
||||
selected={null}
|
||||
mode="duplicate"
|
||||
/>
|
||||
</Box>
|
||||
</StyledGroupItemWrapper>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user