mirror of
https://github.com/Eugeny/tabby.git
synced 2025-07-21 02:48:00 +00:00
download/upload implementation for the web
This commit is contained in:
@@ -36,7 +36,6 @@
|
|||||||
"native-process-working-directory": "^1.0.2",
|
"native-process-working-directory": "^1.0.2",
|
||||||
"ngx-toastr": "^14.0.0",
|
"ngx-toastr": "^14.0.0",
|
||||||
"npm": "6",
|
"npm": "6",
|
||||||
"path": "0.12.7",
|
|
||||||
"rxjs": "^7.1.0",
|
"rxjs": "^7.1.0",
|
||||||
"ssh2": "^1.1.0",
|
"ssh2": "^1.1.0",
|
||||||
"yargs": "^17.0.1",
|
"yargs": "^17.0.1",
|
||||||
|
@@ -1423,11 +1423,6 @@ inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1,
|
|||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz"
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
|
|
||||||
inherits@2.0.3:
|
|
||||||
version "2.0.3"
|
|
||||||
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz"
|
|
||||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
|
||||||
|
|
||||||
ini@^1.3.4, ini@^1.3.5, ini@^1.3.8, ini@~1.3.0:
|
ini@^1.3.4, ini@^1.3.5, ini@^1.3.8, ini@~1.3.0:
|
||||||
version "1.3.8"
|
version "1.3.8"
|
||||||
resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz"
|
resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz"
|
||||||
@@ -2652,14 +2647,6 @@ path-type@^2.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
pify "^2.0.0"
|
pify "^2.0.0"
|
||||||
|
|
||||||
path@0.12.7:
|
|
||||||
version "0.12.7"
|
|
||||||
resolved "https://registry.npmjs.org/path/-/path-0.12.7.tgz"
|
|
||||||
integrity sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=
|
|
||||||
dependencies:
|
|
||||||
process "^0.11.1"
|
|
||||||
util "^0.10.3"
|
|
||||||
|
|
||||||
performance-now@^2.1.0:
|
performance-now@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz"
|
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz"
|
||||||
@@ -2713,11 +2700,6 @@ process-nextick-args@~2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz"
|
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz"
|
||||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||||
|
|
||||||
process@^0.11.1:
|
|
||||||
version "0.11.10"
|
|
||||||
resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz"
|
|
||||||
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
|
|
||||||
|
|
||||||
promise-inflight@^1.0.1, promise-inflight@~1.0.1:
|
promise-inflight@^1.0.1, promise-inflight@~1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz"
|
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz"
|
||||||
@@ -3600,13 +3582,6 @@ util-promisify@^2.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
object.getownpropertydescriptors "^2.0.3"
|
object.getownpropertydescriptors "^2.0.3"
|
||||||
|
|
||||||
util@^0.10.3:
|
|
||||||
version "0.10.4"
|
|
||||||
resolved "https://registry.npmjs.org/util/-/util-0.10.4.tgz"
|
|
||||||
integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==
|
|
||||||
dependencies:
|
|
||||||
inherits "2.0.3"
|
|
||||||
|
|
||||||
uuid@^3.0.1, uuid@^3.3.2, uuid@^3.3.3:
|
uuid@^3.0.1, uuid@^3.3.2, uuid@^3.3.3:
|
||||||
version "3.4.0"
|
version "3.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||||
|
@@ -10,7 +10,7 @@ export { Theme } from './theme'
|
|||||||
export { TabContextMenuItemProvider } from './tabContextMenuProvider'
|
export { TabContextMenuItemProvider } from './tabContextMenuProvider'
|
||||||
export { SelectorOption } from './selector'
|
export { SelectorOption } from './selector'
|
||||||
export { CLIHandler, CLIEvent } from './cli'
|
export { CLIHandler, CLIEvent } from './cli'
|
||||||
export { PlatformService, ClipboardContent, MessageBoxResult, MessageBoxOptions, FileDownload, FileUpload, FileTransfer, FileUploadOptions } from './platform'
|
export { PlatformService, ClipboardContent, MessageBoxResult, MessageBoxOptions, FileDownload, FileUpload, FileTransfer, HTMLFileUpload, FileUploadOptions } from './platform'
|
||||||
export { MenuItemOptions } from './menu'
|
export { MenuItemOptions } from './menu'
|
||||||
export { BootstrapData, BOOTSTRAP_DATA } from './mainProcess'
|
export { BootstrapData, BOOTSTRAP_DATA } from './mainProcess'
|
||||||
export { HostWindowService } from './hostWindow'
|
export { HostWindowService } from './hostWindow'
|
||||||
|
@@ -88,7 +88,7 @@ export abstract class PlatformService {
|
|||||||
abstract startDownload (name: string, size: number): Promise<FileDownload|null>
|
abstract startDownload (name: string, size: number): Promise<FileDownload|null>
|
||||||
abstract startUpload (options?: FileUploadOptions): Promise<FileUpload[]>
|
abstract startUpload (options?: FileUploadOptions): Promise<FileUpload[]>
|
||||||
|
|
||||||
startUploadFromDragEvent (event: DragEvent): FileUpload[] {
|
startUploadFromDragEvent (event: DragEvent, multiple = false): FileUpload[] {
|
||||||
const result: FileUpload[] = []
|
const result: FileUpload[] = []
|
||||||
if (!event.dataTransfer) {
|
if (!event.dataTransfer) {
|
||||||
return []
|
return []
|
||||||
@@ -96,9 +96,12 @@ export abstract class PlatformService {
|
|||||||
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
||||||
for (let i = 0; i < event.dataTransfer.files.length; i++) {
|
for (let i = 0; i < event.dataTransfer.files.length; i++) {
|
||||||
const file = event.dataTransfer.files[i]
|
const file = event.dataTransfer.files[i]
|
||||||
const transfer = new DropUpload(file)
|
const transfer = new HTMLFileUpload(file)
|
||||||
this.fileTransferStarted.next(transfer)
|
this.fileTransferStarted.next(transfer)
|
||||||
result.push(transfer)
|
result.push(transfer)
|
||||||
|
if (!multiple) {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -160,8 +163,7 @@ export abstract class PlatformService {
|
|||||||
abstract quit (): void
|
abstract quit (): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class HTMLFileUpload extends FileUpload {
|
||||||
class DropUpload extends FileUpload {
|
|
||||||
private stream: ReadableStream
|
private stream: ReadableStream
|
||||||
private reader: ReadableStreamDefaultReader
|
private reader: ReadableStreamDefaultReader
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@ import '@vaadin/vaadin-context-menu/vaadin-context-menu.js'
|
|||||||
import copyToClipboard from 'copy-text-to-clipboard'
|
import copyToClipboard from 'copy-text-to-clipboard'
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { PlatformService, ClipboardContent, MenuItemOptions, MessageBoxOptions, MessageBoxResult } from 'terminus-core'
|
import { PlatformService, ClipboardContent, MenuItemOptions, MessageBoxOptions, MessageBoxResult, FileUpload, FileUploadOptions, FileDownload, HTMLFileUpload } from 'terminus-core'
|
||||||
|
|
||||||
// eslint-disable-next-line no-duplicate-imports
|
// eslint-disable-next-line no-duplicate-imports
|
||||||
import type { ContextMenuElement, ContextMenuItem } from '@vaadin/vaadin-context-menu/vaadin-context-menu.js'
|
import type { ContextMenuElement, ContextMenuItem } from '@vaadin/vaadin-context-menu/vaadin-context-menu.js'
|
||||||
@@ -14,6 +14,7 @@ import './styles.scss'
|
|||||||
export class WebPlatformService extends PlatformService {
|
export class WebPlatformService extends PlatformService {
|
||||||
private menu: ContextMenuElement
|
private menu: ContextMenuElement
|
||||||
private contextMenuHandlers = new Map<ContextMenuItem, () => void>()
|
private contextMenuHandlers = new Map<ContextMenuItem, () => void>()
|
||||||
|
private fileSelector: HTMLInputElement
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private ngbModal: NgbModal,
|
private ngbModal: NgbModal,
|
||||||
@@ -24,6 +25,11 @@ export class WebPlatformService extends PlatformService {
|
|||||||
this.contextMenuHandlers.get(e.detail.value)?.()
|
this.contextMenuHandlers.get(e.detail.value)?.()
|
||||||
})
|
})
|
||||||
document.body.appendChild(this.menu)
|
document.body.appendChild(this.menu)
|
||||||
|
|
||||||
|
this.fileSelector = document.createElement('input')
|
||||||
|
this.fileSelector.type = 'file'
|
||||||
|
this.fileSelector.style.visibility = 'hidden'
|
||||||
|
document.body.appendChild(this.fileSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
readClipboard (): string {
|
readClipboard (): string {
|
||||||
@@ -99,4 +105,71 @@ export class WebPlatformService extends PlatformService {
|
|||||||
quit (): void {
|
quit (): void {
|
||||||
window.close()
|
window.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async startDownload (name: string, size: number): Promise<FileDownload|null> {
|
||||||
|
const transfer = new HTMLFileDownload(name, size)
|
||||||
|
this.fileTransferStarted.next(transfer)
|
||||||
|
return transfer
|
||||||
|
}
|
||||||
|
|
||||||
|
startUpload (options?: FileUploadOptions): Promise<FileUpload[]> {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
this.fileSelector.onchange = () => {
|
||||||
|
const transfers: FileUpload[] = []
|
||||||
|
const fileList = this.fileSelector.files!
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
|
for (let i = 0; i < (fileList.length ?? 0); i++) {
|
||||||
|
const file = fileList[i]
|
||||||
|
const transfer = new HTMLFileUpload(file)
|
||||||
|
this.fileTransferStarted.next(transfer)
|
||||||
|
transfers.push(transfer)
|
||||||
|
if (!options?.multiple) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(transfers)
|
||||||
|
}
|
||||||
|
this.fileSelector.click()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HTMLFileDownload extends FileDownload {
|
||||||
|
private buffers: Buffer[] = []
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
private name: string,
|
||||||
|
private size: number,
|
||||||
|
) {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
getName (): string {
|
||||||
|
return this.name
|
||||||
|
}
|
||||||
|
|
||||||
|
getSize (): number {
|
||||||
|
return this.size
|
||||||
|
}
|
||||||
|
|
||||||
|
async write (buffer: Buffer): Promise<void> {
|
||||||
|
this.buffers.push(Buffer.from(buffer))
|
||||||
|
this.increaseProgress(buffer.length)
|
||||||
|
if (this.isComplete()) {
|
||||||
|
this.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finish () {
|
||||||
|
const blob = new Blob(this.buffers, { type: 'application/octet-stream' })
|
||||||
|
const element = window.document.createElement('a')
|
||||||
|
element.href = window.URL.createObjectURL(blob)
|
||||||
|
element.download = this.name
|
||||||
|
document.body.appendChild(element)
|
||||||
|
element.click()
|
||||||
|
document.body.removeChild(element)
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
close (): void { }
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user