Introduce "useAppAction" hook
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import List from '@mui/material/List';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import { fromEvent } from 'file-selector';
|
||||
@@ -37,7 +37,6 @@ 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';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
type BackupSettingsType = Pick<ServerSettings, 'backupPath' | 'backupTime' | 'backupInterval' | 'backupTTL'>;
|
||||
@@ -61,15 +60,8 @@ let backupRestoreId: string | undefined;
|
||||
|
||||
export function Backup() {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
useAppTitle(t('settings.backup.title'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t]);
|
||||
useAppTitle(t('settings.backup.title'));
|
||||
|
||||
const {
|
||||
data: settingsData,
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { useLayoutEffect } from 'react';
|
||||
import List from '@mui/material/List';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
@@ -27,7 +26,6 @@ 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';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
type ExtensionsSettings = Pick<GqlServerSettings, 'maxSourcesInParallel' | 'localSourcePath' | 'extensionRepos'>;
|
||||
@@ -40,12 +38,8 @@ const extractBrowseSettings = (settings: GqlServerSettings): ExtensionsSettings
|
||||
|
||||
export const BrowseSettings = () => {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
useAppTitle(t('global.label.browse'));
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
}, [t]);
|
||||
useAppTitle(t('global.label.browse'));
|
||||
|
||||
const { data, loading, error, refetch } = requestManager.useGetServerSettings({
|
||||
notifyOnNetworkStatusChange: true,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { ComponentProps, useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { ComponentProps, useMemo, useState } from 'react';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import Fab from '@mui/material/Fab';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
@@ -32,7 +32,6 @@ 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, noOp } from '@/lib/HelperFunctions.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { makeToast } from '@/modules/core/utils/Toast.ts';
|
||||
import { DndSortableItem } from '@/lib/dnd-kit/DndSortableItem.tsx';
|
||||
import { DndKitUtil } from '@/lib/dnd-kit/DndKitUtil.ts';
|
||||
@@ -41,17 +40,9 @@ import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
export function CategorySettings() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
useAppTitle(t('category.dialog.title.edit_category_other'));
|
||||
|
||||
const { setAction } = useNavBarContext();
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
const { data, loading, error, refetch } = requestManager.useGetCategories<
|
||||
GetCategoriesSettingsQuery,
|
||||
GetCategoriesSettingsQueryVariables
|
||||
|
||||
@@ -11,7 +11,6 @@ import ListItem from '@mui/material/ListItem';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLayoutEffect } from 'react';
|
||||
import {
|
||||
updateMetadataServerSettings,
|
||||
useMetadataServerSettings,
|
||||
@@ -26,23 +25,13 @@ 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';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
export const DeviceSetting = () => {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
useAppTitle(t('settings.device.title.device'));
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
const {
|
||||
metadata,
|
||||
settings: { devices },
|
||||
|
||||
@@ -10,7 +10,7 @@ import PauseIcon from '@mui/icons-material/Pause';
|
||||
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
||||
import Box from '@mui/material/Box';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import React, { useLayoutEffect, useMemo, useState } from 'react';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import DeleteSweepIcon from '@mui/icons-material/DeleteSweep';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
@@ -26,12 +26,12 @@ import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'
|
||||
import { ChapterDownloadStatus } from '@/modules/chapter/services/Chapters.ts';
|
||||
import { DownloaderState } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { DndSortableItem } from '@/lib/dnd-kit/DndSortableItem.tsx';
|
||||
import { DndKitUtil } from '@/lib/dnd-kit/DndKitUtil.ts';
|
||||
import { DndOverlayItem } from '@/lib/dnd-kit/DndOverlayItem.tsx';
|
||||
import { DownloadQueueChapterCard } from '@/modules/downloads/components/DownloadQueueChapterCard.tsx';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
|
||||
|
||||
export const DownloadQueue: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -52,8 +52,6 @@ export const DownloadQueue: React.FC = () => {
|
||||
const status = downloaderData?.state ?? DownloaderState.Started;
|
||||
const isQueueEmpty = !queue.length;
|
||||
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
const dndItems = useMemo(() => queue.map((download) => download.chapter), [queue]);
|
||||
const dndSensors = DndKitUtil.useSensorsForDevice();
|
||||
const [dndActiveDownload, setDndActiveDownload] = useState<ChapterDownloadStatus | null>(null);
|
||||
@@ -99,30 +97,24 @@ export const DownloadQueue: React.FC = () => {
|
||||
categoryReorder(queue, oldIndex, newIndex);
|
||||
};
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setAction(
|
||||
<>
|
||||
<CustomTooltip title={t('download.queue.label.delete_all')}>
|
||||
<IconButton onClick={clearQueue} color="inherit">
|
||||
<DeleteSweepIcon />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
useAppAction(
|
||||
<>
|
||||
<CustomTooltip title={t('download.queue.label.delete_all')}>
|
||||
<IconButton onClick={clearQueue} color="inherit">
|
||||
<DeleteSweepIcon />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
|
||||
<CustomTooltip
|
||||
title={t(status === DownloaderState.Started ? 'global.button.start' : 'global.button.stop')}
|
||||
disabled={isQueueEmpty}
|
||||
>
|
||||
<IconButton onClick={toggleQueueStatus} disabled={isQueueEmpty} color="inherit">
|
||||
{status === DownloaderState.Stopped ? <PlayArrowIcon /> : <PauseIcon />}
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
</>,
|
||||
);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t, status, isQueueEmpty]);
|
||||
<CustomTooltip
|
||||
title={t(status === DownloaderState.Started ? 'global.button.start' : 'global.button.stop')}
|
||||
disabled={isQueueEmpty}
|
||||
>
|
||||
<IconButton onClick={toggleQueueStatus} disabled={isQueueEmpty} color="inherit">
|
||||
{status === DownloaderState.Stopped ? <PlayArrowIcon /> : <PauseIcon />}
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
</>,
|
||||
);
|
||||
|
||||
// Virtuoso's resize observer can throw this error,
|
||||
// which is caught by DnD and aborts dragging.
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLayoutEffect } from 'react';
|
||||
import List from '@mui/material/List';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
@@ -32,7 +31,6 @@ 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';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
type DownloadSettingsType = Pick<
|
||||
@@ -56,18 +54,9 @@ const extractDownloadSettings = (settings: ServerSettings): DownloadSettingsType
|
||||
|
||||
export const DownloadSettings = () => {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
useAppTitle(t('download.title.download'));
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
const categories = requestManager.useGetCategories<GetCategoriesSettingsQuery, GetCategoriesSettingsQueryVariables>(
|
||||
GET_CATEGORIES_SETTINGS,
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { fromEvent } from 'file-selector';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
@@ -45,13 +45,13 @@ import {
|
||||
import { EXTENSION_ACTION_TO_FAILURE_TRANSLATION_KEY_MAP } from '@/modules/extension/Extensions.constants.ts';
|
||||
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { ExtensionOptions } from '@/modules/extension/components/ExtensionOptions';
|
||||
import {
|
||||
createUpdateMetadataServerSettings,
|
||||
useMetadataServerSettings,
|
||||
} from '@/modules/settings/services/ServerSettingsMetadata.ts';
|
||||
import { MetadataBrowseSettings } from '@/modules/browse/Browse.types.ts';
|
||||
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
|
||||
|
||||
const LANGUAGE = 0;
|
||||
const EXTENSIONS = 1;
|
||||
@@ -115,7 +115,6 @@ const GroupHeader = ({
|
||||
|
||||
export function Extensions({ tabsMenuHeight }: { tabsMenuHeight: number }) {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
const navigate = useNavigate();
|
||||
const { pathname, search, state } = useLocation<{ selectedExtensionPkg?: TExtension['pkgName'] }>();
|
||||
const selectedExtensionPkg = state?.selectedExtensionPkg;
|
||||
@@ -201,47 +200,42 @@ export function Extensions({ tabsMenuHeight }: { tabsMenuHeight: number }) {
|
||||
fetchExtensions();
|
||||
}, [refetchExtensions]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setAction(
|
||||
<>
|
||||
<AppbarSearch />
|
||||
<CustomTooltip title={t('extension.action.label.install_external')}>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
const input = document.createElement('input');
|
||||
input.style.display = 'none';
|
||||
input.type = 'file';
|
||||
input.onchange = () => {
|
||||
const file = input.files?.[0];
|
||||
if (file) {
|
||||
submitExternalExtension(file);
|
||||
}
|
||||
};
|
||||
useAppAction(
|
||||
<>
|
||||
<AppbarSearch />
|
||||
<CustomTooltip title={t('extension.action.label.install_external')}>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
const input = document.createElement('input');
|
||||
input.style.display = 'none';
|
||||
input.type = 'file';
|
||||
input.onchange = () => {
|
||||
const file = input.files?.[0];
|
||||
if (file) {
|
||||
submitExternalExtension(file);
|
||||
}
|
||||
};
|
||||
|
||||
document.documentElement.appendChild(input);
|
||||
input.click();
|
||||
document.documentElement.removeChild(input);
|
||||
}}
|
||||
color="inherit"
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
document.documentElement.appendChild(input);
|
||||
input.click();
|
||||
document.documentElement.removeChild(input);
|
||||
}}
|
||||
color="inherit"
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
|
||||
<LanguageSelect
|
||||
selectedLanguages={shownLangs}
|
||||
setSelectedLanguages={(languages: string[]) =>
|
||||
updateMetadataServerSettings('extensionLanguages', languages)
|
||||
}
|
||||
languages={allLangs}
|
||||
/>
|
||||
</>,
|
||||
);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t, shownLangs, allLangs]);
|
||||
<LanguageSelect
|
||||
selectedLanguages={shownLangs}
|
||||
setSelectedLanguages={(languages: string[]) =>
|
||||
updateMetadataServerSettings('extensionLanguages', languages)
|
||||
}
|
||||
languages={allLangs}
|
||||
/>
|
||||
</>,
|
||||
[t, shownLangs, allLangs],
|
||||
);
|
||||
|
||||
useWindowEvent('drop', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import Card from '@mui/material/Card';
|
||||
import CardActionArea from '@mui/material/CardActionArea';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { StringParam, useQueryParam } from 'use-query-params';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -30,11 +30,11 @@ import { EmptyViewAbsoluteCentered } from '@/modules/core/components/feedback/Em
|
||||
import { translateExtensionLanguage } from '@/modules/extension/Extensions.utils.ts';
|
||||
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { Sources } from '@/modules/source/services/Sources.ts';
|
||||
import { SourceDisplayNameInfo, SourceIdInfo } from '@/modules/source/Source.types.ts';
|
||||
import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
|
||||
|
||||
type SourceLoadingState = { isLoading: boolean; hasResults: boolean; emptySearch: boolean; error: any };
|
||||
type SourceToLoadingStateMap = Map<string, SourceLoadingState>;
|
||||
@@ -189,8 +189,6 @@ const SourceSearchPreview = React.memo(
|
||||
export const SearchAll: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
const { pathname, state } = useLocation<{ mangaTitle?: string }>();
|
||||
const isMigrateMode = pathname.startsWith('/migrate/source');
|
||||
|
||||
@@ -236,22 +234,21 @@ export const SearchAll: React.FC = () => {
|
||||
[setSourceToLoadingStateMap],
|
||||
);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setAction(
|
||||
<>
|
||||
<AppbarSearch isClosable={false} />
|
||||
<LanguageSelect
|
||||
selectedLanguages={shownLangs}
|
||||
setSelectedLanguages={setShownLangs}
|
||||
languages={sourceLanguages}
|
||||
/>
|
||||
</>,
|
||||
);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t, shownLangs, setShownLangs, sources]);
|
||||
useAppAction(
|
||||
useMemo(
|
||||
() => (
|
||||
<>
|
||||
<AppbarSearch isClosable={false} />
|
||||
<LanguageSelect
|
||||
selectedLanguages={shownLangs}
|
||||
setSelectedLanguages={setShownLangs}
|
||||
languages={sourceLanguages}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
[shownLangs, setShownLangs, sourceLanguages],
|
||||
),
|
||||
);
|
||||
|
||||
if (loading) {
|
||||
return <LoadingPlaceholder />;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLayoutEffect } from 'react';
|
||||
import List from '@mui/material/List';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
@@ -21,20 +20,14 @@ import { EmptyViewAbsoluteCentered } from '@/modules/core/components/feedback/Em
|
||||
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
||||
import { makeToast } from '@/modules/core/utils/Toast.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { MetadataHistorySettings } from '@/modules/history/History.types.ts';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
export const HistorySettings = () => {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
useAppTitle(t('history.title'));
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
}, [t]);
|
||||
|
||||
const {
|
||||
settings: { hideHistory },
|
||||
request: { loading, error, refetch },
|
||||
|
||||
@@ -43,8 +43,8 @@ import { useLibraryOptionsContext } from '@/modules/library/contexts/LibraryOpti
|
||||
import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts';
|
||||
import { getCategoryMetadata } from '@/modules/category/services/CategoryMetadata.ts';
|
||||
import { GET_LIBRARY_MANGA_COUNT } from '@/lib/graphql/queries/MangaQuery.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
|
||||
|
||||
const TitleWithSizeTag = styled('span')({
|
||||
display: 'flex',
|
||||
@@ -167,7 +167,6 @@ export function Library() {
|
||||
);
|
||||
}, [isSelectModeActive, selectedMangas]);
|
||||
|
||||
const { setAction } = useNavBarContext();
|
||||
useAppTitle(
|
||||
<TitleWithSizeTag>
|
||||
{t('library.title')}
|
||||
@@ -176,49 +175,33 @@ export function Library() {
|
||||
t('library.title'),
|
||||
[t, showTabSize, librarySize],
|
||||
);
|
||||
useLayoutEffect(() => {
|
||||
setAction(
|
||||
<>
|
||||
{!isSelectModeActive && activeTab && (
|
||||
<>
|
||||
<AppbarSearch />
|
||||
<LibraryToolbarMenu category={activeTab} />
|
||||
<UpdateChecker categoryId={activeTab?.id} />
|
||||
</>
|
||||
)}
|
||||
<SelectableCollectionSelectMode
|
||||
isActive={isSelectModeActive}
|
||||
areAllItemsSelected={areAllItemsSelected}
|
||||
areNoItemsSelected={areNoItemsSelected}
|
||||
onSelectAll={(selectAll) =>
|
||||
handleSelectAll(selectAll, [...new Set(mangas.map((manga) => manga.id))])
|
||||
}
|
||||
onModeChange={(checked) => {
|
||||
setIsSelectModeActive(checked);
|
||||
useAppAction(
|
||||
<>
|
||||
{!isSelectModeActive && activeTab && (
|
||||
<>
|
||||
<AppbarSearch />
|
||||
<LibraryToolbarMenu category={activeTab} />
|
||||
<UpdateChecker categoryId={activeTab?.id} />
|
||||
</>
|
||||
)}
|
||||
<SelectableCollectionSelectMode
|
||||
isActive={isSelectModeActive}
|
||||
areAllItemsSelected={areAllItemsSelected}
|
||||
areNoItemsSelected={areNoItemsSelected}
|
||||
onSelectAll={(selectAll) => handleSelectAll(selectAll, [...new Set(mangas.map((manga) => manga.id))])}
|
||||
onModeChange={(checked) => {
|
||||
setIsSelectModeActive(checked);
|
||||
|
||||
if (checked) {
|
||||
handleSelectAll(true, [...new Set(mangas.map((manga) => manga.id))]);
|
||||
} else {
|
||||
tabs.forEach((tab) => handleSelectAll(false, [], tab.id.toString()));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</>,
|
||||
);
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [
|
||||
t,
|
||||
librarySize,
|
||||
areCategoriesLoading,
|
||||
isSelectModeActive,
|
||||
areNoItemsSelected,
|
||||
areAllItemsSelected,
|
||||
mangas.length,
|
||||
activeTab,
|
||||
showTabSize,
|
||||
]);
|
||||
if (checked) {
|
||||
handleSelectAll(true, [...new Set(mangas.map((manga) => manga.id))]);
|
||||
} else {
|
||||
tabs.forEach((tab) => handleSelectAll(false, [], tab.id.toString()));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</>,
|
||||
[isSelectModeActive, areNoItemsSelected, areAllItemsSelected, activeTab],
|
||||
);
|
||||
|
||||
const handleTabChange = (newTab: number) => {
|
||||
setTabSearchParam(newTab);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import SettingsIcon from '@mui/icons-material/Settings';
|
||||
import PopupState, { bindMenu, bindTrigger } from 'material-ui-popup-state';
|
||||
@@ -34,8 +34,8 @@ import { VirtuosoUtil } from '@/lib/virtuoso/Virtuoso.util.tsx';
|
||||
import { LibraryDuplicatesWorkerInput, TMangaDuplicate, TMangaDuplicates } from '@/modules/library/Library.types.ts';
|
||||
import { GridLayout } from '@/modules/core/Core.types.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
|
||||
|
||||
export const LibraryDuplicates = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -46,39 +46,30 @@ export const LibraryDuplicates = () => {
|
||||
false,
|
||||
);
|
||||
|
||||
const { setAction } = useNavBarContext();
|
||||
useAppTitle(t('library.settings.advanced.duplicates.label.title'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(
|
||||
<>
|
||||
<GridLayouts gridLayout={gridLayout} onChange={setGridLayout} />
|
||||
<PopupState variant="popover" popupId="library-dupliactes-settings">
|
||||
{(popupState) => (
|
||||
<>
|
||||
<IconButton {...bindTrigger(popupState)} color="inherit">
|
||||
<SettingsIcon />
|
||||
</IconButton>
|
||||
<Menu {...bindMenu(popupState)}>
|
||||
<MenuItem>
|
||||
<CheckboxInput
|
||||
label={t(
|
||||
'library.settings.advanced.duplicates.settings.label.check_description',
|
||||
)}
|
||||
checked={checkAlternativeTitles}
|
||||
onChange={(_, checked) => setCheckAlternativeTitles(checked)}
|
||||
/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</>
|
||||
)}
|
||||
</PopupState>
|
||||
</>,
|
||||
);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t, gridLayout, checkAlternativeTitles]);
|
||||
useAppAction(
|
||||
<>
|
||||
<GridLayouts gridLayout={gridLayout} onChange={setGridLayout} />
|
||||
<PopupState variant="popover" popupId="library-dupliactes-settings">
|
||||
{(popupState) => (
|
||||
<>
|
||||
<IconButton {...bindTrigger(popupState)} color="inherit">
|
||||
<SettingsIcon />
|
||||
</IconButton>
|
||||
<Menu {...bindMenu(popupState)}>
|
||||
<MenuItem>
|
||||
<CheckboxInput
|
||||
label={t('library.settings.advanced.duplicates.settings.label.check_description')}
|
||||
checked={checkAlternativeTitles}
|
||||
onChange={(_, checked) => setCheckAlternativeTitles(checked)}
|
||||
/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</>
|
||||
)}
|
||||
</PopupState>
|
||||
</>,
|
||||
);
|
||||
|
||||
const { data, loading, error, refetch } = requestManager.useGetMangas<
|
||||
GetMangasDuplicatesQuery,
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLayoutEffect } from 'react';
|
||||
import List from '@mui/material/List';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
@@ -38,7 +37,6 @@ import { GET_MANGAS_BASE } from '@/lib/graphql/queries/MangaQuery.ts';
|
||||
import { MetadataLibrarySettings } from '@/modules/library/Library.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';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
const removeNonLibraryMangasFromCategories = async (): Promise<void> => {
|
||||
@@ -65,16 +63,8 @@ const removeNonLibraryMangasFromCategories = async (): Promise<void> => {
|
||||
|
||||
export function LibrarySettings() {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
useAppTitle(t('library.title'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
const categories = requestManager.useGetCategories<GetCategoriesSettingsQuery, GetCategoriesSettingsQueryVariables>(
|
||||
GET_CATEGORIES_SETTINGS,
|
||||
|
||||
@@ -11,7 +11,7 @@ import CircularProgress from '@mui/material/CircularProgress';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Box from '@mui/material/Box';
|
||||
import React, { useEffect, useLayoutEffect, useRef } from 'react';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { isNetworkRequestInFlight } from '@apollo/client/core/networkStatus';
|
||||
@@ -26,13 +26,12 @@ import { LoadingPlaceholder } from '@/modules/core/components/feedback/LoadingPl
|
||||
import { GetMangaScreenQuery } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { GET_MANGA_SCREEN } from '@/lib/graphql/queries/MangaQuery.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
|
||||
|
||||
export const Manga: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { setAction } = useNavBarContext();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const autofetchedRef = useRef(false);
|
||||
|
||||
@@ -61,50 +60,36 @@ export const Manga: React.FC = () => {
|
||||
}, [manga]);
|
||||
|
||||
useAppTitle(manga?.title ?? t('manga.title_one'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t, manga?.title]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setAction(
|
||||
<Stack
|
||||
direction="row"
|
||||
sx={{
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{error && !isValidating && !refreshing && (
|
||||
<CustomTooltip
|
||||
title={
|
||||
<>
|
||||
{t('manga.error.label.request_failure')}
|
||||
<br />
|
||||
{getErrorMessage(error)}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<IconButton onClick={() => refetch()}>
|
||||
<Warning color="error" />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
)}
|
||||
{manga && (refreshing || isValidating) && (
|
||||
<IconButton disabled>
|
||||
<CircularProgress size={16} />
|
||||
useAppAction(
|
||||
<Stack
|
||||
direction="row"
|
||||
sx={{
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{error && !isValidating && !refreshing && (
|
||||
<CustomTooltip
|
||||
title={
|
||||
<>
|
||||
{t('manga.error.label.request_failure')}
|
||||
<br />
|
||||
{getErrorMessage(error)}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<IconButton onClick={() => refetch()}>
|
||||
<Warning color="error" />
|
||||
</IconButton>
|
||||
)}
|
||||
{manga && <MangaToolbarMenu manga={manga} onRefresh={refresh} refreshing={refreshing} />}
|
||||
</Stack>,
|
||||
);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t, error, isValidating, refreshing, manga, refresh]);
|
||||
</CustomTooltip>
|
||||
)}
|
||||
{manga && (refreshing || isValidating) && (
|
||||
<IconButton disabled>
|
||||
<CircularProgress size={16} />
|
||||
</IconButton>
|
||||
)}
|
||||
{manga && <MangaToolbarMenu manga={manga} onRefresh={refresh} refreshing={refreshing} />}
|
||||
</Stack>,
|
||||
);
|
||||
|
||||
if (error && !manga) {
|
||||
return (
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useEffect, useLayoutEffect, useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
@@ -22,12 +22,11 @@ import { SOURCE_BASE_FIELDS } from '@/lib/graphql/fragments/SourceFragments.ts';
|
||||
import { BaseMangaGrid } from '@/modules/manga/components/BaseMangaGrid.tsx';
|
||||
import { GridLayout } from '@/modules/core/Core.types.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
|
||||
|
||||
export const Migrate = () => {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
const { sourceId: paramSourceId } = useParams<{ sourceId: string }>();
|
||||
|
||||
@@ -70,13 +69,7 @@ export const Migrate = () => {
|
||||
});
|
||||
|
||||
useAppTitle(name ?? sourceId ?? t('migrate.title'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(<GridLayouts gridLayout={gridLayout} onChange={setGridLayout} />);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t, name, sourceId, gridLayout]);
|
||||
useAppAction(<GridLayouts gridLayout={gridLayout} onChange={setGridLayout} />);
|
||||
|
||||
useEffect(() => {
|
||||
if (isSourceLoading || isKnownSource) {
|
||||
|
||||
20
src/modules/navigation-bar/hooks/useAppAction.ts
Normal file
20
src/modules/navigation-bar/hooks/useAppAction.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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 } from 'react';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { NavbarContextType } from '@/modules/navigation-bar/NavigationBar.types.ts';
|
||||
|
||||
export const useAppAction = (action: NavbarContextType['action'], dependencies: any[] = []) => {
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
useEffect(() => {
|
||||
setAction(action);
|
||||
return () => setAction(null);
|
||||
}, dependencies);
|
||||
};
|
||||
@@ -7,12 +7,11 @@
|
||||
*/
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLayoutEffect, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { useDefaultReaderSettingsWithDefaultFlag } from '@/modules/reader/services/ReaderSettingsMetadata.ts';
|
||||
import { LoadingPlaceholder } from '@/modules/core/components/feedback/LoadingPlaceholder.tsx';
|
||||
import { EmptyViewAbsoluteCentered } from '@/modules/core/components/feedback/EmptyViewAbsoluteCentered.tsx';
|
||||
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { IReaderSettings, ReadingMode } from '@/modules/reader/types/Reader.types.ts';
|
||||
import { ReaderService } from '@/modules/reader/services/ReaderService.ts';
|
||||
import { ReaderSettingsTabs } from '@/modules/reader/components/settings/ReaderSettingsTabs.tsx';
|
||||
@@ -22,16 +21,8 @@ import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
export const GlobalReaderSettings = () => {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
useAppTitle(t('reader.settings.title.reader'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useLayoutEffect } from 'react';
|
||||
import List from '@mui/material/List';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
@@ -21,22 +20,13 @@ import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'
|
||||
import { EmptyViewAbsoluteCentered } from '@/modules/core/components/feedback/EmptyViewAbsoluteCentered.tsx';
|
||||
import { VersionInfo } from '@/modules/app-updates/components/VersionInfo.tsx';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { epochToDate } from '@/util/DateHelper.ts';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
export function About() {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
useAppTitle(t('settings.about.title'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
const { data, loading, error, refetch } = requestManager.useGetAbout({ notifyOnNetworkStatusChange: true });
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLayoutEffect } from 'react';
|
||||
import List from '@mui/material/List';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
@@ -35,7 +34,6 @@ import { makeToast } from '@/modules/core/utils/Toast.ts';
|
||||
import { MetadataThemeSettings } from '@/modules/theme/AppTheme.types.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { AppStorage } from '@/lib/storage/AppStorage.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
export const Appearance = () => {
|
||||
@@ -44,15 +42,7 @@ export const Appearance = () => {
|
||||
const { mode, setMode } = useColorScheme();
|
||||
const actualThemeMode = (mode ?? themeMode) as ThemeMode;
|
||||
|
||||
const { setAction } = useNavBarContext();
|
||||
useAppTitle(t('settings.appearance.title'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
const {
|
||||
settings,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { Fragment, useLayoutEffect } from 'react';
|
||||
import { Fragment } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import List from '@mui/material/List';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
@@ -15,7 +15,6 @@ import ListAltIcon from '@mui/icons-material/ListAlt';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
|
||||
import { ListItemLink } from '@/modules/core/components/lists/ListItemLink.tsx';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { NAVIGATION_BAR_ITEMS } from '@/modules/navigation-bar/NavigationBar.constants.ts';
|
||||
import { MediaQuery } from '@/modules/core/utils/MediaQuery.tsx';
|
||||
import { NavigationBarUtil } from '@/modules/navigation-bar/NavigationBar.util.ts';
|
||||
@@ -25,9 +24,10 @@ import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
export const More = () => {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
const isMobileWidth = MediaQuery.useIsMobileWidth();
|
||||
|
||||
useAppTitle(t('global.label.more'));
|
||||
|
||||
const {
|
||||
settings: { hideHistory },
|
||||
} = useMetadataServerSettings();
|
||||
@@ -59,15 +59,6 @@ export const More = () => {
|
||||
[NavBarItemMoreGroup.HIDDEN_ITEM]: hiddenItemsMoreGroup,
|
||||
};
|
||||
|
||||
useAppTitle(t('global.label.more'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
return (
|
||||
<List sx={{ p: 0 }}>
|
||||
{Object.entries(finalHiddenNavBarItemsByGroup).map(([group, items], index, list) => (
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import { useTranslation, Trans } from 'react-i18next';
|
||||
import { useLayoutEffect, useMemo } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import Link from '@mui/material/Link';
|
||||
import List from '@mui/material/List';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
@@ -31,7 +31,6 @@ import { makeToast } from '@/modules/core/utils/Toast.ts';
|
||||
import { MetadataUpdateSettings } from '@/modules/app-updates/AppUpdateChecker.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';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
type ServerSettingsType = Pick<
|
||||
@@ -95,16 +94,8 @@ const getLogFilesCleanupDisplayValue = (ttl: number): string => {
|
||||
|
||||
export const ServerSettings = () => {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
useAppTitle(t('settings.server.title.server'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
const {
|
||||
settings: { serverInformAvailableUpdate },
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useLayoutEffect } from 'react';
|
||||
import AutoStoriesIcon from '@mui/icons-material/AutoStories';
|
||||
import List from '@mui/material/List';
|
||||
import BackupIcon from '@mui/icons-material/Backup';
|
||||
@@ -29,21 +28,12 @@ import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import { makeToast } from '@/modules/core/utils/Toast.ts';
|
||||
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
export function Settings() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { setAction } = useNavBarContext();
|
||||
useAppTitle(t('settings.title'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
const [triggerClearServerCache, { loading: isClearingServerCache }] = requestManager.useClearServerCache();
|
||||
|
||||
|
||||
@@ -7,12 +7,10 @@
|
||||
*/
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
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 { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import { WebUIUpdateIntervalSetting } from '@/modules/settings/components/webUI/WebUIUpdateIntervalSetting.tsx';
|
||||
import { TextSetting } from '@/modules/core/components/settings/text/TextSetting.tsx';
|
||||
@@ -121,16 +119,8 @@ const extractWebUISettings = (settings: ServerSettings): WebUISettingsType => ({
|
||||
|
||||
export const WebUISettings = () => {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
useAppTitle(t('settings.webui.title.webui'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
const {
|
||||
settings: { webUIInformAvailableUpdate },
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { createElement, useLayoutEffect } from 'react';
|
||||
import { createElement } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import List from '@mui/material/List';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -27,7 +27,6 @@ import { GET_SOURCE_SETTINGS } from '@/lib/graphql/queries/SourceQuery.ts';
|
||||
import { makeToast } from '@/modules/core/utils/Toast.ts';
|
||||
import { PreferenceProps } from '@/modules/source/Source.types.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
|
||||
function getPrefComponent(type: string) {
|
||||
@@ -49,16 +48,8 @@ function getPrefComponent(type: string) {
|
||||
|
||||
export function SourceConfigure() {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
useAppTitle(t('source.configuration.title'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(null);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
const { sourceId } = useParams<{ sourceId: string }>();
|
||||
const { data, loading, error, refetch } = requestManager.useGetSource<
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useParams, useNavigate, useLocation, useSearchParams } from 'react-router-dom';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import SettingsIcon from '@mui/icons-material/Settings';
|
||||
@@ -51,9 +51,10 @@ import { MangaIdInfo } from '@/modules/manga/Manga.types.ts';
|
||||
import { GridLayout } from '@/modules/core/Core.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';
|
||||
import { Sources } from '@/modules/source/services/Sources.ts';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
|
||||
const DEFAULT_SOURCE: SourceIdInfo = { id: '-1' };
|
||||
|
||||
@@ -205,7 +206,7 @@ const useSourceManga = (
|
||||
|
||||
export function SourceMangas() {
|
||||
const { t } = useTranslation();
|
||||
const { setAction, appBarHeight } = useNavBarContext();
|
||||
const { appBarHeight } = useNavBarContext();
|
||||
|
||||
const { sourceId } = useParams<{ sourceId: string }>();
|
||||
|
||||
@@ -400,30 +401,24 @@ export function SourceMangas() {
|
||||
}, [clearCache]);
|
||||
|
||||
useAppTitle(source?.displayName ?? t('source.title_one'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(
|
||||
<>
|
||||
<AppbarSearch />
|
||||
<SourceGridLayout />
|
||||
{source?.isConfigurable && (
|
||||
<CustomTooltip title={t('settings.title')}>
|
||||
<IconButton
|
||||
onClick={() => navigate(AppRoutes.sources.childRoutes.configure.path(sourceId))}
|
||||
aria-label="display more actions"
|
||||
edge="end"
|
||||
color="inherit"
|
||||
>
|
||||
<SettingsIcon />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
)}
|
||||
</>,
|
||||
);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t, source]);
|
||||
useAppAction(
|
||||
<>
|
||||
<AppbarSearch />
|
||||
<SourceGridLayout />
|
||||
{source?.isConfigurable && (
|
||||
<CustomTooltip title={t('settings.title')}>
|
||||
<IconButton
|
||||
onClick={() => navigate(AppRoutes.sources.childRoutes.configure.path(sourceId))}
|
||||
aria-label="display more actions"
|
||||
edge="end"
|
||||
color="inherit"
|
||||
>
|
||||
<SettingsIcon />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
)}
|
||||
</>,
|
||||
);
|
||||
|
||||
const EmptyViewComponent = mangas.length ? EmptyView : EmptyViewAbsoluteCentered;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { Fragment, useLayoutEffect, useMemo } from 'react';
|
||||
import { Fragment, useMemo } from 'react';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import TravelExploreIcon from '@mui/icons-material/TravelExplore';
|
||||
@@ -24,13 +24,12 @@ import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'
|
||||
import { translateExtensionLanguage } from '@/modules/extension/Extensions.utils.ts';
|
||||
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
|
||||
import { Sources as SourceService } from '@/modules/source/services/Sources.ts';
|
||||
import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts';
|
||||
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
|
||||
|
||||
export function Sources() {
|
||||
const { t } = useTranslation();
|
||||
const { setAction } = useNavBarContext();
|
||||
|
||||
const [shownLangs, setShownLangs] = useLocalStorage<string[]>('shownSourceLangs', sourceDefualtLangs());
|
||||
const {
|
||||
@@ -61,26 +60,21 @@ export function Sources() {
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setAction(
|
||||
<>
|
||||
<CustomTooltip title={t('search.title.global_search')}>
|
||||
<IconButton onClick={() => navigate(AppRoutes.sources.childRoutes.searchAll.path)} color="inherit">
|
||||
<TravelExploreIcon />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
<LanguageSelect
|
||||
selectedLanguages={shownLangs}
|
||||
setSelectedLanguages={setShownLangs}
|
||||
languages={sourceLanguages}
|
||||
/>
|
||||
</>,
|
||||
);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t, shownLangs, sourceLanguages]);
|
||||
useAppAction(
|
||||
<>
|
||||
<CustomTooltip title={t('search.title.global_search')}>
|
||||
<IconButton onClick={() => navigate(AppRoutes.sources.childRoutes.searchAll.path)} color="inherit">
|
||||
<TravelExploreIcon />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
<LanguageSelect
|
||||
selectedLanguages={shownLangs}
|
||||
setSelectedLanguages={setShownLangs}
|
||||
languages={sourceLanguages}
|
||||
/>
|
||||
</>,
|
||||
[t, shownLangs, sourceLanguages],
|
||||
);
|
||||
|
||||
if (isLoading) return <LoadingPlaceholder />;
|
||||
|
||||
|
||||
@@ -25,12 +25,12 @@ import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContex
|
||||
import { Chapters } from '@/modules/chapter/services/Chapters.ts';
|
||||
import { GROUPED_VIRTUOSO_Z_INDEX } from '@/modules/core/AppRoute.constants.ts';
|
||||
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
|
||||
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
|
||||
|
||||
export const Updates: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
const { appBarHeight } = useNavBarContext();
|
||||
|
||||
const { setAction } = useNavBarContext();
|
||||
const {
|
||||
data: chapterUpdateData,
|
||||
loading: isLoading,
|
||||
@@ -74,13 +74,7 @@ export const Updates: React.FC = () => {
|
||||
const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp;
|
||||
|
||||
useAppTitle(t('updates.title'));
|
||||
useLayoutEffect(() => {
|
||||
setAction(<UpdateChecker />);
|
||||
|
||||
return () => {
|
||||
setAction(null);
|
||||
};
|
||||
}, [t, lastUpdateTimestamp]);
|
||||
useAppAction(<UpdateChecker />);
|
||||
|
||||
const loadMore = useCallback(() => {
|
||||
if (!hasNextPage) {
|
||||
|
||||
Reference in New Issue
Block a user