Introduce "SearchParam" enum

This commit is contained in:
schroda
2025-07-23 01:52:41 +02:00
parent 18f524c91a
commit 9a9dbab7df
9 changed files with 25 additions and 13 deletions

View File

@@ -20,6 +20,7 @@ import { useResizeObserver } from '@/modules/core/hooks/useResizeObserver.tsx';
import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts'; import { useAppTitle } from '@/modules/navigation-bar/hooks/useAppTitle.ts';
import { BrowseTab } from '@/modules/browse/Browse.types.ts'; import { BrowseTab } from '@/modules/browse/Browse.types.ts';
import { GROUPED_VIRTUOSO_Z_INDEX } from '@/lib/virtuoso/Virtuoso.constants.ts'; import { GROUPED_VIRTUOSO_Z_INDEX } from '@/lib/virtuoso/Virtuoso.constants.ts';
import { SearchParam } from '@/modules/core/Core.types.ts';
export function Browse() { export function Browse() {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -32,7 +33,7 @@ export function Browse() {
useCallback(() => setTabsMenuHeight(tabsMenuRef.current!.offsetHeight), [tabsMenuRef.current]), useCallback(() => setTabsMenuHeight(tabsMenuRef.current!.offsetHeight), [tabsMenuRef.current]),
); );
const [tabSearchParam, setTabSearchParam] = useQueryParam('tab', StringParam, {}); const [tabSearchParam, setTabSearchParam] = useQueryParam(SearchParam.TAB, StringParam, {});
const tabName = (tabSearchParam as BrowseTab) ?? BrowseTab.SOURCES; const tabName = (tabSearchParam as BrowseTab) ?? BrowseTab.SOURCES;
if (!tabSearchParam) { if (!tabSearchParam) {

View File

@@ -11,6 +11,7 @@ import { MangaIdInfo } from '@/modules/manga/Manga.types.ts';
import { ChapterSourceOrderInfo } from '@/modules/chapter/Chapter.types.ts'; import { ChapterSourceOrderInfo } from '@/modules/chapter/Chapter.types.ts';
import { BrowseTab } from '@/modules/browse/Browse.types.ts'; import { BrowseTab } from '@/modules/browse/Browse.types.ts';
import { SearchParam } from '@/modules/core/Core.types.ts';
type AppRouteInfo = { type AppRouteInfo = {
match: string; match: string;
@@ -21,7 +22,7 @@ type TAppRoutes = Record<string, AppRouteInfo & { childRoutes?: TAppRoutes }>;
const createParam = (name: string, value: any): string => (value ? `${name}=${encodeURIComponent(value)}` : ''); const createParam = (name: string, value: any): string => (value ? `${name}=${encodeURIComponent(value)}` : '');
const createQueryParam = (query: string | null | undefined): string => createParam('query', query); const createQueryParam = (query: string | null | undefined): string => createParam(SearchParam.QUERY, query);
const addParams = (path: string, ...params: string[]) => { const addParams = (path: string, ...params: string[]) => {
const joinedParams = params.filter(Boolean).join('&'); const joinedParams = params.filter(Boolean).join('&');
@@ -151,7 +152,7 @@ export const AppRoutes = {
library: { library: {
match: 'library', match: 'library',
path: (tab?: string, search?: string) => path: (tab?: string, search?: string) =>
addParams('/library', createParam('tab', tab), createQueryParam(search)), addParams('/library', createParam(SearchParam.TAB, tab), createQueryParam(search)),
}, },
updates: { updates: {
match: 'updates', match: 'updates',
@@ -167,7 +168,7 @@ export const AppRoutes = {
}, },
browse: { browse: {
match: 'browse', match: 'browse',
path: (tab?: BrowseTab) => addParams('/browse', createParam('tab', tab)), path: (tab?: BrowseTab) => addParams('/browse', createParam(SearchParam.TAB, tab)),
}, },
migrate: { migrate: {
match: 'migrate/source/:sourceId', match: 'migrate/source/:sourceId',

View File

@@ -60,3 +60,8 @@ export enum ScrollDirection {
Y, Y,
XY, XY,
} }
export enum SearchParam {
TAB = 'tab',
QUERY = 'query',
}

View File

@@ -16,6 +16,7 @@ import { useTheme } from '@mui/material/styles';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { CustomTooltip } from '@/modules/core/components/CustomTooltip.tsx'; import { CustomTooltip } from '@/modules/core/components/CustomTooltip.tsx';
import { SearchTextField } from '@/modules/core/components/inputs/SearchTextField.tsx'; import { SearchTextField } from '@/modules/core/components/inputs/SearchTextField.tsx';
import { SearchParam } from '@/modules/core/Core.types.ts';
interface IProps { interface IProps {
isClosable?: boolean; isClosable?: boolean;
@@ -30,7 +31,7 @@ export const AppbarSearch: React.FunctionComponent<IProps> = (props) => {
const [prevLocationKey, setPrevLocationKey] = useState<string>(); const [prevLocationKey, setPrevLocationKey] = useState<string>();
const location = useLocation(); const location = useLocation();
const [query, setQuery] = useQueryParam('query', StringParam); const [query, setQuery] = useQueryParam(SearchParam.QUERY, StringParam);
const [isSearchOpen, setIsSearchOpen] = useState(!isClosable || !!query); const [isSearchOpen, setIsSearchOpen] = useState(!isClosable || !!query);
const inputRef = React.useRef<HTMLInputElement>(undefined); const inputRef = React.useRef<HTMLInputElement>(undefined);

View File

@@ -51,6 +51,7 @@ import {
} 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'; import { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
import { SearchParam } from '@/modules/core/Core.types.ts';
const LANGUAGE = 0; const LANGUAGE = 0;
const EXTENSIONS = 1; const EXTENSIONS = 1;
@@ -131,7 +132,7 @@ export function Extensions({ tabsMenuHeight }: { tabsMenuHeight: number }) {
keyof Pick<MetadataBrowseSettings, 'extensionLanguages'> keyof Pick<MetadataBrowseSettings, 'extensionLanguages'>
>((e) => makeToast(t('global.error.label.failed_to_save_changes'), 'error', getErrorMessage(e))); >((e) => makeToast(t('global.error.label.failed_to_save_changes'), 'error', getErrorMessage(e)));
const [query] = useQueryParam('query', StringParam); const [query] = useQueryParam(SearchParam.QUERY, StringParam);
const [updatingExtensionIds, setUpdatingExtensionIds] = useState<string[]>([]); const [updatingExtensionIds, setUpdatingExtensionIds] = useState<string[]>([]);
const [refetchExtensions, setRefetchExtensions] = useState({}); const [refetchExtensions, setRefetchExtensions] = useState({});

View File

@@ -53,6 +53,7 @@ import { CustomTooltip } from '@/modules/core/components/CustomTooltip.tsx';
import { MUIUtil } from '@/lib/mui/MUI.util.ts'; import { MUIUtil } from '@/lib/mui/MUI.util.ts';
import { MetadataBrowseSettings } from '@/modules/browse/Browse.types.ts'; import { MetadataBrowseSettings } from '@/modules/browse/Browse.types.ts';
import { SourceLanguageSelect } from '@/modules/source/components/SourceLanguageSelect.tsx'; import { SourceLanguageSelect } from '@/modules/source/components/SourceLanguageSelect.tsx';
import { SearchParam } from '@/modules/core/Core.types.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>;
@@ -238,7 +239,7 @@ export const SearchAll: React.FC = () => {
const shouldShowOnlyPinnedSources = state?.shouldShowOnlyPinnedSources ?? true; const shouldShowOnlyPinnedSources = state?.shouldShowOnlyPinnedSources ?? true;
const isMigrateMode = pathname.startsWith('/migrate/source'); const isMigrateMode = pathname.startsWith('/migrate/source');
const [query] = useQueryParam('query', StringParam); const [query] = useQueryParam(SearchParam.QUERY, StringParam);
const searchString = useDebounce(query, TRIGGER_SEARCH_THRESHOLD); const searchString = useDebounce(query, TRIGGER_SEARCH_THRESHOLD);
const { languages: shownLangs, setLanguages: setShownLangs } = Sources.useLanguages(); const { languages: shownLangs, setLanguages: setShownLangs } = Sources.useLanguages();

View File

@@ -23,6 +23,7 @@ import {
MangaUnreadInfo, MangaUnreadInfo,
} from '@/modules/manga/Manga.types.ts'; } from '@/modules/manga/Manga.types.ts';
import { SourceDisplayNameInfo } from '@/modules/source/Source.types.ts'; import { SourceDisplayNameInfo } from '@/modules/source/Source.types.ts';
import { SearchParam } from '@/modules/core/Core.types.ts';
const triStateFilter = ( const triStateFilter = (
triState: NullAndUndefined<boolean>, triState: NullAndUndefined<boolean>,
@@ -220,7 +221,7 @@ export const useGetVisibleLibraryMangas = <Manga extends MangaIdInfo & TMangasFi
showFilteredOutMessage: boolean; showFilteredOutMessage: boolean;
filterKey: string; filterKey: string;
} => { } => {
const [query] = useQueryParam('query', StringParam); const [query] = useQueryParam(SearchParam.QUERY, StringParam);
const options = useGetCategoryMetadata(category ?? DEFAULT_CATEGORY); const options = useGetCategoryMetadata(category ?? DEFAULT_CATEGORY);
const { const {
hasUnreadChapters, hasUnreadChapters,

View File

@@ -47,6 +47,7 @@ import { GET_LIBRARY_MANGA_COUNT } from '@/lib/graphql/queries/MangaQuery.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 { useAppAction } from '@/modules/navigation-bar/hooks/useAppAction.ts';
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts'; import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
import { SearchParam } from '@/modules/core/Core.types.ts';
const TitleWithSizeTag = styled('span')({ const TitleWithSizeTag = styled('span')({
display: 'flex', display: 'flex',
@@ -87,8 +88,8 @@ export function Library() {
const librarySize = librarySizeResponse.data?.mangas.totalCount ?? 0; const librarySize = librarySizeResponse.data?.mangas.totalCount ?? 0;
const [tabSearchParam, setTabSearchParam] = useQueryParam('tab', NumberParam); const [tabSearchParam, setTabSearchParam] = useQueryParam(SearchParam.TAB, NumberParam);
const [query] = useQueryParam('query', StringParam); const [query] = useQueryParam(SearchParam.QUERY, StringParam);
const activeTab: (typeof tabs)[number] | undefined = tabs.find((tab) => tab.id === tabSearchParam) ?? tabs[0]; const activeTab: (typeof tabs)[number] | undefined = tabs.find((tab) => tab.id === tabSearchParam) ?? tabs[0];

View File

@@ -50,7 +50,7 @@ import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'
import { EmptyView } from '@/modules/core/components/feedback/EmptyView.tsx'; import { EmptyView } from '@/modules/core/components/feedback/EmptyView.tsx';
import { EmptyViewAbsoluteCentered } from '@/modules/core/components/feedback/EmptyViewAbsoluteCentered.tsx'; import { EmptyViewAbsoluteCentered } from '@/modules/core/components/feedback/EmptyViewAbsoluteCentered.tsx';
import { MangaIdInfo } from '@/modules/manga/Manga.types.ts'; import { MangaIdInfo } from '@/modules/manga/Manga.types.ts';
import { GridLayout } from '@/modules/core/Core.types.ts'; import { GridLayout, SearchParam } 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';
@@ -227,7 +227,7 @@ export function SourceMangas() {
} = useMetadataServerSettings(); } = useMetadataServerSettings();
const [sourceGridLayout] = useLocalStorage('source-grid-layout', GridLayout.Compact); const [sourceGridLayout] = useLocalStorage('source-grid-layout', GridLayout.Compact);
const [query] = useQueryParam('query', StringParam); const [query] = useQueryParam(SearchParam.QUERY, StringParam);
const [currentFiltersToApply, setCurrentFiltersToApply] = useSessionStorage<IPos[] | undefined>( const [currentFiltersToApply, setCurrentFiltersToApply] = useSessionStorage<IPos[] | undefined>(
`source-mangas-${sourceId}-filters`, `source-mangas-${sourceId}-filters`,
[], [],
@@ -314,7 +314,7 @@ export function SourceMangas() {
} }
if (savedSearchQuery) { if (savedSearchQuery) {
searchParams.set('query', savedSearchQuery); searchParams.set(SearchParam.QUERY, savedSearchQuery);
setSearchParams(searchParams); setSearchParams(searchParams);
} }
}, },