Skip to content

Commit 1b9e219

Browse files
committed
Merge branch 'version-10.0.0-dev' of https://github.com/firebase/FirebaseUI-Android into version-10.0.0-dev
2 parents 5f515b1 + e5d5f1d commit 1b9e219

File tree

9 files changed

+71
-43
lines changed

9 files changed

+71
-43
lines changed

auth/src/main/java/com/firebase/ui/auth/compose/configuration/theme/ProviderStyleDefaults.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ internal object ProviderStyleDefaults {
4343
Provider.FACEBOOK -> {
4444
provider.id to AuthUITheme.ProviderStyle(
4545
icon = AuthUIAsset.Resource(R.drawable.fui_ic_facebook_white_22dp),
46-
backgroundColor = Color(0xFF3B5998),
46+
backgroundColor = Color(0xFF1877F2),
4747
contentColor = Color.White
4848
)
4949
}

auth/src/main/java/com/firebase/ui/auth/compose/ui/components/AuthProviderButton.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import androidx.compose.foundation.layout.PaddingValues
2121
import androidx.compose.foundation.layout.Row
2222
import androidx.compose.foundation.layout.Spacer
2323
import androidx.compose.foundation.layout.fillMaxSize
24+
import androidx.compose.foundation.layout.size
2425
import androidx.compose.foundation.layout.width
2526
import androidx.compose.foundation.shape.RoundedCornerShape
2627
import androidx.compose.material.icons.Icons
@@ -106,12 +107,16 @@ fun AuthProviderButton(
106107
val iconTint = providerStyle.iconTint
107108
if (iconTint != null) {
108109
Icon(
110+
modifier = Modifier
111+
.size(24.dp),
109112
painter = providerIcon.painter,
110113
contentDescription = providerLabel,
111114
tint = iconTint
112115
)
113116
} else {
114117
Image(
118+
modifier = Modifier
119+
.size(24.dp),
115120
painter = providerIcon.painter,
116121
contentDescription = providerLabel
117122
)

auth/src/main/java/com/firebase/ui/auth/compose/ui/components/TopLevelDialogController.kt

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import androidx.compose.runtime.mutableStateOf
2121
import androidx.compose.runtime.remember
2222
import androidx.compose.runtime.setValue
2323
import com.firebase.ui.auth.compose.AuthException
24+
import com.firebase.ui.auth.compose.AuthState
2425
import com.firebase.ui.auth.compose.configuration.string_provider.AuthUIStringProvider
2526

2627
/**
@@ -66,12 +67,15 @@ val LocalTopLevelDialogController = compositionLocalOf<TopLevelDialogController?
6667
* @since 10.0.0
6768
*/
6869
class TopLevelDialogController(
69-
private val stringProvider: AuthUIStringProvider
70+
private val stringProvider: AuthUIStringProvider,
71+
private val authState: AuthState
7072
) {
7173
private var dialogState by mutableStateOf<DialogState?>(null)
74+
private val shownErrorStates = mutableSetOf<AuthState.Error>()
7275

7376
/**
7477
* Shows an error recovery dialog at the top level using [ErrorRecoveryDialog].
78+
* Automatically prevents duplicate dialogs for the same AuthState.Error instance.
7579
*
7680
* @param exception The auth exception to display
7781
* @param onRetry Callback when user clicks retry button
@@ -84,6 +88,17 @@ class TopLevelDialogController(
8488
onRecover: (AuthException) -> Unit = {},
8589
onDismiss: () -> Unit = {}
8690
) {
91+
// Get current error state
92+
val currentErrorState = authState as? AuthState.Error
93+
94+
// If this exact error state has already been shown, skip
95+
if (currentErrorState != null && currentErrorState in shownErrorStates) {
96+
return
97+
}
98+
99+
// Mark this error state as shown
100+
currentErrorState?.let { shownErrorStates.add(it) }
101+
87102
dialogState = DialogState.ErrorDialog(
88103
exception = exception,
89104
onRetry = onRetry,
@@ -148,9 +163,10 @@ class TopLevelDialogController(
148163
*/
149164
@Composable
150165
fun rememberTopLevelDialogController(
151-
stringProvider: AuthUIStringProvider
166+
stringProvider: AuthUIStringProvider,
167+
authState: AuthState
152168
): TopLevelDialogController {
153-
return remember(stringProvider) {
154-
TopLevelDialogController(stringProvider)
169+
return remember(stringProvider, authState) {
170+
TopLevelDialogController(stringProvider, authState)
155171
}
156172
}

auth/src/main/java/com/firebase/ui/auth/compose/ui/screens/FirebaseAuthScreen.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,9 @@ fun FirebaseAuthScreen(
9797
val coroutineScope = rememberCoroutineScope()
9898
val stringProvider = DefaultAuthUIStringProvider(context)
9999
val navController = rememberNavController()
100-
val dialogController = rememberTopLevelDialogController(stringProvider)
101100

102101
val authState by authUI.authStateFlow().collectAsState(AuthState.Idle)
102+
val dialogController = rememberTopLevelDialogController(stringProvider, authState)
103103
val lastSuccessfulUserId = remember { mutableStateOf<String?>(null) }
104104
val pendingLinkingCredential = remember { mutableStateOf<AuthCredential?>(null) }
105105
val pendingResolver = remember { mutableStateOf<MultiFactorResolver?>(null) }

auth/src/main/java/com/firebase/ui/auth/compose/ui/screens/email/SignUpUI.kt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -116,18 +116,6 @@ fun SignUpUI(
116116
.padding(horizontal = 16.dp)
117117
.verticalScroll(rememberScrollState()),
118118
) {
119-
AuthTextField(
120-
value = email,
121-
validator = emailValidator,
122-
enabled = !isLoading,
123-
label = {
124-
Text(stringProvider.emailHint)
125-
},
126-
onValueChange = { text ->
127-
onEmailChange(text)
128-
}
129-
)
130-
Spacer(modifier = Modifier.height(16.dp))
131119
if (provider.isDisplayNameRequired) {
132120
AuthTextField(
133121
value = displayName,
@@ -142,6 +130,18 @@ fun SignUpUI(
142130
)
143131
Spacer(modifier = Modifier.height(16.dp))
144132
}
133+
AuthTextField(
134+
value = email,
135+
validator = emailValidator,
136+
enabled = !isLoading,
137+
label = {
138+
Text(stringProvider.emailHint)
139+
},
140+
onValueChange = { text ->
141+
onEmailChange(text)
142+
}
143+
)
144+
Spacer(modifier = Modifier.height(16.dp))
145145
AuthTextField(
146146
value = password,
147147
validator = passwordValidator,

auth/src/main/java/com/firebase/ui/auth/compose/ui/screens/phone/EnterPhoneNumberUI.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,14 @@ import androidx.compose.foundation.rememberScrollState
2727
import androidx.compose.foundation.text.KeyboardOptions
2828
import androidx.compose.foundation.verticalScroll
2929
import androidx.compose.material.icons.Icons
30+
import androidx.compose.material.icons.automirrored.filled.ArrowBack
3031
import androidx.compose.material.icons.filled.CheckBox
3132
import androidx.compose.material.icons.filled.CheckBoxOutlineBlank
3233
import androidx.compose.material3.Button
3334
import androidx.compose.material3.CircularProgressIndicator
3435
import androidx.compose.material3.ExperimentalMaterial3Api
3536
import androidx.compose.material3.Icon
37+
import androidx.compose.material3.IconButton
3638
import androidx.compose.material3.MaterialTheme
3739
import androidx.compose.material3.Scaffold
3840
import androidx.compose.material3.Text
@@ -70,6 +72,7 @@ fun EnterPhoneNumberUI(
7072
onCountrySelected: (CountryData) -> Unit,
7173
onSendCodeClick: () -> Unit,
7274
title: String? = null,
75+
onNavigateBack: (() -> Unit)? = null,
7376
) {
7477
val context = LocalContext.current
7578
val provider = configuration.providers.filterIsInstance<AuthProvider.Phone>().first()
@@ -91,6 +94,16 @@ fun EnterPhoneNumberUI(
9194
title = {
9295
Text(title ?: stringProvider.signInWithPhone)
9396
},
97+
navigationIcon = {
98+
if (onNavigateBack != null) {
99+
IconButton(onClick = onNavigateBack) {
100+
Icon(
101+
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
102+
contentDescription = stringProvider.backAction
103+
)
104+
}
105+
}
106+
},
94107
colors = AuthUITheme.topAppBarColors
95108
)
96109
},

auth/src/main/java/com/firebase/ui/auth/compose/ui/screens/phone/PhoneAuthScreen.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,15 +308,17 @@ fun PhoneAuthScreen(
308308
} else {
309309
DefaultPhoneAuthContent(
310310
configuration = configuration,
311-
state = state
311+
state = state,
312+
onCancel = onCancel
312313
)
313314
}
314315
}
315316

316317
@Composable
317318
private fun DefaultPhoneAuthContent(
318319
configuration: AuthUIConfiguration,
319-
state: PhoneAuthContentState
320+
state: PhoneAuthContentState,
321+
onCancel: () -> Unit,
320322
) {
321323
when (state.step) {
322324
PhoneAuthStep.EnterPhoneNumber -> {
@@ -327,7 +329,8 @@ private fun DefaultPhoneAuthContent(
327329
selectedCountry = state.selectedCountry,
328330
onPhoneNumberChange = state.onPhoneNumberChange,
329331
onCountrySelected = state.onCountrySelected,
330-
onSendCodeClick = state.onSendCodeClick
332+
onSendCodeClick = state.onSendCodeClick,
333+
onNavigateBack = onCancel
331334
)
332335
}
333336

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
<vector
2-
xmlns:android="http://schemas.android.com/apk/res/android"
3-
android:width="22dp"
4-
android:height="22dp"
5-
android:viewportHeight="266.895"
6-
android:viewportWidth="266.893">
7-
<path
8-
android:fillColor="#FFFFFF"
9-
android:pathData="M248.08,262.31c7.85,0 14.22,-6.37 14.22,-14.23V18.81c0,-7.86 -6.37,-14.22 -14.22,-14.22H18.81c-7.86,0 -14.22,6.37 -14.22,14.22v229.27c0,7.86 6.37,14.23 14.22,14.23H248.08z" />
10-
<path
11-
android:fillColor="#3C5A99"
12-
android:pathData="M182.41,262.31v-99.8h33.5l5.02,-38.9h-38.51V98.78c0,-11.26 3.13,-18.93 19.27,-18.93l20.6,-0.01V45.04c-3.56,-0.47 -15.79,-1.53 -30.01,-1.53c-29.69,0 -50.03,18.13 -50.03,51.41v28.68h-33.58v38.9h33.58v99.8H182.41z" />
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="314dp"
3+
android:height="313dp"
4+
android:viewportWidth="314"
5+
android:viewportHeight="313">
6+
<path
7+
android:pathData="M314,157.07C314,70.33 243.71,0 157,0C70.29,0 0,70.33 0,157.07C0,230.74 50.69,292.55 119.07,309.52V205.08H86.7V157.07H119.07V136.39C119.07,82.93 143.26,58.15 195.72,58.15C205.67,58.15 222.83,60.1 229.85,62.05V105.56C226.15,105.17 219.71,104.98 211.72,104.98C185.98,104.98 176.03,114.73 176.03,140.1V157.07H227.31L218.5,205.08H176.03V313C253.76,303.61 314,237.38 314,157.07Z"
8+
android:fillColor="#ffffff"/>
139
</vector>

composeapp/build.gradle.kts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,18 @@ android {
1919
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
2020
}
2121

22-
signingConfigs {
23-
getByName("debug") {
24-
storeFile = file("${System.getProperty("user.home")}/.android/debug.keystore")
25-
storePassword = "android"
26-
keyAlias = "androiddebugkey"
27-
keyPassword = "android"
28-
}
29-
}
30-
3122
buildTypes {
3223
release {
3324
isMinifyEnabled = false
3425
proguardFiles(
3526
getDefaultProguardFile("proguard-android-optimize.txt"),
3627
"proguard-rules.pro"
3728
)
38-
signingConfig = signingConfigs.getByName("debug")
29+
// Only sign with debug keystore if it exists (for local testing)
30+
val debugKeystoreFile = file("${System.getProperty("user.home")}/.android/debug.keystore")
31+
if (debugKeystoreFile.exists()) {
32+
signingConfig = signingConfigs.getByName("debug")
33+
}
3934
}
4035
}
4136
compileOptions {

0 commit comments

Comments
 (0)