Merge pull request #8589 from Clem-Fern/feat#6518

This commit is contained in:
Eugene 2023-06-16 18:08:11 +02:00 committed by GitHub
commit 5e673106e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 66 additions and 8 deletions

View File

@ -23,6 +23,7 @@ hotkeys:
duplicate-tab: [] duplicate-tab: []
restart-tab: [] restart-tab: []
reconnect-tab: [] reconnect-tab: []
disconnect-tab: []
explode-tab: explode-tab:
- 'Ctrl-Shift-.' - 'Ctrl-Shift-.'
combine-tabs: combine-tabs:

View File

@ -40,6 +40,7 @@ hotkeys:
duplicate-tab: [] duplicate-tab: []
restart-tab: [] restart-tab: []
reconnect-tab: [] reconnect-tab: []
disconnect-tab: []
explode-tab: explode-tab:
- '⌘-Shift-.' - '⌘-Shift-.'
combine-tabs: combine-tabs:

View File

@ -24,6 +24,7 @@ hotkeys:
duplicate-tab: [] duplicate-tab: []
restart-tab: [] restart-tab: []
reconnect-tab: [] reconnect-tab: []
disconnect-tab: []
explode-tab: explode-tab:
- 'Ctrl-Shift-.' - 'Ctrl-Shift-.'
combine-tabs: combine-tabs:

View File

@ -772,10 +772,7 @@ export class BaseTerminalTabComponent<P extends BaseTerminalProfile> extends Bas
}) })
this.attachSessionHandler(this.session.closed$, () => { this.attachSessionHandler(this.session.closed$, () => {
const behavior = this.profile.behaviorOnSessionEnd this.onSessionClosed(destroyOnSessionClose)
if (destroyOnSessionClose || behavior === 'close' || behavior === 'auto' && this.isSessionExplicitlyTerminated()) {
this.destroy()
}
}) })
this.attachSessionHandler(this.session.destroyed$, () => { this.attachSessionHandler(this.session.destroyed$, () => {
@ -788,6 +785,23 @@ export class BaseTerminalTabComponent<P extends BaseTerminalProfile> extends Bas
}) })
} }
/**
* Method called when session is closed.
*/
protected onSessionClosed (destroyOnSessionClose = false): void {
if (destroyOnSessionClose || this.shouldTabBeDestroyedOnSessionClose()) {
this.destroy()
}
}
/**
* Return true if tab should be destroyed on session closed.
*/
protected shouldTabBeDestroyedOnSessionClose (): boolean {
const behavior = this.profile.behaviorOnSessionEnd
return behavior === 'close' || behavior === 'auto' && this.isSessionExplicitlyTerminated()
}
/** /**
* Method called when session is destroyed. Set the session to null * Method called when session is destroyed. Set the session to null
*/ */

View File

@ -16,13 +16,25 @@ import { GetRecoveryTokenOptions, RecoveryToken } from 'tabby-core'
export abstract class ConnectableTerminalTabComponent<P extends BaseTerminalProfile> extends BaseTerminalTabComponent<P> { export abstract class ConnectableTerminalTabComponent<P extends BaseTerminalProfile> extends BaseTerminalTabComponent<P> {
protected reconnectOffered = false protected reconnectOffered = false
protected isDisconnectedByHand = false
constructor (protected injector: Injector) { constructor (protected injector: Injector) {
super(injector) super(injector)
this.subscribeUntilDestroyed(this.hotkeys.hotkey$, hotkey => { this.subscribeUntilDestroyed(this.hotkeys.hotkey$, hotkey => {
if (this.hasFocus && hotkey === 'reconnect-tab') { if (!this.hasFocus) {
this.reconnect() 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
} }
}) })
} }
@ -44,6 +56,7 @@ export abstract class ConnectableTerminalTabComponent<P extends BaseTerminalProf
*/ */
async initializeSession (): Promise<void> { async initializeSession (): Promise<void> {
this.reconnectOffered = false this.reconnectOffered = false
this.isDisconnectedByHand = false
} }
/** /**
@ -53,9 +66,9 @@ export abstract class ConnectableTerminalTabComponent<P extends BaseTerminalProf
super.onSessionDestroyed() super.onSessionDestroyed()
if (this.frontend) { if (this.frontend) {
if (this.profile.behaviorOnSessionEnd === 'reconnect') { if (this.profile.behaviorOnSessionEnd === 'reconnect' && !this.isDisconnectedByHand) {
this.reconnect() this.reconnect()
} else if (this.profile.behaviorOnSessionEnd === 'keep' || this.profile.behaviorOnSessionEnd === 'auto' && !this.isSessionExplicitlyTerminated()) { } else if (this.profile.behaviorOnSessionEnd === 'keep' || !this.shouldTabBeDestroyedOnSessionClose()) {
this.offerReconnection() this.offerReconnection()
} }
} }
@ -77,6 +90,16 @@ export abstract class ConnectableTerminalTabComponent<P extends BaseTerminalProf
} }
} }
/**
* 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> { async getRecoveryToken (options?: GetRecoveryTokenOptions): Promise<RecoveryToken> {
return { return {
type: `app:${this.profile.type}-tab`, type: `app:${this.profile.type}-tab`,
@ -85,6 +108,11 @@ export abstract class ConnectableTerminalTabComponent<P extends BaseTerminalProf
} }
} }
async disconnect (): Promise<void> {
this.isDisconnectedByHand = true
await this.session?.destroy()
}
async reconnect (): Promise<void> { async reconnect (): Promise<void> {
this.session?.destroy() this.session?.destroy()
await this.initializeSession() await this.initializeSession()

View File

@ -101,6 +101,10 @@ export class TerminalHotkeyProvider extends HotkeyProvider {
id: 'reconnect-tab', id: 'reconnect-tab',
name: this.translate.instant('Reconnect current tab (Serial/Telnet/SSH)'), name: this.translate.instant('Reconnect current tab (Serial/Telnet/SSH)'),
}, },
{
id: 'disconnect-tab',
name: this.translate.instant('Disconnect current tab (Serial/Telnet/SSH)'),
},
] ]
constructor (private translate: TranslateService) { super() } constructor (private translate: TranslateService) { super() }

View File

@ -99,6 +99,15 @@ export class ReconnectContextMenu extends TabContextMenuItemProvider {
async getItems (tab: BaseTabComponent): Promise<MenuItemOptions[]> { async getItems (tab: BaseTabComponent): Promise<MenuItemOptions[]> {
if (tab instanceof ConnectableTerminalTabComponent) { if (tab instanceof ConnectableTerminalTabComponent) {
return [ return [
{
label: this.translate.instant('Disconnect'),
click: (): void => {
setTimeout(() => {
tab.disconnect()
this.notifications.notice(this.translate.instant('Disconnect'))
})
},
},
{ {
label: this.translate.instant('Reconnect'), label: this.translate.instant('Reconnect'),
click: (): void => { click: (): void => {