fix: SFTP path not jumping on Windows (#483)

This commit is contained in:
hstyi
2025-04-10 11:08:51 +08:00
committed by GitHub
parent 5ffdd219d9
commit ed65853ebe
5 changed files with 50 additions and 13 deletions

View File

@@ -0,0 +1,9 @@
package app.termora.sftp
import org.apache.commons.vfs2.FileSystem
interface FileSystemProvider {
fun getFileSystem(): FileSystem
fun setFileSystem(fileSystem: FileSystem)
}

View File

@@ -27,7 +27,7 @@ import javax.swing.filechooser.FileSystemView
import kotlin.io.path.absolutePathString
class FileSystemViewNav(
private val fileSystem: org.apache.commons.vfs2.FileSystem,
private val fileSystemProvider: FileSystemProvider,
private val homeDirectory: FileObject
) : JPanel(BorderLayout()) {
@@ -103,7 +103,7 @@ class FileSystemViewNav(
add(layeredPane, BorderLayout.CENTER)
if (SystemInfo.isWindows && fileSystem is LocalFileSystem) {
if (SystemInfo.isWindows && fileSystemProvider.getFileSystem() is LocalFileSystem) {
try {
for (root in fileSystemView.roots) {
history.add(root.absolutePath)
@@ -174,9 +174,14 @@ class FileSystemViewNav(
override fun actionPerformed(e: ActionEvent) {
val name = textField.text.trim()
if (name.isBlank()) return
val fileSystem = fileSystemProvider.getFileSystem()
try {
if (fileSystem is LocalFileSystem && SystemUtils.IS_OS_WINDOWS) {
changeSelectedPath(fileSystem.resolveFile("file://${name}"))
val file = VFS.getManager().resolveFile("file://${name}")
if (!StringUtils.equals(file.fileSystem.rootURI, fileSystemProvider.getFileSystem().rootURI)) {
fileSystemProvider.setFileSystem(file.fileSystem)
}
changeSelectedPath(file)
} else {
changeSelectedPath(fileSystem.resolveFile(name))
}
@@ -192,6 +197,7 @@ class FileSystemViewNav(
private fun showComboBoxPopup() {
comboBox.removeAllItems()
val fileSystem = fileSystemProvider.getFileSystem()
for (text in history) {
val path = if (SystemInfo.isWindows && fileSystem is LocalFileSystem) {

View File

@@ -10,9 +10,13 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.swing.Swing
import kotlinx.coroutines.withContext
import org.apache.commons.lang3.StringUtils
import org.apache.commons.lang3.SystemUtils
import org.apache.commons.lang3.exception.ExceptionUtils
import org.apache.commons.vfs2.FileObject
import org.apache.commons.vfs2.FileSystem
import org.apache.commons.vfs2.VFS
import org.apache.commons.vfs2.provider.local.LocalFileSystem
import org.jdesktop.swingx.JXBusyLabel
import java.awt.BorderLayout
import java.awt.event.*
@@ -22,14 +26,14 @@ import javax.swing.*
class FileSystemViewPanel(
val host: Host,
val fileSystem: org.apache.commons.vfs2.FileSystem,
private var fileSystem: FileSystem,
private val transportManager: TransportManager,
private val coroutineScope: CoroutineScope,
) : JPanel(BorderLayout()), Disposable, DataProvider {
) : JPanel(BorderLayout()), Disposable, DataProvider, FileSystemProvider {
private val properties get() = Database.getDatabase().properties
private val sftp get() = Database.getDatabase().sftp
private val table = FileSystemViewTable(fileSystem, transportManager, coroutineScope)
private val table = FileSystemViewTable(this, transportManager, coroutineScope)
private val disposed = AtomicBoolean(false)
private var nextReloadTicks = emptyArray<Consumer<Unit>>()
private val isLoading = AtomicBoolean(false)
@@ -37,7 +41,7 @@ class FileSystemViewPanel(
private val loadingPanel = LoadingPanel()
private val layeredPane = LayeredPane()
private val homeDirectory = getHomeDirectory()
private val nav = FileSystemViewNav(fileSystem, homeDirectory)
private val nav = FileSystemViewNav(this, homeDirectory)
private var workdir = homeDirectory
private val model get() = table.model as FileSystemViewTableModel
private val showHiddenFilesKey = "termora.transport.host.${host.id}.show-hidden-files"
@@ -173,7 +177,15 @@ class FileSystemViewPanel(
}
bookmarkBtn.isBookmark = !bookmarkBtn.isBookmark
} else {
changeWorkdir(fileSystem.resolveFile(e.actionCommand))
if (fileSystem is LocalFileSystem && SystemUtils.IS_OS_WINDOWS) {
val file = VFS.getManager().resolveFile("file://${e.actionCommand}")
if (!StringUtils.equals(file.fileSystem.rootURI, fileSystem.rootURI)) {
fileSystem = file.fileSystem
}
changeWorkdir(file)
} else {
changeWorkdir(fileSystem.resolveFile(e.actionCommand))
}
}
}
@@ -372,6 +384,7 @@ class FileSystemViewPanel(
}
private fun getHomeDirectory(): FileObject {
val fileSystem = this.fileSystem
if (fileSystem is MySftpFileSystem) {
val host = fileSystem.getClientSession().getAttribute(SshClients.HOST_KEY)
?: return fileSystem.resolveFile(fileSystem.getDefaultDir())
@@ -429,6 +442,14 @@ class FileSystemViewPanel(
return if (dataKey == SFTPDataProviders.FileSystemViewTable) table as T else null
}
override fun getFileSystem(): FileSystem {
return fileSystem
}
override fun setFileSystem(fileSystem: FileSystem) {
this.fileSystem = fileSystem
}
private class LoadingPanel : JPanel() {
private val busyLabel = JXBusyLabel()

View File

@@ -52,7 +52,7 @@ import kotlin.time.Duration.Companion.milliseconds
@Suppress("DuplicatedCode", "CascadeIf")
class FileSystemViewTable(
private val fileSystem: org.apache.commons.vfs2.FileSystem,
private val fileSystemProvider: FileSystemProvider,
private val transportManager: TransportManager,
private val coroutineScope: CoroutineScope
) : JTable(), Disposable {
@@ -184,7 +184,7 @@ class FileSystemViewTable(
val data = support.transferable.getTransferData(FileSystemTableRowTransferable.dataFlavor)
return data is FileSystemTableRowTransferable && data.source != table
} else if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return fileSystem !is LocalFileSystem
return fileSystemProvider.getFileSystem() !is LocalFileSystem
}
return false
@@ -261,6 +261,7 @@ class FileSystemViewTable(
private fun showContextMenu(rows: IntArray, e: MouseEvent) {
val files = rows.map { model.getFileObject(it) }
val hasParent = rows.contains(0)
val fileSystem = fileSystemProvider.getFileSystem()
val popupMenu = FlatPopupMenu()
val newMenu = JMenu(I18n.getString("termora.transport.table.contextmenu.new"))
@@ -571,7 +572,7 @@ class FileSystemViewTable(
coroutineScope.launch(Dispatchers.IO) {
runCatching {
if (fileSystem is MySftpFileSystem) {
if (fileSystemProvider.getFileSystem() is MySftpFileSystem) {
deleteSftpPaths(paths, rm)
} else {
deleteRecursively(paths)
@@ -594,7 +595,7 @@ class FileSystemViewTable(
private fun deleteSftpPaths(files: List<FileObject>, rm: Boolean = false) {
if (rm) {
val session = (this.fileSystem as MySftpFileSystem).getClientSession()
val session = (this.fileSystemProvider.getFileSystem() as MySftpFileSystem).getClientSession()
for (path in files) {
session.executeRemoteCommand(
"rm -rf '${path.absolutePathString()}'",

View File

@@ -127,7 +127,7 @@ class SFTPPanel : JPanel(BorderLayout()), DataProvider, Disposable {
return
}
val fs = c.fileSystem
val fs = c.getFileSystem()
val root = transportManager.root
transportManager.lock.withLock {