Skip to content
Merged
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 @@ -316,12 +316,12 @@ class FirebaseAuthUI private constructor(

/**
* Updates the internal authentication state.
* This method is intended for internal use by authentication operations.
* This method can be used to manually trigger state updates when the Firebase Auth state
* listener doesn't automatically detect changes (e.g., after reloading user properties).
*
* @param state The new [AuthState] to emit
* @suppress This is an internal API
*/
internal fun updateAuthState(state: AuthState) {
fun updateAuthState(state: AuthState) {
_authStateFlow.value = state
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@ abstract class AuthProvider(open val providerId: String, open val providerName:
* A list of custom password validation rules.
*/
val passwordValidationRules: List<PasswordRule>,

/**
* Optional custom button label to differentiate between multiple email providers.
* If null, uses the default string from stringProvider. Defaults to null.
*/
val buttonLabel: String? = null,
) : AuthProvider(providerId = Provider.EMAIL.id, providerName = Provider.EMAIL.providerName) {
companion object {
const val SESSION_ID_LENGTH = 10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ internal fun resolveProviderLabel(
context: android.content.Context
): String = when (provider) {
is AuthProvider.GenericOAuth -> provider.buttonLabel
is AuthProvider.Email -> {
// Use custom button label if provided, otherwise use default
provider.buttonLabel ?: stringProvider.signInWithEmail
}
is AuthProvider.Apple -> {
// Use Apple-specific locale if provided, otherwise use default stringProvider
if (provider.locale != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,32 @@ fun FirebaseAuthScreen(
onReloadUser = {
coroutineScope.launch {
try {
// Reload user to get fresh data from server
authUI.getCurrentUser()?.reload()
authUI.getCurrentUser()?.getIdToken(true)

// Check the user's email verification status after reload
val user = authUI.getCurrentUser()
if (user != null) {
// If email is now verified, transition to Success state
if (user.isEmailVerified) {
authUI.updateAuthState(
AuthState.Success(
result = null,
user = user,
isNewUser = false
)
)
} else {
// Email still not verified, keep showing verification screen
authUI.updateAuthState(
AuthState.RequiresEmailVerification(
user = user,
email = user.email ?: ""
)
)
}
}
} catch (e: Exception) {
Log.e("FirebaseAuthScreen", "Failed to refresh user", e)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,15 +310,17 @@ fun EmailAuthScreen(
} else {
DefaultEmailAuthContent(
configuration = configuration,
state = state
state = state,
onCancel = onCancel
)
}
}

@Composable
private fun DefaultEmailAuthContent(
configuration: AuthUIConfiguration,
state: EmailAuthContentState
state: EmailAuthContentState,
onCancel: () -> Unit
) {
when (state.mode) {
EmailAuthMode.SignIn -> {
Expand All @@ -332,7 +334,8 @@ private fun DefaultEmailAuthContent(
onPasswordChange = state.onPasswordChange,
onSignInClick = state.onSignInClick,
onGoToSignUp = state.onGoToSignUp,
onGoToResetPassword = state.onGoToResetPassword
onGoToResetPassword = state.onGoToResetPassword,
onNavigateBack = onCancel
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,14 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
Expand Down Expand Up @@ -73,6 +77,7 @@ fun SignInUI(
onSignInClick: () -> Unit,
onGoToSignUp: () -> Unit,
onGoToResetPassword: () -> Unit,
onNavigateBack: (() -> Unit)? = null,
) {
val provider = configuration.providers.filterIsInstance<AuthProvider.Email>().first()
val stringProvider = LocalAuthUIStringProvider.current
Expand Down Expand Up @@ -138,6 +143,16 @@ fun SignInUI(
modifier = Modifier.semantics { heading() }
)
},
navigationIcon = {
if (onNavigateBack != null) {
IconButton(onClick = onNavigateBack) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = stringProvider.backAction
)
}
}
},
colors = AuthUITheme.topAppBarColors
)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,23 @@ class HighLevelApiDemoActivity : ComponentActivity() {
serverClientId = "771411398215-o39fujhds88bs4mb5ai7u6o73g86fspp.apps.googleusercontent.com",
)
)
// Email/Password Sign-in
provider(
AuthProvider.Email(
isDisplayNameRequired = true,
isEmailLinkSignInEnabled = false,
isNewAccountsAllowed = true,
minimumPasswordLength = 8,
passwordValidationRules = listOf(
PasswordRule.MinimumLength(8),
PasswordRule.RequireLowercase,
PasswordRule.RequireUppercase,
),
emailLinkActionCodeSettings = null,
buttonLabel = "Sign in with Email"
)
)
// Email Link Sign-in (passwordless)
provider(
AuthProvider.Email(
isDisplayNameRequired = true,
Expand All @@ -76,7 +93,8 @@ class HighLevelApiDemoActivity : ComponentActivity() {
PasswordRule.MinimumLength(8),
PasswordRule.RequireLowercase,
PasswordRule.RequireUppercase,
)
),
buttonLabel = "Sign in with Email Link"
)
)
provider(
Expand Down