Implements FileSaverLauncher to save Source with path

This commit is contained in:
hasinarak3@gmail.com 2026-05-08 16:27:17 +03:00
parent 76f99cadce
commit 184cb48c92
6 changed files with 110 additions and 16 deletions

View file

@ -85,22 +85,39 @@ class AndroidFileRepository(private val context: Context) : FileRepository {
file.readBytes()
}*/
override suspend fun saveLocalFile(filePath: String, data: ByteArray) = withContext(Dispatchers.IO) {
try {
if (filePath.startsWith("content://") || filePath.startsWith("file://")) {
val uri = Uri.parse(filePath)
context.contentResolver.openOutputStream(uri)?.use { outputStream ->
outputStream.write(data)
outputStream.flush()
} ?: throw Exception("Impossible d'ouvrir l'Uri pour écriture")
} else {
val file = if (filePath.contains("/")) {
File(filePath)
} else {
File(getPAppPublicFolder(), filePath)
}
try {
file.parentFile?.mkdirs()
file.writeBytes(data)
println("Fichier sauvegardé dans : ${file.absolutePath}")
}
if (file.extension.lowercase() == "pdf") {
openPdfFile(context = context, filePath = file.absolutePath)
withContext(Dispatchers.Main) {
if (filePath.endsWith(".pdf", ignoreCase = true)) {
openPdfFile(context = context, filePath = filePath)
} else {
Toast.makeText(
context.applicationContext,
"Sauvegarde réussie",
Toast.LENGTH_LONG
).show()
}
}
} catch (e: Exception) {
e.printStackTrace()
withContext(Dispatchers.Main) {
Toast.makeText(context, "Erreur de sauvegarde : ${e.message}", Toast.LENGTH_SHORT).show()
}
throw e
}
}
@ -121,8 +138,9 @@ class AndroidFileRepository(private val context: Context) : FileRepository {
return appDir
}
override fun pickSavePath(defaultName: String): String? {
return File(getPAppPublicFolder(), defaultName).absolutePath
override fun pickSavePath(defaultName: String, title: String): String? {
val file = File(context.filesDir, defaultName)
return file?.absolutePath
}
suspend fun openPdfFile(context: Context, filePath: String) {
val file = File(filePath)

View file

@ -0,0 +1,25 @@
package mg.dot.feufaro.ui
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
@Composable
actual fun rememberFileSaveLauncher(
onResult: (String?) -> Unit
): FileSaveLauncher {
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.CreateDocument("text/plain")
) { uri ->
onResult(uri?.toString())
}
return remember {
object : FileSaveLauncher {
override fun launch(defaultName: String) {
launcher.launch(defaultName)
}
}
}
}

View file

@ -20,7 +20,7 @@ interface FileRepository {
suspend fun getAppPublicFolder() : File
fun getFileName(shortName: String) : String
// suspend fun readFileBytes(filePath: String): ByteArray
fun pickSavePath(defaultName: String): String?
fun pickSavePath(defaultName: String, title: String): String?
}
// This is just a regular class that implements the common 'FileRepository' interface.

View file

@ -0,0 +1,12 @@
package mg.dot.feufaro.ui
import androidx.compose.runtime.Composable
interface FileSaveLauncher {
fun launch(defaultName: String)
}
@Composable
expect fun rememberFileSaveLauncher(
onResult: (String?) -> Unit
): FileSaveLauncher

View file

@ -72,8 +72,8 @@ class DesktopFileRepository : FileRepository { // IMPORTS AND IMPLEMENTS THE com
return "$userHome/$shortName"
}
override fun pickSavePath(defaultName: String): String? {
val dialog = FileDialog(null as Frame?, "Exporter en PDF", FileDialog.SAVE)
override fun pickSavePath(defaultName: String, title: String): String? {
val dialog = FileDialog(null as Frame?, title, FileDialog.SAVE)
dialog.directory = System.getProperty("user.home")
dialog.file = defaultName
dialog.isVisible = true

View file

@ -0,0 +1,39 @@
package mg.dot.feufaro.ui
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.awt.FileDialog
import java.awt.Frame
import java.io.File
@Composable
actual fun rememberFileSaveLauncher(
onResult: (String?) -> Unit
): FileSaveLauncher {
return remember {
object : FileSaveLauncher {
override fun launch(defaultName: String) {
CoroutineScope(Dispatchers.IO).launch {
val dialog = FileDialog(null as Frame?, "Sauvegarder la source", FileDialog.SAVE)
dialog.directory = System.getProperty("user.home")
dialog.file = defaultName
dialog.isVisible = true
val path = if (dialog.directory != null && dialog.file != null) {
File(dialog.directory, dialog.file).absolutePath
} else {
null
}
withContext(Dispatchers.Main) {
onResult(path)
}
}
}
}
}
}