aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Molakvoæ <skjnldsv@protonmail.com>2023-10-12 10:05:02 +0200
committerJohn Molakvoæ <skjnldsv@protonmail.com>2023-10-17 11:19:01 +0200
commit0f1f73478a59f59d92c4542aa42dc61973c600de (patch)
treee7ece617499984de35973536b4470f8e17bd8018
parent60260bb58e22a9309c126d54441e0ac28d2b140f (diff)
downloadnextcloud-server-0f1f73478a59f59d92c4542aa42dc61973c600de.tar.gz
nextcloud-server-0f1f73478a59f59d92c4542aa42dc61973c600de.zip
fix(files): split FileEntry Checkbox and fix range selection
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
-rw-r--r--apps/files/src/components/FileEntry.vue59
-rw-r--r--apps/files/src/components/FileEntry/FileEntryCheckbox.vue130
2 files changed, 137 insertions, 52 deletions
diff --git a/apps/files/src/components/FileEntry.vue b/apps/files/src/components/FileEntry.vue
index 1a1bf6d9baf..87c36356210 100644
--- a/apps/files/src/components/FileEntry.vue
+++ b/apps/files/src/components/FileEntry.vue
@@ -37,13 +37,11 @@
<span v-if="source.attributes.failed" class="files-list__row--failed" />
<!-- Checkbox -->
- <td class="files-list__row-checkbox">
- <NcLoadingIcon v-if="isLoading" />
- <NcCheckboxRadioSwitch v-else-if="visible"
- :aria-label="t('files', 'Select the row for {displayName}', { displayName })"
- :checked="isSelected"
- @update:checked="onSelectionChange" />
- </td>
+ <FileEntryCheckbox v-if="visible"
+ :display-name="displayName"
+ :fileid="fileid"
+ :loading="isLoading"
+ :nodes="nodes"/>
<!-- Link to file -->
<td class="files-list__row-name" data-cy-files-list-row-name>
@@ -177,7 +175,6 @@ import Vue from 'vue'
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
-import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js'
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
@@ -190,10 +187,10 @@ import { hashCode } from '../utils/hashUtils.ts'
import { useActionsMenuStore } from '../store/actionsmenu.ts'
import { useDragAndDropStore } from '../store/dragging.ts'
import { useFilesStore } from '../store/files.ts'
-import { useKeyboardStore } from '../store/keyboard.ts'
import { useRenamingStore } from '../store/renaming.ts'
import { useSelectionStore } from '../store/selection.ts'
import CustomElementRender from './CustomElementRender.vue'
+import FileEntryCheckbox from './FileEntry/FileEntryCheckbox.vue'
import FileEntryPreview from './FileEntry/FileEntryPreview.vue'
import logger from '../logger.js'
@@ -212,10 +209,10 @@ export default Vue.extend({
FileEntryPreview,
NcActionButton,
NcActions,
- NcCheckboxRadioSwitch,
NcIconSvgWrapper,
NcLoadingIcon,
NcTextField,
+ FileEntryCheckbox,
},
props: {
@@ -235,10 +232,6 @@ export default Vue.extend({
type: [Folder, NcFile, Node] as PropType<Node>,
required: true,
},
- index: {
- type: Number,
- required: true,
- },
nodes: {
type: Array as PropType<Node[]>,
required: true,
@@ -253,14 +246,12 @@ export default Vue.extend({
const actionsMenuStore = useActionsMenuStore()
const draggingStore = useDragAndDropStore()
const filesStore = useFilesStore()
- const keyboardStore = useKeyboardStore()
const renamingStore = useRenamingStore()
const selectionStore = useSelectionStore()
return {
actionsMenuStore,
draggingStore,
filesStore,
- keyboardStore,
renamingStore,
selectionStore,
}
@@ -276,7 +267,6 @@ export default Vue.extend({
},
computed: {
-
currentView() {
return this.$navigation.active
},
@@ -600,41 +590,6 @@ export default Vue.extend({
}
},
- onSelectionChange(selected: boolean) {
- const newSelectedIndex = this.index
- const lastSelectedIndex = this.selectionStore.lastSelectedIndex
-
- // Get the last selected and select all files in between
- if (this.keyboardStore?.shiftKey && lastSelectedIndex !== null) {
- const isAlreadySelected = this.selectedFiles.includes(this.fileid)
-
- const start = Math.min(newSelectedIndex, lastSelectedIndex)
- const end = Math.max(lastSelectedIndex, newSelectedIndex)
-
- const lastSelection = this.selectionStore.lastSelection
- const filesToSelect = this.nodes
- .map(file => file.fileid?.toString?.())
- .slice(start, end + 1)
-
- // If already selected, update the new selection _without_ the current file
- const selection = [...lastSelection, ...filesToSelect]
- .filter(fileid => !isAlreadySelected || fileid !== this.fileid)
-
- logger.debug('Shift key pressed, selecting all files in between', { start, end, filesToSelect, isAlreadySelected })
- // Keep previous lastSelectedIndex to be use for further shift selections
- this.selectionStore.set(selection)
- return
- }
-
- const selection = selected
- ? [...this.selectedFiles, this.fileid]
- : this.selectedFiles.filter(fileid => fileid !== this.fileid)
-
- logger.debug('Updating selection', { selection })
- this.selectionStore.set(selection)
- this.selectionStore.setLastIndex(newSelectedIndex)
- },
-
// Open the actions menu on right click
onRightClick(event) {
// If already opened, fallback to default browser
diff --git a/apps/files/src/components/FileEntry/FileEntryCheckbox.vue b/apps/files/src/components/FileEntry/FileEntryCheckbox.vue
new file mode 100644
index 00000000000..376d14d4073
--- /dev/null
+++ b/apps/files/src/components/FileEntry/FileEntryCheckbox.vue
@@ -0,0 +1,130 @@
+<!--
+ - @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com>
+ -
+ - @author John Molakvoæ <skjnldsv@protonmail.com>
+ -
+ - @license GNU AGPL version 3 or any later version
+ -
+ - This program is free software: you can redistribute it and/or modify
+ - it under the terms of the GNU Affero General Public License as
+ - published by the Free Software Foundation, either version 3 of the
+ - License, or (at your option) any later version.
+ -
+ - This program is distributed in the hope that it will be useful,
+ - but WITHOUT ANY WARRANTY; without even the implied warranty of
+ - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ - GNU Affero General Public License for more details.
+ -
+ - You should have received a copy of the GNU Affero General Public License
+ - along with this program. If not, see <http://www.gnu.org/licenses/>.
+ -
+ -->
+<template>
+ <td class="files-list__row-checkbox">
+ <NcLoadingIcon v-if="loading" />
+ <NcCheckboxRadioSwitch :aria-label="t('files', 'Select the row for {displayName}', { displayName })"
+ :checked="isSelected"
+ @update:checked="onSelectionChange" />
+ </td>
+</template>
+
+<script lang="ts">
+import { Node } from '@nextcloud/files'
+import { translate as t } from '@nextcloud/l10n'
+import Vue, { PropType } from 'vue'
+
+import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
+import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
+
+import { useKeyboardStore } from '../../store/keyboard.ts'
+import { useSelectionStore } from '../../store/selection.ts'
+import logger from '../../logger.js'
+
+export default Vue.extend({
+ name: 'FileEntryCheckbox',
+
+ components: {
+ NcCheckboxRadioSwitch,
+ NcLoadingIcon,
+ },
+
+ props: {
+ displayName: {
+ type: String,
+ required: true,
+ },
+ fileid: {
+ type: String,
+ required: true,
+ },
+ loading: {
+ type: Boolean,
+ default: false,
+ },
+ nodes: {
+ type: Array as PropType<Node[]>,
+ required: true,
+ },
+ },
+
+ setup() {
+ const selectionStore = useSelectionStore()
+ const keyboardStore = useKeyboardStore()
+ return {
+ keyboardStore,
+ selectionStore,
+ }
+ },
+
+ computed: {
+ selectedFiles() {
+ return this.selectionStore.selected
+ },
+ isSelected() {
+ return this.selectedFiles.includes(this.fileid)
+ },
+ index() {
+ return this.nodes.findIndex((node: Node) => node.fileid === parseInt(this.fileid))
+ },
+ },
+
+ methods: {
+ onSelectionChange(selected: boolean) {
+ const newSelectedIndex = this.index
+ const lastSelectedIndex = this.selectionStore.lastSelectedIndex
+
+ // Get the last selected and select all files in between
+ if (this.keyboardStore?.shiftKey && lastSelectedIndex !== null) {
+ const isAlreadySelected = this.selectedFiles.includes(this.fileid)
+
+ const start = Math.min(newSelectedIndex, lastSelectedIndex)
+ const end = Math.max(lastSelectedIndex, newSelectedIndex)
+
+ const lastSelection = this.selectionStore.lastSelection
+ const filesToSelect = this.nodes
+ .map(file => file.fileid?.toString?.())
+ .slice(start, end + 1)
+
+ // If already selected, update the new selection _without_ the current file
+ const selection = [...lastSelection, ...filesToSelect]
+ .filter(fileid => !isAlreadySelected || fileid !== this.fileid)
+
+ logger.debug('Shift key pressed, selecting all files in between', { start, end, filesToSelect, isAlreadySelected })
+ // Keep previous lastSelectedIndex to be use for further shift selections
+ this.selectionStore.set(selection)
+ return
+ }
+
+ const selection = selected
+ ? [...this.selectedFiles, this.fileid]
+ : this.selectedFiles.filter(fileid => fileid !== this.fileid)
+
+ logger.debug('Updating selection', { selection })
+ this.selectionStore.set(selection)
+ this.selectionStore.setLastIndex(newSelectedIndex)
+ },
+
+ t,
+ },
+})
+</script>