Drag upload support.

This commit is contained in:
marko1616
2024-08-22 08:05:37 +08:00
parent aa105bdf4d
commit 3c5f2ba28c
5 changed files with 50 additions and 21 deletions

View File

@@ -109,22 +109,50 @@ export abstract class PlatformService {
abstract startDownload (name: string, mode: number, size: number): Promise<FileDownload|null> abstract startDownload (name: string, mode: number, size: number): Promise<FileDownload|null>
abstract startUpload (options?: FileUploadOptions): Promise<FileUpload[]> abstract startUpload (options?: FileUploadOptions): Promise<FileUpload[]>
startUploadFromDragEvent (event: DragEvent, multiple = false): FileUpload[] { async startUploadFromDragEvent(event: DragEvent, multiple = false): Promise<FileUpload[]> {
const result: FileUpload[] = [] const result: FileUpload[] = []
if (!event.dataTransfer) { if (!event.dataTransfer) {
return [] return Promise.resolve([])
} }
// eslint-disable-next-line @typescript-eslint/prefer-for-of
for (let i = 0; i < event.dataTransfer.files.length; i++) { const traverseFileTree = (item: any, path = ''): Promise<void> => {
const file = event.dataTransfer.files[i] return new Promise((resolve) => {
const transfer = new HTMLFileUpload(file) if (item.isFile) {
item.file((file: File) => {
const transfer = new HTMLFileUpload(file, `${path}/${item.name}`)
this.fileTransferStarted.next(transfer) this.fileTransferStarted.next(transfer)
result.push(transfer) result.push(transfer)
resolve()
});
} else if (item.isDirectory) {
const dirReader = item.createReader()
dirReader.readEntries(async (entries: any[]) => {
for (const entry of entries) {
await traverseFileTree(entry, `${path}${item.name}/`)
}
resolve()
})
} else {
resolve()
}
})
}
const promises: Promise<void>[] = []
const items = event.dataTransfer.items
for (let i = 0; i < items.length; i++) {
const item = items[i].webkitGetAsEntry()
if (item) {
promises.push(traverseFileTree(item))
if (!multiple) { if (!multiple) {
break break
} }
} }
return result }
return Promise.all(promises).then(() => result)
} }
getConfigPath (): string|null { getConfigPath (): string|null {
@@ -194,7 +222,7 @@ export class HTMLFileUpload extends FileUpload {
private stream: ReadableStream private stream: ReadableStream
private reader: ReadableStreamDefaultReader private reader: ReadableStreamDefaultReader
constructor (private file: File) { constructor (private file: File, private relativePath: string|null = null) {
super() super()
this.stream = this.file.stream() this.stream = this.file.stream()
this.reader = this.stream.getReader() this.reader = this.stream.getReader()
@@ -204,8 +232,8 @@ export class HTMLFileUpload extends FileUpload {
return this.file.name return this.file.name
} }
getRelativePath (): null { getRelativePath (): string|null {
return null return this.relativePath
} }
getMode (): number { getMode (): number {

View File

@@ -27,9 +27,9 @@ export class DropZoneDirective implements AfterViewInit {
}) })
} }
}) })
this.el.nativeElement.addEventListener('drop', (event: DragEvent) => { this.el.nativeElement.addEventListener('drop', async (event: DragEvent) => {
this.removeHint() this.removeHint()
for (const transfer of this.platform.startUploadFromDragEvent(event, true)) { for (const transfer of await this.platform.startUploadFromDragEvent(event, true)) {
this.transfer.emit(transfer) this.transfer.emit(transfer)
} }
}) })

View File

@@ -301,7 +301,7 @@ class ElectronFileUpload extends FileUpload {
private buffer: Buffer private buffer: Buffer
private powerSaveBlocker = 0 private powerSaveBlocker = 0
constructor (private filePath: string, private electron: ElectronService, private relativePath = '') { constructor (private filePath: string, private electron: ElectronService, private relativePath: string|null = null ) {
super() super()
this.buffer = Buffer.alloc(256 * 1024) this.buffer = Buffer.alloc(256 * 1024)
this.powerSaveBlocker = electron.powerSaveBlocker.start('prevent-app-suspension') this.powerSaveBlocker = electron.powerSaveBlocker.start('prevent-app-suspension')
@@ -318,7 +318,7 @@ class ElectronFileUpload extends FileUpload {
return path.basename(this.filePath) return path.basename(this.filePath)
} }
getRelativePath (): string { getRelativePath (): string|null {
return this.relativePath return this.relativePath
} }

View File

@@ -31,7 +31,7 @@
button.btn.btn-link.text-decoration-none((click)='close()') !{require('../../../tabby-core/src/icons/times.svg')} button.btn.btn-link.text-decoration-none((click)='close()') !{require('../../../tabby-core/src/icons/times.svg')}
.body(dropZone, (transfer)='uploadOne($event)') .body(dropZone, (transfer)='uploadOneWithFolder($event)')
a.alert.alert-info.d-flex.align-items-center( a.alert.alert-info.d-flex.align-items-center(
*ngIf='shouldShowCWDTip && !cwdDetectionAvailable', *ngIf='shouldShowCWDTip && !cwdDetectionAvailable',
(click)='platform.openExternal("https://tabby.sh/go/cwd-detection")' (click)='platform.openExternal("https://tabby.sh/go/cwd-detection")'

View File

@@ -151,6 +151,7 @@ class HTMLFileDownload extends FileDownload {
private name: string, private name: string,
private mode: number, private mode: number,
private size: number, private size: number,
private relativePath: string|null = null,
) { ) {
super() super()
} }
@@ -159,8 +160,8 @@ class HTMLFileDownload extends FileDownload {
return this.name return this.name
} }
getRelativePath (): null { getRelativePath (): string|null {
return null return this.relativePath
} }
getMode (): number { getMode (): number {