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
Expand Up @@ -50,6 +50,9 @@ import com.firebase.ui.auth.configuration.AuthUITransitions
import com.firebase.ui.auth.configuration.PasswordRule
import com.firebase.ui.auth.configuration.authUIConfiguration
import com.firebase.ui.auth.configuration.auth_provider.AuthProvider
import com.firebase.ui.auth.configuration.string_provider.AuthUIStringProvider
import com.firebase.ui.auth.configuration.string_provider.AuthUIStringProviderSample.CustomAuthUIStringProvider
import com.firebase.ui.auth.configuration.string_provider.DefaultAuthUIStringProvider
import com.firebase.ui.auth.configuration.theme.AuthUIAsset
import com.firebase.ui.auth.configuration.theme.AuthUITheme
import com.firebase.ui.auth.ui.screens.AuthSuccessUiContext
Expand All @@ -71,6 +74,17 @@ class HighLevelApiDemoActivity : ComponentActivity() {
providerButtonShape = ShapeDefaults.ExtraLarge
)

class CustomAuthUIStringProvider(
private val defaultProvider: AuthUIStringProvider
) : AuthUIStringProvider by defaultProvider {

override val loadingSigningInAnonymously: String
get() = "Overriding signing in anonymously loading message..."
}

val customStringProvider =
CustomAuthUIStringProvider(DefaultAuthUIStringProvider(applicationContext))

