This commit is contained in:
Eugene Pankov
2020-03-01 16:10:45 +01:00
parent fda4d2dcef
commit 04a0a0cc64
81 changed files with 284 additions and 295 deletions

View File

@@ -31,7 +31,7 @@ export class Application {
} }
} }
init () { init (): void {
electron.screen.on('display-metrics-changed', () => this.broadcast('host:display-metrics-changed')) electron.screen.on('display-metrics-changed', () => this.broadcast('host:display-metrics-changed'))
} }
@@ -52,20 +52,20 @@ export class Application {
return window return window
} }
broadcast (event, ...args) { broadcast (event: string, ...args): void {
for (let window of this.windows) { for (const window of this.windows) {
window.send(event, ...args) window.send(event, ...args)
} }
} }
async send (event, ...args) { async send (event: string, ...args): void {
if (!this.hasWindows()) { if (!this.hasWindows()) {
await this.newWindow() await this.newWindow()
} }
this.windows.filter(w => !w.isDestroyed())[0].send(event, ...args) this.windows.filter(w => !w.isDestroyed())[0].send(event, ...args)
} }
enableTray () { enableTray (): void {
if (this.tray) { if (this.tray) {
return return
} }
@@ -90,18 +90,18 @@ export class Application {
this.tray.setToolTip(`Terminus ${app.getVersion()}`) this.tray.setToolTip(`Terminus ${app.getVersion()}`)
} }
disableTray () { disableTray (): void {
if (this.tray) { if (this.tray) {
this.tray.destroy() this.tray.destroy()
this.tray = null this.tray = null
} }
} }
hasWindows () { hasWindows (): bool {
return !!this.windows.length return !!this.windows.length
} }
focus () { focus (): void {
for (let window of this.windows) { for (let window of this.windows) {
window.show() window.show()
} }

View File

@@ -1,6 +1,6 @@
import { app } from 'electron' import { app } from 'electron'
export function parseArgs (argv, cwd) { export function parseArgs (argv: string[], cwd: string): any {
if (argv[0].includes('node')) { if (argv[0].includes('node')) {
argv = argv.slice(1) argv = argv.slice(1)
} }

View File

@@ -119,7 +119,7 @@ export class Window {
}) })
} }
setVibrancy (enabled: boolean, type?: string) { setVibrancy (enabled: boolean, type?: string): void {
this.lastVibrancy = { enabled, type } this.lastVibrancy = { enabled, type }
if (process.platform === 'win32') { if (process.platform === 'win32') {
if (parseFloat(os.release()) >= 10) { if (parseFloat(os.release()) >= 10) {
@@ -140,22 +140,22 @@ export class Window {
} }
} }
show () { show (): void {
this.window.show() this.window.show()
} }
focus () { focus (): void {
this.window.focus() this.window.focus()
} }
send (event, ...args) { send (event: string, ...args): void {
if (!this.window) { if (!this.window) {
return return
} }
this.window.webContents.send(event, ...args) this.window.webContents.send(event, ...args)
} }
isDestroyed () { isDestroyed (): void {
return !this.window || this.window.isDestroyed() return !this.window || this.window.isDestroyed()
} }

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { NgModule } from '@angular/core' import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser' import { BrowserModule } from '@angular/platform-browser'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap' import { NgbModule } from '@ng-bootstrap/ng-bootstrap'

View File

@@ -1,7 +1,7 @@
export { BaseTabComponent, BaseTabProcess } from '../components/baseTab.component' export { BaseTabComponent, BaseTabProcess } from '../components/baseTab.component'
export { TabHeaderComponent } from '../components/tabHeader.component' export { TabHeaderComponent } from '../components/tabHeader.component'
export { SplitTabComponent, SplitContainer } from '../components/splitTab.component' export { SplitTabComponent, SplitContainer } from '../components/splitTab.component'
export { TabRecoveryProvider, RecoveredTab } from './tabRecovery' export { TabRecoveryProvider, RecoveredTab, RecoveryToken } from './tabRecovery'
export { ToolbarButtonProvider, ToolbarButton } from './toolbarButtonProvider' export { ToolbarButtonProvider, ToolbarButton } from './toolbarButtonProvider'
export { ConfigProvider } from './configProvider' export { ConfigProvider } from './configProvider'
export { HotkeyProvider, HotkeyDescription } from './hotkeyProvider' export { HotkeyProvider, HotkeyDescription } from './hotkeyProvider'

View File

@@ -12,6 +12,12 @@ export interface RecoveredTab {
options?: any options?: any
} }
export interface RecoveryToken {
[_: string]: any
type: string
tabColor?: string|null
}
/** /**
* Extend to enable recovery for your custom tab. * Extend to enable recovery for your custom tab.
* This works in conjunction with [[getRecoveryToken()]] * This works in conjunction with [[getRecoveryToken()]]
@@ -34,5 +40,5 @@ export abstract class TabRecoveryProvider {
* @returns [[RecoveredTab]] descriptor containing tab type and component inputs * @returns [[RecoveredTab]] descriptor containing tab type and component inputs
* or `null` if this token is from a different tab type or is not supported * or `null` if this token is from a different tab type or is not supported
*/ */
abstract async recover (recoveryToken: any): Promise<RecoveredTab|null> abstract async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null>
} }

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Inject, Input, HostListener, HostBinding } from '@angular/core' import { Component, Inject, Input, HostListener, HostBinding } from '@angular/core'
import { trigger, style, animate, transition, state } from '@angular/animations' import { trigger, style, animate, transition, state } from '@angular/animations'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'

View File

@@ -1,5 +1,6 @@
import { Observable, Subject } from 'rxjs' import { Observable, Subject } from 'rxjs'
import { ViewRef } from '@angular/core' import { ViewRef } from '@angular/core'
import { RecoveryToken } from '../api/tabRecovery'
/** /**
* Represents an active "process" inside a tab, * Represents an active "process" inside a tab,
@@ -71,7 +72,7 @@ export abstract class BaseTabComponent {
}) })
} }
setTitle (title: string) { setTitle (title: string): void {
this.title = title this.title = title
if (!this.customTitle) { if (!this.customTitle) {
this.titleChange.next(title) this.titleChange.next(title)
@@ -83,7 +84,7 @@ export abstract class BaseTabComponent {
* *
* @param {type} progress: value between 0 and 1, or `null` to remove * @param {type} progress: value between 0 and 1, or `null` to remove
*/ */
setProgress (progress: number|null) { setProgress (progress: number|null): void {
this.progress.next(progress) this.progress.next(progress)
if (progress) { if (progress) {
if (this.progressClearTimeout) { if (this.progressClearTimeout) {
@@ -118,7 +119,7 @@ export abstract class BaseTabComponent {
* @return JSON serializable tab state representation * @return JSON serializable tab state representation
* for your [[TabRecoveryProvider]] to parse * for your [[TabRecoveryProvider]] to parse
*/ */
async getRecoveryToken (): Promise<any> { async getRecoveryToken (): Promise<RecoveryToken|null> {
return null return null
} }
@@ -136,11 +137,11 @@ export abstract class BaseTabComponent {
return true return true
} }
emitFocused () { emitFocused (): void {
this.focused.next() this.focused.next()
} }
emitBlurred () { emitBlurred (): void {
this.blurred.next() this.blurred.next()
} }

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { NgZone, Component, Input, HostBinding, HostListener } from '@angular/core' import { NgZone, Component, Input, HostBinding, HostListener } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Input, ElementRef, ViewChild } from '@angular/core' import { Component, Input, ElementRef, ViewChild } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'

View File

@@ -14,7 +14,7 @@ export class SafeModeModalComponent {
this.error = window['safeModeReason'] this.error = window['safeModeReason']
} }
close () { close (): void {
this.modalInstance.dismiss() this.modalInstance.dismiss()
} }
} }

View File

@@ -17,11 +17,11 @@ export class SelectorModalComponent<T> {
public modalInstance: NgbActiveModal, public modalInstance: NgbActiveModal,
) { } ) { }
ngOnInit () { ngOnInit (): void {
this.onFilterChange() this.onFilterChange()
} }
onFilterChange () { 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
@@ -31,17 +31,17 @@ export class SelectorModalComponent<T> {
} }
} }
onFilterEnter () { onFilterEnter (): void {
if (this.filteredOptions.length === 1) { if (this.filteredOptions.length === 1) {
this.selectOption(this.filteredOptions[0]) this.selectOption(this.filteredOptions[0])
} }
} }
selectOption (option: SelectorOption<T>) { selectOption (option: SelectorOption<T>): void {
this.modalInstance.close(option.result) this.modalInstance.close(option.result)
} }
close () { close (): void {
this.modalInstance.dismiss() this.modalInstance.dismiss()
} }
} }

View File

