From b0600b10cc25182332b2fb1b26b0d10dc4132ad7 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Mon, 5 Dec 2022 12:03:08 +0100 Subject: [PATCH] support for providing commands as toolbar buttons --- tabby-core/src/api/commands.ts | 45 +++++++++++++++++-- tabby-core/src/api/toolbarButtonProvider.ts | 7 --- .../src/{buttonProvider.ts => commands.ts} | 28 +++++------- .../src/components/appRoot.component.pug | 34 +++----------- .../src/components/appRoot.component.ts | 39 +++++----------- .../src/components/baseTab.component.ts | 8 +++- .../src/components/selectorModal.component.ts | 2 +- .../src/components/splitTab.component.ts | 7 ++- .../src/components/startPage.component.pug | 8 ++-- .../src/components/startPage.component.ts | 26 +++++------ .../src/components/welcomeTab.component.ts | 5 ++- tabby-core/src/index.ts | 12 +++-- tabby-core/src/services/commands.service.ts | 21 ++++++--- .../components/releaseNotesTab.component.ts | 6 +-- .../src/components/settingsTab.component.ts | 5 ++- tabby-telnet/package.json | 1 + tabby-telnet/yarn.lock | 5 +++ .../src/api/baseTerminalTab.component.ts | 2 +- 18 files changed, 133 insertions(+), 128 deletions(-) rename tabby-core/src/{buttonProvider.ts => commands.ts} (64%) diff --git a/tabby-core/src/api/commands.ts b/tabby-core/src/api/commands.ts index e3d278b0..b217a11a 100644 --- a/tabby-core/src/api/commands.ts +++ b/tabby-core/src/api/commands.ts @@ -2,21 +2,51 @@ import { BaseTabComponent } from '../components/baseTab.component' import { MenuItemOptions } from './menu' import { ToolbarButton } from './toolbarButtonProvider' +export enum CommandLocation { + LeftToolbar = 'left-toolbar', + RightToolbar = 'right-toolbar', + StartPage = 'start-page', +} + export class Command { + id?: string label: string sublabel?: string - click?: () => void + locations?: CommandLocation[] + run: () => Promise /** * Raw SVG icon code */ icon?: string + /** + * Optional Touch Bar icon ID + */ + touchBarNSImage?: string + + /** + * Optional Touch Bar button label + */ + touchBarTitle?: string + + weight?: number + static fromToolbarButton (button: ToolbarButton): Command { const command = new Command() - command.label = button.commandLabel ?? button.title - command.click = button.click + command.label = button.title + command.run = async () => button.click?.() command.icon = button.icon + command.locations = [CommandLocation.StartPage] + if ((button.weight ?? 0) <= 0) { + command.locations.push(CommandLocation.LeftToolbar) + } + if ((button.weight ?? 0) > 0) { + command.locations.push(CommandLocation.RightToolbar) + } + command.touchBarNSImage = button.touchBarNSImage + command.touchBarTitle = button.touchBarTitle + command.weight = button.weight return command } @@ -24,7 +54,7 @@ export class Command { const command = new Command() command.label = item.commandLabel ?? item.label ?? '' command.sublabel = item.sublabel - command.click = item.click + command.run = async () => item.click?.() return command } } @@ -32,3 +62,10 @@ export class Command { export interface CommandContext { tab?: BaseTabComponent, } + +/** + * Extend to add commands + */ +export abstract class CommandProvider { + abstract provide (context: CommandContext): Promise +} diff --git a/tabby-core/src/api/toolbarButtonProvider.ts b/tabby-core/src/api/toolbarButtonProvider.ts index 8243cda6..a30b9987 100644 --- a/tabby-core/src/api/toolbarButtonProvider.ts +++ b/tabby-core/src/api/toolbarButtonProvider.ts @@ -27,13 +27,6 @@ export interface ToolbarButton { /** @hidden */ submenuItems?: ToolbarButton[] - - showInToolbar?: boolean - - showInStartPage?: boolean - - /** @hidden */ - commandLabel?: string } /** diff --git a/tabby-core/src/buttonProvider.ts b/tabby-core/src/commands.ts similarity index 64% rename from tabby-core/src/buttonProvider.ts rename to tabby-core/src/commands.ts index ff76026b..e7e71b04 100644 --- a/tabby-core/src/buttonProvider.ts +++ b/tabby-core/src/commands.ts @@ -2,26 +2,19 @@ import { Injectable } from '@angular/core' import { TranslateService } from '@ngx-translate/core' -import { ToolbarButton, ToolbarButtonProvider } from './api/toolbarButtonProvider' import { HostAppService, Platform } from './api/hostApp' -import { HotkeysService } from './services/hotkeys.service' import { ProfilesService } from './services/profiles.service' +import { CommandProvider, Command, CommandLocation } from './api/commands' /** @hidden */ -@Injectable() -export class ButtonProvider extends ToolbarButtonProvider { +@Injectable({ providedIn: 'root' }) +export class CoreCommandProvider extends CommandProvider { constructor ( private hostApp: HostAppService, private profilesService: ProfilesService, private translate: TranslateService, - hotkeys: HotkeysService, ) { super() - hotkeys.hotkey$.subscribe(hotkey => { - if (hotkey === 'profile-selector') { - this.activate() - } - }) } async activate () { @@ -31,21 +24,22 @@ export class ButtonProvider extends ToolbarButtonProvider { } } - provide (): ToolbarButton[] { + async provide (): Promise { return [ { + id: 'profile-selector', + locations: [CommandLocation.LeftToolbar, CommandLocation.StartPage], + label: this.translate.instant('Profiles & connections'), icon: this.hostApp.platform === Platform.Web ? require('./icons/plus.svg') : require('./icons/profiles.svg'), - title: this.translate.instant('Profiles & connections'), - click: () => this.activate(), + run: async () => this.activate(), }, ...this.profilesService.getRecentProfiles().map(profile => ({ + label: profile.name, + locations: [CommandLocation.StartPage], icon: require('./icons/history.svg'), - title: profile.name, - showInToolbar: false, - showinStartPage: true, - click: async () => { + run: async () => { const p = (await this.profilesService.getProfiles()).find(x => x.id === profile.id) ?? profile this.profilesService.launchProfile(p) }, diff --git a/tabby-core/src/components/appRoot.component.pug b/tabby-core/src/components/appRoot.component.pug index eeb3ff3a..0533ce35 100644 --- a/tabby-core/src/components/appRoot.component.pug +++ b/tabby-core/src/components/appRoot.component.pug @@ -38,26 +38,14 @@ title-bar( .btn-group.background .d-flex( *ngFor='let button of leftToolbarButtons', - ngbDropdown, - (openChange)='generateButtonSubmenu(button)', + ngbDropdown ) button.btn.btn-secondary.btn-tab-bar( - [title]='button.title', - (click)='button.click && button.click()', + [title]='button.label', + (click)='button.run && button.run()', [fastHtmlBind]='button.icon', ngbDropdownToggle, ) - div(*ngIf='button.submenu', ngbDropdownMenu) - button.dropdown-item.d-flex.align-items-center( - *ngFor='let item of button.submenuItems', - (click)='item.click()', - ngbDropdownItem, - ) - .icon-wrapper( - *ngIf='hasIcons(button.submenuItems)', - [fastHtmlBind]='item.icon' - ) - div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} .d-flex( ngbDropdown, @@ -80,26 +68,14 @@ title-bar( .btn-group.background .d-flex( *ngFor='let button of rightToolbarButtons', - ngbDropdown, - (openChange)='generateButtonSubmenu(button)', + ngbDropdown ) button.btn.btn-secondary.btn-tab-bar( [title]='button.title', - (click)='button.click && button.click()', + (click)='button.run && button.run()', [fastHtmlBind]='button.icon', ngbDropdownToggle, ) - div(*ngIf='button.submenu', ngbDropdownMenu) - button.dropdown-item.d-flex.align-items-center( - *ngFor='let item of button.submenuItems', - (click)='item.click()', - ngbDropdownItem, - ) - .icon-wrapper( - *ngIf='hasIcons(button.submenuItems)', - [fastHtmlBind]='item.icon' - ) - div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} button.btn.btn-secondary.btn-tab-bar.btn-update( *ngIf='updatesAvailable', diff --git a/tabby-core/src/components/appRoot.component.ts b/tabby-core/src/components/appRoot.component.ts index 6384a909..cd51c9d9 100644 --- a/tabby-core/src/components/appRoot.component.ts +++ b/tabby-core/src/components/appRoot.component.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -import { Component, Inject, Input, HostListener, HostBinding, ViewChildren, ViewChild } from '@angular/core' +import { Component, Input, HostListener, HostBinding, ViewChildren, ViewChild } from '@angular/core' import { trigger, style, animate, transition, state } from '@angular/animations' import { NgbDropdown, NgbModal } from '@ng-bootstrap/ng-bootstrap' import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop' @@ -10,12 +10,13 @@ import { Logger, LogService } from '../services/log.service' import { ConfigService } from '../services/config.service' import { ThemesService } from '../services/themes.service' import { UpdaterService } from '../services/updater.service' +import { CommandService } from '../services/commands.service' import { BaseTabComponent } from './baseTab.component' import { SafeModeModalComponent } from './safeModeModal.component' import { TabBodyComponent } from './tabBody.component' import { SplitTabComponent } from './splitTab.component' -import { AppService, FileTransfer, HostWindowService, PlatformService, ToolbarButton, ToolbarButtonProvider } from '../api' +import { AppService, Command, CommandLocation, FileTransfer, HostWindowService, PlatformService } from '../api' function makeTabAnimation (dimension: string, size: number) { return [ @@ -63,8 +64,8 @@ function makeTabAnimation (dimension: string, size: number) { export class AppRootComponent { Platform = Platform @Input() ready = false - @Input() leftToolbarButtons: ToolbarButton[] - @Input() rightToolbarButtons: ToolbarButton[] + @Input() leftToolbarButtons: Command[] + @Input() rightToolbarButtons: Command[] @HostBinding('class.platform-win32') platformClassWindows = process.platform === 'win32' @HostBinding('class.platform-darwin') platformClassMacOS = process.platform === 'darwin' @HostBinding('class.platform-linux') platformClassLinux = process.platform === 'linux' @@ -79,11 +80,11 @@ export class AppRootComponent { constructor ( private hotkeys: HotkeysService, private updater: UpdaterService, + private commands: CommandService, public hostWindow: HostWindowService, public hostApp: HostAppService, public config: ConfigService, public app: AppService, - @Inject(ToolbarButtonProvider) private toolbarButtonProviders: ToolbarButtonProvider[], platform: PlatformService, log: LogService, ngbModal: NgbModal, @@ -170,9 +171,9 @@ export class AppRootComponent { this.activeTransfersDropdown.open() }) - config.ready$.toPromise().then(() => { - this.leftToolbarButtons = this.getToolbarButtons(false) - this.rightToolbarButtons = this.getToolbarButtons(true) + config.ready$.toPromise().then(async () => { + this.leftToolbarButtons = await this.getToolbarButtons(false) + this.rightToolbarButtons = await this.getToolbarButtons(true) setInterval(() => { if (this.config.store.enableAutomaticUpdates) { @@ -212,16 +213,6 @@ export class AppRootComponent { return this.config.store.appearance.flexTabs ? '*' : '200px' } - async generateButtonSubmenu (button: ToolbarButton) { - if (button.submenu) { - button.submenuItems = await button.submenu() - } - } - - hasIcons (submenuItems: ToolbarButton[]): boolean { - return submenuItems.some(x => !!x.icon) - } - onTabsReordered (event: CdkDragDrop) { const tab: BaseTabComponent = event.item.data if (!this.app.tabs.includes(tab)) { @@ -244,14 +235,8 @@ export class AppRootComponent { return this.config.store?.appearance.vibrancy } - private getToolbarButtons (aboveZero: boolean): ToolbarButton[] { - let buttons: ToolbarButton[] = [] - this.config.enabledServices(this.toolbarButtonProviders).forEach(provider => { - buttons = buttons.concat(provider.provide()) - }) - return buttons - .filter(x => x.showInToolbar ?? true) - .filter(button => (button.weight ?? 0) > 0 === aboveZero) - .sort((a: ToolbarButton, b: ToolbarButton) => (a.weight ?? 0) - (b.weight ?? 0)) + private async getToolbarButtons (aboveZero: boolean): Promise { + return (await this.commands.getCommands({ tab: this.app.activeTab ?? undefined })) + .filter(x => x.locations?.includes(aboveZero ? CommandLocation.RightToolbar : CommandLocation.LeftToolbar)) } } diff --git a/tabby-core/src/components/baseTab.component.ts b/tabby-core/src/components/baseTab.component.ts index 59a463ad..20bacd7e 100644 --- a/tabby-core/src/components/baseTab.component.ts +++ b/tabby-core/src/components/baseTab.component.ts @@ -1,7 +1,8 @@ import { Observable, Subject, distinctUntilChanged, filter, debounceTime } from 'rxjs' -import { EmbeddedViewRef, ViewContainerRef, ViewRef } from '@angular/core' +import { EmbeddedViewRef, Injector, ViewContainerRef, ViewRef } from '@angular/core' import { RecoveryToken } from '../api/tabRecovery' import { BaseComponent } from './base.component' +import { ConfigService } from '../services/config.service' /** * Represents an active "process" inside a tab, @@ -87,8 +88,11 @@ export abstract class BaseTabComponent extends BaseComponent { get destroyed$ (): Observable { return this.destroyed } get recoveryStateChangedHint$ (): Observable { return this.recoveryStateChangedHint } - protected constructor () { + protected config: ConfigService + + protected constructor (injector: Injector) { super() + this.config = injector.get(ConfigService) this.focused$.subscribe(() => { this.hasFocus = true }) diff --git a/tabby-core/src/components/selectorModal.component.ts b/tabby-core/src/components/selectorModal.component.ts index 13a328b2..0236d2d6 100644 --- a/tabby-core/src/components/selectorModal.component.ts +++ b/tabby-core/src/components/selectorModal.component.ts @@ -97,8 +97,8 @@ export class SelectorModalComponent { } selectOption (option: SelectorOption): void { - option.callback?.(this.filter) this.modalInstance.close(option.result) + setTimeout(() => option.callback?.(this.filter)) } canEditSelected (): boolean { diff --git a/tabby-core/src/components/splitTab.component.ts b/tabby-core/src/components/splitTab.component.ts index 9f22c137..0f398d40 100644 --- a/tabby-core/src/components/splitTab.component.ts +++ b/tabby-core/src/components/splitTab.component.ts @@ -1,11 +1,10 @@ import { Observable, Subject } from 'rxjs' -import { Component, Injectable, ViewChild, ViewContainerRef, EmbeddedViewRef, AfterViewInit, OnDestroy } from '@angular/core' +import { Component, Injectable, ViewChild, ViewContainerRef, EmbeddedViewRef, AfterViewInit, OnDestroy, Injector } from '@angular/core' import { BaseTabComponent, BaseTabProcess, GetRecoveryTokenOptions } from './baseTab.component' import { TabRecoveryProvider, RecoveryToken } from '../api/tabRecovery' import { TabsService, NewTabParameters } from '../services/tabs.service' import { HotkeysService } from '../services/hotkeys.service' import { TabRecoveryService } from '../services/tabRecovery.service' -import { ConfigService } from '../api' export type SplitOrientation = 'v' | 'h' export type SplitDirection = 'r' | 't' | 'b' | 'l' @@ -261,9 +260,9 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit private hotkeys: HotkeysService, private tabsService: TabsService, private tabRecovery: TabRecoveryService, - private config: ConfigService, + injector: Injector, ) { - super() + super(injector) this.root = new SplitContainer() this.setTitle('') diff --git a/tabby-core/src/components/startPage.component.pug b/tabby-core/src/components/startPage.component.pug index 4580451e..77b9546b 100644 --- a/tabby-core/src/components/startPage.component.pug +++ b/tabby-core/src/components/startPage.component.pug @@ -5,11 +5,11 @@ div .list-group.mb-4 a.list-group-item.list-group-item-action.d-flex( - *ngFor='let button of getButtons(); trackBy: buttonsTrackBy', - (click)='button.click()', + *ngFor='let command of commands; trackBy: buttonsTrackBy', + (click)='command.run()', ) - .d-flex.align-self-center([innerHTML]='sanitizeIcon(button.icon)') - span {{button.title}} + .d-flex.align-self-center([innerHTML]='sanitizeIcon(command.icon)') + span {{command.label}} footer.d-flex.align-items-center .btn-group.mr-auto diff --git a/tabby-core/src/components/startPage.component.ts b/tabby-core/src/components/startPage.component.ts index 60fc7ca1..07dca71d 100644 --- a/tabby-core/src/components/startPage.component.ts +++ b/tabby-core/src/components/startPage.component.ts @@ -1,8 +1,8 @@ -import { Component, Inject } from '@angular/core' +import { Component } from '@angular/core' import { DomSanitizer } from '@angular/platform-browser' -import { ConfigService } from '../services/config.service' import { HomeBaseService } from '../services/homeBase.service' -import { ToolbarButton, ToolbarButtonProvider } from '../api' +import { CommandService } from '../services/commands.service' +import { Command, CommandLocation } from '../api/commands' /** @hidden */ @Component({ @@ -12,29 +12,23 @@ import { ToolbarButton, ToolbarButtonProvider } from '../api' }) export class StartPageComponent { version: string + commands: Command[] = [] constructor ( - private config: ConfigService, private domSanitizer: DomSanitizer, public homeBase: HomeBaseService, - @Inject(ToolbarButtonProvider) private toolbarButtonProviders: ToolbarButtonProvider[], + commands: CommandService, ) { - } - - getButtons (): ToolbarButton[] { - return this.config.enabledServices(this.toolbarButtonProviders) - .map(provider => provider.provide()) - .reduce((a, b) => a.concat(b)) - .filter(x => x.showInStartPage ?? true) - .filter(x => !!x.click) - .sort((a: ToolbarButton, b: ToolbarButton) => (a.weight ?? 0) - (b.weight ?? 0)) + commands.getCommands({}).then(c => { + this.commands = c.filter(x => x.locations?.includes(CommandLocation.StartPage)) + }) } sanitizeIcon (icon?: string): any { return this.domSanitizer.bypassSecurityTrustHtml(icon ?? '') } - buttonsTrackBy (btn: ToolbarButton): any { - return btn.title + btn.icon + buttonsTrackBy (btn: Command): any { + return btn.label + btn.icon } } diff --git a/tabby-core/src/components/welcomeTab.component.ts b/tabby-core/src/components/welcomeTab.component.ts index 83814dee..43b71a1d 100644 --- a/tabby-core/src/components/welcomeTab.component.ts +++ b/tabby-core/src/components/welcomeTab.component.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -import { Component } from '@angular/core' +import { Component, Injector } from '@angular/core' import { TranslateService } from '@ngx-translate/core' import { BaseTabComponent } from './baseTab.component' import { ConfigService } from '../services/config.service' @@ -19,8 +19,9 @@ export class WelcomeTabComponent extends BaseTabComponent { public config: ConfigService, public locale: LocaleService, translate: TranslateService, + injector: Injector, ) { - super() + super(injector) this.setTitle(translate.instant('Welcome')) } diff --git a/tabby-core/src/index.ts b/tabby-core/src/index.ts index f5e8e2b4..a05bc691 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, ToolbarButtonProvider, ProfilesService, ProfileProvider, SelectorOption, Profile, SelectorService } from './api' +import { Theme, CLIHandler, TabContextMenuItemProvider, TabRecoveryProvider, HotkeyProvider, ConfigProvider, PlatformService, FileProvider, ProfilesService, ProfileProvider, SelectorOption, Profile, SelectorService, CommandProvider } from './api' import { AppService } from './services/app.service' import { ConfigService } from './services/config.service' @@ -51,8 +51,8 @@ import { CoreConfigProvider } from './config' import { AppHotkeyProvider } from './hotkeys' import { TaskCompletionContextMenu, CommonOptionsContextMenu, TabManagementContextMenu, ProfilesContextMenu } from './tabContextMenu' import { LastCLIHandler, ProfileCLIHandler } from './cli' -import { ButtonProvider } from './buttonProvider' import { SplitLayoutProfilesService } from './profiles' +import { CoreCommandProvider } from './commands' import 'perfect-scrollbar/css/perfect-scrollbar.css' @@ -75,8 +75,8 @@ const PROVIDERS = [ { provide: CLIHandler, useClass: LastCLIHandler, multi: true }, { provide: PERFECT_SCROLLBAR_CONFIG, useValue: { suppressScrollX: true } }, { provide: FileProvider, useClass: VaultFileProvider, multi: true }, - { provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true }, { provide: ProfileProvider, useExisting: SplitLayoutProfilesService, multi: true }, + { provide: CommandProvider, useExisting: CoreCommandProvider, multi: true }, { provide: LOCALE_ID, deps: [LocaleService], @@ -180,7 +180,7 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex console.error('Unhandled exception:', err) }) - hotkeys.hotkey$.subscribe(async (hotkey) => { + hotkeys.hotkey$.subscribe(async hotkey => { if (hotkey.startsWith('profile.')) { const id = hotkey.substring(hotkey.indexOf('.') + 1) const profiles = await profilesService.getProfiles() @@ -200,6 +200,10 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex if (hotkey === 'command-selector') { commands.showSelector() } + + if (hotkey === 'profile-selector') { + commands.run('profile-selector', {}) + } }) } diff --git a/tabby-core/src/services/commands.service.ts b/tabby-core/src/services/commands.service.ts index fccef840..64fa78d7 100644 --- a/tabby-core/src/services/commands.service.ts +++ b/tabby-core/src/services/commands.service.ts @@ -1,5 +1,5 @@ import { Inject, Injectable, Optional } from '@angular/core' -import { AppService, Command, CommandContext, ConfigService, MenuItemOptions, SplitTabComponent, TabContextMenuItemProvider, ToolbarButton, ToolbarButtonProvider, TranslateService } from '../api' +import { AppService, Command, CommandContext, CommandProvider, ConfigService, MenuItemOptions, SplitTabComponent, TabContextMenuItemProvider, ToolbarButton, ToolbarButtonProvider, TranslateService } from '../api' import { SelectorService } from './selector.service' @Injectable({ providedIn: 'root' }) @@ -11,6 +11,7 @@ export class CommandService { private translate: TranslateService, @Optional() @Inject(TabContextMenuItemProvider) protected contextMenuProviders: TabContextMenuItemProvider[], @Inject(ToolbarButtonProvider) private toolbarButtonProviders: ToolbarButtonProvider[], + @Inject(CommandProvider) private commandProviders: CommandProvider[], ) { this.contextMenuProviders.sort((a, b) => a.weight - b.weight) } @@ -60,10 +61,20 @@ export class CommandService { } items.forEach(x => flattenItem(x)) - let commands = buttons.map(x => Command.fromToolbarButton(x)) - commands = commands.concat(flatItems.map(x => Command.fromMenuItem(x))) + const commands = buttons.map(x => Command.fromToolbarButton(x)) + commands.push(...flatItems.map(x => Command.fromMenuItem(x))) - return commands + for (const provider of this.config.enabledServices(this.commandProviders)) { + commands.push(...await provider.provide(context)) + } + + return commands.sort((a, b) => (a.weight ?? 0) - (b.weight ?? 0)) + } + + async run (id: string, context: CommandContext): Promise { + const commands = await this.getCommands(context) + const command = commands.find(x => x.id === id) + await command?.run() } async showSelector (): Promise { @@ -81,7 +92,7 @@ export class CommandService { this.translate.instant('Commands'), commands.map(c => ({ name: c.label, - callback: c.click, + callback: c.run, description: c.sublabel, icon: c.icon, })), diff --git a/tabby-settings/src/components/releaseNotesTab.component.ts b/tabby-settings/src/components/releaseNotesTab.component.ts index 123a0e7c..d8e85d56 100644 --- a/tabby-settings/src/components/releaseNotesTab.component.ts +++ b/tabby-settings/src/components/releaseNotesTab.component.ts @@ -2,7 +2,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker' import axios from 'axios' import { marked } from 'marked' -import { Component } from '@angular/core' +import { Component, Injector } from '@angular/core' import { BaseTabComponent, TranslateService } from 'tabby-core' export interface Release { @@ -22,8 +22,8 @@ export class ReleaseNotesComponent extends BaseTabComponent { releases: Release[] = [] lastPage = 1 - constructor (translate: TranslateService) { - super() + constructor (translate: TranslateService, injector: Injector) { + super(injector) this.setTitle(translate.instant(_('Release notes'))) this.loadReleases(1) } diff --git a/tabby-settings/src/components/settingsTab.component.ts b/tabby-settings/src/components/settingsTab.component.ts index 913b2c12..2e370d7e 100644 --- a/tabby-settings/src/components/settingsTab.component.ts +++ b/tabby-settings/src/components/settingsTab.component.ts @@ -2,7 +2,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker' import * as yaml from 'js-yaml' import { debounce } from 'utils-decorators/dist/esm/debounce/debounce' -import { Component, Inject, Input, HostBinding, NgZone } from '@angular/core' +import { Component, Inject, Input, HostBinding, NgZone, Injector } from '@angular/core' import { ConfigService, BaseTabComponent, @@ -52,8 +52,9 @@ export class SettingsTabComponent extends BaseTabComponent { private app: AppService, @Inject(SettingsTabProvider) public settingsProviders: SettingsTabProvider[], translate: TranslateService, + injector: Injector, ) { - super() + super(injector) this.setTitle(translate.instant(_('Settings'))) this.settingsProviders = config.enabledServices(this.settingsProviders) this.settingsProviders = this.settingsProviders.filter(x => !!x.getComponentType()) diff --git a/tabby-telnet/package.json b/tabby-telnet/package.json index 6d26b4ca..c2ede496 100644 --- a/tabby-telnet/package.json +++ b/tabby-telnet/package.json @@ -17,6 +17,7 @@ "author": "Eugene Pankov", "license": "MIT", "devDependencies": { + "ansi-colors": "^4.1.1", "@types/node": "14.14.31" }, "peerDependencies": { diff --git a/tabby-telnet/yarn.lock b/tabby-telnet/yarn.lock index 0bf88e60..20e4d9ee 100644 --- a/tabby-telnet/yarn.lock +++ b/tabby-telnet/yarn.lock @@ -6,3 +6,8 @@ version "14.14.31" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055" integrity sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g== + +ansi-colors@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== diff --git a/tabby-terminal/src/api/baseTerminalTab.component.ts b/tabby-terminal/src/api/baseTerminalTab.component.ts index 369bcd7f..c826f333 100644 --- a/tabby-terminal/src/api/baseTerminalTab.component.ts +++ b/tabby-terminal/src/api/baseTerminalTab.component.ts @@ -175,7 +175,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit get sessionChanged$ (): Observable { return this.sessionChanged } constructor (protected injector: Injector) { - super() + super(injector) this.config = injector.get(ConfigService) this.element = injector.get(ElementRef)