Refactor base app layout

This commit is contained in:
schroda
2024-07-11 17:22:52 +02:00
parent 31837392b5
commit f43b7af3cd
19 changed files with 443 additions and 288 deletions

View File

@@ -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 />

View File

@@ -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}

View File

@@ -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>
))}

View File

@@ -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}

View File

@@ -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}

View File

@@ -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')}
/>

View File

@@ -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>
)}
/>
);