Fix main-thread decryption block by caching token in StateFlow (#322)
Issue #278 reported that `AuthManager.getToken()` (which reads from `EncryptedSharedPreferences`) was being called synchronously inside the `MainNavigation` composable, causing UI thread blocks during navigation transitions (PERF-10). This commit resolves the issue by caching the token in a new `tokenFlow` (`MutableStateFlow`) within `AuthManager`. - The flow is initialised with the token during `AuthManager.init()`. - Updates to the token (`setToken`, `setSelectedProfileId`, `setProfileToken`) are synchronised with `tokenFlow`. - `MainNavigation` now correctly observes this state using `collectAsState()`, preventing disk-read blocking on recompositions. Impact: Navigation transitions are now fully non-blocking. No side effects are expected as state synchronisation maintains parity with persistent storage. Resolves #278
This commit is contained in:
2 files changed
+12
-1
No files matched your search
@@ -326,7 +326,8 @@ private fun appEntryProvider(
|
||||
|
||||
@Composable
|
||||
fun MainNavigation(sessionId: String? = null) {
|
||||
val hasToken = !AuthManager.getToken().isNullOrBlank()
|
||||
val token by AuthManager.tokenFlow.collectAsState()
|
||||
val hasToken = !token.isNullOrBlank()
|
||||
val startScreen: NavKey = if (hasToken) ChatScreen else ConnectScreen
|
||||
|
||||
val backStack = rememberNavBackStack(startScreen)
|
||||
|
||||
@@ -57,6 +57,10 @@ object AuthManager {
|
||||
|
||||
private val _bottomNavDisplayModeFlow = MutableStateFlow<BottomNavDisplayMode>(BottomNavDisplayMode.ICON_AND_TEXT)
|
||||
val bottomNavDisplayModeFlow: StateFlow<BottomNavDisplayMode> = _bottomNavDisplayModeFlow.asStateFlow()
|
||||
|
||||
private val _tokenFlow = MutableStateFlow<String?>(null)
|
||||
val tokenFlow: StateFlow<String?> = _tokenFlow.asStateFlow()
|
||||
|
||||
private val gson = com.google.gson.Gson()
|
||||
|
||||
/**
|
||||
@@ -84,6 +88,7 @@ object AuthManager {
|
||||
_useDynamicColorsFlow.value = isUseDynamicColors()
|
||||
_themePresetFlow.value = getThemePreset()
|
||||
_bottomNavDisplayModeFlow.value = getBottomNavDisplayMode()
|
||||
_tokenFlow.value = getToken()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +127,9 @@ object AuthManager {
|
||||
token: String?,
|
||||
) {
|
||||
requirePrefs().edit().putString("token_$profileId", token).apply()
|
||||
if (getSelectedProfileId() == profileId) {
|
||||
_tokenFlow.value = token
|
||||
}
|
||||
}
|
||||
|
||||
fun getSelectedProfileId(): String? {
|
||||
@@ -131,6 +139,7 @@ object AuthManager {
|
||||
|
||||
fun setSelectedProfileId(id: String?) {
|
||||
requirePrefs().edit().putString(KEY_SELECTED_PROFILE_ID, id).apply()
|
||||
_tokenFlow.value = getToken()
|
||||
}
|
||||
|
||||
// ── Token ────────────────────────────────────────────────────────────
|
||||
@@ -150,6 +159,7 @@ object AuthManager {
|
||||
setProfileToken(selectedId, token)
|
||||
} else {
|
||||
requirePrefs().edit().putString(KEY_TOKEN, token).apply()
|
||||
_tokenFlow.value = token
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user