@@ -1,7 +1,7 @@
import { Observable, Subject, Subscription } from 'rxjs' import { Observable, Subject, Subscription } from 'rxjs'
import { Component, Injectable, ViewChild, ViewContainerRef, EmbeddedViewRef, AfterViewInit, OnDestroy } from '@angular/core' import { Component, Injectable, ViewChild, ViewContainerRef, EmbeddedViewRef, AfterViewInit, OnDestroy } from '@angular/core'
import { BaseTabComponent, BaseTabProcess } from './baseTab.component' import { BaseTabComponent, BaseTabProcess } from './baseTab.component'
import { TabRecoveryProvider, RecoveredTab } from '../api/tabRecovery' import { TabRecoveryProvider, RecoveredTab, RecoveryToken } from '../api/tabRecovery'
import { TabsService } from '../services/tabs.service' import { TabsService } from '../services/tabs.service'
import { HotkeysService } from '../services/hotkeys.service' import { HotkeysService } from '../services/hotkeys.service'
import { TabRecoveryService } from '../services/tabRecovery.service' import { TabRecoveryService } from '../services/tabRecovery.service'
@@ -48,7 +48,7 @@ export class SplitContainer {
/** /**
* Remove unnecessarily nested child containers and renormalizes [[ratios]] * Remove unnecessarily nested child containers and renormalizes [[ratios]]
*/ */
normalize () { normalize (): void {
for (let i = 0; i < this.children.length; i++) { for (let i = 0; i < this.children.length; i++) {
const child = this.children[i] const child = this.children[i]
@@ -93,7 +93,7 @@ export class SplitContainer {
return s return s
} }
async serialize () { async serialize (): Promise<RecoveryToken> {
const children: any[] = [] const children: any[] = []
for (const child of this.children) { for (const child of this.children) {
if (child instanceof SplitContainer) { if (child instanceof SplitContainer) {
@@ -250,7 +250,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
} }
/** @hidden */ /** @hidden */
async ngAfterViewInit () { async ngAfterViewInit (): Promise<void> {
if (this._recoveredState) { if (this._recoveredState) {
await this.recoverContainer(this.root, this._recoveredState) await this.recoverContainer(this.root, this._recoveredState)
this.layout() this.layout()
@@ -266,12 +266,12 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
} }
/** @hidden */ /** @hidden */
ngOnDestroy () { ngOnDestroy (): void {
this.hotkeysSubscription.unsubscribe() this.hotkeysSubscription.unsubscribe()
} }
/** @returns Flat list of all sub-tabs */ /** @returns Flat list of all sub-tabs */
getAllTabs () { getAllTabs (): BaseTabComponent[] {
return this.root.getAllTabs() return this.root.getAllTabs()
} }
@@ -283,7 +283,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
return this.maximizedTab return this.maximizedTab
} }
focus (tab: BaseTabComponent) { focus (tab: BaseTabComponent): void {
this.focusedTab = tab this.focusedTab = tab
for (const x of this.getAllTabs()) { for (const x of this.getAllTabs()) {
if (x !== tab) { if (x !== tab) {
@@ -301,7 +301,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
this.layout() this.layout()
} }
maximize (tab: BaseTabComponent|null) { maximize (tab: BaseTabComponent|null): void {
this.maximizedTab = tab this.maximizedTab = tab
this.layout() this.layout()
} }
@@ -309,7 +309,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
/** /**
* Focuses the first available tab inside the given [[SplitContainer]] * Focuses the first available tab inside the given [[SplitContainer]]
*/ */
focusAnyIn (parent: BaseTabComponent | SplitContainer) { focusAnyIn (parent: BaseTabComponent | SplitContainer): void {
if (!parent) { if (!parent) {
return return
} }
@@ -323,7 +323,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
/** /**
* Inserts a new `tab` to the `side` of the `relative` tab * Inserts a new `tab` to the `side` of the `relative` tab
*/ */
async addTab (tab: BaseTabComponent, relative: BaseTabComponent|null, side: SplitDirection) { async addTab (tab: BaseTabComponent, relative: BaseTabComponent|null, side: SplitDirection): Promise<void> {
await this.initialized$.toPromise() await this.initialized$.toPromise()
let target = (relative ? this.getParentOf(relative) : null) || this.root let target = (relative ? this.getParentOf(relative) : null) || this.root
@@ -364,7 +364,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
}) })
} }
removeTab (tab: BaseTabComponent) { removeTab (tab: BaseTabComponent): void {
const parent = this.getParentOf(tab) const parent = this.getParentOf(tab)
if (!parent) { if (!parent) {
return return
@@ -389,7 +389,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
/** /**
* Moves focus in the given direction * Moves focus in the given direction
*/ */
navigate (dir: SplitDirection) { navigate (dir: SplitDirection): void {
let rel: BaseTabComponent | SplitContainer = this.focusedTab let rel: BaseTabComponent | SplitContainer = this.focusedTab
let parent = this.getParentOf(rel) let parent = this.getParentOf(rel)
if (!parent) { if (!parent) {
@@ -422,11 +422,12 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
} }
} }
async splitTab (tab: BaseTabComponent, dir: SplitDirection) { async splitTab (tab: BaseTabComponent, dir: SplitDirection): Promise<BaseTabComponent|null> {
const newTab = await this.tabsService.duplicate(tab) const newTab = await this.tabsService.duplicate(tab)
if (newTab) { if (newTab) {
this.addTab(newTab, tab, dir) this.addTab(newTab, tab, dir)
} }
return newTab
} }
/** /**
@@ -464,12 +465,12 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
} }
/** @hidden */ /** @hidden */
onSpannerAdjusted (spanner: SplitSpannerInfo) { onSpannerAdjusted (spanner: SplitSpannerInfo): void {
this.layout() this.layout()
this.splitAdjusted.next(spanner) this.splitAdjusted.next(spanner)
} }
destroy () { destroy (): void {
super.destroy() super.destroy()
for (const x of this.getAllTabs()) { for (const x of this.getAllTabs()) {
x.destroy() x.destroy()
@@ -584,7 +585,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
/** @hidden */ /** @hidden */
@Injectable() @Injectable()
export class SplitTabRecoveryProvider extends TabRecoveryProvider { export class SplitTabRecoveryProvider extends TabRecoveryProvider {
async recover (recoveryToken: any): Promise<RecoveredTab|null> { async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
if (recoveryToken && recoveryToken.type === 'app:split-tab') { if (recoveryToken && recoveryToken.type === 'app:split-tab') {
return { return {
type: SplitTabComponent, type: SplitTabComponent,

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Input, HostBinding, ElementRef, Output, EventEmitter } from '@angular/core' import { Component, Input, HostBinding, ElementRef, Output, EventEmitter } from '@angular/core'
import { SplitContainer } from './splitTab.component' import { SplitContainer } from './splitTab.component'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Input, ViewChild, HostBinding, ViewContainerRef, OnChanges } from '@angular/core' import { Component, Input, ViewChild, HostBinding, ViewContainerRef, OnChanges } from '@angular/core'
import { BaseTabComponent } from '../components/baseTab.component' import { BaseTabComponent } from '../components/baseTab.component'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Input, Optional, Inject, HostBinding, HostListener, ViewChild, ElementRef } from '@angular/core' import { Component, Input, Optional, Inject, HostBinding, HostListener, ViewChild, ElementRef } from '@angular/core'
import { SortableComponent } from 'ng2-dnd' import { SortableComponent } from 'ng2-dnd'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component } from '@angular/core' import { Component } from '@angular/core'
import { BaseTabComponent } from './baseTab.component' import { BaseTabComponent } from './baseTab.component'
import { ConfigService } from '../services/config.service' import { ConfigService } from '../services/config.service'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component } from '@angular/core' import { Component } from '@angular/core'
import { HostAppService } from '../services/hostApp.service' import { HostAppService } from '../services/hostApp.service'
import { AppService } from '../services/app.service' import { AppService } from '../services/app.service'

View File

@@ -7,7 +7,7 @@ import { Directive, AfterViewInit, ElementRef } from '@angular/core'
export class AutofocusDirective implements AfterViewInit { export class AutofocusDirective implements AfterViewInit {
constructor (private el: ElementRef) { } constructor (private el: ElementRef) { }
ngAfterViewInit () { ngAfterViewInit (): void {
this.el.nativeElement.blur() this.el.nativeElement.blur()
setTimeout(() => { setTimeout(() => {
this.el.nativeElement.focus() this.el.nativeElement.focus()

View File

@@ -8,7 +8,7 @@ export class FastHtmlBindDirective implements OnChanges {
@Input() fastHtmlBind: string @Input() fastHtmlBind: string
constructor (private el: ElementRef) { } constructor (private el: ElementRef) { }
ngOnChanges () { ngOnChanges (): void {
this.el.nativeElement.innerHTML = this.fastHtmlBind || '' this.el.nativeElement.innerHTML = this.fastHtmlBind || ''
} }
} }

View File

@@ -93,7 +93,7 @@ export class AppService {
}) })
} }
startTabStorage () { startTabStorage (): void {
this.tabsChanged$.subscribe(() => { this.tabsChanged$.subscribe(() => {
this.tabRecovery.saveTabs(this.tabs) this.tabRecovery.saveTabs(this.tabs)
}) })
@@ -102,7 +102,7 @@ export class AppService {
}, 30000) }, 30000)
} }
addTabRaw (tab: BaseTabComponent, index: number|null = null) { addTabRaw (tab: BaseTabComponent, index: number|null = null): void {
if (index !== null) { if (index !== null) {
this.tabs.splice(index, 0, tab) this.tabs.splice(index, 0, tab)
} else { } else {
@@ -145,7 +145,7 @@ export class AppService {
* Adds a new tab **without** wrapping it in a SplitTabComponent * Adds a new tab **without** wrapping it in a SplitTabComponent
* @param inputs Properties to be assigned on the new tab component instance * @param inputs Properties to be assigned on the new tab component instance
*/ */
openNewTabRaw (type: TabComponentType, inputs?: any): BaseTabComponent { openNewTabRaw (type: TabComponentType, inputs?: Record<string, any>): BaseTabComponent {
const tab = this.tabsService.create(type, inputs) const tab = this.tabsService.create(type, inputs)
this.addTabRaw(tab) this.addTabRaw(tab)
return tab return tab
@@ -155,7 +155,7 @@ export class AppService {
* Adds a new tab while wrapping it in a SplitTabComponent * Adds a new tab while wrapping it in a SplitTabComponent
* @param inputs Properties to be assigned on the new tab component instance * @param inputs Properties to be assigned on the new tab component instance
*/ */
openNewTab (type: TabComponentType, inputs?: any): BaseTabComponent { openNewTab (type: TabComponentType, inputs?: Record<string, any>): BaseTabComponent {
const splitTab = this.tabsService.create(SplitTabComponent) as SplitTabComponent const splitTab = this.tabsService.create(SplitTabComponent) as SplitTabComponent
const tab = this.tabsService.create(type, inputs) const tab = this.tabsService.create(type, inputs)
splitTab.addTab(tab, null, 'r') splitTab.addTab(tab, null, 'r')
@@ -163,7 +163,7 @@ export class AppService {
return tab return tab
} }
selectTab (tab: BaseTabComponent) { selectTab (tab: BaseTabComponent): void {
if (this._activeTab === tab) { if (this._activeTab === tab) {
this._activeTab.emitFocused() this._activeTab.emitFocused()
return return
@@ -199,14 +199,14 @@ export class AppService {
} }
/** Switches between the current tab and the previously active one */ /** Switches between the current tab and the previously active one */
toggleLastTab () { toggleLastTab (): void {
if (!this.lastTabIndex || this.lastTabIndex >= this.tabs.length) { if (!this.lastTabIndex || this.lastTabIndex >= this.tabs.length) {
this.lastTabIndex = 0 this.lastTabIndex = 0
} }
this.selectTab(this.tabs[this.lastTabIndex]) this.selectTab(this.tabs[this.lastTabIndex])
} }
nextTab () { nextTab (): void {
if (this.tabs.length > 1) { if (this.tabs.length > 1) {
const tabIndex = this.tabs.indexOf(this._activeTab) const tabIndex = this.tabs.indexOf(this._activeTab)
if (tabIndex < this.tabs.length - 1) { if (tabIndex < this.tabs.length - 1) {
@@ -217,7 +217,7 @@ export class AppService {
} }
} }
previousTab () { previousTab (): void {
if (this.tabs.length > 1) { if (this.tabs.length > 1) {
const tabIndex = this.tabs.indexOf(this._activeTab) const tabIndex = this.tabs.indexOf(this._activeTab)
if (tabIndex > 0) { if (tabIndex > 0) {
@@ -228,7 +228,7 @@ export class AppService {
} }
} }
moveSelectedTabLeft () { moveSelectedTabLeft (): void {
if (this.tabs.length > 1) { if (this.tabs.length > 1) {
const tabIndex = this.tabs.indexOf(this._activeTab) const tabIndex = this.tabs.indexOf(this._activeTab)
if (tabIndex > 0) { if (tabIndex > 0) {
@@ -239,7 +239,7 @@ export class AppService {
} }
} }
moveSelectedTabRight () { moveSelectedTabRight (): void {
if (this.tabs.length > 1) { if (this.tabs.length > 1) {
const tabIndex = this.tabs.indexOf(this._activeTab) const tabIndex = this.tabs.indexOf(this._activeTab)
if (tabIndex < this.tabs.length - 1) { if (tabIndex < this.tabs.length - 1) {
@@ -250,7 +250,7 @@ export class AppService {
} }
} }
swapTabs (a: BaseTabComponent, b: BaseTabComponent) { swapTabs (a: BaseTabComponent, b: BaseTabComponent): void {
const i1 = this.tabs.indexOf(a) const i1 = this.tabs.indexOf(a)
const i2 = this.tabs.indexOf(b) const i2 = this.tabs.indexOf(b)
this.tabs[i1] = b this.tabs[i1] = b
@@ -258,7 +258,7 @@ export class AppService {
} }
/** @hidden */ /** @hidden */
emitTabsChanged () { emitTabsChanged (): void {
this.tabsChanged.next() this.tabsChanged.next()
} }
@@ -272,11 +272,12 @@ export class AppService {
tab.destroy() tab.destroy()
} }
async duplicateTab (tab: BaseTabComponent) { async duplicateTab (tab: BaseTabComponent): Promise<BaseTabComponent|null> {
const dup = await this.tabsService.duplicate(tab) const dup = await this.tabsService.duplicate(tab)
if (dup) { if (dup) {
this.addTabRaw(dup, this.tabs.indexOf(tab) + 1) this.addTabRaw(dup, this.tabs.indexOf(tab) + 1)
} }
return dup
} }
/** /**
@@ -295,7 +296,7 @@ export class AppService {
} }
/** @hidden */ /** @hidden */
emitReady () { emitReady (): void {
this.ready.next() this.ready.next()
this.ready.complete() this.ready.complete()
this.hostApp.emitReady() this.hostApp.emitReady()
@@ -316,7 +317,7 @@ export class AppService {
return this.completionObservers.get(tab)!.done$ return this.completionObservers.get(tab)!.done$
} }
stopObservingTabCompletion (tab: BaseTabComponent) { stopObservingTabCompletion (tab: BaseTabComponent): void {
this.completionObservers.delete(tab) this.completionObservers.delete(tab)
} }

View File

@@ -20,7 +20,7 @@ function isNonStructuralObjectMember (v): boolean {
/** @hidden */ /** @hidden */
export class ConfigProxy { export class ConfigProxy {
constructor (real: any, defaults: any) { constructor (real: Record<string, any>, defaults: Record<string, any>) {
for (const key in defaults) { for (const key in defaults) {
if (isStructuralMember(defaults[key])) { if (isStructuralMember(defaults[key])) {
if (!real[key]) { if (!real[key]) {
@@ -71,8 +71,10 @@ export class ConfigProxy {
} }
} }
getValue (_key: string): any { } // eslint-disable-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-empty-function
setValue (_key: string, _value: any) { } // eslint-disable-line @typescript-eslint/no-empty-function getValue (_key: string): any { }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-empty-function
setValue (_key: string, _value: any) { }
} }
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
@@ -124,7 +126,7 @@ export class ConfigService {
}) })
} }
getDefaults () { getDefaults (): Record<string, any> {
const cleanup = o => { const cleanup = o => {
if (o instanceof Array) { if (o instanceof Array) {
return o.map(cleanup) return o.map(cleanup)

View File

@@ -15,7 +15,7 @@ export class DockingService {
electron.screen.on('display-metrics-changed', () => this.repositionWindow()) electron.screen.on('display-metrics-changed', () => this.repositionWindow())
} }
dock () { dock (): void {
const dockSide = this.config.store.appearance.dock const dockSide = this.config.store.appearance.dock
if (dockSide === 'off') { if (dockSide === 'off') {
@@ -59,16 +59,17 @@ export class DockingService {
}) })
} }
getCurrentScreen () { getCurrentScreen (): Electron.Display {
return this.electron.screen.getDisplayNearestPoint(this.electron.screen.getCursorScreenPoint()) return this.electron.screen.getDisplayNearestPoint(this.electron.screen.getCursorScreenPoint())
} }
getScreens () { getScreens (): Electron.Display[] {
const primaryDisplayID = this.electron.screen.getPrimaryDisplay().id const primaryDisplayID = this.electron.screen.getPrimaryDisplay().id
return this.electron.screen.getAllDisplays().sort((a, b) => return this.electron.screen.getAllDisplays().sort((a, b) =>
a.bounds.x === b.bounds.x ? a.bounds.y - b.bounds.y : a.bounds.x - b.bounds.x a.bounds.x === b.bounds.x ? a.bounds.y - b.bounds.y : a.bounds.x - b.bounds.x
).map((display,index) => { ).map((display, index) => {
return { return {
...display,
id: display.id, id: display.id,
name: display.id === primaryDisplayID ? 'Primary Display' : `Display ${index +1}`, name: display.id === primaryDisplayID ? 'Primary Display' : `Display ${index +1}`,
} }

View File

@@ -46,7 +46,7 @@ export class ElectronService {
/** /**
* Removes OS focus from Terminus' window * Removes OS focus from Terminus' window
*/ */
loseFocus () { loseFocus (): void {
if (process.platform === 'darwin') { if (process.platform === 'darwin') {
this.remote.Menu.sendActionToFirstResponder('hide:') this.remote.Menu.sendActionToFirstResponder('hide:')
} }

View File

@@ -22,11 +22,11 @@ export class HomeBaseService {
} }
} }
openGitHub () { openGitHub (): void {
this.electron.shell.openExternal('https://github.com/eugeny/terminus') this.electron.shell.openExternal('https://github.com/eugeny/terminus')
} }
reportBug () { reportBug (): void {
let body = `Version: ${this.appVersion}\n` let body = `Version: ${this.appVersion}\n`
body += `Platform: ${os.platform()} ${os.release()}\n` body += `Platform: ${os.platform()} ${os.release()}\n`
const label = { const label = {
@@ -44,7 +44,7 @@ export class HomeBaseService {
this.electron.shell.openExternal(`https://github.com/eugeny/terminus/issues/new?body=${encodeURIComponent(body)}&labels=${label}`) this.electron.shell.openExternal(`https://github.com/eugeny/terminus/issues/new?body=${encodeURIComponent(body)}&labels=${label}`)
} }
enableAnalytics () { enableAnalytics (): void {
if (!window.localStorage.analyticsUserID) { if (!window.localStorage.analyticsUserID) {
window.localStorage.analyticsUserID = uuidv4() window.localStorage.analyticsUserID = uuidv4()
} }
@@ -56,7 +56,7 @@ export class HomeBaseService {
this.mixpanel.track('launch', this.getAnalyticsProperties()) this.mixpanel.track('launch', this.getAnalyticsProperties())
} }
getAnalyticsProperties () { getAnalyticsProperties (): Record<string, string> {
return { return {
distinct_id: window.localStorage.analyticsUserID, // eslint-disable-line @typescript-eslint/camelcase distinct_id: window.localStorage.analyticsUserID, // eslint-disable-line @typescript-eslint/camelcase
platform: process.platform, platform: process.platform,

View File

@@ -178,48 +178,48 @@ export class HostAppService {
/** /**
* Returns the current remote [[BrowserWindow]] * Returns the current remote [[BrowserWindow]]
*/ */
getWindow () { getWindow (): Electron.BrowserWindow {
return this.electron.BrowserWindow.fromId(this.windowId) return this.electron.BrowserWindow.fromId(this.windowId)
} }
newWindow () { newWindow (): void {
this.electron.ipcRenderer.send('app:new-window') this.electron.ipcRenderer.send('app:new-window')
} }
toggleFullscreen () { toggleFullscreen (): void {
const window = this.getWindow() const window = this.getWindow()
window.setFullScreen(!this.isFullScreen) window.setFullScreen(!this.isFullScreen)
} }
openDevTools () { openDevTools (): void {
this.getWindow().webContents.openDevTools({ mode: 'undocked' }) this.getWindow().webContents.openDevTools({ mode: 'undocked' })
} }
focusWindow () { focusWindow (): void {
this.electron.ipcRenderer.send('window-focus') this.electron.ipcRenderer.send('window-focus')
} }
minimize () { minimize (): void {
this.electron.ipcRenderer.send('window-minimize') this.electron.ipcRenderer.send('window-minimize')
} }
maximize () { maximize (): void {
this.electron.ipcRenderer.send('window-maximize') this.electron.ipcRenderer.send('window-maximize')
} }
unmaximize () { unmaximize (): void {
this.electron.ipcRenderer.send('window-unmaximize') this.electron.ipcRenderer.send('window-unmaximize')
} }
toggleMaximize () { toggleMaximize (): void {
this.electron.ipcRenderer.send('window-toggle-maximize') this.electron.ipcRenderer.send('window-toggle-maximize')
} }
setBounds (bounds: Bounds) { setBounds (bounds: Bounds): void {
this.electron.ipcRenderer.send('window-set-bounds', bounds) this.electron.ipcRenderer.send('window-set-bounds', bounds)
} }
setAlwaysOnTop (flag: boolean) { setAlwaysOnTop (flag: boolean): void {
this.electron.ipcRenderer.send('window-set-always-on-top', flag) this.electron.ipcRenderer.send('window-set-always-on-top', flag)
} }
@@ -228,7 +228,7 @@ export class HostAppService {
* *
* @param type `null`, or `fluent` when supported (Windowd only) * @param type `null`, or `fluent` when supported (Windowd only)
*/ */
setVibrancy (enable: boolean, type: string|null) { setVibrancy (enable: boolean, type: string|null): void {
if (!isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED)) { if (!isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED)) {
type = null type = null
} }
@@ -236,38 +236,38 @@ export class HostAppService {
this.electron.ipcRenderer.send('window-set-vibrancy', enable, type) this.electron.ipcRenderer.send('window-set-vibrancy', enable, type)
} }
setTitle (title: string) { setTitle (title: string): void {
this.electron.ipcRenderer.send('window-set-title', title) this.electron.ipcRenderer.send('window-set-title', title)
} }
setTouchBar (touchBar: Electron.TouchBar) { setTouchBar (touchBar: Electron.TouchBar): void {
this.getWindow().setTouchBar(touchBar) this.getWindow().setTouchBar(touchBar)
} }
popupContextMenu (menuDefinition: Electron.MenuItemConstructorOptions[]) { popupContextMenu (menuDefinition: Electron.MenuItemConstructorOptions[]): void {
this.electron.Menu.buildFromTemplate(menuDefinition).popup({}) this.electron.Menu.buildFromTemplate(menuDefinition).popup({})
} }
/** /**
* Notifies other windows of config file changes * Notifies other windows of config file changes
*/ */
broadcastConfigChange () { broadcastConfigChange (): void {
this.electron.ipcRenderer.send('app:config-change') this.electron.ipcRenderer.send('app:config-change')
} }
emitReady () { emitReady (): void {
this.electron.ipcRenderer.send('app:ready') this.electron.ipcRenderer.send('app:ready')
} }
bringToFront () { bringToFront (): void {
this.electron.ipcRenderer.send('window-bring-to-front') this.electron.ipcRenderer.send('window-bring-to-front')
} }
closeWindow () { closeWindow (): void {
this.electron.ipcRenderer.send('window-close') this.electron.ipcRenderer.send('window-close')
} }
relaunch () { relaunch (): void {
if (this.isPortable) { if (this.isPortable) {
this.electron.app.relaunch({ execPath: process.env.PORTABLE_EXECUTABLE_FILE }) this.electron.app.relaunch({ execPath: process.env.PORTABLE_EXECUTABLE_FILE })
} else { } else {
@@ -276,7 +276,7 @@ export class HostAppService {
this.electron.app.exit() this.electron.app.exit()
} }
quit () { quit (): void {
this.logger.info('Quitting') this.logger.info('Quitting')
this.electron.app.quit() this.electron.app.quit()
} }

View File

@@ -70,7 +70,7 @@ export class HotkeysService {
* @param name DOM event name * @param name DOM event name
* @param nativeEvent event object * @param nativeEvent event object
*/ */
pushKeystroke (name: string, nativeEvent: KeyboardEvent) { pushKeystroke (name: string, nativeEvent: KeyboardEvent): void {
(nativeEvent as any).event = name (nativeEvent as any).event = name
this.currentKeystrokes.push({ event: nativeEvent, time: performance.now() }) this.currentKeystrokes.push({ event: nativeEvent, time: performance.now() })
} }
@@ -78,7 +78,7 @@ export class HotkeysService {
/** /**
* Check the buffer for new complete keystrokes * Check the buffer for new complete keystrokes
*/ */
processKeystrokes () { processKeystrokes (): void {
if (this.isEnabled()) { if (this.isEnabled()) {
this.zone.run(() => { this.zone.run(() => {
const matched = this.getCurrentFullyMatchedHotkey() const matched = this.getCurrentFullyMatchedHotkey()
@@ -91,13 +91,13 @@ export class HotkeysService {
} }
} }
emitKeyEvent (nativeEvent: KeyboardEvent) { emitKeyEvent (nativeEvent: KeyboardEvent): void {
this.zone.run(() => { this.zone.run(() => {
this.key.emit(nativeEvent) this.key.emit(nativeEvent)
}) })
} }
clearCurrentKeystrokes () { clearCurrentKeystrokes (): void {
this.currentKeystrokes = [] this.currentKeystrokes = []
} }
@@ -155,15 +155,15 @@ export class HotkeysService {
return this.hotkeyDescriptions.filter((x) => x.id === id)[0] return this.hotkeyDescriptions.filter((x) => x.id === id)[0]
} }
enable () { enable (): void {
this.disabledLevel-- this.disabledLevel--
} }
disable () { disable (): void {
this.disabledLevel++ this.disabledLevel++
} }
isEnabled () { isEnabled (): boolean {
return this.disabledLevel === 0 return this.disabledLevel === 0
} }

View File

@@ -32,27 +32,27 @@ export class Logger {
private name: string, private name: string,
) {} ) {}
debug (...args: any[]) { debug (...args: any[]): void {
this.doLog('debug', ...args) this.doLog('debug', ...args)
} }
info (...args: any[]) { info (...args: any[]): void {
this.doLog('info', ...args) this.doLog('info', ...args)
} }
warn (...args: any[]) { warn (...args: any[]): void {
this.doLog('warn', ...args) this.doLog('warn', ...args)
} }
error (...args: any[]) { error (...args: any[]): void {
this.doLog('error', ...args) this.doLog('error', ...args)
} }
log (...args: any[]) { log (...args: any[]): void {
this.doLog('log', ...args) this.doLog('log', ...args)
} }
private doLog (level: string, ...args: any[]) { private doLog (level: string, ...args: any[]): void {
console[level](`%c[${this.name}]`, 'color: #aaa', ...args) console[level](`%c[${this.name}]`, 'color: #aaa', ...args)
if (this.winstonLogger) { if (this.winstonLogger) {
this.winstonLogger[level](...args) this.winstonLogger[level](...args)

View File

@@ -58,7 +58,7 @@ export class ShellIntegrationService {
return true return true
} }
async install () { async install (): Promise<void> {
const exe: string = process.env.PORTABLE_EXECUTABLE_FILE || this.electron.app.getPath('exe') const exe: string = process.env.PORTABLE_EXECUTABLE_FILE || this.electron.app.getPath('exe')
if (this.hostApp.platform === Platform.macOS) { if (this.hostApp.platform === Platform.macOS) {
for (const wf of this.automatorWorkflows) { for (const wf of this.automatorWorkflows) {
@@ -82,7 +82,7 @@ export class ShellIntegrationService {
} }
} }
async remove () { async remove (): Promise<void> {
if (this.hostApp.platform === Platform.macOS) { if (this.hostApp.platform === Platform.macOS) {
for (const wf of this.automatorWorkflows) { for (const wf of this.automatorWorkflows) {
await exec(`rm -rf "${this.automatorWorkflowsDestination}/${wf}"`) await exec(`rm -rf "${this.automatorWorkflowsDestination}/${wf}"`)

View File

@@ -1,5 +1,5 @@
import { Injectable, Inject } from '@angular/core' import { Injectable, Inject } from '@angular/core'
import { TabRecoveryProvider, RecoveredTab } from '../api/tabRecovery' import { TabRecoveryProvider, RecoveredTab, RecoveryToken } from '../api/tabRecovery'
import { BaseTabComponent } from '../components/baseTab.component' import { BaseTabComponent } from '../components/baseTab.component'
import { Logger, LogService } from '../services/log.service' import { Logger, LogService } from '../services/log.service'
import { ConfigService } from '../services/config.service' import { ConfigService } from '../services/config.service'
@@ -17,7 +17,7 @@ export class TabRecoveryService {
this.logger = log.create('tabRecovery') this.logger = log.create('tabRecovery')
} }
async saveTabs (tabs: BaseTabComponent[]) { async saveTabs (tabs: BaseTabComponent[]): Promise<void> {
window.localStorage.tabsRecovery = JSON.stringify( window.localStorage.tabsRecovery = JSON.stringify(
await Promise.all( await Promise.all(
tabs tabs
@@ -25,7 +25,7 @@ export class TabRecoveryService {
let token = tab.getRecoveryToken() let token = tab.getRecoveryToken()
if (token) { if (token) {
token = token.then(r => { token = token.then(r => {
if (r) { if (r && tab.color) {
r.tabColor = tab.color r.tabColor = tab.color
} }
return r return r
@@ -38,7 +38,7 @@ export class TabRecoveryService {
) )
} }
async recoverTab (token: any): Promise<RecoveredTab|null> { async recoverTab (token: RecoveryToken): Promise<RecoveredTab|null> {
for (const provider of this.config.enabledServices(this.tabRecoveryProviders)) { for (const provider of this.config.enabledServices(this.tabRecoveryProviders)) {
try { try {
const tab = await provider.recover(token) const tab = await provider.recover(token)

View File

@@ -17,7 +17,7 @@ export class TabsService {
/** /**
* Instantiates a tab component and assigns given inputs * Instantiates a tab component and assigns given inputs
*/ */
create (type: TabComponentType, inputs?: any): BaseTabComponent { create (type: TabComponentType, inputs?: Record<string, any>): BaseTabComponent {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(type) const componentFactory = this.componentFactoryResolver.resolveComponentFactory(type)
const componentRef = componentFactory.create(this.injector) const componentRef = componentFactory.create(this.injector)
const tab = componentRef.instance const tab = componentRef.instance

View File

@@ -48,7 +48,7 @@ export class TouchbarService {
}) })
} }
updateTabs () { updateTabs (): void {
this.tabSegments = this.app.tabs.map(tab => ({ this.tabSegments = this.app.tabs.map(tab => ({
label: this.shortenTitle(tab.title), label: this.shortenTitle(tab.title),
})) }))
@@ -56,7 +56,7 @@ export class TouchbarService {
this.tabsSegmentedControl.selectedIndex = this.app.tabs.indexOf(this.app.activeTab) this.tabsSegmentedControl.selectedIndex = this.app.tabs.indexOf(this.app.activeTab)
} }
update () { update (): void {
if (this.hostApp.platform !== Platform.macOS) { if (this.hostApp.platform !== Platform.macOS) {
return return
} }

View File

@@ -80,7 +80,7 @@ export class UpdaterService {
return this.downloaded return this.downloaded
} }
async update () { async update (): Promise<void> {
if (!this.electronUpdaterAvailable) { if (!this.electronUpdaterAvailable) {
this.electron.shell.openExternal(this.updateURL) this.electron.shell.openExternal(this.updateURL)
} else { } else {

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Injectable, NgZone } from '@angular/core' import { Injectable, NgZone } from '@angular/core'
import { Subscription } from 'rxjs' import { Subscription } from 'rxjs'
import { AppService } from './services/app.service' import { AppService } from './services/app.service'

View File

@@ -10,6 +10,7 @@ export function isWindowsBuild (build: number): boolean {
return process.platform === 'win32' && parseFloat(os.release()) >= 10 && parseInt(os.release().split('.')[2]) >= build return process.platform === 'win32' && parseFloat(os.release()) >= 10 && parseInt(os.release().split('.')[2]) >= build
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function getCSSFontFamily (config: any): string { export function getCSSFontFamily (config: any): string {
let fonts: string[] = config.terminal.font.split(',').map(x => x.trim().replace(/"/g, '')) let fonts: string[] = config.terminal.font.split(',').map(x => x.trim().replace(/"/g, ''))
if (config.terminal.fallbackFont) { if (config.terminal.fallbackFont) {

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { BehaviorSubject, Observable } from 'rxjs' import { BehaviorSubject, Observable } from 'rxjs'
import { debounceTime, distinctUntilChanged, first, tap, flatMap, map } from 'rxjs/operators' import { debounceTime, distinctUntilChanged, first, tap, flatMap, map } from 'rxjs/operators'
import semverGt from 'semver/functions/gt' import semverGt from 'semver/functions/gt'

View File

@@ -40,7 +40,7 @@ export class PluginManagerService {
this.logger = log.create('pluginManager') this.logger = log.create('pluginManager')
} }
async getNPM () { async getNPM (): Promise<any> {
if (!this.npm) { if (!this.npm) {
if (!this.npmReady) { if (!this.npmReady) {
this.npmReady = new Promise(resolve => { this.npmReady = new Promise(resolve => {
@@ -83,7 +83,7 @@ export class PluginManagerService {
) )
} }
async installPlugin (plugin: PluginInfo) { async installPlugin (plugin: PluginInfo): Promise<void> {
(await this.getNPM()).commands.install([`${plugin.packageName}@${plugin.version}`], err => { (await this.getNPM()).commands.install([`${plugin.packageName}@${plugin.version}`], err => {
if (err) { if (err) {
this.logger.error(err) this.logger.error(err)
@@ -93,7 +93,7 @@ export class PluginManagerService {
}) })
} }
async uninstallPlugin (plugin: PluginInfo) { async uninstallPlugin (plugin: PluginInfo): Promise<void> {
(await this.getNPM()).commands.remove([plugin.packageName], err => { (await this.getNPM()).commands.remove([plugin.packageName], err => {
if (err) { if (err) {
this.logger.error(err) this.logger.error(err)

View File

@@ -47,7 +47,7 @@ export class SerialSession extends BaseSession {
this.scripts = connection.scripts || [] this.scripts = connection.scripts || []
} }
async start () { async start (): Promise<void> {
this.open = true this.open = true
this.serial.on('data', data => { this.serial.on('data', data => {
@@ -105,12 +105,7 @@ export class SerialSession extends BaseSession {
this.executeUnconditionalScripts() this.executeUnconditionalScripts()
} }
emitServiceMessage (msg: string) { write (data: string): void {
this.serviceMessage.next(msg)
this.logger.info(msg)
}
write (data) {
if (this.serial) { if (this.serial) {
this.serial.write(data) this.serial.write(data)
} }
@@ -121,11 +116,10 @@ export class SerialSession extends BaseSession {
await super.destroy() await super.destroy()
} }
resize (_, _1) { // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-empty-function
console.log('resize') resize (_, __) { }
}
kill (_?: string) { kill (_?: string): void {
this.serial.close() this.serial.close()
} }

View File

@@ -1,3 +1,4 @@
/* 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 { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { HotkeysService, ToolbarButtonProvider, ToolbarButton } from 'terminus-core' import { HotkeysService, ToolbarButtonProvider, ToolbarButton } from 'terminus-core'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component } from '@angular/core' import { Component } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { map } from 'rxjs/operators' import { map } from 'rxjs/operators'

View File

@@ -1,14 +0,0 @@
.modal-body
input.form-control(
[type]='"text"',
autofocus,
[(ngModel)]='value',
#input,
[placeholder]='prompt',
(keyup.enter)='ok()',
(keyup.esc)='cancel()',
)
.d-flex.align-items-start.mt-2
button.btn.btn-primary.ml-auto(
(click)='ok()',
) Enter

View File

@@ -1,31 +0,0 @@
import { Component, Input, ViewChild, ElementRef } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
/** @hidden */
@Component({
template: require('./promptModal.component.pug'),
})
export class PromptModalComponent {
@Input() value: string
@ViewChild('input') input: ElementRef
constructor (
private modalInstance: NgbActiveModal,
) { }
ngOnInit () {
setTimeout(() => {
this.input.nativeElement.focus()
})
}
ok () {
this.modalInstance.close({
value: this.value,
})
}
cancel () {
this.modalInstance.close(null)
}
}

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, NgZone } from '@angular/core' import { Component, NgZone } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ToastrService } from 'ngx-toastr' import { ToastrService } from 'ngx-toastr'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component } from '@angular/core' import { Component } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { ConfigService, ElectronService, HostAppService } from 'terminus-core' import { ConfigService, ElectronService, HostAppService } from 'terminus-core'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import colors from 'ansi-colors' import colors from 'ansi-colors'
import { Spinner } from 'cli-spinner' import { Spinner } from 'cli-spinner'
import { Component, Injector } from '@angular/core' import { Component, Injector } from '@angular/core'

View File

@@ -1,18 +1,18 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { TabRecoveryProvider, RecoveredTab } from 'terminus-core' import { TabRecoveryProvider, RecoveredTab, RecoveryToken } from 'terminus-core'
import { SerialTabComponent } from './components/serialTab.component' import { SerialTabComponent } from './components/serialTab.component'
/** @hidden */ /** @hidden */
@Injectable() @Injectable()
export class RecoveryProvider extends TabRecoveryProvider { export class RecoveryProvider extends TabRecoveryProvider {
async recover (recoveryToken: any): Promise<RecoveredTab|null> { async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
if (recoveryToken?.type === 'app:serial-tab') { if (recoveryToken?.type === 'app:serial-tab') {
return { return {
type: SerialTabComponent, type: SerialTabComponent,
options: { options: {
connection: recoveryToken.connection, connection: recoveryToken['connection'],
savedState: recoveryToken.savedState, savedState: recoveryToken['savedState'],
}, },
} }
} }

View File

@@ -27,7 +27,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
title: 'Settings', title: 'Settings',
touchBarNSImage: 'NSTouchBarComposeTemplate', touchBarNSImage: 'NSTouchBarComposeTemplate',
weight: 10, weight: 10,
click: () => this.open(), click: (): void => this.open(),
}] }]
} }

View File

@@ -61,7 +61,7 @@ export class HotkeyInputModalComponent {
return keys.split('+').map((x) => x.trim()) return keys.split('+').map((x) => x.trim())
} }
ngOnInit () { ngOnInit (): void {
this.keyTimeoutInterval = window.setInterval(() => { this.keyTimeoutInterval = window.setInterval(() => {
if (!this.lastKeyEvent) { if (!this.lastKeyEvent) {
return return
@@ -74,14 +74,14 @@ export class HotkeyInputModalComponent {
this.hotkeys.disable() this.hotkeys.disable()
} }
ngOnDestroy () { ngOnDestroy (): void {
this.keySubscription.unsubscribe() this.keySubscription.unsubscribe()
this.hotkeys.clearCurrentKeystrokes() this.hotkeys.clearCurrentKeystrokes()
this.hotkeys.enable() this.hotkeys.enable()
clearInterval(this.keyTimeoutInterval!) clearInterval(this.keyTimeoutInterval!)
} }
close () { close (): void {
this.modalInstance.dismiss() this.modalInstance.dismiss()
} }
} }

View File

@@ -17,7 +17,7 @@ export class MultiHotkeyInputComponent {
private ngbModal: NgbModal, private ngbModal: NgbModal,
) { } ) { }
ngOnInit () { ngOnInit (): void {
if (!this.model) { if (!this.model) {
this.model = [] this.model = []
} }
@@ -27,7 +27,7 @@ export class MultiHotkeyInputComponent {
this.model = this.model.map(item => typeof item === 'string' ? [item] : item) this.model = this.model.map(item => typeof item === 'string' ? [item] : item)
} }
editItem (item) { editItem (item: string[]): void {
this.ngbModal.open(HotkeyInputModalComponent).result.then((value: string[]) => { this.ngbModal.open(HotkeyInputModalComponent).result.then((value: string[]) => {
this.model[this.model.findIndex(x => x === item)] = value this.model[this.model.findIndex(x => x === item)] = value
this.model = this.model.slice() this.model = this.model.slice()
@@ -35,14 +35,14 @@ export class MultiHotkeyInputComponent {
}) })
} }
addItem () { addItem (): void {
this.ngbModal.open(HotkeyInputModalComponent).result.then((value: string[]) => { this.ngbModal.open(HotkeyInputModalComponent).result.then((value: string[]) => {
this.model = this.model.concat([value]) this.model = this.model.concat([value])
this.modelChange.emit(this.model) this.modelChange.emit(this.model)
}) })
} }
removeItem (item) { removeItem (item: string[]): void {
this.model = this.model.filter(x => x !== item) this.model = this.model.filter(x => x !== item)
this.modelChange.emit(this.model) this.modelChange.emit(this.model)
} }

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import * as yaml from 'js-yaml' import * as yaml from 'js-yaml'
import { Subscription } from 'rxjs' import { Subscription } from 'rxjs'
import { Component, Inject, Input, HostBinding, NgZone } from '@angular/core' import { Component, Inject, Input, HostBinding, NgZone } from '@angular/core'

View File

@@ -13,7 +13,7 @@ export class SettingsTabBodyComponent {
constructor (private componentFactoryResolver: ComponentFactoryResolver) { } constructor (private componentFactoryResolver: ComponentFactoryResolver) { }
ngAfterViewInit () { ngAfterViewInit (): void {
// run after the change detection finishes // run after the change detection finishes
setImmediate(() => { setImmediate(() => {
this.component = this.placeholder.createComponent( this.component = this.placeholder.createComponent(

View File

@@ -60,11 +60,11 @@ export class ForwardedPort {
}) })
} }
stopLocalListener () { stopLocalListener (): void {
this.listener.close() this.listener.close()
} }
toString () { toString (): string {
if (this.type === PortForwardType.Local) { if (this.type === PortForwardType.Local) {
return `(local) ${this.host}:${this.port} → (remote) ${this.targetAddress}:${this.targetPort}` return `(local) ${this.host}:${this.port} → (remote) ${this.targetAddress}:${this.targetPort}`
} else { } else {
@@ -88,7 +88,7 @@ export class SSHSession extends BaseSession {
this.scripts = connection.scripts || [] this.scripts = connection.scripts || []
} }
async start () { async start (): Promise<void> {
this.open = true this.open = true
try { try {
@@ -217,12 +217,12 @@ export class SSHSession extends BaseSession {
this.executeUnconditionalScripts() this.executeUnconditionalScripts()
} }
emitServiceMessage (msg: string) { emitServiceMessage (msg: string): void {
this.serviceMessage.next(msg) this.serviceMessage.next(msg)
this.logger.info(msg) this.logger.info(msg)
} }
async addPortForward (fw: ForwardedPort) { async addPortForward (fw: ForwardedPort): Promise<void> {
if (fw.type === PortForwardType.Local) { if (fw.type === PortForwardType.Local) {
await fw.startLocalListener((socket: Socket) => { await fw.startLocalListener((socket: Socket) => {
this.logger.info(`New connection on ${fw}`) this.logger.info(`New connection on ${fw}`)
@@ -270,7 +270,7 @@ export class SSHSession extends BaseSession {
} }
} }
async removePortForward (fw: ForwardedPort) { async removePortForward (fw: ForwardedPort): Promise<void> {
if (fw.type === PortForwardType.Local) { if (fw.type === PortForwardType.Local) {
fw.stopLocalListener() fw.stopLocalListener()
this.forwardedPorts = this.forwardedPorts.filter(x => x !== fw) this.forwardedPorts = this.forwardedPorts.filter(x => x !== fw)
@@ -282,19 +282,19 @@ export class SSHSession extends BaseSession {
this.emitServiceMessage(`Stopped forwarding ${fw}`) this.emitServiceMessage(`Stopped forwarding ${fw}`)
} }
resize (columns, rows) { resize (columns: number, rows: number): void {
if (this.shell) { if (this.shell) {
this.shell.setWindow(rows, columns, rows, columns) this.shell.setWindow(rows, columns, rows, columns)
} }
} }
write (data) { write (data: string): void {
if (this.shell) { if (this.shell) {
this.shell.write(data) this.shell.write(data)
} }
} }
kill (signal?: string) { kill (signal?: string): void {
if (this.shell) { if (this.shell) {
this.shell.signal(signal || 'TERM') this.shell.signal(signal || 'TERM')
} }

View File

@@ -1,3 +1,4 @@
/* 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 { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { HotkeysService, ToolbarButtonProvider, ToolbarButton } from 'terminus-core' import { HotkeysService, ToolbarButtonProvider, ToolbarButton } from 'terminus-core'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component } from '@angular/core' import { Component } from '@angular/core'
import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ElectronService, HostAppService } from 'terminus-core' import { ElectronService, HostAppService } from 'terminus-core'

View File

@@ -16,20 +16,20 @@ export class PromptModalComponent {
private modalInstance: NgbActiveModal, private modalInstance: NgbActiveModal,
) { } ) { }
ngOnInit () { ngOnInit (): void {
setTimeout(() => { setTimeout(() => {
this.input.nativeElement.focus() this.input.nativeElement.focus()
}) })
} }
ok () { ok (): void {
this.modalInstance.close({ this.modalInstance.close({
value: this.value, value: this.value,
remember: this.remember, remember: this.remember,
}) })
} }
cancel () { cancel (): void {
this.modalInstance.close(null) this.modalInstance.close(null)
} }
} }

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, NgZone } from '@angular/core' import { Component, NgZone } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ToastrService } from 'ngx-toastr' import { ToastrService } from 'ngx-toastr'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Input } from '@angular/core' import { Component, Input } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ForwardedPort, PortForwardType, SSHSession } from '../api' import { ForwardedPort, PortForwardType, SSHSession } from '../api'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component } from '@angular/core' import { Component } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { ConfigService, ElectronService, HostAppService } from 'terminus-core' import { ConfigService, ElectronService, HostAppService } from 'terminus-core'

View File

@@ -3,6 +3,7 @@ import { Spinner } from 'cli-spinner'
import { Component, Injector } from '@angular/core' import { Component, Injector } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { first } from 'rxjs/operators' import { first } from 'rxjs/operators'
import { RecoveryToken } from 'terminus-core'
import { BaseTerminalTabComponent } from 'terminus-terminal' import { BaseTerminalTabComponent } from 'terminus-terminal'
import { SSHService } from '../services/ssh.service' import { SSHService } from '../services/ssh.service'
import { SSHConnection, SSHSession } from '../api' import { SSHConnection, SSHSession } from '../api'
@@ -29,7 +30,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
super(injector) super(injector)
} }
ngOnInit () { ngOnInit (): void {
this.logger = this.log.create('terminalTab') this.logger = this.log.create('terminalTab')
this.homeEndSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => { this.homeEndSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
@@ -57,7 +58,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
}) })
} }
async initializeSession () { async initializeSession (): void {
if (!this.connection) { if (!this.connection) {
this.logger.error('No SSH connection info supplied') this.logger.error('No SSH connection info supplied')
return return
@@ -96,7 +97,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
this.session.resize(this.size.columns, this.size.rows) this.session.resize(this.size.columns, this.size.rows)
} }
async getRecoveryToken (): Promise<any> { async getRecoveryToken (): Promise<RecoveryToken> {
return { return {
type: 'app:ssh-tab', type: 'app:ssh-tab',
connection: this.connection, connection: this.connection,
@@ -104,16 +105,16 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
} }
} }
showPortForwarding () { showPortForwarding (): void {
const modal = this.ngbModal.open(SSHPortForwardingModalComponent).componentInstance as SSHPortForwardingModalComponent const modal = this.ngbModal.open(SSHPortForwardingModalComponent).componentInstance as SSHPortForwardingModalComponent
modal.session = this.session modal.session = this.session
} }
reconnect () { reconnect (): void {
this.initializeSession() this.initializeSession()
} }
ngOnDestroy () { ngOnDestroy (): void {
this.homeEndSubscription.unsubscribe() this.homeEndSubscription.unsubscribe()
super.ngOnDestroy() super.ngOnDestroy()
} }

View File

@@ -1,18 +1,18 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { TabRecoveryProvider, RecoveredTab } from 'terminus-core' import { TabRecoveryProvider, RecoveredTab, RecoveryToken } from 'terminus-core'
import { SSHTabComponent } from './components/sshTab.component' import { SSHTabComponent } from './components/sshTab.component'
/** @hidden */ /** @hidden */
@Injectable() @Injectable()
export class RecoveryProvider extends TabRecoveryProvider { export class RecoveryProvider extends TabRecoveryProvider {
async recover (recoveryToken: any): Promise<RecoveredTab|null> { async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
if (recoveryToken && recoveryToken.type === 'app:ssh-tab') { if (recoveryToken?.type === 'app:ssh-tab') {
return { return {
type: SSHTabComponent, type: SSHTabComponent,
options: { options: {
connection: recoveryToken.connection, connection: recoveryToken['connection'],
savedState: recoveryToken.savedState, savedState: recoveryToken['savedState'],
}, },
} }
} }

View File

@@ -174,7 +174,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
} }
/** @hidden */ /** @hidden */
ngOnInit () { ngOnInit (): void {
this.focused$.subscribe(() => { this.focused$.subscribe(() => {
this.configure() this.configure()
this.frontend.focus() this.frontend.focus()
@@ -259,7 +259,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
/** /**
* Feeds input into the active session * Feeds input into the active session
*/ */
sendInput (data: string|Buffer) { sendInput (data: string|Buffer): void {
if (!(data instanceof Buffer)) { if (!(data instanceof Buffer)) {
data = Buffer.from(data, 'utf-8') data = Buffer.from(data, 'utf-8')
} }
@@ -272,7 +272,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
/** /**
* Feeds input into the terminal frontend * Feeds input into the terminal frontend
*/ */
write (data: string) { write (data: string): void {
const percentageMatch = /(^|[^\d])(\d+(\.\d+)?)%([^\d]|$)/.exec(data) const percentageMatch = /(^|[^\d])(\d+(\.\d+)?)%([^\d]|$)/.exec(data)
if (percentageMatch) { if (percentageMatch) {
const percentage = percentageMatch[3] ? parseFloat(percentageMatch[2]) : parseInt(percentageMatch[2]) const percentage = percentageMatch[3] ? parseFloat(percentageMatch[2]) : parseInt(percentageMatch[2])
@@ -286,7 +286,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.frontend.write(data) this.frontend.write(data)
} }
paste () { paste (): void {
let data = this.electron.clipboard.readText() as string let data = this.electron.clipboard.readText() as string
if (this.config.store.terminal.bracketedPaste) { if (this.config.store.terminal.bracketedPaste) {
data = '\x1b[200~' + data + '\x1b[201~' data = '\x1b[200~' + data + '\x1b[201~'
@@ -318,23 +318,23 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
} }
} }
zoomIn () { zoomIn (): void {
this.zoom++ this.zoom++
this.frontend.setZoom(this.zoom) this.frontend.setZoom(this.zoom)
} }
zoomOut () { zoomOut (): void {
this.zoom-- this.zoom--
this.frontend.setZoom(this.zoom) this.frontend.setZoom(this.zoom)
} }
resetZoom () { resetZoom (): void {
this.zoom = 0 this.zoom = 0
this.frontend.setZoom(this.zoom) this.frontend.setZoom(this.zoom)
} }
/** @hidden */ /** @hidden */
ngOnDestroy () { ngOnDestroy (): void {
this.frontend.detach(this.content.nativeElement) this.frontend.detach(this.content.nativeElement)
this.detachTermContainerHandlers() this.detachTermContainerHandlers()
this.config.enabledServices(this.decorators).forEach(decorator => { this.config.enabledServices(this.decorators).forEach(decorator => {
@@ -351,21 +351,21 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.output.complete() this.output.complete()
} }
async destroy () { async destroy (): Promise<void> {
super.destroy() super.destroy()
if (this.session && this.session.open) { if (this.session && this.session.open) {
await this.session.destroy() await this.session.destroy()
} }
} }
protected detachTermContainerHandlers () { protected detachTermContainerHandlers (): void {
for (const subscription of this.termContainerSubscriptions) { for (const subscription of this.termContainerSubscriptions) {
subscription.unsubscribe() subscription.unsubscribe()
} }
this.termContainerSubscriptions = [] this.termContainerSubscriptions = []
} }
protected attachTermContainerHandlers () { protected attachTermContainerHandlers (): void {
this.detachTermContainerHandlers() this.detachTermContainerHandlers()
const maybeConfigure = () => { const maybeConfigure = () => {
@@ -437,7 +437,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
] ]
} }
protected attachSessionHandlers () { protected attachSessionHandlers (): void {
// this.session.output$.bufferTime(10).subscribe((datas) => { // this.session.output$.bufferTime(10).subscribe((datas) => {
this.session.output$.subscribe(data => { this.session.output$.subscribe(data => {
if (this.enablePassthrough) { if (this.enablePassthrough) {

View File

@@ -26,7 +26,7 @@ export abstract class TerminalDecorator {
/** /**
* Automatically cancel @subscription once detached from @terminal * Automatically cancel @subscription once detached from @terminal
*/ */
protected subscribeUntilDetached (terminal: BaseTerminalTabComponent, subscription: Subscription) { protected subscribeUntilDetached (terminal: BaseTerminalTabComponent, subscription: Subscription): void {
if (!this.smartSubscriptions.has(terminal)) { if (!this.smartSubscriptions.has(terminal)) {
this.smartSubscriptions.set(terminal, []) this.smartSubscriptions.set(terminal, [])
} }

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import * as fs from 'mz/fs' import * as fs from 'mz/fs'
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { ToolbarButtonProvider, ToolbarButton, ElectronService } from 'terminus-core' import { ToolbarButtonProvider, ToolbarButton, ElectronService } from 'terminus-core'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Observable } from 'rxjs' import { Observable } from 'rxjs'
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators' import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators'
import { exec } from 'mz/child_process' import { exec } from 'mz/child_process'

View File

@@ -15,7 +15,7 @@ export class ColorPickerComponent {
@ViewChild('input') input @ViewChild('input') input
isOpen: boolean isOpen: boolean
open () { open (): void {
setImmediate(() => { setImmediate(() => {
this.popover.open() this.popover.open()
setImmediate(() => { setImmediate(() => {
@@ -25,7 +25,7 @@ export class ColorPickerComponent {
}) })
} }
@HostListener('document:click', ['$event']) onOutsideClick ($event) { @HostListener('document:click', ['$event']) onOutsideClick ($event: MouseEvent): void {
if (!this.isOpen) { if (!this.isOpen) {
return return
} }
@@ -40,7 +40,7 @@ export class ColorPickerComponent {
} }
} }
onChange () { onChange (): void {
this.modelChange.emit(this.model) this.modelChange.emit(this.model)
} }
} }

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component } from '@angular/core' import { Component } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { UACService } from '../services/uac.service' import { UACService } from '../services/uac.service'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Output, Input } from '@angular/core' import { Component, Output, Input } from '@angular/core'
import { Subject } from 'rxjs' import { Subject } from 'rxjs'

View File

@@ -21,19 +21,19 @@ export class SearchPanelComponent {
private toastr: ToastrService, private toastr: ToastrService,
) { } ) { }
onQueryChange () { onQueryChange (): void {
this.notFound = false this.notFound = false
this.findNext(true) this.findNext(true)
} }
findNext (incremental = false) { findNext (incremental = false): void {
if (!this.frontend.findNext(this.query, { ...this.options, incremental: incremental || undefined })) { if (!this.frontend.findNext(this.query, { ...this.options, incremental: incremental || undefined })) {
this.notFound = true this.notFound = true
this.toastr.error('Not found') this.toastr.error('Not found')
} }
} }
findPrevious () { findPrevious (): void {
if (!this.frontend.findPrevious(this.query, this.options)) { if (!this.frontend.findPrevious(this.query, this.options)) {
this.notFound = true this.notFound = true
this.toastr.error('Not found') this.toastr.error('Not found')

View File

@@ -37,19 +37,19 @@ export class ShellSettingsTabComponent {
this.isConPTYStable = isWindowsBuild(WIN_BUILD_CONPTY_STABLE) this.isConPTYStable = isWindowsBuild(WIN_BUILD_CONPTY_STABLE)
} }
async ngOnInit () { async ngOnInit (): void {
this.shells = await this.terminalService.shells$.toPromise() this.shells = await this.terminalService.shells$.toPromise()
} }
ngOnDestroy () { ngOnDestroy (): void {
this.configSubscription.unsubscribe() this.configSubscription.unsubscribe()
} }
async reload () { async reload (): void {
this.profiles = await this.terminalService.getProfiles(true) this.profiles = await this.terminalService.getProfiles(true)
} }
pickWorkingDirectory () { pickWorkingDirectory (): void {
const shell = this.shells.find(x => x.id === this.config.store.terminal.shell) const shell = this.shells.find(x => x.id === this.config.store.terminal.shell)
if (!shell) { if (!shell) {
return return
@@ -66,7 +66,7 @@ export class ShellSettingsTabComponent {
} }
} }
newProfile (shell: Shell) { newProfile (shell: Shell): void {
const profile: Profile = { const profile: Profile = {
name: shell.name || '', name: shell.name || '',
sessionOptions: this.terminalService.optionsFromShell(shell), sessionOptions: this.terminalService.optionsFromShell(shell),
@@ -76,7 +76,7 @@ export class ShellSettingsTabComponent {
this.reload() this.reload()
} }
editProfile (profile: Profile) { editProfile (profile: Profile): void {
const modal = this.ngbModal.open(EditProfileModalComponent) const modal = this.ngbModal.open(EditProfileModalComponent)
modal.componentInstance.profile = Object.assign({}, profile) modal.componentInstance.profile = Object.assign({}, profile)
modal.result.then(result => { modal.result.then(result => {
@@ -85,7 +85,7 @@ export class ShellSettingsTabComponent {
}) })
} }
deleteProfile (profile: Profile) { deleteProfile (profile: Profile): void {
this.config.store.terminal.profiles = this.config.store.terminal.profiles.filter(x => x !== profile) this.config.store.terminal.profiles = this.config.store.terminal.profiles.filter(x => x !== profile)
this.config.save() this.config.save()
this.reload() this.reload()

View File

@@ -13,7 +13,7 @@ export class TerminalSettingsTabComponent {
private terminal: TerminalService, private terminal: TerminalService,
) { } ) { }
openWSLVolumeMixer () { openWSLVolumeMixer (): void {
this.electron.shell.openItem('sndvol.exe') this.electron.shell.openItem('sndvol.exe')
this.terminal.openTab({ this.terminal.openTab({
name: '', name: '',

View File

@@ -24,7 +24,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
super(injector) super(injector)
} }
ngOnInit () { ngOnInit (): void {
this.logger = this.log.create('terminalTab') this.logger = this.log.create('terminalTab')
this.session = new Session(this.config) this.session = new Session(this.config)
@@ -51,7 +51,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
super.ngOnInit() super.ngOnInit()
} }
initializeSession (columns: number, rows: number) { initializeSession (columns: number, rows: number): void {
this.sessions.addSession( this.sessions.addSession(
this.session, this.session,
Object.assign({}, this.sessionOptions, { Object.assign({}, this.sessionOptions, {
@@ -101,7 +101,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
)).response === 1 )).response === 1
} }
ngOnDestroy () { ngOnDestroy (): void {
this.homeEndSubscription.unsubscribe() this.homeEndSubscription.unsubscribe()
super.ngOnDestroy() super.ngOnDestroy()
this.session.destroy() this.session.destroy()

View File

@@ -61,7 +61,7 @@ export class DebugDecorator extends TerminalDecorator {
}) })
} }
async loadFile (): Promise<string|null> { private async loadFile (): Promise<string|null> {
const result = await this.electron.dialog.showOpenDialog( const result = await this.electron.dialog.showOpenDialog(
this.hostApp.getWindow(), this.hostApp.getWindow(),
{ {
@@ -75,7 +75,7 @@ export class DebugDecorator extends TerminalDecorator {
return null return null
} }
async saveFile (content: string, name: string) { private async saveFile (content: string, name: string) {
const result = await this.electron.dialog.showSaveDialog( const result = await this.electron.dialog.showSaveDialog(
this.hostApp.getWindow(), this.hostApp.getWindow(),
{ {
@@ -87,21 +87,21 @@ export class DebugDecorator extends TerminalDecorator {
} }
} }
doSaveState (terminal: TerminalTabComponent) { private doSaveState (terminal: TerminalTabComponent) {
this.saveFile(terminal.frontend.saveState(), 'state.txt') this.saveFile(terminal.frontend.saveState(), 'state.txt')
} }
async doCopyState (terminal: TerminalTabComponent) { private async doCopyState (terminal: TerminalTabComponent) {
const data = '```' + JSON.stringify(terminal.frontend.saveState()) + '```' const data = '```' + JSON.stringify(terminal.frontend.saveState()) + '```'
this.electron.clipboard.writeText(data) this.electron.clipboard.writeText(data)
} }
async doLoadState (terminal: TerminalTabComponent) { private async doLoadState (terminal: TerminalTabComponent) {
const data = await this.loadFile() const data = await this.loadFile()
terminal.frontend.restoreState(data) terminal.frontend.restoreState(data)
} }
async doPasteState (terminal: TerminalTabComponent) { private async doPasteState (terminal: TerminalTabComponent) {
let data = this.electron.clipboard.readText() let data = this.electron.clipboard.readText()
if (data) { if (data) {
if (data.startsWith('`')) { if (data.startsWith('`')) {
@@ -111,23 +111,23 @@ export class DebugDecorator extends TerminalDecorator {
} }
} }
doSaveOutput (buffer: string) { private doSaveOutput (buffer: string) {
this.saveFile(buffer, 'output.txt') this.saveFile(buffer, 'output.txt')
} }
async doCopyOutput (buffer: string) { private async doCopyOutput (buffer: string) {
const data = '```' + JSON.stringify(buffer) + '```' const data = '```' + JSON.stringify(buffer) + '```'
this.electron.clipboard.writeText(data) this.electron.clipboard.writeText(data)
} }
async doLoadOutput (terminal: TerminalTabComponent) { private async doLoadOutput (terminal: TerminalTabComponent) {
const data = await this.loadFile() const data = await this.loadFile()
if (data) { if (data) {
terminal.frontend.write(data) terminal.frontend.write(data)
} }
} }
async doPasteOutput (terminal: TerminalTabComponent) { private async doPasteOutput (terminal: TerminalTabComponent) {
let data = this.electron.clipboard.readText() let data = this.electron.clipboard.readText()
if (data) { if (data) {
if (data.startsWith('`')) { if (data.startsWith('`')) {

View File

@@ -19,7 +19,7 @@ export class PathDropDecorator extends TerminalDecorator {
}) })
} }
injectPath (terminal: TerminalTabComponent, path: string) { private injectPath (terminal: TerminalTabComponent, path: string) {
if (path.includes(' ')) { if (path.includes(' ')) {
path = `"${path}"` path = `"${path}"`
} }

View File

@@ -68,7 +68,7 @@ export class ZModemDecorator extends TerminalDecorator {
}) })
} }
async process (terminal, detection) { private async process (terminal, detection): Promise<void> {
this.showMessage(terminal, colors.bgBlue.black(' ZMODEM ') + ' Session started') this.showMessage(terminal, colors.bgBlue.black(' ZMODEM ') + ' Session started')
this.showMessage(terminal, '------------------------') this.showMessage(terminal, '------------------------')

View File

@@ -76,5 +76,5 @@ export abstract class Frontend {
abstract findPrevious (term: string, searchOptions?: SearchOptions): boolean abstract findPrevious (term: string, searchOptions?: SearchOptions): boolean
abstract saveState (): any abstract saveState (): any
abstract restoreState (state: any): void abstract restoreState (state: string): void
} }

View File

@@ -13,7 +13,7 @@ export class HTermFrontend extends Frontend {
private configuredBackgroundColor = 'transparent' private configuredBackgroundColor = 'transparent'
private zoom = 0 private zoom = 0
attach (host: HTMLElement) { attach (host: HTMLElement): void {
if (!this.initialized) { if (!this.initialized) {
this.init() this.init()
this.initialized = true this.initialized = true
@@ -29,15 +29,15 @@ export class HTermFrontend extends Frontend {
return this.term.getSelectionText() return this.term.getSelectionText()
} }
copySelection () { copySelection (): void {
this.term.copySelectionToClipboard() this.term.copySelectionToClipboard()
} }
clearSelection () { clearSelection (): void {
this.term.getDocument().getSelection().removeAllRanges() this.term.getDocument().getSelection().removeAllRanges()
} }
focus () { focus (): void {
setTimeout(() => { setTimeout(() => {
this.term.scrollPort_.resize() this.term.scrollPort_.resize()
this.term.scrollPort_.focus() this.term.scrollPort_.focus()
@@ -168,7 +168,7 @@ export class HTermFrontend extends Frontend {
saveState (): any { } saveState (): any { }
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
restoreState (_state: any): void { } restoreState (_state: string): void { }
private setFontSize () { private setFontSize () {
const size = this.configuredFontSize * Math.pow(1.1, this.zoom) const size = this.configuredFontSize * Math.pow(1.1, this.zoom)
@@ -262,7 +262,7 @@ export class HTermFrontend extends Frontend {
// Drop whitespace at the end of selection // Drop whitespace at the end of selection
const range = selection.getRangeAt(0) const range = selection.getRangeAt(0)
if (range.endOffset > 0 && range.endContainer.nodeType === 3 && range.endContainer.textContent !== '') { if (range.endOffset > 0 && range.endContainer.nodeType === 3 && range.endContainer.textContent !== '') {
while (/[\s\S]+\s$/.test(range.endContainer.textContent.substr(0,range.endOffset))) { while (/[\s\S]+\s$/.test(range.endContainer.textContent.substr(0, range.endOffset))) {
range.setEnd(range.endContainer, range.endOffset - 1) range.setEnd(range.endContainer, range.endOffset - 1)
} }
} }

View File

@@ -259,7 +259,7 @@ export class XTermFrontend extends Frontend {
return this.serializeAddon.serialize(1000) return this.serializeAddon.serialize(1000)
} }
restoreState (state: any): void { restoreState (state: string): void {
this.xterm.write(state) this.xterm.write(state)
} }

View File

@@ -1,18 +1,18 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { TabRecoveryProvider, RecoveredTab } from 'terminus-core' import { TabRecoveryProvider, RecoveredTab, RecoveryToken } from 'terminus-core'
import { TerminalTabComponent } from './components/terminalTab.component' import { TerminalTabComponent } from './components/terminalTab.component'
/** @hidden */ /** @hidden */
@Injectable() @Injectable()
export class RecoveryProvider extends TabRecoveryProvider { export class RecoveryProvider extends TabRecoveryProvider {
async recover (recoveryToken: any): Promise<RecoveredTab|null> { async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
if (recoveryToken && recoveryToken.type === 'app:terminal-tab') { if (recoveryToken?.type === 'app:terminal-tab') {
return { return {
type: TerminalTabComponent, type: TerminalTabComponent,
options: { options: {
sessionOptions: recoveryToken.sessionOptions, sessionOptions: recoveryToken['sessionOptions'],
savedState: recoveryToken.savedState, savedState: recoveryToken['savedState'],
}, },
} }
} }

View File

@@ -17,7 +17,7 @@ export class DockMenuService {
config.changed$.subscribe(() => this.update()) config.changed$.subscribe(() => this.update())
} }
update () { update (): void {
if (this.hostApp.platform === Platform.Windows) { if (this.hostApp.platform === Platform.Windows) {
this.electron.app.setJumpList(this.config.store.terminal.profiles.length ? [{ this.electron.app.setJumpList(this.config.store.terminal.profiles.length ? [{
type: 'custom', type: 'custom',

View File

@@ -52,7 +52,7 @@ export abstract class BaseSession {
get closed$ (): Observable<void> { return this.closed } get closed$ (): Observable<void> { return this.closed }
get destroyed$ (): Observable<void> { return this.destroyed } get destroyed$ (): Observable<void> { return this.destroyed }
emitOutput (data: Buffer) { emitOutput (data: Buffer): void {
if (!this.initialDataBufferReleased) { if (!this.initialDataBufferReleased) {
this.initialDataBuffer = Buffer.concat([this.initialDataBuffer, data]) this.initialDataBuffer = Buffer.concat([this.initialDataBuffer, data])
} else { } else {
@@ -61,7 +61,7 @@ export abstract class BaseSession {
} }
} }
releaseInitialDataBuffer () { releaseInitialDataBuffer (): void {
this.initialDataBufferReleased = true this.initialDataBufferReleased = true
this.output.next(this.initialDataBuffer.toString()) this.output.next(this.initialDataBuffer.toString())
this.binaryOutput.next(this.initialDataBuffer) this.binaryOutput.next(this.initialDataBuffer)
@@ -99,7 +99,7 @@ export class Session extends BaseSession {
super() super()
} }
start (options: SessionOptions) { start (options: SessionOptions): void {
this.name = options.name || '' this.name = options.name || ''
const env = { const env = {
@@ -182,31 +182,13 @@ export class Session extends BaseSession {
this.pauseAfterExit = options.pauseAfterExit || false this.pauseAfterExit = options.pauseAfterExit || false
} }
processOSC1337 (data: Buffer) { resize (columns: number, rows: number): void {
if (data.includes(OSC1337Prefix)) {
const preData = data.subarray(0, data.indexOf(OSC1337Prefix))
let params = data.subarray(data.indexOf(OSC1337Prefix) + OSC1337Prefix.length)
const postData = params.subarray(params.indexOf(OSC1337Suffix) + OSC1337Suffix.length)
const paramString = params.subarray(0, params.indexOf(OSC1337Suffix)).toString()
if (paramString.startsWith('CurrentDir=')) {
this.reportedCWD = paramString.split('=')[1]
if (this.reportedCWD.startsWith('~')) {
this.reportedCWD = os.homedir() + this.reportedCWD.substring(1)
}
data = Buffer.concat([preData, postData])
}
}
return data
}
resize (columns, rows) {
if (this.pty._writable) { if (this.pty._writable) {
this.pty.resize(columns, rows) this.pty.resize(columns, rows)
} }
} }
write (data: Buffer) { write (data: Buffer): void {
if (this.open) { if (this.open) {
if (this.pty._writable) { if (this.pty._writable) {
this.pty.write(data) this.pty.write(data)
@@ -216,7 +198,7 @@ export class Session extends BaseSession {
} }
} }
kill (signal?: string) { kill (signal?: string): void {
this.pty.kill(signal) this.pty.kill(signal)
} }
@@ -323,6 +305,24 @@ export class Session extends BaseSession {
this.guessedCWD = match[0] this.guessedCWD = match[0]
} }
} }
private processOSC1337 (data: Buffer) {
if (data.includes(OSC1337Prefix)) {
const preData = data.subarray(0, data.indexOf(OSC1337Prefix))
let params = data.subarray(data.indexOf(OSC1337Prefix) + OSC1337Prefix.length)
const postData = params.subarray(params.indexOf(OSC1337Suffix) + OSC1337Suffix.length)
const paramString = params.subarray(0, params.indexOf(OSC1337Suffix)).toString()
if (paramString.startsWith('CurrentDir=')) {
this.reportedCWD = paramString.split('=')[1]
if (this.reportedCWD.startsWith('~')) {
this.reportedCWD = os.homedir() + this.reportedCWD.substring(1)
}
data = Buffer.concat([preData, postData])
}
}
return data
}
} }
/** @hidden */ /** @hidden */
@@ -339,7 +339,7 @@ export class SessionsService {
this.logger = log.create('sessions') this.logger = log.create('sessions')
} }
addSession (session: BaseSession, options: SessionOptions) { addSession (session: BaseSession, options: SessionOptions): BaseSession {
this.lastID++ this.lastID++
options.name = `session-${this.lastID}` options.name = `session-${this.lastID}`
session.start(options) session.start(options)

View File

@@ -137,7 +137,7 @@ export class CopyPasteContextMenu extends TabContextMenuItemProvider {
return [ return [
{ {
label: 'Copy', label: 'Copy',
click: () => { click: (): void => {
this.zone.run(() => { this.zone.run(() => {
setTimeout(() => { setTimeout(() => {
(tab as BaseTerminalTabComponent).frontend.copySelection() (tab as BaseTerminalTabComponent).frontend.copySelection()
@@ -148,7 +148,7 @@ export class CopyPasteContextMenu extends TabContextMenuItemProvider {
}, },
{ {
label: 'Paste', label: 'Paste',
click: () => { click: (): void => {
this.zone.run(() => (tab as BaseTerminalTabComponent).paste()) this.zone.run(() => (tab as BaseTerminalTabComponent).paste())
}, },
}, },