diff --git a/tabby-core/src/configDefaults.linux.yaml b/tabby-core/src/configDefaults.linux.yaml index 1d213e10f9..dc150aff1a 100644 --- a/tabby-core/src/configDefaults.linux.yaml +++ b/tabby-core/src/configDefaults.linux.yaml @@ -23,6 +23,7 @@ hotkeys: duplicate-tab: [] restart-tab: [] reconnect-tab: [] + disconnect-tab: [] explode-tab: - 'Ctrl-Shift-.' combine-tabs: diff --git a/tabby-core/src/configDefaults.macos.yaml b/tabby-core/src/configDefaults.macos.yaml index d47050c4f8..6f22f2ac5e 100644 --- a/tabby-core/src/configDefaults.macos.yaml +++ b/tabby-core/src/configDefaults.macos.yaml @@ -40,6 +40,7 @@ hotkeys: duplicate-tab: [] restart-tab: [] reconnect-tab: [] + disconnect-tab: [] explode-tab: - '⌘-Shift-.' combine-tabs: diff --git a/tabby-core/src/configDefaults.windows.yaml b/tabby-core/src/configDefaults.windows.yaml index 58870f8e07..2fe150a1ff 100644 --- a/tabby-core/src/configDefaults.windows.yaml +++ b/tabby-core/src/configDefaults.windows.yaml @@ -24,6 +24,7 @@ hotkeys: duplicate-tab: [] restart-tab: [] reconnect-tab: [] + disconnect-tab: [] explode-tab: - 'Ctrl-Shift-.' combine-tabs: diff --git a/tabby-terminal/src/api/baseTerminalTab.component.ts b/tabby-terminal/src/api/baseTerminalTab.component.ts index a52852934c..c1adf56dfe 100644 --- a/tabby-terminal/src/api/baseTerminalTab.component.ts +++ b/tabby-terminal/src/api/baseTerminalTab.component.ts @@ -772,10 +772,7 @@ export class BaseTerminalTabComponent

extends Bas }) this.attachSessionHandler(this.session.closed$, () => { - const behavior = this.profile.behaviorOnSessionEnd - if (destroyOnSessionClose || behavior === 'close' || behavior === 'auto' && this.isSessionExplicitlyTerminated()) { - this.destroy() - } + this.onSessionClosed(destroyOnSessionClose) }) this.attachSessionHandler(this.session.destroyed$, () => { @@ -788,6 +785,23 @@ export class BaseTerminalTabComponent

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 */ diff --git a/tabby-terminal/src/api/connectableTerminalTab.component.ts b/tabby-terminal/src/api/connectableTerminalTab.component.ts index 0d63ff2d16..97560ec172 100644 --- a/tabby-terminal/src/api/connectableTerminalTab.component.ts +++ b/tabby-terminal/src/api/connectableTerminalTab.component.ts @@ -16,13 +16,25 @@ import { GetRecoveryTokenOptions, RecoveryToken } from 'tabby-core' export abstract class ConnectableTerminalTabComponent

extends BaseTerminalTabComponent

{ protected reconnectOffered = false + protected isDisconnectedByHand = false constructor (protected injector: Injector) { super(injector) this.subscribeUntilDestroyed(this.hotkeys.hotkey$, hotkey => { - if (this.hasFocus && hotkey === 'reconnect-tab') { - this.reconnect() + 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 } }) } @@ -44,6 +56,7 @@ export abstract class ConnectableTerminalTabComponent

{ this.reconnectOffered = false + this.isDisconnectedByHand = false } /** @@ -53,9 +66,9 @@ export abstract class ConnectableTerminalTabComponent

{ return { type: `app:${this.profile.type}-tab`, @@ -85,6 +108,11 @@ export abstract class ConnectableTerminalTabComponent

{ + this.isDisconnectedByHand = true + await this.session?.destroy() + } + async reconnect (): Promise { this.session?.destroy() await this.initializeSession() diff --git a/tabby-terminal/src/hotkeys.ts b/tabby-terminal/src/hotkeys.ts index 08c69798ec..98974acf90 100644 --- a/tabby-terminal/src/hotkeys.ts +++ b/tabby-terminal/src/hotkeys.ts @@ -101,6 +101,10 @@ export class TerminalHotkeyProvider extends HotkeyProvider { id: 'reconnect-tab', 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() } diff --git a/tabby-terminal/src/tabContextMenu.ts b/tabby-terminal/src/tabContextMenu.ts index 5d48502218..9be7947618 100644 --- a/tabby-terminal/src/tabContextMenu.ts +++ b/tabby-terminal/src/tabContextMenu.ts @@ -99,6 +99,15 @@ export class ReconnectContextMenu extends TabContextMenuItemProvider { async getItems (tab: BaseTabComponent): Promise { if (tab instanceof ConnectableTerminalTabComponent) { return [ + { + label: this.translate.instant('Disconnect'), + click: (): void => { + setTimeout(() => { + tab.disconnect() + this.notifications.notice(this.translate.instant('Disconnect')) + }) + }, + }, { label: this.translate.instant('Reconnect'), click: (): void => {