fix(files): Adjust dropservice to work with Blink enginetags/v29.0.0beta4
--> | --> | ||||
<template> | <template> | ||||
<div v-show="dragover" | <div v-show="dragover" | ||||
data-cy-files-drag-drop-area | |||||
class="files-list__drag-drop-notice" | class="files-list__drag-drop-notice" | ||||
@drop="onDrop"> | @drop="onDrop"> | ||||
<div class="files-list__drag-drop-notice-wrapper"> | <div class="files-list__drag-drop-notice-wrapper"> |
// TODO: Maybe handle `getAsFileSystemHandle()` in the future | // TODO: Maybe handle `getAsFileSystemHandle()` in the future | ||||
const uploads = [] as Upload[] | const uploads = [] as Upload[] | ||||
for (const item of data.items) { | |||||
if (item.kind !== 'file') { | |||||
logger.debug('Skipping dropped item', { kind: item.kind, type: item.type }) | |||||
continue | |||||
} | |||||
// MDN recommends to try both, as it might be renamed in the future | |||||
const entry = (item as unknown as { getAsEntry?: () => FileSystemEntry|undefined})?.getAsEntry?.() ?? item.webkitGetAsEntry() | |||||
// we need to cache the entries to prevent Blink engine bug that clears the list (`data.items`) after first access props of one of the entries | |||||
const entries = [...data.items] | |||||
.filter((item) => { | |||||
if (item.kind !== 'file') { | |||||
logger.debug('Skipping dropped item', { kind: item.kind, type: item.type }) | |||||
return false | |||||
} | |||||
return true | |||||
}) | |||||
.map((item) => { | |||||
// MDN recommends to try both, as it might be renamed in the future | |||||
return (item as unknown as { getAsEntry?: () => FileSystemEntry|undefined})?.getAsEntry?.() ?? item.webkitGetAsEntry() ?? item | |||||
}) | |||||
for (const entry of entries) { | |||||
// Handle browser issues if Filesystem API is not available. Fallback to File API | // Handle browser issues if Filesystem API is not available. Fallback to File API | ||||
if (entry === null) { | |||||
if (entry instanceof DataTransferItem) { | |||||
logger.debug('Could not get FilesystemEntry of item, falling back to file') | logger.debug('Could not get FilesystemEntry of item, falling back to file') | ||||
const file = item.getAsFile() | |||||
const file = entry.getAsFile() | |||||
if (file === null) { | if (file === null) { | ||||
logger.warn('Could not process DataTransferItem', { type: item.type, kind: item.kind }) | |||||
logger.warn('Could not process DataTransferItem', { type: entry.type, kind: entry.kind }) | |||||
showError(t('files', 'One of the dropped files could not be processed')) | showError(t('files', 'One of the dropped files could not be processed')) | ||||
} else { | } else { | ||||
uploads.push(await handleFileUpload(file)) | uploads.push(await handleFileUpload(file)) |
import { getRowForFile } from './FilesUtils.ts' | |||||
describe('files: Drag and Drop', { testIsolation: true }, () => { | |||||
beforeEach(() => { | |||||
cy.createRandomUser().then((user) => { | |||||
cy.login(user) | |||||
}) | |||||
cy.visit('/apps/files') | |||||
}) | |||||
it('can drop a file', () => { | |||||
const dataTransfer = new DataTransfer() | |||||
dataTransfer.items.add(new File([], 'single-file.txt')) | |||||
cy.intercept('PUT', /\/remote.php\/dav\/files\//).as('uploadFile') | |||||
cy.get('[data-cy-files-drag-drop-area]').should('not.be.visible') | |||||
// Trigger the drop notice | |||||
cy.get('main.app-content').trigger('dragover', { dataTransfer }) | |||||
cy.get('[data-cy-files-drag-drop-area]').should('be.visible') | |||||
// Upload drop a file | |||||
cy.get('[data-cy-files-drag-drop-area]').selectFile({ | |||||
fileName: 'single-file.txt', | |||||
contents: ['hello '.repeat(1024)], | |||||
}, { action: 'drag-drop' }) | |||||
cy.wait('@uploadFile') | |||||
getRowForFile('single-file.txt').should('be.visible') | |||||
getRowForFile('single-file.txt').find('[data-cy-files-list-row-size]').should('contain', '6 KB') | |||||
}) | |||||
it('can drop multiple files', () => { | |||||
const dataTransfer = new DataTransfer() | |||||
dataTransfer.items.add(new File([], 'first.txt')) | |||||
dataTransfer.items.add(new File([], 'second.txt')) | |||||
cy.intercept('PUT', /\/remote.php\/dav\/files\//).as('uploadFile') | |||||
// Trigger the drop notice | |||||
cy.get('main.app-content').trigger('dragover', { dataTransfer }) | |||||
cy.get('[data-cy-files-drag-drop-area]').should('be.visible') | |||||
// Upload drop a file | |||||
cy.get('[data-cy-files-drag-drop-area]').selectFile([ | |||||
{ | |||||
fileName: 'first.txt', | |||||
contents: ['Hello'], | |||||
}, | |||||
{ | |||||
fileName: 'second.txt', | |||||
contents: ['World'], | |||||
}, | |||||
], { action: 'drag-drop' }) | |||||
cy.wait('@uploadFile') | |||||
getRowForFile('first.txt').should('be.visible') | |||||
getRowForFile('second.txt').should('be.visible') | |||||
}) | |||||
}) |