]> source.dussan.org Git - nextcloud-server.git/commitdiff
chore: use Navigation from `@nextcloud/files`
authorJohn Molakvoæ <skjnldsv@protonmail.com>
Fri, 18 Aug 2023 08:59:14 +0000 (10:59 +0200)
committerJohn Molakvoæ <skjnldsv@protonmail.com>
Wed, 23 Aug 2023 12:03:50 +0000 (14:03 +0200)
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
43 files changed:
apps/files/src/actions/deleteAction.spec.ts
apps/files/src/actions/deleteAction.ts
apps/files/src/actions/downloadAction.spec.ts
apps/files/src/actions/downloadAction.ts
apps/files/src/actions/editLocallyAction.spec.ts
apps/files/src/actions/favoriteAction.spec.ts
apps/files/src/actions/favoriteAction.ts
apps/files/src/actions/openFolderAction.spec.ts
apps/files/src/actions/openFolderAction.ts
apps/files/src/actions/openInFilesAction.spec.ts
apps/files/src/actions/renameAction.spec.ts
apps/files/src/actions/sidebarAction.spec.ts
apps/files/src/actions/sidebarAction.ts
apps/files/src/actions/viewInFolderAction.spec.ts
apps/files/src/actions/viewInFolderAction.ts
apps/files/src/components/FilesListHeader.vue
apps/files/src/main.ts
apps/files/src/mixins/filesSorting.ts
apps/files/src/services/Navigation.ts [deleted file]
apps/files/src/views/FilesList.vue
apps/files/src/views/Navigation.cy.ts
apps/files/src/views/Navigation.vue
apps/files/src/views/favorites.spec.ts
apps/files/src/views/favorites.ts
apps/files/src/views/files.ts
apps/files/src/views/recent.ts
apps/files_external/src/actions/enterCredentialsAction.spec.ts
apps/files_external/src/actions/openInFilesAction.spec.ts
apps/files_external/src/main.ts
apps/files_external/src/services/externalStorage.ts
apps/files_sharing/src/actions/acceptShareAction.spec.ts
apps/files_sharing/src/actions/acceptShareAction.ts
apps/files_sharing/src/actions/openInFilesAction.spec.ts
apps/files_sharing/src/actions/rejectShareAction.spec.ts
apps/files_sharing/src/actions/rejectShareAction.ts
apps/files_sharing/src/actions/restoreShareAction.spec.ts
apps/files_sharing/src/actions/restoreShareAction.ts
apps/files_sharing/src/services/SharingService.ts
apps/files_sharing/src/views/shares.spec.ts
apps/files_sharing/src/views/shares.ts
apps/files_trashbin/src/actions/restoreAction.ts
apps/files_trashbin/src/main.ts
apps/files_trashbin/src/services/trashbin.ts

index 8d99b195c3d3195f015d621cd1ce747aa38c2323..d7b7cd5307d1664a1fe04b8c7363f6bacd5d7997 100644 (file)
  */
 import { action } from './deleteAction'
 import { expect } from '@jest/globals'
-import { File, Folder, Permission } from '@nextcloud/files'
+import { File, Folder, Permission, View } from '@nextcloud/files'
 import { FileAction } from '../services/FileAction'
 import * as eventBus from '@nextcloud/event-bus'
 import axios from '@nextcloud/axios'
 import logger from '../logger'
