From 4be1391947484c773a62599082292bc6da5cbcb8 Mon Sep 17 00:00:00 2001 From: Paul Neubauer Date: Tue, 21 Jun 2022 10:03:29 +0200 Subject: [PATCH 01/23] WIP selection via keyboard --- packages/web-app-files/src/App.vue | 42 ++++++++++++++++++- packages/web-app-files/src/store/mutations.js | 8 ++++ packages/web-app-files/src/store/state.js | 1 + 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/packages/web-app-files/src/App.vue b/packages/web-app-files/src/App.vue index c217eab3984..4c99e2a67f1 100644 --- a/packages/web-app-files/src/App.vue +++ b/packages/web-app-files/src/App.vue @@ -34,6 +34,7 @@ export default defineComponent({ sidebarClosed: 'closed', sidebarActivePanel: 'activePanel' }), + ...mapState('Files', ['latestSelectedId']), showSidebar() { return !this.sidebarClosed @@ -47,7 +48,8 @@ export default defineComponent({ this.closeSidebar() } } - } + }, + }, created() { this.$root.$on('upload-end', () => { @@ -64,7 +66,7 @@ export default defineComponent({ }, methods: { - ...mapActions('Files', ['resetFileSelection']), + ...mapActions('Files', ['resetFileSelection', 'toggleFileSelection']), ...mapActions('Files/sidebar', { closeSidebar: 'close', setActiveSidebarPanel: 'setActivePanel' @@ -74,6 +76,42 @@ export default defineComponent({ ...mapMutations('Files', ['UPSERT_RESOURCE']), handleShortcut(event) { + this.handleFileActionsShortcuts(event) + this.handleFileSelectionShortcuts(event) + }, + + handleFileSelectionShortcuts(event) { + const key = event.keyCode || event.which + const isShiftPressed = event.shiftKey + if(!isShiftPressed) return + const isUpPressed = key === 38 + const isDownPressed = key === 40 + if(isDownPressed) { + const latestSelectedRow = document.querySelectorAll(`[data-item-id='${this.latestSelectedId}']`)[0] + const nextRow = latestSelectedRow.nextSibling as HTMLElement + const nextResourceId = nextRow.getAttribute("data-item-id") + + console.log(nextRow) + console.log(nextResourceId) + this.toggleFileSelection({id: nextResourceId}) + } + if(isUpPressed) { + const latestSelectedRow = document.querySelectorAll(`[data-item-id='${this.latestSelectedId}']`)[0] + const nextRow = latestSelectedRow.previousSibling as HTMLElement + const nextResourceId = nextRow.getAttribute("data-item-id") + + console.log(nextRow) + console.log(nextResourceId) + this.toggleFileSelection({id: nextResourceId}) + } + // get last selected id + // find index in dom + // get id from dom index + 1 or - 1 + + //document.getElementsByClassName("oc-table-highlighted")[0].parentElement.childNodes[0] + }, + + handleFileActionsShortcuts(event) { const key = event.keyCode || event.which const ctr = window.navigator.platform.match('Mac') ? event.metaKey : event.ctrlKey if (!ctr /* CTRL | CMD */) return diff --git a/packages/web-app-files/src/store/mutations.js b/packages/web-app-files/src/store/mutations.js index 95149ffce5b..e281c0aeb52 100644 --- a/packages/web-app-files/src/store/mutations.js +++ b/packages/web-app-files/src/store/mutations.js @@ -92,14 +92,22 @@ export default { state.clipboardAction = action }, SET_FILE_SELECTION(state, files) { + console.log("im here jo") + console.log(files) + const latestSelected = files.find(i => !state.selectedIds.some(j => j === i.id)) + const latestSelectedId = latestSelected ? latestSelected.id : state.latestSelectedId + state.latestSelectedId = latestSelectedId + console.log(state.latestSelectedId) state.selectedIds = files.map((f) => f.id) }, ADD_FILE_SELECTION(state, file) { + console.log("im here jo 2") const selected = [...state.selectedIds] const fileIndex = selected.findIndex((id) => { return id === file.id }) if (fileIndex === -1) { + state.latestSelectedId = file.id selected.push(file.id) state.selectedIds = selected } diff --git a/packages/web-app-files/src/store/state.js b/packages/web-app-files/src/store/state.js index 1440de67582..d37620910db 100644 --- a/packages/web-app-files/src/store/state.js +++ b/packages/web-app-files/src/store/state.js @@ -3,6 +3,7 @@ export default { files: [], filesSearched: null, selectedIds: [], + latestSelectedId: null, clipboardResources: [], clipboardAction: null, versions: [], From a90545a4740fa4ee392b6a20f58c0bc09dea363f Mon Sep 17 00:00:00 2001 From: Paul Neubauer Date: Tue, 21 Jun 2022 16:14:15 +0200 Subject: [PATCH 02/23] WIP --- packages/web-app-files/src/App.vue | 48 ++++++++++++------- .../components/FilesList/ResourceTable.vue | 4 +- packages/web-app-files/src/store/mutations.js | 8 ++-- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/packages/web-app-files/src/App.vue b/packages/web-app-files/src/App.vue index 93999fcd9a0..dafa44dc66d 100644 --- a/packages/web-app-files/src/App.vue +++ b/packages/web-app-files/src/App.vue @@ -19,6 +19,7 @@ diff --git a/packages/web-app-files/src/components/FilesList/ResourceTable.vue b/packages/web-app-files/src/components/FilesList/ResourceTable.vue index 4814560a29c..59d546c9db0 100644 --- a/packages/web-app-files/src/components/FilesList/ResourceTable.vue +++ b/packages/web-app-files/src/components/FilesList/ResourceTable.vue @@ -41,7 +41,7 @@ size="large" :value="selection" :option="item" - @input="fileClicked" + @input="onCheckboxInput" @click.native.stop /> @@ -303,7 +303,7 @@ export default defineComponent({ default: true }, /** - * Top position of header used when the header is sticky in pixels + * Top position of header used when the head^er is sticky in pixels */ headerPosition: { type: Number, @@ -564,6 +564,9 @@ export default defineComponent({ }, methods: { ...mapActions('Files/sidebar', ['openWithPanel']), + onCheckboxInput(resources) { + this.emitSelect(resources) + }, hasRenameAction(item) { return this.$_rename_items.filter((menuItem) => menuItem.isEnabled({ resources: [item] })) .length @@ -678,7 +681,6 @@ export default defineComponent({ * Triggered when the file row is clicked * @property {object} resource The resource for which the event is triggered */ - bus.publish('app.files.list.clicked', resource); this.emitSelect([resource]) }, formatDate(date) { @@ -694,6 +696,7 @@ export default defineComponent({ * Triggered when a checkbox for selecting a resource or the checkbox for selecting all resources is clicked * @property {array} resources The selected resources */ + bus.publish('app.files.list.clicked') this.$emit('select', resources) }, toggleSelectionAll() { From c578699a0a7a526335da09334aadd2a86a5881c3 Mon Sep 17 00:00:00 2001 From: Paul Neubauer Date: Wed, 22 Jun 2022 10:29:21 +0200 Subject: [PATCH 04/23] Add space, escape keyboard actions --- packages/web-app-files/src/App.vue | 5 +- .../components/FilesList/KeymapActions.vue | 172 ++++++++++-------- packages/web-app-files/src/store/mutations.js | 2 +- 3 files changed, 98 insertions(+), 81 deletions(-) diff --git a/packages/web-app-files/src/App.vue b/packages/web-app-files/src/App.vue index 65d2ab6d995..ebb8df76598 100644 --- a/packages/web-app-files/src/App.vue +++ b/packages/web-app-files/src/App.vue @@ -21,7 +21,7 @@ diff --git a/packages/web-app-files/src/store/mutations.js b/packages/web-app-files/src/store/mutations.js index 4cee1756f76..e0943ca8c92 100644 --- a/packages/web-app-files/src/store/mutations.js +++ b/packages/web-app-files/src/store/mutations.js @@ -95,7 +95,7 @@ export default { state.latestSelectedId = file }, SET_FILE_SELECTION(state, files) { - const latestSelected = files.find(i => !state.selectedIds.some(j => j === i.id)) + const latestSelected = files.find((i) => !state.selectedIds.some((j) => j === i.id)) const latestSelectedId = latestSelected ? latestSelected.id : state.latestSelectedId state.latestSelectedId = latestSelectedId state.selectedIds = files.map((f) => f.id) From 6a3b9cf448d1897c6c270eb9fddbf9a0407cc31d Mon Sep 17 00:00:00 2001 From: Paul Neubauer Date: Wed, 22 Jun 2022 10:42:51 +0200 Subject: [PATCH 05/23] Add select all shortcut --- .../components/FilesList/KeymapActions.vue | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/web-app-files/src/components/FilesList/KeymapActions.vue b/packages/web-app-files/src/components/FilesList/KeymapActions.vue index 20462035f72..047fb59ee93 100644 --- a/packages/web-app-files/src/components/FilesList/KeymapActions.vue +++ b/packages/web-app-files/src/components/FilesList/KeymapActions.vue @@ -4,6 +4,8 @@ From b3eb6a4a630a5a3a6337c164d15ec0c6dafb8daf Mon Sep 17 00:00:00 2001 From: Paul Neubauer Date: Thu, 23 Jun 2022 11:39:38 +0200 Subject: [PATCH 07/23] Add latest selection checkbox outline, fix toggle multiple select issue --- packages/web-app-files/src/App.vue | 2 +- ...{KeymapActions.vue => KeyboardActions.vue} | 10 +++++----- .../components/FilesList/ResourceTable.vue | 19 ++++++++++++------- packages/web-app-files/src/store/mutations.js | 4 ++-- 4 files changed, 20 insertions(+), 15 deletions(-) rename packages/web-app-files/src/components/FilesList/{KeymapActions.vue => KeyboardActions.vue} (95%) diff --git a/packages/web-app-files/src/App.vue b/packages/web-app-files/src/App.vue index ebb8df76598..b0d7ef22861 100644 --- a/packages/web-app-files/src/App.vue +++ b/packages/web-app-files/src/App.vue @@ -23,7 +23,7 @@ import Mixins from './mixins' import { mapActions, mapState } from 'vuex' import SideBar from './components/SideBar/SideBar.vue' -import KeymapActions from './components/FilesList/KeymapActions.vue' +import KeymapActions from './components/FilesList/KeyboardActions.vue' import { defineComponent } from '@vue/composition-api' import { usePublicLinkPassword, useStore } from 'web-pkg/src/composables' diff --git a/packages/web-app-files/src/components/FilesList/KeymapActions.vue b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue similarity index 95% rename from packages/web-app-files/src/components/FilesList/KeymapActions.vue rename to packages/web-app-files/src/components/FilesList/KeyboardActions.vue index 280756ec313..e0414c84285 100644 --- a/packages/web-app-files/src/components/FilesList/KeymapActions.vue +++ b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue @@ -44,7 +44,7 @@ export default { 'resetFileSelection', 'toggleFileSelection' ]), - ...mapMutations('Files', ['UPSERT_RESOURCE', 'SET_LATEST_SELECTED_FILE', 'SET_FILE_SELECTION']), + ...mapMutations('Files', ['UPSERT_RESOURCE', 'SET_LATEST_SELECTED_FILE', 'SET_FILE_SELECTION', 'ADD_FILE_SELECTION']), handleShortcut(event) { const key = event.keyCode || event.which @@ -74,8 +74,8 @@ export default { if (isSpacePressed) return this.handleSpaceAction(event) if (isEscapePressed) return this.handleEscapeAction() - if (isDownPressed && shift) return this.handleShiftDownAction() - if (isUpPressed && shift) return this.handleShiftUpAction() + if (isDownPressed && shift) return this.handleShiftDownAction(event) + if (isUpPressed && shift) return this.handleShiftUpAction(event) if (isAPressed && ctrl) return this.handleSelectAllAction(event) }, @@ -104,7 +104,7 @@ export default { this.SET_LATEST_SELECTED_FILE(nextResourceId) } else { // select - this.toggleFileSelection({ id: nextResourceId }) + this.ADD_FILE_SELECTION({ id: nextResourceId }) } this.selectionCursor = this.selectionCursor - 1 }, @@ -118,7 +118,7 @@ export default { this.SET_LATEST_SELECTED_FILE(nextResourceId) } else { // select - this.toggleFileSelection({ id: nextResourceId }) + this.ADD_FILE_SELECTION({ id: nextResourceId }) } this.selectionCursor = this.selectionCursor + 1 }, diff --git a/packages/web-app-files/src/components/FilesList/ResourceTable.vue b/packages/web-app-files/src/components/FilesList/ResourceTable.vue index 59d546c9db0..d3bebd13687 100644 --- a/packages/web-app-files/src/components/FilesList/ResourceTable.vue +++ b/packages/web-app-files/src/components/FilesList/ResourceTable.vue @@ -41,7 +41,8 @@ size="large" :value="selection" :option="item" - @input="onCheckboxInput" + :outline="isLatestSelectedItem(item)" + @input="emitSelect" @click.native.stop /> @@ -398,7 +399,7 @@ export default defineComponent({ }, computed: { ...mapGetters(['configuration']), - ...mapState('Files', ['areFileExtensionsShown', 'spaces']), + ...mapState('Files', ['areFileExtensionsShown', 'spaces', 'latestSelectedId']), popperOptions() { return { modifiers: [ @@ -564,8 +565,8 @@ export default defineComponent({ }, methods: { ...mapActions('Files/sidebar', ['openWithPanel']), - onCheckboxInput(resources) { - this.emitSelect(resources) + isLatestSelectedItem(item) { + return item.id === this.latestSelectedId }, hasRenameAction(item) { return this.$_rename_items.filter((menuItem) => menuItem.isEnabled({ resources: [item] })) @@ -676,12 +677,16 @@ export default defineComponent({ */ this.$emit('rowMounted', resource, component) }, - fileClicked(resource) { + fileClicked(data) { /** * Triggered when the file row is clicked * @property {object} resource The resource for which the event is triggered */ - this.emitSelect([resource]) + if(data[1].metaKey) { + alert("ctrl is pressed") + }else { + this.emitSelect([data[0]]) + } }, formatDate(date) { return DateTime.fromJSDate(new Date(date)) @@ -710,7 +715,7 @@ export default defineComponent({ * Triggered when a default action is triggered on a file * @property {object} resource resource for which the event is triggered */ - this.$emit('fileClick', resource) + //this.$emit('fileClick', resource) }, isResourceClickable(resourceId) { if (!this.areResourcesClickable) { diff --git a/packages/web-app-files/src/store/mutations.js b/packages/web-app-files/src/store/mutations.js index e0943ca8c92..c8c2c84f541 100644 --- a/packages/web-app-files/src/store/mutations.js +++ b/packages/web-app-files/src/store/mutations.js @@ -105,16 +105,16 @@ export default { const fileIndex = selected.findIndex((id) => { return id === file.id }) + state.latestSelectedId = file.id if (fileIndex === -1) { - state.latestSelectedId = file.id selected.push(file.id) state.selectedIds = selected } }, REMOVE_FILE_SELECTION(state, file) { const selected = [...state.selectedIds] + state.latestSelectedId = file.id if (selected.length > 1) { - state.latestSelectedId = file.id state.selectedIds = selected.filter((id) => file.id !== id) return } From 03dffbb24d16488c1bdaf49a263919ed08258648 Mon Sep 17 00:00:00 2001 From: Paul Neubauer Date: Thu, 23 Jun 2022 11:58:59 +0200 Subject: [PATCH 08/23] Add ctrl + left click selection --- .../src/components/FilesList/KeyboardActions.vue | 6 ++++++ .../src/components/FilesList/ResourceTable.vue | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/web-app-files/src/components/FilesList/KeyboardActions.vue b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue index e0414c84285..897ef4307cd 100644 --- a/packages/web-app-files/src/components/FilesList/KeyboardActions.vue +++ b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue @@ -28,9 +28,11 @@ export default { mounted() { document.addEventListener('keydown', this.handleShortcut, false) const fileListClickedEvent = bus.subscribe('app.files.list.clicked', this.resetSelectionCursor) + const fileListClickedMetaEvent = bus.subscribe('app.files.list.clicked.meta', this.handleCtrlClick) this.$on('beforeDestroy', () => { bus.unsubscribe('app.files.list.clicked', fileListClickedEvent) + bus.unsubscribe('app.files.list.clicked.meta', fileListClickedMetaEvent) document.removeEventListener('keydown', this.handleShortcut) }) }, @@ -79,6 +81,10 @@ export default { if (isAPressed && ctrl) return this.handleSelectAllAction(event) }, + handleCtrlClick(resource) { + this.toggleFileSelection({ id: resource.id }) + }, + handleEscapeAction() { this.resetSelectionCursor() this.resetFileSelection() diff --git a/packages/web-app-files/src/components/FilesList/ResourceTable.vue b/packages/web-app-files/src/components/FilesList/ResourceTable.vue index d3bebd13687..960e2353116 100644 --- a/packages/web-app-files/src/components/FilesList/ResourceTable.vue +++ b/packages/web-app-files/src/components/FilesList/ResourceTable.vue @@ -683,7 +683,7 @@ export default defineComponent({ * @property {object} resource The resource for which the event is triggered */ if(data[1].metaKey) { - alert("ctrl is pressed") + bus.publish('app.files.list.clicked.meta', data[0]) }else { this.emitSelect([data[0]]) } From 23ab860a20d9d5a573b33502eca40c2448c6d8a0 Mon Sep 17 00:00:00 2001 From: Paul Neubauer Date: Thu, 23 Jun 2022 14:51:52 +0200 Subject: [PATCH 09/23] Add shift + click selection --- .../components/FilesList/KeyboardActions.vue | 108 ++++++++++++------ .../components/FilesList/ResourceTable.vue | 8 +- 2 files changed, 77 insertions(+), 39 deletions(-) diff --git a/packages/web-app-files/src/components/FilesList/KeyboardActions.vue b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue index 897ef4307cd..2681c455f3e 100644 --- a/packages/web-app-files/src/components/FilesList/KeyboardActions.vue +++ b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue @@ -19,21 +19,29 @@ export default { ...mapState('Files', ['latestSelectedId']) }, - setup() { + setup() { return { - ...useResourcesViewDefaults(), + ...useResourcesViewDefaults() } }, mounted() { - document.addEventListener('keydown', this.handleShortcut, false) + document.addEventListener('keydown', this.handleShortcut, false) const fileListClickedEvent = bus.subscribe('app.files.list.clicked', this.resetSelectionCursor) - const fileListClickedMetaEvent = bus.subscribe('app.files.list.clicked.meta', this.handleCtrlClick) + const fileListClickedMetaEvent = bus.subscribe( + 'app.files.list.clicked.meta', + this.handleCtrlClick + ) + const fileListClickedShiftEvent = bus.subscribe( + 'app.files.list.clicked.shift', + this.handleShiftClick + ) this.$on('beforeDestroy', () => { bus.unsubscribe('app.files.list.clicked', fileListClickedEvent) bus.unsubscribe('app.files.list.clicked.meta', fileListClickedMetaEvent) - document.removeEventListener('keydown', this.handleShortcut) + bus.unsubscribe('app.files.list.clicked.shift', fileListClickedShiftEvent) + document.removeEventListener('keydown', this.handleShortcut) }) }, @@ -46,7 +54,12 @@ export default { 'resetFileSelection', 'toggleFileSelection' ]), - ...mapMutations('Files', ['UPSERT_RESOURCE', 'SET_LATEST_SELECTED_FILE', 'SET_FILE_SELECTION', 'ADD_FILE_SELECTION']), + ...mapMutations('Files', [ + 'UPSERT_RESOURCE', + 'SET_LATEST_SELECTED_FILE', + 'SET_FILE_SELECTION', + 'ADD_FILE_SELECTION' + ]), handleShortcut(event) { const key = event.keyCode || event.which @@ -70,40 +83,61 @@ export default { handleFileSelectionShortcuts(key, shift, ctrl, event) { const isUpPressed = key === 38 const isDownPressed = key === 40 - const isEscapePressed = key === 27 - const isSpacePressed = key === 32 - const isAPressed = key === 65 + const isEscapePressed = key === 27 + const isSpacePressed = key === 32 + const isAPressed = key === 65 - if (isSpacePressed) return this.handleSpaceAction(event) - if (isEscapePressed) return this.handleEscapeAction() + if (isSpacePressed) return this.handleSpaceAction(event) + if (isEscapePressed) return this.handleEscapeAction() if (isDownPressed && shift) return this.handleShiftDownAction(event) if (isUpPressed && shift) return this.handleShiftUpAction(event) - if (isAPressed && ctrl) return this.handleSelectAllAction(event) + if (isAPressed && ctrl) return this.handleSelectAllAction(event) + }, + + handleShiftClick(resource) { + const parent = document.querySelectorAll(`[data-item-id='${resource.id}']`)[0] + const resourceNodes = Object.values(parent.parentNode.childNodes) as HTMLElement[] + const latestNode = resourceNodes.find( + (r) => r.getAttribute('data-item-id') === this.latestSelectedId + ) + const clickedNode = resourceNodes.find((r) => r.getAttribute('data-item-id') === resource.id) + + let latestNodeIndex = resourceNodes.indexOf(latestNode) + latestNodeIndex = latestNodeIndex === -1 ? 0 : latestNodeIndex + + const clickedNodeIndex = resourceNodes.indexOf(clickedNode) + const minIndex = Math.min(latestNodeIndex, clickedNodeIndex) + const maxIndex = Math.max(latestNodeIndex, clickedNodeIndex) + + for (let i = minIndex; i <= maxIndex; i++) { + const nodeId = resourceNodes[i].getAttribute('data-item-id') + this.ADD_FILE_SELECTION({ id: nodeId }) + } }, handleCtrlClick(resource) { this.toggleFileSelection({ id: resource.id }) }, - handleEscapeAction() { - this.resetSelectionCursor() - this.resetFileSelection() - }, + handleEscapeAction() { + this.resetSelectionCursor() + this.resetFileSelection() + }, - handleSelectAllAction(event) { - event.preventDefault() - this.resetSelectionCursor() - this.SET_FILE_SELECTION(this.paginatedResources) - }, + handleSelectAllAction(event) { + event.preventDefault() + this.resetSelectionCursor() + this.SET_FILE_SELECTION(this.paginatedResources) + }, - handleSpaceAction(event) { - event.preventDefault() - this.toggleFileSelection({ id: this.latestSelectedId }) - }, + handleSpaceAction(event) { + event.preventDefault() + this.toggleFileSelection({ id: this.latestSelectedId }) + }, handleShiftUpAction() { const nextResourceId = this.getNextResourceId(true) - if(nextResourceId === -1) return + if (nextResourceId === -1) return if (this.selectionCursor > 0) { // deselect this.toggleFileSelection({ id: this.latestSelectedId }) @@ -117,7 +151,7 @@ export default { handleShiftDownAction() { const nextResourceId = this.getNextResourceId() - if(nextResourceId === -1) return + if (nextResourceId === -1) return if (this.selectionCursor < 0) { // deselect this.toggleFileSelection({ id: this.latestSelectedId }) @@ -141,20 +175,22 @@ export default { upsertResource: this.UPSERT_RESOURCE }) }, - - resetSelectionCursor() { - this.selectionCursor = 0 - }, - getNextResourceId(previous=false) { - const latestSelectedRow = document.querySelectorAll( + resetSelectionCursor() { + this.selectionCursor = 0 + }, + + getNextResourceId(previous = false) { + const latestSelectedRow = document.querySelectorAll( `[data-item-id='${this.latestSelectedId}']` )[0] - const nextRow = (previous ? latestSelectedRow.previousSibling : latestSelectedRow.nextSibling) as HTMLElement + const nextRow = ( + previous ? latestSelectedRow.previousSibling : latestSelectedRow.nextSibling + ) as HTMLElement if (nextRow === null) return -1 const nextResourceId = nextRow.getAttribute('data-item-id') - return nextResourceId - } + return nextResourceId + } } } diff --git a/packages/web-app-files/src/components/FilesList/ResourceTable.vue b/packages/web-app-files/src/components/FilesList/ResourceTable.vue index 960e2353116..b27a174eff3 100644 --- a/packages/web-app-files/src/components/FilesList/ResourceTable.vue +++ b/packages/web-app-files/src/components/FilesList/ResourceTable.vue @@ -682,9 +682,11 @@ export default defineComponent({ * Triggered when the file row is clicked * @property {object} resource The resource for which the event is triggered */ - if(data[1].metaKey) { + if (data[1].metaKey) { bus.publish('app.files.list.clicked.meta', data[0]) - }else { + } else if (data[1].shiftKey) { + bus.publish('app.files.list.clicked.shift', data[0]) + } else { this.emitSelect([data[0]]) } }, @@ -715,7 +717,7 @@ export default defineComponent({ * Triggered when a default action is triggered on a file * @property {object} resource resource for which the event is triggered */ - //this.$emit('fileClick', resource) + // this.$emit('fileClick', resource) }, isResourceClickable(resourceId) { if (!this.areResourcesClickable) { From 670607557b5d94a84705cd4a55c57782cf1fcc0d Mon Sep 17 00:00:00 2001 From: Paul Neubauer Date: Thu, 23 Jun 2022 15:19:53 +0200 Subject: [PATCH 10/23] Add keyboard up/down navigation --- .../components/FilesList/KeyboardActions.vue | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/packages/web-app-files/src/components/FilesList/KeyboardActions.vue b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue index 2681c455f3e..aa06266cc7a 100644 --- a/packages/web-app-files/src/components/FilesList/KeyboardActions.vue +++ b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue @@ -30,11 +30,11 @@ export default { const fileListClickedEvent = bus.subscribe('app.files.list.clicked', this.resetSelectionCursor) const fileListClickedMetaEvent = bus.subscribe( 'app.files.list.clicked.meta', - this.handleCtrlClick + this.handleCtrlClickAction ) const fileListClickedShiftEvent = bus.subscribe( 'app.files.list.clicked.shift', - this.handleShiftClick + this.handleShiftClickAction ) this.$on('beforeDestroy', () => { @@ -54,12 +54,12 @@ export default { 'resetFileSelection', 'toggleFileSelection' ]), - ...mapMutations('Files', [ - 'UPSERT_RESOURCE', - 'SET_LATEST_SELECTED_FILE', - 'SET_FILE_SELECTION', - 'ADD_FILE_SELECTION' - ]), + ...mapMutations('Files', { + upsertResource: 'UPSERT_RESOURCE', + setLatestSelectedFile: 'SET_LATEST_SELECTED_FILE', + setFileSelection: 'SET_FILE_SELECTION', + addFileSelection: 'ADD_FILE_SELECTION' + }), handleShortcut(event) { const key = event.keyCode || event.which @@ -87,6 +87,8 @@ export default { const isSpacePressed = key === 32 const isAPressed = key === 65 + if (isDownPressed && !shift) return this.handleNavigateAction(event) + if (isUpPressed && !shift) return this.handleNavigateAction(event, true) if (isSpacePressed) return this.handleSpaceAction(event) if (isEscapePressed) return this.handleEscapeAction() if (isDownPressed && shift) return this.handleShiftDownAction(event) @@ -94,7 +96,17 @@ export default { if (isAPressed && ctrl) return this.handleSelectAllAction(event) }, - handleShiftClick(resource) { + handleNavigateAction(event, up = false) { + event.preventDefault() + this.resetSelectionCursor() + this.resetFileSelection() + if (!this.latestSelectedId) return + const nextId = this.getNextResourceId(up) + if (nextId === -1) return + this.addFileSelection({ id: nextId }) + }, + + handleShiftClickAction(resource) { const parent = document.querySelectorAll(`[data-item-id='${resource.id}']`)[0] const resourceNodes = Object.values(parent.parentNode.childNodes) as HTMLElement[] const latestNode = resourceNodes.find( @@ -111,11 +123,11 @@ export default { for (let i = minIndex; i <= maxIndex; i++) { const nodeId = resourceNodes[i].getAttribute('data-item-id') - this.ADD_FILE_SELECTION({ id: nodeId }) + this.addFileSelection({ id: nodeId }) } }, - handleCtrlClick(resource) { + handleCtrlClickAction(resource) { this.toggleFileSelection({ id: resource.id }) }, @@ -127,7 +139,7 @@ export default { handleSelectAllAction(event) { event.preventDefault() this.resetSelectionCursor() - this.SET_FILE_SELECTION(this.paginatedResources) + this.setFileSelection(this.paginatedResources) }, handleSpaceAction(event) { @@ -141,10 +153,10 @@ export default { if (this.selectionCursor > 0) { // deselect this.toggleFileSelection({ id: this.latestSelectedId }) - this.SET_LATEST_SELECTED_FILE(nextResourceId) + this.setLatestSelectedFile(nextResourceId) } else { // select - this.ADD_FILE_SELECTION({ id: nextResourceId }) + this.addFileSelection({ id: nextResourceId }) } this.selectionCursor = this.selectionCursor - 1 }, @@ -155,10 +167,10 @@ export default { if (this.selectionCursor < 0) { // deselect this.toggleFileSelection({ id: this.latestSelectedId }) - this.SET_LATEST_SELECTED_FILE(nextResourceId) + this.setLatestSelectedFile(nextResourceId) } else { // select - this.ADD_FILE_SELECTION({ id: nextResourceId }) + this.addFileSelection({ id: nextResourceId }) } this.selectionCursor = this.selectionCursor + 1 }, @@ -172,7 +184,7 @@ export default { $gettext: this.$gettext, $gettextInterpolate: this.$gettextInterpolate, $ngettext: this.$ngettext, - upsertResource: this.UPSERT_RESOURCE + upsertResource: this.upsertResource }) }, From 9096d04943e92dffe4eaee602f9b301d209fc29c Mon Sep 17 00:00:00 2001 From: Paul Neubauer Date: Fri, 24 Jun 2022 10:25:55 +0200 Subject: [PATCH 11/23] Fix navigation deselects first and last row bug --- .../src/components/FilesList/KeyboardActions.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/web-app-files/src/components/FilesList/KeyboardActions.vue b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue index aa06266cc7a..b134661db80 100644 --- a/packages/web-app-files/src/components/FilesList/KeyboardActions.vue +++ b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue @@ -98,11 +98,11 @@ export default { handleNavigateAction(event, up = false) { event.preventDefault() - this.resetSelectionCursor() - this.resetFileSelection() if (!this.latestSelectedId) return const nextId = this.getNextResourceId(up) if (nextId === -1) return + this.resetSelectionCursor() + this.resetFileSelection() this.addFileSelection({ id: nextId }) }, From 58454c16ad7bcaa460d84bddab93f5a15ede5e82 Mon Sep 17 00:00:00 2001 From: Paul Neubauer Date: Fri, 24 Jun 2022 11:06:16 +0200 Subject: [PATCH 12/23] Fix shift+click doesnt set latest selected item --- .../web-app-files/src/components/FilesList/KeyboardActions.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/web-app-files/src/components/FilesList/KeyboardActions.vue b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue index b134661db80..455742087a3 100644 --- a/packages/web-app-files/src/components/FilesList/KeyboardActions.vue +++ b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue @@ -125,6 +125,7 @@ export default { const nodeId = resourceNodes[i].getAttribute('data-item-id') this.addFileSelection({ id: nodeId }) } + this.setLatestSelectedFile(resource.id) }, handleCtrlClickAction(resource) { From cf34fc318d14a7e4287bbb73be653a30a20fbe1b Mon Sep 17 00:00:00 2001 From: Paul Neubauer Date: Fri, 24 Jun 2022 13:53:20 +0200 Subject: [PATCH 13/23] Bump ODS, Address PR issues --- .../src/components/FilesList/KeyboardActions.vue | 2 +- .../web-app-files/src/components/FilesList/ResourceTable.vue | 4 ++-- packages/web-app-files/src/store/mutations.js | 2 +- packages/web-runtime/package.json | 4 ++-- yarn.lock | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/web-app-files/src/components/FilesList/KeyboardActions.vue b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue index 455742087a3..a6283753b85 100644 --- a/packages/web-app-files/src/components/FilesList/KeyboardActions.vue +++ b/packages/web-app-files/src/components/FilesList/KeyboardActions.vue @@ -56,7 +56,7 @@ export default { ]), ...mapMutations('Files', { upsertResource: 'UPSERT_RESOURCE', - setLatestSelectedFile: 'SET_LATEST_SELECTED_FILE', + setLatestSelectedFile: 'SET_LATEST_SELECTED_FILE_ID', setFileSelection: 'SET_FILE_SELECTION', addFileSelection: 'ADD_FILE_SELECTION' }), diff --git a/packages/web-app-files/src/components/FilesList/ResourceTable.vue b/packages/web-app-files/src/components/FilesList/ResourceTable.vue index b27a174eff3..98abce291ff 100644 --- a/packages/web-app-files/src/components/FilesList/ResourceTable.vue +++ b/packages/web-app-files/src/components/FilesList/ResourceTable.vue @@ -304,7 +304,7 @@ export default defineComponent({ default: true }, /** - * Top position of header used when the head^er is sticky in pixels + * Top position of header used when the header is sticky in pixels */ headerPosition: { type: Number, @@ -717,7 +717,7 @@ export default defineComponent({ * Triggered when a default action is triggered on a file * @property {object} resource resource for which the event is triggered */ - // this.$emit('fileClick', resource) + this.$emit('fileClick', resource) }, isResourceClickable(resourceId) { if (!this.areResourcesClickable) { diff --git a/packages/web-app-files/src/store/mutations.js b/packages/web-app-files/src/store/mutations.js index c8c2c84f541..b40d2dfa2ea 100644 --- a/packages/web-app-files/src/store/mutations.js +++ b/packages/web-app-files/src/store/mutations.js @@ -91,7 +91,7 @@ export default { SET_CLIPBOARD_ACTION(state, action) { state.clipboardAction = action }, - SET_LATEST_SELECTED_FILE(state, file) { + SET_LATEST_SELECTED_FILE_ID(state, file) { state.latestSelectedId = file }, SET_FILE_SELECTION(state, files) { diff --git a/packages/web-runtime/package.json b/packages/web-runtime/package.json index d9156acbd4a..dbb40855037 100644 --- a/packages/web-runtime/package.json +++ b/packages/web-runtime/package.json @@ -24,7 +24,7 @@ "luxon": "^2.4.0", "marked": "^4.0.12", "oidc-client-ts": "^2.0.5", - "owncloud-design-system": "^14.0.0-alpha.2", + "owncloud-design-system": "^14.0.0-alpha.3", "owncloud-sdk": "~3.0.0-alpha.14", "p-queue": "^6.6.2", "popper-max-size-modifier": "^0.2.0", @@ -62,4 +62,4 @@ "@types/luxon": "^2.3.1", "@types/semver": "^7.3.8" } -} +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 6e399c5cddf..271c458fcb8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9711,7 +9711,7 @@ __metadata: languageName: node linkType: hard -"owncloud-design-system@npm:^14.0.0-alpha.2": +"owncloud-design-system@npm:^14.0.0-alpha.3": version: 14.0.0 resolution: "owncloud-design-system@npm:14.0.0" peerDependencies: @@ -13773,7 +13773,7 @@ __metadata: luxon: ^2.4.0 marked: ^4.0.12 oidc-client-ts: ^2.0.5 - owncloud-design-system: ^14.0.0-alpha.2 + owncloud-design-system: ^14.0.0-alpha.3 owncloud-sdk: ~3.0.0-alpha.14 p-queue: ^6.6.2 popper-max-size-modifier: ^0.2.0 From 626a4a1dbb263de4809422a820979214f955624b Mon Sep 17 00:00:00 2001 From: Paul Neubauer Date: Mon, 27 Jun 2022 12:00:54 +0200 Subject: [PATCH 14/23] Fix ODS not updated, fix row click bug undefined error --- .../src/components/FilesList/ResourceTable.vue | 14 ++++++++------ packages/web-runtime/package.json | 2 +- yarn.lock | 10 +++++----- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/web-app-files/src/components/FilesList/ResourceTable.vue b/packages/web-app-files/src/components/FilesList/ResourceTable.vue index 98abce291ff..d4e489acc70 100644 --- a/packages/web-app-files/src/components/FilesList/ResourceTable.vue +++ b/packages/web-app-files/src/components/FilesList/ResourceTable.vue @@ -682,13 +682,15 @@ export default defineComponent({ * Triggered when the file row is clicked * @property {object} resource The resource for which the event is triggered */ - if (data[1].metaKey) { - bus.publish('app.files.list.clicked.meta', data[0]) - } else if (data[1].shiftKey) { - bus.publish('app.files.list.clicked.shift', data[0]) - } else { - this.emitSelect([data[0]]) + const resource = data[0] + const eventData = data[1] + if (eventData && eventData.metaKey) { + return bus.publish('app.files.list.clicked.meta', resource) + } + if (eventData && eventData.shiftKey) { + return bus.publish('app.files.list.clicked.shift', resource) } + return this.emitSelect([resource]) }, formatDate(date) { return DateTime.fromJSDate(new Date(date)) diff --git a/packages/web-runtime/package.json b/packages/web-runtime/package.json index dbb40855037..4f8f7df414d 100644 --- a/packages/web-runtime/package.json +++ b/packages/web-runtime/package.json @@ -24,7 +24,7 @@ "luxon": "^2.4.0", "marked": "^4.0.12", "oidc-client-ts": "^2.0.5", - "owncloud-design-system": "^14.0.0-alpha.3", + "owncloud-design-system": "14.0.0-alpha.4", "owncloud-sdk": "~3.0.0-alpha.14", "p-queue": "^6.6.2", "popper-max-size-modifier": "^0.2.0", diff --git a/yarn.lock b/yarn.lock index 271c458fcb8..43bb6f8914f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9711,9 +9711,9 @@ __metadata: languageName: node linkType: hard -"owncloud-design-system@npm:^14.0.0-alpha.3": - version: 14.0.0 - resolution: "owncloud-design-system@npm:14.0.0" +"owncloud-design-system@npm:14.0.0-alpha.4": + version: 14.0.0-alpha.4 + resolution: "owncloud-design-system@npm:14.0.0-alpha.4" peerDependencies: "@popperjs/core": ^2.4.0 "@vue/composition-api": ^1.4.3 @@ -9730,7 +9730,7 @@ __metadata: vue-inline-svg: ^2.0.0 vue-select: ^3.12.0 webfontloader: ^1.6.28 - checksum: 1b3b43770d9d5e0fe7bb52b997b2a165f5f8dfdc9765b5f95cc30c050be9f8b4b7af5b2438006f701fd0c48a8c62d6fd005c969e4aa6e9f804324b88a157214b + checksum: b45901f01adcf50de706d89f66387a524c18d241b0123e745a6e4c167d1350f68f3ca3ebe636857fea12e58b6b6534c49bff9c2f82757548ed3d61b9774e78dc languageName: node linkType: hard @@ -13773,7 +13773,7 @@ __metadata: luxon: ^2.4.0 marked: ^4.0.12 oidc-client-ts: ^2.0.5 - owncloud-design-system: ^14.0.0-alpha.3 + owncloud-design-system: 14.0.0-alpha.4 owncloud-sdk: ~3.0.0-alpha.14 p-queue: ^6.6.2 popper-max-size-modifier: ^0.2.0 From 9bc4379837fc8bb0445c7a046fc9b1b98448a423 Mon Sep 17 00:00:00 2001 From: Paul Neubauer Date: Mon, 27 Jun 2022 14:58:55 +0200 Subject: [PATCH 15/23] Fix focus sidebar on selection killing keyboard shortcuts --- packages/web-app-files/src/App.vue | 7 ++++++- .../src/components/FilesList/KeyboardActions.vue | 3 ++- packages/web-pkg/src/components/sidebar/SideBar.vue | 11 ----------- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/packages/web-app-files/src/App.vue b/packages/web-app-files/src/App.vue index b0d7ef22861..6322535e7c2 100644 --- a/packages/web-app-files/src/App.vue +++ b/packages/web-app-files/src/App.vue @@ -1,7 +1,12 @@