diff --git a/apps/files/src/actions/openFolderAction.ts b/apps/files/src/actions/openFolderAction.ts index 8719f7a93fb04..99916e9ab896e 100644 --- a/apps/files/src/actions/openFolderAction.ts +++ b/apps/files/src/actions/openFolderAction.ts @@ -2,10 +2,12 @@ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { Permission, Node, FileType, View, FileAction, DefaultType } from '@nextcloud/files' +import { Permission, Node, FileType, View, FileAction, DefaultType, Folder } from '@nextcloud/files' import { translate as t } from '@nextcloud/l10n' import FolderSvg from '@mdi/svg/svg/folder.svg?raw' +import { folderTreeId, getFolderTreeViewId } from '../services/FolderTree.ts' + export const action = new FileAction({ id: 'open-folder', displayName(files: Node[]) { diff --git a/apps/files/src/components/BreadCrumbs.vue b/apps/files/src/components/BreadCrumbs.vue index 169bc504ab90a..4527c52c72169 100644 --- a/apps/files/src/components/BreadCrumbs.vue +++ b/apps/files/src/components/BreadCrumbs.vue @@ -109,12 +109,11 @@ export default defineComponent({ return this.dirs.map((dir: string, index: number) => { const source = this.getFileSourceFromPath(dir) const node: Node | undefined = source ? this.getNodeFromSource(source) : undefined - const to = { ...this.$route, params: { node: node?.fileid }, query: { dir } } return { dir, exact: true, name: this.getDirDisplayName(dir), - to, + to: this.getTo(dir, node), // disable drop on current directory disableDrop: index === this.dirs.length - 1, } @@ -163,6 +162,20 @@ export default defineComponent({ return node?.displayname || basename(path) }, + getTo(dir: string, node?: Node): Record { + if (node === undefined) { + return { + ...this.$route, + query: { dir }, + } + } + return { + ...this.$route, + params: { fileid: String(node.fileid) }, + query: { dir: node.path }, + } + }, + onClick(to) { if (to?.query?.dir === this.$route.query.dir) { this.$emit('reload') diff --git a/apps/files/src/components/FileEntry/FileEntryName.vue b/apps/files/src/components/FileEntry/FileEntryName.vue index be491db016f5c..2a816f7344940 100644 --- a/apps/files/src/components/FileEntry/FileEntryName.vue +++ b/apps/files/src/components/FileEntry/FileEntryName.vue @@ -45,6 +45,7 @@ import { showError, showSuccess } from '@nextcloud/dialogs' import { emit } from '@nextcloud/event-bus' import { FileType, NodeStatus, Permission } from '@nextcloud/files' import { translate as t } from '@nextcloud/l10n' +import { dirname } from '@nextcloud/paths' import { defineComponent } from 'vue' import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js' @@ -275,6 +276,10 @@ export default defineComponent({ // Success 🎉 emit('files:node:updated', this.source) emit('files:node:renamed', this.source) + emit('files:node:moved', { + node: this.source, + oldSource: `${dirname(this.source.source)}/${oldName}`, + }) showSuccess(t('files', 'Renamed "{oldName}" to "{newName}"', { oldName, newName })) // Reset the renaming store diff --git a/apps/files/src/components/FilesNavigationItem.vue b/apps/files/src/components/FilesNavigationItem.vue new file mode 100644 index 0000000000000..7550780395778 --- /dev/null +++ b/apps/files/src/components/FilesNavigationItem.vue @@ -0,0 +1,170 @@ + + + + + diff --git a/apps/files/src/composables/useNavigation.ts b/apps/files/src/composables/useNavigation.ts index f410aec895fa8..2fff5633e230e 100644 --- a/apps/files/src/composables/useNavigation.ts +++ b/apps/files/src/composables/useNavigation.ts @@ -3,9 +3,10 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ import type { View } from '@nextcloud/files' +import type { ShallowRef } from 'vue' import { getNavigation } from '@nextcloud/files' -import { onMounted, onUnmounted, shallowRef, type ShallowRef } from 'vue' +import { onMounted, onUnmounted, shallowRef, triggerRef } from 'vue' /** * Composable to get the currently active files view from the files navigation @@ -28,6 +29,7 @@ export function useNavigation() { */ function onUpdateViews() { views.value = navigation.views + triggerRef(views) } onMounted(() => { diff --git a/apps/files/src/eventbus.d.ts b/apps/files/src/eventbus.d.ts index db90c40eeaef2..e1fd8c73b4b40 100644 --- a/apps/files/src/eventbus.d.ts +++ b/apps/files/src/eventbus.d.ts @@ -11,7 +11,12 @@ declare module '@nextcloud/event-bus' { 'files:favorites:removed': Node 'files:favorites:added': Node + + 'files:node:created': Node + 'files:node:deleted': Node + 'files:node:updated': Node 'files:node:renamed': Node + 'files:node:moved': { node: Node, oldSource: string } 'files:filter:added': IFileListFilter 'files:filter:removed': string diff --git a/apps/files/src/init.ts b/apps/files/src/init.ts index 4266453a4a309..846f1049d5ac5 100644 --- a/apps/files/src/init.ts +++ b/apps/files/src/init.ts @@ -27,6 +27,7 @@ import registerFavoritesView from './views/favorites' import registerRecentView from './views/recent' import registerPersonalFilesView from './views/personal-files' import registerFilesView from './views/files' +import { registerFolderTreeView } from './views/folderTree.ts' import registerPreviewServiceWorker from './services/ServiceWorker.js' import { initLivePhotos } from './services/LivePhotos' @@ -53,6 +54,7 @@ registerFavoritesView() registerFilesView() registerRecentView() registerPersonalFilesView() +registerFolderTreeView() // Register file list filters registerHiddenFilesFilter() diff --git a/apps/files/src/services/FolderTree.ts b/apps/files/src/services/FolderTree.ts new file mode 100644 index 0000000000000..e48d0594638be --- /dev/null +++ b/apps/files/src/services/FolderTree.ts @@ -0,0 +1,65 @@ +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import type { ContentsWithRoot, Permission } from '@nextcloud/files' + +import { CancelablePromise } from 'cancelable-promise' +import { + davRemoteURL, + davRootPath, + Folder, +} from '@nextcloud/files' +import { getCurrentUser } from '@nextcloud/auth' +import { loadState } from '@nextcloud/initial-state' +import { dirname } from '@nextcloud/paths' + +import { getContents as getFiles } from './Files.ts' + +export const folderTreeId = 'folders' + +interface FolderTreeFolder { + fileid: number, + displayname: string, + owner: string, + path: string, + mountType: string, + mime: string, + size: number, + mtime: number, + crtime: number, + permissions: Permission, +} + +export const getFolders = (): Folder[] => { + return loadState('files', 'folderTreeFolders', []) + .map(folder => new Folder({ + id: folder.fileid, + displayname: folder.displayname, + owner: folder.owner, + source: `${davRemoteURL}/files/${getCurrentUser()?.uid}${folder.path}`, + attributes: { + 'mount-type': folder.mountType, + }, + mime: folder.mime, + size: folder.size, + mtime: new Date(folder.mtime * 1000), + crtime: new Date(folder.crtime * 1000), + permissions: folder.permissions, + root: davRootPath, + })) +} + +export const getContents = (path: string): CancelablePromise => getFiles(path) + +export const getFolderTreeViewId = (folder: Folder): string => { + return folder.encodedSource +} + +export const getFolderTreeParentId = (folder: Folder): string => { + if (folder.dirname === '/') { + return folderTreeId + } + return dirname(folder.encodedSource) +} diff --git a/apps/files/src/views/Navigation.vue b/apps/files/src/views/Navigation.vue index cfd170bd073e8..81cf22c707816 100644 --- a/apps/files/src/views/Navigation.vue +++ b/apps/files/src/views/Navigation.vue @@ -4,38 +4,11 @@ -->