mirror of
https://github.com/nextcloud/server.git
synced 2026-04-12 20:47:04 -04:00
Merge pull request #58700 from nextcloud/backport/58680/stable32
Some checks are pending
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Integration sqlite / changes (push) Waiting to run
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, --tags ~@large files_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, capabilities_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, collaboration_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, comments_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, dav_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, federation_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, file_conversions) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, files_reminders) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, filesdrop_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, ldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, openldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, openldap_numerical_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, remoteapi_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, routing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, setup_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, sharees_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, sharing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, theming_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, videoverification_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite-summary (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis (push) Waiting to run
Psalm static code analysis / static-code-analysis-security (push) Waiting to run
Psalm static code analysis / static-code-analysis-ocp (push) Waiting to run
Psalm static code analysis / static-code-analysis-ncu (push) Waiting to run
Some checks are pending
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Integration sqlite / changes (push) Waiting to run
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, --tags ~@large files_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, capabilities_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, collaboration_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, comments_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, dav_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, federation_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, file_conversions) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, files_reminders) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, filesdrop_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, ldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, openldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, openldap_numerical_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, remoteapi_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, routing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, setup_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, sharees_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, sharing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, theming_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable32, 8.1, stable32, videoverification_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite-summary (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis (push) Waiting to run
Psalm static code analysis / static-code-analysis-security (push) Waiting to run
Psalm static code analysis / static-code-analysis-ocp (push) Waiting to run
Psalm static code analysis / static-code-analysis-ncu (push) Waiting to run
[stable32] fix(files): properly handle dropping files
This commit is contained in:
commit
ee1a7d633f
3 changed files with 62 additions and 34 deletions
|
|
@ -6,17 +6,18 @@
|
|||
import type { PropType } from 'vue'
|
||||
import type { FileSource } from '../types.ts'
|
||||
|
||||
import { extname } from 'path'
|
||||
import { FileType, Permission, Folder, File as NcFile, NodeStatus, Node, getFileActions } from '@nextcloud/files'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import { isPublicShare } from '@nextcloud/sharing/public'
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
import { openConflictPicker } from '@nextcloud/dialogs'
|
||||
import { FileType, Folder, getFileActions, File as NcFile, Node, NodeStatus, Permission } 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 { getConflicts, getUploader } from '@nextcloud/upload'
|
||||
import { vOnClickOutside } from '@vueuse/components'
|
||||
import Vue, { computed, defineComponent } from 'vue'
|
||||
|
||||
import { action as sidebarAction } from '../actions/sidebarAction.ts'
|
||||
import { dataTransferToFileTree, onDropExternalFiles, onDropInternalFiles } from '../services/DropService.ts'
|
||||
import { onDropInternalFiles } from '../services/DropService.ts'
|
||||
import { getDragAndDropPreview } from '../utils/dragUtils.ts'
|
||||
import { hashCode } from '../utils/hashUtils.ts'
|
||||
import { isDownloadable } from '../utils/permissions.ts'
|
||||
|
|
@ -459,42 +460,69 @@ export default defineComponent({
|
|||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
// Caching the selection
|
||||
const selection = this.draggingFiles
|
||||
const items = [...event.dataTransfer?.items || []] as DataTransferItem[]
|
||||
|
||||
// We need to process the dataTransfer ASAP before the
|
||||
// browser clears it. This is why we cache the items too.
|
||||
const fileTree = await dataTransferToFileTree(items)
|
||||
|
||||
// We might not have the target directory fetched yet
|
||||
const contents = await this.currentView?.getContents(this.source.path)
|
||||
const folder = contents?.folder
|
||||
if (!folder) {
|
||||
showError(this.t('files', 'Target folder does not exist any more'))
|
||||
return
|
||||
}
|
||||
|
||||
// If another button is pressed, cancel it. This
|
||||
// allows cancelling the drag with the right click.
|
||||
if (!this.canDrop || event.button) {
|
||||
return
|
||||
}
|
||||
|
||||
const isCopy = event.ctrlKey
|
||||
this.dragover = false
|
||||
// Caching the selection
|
||||
const selection = this.draggingFiles
|
||||
const items = Array.from(event.dataTransfer?.items || [])
|
||||
|
||||
logger.debug('Dropped', { event, folder, selection, fileTree })
|
||||
if (selection.length === 0 && items.some((item) => item.kind === 'file')) {
|
||||
const uploader = getUploader()
|
||||
await uploader.batchUpload(
|
||||
this.source.path,
|
||||
items.filter((item) => item.kind === 'file')
|
||||
.map((item) => 'webkitGetAsEntry' in item ? item.webkitGetAsEntry() : item.getAsFile())
|
||||
.filter(Boolean) as (FileSystemEntry | File)[],
|
||||
async (nodes, path) => {
|
||||
try {
|
||||
const { contents, folder } = await this.activeView!.getContents(path)
|
||||
const conflicts = getConflicts(nodes, contents)
|
||||
if (conflicts.length === 0) {
|
||||
return nodes
|
||||
}
|
||||
|
||||
// Check whether we're uploading files
|
||||
if (selection.length === 0 && fileTree.contents.length > 0) {
|
||||
await onDropExternalFiles(fileTree, folder, contents.contents)
|
||||
const result = await openConflictPicker(
|
||||
folder.displayname,
|
||||
conflicts,
|
||||
(contents as Node[]).filter((node) => conflicts.some((conflict) => conflict.name === node.basename)),
|
||||
{
|
||||
recursive: true,
|
||||
},
|
||||
)
|
||||
if (result === null) {
|
||||
return false
|
||||
}
|
||||
return [
|
||||
...nodes.filter((node) => !conflicts.some((conflict) => conflict.name === node.name)),
|
||||
...result.selected,
|
||||
...result.renamed,
|
||||
]
|
||||
} catch {
|
||||
return nodes
|
||||
}
|
||||
},
|
||||
)
|
||||
this.dragover = false
|
||||
return
|
||||
}
|
||||
|
||||
// Else we're moving/copying files
|
||||
const nodes = selection.map(source => this.filesStore.getNode(source)) as Node[]
|
||||
await onDropInternalFiles(nodes, folder, contents.contents, isCopy)
|
||||
// We might not have the target directory fetched yet
|
||||
const cachedContents = this.filesStore.getNodesByPath(this.activeView.id, this.source.path)
|
||||
const contents = cachedContents.length === 0
|
||||
? (await this.activeView!.getContents(this.source.path)).contents
|
||||
: cachedContents
|
||||
|
||||
const isCopy = event.ctrlKey
|
||||
this.dragover = false
|
||||
|
||||
logger.debug('Dropped', { event, folder: this.source, selection, fileTree })
|
||||
|
||||
const nodes = selection.map((source) => this.filesStore.getNode(source)) as Node[]
|
||||
await onDropInternalFiles(nodes, this.source, contents, isCopy)
|
||||
|
||||
// Reset selection after we dropped the files
|
||||
// if the dropped files are within the selection
|
||||
|
|
|
|||
4
dist/files-main.js
vendored
4
dist/files-main.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files-main.js.map
vendored
2
dist/files-main.js.map
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue