Does Compose Desktop or something else kotlinx/Kot...
# compose-desktop
l
Does Compose Desktop or something else kotlinx/Kotlin provide the paths for app data, and app cache dirs that are appropriate for the platform the app is running on?
e
j
k
c
i used https://github.com/Syer10/Kotlin-Multiplatform-AppDirs in a desktop (macos windows linux) app with success recently.
m
So many options nice!
k
if you dont want to be lazy like everybody else here and want to Do It Yourself, here's a starter
Copy code
expect object AppDirs {
    fun init(platformCtx: Any? = null)

    /** Absolute, per-user, per-app directory – valid after `init` */
    val path: Path
}
Desktop target :
Copy code
actual object AppDirs {
    actual fun init(platformCtx: Any?) {}

    actual val path: Path by lazy {
        val p = (System.getProperty("user.home") + "/.someName").toPath()
        FileSystem.SYSTEM.createDirectories(p)
        p
    }
}
Android target:
Copy code
actual object AppDirs {
    private lateinit var internal: Path

    /** MUST be called from Application.onCreate() */
    actual fun init(platformCtx: Any?) {
        val ctx = platformCtx as Context
        val dir = ctx.getDir("someName", Context.MODE_PRIVATE)
        internal = dir.absolutePath.toPath()
    }

    actual val path: Path
        get() = if (::internal.isInitialized) internal
        else error("AppDirs.init(ctx) not called yet")
}
...and so on.....
😂 1
l
@Kaanixir That's not going to work on Compose Desktop, because there's a single Kotlin/JVM source set.
a
> if you dont want to be lazy like everybody else here and want to Do It Yourself, here's a starter You should not hardcode these paths on desktop, even if you have the user home directory and the app name, instead you should depend on platform APIs to get it for you. The reason is that your code will not work under some cases, for example, when packaging using Flatpak on Linux, your app won't respect the path overridden by Flatpak/Snap or other sandboxed environments and will cause issues. There are other cases but it's vary by platform. It's important to follow the platform conventions for better integration and consistency.
k
👍 you're right, going through suggestions -
directories-jvm
contains the perfect platform default logic that I'll reuse in this solution, to get a something more accurate
a
This library spawns process: https://codeberg.org/dirs/directories-jvm/src/branch/main/src/main/java/dev/dirs/impl/Linux.java#L48 Which might not be always ideal, especially in sandboxed environments (e.g., Apple macOS, Linux Flatpak/Snap, msix). Also, it's usually slower and more resource expensive, I would prefer other solutions that uses the native platform API. For example, in Flutter—specifically on Windows—it uses the Win32 API directly. See also: Linux implementation and macOS. This is maintained by Flutter/Google and I never experienced any issues with it, it works perfectly on all cases, including Flatpak and also WSL. `For example, in
https://klibs.io/project/psuzn/multiplatform-paths
https://github.com/psuzn/multiplatform-paths/blob/main/multiplatform-paths/src/des[…]/kotlin/me/sujanpoudel/utils/paths/directories.desktopCommon.kt I mean this solution works but I still prefer to avoid it, it's not a good practice to hardcode these paths as I mentioned earlier. This is just something to keep in mind, even if you don't plan on using better solutions.
For example, in Flutter—specifically on Windows—it uses the Win32 API directly.
See also: Linux implementation and macOS. This is maintained by Flutter/Google and I never experienced any issues with it, it works perfectly on all cases, including Flatpak and also WSL.
BTW, thanks to KMP, it's possible to port path_provider from the Flutter world to Kotlin in even easier way, this is a great opportunity for whoever want to create their first KMP library that solves common issues.
l
Wow, this is way, way more complicated than I expected! I wonder how IntelliJ IDEA is doing it, and why there's no standard JVM or Kotlin stdlib API for that blob thinking fast
a
I don't use Compose Desktop or JVM apps these days but I took a look at FileKit and I find it the most reliable solution (although I didn't used this library). It doesn't have a platform implementation on Windows or Linux but it's well implemented on macOS. The main issue is that it hardcodes some part of the path instead of using native platform API but generally it should work well for most cases. See the related code: https://github.com/vinceglb/FileKit/blob/main/filekit-core/src/jvmMain/kotlin/io/github/vinceglb/filekit/FileKit.jvm.kt#L37
l
It doesn't have a platform implementation on Windows or Linux but it's well implemented on macOS.
Aren't you saying the opposite of what the code you linked says?
a
> Aren't you saying the opposite of what the code you linked says? It has two implementations for macOS, native and JVM. On macOS/native it uses
NSFileManager
, on Linux and Windows and macOS/JVM, it uses environment variables of the OS. See also: https://github.com/vinceglb/FileKit/blob/main/filekit-core/src/macosMain/kotlin/io/github/vinceglb/filekit/FileKit.macos.kt#L29
l
I am mostly interested in the JVM implementation, which seems to support all 3 platforms. Compose Desktop only works on JVM, and can be hacked to run on macOS native only, anyway.
a
There are some methods to call native code using Kotlin/JVM target, whether it's Win32 or Apple foundation. I think it's probably better to use FileKit library and you shouldn't run into issues, but keep in mind, if you use Apple macOS sandbox mode, which is required to publish to Apple store, then this line might cause issues: https://github.com/vinceglb/FileKit/blob/main/filekit-core/src/jvmMain/kotlin/io/github/vinceglb/filekit/FileKit.jvm.kt#L40 As the path will be different in Apple sandbox mode.