aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files/src/components/FileEntry/FileEntryCheckbox.vue
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files/src/components/FileEntry/FileEntryCheckbox.vue')
-rw-r--r--apps/files/src/components/FileEntry/FileEntryCheckbox.vue98
1 files changed, 63 insertions, 35 deletions
diff --git a/apps/files/src/components/FileEntry/FileEntryCheckbox.vue b/apps/files/src/components/FileEntry/FileEntryCheckbox.vue
index 747ff8d6cc9..5b80a971118 100644
--- a/apps/files/src/components/FileEntry/FileEntryCheckbox.vue
+++ b/apps/files/src/components/FileEntry/FileEntryCheckbox.vue
@@ -1,46 +1,36 @@
<!--
- - @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/>.
- -
- -->
+ - SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
<template>
<td class="files-list__row-checkbox"
@keyup.esc.exact="resetSelection">
- <NcLoadingIcon v-if="isLoading" />
+ <NcLoadingIcon v-if="isLoading" :name="loadingLabel" />
<NcCheckboxRadioSwitch v-else
:aria-label="ariaLabel"
:checked="isSelected"
+ data-cy-files-list-row-checkbox
@update:checked="onSelectionChange" />
</td>
</template>
<script lang="ts">
-import { Node, FileType } from '@nextcloud/files'
+import type { Node } from '@nextcloud/files'
+import type { PropType } from 'vue'
+import type { FileSource } from '../../types.ts'
+
+import { FileType } from '@nextcloud/files'
import { translate as t } from '@nextcloud/l10n'
-import { type PropType, defineComponent } from 'vue'
+import { useHotKey } from '@nextcloud/vue/composables/useHotKey'
+import { defineComponent } from 'vue'
-import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
-import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
+import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'
+import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
+import { useActiveStore } from '../../store/active.ts'
import { useKeyboardStore } from '../../store/keyboard.ts'
import { useSelectionStore } from '../../store/selection.ts'
-import logger from '../../logger.js'
+import logger from '../../logger.ts'
export default defineComponent({
name: 'FileEntryCheckbox',
@@ -72,21 +62,29 @@ export default defineComponent({
setup() {
const selectionStore = useSelectionStore()
const keyboardStore = useKeyboardStore()
+ const activeStore = useActiveStore()
+
return {
+ activeStore,
keyboardStore,
selectionStore,
+ t,
}
},
computed: {
+ isActive() {
+ return this.activeStore.activeNode?.source === this.source.source
+ },
+
selectedFiles() {
return this.selectionStore.selected
},
isSelected() {
- return this.selectedFiles.includes(this.fileid)
+ return this.selectedFiles.includes(this.source.source)
},
index() {
- return this.nodes.findIndex((node: Node) => node.fileid === this.fileid)
+ return this.nodes.findIndex((node: Node) => node.source === this.source.source)
},
isFile() {
return this.source.type === FileType.File
@@ -96,6 +94,28 @@ export default defineComponent({
? t('files', 'Toggle selection for file "{displayName}"', { displayName: this.source.basename })
: t('files', 'Toggle selection for folder "{displayName}"', { displayName: this.source.basename })
},
+ loadingLabel() {
+ return this.isFile
+ ? t('files', 'File is loading')
+ : t('files', 'Folder is loading')
+ },
+ },
+
+ created() {
+ // ctrl+space toggle selection
+ useHotKey(' ', this.onToggleSelect, {
+ stop: true,
+ prevent: true,
+ ctrl: true,
+ })
+
+ // ctrl+shift+space toggle range selection
+ useHotKey(' ', this.onToggleSelect, {
+ stop: true,
+ prevent: true,
+ ctrl: true,
+ shift: true,
+ })
},
methods: {
@@ -105,20 +125,20 @@ export default defineComponent({
// Get the last selected and select all files in between
if (this.keyboardStore?.shiftKey && lastSelectedIndex !== null) {
- const isAlreadySelected = this.selectedFiles.includes(this.fileid)
+ const isAlreadySelected = this.selectedFiles.includes(this.source.source)
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)
+ .map(file => file.source)
.slice(start, end + 1)
- .filter(Boolean) as number[]
+ .filter(Boolean) as FileSource[]
// If already selected, update the new selection _without_ the current file
const selection = [...lastSelection, ...filesToSelect]
- .filter(fileid => !isAlreadySelected || fileid !== this.fileid)
+ .filter(source => !isAlreadySelected || source !== this.source.source)
logger.debug('Shift key pressed, selecting all files in between', { start, end, filesToSelect, isAlreadySelected })
// Keep previous lastSelectedIndex to be use for further shift selections
@@ -127,8 +147,8 @@ export default defineComponent({
}
const selection = selected
- ? [...this.selectedFiles, this.fileid]
- : this.selectedFiles.filter(fileid => fileid !== this.fileid)
+ ? [...this.selectedFiles, this.source.source]
+ : this.selectedFiles.filter(source => source !== this.source.source)
logger.debug('Updating selection', { selection })
this.selectionStore.set(selection)
@@ -139,7 +159,15 @@ export default defineComponent({
this.selectionStore.reset()
},
- t,
+ onToggleSelect() {
+ // Don't react if the node is not active
+ if (!this.isActive) {
+ return
+ }
+
+ logger.debug('Toggling selection for file', { source: this.source })
+ this.onSelectionChange(!this.isSelected)
+ },
},
})
</script>