mirror of
https://github.com/Eugeny/tabby.git
synced 2025-06-08 21:40:03 +00:00
resolves Eugeny/tabby#7751, Eugeny/tabby#8062, Eugeny/tabby#6617 add behavior when session ends
This commit is contained in:
parent
f2a62413da
commit
b1acfe2519
@ -14,6 +14,7 @@ export interface Profile {
|
|||||||
icon?: string
|
icon?: string
|
||||||
color?: string
|
color?: string
|
||||||
disableDynamicTitle: boolean
|
disableDynamicTitle: boolean
|
||||||
|
behaviorOnSessionEnd: 'auto'|'keep'|'reconnect'|'close'
|
||||||
|
|
||||||
weight: number
|
weight: number
|
||||||
isBuiltin: boolean
|
isBuiltin: boolean
|
||||||
|
@ -24,6 +24,7 @@ export class ProfilesService {
|
|||||||
isBuiltin: false,
|
isBuiltin: false,
|
||||||
isTemplate: false,
|
isTemplate: false,
|
||||||
terminalColorScheme: null,
|
terminalColorScheme: null,
|
||||||
|
behaviorOnSessionEnd: 'auto',
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
|
@ -71,7 +71,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent<LocalProfile>
|
|||||||
height: rows,
|
height: rows,
|
||||||
})
|
})
|
||||||
|
|
||||||
this.setSession(session, true)
|
this.setSession(session)
|
||||||
this.recoveryStateChangedHint.next()
|
this.recoveryStateChangedHint.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,4 +127,12 @@ export class TerminalTabComponent extends BaseTerminalTabComponent<LocalProfile>
|
|||||||
super.ngOnDestroy()
|
super.ngOnDestroy()
|
||||||
this.session?.destroy()
|
this.session?.destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the user explicitly exit the session.
|
||||||
|
* Always return true for terminalTab as the session can only be ended by the user
|
||||||
|
*/
|
||||||
|
protected isSessionExplicitlyTerminated (): boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,12 +83,21 @@ export class SerialTabComponent extends BaseTerminalTabComponent<SerialProfile>
|
|||||||
this.session?.resize(this.size.columns, this.size.rows)
|
this.session?.resize(this.size.columns, this.size.rows)
|
||||||
})
|
})
|
||||||
this.attachSessionHandler(this.session!.destroyed$, () => {
|
this.attachSessionHandler(this.session!.destroyed$, () => {
|
||||||
|
if (this.frontend) {
|
||||||
|
// Session was closed abruptly
|
||||||
|
this.write('\r\n' + colors.black.bgWhite(' SERIAL ') + ` session closed\r\n`)
|
||||||
|
|
||||||
|
if (this.profile.behaviorOnSessionEnd === 'reconnect') {
|
||||||
|
this.reconnect()
|
||||||
|
} else if (this.profile.behaviorOnSessionEnd === 'keep' || this.profile.behaviorOnSessionEnd === 'auto' && !this.isSessionExplicitlyTerminated()) {
|
||||||
this.write(this.translate.instant(_('Press any key to reconnect')) + '\r\n')
|
this.write(this.translate.instant(_('Press any key to reconnect')) + '\r\n')
|
||||||
this.input$.pipe(first()).subscribe(() => {
|
this.input$.pipe(first()).subscribe(() => {
|
||||||
if (!this.session?.open) {
|
if (!this.session?.open) {
|
||||||
this.reconnect()
|
this.reconnect()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
super.attachSessionHandlers()
|
super.attachSessionHandlers()
|
||||||
}
|
}
|
||||||
@ -117,4 +126,10 @@ export class SerialTabComponent extends BaseTerminalTabComponent<SerialProfile>
|
|||||||
this.session?.serial?.update({ baudRate: rate })
|
this.session?.serial?.update({ baudRate: rate })
|
||||||
this.profile.options.baudrate = rate
|
this.profile.options.baudrate = rate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected isSessionExplicitlyTerminated (): boolean {
|
||||||
|
return super.isSessionExplicitlyTerminated() ||
|
||||||
|
this.recentInputs.endsWith('close\r') ||
|
||||||
|
this.recentInputs.endsWith('quit\r')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,18 @@
|
|||||||
.description(translate) Connection name will be used instead
|
.description(translate) Connection name will be used instead
|
||||||
toggle([(ngModel)]='profile.disableDynamicTitle')
|
toggle([(ngModel)]='profile.disableDynamicTitle')
|
||||||
|
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title(translate) When a session ends
|
||||||
|
.description(*ngIf='profile.behaviorOnSessionEnd == "auto"', translate) Only close the tab when session is explicitly terminated
|
||||||
|
select.form-control(
|
||||||
|
[(ngModel)]='profile.behaviorOnSessionEnd',
|
||||||
|
)
|
||||||
|
option(ngValue='auto', translate) Auto
|
||||||
|
option(ngValue='keep', translate) Keep
|
||||||
|
option(*ngIf='profile.type == "serial" || profile.type == "telnet" || profile.type == "ssh"', ngValue='reconnect', translate) Reconnect
|
||||||
|
option(ngValue='close', translate) Close
|
||||||
|
|
||||||
.mb-4
|
.mb-4
|
||||||
|
|
||||||
.col-12.col-lg-8(*ngIf='this.profileProvider.settingsComponent')
|
.col-12.col-lg-8(*ngIf='this.profileProvider.settingsComponent')
|
||||||
|
@ -153,16 +153,13 @@ export class SSHTabComponent extends BaseTerminalTabComponent<SSHProfile> implem
|
|||||||
protected attachSessionHandlers (): void {
|
protected attachSessionHandlers (): void {
|
||||||
const session = this.session!
|
const session = this.session!
|
||||||
this.attachSessionHandler(session.destroyed$, () => {
|
this.attachSessionHandler(session.destroyed$, () => {
|
||||||
if (
|
if (this.frontend) {
|
||||||
// Ctrl-D
|
|
||||||
this.recentInputs.charCodeAt(this.recentInputs.length - 1) === 4 ||
|
|
||||||
this.recentInputs.endsWith('exit\r')
|
|
||||||
) {
|
|
||||||
// User closed the session
|
|
||||||
this.destroy()
|
|
||||||
} else if (this.frontend) {
|
|
||||||
// Session was closed abruptly
|
// Session was closed abruptly
|
||||||
this.write('\r\n' + colors.black.bgWhite(' SSH ') + ` ${this.sshSession?.profile.options.host}: session closed\r\n`)
|
this.write('\r\n' + colors.black.bgWhite(' SSH ') + ` ${this.sshSession?.profile.options.host}: session closed\r\n`)
|
||||||
|
|
||||||
|
if (this.profile.behaviorOnSessionEnd === 'reconnect') {
|
||||||
|
this.reconnect()
|
||||||
|
} else if (this.profile.behaviorOnSessionEnd === 'keep' || this.profile.behaviorOnSessionEnd === 'auto' && !this.isSessionExplicitlyTerminated()) {
|
||||||
if (!this.reconnectOffered) {
|
if (!this.reconnectOffered) {
|
||||||
this.reconnectOffered = true
|
this.reconnectOffered = true
|
||||||
this.write(this.translate.instant(_('Press any key to reconnect')) + '\r\n')
|
this.write(this.translate.instant(_('Press any key to reconnect')) + '\r\n')
|
||||||
@ -173,6 +170,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent<SSHProfile> implem
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
super.attachSessionHandlers()
|
super.attachSessionHandlers()
|
||||||
}
|
}
|
||||||
@ -262,4 +260,10 @@ export class SSHTabComponent extends BaseTerminalTabComponent<SSHProfile> implem
|
|||||||
onClick (): void {
|
onClick (): void {
|
||||||
this.sftpPanelVisible = false
|
this.sftpPanelVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected isSessionExplicitlyTerminated (): boolean {
|
||||||
|
return super.isSessionExplicitlyTerminated() ||
|
||||||
|
this.recentInputs.charCodeAt(this.recentInputs.length - 1) === 4 ||
|
||||||
|
this.recentInputs.endsWith('exit\r')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,11 @@ export class TelnetTabComponent extends BaseTerminalTabComponent<TelnetProfile>
|
|||||||
this.attachSessionHandler(session.destroyed$, () => {
|
this.attachSessionHandler(session.destroyed$, () => {
|
||||||
if (this.frontend) {
|
if (this.frontend) {
|
||||||
// Session was closed abruptly
|
// Session was closed abruptly
|
||||||
|
this.write('\r\n' + colors.black.bgWhite(' TELNET ') + ` ${this.session?.profile.options.host}: session closed\r\n`)
|
||||||
|
|
||||||
|
if (this.profile.behaviorOnSessionEnd === 'reconnect') {
|
||||||
|
this.reconnect()
|
||||||
|
} else if (this.profile.behaviorOnSessionEnd === 'keep' || this.profile.behaviorOnSessionEnd === 'auto' && !this.isSessionExplicitlyTerminated()) {
|
||||||
if (!this.reconnectOffered) {
|
if (!this.reconnectOffered) {
|
||||||
this.reconnectOffered = true
|
this.reconnectOffered = true
|
||||||
this.write(this.translate.instant(_('Press any key to reconnect')) + '\r\n')
|
this.write(this.translate.instant(_('Press any key to reconnect')) + '\r\n')
|
||||||
@ -59,6 +64,7 @@ export class TelnetTabComponent extends BaseTerminalTabComponent<TelnetProfile>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
super.attachSessionHandlers()
|
super.attachSessionHandlers()
|
||||||
}
|
}
|
||||||
@ -121,4 +127,11 @@ export class TelnetTabComponent extends BaseTerminalTabComponent<TelnetProfile>
|
|||||||
},
|
},
|
||||||
)).response === 0
|
)).response === 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected isSessionExplicitlyTerminated (): boolean {
|
||||||
|
return super.isSessionExplicitlyTerminated() ||
|
||||||
|
this.recentInputs.endsWith('close\r') ||
|
||||||
|
this.recentInputs.endsWith('quit\r')
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -771,11 +771,12 @@ export class BaseTerminalTabComponent<P extends BaseTerminalProfile> extends Bas
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (destroyOnSessionClose) {
|
|
||||||
this.attachSessionHandler(this.session.closed$, () => {
|
this.attachSessionHandler(this.session.closed$, () => {
|
||||||
|
const behavior = this.profile.behaviorOnSessionEnd
|
||||||
|
if (destroyOnSessionClose || behavior === 'close' || behavior === 'auto' && this.isSessionExplicitlyTerminated()) {
|
||||||
this.destroy()
|
this.destroy()
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
this.attachSessionHandler(this.session.destroyed$, () => {
|
this.attachSessionHandler(this.session.destroyed$, () => {
|
||||||
this.setSession(null)
|
this.setSession(null)
|
||||||
@ -841,4 +842,11 @@ export class BaseTerminalTabComponent<P extends BaseTerminalProfile> extends Bas
|
|||||||
cb(this)
|
cb(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the user explicitly exit the session
|
||||||
|
*/
|
||||||
|
protected isSessionExplicitlyTerminated (): boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user