@@ -7,18 +7,20 @@ import type { PropType } from 'vue'
77import type { FileSource } from '../types.ts'
88
99import { openConflictPicker } from '@nextcloud/dialogs'
10- import { FileType , Folder , getFileActions , File as NcFile , Node , NodeStatus , Permission } from '@nextcloud/files'
10+ import { FileType , Folder , getFileActions , File as NcFile , Node , NodeStatus , Permission , type View } from '@nextcloud/files'
1111import { t } from '@nextcloud/l10n'
1212import { extname } from '@nextcloud/paths'
1313import { isPublicShare } from '@nextcloud/sharing/public'
1414import { generateUrl } from '@nextcloud/router'
1515import { getConflicts , getUploader } from '@nextcloud/upload'
1616import { vOnClickOutside } from '@vueuse/components'
1717import { relative } from 'path'
18+ import { storeToRefs } from 'pinia'
1819import Vue , { computed , defineComponent } from 'vue'
1920
2021import { action as sidebarAction } from '../actions/sidebarAction.ts'
2122import { onDropInternalFiles } from '../services/DropService.ts'
23+ import { useActiveStore } from '../store/active.ts'
2224import { getDragAndDropPreview } from '../utils/dragUtils.ts'
2325import { hashCode } from '../utils/hashUtils.ts'
2426import { isDownloadable } from '../utils/permissions.ts'
@@ -59,6 +61,14 @@ export default defineComponent({
5961 }
6062 } ,
6163
64+ setup ( ) {
65+ const { activeView } = storeToRefs ( useActiveStore ( ) )
66+
67+ return {
68+ activeView,
69+ }
70+ } ,
71+
6272 data ( ) {
6373 return {
6474 dragover : false ,
@@ -128,6 +138,12 @@ export default defineComponent({
128138 return String ( this . fileid ) === String ( this . currentFileId )
129139 } ,
130140
141+ isSourceFolder ( ) : boolean {
142+ return this . source . type === FileType . Folder
143+ || this . source . type === 'folder'
144+ || this . source . mime === 'httpd/unix-directory'
145+ } ,
146+
131147 /**
132148 * Check if the source is in a failed state after an API request
133149 */
@@ -229,6 +245,10 @@ export default defineComponent({
229245 }
230246 } ,
231247
248+ fileActionView ( ) : View {
249+ return this . activeView ?? this . currentView
250+ } ,
251+
232252 /**
233253 * Sorted actions that are enabled for this node
234254 */
@@ -246,7 +266,7 @@ export default defineComponent({
246266 // In case something goes wrong, since we don't want to break
247267 // the entire list, we filter out actions that throw an error.
248268 try {
249- return action . enabled ( [ this . source ] , this . currentView )
269+ return action . enabled ( [ this . source ] , this . fileActionView )
250270 } catch ( error ) {
251271 logger . error ( 'Error while checking action' , { action, error } )
252272 return false
@@ -256,7 +276,14 @@ export default defineComponent({
256276 } ,
257277
258278 defaultFileAction ( ) {
259- return this . enabledFileActions . find ( ( action ) => action . default !== undefined )
279+ const defaultAction = this . enabledFileActions . find ( ( action ) => action . default !== undefined )
280+
281+ // Folders must open, not download
282+ if ( this . isSourceFolder && defaultAction ?. id === 'download' ) {
283+ return this . enabledFileActions . find ( ( action ) => action . id === 'open-folder' ) ?? defaultAction
284+ }
285+
286+ return defaultAction
260287 } ,
261288 } ,
262289
@@ -301,6 +328,21 @@ export default defineComponent({
301328 this . openedMenu = false
302329 } ,
303330
331+ openFolderNode ( ) : boolean {
332+ const view = this . fileActionView
333+ if ( ! view ?. id || ! this . source . fileid ) {
334+ logger . warn ( 'Cannot open folder, missing view or fileid' , { view, source : this . source } )
335+ return false
336+ }
337+
338+ window . OCP . Files . Router . goToRoute (
339+ null ,
340+ { view : view . id , fileid : String ( this . source . fileid ) } ,
341+ { dir : this . source . path } ,
342+ )
343+ return true
344+ } ,
345+
304346 // Open the actions menu on right click
305347 onRightClick ( event ) {
306348 // If already opened, fallback to default browser
@@ -359,6 +401,15 @@ export default defineComponent({
359401 // if ctrl+click / cmd+click (MacOS uses the meta key) or middle mouse button (button & 4), open in new tab
360402 // also if there is no default action use this as a fallback
361403 const metaKeyPressed = event . ctrlKey || event . metaKey || event . button === 1
404+
405+ // Folders must navigate in the files app, never download
406+ if ( ! metaKeyPressed && this . isSourceFolder ) {
407+ event . preventDefault ( )
408+ event . stopPropagation ( )
409+ this . openFolderNode ( )
410+ return
411+ }
412+
362413 if ( metaKeyPressed || ! this . defaultFileAction ) {
363414 // If no download permission, then we can not allow to download (direct link) the files
364415 if ( ! isDownloadable ( this . source ) ) {
@@ -380,14 +431,14 @@ export default defineComponent({
380431 event . preventDefault ( )
381432 event . stopPropagation ( )
382433 // Execute the first default action if any
383- this . defaultFileAction . exec ( this . source , this . currentView , this . currentDir )
434+ this . defaultFileAction . exec ( this . source , this . fileActionView , this . currentDir )
384435 } ,
385436
386437 openDetailsIfAvailable ( event ) {
387438 event . preventDefault ( )
388439 event . stopPropagation ( )
389- if ( sidebarAction ?. enabled ?.( [ this . source ] , this . currentView ) ) {
390- sidebarAction . exec ( this . source , this . currentView , this . currentDir )
440+ if ( sidebarAction ?. enabled ?.( [ this . source ] , this . fileActionView ) ) {
441+ sidebarAction . exec ( this . source , this . fileActionView , this . currentDir )
391442 }
392443 } ,
393444
0 commit comments