FirebaseUI-Android icon indicating copy to clipboard operation
FirebaseUI-Android copied to clipboard

[Feature Request] Jetpack Compose Support for AuthUI

Open jossiwolf opened this issue 3 years ago • 17 comments

I haven't worked with other FirebaseUI libraries, but I reckon that it'll be a feature request for most libraries :) I'm thinking that AuthUI could be a good place to start. Now that Compose is in beta, it'd be super awesome to provide experimental APIs for that.

Something like this:

@Composable
fun AppLoginScreen() {
    val navController = rememberNavController()
    FirebaseLoginScreen(
        onAuthenticated = { navController.navigate(...) }
    ) { authenticationMethods ->
        Column {
            Image(painterResource(R.drawable.bg_onboarding), contentDescription = null)
            Spacer(Modifier.height(32.dp))
            Text(stringResource(R.string.onboarding_title), style = titleTextStyle)
            Text(stringResource(R.string.onboarding_subtitle))
            authenticationMethods.forEach { method ->
                LoginButton(stringResource(method.name)) { requestAuthentication(method) }
            }
        }
    }
}

// API

@Composable
fun FirebaseLoginScreen(
    onAuthenticated: (response: IdpResponse) -> Unit,
    content: @Composable FirebaseLoginScreenScope.(
        authenticationMethods: List<AuthUI.IdpConfig>,
    ) -> Unit,
) {
    val authenticationMethods = listOf<AuthUI.IdpConfig>()
    FirebaseLoginScreenScope().content(authenticationMethods)
}

class FirebaseLoginScreenScope {

    fun requestAuthentication(method: AuthUI.IdpConfig) {
        ...
    }
}

I'd be super happy to contribute here if that's something you'd accept contributions for.

jossiwolf avatar Feb 28 '21 13:02 jossiwolf

@jossiwolf this is super interesting! So would this primarily be a replacement for the "custom XML layout" feature we have now? Or would it be something deeper.

I have only recently started playing with Compose and I have not at all begun to consider how FirebaseUI should work with compose.

samtstern avatar Mar 01 '21 10:03 samtstern

It would be something deeper!

Let's consider two cases:

  1. Authentication with default layout
  2. Authentication with custom layout

Case 1 works with Jetpack Compose when using the Activity Result APIs (there's a registerActivityForResult composable introduced in androidx.activity:activity-ktx 1.3.0-alpha03: https://android-review.googlesource.com/c/platform/frameworks/support/+/1569321) which is pretty cool. I think it already works today when using ActivityResultContracts.StartActivityForResult as contract type, but a bit more manual work is required. Here's what it could look like using Compose once we added official support for the Activity Result APIs:

@Composable
fun LoginScreen(navController: NavController) {
    val firebaseLogin = registerForActivityResult(FirebaseAuthUIActivityResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            navController.navigate(NavDestinations.Home)
        }
    }
    // Run this every composition (which should be once in our case)
    SideEffect {
        firebaseLogin.launch(...)
    }
}

So custom layouts are the primary motivation for this, but given the prototype mentioned above we could provide a default value for the content:

@Composable
fun FirebaseLoginScreen(
    onAuthenticated: (response: IdpResponse) -> Unit,
    content: @Composable FirebaseLoginScreenScope.(
        authenticationMethods: List<AuthUI.IdpConfig>,
    ) -> Unit = { DefaultLoginScreenContent(...) },
) { ... }

@Composable
private fun FirebaseLoginScreenScope.DefaultLoginScreenContent(
    authenticationMethods: List<AuthUI.IdpConfig>
) {
   // Our default UI implementation
}

