diff --git a/tabby-core/src/api/index.ts b/tabby-core/src/api/index.ts index 0384396d..f74a647b 100644 --- a/tabby-core/src/api/index.ts +++ b/tabby-core/src/api/index.ts @@ -16,7 +16,7 @@ export { BootstrapData, PluginInfo, BOOTSTRAP_DATA } from './mainProcess' export { HostWindowService } from './hostWindow' export { HostAppService, Platform } from './hostApp' export { FileProvider } from './fileProvider' -export { ProfileProvider, Profile, PartialProfile, ProfileSettingsComponent } from './profileProvider' +export { ProfileProvider, ConnectableProfileProvider, Profile, ConnectableProfile, PartialProfile, ProfileSettingsComponent } from './profileProvider' export { PromptModalComponent } from '../components/promptModal.component' export * from './commands' diff --git a/tabby-core/src/api/profileProvider.ts b/tabby-core/src/api/profileProvider.ts index a6e6bdd6..31fa1f75 100644 --- a/tabby-core/src/api/profileProvider.ts +++ b/tabby-core/src/api/profileProvider.ts @@ -21,6 +21,9 @@ export interface Profile { isTemplate: boolean } +export interface ConnectableProfile extends Profile { +} + export type PartialProfile = Omit, 'type'>, 'name'> & { @@ -39,7 +42,6 @@ export interface ProfileSettingsComponent

{ export abstract class ProfileProvider

{ id: string name: string - supportsQuickConnect = false settingsComponent?: new (...args: any[]) => ProfileSettingsComponent

configDefaults = {} @@ -53,6 +55,11 @@ export abstract class ProfileProvider

{ abstract getDescription (profile: PartialProfile

): string + deleteProfile (profile: P): void { } +} + +export abstract class ConnectableProfileProvider

extends ProfileProvider

{ + quickConnect (query: string): PartialProfile

|null { return null } @@ -61,5 +68,4 @@ export abstract class ProfileProvider

{ return null } - deleteProfile (profile: P): void { } } diff --git a/tabby-core/src/index.ts b/tabby-core/src/index.ts index 6cf14a24..c6974784 100644 --- a/tabby-core/src/index.ts +++ b/tabby-core/src/index.ts @@ -37,7 +37,7 @@ import { FastHtmlBindDirective } from './directives/fastHtmlBind.directive' import { DropZoneDirective } from './directives/dropZone.directive' import { CdkAutoDropGroup } from './directives/cdkAutoDropGroup.directive' -import { Theme, CLIHandler, TabContextMenuItemProvider, TabRecoveryProvider, HotkeyProvider, ConfigProvider, PlatformService, FileProvider, ProfilesService, ProfileProvider, SelectorOption, Profile, SelectorService, CommandProvider } from './api' +import { Theme, CLIHandler, TabContextMenuItemProvider, TabRecoveryProvider, HotkeyProvider, ConfigProvider, PlatformService, FileProvider, ProfilesService, ProfileProvider, ConnectableProfileProvider, SelectorOption, Profile, SelectorService, CommandProvider } from './api' import { AppService } from './services/app.service' import { ConfigService } from './services/config.service' @@ -214,7 +214,7 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex callback: () => this.profilesService.openNewTabForProfile(p), })) - if (provider.supportsQuickConnect) { + if (provider instanceof ConnectableProfileProvider) { options.push({ name: this.translate.instant('Quick connect'), freeInputPattern: this.translate.instant('Connect to "%s"...'), diff --git a/tabby-core/src/services/profiles.service.ts b/tabby-core/src/services/profiles.service.ts index 943d11c2..931501f3 100644 --- a/tabby-core/src/services/profiles.service.ts +++ b/tabby-core/src/services/profiles.service.ts @@ -2,7 +2,7 @@ import { Injectable, Inject } from '@angular/core' import { TranslateService } from '@ngx-translate/core' import { NewTabParameters } from './tabs.service' import { BaseTabComponent } from '../components/baseTab.component' -import { PartialProfile, Profile, ProfileProvider } from '../api/profileProvider' +import { ConnectableProfileProvider, PartialProfile, Profile, ProfileProvider } from '../api/profileProvider' import { SelectorOption } from '../api/selector' import { AppService } from './app.service' import { configMerge, ConfigProxy, ConfigService } from './config.service' @@ -93,7 +93,7 @@ export class ProfilesService { selectorOptionForProfile

(profile: PartialProfile

): SelectorOption { const fullProfile = this.getConfigProxyForProfile(profile) const provider = this.providerForProfile(fullProfile) - const freeInputEquivalent = provider?.intoQuickConnectString(fullProfile) ?? undefined + const freeInputEquivalent = provider instanceof ConnectableProfileProvider ? provider.intoQuickConnectString(fullProfile) ?? undefined : undefined return { ...profile, // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing @@ -177,18 +177,20 @@ export class ProfilesService { }) } catch { } - this.getProviders().filter(x => x.supportsQuickConnect).forEach(provider => { - options.push({ - name: this.translate.instant('Quick connect'), - freeInputPattern: this.translate.instant('Connect to "%s"...'), - description: `(${provider.name.toUpperCase()})`, - icon: 'fas fa-arrow-right', - weight: provider.id !== this.config.store.defaultQuickConnectProvider ? 1 : 0, - callback: query => { - const profile = provider.quickConnect(query) - resolve(profile) - }, - }) + this.getProviders().forEach(provider => { + if (provider instanceof ConnectableProfileProvider) { + options.push({ + name: this.translate.instant('Quick connect'), + freeInputPattern: this.translate.instant('Connect to "%s"...'), + description: `(${provider.name.toUpperCase()})`, + icon: 'fas fa-arrow-right', + weight: provider.id !== this.config.store.defaultQuickConnectProvider ? 1 : 0, + callback: query => { + const profile = provider.quickConnect(query) + resolve(profile) + }, + }) + } }) await this.selector.show(this.translate.instant('Select profile or enter an address'), options) @@ -200,7 +202,7 @@ export class ProfilesService { async quickConnect (query: string): Promise|null> { for (const provider of this.getProviders()) { - if (provider.supportsQuickConnect) { + if (provider instanceof ConnectableProfileProvider) { const profile = provider.quickConnect(query) if (profile) { return profile diff --git a/tabby-serial/src/api.ts b/tabby-serial/src/api.ts index 64d46e68..bc9d741c 100644 --- a/tabby-serial/src/api.ts +++ b/tabby-serial/src/api.ts @@ -3,10 +3,10 @@ import { SerialPortStream } from '@serialport/stream' import { LogService, NotificationsService } from 'tabby-core' import { Subject, Observable } from 'rxjs' import { Injector, NgZone } from '@angular/core' -import { BaseSession, BaseTerminalProfile, InputProcessingOptions, InputProcessor, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor, UTF8SplitterMiddleware } from 'tabby-terminal' +import { BaseSession, ConnectableTerminalProfile, InputProcessingOptions, InputProcessor, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor, UTF8SplitterMiddleware } from 'tabby-terminal' import { SerialService } from './services/serial.service' -export interface SerialProfile extends BaseTerminalProfile { +export interface SerialProfile extends ConnectableTerminalProfile { options: SerialProfileOptions } diff --git a/tabby-serial/src/profiles.ts b/tabby-serial/src/profiles.ts index c6c5d5bf..cf31c229 100644 --- a/tabby-serial/src/profiles.ts +++ b/tabby-serial/src/profiles.ts @@ -2,14 +2,14 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker' import slugify from 'slugify' import deepClone from 'clone-deep' import { Injectable } from '@angular/core' -import { ProfileProvider, NewTabParameters, SelectorService, HostAppService, Platform, TranslateService } from 'tabby-core' +import { NewTabParameters, SelectorService, HostAppService, Platform, TranslateService, ConnectableProfileProvider } from 'tabby-core' import { SerialProfileSettingsComponent } from './components/serialProfileSettings.component' import { SerialTabComponent } from './components/serialTab.component' import { SerialService } from './services/serial.service' import { BAUD_RATES, SerialProfile } from './api' @Injectable({ providedIn: 'root' }) -export class SerialProfilesService extends ProfileProvider { +export class SerialProfilesService extends ConnectableProfileProvider { id = 'serial' name = _('Serial') settingsComponent = SerialProfileSettingsComponent diff --git a/tabby-settings/src/components/editProfileModal.component.pug b/tabby-settings/src/components/editProfileModal.component.pug index 7869099b..da86efdb 100644 --- a/tabby-settings/src/components/editProfileModal.component.pug +++ b/tabby-settings/src/components/editProfileModal.component.pug @@ -74,7 +74,7 @@ ) option(ngValue='auto', translate) Auto option(ngValue='keep', translate) Keep - option(*ngIf='profile.type == "serial" || profile.type == "telnet" || profile.type == "ssh"', ngValue='reconnect', translate) Reconnect + option(*ngIf='isConnectable()', ngValue='reconnect', translate) Reconnect option(ngValue='close', translate) Close .mb-4 diff --git a/tabby-settings/src/components/editProfileModal.component.ts b/tabby-settings/src/components/editProfileModal.component.ts index 90636672..e259a39a 100644 --- a/tabby-settings/src/components/editProfileModal.component.ts +++ b/tabby-settings/src/components/editProfileModal.component.ts @@ -2,7 +2,7 @@ import { Observable, OperatorFunction, debounceTime, map, distinctUntilChanged } from 'rxjs' import { Component, Input, ViewChild, ViewContainerRef, ComponentFactoryResolver, Injector } from '@angular/core' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' -import { ConfigProxy, ConfigService, Profile, ProfileProvider, ProfileSettingsComponent, ProfilesService, TAB_COLORS } from 'tabby-core' +import { ConfigProxy, ConfigService, Profile, ProfileProvider, ProfileSettingsComponent, ProfilesService, TAB_COLORS, ConnectableProfileProvider } from 'tabby-core' const iconsData = require('../../../tabby-core/src/icons.json') const iconsClassList = Object.keys(iconsData).map( @@ -95,4 +95,9 @@ export class EditProfileModalComponent

{ cancel () { this.modalInstance.dismiss() } + + isConnectable (): boolean { + return this.profileProvider instanceof ConnectableProfileProvider + } + } diff --git a/tabby-settings/src/components/profilesSettingsTab.component.ts b/tabby-settings/src/components/profilesSettingsTab.component.ts index 38898ae6..1ed3963b 100644 --- a/tabby-settings/src/components/profilesSettingsTab.component.ts +++ b/tabby-settings/src/components/profilesSettingsTab.component.ts @@ -4,7 +4,7 @@ import slugify from 'slugify' import deepClone from 'clone-deep' import { Component, Inject } from '@angular/core' import { NgbModal } from '@ng-bootstrap/ng-bootstrap' -import { ConfigService, HostAppService, Profile, SelectorService, ProfilesService, PromptModalComponent, PlatformService, BaseComponent, PartialProfile, ProfileProvider, TranslateService, Platform, AppHotkeyProvider } from 'tabby-core' +import { ConfigService, HostAppService, Profile, SelectorService, ProfilesService, PromptModalComponent, PlatformService, BaseComponent, PartialProfile, ProfileProvider, TranslateService, Platform, AppHotkeyProvider, ConnectableProfileProvider } from 'tabby-core' import { EditProfileModalComponent } from './editProfileModal.component' interface ProfileGroup { @@ -314,6 +314,6 @@ export class ProfilesSettingsTabComponent extends BaseComponent { } getQuickConnectProviders (): ProfileProvider[] { - return this.profileProviders.filter(x => x.supportsQuickConnect) + return this.profileProviders.filter(x => x instanceof ConnectableProfileProvider) } } diff --git a/tabby-ssh/src/api/interfaces.ts b/tabby-ssh/src/api/interfaces.ts index 901d5dd1..07a77a5c 100644 --- a/tabby-ssh/src/api/interfaces.ts +++ b/tabby-ssh/src/api/interfaces.ts @@ -1,4 +1,4 @@ -import { BaseTerminalProfile, InputProcessingOptions, LoginScriptsOptions } from 'tabby-terminal' +import { ConnectableTerminalProfile, InputProcessingOptions, LoginScriptsOptions } from 'tabby-terminal' export enum SSHAlgorithmType { HMAC = 'hmac', @@ -7,7 +7,7 @@ export enum SSHAlgorithmType { HOSTKEY = 'serverHostKey', } -export interface SSHProfile extends BaseTerminalProfile { +export interface SSHProfile extends ConnectableTerminalProfile { options: SSHProfileOptions } diff --git a/tabby-ssh/src/components/sshTab.component.ts b/tabby-ssh/src/components/sshTab.component.ts index b6c6d3eb..e7fd7815 100644 --- a/tabby-ssh/src/components/sshTab.component.ts +++ b/tabby-ssh/src/components/sshTab.component.ts @@ -83,7 +83,7 @@ export class SSHTabComponent extends ConnectableTerminalTabComponent const jumpSession = await this.setupOneSession( this.injector, - this.profilesService.getConfigProxyForProfile(jumpConnection), + this.profilesService.getConfigProxyForProfile(jumpConnection), ) jumpSession.ref() diff --git a/tabby-ssh/src/profiles.ts b/tabby-ssh/src/profiles.ts index 0952e713..0694de7e 100644 --- a/tabby-ssh/src/profiles.ts +++ b/tabby-ssh/src/profiles.ts @@ -1,5 +1,5 @@ import { Injectable, InjectFlags, Injector } from '@angular/core' -import { ProfileProvider, NewTabParameters, PartialProfile, TranslateService } from 'tabby-core' +import { NewTabParameters, PartialProfile, TranslateService, ConnectableProfileProvider } from 'tabby-core' import * as ALGORITHMS from 'ssh2/lib/protocol/constants' import { SSHProfileSettingsComponent } from './components/sshProfileSettings.component' import { SSHTabComponent } from './components/sshTab.component' @@ -8,10 +8,9 @@ import { ALGORITHM_BLACKLIST, SSHAlgorithmType, SSHProfile } from './api' import { SSHProfileImporter } from './api/importer' @Injectable({ providedIn: 'root' }) -export class SSHProfilesService extends ProfileProvider { +export class SSHProfilesService extends ConnectableProfileProvider { id = 'ssh' name = 'SSH' - supportsQuickConnect = true settingsComponent = SSHProfileSettingsComponent configDefaults = { options: { diff --git a/tabby-ssh/src/services/sshMultiplexer.service.ts b/tabby-ssh/src/services/sshMultiplexer.service.ts index 2665187e..775e20fa 100644 --- a/tabby-ssh/src/services/sshMultiplexer.service.ts +++ b/tabby-ssh/src/services/sshMultiplexer.service.ts @@ -34,7 +34,7 @@ export class SSHMultiplexerService { if (!jumpConnection) { return key } - const jumpProfile = this.profilesService.getConfigProxyForProfile(jumpConnection) + const jumpProfile = this.profilesService.getConfigProxyForProfile(jumpConnection) key += '$' + await this.getMultiplexerKey(jumpProfile) } return key diff --git a/tabby-telnet/src/profiles.ts b/tabby-telnet/src/profiles.ts index fad4f8ce..a88ea0a2 100644 --- a/tabby-telnet/src/profiles.ts +++ b/tabby-telnet/src/profiles.ts @@ -1,11 +1,11 @@ import { Injectable } from '@angular/core' -import { ProfileProvider, NewTabParameters, PartialProfile, TranslateService } from 'tabby-core' +import { NewTabParameters, PartialProfile, TranslateService, ConnectableProfileProvider } from 'tabby-core' import { TelnetProfileSettingsComponent } from './components/telnetProfileSettings.component' import { TelnetTabComponent } from './components/telnetTab.component' import { TelnetProfile } from './session' @Injectable({ providedIn: 'root' }) -export class TelnetProfilesService extends ProfileProvider { +export class TelnetProfilesService extends ConnectableProfileProvider { id = 'telnet' name = 'Telnet' supportsQuickConnect = true diff --git a/tabby-telnet/src/session.ts b/tabby-telnet/src/session.ts index 27c2cc27..1200d1c3 100644 --- a/tabby-telnet/src/session.ts +++ b/tabby-telnet/src/session.ts @@ -3,11 +3,11 @@ import colors from 'ansi-colors' import stripAnsi from 'strip-ansi' import { Injector } from '@angular/core' import { LogService } from 'tabby-core' -import { BaseSession, BaseTerminalProfile, InputProcessingOptions, InputProcessor, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor } from 'tabby-terminal' +import { BaseSession, ConnectableTerminalProfile, InputProcessingOptions, InputProcessor, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor } from 'tabby-terminal' import { Subject, Observable } from 'rxjs' -export interface TelnetProfile extends BaseTerminalProfile { +export interface TelnetProfile extends ConnectableTerminalProfile { options: TelnetProfileOptions } diff --git a/tabby-terminal/src/api/connectableTerminalTab.component.ts b/tabby-terminal/src/api/connectableTerminalTab.component.ts index 97560ec1..21abaa91 100644 --- a/tabby-terminal/src/api/connectableTerminalTab.component.ts +++ b/tabby-terminal/src/api/connectableTerminalTab.component.ts @@ -4,7 +4,7 @@ import { Injector, Component } from '@angular/core' import { first } from 'rxjs' -import { BaseTerminalProfile } from './interfaces' +import { ConnectableTerminalProfile } from './interfaces' import { BaseTerminalTabComponent } from './baseTerminalTab.component' import { GetRecoveryTokenOptions, RecoveryToken } from 'tabby-core' @@ -13,7 +13,7 @@ import { GetRecoveryTokenOptions, RecoveryToken } from 'tabby-core' * A class to base your custom connectable terminal tabs on */ @Component({ template: '' }) -export abstract class ConnectableTerminalTabComponent

extends BaseTerminalTabComponent

{ +export abstract class ConnectableTerminalTabComponent

extends BaseTerminalTabComponent

{ protected reconnectOffered = false protected isDisconnectedByHand = false diff --git a/tabby-terminal/src/api/interfaces.ts b/tabby-terminal/src/api/interfaces.ts index 74143339..eb61a8f1 100644 --- a/tabby-terminal/src/api/interfaces.ts +++ b/tabby-terminal/src/api/interfaces.ts @@ -1,4 +1,4 @@ -import { Profile } from 'tabby-core' +import { ConnectableProfile, Profile } from 'tabby-core' export interface ResizeEvent { columns: number @@ -19,3 +19,5 @@ export interface TerminalColorScheme { export interface BaseTerminalProfile extends Profile { terminalColorScheme?: TerminalColorScheme } + +export interface ConnectableTerminalProfile extends BaseTerminalProfile, ConnectableProfile {}