val configuration = authUIConfiguration {
context = applicationContext
theme = customTheme
Expand All @@ -79,6 +93,7 @@ class HighLevelApiDemoActivity : ComponentActivity() {
privacyPolicyUrl = "https://policies.google.com/privacy"
isAnonymousUpgradeEnabled = false
isMfaEnabled = false
stringProvider = customStringProvider
transitions = AuthUITransitions(
enterTransition = { slideInHorizontally { it } },
exitTransition = { slideOutHorizontally { -it } },
Expand Down Expand Up @@ -197,7 +212,10 @@ class HighLevelApiDemoActivity : ComponentActivity() {
authUI = authUI,
emailLink = emailLink,
onSignInSuccess = { result ->
Log.d("HighLevelApiDemoActivity", "Authentication success: ${result.user?.uid}")
Log.d(
"HighLevelApiDemoActivity",
"Authentication success: ${result.user?.uid}"
)
},
onSignInFailure = { exception: AuthException ->
Log.e("HighLevelApiDemoActivity", "Authentication failed", exception)
Expand Down Expand Up @@ -327,7 +345,8 @@ private fun AppAuthenticatedContent(
}

is AuthState.RequiresEmailVerification -> {
val email = uiContext.authUI.getCurrentUser().getDisplayEmail(stringProvider.emailProvider)
val email =
uiContext.authUI.getCurrentUser().getDisplayEmail(stringProvider.emailProvider)
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
Expand Down Expand Up @@ -489,7 +508,8 @@ private fun ChangePasswordDialog(
var updateError by remember { mutableStateOf<String?>(null) }

val emailProvider = remember(configuration) {
configuration.providers.filterIsInstance<com.firebase.ui.auth.configuration.auth_provider.AuthProvider.Email>().firstOrNull()
configuration.providers.filterIsInstance<com.firebase.ui.auth.configuration.auth_provider.AuthProvider.Email>()
.firstOrNull()
}
val passwordValidator = remember(emailProvider, stringProvider) {
com.firebase.ui.auth.configuration.validators.PasswordValidator(
Expand Down
4 changes: 2 additions & 2 deletions auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ class FirebaseAuthUI private constructor(
suspend fun signOut(context: Context) {
try {
// Update state to loading
updateAuthState(AuthState.Loading("Signing out..."))
updateAuthState(AuthState.Loading(context.getString(R.string.fui_loading_signing_out)))

// Sign out from Firebase Auth
auth.signOut()
Expand Down Expand Up @@ -555,7 +555,7 @@ class FirebaseAuthUI private constructor(
)

// Update state to loading
updateAuthState(AuthState.Loading("Deleting account..."))
updateAuthState(AuthState.Loading(context.getString(R.string.fui_loading_deleting_account)))

// Delete the user account
currentUser.delete().await()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import com.firebase.ui.auth.AuthException
import com.firebase.ui.auth.AuthState
import com.firebase.ui.auth.FirebaseAuthUI
import com.firebase.ui.auth.configuration.AuthUIConfiguration
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await
Expand All @@ -19,14 +20,14 @@ import kotlinx.coroutines.tasks.await
* @see createOrLinkUserWithEmailAndPassword for upgrading anonymous accounts
*/
@Composable
internal fun FirebaseAuthUI.rememberAnonymousSignInHandler(): () -> Unit {
internal fun FirebaseAuthUI.rememberAnonymousSignInHandler(config: AuthUIConfiguration): () -> Unit {
val context = androidx.compose.ui.platform.LocalContext.current
val coroutineScope = rememberCoroutineScope()
return remember(this) {
{
coroutineScope.launch {
try {
signInAnonymously()
signInAnonymously(config)
} catch (e: AuthException) {
// Already an AuthException, don't re-wrap it
updateAuthState(AuthState.Error(e))
Expand Down Expand Up @@ -107,9 +108,9 @@ internal fun FirebaseAuthUI.rememberAnonymousSignInHandler(): () -> Unit {
* @see createOrLinkUserWithEmailAndPassword for email/password upgrade
* @see signInWithPhoneAuthCredential for phone authentication upgrade
*/
internal suspend fun FirebaseAuthUI.signInAnonymously() {
internal suspend fun FirebaseAuthUI.signInAnonymously(config: AuthUIConfiguration) {
try {
updateAuthState(AuthState.Loading("Signing in anonymously..."))
updateAuthState(AuthState.Loading(config.stringProvider.loadingSigningInAnonymously))
val result = auth.signInAnonymously().await()
updateAuthStateWithResult(result, defaultIsNewUser = true)
} catch (e: CancellationException) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ internal suspend fun FirebaseAuthUI.createOrLinkUserWithEmailAndPassword(
}
}

updateAuthState(AuthState.Loading("Creating user..."))
updateAuthState(AuthState.Loading(config.stringProvider.loadingCreatingUser))
val result = if (shouldLinkCredential) {
auth.currentUser?.linkWithCredential(requireNotNull(pendingCredential))?.await()
} else {
Expand Down Expand Up @@ -344,7 +344,7 @@ internal suspend fun FirebaseAuthUI.signInWithEmailAndPassword(
skipCredentialSave: Boolean = false,
): AuthResult? {
try {
updateAuthState(AuthState.Loading("Signing in..."))
updateAuthState(AuthState.Loading(config.stringProvider.loadingSigningIn))
// In reauth mode build a credential and go through signInAndLinkWithCredential so
// signInOrReauth routes to FirebaseUser.reauthenticate() instead of signInWithCredential().
if (config.isReauthenticationMode) {
Expand Down Expand Up @@ -645,7 +645,7 @@ internal suspend fun FirebaseAuthUI.signInAndLinkWithCredential(
photoUrl: Uri? = null,
): AuthResult? {
try {
updateAuthState(AuthState.Loading("Signing in user..."))
updateAuthState(AuthState.Loading(config.stringProvider.loadingLinkingCredential))
val result = if (canUpgradeAnonymous(config, auth) || canLinkCredential(config, auth)) {
auth.currentUser?.linkWithCredential(credential)?.await()
} else {
Expand Down Expand Up @@ -830,7 +830,7 @@ internal suspend fun FirebaseAuthUI.sendSignInLinkToEmail(
persistenceManager: PersistenceManager = EmailLinkPersistenceManager.default,
) {
try {
updateAuthState(AuthState.Loading("Sending sign in email link..."))
updateAuthState(AuthState.Loading(config.stringProvider.loadingSendingEmailLink))

// Get anonymousUserId if can upgrade anonymously else default to empty string.
// NOTE: check for empty string instead of null to validate anonymous user ID matches
Expand Down Expand Up @@ -988,7 +988,7 @@ internal suspend fun FirebaseAuthUI.signInWithEmailLink(
persistenceManager: PersistenceManager = EmailLinkPersistenceManager.default,
): AuthResult? {
try {
updateAuthState(AuthState.Loading("Signing in with email link..."))
updateAuthState(AuthState.Loading(config.stringProvider.loadingSigningInWithEmailLink))

// Validate link format
if (!auth.isSignInWithEmailLink(emailLink)) {
Expand Down Expand Up @@ -1256,10 +1256,11 @@ private suspend fun FirebaseAuthUI.handleEmailLinkCredentialLinkingFlow(
*/
internal suspend fun FirebaseAuthUI.sendPasswordResetEmail(
email: String,
config: AuthUIConfiguration,
actionCodeSettings: ActionCodeSettings? = null,
) {
try {
updateAuthState(AuthState.Loading("Sending password reset email..."))
updateAuthState(AuthState.Loading(config.stringProvider.loadingSendingPasswordResetEmail))
auth.sendPasswordResetEmail(email, actionCodeSettings).await()
updateAuthState(AuthState.PasswordResetLinkSent())
} catch (e: CancellationException) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ internal fun FirebaseAuthUI.rememberSignInWithFacebookLauncher(

return {
updateAuthState(
AuthState.Loading("Signing in with facebook...")
AuthState.Loading(config.stringProvider.loadingSigningInWithFacebook)
)
try {
(testLoginManagerProvider ?: loginManagerProvider).logOut()
Expand Down Expand Up @@ -155,7 +155,7 @@ internal suspend fun FirebaseAuthUI.signInWithFacebook(
) {
try {
updateAuthState(
AuthState.Loading("Signing in with facebook...")
AuthState.Loading(config.stringProvider.loadingSigningInWithFacebook)
)
val profileData = provider.fetchFacebookProfile(accessToken)
val credential = credentialProvider.getCredential(accessToken.token)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ internal suspend fun FirebaseAuthUI.signInWithGoogle(
) {
var idTokenFromResult: String? = null
try {
updateAuthState(AuthState.Loading("Signing in with google..."))
updateAuthState(AuthState.Loading(config.stringProvider.loadingSigningInWithGoogle))

// Request OAuth scopes if specified (before sign-in)
if (provider.scopes.isNotEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ internal suspend fun FirebaseAuthUI.signInWithProvider(
provider: AuthProvider.OAuth,
) {
try {
updateAuthState(AuthState.Loading("Signing in with ${provider.providerName}..."))
updateAuthState(AuthState.Loading(config.stringProvider.loadingSigningInWithProvider(provider.providerName)))

// Build OAuth provider with scopes and custom parameters
val oauthProvider = OAuthProvider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,13 @@ internal suspend fun FirebaseAuthUI.verifyPhoneNumber(
provider: AuthProvider.Phone,
activity: Activity?,
phoneNumber: String,
config: AuthUIConfiguration,
multiFactorSession: MultiFactorSession? = null,
forceResendingToken: PhoneAuthProvider.ForceResendingToken? = null,
verifier: AuthProvider.Phone.Verifier = AuthProvider.Phone.DefaultVerifier(),
) {
try {
updateAuthState(AuthState.Loading("Verifying phone number..."))
updateAuthState(AuthState.Loading(config.stringProvider.loadingVerifyingPhoneNumber))
val result = provider.verifyPhoneNumberAwait(
auth = auth,
activity = activity,
Expand Down Expand Up @@ -206,7 +207,7 @@ internal suspend fun FirebaseAuthUI.submitVerificationCode(
credentialProvider: AuthProvider.Phone.CredentialProvider = AuthProvider.Phone.DefaultCredentialProvider(),
): AuthResult? {
try {
updateAuthState(AuthState.Loading("Submitting verification code..."))
updateAuthState(AuthState.Loading(config.stringProvider.loadingSubmittingVerificationCode))
val credential = credentialProvider.getCredential(verificationId, code)
return signInWithPhoneAuthCredential(
context = context,
Expand Down Expand Up @@ -297,7 +298,7 @@ internal suspend fun FirebaseAuthUI.signInWithPhoneAuthCredential(
credential: PhoneAuthCredential,
): AuthResult? {
try {
updateAuthState(AuthState.Loading("Signing in with phone..."))
updateAuthState(AuthState.Loading(config.stringProvider.loadingSigningInWithPhone))
val result = signInAndLinkWithCredential(
config = config,
credential = credential,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,51 @@ interface AuthUIStringProvider {
/** Loading text displayed during initialization or processing states */
val initializing: String

/** Progress dialog message shown while signing in anonymously */
val loadingSigningInAnonymously: String

/** Progress dialog message shown while signing in with Google */
val loadingSigningInWithGoogle: String

/** Progress dialog message shown while signing in with Facebook */
val loadingSigningInWithFacebook: String

/** Progress dialog message shown while signing in with a named OAuth provider. [providerName] is the display name of the provider. */
fun loadingSigningInWithProvider(providerName: String): String

/** Progress dialog message shown while verifying a phone number */
val loadingVerifyingPhoneNumber: String

/** Progress dialog message shown while submitting an SMS verification code */
val loadingSubmittingVerificationCode: String

/** Progress dialog message shown while completing phone number sign-in */
val loadingSigningInWithPhone: String

/** Progress dialog message shown while creating a new user account */
val loadingCreatingUser: String

/** Progress dialog message shown while signing in with email and password */
val loadingSigningIn: String

/** Progress dialog message shown while linking a credential to the current account */
val loadingLinkingCredential: String

/** Progress dialog message shown while sending the sign-in email link */
val loadingSendingEmailLink: String

/** Progress dialog message shown while completing an email link sign-in */
val loadingSigningInWithEmailLink: String

/** Progress dialog message shown while sending the password reset email */
val loadingSendingPasswordResetEmail: String

/** Progress dialog message shown while signing the user out */
val loadingSigningOut: String

/** Progress dialog message shown while deleting the user's account */
val loadingDeletingAccount: String

/** Text for Google Provider */
val googleProvider: String

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,41 @@ class DefaultAuthUIStringProvider(
* Common Strings
*/
override val initializing: String
get() = "Initializing"
get() = localizedContext.getString(R.string.fui_initializing)

/**
* Loading State Strings
*/
override val loadingSigningInAnonymously: String
get() = localizedContext.getString(R.string.fui_loading_signing_in_anonymously)
override val loadingSigningInWithGoogle: String
get() = localizedContext.getString(R.string.fui_loading_signing_in_with_google)
override val loadingSigningInWithFacebook: String
get() = localizedContext.getString(R.string.fui_loading_signing_in_with_facebook)
override fun loadingSigningInWithProvider(providerName: String): String =
localizedContext.getString(R.string.fui_loading_signing_in_with_provider, providerName)
override val loadingVerifyingPhoneNumber: String
get() = localizedContext.getString(R.string.fui_loading_verifying_phone_number)
override val loadingSubmittingVerificationCode: String
get() = localizedContext.getString(R.string.fui_loading_submitting_verification_code)
override val loadingSigningInWithPhone: String
get() = localizedContext.getString(R.string.fui_loading_signing_in_with_phone)
override val loadingCreatingUser: String
get() = localizedContext.getString(R.string.fui_loading_creating_user)
override val loadingSigningIn: String
get() = localizedContext.getString(R.string.fui_loading_signing_in)
override val loadingLinkingCredential: String
get() = localizedContext.getString(R.string.fui_loading_linking_credential)
override val loadingSendingEmailLink: String
get() = localizedContext.getString(R.string.fui_loading_sending_email_link)
override val loadingSigningInWithEmailLink: String
get() = localizedContext.getString(R.string.fui_loading_signing_in_with_email_link)
override val loadingSendingPasswordResetEmail: String
get() = localizedContext.getString(R.string.fui_loading_sending_password_reset)
override val loadingSigningOut: String
get() = localizedContext.getString(R.string.fui_loading_signing_out)
override val loadingDeletingAccount: String
get() = localizedContext.getString(R.string.fui_loading_deleting_account)

/**
* Auth Provider strings
Expand Down Expand Up @@ -278,7 +312,7 @@ class DefaultAuthUIStringProvider(
* Multi-Factor Authentication Strings
*/
override val enterTOTPCode: String
get() = "Enter TOTP Code"
get() = localizedContext.getString(R.string.fui_enter_totp_code)

/**
* Provider Picker Strings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -986,7 +986,7 @@ private fun FirebaseAuthUI.rememberOnProviderSelected(
val twitterProvider = config.providers.filterIsInstance<AuthProvider.Twitter>().firstOrNull()
val genericOAuthProviders = config.providers.filterIsInstance<AuthProvider.GenericOAuth>()

val onSignInAnonymously = anonymousProvider?.let { rememberAnonymousSignInHandler() }
val onSignInAnonymously = anonymousProvider?.let { rememberAnonymousSignInHandler(config) }
val onSignInWithGoogle = googleProvider?.let { rememberGoogleSignInHandler(context, config, it) }
val onSignInWithFacebook = facebookProvider?.let { rememberSignInWithFacebookLauncher(context, config, it) }
val onSignInWithApple = appleProvider?.let { rememberOAuthSignInHandler(context, activity, config, it) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ fun EmailAuthScreen(
try {
authUI.sendPasswordResetEmail(
email = emailTextValue.value,
config = configuration,
actionCodeSettings = configuration.passwordResetActionCodeSettings,
)
} catch (e: Exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ fun PhoneAuthScreen(
provider = provider,
activity = activity,
phoneNumber = fullPhoneNumber,
config = configuration,
)
} catch (e: Exception) {
// Error will be handled by authState flow
Expand Down Expand Up @@ -319,6 +320,7 @@ fun PhoneAuthScreen(
activity = activity,
provider = provider,
phoneNumber = fullPhoneNumber,
config = configuration,
forceResendingToken = forceResendingToken.value,
)
resendTimerSeconds.intValue = provider.timeout.toInt() // Restart timer
Expand Down
Loading
Loading