From 9398dd6abe2d4e69a00dfba7a6ebe18a9299cc08 Mon Sep 17 00:00:00 2001 From: AmirHossein Abdolmotallebi Date: Tue, 10 Sep 2024 05:39:14 +0330 Subject: [PATCH] fix folder opened two times when clicking on open folder --- .../main/kotlin/ir/amirab/util/FileUtils.kt | 71 ++++++++++--------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/shared/utils/src/main/kotlin/ir/amirab/util/FileUtils.kt b/shared/utils/src/main/kotlin/ir/amirab/util/FileUtils.kt index 7469cbb..a4b3a46 100644 --- a/shared/utils/src/main/kotlin/ir/amirab/util/FileUtils.kt +++ b/shared/utils/src/main/kotlin/ir/amirab/util/FileUtils.kt @@ -4,6 +4,7 @@ import ir.amirab.util.platform.Platform import java.awt.Desktop import java.io.File import java.io.FileNotFoundException +import java.util.concurrent.TimeUnit interface FileUtils { fun openFile(file: File) @@ -31,7 +32,7 @@ private open class DefaultFileUtils : FileUtils { if (!file.exists()) { throw FileNotFoundException("$file not found") } - val desktop = Desktop.getDesktop() ?: return; + val desktop = Desktop.getDesktop() ?: return desktop.open(file) } @@ -74,50 +75,56 @@ private open class DefaultFileUtils : FileUtils { private class WindowsFileUtils : DefaultFileUtils() { override fun fallBackOpenFolderOfFile(file: File): Boolean { - return kotlin.runCatching { - Runtime.getRuntime() - .exec( - arrayOf( - "cmd", "/c", - "explorer.exe", - "/select,", - file.path - ) - ).exitValue() == 0 - }.getOrElse { false } + return execAndWait(arrayOf("cmd", "/c", "explorer.exe", "/select,", file.path)) } } private class LinuxFileUtils : DefaultFileUtils() { override fun fallBackOpenFolderOfFile(file: File): Boolean { - val dbusSendResult = kotlin.runCatching { - Runtime.getRuntime().exec( - arrayOf( - "dbus-send", - "--print-reply", - "--dest=org.freedesktop.FileManager1", - "/org/freedesktop/FileManager1", - "org.freedesktop.FileManager1.ShowItems", - "array:string:file://${file.path}", - "string:" - ) - ).exitValue() == 0 - }.getOrElse { false } + val dbusSendResult = execAndWait( + arrayOf( + "dbus-send", + "--print-reply", + "--dest=org.freedesktop.FileManager1", + "/org/freedesktop/FileManager1", + "org.freedesktop.FileManager1.ShowItems", + "array:string:file://${file.path}", + "string:" + ) + ) if (dbusSendResult) { return true } - val xdgOpenResult = kotlin.runCatching { - Runtime.getRuntime().exec(arrayOf("xdg-open", file.parent)).exitValue() == 0 - }.getOrElse { false } + val xdgOpenResult = execAndWait( + arrayOf("xdg-open", file.parent) + ) return xdgOpenResult } } private class MacOsFileUtils : DefaultFileUtils() { override fun fallBackOpenFolderOfFile(file: File): Boolean { - return kotlin.runCatching { - Runtime.getRuntime() - .exec(arrayOf("open", "-R", file.path)).exitValue() == 0 - }.getOrElse { false } + return execAndWait(arrayOf("open", "-R", file.path)) } +} + +/** + * this helper function is here to execute a command and waits for the process to finish and return the result based on exit code + * @param command the command + * @param waitFor maximum time allowed process finish ( in milliseconds ) + * @return `true` when process exits with `0` exit code, `false` if the process fails with non-zero exit code or execution time exceeds the [waitFor] + */ +private fun execAndWait( + command: Array, + waitFor: Long = 2_000, +): Boolean { + return runCatching { + val p = Runtime.getRuntime().exec(command) + val exited = p.waitFor(waitFor, TimeUnit.MILLISECONDS) + if (exited) { + p.exitValue() == 0 + } else { + false + } + }.getOrElse { false } } \ No newline at end of file