Feature/merge source and extensions screen on desktop (#535)
* Merge "source" and "extension" screen for desktop * Move "tab" related components into new folder * Reuse "tab" components for "browse" screen * Prevent extension list from being taller than 100% of the parents height - remove margin - virtuoso has issues calculating the height otherwise - change group title styling, fontSize caused issues * Align "source" list group header with "extension" * Remove bottom padding from "ExtensionCard" * Move "GroupedVirtuoso" related components into folder * Use "GroupedVirtuoso" for "extensions" There was an issue with the height calculation of the virtuoso list, which apparently was caused by the conditional rendering of the group title and item as list items. Due to this, while scrolling down, the virtuoso list caused an overflow, which rendered the scrollbar, which in turn caused the list items to shrink in width. The end result of this was, that the list items "jumped" slightly on the initial render of the items, due to the scrollbar appearing and disappearing
This commit is contained in:
@@ -11,9 +11,9 @@ import { fromEvent } from 'file-selector';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import { StringParam, useQueryParam } from 'use-query-params';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
import { Tooltip, Typography, useMediaQuery, useTheme } from '@mui/material';
|
||||
import { Tooltip, useMediaQuery } from '@mui/material';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import { extensionDefaultLangs, DefaultLanguage, langSortCmp } from '@/util/language';
|
||||
import { useLocalStorage } from '@/util/useLocalStorage';
|
||||
@@ -31,6 +31,9 @@ import { LangSelect } from '@/components/navbar/action/LangSelect';
|
||||
import { ExtensionCard } from '@/components/ExtensionCard';
|
||||
import { PartialExtension } from '@/typings.ts';
|
||||
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||
import { StyledGroupedVirtuoso } from '@/components/virtuoso/StyledGroupedVirtuoso.tsx';
|
||||
import { StyledGroupHeader } from '@/components/virtuoso/StyledGroupHeader.tsx';
|
||||
import { StyledGroupItemWrapper } from '@/components/virtuoso/StyledGroupItemWrapper.tsx';
|
||||
|
||||
const LANGUAGE = 0;
|
||||
const EXTENSIONS = 1;
|
||||
@@ -92,12 +95,13 @@ function getExtensionsInfo(extensions: PartialExtension[]): {
|
||||
export function Extensions() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const theme = useTheme();
|
||||
const isMobileWidth = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const { setTitle, setAction } = useContext(NavBarContext);
|
||||
const [shownLangs, setShownLangs] = useLocalStorage<string[]>('shownExtensionLangs', extensionDefaultLangs());
|
||||
const [showNsfw] = useLocalStorage<boolean>('showNsfw', true);
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
const [query] = useQueryParam('query', StringParam);
|
||||
|
||||
const [refetchExtensions, setRefetchExtensions] = useState({});
|
||||
@@ -130,7 +134,14 @@ export function Extensions() {
|
||||
[shownLangs, groupedExtensions],
|
||||
);
|
||||
|
||||
const flatRenderItems: (PartialExtension | string)[] = filteredGroupedExtensions.flat(2);
|
||||
const groupCounts = useMemo(
|
||||
() => filteredGroupedExtensions.map((extensionGroup) => extensionGroup[EXTENSIONS].length - 1),
|
||||
[filteredGroupedExtensions],
|
||||
);
|
||||
const visibleExtensions = useMemo(
|
||||
() => filteredGroupedExtensions.map(([, extensions]) => extensions).flat(1),
|
||||
[filteredGroupedExtensions],
|
||||
);
|
||||
|
||||
const [toasts, makeToast] = makeToaster(useState<React.ReactElement[]>([]));
|
||||
|
||||
@@ -206,33 +217,47 @@ export function Extensions() {
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Virtuoso
|
||||
<StyledGroupedVirtuoso
|
||||
style={{
|
||||
height: isMobile ? 'calc(100vh - 64px - 64px)' : 'calc(100vh - 64px)',
|
||||
// override Virtuoso default values and set them with class
|
||||
height: 'undefined',
|
||||
}}
|
||||
totalCount={flatRenderItems.length}
|
||||
itemContent={(index) => {
|
||||
if (typeof flatRenderItems[index] === 'string') {
|
||||
const item = flatRenderItems[index] as string;
|
||||
return (
|
||||
<Typography
|
||||
key={item}
|
||||
variant="h2"
|
||||
style={{
|
||||
paddingLeft: 25,
|
||||
paddingBottom: '0.83em',
|
||||
paddingTop: '0.83em',
|
||||
fontSize: '2em',
|
||||
fontWeight: 'bold',
|
||||
}}
|
||||
>
|
||||
{translateExtensionLanguage(item)}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
const item = flatRenderItems[index] as PartialExtension;
|
||||
heightToSubtract={
|
||||
isMobileWidth
|
||||
? // desktop: TabsMenu height
|
||||
48
|
||||
: // desktop: TabsMenu height - TabsMenu bottom padding + grid item top padding
|
||||
48 + 13 - 8
|
||||
}
|
||||
overscan={window.innerHeight * 0.5}
|
||||
groupCounts={groupCounts}
|
||||
groupContent={(index) => {
|
||||
const [groupName] = filteredGroupedExtensions[index];
|
||||
|
||||
return <ExtensionCard key={item.apkName} extension={item} handleUpdate={handleExtensionUpdate} />;
|
||||
return (
|
||||
<StyledGroupHeader
|
||||
key={groupName}
|
||||
variant="h4"
|
||||
style={{
|
||||
paddingLeft: '24px',
|
||||
paddingTop: '6px',
|
||||
paddingBottom: '16px',
|
||||
fontWeight: 'bold',
|
||||
}}
|
||||
isFirstItem={index === 0}
|
||||
>
|
||||
{translateExtensionLanguage(groupName)}
|
||||
</StyledGroupHeader>
|
||||
);
|
||||
}}
|
||||
itemContent={(index) => {
|
||||
const item = visibleExtensions[index];
|
||||
|
||||
return (
|
||||
<StyledGroupItemWrapper key={item.apkName} isLastItem={index === visibleExtensions.length - 1}>
|
||||
<ExtensionCard extension={item} handleUpdate={handleExtensionUpdate} />
|
||||
</StyledGroupItemWrapper>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user