Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/reader infinite scroll #865

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/lib/HelperFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,5 @@ export const getValueFromObject = <T>(obj: Record<string, any>, key: string): T
};

export const coerceIn = (value: number, min: number, max: number): number => Math.min(Math.max(value, min), max);

export const noOp = () => {};
6 changes: 3 additions & 3 deletions src/modules/backup/screens/Backup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

import { useContext, useEffect, useLayoutEffect, useState } from 'react';
import { useEffect, useLayoutEffect, useState } from 'react';
import List from '@mui/material/List';
import ListItemText from '@mui/material/ListItemText';
import { fromEvent } from 'file-selector';
Expand All @@ -25,7 +25,6 @@ import { Link } from 'react-router-dom';
import Stack from '@mui/material/Stack';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { makeToast } from '@/modules/core/utils/Toast.ts';
import { NavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
import { BackupRestoreState, ValidateBackupQuery } from '@/lib/graphql/generated/graphql.ts';
import { Progress } from '@/modules/core/components/Progress.tsx';
import { TextSetting } from '@/modules/core/components/settings/text/TextSetting.tsx';
Expand All @@ -37,6 +36,7 @@ import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'
import { ServerSettings } from '@/modules/settings/Settings.types.ts';
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';

type BackupSettingsType = Pick<ServerSettings, 'backupPath' | 'backupTime' | 'backupInterval' | 'backupTTL'>;

Expand All @@ -59,7 +59,7 @@ let backupRestoreId: string | undefined;

export function Backup() {
const { t } = useTranslation();
const { setTitle, setAction } = useContext(NavBarContext);
const { setTitle, setAction } = useNavBarContext();
useLayoutEffect(() => {
setTitle(t('settings.backup.title'));
setAction(null);
Expand Down
6 changes: 3 additions & 3 deletions src/modules/browse/screens/Browse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

import { useCallback, useContext, useLayoutEffect, useRef, useState } from 'react';
import { useCallback, useLayoutEffect, useRef, useState } from 'react';
import Tab from '@mui/material/Tab';
import { useTranslation } from 'react-i18next';
import { StringParam, useQueryParam } from 'use-query-params';
Expand All @@ -16,8 +16,8 @@ import { TabPanel } from '@/modules/core/components/tabs/TabPanel.tsx';
import { TabsWrapper } from '@/modules/core/components/tabs/TabsWrapper.tsx';
import { TabsMenu } from '@/modules/core/components/tabs/TabsMenu.tsx';
import { Migration } from '@/modules/migration/screens/Migration.tsx';
import { NavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
import { useResizeObserver } from '@/modules/core/hooks/useResizeObserver.tsx';
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';

enum Tabs {
SOURCE = 'source',
Expand All @@ -27,7 +27,7 @@ enum Tabs {

export function Browse() {
const { t } = useTranslation();
const { setTitle } = useContext(NavBarContext);
const { setTitle } = useNavBarContext();

useLayoutEffect(() => {
setTitle(t('global.label.browse'));
Expand Down
6 changes: 3 additions & 3 deletions src/modules/browse/screens/BrowseSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
*/

import { Trans, useTranslation } from 'react-i18next';
import { useContext, useLayoutEffect } from 'react';
import { useLayoutEffect } from 'react';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText';
import Switch from '@mui/material/Switch';
import { NavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { NumberSetting } from '@/modules/core/components/settings/NumberSetting.tsx';
import { MutableListSetting } from '@/modules/core/components/settings/MutableListSetting.tsx';
Expand All @@ -29,6 +28,7 @@ import { makeToast } from '@/modules/core/utils/Toast.ts';
import { MetadataBrowseSettings } from '@/modules/browse/Browse.types.ts';
import { ServerSettings as GqlServerSettings } from '@/modules/settings/Settings.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';

type ExtensionsSettings = Pick<GqlServerSettings, 'maxSourcesInParallel' | 'localSourcePath' | 'extensionRepos'>;

Expand All @@ -40,7 +40,7 @@ const extractBrowseSettings = (settings: GqlServerSettings): ExtensionsSettings

export const BrowseSettings = () => {
const { t } = useTranslation();
const { setTitle, setAction } = useContext(NavBarContext);
const { setTitle, setAction } = useNavBarContext();

useLayoutEffect(() => {
setTitle(t('settings.browse.title'));
Expand Down
6 changes: 3 additions & 3 deletions src/modules/category/screens/CategorySettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

import { useContext, useLayoutEffect, useMemo, useState } from 'react';
import { useLayoutEffect, useMemo, useState } from 'react';
import { DragDropContext, Draggable, DropResult } from 'react-beautiful-dnd';
import { useTheme } from '@mui/material/styles';
import Fab from '@mui/material/Fab';
Expand All @@ -24,7 +24,6 @@ import Box from '@mui/material/Box';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { StrictModeDroppable } from '@/modules/core/components/StrictModeDroppable.tsx';
import { DEFAULT_FULL_FAB_HEIGHT } from '@/modules/core/components/buttons/StyledFab.tsx';
import { NavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
import { LoadingPlaceholder } from '@/modules/core/components/placeholder/LoadingPlaceholder.tsx';
import { EmptyViewAbsoluteCentered } from '@/modules/core/components/placeholder/EmptyViewAbsoluteCentered.tsx';
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
Expand All @@ -33,11 +32,12 @@ import { GET_CATEGORIES_SETTINGS } from '@/lib/graphql/queries/CategoryQuery.ts'
import { CategorySettingsCard } from '@/modules/category/components/CategorySettingsCard.tsx';
import { CategoryIdInfo } from '@/modules/category/Category.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';

export function CategorySettings() {
const { t } = useTranslation();

const { setTitle, setAction } = useContext(NavBarContext);
const { setTitle, setAction } = useNavBarContext();
useLayoutEffect(() => {
setTitle(t('category.title.category_other'));
setAction(null);
Expand Down
33 changes: 18 additions & 15 deletions src/modules/core/contexts/AppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { ReaderContextProvider } from '@/modules/reader/contexts/ReaderContextPr
import { DIRECTION_TO_CACHE } from '@/modules/theme/ThemeDirectionCache.ts';
import { AppHotkeysProvider } from '@/modules/hotkeys/contexts/AppHotkeysProvider.tsx';
import { SnackbarWithDescription } from '@/modules/core/components/snackbar/SnackbarWithDescription.tsx';
import { AppPageHistoryContextProvider } from '@/modules/core/contexts/AppPageHistoryContextProvider.tsx';

interface Props {
children: React.ReactNode;
Expand Down Expand Up @@ -93,21 +94,23 @@ export const AppContext: React.FC<Props> = ({ children }) => {
<QueryParamProvider adapter={ReactRouter6Adapter}>
<LibraryOptionsContextProvider>
<NavBarContextProvider>
<ActiveDeviceContextProvider>
<SnackbarProvider
Components={{
default: SnackbarWithDescription,
info: SnackbarWithDescription,
success: SnackbarWithDescription,
warning: SnackbarWithDescription,
error: SnackbarWithDescription,
}}
>
<ReaderContextProvider>
<AppHotkeysProvider>{children}</AppHotkeysProvider>
</ReaderContextProvider>
</SnackbarProvider>
</ActiveDeviceContextProvider>
<AppPageHistoryContextProvider>
<ActiveDeviceContextProvider>
<SnackbarProvider
Components={{
default: SnackbarWithDescription,
info: SnackbarWithDescription,
success: SnackbarWithDescription,
warning: SnackbarWithDescription,
error: SnackbarWithDescription,
}}
>
<ReaderContextProvider>
<AppHotkeysProvider>{children}</AppHotkeysProvider>
</ReaderContextProvider>
</SnackbarProvider>
</ActiveDeviceContextProvider>
</AppPageHistoryContextProvider>
</NavBarContextProvider>
</LibraryOptionsContextProvider>
</QueryParamProvider>
Expand Down
13 changes: 13 additions & 0 deletions src/modules/core/contexts/AppPageHistoryContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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 { createContext, useContext } from 'react';

export const AppPageHistoryContext = createContext<string[]>([]);

export const useAppPageHistoryContext = () => useContext(AppPageHistoryContext);
17 changes: 17 additions & 0 deletions src/modules/core/contexts/AppPageHistoryContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* 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 React from 'react';
import { AppPageHistoryContext } from '@/modules/core/contexts/AppPageHistoryContext.tsx';
import { useHistory } from '@/modules/core/hooks/useHistory.ts';

export const AppPageHistoryContextProvider = ({ children }: { children: React.ReactNode }) => {
const history = useHistory();

return <AppPageHistoryContext.Provider value={history}>{children}</AppPageHistoryContext.Provider>;
};
13 changes: 9 additions & 4 deletions src/modules/core/hoc/withPropsFrom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,27 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

import { ComponentType, forwardRef, memo } from 'react';
import { ComponentType, memo, forwardRef } from 'react';

type PropsSourceCreator<T> = () => T;
type PropsSourceCreator<T, Props extends Record<string, any>> = (props: Props) => T;

export const withPropsFrom = <
ComponentProps extends Record<string, any>,
SourceProps extends Record<string, any>[],
SourcePropKeys extends keyof (ComponentProps | MergeObjectsArray<SourceProps>),
>(
Component: ComponentType<ComponentProps>,
propsSources: { [K in keyof SourceProps]: PropsSourceCreator<SourceProps[K]> },
propsSources: {
[K in keyof SourceProps]: PropsSourceCreator<SourceProps[K], Omit<ComponentProps, SourcePropKeys>>;
},
sourcePropKeys: SourcePropKeys[],
) =>
memo(
forwardRef<HTMLElement, Omit<ComponentProps, SourcePropKeys>>((props, ref) => {
const sourceProps = propsSources.reduce((acc, propsSource) => ({ ...acc, ...propsSource() }), {});
const sourceProps = propsSources.reduce(
(acc, propsSource) => ({ ...acc, ...propsSource(props as Omit<ComponentProps, SourcePropKeys>) }),
{},
);

const selectedProps = Object.fromEntries(
Object.entries(sourceProps).filter(([key]) => sourcePropKeys.includes(key as SourcePropKeys)),
Expand Down
4 changes: 2 additions & 2 deletions src/modules/core/hooks/useBackButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@

import { useLocation, useNavigate } from 'react-router-dom';
import { useCallback } from 'react';
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
import { useAppPageHistoryContext } from '@/modules/core/contexts/AppPageHistoryContext.tsx';

const PAGES_TO_IGNORE: readonly RegExp[] = [/\/manga\/[0-9]+\/chapter\/[0-9]+/g];

export const useBackButton = () => {
const navigate = useNavigate();
const location = useLocation();
const { history } = useNavBarContext();
const history = useAppPageHistoryContext();

return useCallback(() => {
const isHistoryEmpty = !history.length;
Expand Down
4 changes: 2 additions & 2 deletions src/modules/device/screens/DeviceSetting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
} from '@/modules/settings/services/ServerSettingsMetadata.ts';
import { makeToast } from '@/modules/core/utils/Toast.ts';
import { MutableListSetting } from '@/modules/core/components/settings/MutableListSetting.tsx';
import { NavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
import { DeviceContext } from '@/modules/device/contexts/DeviceContext.tsx';
import { Select } from '@/modules/core/components/inputs/Select.tsx';
import { LoadingPlaceholder } from '@/modules/core/components/placeholder/LoadingPlaceholder.tsx';
Expand All @@ -27,10 +26,11 @@ import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'
import { DEFAULT_DEVICE } from '@/modules/device/services/Device.ts';
import { MetadataServerSettingKeys, MetadataServerSettings } from '@/modules/settings/Settings.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';

export const DeviceSetting = () => {
const { t } = useTranslation();
const { setTitle, setAction } = useContext(NavBarContext);
const { setTitle, setAction } = useNavBarContext();

useLayoutEffect(() => {
setTitle(t('settings.device.title.settings'));
Expand Down
6 changes: 3 additions & 3 deletions src/modules/downloads/screens/DownloadQueue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Stack from '@mui/material/Stack';
import Box, { BoxProps } from '@mui/material/Box';
import Tooltip from '@mui/material/Tooltip';
import IconButton from '@mui/material/IconButton';
import React, { memo, useCallback, useContext, useEffect, useLayoutEffect } from 'react';
import React, { memo, useCallback, useEffect, useLayoutEffect } from 'react';
import { DragDropContext, Draggable, DraggableProvided, DropResult } from 'react-beautiful-dnd';
import Typography from '@mui/material/Typography';
import { Link } from 'react-router-dom';
Expand All @@ -30,13 +30,13 @@ import { StrictModeDroppable } from '@/modules/core/components/StrictModeDroppab
import { makeToast } from '@/modules/core/utils/Toast.ts';
import { DownloadStateIndicator } from '@/modules/core/components/DownloadStateIndicator.tsx';
import { EmptyViewAbsoluteCentered } from '@/modules/core/components/placeholder/EmptyViewAbsoluteCentered.tsx';
import { NavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
import { LoadingPlaceholder } from '@/modules/core/components/placeholder/LoadingPlaceholder.tsx';
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
import { ChapterDownloadStatus, ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts';
import { DownloaderState, DownloadState } from '@/lib/graphql/generated/graphql.ts';
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';

const HeightPreservingItem = ({ children, ...props }: BoxProps) => (
// the height is necessary to prevent the item container from collapsing, which confuses Virtuoso measurements
Expand Down Expand Up @@ -143,7 +143,7 @@ export const DownloadQueue: React.FC = () => {
const status = downloaderData?.state ?? 'STARTED';
const isQueueEmpty = !queue.length;

const { setTitle, setAction } = useContext(NavBarContext);
const { setTitle, setAction } = useNavBarContext();

const clearQueue = async () => {
try {
Expand Down
6 changes: 3 additions & 3 deletions src/modules/downloads/screens/DownloadSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@
*/

import { useTranslation } from 'react-i18next';
import { useContext, useLayoutEffect } from 'react';
import { useLayoutEffect } from 'react';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText';
import Switch from '@mui/material/Switch';
import ListSubheader from '@mui/material/ListSubheader';
import { TextSetting } from '@/modules/core/components/settings/text/TextSetting.tsx';
import { NavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { DownloadAheadSetting } from '@/modules/downloads/components/DownloadAheadSetting.tsx';
import {
Expand All @@ -33,6 +32,7 @@ import { GET_CATEGORIES_SETTINGS } from '@/lib/graphql/queries/CategoryQuery.ts'
import { MetadataDownloadSettings } from '@/modules/downloads/Downloads.types.ts';
import { ServerSettings } from '@/modules/settings/Settings.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';

type DownloadSettingsType = Pick<
ServerSettings,
Expand All @@ -55,7 +55,7 @@ const extractDownloadSettings = (settings: ServerSettings): DownloadSettingsType

export const DownloadSettings = () => {
const { t } = useTranslation();
const { setTitle, setAction } = useContext(NavBarContext);
const { setTitle, setAction } = useNavBarContext();

useLayoutEffect(() => {
setTitle(t('download.settings.title'));
Expand Down
Loading
Loading