From 1098ca44478265980397454a587741e2f13a8857 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 30 Jul 2025 14:15:18 -0400 Subject: [PATCH] Use query parameters for plugin filters --- src/apps/dashboard/routes/plugins/index.tsx | 20 ++++++++++++++------ src/hooks/useSearchParam.ts | 14 ++++++++++---- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/apps/dashboard/routes/plugins/index.tsx b/src/apps/dashboard/routes/plugins/index.tsx index 0675d0316..b593f2c84 100644 --- a/src/apps/dashboard/routes/plugins/index.tsx +++ b/src/apps/dashboard/routes/plugins/index.tsx @@ -6,7 +6,7 @@ import Divider from '@mui/material/Divider'; import Grid from '@mui/material/Grid'; import Stack from '@mui/material/Stack'; import Typography from '@mui/material/Typography'; -import React, { useCallback, useMemo, useState } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { Link } from 'react-router-dom'; import SearchInput from 'apps/dashboard/components/SearchInput'; @@ -18,7 +18,9 @@ import { PluginCategory } from 'apps/dashboard/features/plugins/constants/plugin import { PluginStatusOption } from 'apps/dashboard/features/plugins/constants/pluginStatusOption'; import Loading from 'components/loading/LoadingComponent'; import Page from 'components/Page'; +import useSearchParam from 'hooks/useSearchParam'; import globalize from 'lib/globalize'; + /** * The list of primary/main categories. * Any category not in this list will be added to the "other" category. @@ -34,23 +36,29 @@ const MAIN_CATEGORIES = [ PluginCategory.Subtitles.toLowerCase() ]; +const CATEGORY_PARAM = 'category'; +const QUERY_PARAM = 'query'; +const STATUS_PARAM = 'status'; + export const Component = () => { const { data: pluginDetails, isError, isPending } = usePluginDetails(); - const [ category, setCategory ] = useState(); - const [ searchQuery, setSearchQuery ] = useState(''); - const [ status, setStatus ] = useState(PluginStatusOption.Installed); + const [ category, setCategory ] = useSearchParam(CATEGORY_PARAM); + const [ searchQuery, setSearchQuery ] = useSearchParam(QUERY_PARAM); + const [ status, setStatus ] = useSearchParam(STATUS_PARAM, PluginStatusOption.Installed); const onSearchChange = useCallback((event: React.ChangeEvent) => { setSearchQuery(event.target.value); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const onViewAll = useCallback(() => { - if (category) setCategory(undefined); + if (category) setCategory(''); else setStatus(PluginStatusOption.All); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ category ]); const filteredPlugins = useMemo(() => { @@ -198,7 +206,7 @@ export const Component = () => { setCategory(undefined)} + onClick={() => setCategory('')} label={globalize.translate('All')} /> diff --git a/src/hooks/useSearchParam.ts b/src/hooks/useSearchParam.ts index 6d45c56f5..83b42ae9e 100644 --- a/src/hooks/useSearchParam.ts +++ b/src/hooks/useSearchParam.ts @@ -7,15 +7,21 @@ import { usePrevious } from './usePrevious'; * A hook for getting and setting a URL search parameter value that automatically handles updates to/from the URL. * @param param The search parameter name. */ -const useSearchParam: (param: string) => [ string, React.Dispatch> ] = param => { +const useSearchParam: ( + param: string, + defaultValue?: string +) => [ string, React.Dispatch> ] = ( + param, + defaultValue = '' +) => { const [ searchParams, setSearchParams ] = useSearchParams(); - const urlValue = searchParams.get(param) || ''; + const urlValue = searchParams.get(param) || defaultValue; const [ value, setValue ] = useState(urlValue); - const previousValue = usePrevious(value, ''); + const previousValue = usePrevious(value, defaultValue); useEffect(() => { if (value !== previousValue) { - if (value === '' && urlValue !== '') { + if (value === defaultValue && urlValue !== defaultValue) { // The query input has been cleared; remove the url param searchParams.delete(param); setSearchParams(searchParams, { replace: true });