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 { 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() 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()) } }