aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorskjnldsv <skjnldsv@protonmail.com>2024-12-13 12:08:34 +0100
committerskjnldsv <skjnldsv@protonmail.com>2024-12-17 09:59:57 +0100
commit2b330c6f347208370f70ca7c668c99968426c86f (patch)
treeb3a283e4b74fe4ea6eb8210d5f1cfc253c9b7659 /apps
parent74b2562e6b40a9339943bfa83d323ea11203f401 (diff)
downloadnextcloud-server-2b330c6f347208370f70ca7c668c99968426c86f.tar.gz
nextcloud-server-2b330c6f347208370f70ca7c668c99968426c86f.zip
feat(files): add selection keyboard shortcuts
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
Diffstat (limited to 'apps')
-rw-r--r--apps/files/src/components/FileEntry/FileEntryCheckbox.vue37
-rw-r--r--apps/files/src/components/FilesListTableHeader.vue28
2 files changed, 59 insertions, 6 deletions
diff --git a/apps/files/src/components/FileEntry/FileEntryCheckbox.vue b/apps/files/src/components/FileEntry/FileEntryCheckbox.vue
index 9caa08cfe22..1b6112373f4 100644
--- a/apps/files/src/components/FileEntry/FileEntryCheckbox.vue
+++ b/apps/files/src/components/FileEntry/FileEntryCheckbox.vue
@@ -23,9 +23,11 @@ import { FileType } from '@nextcloud/files'
import { translate as t } from '@nextcloud/l10n'
import { defineComponent } from 'vue'
+import { useHotKey } from '@nextcloud/vue/dist/Composables/useHotKey.js'
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
+import { useActiveStore } from '../../store/active.ts'
import { useKeyboardStore } from '../../store/keyboard.ts'
import { useSelectionStore } from '../../store/selection.ts'
import logger from '../../logger.ts'
@@ -60,13 +62,21 @@ 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
},
@@ -91,6 +101,23 @@ export default defineComponent({
},
},
+ 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: {
onSelectionChange(selected: boolean) {
const newSelectedIndex = this.index
@@ -132,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>
diff --git a/apps/files/src/components/FilesListTableHeader.vue b/apps/files/src/components/FilesListTableHeader.vue
index c8334abda5e..b7818a9a40f 100644
--- a/apps/files/src/components/FilesListTableHeader.vue
+++ b/apps/files/src/components/FilesListTableHeader.vue
@@ -58,15 +58,15 @@ import type { Node } from '@nextcloud/files'
import type { PropType } from 'vue'
import type { FileSource } from '../types.ts'
-import { translate as t } from '@nextcloud/l10n'
import { defineComponent } from 'vue'
-
+import { translate as t } from '@nextcloud/l10n'
+import { useHotKey } from '@nextcloud/vue/dist/Composables/useHotKey.js'
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
-import FilesListTableHeaderButton from './FilesListTableHeaderButton.vue'
-import { useNavigation } from '../composables/useNavigation'
import { useFilesStore } from '../store/files.ts'
+import { useNavigation } from '../composables/useNavigation'
import { useSelectionStore } from '../store/selection.ts'
+import FilesListTableHeaderButton from './FilesListTableHeaderButton.vue'
import filesSortingMixin from '../mixins/filesSorting.ts'
import logger from '../logger.ts'
@@ -155,6 +155,21 @@ export default defineComponent({
},
},
+ created() {
+ // ctrl+a selects all
+ useHotKey('a', this.onToggleAll, {
+ ctrl: true,
+ stop: true,
+ prevent: true,
+ })
+
+ // Escape key cancels selection
+ useHotKey('Escape', this.resetSelection, {
+ stop: true,
+ prevent: true,
+ })
+ },
+
methods: {
ariaSortForMode(mode: string): ARIAMixin['ariaSort'] {
if (this.sortingMode === mode) {
@@ -172,7 +187,7 @@ export default defineComponent({
}
},
- onToggleAll(selected) {
+ onToggleAll(selected = true) {
if (selected) {
const selection = this.nodes.map(node => node.source).filter(Boolean) as FileSource[]
logger.debug('Added all nodes to selection', { selection })
@@ -185,6 +200,9 @@ export default defineComponent({
},
resetSelection() {
+ if (this.isNoneSelected) {
+ return
+ }
this.selectionStore.reset()
},