From 8ba74f084652c5ca6b27bfb5a190091dfb085869 Mon Sep 17 00:00:00 2001 From: hstyi Date: Fri, 1 Aug 2025 18:10:34 +0800 Subject: [PATCH] fix: terminal exception caused by reconnection --- plugins/serial/build.gradle.kts | 2 +- .../termora/plugins/serial/SerialTerminalTab.kt | 11 +++++++---- src/main/kotlin/app/termora/HostTerminalTab.kt | 2 +- src/main/kotlin/app/termora/PtyHostTerminalTab.kt | 15 +++++++++++++-- src/main/kotlin/app/termora/TerminalTabbed.kt | 4 ++++ .../kotlin/app/termora/TerminalTabbedManager.kt | 1 + .../plugin/internal/local/LocalTerminalTab.kt | 3 +++ .../plugin/internal/sftppty/SFTPPtyTerminalTab.kt | 4 ++++ .../termora/plugin/internal/ssh/SSHTerminalTab.kt | 15 ++++----------- .../plugin/internal/telnet/TelnetTerminalTab.kt | 9 +++++---- .../plugin/internal/wsl/WSLHostTerminalTab.kt | 9 +++++---- .../app/termora/tlog/LogViewerTerminalTab.kt | 9 +++++---- 12 files changed, 53 insertions(+), 31 deletions(-) diff --git a/plugins/serial/build.gradle.kts b/plugins/serial/build.gradle.kts index ec3fb64..ccd9b99 100644 --- a/plugins/serial/build.gradle.kts +++ b/plugins/serial/build.gradle.kts @@ -4,7 +4,7 @@ plugins { -project.version = "0.0.4" +project.version = "0.0.5" dependencies { diff --git a/plugins/serial/src/main/kotlin/app/termora/plugins/serial/SerialTerminalTab.kt b/plugins/serial/src/main/kotlin/app/termora/plugins/serial/SerialTerminalTab.kt index 6859698..7e2ad29 100644 --- a/plugins/serial/src/main/kotlin/app/termora/plugins/serial/SerialTerminalTab.kt +++ b/plugins/serial/src/main/kotlin/app/termora/plugins/serial/SerialTerminalTab.kt @@ -1,9 +1,6 @@ package app.termora.plugins.serial -import app.termora.Host -import app.termora.Icons -import app.termora.PtyHostTerminalTab -import app.termora.WindowScope +import app.termora.* import app.termora.terminal.PtyConnector import org.apache.commons.io.Charsets import java.nio.charset.StandardCharsets @@ -11,6 +8,8 @@ import javax.swing.Icon class SerialTerminalTab(windowScope: WindowScope, host: Host) : PtyHostTerminalTab(windowScope, host) { + + override suspend fun openPtyConnector(): PtyConnector { val serialPort = Serials.openPort(host) return SerialPortPtyConnector( @@ -19,6 +18,10 @@ class SerialTerminalTab(windowScope: WindowScope, host: Host) : ) } + override fun createReconnectTerminalTab(): TerminalTab { + return SerialTerminalTab(windowScope, host) + } + override fun getIcon(): Icon { return Icons.plugin } diff --git a/src/main/kotlin/app/termora/HostTerminalTab.kt b/src/main/kotlin/app/termora/HostTerminalTab.kt index c586b7f..7cf8b26 100644 --- a/src/main/kotlin/app/termora/HostTerminalTab.kt +++ b/src/main/kotlin/app/termora/HostTerminalTab.kt @@ -27,7 +27,7 @@ abstract class HostTerminalTab( protected val terminalTabbedManager get() = AnActionEvent(getJComponent(), StringUtils.EMPTY, EventObject(getJComponent())) .getData(DataProviders.TerminalTabbedManager) - protected val coroutineScope by lazy { CoroutineScope(SupervisorJob() + Dispatchers.Swing) } + protected val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Swing) protected val terminalModel get() = terminal.getTerminalModel() protected var unread = false set(value) { diff --git a/src/main/kotlin/app/termora/PtyHostTerminalTab.kt b/src/main/kotlin/app/termora/PtyHostTerminalTab.kt index 6503505..1f3fdfc 100644 --- a/src/main/kotlin/app/termora/PtyHostTerminalTab.kt +++ b/src/main/kotlin/app/termora/PtyHostTerminalTab.kt @@ -173,10 +173,21 @@ abstract class PtyHostTerminalTab( } override fun reconnect() { - stop() - start() + val manager = terminalTabbedManager ?: return + val index = manager.indexOfTerminalTab(this) + if (index < 0) return + + val tab = createReconnectTerminalTab() + manager.addTerminalTab(index, tab, true) + manager.closeTerminalTab(this, true) + + if (tab is HostTerminalTab) { + tab.start() + } } + protected abstract fun createReconnectTerminalTab(): TerminalTab + override fun getJComponent(): JComponent { return terminalPanel } diff --git a/src/main/kotlin/app/termora/TerminalTabbed.kt b/src/main/kotlin/app/termora/TerminalTabbed.kt index 2f6584e..75fcec8 100644 --- a/src/main/kotlin/app/termora/TerminalTabbed.kt +++ b/src/main/kotlin/app/termora/TerminalTabbed.kt @@ -367,6 +367,10 @@ class TerminalTabbed( } } + override fun indexOfTerminalTab(tab: TerminalTab):Int { + return tabbedPane.indexOfComponent(tab.getJComponent()) + } + private inner class SwitchFindEverywhereResult( private val title: String, private val icon: Icon?, diff --git a/src/main/kotlin/app/termora/TerminalTabbedManager.kt b/src/main/kotlin/app/termora/TerminalTabbedManager.kt index 57c22e1..518a9b1 100644 --- a/src/main/kotlin/app/termora/TerminalTabbedManager.kt +++ b/src/main/kotlin/app/termora/TerminalTabbedManager.kt @@ -8,4 +8,5 @@ interface TerminalTabbedManager { fun setSelectedTerminalTab(tab: TerminalTab) fun closeTerminalTab(tab: TerminalTab, disposable: Boolean = true) fun refreshTerminalTabs() + fun indexOfTerminalTab(tab: TerminalTab): Int } \ No newline at end of file diff --git a/src/main/kotlin/app/termora/plugin/internal/local/LocalTerminalTab.kt b/src/main/kotlin/app/termora/plugin/internal/local/LocalTerminalTab.kt index 7b3108d..f42b694 100644 --- a/src/main/kotlin/app/termora/plugin/internal/local/LocalTerminalTab.kt +++ b/src/main/kotlin/app/termora/plugin/internal/local/LocalTerminalTab.kt @@ -62,6 +62,9 @@ class LocalTerminalTab(windowScope: WindowScope, host: Host) : ) == JOptionPane.OK_OPTION } + override fun createReconnectTerminalTab(): TerminalTab { + return LocalTerminalTab(windowScope, host) + } private fun getPtyProcessConnector(): PtyProcessConnector? { var p = getPtyConnector() as PtyConnector? diff --git a/src/main/kotlin/app/termora/plugin/internal/sftppty/SFTPPtyTerminalTab.kt b/src/main/kotlin/app/termora/plugin/internal/sftppty/SFTPPtyTerminalTab.kt index fa6c164..ea573a3 100644 --- a/src/main/kotlin/app/termora/plugin/internal/sftppty/SFTPPtyTerminalTab.kt +++ b/src/main/kotlin/app/termora/plugin/internal/sftppty/SFTPPtyTerminalTab.kt @@ -185,6 +185,10 @@ class SFTPPtyTerminalTab(windowScope: WindowScope, host: Host) : PtyHostTerminal return Icons.fileFormat } + override fun createReconnectTerminalTab(): TerminalTab { + return SFTPPtyTerminalTab(windowScope, host) + } + override fun sendStartupCommand(ptyConnector: PtyConnector, bytes: ByteArray) { // Nothing } diff --git a/src/main/kotlin/app/termora/plugin/internal/ssh/SSHTerminalTab.kt b/src/main/kotlin/app/termora/plugin/internal/ssh/SSHTerminalTab.kt index 378f594..7942879 100644 --- a/src/main/kotlin/app/termora/plugin/internal/ssh/SSHTerminalTab.kt +++ b/src/main/kotlin/app/termora/plugin/internal/ssh/SSHTerminalTab.kt @@ -54,6 +54,10 @@ class SSHTerminalTab( return mutex.isLocked.not() } + override fun createReconnectTerminalTab(): TerminalTab { + return SSHTerminalTab(windowScope, host) + } + override suspend fun openPtyConnector(): PtyConnector { if (mutex.tryLock()) { try { @@ -211,17 +215,6 @@ class SSHTerminalTab( return super.getData(dataKey) } - override fun reconnect() { - stop() - - // 重新连接时就等于重新打开了一个标签,handler 重置 - handler.client = null - handler.session = null - handler.client = null - - start() - } - override fun stop() { if (mutex.tryLock()) { try { diff --git a/src/main/kotlin/app/termora/plugin/internal/telnet/TelnetTerminalTab.kt b/src/main/kotlin/app/termora/plugin/internal/telnet/TelnetTerminalTab.kt index 56355a2..31fefe3 100644 --- a/src/main/kotlin/app/termora/plugin/internal/telnet/TelnetTerminalTab.kt +++ b/src/main/kotlin/app/termora/plugin/internal/telnet/TelnetTerminalTab.kt @@ -1,9 +1,6 @@ package app.termora.plugin.internal.telnet -import app.termora.Host -import app.termora.ProxyType -import app.termora.PtyHostTerminalTab -import app.termora.WindowScope +import app.termora.* import app.termora.terminal.ControlCharacters import app.termora.terminal.KeyEncoderImpl import app.termora.terminal.PtyConnector @@ -71,5 +68,9 @@ class TelnetTerminalTab( return ptyConnectorFactory.decorate(TelnetStreamPtyConnector(telnet, telnet.charset, characterMode)) } + override fun createReconnectTerminalTab(): TerminalTab { + return TelnetTerminalTab(windowScope, host) + } + } \ No newline at end of file diff --git a/src/main/kotlin/app/termora/plugin/internal/wsl/WSLHostTerminalTab.kt b/src/main/kotlin/app/termora/plugin/internal/wsl/WSLHostTerminalTab.kt index bc18985..31fc848 100644 --- a/src/main/kotlin/app/termora/plugin/internal/wsl/WSLHostTerminalTab.kt +++ b/src/main/kotlin/app/termora/plugin/internal/wsl/WSLHostTerminalTab.kt @@ -1,9 +1,6 @@ package app.termora.plugin.internal.wsl -import app.termora.Host -import app.termora.PtyConnectorFactory -import app.termora.PtyHostTerminalTab -import app.termora.WindowScope +import app.termora.* import app.termora.terminal.PtyConnector import org.apache.commons.io.Charsets import org.apache.commons.io.FileUtils @@ -51,6 +48,10 @@ class WSLHostTerminalTab(windowScope: WindowScope, host: Host) : PtyHostTerminal return ptyConnector } + override fun createReconnectTerminalTab(): TerminalTab { + return WSLHostTerminalTab(windowScope, host) + } + override fun sendStartupCommand(ptyConnector: PtyConnector, bytes: ByteArray) { // Nothing diff --git a/src/main/kotlin/app/termora/tlog/LogViewerTerminalTab.kt b/src/main/kotlin/app/termora/tlog/LogViewerTerminalTab.kt index 6c3caf8..b4043a9 100644 --- a/src/main/kotlin/app/termora/tlog/LogViewerTerminalTab.kt +++ b/src/main/kotlin/app/termora/tlog/LogViewerTerminalTab.kt @@ -1,9 +1,6 @@ package app.termora.tlog -import app.termora.Host -import app.termora.Icons -import app.termora.PtyHostTerminalTab -import app.termora.WindowScope +import app.termora.* import app.termora.terminal.PtyConnector import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -71,6 +68,10 @@ class LogViewerTerminalTab( return false } + override fun createReconnectTerminalTab(): TerminalTab { + throw UnsupportedOperationException() + } + override fun canClone(): Boolean { return false }