mirror of
https://github.com/Eugeny/tabby.git
synced 2025-06-09 05:50:08 +00:00
new ssh connection selector - fixes #1557
This commit is contained in:
parent
68efe2b3c4
commit
28c58d4ec0
@ -1,5 +1,8 @@
|
|||||||
export interface SelectorOption<T> {
|
export interface SelectorOption<T> {
|
||||||
name: string
|
name: string
|
||||||
description?: string
|
description?: string
|
||||||
result: T
|
result?: T
|
||||||
|
icon?: string
|
||||||
|
freeInputPattern?: string
|
||||||
|
callback?: (string?) => void
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,15 @@
|
|||||||
[(ngModel)]='filter',
|
[(ngModel)]='filter',
|
||||||
autofocus,
|
autofocus,
|
||||||
[placeholder]='name',
|
[placeholder]='name',
|
||||||
(ngModelChange)='onFilterChange()',
|
(ngModelChange)='onFilterChange()'
|
||||||
(keyup.enter)='onFilterEnter()',
|
|
||||||
(keyup.escape)='close()'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
.list-group.mt-3(*ngIf='filteredOptions.length')
|
.list-group.mt-3(*ngIf='filteredOptions.length')
|
||||||
a.list-group-item.list-group-item-action.d-flex.align-items-center(
|
a.list-group-item.list-group-item-action.d-flex.align-items-center(
|
||||||
(click)='selectOption(option)',
|
(click)='selectOption(option)',
|
||||||
*ngFor='let option of filteredOptions'
|
[class.active]='selectedIndex == i',
|
||||||
|
*ngFor='let option of filteredOptions; let i = index'
|
||||||
)
|
)
|
||||||
.mr-2 {{option.name}}
|
i(class='fa-fw fas mr-1 fa-{{option.icon}}')
|
||||||
|
.mr-2 {{getOptionText(option)}}
|
||||||
.text-muted {{option.description}}
|
.text-muted {{option.description}}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, Input } from '@angular/core'
|
import { Component, Input, HostListener } from '@angular/core'
|
||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { SelectorOption } from '../api/selector'
|
import { SelectorOption } from '../api/selector'
|
||||||
|
|
||||||
@ -12,6 +12,7 @@ export class SelectorModalComponent<T> {
|
|||||||
@Input() filteredOptions: SelectorOption<T>[]
|
@Input() filteredOptions: SelectorOption<T>[]
|
||||||
@Input() filter = ''
|
@Input() filter = ''
|
||||||
@Input() name: string
|
@Input() name: string
|
||||||
|
@Input() selectedIndex = 0
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
public modalInstance: NgbActiveModal,
|
public modalInstance: NgbActiveModal,
|
||||||
@ -21,23 +22,44 @@ export class SelectorModalComponent<T> {
|
|||||||
this.onFilterChange()
|
this.onFilterChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@HostListener('keyup', ['$event']) onKeyUp (event: KeyboardEvent): void {
|
||||||
|
if (event.key === 'ArrowUp') {
|
||||||
|
this.selectedIndex--
|
||||||
|
}
|
||||||
|
if (event.key === 'ArrowDown') {
|
||||||
|
this.selectedIndex++
|
||||||
|
}
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
this.selectOption(this.filteredOptions[this.selectedIndex])
|
||||||
|
}
|
||||||
|
if (event.key === 'Escape') {
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectedIndex = (this.selectedIndex + this.filteredOptions.length) % this.filteredOptions.length
|
||||||
|
}
|
||||||
|
|
||||||
onFilterChange (): void {
|
onFilterChange (): void {
|
||||||
const f = this.filter.trim().toLowerCase()
|
const f = this.filter.trim().toLowerCase()
|
||||||
if (!f) {
|
if (!f) {
|
||||||
this.filteredOptions = this.options
|
this.filteredOptions = this.options.filter(x => !x.freeInputPattern)
|
||||||
} else {
|
} else {
|
||||||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
||||||
this.filteredOptions = this.options.filter(x => (x.name + (x.description || '')).toLowerCase().includes(f))
|
this.filteredOptions = this.options.filter(x => x.freeInputPattern || (x.name + (x.description || '')).toLowerCase().includes(f))
|
||||||
}
|
}
|
||||||
|
this.selectedIndex = Math.max(0, this.selectedIndex)
|
||||||
|
this.selectedIndex = Math.min(this.filteredOptions.length - 1, this.selectedIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
onFilterEnter (): void {
|
getOptionText (option: SelectorOption<T>): string {
|
||||||
if (this.filteredOptions.length === 1) {
|
if (option.freeInputPattern) {
|
||||||
this.selectOption(this.filteredOptions[0])
|
return option.freeInputPattern.replace('%s', this.filter)
|
||||||
}
|
}
|
||||||
|
return option.name
|
||||||
}
|
}
|
||||||
|
|
||||||
selectOption (option: SelectorOption<T>): void {
|
selectOption (option: SelectorOption<T>): void {
|
||||||
|
option.callback?.(this.filter)
|
||||||
this.modalInstance.close(option.result)
|
this.modalInstance.close(option.result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ ngb-tabset .tab-content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.list-group-item {
|
.list-group-item {
|
||||||
transition: 0.25s background;
|
transition: 0.0625s background;
|
||||||
|
|
||||||
i + * {
|
i + * {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
|
||||||
import { HotkeysService, ToolbarButtonProvider, ToolbarButton } from 'terminus-core'
|
import { HotkeysService, ToolbarButtonProvider, ToolbarButton } from 'terminus-core'
|
||||||
import { SSHModalComponent } from './components/sshModal.component'
|
import { SSHService } from './services/ssh.service'
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ButtonProvider extends ToolbarButtonProvider {
|
export class ButtonProvider extends ToolbarButtonProvider {
|
||||||
constructor (
|
constructor (
|
||||||
private ngbModal: NgbModal,
|
|
||||||
hotkeys: HotkeysService,
|
hotkeys: HotkeysService,
|
||||||
|
private ssh: SSHService,
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
hotkeys.matchedHotkey.subscribe(async (hotkey: string) => {
|
hotkeys.matchedHotkey.subscribe(async (hotkey: string) => {
|
||||||
@ -20,7 +19,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
activate () {
|
activate () {
|
||||||
this.ngbModal.open(SSHModalComponent)
|
this.ssh.showConnectionSelector()
|
||||||
}
|
}
|
||||||
|
|
||||||
provide (): ToolbarButton[] {
|
provide (): ToolbarButton[] {
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
.modal-body
|
|
||||||
input.form-control(
|
|
||||||
type='text',
|
|
||||||
[(ngModel)]='quickTarget',
|
|
||||||
autofocus,
|
|
||||||
placeholder='Quick connect: [user@]host[:port]',
|
|
||||||
(ngModelChange)='refresh()',
|
|
||||||
(keyup.enter)='quickConnect()'
|
|
||||||
)
|
|
||||||
|
|
||||||
.list-group.mt-3(*ngIf='recentConnections')
|
|
||||||
a.list-group-item.list-group-item-action.d-flex.align-items-center(
|
|
||||||
*ngFor='let connection of recentConnections',
|
|
||||||
(click)='connect(connection)'
|
|
||||||
)
|
|
||||||
i.fas.fa-fw.fa-history
|
|
||||||
.mr-auto {{connection.name}}
|
|
||||||
button.btn.btn-outline-danger.btn-sm((click)='clearConnection(connection); $event.stopPropagation()')
|
|
||||||
i.fas.fa-trash
|
|
||||||
|
|
||||||
.list-group.mt-3.connections-list(*ngIf='childGroups.length')
|
|
||||||
ng-container(*ngFor='let group of childGroups')
|
|
||||||
.list-group-item.list-group-item-action.d-flex.align-items-center(
|
|
||||||
(click)='groupCollapsed[group.name] = !groupCollapsed[group.name]'
|
|
||||||
)
|
|
||||||
.fa.fa-fw.fa-chevron-right(*ngIf='groupCollapsed[group.name]')
|
|
||||||
.fa.fa-fw.fa-chevron-down(*ngIf='!groupCollapsed[group.name]')
|
|
||||||
.ml-2 {{group.name || "Ungrouped"}}
|
|
||||||
ng-container(*ngIf='!groupCollapsed[group.name]')
|
|
||||||
.list-group-item.list-group-item-action.pl-5.d-flex.align-items-center(
|
|
||||||
*ngFor='let connection of group.connections',
|
|
||||||
(click)='connect(connection)'
|
|
||||||
)
|
|
||||||
.mr-2 {{connection.name}}
|
|
||||||
.text-muted {{connection.host}}
|
|
@ -1,5 +0,0 @@
|
|||||||
.list-group.connections-list {
|
|
||||||
display: block;
|
|
||||||
max-height: 70vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
@ -1,123 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
||||||
import { Component, NgZone } from '@angular/core'
|
|
||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
|
||||||
import { ToastrService } from 'ngx-toastr'
|
|
||||||
import { ConfigService, AppService } from 'terminus-core'
|
|
||||||
import { SettingsTabComponent } from 'terminus-settings'
|
|
||||||
import { SSHConnection, SSHConnectionGroup } from '../api'
|
|
||||||
import { SSHTabComponent } from './sshTab.component'
|
|
||||||
|
|
||||||
/** @hidden */
|
|
||||||
@Component({
|
|
||||||
template: require('./sshModal.component.pug'),
|
|
||||||
styles: [require('./sshModal.component.scss')],
|
|
||||||
})
|
|
||||||
export class SSHModalComponent {
|
|
||||||
connections: SSHConnection[]
|
|
||||||
childFolders: SSHConnectionGroup[]
|
|
||||||
quickTarget: string
|
|
||||||
recentConnections: SSHConnection[]
|
|
||||||
childGroups: SSHConnectionGroup[]
|
|
||||||
groupCollapsed: {[id: string]: boolean} = {}
|
|
||||||
|
|
||||||
constructor (
|
|
||||||
public modalInstance: NgbActiveModal,
|
|
||||||
private config: ConfigService,
|
|
||||||
private app: AppService,
|
|
||||||
private toastr: ToastrService,
|
|
||||||
private zone: NgZone,
|
|
||||||
) { }
|
|
||||||
|
|
||||||
ngOnInit () {
|
|
||||||
this.connections = this.config.store.ssh.connections
|
|
||||||
this.recentConnections = this.config.store.ssh.recentConnections
|
|
||||||
this.refresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
quickConnect () {
|
|
||||||
let user = 'root'
|
|
||||||
let host = this.quickTarget
|
|
||||||
let port = 22
|
|
||||||
if (host.includes('@')) {
|
|
||||||
[user, host] = host.split('@')
|
|
||||||
}
|
|
||||||
if (host.includes(':')) {
|
|
||||||
port = parseInt(host.split(':')[1])
|
|
||||||
host = host.split(':')[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
const connection: SSHConnection = {
|
|
||||||
name: this.quickTarget,
|
|
||||||
group: null,
|
|
||||||
host,
|
|
||||||
user,
|
|
||||||
port,
|
|
||||||
}
|
|
||||||
this.recentConnections.unshift(connection)
|
|
||||||
if (this.recentConnections.length > 5) {
|
|
||||||
this.recentConnections.pop()
|
|
||||||
}
|
|
||||||
this.config.store.ssh.recentConnections = this.recentConnections
|
|
||||||
this.config.save()
|
|
||||||
this.connect(connection)
|
|
||||||
}
|
|
||||||
|
|
||||||
clearConnection (connection) {
|
|
||||||
this.recentConnections = this.recentConnections.filter(function (el) {
|
|
||||||
return el !== connection
|
|
||||||
})
|
|
||||||
this.config.store.ssh.recentConnections = this.recentConnections
|
|
||||||
this.config.save()
|
|
||||||
}
|
|
||||||
|
|
||||||
async connect (connection: SSHConnection) {
|
|
||||||
this.close()
|
|
||||||
|
|
||||||
try {
|
|
||||||
const tab = this.zone.run(() => this.app.openNewTab(
|
|
||||||
SSHTabComponent,
|
|
||||||
{ connection }
|
|
||||||
) as SSHTabComponent)
|
|
||||||
if (connection.color) {
|
|
||||||
(this.app.getParentTab(tab) || tab).color = connection.color
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.app.activeTab?.emitFocused()
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
this.toastr.error(`Could not connect: ${error}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manageConnections () {
|
|
||||||
this.close()
|
|
||||||
this.app.openNewTab(SettingsTabComponent, { activeTab: 'ssh' })
|
|
||||||
}
|
|
||||||
|
|
||||||
close () {
|
|
||||||
this.modalInstance.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh () {
|
|
||||||
this.childGroups = []
|
|
||||||
|
|
||||||
let connections = this.connections
|
|
||||||
if (this.quickTarget) {
|
|
||||||
connections = connections.filter((connection: SSHConnection) => (connection.name + connection.group!).toLowerCase().includes(this.quickTarget))
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const connection of connections) {
|
|
||||||
connection.group = connection.group || null
|
|
||||||
let group = this.childGroups.find(x => x.name === connection.group)
|
|
||||||
if (!group) {
|
|
||||||
group = {
|
|
||||||
name: connection.group!,
|
|
||||||
connections: [],
|
|
||||||
}
|
|
||||||
this.childGroups.push(group!)
|
|
||||||
}
|
|
||||||
group.connections.push(connection)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,6 @@ import { SettingsTabProvider } from 'terminus-settings'
|
|||||||
import TerminusTerminalModule from 'terminus-terminal'
|
import TerminusTerminalModule from 'terminus-terminal'
|
||||||
|
|
||||||
import { EditConnectionModalComponent } from './components/editConnectionModal.component'
|
import { EditConnectionModalComponent } from './components/editConnectionModal.component'
|
||||||
import { SSHModalComponent } from './components/sshModal.component'
|
|
||||||
import { SSHPortForwardingModalComponent } from './components/sshPortForwardingModal.component'
|
import { SSHPortForwardingModalComponent } from './components/sshPortForwardingModal.component'
|
||||||
import { PromptModalComponent } from './components/promptModal.component'
|
import { PromptModalComponent } from './components/promptModal.component'
|
||||||
import { SSHSettingsTabComponent } from './components/sshSettingsTab.component'
|
import { SSHSettingsTabComponent } from './components/sshSettingsTab.component'
|
||||||
@ -40,7 +39,6 @@ import { SSHHotkeyProvider } from './hotkeys'
|
|||||||
entryComponents: [
|
entryComponents: [
|
||||||
EditConnectionModalComponent,
|
EditConnectionModalComponent,
|
||||||
PromptModalComponent,
|
PromptModalComponent,
|
||||||
SSHModalComponent,
|
|
||||||
SSHPortForwardingModalComponent,
|
SSHPortForwardingModalComponent,
|
||||||
SSHSettingsTabComponent,
|
SSHSettingsTabComponent,
|
||||||
SSHTabComponent,
|
SSHTabComponent,
|
||||||
@ -48,7 +46,6 @@ import { SSHHotkeyProvider } from './hotkeys'
|
|||||||
declarations: [
|
declarations: [
|
||||||
EditConnectionModalComponent,
|
EditConnectionModalComponent,
|
||||||
PromptModalComponent,
|
PromptModalComponent,
|
||||||
SSHModalComponent,
|
|
||||||
SSHPortForwardingModalComponent,
|
SSHPortForwardingModalComponent,
|
||||||
SSHSettingsTabComponent,
|
SSHSettingsTabComponent,
|
||||||
SSHTabComponent,
|
SSHTabComponent,
|
||||||
|
@ -3,16 +3,18 @@ import { open as openTemp } from 'temp'
|
|||||||
import { Injectable, NgZone } from '@angular/core'
|
import { Injectable, NgZone } from '@angular/core'
|
||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { Client } from 'ssh2'
|
import { Client } from 'ssh2'
|
||||||
|
import { SSH2Stream } from 'ssh2-streams'
|
||||||
import * as fs from 'mz/fs'
|
import * as fs from 'mz/fs'
|
||||||
import { execFile } from 'mz/child_process'
|
import { execFile } from 'mz/child_process'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as sshpk from 'sshpk'
|
import * as sshpk from 'sshpk'
|
||||||
import { ToastrService } from 'ngx-toastr'
|
import { ToastrService } from 'ngx-toastr'
|
||||||
import { HostAppService, Platform, Logger, LogService, ElectronService } from 'terminus-core'
|
import { HostAppService, Platform, Logger, LogService, ElectronService, AppService, SelectorOption, ConfigService } from 'terminus-core'
|
||||||
|
import { SettingsTabComponent } from 'terminus-settings'
|
||||||
import { SSHConnection, SSHSession } from '../api'
|
import { SSHConnection, SSHSession } from '../api'
|
||||||
import { PromptModalComponent } from '../components/promptModal.component'
|
import { PromptModalComponent } from '../components/promptModal.component'
|
||||||
import { PasswordStorageService } from './passwordStorage.service'
|
import { PasswordStorageService } from './passwordStorage.service'
|
||||||
import { SSH2Stream } from 'ssh2-streams'
|
import { SSHTabComponent } from '../components/sshTab.component'
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var windowsProcessTreeNative = require('windows-process-tree/build/Release/windows_process_tree.node') // eslint-disable-line @typescript-eslint/no-var-requires, no-var
|
var windowsProcessTreeNative = require('windows-process-tree/build/Release/windows_process_tree.node') // eslint-disable-line @typescript-eslint/no-var-requires, no-var
|
||||||
@ -30,6 +32,8 @@ export class SSHService {
|
|||||||
private hostApp: HostAppService,
|
private hostApp: HostAppService,
|
||||||
private passwordStorage: PasswordStorageService,
|
private passwordStorage: PasswordStorageService,
|
||||||
private toastr: ToastrService,
|
private toastr: ToastrService,
|
||||||
|
private app: AppService,
|
||||||
|
private config: ConfigService,
|
||||||
) {
|
) {
|
||||||
this.logger = log.create('ssh')
|
this.logger = log.create('ssh')
|
||||||
}
|
}
|
||||||
@ -249,6 +253,124 @@ export class SSHService {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async showConnectionSelector (): Promise<void> {
|
||||||
|
const options: SelectorOption<void>[] = []
|
||||||
|
const recentConnections = this.config.store.ssh.recentConnections
|
||||||
|
|
||||||
|
for (const connection of recentConnections) {
|
||||||
|
options.push({
|
||||||
|
name: connection.name,
|
||||||
|
description: connection.host,
|
||||||
|
icon: 'history',
|
||||||
|
callback: () => this.connect(connection),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recentConnections.length) {
|
||||||
|
options.push({
|
||||||
|
name: 'Clear recent connections',
|
||||||
|
icon: 'eraser',
|
||||||
|
callback: () => {
|
||||||
|
this.config.store.ssh.recentConnections = []
|
||||||
|
this.config.save()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let groups: { name: string, connections: SSHConnection[] }[] = []
|
||||||
|
let connections = this.config.store.ssh.connections
|
||||||
|
for (const connection of connections) {
|
||||||
|
connection.group = connection.group || null
|
||||||
|
let group = groups.find(x => x.name === connection.group)
|
||||||
|
if (!group) {
|
||||||
|
group = {
|
||||||
|
name: connection.group!,
|
||||||
|
connections: [],
|
||||||
|
}
|
||||||
|
groups.push(group!)
|
||||||
|
}
|
||||||
|
group.connections.push(connection)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const group of groups) {
|
||||||
|
for (const connection of group.connections) {
|
||||||
|
options.push({
|
||||||
|
name: (group.name ? `${group.name} / ` : '') + connection.name,
|
||||||
|
description: connection.host,
|
||||||
|
icon: 'desktop',
|
||||||
|
callback: () => this.connect(connection),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
options.push({
|
||||||
|
name: 'Manage connections',
|
||||||
|
icon: 'cog',
|
||||||
|
callback: () => this.app.openNewTab(SettingsTabComponent, { activeTab: 'ssh' }),
|
||||||
|
})
|
||||||
|
|
||||||
|
options.push({
|
||||||
|
name: 'Quick connect',
|
||||||
|
freeInputPattern: 'Connect to "%s"...',
|
||||||
|
icon: 'arrow-right',
|
||||||
|
callback: query => this.quickConnect(query),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
await this.app.showSelector('Open an SSH connection', options)
|
||||||
|
}
|
||||||
|
|
||||||
|
async connect (connection: SSHConnection): Promise<SSHTabComponent> {
|
||||||
|
try {
|
||||||
|
const tab = this.app.openNewTab(
|
||||||
|
SSHTabComponent,
|
||||||
|
{ connection }
|
||||||
|
) as SSHTabComponent
|
||||||
|
if (connection.color) {
|
||||||
|
(this.app.getParentTab(tab) || tab).color = connection.color
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.app.activeTab?.emitFocused()
|
||||||
|
})
|
||||||
|
|
||||||
|
return tab
|
||||||
|
} catch (error) {
|
||||||
|
this.toastr.error(`Could not connect: ${error}`)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quickConnect (query: string): Promise<SSHTabComponent> {
|
||||||
|
let user = 'root'
|
||||||
|
let host = query
|
||||||
|
let port = 22
|
||||||
|
if (host.includes('@')) {
|
||||||
|
[user, host] = host.split('@')
|
||||||
|
}
|
||||||
|
if (host.includes(':')) {
|
||||||
|
port = parseInt(host.split(':')[1])
|
||||||
|
host = host.split(':')[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
const connection: SSHConnection = {
|
||||||
|
name: query,
|
||||||
|
group: null,
|
||||||
|
host,
|
||||||
|
user,
|
||||||
|
port,
|
||||||
|
}
|
||||||
|
|
||||||
|
const recentConnections = this.config.store.ssh.recentConnections
|
||||||
|
recentConnections.unshift(connection)
|
||||||
|
if (recentConnections.length > 5) {
|
||||||
|
recentConnections.pop()
|
||||||
|
}
|
||||||
|
this.config.store.ssh.recentConnections = recentConnections
|
||||||
|
this.config.save()
|
||||||
|
return this.connect(connection)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user