Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/files/src/components/FileEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ export default defineComponent({
return
}

this.defaultFileAction?.exec(this.source, this.currentView, this.currentDir)
this.defaultFileAction?.exec(this.source, this.fileActionView, this.currentDir)
},
},
})
Expand Down
21 changes: 10 additions & 11 deletions apps/files/src/components/FileEntry/FileEntryName.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,15 @@ import type { PropType } from 'vue'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { FileType, NodeStatus } from '@nextcloud/files'
import { translate as t } from '@nextcloud/l10n'
import { defineComponent, inject } from 'vue'
import { defineComponent, inject, unref } from 'vue'

import NcTextField from '@nextcloud/vue/components/NcTextField'

import { getFilenameValidity } from '../../utils/filenameValidity.ts'
import { useFileListWidth } from '../../composables/useFileListWidth.ts'
import { useNavigation } from '../../composables/useNavigation.ts'
import { useRenamingStore } from '../../store/renaming.ts'
import { useRouteParameters } from '../../composables/useRouteParameters.ts'
import { useUserConfigStore } from '../../store/userconfig.ts'
import { useActiveStore } from '../../store/active.ts'
import logger from '../../logger.ts'

export default defineComponent({
Expand Down Expand Up @@ -91,19 +90,16 @@ export default defineComponent({
},

setup() {
// The file list is guaranteed to be only shown with active view - thus we can set the `loaded` flag
const { currentView } = useNavigation(true)
const { directory } = useRouteParameters()
const filesListWidth = useFileListWidth()
const renamingStore = useRenamingStore()
const userConfigStore = useUserConfigStore()
const { activeView } = useActiveStore()

const defaultFileAction = inject<FileAction | undefined>('defaultFileAction')
const defaultFileAction = inject<{ value: FileAction | undefined } | FileAction | undefined>('defaultFileAction')

return {
currentView,
activeView,
defaultFileAction,
directory,
filesListWidth,

renamingStore,
Expand Down Expand Up @@ -145,8 +141,11 @@ export default defineComponent({
}
}

if (this.defaultFileAction) {
const displayName = this.defaultFileAction.displayName([this.source], this.currentView)
const defaultFileAction = unref(this.defaultFileAction)
const view = this.activeView

if (defaultFileAction && view) {
const displayName = defaultFileAction.displayName([this.source], view)
return {
is: 'button',
params: {
Expand Down
63 changes: 57 additions & 6 deletions apps/files/src/components/FileEntryMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
import type { PropType } from 'vue'
import type { FileSource } from '../types.ts'

import { FileType, Folder, getFileActions, File as NcFile, Node, NodeStatus, Permission } from '@nextcloud/files'
import { FileType, Folder, getFileActions, File as NcFile, Node, NodeStatus, Permission, type View } from '@nextcloud/files'
import { t } from '@nextcloud/l10n'
import { extname } from '@nextcloud/paths'
import { isPublicShare } from '@nextcloud/sharing/public'
import { generateUrl } from '@nextcloud/router'
import { vOnClickOutside } from '@vueuse/components'
import { storeToRefs } from 'pinia'
import Vue, { computed, defineComponent } from 'vue'

import { action as sidebarAction } from '../actions/sidebarAction.ts'
import { dataTransferToFileTree, onDropExternalFiles, onDropInternalFiles } from '../services/DropService.ts'
import { useActiveStore } from '../store/active.ts'
import { getDragAndDropPreview } from '../utils/dragUtils.ts'
import { hashCode } from '../utils/hashUtils.ts'
import { isDownloadable } from '../utils/permissions.ts'
Expand Down Expand Up @@ -56,6 +58,14 @@ export default defineComponent({
}
},

setup() {
const { activeView } = storeToRefs(useActiveStore())

return {
activeView,
}
},

data() {
return {
dragover: false,
Expand Down Expand Up @@ -125,6 +135,12 @@ export default defineComponent({
return String(this.fileid) === String(this.currentFileId)
},

isSourceFolder(): boolean {
return this.source.type === FileType.Folder
|| this.source.type === 'folder'
|| this.source.mime === 'httpd/unix-directory'
},

/**
* Check if the source is in a failed state after an API request
*/
Expand Down Expand Up @@ -226,6 +242,10 @@ export default defineComponent({
}
},

fileActionView(): View {
return this.activeView ?? this.currentView
},

/**
* Sorted actions that are enabled for this node
*/
Expand All @@ -243,7 +263,7 @@ export default defineComponent({
// In case something goes wrong, since we don't want to break
// the entire list, we filter out actions that throw an error.
try {
return action.enabled([this.source], this.currentView)
return action.enabled([this.source], this.fileActionView)
} catch (error) {
logger.error('Error while checking action', { action, error })
return false
Expand All @@ -253,7 +273,14 @@ export default defineComponent({
},

defaultFileAction() {
return this.enabledFileActions.find((action) => action.default !== undefined)
const defaultAction = this.enabledFileActions.find((action) => action.default !== undefined)

// Folders must open, not download
if (this.isSourceFolder && defaultAction?.id === 'download') {
return this.enabledFileActions.find((action) => action.id === 'open-folder') ?? defaultAction
}

return defaultAction
},
},

Expand Down Expand Up @@ -298,6 +325,21 @@ export default defineComponent({
this.openedMenu = false
},

openFolderNode(): boolean {
const view = this.fileActionView
if (!view?.id || !this.source.fileid) {
logger.warn('Cannot open folder, missing view or fileid', { view, source: this.source })
return false
}

window.OCP.Files.Router.goToRoute(
null,
{ view: view.id, fileid: String(this.source.fileid) },
{ dir: this.source.path },
)
return true
},

// Open the actions menu on right click
onRightClick(event) {
// If already opened, fallback to default browser
Expand Down Expand Up @@ -356,6 +398,15 @@ export default defineComponent({
// if ctrl+click / cmd+click (MacOS uses the meta key) or middle mouse button (button & 4), open in new tab
// also if there is no default action use this as a fallback
const metaKeyPressed = event.ctrlKey || event.metaKey || event.button === 1

// Folders must navigate in the files app, never download
if (!metaKeyPressed && this.isSourceFolder) {
event.preventDefault()
event.stopPropagation()
this.openFolderNode()
return
}

if (metaKeyPressed || !this.defaultFileAction) {
// If no download permission, then we can not allow to download (direct link) the files
if (!isDownloadable(this.source)) {
Expand All @@ -377,14 +428,14 @@ export default defineComponent({
event.preventDefault()
event.stopPropagation()
// Execute the first default action if any
this.defaultFileAction.exec(this.source, this.currentView, this.currentDir)
this.defaultFileAction.exec(this.source, this.fileActionView, this.currentDir)
},

openDetailsIfAvailable(event) {
event.preventDefault()
event.stopPropagation()
if (sidebarAction?.enabled?.([this.source], this.currentView)) {
sidebarAction.exec(this.source, this.currentView, this.currentDir)
if (sidebarAction?.enabled?.([this.source], this.fileActionView)) {
sidebarAction.exec(this.source, this.fileActionView, this.currentDir)
}
},

Expand Down
Loading