upgrade and refactor for react-query v5

This commit is contained in:
jeffvli 2025-11-02 01:16:53 -07:00
parent dd70d30cd3
commit 8115963264
94 changed files with 1650 additions and 1750 deletions

View file

@ -1,5 +1,6 @@
import { useForm } from '@mantine/form';
import { closeModal, ContextModalProps } from '@mantine/modals';
import { useQuery } from '@tanstack/react-query';
import { memo, useCallback, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
@ -8,8 +9,8 @@ import styles from './add-to-playlist-context-modal.module.css';
import { api } from '/@/renderer/api';
import { queryKeys } from '/@/renderer/api/query-keys';
import { getGenreSongsById } from '/@/renderer/features/player';
import { playlistsQueries } from '/@/renderer/features/playlists/api/playlists-api';
import { useAddToPlaylist } from '/@/renderer/features/playlists/mutations/add-to-playlist-mutation';
import { usePlaylistList } from '/@/renderer/features/playlists/queries/playlist-list-query';
import { queryClient } from '/@/renderer/lib/react-query';
import { useCurrentServer } from '/@/renderer/store';
import { formatDurationString } from '/@/renderer/utils';
@ -66,19 +67,21 @@ export const AddToPlaylistContextModal = ({
const addToPlaylistMutation = useAddToPlaylist({});
const playlistList = usePlaylistList({
query: {
_custom: {
navidrome: {
smart: false,
const playlistList = useQuery(
playlistsQueries.list({
query: {
_custom: {
navidrome: {
smart: false,
},
},
sortBy: PlaylistListSort.NAME,
sortOrder: SortOrder.ASC,
startIndex: 0,
},
sortBy: PlaylistListSort.NAME,
sortOrder: SortOrder.ASC,
startIndex: 0,
},
serverId: server?.id,
});
serverId: server?.id,
}),
);
const [playlistSelect, playlistMap] = useMemo(() => {
const existingPlaylists = new Array<Playlist & { label: string; value: string }>();
@ -113,9 +116,15 @@ export const AddToPlaylistContextModal = ({
const queryKey = queryKeys.songs.list(server?.id || '', query);
const songsRes = await queryClient.fetchQuery(queryKey, ({ signal }) => {
if (!server) throw new Error('No server');
return api.controller.getSongList({ apiClientProps: { server, signal }, query });
const songsRes = await queryClient.fetchQuery({
queryFn: ({ signal }) => {
if (!server) throw new Error('No server');
return api.controller.getSongList({
apiClientProps: { server, signal },
query,
});
},
queryKey,
});
return songsRes;
@ -134,9 +143,15 @@ export const AddToPlaylistContextModal = ({
const queryKey = queryKeys.songs.list(server?.id || '', query);
const songsRes = await queryClient.fetchQuery(queryKey, ({ signal }) => {
if (!server) throw new Error('No server');
return api.controller.getSongList({ apiClientProps: { server, signal }, query });
const songsRes = await queryClient.fetchQuery({
queryFn: ({ signal }) => {
if (!server) throw new Error('No server');
return api.controller.getSongList({
apiClientProps: { server, signal },
query,
});
},
queryKey,
});
return songsRes;
@ -213,9 +228,8 @@ export const AddToPlaylistContextModal = ({
if (values.skipDuplicates) {
const queryKey = queryKeys.playlists.songList(server?.id || '', playlistId);
const playlistSongsRes = await queryClient.fetchQuery(
queryKey,
({ signal }) => {
const playlistSongsRes = await queryClient.fetchQuery({
queryFn: ({ signal }) => {
if (!server)
throw new Error(
t('error.serverNotSelectedError', {
@ -232,7 +246,8 @@ export const AddToPlaylistContextModal = ({
},
});
},
);
queryKey,
});
const playlistSongIds = playlistSongsRes?.items?.map((song) => song.id);
@ -508,7 +523,7 @@ export const AddToPlaylistContextModal = ({
/>
<Group justify="flex-end">
<ModalButton
disabled={isLoading || addToPlaylistMutation.isLoading}
disabled={isLoading || addToPlaylistMutation.isPending}
onClick={() => closeModal(id)}
uppercase
variant="subtle"
@ -518,7 +533,7 @@ export const AddToPlaylistContextModal = ({
<ModalButton
disabled={
isLoading ||
addToPlaylistMutation.isLoading ||
addToPlaylistMutation.isPending ||
(form.values.selectedPlaylistIds.length === 0 &&
form.values.newPlaylists.length === 0)
}

View file

@ -95,7 +95,7 @@ export const CreatePlaylistForm = ({ onCancel }: CreatePlaylistFormProps) => {
});
const isPublicDisplayed = hasFeature(server, ServerFeature.PUBLIC_PLAYLIST);
const isSubmitDisabled = !form.values.name || mutation.isLoading;
const isSubmitDisabled = !form.values.name || mutation.isPending;
return (
<form onSubmit={handleSubmit}>
@ -160,7 +160,7 @@ export const CreatePlaylistForm = ({ onCancel }: CreatePlaylistFormProps) => {
</ModalButton>
<ModalButton
disabled={isSubmitDisabled}
loading={mutation.isLoading}
loading={mutation.isPending}
type="submit"
variant="filled"
>

View file

@ -8,7 +8,7 @@ import type {
} from '@ag-grid-community/core';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { useQueryClient } from '@tanstack/react-query';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import debounce from 'lodash/debounce';
import { AnimatePresence } from 'motion/react';
import { MutableRefObject, useCallback, useMemo } from 'react';
@ -25,7 +25,7 @@ import {
SMART_PLAYLIST_SONG_CONTEXT_MENU_ITEMS,
} from '/@/renderer/features/context-menu/context-menu-items';
import { usePlayQueueAdd } from '/@/renderer/features/player';
import { usePlaylistDetail } from '/@/renderer/features/playlists/queries/playlist-detail-query';
import { playlistsQueries } from '/@/renderer/features/playlists/api/playlists-api';
import { useAppFocus } from '/@/renderer/hooks';
import {
useCurrentServer,
@ -70,7 +70,9 @@ export const PlaylistDetailSongListContent = ({ songs, tableRef }: PlaylistDetai
};
}, [page?.table.id, playlistId]);
const detailQuery = usePlaylistDetail({ query: { id: playlistId }, serverId: server?.id });
const detailQuery = useQuery(
playlistsQueries.detail({ query: { id: playlistId }, serverId: server?.id }),
);
const p = usePlaylistDetailTablePagination(playlistId);
const pagination = {

View file

@ -1,7 +1,7 @@
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { closeAllModals, openModal } from '@mantine/modals';
import { useQueryClient } from '@tanstack/react-query';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import debounce from 'lodash/debounce';
import { ChangeEvent, MouseEvent, MutableRefObject, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
@ -10,9 +10,9 @@ import { useNavigate, useParams } from 'react-router';
import i18n from '/@/i18n/i18n';
import { queryKeys } from '/@/renderer/api/query-keys';
import { SONG_TABLE_COLUMNS } from '/@/renderer/components/virtual-table';
import { playlistsQueries } from '/@/renderer/features/playlists/api/playlists-api';
import { openUpdatePlaylistModal } from '/@/renderer/features/playlists/components/update-playlist-form';
import { useDeletePlaylist } from '/@/renderer/features/playlists/mutations/delete-playlist-mutation';
import { usePlaylistDetail } from '/@/renderer/features/playlists/queries/playlist-detail-query';
import { OrderToggleButton } from '/@/renderer/features/shared';
import { ListConfigMenu } from '/@/renderer/features/shared/components/list-config-menu';
import { MoreButton } from '/@/renderer/features/shared/components/more-button';
@ -262,7 +262,9 @@ export const PlaylistDetailSongListHeaderFilters = ({
const sortBy = page?.table.id[playlistId]?.filter?.sortBy || SongListSort.ID;
const sortOrder = page?.table.id[playlistId]?.filter?.sortOrder || SortOrder.ASC;
const detailQuery = usePlaylistDetail({ query: { id: playlistId }, serverId: server?.id });
const detailQuery = useQuery(
playlistsQueries.detail({ query: { id: playlistId }, serverId: server?.id }),
);
const isSmartPlaylist = detailQuery.data?.rules;
const cq = useContainerQuery();
@ -291,7 +293,9 @@ export const PlaylistDetailSongListHeaderFilters = ({
}, [tableRef, page.display, setPagination]);
const handleRefresh = () => {
queryClient.invalidateQueries(queryKeys.playlists.songList(server?.id || '', playlistId));
queryClient.invalidateQueries({
queryKey: queryKeys.playlists.songList(server?.id || '', playlistId),
});
handleFilterChange();
};

View file

@ -1,19 +1,27 @@
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { useQuery } from '@tanstack/react-query';
import { MutableRefObject } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router';
import { PageHeader } from '/@/renderer/components/page-header/page-header';
import { usePlayQueueAdd } from '/@/renderer/features/player';
import { playlistsQueries } from '/@/renderer/features/playlists/api/playlists-api';
import { PlaylistDetailSongListHeaderFilters } from '/@/renderer/features/playlists/components/playlist-detail-song-list-header-filters';
import { usePlaylistDetail } from '/@/renderer/features/playlists/queries/playlist-detail-query';
import { FilterBar, LibraryHeaderBar } from '/@/renderer/features/shared';
import { useCurrentServer } from '/@/renderer/store';
import { useCurrentServer, usePlaylistDetailStore } from '/@/renderer/store';
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
import { formatDurationString } from '/@/renderer/utils';
import { Badge } from '/@/shared/components/badge/badge';
import { SpinnerIcon } from '/@/shared/components/spinner/spinner';
import { Stack } from '/@/shared/components/stack/stack';
import {
LibraryItem,
PlaylistSongListQueryClientSide,
SongListSort,
SortOrder,
} from '/@/shared/types/domain-types';
import { Play } from '/@/shared/types/types';
interface PlaylistDetailHeaderProps {
@ -33,7 +41,23 @@ export const PlaylistDetailSongListHeader = ({
const { t } = useTranslation();
const { playlistId } = useParams() as { playlistId: string };
const server = useCurrentServer();
const detailQuery = usePlaylistDetail({ query: { id: playlistId }, serverId: server?.id });
const detailQuery = useQuery(
playlistsQueries.detail({ query: { id: playlistId }, serverId: server?.id }),
);
const handlePlayQueueAdd = usePlayQueueAdd();
const page = usePlaylistDetailStore();
const filters: Partial<PlaylistSongListQueryClientSide> = {
sortBy: page?.table.id[playlistId]?.filter?.sortBy || SongListSort.ID,
sortOrder: page?.table.id[playlistId]?.filter?.sortOrder || SortOrder.ASC,
};
const handlePlay = async (playType: Play) => {
handlePlayQueueAdd?.({
byItemType: { id: [playlistId], type: LibraryItem.PLAYLIST },
playType,
query: filters,
});
};
const playButtonBehavior = usePlayButtonBehavior();

View file

@ -121,15 +121,17 @@ export const PlaylistListGridView = ({ gridRef, itemCount }: PlaylistListGridVie
const queryKey = queryKeys.playlists.list(server?.id || '', query);
const playlists = await queryClient.fetchQuery(queryKey, async ({ signal }) =>
controller.getPlaylistList({
apiClientProps: {
server,
signal,
},
query,
}),
);
const playlists = await queryClient.fetchQuery({
queryFn: async ({ signal }) =>
controller.getPlaylistList({
apiClientProps: {
server,
signal,
},
query,
}),
queryKey,
});
return playlists;
},

View file

@ -170,15 +170,17 @@ export const PlaylistListHeaderFilters = ({
const queryKey = queryKeys.playlists.list(server?.id || '', query);
const playlists = await queryClient.fetchQuery(queryKey, async ({ signal }) =>
api.controller.getPlaylistList({
apiClientProps: {
server,
signal,
},
query,
}),
);
const playlists = await queryClient.fetchQuery({
queryFn: async ({ signal }) =>
api.controller.getPlaylistList({
apiClientProps: {
server,
signal,
},
query,
}),
queryKey,
});
return playlists;
},
@ -207,9 +209,8 @@ export const PlaylistListHeaderFilters = ({
...pageFilters,
});
const playlistsRes = await queryClient.fetchQuery(
queryKey,
async ({ signal }) =>
const playlistsRes = await queryClient.fetchQuery({
queryFn: async ({ signal }) =>
api.controller.getPlaylistList({
apiClientProps: {
server,
@ -221,7 +222,8 @@ export const PlaylistListHeaderFilters = ({
...pageFilters,
},
}),
);
queryKey,
});
params.successCallback(
playlistsRes?.items || [],
@ -338,7 +340,9 @@ export const PlaylistListHeaderFilters = ({
};
const handleRefresh = () => {
queryClient.invalidateQueries(queryKeys.playlists.list(server?.id || '', filter));
queryClient.invalidateQueries({
queryKey: queryKeys.playlists.list(server?.id || '', filter),
});
handleFilterChange(filter);
};

View file

@ -1,5 +1,6 @@
import { useForm } from '@mantine/form';
import { openModal } from '@mantine/modals';
import { useQuery } from '@tanstack/react-query';
import clone from 'lodash/clone';
import get from 'lodash/get';
import setWith from 'lodash/setWith';
@ -8,7 +9,7 @@ import { forwardRef, Ref, useImperativeHandle, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { QueryBuilder } from '/@/renderer/components/query-builder';
import { usePlaylistList } from '/@/renderer/features/playlists/queries/playlist-list-query';
import { playlistsQueries } from '/@/renderer/features/playlists/api/playlists-api';
import {
convertNDQueryToQueryGroup,
convertQueryGroupToNDQuery,
@ -108,10 +109,12 @@ export const PlaylistQueryBuilder = forwardRef(
query ? convertNDQueryToQueryGroup(query) : DEFAULT_QUERY,
);
const { data: playlists } = usePlaylistList({
query: { sortBy: PlaylistListSort.NAME, sortOrder: SortOrder.ASC, startIndex: 0 },
serverId: server?.id,
});
const { data: playlists } = useQuery(
playlistsQueries.list({
query: { sortBy: PlaylistListSort.NAME, sortOrder: SortOrder.ASC, startIndex: 0 },
serverId: server?.id,
}),
);
const playlistData = useMemo(() => {
if (!playlists) return [];

View file

@ -70,7 +70,7 @@ export const SaveAsPlaylistForm = ({
});
const isPublicDisplayed = hasFeature(server, ServerFeature.PUBLIC_PLAYLIST);
const isSubmitDisabled = !form.values.name || mutation.isLoading;
const isSubmitDisabled = !form.values.name || mutation.isPending;
return (
<form onSubmit={handleSubmit}>
@ -106,7 +106,7 @@ export const SaveAsPlaylistForm = ({
<ModalButton onClick={onCancel}>{t('common.cancel')}</ModalButton>
<ModalButton
disabled={isSubmitDisabled}
loading={mutation.isLoading}
loading={mutation.isPending}
type="submit"
variant="filled"
>

View file

@ -88,7 +88,7 @@ export const UpdatePlaylistForm = ({ body, onCancel, query, users }: UpdatePlayl
const isPublicDisplayed = hasFeature(server, ServerFeature.PUBLIC_PLAYLIST);
const isOwnerDisplayed = server?.type === ServerType.NAVIDROME && userList;
const isSubmitDisabled = !form.values.name || mutation.isLoading;
const isSubmitDisabled = !form.values.name || mutation.isPending;
return (
<form onSubmit={handleSubmit}>
@ -143,7 +143,7 @@ export const UpdatePlaylistForm = ({ body, onCancel, query, users }: UpdatePlayl
<ModalButton onClick={onCancel}>{t('common.cancel')}</ModalButton>
<ModalButton
disabled={isSubmitDisabled}
loading={mutation.isLoading}
loading={mutation.isPending}
type="submit"
variant="filled"
>