mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-07 04:20:12 +02:00
re-add useTransition to router
This commit is contained in:
@@ -349,9 +349,12 @@ export const useItemListInfiniteLoader = ({
|
||||
mutationKey: getListRefreshMutationKey(eventKey),
|
||||
});
|
||||
|
||||
const refreshMutationRef = useRef(refreshMutation);
|
||||
refreshMutationRef.current = refreshMutation;
|
||||
|
||||
const refresh = useCallback(
|
||||
async (force?: boolean) => refreshMutation.mutateAsync(force),
|
||||
[refreshMutation],
|
||||
async (force?: boolean) => refreshMutationRef.current.mutateAsync(force),
|
||||
[],
|
||||
);
|
||||
|
||||
const updateItems = useCallback(
|
||||
@@ -383,7 +386,7 @@ export const useItemListInfiniteLoader = ({
|
||||
return;
|
||||
}
|
||||
|
||||
refreshMutation.mutate(true);
|
||||
refreshMutationRef.current.mutate(true);
|
||||
};
|
||||
|
||||
eventEmitter.on('ITEM_LIST_REFRESH', handleRefresh);
|
||||
@@ -391,7 +394,7 @@ export const useItemListInfiniteLoader = ({
|
||||
return () => {
|
||||
eventEmitter.off('ITEM_LIST_REFRESH', handleRefresh);
|
||||
};
|
||||
}, [eventKey, refreshMutation]);
|
||||
}, [eventKey]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleFavorite = (payload: UserFavoriteEventPayload) => {
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
useSuspenseQuery,
|
||||
UseSuspenseQueryOptions,
|
||||
} from '@tanstack/react-query';
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
|
||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||
import { useListContext } from '/@/renderer/context/list-context';
|
||||
@@ -115,6 +115,9 @@ export const useItemListPaginatedLoader = ({
|
||||
mutationKey: getListRefreshMutationKey(eventKey ?? 'paginated'),
|
||||
});
|
||||
|
||||
const refreshMutationRef = useRef(refreshMutation);
|
||||
refreshMutationRef.current = refreshMutation;
|
||||
|
||||
const updateItems = useCallback(
|
||||
(indexes: number[], value: object) => {
|
||||
return queryClient.setQueryData(
|
||||
@@ -153,7 +156,7 @@ export const useItemListPaginatedLoader = ({
|
||||
return;
|
||||
}
|
||||
|
||||
refreshMutation.mutate(true);
|
||||
refreshMutationRef.current.mutate(true);
|
||||
};
|
||||
|
||||
const handleFavorite = (payload: UserFavoriteEventPayload) => {
|
||||
@@ -220,7 +223,7 @@ export const useItemListPaginatedLoader = ({
|
||||
eventEmitter.off('USER_FAVORITE', handleFavorite);
|
||||
eventEmitter.off('USER_RATING', handleRating);
|
||||
};
|
||||
}, [data, eventKey, itemType, refreshMutation, serverId, updateItems]);
|
||||
}, [data, eventKey, itemType, serverId, updateItems]);
|
||||
|
||||
return { data: data?.items || [], pageCount, totalItemCount };
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
setMultipleSearchParams,
|
||||
setSearchParam,
|
||||
} from '/@/renderer/utils/query-params';
|
||||
import { runInUrlTransition } from '/@/renderer/utils/url-transition';
|
||||
import { AlbumListSort, SortOrder } from '/@/shared/types/domain-types';
|
||||
import { ItemListKey } from '/@/shared/types/types';
|
||||
|
||||
@@ -74,8 +75,10 @@ export const useAlbumListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setGenreId = useCallback(
|
||||
(value: null | string[]) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.GENRE_ID, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.GENRE_ID, value), {
|
||||
replace: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -83,8 +86,13 @@ export const useAlbumListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setAlbumArtist = useCallback(
|
||||
(value: null | string[]) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.ARTIST_IDS, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.ARTIST_IDS, value),
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -92,8 +100,10 @@ export const useAlbumListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setMinYear = useCallback(
|
||||
(value: null | number) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.MIN_YEAR, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.MIN_YEAR, value), {
|
||||
replace: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -101,8 +111,10 @@ export const useAlbumListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setMaxYear = useCallback(
|
||||
(value: null | number) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.MAX_YEAR, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.MAX_YEAR, value), {
|
||||
replace: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -110,8 +122,10 @@ export const useAlbumListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setFavorite = useCallback(
|
||||
(value: boolean | null) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.FAVORITE, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.FAVORITE, value), {
|
||||
replace: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -119,8 +133,13 @@ export const useAlbumListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setCompilation = useCallback(
|
||||
(value: boolean | null) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.COMPILATION, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.COMPILATION, value),
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -128,8 +147,13 @@ export const useAlbumListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setHasRating = useCallback(
|
||||
(value: boolean | null) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.HAS_RATING, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.HAS_RATING, value),
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -137,65 +161,71 @@ export const useAlbumListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setRecentlyPlayed = useCallback(
|
||||
(value: boolean | null) => {
|
||||
setSearchParams(
|
||||
(prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.RECENTLY_PLAYED, value),
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => setSearchParam(prev, FILTER_KEYS.ALBUM.RECENTLY_PLAYED, value),
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
);
|
||||
|
||||
const setCustom = useCallback(
|
||||
(value: null | Record<string, any>) => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const previousValue = prev.get(FILTER_KEYS.ALBUM._CUSTOM);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const previousValue = prev.get(FILTER_KEYS.ALBUM._CUSTOM);
|
||||
|
||||
const newCustom = {
|
||||
...(previousValue ? JSON.parse(previousValue) : {}),
|
||||
...value,
|
||||
};
|
||||
const newCustom = {
|
||||
...(previousValue ? JSON.parse(previousValue) : {}),
|
||||
...value,
|
||||
};
|
||||
|
||||
const filteredNewCustom = Object.fromEntries(
|
||||
Object.entries(newCustom).filter(
|
||||
([, value]) => value !== null && value !== undefined,
|
||||
),
|
||||
);
|
||||
const filteredNewCustom = Object.fromEntries(
|
||||
Object.entries(newCustom).filter(
|
||||
([, value]) => value !== null && value !== undefined,
|
||||
),
|
||||
);
|
||||
|
||||
prev.set(FILTER_KEYS.ALBUM._CUSTOM, JSON.stringify(filteredNewCustom));
|
||||
return prev;
|
||||
},
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
prev.set(FILTER_KEYS.ALBUM._CUSTOM, JSON.stringify(filteredNewCustom));
|
||||
return prev;
|
||||
},
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
);
|
||||
|
||||
const clear = useCallback(() => {
|
||||
setSearchParams(
|
||||
(prev) =>
|
||||
setMultipleSearchParams(
|
||||
prev,
|
||||
{
|
||||
[FILTER_KEYS.ALBUM._CUSTOM]: null,
|
||||
[FILTER_KEYS.ALBUM.ARTIST_IDS]: null,
|
||||
[FILTER_KEYS.ALBUM.COMPILATION]: null,
|
||||
[FILTER_KEYS.ALBUM.FAVORITE]: null,
|
||||
[FILTER_KEYS.ALBUM.GENRE_ID]: null,
|
||||
[FILTER_KEYS.ALBUM.HAS_RATING]: null,
|
||||
[FILTER_KEYS.ALBUM.MAX_YEAR]: null,
|
||||
[FILTER_KEYS.ALBUM.MIN_YEAR]: null,
|
||||
[FILTER_KEYS.ALBUM.RECENTLY_PLAYED]: null,
|
||||
[FILTER_KEYS.SHARED.SEARCH_TERM]: null,
|
||||
},
|
||||
new Set([FILTER_KEYS.ALBUM._CUSTOM]),
|
||||
),
|
||||
{ replace: true },
|
||||
);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) =>
|
||||
setMultipleSearchParams(
|
||||
prev,
|
||||
{
|
||||
[FILTER_KEYS.ALBUM._CUSTOM]: null,
|
||||
[FILTER_KEYS.ALBUM.ARTIST_IDS]: null,
|
||||
[FILTER_KEYS.ALBUM.COMPILATION]: null,
|
||||
[FILTER_KEYS.ALBUM.FAVORITE]: null,
|
||||
[FILTER_KEYS.ALBUM.GENRE_ID]: null,
|
||||
[FILTER_KEYS.ALBUM.HAS_RATING]: null,
|
||||
[FILTER_KEYS.ALBUM.MAX_YEAR]: null,
|
||||
[FILTER_KEYS.ALBUM.MIN_YEAR]: null,
|
||||
[FILTER_KEYS.ALBUM.RECENTLY_PLAYED]: null,
|
||||
[FILTER_KEYS.SHARED.SEARCH_TERM]: null,
|
||||
},
|
||||
new Set([FILTER_KEYS.ALBUM._CUSTOM]),
|
||||
),
|
||||
{ replace: true },
|
||||
);
|
||||
});
|
||||
}, [setSearchParams]);
|
||||
|
||||
const query = useMemo(
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useSortByFilter } from '/@/renderer/features/shared/hooks/use-sort-by-f
|
||||
import { useSortOrderFilter } from '/@/renderer/features/shared/hooks/use-sort-order-filter';
|
||||
import { FILTER_KEYS } from '/@/renderer/features/shared/utils';
|
||||
import { setMultipleSearchParams } from '/@/renderer/utils/query-params';
|
||||
import { runInUrlTransition } from '/@/renderer/utils/url-transition';
|
||||
import { AlbumArtistListSort } from '/@/shared/types/domain-types';
|
||||
import { ItemListKey } from '/@/shared/types/types';
|
||||
|
||||
@@ -19,13 +20,15 @@ export const useAlbumArtistListFilters = () => {
|
||||
const [, setSearchParams] = useSearchParams();
|
||||
|
||||
const clear = useCallback(() => {
|
||||
setSearchParams(
|
||||
(prev) =>
|
||||
setMultipleSearchParams(prev, {
|
||||
[FILTER_KEYS.SHARED.SEARCH_TERM]: null,
|
||||
}),
|
||||
{ replace: true },
|
||||
);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) =>
|
||||
setMultipleSearchParams(prev, {
|
||||
[FILTER_KEYS.SHARED.SEARCH_TERM]: null,
|
||||
}),
|
||||
{ replace: true },
|
||||
);
|
||||
});
|
||||
}, [setSearchParams]);
|
||||
|
||||
const query = {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useSortByFilter } from '/@/renderer/features/shared/hooks/use-sort-by-f
|
||||
import { useSortOrderFilter } from '/@/renderer/features/shared/hooks/use-sort-order-filter';
|
||||
import { FILTER_KEYS } from '/@/renderer/features/shared/utils';
|
||||
import { parseJsonParam, setJsonSearchParam } from '/@/renderer/utils/query-params';
|
||||
import { runInUrlTransition } from '/@/renderer/utils/url-transition';
|
||||
import { SongListSort, SortOrder } from '/@/shared/types/domain-types';
|
||||
import { ItemListKey } from '/@/shared/types/types';
|
||||
|
||||
@@ -29,13 +30,19 @@ export const useFolderListFilters = () => {
|
||||
}, [searchParams]);
|
||||
|
||||
const setFolderPath = (path: FolderPathItem[]) => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const newParams = setJsonSearchParam(prev, FILTER_KEYS.FOLDER.FOLDER_PATH, path);
|
||||
return newParams;
|
||||
},
|
||||
{ replace: false },
|
||||
);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const newParams = setJsonSearchParam(
|
||||
prev,
|
||||
FILTER_KEYS.FOLDER.FOLDER_PATH,
|
||||
path,
|
||||
);
|
||||
return newParams;
|
||||
},
|
||||
{ replace: false },
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// Navigate to a folder (adds to path)
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useSortByFilter } from '/@/renderer/features/shared/hooks/use-sort-by-f
|
||||
import { useSortOrderFilter } from '/@/renderer/features/shared/hooks/use-sort-order-filter';
|
||||
import { FILTER_KEYS } from '/@/renderer/features/shared/utils';
|
||||
import { parseCustomFiltersParam } from '/@/renderer/utils/query-params';
|
||||
import { runInUrlTransition } from '/@/renderer/utils/url-transition';
|
||||
import { PlaylistListSort } from '/@/shared/types/domain-types';
|
||||
import { ItemListKey } from '/@/shared/types/types';
|
||||
|
||||
@@ -24,28 +25,30 @@ export const usePlaylistListFilters = () => {
|
||||
|
||||
const setCustom = useCallback(
|
||||
(value: null | Record<string, any>) => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const previousValue = prev.get(FILTER_KEYS.ALBUM._CUSTOM);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const previousValue = prev.get(FILTER_KEYS.ALBUM._CUSTOM);
|
||||
|
||||
const newCustom = {
|
||||
...(previousValue ? JSON.parse(previousValue) : {}),
|
||||
...value,
|
||||
};
|
||||
const newCustom = {
|
||||
...(previousValue ? JSON.parse(previousValue) : {}),
|
||||
...value,
|
||||
};
|
||||
|
||||
const filteredNewCustom = Object.fromEntries(
|
||||
Object.entries(newCustom).filter(
|
||||
([, value]) => value !== null && value !== undefined,
|
||||
),
|
||||
);
|
||||
const filteredNewCustom = Object.fromEntries(
|
||||
Object.entries(newCustom).filter(
|
||||
([, value]) => value !== null && value !== undefined,
|
||||
),
|
||||
);
|
||||
|
||||
prev.set(FILTER_KEYS.ALBUM._CUSTOM, JSON.stringify(filteredNewCustom));
|
||||
return prev;
|
||||
},
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
prev.set(FILTER_KEYS.ALBUM._CUSTOM, JSON.stringify(filteredNewCustom));
|
||||
return prev;
|
||||
},
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
);
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
setMultipleSearchParams,
|
||||
setSearchParam,
|
||||
} from '/@/renderer/utils/query-params';
|
||||
import { runInUrlTransition } from '/@/renderer/utils/url-transition';
|
||||
import { SongListSort, SortOrder } from '/@/shared/types/domain-types';
|
||||
import { ItemListKey } from '/@/shared/types/types';
|
||||
|
||||
@@ -74,18 +75,22 @@ export const usePlaylistSongListFilters = () => {
|
||||
|
||||
const setAlbumArtistIds = useCallback(
|
||||
(value: null | string[]) => {
|
||||
setSearchParams(
|
||||
(prev) => setSearchParam(prev, FILTER_KEYS.SONG.ALBUM_ARTIST_IDS, value),
|
||||
{ replace: true },
|
||||
);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => setSearchParam(prev, FILTER_KEYS.SONG.ALBUM_ARTIST_IDS, value),
|
||||
{ replace: true },
|
||||
);
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
);
|
||||
|
||||
const setGenreId = useCallback(
|
||||
(value: null | string[]) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.GENRE_ID, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.GENRE_ID, value), {
|
||||
replace: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -93,8 +98,13 @@ export const usePlaylistSongListFilters = () => {
|
||||
|
||||
const setArtistIds = useCallback(
|
||||
(value: null | string[]) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.ARTIST_IDS, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => setSearchParam(prev, FILTER_KEYS.SONG.ARTIST_IDS, value),
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -102,8 +112,10 @@ export const usePlaylistSongListFilters = () => {
|
||||
|
||||
const setMinYear = useCallback(
|
||||
(value: null | number) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.MIN_YEAR, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.MIN_YEAR, value), {
|
||||
replace: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -111,8 +123,10 @@ export const usePlaylistSongListFilters = () => {
|
||||
|
||||
const setMaxYear = useCallback(
|
||||
(value: null | number) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.MAX_YEAR, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.MAX_YEAR, value), {
|
||||
replace: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -120,8 +134,10 @@ export const usePlaylistSongListFilters = () => {
|
||||
|
||||
const setFavorite = useCallback(
|
||||
(value: boolean | null) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.FAVORITE, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.FAVORITE, value), {
|
||||
replace: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -129,8 +145,13 @@ export const usePlaylistSongListFilters = () => {
|
||||
|
||||
const setHasRating = useCallback(
|
||||
(value: boolean | null) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.HAS_RATING, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => setSearchParam(prev, FILTER_KEYS.SONG.HAS_RATING, value),
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -153,51 +174,55 @@ export const usePlaylistSongListFilters = () => {
|
||||
|
||||
const setCustom = useCallback(
|
||||
(value: null | Record<string, any>) => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const previousValue = prev.get(FILTER_KEYS.ALBUM._CUSTOM);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const previousValue = prev.get(FILTER_KEYS.ALBUM._CUSTOM);
|
||||
|
||||
const newCustom = {
|
||||
...(previousValue ? JSON.parse(previousValue) : {}),
|
||||
...value,
|
||||
};
|
||||
const newCustom = {
|
||||
...(previousValue ? JSON.parse(previousValue) : {}),
|
||||
...value,
|
||||
};
|
||||
|
||||
const filteredNewCustom = Object.fromEntries(
|
||||
Object.entries(newCustom).filter(
|
||||
([, value]) => value !== null && value !== undefined,
|
||||
),
|
||||
);
|
||||
const filteredNewCustom = Object.fromEntries(
|
||||
Object.entries(newCustom).filter(
|
||||
([, value]) => value !== null && value !== undefined,
|
||||
),
|
||||
);
|
||||
|
||||
prev.set(FILTER_KEYS.ALBUM._CUSTOM, JSON.stringify(filteredNewCustom));
|
||||
return prev;
|
||||
},
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
prev.set(FILTER_KEYS.ALBUM._CUSTOM, JSON.stringify(filteredNewCustom));
|
||||
return prev;
|
||||
},
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
);
|
||||
|
||||
const clear = useCallback(() => {
|
||||
setSearchParams(
|
||||
(prev) =>
|
||||
setMultipleSearchParams(
|
||||
prev,
|
||||
{
|
||||
[FILTER_KEYS.SONG._CUSTOM]: null,
|
||||
[FILTER_KEYS.SONG.ALBUM_ARTIST_IDS]: null,
|
||||
[FILTER_KEYS.SONG.ARTIST_IDS]: null,
|
||||
[FILTER_KEYS.SONG.FAVORITE]: null,
|
||||
[FILTER_KEYS.SONG.GENRE_ID]: null,
|
||||
[FILTER_KEYS.SONG.HAS_RATING]: null,
|
||||
[FILTER_KEYS.SONG.MAX_YEAR]: null,
|
||||
[FILTER_KEYS.SONG.MIN_YEAR]: null,
|
||||
},
|
||||
new Set([FILTER_KEYS.SONG._CUSTOM]),
|
||||
),
|
||||
{ replace: true },
|
||||
);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) =>
|
||||
setMultipleSearchParams(
|
||||
prev,
|
||||
{
|
||||
[FILTER_KEYS.SONG._CUSTOM]: null,
|
||||
[FILTER_KEYS.SONG.ALBUM_ARTIST_IDS]: null,
|
||||
[FILTER_KEYS.SONG.ARTIST_IDS]: null,
|
||||
[FILTER_KEYS.SONG.FAVORITE]: null,
|
||||
[FILTER_KEYS.SONG.GENRE_ID]: null,
|
||||
[FILTER_KEYS.SONG.HAS_RATING]: null,
|
||||
[FILTER_KEYS.SONG.MAX_YEAR]: null,
|
||||
[FILTER_KEYS.SONG.MIN_YEAR]: null,
|
||||
},
|
||||
new Set([FILTER_KEYS.SONG._CUSTOM]),
|
||||
),
|
||||
{ replace: true },
|
||||
);
|
||||
});
|
||||
}, [setSearchParams]);
|
||||
|
||||
const query = useMemo(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { useCallback, useDeferredValue, useRef, useState } from 'react';
|
||||
|
||||
import { Command, CommandPalettePages } from '/@/renderer/features/search/components/command';
|
||||
import { GoToCommands } from '/@/renderer/features/search/components/go-to-commands';
|
||||
@@ -49,6 +49,7 @@ function CommandPaletteSearch({
|
||||
setQuery,
|
||||
}: CommandPaletteSearchProps) {
|
||||
const [debouncedQuery] = useDebouncedValue(query, 400);
|
||||
const deferredSearchQuery = useDeferredValue(debouncedQuery ?? '');
|
||||
const searchSectionsExpanded = useAppStore(
|
||||
(state) => state.commandPaletteSearchSectionsExpanded,
|
||||
);
|
||||
@@ -83,7 +84,7 @@ function CommandPaletteSearch({
|
||||
<Command.List>
|
||||
<Stack gap="xs">
|
||||
<SearchAlbumsSection
|
||||
debouncedQuery={debouncedQuery ?? ''}
|
||||
debouncedQuery={deferredSearchQuery}
|
||||
expanded={searchSectionsExpanded[SEARCH_SECTION_IDS.albums] ?? true}
|
||||
isHome={isHome}
|
||||
onSelectResult={onSelectResult}
|
||||
@@ -96,7 +97,7 @@ function CommandPaletteSearch({
|
||||
query={query}
|
||||
/>
|
||||
<SearchAlbumArtistsSection
|
||||
debouncedQuery={debouncedQuery ?? ''}
|
||||
debouncedQuery={deferredSearchQuery}
|
||||
expanded={searchSectionsExpanded[SEARCH_SECTION_IDS.artists] ?? true}
|
||||
isHome={isHome}
|
||||
onSelectResult={onSelectResult}
|
||||
@@ -109,7 +110,7 @@ function CommandPaletteSearch({
|
||||
query={query}
|
||||
/>
|
||||
<SearchSongsSection
|
||||
debouncedQuery={debouncedQuery ?? ''}
|
||||
debouncedQuery={deferredSearchQuery}
|
||||
expanded={searchSectionsExpanded[SEARCH_SECTION_IDS.tracks] ?? true}
|
||||
isHome={isHome}
|
||||
onSelectResult={onSelectResult}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { motion } from 'motion/react';
|
||||
import { createContext, ReactNode, useContext, useMemo, useRef } from 'react';
|
||||
import { createContext, ReactNode, useContext, useMemo, useState } from 'react';
|
||||
|
||||
import styles from './list-with-sidebar-container.module.css';
|
||||
|
||||
@@ -8,7 +8,7 @@ import { animationProps } from '/@/shared/components/animations/animation-props'
|
||||
import { Portal } from '/@/shared/components/portal/portal';
|
||||
|
||||
interface ListWithSidebarContainerContextValue {
|
||||
sidebarRef: React.RefObject<HTMLDivElement | null>;
|
||||
sidebarElement: HTMLDivElement | null;
|
||||
}
|
||||
|
||||
const ListWithSidebarContainerContext = createContext<ListWithSidebarContainerContextValue | null>(
|
||||
@@ -36,12 +36,12 @@ function Sidebar({ children }: SidebarProps) {
|
||||
throw new Error('Sidebar must be used within ListWithSidebarContainer');
|
||||
}
|
||||
|
||||
if (!context.sidebarRef?.current) {
|
||||
if (!context.sidebarElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Portal target={context.sidebarRef.current}>
|
||||
<Portal target={context.sidebarElement}>
|
||||
<motion.div {...animationProps.slideInLeft} style={{ height: '100%', width: '100%' }}>
|
||||
{children}
|
||||
</motion.div>
|
||||
@@ -56,25 +56,25 @@ function SidebarPortal({ children }: SidebarPortalProps) {
|
||||
throw new Error('SidebarPortal must be used within ListWithSidebarContainer');
|
||||
}
|
||||
|
||||
if (!context.sidebarRef?.current) {
|
||||
if (!context.sidebarElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <Portal target={context.sidebarRef.current}>{children}</Portal>;
|
||||
return <Portal target={context.sidebarElement}>{children}</Portal>;
|
||||
}
|
||||
|
||||
export const ListWithSidebarContainer = ({
|
||||
children,
|
||||
useBreakpoint = false,
|
||||
}: ListWithSidebarContainerProps) => {
|
||||
const sidebarRef = useRef<HTMLDivElement>(null);
|
||||
const [sidebarElement, setSidebarElement] = useState<HTMLDivElement | null>(null);
|
||||
const { isSidebarOpen = false } = useListContext();
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
sidebarRef,
|
||||
sidebarElement,
|
||||
}),
|
||||
[],
|
||||
[sidebarElement],
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -84,7 +84,7 @@ export const ListWithSidebarContainer = ({
|
||||
data-sidebar-open={useBreakpoint ? undefined : isSidebarOpen}
|
||||
data-use-breakpoint={useBreakpoint}
|
||||
>
|
||||
<div className={styles.sidebarContainer} ref={sidebarRef} />
|
||||
<div className={styles.sidebarContainer} ref={setSidebarElement} />
|
||||
<div className={styles.contentContainer}>{children}</div>
|
||||
</div>
|
||||
</ListWithSidebarContainerContext.Provider>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useSearchParams } from 'react-router';
|
||||
|
||||
import { FILTER_KEYS } from '/@/renderer/features/shared/utils';
|
||||
import { parseStringParam, setSearchParam } from '/@/renderer/utils/query-params';
|
||||
import { runInUrlTransition } from '/@/renderer/utils/url-transition';
|
||||
import { useDebouncedCallback } from '/@/shared/hooks/use-debounced-callback';
|
||||
|
||||
export const useSearchTermFilter = (defaultValue?: string) => {
|
||||
@@ -14,17 +15,19 @@ export const useSearchTermFilter = (defaultValue?: string) => {
|
||||
}, [searchParams, defaultValue]);
|
||||
|
||||
const handleSetSearchTerm = (value: null | string) => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const newParams = setSearchParam(
|
||||
prev,
|
||||
FILTER_KEYS.SHARED.SEARCH_TERM,
|
||||
value === '' ? null : value,
|
||||
);
|
||||
return newParams;
|
||||
},
|
||||
{ replace: true },
|
||||
);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const newParams = setSearchParam(
|
||||
prev,
|
||||
FILTER_KEYS.SHARED.SEARCH_TERM,
|
||||
value === '' ? null : value,
|
||||
);
|
||||
return newParams;
|
||||
},
|
||||
{ replace: true },
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const debouncedSetSearchTerm = useDebouncedCallback(handleSetSearchTerm, 300);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useCallback, useRef } from 'react';
|
||||
|
||||
import { useCreateFavorite } from '/@/renderer/features/shared/mutations/create-favorite-mutation';
|
||||
import { useDeleteFavorite } from '/@/renderer/features/shared/mutations/delete-favorite-mutation';
|
||||
@@ -8,21 +8,26 @@ export const useSetFavorite = () => {
|
||||
const createFavoriteMutation = useCreateFavorite({});
|
||||
const deleteFavoriteMutation = useDeleteFavorite({});
|
||||
|
||||
const createFavoriteMutationRef = useRef(createFavoriteMutation);
|
||||
const deleteFavoriteMutationRef = useRef(deleteFavoriteMutation);
|
||||
createFavoriteMutationRef.current = createFavoriteMutation;
|
||||
deleteFavoriteMutationRef.current = deleteFavoriteMutation;
|
||||
|
||||
const setFavorite = useCallback(
|
||||
(serverId: string, id: string[], itemType: LibraryItem, isFavorite: boolean) => {
|
||||
if (isFavorite) {
|
||||
createFavoriteMutation.mutate({
|
||||
createFavoriteMutationRef.current.mutate({
|
||||
apiClientProps: { serverId },
|
||||
query: { id, type: itemType },
|
||||
});
|
||||
} else {
|
||||
deleteFavoriteMutation.mutate({
|
||||
deleteFavoriteMutationRef.current.mutate({
|
||||
apiClientProps: { serverId },
|
||||
query: { id, type: itemType },
|
||||
});
|
||||
}
|
||||
},
|
||||
[createFavoriteMutation, deleteFavoriteMutation],
|
||||
[],
|
||||
);
|
||||
|
||||
return setFavorite;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useCallback, useRef } from 'react';
|
||||
|
||||
import { useSetRatingMutation } from '/@/renderer/features/shared/mutations/set-rating-mutation';
|
||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
||||
@@ -6,14 +6,17 @@ import { LibraryItem } from '/@/shared/types/domain-types';
|
||||
export const useSetRating = () => {
|
||||
const setRatingMutation = useSetRatingMutation({});
|
||||
|
||||
const setRatingMutationRef = useRef(setRatingMutation);
|
||||
setRatingMutationRef.current = setRatingMutation;
|
||||
|
||||
const setRating = useCallback(
|
||||
(serverId: string, id: string[], itemType: LibraryItem, rating: number) => {
|
||||
setRatingMutation.mutate({
|
||||
setRatingMutationRef.current.mutate({
|
||||
apiClientProps: { serverId },
|
||||
query: { id, rating, type: itemType },
|
||||
});
|
||||
},
|
||||
[setRatingMutation],
|
||||
[],
|
||||
);
|
||||
|
||||
return setRating;
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useListFilterPersistence } from '/@/renderer/features/shared/hooks/use-
|
||||
import { FILTER_KEYS } from '/@/renderer/features/shared/utils';
|
||||
import { useCurrentServer } from '/@/renderer/store';
|
||||
import { parseStringParam, setSearchParam } from '/@/renderer/utils/query-params';
|
||||
import { runInUrlTransition } from '/@/renderer/utils/url-transition';
|
||||
import { ItemListKey } from '/@/shared/types/types';
|
||||
|
||||
export const useSortByFilter = <TSortBy>(defaultValue: null | string, listKey: ItemListKey) => {
|
||||
@@ -20,14 +21,16 @@ export const useSortByFilter = <TSortBy>(defaultValue: null | string, listKey: I
|
||||
}, [searchParams, persisted, defaultValue]);
|
||||
|
||||
const handleSetSortBy = (sortBy: string) => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const newParams = setSearchParam(prev, FILTER_KEYS.SHARED.SORT_BY, sortBy);
|
||||
return newParams;
|
||||
},
|
||||
{ replace: true },
|
||||
);
|
||||
setFilter(FILTER_KEYS.SHARED.SORT_BY, sortBy);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const newParams = setSearchParam(prev, FILTER_KEYS.SHARED.SORT_BY, sortBy);
|
||||
return newParams;
|
||||
},
|
||||
{ replace: true },
|
||||
);
|
||||
setFilter(FILTER_KEYS.SHARED.SORT_BY, sortBy);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useListFilterPersistence } from '/@/renderer/features/shared/hooks/use-
|
||||
import { FILTER_KEYS } from '/@/renderer/features/shared/utils';
|
||||
import { useCurrentServer } from '/@/renderer/store';
|
||||
import { parseStringParam, setSearchParam } from '/@/renderer/utils/query-params';
|
||||
import { runInUrlTransition } from '/@/renderer/utils/url-transition';
|
||||
import { SortOrder } from '/@/shared/types/domain-types';
|
||||
import { ItemListKey } from '/@/shared/types/types';
|
||||
|
||||
@@ -21,14 +22,20 @@ export const useSortOrderFilter = (defaultValue: null | string, listKey: ItemLis
|
||||
}, [searchParams, persisted, defaultValue]);
|
||||
|
||||
const handleSetSortOrder = (sortOrder: SortOrder) => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const newParams = setSearchParam(prev, FILTER_KEYS.SHARED.SORT_ORDER, sortOrder);
|
||||
return newParams;
|
||||
},
|
||||
{ replace: true },
|
||||
);
|
||||
setFilter(FILTER_KEYS.SHARED.SORT_ORDER, sortOrder);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const newParams = setSearchParam(
|
||||
prev,
|
||||
FILTER_KEYS.SHARED.SORT_ORDER,
|
||||
sortOrder,
|
||||
);
|
||||
return newParams;
|
||||
},
|
||||
{ replace: true },
|
||||
);
|
||||
setFilter(FILTER_KEYS.SHARED.SORT_ORDER, sortOrder);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
setMultipleSearchParams,
|
||||
setSearchParam,
|
||||
} from '/@/renderer/utils/query-params';
|
||||
import { runInUrlTransition } from '/@/renderer/utils/url-transition';
|
||||
import { SongListSort, SortOrder } from '/@/shared/types/domain-types';
|
||||
import { ItemListKey } from '/@/shared/types/types';
|
||||
|
||||
@@ -65,8 +66,10 @@ export const useSongListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setGenreId = useCallback(
|
||||
(value: null | string[]) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.GENRE_ID, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.GENRE_ID, value), {
|
||||
replace: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -74,8 +77,13 @@ export const useSongListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setArtistIds = useCallback(
|
||||
(value: null | string[]) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.ARTIST_IDS, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => setSearchParam(prev, FILTER_KEYS.SONG.ARTIST_IDS, value),
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -83,8 +91,10 @@ export const useSongListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setMinYear = useCallback(
|
||||
(value: null | number) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.MIN_YEAR, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.MIN_YEAR, value), {
|
||||
replace: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -92,8 +102,10 @@ export const useSongListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setMaxYear = useCallback(
|
||||
(value: null | number) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.MAX_YEAR, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.MAX_YEAR, value), {
|
||||
replace: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -101,8 +113,10 @@ export const useSongListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setFavorite = useCallback(
|
||||
(value: boolean | null) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.FAVORITE, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.FAVORITE, value), {
|
||||
replace: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -110,8 +124,13 @@ export const useSongListFilters = (listKey?: ItemListKey) => {
|
||||
|
||||
const setHasRating = useCallback(
|
||||
(value: boolean | null) => {
|
||||
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.HAS_RATING, value), {
|
||||
replace: true,
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => setSearchParam(prev, FILTER_KEYS.SONG.HAS_RATING, value),
|
||||
{
|
||||
replace: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
@@ -124,46 +143,53 @@ export const useSongListFilters = (listKey?: ItemListKey) => {
|
||||
| null
|
||||
| Record<string, any>,
|
||||
) => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const currentCustom = parseCustomFiltersParam(prev, FILTER_KEYS.SONG._CUSTOM);
|
||||
let newValue =
|
||||
typeof value === 'function' ? value(currentCustom ?? null) : value;
|
||||
// Convert empty objects to null to clear them from URL
|
||||
if (
|
||||
newValue &&
|
||||
typeof newValue === 'object' &&
|
||||
Object.keys(newValue).length === 0
|
||||
) {
|
||||
newValue = null;
|
||||
}
|
||||
return setJsonSearchParam(prev, FILTER_KEYS.SONG._CUSTOM, newValue);
|
||||
},
|
||||
{ replace: true },
|
||||
);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) => {
|
||||
const currentCustom = parseCustomFiltersParam(
|
||||
prev,
|
||||
FILTER_KEYS.SONG._CUSTOM,
|
||||
);
|
||||
let newValue =
|
||||
typeof value === 'function' ? value(currentCustom ?? null) : value;
|
||||
// Convert empty objects to null to clear them from URL
|
||||
if (
|
||||
newValue &&
|
||||
typeof newValue === 'object' &&
|
||||
Object.keys(newValue).length === 0
|
||||
) {
|
||||
newValue = null;
|
||||
}
|
||||
return setJsonSearchParam(prev, FILTER_KEYS.SONG._CUSTOM, newValue);
|
||||
},
|
||||
{ replace: true },
|
||||
);
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
);
|
||||
|
||||
const clear = useCallback(() => {
|
||||
setSearchParams(
|
||||
(prev) =>
|
||||
setMultipleSearchParams(
|
||||
prev,
|
||||
{
|
||||
[FILTER_KEYS.SHARED.SEARCH_TERM]: null,
|
||||
[FILTER_KEYS.SONG._CUSTOM]: null,
|
||||
[FILTER_KEYS.SONG.ARTIST_IDS]: null,
|
||||
[FILTER_KEYS.SONG.FAVORITE]: null,
|
||||
[FILTER_KEYS.SONG.GENRE_ID]: null,
|
||||
[FILTER_KEYS.SONG.HAS_RATING]: null,
|
||||
[FILTER_KEYS.SONG.MAX_YEAR]: null,
|
||||
[FILTER_KEYS.SONG.MIN_YEAR]: null,
|
||||
},
|
||||
new Set([FILTER_KEYS.SONG._CUSTOM]),
|
||||
),
|
||||
{ replace: true },
|
||||
);
|
||||
runInUrlTransition(() => {
|
||||
setSearchParams(
|
||||
(prev) =>
|
||||
setMultipleSearchParams(
|
||||
prev,
|
||||
{
|
||||
[FILTER_KEYS.SHARED.SEARCH_TERM]: null,
|
||||
[FILTER_KEYS.SONG._CUSTOM]: null,
|
||||
[FILTER_KEYS.SONG.ARTIST_IDS]: null,
|
||||
[FILTER_KEYS.SONG.FAVORITE]: null,
|
||||
[FILTER_KEYS.SONG.GENRE_ID]: null,
|
||||
[FILTER_KEYS.SONG.HAS_RATING]: null,
|
||||
[FILTER_KEYS.SONG.MAX_YEAR]: null,
|
||||
[FILTER_KEYS.SONG.MIN_YEAR]: null,
|
||||
},
|
||||
new Set([FILTER_KEYS.SONG._CUSTOM]),
|
||||
),
|
||||
{ replace: true },
|
||||
);
|
||||
});
|
||||
}, [setSearchParams]);
|
||||
|
||||
const query = useMemo(
|
||||
|
||||
@@ -200,7 +200,7 @@ const appRouterModals = {
|
||||
|
||||
export const AppRouter = () => {
|
||||
const router = (
|
||||
<HashRouter unstable_useTransitions={false}>
|
||||
<HashRouter unstable_useTransitions>
|
||||
<ModalsProvider modals={appRouterModals}>
|
||||
<RouterErrorBoundary>
|
||||
<Routes>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { startTransition } from 'react';
|
||||
|
||||
export function runInUrlTransition(update: () => void): void {
|
||||
startTransition(update);
|
||||
}
|
||||
Reference in New Issue
Block a user