FirebaseUI-Android
FirebaseUI-Android copied to clipboard
[Feature Request] Jetpack Compose Support for AuthUI
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 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.
It would be something deeper!
Let's consider two cases:
- Authentication with default layout
- 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 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
Perfect! Sounds like syncing that would be great. What do you think of adding an AuthUI-Compose module with support for Compose?
@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.
@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
@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 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.
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!
@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 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.
@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!
Hi, is there any update about this?
2023 now, we are 100% compose now, and I'm wondering is anything is happening with this one?
This would be super helpful in getting a standard Login template for 100% compose apps. Hoping this is in the works!
We need this!
Hey Buddy @jossiwolf its now 2024 already in March. Are we ever gonna get Firebase Auth UI in Jet Pack Compose.