diff options
author | Ferdinand Thiessen <opensource@fthiessen.de> | 2025-02-05 17:56:22 +0100 |
---|---|---|
committer | Ferdinand Thiessen <opensource@fthiessen.de> | 2025-02-13 16:00:03 +0100 |
commit | 03e15b9297204c520cec58810361b8524dc70b66 (patch) | |
tree | 79efac2cd728555bb625dc875ec2ad1a725ce2fe /apps | |
parent | a560c3e97d65ce5edcb55ad31387ee61711ee2a4 (diff) | |
download | nextcloud-server-03e15b9297204c520cec58810361b8524dc70b66.tar.gz nextcloud-server-03e15b9297204c520cec58810361b8524dc70b66.zip |
fix(files): Do not download files with `openfile` query flag
Instead of downloading files, if there is no other default action,
we should just open the details tab.
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Diffstat (limited to 'apps')
-rw-r--r-- | apps/files/src/components/FilesListVirtual.vue | 58 | ||||
-rw-r--r-- | apps/files/src/router/router.ts | 35 |
2 files changed, 65 insertions, 28 deletions
diff --git a/apps/files/src/components/FilesListVirtual.vue b/apps/files/src/components/FilesListVirtual.vue index 488d4e8ef2c..64f606891e4 100644 --- a/apps/files/src/components/FilesListVirtual.vue +++ b/apps/files/src/components/FilesListVirtual.vue @@ -58,9 +58,10 @@ </template> <script lang="ts"> +import type { UserConfig } from '../types.ts' import type { Node as NcNode } from '@nextcloud/files' import type { ComponentPublicInstance, PropType } from 'vue' -import type { UserConfig } from '../types' +import type { Location } from 'vue-router' import { getFileListHeaders, Folder, View, getFileActions, FileType } from '@nextcloud/files' import { showError } from '@nextcloud/dialogs' @@ -280,30 +281,45 @@ export default defineComponent({ * Handle opening a file (e.g. by ?openfile=true) * @param fileId File to open */ - handleOpenFile(fileId: number|null) { - if (fileId === null) { - return - } - + async handleOpenFile(fileId: number) { const node = this.nodes.find(n => n.fileid === fileId) as NcNode - if (node === undefined || node.type === FileType.Folder) { + if (node === undefined) { return } - logger.debug('Opening file ' + node.path, { node }) - this.openFileId = fileId - const defaultAction = getFileActions() - // Get only default actions (visible and hidden) - .filter(action => !!action?.default) - // Find actions that are either always enabled or enabled for the current node - .filter((action) => !action.enabled || action.enabled([node], this.currentView)) - // Sort enabled default actions by order - .sort((a, b) => (a.order || 0) - (b.order || 0)) - // Get the first one - .at(0) - // Some file types do not have a default action (e.g. they can only be downloaded) - // So if there is an enabled default action, so execute it - defaultAction?.exec(node, this.currentView, this.currentFolder.path) + if (node.type === FileType.File) { + const defaultAction = getFileActions() + // Get only default actions (visible and hidden) + .filter((action) => !!action?.default) + // Find actions that are either always enabled or enabled for the current node + .filter((action) => !action.enabled || action.enabled([node], this.currentView)) + .filter((action) => action.id !== 'download') + // Sort enabled default actions by order + .sort((a, b) => (a.order || 0) - (b.order || 0)) + // Get the first one + .at(0) + + // Some file types do not have a default action (e.g. they can only be downloaded) + // So if there is an enabled default action, so execute it + if (defaultAction) { + logger.debug('Opening file ' + node.path, { node }) + return await defaultAction.exec(node, this.currentView, this.currentFolder.path) + } + } + // The file is either a folder or has no default action other than downloading + // in this case we need to open the details instead and remove the route from the history + const query = this.$route.query + delete query.openfile + query.opendetails = '' + + logger.debug('Ignore `openfile` query and replacing with `opendetails` for ' + node.path, { node }) + await this.$router.replace({ + ...(this.$route as Location), + query, + }) + // Remove if we backport https://github.com/nextcloud/server/pull/49432 to Nextcloud 30 + // otherwise this will still set the correct URL and result in the same view with this + this.openSidebarForFile(this.fileId) }, onDragOver(event: DragEvent) { diff --git a/apps/files/src/router/router.ts b/apps/files/src/router/router.ts index de81755d234..13e74c26451 100644 --- a/apps/files/src/router/router.ts +++ b/apps/files/src/router/router.ts @@ -3,20 +3,41 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ import type { RawLocation, Route } from 'vue-router' -import type { ErrorHandler } from 'vue-router/types/router.d.ts' - import { generateUrl } from '@nextcloud/router' import queryString from 'query-string' -import Router from 'vue-router' +import Router, { isNavigationFailure, NavigationFailureType } from 'vue-router' import Vue from 'vue' +import logger from '../logger' Vue.use(Router) // Prevent router from throwing errors when we're already on the page we're trying to go to -const originalPush = Router.prototype.push as (to, onComplete?, onAbort?) => Promise<Route> -Router.prototype.push = function push(to: RawLocation, onComplete?: ((route: Route) => void) | undefined, onAbort?: ErrorHandler | undefined): Promise<Route> { - if (onComplete || onAbort) return originalPush.call(this, to, onComplete, onAbort) - return originalPush.call(this, to).catch(err => err) +const originalPush = Router.prototype.push +Router.prototype.push = (function(this: Router, ...args: Parameters<typeof originalPush>) { + if (args.length > 1) { + return originalPush.call(this, ...args) + } + return originalPush.call<Router, [RawLocation], Promise<Route>>(this, args[0]).catch(ignoreDuplicateNavigation) +}) as typeof originalPush + +const originalReplace = Router.prototype.replace +Router.prototype.replace = (function(this: Router, ...args: Parameters<typeof originalReplace>) { + if (args.length > 1) { + return originalReplace.call(this, ...args) + } + return originalReplace.call<Router, [RawLocation], Promise<Route>>(this, args[0]).catch(ignoreDuplicateNavigation) +}) as typeof originalReplace + +/** + * Ignore duplicated-navigation error but forward real exceptions + * @param error The thrown error + */ +function ignoreDuplicateNavigation(error: unknown): void { + if (isNavigationFailure(error, NavigationFailureType.duplicated)) { + logger.debug('Ignoring duplicated navigation from vue-router', { error }) + } else { + throw error + } } const router = new Router({ |