Add favoriting from context menu
This commit is contained in:
parent
f4f06abd72
commit
0aa0e51daa
5 changed files with 94 additions and 9 deletions
|
@ -5,8 +5,8 @@ export const SONG_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
{ id: 'playLast' },
|
{ id: 'playLast' },
|
||||||
{ divider: true, id: 'playNext' },
|
{ divider: true, id: 'playNext' },
|
||||||
{ disabled: true, id: 'addToPlaylist' },
|
{ disabled: true, id: 'addToPlaylist' },
|
||||||
{ disabled: true, id: 'addToFavorites' },
|
{ id: 'addToFavorites' },
|
||||||
{ disabled: true, id: 'removeFromFavorites' },
|
{ id: 'removeFromFavorites' },
|
||||||
{ disabled: true, id: 'setRating' },
|
{ disabled: true, id: 'setRating' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -15,8 +15,8 @@ export const ALBUM_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
{ id: 'playLast' },
|
{ id: 'playLast' },
|
||||||
{ divider: true, id: 'playNext' },
|
{ divider: true, id: 'playNext' },
|
||||||
{ disabled: true, id: 'addToPlaylist' },
|
{ disabled: true, id: 'addToPlaylist' },
|
||||||
{ disabled: true, id: 'addToFavorites' },
|
{ id: 'addToFavorites' },
|
||||||
{ disabled: true, id: 'removeFromFavorites' },
|
{ id: 'removeFromFavorites' },
|
||||||
{ disabled: true, id: 'setRating' },
|
{ disabled: true, id: 'setRating' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ export const ARTIST_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
{ id: 'playLast' },
|
{ id: 'playLast' },
|
||||||
{ divider: true, id: 'playNext' },
|
{ divider: true, id: 'playNext' },
|
||||||
{ disabled: true, id: 'addToPlaylist' },
|
{ disabled: true, id: 'addToPlaylist' },
|
||||||
{ disabled: true, id: 'addToFavorites' },
|
{ id: 'addToFavorites' },
|
||||||
{ disabled: true, id: 'removeFromFavorites' },
|
{ id: 'removeFromFavorites' },
|
||||||
{ disabled: true, id: 'setRating' },
|
{ disabled: true, id: 'setRating' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,11 @@ import { LibraryItem } from '/@/renderer/api/types';
|
||||||
import { ConfirmModal, ContextMenu, ContextMenuButton, Text, toast } from '/@/renderer/components';
|
import { ConfirmModal, ContextMenu, ContextMenuButton, Text, toast } from '/@/renderer/components';
|
||||||
import {
|
import {
|
||||||
OpenContextMenuProps,
|
OpenContextMenuProps,
|
||||||
SetContextMenuItems,
|
|
||||||
useContextMenuEvents,
|
useContextMenuEvents,
|
||||||
} from '/@/renderer/features/context-menu/events';
|
} from '/@/renderer/features/context-menu/events';
|
||||||
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
||||||
import { useDeletePlaylist } from '/@/renderer/features/playlists';
|
import { useDeletePlaylist } from '/@/renderer/features/playlists';
|
||||||
|
import { useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared';
|
||||||
import { Play } from '/@/renderer/types';
|
import { Play } from '/@/renderer/types';
|
||||||
|
|
||||||
type ContextMenuContextProps = {
|
type ContextMenuContextProps = {
|
||||||
|
@ -167,8 +167,61 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const createFavoriteMutation = useCreateFavorite();
|
||||||
|
const deleteFavoriteMutation = useDeleteFavorite();
|
||||||
|
const handleAddToFavorites = () => {
|
||||||
|
if (!ctx.dataNodes) return;
|
||||||
|
const nodesToFavorite = ctx.dataNodes.filter((item) => !item.data.userFavorite);
|
||||||
|
createFavoriteMutation.mutate(
|
||||||
|
{
|
||||||
|
query: {
|
||||||
|
id: nodesToFavorite.map((item) => item.data.id),
|
||||||
|
type: ctx.type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onError: (err) => {
|
||||||
|
toast.error({
|
||||||
|
message: err.message,
|
||||||
|
title: 'Error adding to favorites',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
for (const node of nodesToFavorite) {
|
||||||
|
node.setData({ ...node.data, userFavorite: true });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRemoveFromFavorites = () => {
|
||||||
|
if (!ctx.dataNodes) return;
|
||||||
|
const nodesToUnfavorite = ctx.dataNodes.filter((item) => item.data.userFavorite);
|
||||||
|
|
||||||
|
deleteFavoriteMutation.mutate(
|
||||||
|
{
|
||||||
|
query: {
|
||||||
|
id: nodesToUnfavorite.map((item) => item.data.id),
|
||||||
|
type: ctx.type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
for (const node of nodesToUnfavorite) {
|
||||||
|
node.setData({ ...node.data, userFavorite: false });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const contextMenuItems = {
|
const contextMenuItems = {
|
||||||
addToFavorites: { id: 'addToFavorites', label: 'Add to favorites', onClick: () => {} },
|
addToFavorites: {
|
||||||
|
id: 'addToFavorites',
|
||||||
|
label: 'Add to favorites',
|
||||||
|
onClick: handleAddToFavorites,
|
||||||
|
},
|
||||||
addToPlaylist: { id: 'addToPlaylist', label: 'Add to playlist', onClick: () => {} },
|
addToPlaylist: { id: 'addToPlaylist', label: 'Add to playlist', onClick: () => {} },
|
||||||
createPlaylist: { id: 'createPlaylist', label: 'Create playlist', onClick: () => {} },
|
createPlaylist: { id: 'createPlaylist', label: 'Create playlist', onClick: () => {} },
|
||||||
deletePlaylist: {
|
deletePlaylist: {
|
||||||
|
@ -194,7 +247,7 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
||||||
removeFromFavorites: {
|
removeFromFavorites: {
|
||||||
id: 'removeFromFavorites',
|
id: 'removeFromFavorites',
|
||||||
label: 'Remove from favorites',
|
label: 'Remove from favorites',
|
||||||
onClick: () => {},
|
onClick: handleRemoveFromFavorites,
|
||||||
},
|
},
|
||||||
setRating: { id: 'setRating', label: 'Set rating', onClick: () => {} },
|
setRating: { id: 'setRating', label: 'Set rating', onClick: () => {} },
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,3 +4,5 @@ export * from './components/play-button';
|
||||||
export * from './utils';
|
export * from './utils';
|
||||||
export * from './components/library-header';
|
export * from './components/library-header';
|
||||||
export * from './components/library-header-bar';
|
export * from './components/library-header-bar';
|
||||||
|
export * from './mutations/create-favorite-mutation';
|
||||||
|
export * from './mutations/delete-favorite-mutation';
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { useMutation } from '@tanstack/react-query';
|
||||||
|
import { HTTPError } from 'ky';
|
||||||
|
import { api } from '/@/renderer/api';
|
||||||
|
import { FavoriteArgs, RawFavoriteResponse } from '/@/renderer/api/types';
|
||||||
|
import { MutationOptions } from '/@/renderer/lib/react-query';
|
||||||
|
import { useCurrentServer } from '/@/renderer/store';
|
||||||
|
|
||||||
|
export const useCreateFavorite = (options?: MutationOptions) => {
|
||||||
|
const server = useCurrentServer();
|
||||||
|
|
||||||
|
return useMutation<RawFavoriteResponse, HTTPError, Omit<FavoriteArgs, 'server'>, null>({
|
||||||
|
mutationFn: (args) => api.controller.createFavorite({ ...args, server }),
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
};
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { useMutation } from '@tanstack/react-query';
|
||||||
|
import { HTTPError } from 'ky';
|
||||||
|
import { api } from '/@/renderer/api';
|
||||||
|
import { FavoriteArgs, RawFavoriteResponse } from '/@/renderer/api/types';
|
||||||
|
import { MutationOptions } from '/@/renderer/lib/react-query';
|
||||||
|
import { useCurrentServer } from '/@/renderer/store';
|
||||||
|
|
||||||
|
export const useDeleteFavorite = (options?: MutationOptions) => {
|
||||||
|
const server = useCurrentServer();
|
||||||
|
|
||||||
|
return useMutation<RawFavoriteResponse, HTTPError, Omit<FavoriteArgs, 'server'>, null>({
|
||||||
|
mutationFn: (args) => api.controller.deleteFavorite({ ...args, server }),
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
};
|
Reference in a new issue