aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorFerdinand Thiessen <opensource@fthiessen.de>2025-02-05 17:56:22 +0100
committerFerdinand Thiessen <opensource@fthiessen.de>2025-02-13 16:00:03 +0100
commit03e15b9297204c520cec58810361b8524dc70b66 (patch)
tree79efac2cd728555bb625dc875ec2ad1a725ce2fe /apps
parenta560c3e97d65ce5edcb55ad31387ee61711ee2a4 (diff)
downloadnextcloud-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.vue58
-rw-r--r--apps/files/src/router/router.ts35
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({