mirror of
https://github.com/TermoraDev/termora.git
synced 2026-01-16 02:12:58 +08:00
fix: SFTP path not jumping on Windows (#483)
This commit is contained in:
9
src/main/kotlin/app/termora/sftp/FileSystemProvider.kt
Normal file
9
src/main/kotlin/app/termora/sftp/FileSystemProvider.kt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package app.termora.sftp
|
||||||
|
|
||||||
|
import org.apache.commons.vfs2.FileSystem
|
||||||
|
|
||||||
|
|
||||||
|
interface FileSystemProvider {
|
||||||
|
fun getFileSystem(): FileSystem
|
||||||
|
fun setFileSystem(fileSystem: FileSystem)
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ import javax.swing.filechooser.FileSystemView
|
|||||||
import kotlin.io.path.absolutePathString
|
import kotlin.io.path.absolutePathString
|
||||||
|
|
||||||
class FileSystemViewNav(
|
class FileSystemViewNav(
|
||||||
private val fileSystem: org.apache.commons.vfs2.FileSystem,
|
private val fileSystemProvider: FileSystemProvider,
|
||||||
private val homeDirectory: FileObject
|
private val homeDirectory: FileObject
|
||||||
) : JPanel(BorderLayout()) {
|
) : JPanel(BorderLayout()) {
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ class FileSystemViewNav(
|
|||||||
add(layeredPane, BorderLayout.CENTER)
|
add(layeredPane, BorderLayout.CENTER)
|
||||||
|
|
||||||
|
|
||||||
if (SystemInfo.isWindows && fileSystem is LocalFileSystem) {
|
if (SystemInfo.isWindows && fileSystemProvider.getFileSystem() is LocalFileSystem) {
|
||||||
try {
|
try {
|
||||||
for (root in fileSystemView.roots) {
|
for (root in fileSystemView.roots) {
|
||||||
history.add(root.absolutePath)
|
history.add(root.absolutePath)
|
||||||
@@ -174,9 +174,14 @@ class FileSystemViewNav(
|
|||||||
override fun actionPerformed(e: ActionEvent) {
|
override fun actionPerformed(e: ActionEvent) {
|
||||||
val name = textField.text.trim()
|
val name = textField.text.trim()
|
||||||
if (name.isBlank()) return
|
if (name.isBlank()) return
|
||||||
|
val fileSystem = fileSystemProvider.getFileSystem()
|
||||||
try {
|
try {
|
||||||
if (fileSystem is LocalFileSystem && SystemUtils.IS_OS_WINDOWS) {
|
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 {
|
} else {
|
||||||
changeSelectedPath(fileSystem.resolveFile(name))
|
changeSelectedPath(fileSystem.resolveFile(name))
|
||||||
}
|
}
|
||||||
@@ -192,6 +197,7 @@ class FileSystemViewNav(
|
|||||||
private fun showComboBoxPopup() {
|
private fun showComboBoxPopup() {
|
||||||
|
|
||||||
comboBox.removeAllItems()
|
comboBox.removeAllItems()
|
||||||
|
val fileSystem = fileSystemProvider.getFileSystem()
|
||||||
|
|
||||||
for (text in history) {
|
for (text in history) {
|
||||||
val path = if (SystemInfo.isWindows && fileSystem is LocalFileSystem) {
|
val path = if (SystemInfo.isWindows && fileSystem is LocalFileSystem) {
|
||||||
|
|||||||
@@ -10,9 +10,13 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.swing.Swing
|
import kotlinx.coroutines.swing.Swing
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.apache.commons.lang3.StringUtils
|
||||||
import org.apache.commons.lang3.SystemUtils
|
import org.apache.commons.lang3.SystemUtils
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils
|
import org.apache.commons.lang3.exception.ExceptionUtils
|
||||||
import org.apache.commons.vfs2.FileObject
|
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 org.jdesktop.swingx.JXBusyLabel
|
||||||
import java.awt.BorderLayout
|
import java.awt.BorderLayout
|
||||||
import java.awt.event.*
|
import java.awt.event.*
|
||||||
@@ -22,14 +26,14 @@ import javax.swing.*
|
|||||||
|
|
||||||
class FileSystemViewPanel(
|
class FileSystemViewPanel(
|
||||||
val host: Host,
|
val host: Host,
|
||||||
val fileSystem: org.apache.commons.vfs2.FileSystem,
|
private var fileSystem: FileSystem,
|
||||||
private val transportManager: TransportManager,
|
private val transportManager: TransportManager,
|
||||||
private val coroutineScope: CoroutineScope,
|
private val coroutineScope: CoroutineScope,
|
||||||
) : JPanel(BorderLayout()), Disposable, DataProvider {
|
) : JPanel(BorderLayout()), Disposable, DataProvider, FileSystemProvider {
|
||||||
|
|
||||||
private val properties get() = Database.getDatabase().properties
|
private val properties get() = Database.getDatabase().properties
|
||||||
private val sftp get() = Database.getDatabase().sftp
|
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 val disposed = AtomicBoolean(false)
|
||||||
private var nextReloadTicks = emptyArray<Consumer<Unit>>()
|
private var nextReloadTicks = emptyArray<Consumer<Unit>>()
|
||||||
private val isLoading = AtomicBoolean(false)
|
private val isLoading = AtomicBoolean(false)
|
||||||
@@ -37,7 +41,7 @@ class FileSystemViewPanel(
|
|||||||
private val loadingPanel = LoadingPanel()
|
private val loadingPanel = LoadingPanel()
|
||||||
private val layeredPane = LayeredPane()
|
private val layeredPane = LayeredPane()
|
||||||
private val homeDirectory = getHomeDirectory()
|
private val homeDirectory = getHomeDirectory()
|
||||||
private val nav = FileSystemViewNav(fileSystem, homeDirectory)
|
private val nav = FileSystemViewNav(this, homeDirectory)
|
||||||
private var workdir = homeDirectory
|
private var workdir = homeDirectory
|
||||||
private val model get() = table.model as FileSystemViewTableModel
|
private val model get() = table.model as FileSystemViewTableModel
|
||||||
private val showHiddenFilesKey = "termora.transport.host.${host.id}.show-hidden-files"
|
private val showHiddenFilesKey = "termora.transport.host.${host.id}.show-hidden-files"
|
||||||
@@ -173,7 +177,15 @@ class FileSystemViewPanel(
|
|||||||
}
|
}
|
||||||
bookmarkBtn.isBookmark = !bookmarkBtn.isBookmark
|
bookmarkBtn.isBookmark = !bookmarkBtn.isBookmark
|
||||||
} else {
|
} 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 {
|
private fun getHomeDirectory(): FileObject {
|
||||||
|
val fileSystem = this.fileSystem
|
||||||
if (fileSystem is MySftpFileSystem) {
|
if (fileSystem is MySftpFileSystem) {
|
||||||
val host = fileSystem.getClientSession().getAttribute(SshClients.HOST_KEY)
|
val host = fileSystem.getClientSession().getAttribute(SshClients.HOST_KEY)
|
||||||
?: return fileSystem.resolveFile(fileSystem.getDefaultDir())
|
?: return fileSystem.resolveFile(fileSystem.getDefaultDir())
|
||||||
@@ -429,6 +442,14 @@ class FileSystemViewPanel(
|
|||||||
return if (dataKey == SFTPDataProviders.FileSystemViewTable) table as T else null
|
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 class LoadingPanel : JPanel() {
|
||||||
private val busyLabel = JXBusyLabel()
|
private val busyLabel = JXBusyLabel()
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ import kotlin.time.Duration.Companion.milliseconds
|
|||||||
|
|
||||||
@Suppress("DuplicatedCode", "CascadeIf")
|
@Suppress("DuplicatedCode", "CascadeIf")
|
||||||
class FileSystemViewTable(
|
class FileSystemViewTable(
|
||||||
private val fileSystem: org.apache.commons.vfs2.FileSystem,
|
private val fileSystemProvider: FileSystemProvider,
|
||||||
private val transportManager: TransportManager,
|
private val transportManager: TransportManager,
|
||||||
private val coroutineScope: CoroutineScope
|
private val coroutineScope: CoroutineScope
|
||||||
) : JTable(), Disposable {
|
) : JTable(), Disposable {
|
||||||
@@ -184,7 +184,7 @@ class FileSystemViewTable(
|
|||||||
val data = support.transferable.getTransferData(FileSystemTableRowTransferable.dataFlavor)
|
val data = support.transferable.getTransferData(FileSystemTableRowTransferable.dataFlavor)
|
||||||
return data is FileSystemTableRowTransferable && data.source != table
|
return data is FileSystemTableRowTransferable && data.source != table
|
||||||
} else if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
|
} else if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
|
||||||
return fileSystem !is LocalFileSystem
|
return fileSystemProvider.getFileSystem() !is LocalFileSystem
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
@@ -261,6 +261,7 @@ class FileSystemViewTable(
|
|||||||
private fun showContextMenu(rows: IntArray, e: MouseEvent) {
|
private fun showContextMenu(rows: IntArray, e: MouseEvent) {
|
||||||
val files = rows.map { model.getFileObject(it) }
|
val files = rows.map { model.getFileObject(it) }
|
||||||
val hasParent = rows.contains(0)
|
val hasParent = rows.contains(0)
|
||||||
|
val fileSystem = fileSystemProvider.getFileSystem()
|
||||||
|
|
||||||
val popupMenu = FlatPopupMenu()
|
val popupMenu = FlatPopupMenu()
|
||||||
val newMenu = JMenu(I18n.getString("termora.transport.table.contextmenu.new"))
|
val newMenu = JMenu(I18n.getString("termora.transport.table.contextmenu.new"))
|
||||||
@@ -571,7 +572,7 @@ class FileSystemViewTable(
|
|||||||
coroutineScope.launch(Dispatchers.IO) {
|
coroutineScope.launch(Dispatchers.IO) {
|
||||||
|
|
||||||
runCatching {
|
runCatching {
|
||||||
if (fileSystem is MySftpFileSystem) {
|
if (fileSystemProvider.getFileSystem() is MySftpFileSystem) {
|
||||||
deleteSftpPaths(paths, rm)
|
deleteSftpPaths(paths, rm)
|
||||||
} else {
|
} else {
|
||||||
deleteRecursively(paths)
|
deleteRecursively(paths)
|
||||||
@@ -594,7 +595,7 @@ class FileSystemViewTable(
|
|||||||
|
|
||||||
private fun deleteSftpPaths(files: List<FileObject>, rm: Boolean = false) {
|
private fun deleteSftpPaths(files: List<FileObject>, rm: Boolean = false) {
|
||||||
if (rm) {
|
if (rm) {
|
||||||
val session = (this.fileSystem as MySftpFileSystem).getClientSession()
|
val session = (this.fileSystemProvider.getFileSystem() as MySftpFileSystem).getClientSession()
|
||||||
for (path in files) {
|
for (path in files) {
|
||||||
session.executeRemoteCommand(
|
session.executeRemoteCommand(
|
||||||
"rm -rf '${path.absolutePathString()}'",
|
"rm -rf '${path.absolutePathString()}'",
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ class SFTPPanel : JPanel(BorderLayout()), DataProvider, Disposable {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val fs = c.fileSystem
|
val fs = c.getFileSystem()
|
||||||
val root = transportManager.root
|
val root = transportManager.root
|
||||||
|
|
||||||
transportManager.lock.withLock {
|
transportManager.lock.withLock {
|
||||||
|
|||||||
Reference in New Issue
Block a user