|
@@ -5,12 +5,11 @@ import * as os from 'os'
|
|
|
import promiseIpc, { RendererProcessType } from 'electron-promise-ipc'
|
|
|
import { execFile } from 'mz/child_process'
|
|
|
import { Injectable, NgZone } from '@angular/core'
|
|
|
-import { PlatformService, ClipboardContent, Platform, MenuItemOptions, MessageBoxOptions, MessageBoxResult, DirectoryUpload, FileUpload, FileDownload, FileUploadOptions, wrapPromise, TranslateService } from 'tabby-core'
|
|
|
+import { PlatformService, ClipboardContent, Platform, MenuItemOptions, MessageBoxOptions, MessageBoxResult, DirectoryUpload, FileUpload, FileDownload, DirectoryDownload, FileUploadOptions, wrapPromise, TranslateService, FileTransfer, PlatformTheme } from 'tabby-core'
|
|
|
import { ElectronService } from '../services/electron.service'
|
|
|
import { ElectronHostWindow } from './hostWindow.service'
|
|
|
import { ShellIntegrationService } from './shellIntegration.service'
|
|
|
import { ElectronHostAppService } from './hostApp.service'
|
|
|
-import { PlatformTheme } from '../../../tabby-core/src/api/platform'
|
|
|
import { configPath } from '../../../app/lib/config'
|
|
|
const fontManager = require('fontmanager-redux') // eslint-disable-line
|
|
|
|
|
@@ -272,19 +271,48 @@ export class ElectronPlatformService extends PlatformService {
|
|
|
return transfer
|
|
|
}
|
|
|
|
|
|
+ async startDownloadDirectory (name: string, estimatedSize?: number): Promise<DirectoryDownload|null> {
|
|
|
+ const selectedFolder = await this.pickDirectory(this.translate.instant('Select destination folder for {name}', { name }), this.translate.instant('Download here'))
|
|
|
+ if (!selectedFolder) {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+
|
|
|
+ let downloadPath = path.join(selectedFolder, name)
|
|
|
+ let counter = 1
|
|
|
+ while (fsSync.existsSync(downloadPath)) {
|
|
|
+ downloadPath = path.join(selectedFolder, `${name} (${counter})`)
|
|
|
+ counter++
|
|
|
+ }
|
|
|
+
|
|
|
+ const transfer = new ElectronDirectoryDownload(downloadPath, name, estimatedSize ?? 0, this.electron, this.zone)
|
|
|
+ await wrapPromise(this.zone, transfer.open())
|
|
|
+ this.fileTransferStarted.next(transfer)
|
|
|
+ return transfer
|
|
|
+ }
|
|
|
+
|
|
|
+ _registerFileTransfer (transfer: FileTransfer): void {
|
|
|
+ this.fileTransferStarted.next(transfer)
|
|
|
+ }
|
|
|
+
|
|
|
setErrorHandler (handler: (_: any) => void): void {
|
|
|
this.electron.ipcRenderer.on('uncaughtException', (_$event, err) => {
|
|
|
handler(err)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
- async pickDirectory (): Promise<string> {
|
|
|
- return (await this.electron.dialog.showOpenDialog(
|
|
|
+ async pickDirectory (title?: string, buttonLabel?: string): Promise<string | null> {
|
|
|
+ const result = await this.electron.dialog.showOpenDialog(
|
|
|
this.hostWindow.getWindow(),
|
|
|
{
|
|
|
+ title,
|
|
|
+ buttonLabel,
|
|
|
properties: ['openDirectory', 'showHiddenFiles'],
|
|
|
},
|
|
|
- )).filePaths[0]
|
|
|
+ )
|
|
|
+ if (result.canceled || !result.filePaths.length) {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ return result.filePaths[0]
|
|
|
}
|
|
|
|
|
|
getTheme (): PlatformTheme {
|
|
@@ -313,6 +341,7 @@ class ElectronFileUpload extends FileUpload {
|
|
|
const stat = await fs.stat(this.filePath)
|
|
|
this.size = stat.size
|
|
|
this.mode = stat.mode
|
|
|
+ this.setTotalSize(this.size)
|
|
|
this.file = await fs.open(this.filePath, 'r')
|
|
|
}
|
|
|
|
|
@@ -331,6 +360,9 @@ class ElectronFileUpload extends FileUpload {
|
|
|
async read (): Promise<Uint8Array> {
|
|
|
const result = await this.file.read(this.buffer, 0, this.buffer.length, null)
|
|
|
this.increaseProgress(result.bytesRead)
|
|
|
+ if (this.getCompletedBytes() >= this.getSize()) {
|
|
|
+ this.setCompleted(true)
|
|
|
+ }
|
|
|
return this.buffer.slice(0, result.bytesRead)
|
|
|
}
|
|
|
|
|
@@ -352,6 +384,7 @@ class ElectronFileDownload extends FileDownload {
|
|
|
) {
|
|
|
super()
|
|
|
this.powerSaveBlocker = electron.powerSaveBlocker.start('prevent-app-suspension')
|
|
|
+ this.setTotalSize(size)
|
|
|
}
|
|
|
|
|
|
async open (): Promise<void> {
|
|
@@ -362,10 +395,6 @@ class ElectronFileDownload extends FileDownload {
|
|
|
return path.basename(this.filePath)
|
|
|
}
|
|
|
|
|
|
- getMode (): number {
|
|
|
- return this.mode
|
|
|
- }
|
|
|
-
|
|
|
getSize (): number {
|
|
|
return this.size
|
|
|
}
|
|
@@ -377,6 +406,9 @@ class ElectronFileDownload extends FileDownload {
|
|
|
this.increaseProgress(result.bytesWritten)
|
|
|
pos += result.bytesWritten
|
|
|
}
|
|
|
+ if (this.getCompletedBytes() >= this.getSize()) {
|
|
|
+ this.setCompleted(true)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
close (): void {
|
|
@@ -384,3 +416,49 @@ class ElectronFileDownload extends FileDownload {
|
|
|
this.file.close()
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+class ElectronDirectoryDownload extends DirectoryDownload {
|
|
|
+ private powerSaveBlocker = 0
|
|
|
+
|
|
|
+ constructor (
|
|
|
+ private basePath: string,
|
|
|
+ private name: string,
|
|
|
+ estimatedSize: number,
|
|
|
+ private electron: ElectronService,
|
|
|
+ private zone: NgZone,
|
|
|
+ ) {
|
|
|
+ super()
|
|
|
+ this.powerSaveBlocker = electron.powerSaveBlocker.start('prevent-app-suspension')
|
|
|
+ this.setTotalSize(estimatedSize)
|
|
|
+ }
|
|
|
+
|
|
|
+ async open (): Promise<void> {
|
|
|
+ await fs.mkdir(this.basePath, { recursive: true })
|
|
|
+ }
|
|
|
+
|
|
|
+ getName (): string {
|
|
|
+ return this.name
|
|
|
+ }
|
|
|
+
|
|
|
+ getSize (): number {
|
|
|
+ return this.getTotalSize()
|
|
|
+ }
|
|
|
+
|
|
|
+ async createDirectory (relativePath: string): Promise<void> {
|
|
|
+ const fullPath = path.join(this.basePath, relativePath)
|
|
|
+ await fs.mkdir(fullPath, { recursive: true })
|
|
|
+ }
|
|
|
+
|
|
|
+ async createFile (relativePath: string, mode: number, size: number): Promise<FileDownload> {
|
|
|
+ const fullPath = path.join(this.basePath, relativePath)
|
|
|
+ await fs.mkdir(path.dirname(fullPath), { recursive: true })
|
|
|
+
|
|
|
+ const fileDownload = new ElectronFileDownload(fullPath, mode, size, this.electron)
|
|
|
+ await wrapPromise(this.zone, fileDownload.open())
|
|
|
+ return fileDownload
|
|
|
+ }
|
|
|
+
|
|
|
+ close (): void {
|
|
|
+ this.electron.powerSaveBlocker.stop(this.powerSaveBlocker)
|
|
|
+ }
|
|
|
+}
|