mirror of
https://github.com/jeffvli/feishin.git
synced 2026-06-15 16:04:19 +02:00
fix playlist song list context menu showing remove item
This commit is contained in:
@@ -295,10 +295,15 @@ export const useDefaultItemListControls = (args?: UseDefaultItemListControlsArgs
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the item's _itemType if available, otherwise fall back to the prop itemType
|
console.log(item, itemType);
|
||||||
// This allows mixed lists (e.g., folders + songs) to show the correct context menu
|
|
||||||
|
// For context menus, prioritize the itemType prop when it's PLAYLIST_SONG or QUEUE_SONG
|
||||||
|
// This is because playlist/queue songs are Song objects (_itemType: SONG) but need special context menus
|
||||||
|
// Otherwise, use the item's _itemType if available, or fall back to the mapped itemType
|
||||||
const actualItemType =
|
const actualItemType =
|
||||||
(item as any)?._itemType || itemTypeMapping[itemType] || itemType;
|
itemType === LibraryItem.PLAYLIST_SONG || itemType === LibraryItem.QUEUE_SONG
|
||||||
|
? itemType
|
||||||
|
: (item as any)?._itemType || itemTypeMapping[itemType] || itemType;
|
||||||
|
|
||||||
// If no internalState, call ContextMenuController directly
|
// If no internalState, call ContextMenuController directly
|
||||||
if (!internalState) {
|
if (!internalState) {
|
||||||
@@ -331,11 +336,14 @@ export const useDefaultItemListControls = (args?: UseDefaultItemListControlsArgs
|
|||||||
|
|
||||||
const selectedItems = internalState.getSelected();
|
const selectedItems = internalState.getSelected();
|
||||||
|
|
||||||
// For multiple selected items, use the itemType prop (assumes all selected items are of the same type)
|
// For multiple selected items, prioritize the itemType prop for PLAYLIST_SONG/QUEUE_SONG
|
||||||
|
// Otherwise use the first item's _itemType or the mapped type
|
||||||
const selectedItemType =
|
const selectedItemType =
|
||||||
selectedItems.length > 0 && (selectedItems[0] as any)?._itemType
|
itemType === LibraryItem.PLAYLIST_SONG || itemType === LibraryItem.QUEUE_SONG
|
||||||
? (selectedItems[0] as any)._itemType
|
? itemType
|
||||||
: actualItemType;
|
: selectedItems.length > 0 && (selectedItems[0] as any)?._itemType
|
||||||
|
? (selectedItems[0] as any)._itemType
|
||||||
|
: itemTypeMapping[itemType] || itemType;
|
||||||
|
|
||||||
return ContextMenuController.call({
|
return ContextMenuController.call({
|
||||||
cmd: { items: selectedItems as any[], type: selectedItemType as any },
|
cmd: { items: selectedItems as any[], type: selectedItemType as any },
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { closeAllModals, openModal } from '@mantine/modals';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useParams } from 'react-router';
|
import { useParams } from 'react-router';
|
||||||
@@ -5,6 +6,8 @@ import { useParams } from 'react-router';
|
|||||||
import { useRemoveFromPlaylist } from '/@/renderer/features/playlists/mutations/remove-from-playlist-mutation';
|
import { useRemoveFromPlaylist } from '/@/renderer/features/playlists/mutations/remove-from-playlist-mutation';
|
||||||
import { useCurrentServerId } from '/@/renderer/store';
|
import { useCurrentServerId } from '/@/renderer/store';
|
||||||
import { ContextMenu } from '/@/shared/components/context-menu/context-menu';
|
import { ContextMenu } from '/@/shared/components/context-menu/context-menu';
|
||||||
|
import { ConfirmModal } from '/@/shared/components/modal/modal';
|
||||||
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import { toast } from '/@/shared/components/toast/toast';
|
import { toast } from '/@/shared/components/toast/toast';
|
||||||
import { Song } from '/@/shared/types/domain-types';
|
import { Song } from '/@/shared/types/domain-types';
|
||||||
|
|
||||||
@@ -19,41 +22,52 @@ export const RemoveFromPlaylistAction = ({ items }: RemoveFromPlaylistActionProp
|
|||||||
const removeFromPlaylistMutation = useRemoveFromPlaylist();
|
const removeFromPlaylistMutation = useRemoveFromPlaylist();
|
||||||
|
|
||||||
const { ids } = useMemo(() => {
|
const { ids } = useMemo(() => {
|
||||||
const ids = items.map((item) => item.id);
|
const ids = items.map((item) => item.playlistItemId).filter((id) => id !== undefined);
|
||||||
return { ids };
|
return { ids };
|
||||||
}, [items]);
|
}, [items]);
|
||||||
|
|
||||||
const handleRemoveFromPlaylist = useCallback(() => {
|
const handleRemoveFromPlaylist = useCallback(async () => {
|
||||||
if (ids.length === 0 || !serverId || !playlistId) return;
|
if (ids.length === 0 || !serverId || !playlistId) return;
|
||||||
|
|
||||||
removeFromPlaylistMutation.mutate(
|
try {
|
||||||
{
|
await removeFromPlaylistMutation.mutateAsync({
|
||||||
apiClientProps: { serverId },
|
apiClientProps: { serverId },
|
||||||
query: {
|
query: {
|
||||||
id: playlistId,
|
id: playlistId,
|
||||||
songId: ids,
|
songId: ids,
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
{
|
|
||||||
onError: (err) => {
|
toast.success({
|
||||||
toast.error({
|
message: t('action.removeFromPlaylist', { postProcess: 'sentenceCase' }),
|
||||||
message: err.message,
|
});
|
||||||
title: t('error.genericError', { postProcess: 'sentenceCase' }),
|
} catch (err: any) {
|
||||||
});
|
toast.error({
|
||||||
},
|
message: err.message,
|
||||||
onSuccess: () => {
|
title: t('error.genericError', { postProcess: 'sentenceCase' }),
|
||||||
toast.success({
|
});
|
||||||
message: t('action.removeFromPlaylist', { postProcess: 'sentenceCase' }),
|
}
|
||||||
});
|
|
||||||
},
|
closeAllModals();
|
||||||
},
|
|
||||||
);
|
|
||||||
}, [ids, playlistId, removeFromPlaylistMutation, serverId, t]);
|
}, [ids, playlistId, removeFromPlaylistMutation, serverId, t]);
|
||||||
|
|
||||||
|
const openRemoveFromPlaylistModal = useCallback(() => {
|
||||||
|
if (ids.length === 0 || !playlistId) return;
|
||||||
|
|
||||||
|
openModal({
|
||||||
|
children: (
|
||||||
|
<ConfirmModal onConfirm={handleRemoveFromPlaylist}>
|
||||||
|
<Text>{t('common.areYouSure', { postProcess: 'sentenceCase' })}</Text>
|
||||||
|
</ConfirmModal>
|
||||||
|
),
|
||||||
|
title: t('action.removeFromPlaylist', { postProcess: 'sentenceCase' }),
|
||||||
|
});
|
||||||
|
}, [handleRemoveFromPlaylist, ids, playlistId, t]);
|
||||||
|
|
||||||
if (ids.length === 0 || !playlistId) return null;
|
if (ids.length === 0 || !playlistId) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenu.Item leftIcon="remove" onSelect={handleRemoveFromPlaylist}>
|
<ContextMenu.Item leftIcon="remove" onSelect={openRemoveFromPlaylistModal}>
|
||||||
{t('action.removeFromPlaylist', { postProcess: 'sentenceCase' })}
|
{t('action.removeFromPlaylist', { postProcess: 'sentenceCase' })}
|
||||||
</ContextMenu.Item>
|
</ContextMenu.Item>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ export const PlaylistSongContextMenu = ({ items, type }: PlaylistSongContextMenu
|
|||||||
return { ids };
|
return { ids };
|
||||||
}, [items]);
|
}, [items]);
|
||||||
|
|
||||||
|
console.log('items', items, ids);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenu.Content
|
<ContextMenu.Content
|
||||||
bottomStickyContent={<ContextMenuPreview items={items} itemType={type} />}
|
bottomStickyContent={<ContextMenuPreview items={items} itemType={type} />}
|
||||||
|
|||||||
Reference in New Issue
Block a user