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