@@ -33,8 +33,10 @@ import com.firebase.ui.auth.compose.configuration.auth_provider.createOrLinkUser
3333import com.firebase.ui.auth.compose.configuration.auth_provider.sendPasswordResetEmail
3434import com.firebase.ui.auth.compose.configuration.auth_provider.sendSignInLinkToEmail
3535import com.firebase.ui.auth.compose.configuration.auth_provider.signInWithEmailAndPassword
36+ import com.firebase.ui.auth.compose.configuration.auth_provider.signInWithEmailLink
3637import com.firebase.ui.auth.compose.configuration.string_provider.DefaultAuthUIStringProvider
3738import com.firebase.ui.auth.compose.ui.components.ErrorRecoveryDialog
39+ import com.firebase.ui.auth.compose.util.EmailLinkPersistenceManager
3840import com.google.firebase.auth.AuthResult
3941import kotlinx.coroutines.launch
4042
@@ -74,6 +76,8 @@ enum class EmailAuthMode {
7476 * send a password reset email.
7577 * @param resetLinkSent (Mode: [EmailAuthMode.ResetPassword]) true after the password reset link
7678 * has been successfully sent.
79+ * @param emailSignInLinkSent (Mode: [EmailAuthMode.SignIn]) true after the email sign in link has
80+ * been successfully sent.
7781 * @param onGoToSignUp A callback to switch the UI to the SignUp mode.
7882 * @param onGoToSignIn A callback to switch the UI to the SignIn mode.
7983 * @param onGoToResetPassword A callback to switch the UI to the ResetPassword mode.
@@ -94,6 +98,7 @@ class EmailAuthContentState(
9498 val onSignUpClick : () -> Unit ,
9599 val onSendResetLinkClick : () -> Unit ,
96100 val resetLinkSent : Boolean = false ,
101+ val emailSignInLinkSent : Boolean = false ,
97102 val onGoToSignUp : () -> Unit ,
98103 val onGoToSignIn : () -> Unit ,
99104 val onGoToResetPassword : () -> Unit ,
@@ -104,8 +109,7 @@ class EmailAuthContentState(
104109 * including sign-in, sign-up, and password reset. It exposes the state for the current mode to
105110 * a custom UI via a trailing lambda (slot), allowing for complete visual customization.
106111 *
107- * @param provider The configuration object contains rules for email auth, such as whether a
108- * display name is required.
112+ * @param configuration
109113 * @param onSuccess
110114 * @param onError
111115 * @param onCancel
@@ -116,12 +120,12 @@ fun EmailAuthScreen(
116120 context : Context ,
117121 configuration : AuthUIConfiguration ,
118122 authUI : FirebaseAuthUI ,
119- provider : AuthProvider .Email ,
120123 onSuccess : (AuthResult ) -> Unit ,
121124 onError : (AuthException ) -> Unit ,
122125 onCancel : () -> Unit ,
123126 content : @Composable ((EmailAuthContentState ) -> Unit )? = null,
124127) {
128+ val provider = configuration.providers.filterIsInstance<AuthProvider .Email >().first()
125129 val stringProvider = DefaultAuthUIStringProvider (context)
126130 val coroutineScope = rememberCoroutineScope()
127131
@@ -144,6 +148,7 @@ fun EmailAuthScreen(
144148 val errorMessage =
145149 if (authState is AuthState .Error ) (authState as AuthState .Error ).exception.message else null
146150 val resetLinkSent = authState is AuthState .PasswordResetLinkSent
151+ val emailSignInLinkSent = authState is AuthState .EmailSignInLinkSent
147152
148153 val isErrorDialogVisible =
149154 remember(authState) { mutableStateOf(authState is AuthState .Error ) }
@@ -178,6 +183,7 @@ fun EmailAuthScreen(
178183 isLoading = isLoading,
179184 error = errorMessage,
180185 resetLinkSent = resetLinkSent,
186+ emailSignInLinkSent = emailSignInLinkSent,
181187 onEmailChange = { email ->
182188 emailTextValue.value = email
183189 },
@@ -260,25 +266,15 @@ fun EmailAuthScreen(
260266 if (isErrorDialogVisible.value) {
261267 ErrorRecoveryDialog (
262268 error = when ((authState as AuthState .Error ).exception) {
263- is AuthException -> {
264- (authState as AuthState .Error ).exception as AuthException
265- }
266-
267- else -> {
268- AuthException
269- .from((authState as AuthState .Error ).exception)
270- }
269+ is AuthException -> (authState as AuthState .Error ).exception as AuthException
270+ else -> AuthException
271+ .from((authState as AuthState .Error ).exception)
271272 },
272273 stringProvider = stringProvider,
273274 onRetry = { exception ->
274275 when (exception) {
275- is AuthException .InvalidCredentialsException -> {
276- state.onSignInClick()
277- }
278-
279- is AuthException .EmailAlreadyInUseException -> {
280- state.onGoToSignIn()
281- }
276+ is AuthException .InvalidCredentialsException -> state.onSignInClick()
277+ is AuthException .EmailAlreadyInUseException -> state.onGoToSignIn()
282278 }
283279 isErrorDialogVisible.value = false
284280 },
@@ -290,102 +286,3 @@ fun EmailAuthScreen(
290286
291287 content?.invoke(state)
292288}
293-
294- // @Preview
295- // @Composable
296- // internal fun PreviewEmailAuthScreen() {
297- // val applicationContext = LocalContext.current
298- // val provider = AuthProvider.Email(
299- // isDisplayNameRequired = true,
300- // isEmailLinkSignInEnabled = false,
301- // isEmailLinkForceSameDeviceEnabled = true,
302- // actionCodeSettings = null,
303- // isNewAccountsAllowed = true,
304- // minimumPasswordLength = 8,
305- // passwordValidationRules = listOf()
306- // )
307- //
308- // AuthUITheme {
309- // EmailAuthScreen(
310- // context = applicationContext,
311- // configuration = authUIConfiguration {
312- // context = applicationContext
313- // providers { provider(provider) }
314- // tosUrl = ""
315- // privacyPolicyUrl = ""
316- // },
317- // authUI = null,
318- // provider = provider,
319- // onSuccess = {
320- //
321- // },
322- // onError = {
323- //
324- // },
325- // onCancel = {
326- //
327- // },
328- // ) { state ->
329- // when (state.mode) {
330- // EmailAuthMode.SignIn -> {
331- // SignInUI(
332- // configuration = authUIConfiguration {
333- // context = applicationContext
334- // providers { provider(provider) }
335- // tosUrl = ""
336- // privacyPolicyUrl = ""
337- // },
338- // provider = provider,
339- // email = state.email,
340- // isLoading = false,
341- // password = state.password,
342- // onEmailChange = state.onEmailChange,
343- // onPasswordChange = state.onPasswordChange,
344- // onSignInClick = state.onSignInClick,
345- // onGoToSignUp = state.onGoToSignUp,
346- // onGoToResetPassword = state.onGoToResetPassword,
347- // )
348- // }
349- //
350- // EmailAuthMode.SignUp -> {
351- // SignUpUI(
352- // configuration = authUIConfiguration {
353- // context = applicationContext
354- // providers { provider(provider) }
355- // tosUrl = ""
356- // privacyPolicyUrl = ""
357- // },
358- // isLoading = state.isLoading,
359- // displayName = state.displayName,
360- // email = state.email,
361- // password = state.password,
362- // confirmPassword = state.confirmPassword,
363- // onDisplayNameChange = state.onDisplayNameChange,
364- // onEmailChange = state.onEmailChange,
365- // onPasswordChange = state.onPasswordChange,
366- // onConfirmPasswordChange = state.onConfirmPasswordChange,
367- // onSignUpClick = state.onSignUpClick,
368- // onGoToSignIn = state.onGoToSignIn,
369- // )
370- // }
371- //
372- // EmailAuthMode.ResetPassword -> {
373- // ResetPasswordUI(
374- // configuration = authUIConfiguration {
375- // context = applicationContext
376- // providers { provider(provider) }
377- // tosUrl = ""
378- // privacyPolicyUrl = ""
379- // },
380- // isLoading = state.isLoading,
381- // email = state.email,
382- // resetLinkSent = state.resetLinkSent,
383- // onEmailChange = state.onEmailChange,
384- // onSendResetLink = state.onSendResetLinkClick,
385- // onGoToSignIn = state.onGoToSignIn
386- // )
387- // }
388- // }
389- // }
390- // }
391- // }
0 commit comments