From e46192ee78d114b7ba0bcc841d66d5318e1c0c7e Mon Sep 17 00:00:00 2001 From: Jerry Ren Date: Mon, 14 Oct 2024 16:29:56 +0800 Subject: [PATCH] fix: select multiple files via click checkbox with shift key (#6895) --- .../dirent-list-view/dirent-list-item.js | 8 ++- .../dirent-list-view/dirent-list-view.js | 4 +- .../lib-content-view/lib-content-view.js | 67 ++++++++++++++----- 3 files changed, 57 insertions(+), 22 deletions(-) diff --git a/frontend/src/components/dirent-list-view/dirent-list-item.js b/frontend/src/components/dirent-list-view/dirent-list-item.js index ccbcf35ea4..625fcea324 100644 --- a/frontend/src/components/dirent-list-view/dirent-list-item.js +++ b/frontend/src/components/dirent-list-view/dirent-list-item.js @@ -230,8 +230,9 @@ class DirentListItem extends React.Component { }; // buiness handler - onItemSelected = () => { - this.props.onItemSelected(this.state.dirent); + onItemSelected = (event) => { + event.stopPropagation(); + this.props.onItemSelected(this.state.dirent, event); }; onItemStarred = (e) => { @@ -822,7 +823,8 @@ class DirentListItem extends React.Component { {}} checked={isSelected} aria-label={isSelected ? gettext('Unselect this item') : gettext('Select this item')} /> diff --git a/frontend/src/components/dirent-list-view/dirent-list-view.js b/frontend/src/components/dirent-list-view/dirent-list-view.js index b8fb044ea2..0c9e06fc32 100644 --- a/frontend/src/components/dirent-list-view/dirent-list-view.js +++ b/frontend/src/components/dirent-list-view/dirent-list-view.js @@ -149,9 +149,9 @@ class DirentListView extends React.Component { this.freezeItem(); }; - onItemSelected = (dirent) => { + onItemSelected = (dirent, event) => { this.setState({ activeDirent: null }); - this.props.onItemSelected(dirent); + this.props.onItemSelected(dirent, event); }; onDirentClick = (dirent, event) => { diff --git a/frontend/src/pages/lib-content-view/lib-content-view.js b/frontend/src/pages/lib-content-view/lib-content-view.js index c8287c62fb..abf07dad0d 100644 --- a/frontend/src/pages/lib-content-view/lib-content-view.js +++ b/frontend/src/pages/lib-content-view/lib-content-view.js @@ -1521,40 +1521,73 @@ class LibContentView extends React.Component { } }; - onDirentSelected = (dirent) => { + onDirentSelected = (dirent, event) => { this.setState({ currentDirent: dirent && dirent.isActive ? null : dirent }); - let direntList = this.state.direntList.map(item => { - if (dirent && item.name === dirent.name) { - item.isSelected = !item.isSelected; + + const { direntList, lastSelectedIndex, selectedDirentList } = this.state; + const clickedDirentIndex = dirent ? direntList.findIndex((currDirent) => currDirent.name === dirent.name) : -1; + const clickedDirent = clickedDirentIndex > -1 ? direntList[clickedDirentIndex] : null; + let nextSelectedIndex = null; + if (clickedDirent && !clickedDirent.isSelected) { + nextSelectedIndex = clickedDirentIndex; + } + + let nextDirentList = direntList; + if (event && event.shiftKey && lastSelectedIndex !== null && nextSelectedIndex !== null) { + // select multiple files with shift key + const start = Math.min(lastSelectedIndex, nextSelectedIndex); + const end = Math.max(lastSelectedIndex, nextSelectedIndex); + const direntListInRange = direntList.slice(start, end + 1); + if (direntListInRange.length > 0) { + const nameDirentSelectedMap = selectedDirentList.reduce((currNameDirentSelectedMap, currDirent) => { + return { ...currNameDirentSelectedMap, [currDirent.name]: true }; + }, {}); + const nameDirentSelectingMap = direntListInRange.reduce((currNameDirentSelectingMap, currDirent) => { + return { ...currNameDirentSelectingMap, [currDirent.name]: true }; + }, {}); + nextDirentList = direntList.map((currDirent) => { + if (nameDirentSelectedMap[currDirent.name] || nameDirentSelectingMap[currDirent.name]) { + currDirent.isSelected = true; + } + return currDirent; + }); } - return item; - }); - let selectedDirentList = direntList.filter(item => { - return item.isSelected; - }); - if (selectedDirentList.length) { + } else { + nextDirentList = direntList.map(item => { + if (dirent && item.name === dirent.name) { + item.isSelected = !item.isSelected; + } + return item; + }); + } + + const nextSelectedDirentList = nextDirentList.filter(item => item.isSelected); + if (nextSelectedDirentList.length) { this.setState({ isDirentSelected: true }); - if (selectedDirentList.length === direntList.length) { + if (nextSelectedDirentList.length === nextDirentList.length) { this.setState({ isAllDirentSelected: true, - direntList: direntList, - selectedDirentList: selectedDirentList, + direntList: nextDirentList, + selectedDirentList: nextSelectedDirentList, + lastSelectedIndex: nextSelectedIndex, }); } else { this.setState({ isAllDirentSelected: false, - direntList: direntList, - selectedDirentList: selectedDirentList + direntList: nextDirentList, + selectedDirentList: nextSelectedDirentList, + lastSelectedIndex: nextSelectedIndex, }); } } else { this.setState({ isDirentSelected: false, isAllDirentSelected: false, - direntList: direntList, - selectedDirentList: [] + direntList: nextDirentList, + selectedDirentList: [], + lastSelectedIndex: nextSelectedIndex, }); } };