tabby/tabby-terminal/src/api/connectableTerminalTab.component.ts

123 lines
3.6 KiB
TypeScript

import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
import { Injector, Component } from '@angular/core'
import { first } from 'rxjs'
import { ConnectableTerminalProfile } from './interfaces'
import { BaseTerminalTabComponent } from './baseTerminalTab.component'
import { GetRecoveryTokenOptions, RecoveryToken } from 'tabby-core'
/**
* A class to base your custom connectable terminal tabs on
*/
@Component({ template: '' })
export abstract class ConnectableTerminalTabComponent<P extends ConnectableTerminalProfile> extends BaseTerminalTabComponent<P> {
protected reconnectOffered = false
protected isDisconnectedByHand = false
constructor (protected injector: Injector) {
super(injector)
this.subscribeUntilDestroyed(this.hotkeys.hotkey$, hotkey => {
if (!this.hasFocus) {
return
}
switch (hotkey) {
case 'reconnect-tab':
this.reconnect()
this.notifications.notice(this.translate.instant('Reconnect'))
break
case 'disconnect-tab':
this.disconnect()
this.notifications.notice(this.translate.instant('Disconnect'))
break
}
})
}
ngOnInit (): void {
this.logger = this.log.create(`${this.profile.type}Tab`)
super.ngOnInit()
}
protected onFrontendReady (): void {
this.initializeSession()
super.onFrontendReady()
}
/**
* Initialize Connectable Session.
* Set reconnectOffered to false
*/
async initializeSession (): Promise<void> {
this.reconnectOffered = false
this.isDisconnectedByHand = false
}
/**
* Method called when session is destroyed. Handle the tab behavior on session end for connectable tab
*/
protected onSessionDestroyed (): void {
super.onSessionDestroyed()
if (this.frontend) {
if (this.profile.behaviorOnSessionEnd === 'reconnect' && !this.isDisconnectedByHand) {
this.reconnect()
} else if (this.profile.behaviorOnSessionEnd === 'keep' || !this.shouldTabBeDestroyedOnSessionClose()) {
this.offerReconnection()
}
}
}
/**
* Offering reconnection to the user if it hasn't been done yet.
* Set reconnectOffered to true
*/
offerReconnection (): void {
if (!this.reconnectOffered) {
this.reconnectOffered = true
this.write(this.translate.instant(_('Press any key to reconnect')) + '\r\n')
this.input$.pipe(first()).subscribe(() => {
if (!this.session?.open && this.reconnectOffered) {
this.reconnect()
}
})
}
}
/**
* Return true if tab should be destroyed on session closed.
*/
protected shouldTabBeDestroyedOnSessionClose (): boolean {
if (this.isDisconnectedByHand) {
return false
}
return super.shouldTabBeDestroyedOnSessionClose()
}
async getRecoveryToken (options?: GetRecoveryTokenOptions): Promise<RecoveryToken> {
return {
type: `app:${this.profile.type}-tab`,
profile: this.profile,
savedState: options?.includeState && this.frontend?.saveState(),
}
}
async disconnect (): Promise<void> {
this.isDisconnectedByHand = true
await this.session?.destroy()
}
async reconnect (): Promise<void> {
this.session?.destroy()
await this.initializeSession()
this.session?.releaseInitialDataBuffer()
}
}