From ca6cc68fed32c2683a5b02ff946cc3e9ca6e6566 Mon Sep 17 00:00:00 2001 From: Mystery0 M Date: Sat, 8 Feb 2025 09:14:57 +0800 Subject: [PATCH] feat: support auto close terminal tab when ssh disconnected normally (#169) --- src/main/kotlin/app/termora/Database.kt | 5 +++++ src/main/kotlin/app/termora/LocalTerminalTab.kt | 3 ++- src/main/kotlin/app/termora/SSHTerminalTab.kt | 16 +++++++++++++++- src/main/kotlin/app/termora/SerialTerminalTab.kt | 3 ++- .../kotlin/app/termora/SettingsOptionsPane.kt | 16 ++++++++++++++-- .../app/termora/tlog/LogViewerTerminalTab.kt | 5 ++++- src/main/resources/i18n/messages.properties | 2 ++ .../resources/i18n/messages_zh_CN.properties | 2 ++ .../resources/i18n/messages_zh_TW.properties | 2 ++ 9 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/app/termora/Database.kt b/src/main/kotlin/app/termora/Database.kt index f96cea3..6a86842 100644 --- a/src/main/kotlin/app/termora/Database.kt +++ b/src/main/kotlin/app/termora/Database.kt @@ -468,6 +468,11 @@ class Database private constructor(private val env: Environment) : Disposable { * 光标样式 */ var cursor by CursorStylePropertyDelegate(CursorStyle.Block) + + /** + * 终端断开连接时自动关闭Tab + */ + var autoCloseTabWhenDisconnected by BooleanPropertyDelegate(false) } /** diff --git a/src/main/kotlin/app/termora/LocalTerminalTab.kt b/src/main/kotlin/app/termora/LocalTerminalTab.kt index 2912b84..d10a123 100644 --- a/src/main/kotlin/app/termora/LocalTerminalTab.kt +++ b/src/main/kotlin/app/termora/LocalTerminalTab.kt @@ -4,7 +4,8 @@ import app.termora.terminal.PtyConnector import org.apache.commons.io.Charsets import java.nio.charset.StandardCharsets -class LocalTerminalTab(windowScope: WindowScope, host: Host) : PtyHostTerminalTab(windowScope, host) { +class LocalTerminalTab(windowScope: WindowScope, host: Host) : + PtyHostTerminalTab(windowScope, host) { override suspend fun openPtyConnector(): PtyConnector { val winSize = terminalPanel.winSize() diff --git a/src/main/kotlin/app/termora/SSHTerminalTab.kt b/src/main/kotlin/app/termora/SSHTerminalTab.kt index 9620484..8f7d58e 100644 --- a/src/main/kotlin/app/termora/SSHTerminalTab.kt +++ b/src/main/kotlin/app/termora/SSHTerminalTab.kt @@ -1,5 +1,7 @@ package app.termora +import app.termora.actions.AnActionEvent +import app.termora.actions.DataProviders import app.termora.actions.TabReconnectAction import app.termora.addons.zmodem.ZModemPtyConnectorAdaptor import app.termora.keyboardinteractive.TerminalUserInteraction @@ -27,11 +29,13 @@ import org.apache.sshd.common.session.SessionListener.Event import org.apache.sshd.common.util.net.SshdSocketAddress import org.slf4j.LoggerFactory import java.nio.charset.StandardCharsets +import java.util.EventObject import javax.swing.JComponent import javax.swing.SwingUtilities -class SSHTerminalTab(windowScope: WindowScope, host: Host) : PtyHostTerminalTab(windowScope, host) { +class SSHTerminalTab(windowScope: WindowScope, host: Host) : + PtyHostTerminalTab(windowScope, host) { companion object { private val log = LoggerFactory.getLogger(PtyHostTerminalTab::class.java) } @@ -41,6 +45,9 @@ class SSHTerminalTab(windowScope: WindowScope, host: Host) : PtyHostTerminalTab( private var sshClient: SshClient? = null private var sshSession: ClientSession? = null private var sshChannelShell: ChannelShell? = null + private val terminalTabbedManager + get() = AnActionEvent(getJComponent(), StringUtils.EMPTY, EventObject(getJComponent())) + .getData(DataProviders.TerminalTabbedManager) init { terminalPanel.dropFiles = false @@ -126,6 +133,13 @@ class SSHTerminalTab(windowScope: WindowScope, host: Host) : PtyHostTerminalTab( terminal.write("\r\n") terminal.write("${ControlCharacters.ESC}[0m") terminalModel.setData(DataKey.ShowCursor, false) + if (Database.getDatabase().terminal.autoCloseTabWhenDisconnected) { + terminalTabbedManager?.let { manager -> + SwingUtilities.invokeLater { + manager.closeTerminalTab(this@SSHTerminalTab, true) + } + } + } } } }) diff --git a/src/main/kotlin/app/termora/SerialTerminalTab.kt b/src/main/kotlin/app/termora/SerialTerminalTab.kt index 3b911c3..9701705 100644 --- a/src/main/kotlin/app/termora/SerialTerminalTab.kt +++ b/src/main/kotlin/app/termora/SerialTerminalTab.kt @@ -5,7 +5,8 @@ import org.apache.commons.io.Charsets import java.nio.charset.StandardCharsets import javax.swing.Icon -class SerialTerminalTab(windowScope: WindowScope, host: Host) : PtyHostTerminalTab(windowScope, host) { +class SerialTerminalTab(windowScope: WindowScope, host: Host) : + PtyHostTerminalTab(windowScope, host) { override suspend fun openPtyConnector(): PtyConnector { val serialPort = Serials.openPort(host) return SerialPortPtyConnector( diff --git a/src/main/kotlin/app/termora/SettingsOptionsPane.kt b/src/main/kotlin/app/termora/SettingsOptionsPane.kt index afb868e..d28a293 100644 --- a/src/main/kotlin/app/termora/SettingsOptionsPane.kt +++ b/src/main/kotlin/app/termora/SettingsOptionsPane.kt @@ -46,6 +46,7 @@ import java.awt.BorderLayout import java.awt.Component import java.awt.Toolkit import java.awt.datatransfer.StringSelection +import java.awt.event.ActionEvent import java.awt.event.ItemEvent import java.io.File import java.net.URI @@ -307,6 +308,7 @@ class SettingsOptionsPane : OptionsPane() { private val fontSizeTextField = IntSpinner(0, 9, 99) private val terminalSetting get() = Database.getDatabase().terminal private val selectCopyComboBox = YesOrNoComboBox() + private val autoCloseTabComboBox = YesOrNoComboBox() init { initView() @@ -322,6 +324,13 @@ class SettingsOptionsPane : OptionsPane() { } } + autoCloseTabComboBox.addItemListener { e -> + if (e.stateChange == ItemEvent.SELECTED) { + terminalSetting.autoCloseTabWhenDisconnected = autoCloseTabComboBox.selectedItem as Boolean + } + } + autoCloseTabComboBox.toolTipText = I18n.getString("termora.settings.terminal.auto-close-tab-description") + selectCopyComboBox.addItemListener { e -> if (e.stateChange == ItemEvent.SELECTED) { terminalSetting.selectCopy = selectCopyComboBox.selectedItem as Boolean @@ -466,6 +475,7 @@ class SettingsOptionsPane : OptionsPane() { beepComboBox.selectedItem = terminalSetting.beep cursorStyleComboBox.selectedItem = terminalSetting.cursor selectCopyComboBox.selectedItem = terminalSetting.selectCopy + autoCloseTabComboBox.selectedItem = terminalSetting.autoCloseTabWhenDisconnected } override fun getIcon(isSelected: Boolean): Icon { @@ -483,7 +493,7 @@ class SettingsOptionsPane : OptionsPane() { private fun getCenterComponent(): JComponent { val layout = FormLayout( "left:pref, $formMargin, default:grow, $formMargin, left:pref, $formMargin, pref, default:grow", - "pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref" + "pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref" ) val beepBtn = JButton(Icons.run) @@ -511,7 +521,9 @@ class SettingsOptionsPane : OptionsPane() { .add("${I18n.getString("termora.settings.terminal.cursor-style")}:").xy(1, rows) .add(cursorStyleComboBox).xy(3, rows).apply { rows += step } .add("${I18n.getString("termora.settings.terminal.local-shell")}:").xy(1, rows) - .add(shellComboBox).xyw(3, rows, 5) + .add(shellComboBox).xyw(3, rows, 5).apply { rows += step } + .add("${I18n.getString("termora.settings.terminal.auto-close-tab")}:").xy(1, rows) + .add(autoCloseTabComboBox).xy(3, rows) .build() diff --git a/src/main/kotlin/app/termora/tlog/LogViewerTerminalTab.kt b/src/main/kotlin/app/termora/tlog/LogViewerTerminalTab.kt index 3ed5d7d..6dea6ea 100644 --- a/src/main/kotlin/app/termora/tlog/LogViewerTerminalTab.kt +++ b/src/main/kotlin/app/termora/tlog/LogViewerTerminalTab.kt @@ -9,7 +9,10 @@ import java.io.FileNotFoundException import java.nio.file.Files import javax.swing.Icon -class LogViewerTerminalTab(windowScope: WindowScope, private val file: File) : PtyHostTerminalTab( +class LogViewerTerminalTab( + windowScope: WindowScope, + private val file: File, +) : PtyHostTerminalTab( windowScope, Host( name = file.name, diff --git a/src/main/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties index dd7b082..8f4754b 100644 --- a/src/main/resources/i18n/messages.properties +++ b/src/main/resources/i18n/messages.properties @@ -67,6 +67,8 @@ termora.settings.terminal.beep=Beep termora.settings.terminal.select-copy=Select copy termora.settings.terminal.cursor-style=Cursor type termora.settings.terminal.local-shell=Local shell +termora.settings.terminal.auto-close-tab=Auto Close Tab +termora.settings.terminal.auto-close-tab-description=Automatically close the tab when the terminal is disconnected normally. termora.settings.sync=Sync termora.settings.sync.push=Push diff --git a/src/main/resources/i18n/messages_zh_CN.properties b/src/main/resources/i18n/messages_zh_CN.properties index 6d3c139..4649de7 100644 --- a/src/main/resources/i18n/messages_zh_CN.properties +++ b/src/main/resources/i18n/messages_zh_CN.properties @@ -70,6 +70,8 @@ termora.settings.terminal.beep=蜂鸣声 termora.settings.terminal.select-copy=选中复制 termora.settings.terminal.cursor-style=光标样式 termora.settings.terminal.local-shell=本地终端 +termora.settings.terminal.auto-close-tab=自动关闭标签 +termora.settings.terminal.auto-close-tab-description=当终端正常断开连接时自动关闭标签页。 termora.settings.sync=同步 diff --git a/src/main/resources/i18n/messages_zh_TW.properties b/src/main/resources/i18n/messages_zh_TW.properties index 889a95f..0079226 100644 --- a/src/main/resources/i18n/messages_zh_TW.properties +++ b/src/main/resources/i18n/messages_zh_TW.properties @@ -75,6 +75,8 @@ termora.settings.terminal.beep=蜂鳴聲 termora.settings.terminal.select-copy=選取複製 termora.settings.terminal.cursor-style=遊標風格 termora.settings.terminal.local-shell=本地端 +termora.settings.terminal.auto-close-tab=自動關閉標籤 +termora.settings.terminal.auto-close-tab-description=當終端正常斷開連線時自動關閉標籤頁。。 termora.settings.sync=同步 termora.settings.sync.push=推送