Browse Source

Refactor drag end to hook

master
jeffvli 3 years ago
committed by Jeff
parent
commit
97457de061
  1. 22
      src/components/player/NowPlayingMiniView.tsx
  2. 22
      src/components/player/NowPlayingView.tsx
  3. 18
      src/components/playlist/PlaylistView.tsx
  4. 22
      src/components/shared/ContextMenu.tsx
  5. 6
      src/components/viewtypes/ListViewTable.tsx
  6. 45
      src/hooks/useListClickHandler.ts
  7. 69
      src/redux/playQueueSlice.ts
  8. 12
      src/redux/playlistSlice.ts

22
src/components/player/NowPlayingMiniView.tsx

@ -6,13 +6,12 @@ import { useHotkeys } from 'react-hotkeys-hook';
import { useQuery } from 'react-query';
import { useTranslation } from 'react-i18next';
import { useAppDispatch, useAppSelector } from '../../redux/hooks';
import { clearSelected, setIsDragging } from '../../redux/multiSelectSlice';
import { clearSelected } from '../../redux/multiSelectSlice';
import {
fixPlayer2Index,
clearPlayQueue,
shuffleInPlace,
toggleShuffle,
moveToIndex,
setPlaybackSetting,
removeFromPlayQueue,
setStar,
@ -129,22 +128,9 @@ const NowPlayingMiniView = () => {
}
}, [playQueue.currentIndex, tableRef, playQueue.displayQueue, playQueue.scrollWithCurrentSong]);
const { handleRowClick, handleRowDoubleClick } = useListClickHandler();
const handleDragEnd = () => {
if (multiSelect.isDragging) {
dispatch(
moveToIndex({
entries: multiSelect.selected,
moveBeforeId: multiSelect.currentMouseOverId,
})
);
dispatch(setIsDragging(false));
if (playQueue.currentPlayer === 1) {
dispatch(fixPlayer2Index());
}
}
};
const { handleRowClick, handleRowDoubleClick, handleDragEnd } = useListClickHandler({
dnd: 'playQueue',
});
const handlePlayRandom = async (action: 'play' | 'addNext' | 'addLater') => {
setIsLoadingRandom(true);

22
src/components/player/NowPlayingView.tsx

@ -12,7 +12,6 @@ import {
clearPlayQueue,
shuffleInPlace,
toggleShuffle,
moveToIndex,
setPlaybackSetting,
removeFromPlayQueue,
setPlayQueue,
@ -22,7 +21,7 @@ import {
moveToTop,
moveToBottom,
} from '../../redux/playQueueSlice';
import { clearSelected, setIsDragging } from '../../redux/multiSelectSlice';
import { clearSelected } from '../../redux/multiSelectSlice';
import GenericPage from '../layout/GenericPage';
import GenericPageHeader from '../layout/GenericPageHeader';
import ListViewType from '../viewtypes/ListViewType';
@ -143,22 +142,9 @@ const NowPlayingView = () => {
}
}, [playQueue.currentIndex, playQueue.scrollWithCurrentSong, tableRef]);
const { handleRowClick, handleRowDoubleClick } = useListClickHandler();
const handleDragEnd = () => {
if (multiSelect.isDragging) {
dispatch(
moveToIndex({
entries: multiSelect.selected,
moveBeforeId: multiSelect.currentMouseOverId,
})
);
dispatch(setIsDragging(false));
if (playQueue.currentPlayer === 1) {
dispatch(fixPlayer2Index());
}
}
};
const { handleRowClick, handleRowDoubleClick, handleDragEnd } = useListClickHandler({
dnd: 'playQueue',
});
const handlePlayRandom = async (action: 'play' | 'addNext' | 'addLater') => {
setIsLoadingRandom(true);

18
src/components/playlist/PlaylistView.tsx

@ -27,7 +27,7 @@ import {
setRate,
clearPlayQueue,
} from '../../redux/playQueueSlice';
import { clearSelected, setIsDragging } from '../../redux/multiSelectSlice';
import { clearSelected } from '../../redux/multiSelectSlice';
import {
createRecoveryFile,
errorMessages,
@ -57,7 +57,6 @@ import {
StyledPopover,
} from '../shared/styled';
import {
moveToIndex,
removeFromPlaylist,
setPlaylistData,
setPlaylistRate,
@ -148,7 +147,7 @@ const PlaylistView = ({ ...rest }) => {
}
}, [data?.song, playlist]);
const { handleRowClick, handleRowDoubleClick } = useListClickHandler({
const { handleRowClick, handleRowDoubleClick, handleDragEnd } = useListClickHandler({
doubleClick: (rowData: any) => {
dispatch(
setPlayQueueByRowClick({
@ -162,6 +161,7 @@ const PlaylistView = ({ ...rest }) => {
dispatch(setStatus('PLAYING'));
dispatch(fixPlayer2Index());
},
dnd: 'playlist',
});
const handlePlay = () => {
@ -392,18 +392,6 @@ const PlaylistView = ({ ...rest }) => {
}
};
const handleDragEnd = () => {
if (multiSelect.isDragging) {
dispatch(
moveToIndex({
selectedEntries: multiSelect.selected,
moveBeforeId: multiSelect.currentMouseOverId,
})
);
dispatch(setIsDragging(false));
}
};
const handleRowFavorite = async (rowData: any) => {
if (!rowData.starred) {
await apiController({

22
src/components/shared/ContextMenu.tsx

@ -56,6 +56,7 @@ import {
getCurrentEntryList,
getPlayedSongsNotification,
isFailedResponse,
moveSelectedToIndex,
} from '../../shared/utils';
import { setStatus } from '../../redux/playerSlice';
import { apiController } from '../../api/controller';
@ -644,20 +645,27 @@ export const GlobalContextMenu = () => {
if (Number(indexToMoveTo) === playQueue[currentEntryList].length) {
dispatch(moveToBottom({ selectedEntries: multiSelect.selected }));
} else {
const uniqueIdOfIndexToMoveTo = playQueue[currentEntryList][indexToMoveTo].uniqueId;
dispatch(
moveToIndex({ entries: multiSelect.selected, moveBeforeId: uniqueIdOfIndexToMoveTo })
moveToIndex(
moveSelectedToIndex(
playQueue[currentEntryList],
multiSelect.selected,
playQueue[currentEntryList][indexToMoveTo].uniqueId
)
)
);
}
} else if (Number(indexToMoveTo) === playlist.entry.length) {
dispatch(plMoveToBottom({ selectedEntries: multiSelect.selected }));
} else {
const uniqueIdOfIndexToMoveTo = playlist.entry[indexToMoveTo].uniqueId;
dispatch(
plMoveToIndex({
selectedEntries: multiSelect.selected,
moveBeforeId: uniqueIdOfIndexToMoveTo,
})
plMoveToIndex(
moveSelectedToIndex(
playlist.entry,
multiSelect.selected,
playlist.entry[indexToMoveTo].uniqueId
)
)
);
}
};

6
src/components/viewtypes/ListViewTable.tsx

@ -602,7 +602,11 @@ const ListViewTable = ({
}}
onMouseUp={() => {
if (dnd) {
handleDragEnd();
handleDragEnd(sortColumn && !nowPlaying ? sortedData : data);
if (nowPlaying && playQueue.currentPlayer === 1) {
dispatch(fixPlayer2Index());
}
} else {
handleSelectMouseUp();
}

45
src/hooks/useListClickHandler.ts

@ -1,10 +1,21 @@
import { useAppDispatch, useAppSelector } from '../redux/hooks';
import { clearSelected, setSelected, toggleSelected } from '../redux/multiSelectSlice';
import {
clearSelected,
setIsDragging,
setSelected,
toggleSelected,
} from '../redux/multiSelectSlice';
import { setStatus } from '../redux/playerSlice';
import { fixPlayer2Index, setPlayerIndex } from '../redux/playQueueSlice';
import { sliceRangeByUniqueId } from '../shared/utils';
import { fixPlayer2Index, moveToIndex, setPlayerIndex } from '../redux/playQueueSlice';
import { moveToIndex as moveToIndexPlaylist } from '../redux/playlistSlice';
import { moveToIndex as moveToIndexConfig } from '../redux/configSlice';
import { moveSelectedToIndex, sliceRangeByUniqueId } from '../shared/utils';
const useListClickHandler = (options?: { singleClick?: any; doubleClick?: any }) => {
const useListClickHandler = (options?: {
singleClick?: any;
doubleClick?: any;
dnd?: 'playQueue' | 'playlist' | 'config';
}) => {
const dispatch = useAppDispatch();
const multiSelect = useAppSelector((state) => state.multiSelect);
@ -46,7 +57,31 @@ const useListClickHandler = (options?: { singleClick?: any; doubleClick?: any })
}
};
return { handleRowClick, handleRowDoubleClick };
const handleDragEnd = (entries: any) => {
if (multiSelect.isDragging) {
const reorderedQueue = moveSelectedToIndex(
entries,
multiSelect.selected,
multiSelect.currentMouseOverId
);
if (options?.dnd === 'playQueue') {
dispatch(moveToIndex(reorderedQueue));
}
if (options?.dnd === 'playlist') {
dispatch(moveToIndexPlaylist(reorderedQueue));
}
if (options?.dnd === 'config') {
dispatch(moveToIndexConfig(reorderedQueue));
}
dispatch(setIsDragging(false));
}
};
return { handleRowClick, handleRowDoubleClick, handleDragEnd };
};
export default useListClickHandler;

69
src/redux/playQueueSlice.ts

@ -907,73 +907,18 @@ const playQueueSlice = createSlice({
state.isFading = action.payload;
},
moveToIndex: (state, action: PayloadAction<{ entries: Entry[]; moveBeforeId: string }>) => {
moveToIndex: (state, action: PayloadAction<Entry[]>) => {
const currentEntry = entrySelect(state);
const tempQueue = state[currentEntry].slice();
const uniqueIds = _.map(action.payload.entries, 'uniqueId');
// Remove the selected entries from the queue
const newQueue = tempQueue.filter((entry: Entry) => {
return !uniqueIds.includes(entry.uniqueId);
});
/* Used if dragging onto the first selected row. We'll need to calculate the number of selected rows above the first selected row
so we can subtract it from the spliceIndexPre value when moving it into the newQueue, which has all selected entries removed */
const spliceIndexPre = getCurrentEntryIndexByUID(tempQueue, action.payload.moveBeforeId);
const queueAbovePre = tempQueue.slice(0, spliceIndexPre);
const selectedAbovePre = queueAbovePre.filter((entry: Entry) => {
return uniqueIds.includes(entry.uniqueId);
});
// Used if dragging onto a non-selected row
const spliceIndexPost = getCurrentEntryIndexByUID(newQueue, action.payload.moveBeforeId);
/* Used if dragging onto consecutive selected rows
If the moveBeforeId index is selected, then we find the first consecutive selected index to move to */
let firstConsecutiveSelectedDragIndex = -1;
for (let i = spliceIndexPre - 1; i > 0; i -= 1) {
if (uniqueIds.includes(tempQueue[i].uniqueId)) {
firstConsecutiveSelectedDragIndex = i;
} else {
break;
}
}
/* If we get a negative index, don't move the entry.
This can happen if you try to drag and drop too fast */
if (spliceIndexPre < 0 && spliceIndexPre < 0) {
return;
}
// Find the slice index to add the selected entries to
const spliceIndex =
spliceIndexPost >= 0
? spliceIndexPost
: firstConsecutiveSelectedDragIndex >= 0
? firstConsecutiveSelectedDragIndex
: spliceIndexPre - selectedAbovePre.length;
// Get the updated entry rowIndexes since dragging an entry multiple times will change the existing selected rowIndex
const updatedEntries = action.payload.entries.map((entry: Entry) => {
const findIndex = state[currentEntry].findIndex(
(item: Entry) => item.uniqueId === entry.uniqueId
);
return { ...entry, rowIndex: findIndex };
});
// Sort the entries by their rowIndex so that we can re-add them in the proper order
const sortedEntries = updatedEntries.sort((a, b) => a.rowIndex - b.rowIndex);
// Splice the entries into the new queue array
newQueue.splice(spliceIndex, 0, ...sortedEntries);
// Finally, set the modified entries into the redux state
state[currentEntry] = newQueue;
// Set the modified entries into the redux state
state[currentEntry] = action.payload;
// We'll need to fix the current player index after swapping the queue order
// This will be used in conjunction with fixPlayer2Index
const newCurrentSongIndex = getCurrentEntryIndexByUID(newQueue, state.currentSongUniqueId);
const newCurrentSongIndex = getCurrentEntryIndexByUID(
action.payload,
state.currentSongUniqueId
);
if (state.currentPlayer === 1) {
state.player1.index = newCurrentSongIndex;

12
src/redux/playlistSlice.ts

@ -3,7 +3,6 @@ import _ from 'lodash';
import {
moveSelectedDown,
moveSelectedToBottom,
moveSelectedToIndex,
moveSelectedToTop,
moveSelectedUp,
} from '../shared/utils';
@ -85,15 +84,8 @@ const playlistSlice = createSlice({
state.entry = state.entry.filter((entry) => !uniqueIds.includes(entry.uniqueId));
},
moveToIndex: (
state,
action: PayloadAction<{ selectedEntries: Entry[]; moveBeforeId: string }>
) => {
state.entry = moveSelectedToIndex(
state.entry,
action.payload.selectedEntries,
action.payload.moveBeforeId
);
moveToIndex: (state, action: PayloadAction<Entry[]>) => {
state.entry = action.payload;
},
moveUp: (state, action: PayloadAction<{ selectedEntries: Entry[] }>) => {

Loading…
Cancel
Save