-import type { Navigation } from '../services/Navigation'
 
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 const trashbinView = {
        id: 'trashbin',
        name: 'Trashbin',
-} as Navigation
+} as View
 
 describe('Delete action conditions tests', () => {
        test('Default values', () => {
index 52dd2f534915ca1a089dd337ec9a064921176637..6fd8fc467e321245771759310c61f19bccd30b2a 100644 (file)
  *
  */
 import { emit } from '@nextcloud/event-bus'
-import { Permission, Node } from '@nextcloud/files'
+import { Permission, Node, View } from '@nextcloud/files'
 import { translate as t } from '@nextcloud/l10n'
 import axios from '@nextcloud/axios'
 import TrashCanSvg from '@mdi/svg/svg/trash-can.svg?raw'
 
 import { registerFileAction, FileAction } from '../services/FileAction'
 import logger from '../logger.js'
-import type { Navigation } from '../services/Navigation'
 
 export const action = new FileAction({
        id: 'delete',
-       displayName(nodes: Node[], view: Navigation) {
+       displayName(nodes: Node[], view: View) {
                return view.id === 'trashbin'
                        ? t('files_trashbin', 'Delete permanently')
                        : t('files', 'Delete')
@@ -58,7 +57,7 @@ export const action = new FileAction({
                        return false
                }
        },
-       async execBatch(nodes: Node[], view: Navigation, dir: string) {
+       async execBatch(nodes: Node[], view: View, dir: string) {
                return Promise.all(nodes.map(node => this.exec(node, view, dir)))
        },
 
index abe099af3f89798f1fa6ca717b010868c281b346..35a4c0a277af649253c4487e92dd1b6908522195 100644 (file)
  */
 import { action } from './downloadAction'
 import { expect } from '@jest/globals'
-import { File, Folder, Permission } from '@nextcloud/files'
+import { File, Folder, Permission, View } from '@nextcloud/files'
 import { FileAction } from '../services/FileAction'
-import * as eventBus from '@nextcloud/event-bus'
-import axios from '@nextcloud/axios'
-import type { Navigation } from '../services/Navigation'
-import logger from '../logger'
 
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 describe('Download action conditions tests', () => {
        test('Default values', () => {
index 13fcde6106326411a5c94c9b420ef4147538885c..bf4e05ec8b0b55303ddcef2f0456299832899bf5 100644 (file)
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import { Permission, Node, FileType } from '@nextcloud/files'
+import { Permission, Node, FileType, View } from '@nextcloud/files'
 import { translate as t } from '@nextcloud/l10n'
 import ArrowDownSvg from '@mdi/svg/svg/arrow-down.svg?raw'
 
-import { registerFileAction, FileAction, DefaultType } from '../services/FileAction'
+import { registerFileAction, FileAction } from '../services/FileAction'
 import { generateUrl } from '@nextcloud/router'
-import type { Navigation } from '../services/Navigation'
 
 const triggerDownload = function(url: string) {
        const hiddenElement = document.createElement('a')
@@ -55,7 +54,7 @@ export const action = new FileAction({
                        .every(permission => (permission & Permission.READ) !== 0)
        },
 
-       async exec(node: Node, view: Navigation, dir: string) {
+       async exec(node: Node, view: View, dir: string) {
                if (node.type === FileType.Folder) {
                        downloadNodes(dir, [node])
                        return null
@@ -65,7 +64,7 @@ export const action = new FileAction({
                return null
        },
 
-       async execBatch(nodes: Node[], view: Navigation, dir: string) {
+       async execBatch(nodes: Node[], view: View, dir: string) {
                if (nodes.length === 1) {
                        this.exec(nodes[0], view, dir)
                        return [null]
index f40b3b558db4fe1a358737f68ae67bfb2f3d4ed6..3d2c31c468e1055cc2c50821defa6c050eaaaa6e 100644 (file)
  */
 import { action } from './editLocallyAction'
 import { expect } from '@jest/globals'
-import { File, Permission } from '@nextcloud/files'
-import { DefaultType, FileAction } from '../services/FileAction'
+import { File, Permission, View } from '@nextcloud/files'
+import { FileAction } from '../services/FileAction'
 import * as ncDialogs from '@nextcloud/dialogs'
 import axios from '@nextcloud/axios'
-import type { Navigation } from '../services/Navigation'
 
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 describe('Edit locally action conditions tests', () => {
        test('Default values', () => {
index 57957e67a33e350ad29a813f78b9460f8b39ba90..b24984dfdc26a3e05f06540a325bcceed2878d50 100644 (file)
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import * as favoriteAction from './favoriteAction'
 import { action } from './favoriteAction'
 import { expect } from '@jest/globals'
-import { File, Permission } from '@nextcloud/files'
+import { File, Permission, View } from '@nextcloud/files'
 import { FileAction } from '../services/FileAction'
 import * as eventBus from '@nextcloud/event-bus'
+import * as favoriteAction from './favoriteAction'
 import axios from '@nextcloud/axios'
-import type { Navigation } from '../services/Navigation'
 import logger from '../logger'
 
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 const favoriteView = {
        id: 'favorites',
        name: 'Favorites',
-} as Navigation
+} as View
 
 global.window.OC = {
        TAG_FAVORITE: '_$!<Favorite>!$_',
index a33aacf49473234869fd63bda6abc5e964bef6f6..7a067bb94074113755a8a6a1cee43ac3d8713867 100644 (file)
@@ -21,7 +21,7 @@
  */
 import { emit } from '@nextcloud/event-bus'
 import { generateUrl } from '@nextcloud/router'
-import { Permission, type Node } from '@nextcloud/files'
+import { Permission, type Node, View } from '@nextcloud/files'
 import { translate as t } from '@nextcloud/l10n'
 import axios from '@nextcloud/axios'
 import Vue from 'vue'
@@ -31,14 +31,13 @@ import StarSvg from '@mdi/svg/svg/star.svg?raw'
 
 import { registerFileAction, FileAction } from '../services/FileAction'
 import logger from '../logger.js'
-import type { Navigation } from '../services/Navigation'
 
 // If any of the nodes is not favorited, we display the favorite action.
 const shouldFavorite = (nodes: Node[]): boolean => {
        return nodes.some(node => node.attributes.favorite !== 1)
 }
 
-export const favoriteNode = async (node: Node, view: Navigation, willFavorite: boolean): Promise<boolean> => {
+export const favoriteNode = async (node: Node, view: View, willFavorite: boolean): Promise<boolean> => {
        try {
                // TODO: migrate to webdav tags plugin
                const url = generateUrl('/apps/files/api/v1/files') + node.path
@@ -92,11 +91,11 @@ export const action = new FileAction({
                        && nodes.every(node => node.permissions !== Permission.NONE)
        },
 
-       async exec(node: Node, view: Navigation) {
+       async exec(node: Node, view: View) {
                const willFavorite = shouldFavorite([node])
                return await favoriteNode(node, view, willFavorite)
        },
-       async execBatch(nodes: Node[], view: Navigation) {
+       async execBatch(nodes: Node[], view: View) {
                const willFavorite = shouldFavorite(nodes)
                return Promise.all(nodes.map(async node => await favoriteNode(node, view, willFavorite)))
        },
index 49fc9a9a63ac5d9354c92ab70d268940b02b9dc4..ff72f10b4d7edf6cb0abe897fb7763437399627b 100644 (file)
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import type { Navigation } from '../services/Navigation'
-
 import { expect } from '@jest/globals'
-import { File, Folder, Node, Permission } from '@nextcloud/files'
+import { File, Folder, Node, Permission, View } from '@nextcloud/files'
 
 import { action } from './openFolderAction'
 import { DefaultType, FileAction } from '../services/FileAction'
@@ -30,7 +28,7 @@ import { DefaultType, FileAction } from '../services/FileAction'
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 describe('Open folder action conditions tests', () => {
        test('Default values', () => {
index c0e03b20af0a2ea4f96349e7110f1df090160488..0d28792f15e2cc7e5320f20fb727c0e5331490e0 100644 (file)
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import { Permission, Node, FileType } from '@nextcloud/files'
+import { Permission, Node, FileType, View } from '@nextcloud/files'
 import { translate as t } from '@nextcloud/l10n'
 import FolderSvg from '@mdi/svg/svg/folder.svg?raw'
 
-import type { Navigation } from '../services/Navigation'
 import { join } from 'path'
 import { registerFileAction, FileAction, DefaultType } from '../services/FileAction'
 
@@ -52,7 +51,7 @@ export const action = new FileAction({
                        && (node.permissions & Permission.READ) !== 0
        },
 
-       async exec(node: Node, view: Navigation, dir: string) {
+       async exec(node: Node, view: View, dir: string) {
                if (!node || node.type !== FileType.Folder) {
                        return false
                }
index 4fc402c73a832cd31527f278d367725f9df6f341..2097095c9ef955bf536064c677def63ec3b16696 100644 (file)
  */
 import { action } from './openInFilesAction'
 import { expect } from '@jest/globals'
-import { File, Folder, Permission } from '@nextcloud/files'
+import { File, Folder, Permission, View } from '@nextcloud/files'
 import { DefaultType, FileAction } from '../../../files/src/services/FileAction'
-import type { Navigation } from '../../../files/src/services/Navigation'
 
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 const recentView = {
        id: 'recent',
        name: 'Recent',
-} as Navigation
+} as View
 
 describe('Open in files action conditions tests', () => {
        test('Default values', () => {
index c4d5d45cde9b9b4a47d44766d03bc47168708829..8e76bea4b84fd29664e9414dbddc96ade84cfd47 100644 (file)
  */
 import { action } from './renameAction'
 import { expect } from '@jest/globals'
-import { File, Permission } from '@nextcloud/files'
+import { File, Permission, View } from '@nextcloud/files'
 import { FileAction } from '../services/FileAction'
 import * as eventBus from '@nextcloud/event-bus'
-import type { Navigation } from '../services/Navigation'
 
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 describe('Rename action conditions tests', () => {
        test('Default values', () => {
index 6b33667d1dd5e3023c0ce19d01674b5438e95e78..1fb319599447272a337069d4c8f7014a1cce78b5 100644 (file)
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import type { Navigation } from '../services/Navigation'
-
 import { expect } from '@jest/globals'
-import { File, Permission } from '@nextcloud/files'
+import { File, Permission, View } from '@nextcloud/files'
 
 import { action } from './sidebarAction'
 import { FileAction } from '../services/FileAction'
@@ -31,7 +29,7 @@ import logger from '../logger'
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 describe('Open sidebar action conditions tests', () => {
        test('Default values', () => {
index 849cf78368dff5780d1cfc58391746ada60ccebe..52244d9912a318c808d3a3807aef7399cf50909f 100644 (file)
@@ -19,9 +19,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import type { Navigation } from '../services/Navigation'
-
-import { Permission, type Node } from '@nextcloud/files'
+import { Permission, type Node, View } from '@nextcloud/files'
 import { translate as t } from '@nextcloud/l10n'
 import InformationSvg from '@mdi/svg/svg/information-variant.svg?raw'
 
@@ -54,7 +52,7 @@ export const action = new FileAction({
                return (nodes[0].root?.startsWith('/files/') && nodes[0].permissions !== Permission.NONE) ?? false
        },
 
-       async exec(node: Node, view: Navigation) {
+       async exec(node: Node, view: View) {
                try {
                        // TODO: migrate Sidebar to use a Node instead
                        await window.OCA.Files.Sidebar.open(node.path)
index 7d61fa4298d29a32128fcfc51f2948fce1e15789..c26eb52e40052d3fd568f1f6c6ce915555baa5d1 100644 (file)
  */
 import { action } from './viewInFolderAction'
 import { expect } from '@jest/globals'
-import { File, Folder, Node, Permission } from '@nextcloud/files'
+import { File, Folder, Node, Permission, View } from '@nextcloud/files'
 import { FileAction } from '../services/FileAction'
-import type { Navigation } from '../services/Navigation'
 
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 describe('View in folder action conditions tests', () => {
        test('Default values', () => {
index f0c5d2485a3b3c3ca376e38d6ac14440c53a8a6a..c8abcbb72f14b5ae57c32ddc90bdd6dc567f3960 100644 (file)
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import { Node, FileType, Permission } from '@nextcloud/files'
+import { Node, FileType, Permission, View } from '@nextcloud/files'
 import { translate as t } from '@nextcloud/l10n'
 import FolderMoveSvg from '@mdi/svg/svg/folder-move.svg?raw'
 
-import type { Navigation } from '../services/Navigation'
-import { join } from 'path'
 import { registerFileAction, FileAction } from '../services/FileAction'
 
 export const action = new FileAction({
@@ -53,7 +51,7 @@ export const action = new FileAction({
                return node.type === FileType.File
        },
 
-       async exec(node: Node, view: Navigation, dir: string) {
+       async exec(node: Node, view: View, dir: string) {
                if (!node || node.type !== FileType.File) {
                        return false
                }
index 74dc224a39b7be02353bb8f8c8bb5b61ebd42a17..a1ad790da98c666d62ba6927b40f682ff7f72ae4 100644 (file)
@@ -50,7 +50,6 @@ export default {
        },
        computed: {
                enabled() {
-                       console.debug('Enabled', this.header.id)
                        return this.header.enabled(this.currentFolder, this.currentView)
                },
        },
index d0fb3922229138b0e129838c7e5206b06c7e861f..3094656ecc09b4b01b0597b0515a6829cc01ad9a 100644 (file)
@@ -10,12 +10,13 @@ import './actions/openInFilesAction.js'
 import './actions/renameAction'
 import './actions/sidebarAction'
 import './actions/viewInFolderAction'
+import './newMenu/newFolder'
 
 import Vue from 'vue'
 import { createPinia, PiniaVuePlugin } from 'pinia'
+import { getNavigation } from '@nextcloud/files'
 
 import FilesListView from './views/FilesList.vue'
-import { NavigationService } from './services/Navigation'
 import NavigationView from './views/Navigation.vue'
 import registerFavoritesView from './views/favorites'
 import registerRecentView from './views/recent'
@@ -47,8 +48,7 @@ Vue.use(PiniaVuePlugin)
 const pinia = createPinia()
 
 // Init Navigation Service
-const Navigation = new NavigationService()
-Object.assign(window.OCP.Files, { Navigation })
+const Navigation = getNavigation()
 Vue.prototype.$navigation = Navigation
 
 // Init Files App Settings Service
index e766ea631f301053363c0080361b8b77f1dbaf3d..2ec3d94d67e74e751575f83477b65fe9a242355b 100644 (file)
@@ -23,14 +23,14 @@ import Vue from 'vue'
 
 import { mapState } from 'pinia'
 import { useViewConfigStore } from '../store/viewConfig'
-import type { NavigationService, Navigation } from '../services/Navigation'
+import { Navigation, View } from '@nextcloud/files'
 
 export default Vue.extend({
        computed: {
                ...mapState(useViewConfigStore, ['getConfig', 'setSortingBy', 'toggleSortingDirection']),
 
-               currentView(): Navigation {
-                       return (this.$navigation as NavigationService).active as Navigation
+               currentView(): View {
+                       return (this.$navigation as Navigation).active as View
                },
 
                /**
diff --git a/apps/files/src/services/Navigation.ts b/apps/files/src/services/Navigation.ts
deleted file mode 100644 (file)
index 8f82127..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/**
- * @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @license AGPL-3.0-or-later
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-/* eslint-disable no-use-before-define */
-import type { Folder, Node } from '@nextcloud/files'
-import isSvg from 'is-svg'
-
-import logger from '../logger.js'
-
-export type ContentsWithRoot = {
-       folder: Folder,
-       contents: Node[]
-}
-
-export interface Column {
-       /** Unique column ID */
-       id: string
-       /** Translated column title */
-       title: string
-       /** The content of the cell. The element will be appended within */
-       render: (node: Node, view: Navigation) => HTMLElement
-       /** Function used to sort Nodes between them */
-       sort?: (nodeA: Node, nodeB: Node) => number
-       /**
-        * Custom summary of the column to display at the end of the list.
-        * Will not be displayed if  nothing is provided
-        */
-       summary?: (node: Node[], view: Navigation) => string
-}
-
-export interface Navigation {
-       /** Unique view ID */
-       id: string
-       /** Translated view name */
-       name: string
-       /** Translated accessible description of the view */
-       caption?: string
-
-       /** Translated title of the empty view */
-       emptyTitle?: string
-       /** Translated description of the empty view */
-       emptyCaption?: string
-
-       /**
-        * Method return the content of the  provided path
-        * This ideally should be a cancellable promise.
-        * promise.cancel(reason) will be called when the directory
-        * change and the promise is not resolved yet.
-        * You _must_ also return the current directory
-        * information alongside with its content.
-        */
-       getContents: (path: string) => Promise<ContentsWithRoot>
-       /** The view icon as an inline svg */
-       icon: string
-       /** The view order */
-       order: number
-
-       /**
-        * This view column(s). Name and actions are
-        * by default always included
-        */
-       columns?: Column[]
-       /** The empty view element to render your empty content into */
-       emptyView?: (div: HTMLDivElement) => void
-       /** The parent unique ID */
-       parent?: string
-       /** This view is sticky (sent at the bottom) */
-       sticky?: boolean
-
-       /**
-        * This view has children and is expanded or not,
-        * will be overridden by user config.
-        */
-       expanded?: boolean
-
-       /**
-        * Will be used as default if the user
-        * haven't customized their sorting column
-        */
-       defaultSortKey?: string
-}
-
-export class NavigationService {
-
-       private _views: Navigation[] = []
-       private _currentView: Navigation | null = null
-
-       constructor() {
-               logger.debug('Navigation service initialized')
-       }
-
-       register(view: Navigation) {
-               try {
-                       isValidNavigation(view)
-                       isUniqueNavigation(view, this._views)
-               } catch (e) {
-                       if (e instanceof Error) {
-                               logger.error(e.message, { view })
-                       }
-                       throw e
-               }
-
-               this._views.push(view)
-       }
-
-       remove(id: string) {
-               const index = this._views.findIndex(view => view.id === id)
-               if (index !== -1) {
-                       this._views.splice(index, 1)
-               }
-       }
-
-       get views(): Navigation[] {
-               return this._views
-       }
-
-       setActive(view: Navigation | null) {
-               this._currentView = view
-       }
-
-       get active(): Navigation | null {
-               return this._currentView
-       }
-
-}
-
-/**
- * Make sure the given view is unique
- * and not already registered.
- */
-const isUniqueNavigation = function(view: Navigation, views: Navigation[]): boolean {
-       if (views.find(search => search.id === view.id)) {
-               throw new Error(`Navigation id ${view.id} is already registered`)
-       }
-       return true
-}
-
-/**
- * Typescript cannot validate an interface.
- * Please keep in sync with the Navigation interface requirements.
- */
-const isValidNavigation = function(view: Navigation): boolean {
-       if (!view.id || typeof view.id !== 'string') {
-               throw new Error('Navigation id is required and must be a string')
-       }
-
-       if (!view.name || typeof view.name !== 'string') {
-               throw new Error('Navigation name is required and must be a string')
-       }
-
-       if (view.columns && view.columns.length > 0
-               && (!view.caption || typeof view.caption !== 'string')) {
-               throw new Error('Navigation caption is required for top-level views and must be a string')
-       }
-
-       if (!view.getContents || typeof view.getContents !== 'function') {
-               throw new Error('Navigation getContents is required and must be a function')
-       }
-
-       if (!view.icon || typeof view.icon !== 'string' || !isSvg(view.icon)) {
-               throw new Error('Navigation icon is required and must be a valid svg string')
-       }
-
-       if (!('order' in view) || typeof view.order !== 'number') {
-               throw new Error('Navigation order is required and must be a number')
-       }
-
-       // Optional properties
-       if (view.columns) {
-               view.columns.forEach(isValidColumn)
-       }
-
-       if (view.emptyView && typeof view.emptyView !== 'function') {
-               throw new Error('Navigation emptyView must be a function')
-       }
-
-       if (view.parent && typeof view.parent !== 'string') {
-               throw new Error('Navigation parent must be a string')
-       }
-
-       if ('sticky' in view && typeof view.sticky !== 'boolean') {
-               throw new Error('Navigation sticky must be a boolean')
-       }
-
-       if ('expanded' in view && typeof view.expanded !== 'boolean') {
-               throw new Error('Navigation expanded must be a boolean')
-       }
-
-       if (view.defaultSortKey && typeof view.defaultSortKey !== 'string') {
-               throw new Error('Navigation defaultSortKey must be a string')
-       }
-
-       return true
-}
-
-/**
- * Typescript cannot validate an interface.
- * Please keep in sync with the Column interface requirements.
- */
-const isValidColumn = function(column: Column): boolean {
-       if (!column.id || typeof column.id !== 'string') {
-               throw new Error('A column id is required')
-       }
-
-       if (!column.title || typeof column.title !== 'string') {
-               throw new Error('A column title is required')
-       }
-
-       if (!column.render || typeof column.render !== 'function') {
-               throw new Error('A render function is required')
-       }
-
-       // Optional properties
-       if (column.sort && typeof column.sort !== 'function') {
-               throw new Error('Column sortFunction must be a function')
-       }
-
-       if (column.summary && typeof column.summary !== 'function') {
-               throw new Error('Column summary must be a function')
-       }
-
-       return true
-}
index eb38d09e290a374c8a6965f42b6348d3330e9826..8aa93dd41a5ff285ceddf7241b4d18b0d6781ea8 100644 (file)
 
 <script lang="ts">
 import type { Route } from 'vue-router'
-import type { Navigation, ContentsWithRoot } from '../services/Navigation.ts'
 import type { UserConfig } from '../types.ts'
 
-import { Folder, Node } from '@nextcloud/files'
+import { Folder, Node, type View, type ContentsWithRoot } from '@nextcloud/files'
 import { join } from 'path'
 import { orderBy } from 'natural-orderby'
 import { translate } from '@nextcloud/l10n'
@@ -132,9 +131,9 @@ export default Vue.extend({
                        return this.userConfigStore.userConfig
                },
 
-               currentView(): Navigation {
+               currentView(): View {
                        return (this.$navigation.active
-                               || this.$navigation.views.find(view => view.id === 'files')) as Navigation
+                               || this.$navigation.views.find(view => view.id === 'files')) as View
                },
 
                /**
index a65016da2974ed888c18b6ba15fa2e50d4cbcaf5..a84a4927bb2e7ac9ae0c6247e12de4c03703f9d5 100644 (file)
@@ -2,13 +2,14 @@ import FolderSvg from '@mdi/svg/svg/folder.svg'
 import ShareSvg from '@mdi/svg/svg/share-variant.svg'
 import { createTestingPinia } from '@pinia/testing'
 
-import { NavigationService } from '../services/Navigation'
 import NavigationView from './Navigation.vue'
 import router from '../router/router'
 import { useViewConfigStore } from '../store/viewConfig'
+import { Folder, View, getNavigation } from '@nextcloud/files'
 
 describe('Navigation renders', () => {
-       const Navigation = new NavigationService() as NavigationService
+       delete window._nc_navigation
+       const Navigation = getNavigation()
 
        before(() => {
                cy.mockInitialState('files', 'storageStats', {
@@ -38,16 +39,17 @@ describe('Navigation renders', () => {
 })
 
 describe('Navigation API', () => {
-       const Navigation = new NavigationService() as NavigationService
+       delete window._nc_navigation
+       const Navigation = getNavigation()
 
        it('Check API entries rendering', () => {
-               Navigation.register({
+               Navigation.register(new View({
                        id: 'files',
                        name: 'Files',
-                       getContents: () => Promise.resolve(),
+                       getContents: async () => ({ folder: {} as Folder, contents: [] }),
                        icon: FolderSvg,
                        order: 1,
-               })
+               }))
 
                cy.mount(NavigationView, {
                        propsData: {
@@ -68,13 +70,13 @@ describe('Navigation API', () => {
        })
 
        it('Adds a new entry and render', () => {
-               Navigation.register({
+               Navigation.register(new View({
                        id: 'sharing',
                        name: 'Sharing',
-                       getContents: () => Promise.resolve(),
+                       getContents: async () => ({ folder: {} as Folder, contents: [] }),
                        icon: ShareSvg,
                        order: 2,
-               })
+               }))
 
                cy.mount(NavigationView, {
                        propsData: {
@@ -95,14 +97,14 @@ describe('Navigation API', () => {
        })
 
        it('Adds a new children, render and open menu', () => {
-               Navigation.register({
+               Navigation.register(new View({
                        id: 'sharingin',
                        name: 'Shared with me',
-                       getContents: () => Promise.resolve(),
+                       getContents: async () => ({ folder: {} as Folder, contents: [] }),
                        parent: 'sharing',
                        icon: ShareSvg,
                        order: 1,
-               })
+               }))
 
                cy.mount(NavigationView, {
                        propsData: {
@@ -142,19 +144,20 @@ describe('Navigation API', () => {
 
        it('Throws when adding a duplicate entry', () => {
                expect(() => {
-                       Navigation.register({
+                       Navigation.register(new View({
                                id: 'files',
                                name: 'Files',
-                               getContents: () => Promise.resolve(),
+                               getContents: async () => ({ folder: {} as Folder, contents: [] }),
                                icon: FolderSvg,
                                order: 1,
-                       })
-               }).to.throw('Navigation id files is already registered')
+                       }))
+               }).to.throw('View id files is already registered')
        })
 })
 
 describe('Quota rendering', () => {
-       const Navigation = new NavigationService()
+       delete window._nc_navigation
+       const Navigation = getNavigation()
 
        afterEach(() => cy.unmockInitialState())
 
index 9b1df413ccc69ef88ff25db9188effe1d0f5b999..7544c8991a08f32196a8e7ceda276eb7d0d74d3a 100644 (file)
@@ -83,7 +83,7 @@ import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js
 import { setPageHeading } from '../../../../core/src/OCP/accessibility.js'
 import { useViewConfigStore } from '../store/viewConfig.ts'
 import logger from '../logger.js'
-import type { NavigationService, Navigation } from '../services/Navigation.ts'
+import type { Navigation, View } from '@nextcloud/files'
 import NavigationQuota from '../components/NavigationQuota.vue'
 import SettingsModal from './Settings.vue'
 
@@ -125,15 +125,15 @@ export default {
                        return this.$route?.params?.view || 'files'
                },
 
-               currentView(): Navigation {
+               currentView(): View {
                        return this.views.find(view => view.id === this.currentViewId)
                },
 
-               views(): Navigation[] {
+               views(): View[] {
                        return this.Navigation.views
                },
 
-               parentViews(): Navigation[] {
+               parentViews(): View[] {
                        return this.views
                                // filter child views
                                .filter(view => !view.parent)
@@ -143,7 +143,7 @@ export default {
                                })
                },
 
-               childViews(): Navigation[] {
+               childViews(): View[] {
                        return this.views
                                // filter parent views
                                .filter(view => !!view.parent)
@@ -165,7 +165,7 @@ export default {
                                this.Navigation.setActive(view)
                                logger.debug('Navigation changed', { id: view.id, view })
 
-                               this.showView(view, oldView)
+                               this.showView(view)
                        }
                },
        },
@@ -178,7 +178,7 @@ export default {
        },
 
        methods: {
-               showView(view: Navigation) {
+               showView(view: View) {
                        // Closing any opened sidebar
                        window?.OCA?.Files?.Sidebar?.close?.()
                        this.Navigation.setActive(view)
@@ -190,7 +190,7 @@ export default {
                 * Expand/collapse a a view with children and permanently
                 * save this setting in the server.
                 */
-               onToggleExpand(view: Navigation) {
+               onToggleExpand(view: View) {
                        // Invert state
                        const isExpanded = this.isExpanded(view)
                        // Update the view expanded state, might not be necessary
@@ -202,7 +202,7 @@ export default {
                 * Check if a view is expanded by user config
                 * or fallback to the default value.
                 */
-               isExpanded(view: Navigation): boolean {
+               isExpanded(view: View): boolean {
                        return typeof this.viewConfigStore.getConfig(view.id)?.expanded === 'boolean'
                                ? this.viewConfigStore.getConfig(view.id).expanded === true
                                : view.expanded === true
@@ -211,7 +211,7 @@ export default {
                /**
                 * Generate the route to a view
                 */
-               generateToNavigation(view: Navigation) {
+               generateToNavigation(view: View) {
                        if (view.params) {
                                const { dir, fileid } = view.params
                                return { name: 'filelist', params: view.params, query: { dir, fileid } }
index b13401872443b6f6ea3edee62d339c575d7363d8..f9cf5031f5f0fa3ebbc1c0ced2b685abf5131983 100644 (file)
  */
 import { expect } from '@jest/globals'
 import * as initialState from '@nextcloud/initial-state'
-import { Folder } from '@nextcloud/files'
+import { Folder, getNavigation } from '@nextcloud/files'
 import { basename } from 'path'
 import * as eventBus from '@nextcloud/event-bus'
 
 import { action } from '../actions/favoriteAction'
 import * as favoritesService from '../services/Favorites'
-import { NavigationService } from '../services/Navigation'
 import registerFavoritesView from './favorites'
 
 jest.mock('webdav/dist/node/request.js', () => ({
@@ -41,8 +40,7 @@ global.window.OC = {
 describe('Favorites view definition', () => {
        let Navigation
        beforeEach(() => {
-               Navigation = new NavigationService()
-               window.OCP = { Files: { Navigation } }
+               Navigation = getNavigation()
        })
 
        afterAll(() => {
@@ -114,8 +112,7 @@ describe('Favorites view definition', () => {
 describe('Dynamic update of favourite folders', () => {
        let Navigation
        beforeEach(() => {
-               Navigation = new NavigationService()
-               window.OCP = { Files: { Navigation } }
+               Navigation = getNavigation()
        })
 
        afterAll(() => {
index 7485340a2fe727dfd84755f1fd00fe6830f14b67..738f9b19e6b5366fcc9a5a280c99f9bc15836450 100644 (file)
@@ -19,7 +19,6 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import type { Navigation, NavigationService } from '../services/Navigation'
 import { getLanguage, translate as t } from '@nextcloud/l10n'
 import FolderSvg from '@mdi/svg/svg/folder.svg?raw'
 import StarSvg from '@mdi/svg/svg/star.svg?raw'
@@ -28,12 +27,12 @@ import { basename } from 'path'
 import { getContents } from '../services/Favorites'
 import { hashCode } from '../utils/hashUtils'
 import { loadState } from '@nextcloud/initial-state'
-import { Node, FileType } from '@nextcloud/files'
+import { Node, FileType, View, getNavigation } from '@nextcloud/files'
 import { subscribe } from '@nextcloud/event-bus'
 import logger from '../logger'
 
-export const generateFolderView = function(folder: string, index = 0): Navigation {
-       return {
+export const generateFolderView = function(folder: string, index = 0): View {
+       return new View({
                id: generateIdFromPath(folder),
                name: basename(folder),
 
@@ -49,7 +48,7 @@ export const generateFolderView = function(folder: string, index = 0): Navigatio
                columns: [],
 
                getContents,
-       } as Navigation
+       })
 }
 
 export const generateIdFromPath = function(path: string): string {
@@ -59,10 +58,10 @@ export const generateIdFromPath = function(path: string): string {
 export default () => {
        // Load state in function for mock testing purposes
        const favoriteFolders = loadState<string[]>('files', 'favoriteFolders', [])
-       const favoriteFoldersViews = favoriteFolders.map((folder, index) => generateFolderView(folder, index))
+       const favoriteFoldersViews = favoriteFolders.map((folder, index) => generateFolderView(folder, index)) as View[]
 
-       const Navigation = window.OCP.Files.Navigation as NavigationService
-       Navigation.register({
+       const Navigation = getNavigation()
+       Navigation.register(new View({
                id: 'favorites',
                name: t('files', 'Favorites'),
                caption: t('files', 'List of favorites files and folders.'),
@@ -76,7 +75,7 @@ export default () => {
                columns: [],
 
                getContents,
-       } as Navigation)
+       }))
 
        favoriteFoldersViews.forEach(view => Navigation.register(view))
 
index baafc8572c25e8e9d9c3af6d4ff7ebbcf8cc9e19..a535481a061116c4b20242264f489f4c5d8b20f3 100644 (file)
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import type { NavigationService, Navigation } from '../services/Navigation'
-
 import { translate as t } from '@nextcloud/l10n'
 import FolderSvg from '@mdi/svg/svg/folder.svg?raw'
 
 import { getContents } from '../services/Files'
+import { View, getNavigation } from '@nextcloud/files'
 
 export default () => {
-       const Navigation = window.OCP.Files.Navigation as NavigationService
-       Navigation.register({
+       const Navigation = getNavigation()
+       Navigation.register(new View({
                id: 'files',
                name: t('files', 'All files'),
                caption: t('files', 'List of your files and folders.'),
@@ -37,5 +36,5 @@ export default () => {
                order: 0,
 
                getContents,
-       } as Navigation)
+       }))
 }
index 3e0c51184e4da164eae8b00a8c09327082b01d8e..08ae5db6f39d4f6475c5fed390b9b2091c3f314f 100644 (file)
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import type { NavigationService, Navigation } from '../services/Navigation'
-
 import { translate as t } from '@nextcloud/l10n'
 import HistorySvg from '@mdi/svg/svg/history.svg?raw'
 
 import { getContents } from '../services/Recent'
+import { View, getNavigation } from '@nextcloud/files'
 
 export default () => {
-       const Navigation = window.OCP.Files.Navigation as NavigationService
-       Navigation.register({
+       const Navigation = getNavigation()
+       Navigation.register(new View({
                id: 'recent',
                name: t('files', 'Recent'),
                caption: t('files', 'List of recently modified files and folders.'),
@@ -42,5 +41,5 @@ export default () => {
                defaultSortKey: 'mtime',
 
                getContents,
-       } as Navigation)
+       }))
 }
index 29e1fe31f0294901d16efd6b746e8488b85ec314..ef3a767365b75f57b1f99a490c883587345fa849 100644 (file)
  */
 import { action } from './enterCredentialsAction'
 import { expect } from '@jest/globals'
-import { File, Folder, Permission } from '@nextcloud/files'
+import { File, Folder, Permission, View } from '@nextcloud/files'
 import { DefaultType, FileAction } from '../../../files/src/services/FileAction'
-import type { Navigation } from '../../../files/src/services/Navigation'
 import type { StorageConfig } from '../services/externalStorage'
 import { STORAGE_STATUS } from '../utils/credentialsUtils'
 
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 const externalStorageView = {
        id: 'extstoragemounts',
        name: 'External storage',
-} as Navigation
+} as View
 
 describe('Enter credentials action conditions tests', () => {
        test('Default values', () => {
index 803bee8e096c24e94a87672b0db149bf6dce195c..4f25d2449b4856f6871d3b78c0880da224041fa0 100644 (file)
  */
 import { action } from './openInFilesAction'
 import { expect } from '@jest/globals'
-import { File, Folder, Permission } from '@nextcloud/files'
+import { Folder, Permission, View } from '@nextcloud/files'
 import { DefaultType, FileAction } from '../../../files/src/services/FileAction'
-import type { Navigation } from '../../../files/src/services/Navigation'
 import type { StorageConfig } from '../services/externalStorage'
 import { STORAGE_STATUS } from '../utils/credentialsUtils'
 
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 const externalStorageView = {
        id: 'extstoragemounts',
        name: 'External storage',
-} as Navigation
+} as View
 
 describe('Open in files action conditions tests', () => {
        test('Default values', () => {
index 250ad51e38f878954dc6da5c1fd127ae2a9cca27..c85dd371f5168dd929a439187b189d27056b44ee 100644 (file)
@@ -19,8 +19,6 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import type { NavigationService, Navigation } from '../../files/src/services/Navigation'
-
 import { translate as t } from '@nextcloud/l10n'
 import { loadState } from '@nextcloud/initial-state'
 import FolderNetworkSvg from '@mdi/svg/svg/folder-network.svg?raw'
@@ -29,11 +27,12 @@ import './actions/enterCredentialsAction'
 import './actions/inlineStorageCheckAction'
 import './actions/openInFilesAction'
 import { getContents } from './services/externalStorage'
+import { View, getNavigation, Column } from '@nextcloud/files'
 
 const allowUserMounting = loadState('files_external', 'allowUserMounting', false)
 
-const Navigation = window.OCP.Files.Navigation as NavigationService
-Navigation.register({
+const Navigation = getNavigation()
+Navigation.register(new View({
        id: 'extstoragemounts',
        name: t('files_external', 'External storage'),
        caption: t('files_external', 'List of external storage.'),
@@ -47,7 +46,7 @@ Navigation.register({
        order: 30,
 
        columns: [
-               {
+               new Column({
                        id: 'storage-type',
                        title: t('files_external', 'Storage type'),
                        render(node) {
@@ -56,8 +55,8 @@ Navigation.register({
                                span.textContent = backend
                                return span
                        },
-               },
-               {
+               }),
+               new Column({
                        id: 'scope',
                        title: t('files_external', 'Scope'),
                        render(node) {
@@ -69,8 +68,8 @@ Navigation.register({
                                span.textContent = scope
                                return span
                        },
-               },
+               }),
        ],
 
        getContents,
-} as Navigation)
+}))
index c84ad6bcc5b159dfef5d7c156beccd042c071fa5..95010c2b6a4a743d8b9785d2d35644e2d54c04c1 100644 (file)
  */
 // eslint-disable-next-line n/no-extraneous-import
 import type { AxiosResponse } from 'axios'
-import type { ContentsWithRoot } from '../../../files/src/services/Navigation'
 import type { OCSResponse } from '../../../files_sharing/src/services/SharingService'
 
-import { Folder, Permission } from '@nextcloud/files'
+import { Folder, Permission, type ContentsWithRoot } from '@nextcloud/files'
 import { generateOcsUrl, generateRemoteUrl, generateUrl } from '@nextcloud/router'
 import { getCurrentUser } from '@nextcloud/auth'
 import axios from '@nextcloud/axios'
index acef697b1aabeea0b0bb336f3a38afd7f4579ea5..7ad8a42a1a66f6adf1484175cf3e88aabc377a78 100644 (file)
  */
 import { action } from './acceptShareAction'
 import { expect } from '@jest/globals'
-import { File, Permission } from '@nextcloud/files'
+import { File, Permission, View } from '@nextcloud/files'
 import { FileAction } from '../../../files/src/services/FileAction'
 import * as eventBus from '@nextcloud/event-bus'
 import axios from '@nextcloud/axios'
-import type { Navigation } from '../../../files/src/services/Navigation'
 import '../main'
 
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 const pendingShareView = {
        id: 'pendingshares',
        name: 'Pending shares',
-} as Navigation
+} as View
 
 describe('Accept share action conditions tests', () => {
        test('Default values', () => {
index 4be69633122c0eda0152c9784570c215693a4e10..8bd8d6a5533eea08205ef8a66f0604bcb44508b6 100644 (file)
@@ -19,8 +19,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import type { Node } from '@nextcloud/files'
-import type { Navigation } from '../../../files/src/services/Navigation'
+import type { Node, View } from '@nextcloud/files'
 
 import { emit } from '@nextcloud/event-bus'
 import { generateOcsUrl } from '@nextcloud/router'
@@ -55,7 +54,7 @@ export const action = new FileAction({
                        return false
                }
        },
-       async execBatch(nodes: Node[], view: Navigation, dir: string) {
+       async execBatch(nodes: Node[], view: View, dir: string) {
                return Promise.all(nodes.map(node => this.exec(node, view, dir)))
        },
 
index 49d4e192d390201896565b035a28405449558bc4..2d723770ee91ad81cdb67aac97c9cd425f106d26 100644 (file)
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import type { Navigation } from '../../../files/src/services/Navigation'
-
 import { expect } from '@jest/globals'
-import { File, Permission } from '@nextcloud/files'
+import { File, Permission, View } from '@nextcloud/files'
 
 import '../main'
 import { action } from './openInFilesAction'
@@ -32,19 +30,19 @@ import { deletedSharesViewId, pendingSharesViewId, sharedWithOthersViewId, share
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 const validViews = [
        sharesViewId,
        sharedWithYouViewId,
        sharedWithOthersViewId,
        sharingByLinksViewId,
-].map(id => ({ id, name: id })) as Navigation[]
+].map(id => ({ id, name: id })) as View[]
 
 const invalidViews = [
        deletedSharesViewId,
        pendingSharesViewId,
-].map(id => ({ id, name: id })) as Navigation[]
+].map(id => ({ id, name: id })) as View[]
 
 describe('Open in files action conditions tests', () => {
        test('Default values', () => {
index a075b45eedb71ccf37e6c23478b9e7550ce9a735..bc666b7c081420becc55d248efc2a162208ff403 100644 (file)
  */
 import { action } from './rejectShareAction'
 import { expect } from '@jest/globals'
-import { File, Folder, Permission } from '@nextcloud/files'
+import { File, Folder, Permission, View } from '@nextcloud/files'
 import { FileAction } from '../../../files/src/services/FileAction'
 import * as eventBus from '@nextcloud/event-bus'
 import axios from '@nextcloud/axios'
-import type { Navigation } from '../../../files/src/services/Navigation'
 import '../main'
 
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 const pendingShareView = {
        id: 'pendingshares',
        name: 'Pending shares',
-} as Navigation
+} as View
 
 describe('Reject share action conditions tests', () => {
        test('Default values', () => {
index 44dd36abe55d9ed98e4b86f5311a56e822ea5af4..7fb04d3622757d15064c2e24cb48224551a5bcf1 100644 (file)
@@ -19,8 +19,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import type { Node } from '@nextcloud/files'
-import type { Navigation } from '../../../files/src/services/Navigation'
+import type { Node, View } from '@nextcloud/files'
 
 import { emit } from '@nextcloud/event-bus'
 import { generateOcsUrl } from '@nextcloud/router'
@@ -72,7 +71,7 @@ export const action = new FileAction({
                        return false
                }
        },
-       async execBatch(nodes: Node[], view: Navigation, dir: string) {
+       async execBatch(nodes: Node[], view: View, dir: string) {
                return Promise.all(nodes.map(node => this.exec(node, view, dir)))
        },
 
index 6b87d0549cfe4bb6b4976a57294670e5261114ee..2c37dd838577e830b34a6f714b7b797a0691df30 100644 (file)
  */
 import { action } from './restoreShareAction'
 import { expect } from '@jest/globals'
-import { File, Permission } from '@nextcloud/files'
+import { File, Permission, View } from '@nextcloud/files'
 import { FileAction } from '../../../files/src/services/FileAction'
 import * as eventBus from '@nextcloud/event-bus'
 import axios from '@nextcloud/axios'
-import type { Navigation } from '../../../files/src/services/Navigation'
 import '../main'
 
 const view = {
        id: 'files',
        name: 'Files',
-} as Navigation
+} as View
 
 const deletedShareView = {
        id: 'deletedshares',
        name: 'Deleted shares',
-} as Navigation
+} as View
 
 describe('Restore share action conditions tests', () => {
        test('Default values', () => {
index 6c43b0cfb37c6f49644d59a3e4db31045ca3b43e..d1b67f10b08713d9a35923d446eb428ece08c7cb 100644 (file)
@@ -19,8 +19,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import type { Node } from '@nextcloud/files'
-import type { Navigation } from '../../../files/src/services/Navigation'
+import type { Node, View } from '@nextcloud/files'
 
 import { emit } from '@nextcloud/event-bus'
 import { generateOcsUrl } from '@nextcloud/router'
@@ -54,7 +53,7 @@ export const action = new FileAction({
                        return false
                }
        },
-       async execBatch(nodes: Node[], view: Navigation, dir: string) {
+       async execBatch(nodes: Node[], view: View, dir: string) {
                return Promise.all(nodes.map(node => this.exec(node, view, dir)))
        },
 
index 5f288ce7fc55e4aeaaf1ca67989822c0046204d5..2b5e2e0d329aa79136b1f192605d50e941f4d216 100644 (file)
@@ -21,9 +21,8 @@
  */
 /* eslint-disable camelcase, n/no-extraneous-import */
 import type { AxiosPromise } from 'axios'
-import type { ContentsWithRoot } from '../../../files/src/services/Navigation'
 
-import { Folder, File } from '@nextcloud/files'
+import { Folder, File, type ContentsWithRoot } from '@nextcloud/files'
 import { generateOcsUrl, generateRemoteUrl, generateUrl } from '@nextcloud/router'
 import { getCurrentUser } from '@nextcloud/auth'
 import axios from '@nextcloud/axios'
index 424d3680411932582d9f0fde3b3dc7acfa6d9776..4107c3154baa5cfdaad5b529f006a030488c964f 100644 (file)
 import { expect } from '@jest/globals'
 import axios from '@nextcloud/axios'
 
-import { type Navigation } from '../../../files/src/services/Navigation'
 import { type OCSResponse } from '../services/SharingService'
-import { NavigationService } from '../../../files/src/services/Navigation'
 import registerSharingViews from './shares'
 
 import '../main'
-import { Folder } from '@nextcloud/files'
+import { Folder, getNavigation } from '@nextcloud/files'
 
 describe('Sharing views definition', () => {
        let Navigation
        beforeEach(() => {
-               Navigation = new NavigationService()
-               window.OCP = { Files: { Navigation } }
+               Navigation = getNavigation()
        })
 
        afterAll(() => {
index 74be9e7a503f8e555276c9abc98560f844735d60..e5e8df8fdb9e4560265cff0e4b8e55809b20a7a1 100644 (file)
@@ -19,8 +19,6 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import type { NavigationService, Navigation } from '../../../files/src/services/Navigation'
-
 import { translate as t } from '@nextcloud/l10n'
 import AccountClockSvg from '@mdi/svg/svg/account-clock.svg?raw'
 import AccountGroupSvg from '@mdi/svg/svg/account-group.svg?raw'
@@ -30,6 +28,7 @@ import LinkSvg from '@mdi/svg/svg/link.svg?raw'
 import AccountPlusSvg from '@mdi/svg/svg/account-plus.svg?raw'
 
 import { getContents } from '../services/SharingService'
+import { View, getNavigation } from '@nextcloud/files'
 
 export const sharesViewId = 'shareoverview'
 export const sharedWithYouViewId = 'sharingin'
@@ -39,8 +38,8 @@ export const deletedSharesViewId = 'deletedshares'
 export const pendingSharesViewId = 'pendingshares'
 
 export default () => {
-       const Navigation = window.OCP.Files.Navigation as NavigationService
-       Navigation.register({
+       const Navigation = getNavigation()
+       Navigation.register(new View({
                id: sharesViewId,
                name: t('files_sharing', 'Shares'),
                caption: t('files_sharing', 'Overview of shared files.'),
@@ -54,9 +53,9 @@ export default () => {
                columns: [],
 
                getContents: () => getContents(),
-       } as Navigation)
+       }))
 
-       Navigation.register({
+       Navigation.register(new View({
                id: sharedWithYouViewId,
                name: t('files_sharing', 'Shared with you'),
                caption: t('files_sharing', 'List of files that are shared with you.'),
@@ -71,9 +70,9 @@ export default () => {
                columns: [],
 
                getContents: () => getContents(true, false, false, false),
-       } as Navigation)
+       }))
 
-       Navigation.register({
+       Navigation.register(new View({
                id: sharedWithOthersViewId,
                name: t('files_sharing', 'Shared with others'),
                caption: t('files_sharing', 'List of files that you shared with others.'),
@@ -88,9 +87,9 @@ export default () => {
                columns: [],
 
                getContents: () => getContents(false, true, false, false),
-       } as Navigation)
+       }))
 
-       Navigation.register({
+       Navigation.register(new View({
                id: sharingByLinksViewId,
                name: t('files_sharing', 'Shared by link'),
                caption: t('files_sharing', 'List of files that are shared by link.'),
@@ -105,9 +104,9 @@ export default () => {
                columns: [],
 
                getContents: () => getContents(false, true, false, false, [window.OC.Share.SHARE_TYPE_LINK]),
-       } as Navigation)
+       }))
 
-       Navigation.register({
+       Navigation.register(new View({
                id: deletedSharesViewId,
                name: t('files_sharing', 'Deleted shares'),
                caption: t('files_sharing', 'List of shares you left.'),
@@ -122,9 +121,9 @@ export default () => {
                columns: [],
 
                getContents: () => getContents(false, false, false, true),
-       } as Navigation)
+       }))
 
-       Navigation.register({
+       Navigation.register(new View({
                id: pendingSharesViewId,
                name: t('files_sharing', 'Pending shares'),
                caption: t('files_sharing', 'List of unapproved shares.'),
@@ -139,5 +138,5 @@ export default () => {
                columns: [],
 
                getContents: () => getContents(false, false, true, false),
-       } as Navigation)
+       }))
 }
index 1b14efd545d3f13f57a74d9f6531fa1876b1dfe1..ce8b407719527403ee755af20db0aee0e2ecfa3f 100644 (file)
 import { emit } from '@nextcloud/event-bus'
 import { generateRemoteUrl } from '@nextcloud/router'
 import { getCurrentUser } from '@nextcloud/auth'
-import { Permission, Node } from '@nextcloud/files'
+import { Permission, Node, View } from '@nextcloud/files'
 import { translate as t } from '@nextcloud/l10n'
 import axios from '@nextcloud/axios'
 import History from '@mdi/svg/svg/history.svg?raw'
 
 import { registerFileAction, FileAction } from '../../../files/src/services/FileAction'
 import logger from '../../../files/src/logger.js'
-import type { Navigation } from '../../../files/src/services/Navigation'
 
 registerFileAction(new FileAction({
        id: 'restore',
@@ -70,7 +69,7 @@ registerFileAction(new FileAction({
                        return false
                }
        },
-       async execBatch(nodes: Node[], view: Navigation, dir: string) {
+       async execBatch(nodes: Node[], view: View, dir: string) {
                return Promise.all(nodes.map(node => this.exec(node, view, dir)))
        },
 
index cf5a95bb1d89d3ab9333133980c6f20a4b32cc90..5c625e7bf4fe89e96ae6e8ed09379b1f24d7b0ab 100644 (file)
@@ -19,8 +19,6 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import type { NavigationService, Navigation } from '../../files/src/services/Navigation'
-
 import { translate as t, translate } from '@nextcloud/l10n'
 import DeleteSvg from '@mdi/svg/svg/delete.svg?raw'
 import moment from '@nextcloud/moment'
@@ -29,9 +27,10 @@ import { getContents } from './services/trashbin'
 
 // Register restore action
 import './actions/restoreAction'
+import { Column, View, getNavigation } from '@nextcloud/files'
 
-const Navigation = window.OCP.Files.Navigation as NavigationService
-Navigation.register({
+const Navigation = getNavigation()
+Navigation.register(new View({
        id: 'trashbin',
        name: t('files_trashbin', 'Deleted files'),
        caption: t('files_trashbin', 'List of files that have been deleted.'),
@@ -46,7 +45,7 @@ Navigation.register({
        defaultSortKey: 'deleted',
 
        columns: [
-               {
+               new Column({
                        id: 'deleted',
                        title: t('files_trashbin', 'Deleted'),
                        render(node) {
@@ -67,8 +66,8 @@ Navigation.register({
                                const deletionTimeB = nodeB.attributes?.['trashbin-deletion-time'] || nodeB?.mtime || 0
                                return deletionTimeB - deletionTimeA
                        },
-               },
+               }),
        ],
 
        getContents,
-} as Navigation)
+}))
index bc52100a49283e9d04a6de23335d340b81cbc819..2c4aa373a3fa67f8465b28c3348cf26e0e0f691f 100644 (file)
  */
 /* eslint-disable */
 import { getCurrentUser } from '@nextcloud/auth'
-import { File, Folder, davParsePermissions } from '@nextcloud/files'
+import { File, Folder, davParsePermissions, type ContentsWithRoot } from '@nextcloud/files'
 import { generateRemoteUrl, generateUrl } from '@nextcloud/router'
 
 import type { FileStat, ResponseDataDetailed } from 'webdav'
 import { getDavNameSpaces, getDavProperties } from '../../../files/src/services/DavProperties'
-import type { ContentsWithRoot } from '../../../files/src/services/Navigation.ts'
 
 import client, { rootPath } from './client'