Introduce "useAppAction" hook

This commit is contained in:
schroda
2025-05-03 13:24:55 +02:00
parent 3ab70c4802
commit aacdbaaeef
26 changed files with 230 additions and 430 deletions

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * 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 List from '@mui/material/List';
import ListItemText from '@mui/material/ListItemText'; import ListItemText from '@mui/material/ListItemText';
import { fromEvent } from 'file-selector'; import { fromEvent } from 'file-selector';
@@ -37,7 +37,6 @@ import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'
import { ServerSettings } from '@/modules/settings/Settings.types.ts'; import { ServerSettings } from '@/modules/settings/Settings.types.ts';
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts'; import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
type BackupSettingsType = Pick<ServerSettings, 'backupPath' | 'backupTime' | 'backupInterval' | 'backupTTL'>; type BackupSettingsType = Pick<ServerSettings, 'backupPath' | 'backupTime' | 'backupInterval' | 'backupTTL'>;
@@ -61,15 +60,8 @@ let backupRestoreId: string | undefined;
export function Backup() { export function Backup() {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
useAppTitle(t('settings.backup.title'));
useLayoutEffect(() => {
setAction(null);
return () => { useAppTitle(t('settings.backup.title'));
setAction(null);
};
}, [t]);
const { const {
data: settingsData, data: settingsData,

View File

@@ -7,7 +7,6 @@
*/ */
import { Trans, useTranslation } from 'react-i18next'; import { Trans, useTranslation } from 'react-i18next';
import { useLayoutEffect } from 'react';
import List from '@mui/material/List'; import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem'; import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText'; 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 { MetadataBrowseSettings } from '@/modules/browse/Browse.types.ts';
import { ServerSettings as GqlServerSettings } from '@/modules/settings/Settings.types.ts'; import { ServerSettings as GqlServerSettings } from '@/modules/settings/Settings.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
type ExtensionsSettings = Pick<GqlServerSettings, 'maxSourcesInParallel' | 'localSourcePath' | 'extensionRepos'>; type ExtensionsSettings = Pick<GqlServerSettings, 'maxSourcesInParallel' | 'localSourcePath' | 'extensionRepos'>;
@@ -40,12 +38,8 @@ const extractBrowseSettings = (settings: GqlServerSettings): ExtensionsSettings
export const BrowseSettings = () => { export const BrowseSettings = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
useAppTitle(t('global.label.browse'));
useLayoutEffect(() => { useAppTitle(t('global.label.browse'));
setAction(null);
}, [t]);
const { data, loading, error, refetch } = requestManager.useGetServerSettings({ const { data, loading, error, refetch } = requestManager.useGetServerSettings({
notifyOnNetworkStatusChange: true, notifyOnNetworkStatusChange: true,

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * 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 { useTheme } from '@mui/material/styles';
import Fab from '@mui/material/Fab'; import Fab from '@mui/material/Fab';
import AddIcon from '@mui/icons-material/Add'; 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 { CategorySettingsCard } from '@/modules/category/components/CategorySettingsCard.tsx';
import { CategoryIdInfo } from '@/modules/category/Category.types.ts'; import { CategoryIdInfo } from '@/modules/category/Category.types.ts';
import { getErrorMessage, noOp } from '@/lib/HelperFunctions.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 { makeToast } from '@/modules/core/utils/Toast.ts';
import { DndSortableItem } from '@/lib/dnd-kit/DndSortableItem.tsx'; import { DndSortableItem } from '@/lib/dnd-kit/DndSortableItem.tsx';
import { DndKitUtil } from '@/lib/dnd-kit/DndKitUtil.ts'; import { DndKitUtil } from '@/lib/dnd-kit/DndKitUtil.ts';
@@ -41,17 +40,9 @@ import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
export function CategorySettings() { export function CategorySettings() {
const { t } = useTranslation(); const { t } = useTranslation();
useAppTitle(t('category.dialog.title.edit_category_other')); 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< const { data, loading, error, refetch } = requestManager.useGetCategories<
GetCategoriesSettingsQuery, GetCategoriesSettingsQuery,
GetCategoriesSettingsQueryVariables GetCategoriesSettingsQueryVariables

View File

@@ -11,7 +11,6 @@ import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText'; import ListItemText from '@mui/material/ListItemText';
import MenuItem from '@mui/material/MenuItem'; import MenuItem from '@mui/material/MenuItem';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useLayoutEffect } from 'react';
import { import {
updateMetadataServerSettings, updateMetadataServerSettings,
useMetadataServerSettings, useMetadataServerSettings,
@@ -26,23 +25,13 @@ import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'
import { DEFAULT_DEVICE } from '@/modules/device/services/Device.ts'; import { DEFAULT_DEVICE } from '@/modules/device/services/Device.ts';
import { MetadataServerSettingKeys, MetadataServerSettings } from '@/modules/settings/Settings.types.ts'; import { MetadataServerSettingKeys, MetadataServerSettings } from '@/modules/settings/Settings.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
export const DeviceSetting = () => { export const DeviceSetting = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
useAppTitle(t('settings.device.title.device')); useAppTitle(t('settings.device.title.device'));
useLayoutEffect(() => {
setAction(null);
return () => {
setAction(null);
};
}, [t]);
const { const {
metadata, metadata,
settings: { devices }, settings: { devices },

View File

@@ -10,7 +10,7 @@ import PauseIcon from '@mui/icons-material/Pause';
import PlayArrowIcon from '@mui/icons-material/PlayArrow'; import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import Box from '@mui/material/Box'; import Box from '@mui/material/Box';
import IconButton from '@mui/material/IconButton'; 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 { useTranslation } from 'react-i18next';
import DeleteSweepIcon from '@mui/icons-material/DeleteSweep'; import DeleteSweepIcon from '@mui/icons-material/DeleteSweep';
import { Virtuoso } from 'react-virtuoso'; import { Virtuoso } from 'react-virtuoso';
@@ -26,12 +26,12 @@ import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'
import { ChapterDownloadStatus } from '@/modules/chapter/services/Chapters.ts'; import { ChapterDownloadStatus } from '@/modules/chapter/services/Chapters.ts';
import { DownloaderState } from '@/lib/graphql/generated/graphql.ts'; import { DownloaderState } from '@/lib/graphql/generated/graphql.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { DndSortableItem } from '@/lib/dnd-kit/DndSortableItem.tsx';
import { DndKitUtil } from '@/lib/dnd-kit/DndKitUtil.ts'; import { DndKitUtil } from '@/lib/dnd-kit/DndKitUtil.ts';
import { DndOverlayItem } from '@/lib/dnd-kit/DndOverlayItem.tsx'; import { DndOverlayItem } from '@/lib/dnd-kit/DndOverlayItem.tsx';
import { DownloadQueueChapterCard } from '@/modules/downloads/components/DownloadQueueChapterCard.tsx'; import { DownloadQueueChapterCard } from '@/modules/downloads/components/DownloadQueueChapterCard.tsx';
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts'; import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
export const DownloadQueue: React.FC = () => { export const DownloadQueue: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -52,8 +52,6 @@ export const DownloadQueue: React.FC = () => {
const status = downloaderData?.state ?? DownloaderState.Started; const status = downloaderData?.state ?? DownloaderState.Started;
const isQueueEmpty = !queue.length; const isQueueEmpty = !queue.length;
const { setAction } = useNavBarContext();
const dndItems = useMemo(() => queue.map((download) => download.chapter), [queue]); const dndItems = useMemo(() => queue.map((download) => download.chapter), [queue]);
const dndSensors = DndKitUtil.useSensorsForDevice(); const dndSensors = DndKitUtil.useSensorsForDevice();
const [dndActiveDownload, setDndActiveDownload] = useState<ChapterDownloadStatus | null>(null); const [dndActiveDownload, setDndActiveDownload] = useState<ChapterDownloadStatus | null>(null);
@@ -99,8 +97,7 @@ export const DownloadQueue: React.FC = () => {
categoryReorder(queue, oldIndex, newIndex); categoryReorder(queue, oldIndex, newIndex);
}; };
useLayoutEffect(() => { useAppAction(
setAction(
<> <>
<CustomTooltip title={t('download.queue.label.delete_all')}> <CustomTooltip title={t('download.queue.label.delete_all')}>
<IconButton onClick={clearQueue} color="inherit"> <IconButton onClick={clearQueue} color="inherit">
@@ -119,11 +116,6 @@ export const DownloadQueue: React.FC = () => {
</>, </>,
); );
return () => {
setAction(null);
};
}, [t, status, isQueueEmpty]);
// Virtuoso's resize observer can throw this error, // Virtuoso's resize observer can throw this error,
// which is caught by DnD and aborts dragging. // which is caught by DnD and aborts dragging.
useWindowEvent('error', (e) => { useWindowEvent('error', (e) => {

View File

@@ -7,7 +7,6 @@
*/ */
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useLayoutEffect } from 'react';
import List from '@mui/material/List'; import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem'; import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText'; 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 { MetadataDownloadSettings } from '@/modules/downloads/Downloads.types.ts';
import { ServerSettings } from '@/modules/settings/Settings.types.ts'; import { ServerSettings } from '@/modules/settings/Settings.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
type DownloadSettingsType = Pick< type DownloadSettingsType = Pick<
@@ -56,18 +54,9 @@ const extractDownloadSettings = (settings: ServerSettings): DownloadSettingsType
export const DownloadSettings = () => { export const DownloadSettings = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
useAppTitle(t('download.title.download')); useAppTitle(t('download.title.download'));
useLayoutEffect(() => {
setAction(null);
return () => {
setAction(null);
};
}, [t]);
const categories = requestManager.useGetCategories<GetCategoriesSettingsQuery, GetCategoriesSettingsQueryVariables>( const categories = requestManager.useGetCategories<GetCategoriesSettingsQuery, GetCategoriesSettingsQueryVariables>(
GET_CATEGORIES_SETTINGS, GET_CATEGORIES_SETTINGS,
); );

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * 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 { fromEvent } from 'file-selector';
import IconButton from '@mui/material/IconButton'; import IconButton from '@mui/material/IconButton';
import AddIcon from '@mui/icons-material/Add'; 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 { EXTENSION_ACTION_TO_FAILURE_TRANSLATION_KEY_MAP } from '@/modules/extension/Extensions.constants.ts';
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts'; import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.ts'; import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
import { ExtensionOptions } from '@/modules/extension/components/ExtensionOptions'; import { ExtensionOptions } from '@/modules/extension/components/ExtensionOptions';
import { import {
createUpdateMetadataServerSettings, createUpdateMetadataServerSettings,
useMetadataServerSettings, useMetadataServerSettings,
} from '@/modules/settings/services/ServerSettingsMetadata.ts'; } from '@/modules/settings/services/ServerSettingsMetadata.ts';
import { MetadataBrowseSettings } from '@/modules/browse/Browse.types.ts'; import { MetadataBrowseSettings } from '@/modules/browse/Browse.types.ts';
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
const LANGUAGE = 0; const LANGUAGE = 0;
const EXTENSIONS = 1; const EXTENSIONS = 1;
@@ -115,7 +115,6 @@ const GroupHeader = ({
export function Extensions({ tabsMenuHeight }: { tabsMenuHeight: number }) { export function Extensions({ tabsMenuHeight }: { tabsMenuHeight: number }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
const navigate = useNavigate(); const navigate = useNavigate();
const { pathname, search, state } = useLocation<{ selectedExtensionPkg?: TExtension['pkgName'] }>(); const { pathname, search, state } = useLocation<{ selectedExtensionPkg?: TExtension['pkgName'] }>();
const selectedExtensionPkg = state?.selectedExtensionPkg; const selectedExtensionPkg = state?.selectedExtensionPkg;
@@ -201,8 +200,7 @@ export function Extensions({ tabsMenuHeight }: { tabsMenuHeight: number }) {
fetchExtensions(); fetchExtensions();
}, [refetchExtensions]); }, [refetchExtensions]);
useLayoutEffect(() => { useAppAction(
setAction(
<> <>
<AppbarSearch /> <AppbarSearch />
<CustomTooltip title={t('extension.action.label.install_external')}> <CustomTooltip title={t('extension.action.label.install_external')}>
@@ -236,13 +234,9 @@ export function Extensions({ tabsMenuHeight }: { tabsMenuHeight: number }) {
languages={allLangs} languages={allLangs}
/> />
</>, </>,
[t, shownLangs, allLangs],
); );
return () => {
setAction(null);
};
}, [t, shownLangs, allLangs]);
useWindowEvent('drop', async (e) => { useWindowEvent('drop', async (e) => {
e.preventDefault(); e.preventDefault();
const files = await fromEvent(e); const files = await fromEvent(e);

View File

@@ -9,7 +9,7 @@
import Card from '@mui/material/Card'; import Card from '@mui/material/Card';
import CardActionArea from '@mui/material/CardActionArea'; import CardActionArea from '@mui/material/CardActionArea';
import Typography from '@mui/material/Typography'; 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 { Link, useLocation } from 'react-router-dom';
import { StringParam, useQueryParam } from 'use-query-params'; import { StringParam, useQueryParam } from 'use-query-params';
import { useTranslation } from 'react-i18next'; 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 { translateExtensionLanguage } from '@/modules/extension/Extensions.utils.ts';
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts'; import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { Sources } from '@/modules/source/services/Sources.ts';
import { SourceDisplayNameInfo, SourceIdInfo } from '@/modules/source/Source.types.ts'; import { SourceDisplayNameInfo, SourceIdInfo } from '@/modules/source/Source.types.ts';
import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts'; import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts';
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.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 SourceLoadingState = { isLoading: boolean; hasResults: boolean; emptySearch: boolean; error: any };
type SourceToLoadingStateMap = Map<string, SourceLoadingState>; type SourceToLoadingStateMap = Map<string, SourceLoadingState>;
@@ -189,8 +189,6 @@ const SourceSearchPreview = React.memo(
export const SearchAll: React.FC = () => { export const SearchAll: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
const { pathname, state } = useLocation<{ mangaTitle?: string }>(); const { pathname, state } = useLocation<{ mangaTitle?: string }>();
const isMigrateMode = pathname.startsWith('/migrate/source'); const isMigrateMode = pathname.startsWith('/migrate/source');
@@ -236,8 +234,9 @@ export const SearchAll: React.FC = () => {
[setSourceToLoadingStateMap], [setSourceToLoadingStateMap],
); );
useLayoutEffect(() => { useAppAction(
setAction( useMemo(
() => (
<> <>
<AppbarSearch isClosable={false} /> <AppbarSearch isClosable={false} />
<LanguageSelect <LanguageSelect
@@ -245,14 +244,12 @@ export const SearchAll: React.FC = () => {
setSelectedLanguages={setShownLangs} setSelectedLanguages={setShownLangs}
languages={sourceLanguages} languages={sourceLanguages}
/> />
</>, </>
),
[shownLangs, setShownLangs, sourceLanguages],
),
); );
return () => {
setAction(null);
};
}, [t, shownLangs, setShownLangs, sources]);
if (loading) { if (loading) {
return <LoadingPlaceholder />; return <LoadingPlaceholder />;
} }

View File

@@ -7,7 +7,6 @@
*/ */
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useLayoutEffect } from 'react';
import List from '@mui/material/List'; import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem'; import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText'; 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 { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
import { makeToast } from '@/modules/core/utils/Toast.ts'; import { makeToast } from '@/modules/core/utils/Toast.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { MetadataHistorySettings } from '@/modules/history/History.types.ts';
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts'; import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
export const HistorySettings = () => { export const HistorySettings = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
useAppTitle(t('history.title')); useAppTitle(t('history.title'));
useLayoutEffect(() => {
setAction(null);
}, [t]);
const { const {
settings: { hideHistory }, settings: { hideHistory },
request: { loading, error, refetch }, request: { loading, error, refetch },

View File

@@ -43,8 +43,8 @@ import { useLibraryOptionsContext } from '@/modules/library/contexts/LibraryOpti
import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts'; import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts';
import { getCategoryMetadata } from '@/modules/category/services/CategoryMetadata.ts'; import { getCategoryMetadata } from '@/modules/category/services/CategoryMetadata.ts';
import { GET_LIBRARY_MANGA_COUNT } from '@/lib/graphql/queries/MangaQuery.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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
const TitleWithSizeTag = styled('span')({ const TitleWithSizeTag = styled('span')({
display: 'flex', display: 'flex',
@@ -167,7 +167,6 @@ export function Library() {
); );
}, [isSelectModeActive, selectedMangas]); }, [isSelectModeActive, selectedMangas]);
const { setAction } = useNavBarContext();
useAppTitle( useAppTitle(
<TitleWithSizeTag> <TitleWithSizeTag>
{t('library.title')} {t('library.title')}
@@ -176,8 +175,7 @@ export function Library() {
t('library.title'), t('library.title'),
[t, showTabSize, librarySize], [t, showTabSize, librarySize],
); );
useLayoutEffect(() => { useAppAction(
setAction(
<> <>
{!isSelectModeActive && activeTab && ( {!isSelectModeActive && activeTab && (
<> <>
@@ -190,9 +188,7 @@ export function Library() {
isActive={isSelectModeActive} isActive={isSelectModeActive}
areAllItemsSelected={areAllItemsSelected} areAllItemsSelected={areAllItemsSelected}
areNoItemsSelected={areNoItemsSelected} areNoItemsSelected={areNoItemsSelected}
onSelectAll={(selectAll) => onSelectAll={(selectAll) => handleSelectAll(selectAll, [...new Set(mangas.map((manga) => manga.id))])}
handleSelectAll(selectAll, [...new Set(mangas.map((manga) => manga.id))])
}
onModeChange={(checked) => { onModeChange={(checked) => {
setIsSelectModeActive(checked); setIsSelectModeActive(checked);
@@ -204,21 +200,8 @@ export function Library() {
}} }}
/> />
</>, </>,
[isSelectModeActive, areNoItemsSelected, areAllItemsSelected, activeTab],
); );
return () => {
setAction(null);
};
}, [
t,
librarySize,
areCategoriesLoading,
isSelectModeActive,
areNoItemsSelected,
areAllItemsSelected,
mangas.length,
activeTab,
showTabSize,
]);
const handleTabChange = (newTab: number) => { const handleTabChange = (newTab: number) => {
setTabSearchParam(newTab); setTabSearchParam(newTab);

View File

@@ -7,7 +7,7 @@
*/ */
import { useTranslation } from 'react-i18next'; 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 IconButton from '@mui/material/IconButton';
import SettingsIcon from '@mui/icons-material/Settings'; import SettingsIcon from '@mui/icons-material/Settings';
import PopupState, { bindMenu, bindTrigger } from 'material-ui-popup-state'; 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 { LibraryDuplicatesWorkerInput, TMangaDuplicate, TMangaDuplicates } from '@/modules/library/Library.types.ts';
import { GridLayout } from '@/modules/core/Core.types.ts'; import { GridLayout } from '@/modules/core/Core.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
export const LibraryDuplicates = () => { export const LibraryDuplicates = () => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -46,10 +46,8 @@ export const LibraryDuplicates = () => {
false, false,
); );
const { setAction } = useNavBarContext();
useAppTitle(t('library.settings.advanced.duplicates.label.title')); useAppTitle(t('library.settings.advanced.duplicates.label.title'));
useLayoutEffect(() => { useAppAction(
setAction(
<> <>
<GridLayouts gridLayout={gridLayout} onChange={setGridLayout} /> <GridLayouts gridLayout={gridLayout} onChange={setGridLayout} />
<PopupState variant="popover" popupId="library-dupliactes-settings"> <PopupState variant="popover" popupId="library-dupliactes-settings">
@@ -61,9 +59,7 @@ export const LibraryDuplicates = () => {
<Menu {...bindMenu(popupState)}> <Menu {...bindMenu(popupState)}>
<MenuItem> <MenuItem>
<CheckboxInput <CheckboxInput
label={t( label={t('library.settings.advanced.duplicates.settings.label.check_description')}
'library.settings.advanced.duplicates.settings.label.check_description',
)}
checked={checkAlternativeTitles} checked={checkAlternativeTitles}
onChange={(_, checked) => setCheckAlternativeTitles(checked)} onChange={(_, checked) => setCheckAlternativeTitles(checked)}
/> />
@@ -75,11 +71,6 @@ export const LibraryDuplicates = () => {
</>, </>,
); );
return () => {
setAction(null);
};
}, [t, gridLayout, checkAlternativeTitles]);
const { data, loading, error, refetch } = requestManager.useGetMangas< const { data, loading, error, refetch } = requestManager.useGetMangas<
GetMangasDuplicatesQuery, GetMangasDuplicatesQuery,
GetMangasDuplicatesQueryVariables GetMangasDuplicatesQueryVariables

View File

@@ -7,7 +7,6 @@
*/ */
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useLayoutEffect } from 'react';
import List from '@mui/material/List'; import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem'; import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton'; 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 { MetadataLibrarySettings } from '@/modules/library/Library.types.ts';
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts'; import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
const removeNonLibraryMangasFromCategories = async (): Promise<void> => { const removeNonLibraryMangasFromCategories = async (): Promise<void> => {
@@ -65,16 +63,8 @@ const removeNonLibraryMangasFromCategories = async (): Promise<void> => {
export function LibrarySettings() { export function LibrarySettings() {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
useAppTitle(t('library.title')); useAppTitle(t('library.title'));
useLayoutEffect(() => {
setAction(null);
return () => {
setAction(null);
};
}, [t]);
const categories = requestManager.useGetCategories<GetCategoriesSettingsQuery, GetCategoriesSettingsQueryVariables>( const categories = requestManager.useGetCategories<GetCategoriesSettingsQuery, GetCategoriesSettingsQueryVariables>(
GET_CATEGORIES_SETTINGS, GET_CATEGORIES_SETTINGS,

View File

@@ -11,7 +11,7 @@ import CircularProgress from '@mui/material/CircularProgress';
import IconButton from '@mui/material/IconButton'; import IconButton from '@mui/material/IconButton';
import Stack from '@mui/material/Stack'; import Stack from '@mui/material/Stack';
import Box from '@mui/material/Box'; 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 { useTranslation } from 'react-i18next';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { isNetworkRequestInFlight } from '@apollo/client/core/networkStatus'; 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 { GetMangaScreenQuery } from '@/lib/graphql/generated/graphql.ts';
import { GET_MANGA_SCREEN } from '@/lib/graphql/queries/MangaQuery.ts'; import { GET_MANGA_SCREEN } from '@/lib/graphql/queries/MangaQuery.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
export const Manga: React.FC = () => { export const Manga: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
const { id } = useParams<{ id: string }>(); const { id } = useParams<{ id: string }>();
const autofetchedRef = useRef(false); const autofetchedRef = useRef(false);
@@ -61,16 +60,7 @@ export const Manga: React.FC = () => {
}, [manga]); }, [manga]);
useAppTitle(manga?.title ?? t('manga.title_one')); useAppTitle(manga?.title ?? t('manga.title_one'));
useLayoutEffect(() => { useAppAction(
setAction(null);
return () => {
setAction(null);
};
}, [t, manga?.title]);
useLayoutEffect(() => {
setAction(
<Stack <Stack
direction="row" direction="row"
sx={{ sx={{
@@ -101,11 +91,6 @@ export const Manga: React.FC = () => {
</Stack>, </Stack>,
); );
return () => {
setAction(null);
};
}, [t, error, isValidating, refreshing, manga, refresh]);
if (error && !manga) { if (error && !manga) {
return ( return (
<EmptyViewAbsoluteCentered <EmptyViewAbsoluteCentered

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * 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 { useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { requestManager } from '@/lib/requests/RequestManager.ts'; 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 { BaseMangaGrid } from '@/modules/manga/components/BaseMangaGrid.tsx';
import { GridLayout } from '@/modules/core/Core.types.ts'; import { GridLayout } from '@/modules/core/Core.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
export const Migrate = () => { export const Migrate = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
const { sourceId: paramSourceId } = useParams<{ sourceId: string }>(); const { sourceId: paramSourceId } = useParams<{ sourceId: string }>();
@@ -70,13 +69,7 @@ export const Migrate = () => {
}); });
useAppTitle(name ?? sourceId ?? t('migrate.title')); useAppTitle(name ?? sourceId ?? t('migrate.title'));
useLayoutEffect(() => { useAppAction(<GridLayouts gridLayout={gridLayout} onChange={setGridLayout} />);
setAction(<GridLayouts gridLayout={gridLayout} onChange={setGridLayout} />);
return () => {
setAction(null);
};
}, [t, name, sourceId, gridLayout]);
useEffect(() => { useEffect(() => {
if (isSourceLoading || isKnownSource) { if (isSourceLoading || isKnownSource) {

View 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);
};

View File

@@ -7,12 +7,11 @@
*/ */
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useLayoutEffect, useState } from 'react'; import { useState } from 'react';
import { useDefaultReaderSettingsWithDefaultFlag } from '@/modules/reader/services/ReaderSettingsMetadata.ts'; import { useDefaultReaderSettingsWithDefaultFlag } from '@/modules/reader/services/ReaderSettingsMetadata.ts';
import { LoadingPlaceholder } from '@/modules/core/components/feedback/LoadingPlaceholder.tsx'; import { LoadingPlaceholder } from '@/modules/core/components/feedback/LoadingPlaceholder.tsx';
import { EmptyViewAbsoluteCentered } from '@/modules/core/components/feedback/EmptyViewAbsoluteCentered.tsx'; import { EmptyViewAbsoluteCentered } from '@/modules/core/components/feedback/EmptyViewAbsoluteCentered.tsx';
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; 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 { IReaderSettings, ReadingMode } from '@/modules/reader/types/Reader.types.ts';
import { ReaderService } from '@/modules/reader/services/ReaderService.ts'; import { ReaderService } from '@/modules/reader/services/ReaderService.ts';
import { ReaderSettingsTabs } from '@/modules/reader/components/settings/ReaderSettingsTabs.tsx'; 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 = () => { export const GlobalReaderSettings = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
useAppTitle(t('reader.settings.title.reader')); useAppTitle(t('reader.settings.title.reader'));
useLayoutEffect(() => {
setAction(null);
return () => {
setAction(null);
};
}, [t]);
const [activeTab, setActiveTab] = useState(0); const [activeTab, setActiveTab] = useState(0);

View File

@@ -6,7 +6,6 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
import { useLayoutEffect } from 'react';
import List from '@mui/material/List'; import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem'; import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText'; 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 { EmptyViewAbsoluteCentered } from '@/modules/core/components/feedback/EmptyViewAbsoluteCentered.tsx';
import { VersionInfo } from '@/modules/app-updates/components/VersionInfo.tsx'; import { VersionInfo } from '@/modules/app-updates/components/VersionInfo.tsx';
import { getErrorMessage } from '@/lib/HelperFunctions.ts'; import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
import { epochToDate } from '@/util/DateHelper.ts'; import { epochToDate } from '@/util/DateHelper.ts';
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts'; import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
export function About() { export function About() {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
useAppTitle(t('settings.about.title')); useAppTitle(t('settings.about.title'));
useLayoutEffect(() => {
setAction(null);
return () => {
setAction(null);
};
}, [t]);
const { data, loading, error, refetch } = requestManager.useGetAbout({ notifyOnNetworkStatusChange: true }); const { data, loading, error, refetch } = requestManager.useGetAbout({ notifyOnNetworkStatusChange: true });

View File

@@ -7,7 +7,6 @@
*/ */
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useLayoutEffect } from 'react';
import List from '@mui/material/List'; import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem'; import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText'; 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 { MetadataThemeSettings } from '@/modules/theme/AppTheme.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.ts'; import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { AppStorage } from '@/lib/storage/AppStorage.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'; import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
export const Appearance = () => { export const Appearance = () => {
@@ -44,15 +42,7 @@ export const Appearance = () => {
const { mode, setMode } = useColorScheme(); const { mode, setMode } = useColorScheme();
const actualThemeMode = (mode ?? themeMode) as ThemeMode; const actualThemeMode = (mode ?? themeMode) as ThemeMode;
const { setAction } = useNavBarContext();
useAppTitle(t('settings.appearance.title')); useAppTitle(t('settings.appearance.title'));
useLayoutEffect(() => {
setAction(null);
return () => {
setAction(null);
};
}, [t]);
const { const {
settings, settings,

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * 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 { useTranslation } from 'react-i18next';
import List from '@mui/material/List'; import List from '@mui/material/List';
import ListItemIcon from '@mui/material/ListItemIcon'; import ListItemIcon from '@mui/material/ListItemIcon';
@@ -15,7 +15,6 @@ import ListAltIcon from '@mui/icons-material/ListAlt';
import Divider from '@mui/material/Divider'; import Divider from '@mui/material/Divider';
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts'; import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
import { ListItemLink } from '@/modules/core/components/lists/ListItemLink.tsx'; 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 { NAVIGATION_BAR_ITEMS } from '@/modules/navigation-bar/NavigationBar.constants.ts';
import { MediaQuery } from '@/modules/core/utils/MediaQuery.tsx'; import { MediaQuery } from '@/modules/core/utils/MediaQuery.tsx';
import { NavigationBarUtil } from '@/modules/navigation-bar/NavigationBar.util.ts'; 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 = () => { export const More = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
const isMobileWidth = MediaQuery.useIsMobileWidth(); const isMobileWidth = MediaQuery.useIsMobileWidth();
useAppTitle(t('global.label.more'));
const { const {
settings: { hideHistory }, settings: { hideHistory },
} = useMetadataServerSettings(); } = useMetadataServerSettings();
@@ -59,15 +59,6 @@ export const More = () => {
[NavBarItemMoreGroup.HIDDEN_ITEM]: hiddenItemsMoreGroup, [NavBarItemMoreGroup.HIDDEN_ITEM]: hiddenItemsMoreGroup,
}; };
useAppTitle(t('global.label.more'));
useLayoutEffect(() => {
setAction(null);
return () => {
setAction(null);
};
}, [t]);
return ( return (
<List sx={{ p: 0 }}> <List sx={{ p: 0 }}>
{Object.entries(finalHiddenNavBarItemsByGroup).map(([group, items], index, list) => ( {Object.entries(finalHiddenNavBarItemsByGroup).map(([group, items], index, list) => (

View File

@@ -7,7 +7,7 @@
*/ */
import { useTranslation, Trans } from 'react-i18next'; import { useTranslation, Trans } from 'react-i18next';
import { useLayoutEffect, useMemo } from 'react'; import { useMemo } from 'react';
import Link from '@mui/material/Link'; import Link from '@mui/material/Link';
import List from '@mui/material/List'; import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem'; 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 { MetadataUpdateSettings } from '@/modules/app-updates/AppUpdateChecker.types.ts';
import { ServerSettings as GqlServerSettings } from '@/modules/settings/Settings.types.ts'; import { ServerSettings as GqlServerSettings } from '@/modules/settings/Settings.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
type ServerSettingsType = Pick< type ServerSettingsType = Pick<
@@ -95,16 +94,8 @@ const getLogFilesCleanupDisplayValue = (ttl: number): string => {
export const ServerSettings = () => { export const ServerSettings = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
useAppTitle(t('settings.server.title.server')); useAppTitle(t('settings.server.title.server'));
useLayoutEffect(() => {
setAction(null);
return () => {
setAction(null);
};
}, [t]);
const { const {
settings: { serverInformAvailableUpdate }, settings: { serverInformAvailableUpdate },

View File

@@ -6,7 +6,6 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
import { useLayoutEffect } from 'react';
import AutoStoriesIcon from '@mui/icons-material/AutoStories'; import AutoStoriesIcon from '@mui/icons-material/AutoStories';
import List from '@mui/material/List'; import List from '@mui/material/List';
import BackupIcon from '@mui/icons-material/Backup'; 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 { makeToast } from '@/modules/core/utils/Toast.ts';
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts'; import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
export function Settings() { export function Settings() {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
useAppTitle(t('settings.title')); useAppTitle(t('settings.title'));
useLayoutEffect(() => {
setAction(null);
return () => {
setAction(null);
};
}, [t]);
const [triggerClearServerCache, { loading: isClearingServerCache }] = requestManager.useClearServerCache(); const [triggerClearServerCache, { loading: isClearingServerCache }] = requestManager.useClearServerCache();

View File

@@ -7,12 +7,10 @@
*/ */
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useLayoutEffect } from 'react';
import List from '@mui/material/List'; import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem'; import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText'; import ListItemText from '@mui/material/ListItemText';
import Switch from '@mui/material/Switch'; import Switch from '@mui/material/Switch';
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
import { requestManager } from '@/lib/requests/RequestManager.ts'; import { requestManager } from '@/lib/requests/RequestManager.ts';
import { WebUIUpdateIntervalSetting } from '@/modules/settings/components/webUI/WebUIUpdateIntervalSetting.tsx'; import { WebUIUpdateIntervalSetting } from '@/modules/settings/components/webUI/WebUIUpdateIntervalSetting.tsx';
import { TextSetting } from '@/modules/core/components/settings/text/TextSetting.tsx'; import { TextSetting } from '@/modules/core/components/settings/text/TextSetting.tsx';
@@ -121,16 +119,8 @@ const extractWebUISettings = (settings: ServerSettings): WebUISettingsType => ({
export const WebUISettings = () => { export const WebUISettings = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
useAppTitle(t('settings.webui.title.webui')); useAppTitle(t('settings.webui.title.webui'));
useLayoutEffect(() => {
setAction(null);
return () => {
setAction(null);
};
}, [t]);
const { const {
settings: { webUIInformAvailableUpdate }, settings: { webUIInformAvailableUpdate },

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * 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 { useParams } from 'react-router-dom';
import List from '@mui/material/List'; import List from '@mui/material/List';
import { useTranslation } from 'react-i18next'; 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 { makeToast } from '@/modules/core/utils/Toast.ts';
import { PreferenceProps } from '@/modules/source/Source.types.ts'; import { PreferenceProps } from '@/modules/source/Source.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
function getPrefComponent(type: string) { function getPrefComponent(type: string) {
@@ -49,16 +48,8 @@ function getPrefComponent(type: string) {
export function SourceConfigure() { export function SourceConfigure() {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
useAppTitle(t('source.configuration.title')); useAppTitle(t('source.configuration.title'));
useLayoutEffect(() => {
setAction(null);
return () => {
setAction(null);
};
}, [t]);
const { sourceId } = useParams<{ sourceId: string }>(); const { sourceId } = useParams<{ sourceId: string }>();
const { data, loading, error, refetch } = requestManager.useGetSource< const { data, loading, error, refetch } = requestManager.useGetSource<

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * 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 { useParams, useNavigate, useLocation, useSearchParams } from 'react-router-dom';
import IconButton from '@mui/material/IconButton'; import IconButton from '@mui/material/IconButton';
import SettingsIcon from '@mui/icons-material/Settings'; 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 { GridLayout } from '@/modules/core/Core.types.ts';
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts'; import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { Sources } from '@/modules/source/services/Sources.ts';
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.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' }; const DEFAULT_SOURCE: SourceIdInfo = { id: '-1' };
@@ -205,7 +206,7 @@ const useSourceManga = (
export function SourceMangas() { export function SourceMangas() {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction, appBarHeight } = useNavBarContext(); const { appBarHeight } = useNavBarContext();
const { sourceId } = useParams<{ sourceId: string }>(); const { sourceId } = useParams<{ sourceId: string }>();
@@ -400,8 +401,7 @@ export function SourceMangas() {
}, [clearCache]); }, [clearCache]);
useAppTitle(source?.displayName ?? t('source.title_one')); useAppTitle(source?.displayName ?? t('source.title_one'));
useLayoutEffect(() => { useAppAction(
setAction(
<> <>
<AppbarSearch /> <AppbarSearch />
<SourceGridLayout /> <SourceGridLayout />
@@ -420,11 +420,6 @@ export function SourceMangas() {
</>, </>,
); );
return () => {
setAction(null);
};
}, [t, source]);
const EmptyViewComponent = mangas.length ? EmptyView : EmptyViewAbsoluteCentered; const EmptyViewComponent = mangas.length ? EmptyView : EmptyViewAbsoluteCentered;
return ( return (

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * 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 IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import TravelExploreIcon from '@mui/icons-material/TravelExplore'; 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 { translateExtensionLanguage } from '@/modules/extension/Extensions.utils.ts';
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts'; import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.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 { Sources as SourceService } from '@/modules/source/services/Sources.ts';
import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts'; import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts';
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
export function Sources() { export function Sources() {
const { t } = useTranslation(); const { t } = useTranslation();
const { setAction } = useNavBarContext();
const [shownLangs, setShownLangs] = useLocalStorage<string[]>('shownSourceLangs', sourceDefualtLangs()); const [shownLangs, setShownLangs] = useLocalStorage<string[]>('shownSourceLangs', sourceDefualtLangs());
const { const {
@@ -61,8 +60,7 @@ export function Sources() {
const navigate = useNavigate(); const navigate = useNavigate();
useLayoutEffect(() => { useAppAction(
setAction(
<> <>
<CustomTooltip title={t('search.title.global_search')}> <CustomTooltip title={t('search.title.global_search')}>
<IconButton onClick={() => navigate(AppRoutes.sources.childRoutes.searchAll.path)} color="inherit"> <IconButton onClick={() => navigate(AppRoutes.sources.childRoutes.searchAll.path)} color="inherit">
@@ -75,13 +73,9 @@ export function Sources() {
languages={sourceLanguages} languages={sourceLanguages}
/> />
</>, </>,
[t, shownLangs, sourceLanguages],
); );
return () => {
setAction(null);
};
}, [t, shownLangs, sourceLanguages]);
if (isLoading) return <LoadingPlaceholder />; if (isLoading) return <LoadingPlaceholder />;
if (error) { if (error) {

View File

@@ -25,12 +25,12 @@ import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContex
import { Chapters } from '@/modules/chapter/services/Chapters.ts'; import { Chapters } from '@/modules/chapter/services/Chapters.ts';
import { GROUPED_VIRTUOSO_Z_INDEX } from '@/modules/core/AppRoute.constants.ts'; import { GROUPED_VIRTUOSO_Z_INDEX } from '@/modules/core/AppRoute.constants.ts';
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts'; import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
export const Updates: React.FC = () => { export const Updates: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { appBarHeight } = useNavBarContext(); const { appBarHeight } = useNavBarContext();
const { setAction } = useNavBarContext();
const { const {
data: chapterUpdateData, data: chapterUpdateData,
loading: isLoading, loading: isLoading,
@@ -74,13 +74,7 @@ export const Updates: React.FC = () => {
const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp; const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp;
useAppTitle(t('updates.title')); useAppTitle(t('updates.title'));
useLayoutEffect(() => { useAppAction(<UpdateChecker />);
setAction(<UpdateChecker />);
return () => {
setAction(null);
};
}, [t, lastUpdateTimestamp]);
const loadMore = useCallback(() => { const loadMore = useCallback(() => {
if (!hasNextPage) { if (!hasNextPage) {