Introduce "useAppTitleAndAction" hook

This commit is contained in:
schroda
2025-05-03 13:37:20 +02:00
parent aacdbaaeef
commit 04768d5210
8 changed files with 55 additions and 40 deletions

View File

@@ -33,8 +33,7 @@ import { getErrorMessage } from '@/lib/HelperFunctions.ts';
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 { useAppTitleAndAction } from '@/modules/navigation-bar/hooks/useAppTitleAndAction.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>;
@@ -192,8 +191,6 @@ export const SearchAll: React.FC = () => {
const { pathname, state } = useLocation<{ mangaTitle?: string }>(); const { pathname, state } = useLocation<{ mangaTitle?: string }>();
const isMigrateMode = pathname.startsWith('/migrate/source'); const isMigrateMode = pathname.startsWith('/migrate/source');
useAppTitle(t(isMigrateMode ? 'migrate.search.title' : 'search.title.global_search', { title: state?.mangaTitle }));
const [query] = useQueryParam('query', StringParam); const [query] = useQueryParam('query', StringParam);
const searchString = useDebounce(query, TRIGGER_SEARCH_THRESHOLD); const searchString = useDebounce(query, TRIGGER_SEARCH_THRESHOLD);
@@ -234,20 +231,17 @@ export const SearchAll: React.FC = () => {
[setSourceToLoadingStateMap], [setSourceToLoadingStateMap],
); );
useAppAction( useAppTitleAndAction(
useMemo( t(isMigrateMode ? 'migrate.search.title' : 'search.title.global_search', { title: state?.mangaTitle }),
() => ( <>
<> <AppbarSearch isClosable={false} />
<AppbarSearch isClosable={false} /> <LanguageSelect
<LanguageSelect selectedLanguages={shownLangs}
selectedLanguages={shownLangs} setSelectedLanguages={setShownLangs}
setSelectedLanguages={setShownLangs} languages={sourceLanguages}
languages={sourceLanguages} />
/> </>,
</> [shownLangs, setShownLangs, sourceLanguages],
),
[shownLangs, setShownLangs, sourceLanguages],
),
); );
if (loading) { if (loading) {

View File

@@ -34,8 +34,7 @@ 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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts'; import { useAppTitleAndAction } from '@/modules/navigation-bar/hooks/useAppTitleAndAction.ts';
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
export const LibraryDuplicates = () => { export const LibraryDuplicates = () => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -46,8 +45,8 @@ export const LibraryDuplicates = () => {
false, false,
); );
useAppTitle(t('library.settings.advanced.duplicates.label.title')); useAppTitleAndAction(
useAppAction( t('library.settings.advanced.duplicates.label.title'),
<> <>
<GridLayouts gridLayout={gridLayout} onChange={setGridLayout} /> <GridLayouts gridLayout={gridLayout} onChange={setGridLayout} />
<PopupState variant="popover" popupId="library-dupliactes-settings"> <PopupState variant="popover" popupId="library-dupliactes-settings">
@@ -69,6 +68,7 @@ export const LibraryDuplicates = () => {
)} )}
</PopupState> </PopupState>
</>, </>,
[t, gridLayout, checkAlternativeTitles],
); );
const { data, loading, error, refetch } = requestManager.useGetMangas< const { data, loading, error, refetch } = requestManager.useGetMangas<

View File

