From 2b726fa2dd1597b53159fbdf14936ee4cfbf4999 Mon Sep 17 00:00:00 2001 From: John Molakvoæ Date: Fri, 21 Apr 2023 15:33:08 +0200 Subject: fix(files): always force menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ --- apps/files/src/components/FileEntry.vue | 1 + 1 file changed, 1 insertion(+) (limited to 'apps/files/src/components/FileEntry.vue') diff --git a/apps/files/src/components/FileEntry.vue b/apps/files/src/components/FileEntry.vue index 00ff8a3d533..c42327e8821 100644 --- a/apps/files/src/components/FileEntry.vue +++ b/apps/files/src/components/FileEntry.vue @@ -75,6 +75,7 @@ :container="boundariesElement" :disabled="source._loading" :force-title="true" + :force-menu="true" :inline="enabledInlineActions.length" :open.sync="openedMenu"> Date: Fri, 21 Apr 2023 15:39:31 +0200 Subject: feat(files): add sidebar action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ --- apps/files/src/actions/sidebarAction.ts | 54 +++++++++++++++++++++++++++++++++ apps/files/src/components/FileEntry.vue | 14 +++++++-- apps/files/src/main.ts | 3 +- 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 apps/files/src/actions/sidebarAction.ts (limited to 'apps/files/src/components/FileEntry.vue') diff --git a/apps/files/src/actions/sidebarAction.ts b/apps/files/src/actions/sidebarAction.ts new file mode 100644 index 00000000000..f56d3a9475f --- /dev/null +++ b/apps/files/src/actions/sidebarAction.ts @@ -0,0 +1,54 @@ +/** + * @copyright Copyright (c) 2023 John Molakvoæ + * + * @author John Molakvoæ + * + * @license AGPL-3.0-or-later + * + * 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 . + * + */ +import { translate as t } from '@nextcloud/l10n' +import InformationSvg from '@mdi/svg/svg/information-variant.svg?raw' +import type { Node } from '@nextcloud/files' + +import { registerFileAction, FileAction } from '../services/FileAction.ts' +import logger from '../logger.js' + +export const ACTION_DETAILS = 'details' + +registerFileAction(new FileAction({ + id: ACTION_DETAILS, + displayName: () => t('files', 'Details'), + iconSvgInline: () => InformationSvg, + + // Sidebar currently supports user folder only, /files/USER + enabled: (files: Node[]) => !!window?.OCA?.Files?.Sidebar + && files.some(node => node.root?.startsWith('/files/')), + + async exec(node: Node) { + try { + // TODO: migrate Sidebar to use a Node instead + window?.OCA?.Files?.Sidebar?.open?.(node.path) + + return null + } catch (error) { + logger.error('Error while opening sidebar', { error }) + return false + } + }, + + default: true, + order: -50, +})) diff --git a/apps/files/src/components/FileEntry.vue b/apps/files/src/components/FileEntry.vue index c42327e8821..215a8fdbbc7 100644 --- a/apps/files/src/components/FileEntry.vue +++ b/apps/files/src/components/FileEntry.vue @@ -95,7 +95,7 @@ + @click="openDetailsIfAvailable"> {{ size }} @@ -104,7 +104,7 @@ :key="column.id" :class="`files-list__row-${currentView?.id}-${column.id}`" class="files-list__row-column-custom" - @click="execDefaultAction"> + @click="openDetailsIfAvailable"> action.id === ACTION_DETAILS) + if (detailsAction) { + event.preventDefault() + event.stopPropagation() + detailsAction.exec(this.source, this.currentView) + } + }, + onSelectionChange(selection) { const newSelectedIndex = this.index const lastSelectedIndex = this.selectionStore.lastSelectedIndex diff --git a/apps/files/src/main.ts b/apps/files/src/main.ts index 976714a8f1f..195357d0e0a 100644 --- a/apps/files/src/main.ts +++ b/apps/files/src/main.ts @@ -1,6 +1,7 @@ import './templates.js' import './legacy/filelistSearch.js' import './actions/deleteAction' +import './actions/sidebarAction' import Vue from 'vue' import { createPinia, PiniaVuePlugin } from 'pinia' @@ -11,9 +12,9 @@ import NavigationView from './views/Navigation.vue' import processLegacyFilesViews from './legacy/navigationMapper.js' import registerPreviewServiceWorker from './services/ServiceWorker.js' import router from './router/router.js' +import RouterService from './services/RouterService' import SettingsModel from './models/Setting.js' import SettingsService from './services/Settings.js' -import RouterService from './services/RouterService' declare global { interface Window { -- cgit v1.2.3 From 1de3666e16af8362789d7a000c93b9aea1229c12 Mon Sep 17 00:00:00 2001 From: John Molakvoæ Date: Fri, 21 Apr 2023 15:40:27 +0200 Subject: feat(files): add dir file action parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ --- apps/files/src/actions/deleteAction.ts | 7 ++++--- apps/files/src/components/FileEntry.vue | 4 ++-- apps/files/src/components/FilesListHeaderActions.vue | 6 +++++- apps/files/src/services/FileAction.ts | 5 +++-- 4 files changed, 14 insertions(+), 8 deletions(-) (limited to 'apps/files/src/components/FileEntry.vue') diff --git a/apps/files/src/actions/deleteAction.ts b/apps/files/src/actions/deleteAction.ts index 087884b3362..a633e477b1f 100644 --- a/apps/files/src/actions/deleteAction.ts +++ b/apps/files/src/actions/deleteAction.ts @@ -27,10 +27,11 @@ import TrashCan from '@mdi/svg/svg/trash-can.svg?raw' import { registerFileAction, FileAction } from '../services/FileAction.ts' import logger from '../logger.js' +import type { Navigation } from '../services/Navigation.ts' registerFileAction(new FileAction({ id: 'delete', - displayName(nodes: Node[], view) { + displayName(nodes: Node[], view: Navigation) { return view.id === 'trashbin' ? t('files_trashbin', 'Delete permanently') : t('files', 'Delete') @@ -57,8 +58,8 @@ registerFileAction(new FileAction({ return false } }, - async execBatch(nodes: Node[], view) { - return Promise.all(nodes.map(node => this.exec(node, view))) + async execBatch(nodes: Node[], view: Navigation, dir: string) { + return Promise.all(nodes.map(node => this.exec(node, view, dir))) }, order: 100, diff --git a/apps/files/src/components/FileEntry.vue b/apps/files/src/components/FileEntry.vue index 215a8fdbbc7..d4258f29861 100644 --- a/apps/files/src/components/FileEntry.vue +++ b/apps/files/src/components/FileEntry.vue @@ -503,7 +503,7 @@ export default Vue.extend({ this.loading = action.id Vue.set(this.source, '_loading', true) - const success = await action.exec(this.source, this.currentView) + const success = await action.exec(this.source, this.currentView, this.dir) // If the action returns null, we stay silent if (success === null) { @@ -529,7 +529,7 @@ export default Vue.extend({ event.preventDefault() event.stopPropagation() // Execute the first default action if any - this.enabledDefaultActions[0].exec(this.source, this.currentView) + this.enabledDefaultActions[0].exec(this.source, this.currentView, this.dir) } }, diff --git a/apps/files/src/components/FilesListHeaderActions.vue b/apps/files/src/components/FilesListHeaderActions.vue index a53a1d041bf..f8c60a5cd1b 100644 --- a/apps/files/src/components/FilesListHeaderActions.vue +++ b/apps/files/src/components/FilesListHeaderActions.vue @@ -103,6 +103,10 @@ export default Vue.extend({ }, computed: { + dir() { + // Remove any trailing slash but leave root slash + return (this.$route?.query?.dir || '/').replace(/^(.+)\/$/, '$1') + }, enabledActions() { return actions .filter(action => action.execBatch) @@ -165,7 +169,7 @@ export default Vue.extend({ }) // Dispatch action execution - const results = await action.execBatch(this.nodes, this.currentView) + const results = await action.execBatch(this.nodes, this.currentView, this.dir) // Check if all actions returned null if (!results.some(result => result !== null)) { diff --git a/apps/files/src/services/FileAction.ts b/apps/files/src/services/FileAction.ts index 94fc7e8ce5f..70d6405c804 100644 --- a/apps/files/src/services/FileAction.ts +++ b/apps/files/src/services/FileAction.ts @@ -22,6 +22,7 @@ import type { Node } from '@nextcloud/files' import logger from '../logger' +import type { Navigation } from './Navigation' declare global { interface Window { @@ -48,14 +49,14 @@ interface FileActionData { * @returns true if the action was executed, false otherwise * @throws Error if the action failed */ - exec: (file: Node, view) => Promise, + exec: (file: Node, view: Navigation, dir: string) => Promise, /** * Function executed on multiple files action * @returns true if the action was executed successfully, * false otherwise and null if the action is silent/undefined. * @throws Error if the action failed */ - execBatch?: (files: Node[], view) => Promise<(boolean|null)[]> + execBatch?: (files: Node[], view: Navigation, dir: string) => Promise<(boolean|null)[]> /** This action order in the list */ order?: number, /** Make this action the default */ -- cgit v1.2.3 From 51f2f56b4bc9bd9883857563b9ada57bdb79ba2f Mon Sep 17 00:00:00 2001 From: John Molakvoæ Date: Fri, 21 Apr 2023 15:58:40 +0200 Subject: fix(files): do not execute the default action on folders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ --- apps/files/src/components/FileEntry.vue | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'apps/files/src/components/FileEntry.vue') diff --git a/apps/files/src/components/FileEntry.vue b/apps/files/src/components/FileEntry.vue index d4258f29861..8dc067a407d 100644 --- a/apps/files/src/components/FileEntry.vue +++ b/apps/files/src/components/FileEntry.vue @@ -262,6 +262,15 @@ export default Vue.extend({ }, linkTo() { + if (this.source.type === 'folder') { + const to = { ...this.$route, query: { dir: join(this.dir, this.source.basename) } } + return { + is: 'router-link', + title: this.t('files', 'Open folder {name}', { name: this.displayName }), + to, + } + } + if (this.enabledDefaultActions.length > 0) { const action = this.enabledDefaultActions[0] const displayName = action.displayName([this.source], this.currentView) @@ -271,14 +280,6 @@ export default Vue.extend({ } } - if (this.source.type === 'folder') { - const to = { ...this.$route, query: { dir: join(this.dir, this.source.basename) } } - return { - is: 'router-link', - title: this.t('files', 'Open folder {name}', { name: this.displayName }), - to, - } - } return { href: this.source.source, // TODO: Use first action title ? @@ -525,6 +526,11 @@ export default Vue.extend({ } }, execDefaultAction(event) { + // Do not execute the default action on the folder, navigate instead + if (this.source.type === 'folder') { + return + } + if (this.enabledDefaultActions.length > 0) { event.preventDefault() event.stopPropagation() -- cgit v1.2.3