diff --git a/src/main/kotlin/app/extensions/Shell.kt b/src/main/kotlin/app/extensions/Shell.kt index d517e9e..2c25278 100644 --- a/src/main/kotlin/app/extensions/Shell.kt +++ b/src/main/kotlin/app/extensions/Shell.kt @@ -1,7 +1,11 @@ package app.extensions +import app.logging.printLog +import java.io.IOException import java.util.* +private const val TAG = "Shell" + fun runCommand(command: String): String? { return try { var result: String? @@ -19,5 +23,46 @@ fun runCommand(command: String): String? { ex.printStackTrace() null } +} +fun runCommandWithoutResult(command: String, args: String, file: String): Boolean { + val parts: Array = prepareCommand(command, args, file) + + printLog(TAG, "Running command $parts") + + return try { + val p = Runtime.getRuntime().exec(parts) ?: return false + try { + val exitValue = p.exitValue() + + if (exitValue == 0) { + printLog(TAG, "Process ended immediately.") + false + } else { + printLog(TAG, "Process crashed.") + false + } + } catch (itse: IllegalThreadStateException) { + printLog(TAG, "Process is running.") + true + } + } catch (e: IOException) { + printLog(TAG, "Error running command: ${e.message}") + e.printStackTrace() + false + } +} + + +private fun prepareCommand(command: String, args: String?, file: String): Array { + val parts: MutableList = ArrayList() + parts.add(command) + + if (args != null) { + for (s in args.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) { + val stringFormatted = String.format(s, file) // put in the filename thing + parts.add(stringFormatted.trim { it <= ' ' }) + } + } + return parts.toTypedArray() } \ No newline at end of file diff --git a/src/main/kotlin/app/extensions/SystemUtils.kt b/src/main/kotlin/app/extensions/SystemUtils.kt index ee74721..901d653 100644 --- a/src/main/kotlin/app/extensions/SystemUtils.kt +++ b/src/main/kotlin/app/extensions/SystemUtils.kt @@ -15,6 +15,33 @@ val systemSeparator: String by lazy { } fun openUrlInBrowser(url: String) { + if (!openSystemSpecific(url)) { + openUrlInBrowserJdk(url) + } +} + +private fun openSystemSpecific(url: String): Boolean { + val os = System.getProperty("os.name") + if (os.contains("linux")) { + if (runCommandWithoutResult("xdg-open", "%s", url)) + return true + if (runCommandWithoutResult("kde-open", "%s", url)) + return true + if (runCommandWithoutResult("gnome-open", "%s", url)) + return true + } else if (os.contains("windows")) { + if (runCommandWithoutResult("explorer", "%s", url)) + return true + } else if (os.contains("mac")) { + if (runCommandWithoutResult("open", "%s", url)) + return true + } + + return false +} + +fun openUrlInBrowserJdk(url: String) { + try { Desktop.getDesktop().browse(URI(url)) } catch (ex: Exception) { diff --git a/src/main/kotlin/app/ui/SystemDialogs.kt b/src/main/kotlin/app/ui/SystemDialogs.kt index f7dfeed..307abeb 100644 --- a/src/main/kotlin/app/ui/SystemDialogs.kt +++ b/src/main/kotlin/app/ui/SystemDialogs.kt @@ -1,9 +1,12 @@ package app.ui +import app.extensions.runCommand +import app.logging.printLog import app.viewmodels.TabViewModel import javax.swing.JFileChooser import javax.swing.UIManager +private const val TAG = "SystemDialogs" fun openDirectoryDialog(basePath: String? = null): String? { return openPickerDialog( @@ -36,6 +39,54 @@ private fun openPickerDialog( val os = System.getProperty("os.name") val isLinux = os.lowercase().contains("linux") + return if (isLinux) { + openDirectoryDialogLinux(pickerType) + } else + openJvmDialog(pickerType, basePath, false) +} + +enum class PickerType(val value: Int) { + FILES(JFileChooser.FILES_ONLY), + DIRECTORIES(JFileChooser.DIRECTORIES_ONLY), + FILES_AND_DIRECTORIES(JFileChooser.FILES_AND_DIRECTORIES); +} + + +fun openDirectoryDialogLinux(pickerType: PickerType): String? { + val os = System.getProperty("os.name") + var dirToOpen: String? = null + + if (os.lowercase() == "linux") { + val checkZenityInstalled = runCommand("which zenity 2>/dev/null") + val isZenityInstalled = !checkZenityInstalled.isNullOrEmpty() + + printLog(TAG, "IsZenityInstalled $isZenityInstalled") + + if (isZenityInstalled) { + + val command = when (pickerType) { + PickerType.FILES, PickerType.FILES_AND_DIRECTORIES -> "zenity --file-selection --title=Open" + PickerType.DIRECTORIES -> "zenity --file-selection --title=Open --directory" + } + + val openDirectory = runCommand(command)?.replace("\n", "") + + if (!openDirectory.isNullOrEmpty()) + dirToOpen = openDirectory + } else + dirToOpen = openJvmDialog(pickerType, "", true) + } else { + dirToOpen = openJvmDialog(pickerType, "", false) + } + + return dirToOpen +} + +private fun openJvmDialog( + pickerType: PickerType, + basePath: String?, + isLinux: Boolean, +): String? { if (!isLinux) { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()) } @@ -52,10 +103,4 @@ private fun openPickerDialog( fileChooser.selectedFile.absolutePath else null -} - -enum class PickerType(val value: Int) { - FILES(JFileChooser.FILES_ONLY), - DIRECTORIES(JFileChooser.DIRECTORIES_ONLY), - FILES_AND_DIRECTORIES(JFileChooser.FILES_AND_DIRECTORIES); } \ No newline at end of file