1
1
mirror of https://github.com/Eugeny/tabby.git synced 2024-11-27 10:42:35 +03:00
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'))
}
@ -52,20 +52,20 @@ export class Application {
return window
}
broadcast (event, ...args) {
for (let window of this.windows) {
broadcast (event: string, ...args): void {
for (const window of this.windows) {
window.send(event, ...args)
}
}
async send (event, ...args) {
async send (event: string, ...args): void {
if (!this.hasWindows()) {
await this.newWindow()
}
this.windows.filter(w => !w.isDestroyed())[0].send(event, ...args)
}
enableTray () {
enableTray (): void {
if (this.tray) {
return
}
@ -90,18 +90,18 @@ export class Application {
this.tray.setToolTip(`Terminus ${app.getVersion()}`)
}
disableTray () {
disableTray (): void {
if (this.tray) {
this.tray.destroy()
this.tray = null
}
}
hasWindows () {
hasWindows (): bool {
return !!this.windows.length
}
focus () {
focus (): void {
for (let window of this.windows) {
window.show()
}

View File

@ -1,6 +1,6 @@
import { app } from 'electron'
export function parseArgs (argv, cwd) {
export function parseArgs (argv: string[], cwd: string): any {
if (argv[0].includes('node')) {
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 }
if (process.platform === 'win32') {
if (parseFloat(os.release()) >= 10) {
@ -140,22 +140,22 @@ export class Window {
}
}
show () {
show (): void {
this.window.show()
}
focus () {
focus (): void {
this.window.focus()
}
send (event, ...args) {
send (event: string, ...args): void {
if (!this.window) {
return
}
this.window.webContents.send(event, ...args)
}
isDestroyed () {
isDestroyed (): void {
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 { BrowserModule } from '@angular/platform-browser'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'

View File

@ -1,7 +1,7 @@
export { BaseTabComponent, BaseTabProcess } from '../components/baseTab.component'
export { TabHeaderComponent } from '../components/tabHeader.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 { ConfigProvider } from './configProvider'
export { HotkeyProvider, HotkeyDescription } from './hotkeyProvider'

View File

@ -12,6 +12,12 @@ export interface RecoveredTab {
options?: any
}
export interface RecoveryToken {
[_: string]: any
type: string
tabColor?: string|null
}
/**
* Extend to enable recovery for your custom tab.
* This works in conjunction with [[getRecoveryToken()]]
@ -34,5 +40,5 @@ export abstract class TabRecoveryProvider {
* @returns [[RecoveredTab]] descriptor containing tab type and component inputs
* 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 { trigger, style, animate, transition, state } from '@angular/animations'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'

View File

@ -1,5 +1,6 @@
import { Observable, Subject } from 'rxjs'
import { ViewRef } from '@angular/core'
import { RecoveryToken } from '../api/tabRecovery'
/**
* 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
if (!this.customTitle) {
this.titleChange.next(title)
@ -83,7 +84,7 @@ export abstract class BaseTabComponent {
*
* @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)
if (progress) {
if (this.progressClearTimeout) {
@ -118,7 +119,7 @@ export abstract class BaseTabComponent {
* @return JSON serializable tab state representation
* for your [[TabRecoveryProvider]] to parse
*/
async getRecoveryToken (): Promise<any> {
async getRecoveryToken (): Promise<RecoveryToken|null> {
return null
}
@ -136,11 +137,11 @@ export abstract class BaseTabComponent {
return true
}
emitFocused () {
emitFocused (): void {
this.focused.next()
}
emitBlurred () {
emitBlurred (): void {
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 { 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 { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'

View File

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

View File

@ -17,11 +17,11 @@ export class SelectorModalComponent<T> {
public modalInstance: NgbActiveModal,
) { }
ngOnInit () {
ngOnInit (): void {
this.onFilterChange()
}
onFilterChange () {
onFilterChange (): void {
const f = this.filter.trim().toLowerCase()
if (!f) {
this.filteredOptions = this.options
@ -31,17 +31,17 @@ export class SelectorModalComponent<T> {
}
}
onFilterEnter () {
onFilterEnter (): void {
if (this.filteredOptions.length === 1) {
this.selectOption(this.filteredOptions[0])
}
}
selectOption (option: SelectorOption<T>) {
selectOption (option: SelectorOption<T>): void {
this.modalInstance.close(option.result)
}
close () {
close (): void {
this.modalInstance.dismiss()
}
}

View File

@ -1,7 +1,7 @@
import { Observable, Subject, Subscription } from 'rxjs'
import { Component, Injectable, ViewChild, ViewContainerRef, EmbeddedViewRef, AfterViewInit, OnDestroy } from '@angular/core'
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 { HotkeysService } from '../services/hotkeys.service'
import { TabRecoveryService } from '../services/tabRecovery.service'
@ -48,7 +48,7 @@ export class SplitContainer {
/**
* Remove unnecessarily nested child containers and renormalizes [[ratios]]
*/
normalize () {
normalize (): void {
for (let i = 0; i < this.children.length; i++) {
const child = this.children[i]
@ -93,7 +93,7 @@ export class SplitContainer {
return s
}
async serialize () {
async serialize (): Promise<RecoveryToken> {
const children: any[] = []
for (const child of this.children) {
if (child instanceof SplitContainer) {
@ -250,7 +250,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
}
/** @hidden */
async ngAfterViewInit () {
async ngAfterViewInit (): Promise<void> {
if (this._recoveredState) {
await this.recoverContainer(this.root, this._recoveredState)
this.layout()
@ -266,12 +266,12 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
}
/** @hidden */
ngOnDestroy () {
ngOnDestroy (): void {
this.hotkeysSubscription.unsubscribe()
}
/** @returns Flat list of all sub-tabs */
getAllTabs () {
getAllTabs (): BaseTabComponent[] {
return this.root.getAllTabs()
}
@ -283,7 +283,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
return this.maximizedTab
}
focus (tab: BaseTabComponent) {
focus (tab: BaseTabComponent): void {
this.focusedTab = tab
for (const x of this.getAllTabs()) {
if (x !== tab) {
@ -301,7 +301,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
this.layout()
}
maximize (tab: BaseTabComponent|null) {
maximize (tab: BaseTabComponent|null): void {
this.maximizedTab = tab
this.layout()
}
@ -309,7 +309,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
/**
* Focuses the first available tab inside the given [[SplitContainer]]
*/
focusAnyIn (parent: BaseTabComponent | SplitContainer) {
focusAnyIn (parent: BaseTabComponent | SplitContainer): void {
if (!parent) {
return
}
@ -323,7 +323,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
/**
* 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()
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)
if (!parent) {
return
@ -389,7 +389,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
/**
* Moves focus in the given direction
*/
navigate (dir: SplitDirection) {
navigate (dir: SplitDirection): void {
let rel: BaseTabComponent | SplitContainer = this.focusedTab
let parent = this.getParentOf(rel)
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)
if (newTab) {
this.addTab(newTab, tab, dir)
}
return newTab
}
/**
@ -464,12 +465,12 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
}
/** @hidden */
onSpannerAdjusted (spanner: SplitSpannerInfo) {
onSpannerAdjusted (spanner: SplitSpannerInfo): void {
this.layout()
this.splitAdjusted.next(spanner)
}
destroy () {
destroy (): void {
super.destroy()
for (const x of this.getAllTabs()) {
x.destroy()
@ -584,7 +585,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
/** @hidden */
@Injectable()
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') {
return {
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 { 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 { 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 { SortableComponent } from 'ng2-dnd'
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 { BaseTabComponent } from './baseTab.component'
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 { HostAppService } from '../services/hostApp.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 {
constructor (private el: ElementRef) { }
ngAfterViewInit () {
ngAfterViewInit (): void {
this.el.nativeElement.blur()
setTimeout(() => {
this.el.nativeElement.focus()

View File

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

View File

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

View File

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

View File

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

View File

@ -46,7 +46,7 @@ export class ElectronService {
/**
* Removes OS focus from Terminus' window
*/
loseFocus () {
loseFocus (): void {
if (process.platform === 'darwin') {
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')
}
reportBug () {
reportBug (): void {
let body = `Version: ${this.appVersion}\n`
body += `Platform: ${os.platform()} ${os.release()}\n`
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}`)
}
enableAnalytics () {
enableAnalytics (): void {
if (!window.localStorage.analyticsUserID) {
window.localStorage.analyticsUserID = uuidv4()
}
@ -56,7 +56,7 @@ export class HomeBaseService {
this.mixpanel.track('launch', this.getAnalyticsProperties())
}
getAnalyticsProperties () {
getAnalyticsProperties (): Record<string, string> {
return {
distinct_id: window.localStorage.analyticsUserID, // eslint-disable-line @typescript-eslint/camelcase
platform: process.platform,

View File

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

View File

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

View File

@ -32,27 +32,27 @@ export class Logger {
private name: string,
) {}
debug (...args: any[]) {
debug (...args: any[]): void {
this.doLog('debug', ...args)
}
info (...args: any[]) {
info (...args: any[]): void {
this.doLog('info', ...args)
}
warn (...args: any[]) {
warn (...args: any[]): void {
this.doLog('warn', ...args)
}
error (...args: any[]) {
error (...args: any[]): void {
this.doLog('error', ...args)
}
log (...args: any[]) {
log (...args: any[]): void {
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)
if (this.winstonLogger) {
this.winstonLogger[level](...args)

View File

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

View File

@ -1,5 +1,5 @@
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 { Logger, LogService } from '../services/log.service'
import { ConfigService } from '../services/config.service'
@ -17,7 +17,7 @@ export class TabRecoveryService {
this.logger = log.create('tabRecovery')
}
async saveTabs (tabs: BaseTabComponent[]) {
async saveTabs (tabs: BaseTabComponent[]): Promise<void> {
window.localStorage.tabsRecovery = JSON.stringify(
await Promise.all(
tabs
@ -25,7 +25,7 @@ export class TabRecoveryService {
let token = tab.getRecoveryToken()
if (token) {
token = token.then(r => {
if (r) {
if (r && tab.color) {
r.tabColor = tab.color
}
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)) {
try {
const tab = await provider.recover(token)

View File

@ -17,7 +17,7 @@ export class TabsService {
/**
* 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 componentRef = componentFactory.create(this.injector)
const tab = componentRef.instance

View File

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

View File

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

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Injectable, NgZone } from '@angular/core'
import { Subscription } from 'rxjs'
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
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function getCSSFontFamily (config: any): string {
let fonts: string[] = config.terminal.font.split(',').map(x => x.trim().replace(/"/g, ''))
if (config.terminal.fallbackFont) {

View File

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

View File

@ -40,7 +40,7 @@ export class PluginManagerService {
this.logger = log.create('pluginManager')
}
async getNPM () {
async getNPM (): Promise<any> {
if (!this.npm) {
if (!this.npmReady) {
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 => {
if (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 => {
if (err) {
this.logger.error(err)

View File

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

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Injectable } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
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 { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
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 { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
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 { NgbModal } from '@ng-bootstrap/ng-bootstrap'
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 { Spinner } from 'cli-spinner'
import { Component, Injector } from '@angular/core'

View File

@ -1,18 +1,18 @@
import { Injectable } from '@angular/core'
import { TabRecoveryProvider, RecoveredTab } from 'terminus-core'
import { TabRecoveryProvider, RecoveredTab, RecoveryToken } from 'terminus-core'
import { SerialTabComponent } from './components/serialTab.component'
/** @hidden */
@Injectable()
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') {
return {
type: SerialTabComponent,
options: {
connection: recoveryToken.connection,
savedState: recoveryToken.savedState,
connection: recoveryToken['connection'],
savedState: recoveryToken['savedState'],
},
}
}

View File

@ -27,7 +27,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
title: 'Settings',
touchBarNSImage: 'NSTouchBarComposeTemplate',
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())
}
ngOnInit () {
ngOnInit (): void {
this.keyTimeoutInterval = window.setInterval(() => {
if (!this.lastKeyEvent) {
return
@ -74,14 +74,14 @@ export class HotkeyInputModalComponent {
this.hotkeys.disable()
}
ngOnDestroy () {
ngOnDestroy (): void {
this.keySubscription.unsubscribe()
this.hotkeys.clearCurrentKeystrokes()
this.hotkeys.enable()
clearInterval(this.keyTimeoutInterval!)
}
close () {
close (): void {
this.modalInstance.dismiss()
}
}

View File

@ -17,7 +17,7 @@ export class MultiHotkeyInputComponent {
private ngbModal: NgbModal,
) { }
ngOnInit () {
ngOnInit (): void {
if (!this.model) {
this.model = []
}
@ -27,7 +27,7 @@ export class MultiHotkeyInputComponent {
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.model[this.model.findIndex(x => x === item)] = value
this.model = this.model.slice()
@ -35,14 +35,14 @@ export class MultiHotkeyInputComponent {
})
}
addItem () {
addItem (): void {
this.ngbModal.open(HotkeyInputModalComponent).result.then((value: string[]) => {
this.model = this.model.concat([value])
this.modelChange.emit(this.model)
})
}
removeItem (item) {
removeItem (item: string[]): void {
this.model = this.model.filter(x => x !== item)
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 { Subscription } from 'rxjs'
import { Component, Inject, Input, HostBinding, NgZone } from '@angular/core'

View File

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

View File

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

View File

@ -16,20 +16,20 @@ export class PromptModalComponent {
private modalInstance: NgbActiveModal,
) { }
ngOnInit () {
ngOnInit (): void {
setTimeout(() => {
this.input.nativeElement.focus()
})
}
ok () {
ok (): void {
this.modalInstance.close({
value: this.value,
remember: this.remember,
})
}
cancel () {
cancel (): void {
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 { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
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 { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
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 { NgbModal } from '@ng-bootstrap/ng-bootstrap'
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 { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { first } from 'rxjs/operators'
import { RecoveryToken } from 'terminus-core'
import { BaseTerminalTabComponent } from 'terminus-terminal'
import { SSHService } from '../services/ssh.service'
import { SSHConnection, SSHSession } from '../api'
@ -29,7 +30,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
super(injector)
}
ngOnInit () {
ngOnInit (): void {
this.logger = this.log.create('terminalTab')
this.homeEndSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
@ -57,7 +58,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
})
}
async initializeSession () {
async initializeSession (): void {
if (!this.connection) {
this.logger.error('No SSH connection info supplied')
return
@ -96,7 +97,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
this.session.resize(this.size.columns, this.size.rows)
}
async getRecoveryToken (): Promise<any> {
async getRecoveryToken (): Promise<RecoveryToken> {
return {
type: 'app:ssh-tab',
connection: this.connection,
@ -104,16 +105,16 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
}
}
showPortForwarding () {
showPortForwarding (): void {
const modal = this.ngbModal.open(SSHPortForwardingModalComponent).componentInstance as SSHPortForwardingModalComponent
modal.session = this.session
}
reconnect () {
reconnect (): void {
this.initializeSession()
}
ngOnDestroy () {
ngOnDestroy (): void {
this.homeEndSubscription.unsubscribe()
super.ngOnDestroy()
}

View File

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

View File

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

View File

@ -26,7 +26,7 @@ export abstract class TerminalDecorator {
/**
* 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)) {
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 { Injectable } from '@angular/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 { debounceTime, distinctUntilChanged, map } from 'rxjs/operators'
import { exec } from 'mz/child_process'

View File

@ -15,7 +15,7 @@ export class ColorPickerComponent {
@ViewChild('input') input
isOpen: boolean
open () {
open (): void {
setImmediate(() => {
this.popover.open()
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) {
return
}
@ -40,7 +40,7 @@ export class ColorPickerComponent {
}
}
onChange () {
onChange (): void {
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 { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
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 { Subject } from 'rxjs'

View File

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

View File

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

View File

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

View File

@ -24,7 +24,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
super(injector)
}
ngOnInit () {
ngOnInit (): void {
this.logger = this.log.create('terminalTab')
this.session = new Session(this.config)
@ -51,7 +51,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
super.ngOnInit()
}
initializeSession (columns: number, rows: number) {
initializeSession (columns: number, rows: number): void {
this.sessions.addSession(
this.session,
Object.assign({}, this.sessionOptions, {
@ -101,7 +101,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
)).response === 1
}
ngOnDestroy () {
ngOnDestroy (): void {
this.homeEndSubscription.unsubscribe()
super.ngOnDestroy()
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(
this.hostApp.getWindow(),
{
@ -75,7 +75,7 @@ export class DebugDecorator extends TerminalDecorator {
return null
}
async saveFile (content: string, name: string) {
private async saveFile (content: string, name: string) {
const result = await this.electron.dialog.showSaveDialog(
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')
}
async doCopyState (terminal: TerminalTabComponent) {
private async doCopyState (terminal: TerminalTabComponent) {
const data = '```' + JSON.stringify(terminal.frontend.saveState()) + '```'
this.electron.clipboard.writeText(data)
}
async doLoadState (terminal: TerminalTabComponent) {
private async doLoadState (terminal: TerminalTabComponent) {
const data = await this.loadFile()
terminal.frontend.restoreState(data)
}
async doPasteState (terminal: TerminalTabComponent) {
private async doPasteState (terminal: TerminalTabComponent) {
let data = this.electron.clipboard.readText()
if (data) {
if (data.startsWith('`')) {
@ -111,23 +111,23 @@ export class DebugDecorator extends TerminalDecorator {
}
}
doSaveOutput (buffer: string) {
private doSaveOutput (buffer: string) {
this.saveFile(buffer, 'output.txt')
}
async doCopyOutput (buffer: string) {
private async doCopyOutput (buffer: string) {
const data = '```' + JSON.stringify(buffer) + '```'
this.electron.clipboard.writeText(data)
}
async doLoadOutput (terminal: TerminalTabComponent) {
private async doLoadOutput (terminal: TerminalTabComponent) {
const data = await this.loadFile()
if (data) {
terminal.frontend.write(data)
}
}
async doPasteOutput (terminal: TerminalTabComponent) {
private async doPasteOutput (terminal: TerminalTabComponent) {
let data = this.electron.clipboard.readText()
if (data) {
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(' ')) {
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, '------------------------')

View File

@ -76,5 +76,5 @@ export abstract class Frontend {
abstract findPrevious (term: string, searchOptions?: SearchOptions): boolean
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 zoom = 0
attach (host: HTMLElement) {
attach (host: HTMLElement): void {
if (!this.initialized) {
this.init()
this.initialized = true
@ -29,15 +29,15 @@ export class HTermFrontend extends Frontend {
return this.term.getSelectionText()
}
copySelection () {
copySelection (): void {
this.term.copySelectionToClipboard()
}
clearSelection () {
clearSelection (): void {
this.term.getDocument().getSelection().removeAllRanges()
}
focus () {
focus (): void {
setTimeout(() => {
this.term.scrollPort_.resize()
this.term.scrollPort_.focus()
@ -168,7 +168,7 @@ export class HTermFrontend extends Frontend {
saveState (): any { }
// eslint-disable-next-line @typescript-eslint/no-empty-function
restoreState (_state: any): void { }
restoreState (_state: string): void { }
private setFontSize () {
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
const range = selection.getRangeAt(0)
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)
}
}

View File

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

View File

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

View File

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

View File

@ -52,7 +52,7 @@ export abstract class BaseSession {
get closed$ (): Observable<void> { return this.closed }
get destroyed$ (): Observable<void> { return this.destroyed }
emitOutput (data: Buffer) {
emitOutput (data: Buffer): void {
if (!this.initialDataBufferReleased) {
this.initialDataBuffer = Buffer.concat([this.initialDataBuffer, data])
} else {
@ -61,7 +61,7 @@ export abstract class BaseSession {
}
}
releaseInitialDataBuffer () {
releaseInitialDataBuffer (): void {
this.initialDataBufferReleased = true
this.output.next(this.initialDataBuffer.toString())
this.binaryOutput.next(this.initialDataBuffer)
@ -99,7 +99,7 @@ export class Session extends BaseSession {
super()
}
start (options: SessionOptions) {
start (options: SessionOptions): void {
this.name = options.name || ''
const env = {
@ -182,31 +182,13 @@ export class Session extends BaseSession {
this.pauseAfterExit = options.pauseAfterExit || false
}
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
}
resize (columns, rows) {
resize (columns: number, rows: number): void {
if (this.pty._writable) {
this.pty.resize(columns, rows)
}
}
write (data: Buffer) {
write (data: Buffer): void {
if (this.open) {
if (this.pty._writable) {
this.pty.write(data)
@ -216,7 +198,7 @@ export class Session extends BaseSession {
}
}
kill (signal?: string) {
kill (signal?: string): void {
this.pty.kill(signal)
}
@ -323,6 +305,24 @@ export class Session extends BaseSession {
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 */
@ -339,7 +339,7 @@ export class SessionsService {
this.logger = log.create('sessions')
}
addSession (session: BaseSession, options: SessionOptions) {
addSession (session: BaseSession, options: SessionOptions): BaseSession {
this.lastID++
options.name = `session-${this.lastID}`
session.start(options)

View File

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