From a4c9feeb7c26682ddc624cf803980089a1abb17a Mon Sep 17 00:00:00 2001 From: jeffvli Date: Thu, 23 Sep 2021 02:05:22 -0700 Subject: [PATCH] Improve multiselect dragging - Use range selection instead of appending individual entries --- src/components/layout/Layout.tsx | 8 ++ src/components/library/AlbumList.tsx | 11 +- src/components/library/AlbumView.tsx | 8 +- src/components/library/ArtistView.tsx | 8 +- src/components/player/NowPlayingMiniView.tsx | 3 - src/components/player/NowPlayingView.tsx | 3 - src/components/playlist/PlaylistView.tsx | 3 - src/components/starred/StarredView.tsx | 16 +-- src/components/viewtypes/ListViewTable.tsx | 102 +++++++++++-------- 9 files changed, 81 insertions(+), 81 deletions(-) diff --git a/src/components/layout/Layout.tsx b/src/components/layout/Layout.tsx index 1decccb..385af51 100644 --- a/src/components/layout/Layout.tsx +++ b/src/components/layout/Layout.tsx @@ -6,11 +6,13 @@ import Titlebar from './Titlebar'; import { RootContainer, RootFooter, MainContainer } from './styled'; import { setContextMenu, setExpandSidebar } from '../../redux/miscSlice'; import { useAppDispatch, useAppSelector } from '../../redux/hooks'; +import { clearSelected } from '../../redux/multiSelectSlice'; const Layout = ({ footer, children, disableSidebar, font }: any) => { const history = useHistory(); const dispatch = useAppDispatch(); const misc = useAppSelector((state) => state.misc); + const multiSelect = useAppSelector((state) => state.multiSelect); const handleToggle = () => { dispatch(setExpandSidebar(!misc.expandSidebar)); @@ -72,6 +74,12 @@ const Layout = ({ footer, children, disableSidebar, font }: any) => { }) ); } + if ( + multiSelect.selected.length > 0 && + !multiSelect.isSelectDragging + ) { + dispatch(clearSelected()); + } }} /> { dispatch(toggleSelected(rowData)); } else if (e.shiftKey) { dispatch(setRangeSelected(rowData)); - if (searchQuery !== '') { - dispatch(toggleRangeSelected(filteredData)); - } else { - dispatch(toggleRangeSelected(albums)); - } - } else { - dispatch(setSelected(rowData)); + dispatch( + toggleRangeSelected(searchQuery !== '' ? filteredData : albums) + ); } }, 100); } diff --git a/src/components/library/AlbumView.tsx b/src/components/library/AlbumView.tsx index 44f29c1..ad36d36 100644 --- a/src/components/library/AlbumView.tsx +++ b/src/components/library/AlbumView.tsx @@ -20,7 +20,6 @@ import { toggleSelected, setRangeSelected, toggleRangeSelected, - setSelected, clearSelected, } from '../../redux/multiSelectSlice'; import useSearchQuery from '../../hooks/useSearchQuery'; @@ -67,10 +66,9 @@ const AlbumView = ({ ...rest }: any) => { dispatch(toggleSelected(rowData)); } else if (e.shiftKey) { dispatch(setRangeSelected(rowData)); - - dispatch(toggleRangeSelected(data.song)); - } else { - dispatch(setSelected(rowData)); + dispatch( + toggleRangeSelected(searchQuery !== '' ? filteredData : data.song) + ); } }, 100); } diff --git a/src/components/library/ArtistView.tsx b/src/components/library/ArtistView.tsx index 4efecb4..6e7b9f5 100644 --- a/src/components/library/ArtistView.tsx +++ b/src/components/library/ArtistView.tsx @@ -15,7 +15,6 @@ import { toggleSelected, setRangeSelected, toggleRangeSelected, - setSelected, clearSelected, } from '../../redux/multiSelectSlice'; import useSearchQuery from '../../hooks/useSearchQuery'; @@ -70,10 +69,9 @@ const ArtistView = ({ ...rest }: any) => { dispatch(toggleSelected(rowData)); } else if (e.shiftKey) { dispatch(setRangeSelected(rowData)); - - dispatch(toggleRangeSelected(data.album)); - } else { - dispatch(setSelected(rowData)); + dispatch( + toggleRangeSelected(searchQuery !== '' ? filteredData : data.album) + ); } }, 100); } diff --git a/src/components/player/NowPlayingMiniView.tsx b/src/components/player/NowPlayingMiniView.tsx index 1f0ed6a..a85e629 100644 --- a/src/components/player/NowPlayingMiniView.tsx +++ b/src/components/player/NowPlayingMiniView.tsx @@ -6,7 +6,6 @@ import { toggleSelected, setRangeSelected, toggleRangeSelected, - setSelected, clearSelected, setIsDragging, } from '../../redux/multiSelectSlice'; @@ -77,8 +76,6 @@ const NowPlayingMiniView = () => { : playQueue.entry ) ); - } else { - dispatch(setSelected(rowData)); } }, 100); } diff --git a/src/components/player/NowPlayingView.tsx b/src/components/player/NowPlayingView.tsx index 92d45c6..33ae825 100644 --- a/src/components/player/NowPlayingView.tsx +++ b/src/components/player/NowPlayingView.tsx @@ -19,7 +19,6 @@ import { toggleSelected, setRangeSelected, toggleRangeSelected, - setSelected, clearSelected, setIsDragging, } from '../../redux/multiSelectSlice'; @@ -80,8 +79,6 @@ const NowPlayingView = () => { ) ); } - } else { - dispatch(setSelected(rowData)); } }, 100); } diff --git a/src/components/playlist/PlaylistView.tsx b/src/components/playlist/PlaylistView.tsx index 7d16fe5..9b4f7e6 100644 --- a/src/components/playlist/PlaylistView.tsx +++ b/src/components/playlist/PlaylistView.tsx @@ -32,7 +32,6 @@ import { toggleSelected, setRangeSelected, toggleRangeSelected, - setSelected, clearSelected, setIsDragging, } from '../../redux/multiSelectSlice'; @@ -135,8 +134,6 @@ const PlaylistView = ({ ...rest }) => { searchQuery !== '' ? filteredData : localPlaylistData ) ); - } else { - dispatch(setSelected(rowData)); } }, 100); } diff --git a/src/components/starred/StarredView.tsx b/src/components/starred/StarredView.tsx index 5e0555d..5faed8c 100644 --- a/src/components/starred/StarredView.tsx +++ b/src/components/starred/StarredView.tsx @@ -11,7 +11,6 @@ import { } from '../../redux/playQueueSlice'; import { clearSelected, - setSelected, toggleSelected, toggleRangeSelected, setRangeSelected, @@ -65,17 +64,12 @@ const StarredView = () => { } } else if (currentPage === 'Albums') { dispatch(setRangeSelected(rowData)); - if (searchQuery !== '') { - dispatch(toggleRangeSelected(filteredData)); - } else { - dispatch(toggleRangeSelected(data?.album)); - } - } else { - // !TODO - data.song.slice(); + dispatch( + toggleRangeSelected( + searchQuery !== '' ? filteredData : data?.album + ) + ); } - } else { - dispatch(setSelected(rowData)); } }, 100); } diff --git a/src/components/viewtypes/ListViewTable.tsx b/src/components/viewtypes/ListViewTable.tsx index f8d360a..3d185bc 100644 --- a/src/components/viewtypes/ListViewTable.tsx +++ b/src/components/viewtypes/ListViewTable.tsx @@ -34,11 +34,14 @@ import { import { StyledIconToggle, StyledRate } from '../shared/styled'; import { addModalPage, setContextMenu } from '../../redux/miscSlice'; import { - appendSelected, + clearSelected, setCurrentMouseOverId, setIsDragging, setIsSelectDragging, + setRangeSelected, setSelectedSingle, + toggleRangeSelected, + toggleSelected, } from '../../redux/multiSelectSlice'; const ListViewTable = ({ @@ -134,6 +137,46 @@ const ListViewTable = ({ } }; + // Acts as our initial multiSelect handler by toggling the selected row + // and continuing the selection drag if the mouse button is held down + const handleSelectMouseDown = (e: any, rowData: any) => { + // If ctrl or shift is used, we want to ignore this drag selection handler + // and use the ones provided in handleRowClick + if (e.button === 0 && !e.ctrlKey && !e.shiftKey) { + if ( + multiSelect.selected.length === 1 && + multiSelect.selected[0].uniqueId === rowData.uniqueId + ) { + // Toggle single entry if the same entry is clicked + dispatch(clearSelected()); + } else { + if (multiSelect.selected.length > 0) { + dispatch(clearSelected()); + } + dispatch(setIsSelectDragging(true)); + dispatch(toggleSelected(rowData)); + } + } + }; + + // Completes the multiSelect handler once the mouse button is lifted + const handleSelectMouseUp = () => { + dispatch(setIsDragging(false)); + dispatch(setIsSelectDragging(false)); + }; + + // If mouse is still held down from the handleSelectMouseDown function, then + // mousing over a row will set the range selection from the initial mousedown location + // to the mouse-entered row + const handleSelectMouseEnter = (rowData: any) => { + if (multiSelect.isSelectDragging) { + dispatch(setRangeSelected(rowData)); + dispatch( + toggleRangeSelected(sortColumn && !nowPlaying ? sortedData : data) + ); + } + }; + useEffect(() => { if (!nowPlaying) { if (sortColumn && sortType) { @@ -418,20 +461,11 @@ const ListViewTable = ({ rowIndex, }) } - onMouseDown={(e: any) => { - if (e.button === 0) { - dispatch(setIsSelectDragging(true)); - } - }} - onMouseOver={() => { - if (multiSelect.isSelectDragging) { - dispatch(appendSelected(rowData)); - } - }} - onMouseUp={() => { - dispatch(setIsDragging(false)); - dispatch(setIsSelectDragging(false)); - }} + onMouseDown={(e: any) => + handleSelectMouseDown(e, rowData) + } + onMouseEnter={() => handleSelectMouseEnter(rowData)} + onMouseUp={() => handleSelectMouseUp()} dragover={ multiSelect.currentMouseOverId === rowData.uniqueId && multiSelect.isDragging @@ -595,20 +629,11 @@ const ListViewTable = ({ : 'false' } height={rowHeight} - onMouseDown={(e: any) => { - if (e.button === 0) { - dispatch(setIsSelectDragging(true)); - } - }} - onMouseOver={() => { - if (multiSelect.isSelectDragging) { - dispatch(appendSelected(rowData)); - } - }} - onMouseUp={() => { - dispatch(setIsDragging(false)); - dispatch(setIsSelectDragging(false)); - }} + onMouseDown={(e: any) => + handleSelectMouseDown(e, rowData) + } + onMouseEnter={() => handleSelectMouseEnter(rowData)} + onMouseUp={() => handleSelectMouseUp()} dragover={ multiSelect.currentMouseOverId === rowData.uniqueId && multiSelect.isDragging @@ -692,20 +717,11 @@ const ListViewTable = ({ }); } }} - onMouseDown={(e: any) => { - if (e.button === 0) { - dispatch(setIsSelectDragging(true)); - } - }} - onMouseOver={() => { - if (multiSelect.isSelectDragging) { - dispatch(appendSelected(rowData)); - } - }} - onMouseUp={() => { - dispatch(setIsDragging(false)); - dispatch(setIsSelectDragging(false)); - }} + onMouseDown={(e: any) => + handleSelectMouseDown(e, rowData) + } + onMouseEnter={() => handleSelectMouseEnter(rowData)} + onMouseUp={() => handleSelectMouseUp()} dragover={ multiSelect.currentMouseOverId === rowData.uniqueId && multiSelect.isDragging