Add query cancellation for play queue requests
- Opens a notification after 2s to allow for manual cancellation of in-progress query
This commit is contained in:
parent
652c4a1f81
commit
292737d53c
2 changed files with 65 additions and 2 deletions
|
@ -1001,3 +1001,7 @@ export type SearchResponse = {
|
|||
albums: Album[];
|
||||
songs: Song[];
|
||||
};
|
||||
|
||||
export const instanceOfCancellationError = (error: any) => {
|
||||
return 'revert' in error;
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useCallback } from 'react';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useCurrentServer, usePlayerControls, usePlayerStore } from '/@/renderer/store';
|
||||
import { usePlayerType } from '/@/renderer/store/settings.store';
|
||||
|
@ -6,7 +6,13 @@ import { PlayQueueAddOptions, Play, PlaybackType } from '/@/renderer/types';
|
|||
import { toast } from '/@/renderer/components/toast/index';
|
||||
import isElectron from 'is-electron';
|
||||
import { nanoid } from 'nanoid/non-secure';
|
||||
import { LibraryItem, QueueSong, Song, SongListResponse } from '/@/renderer/api/types';
|
||||
import {
|
||||
LibraryItem,
|
||||
QueueSong,
|
||||
Song,
|
||||
SongListResponse,
|
||||
instanceOfCancellationError,
|
||||
} from '/@/renderer/api/types';
|
||||
import {
|
||||
getPlaylistSongsById,
|
||||
getSongById,
|
||||
|
@ -14,6 +20,31 @@ import {
|
|||
getAlbumArtistSongsById,
|
||||
getSongsByQuery,
|
||||
} from '/@/renderer/features/player/utils';
|
||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||
|
||||
const getRootQueryKey = (itemType: LibraryItem, serverId: string) => {
|
||||
let queryKey;
|
||||
|
||||
switch (itemType) {
|
||||
case LibraryItem.ALBUM:
|
||||
queryKey = queryKeys.songs.list(serverId);
|
||||
break;
|
||||
case LibraryItem.ALBUM_ARTIST:
|
||||
queryKey = queryKeys.songs.list(serverId);
|
||||
break;
|
||||
case LibraryItem.PLAYLIST:
|
||||
queryKey = queryKeys.playlists.songList(serverId);
|
||||
break;
|
||||
case LibraryItem.SONG:
|
||||
queryKey = queryKeys.songs.list(serverId);
|
||||
break;
|
||||
default:
|
||||
queryKey = queryKeys.songs.list(serverId);
|
||||
break;
|
||||
}
|
||||
|
||||
return queryKey;
|
||||
};
|
||||
|
||||
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
|
||||
const utils = isElectron() ? window.electron.utils : null;
|
||||
|
@ -26,6 +57,7 @@ export const useHandlePlayQueueAdd = () => {
|
|||
const playerType = usePlayerType();
|
||||
const server = useCurrentServer();
|
||||
const { play } = usePlayerControls();
|
||||
const timeoutIds = useRef<Record<string, ReturnType<typeof setTimeout>> | null>({});
|
||||
|
||||
const handlePlayQueueAdd = useCallback(
|
||||
async (options: PlayQueueAddOptions) => {
|
||||
|
@ -38,6 +70,25 @@ export const useHandlePlayQueueAdd = () => {
|
|||
let songList: SongListResponse | undefined;
|
||||
const { type: itemType, id } = byItemType;
|
||||
|
||||
const fetchId = nanoid();
|
||||
timeoutIds.current = {
|
||||
...timeoutIds.current,
|
||||
[fetchId]: setTimeout(() => {
|
||||
toast.info({
|
||||
autoClose: false,
|
||||
id: fetchId,
|
||||
message: 'This is taking a while... close the notification to cancel the request',
|
||||
onClose: () => {
|
||||
queryClient.cancelQueries({
|
||||
exact: false,
|
||||
queryKey: getRootQueryKey(itemType, server?.id),
|
||||
});
|
||||
},
|
||||
title: 'Adding to queue',
|
||||
});
|
||||
}, 2000),
|
||||
};
|
||||
|
||||
try {
|
||||
if (itemType === LibraryItem.PLAYLIST) {
|
||||
songList = await getPlaylistSongsById({ id: id?.[0], query, queryClient, server });
|
||||
|
@ -50,7 +101,15 @@ export const useHandlePlayQueueAdd = () => {
|
|||
} else {
|
||||
songList = await getSongById({ id: id?.[0], queryClient, server });
|
||||
}
|
||||
|
||||
clearTimeout(timeoutIds.current[fetchId] as ReturnType<typeof setTimeout>);
|
||||
delete timeoutIds.current[fetchId];
|
||||
toast.hide(fetchId);
|
||||
} catch (err: any) {
|
||||
if (instanceOfCancellationError(err)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return toast.error({
|
||||
message: err.message,
|
||||
title: 'Play queue add failed',
|
||||
|
|
Reference in a new issue