1
1
package com.firebase.ui.auth.compose
2
2
3
- import android.content.Intent
3
+ import android.app.Activity
4
4
import androidx.activity.compose.rememberLauncherForActivityResult
5
5
import androidx.compose.foundation.layout.Box
6
6
import androidx.compose.foundation.layout.fillMaxSize
7
7
import androidx.compose.material3.CircularProgressIndicator
8
8
import androidx.compose.runtime.*
9
+ import androidx.compose.runtime.saveable.rememberSaveable
9
10
import androidx.compose.ui.Alignment
10
11
import androidx.compose.ui.Modifier
11
12
import com.firebase.ui.auth.AuthUI
12
13
import com.firebase.ui.auth.AuthUI.IdpConfig
13
14
import com.firebase.ui.auth.FirebaseAuthUIActivityResultContract
14
15
import com.firebase.ui.auth.data.model.FirebaseAuthUIAuthenticationResult
15
16
import com.google.firebase.auth.FirebaseAuth
16
- import kotlinx.coroutines.launch
17
17
18
18
/* *
19
19
* Composable that handles Firebase Auth UI sign-in and automatically swaps to [signedInContent]
@@ -39,36 +39,23 @@ fun FirebaseAuthUI(
39
39
tosUrl : String? = null,
40
40
privacyPolicyUrl : String? = null,
41
41
enableCredentials : Boolean = true,
42
- enableAnonymousUpgrade : Boolean = false
42
+ enableAnonymousUpgrade : Boolean = false,
43
43
) {
44
44
val auth = remember { FirebaseAuth .getInstance() }
45
45
val authUI = remember { AuthUI .getInstance() }
46
- val scope = rememberCoroutineScope()
47
46
48
- /* ------------- 1) Observe auth state ------------- */
49
47
val firebaseUser by
50
48
produceState(initialValue = auth.currentUser, auth) {
51
- val listener =
52
- FirebaseAuth .AuthStateListener { firebaseAuth ->
53
- value = firebaseAuth.currentUser
54
- }
49
+ val listener = FirebaseAuth .AuthStateListener { value = it.currentUser }
55
50
auth.addAuthStateListener(listener)
56
51
awaitDispose { auth.removeAuthStateListener(listener) }
57
52
}
58
53
59
- /* ------------- 2) If signed in, show caller-provided screen ------------- */
60
54
if (firebaseUser != null ) {
61
55
signedInContent()
62
56
return
63
57
}
64
58
65
- /* ------------- 3) Otherwise prepare & launch Firebase UI sign-in ------------- */
66
- val signInLauncher =
67
- rememberLauncherForActivityResult(
68
- contract = FirebaseAuthUIActivityResultContract (),
69
- onResult = onSignInResult
70
- )
71
-
72
59
val signInIntent =
73
60
remember(
74
61
providers,
@@ -93,21 +80,23 @@ fun FirebaseAuthUI(
93
80
}
94
81
}
95
82
.build()
96
- .apply {
97
- addFlags(
98
- Intent .FLAG_ACTIVITY_CLEAR_TOP or Intent .FLAG_ACTIVITY_NEW_TASK
99
- )
100
- }
101
83
}
102
84
103
- /* ------------- 4) Launch once per composable lifetime ------------- */
104
- LaunchedEffect (signInIntent) {
105
- // Launch from a coroutine so we’re safe even inside composition
106
- scope.launch { signInLauncher.launch(signInIntent) }
107
- }
85
+ var signInAttempted by rememberSaveable { mutableStateOf(false ) }
108
86
109
- /* Optional: lightweight in-place progress indicator while Firebase UI Activity starts */
110
- Box (modifier = Modifier .fillMaxSize(), contentAlignment = Alignment .Center ) {
111
- CircularProgressIndicator ()
87
+ val launcher =
88
+ rememberLauncherForActivityResult(FirebaseAuthUIActivityResultContract ()) { result ->
89
+ onSignInResult(result)
90
+
91
+ signInAttempted = result.resultCode != Activity .RESULT_OK
92
+ }
93
+
94
+ LaunchedEffect (Unit ) {
95
+ if (! signInAttempted) {
96
+ signInAttempted = true
97
+ launcher.launch(signInIntent)
98
+ }
112
99
}
100
+
101
+ Box (Modifier .fillMaxSize(), Alignment .Center ) { CircularProgressIndicator () }
113
102
}
0 commit comments