fix(files): Adjust dropservice to work with Blink enginetags/v29.0.0beta4
@@ -22,6 +22,7 @@ | |||
--> | |||
<template> | |||
<div v-show="dragover" | |||
data-cy-files-drag-drop-area | |||
class="files-list__drag-drop-notice" | |||
@drop="onDrop"> | |||
<div class="files-list__drag-drop-notice-wrapper"> |
@@ -36,21 +36,27 @@ export const handleDrop = async (data: DataTransfer): Promise<Upload[]> => { | |||
// TODO: Maybe handle `getAsFileSystemHandle()` in the future | |||
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 | |||
if (entry === null) { | |||
if (entry instanceof DataTransferItem) { | |||
logger.debug('Could not get FilesystemEntry of item, falling back to file') | |||
const file = item.getAsFile() | |||
const file = entry.getAsFile() | |||
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')) | |||
} else { | |||
uploads.push(await handleFileUpload(file)) |
@@ -0,0 +1,62 @@ | |||
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') | |||
}) | |||
}) |