Browse Source

Add actions to add and remove context menu buttons

master
jeffvli 3 years ago
parent
commit
2e78f5f136
  1. 87
      src/components/shared/ContextMenu.tsx
  2. 59
      src/redux/playQueueSlice.ts

87
src/components/shared/ContextMenu.tsx

@ -1,5 +1,6 @@
/* eslint-disable no-await-in-loop */
import React, { useRef, useState } from 'react';
import _ from 'lodash';
import { useQuery, useQueryClient } from 'react-query';
import { useHistory } from 'react-router';
import { Popover, Whisper } from 'rsuite';
@ -10,7 +11,12 @@ import {
removeProcessingPlaylist,
setContextMenu,
} from '../../redux/miscSlice';
import { setStar } from '../../redux/playQueueSlice';
import {
appendPlayQueue,
fixPlayer2Index,
removeFromPlayQueue,
setStar,
} from '../../redux/playQueueSlice';
import {
ContextMenuDivider,
ContextMenuWindow,
@ -20,11 +26,13 @@ import {
} from './styled';
import { notifyToast } from './toast';
import { sleep } from '../../shared/utils';
import { setStatus } from '../../redux/playerSlice';
export const ContextMenuButton = ({ children, ...rest }: any) => {
export const ContextMenuButton = ({ text, children, ...rest }: any) => {
return (
<StyledContextMenuButton {...rest} appearance="subtle" size="sm" block>
{children}
{text}
</StyledContextMenuButton>
);
};
@ -56,6 +64,7 @@ export const GlobalContextMenu = () => {
const history = useHistory();
const dispatch = useAppDispatch();
const queryClient = useQueryClient();
const playQueue = useAppSelector((state) => state.playQueue);
const misc = useAppSelector((state) => state.misc);
const multiSelect = useAppSelector((state) => state.multiSelect);
const playlistTriggerRef = useRef<any>();
@ -65,6 +74,40 @@ export const GlobalContextMenu = () => {
getPlaylists('name')
);
const handleAddToQueue = () => {
const entriesByRowIndexAsc = _.orderBy(
multiSelect.selected,
'rowIndex',
'asc'
);
notifyToast(
'info',
`Added ${multiSelect.selected.length} song(s) to the queue`
);
dispatch(appendPlayQueue({ entries: entriesByRowIndexAsc }));
dispatch(setContextMenu({ show: false }));
};
const handleRemoveFromQueue = async () => {
dispatch(removeFromPlayQueue({ entries: multiSelect.selected }));
if (playQueue.currentPlayer === 1) {
dispatch(fixPlayer2Index());
}
dispatch(setContextMenu({ show: false }));
// If the currently playing song is removed, then the player will autostart because
// the player src changed. If that happens, automatically set the playing status
if (
_.map(multiSelect.selected, 'uniqueId').includes(
playQueue.current.uniqueId
)
) {
setTimeout(() => dispatch(setStatus('PLAYING')), 50);
}
};
const handleAddToPlaylist = async () => {
// If the window is closed, the selectedPlaylistId will be deleted
const localSelectedPlaylistId = selectedPlaylistId;
@ -173,12 +216,15 @@ export const GlobalContextMenu = () => {
numOfButtons={7}
numOfDividers={3}
>
<ContextMenuButton>
Selected: {multiSelect.selected.length}
</ContextMenuButton>
<ContextMenuButton
text={`Selected: ${multiSelect.selected.length}`}
/>
<ContextMenuDivider />
<ContextMenuButton>Add to queue</ContextMenuButton>
<ContextMenuButton>Remove from current</ContextMenuButton>
<ContextMenuButton text="Add to queue" onClick={handleAddToQueue} />
<ContextMenuButton
text="Remove from current"
onClick={handleRemoveFromQueue}
/>
<ContextMenuDivider />
<Whisper
@ -213,26 +259,27 @@ export const GlobalContextMenu = () => {
}
>
<ContextMenuButton
text="Add to playlist"
onClick={() =>
playlistTriggerRef.current.state.isOverlayShown
? playlistTriggerRef.current.close()
: playlistTriggerRef.current.open()
}
>
Add to playlist
</ContextMenuButton>
/>
</Whisper>
<ContextMenuDivider />
<ContextMenuButton onClick={() => handleFavorite(false)}>
Add to favorites
</ContextMenuButton>
<ContextMenuButton onClick={() => handleFavorite(true)}>
Add to favorites (ordered)
</ContextMenuButton>
<ContextMenuButton onClick={handleUnfavorite}>
Remove from favorites
</ContextMenuButton>
<ContextMenuButton
text="Add to favorites"
onClick={() => handleFavorite(false)}
/>
<ContextMenuButton
text="Add to favorites (ordered)"
onClick={() => handleFavorite(true)}
/>
<ContextMenuButton
text="Remove from favorites"
onClick={handleUnfavorite}
/>
</ContextMenu>
</>
)}

59
src/redux/playQueueSlice.ts

@ -774,13 +774,67 @@ const playQueueSlice = createSlice({
},
appendPlayQueue: (state, action: PayloadAction<{ entries: Entry[] }>) => {
action.payload.entries.map((entry: any) => state.entry.push(entry));
// We'll need to update the uniqueId otherwise selecting a song with duplicates
// will select them all at once
const refreshedEntries = action.payload.entries.map((entry: any) => {
return {
...entry,
uniqueId: nanoid(),
};
});
refreshedEntries.map((entry: any) => state.entry.push(entry));
if (state.shuffle) {
const shuffledEntries = _.shuffle(action.payload.entries);
const shuffledEntries = _.shuffle(refreshedEntries);
shuffledEntries.map((entry: any) => state.shuffledEntry.push(entry));
}
},
removeFromPlayQueue: (
state,
action: PayloadAction<{ entries: Entry[] }>
) => {
const uniqueIds = _.map(action.payload.entries, 'uniqueId');
state.entry = state.entry.filter(
(entry) => !uniqueIds.includes(entry.uniqueId)
);
state.shuffledEntry = (state.shuffledEntry || []).filter(
(entry) => !uniqueIds.includes(entry.uniqueId)
);
state.sortedEntry = (state.sortedEntry || []).filter(
(entry) => !uniqueIds.includes(entry.uniqueId)
);
// If the current song is removed, then reset to the first entry
if (uniqueIds.includes(state.currentSongUniqueId)) {
if (state.sortColumn) {
state.current = { ...state.sortedEntry[0] };
state.currentSongId = state.sortedEntry[0].id;
state.currentSongUniqueId = state.sortedEntry[0].uniqueId;
} else if (state.shuffle) {
state.current = { ...state.shuffledEntry[0] };
state.currentSongId = state.shuffledEntry[0].id;
state.currentSongUniqueId = state.shuffledEntry[0].uniqueId;
} else {
state.current = { ...state.entry[0] };
state.currentSongId = state.entry[0].id;
state.currentSongUniqueId = state.entry[0].uniqueId;
}
if (state.currentPlayer === 1) {
state.player1.index = 0;
} else {
state.player2.index = 0;
}
state.currentIndex = 0;
}
},
clearPlayQueue: (state) => {
state.entry = [];
state.shuffledEntry = [];
@ -1006,6 +1060,7 @@ export const {
setPlayQueue,
setPlayQueueByRowClick,
appendPlayQueue,
removeFromPlayQueue,
clearPlayQueue,
setIsLoading,
setIsLoaded,

Loading…
Cancel
Save