Feature/cleanup files (#528)

* Move menu components into new dir

* Move chapter components into new dir

* Extract menu helper functions

* Move "SelectionFAB" to "collection" dir

* Move debounce hook to global utils dir

* Rename manga "hooks" to "useRefreshManga"
This commit is contained in:
schroda
2023-12-30 14:30:04 +01:00
committed by GitHub
parent ecea80f41e
commit edc2a62a76
20 changed files with 109 additions and 96 deletions

View File

@@ -21,7 +21,7 @@ import { ContinueReadingButton } from '@/components/manga/ContinueReadingButton.
import { SelectableCollectionReturnType } from '@/components/collection/useSelectableCollection.ts';
import { MangaOptionButton } from '@/components/manga/MangaOptionButton.tsx';
import { MangaActionMenuItems, SingleModeProps } from '@/components/manga/MangaActionMenuItems.tsx';
import { Menu } from '@/components/manga/Menu.tsx';
import { Menu } from '@/components/menu/Menu.tsx';
const BottomGradient = styled('div')({
position: 'absolute',

View File

@@ -15,7 +15,6 @@ import { useTranslation } from 'react-i18next';
import BookmarkRemove from '@mui/icons-material/BookmarkRemove';
import BookmarkAdd from '@mui/icons-material/BookmarkAdd';
import DoneAll from '@mui/icons-material/DoneAll';
import { t as translate } from 'i18next';
import { useMemo } from 'react';
import { SelectableCollectionReturnType } from '@/components/collection/useSelectableCollection.ts';
import {
@@ -27,28 +26,10 @@ import {
Chapters,
} from '@/lib/data/Chapters.ts';
import { TChapter } from '@/typings.ts';
import { MenuItem } from '@/components/manga/MenuItem.tsx';
import { IChapterWithMeta } from '@/components/manga/ChapterList.tsx';
import { MenuItem } from '@/components/menu/MenuItem.tsx';
import { IChapterWithMeta } from '@/components/chapter/ChapterList.tsx';
import { ChaptersWithMeta } from '@/lib/data/ChaptersWithMeta.ts';
const createGetMenuItemTitle =
(isSingleMode: boolean) =>
(action: ChapterAction, count: number): string => {
const countSuffix = count > 0 ? ` (${count})` : '';
return `${translate(
actionToTranslationKey[action].action[isSingleMode ? 'single' : 'selected'],
)}${countSuffix}`;
};
const createShouldShowMenuItem =
(isSingleMode: boolean) =>
(shouldBeVisible: boolean = false): boolean =>
isSingleMode ? shouldBeVisible : true;
const createIsMenuItemDisabled =
(isSingleMode: boolean) =>
(shouldBeDisabled: boolean): boolean =>
isSingleMode ? false : shouldBeDisabled;
import { createGetMenuItemTitle, createIsMenuItemDisabled, createShouldShowMenuItem } from '@/components/menu/util.ts';
type BaseProps = { onClose: () => void };
@@ -80,7 +61,7 @@ export const ChapterActionMenuItems = ({
const isSingleMode = !!chapter;
const { isDownloaded, isRead, isBookmarked } = chapter ?? {};
const getMenuItemTitle = createGetMenuItemTitle(isSingleMode);
const getMenuItemTitle = createGetMenuItemTitle(isSingleMode, actionToTranslationKey);
const shouldShowMenuItem = createShouldShowMenuItem(isSingleMode);
const isMenuItemDisabled = createIsMenuItemDisabled(isSingleMode);

View File

@@ -18,12 +18,12 @@ import React, { TouchEvent } from 'react';
import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import PopupState, { bindMenu, bindTrigger } from 'material-ui-popup-state';
import { getUploadDateString } from '@/util/date';
import { DownloadStateIndicator } from '@/components/molecules/DownloadStateIndicator';
import { getUploadDateString } from '@/util/date.ts';
import { DownloadStateIndicator } from '@/components/molecules/DownloadStateIndicator.tsx';
import { DownloadType } from '@/lib/graphql/generated/graphql.ts';
import { TChapter } from '@/typings.ts';
import { ChapterActionMenuItems } from '@/components/manga/ChapterActionMenuItems.tsx';
import { Menu } from '@/components/manga/Menu.tsx';
import { ChapterActionMenuItems } from '@/components/chapter/ChapterActionMenuItems.tsx';
import { Menu } from '@/components/menu/Menu.tsx';
interface IProps {
chapter: TChapter;

View File

@@ -14,21 +14,21 @@ import { useTranslation } from 'react-i18next';
import IconButton from '@mui/material/IconButton';
import DownloadIcon from '@mui/icons-material/Download';
import DoneAllIcon from '@mui/icons-material/DoneAll';
import { TChapter, TManga } from '@/typings';
import { TChapter, TManga } from '@/typings.ts';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { ChapterCard } from '@/components/manga/ChapterCard';
import { ResumeFab } from '@/components/manga/ResumeFAB';
import { filterAndSortChapters, useChapterOptions } from '@/components/manga/util';
import { EmptyView } from '@/components/util/EmptyView';
import { ChaptersToolbarMenu } from '@/components/manga/ChaptersToolbarMenu';
import { SelectionFAB } from '@/components/manga/SelectionFAB';
import { DEFAULT_FULL_FAB_HEIGHT } from '@/components/util/StyledFab';
import { ChapterCard } from '@/components/chapter/ChapterCard.tsx';
import { ResumeFab } from '@/components/manga/ResumeFAB.tsx';
import { filterAndSortChapters, useChapterOptions } from '@/components/chapter/util.tsx';
import { EmptyView } from '@/components/util/EmptyView.tsx';
import { ChaptersToolbarMenu } from '@/components/chapter/ChaptersToolbarMenu.tsx';
import { SelectionFAB } from '@/components/collection/SelectionFAB.tsx';
import { DEFAULT_FULL_FAB_HEIGHT } from '@/components/util/StyledFab.tsx';
import { DownloadType } from '@/lib/graphql/generated/graphql.ts';
import { useSelectableCollection } from '@/components/collection/useSelectableCollection.ts';
import { SelectableCollectionSelectAll } from '@/components/collection/SelectableCollectionSelectAll.tsx';
import { Chapters } from '@/lib/data/Chapters.ts';
import { ChaptersWithMeta } from '@/lib/data/ChaptersWithMeta.ts';
import { ChapterActionMenuItems } from '@/components/manga/ChapterActionMenuItems.tsx';
import { ChapterActionMenuItems } from '@/components/chapter/ChapterActionMenuItems.tsx';
const ChapterListHeader = styled(Stack)(({ theme }) => ({
margin: 8,

View File

@@ -9,12 +9,12 @@
import { RadioGroup } from '@mui/material';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { ChapterListOptions, ChapterOptionsReducerAction, TranslationKey } from '@/typings';
import { RadioInput } from '@/components/atoms/RadioInput';
import { SortRadioInput } from '@/components/atoms/SortRadioInput';
import { ThreeStateCheckboxInput } from '@/components/atoms/ThreeStateCheckboxInput';
import { OptionsTabs } from '@/components/molecules/OptionsTabs';
import { SORT_OPTIONS } from '@/components/manga/util';
import { ChapterListOptions, ChapterOptionsReducerAction, TranslationKey } from '@/typings.ts';
import { RadioInput } from '@/components/atoms/RadioInput.tsx';
import { SortRadioInput } from '@/components/atoms/SortRadioInput.tsx';
import { ThreeStateCheckboxInput } from '@/components/atoms/ThreeStateCheckboxInput.tsx';
import { OptionsTabs } from '@/components/molecules/OptionsTabs.tsx';
import { SORT_OPTIONS } from '@/components/chapter/util.tsx';
interface IProps {
open: boolean;

View File

@@ -10,9 +10,9 @@ import FilterList from '@mui/icons-material/FilterList';
import { IconButton, Tooltip } from '@mui/material';
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { ChapterListOptions, ChapterOptionsReducerAction } from '@/typings';
import { ChapterOptions } from '@/components/manga/ChapterOptions';
import { isFilterActive } from '@/components/manga/util';
import { ChapterListOptions, ChapterOptionsReducerAction } from '@/typings.ts';
import { ChapterOptions } from '@/components/chapter/ChapterOptions.tsx';
import { isFilterActive } from '@/components/chapter/util.tsx';
interface IProps {
options: ChapterListOptions;

View File

@@ -14,8 +14,8 @@ import {
NullAndUndefined,
TChapter,
TranslationKey,
} from '@/typings';
import { useReducerLocalStorage } from '@/util/useLocalStorage';
} from '@/typings.ts';
import { useReducerLocalStorage } from '@/util/useLocalStorage.tsx';
const defaultChapterOptions: ChapterListOptions = {
active: false,

View File

@@ -11,9 +11,9 @@ import { Fab, Box, styled } from '@mui/material';
import React from 'react';
import { useTranslation } from 'react-i18next';
import PopupState, { bindMenu, bindTrigger } from 'material-ui-popup-state';
import { DEFAULT_FAB_STYLE } from '@/components/util/StyledFab';
import { DEFAULT_FAB_STYLE } from '@/components/util/StyledFab.tsx';
import { TranslationKey } from '@/typings.ts';
import { Menu } from '@/components/manga/Menu.tsx';
import { Menu } from '@/components/menu/Menu.tsx';
interface SelectionFABProps {
children: (handleClose: () => void, setHideMenu: (hide: boolean) => void) => JSX.Element;

View File

@@ -15,34 +15,15 @@ import { useTranslation } from 'react-i18next';
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
import Label from '@mui/icons-material/Label';
import { useMemo, useState } from 'react';
import { t as translate } from 'i18next';
import { TManga } from '@/typings.ts';
import { actionToTranslationKey, MangaAction, MangaDownloadInfo, Mangas, MangaUnreadInfo } from '@/lib/data/Mangas.ts';
import { SelectableCollectionReturnType } from '@/components/collection/useSelectableCollection.ts';
import { CategorySelect } from '@/components/navbar/action/CategorySelect.tsx';
import { MenuItem } from '@/components/manga/MenuItem.tsx';
import { MenuItem } from '@/components/menu/MenuItem.tsx';
import { createGetMenuItemTitle, createIsMenuItemDisabled, createShouldShowMenuItem } from '@/components/menu/util.ts';
const ACTION_DISABLES_SELECTION_MODE: MangaAction[] = ['remove_from_library'] as const;
const createGetMenuItemTitle =
(isSingleMode: boolean) =>
(action: MangaAction, count: number): string => {
const countSuffix = count > 0 ? ` (${count})` : '';
return `${translate(
actionToTranslationKey[action].action[isSingleMode ? 'single' : 'selected'],
)}${countSuffix}`;
};
const createShouldShowMenuItem =
(isSingleMode: boolean) =>
(shouldBeVisible: boolean = false): boolean =>
isSingleMode ? shouldBeVisible : true;
const createIsMenuItemDisabled =
(isSingleMode: boolean) =>
(shouldBeDisabled: boolean): boolean =>
isSingleMode ? false : shouldBeDisabled;
type BaseProps = { onClose: (selectionModeState: boolean) => void; setHideMenu: (hide: boolean) => void };
export type SingleModeProps = {
@@ -65,7 +46,7 @@ export const MangaActionMenuItems = ({ manga, handleSelection, selectedMangas =
const isSingleMode = !!manga;
const getMenuItemTitle = createGetMenuItemTitle(isSingleMode);
const getMenuItemTitle = createGetMenuItemTitle(isSingleMode, actionToTranslationKey);
const shouldShowMenuItem = createShouldShowMenuItem(isSingleMode);
const isMenuItemDisabled = createIsMenuItemDisabled(isSingleMode);

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useState } from 'react';
import { requestManager } from '@/lib/requests/RequestManager.ts';
export const useRefreshManga = (mangaId: string) => {
@@ -22,19 +22,3 @@ export const useRefreshManga = (mangaId: string) => {
return [handleRefresh, { loading: fetchingOnline }] as const;
};
export const useDebounce = <Value>(value: Value, delay: number): Value => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
};

View File

@@ -0,0 +1,42 @@
/*
* 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 { t as translate } from 'i18next';
import { TranslationKey } from '@/typings.ts';
export const createGetMenuItemTitle =
<Action extends string>(
isSingleMode: boolean,
actionToTranslationKey: Record<
Action,
{
action: {
single: TranslationKey;
selected: TranslationKey;
};
success: TranslationKey;
error: TranslationKey;
}
>,
) =>
(action: Action, count: number): string => {
const countSuffix = count > 0 ? ` (${count})` : '';
return `${translate(
actionToTranslationKey[action].action[isSingleMode ? 'single' : 'selected'],
)}${countSuffix}`;
};
export const createShouldShowMenuItem =
(isSingleMode: boolean) =>
(shouldBeVisible: boolean = false): boolean =>
isSingleMode ? shouldBeVisible : true;
export const createIsMenuItemDisabled =
(isSingleMode: boolean) =>
(shouldBeDisabled: boolean): boolean =>
isSingleMode ? false : shouldBeDisabled;

View File

@@ -9,7 +9,7 @@
import SearchIcon from '@mui/icons-material/Search';
import { FormControl, Input, InputAdornment, InputLabel } from '@mui/material';
import React, { useEffect } from 'react';
import { useDebounce } from '@/components/manga/hooks';
import { useDebounce } from '@/util/useDebounce.ts';
interface Props {
state: string;

View File

@@ -24,7 +24,7 @@ import { useSelectableCollection } from '@/components/collection/useSelectableCo
import { TManga } from '@/typings.ts';
import { SelectableCollectionSelectMode } from '@/components/collection/SelectableCollectionSelectMode.tsx';
import { useGetVisibleLibraryMangas } from '@/components/library/useGetVisibleLibraryMangas.ts';
import { SelectionFAB } from '@/components/manga/SelectionFAB.tsx';
import { SelectionFAB } from '@/components/collection/SelectionFAB.tsx';
import { PARTIAL_MANGA_FIELDS } from '@/lib/graphql/Fragments.ts';
import { MangaActionMenuItems } from '@/components/manga/MangaActionMenuItems.tsx';

View File

@@ -14,8 +14,8 @@ import { useParams } from 'react-router-dom';
import { isNetworkRequestInFlight } from '@apollo/client/core/networkStatus';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { NavBarContext, useSetDefaultBackTo } from '@/components/context/NavbarContext';
import { ChapterList } from '@/components/manga/ChapterList';
import { useRefreshManga } from '@/components/manga/hooks';
import { ChapterList } from '@/components/chapter/ChapterList.tsx';
import { useRefreshManga } from '@/components/manga/useRefreshManga.ts';
import { MangaDetails } from '@/components/manga/MangaDetails';
import { MangaToolbarMenu } from '@/components/manga/MangaToolbarMenu';
import { EmptyView } from '@/components/util/EmptyView';

View File

@@ -27,7 +27,7 @@ import { VerticalPager } from '@/components/reader/pager/VerticalPager';
import { ReaderNavBar } from '@/components/navbar/ReaderNavBar';
import { makeToast } from '@/components/util/Toast';
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
import { useDebounce } from '@/components/manga/hooks.ts';
import { useDebounce } from '@/util/useDebounce.ts';
import { UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
import { useMetadataServerSettings } from '@/util/metadataServerSettings.ts';

View File

@@ -19,7 +19,7 @@ import { translateExtensionLanguage } from '@/screens/util/Extensions';
import { AppbarSearch } from '@/components/util/AppbarSearch';
import { LangSelect } from '@/components/navbar/action/LangSelect';
import { MangaGrid } from '@/components/MangaGrid';
import { useDebounce } from '@/components/manga/hooks';
import { useDebounce } from '@/util/useDebounce.ts';
import { NavBarContext, useSetDefaultBackTo } from '@/components/context/NavbarContext.tsx';
type SourceLoadingState = { isLoading: boolean; hasResults: boolean; emptySearch: boolean };

View File

@@ -23,7 +23,7 @@ import {
AbortableApolloUseMutationPaginatedResponse,
SPECIAL_ED_SOURCES,
} from '@/lib/requests/RequestManager.ts';
import { useDebounce } from '@/components/manga/hooks';
import { useDebounce } from '@/util/useDebounce.ts';
import { useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
import { SourceGridLayout } from '@/components/source/GridLayouts';
import { AppbarSearch } from '@/components/util/AppbarSearch';

25
src/util/useDebounce.ts Normal file
View File

@@ -0,0 +1,25 @@
/*
* 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 { useEffect, useState } from 'react';
export const useDebounce = <Value>(value: Value, delay: number): Value => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
};