Skip to content

Commit 1b4c084

Browse files
committed
chore(fc): improve auth state handling for quicker log ins
Signed-off-by: Brandon McAnsh <[email protected]>
1 parent 3bff5ed commit 1b4c084

File tree

6 files changed

+85
-63
lines changed

6 files changed

+85
-63
lines changed

flipchatApp/src/main/kotlin/xyz/flipchat/app/FlipchatApp.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,6 @@ class FlipchatApp : Application() {
2323
override fun onCreate() {
2424
super.onCreate()
2525

26-
Firebase.initialize(this)
27-
MnemonicCache.init(this)
28-
authManager.init { trace("NaCl init") }
29-
30-
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
31-
32-
RxJavaPlugins.setErrorHandler {
33-
ErrorUtils.handleError(it)
34-
}
35-
3626
if (BuildConfig.DEBUG) {
3727
Timber.plant(object : Timber.DebugTree() {
3828
override fun createStackElementTag(element: StackTraceElement): String {
@@ -59,6 +49,16 @@ class FlipchatApp : Application() {
5949
} else {
6050
Bugsnag.start(this)
6151
}
52+
53+
RxJavaPlugins.setErrorHandler {
54+
ErrorUtils.handleError(it)
55+
}
56+
57+
Firebase.initialize(this)
58+
MnemonicCache.init(this)
59+
authManager.init { trace("NaCl init") }
60+
61+
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
6262
trace("app onCreate end")
6363
}
6464
}

flipchatApp/src/main/kotlin/xyz/flipchat/app/auth/AuthManager.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ class AuthManager @Inject constructor(
134134
val originalEntropy = userManager.entropy
135135
userManager.establish(entropy = entropyB64)
136136

137-
138137
if (!isSoftLogin) {
139138
loginAnalytics()
140139
}
@@ -146,7 +145,6 @@ class AuthManager @Inject constructor(
146145
if (userId != null) {
147146
Result.success(Base58.decode(userId).toList())
148147
} else {
149-
setupAsNew()
150148
Result.failure(Throwable("No user Id found"))
151149
}
152150
} else {
@@ -161,7 +159,6 @@ class AuthManager @Inject constructor(
161159
}
162160
.onSuccess {
163161
userManager.set(userId = it)
164-
userManager.establish(entropyB64)
165162
savePrefs()
166163
}
167164
.onFailure {

flipchatApp/src/main/kotlin/xyz/flipchat/app/features/home/HomeViewModel.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import androidx.lifecycle.viewModelScope
55
import com.getcode.utils.TraceType
66
import com.getcode.utils.trace
77
import dagger.hilt.android.lifecycle.HiltViewModel
8+
import kotlinx.coroutines.flow.distinctUntilChanged
9+
import kotlinx.coroutines.flow.launchIn
10+
import kotlinx.coroutines.flow.map
11+
import kotlinx.coroutines.flow.mapNotNull
12+
import kotlinx.coroutines.flow.onEach
813
import kotlinx.coroutines.launch
914
import xyz.flipchat.app.util.Router
1015
import xyz.flipchat.controllers.ChatsController
@@ -16,9 +21,18 @@ import javax.inject.Inject
1621
class HomeViewModel @Inject constructor(
1722
private val codeController: CodeController,
1823
private val chatsController: ChatsController,
19-
val router: Router
24+
private val userManager: UserManager,
25+
val router: Router,
2026
): ViewModel() {
2127

28+
init {
29+
userManager.state
30+
.mapNotNull { it.userId }
31+
.distinctUntilChanged()
32+
.onEach { requestAirdrop() }
33+
.launchIn(viewModelScope)
34+
}
35+
2236
fun requestAirdrop() {
2337
viewModelScope.launch {
2438
codeController.fetchBalance()

flipchatApp/src/main/kotlin/xyz/flipchat/app/ui/navigation/MainRoot.kt

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import dev.theolm.rinku.compose.ext.DeepLinkListener
4242
import kotlinx.coroutines.delay
4343
import kotlinx.coroutines.flow.distinctUntilChanged
4444
import kotlinx.coroutines.flow.launchIn
45+
import kotlinx.coroutines.flow.map
4546
import kotlinx.coroutines.flow.onEach
4647
import timber.log.Timber
4748
import xyz.flipchat.services.user.AuthState
@@ -56,7 +57,6 @@ internal object MainRoot : Screen {
5657
override fun Content() {
5758
val navigator = LocalNavigator.currentOrThrow
5859
val userManager = LocalUserManager.currentOrThrow
59-
val sessionState by userManager.authState.collectAsState()
6060
var showLoading by remember { mutableStateOf(false) }
6161

6262
//We are obtaining deep link here, in case we want to allow for some amount of deep linking when not
@@ -104,24 +104,28 @@ internal object MainRoot : Screen {
104104
}
105105
}
106106

107-
LaunchedEffect(sessionState) {
108-
Timber.d("sessionState=$sessionState")
109-
when (sessionState) {
110-
AuthState.AwaitingUser -> {
111-
delay(1_500) // wait at most 1.5s for account retrieval to fail
112-
navigator.replace(ScreenRegistry.get(NavScreenProvider.Login.Home()))
113-
}
114-
AuthState.LoggedIn -> {
115-
navigator.replace(ScreenRegistry.get(NavScreenProvider.AppHomeScreen(deeplink)))
116-
}
117-
AuthState.LoggedOut -> {
118-
navigator.replace(ScreenRegistry.get(NavScreenProvider.Login.Home()))
119-
}
120-
AuthState.Unknown -> {
121-
delay(500)
122-
showLoading = true
123-
}
124-
}
107+
LaunchedEffect(userManager) {
108+
userManager.state
109+
.map { it.authState }
110+
.distinctUntilChanged()
111+
.onEach { state ->
112+
Timber.d("sessionState=$state")
113+
when (state) {
114+
AuthState.AwaitingUser -> {
115+
delay(500)
116+
showLoading = true
117+
}
118+
AuthState.LoggedIn -> {
119+
navigator.replace(ScreenRegistry.get(NavScreenProvider.AppHomeScreen(deeplink)))
120+
}
121+
AuthState.LoggedOut -> {
122+
navigator.replace(ScreenRegistry.get(NavScreenProvider.Login.Home()))
123+
}
124+
AuthState.Unknown -> {
125+
navigator.replace(ScreenRegistry.get(NavScreenProvider.Login.Home()))
126+
}
127+
}
128+
}.launchIn(this)
125129
}
126130
}
127131
}

flipchatApp/src/main/kotlin/xyz/flipchat/app/util/AccountUtils.kt

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,21 @@ object AccountUtils {
120120
suspend fun getUserId(context: Context): String? {
121121
val accountManager = AccountManager.get(context)
122122
val accounts = accountManager.getAccountsByType(ACCOUNT_TYPE)
123-
val account = accounts.firstOrNull()
124-
if (account != null) {
125-
val pw = runCatching { accountManager.getPassword(account) }
126-
.getOrNull()?.takeIf { it.isNotEmpty() }
127-
if (pw != null) {
128-
return pw
123+
124+
fun getPassword(a: Account?): String? {
125+
if (a != null) {
126+
val pw = runCatching { accountManager.getPassword(a) }
127+
.getOrNull()?.takeIf { it.isNotEmpty() }
128+
if (pw != null) {
129+
return pw
130+
}
129131
}
132+
return null
130133
}
131134

135+
val account = accounts.firstOrNull()
136+
getPassword(account)?.let { return it }
137+
132138
val (_, acct) = retryable(
133139
call = { getAccountNoActivity(context) },
134140
onRetry = { currentAttempt ->
@@ -143,15 +149,7 @@ object AccountUtils {
143149
}
144150
) ?: return null
145151

146-
if (acct != null) {
147-
val pw = runCatching { accountManager.getPassword(acct) }
148-
.getOrNull()?.takeIf { it.isNotEmpty() }
149-
if (pw != null) {
150-
return pw
151-
}
152-
}
153-
154-
return null
152+
return getPassword(acct)
155153
}
156154

157155
suspend fun getToken(context: Context): TokenResult? {

services/flipchat/core/src/main/kotlin/xyz/flipchat/services/user/UserManager.kt

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ import javax.inject.Inject
1414
import javax.inject.Singleton
1515

1616
sealed interface AuthState {
17-
data object Unknown: AuthState
18-
data object AwaitingUser: AuthState
19-
data object LoggedOut: AuthState
20-
data object LoggedIn: AuthState
17+
data object Unknown : AuthState
18+
data object AwaitingUser : AuthState
19+
data object LoggedOut : AuthState
20+
data object LoggedIn : AuthState
2121
}
2222

2323
@Singleton
@@ -50,11 +50,8 @@ class UserManager @Inject constructor(
5050
val openRoom: ID?
5151
get() = _state.value.openRoom
5252

53-
private val _authState: MutableStateFlow<AuthState> = MutableStateFlow(AuthState.Unknown)
54-
val authState: StateFlow<AuthState>
55-
get() = _authState
56-
5753
data class State(
54+
val authState: AuthState = AuthState.Unknown,
5855
val entropy: String? = null,
5956
val keyPair: KeyPair? = null,
6057
val userId: ID? = null,
@@ -69,17 +66,21 @@ class UserManager @Inject constructor(
6966
val authority = DerivedKey.derive(com.getcode.crypt.DerivePath.primary, mnemonic)
7067
val organizer = organizerGenerator.generate(mnemonic)
7168
_state.update {
72-
it.copy(entropy = entropy, keyPair = authority.keyPair, organizer = organizer)
69+
it.copy(
70+
authState = AuthState.AwaitingUser,
71+
entropy = entropy,
72+
keyPair = authority.keyPair,
73+
organizer = organizer
74+
)
7375
}
74-
_authState.update { AuthState.AwaitingUser }
7576
}
7677

7778
fun set(userId: ID) {
7879
_state.update {
79-
it.copy(userId = userId)
80+
it.copy(
81+
authState = AuthState.LoggedIn,
82+
userId = userId)
8083
}
81-
82-
_authState.update { AuthState.LoggedIn }
8384
}
8485

8586
fun set(displayName: String) {
@@ -114,8 +115,16 @@ class UserManager @Inject constructor(
114115

115116
fun clear() {
116117
_state.update {
117-
it.copy(entropy = null, keyPair = null, userId = emptyList(), organizer = null, flags = null, openRoom = null)
118+
it.copy(
119+
authState = AuthState.LoggedOut,
120+
entropy = null,
121+
keyPair = null,
122+
userId = emptyList(),
123+
organizer = null,
124+
flags = null,
125+
openRoom = null
126+
)
118127
}
119-
_authState.update { AuthState.LoggedOut }
120128
}
129+
121130
}

0 commit comments

Comments
 (0)