Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package io.github.vinceglb.filekit.dialogs.compose

import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import io.github.vinceglb.filekit.PlatformFile
import io.github.vinceglb.filekit.dialogs.CustomTakePicture
import io.github.vinceglb.filekit.dialogs.FileKitCameraFacing
import io.github.vinceglb.filekit.dialogs.FileKitOpenCameraSettings
import io.github.vinceglb.filekit.dialogs.toAndroidUri
import io.github.vinceglb.filekit.path
import kotlin.let

@Composable
public actual fun rememberCameraPickerLauncher(
cameraFacing: FileKitCameraFacing,
openCameraSettings: FileKitOpenCameraSettings,
onResult: (PlatformFile?) -> Unit,
): PhotoResultLauncher {
val currentOnResult by rememberUpdatedState(onResult)
var currentPhotoPath by rememberSaveable { mutableStateOf<String?>(null) }

val takePictureLauncher = rememberLauncherForActivityResult(
CustomTakePicture(cameraFacing)
) { success ->
if (success) {
currentOnResult(currentPhotoPath?.let(::PlatformFile))
} else {
currentOnResult(null)
}
}

val authority = openCameraSettings.authority
val returnedLauncher = remember(authority) {
PhotoResultLauncher { _, destinationFile ->
val newPhotoPath = destinationFile.path
currentPhotoPath = newPhotoPath
val uri = destinationFile.toAndroidUri(authority)
takePictureLauncher.launch(uri)
}
}
return returnedLauncher
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package io.github.vinceglb.filekit.dialogs.compose

import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.rememberUpdatedState
import io.github.vinceglb.filekit.FileKit
import io.github.vinceglb.filekit.PlatformFile
import io.github.vinceglb.filekit.dialogs.FileKitCameraFacing
import io.github.vinceglb.filekit.dialogs.FileKitOpenCameraSettings
import io.github.vinceglb.filekit.dialogs.openCameraPicker
import kotlinx.coroutines.launch

@Composable
public actual fun rememberCameraPickerLauncher(
cameraFacing: FileKitCameraFacing,
openCameraSettings: FileKitOpenCameraSettings,
onResult: (PlatformFile?) -> Unit,
): PhotoResultLauncher {
// Init FileKit
InitFileKit()

// Coroutine
val coroutineScope = rememberCoroutineScope()

// Updated state
val currentOnResult by rememberUpdatedState(onResult)

// FileKit
val fileKit = remember { FileKit }

// FileKit launcher
// FIXME: Add openCameraSettings as a key to remember().
// To support this safely, openCameraSettings should be a data class (or override equals() and hashCode())
// and annotated with @Immutable.
// Note: On iOS, openCameraSettings is currently an empty class and not actually used,
// so it's safe to temporarily skip it as a key.
val returnedLauncher = remember(cameraFacing) {
PhotoResultLauncher { type, destinationFile ->
coroutineScope.launch {
val result = fileKit.openCameraPicker(
type = type,
cameraFacing = cameraFacing,
destinationFile = destinationFile,
openCameraSettings = openCameraSettings,
)
currentOnResult(result)
}
}
}

return returnedLauncher
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.github.vinceglb.filekit.dialogs.compose

import androidx.compose.runtime.Composable
import io.github.vinceglb.filekit.PlatformFile
import io.github.vinceglb.filekit.dialogs.FileKitCameraFacing
import io.github.vinceglb.filekit.dialogs.FileKitOpenCameraSettings

@Composable
public expect fun rememberCameraPickerLauncher(
cameraFacing: FileKitCameraFacing = FileKitCameraFacing.Back,
openCameraSettings: FileKitOpenCameraSettings = FileKitOpenCameraSettings.createDefault(),
onResult: (PlatformFile?) -> Unit,
): PhotoResultLauncher
Original file line number Diff line number Diff line change
@@ -1,53 +1,13 @@
package io.github.vinceglb.filekit.dialogs.compose

import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.rememberUpdatedState
import io.github.vinceglb.filekit.FileKit
import io.github.vinceglb.filekit.PlatformFile
import io.github.vinceglb.filekit.dialogs.FileKitOpenCameraSettings
import io.github.vinceglb.filekit.dialogs.FileKitShareSettings
import io.github.vinceglb.filekit.dialogs.openCameraPicker
import io.github.vinceglb.filekit.dialogs.shareFile
import kotlinx.coroutines.launch

@Composable
public fun rememberCameraPickerLauncher(
openCameraSettings: FileKitOpenCameraSettings = FileKitOpenCameraSettings.createDefault(),
onResult: (PlatformFile?) -> Unit,
): PhotoResultLauncher {
// Init FileKit
InitFileKit()

// Coroutine
val coroutineScope = rememberCoroutineScope()

// Updated state
val currentOnResult by rememberUpdatedState(onResult)

// FileKit
val fileKit = remember { FileKit }

// FileKit launcher
val returnedLauncher = remember {
PhotoResultLauncher { type, cameraFacing, destinationFile ->
coroutineScope.launch {
val result = fileKit.openCameraPicker(
type = type,
cameraFacing = cameraFacing,
destinationFile = destinationFile,
openCameraSettings = openCameraSettings,
)
currentOnResult(result)
}
}
}

return returnedLauncher
}

@Composable
public fun rememberShareFileLauncher(
shareSettings: FileKitShareSettings = FileKitShareSettings.createDefault(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package io.github.vinceglb.filekit.dialogs.compose
import io.github.vinceglb.filekit.FileKit
import io.github.vinceglb.filekit.PlatformFile
import io.github.vinceglb.filekit.cacheDir
import io.github.vinceglb.filekit.dialogs.FileKitCameraFacing
import io.github.vinceglb.filekit.dialogs.FileKitCameraType
import io.github.vinceglb.filekit.div
import kotlin.uuid.ExperimentalUuidApi
Expand All @@ -12,17 +11,15 @@ import kotlin.uuid.Uuid
public class PhotoResultLauncher(
private val onLaunch: (
type: FileKitCameraType,
cameraFacing: FileKitCameraFacing,
destinationFile: PlatformFile,
) -> Unit,
) {
@OptIn(ExperimentalUuidApi::class)
public fun launch(
type: FileKitCameraType = FileKitCameraType.Photo,
cameraFacing: FileKitCameraFacing = FileKitCameraFacing.Back,
destinationFile: PlatformFile = FileKit.cacheDir / "${Uuid.random()}.jpg",
destinationFile: PlatformFile = FileKit.cacheDir / "${Uuid.random()}.jpg"
) {
onLaunch(type, cameraFacing, destinationFile)
onLaunch(type, destinationFile)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Share
Expand All @@ -24,6 +23,7 @@ import io.github.vinceglb.filekit.filesDir
actual fun TakePhoto(onPhotoTaken: (PlatformFile?) -> Unit) {
val context = LocalContext.current
val takePhotoLauncher = rememberCameraPickerLauncher(
cameraFacing = FileKitCameraFacing.Back,
openCameraSettings = FileKitOpenCameraSettings(
authority = "${context.packageName}.fileprovider"
)
Expand All @@ -34,10 +34,7 @@ actual fun TakePhoto(onPhotoTaken: (PlatformFile?) -> Unit) {
Button(
onClick = {
val destinationFile = FileKit.filesDir / "photo_${System.currentTimeMillis()}.jpg"
takePhotoLauncher.launch(
destinationFile = destinationFile,
cameraFacing = FileKitCameraFacing.Front
)
takePhotoLauncher.launch(destinationFile = destinationFile)
}
) {
Text("Take photo")
Expand Down
12 changes: 5 additions & 7 deletions samples/sample-compose/composeApp/src/iosMain/kotlin/App.ios.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,15 @@ import kotlin.time.ExperimentalTime
@OptIn(ExperimentalTime::class)
@Composable
actual fun TakePhoto(onPhotoTaken: (PlatformFile?) -> Unit) {
val takePhotoLauncher = rememberCameraPickerLauncher {
onPhotoTaken(it)
}
val takePhotoLauncher = rememberCameraPickerLauncher(
cameraFacing = FileKitCameraFacing.Back,
onResult = onPhotoTaken,
)

Button(
onClick = {
val destinationFile = FileKit.filesDir / "photo_${Clock.System.now().toEpochMilliseconds()}.jpg"
takePhotoLauncher.launch(
cameraFacing = FileKitCameraFacing.Front,
destinationFile = destinationFile,
)
takePhotoLauncher.launch(destinationFile = destinationFile)
}
) {
Text("Take photo")
Expand Down