vinceglb / FileKit

Pick and save Files, Medias and Folder for Kotlin Multiplatform / KMP and Compose Multiplatform / CMP
https://vinceglb.github.io/FileKit/
MIT License
465 stars 16 forks source link

Fix crashes on Android inside Compose dialogs #68

Closed Snd-R closed 1 month ago

Snd-R commented 1 month ago

Fixes crashes on Android when rememberFilePickerLauncher() is called inside androidx.compose.ui.window.Dialog

When dialog is created Context is wrapped in ContextThemeWrapper and when attempt is made to cast it to ComponentActivity it crashes with java.lang.ClassCastException

Use LocalActivityResultRegistryOwner as a fix. It either stores a composition local instance of ActivityResultRegistryOwner or unwraps compositon local context until it finds activity that implements ActivityResultRegistryOwner (most oftent it is ComponentActivity)

Example to reproduce the crash:

@Composable
fun App() {
    MaterialTheme {
        var showDialog by remember { mutableStateOf(false) }
        Button(onClick = { showDialog = true }) {
            Text("Show dialog")
        }
        if (showDialog) {
            Dialog(onDismissRequest = { showDialog = false }) {

                var files: Set<PlatformFile> by remember { mutableStateOf(emptySet()) }
                val singleFilePicker = rememberFilePickerLauncher(
                    type = PickerType.Image,
                    title = "Single file picker",
                    onResult = { file -> file?.let { files += it } }
                )
                Button(onClick = { singleFilePicker.launch() }) {
                    Text("Single file picker")
                }
            }
        }
    }
}