feat: support fixed SFTP tab (#286)

This commit is contained in:
hstyi
2025-02-21 17:04:50 +08:00
committed by GitHub
parent 7df317a1b9
commit c49acf7b51
10 changed files with 84 additions and 27 deletions

View File

@@ -599,6 +599,12 @@ class Database private constructor(private val env: Environment) : Disposable {
*/
var sftpCommand by StringPropertyDelegate(StringUtils.EMPTY)
/**
* 是否固定在标签栏
*/
var pinTab by BooleanPropertyDelegate(false)
}
/**

View File

@@ -12,10 +12,11 @@ import javax.swing.SwingUtilities
class SFTPTerminalTab : Disposable, TerminalTab, DataProvider {
private val transportPanel by lazy {
TransportPanel().apply {
Disposer.register(this@SFTPTerminalTab, this)
}
private val sftp get() = Database.getDatabase().sftp
private val transportPanel = TransportPanel()
init {
Disposer.register(this, transportPanel)
}
override fun getTitle(): String {
@@ -43,6 +44,11 @@ class SFTPTerminalTab : Disposable, TerminalTab, DataProvider {
override fun canClose(): Boolean {
assertEventDispatchThread()
if (sftp.pinTab) {
return false
}
val transportManager = transportPanel.getData(TransportDataProviders.TransportManager) ?: return true
if (transportManager.getTransports().isEmpty()) {
return true

View File

@@ -4,6 +4,7 @@ import app.termora.AES.encodeBase64String
import app.termora.Application.ohMyJson
import app.termora.actions.AnAction
import app.termora.actions.AnActionEvent
import app.termora.actions.DataProviders
import app.termora.highlight.KeywordHighlight
import app.termora.highlight.KeywordHighlightManager
import app.termora.keymap.Keymap
@@ -22,6 +23,7 @@ import app.termora.terminal.CursorStyle
import app.termora.terminal.DataKey
import app.termora.terminal.panel.FloatingToolbarPanel
import app.termora.terminal.panel.TerminalPanel
import app.termora.transport.SFTPAction
import cash.z.ecc.android.bip39.Mnemonics
import com.formdev.flatlaf.FlatClientProperties
import com.formdev.flatlaf.extras.FlatSVGIcon
@@ -43,6 +45,7 @@ import org.apache.commons.lang3.SystemUtils
import org.apache.commons.lang3.exception.ExceptionUtils
import org.apache.commons.lang3.time.DateFormatUtils
import org.jdesktop.swingx.JXEditorPane
import org.jdesktop.swingx.action.ActionManager
import org.slf4j.LoggerFactory
import java.awt.BorderLayout
import java.awt.Component
@@ -67,6 +70,7 @@ class SettingsOptionsPane : OptionsPane() {
private val hostManager get() = HostManager.getInstance()
private val keymapManager get() = KeymapManager.getInstance()
private val macroManager get() = MacroManager.getInstance()
private val actionManager get() = ActionManager.getInstance()
private val keywordHighlightManager get() = KeywordHighlightManager.getInstance()
private val keyManager get() = KeyManager.getInstance()
@@ -1306,9 +1310,11 @@ class SettingsOptionsPane : OptionsPane() {
private inner class SFTPOption : JPanel(BorderLayout()), Option {
val editCommandField = OutlineTextField(255)
val sftpCommandField = OutlineTextField(255)
private val editCommandField = OutlineTextField(255)
private val sftpCommandField = OutlineTextField(255)
private val pinTabComboBox = YesOrNoComboBox()
private val sftp get() = database.sftp
private val sftpAction get() = actionManager.getAction(Actions.SFTP) as SFTPAction
init {
initView()
@@ -1329,6 +1335,26 @@ class SettingsOptionsPane : OptionsPane() {
sftp.sftpCommand = sftpCommandField.text
}
})
pinTabComboBox.addItemListener {
if (it.stateChange == ItemEvent.SELECTED) {
sftp.pinTab = pinTabComboBox.selectedItem as Boolean
for (window in TermoraFrameManager.getInstance().getWindows()) {
val evt = AnActionEvent(window, StringUtils.EMPTY, EventObject(window))
if (pinTabComboBox.selectedItem == true) {
sftpAction.openOrCreateSFTPTerminalTab(evt)
}
val tabbed = evt.getData(DataProviders.TabbedPane) ?: continue
val manager = evt.getData(DataProviders.TerminalTabbedManager) ?: continue
for ((index, tab) in manager.getTerminalTabs().withIndex()) {
if (tab is SFTPTerminalTab) {
tabbed.setTabClosable(index, pinTabComboBox.selectedItem != true)
break
}
}
}
}
}
}
@@ -1347,6 +1373,7 @@ class SettingsOptionsPane : OptionsPane() {
editCommandField.text = sftp.editCommand
sftpCommandField.text = sftp.sftpCommand
pinTabComboBox.selectedItem = sftp.pinTab
}
override fun getIcon(isSelected: Boolean): Icon {
@@ -1368,10 +1395,12 @@ class SettingsOptionsPane : OptionsPane() {
)
val builder = FormBuilder.create().layout(layout).debug(false)
builder.add("${I18n.getString("termora.settings.sftp.edit-command")}:").xy(1, 1)
builder.add(editCommandField).xy(3, 1)
builder.add("${I18n.getString("termora.tabbed.contextmenu.sftp-command")}:").xy(1, 3)
builder.add(sftpCommandField).xy(3, 3)
builder.add("${I18n.getString("termora.settings.sftp.fixed-tab")}:").xy(1, 1)
builder.add(pinTabComboBox).xy(3, 1)
builder.add("${I18n.getString("termora.settings.sftp.edit-command")}:").xy(1, 3)
builder.add(editCommandField).xy(3, 3)
builder.add("${I18n.getString("termora.tabbed.contextmenu.sftp-command")}:").xy(1, 5)
builder.add(sftpCommandField).xy(3, 5)
return builder.build()

View File

@@ -280,7 +280,7 @@ class TerminalTabbed(
}
close.isEnabled = c !is WelcomePanel
close.isEnabled = tab.canClose()
rename.isEnabled = close.isEnabled
clone.isEnabled = close.isEnabled
openInNewWindow.isEnabled = close.isEnabled
@@ -306,7 +306,7 @@ class TerminalTabbed(
}
private fun addTab(index: Int, tab: TerminalTab) {
private fun addTab(index: Int, tab: TerminalTab, selected: Boolean) {
val c = tab.getJComponent()
val title = (c.getClientProperty(titleProperty) ?: tab.getTitle()).toString()
@@ -317,13 +317,20 @@ class TerminalTabbed(
StringUtils.EMPTY,
index
)
c.putClientProperty(titleProperty, title)
// 设置标题
c.putClientProperty(titleProperty, title)
// 监听 icons 变化
tab.addPropertyChangeListener(iconListener)
tabs.add(index, tab)
if (selected) {
tabbedPane.selectedIndex = index
}
tabbedPane.setTabClosable(index, tab.canClose())
Disposer.register(this, tab)
}
@@ -445,12 +452,12 @@ class TerminalTabbed(
override fun dispose() {
}
override fun addTerminalTab(tab: TerminalTab) {
addTab(tabs.size, tab)
override fun addTerminalTab(tab: TerminalTab, selected: Boolean) {
addTab(tabs.size, tab, selected)
}
override fun addTerminalTab(index: Int, tab: TerminalTab) {
addTab(index, tab)
override fun addTerminalTab(index: Int, tab: TerminalTab, selected: Boolean) {
addTab(index, tab, selected)
}
override fun getSelectedTerminalTab(): TerminalTab? {

View File

@@ -1,8 +1,8 @@
package app.termora
interface TerminalTabbedManager {
fun addTerminalTab(tab: TerminalTab)
fun addTerminalTab(index: Int, tab: TerminalTab)
fun addTerminalTab(tab: TerminalTab, selected: Boolean = true)
fun addTerminalTab(index: Int, tab: TerminalTab, selected: Boolean = true)
fun getSelectedTerminalTab(): TerminalTab?
fun getTerminalTabs(): List<TerminalTab>
fun setSelectedTerminalTab(tab: TerminalTab)

View File

@@ -1,7 +1,6 @@
package app.termora
import app.termora.actions.ActionManager
import app.termora.actions.DataProvider
import app.termora.actions.DataProviderSupport
import app.termora.actions.DataProviders
@@ -12,7 +11,6 @@ import com.formdev.flatlaf.util.SystemInfo
import com.jetbrains.JBR
import java.awt.Dimension
import java.awt.Insets
import java.awt.KeyboardFocusManager
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.util.*
@@ -32,7 +30,6 @@ fun assertEventDispatchThread() {
class TermoraFrame : JFrame(), DataProvider {
private val actionManager get() = ActionManager.getInstance()
private val id = UUID.randomUUID().toString()
private val windowScope = ApplicationScope.forWindowScope(this)
private val titleBar = LogicCustomTitleBar.createCustomTitleBar(this)
@@ -42,7 +39,7 @@ class TermoraFrame : JFrame(), DataProvider {
private val isWindowDecorationsSupported by lazy { JBR.isWindowDecorationsSupported() }
private val dataProviderSupport = DataProviderSupport()
private val welcomePanel = WelcomePanel(windowScope)
private val keyboardFocusManager by lazy { KeyboardFocusManager.getCurrentKeyboardFocusManager() }
private val sftp get() = Database.getDatabase().sftp
init {
@@ -103,6 +100,13 @@ class TermoraFrame : JFrame(), DataProvider {
minimumSize = Dimension(640, 400)
terminalTabbed.addTerminalTab(welcomePanel)
// 下一次事件循环检测是否固定 SFTP
SwingUtilities.invokeLater {
if (sftp.pinTab) {
terminalTabbed.addTerminalTab(SFTPTerminalTab(), false)
}
}
// macOS 要避开左边的控制栏
if (SystemInfo.isMacOS) {
val left = max(titleBar.leftInset.toInt(), 76)

View File

@@ -23,20 +23,22 @@ class SFTPAction : AnAction("SFTP", Icons.folder) {
*
* @return null 表示当前条件下无法创建
*/
fun openOrCreateSFTPTerminalTab(evt: AnActionEvent): SFTPTerminalTab? {
fun openOrCreateSFTPTerminalTab(evt: AnActionEvent, selected: Boolean = true): SFTPTerminalTab? {
val terminalTabbedManager = evt.getData(DataProviders.TerminalTabbedManager) ?: return null
val tabs = terminalTabbedManager.getTerminalTabs()
for (tab in tabs) {
if (tab is SFTPTerminalTab) {
if (selected) {
terminalTabbedManager.setSelectedTerminalTab(tab)
}
return tab
}
}
// 创建一个新的
val tab = SFTPTerminalTab()
terminalTabbedManager.addTerminalTab(tab)
terminalTabbedManager.addTerminalTab(tab, selected)
return tab
}

View File

@@ -110,6 +110,7 @@ termora.settings.keymap.already-exists=The shortcut [{0}] is already in use by [
termora.settings.sftp.edit-command=Edit Command
termora.settings.sftp.fixed-tab=Fixed tab
termora.settings.restart.title=Restart

View File

@@ -113,6 +113,7 @@ termora.settings.keymap.already-exists=快捷键 [{0}] 已经被 [{1}] 占用
termora.settings.sftp.edit-command=编辑命令
termora.settings.sftp.fixed-tab=固定标签
# Welcome

View File

@@ -63,6 +63,7 @@ termora.settings.keymap.action=操作
termora.settings.keymap.already-exists=快捷鍵 [{0}] 已經被 [{1}] 占用
termora.settings.sftp.edit-command=編輯命令
termora.settings.sftp.fixed-tab=固定標籤
# Find everywhere