Skip to content

Commit 158f301

Browse files
committed
CheckEmail screen
1 parent d8a2c51 commit 158f301

File tree

3 files changed

+371
-163
lines changed

3 files changed

+371
-163
lines changed
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
package com.firebase.ui.auth.ui.email
2+
3+
import android.annotation.SuppressLint
4+
import android.text.TextUtils
5+
import androidx.compose.foundation.layout.*
6+
import androidx.compose.foundation.rememberScrollState
7+
import androidx.compose.foundation.text.KeyboardActions
8+
import androidx.compose.foundation.text.KeyboardOptions
9+
import androidx.compose.foundation.verticalScroll
10+
import androidx.compose.material3.*
11+
import androidx.compose.runtime.*
12+
import androidx.compose.ui.Alignment
13+
import androidx.compose.ui.Modifier
14+
import androidx.compose.ui.platform.LocalContext
15+
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
16+
import androidx.compose.ui.res.stringResource
17+
import androidx.compose.ui.text.input.ImeAction
18+
import androidx.compose.ui.text.input.KeyboardType
19+
import androidx.compose.ui.text.style.TextAlign
20+
import androidx.compose.ui.unit.dp
21+
import androidx.compose.foundation.layout.systemBarsPadding
22+
import com.firebase.ui.auth.R
23+
import com.firebase.ui.auth.data.model.FlowParameters
24+
import com.firebase.ui.auth.data.model.User
25+
import com.firebase.ui.auth.ui.idp.TermsAndPrivacyText
26+
import com.google.firebase.auth.EmailAuthProvider
27+
28+
@SuppressLint("WrongConstant")
29+
@Composable
30+
fun CheckEmailScreen(
31+
modifier: Modifier = Modifier,
32+
flowParameters: FlowParameters,
33+
initialEmail: String? = null,
34+
onExistingEmailUser: (User) -> Unit,
35+
onExistingIdpUser: (User) -> Unit,
36+
onNewUser: (User) -> Unit,
37+
onDeveloperFailure: (Exception) -> Unit,
38+
) {
39+
var email by remember { mutableStateOf(initialEmail ?: "") }
40+
var isEmailError by remember { mutableStateOf(false) }
41+
var emailErrorText by remember { mutableStateOf("") }
42+
var isLoading by remember { mutableStateOf(false) }
43+
val keyboardController = LocalSoftwareKeyboardController.current
44+
val context = LocalContext.current
45+
46+
// Restore initialEmail if provided
47+
LaunchedEffect(initialEmail) {
48+
if (!initialEmail.isNullOrEmpty()) {
49+
email = initialEmail
50+
}
51+
}
52+
53+
// Validate email field
54+
fun validateEmail(): Boolean {
55+
return when {
56+
TextUtils.isEmpty(email) -> {
57+
isEmailError = true
58+
emailErrorText = context.getString(R.string.fui_required_field)
59+
false
60+
}
61+
!android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches() -> {
62+
isEmailError = true
63+
emailErrorText = context.getString(R.string.fui_invalid_email_address)
64+
false
65+
}
66+
else -> true
67+
}
68+
}
69+
70+
// Decide whether to use email‐link provider or password provider
71+
fun getEmailProvider(): String {
72+
flowParameters.providers.forEach { config ->
73+
if (EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD == config.providerId) {
74+
return EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD
75+
}
76+
}
77+
return EmailAuthProvider.PROVIDER_ID
78+
}
79+
80+
// Sign‐in callback
81+
val signIn = {
82+
if (validateEmail()) {
83+
isLoading = true
84+
val provider = getEmailProvider()
85+
val user = User.Builder(provider, email).build()
86+
onExistingEmailUser(user)
87+
}
88+
}
89+
90+
// Sign‐up callback
91+
val signUp = {
92+
if (validateEmail()) {
93+
isLoading = true
94+
val provider = getEmailProvider()
95+
val user = User.Builder(provider, email).build()
96+
onNewUser(user)
97+
}
98+
}
99+
100+
Scaffold(
101+
modifier = modifier
102+
.fillMaxSize()
103+
.systemBarsPadding(),
104+
containerColor = MaterialTheme.colorScheme.background
105+
) { innerPadding ->
106+
Column(
107+
modifier = Modifier
108+
.padding(innerPadding)
109+
.fillMaxSize()
110+
.verticalScroll(rememberScrollState())
111+
.padding(horizontal = 24.dp),
112+
horizontalAlignment = Alignment.CenterHorizontally
113+
) {
114+
// Top loading indicator
115+
if (isLoading) {
116+
LinearProgressIndicator(
117+
modifier = Modifier
118+
.fillMaxWidth()
119+
.height(4.dp)
120+
)
121+
Spacer(Modifier.height(16.dp))
122+
} else {
123+
Spacer(Modifier.height(24.dp))
124+
}
125+
126+
// Header text
127+
Text(
128+
text = stringResource(R.string.fui_email_link_confirm_email_message),
129+
style = MaterialTheme.typography.titleLarge,
130+
textAlign = TextAlign.Start,
131+
modifier = Modifier.fillMaxWidth()
132+
)
133+
134+
Spacer(Modifier.height(32.dp))
135+
136+
// Email input
137+
OutlinedTextField(
138+
value = email,
139+
onValueChange = {
140+
email = it
141+
isEmailError = false
142+
},
143+
label = { Text(stringResource(R.string.fui_email_hint)) },
144+
isError = isEmailError,
145+
supportingText = if (isEmailError) {
146+
{ Text(emailErrorText) }
147+
} else null,
148+
keyboardOptions = KeyboardOptions(
149+
keyboardType = KeyboardType.Email,
150+
imeAction = ImeAction.Done
151+
),
152+
keyboardActions = KeyboardActions(
153+
onDone = {
154+
keyboardController?.hide()
155+
signIn()
156+
}
157+
),
158+
shape = MaterialTheme.shapes.medium,
159+
colors = OutlinedTextFieldDefaults.colors(
160+
focusedBorderColor = MaterialTheme.colorScheme.primary,
161+
unfocusedBorderColor = MaterialTheme.colorScheme.outline,
162+
focusedLabelColor = MaterialTheme.colorScheme.primary,
163+
unfocusedLabelColor = MaterialTheme.colorScheme.onSurfaceVariant,
164+
cursorColor = MaterialTheme.colorScheme.primary,
165+
errorBorderColor = MaterialTheme.colorScheme.error,
166+
errorLabelColor = MaterialTheme.colorScheme.error,
167+
errorSupportingTextColor = MaterialTheme.colorScheme.error
168+
),
169+
modifier = Modifier
170+
.fillMaxWidth()
171+
.padding(bottom = if (isEmailError) 8.dp else 0.dp)
172+
)
173+
174+
Spacer(Modifier.height(24.dp))
175+
176+
// Primary and secondary actions
177+
Row(
178+
modifier = Modifier.fillMaxWidth(),
179+
horizontalArrangement = Arrangement.End,
180+
verticalAlignment = Alignment.CenterVertically
181+
) {
182+
OutlinedButton(
183+
onClick = signUp,
184+
enabled = !isLoading,
185+
modifier = Modifier
186+
.height(48.dp)
187+
) {
188+
Text(stringResource(R.string.fui_title_register_email))
189+
}
190+
191+
Spacer(Modifier.width(8.dp))
192+
193+
Button(
194+
onClick = signIn,
195+
enabled = !isLoading,
196+
modifier = Modifier
197+
.height(48.dp)
198+
) {
199+
Text(stringResource(R.string.fui_sign_in_default))
200+
}
201+
}
202+
203+
Spacer(Modifier.weight(1f))
204+
205+
// Terms & Privacy footer
206+
if (flowParameters.isPrivacyPolicyUrlProvided() &&
207+
flowParameters.isTermsOfServiceUrlProvided()
208+
) {
209+
TermsAndPrivacyText(
210+
tosUrl = flowParameters.termsOfServiceUrl!!,
211+
ppUrl = flowParameters.privacyPolicyUrl!!,
212+
modifier = Modifier
213+
.fillMaxWidth()
214+
.padding(vertical = 16.dp)
215+
)
216+
}
217+
}
218+
}
219+
}

0 commit comments

Comments
 (0)