@@ -26,8 +26,7 @@ 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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts'; import { useAppTitleAndAction } from '@/modules/navigation-bar/hooks/useAppTitleAndAction.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();
@@ -59,8 +58,8 @@ export const Manga: React.FC = () => {
} }
}, [manga]); }, [manga]);
useAppTitle(manga?.title ?? t('manga.title_one')); useAppTitleAndAction(
useAppAction( manga?.title ?? t('manga.title_one'),
<Stack <Stack
direction="row" direction="row"
sx={{ sx={{
@@ -89,6 +88,7 @@ export const Manga: React.FC = () => {
)} )}
{manga && <MangaToolbarMenu manga={manga} onRefresh={refresh} refreshing={refreshing} />} {manga && <MangaToolbarMenu manga={manga} onRefresh={refresh} refreshing={refreshing} />}
</Stack>, </Stack>,
[t, error, isValidating, refreshing, manga, refresh],
); );
if (error && !manga) { if (error && !manga) {

View File

@@ -22,8 +22,7 @@ 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 { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts'; import { useAppTitleAndAction } from '@/modules/navigation-bar/hooks/useAppTitleAndAction.ts';
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
export const Migrate = () => { export const Migrate = () => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -68,8 +67,11 @@ export const Migrate = () => {
notifyOnNetworkStatusChange: true, notifyOnNetworkStatusChange: true,
}); });
useAppTitle(name ?? sourceId ?? t('migrate.title')); useAppTitleAndAction(
useAppAction(<GridLayouts gridLayout={gridLayout} onChange={setGridLayout} />); name ?? sourceId ?? t('migrate.title'),
<GridLayouts gridLayout={gridLayout} onChange={setGridLayout} />,
[gridLayout],
);
useEffect(() => { useEffect(() => {
if (isSourceLoading || isKnownSource) { if (isSourceLoading || isKnownSource) {

View File

@@ -8,6 +8,7 @@
import { OverridableComponent } from '@mui/material/OverridableComponent'; import { OverridableComponent } from '@mui/material/OverridableComponent';
import { SvgIconTypeMap } from '@mui/material/SvgIcon'; import { SvgIconTypeMap } from '@mui/material/SvgIcon';
import { ReactNode } from 'react';
import { TranslationKey } from '@/Base.types.ts'; import { TranslationKey } from '@/Base.types.ts';
import { StaticAppRoute } from '@/modules/core/AppRoute.constants.ts'; import { StaticAppRoute } from '@/modules/core/AppRoute.constants.ts';
@@ -40,8 +41,8 @@ export type NavbarContextType = {
setAppBarHeight: React.Dispatch<React.SetStateAction<number>>; setAppBarHeight: React.Dispatch<React.SetStateAction<number>>;
// AppBar action buttons // AppBar action buttons
action: any; action: ReactNode;
setAction: React.Dispatch<React.SetStateAction<any>>; setAction: React.Dispatch<React.SetStateAction<ReactNode>>;
// Allow default navbar to be overrided // Allow default navbar to be overrided
override: INavbarOverride; override: INavbarOverride;

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 { NavbarContextType } from '@/modules/navigation-bar/NavigationBar.types.ts';
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
export const useAppTitleAndAction = (
title: NavbarContextType['title'],
action: NavbarContextType['action'],
actionDependencies?: any[],
) => {
useAppTitle(title);
useAppAction(action, actionDependencies);
};

View File

@@ -52,8 +52,7 @@ 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 { 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 { useAppTitleAndAction } from '@/modules/navigation-bar/hooks/useAppTitleAndAction.ts';
import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx'; import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
const DEFAULT_SOURCE: SourceIdInfo = { id: '-1' }; const DEFAULT_SOURCE: SourceIdInfo = { id: '-1' };
@@ -400,8 +399,8 @@ export function SourceMangas() {
requestManager.clearBrowseCacheFor(sourceId); requestManager.clearBrowseCacheFor(sourceId);
}, [clearCache]); }, [clearCache]);
useAppTitle(source?.displayName ?? t('source.title_one')); useAppTitleAndAction(
useAppAction( source?.displayName ?? t('source.title_one'),
<> <>
<AppbarSearch /> <AppbarSearch />
<SourceGridLayout /> <SourceGridLayout />
@@ -418,6 +417,7 @@ export function SourceMangas() {
</CustomTooltip> </CustomTooltip>
)} )}
</>, </>,
[source],
); );
const EmptyViewComponent = mangas.length ? EmptyView : EmptyViewAbsoluteCentered; const EmptyViewComponent = mangas.length ? EmptyView : EmptyViewAbsoluteCentered;

View File

@@ -24,8 +24,7 @@ import { ChapterUpdateCard } from '@/modules/updates/components/ChapterUpdateCar
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx'; import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
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 { useAppTitleAndAction } from '@/modules/navigation-bar/hooks/useAppTitleAndAction.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();
@@ -73,8 +72,7 @@ export const Updates: React.FC = () => {
}); });
const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp; const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp;
useAppTitle(t('updates.title')); useAppTitleAndAction(t('updates.title'), <UpdateChecker />);
useAppAction(<UpdateChecker />);
const loadMore = useCallback(() => { const loadMore = useCallback(() => {
if (!hasNextPage) { if (!hasNextPage) {