androidfirebasekotlinfirebase-authenticationandroid-jetpack-compose

How can I initiate a Jetpack Compose AlertDialog from within a onClick (from onClickListener) or onComplete (from onCompleteListener) function


I am working to convert an existing Kotlin application to Kotlin MultiPlatform and Jetpack Compose.

As part of a login activity, I sign in the user and direct logic from there. Part of the sign-in process uses FirebaseAuth as follows:

private fun signInUser(mEmail: String?, mPassword: String?) {
        val c = Calendar.getInstance()
        val df = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS a z")
        currentDateAndTime1 = df.format(c.time)
        Log.i(" ", "Login: signInUser started at $currentDateAndTime1")
        Log.i(" ", "Login signInUser: user= $user")
        Log.i(" ", "Login signInUser: email= $mEmail password= $mPassword")
        mAuth = FirebaseAuth.getInstance()

        mAuth!!.signInWithEmailAndPassword((mEmail)!!, (mPassword)!!)
            .addOnCompleteListener(object : OnCompleteListener<AuthResult?> {
                @OptIn(ExperimentalMaterial3Api::class)
                @Composable
                override fun onComplete(task: Task<AuthResult?>) {
                    if ((task.isSuccessful) || (user != null)) {
                    ........  additional logic 
                    ComposeAlert(onDismissRequest = {openAlertDialog.value = false },
                                onConfirmation = {
                                openAlertDialog.value = false},
                                dialogTitle = "Remove Family Administrator",
                                dialogText = "Please confirm you want to be removed as a family administrator on this device",
                                icon = Icons.Default.Info)
                    }  
                 }
              } 

on the "override fun onComplete" statement, I get an error that indicates

"@Composable annotation mismatch with overridden function @Optin @Composable public open fun onComplete(task: Task<AuthResult?>: Unit defined in
com.grgmobilesolutions.mycomposeapplication.android.Login.signInUser.'<no name provided>, 
public abstract fun onComplete @NonNull p() Task<AuthResult?>: Unit defined in 
com.google.android.gms.tasks.onCompleteListener" 

I get the same basic error on an "onClick" listener function.

My assumption is that the signature for the addOnCompleteListener or onComplete methods needs to be changed, but I cannot find anything that would indicate how. The same would be true for the addOnClickLIstener and onClick methods (activity composable buttons outside of the ComposeAlert composable).

The following is the "ComposeAlert" composable.

 @OptIn(ExperimentalMaterial3Api::class)
    @Composable
    fun ComposeAlert(
        onDismissRequest: () -> Unit,
        onConfirmation: () -> Unit,
        dialogTitle: String,
        dialogText: String,
        icon: ImageVector,
    ) {
        AlertDialog(
            icon = {
                Icon(icon, contentDescription = "Example Icon")
            },
            title = {
                Text(text = dialogTitle)
            },
            text = {
                Text(text = dialogText)
            },
            onDismissRequest = {
                onDismissRequest()
            },
            confirmButton = {
                TextButton(
                    onClick = {
                        onConfirmation()
                    }
                ) {
                    Text("OK")
                }
            },
            dismissButton = {
                TextButton(
                    onClick = {
                        onDismissRequest()
                    }
                ) {
                    Text("Cancel")
                }
            }
        )
    }

Solution

  • You are getting the following error:

    @Composable annotation mismatch with overridden function @Optin @Composable public open fun onComplete(task: Task<AuthResult?>: Unit

    Because you are adding the @Composable annotation in front of a function that overrides a function that is not Composable. Please note that the onComplete(Task task) function is a regular function that exists inside the OnCompleteListener interface. See, there is no @Composable annotation?

    I get the same basic error on an "onClick" listener function.

    That's the exact same thing as above. The onClick(v: View!) function is a regular function that exists inside the View.OnClickListener interface. It's not a Composable function.

    So there is no way you can add the @Composable annotation in front of any of the functions above.

    My assumption is that the signature for the addOnCompleteListener or onComplete methods needs to be changed.

    There is no way you can change the declaration of the onComplete nor of the onClick.

    If you want to call a composable function when the operation of signing in the user with email and password is complete, then you have to define a MutableState variable:

    var composeAlert by remember { mutableStateOf(false) }
    

    Then inside the callback, you have to change the value to true:

    mAuth!!.signInWithEmailAndPassword(mEmail!!, mPassword!!).addOnCompleteListener(object : OnCompleteListener<AuthResult?> {
            override fun onComplete(task: Task<AuthResult?>) {
                if ((task.isSuccessful) || (user != null)) {
                    composeAlert = true
                }
            }
        }
    

    And then display the content of your ComposeAlert composable only if the value of composeAlert is true:

    if(composeAlert) {
        ComposeAlert(/* ... */)
    }