diff options
Diffstat (limited to 'apps/files/src/components/FileEntry/FileEntryCheckbox.vue')
-rw-r--r-- | apps/files/src/components/FileEntry/FileEntryCheckbox.vue | 98 |
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> |