With that, the FirebaseLoginScreen composable could be used as the main entry point for auth from the AuthUI library for both custom and default layout. (I think that's pretty dope!)

@Composable
fun MyLoginScreen(navController: NavController) {
    FirebaseLoginScreen(onAuthenticated = { navController.navigate(...) })
}

Obvs this is all quite early stage and requires a bit of infra, but could be pretty cool to experiment with.

jossiwolf avatar Mar 01 '21 11:03 jossiwolf

@jossiwolf that all sounds super cool! Almost definitely an 8.0.0 feature because I think we'd be moving the codebase to Kotlin but I am not opposed to making that sort of breaking change later in the year, specifically once Jetpack Compose is GA

samtstern avatar Mar 02 '21 15:03 samtstern

Perfect! Sounds like syncing that would be great. What do you think of adding an AuthUI-Compose module with support for Compose?

jossiwolf avatar Mar 02 '21 17:03 jossiwolf

@jossiwolf no strong feelings either way on making a separate module. It will probably make our lives a bit harder because we'd need to change the visibility of some FirebaseUI internals to make them available across modules but it may be the right thing to do as far as separating dependencies.

samtstern avatar Mar 03 '21 12:03 samtstern

@jossiwolf Thank you so much for opening this!! I had already thought of a way to write firestore-compose and database-compose modules for FirebaseUI but the auth module was a big question mark in my mind, so seeing this makes me really happy!

I actually went ahead and wrote a library to show what I had in mind for firestore: https://github.com/rosariopfernandes/firebase-compose. In short, I created a custom State (named it CollectionState) that takes a Firestore Query as parameter and the state's value is a sealed class containing either the list or the error returned from that query in realtime. You can see its usage example here.

Would love to hear your thoughts on it

thatfiredev avatar Mar 04 '21 16:03 thatfiredev

@rosariopfernandes Whoa, that looks super super cool! I think this is incredibly useful and the API is nice. Once I get to play with infra here a bit, let's sync and see if we can join forces for this. I'm pretty sure we'll have to make some internal adjustments and open up some APIs as Sam mentioned so I'm not sure if I can work in a fork of your repo, but I'm sure we'll find something cool!

@samtstern Talking about separate module vs using the same module: Using a separate module would enable us to publish it as an "independent" artefact and not force the main module to AGP 7 before Compose is stable. I think it would be great to provide early access to the Compose version of this to get feedback, the best way is probably by making it easy to try out. I'll experiment starting with a separate module!

jossiwolf avatar Mar 04 '21 19:03 jossiwolf

@jossiwolf Instead of forking my repo, we could simply create a separate module here for firestore (if @samtstern agrees) and start doing experiments the same way you'll do with auth.

I'm not thinking about RTDB yet so that we can focus on the ones we're kickstarting with (auth and firestore), but once we get to it the approach should be similar to firestore.

thatfiredev avatar Mar 04 '21 19:03 thatfiredev

I think a separate module sounds like a good idea for this, if you can make it work without making the build too complex! I have a feeling you two can figure this out ... I don't know half of the gradle magic that you do.

It's probably easiest if you two use a shared fork of this project for your experiments but if that turns out to be a pain I could add you both as collaborators here and create a new experimental branch with no restrictions for you two to use as a playground. Let me know if you need that!

samtstern avatar Mar 05 '21 11:03 samtstern

@rosariopfernandes @jossiwolf it would be great if we could enumerate the breaking changes needed for this, so we can make decisions about 8.0. It's fine if we want to delay this work to be a feature release in 8.1 or 8.2 but if there are breaking build changes (Java 8, AGP 7, etc) we should try and list those now and make a yes/no decision.

samtstern avatar Jun 23 '21 09:06 samtstern

@samtstern We migrated to Java 8 and AGP 7 in jossiwolf/FirebaseUI-Android#1 I don't see any other breaking changes for developers using the library. Most of the build breakages that we had were lint errors and we had to supress some of those.

thatfiredev avatar Jun 25 '21 15:06 thatfiredev

@samtstern Sorry for the slow reply, got a lot to do! Yep, the breaking changes are Java 8 and AGP 7. Technically, Compose works with AGP 4.2 but it's not officially supported so I think it'd be good to stick to 7. I'm going to go back to the code this weekend - I suspect that we might need some API changes to support Compose in a nice way. I'll let you know beginning of next week!

jossiwolf avatar Jul 02 '21 07:07 jossiwolf

Hi, is there any update about this?

0xf0f17a avatar Jun 12 '22 05:06 0xf0f17a

2023 now, we are 100% compose now, and I'm wondering is anything is happening with this one?

bpappin avatar Mar 11 '23 04:03 bpappin

This would be super helpful in getting a standard Login template for 100% compose apps. Hoping this is in the works!

dhruvki94 avatar Apr 19 '23 07:04 dhruvki94

We need this!

bmilovanovic avatar Oct 17 '23 10:10 bmilovanovic

Hey Buddy @jossiwolf its now 2024 already in March. Are we ever gonna get Firebase Auth UI in Jet Pack Compose.

harismuntazir avatar Mar 25 '24 17:03 harismuntazir