tabby/tabby-electron/src/sftpContextMenu.ts
2022-06-16 18:34:44 +02:00

60 lines
2 KiB
TypeScript

import * as tmp from 'tmp-promise'
import * as path from 'path'
import * as fs from 'fs'
import { Subject, debounceTime, debounce } from 'rxjs'
import { Injectable } from '@angular/core'
import { MenuItemOptions, TranslateService } from 'tabby-core'
import { SFTPFile, SFTPPanelComponent, SFTPContextMenuItemProvider, SFTPSession } from 'tabby-ssh'
import { ElectronPlatformService } from './services/platform.service'
/** @hidden */
@Injectable()
export class EditSFTPContextMenu extends SFTPContextMenuItemProvider {
weight = 0
constructor (
private translate: TranslateService,
private platform: ElectronPlatformService,
) {
super()
}
async getItems (item: SFTPFile, panel: SFTPPanelComponent): Promise<MenuItemOptions[]> {
if (item.isDirectory) {
return []
}
return [
{
click: () => this.edit(item, panel.sftp),
label: this.translate.instant('Edit locally'),
},
]
}
private async edit (item: SFTPFile, sftp: SFTPSession) {
const tempDir = (await tmp.dir({ unsafeCleanup: true })).path
const tempPath = path.join(tempDir, item.name)
const transfer = await this.platform.startDownload(item.name, item.mode, item.size, tempPath)
if (!transfer) {
return
}
await sftp.download(item.fullPath, transfer)
this.platform.openPath(tempPath)
const events = new Subject<string>()
const watcher = fs.watch(tempPath, event => events.next(event))
events.pipe(debounceTime(1000), debounce(async event => {
if (event === 'rename') {
watcher.close()
}
const upload = await this.platform.startUpload({ multiple: false }, [tempPath])
if (!upload.length) {
return
}
sftp.upload(item.fullPath, upload[0])
})).subscribe()
watcher.on('close', () => events.complete())
sftp.closed$.subscribe(() => watcher.close())
}
}