1+ /*
2+ * Copyright 2025 Google Inc. All Rights Reserved.
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+ * in compliance with the License. You may obtain a copy of the License at
6+ *
7+ * http://www.apache.org/licenses/LICENSE-2.0
8+ *
9+ * Unless required by applicable law or agreed to in writing, software distributed under the
10+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+ * express or implied. See the License for the specific language governing permissions and
12+ * limitations under the License.
13+ */
14+
15+ package com.firebase.ui.auth.compose
16+
17+ import com.google.firebase.auth.AuthResult
18+ import com.google.firebase.auth.FirebaseUser
19+ import com.google.firebase.auth.MultiFactorResolver
20+
21+ /* *
22+ * Represents the authentication state in Firebase Auth UI.
23+ *
24+ * This class encapsulates all possible authentication states that can occur during
25+ * the authentication flow, including success, error, and intermediate states.
26+ *
27+ * Use the companion object factory methods or specific subclass constructors to create instances.
28+ *
29+ * @since 10.0.0
30+ */
31+ abstract class AuthState private constructor() {
32+
33+ /* *
34+ * Initial state before any authentication operation has been started.
35+ */
36+ class Idle internal constructor() : AuthState() {
37+ override fun equals (other : Any? ): Boolean = other is Idle
38+ override fun hashCode (): Int = javaClass.hashCode()
39+ override fun toString (): String = " AuthState.Idle"
40+ }
41+
42+ /* *
43+ * Authentication operation is in progress.
44+ *
45+ * @property message Optional message describing what is being loaded
46+ */
47+ class Loading (val message : String? = null ) : AuthState() {
48+ override fun equals (other : Any? ): Boolean {
49+ if (this == = other) return true
50+ if (other !is Loading ) return false
51+ return message == other.message
52+ }
53+
54+ override fun hashCode (): Int = message?.hashCode() ? : 0
55+
56+ override fun toString (): String = " AuthState.Loading(message=$message )"
57+ }
58+
59+ /* *
60+ * Authentication completed successfully.
61+ *
62+ * @property result The [AuthResult] containing the authenticated user, may be null if not available
63+ * @property user The authenticated [FirebaseUser]
64+ * @property isNewUser Whether this is a newly created user account
65+ */
66+ class Success (
67+ val result : AuthResult ? ,
68+ val user : FirebaseUser ,
69+ val isNewUser : Boolean = false
70+ ) : AuthState() {
71+ override fun equals (other : Any? ): Boolean {
72+ if (this == = other) return true
73+ if (other !is Success ) return false
74+ return result == other.result &&
75+ user == other.user &&
76+ isNewUser == other.isNewUser
77+ }
78+
79+ override fun hashCode (): Int {
80+ var result1 = result?.hashCode() ? : 0
81+ result1 = 31 * result1 + user.hashCode()
82+ result1 = 31 * result1 + isNewUser.hashCode()
83+ return result1
84+ }
85+
86+ override fun toString (): String =
87+ " AuthState.Success(result=$result , user=$user , isNewUser=$isNewUser )"
88+ }
89+
90+ /* *
91+ * An error occurred during authentication.
92+ *
93+ * @property exception The [Exception] that occurred
94+ * @property isRecoverable Whether the error can be recovered from
95+ */
96+ class Error (
97+ val exception : Exception ,
98+ val isRecoverable : Boolean = true
99+ ) : AuthState() {
100+ override fun equals (other : Any? ): Boolean {
101+ if (this == = other) return true
102+ if (other !is Error ) return false
103+ return exception == other.exception &&
104+ isRecoverable == other.isRecoverable
105+ }
106+
107+ override fun hashCode (): Int {
108+ var result = exception.hashCode()
109+ result = 31 * result + isRecoverable.hashCode()
110+ return result
111+ }
112+
113+ override fun toString (): String =
114+ " AuthState.Error(exception=$exception , isRecoverable=$isRecoverable )"
115+ }
116+
117+ /* *
118+ * Authentication was cancelled by the user.
119+ */
120+ class Cancelled internal constructor() : AuthState() {
121+ override fun equals (other : Any? ): Boolean = other is Cancelled
122+ override fun hashCode (): Int = javaClass.hashCode()
123+ override fun toString (): String = " AuthState.Cancelled"
124+ }
125+
126+ /* *
127+ * Multi-factor authentication is required to complete sign-in.
128+ *
129+ * @property resolver The [MultiFactorResolver] to complete MFA
130+ * @property hint Optional hint about which factor to use
131+ */
132+ class RequiresMfa (
133+ val resolver : MultiFactorResolver ,
134+ val hint : String? = null
135+ ) : AuthState() {
136+ override fun equals (other : Any? ): Boolean {
137+ if (this == = other) return true
138+ if (other !is RequiresMfa ) return false
139+ return resolver == other.resolver &&
140+ hint == other.hint
141+ }
142+
143+ override fun hashCode (): Int {
144+ var result = resolver.hashCode()
145+ result = 31 * result + (hint?.hashCode() ? : 0 )
146+ return result
147+ }
148+
149+ override fun toString (): String =
150+ " AuthState.RequiresMfa(resolver=$resolver , hint=$hint )"
151+ }
152+
153+ /* *
154+ * Email verification is required before the user can access the app.
155+ *
156+ * @property user The [FirebaseUser] who needs to verify their email
157+ * @property email The email address that needs verification
158+ */
159+ class RequiresEmailVerification (
160+ val user : FirebaseUser ,
161+ val email : String
162+ ) : AuthState() {
163+ override fun equals (other : Any? ): Boolean {
164+ if (this == = other) return true
165+ if (other !is RequiresEmailVerification ) return false
166+ return user == other.user &&
167+ email == other.email
168+ }
169+
170+ override fun hashCode (): Int {
171+ var result = user.hashCode()
172+ result = 31 * result + email.hashCode()
173+ return result
174+ }
175+
176+ override fun toString (): String =
177+ " AuthState.RequiresEmailVerification(user=$user , email=$email )"
178+ }
179+
180+ /* *
181+ * The user needs to complete their profile information.
182+ *
183+ * @property user The [FirebaseUser] who needs to complete their profile
184+ * @property missingFields List of profile fields that need to be completed
185+ */
186+ class RequiresProfileCompletion (
187+ val user : FirebaseUser ,
188+ val missingFields : List <String > = emptyList()
189+ ) : AuthState() {
190+ override fun equals (other : Any? ): Boolean {
191+ if (this == = other) return true
192+ if (other !is RequiresProfileCompletion ) return false
193+ return user == other.user &&
194+ missingFields == other.missingFields
195+ }
196+
197+ override fun hashCode (): Int {
198+ var result = user.hashCode()
199+ result = 31 * result + missingFields.hashCode()
200+ return result
201+ }
202+
203+ override fun toString (): String =
204+ " AuthState.RequiresProfileCompletion(user=$user , missingFields=$missingFields )"
205+ }
206+
207+ companion object {
208+ /* *
209+ * Creates an Idle state instance.
210+ * @return A new [Idle] state
211+ */
212+ @JvmStatic
213+ val Idle : Idle = Idle ()
214+
215+ /* *
216+ * Creates a Cancelled state instance.
217+ * @return A new [Cancelled] state
218+ */
219+ @JvmStatic
220+ val Cancelled : Cancelled = Cancelled ()
221+ }
222+ }
0 commit comments