diff --git a/apps/files/src/services/DropService.ts b/apps/files/src/services/DropService.ts index 1fec09ae415..7b15cad3959 100644 --- a/apps/files/src/services/DropService.ts +++ b/apps/files/src/services/DropService.ts @@ -3,17 +3,18 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +import type { Folder, Node, IFolder, INode } from '@nextcloud/files' import type { Upload } from '@nextcloud/upload' -import type { RootDirectory } from './DropServiceUtils' +import type { RootDirectory } from './DropServiceUtils.ts' -import { Folder, Node, NodeStatus, davRootPath } from '@nextcloud/files' +import { NodeStatus } from '@nextcloud/files' import { getUploader, hasConflict } from '@nextcloud/upload' import { join } from '@nextcloud/paths' import { showError, showInfo, showSuccess, showWarning } from '@nextcloud/dialogs' import { t } from '@nextcloud/l10n' import Vue from 'vue' -import { Directory, traverseTree, resolveConflict, createDirectoryIfNotExists } from './DropServiceUtils' +import { Directory, traverseTree, resolveConflict, createDirectoryIfNotExists } from './DropServiceUtils.ts' import { handleCopyMoveNodeTo } from '../actions/moveOrCopyAction' import { MoveCopyAction } from '../actions/moveOrCopyActionUtils' import logger from '../logger.ts' @@ -95,11 +96,11 @@ export const dataTransferToFileTree = async (items: DataTransferItem[]): Promise * @param destination - The destination folder * @param contents - The contents of the destination folder */ -export async function onDropExternalFiles(root: RootDirectory, destination: Folder, contents: Node[]): Promise { +export async function onDropExternalFiles(root: RootDirectory, destination: IFolder, contents: INode[]): Promise { const uploader = getUploader() // Check for conflicts on root elements - if (await hasConflict(root.contents, contents)) { + if (hasConflict(root.contents, contents as Node[])) { root.contents = await resolveConflict(root.contents, destination, contents) if (root.contents.length === 0) { // user cancelled the upload @@ -124,14 +125,13 @@ export async function onDropExternalFiles(root: RootDirectory, destination: Fold // If the file is a directory, we need to create it first // then browse its tree and upload its contents. if (file instanceof Directory) { - const absolutePath = join(davRootPath, destination.path, relativePath) try { - console.debug('Processing directory', { relativePath }) - await createDirectoryIfNotExists(absolutePath) + logger.debug('Processing directory', { relativePath }) + await createDirectoryIfNotExists(relativePath) await uploadDirectoryContents(file, relativePath) } catch (error) { showError(t('files', 'Unable to create the directory {directory}', { directory: file.name })) - logger.error('', { error, absolutePath, directory: file }) + logger.error('Unable to create the directory', { error, relativePath, directory: file }) } continue } @@ -170,11 +170,11 @@ export async function onDropExternalFiles(root: RootDirectory, destination: Fold return Promise.all(queue) } -export const onDropInternalFiles = async (nodes: Node[], destination: Folder, contents: Node[], isCopy = false) => { +export const onDropInternalFiles = async (nodes: Node[], destination: IFolder, contents: INode[], isCopy = false) => { const queue = [] as Promise[] // Check for conflicts on root elements - if (await hasConflict(nodes, contents)) { + if (hasConflict(nodes, contents as Node[])) { nodes = await resolveConflict(nodes, destination, contents) } @@ -186,7 +186,7 @@ export const onDropInternalFiles = async (nodes: Node[], destination: Folder, co for (const node of nodes) { Vue.set(node, 'status', NodeStatus.LOADING) - queue.push(handleCopyMoveNodeTo(node, destination, isCopy ? MoveCopyAction.COPY : MoveCopyAction.MOVE, true)) + queue.push(handleCopyMoveNodeTo(node, destination as Folder, isCopy ? MoveCopyAction.COPY : MoveCopyAction.MOVE, true)) } // Wait for all promises to settle diff --git a/apps/files/src/services/DropServiceUtils.ts b/apps/files/src/services/DropServiceUtils.ts index 4eab3af9a1d..86ac2ae0627 100644 --- a/apps/files/src/services/DropServiceUtils.ts +++ b/apps/files/src/services/DropServiceUtils.ts @@ -2,13 +2,16 @@ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ + +import type { IFolder, INode, Node } from '@nextcloud/files' import type { FileStat, ResponseDataDetailed } from 'webdav' import { showWarning, showInfo } from '@nextcloud/dialogs' import { emit } from '@nextcloud/event-bus' -import { Folder, Node, davGetClient, davGetDefaultPropfind, davResultToNode } from '@nextcloud/files' +import { defaultRemoteURL, defaultRootPath, getClient, getDefaultPropfind, resultToNode } from '@nextcloud/files/dav' +import { t } from '@nextcloud/l10n' +import { join } from '@nextcloud/paths' import { openConflictPicker } from '@nextcloud/upload' -import { translate as t } from '@nextcloud/l10n' import logger from '../logger.ts' @@ -129,31 +132,35 @@ const readDirectory = (directory: FileSystemDirectoryEntry): Promise { - const davClient = davGetClient() - const dirExists = await davClient.exists(absolutePath) +/** + * @param path - The path relative to the dav root + */ +export async function createDirectoryIfNotExists(path: string) { + const davUrl = join(defaultRemoteURL, defaultRootPath) + const davClient = getClient(davUrl) + const dirExists = await davClient.exists(path) if (!dirExists) { - logger.debug('Directory does not exist, creating it', { absolutePath }) - await davClient.createDirectory(absolutePath, { recursive: true }) - const stat = await davClient.stat(absolutePath, { details: true, data: davGetDefaultPropfind() }) as ResponseDataDetailed - emit('files:node:created', davResultToNode(stat.data)) + logger.debug('Directory does not exist, creating it', { path }) + await davClient.createDirectory(path, { recursive: true }) + const stat = await davClient.stat(path, { details: true, data: getDefaultPropfind() }) as ResponseDataDetailed + emit('files:node:created', resultToNode(stat.data, defaultRootPath, davUrl)) } } -export const resolveConflict = async (files: Array, destination: Folder, contents: Node[]): Promise => { +export const resolveConflict = async (files: Array, destination: IFolder, contents: INode[]): Promise => { try { // List all conflicting files - const conflicts = files.filter((file: File|Node) => { - return contents.find((node: Node) => node.basename === (file instanceof File ? file.name : file.basename)) - }).filter(Boolean) as (File|Node)[] + const conflicts = files.filter((file: File|INode) => { + return contents.find((node: INode) => node.basename === (file instanceof File ? file.name : file.basename)) + }).filter(Boolean) as (File|INode)[] // List of incoming files that are NOT in conflict - const uploads = files.filter((file: File|Node) => { + const uploads = files.filter((file: T) => { return !conflicts.includes(file) }) // Let the user choose what to do with the conflicting files - const { selected, renamed } = await openConflictPicker(destination.path, conflicts, contents) + const { selected, renamed } = await openConflictPicker(destination.path, conflicts as (File | Node)[], contents as Node[]) logger.debug('Conflict resolution', { uploads, selected, renamed })