Skip to content

Commit 4981c35

Browse files
authored
Merge pull request #109 from MohamedRejeb/0.5.x
Add FileSaverLauncher to desktop
2 parents de4e950 + 8c652f2 commit 4981c35

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.mohamedrejeb.calf.picker
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.compose.runtime.getValue
5+
import androidx.compose.runtime.rememberCoroutineScope
6+
import androidx.compose.runtime.rememberUpdatedState
7+
import com.mohamedrejeb.calf.io.KmpFile
8+
import com.mohamedrejeb.calf.picker.platform.awt.AwtFileSaver
9+
import kotlinx.coroutines.launch
10+
11+
@Composable
12+
fun rememberFileSaverLauncher(
13+
bytes: ByteArray?,
14+
baseName: String,
15+
extension: String,
16+
initialDirectory: String?,
17+
onResult: (KmpFile?) -> Unit,
18+
): FileSaverLauncher {
19+
val scope = rememberCoroutineScope()
20+
21+
val currentBytes by rememberUpdatedState(bytes)
22+
val currentBaseName by rememberUpdatedState(baseName)
23+
val currentExtension by rememberUpdatedState(extension)
24+
val currentInitialDirectory by rememberUpdatedState(initialDirectory)
25+
val currentOnResult by rememberUpdatedState(onResult)
26+
27+
return FileSaverLauncher(
28+
onLaunch = {
29+
scope.launch {
30+
val file = AwtFileSaver.saveFile(
31+
bytes = currentBytes,
32+
baseName = currentBaseName,
33+
extension = currentExtension,
34+
initialDirectory = currentInitialDirectory,
35+
parentWindow = null,
36+
)
37+
38+
currentOnResult(file)
39+
}
40+
}
41+
)
42+
}
43+
44+
class FileSaverLauncher(
45+
private val onLaunch: () -> Unit,
46+
) {
47+
fun launch() {
48+
onLaunch()
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.mohamedrejeb.calf.picker.platform.awt
2+
3+
import com.mohamedrejeb.calf.io.KmpFile
4+
import kotlinx.coroutines.suspendCancellableCoroutine
5+
import java.awt.Dialog
6+
import java.awt.FileDialog
7+
import java.awt.Frame
8+
import java.awt.Window
9+
import java.io.File
10+
import kotlin.coroutines.resume
11+
12+
internal object AwtFileSaver {
13+
suspend fun saveFile(
14+
bytes: ByteArray?,
15+
baseName: String,
16+
extension: String,
17+
initialDirectory: String?,
18+
parentWindow: Window?,
19+
): KmpFile? = suspendCancellableCoroutine { continuation ->
20+
fun handleResult(value: Boolean, files: Array<File>?) {
21+
if (value) {
22+
val file = files?.firstOrNull()?.let { file ->
23+
// Write bytes to file, or create a new file
24+
bytes?.let { file.writeBytes(bytes) } ?: file.createNewFile()
25+
KmpFile(file)
26+
}
27+
continuation.resume(file)
28+
}
29+
}
30+
31+
// Handle parentWindow: Dialog, Frame, or null
32+
val dialog = when (parentWindow) {
33+
is Dialog -> object : FileDialog(parentWindow, "Save dialog", SAVE) {
34+
override fun setVisible(value: Boolean) {
35+
super.setVisible(value)
36+
handleResult(value, files)
37+
}
38+
}
39+
40+
else -> object : FileDialog(parentWindow as? Frame, "Save dialog", SAVE) {
41+
override fun setVisible(value: Boolean) {
42+
super.setVisible(value)
43+
handleResult(value, files)
44+
}
45+
}
46+
}
47+
48+
// Set initial directory
49+
dialog.directory = initialDirectory
50+
51+
// Set file name
52+
dialog.file = "$baseName.$extension"
53+
54+
// Show the dialog
55+
dialog.isVisible = true
56+
57+
// Dispose the dialog when the continuation is cancelled
58+
continuation.invokeOnCancellation { dialog.dispose() }
59+
}
60+
}

0 commit comments

Comments
 (0)