mirror of
https://github.com/Eugeny/tabby.git
synced 2025-07-21 02:48:00 +00:00
Drag upload support.
This commit is contained in:
@@ -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 {
|
||||||
|
@@ -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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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")'
|
||||||
|
@@ -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 {
|
||||||
|
Reference in New Issue
Block a user