fix: smoother account switch (#570)

This commit is contained in:
Diego Beraldin 2024-03-05 21:11:58 +01:00 committed by GitHub
parent b5cb415737
commit 6d03b3b327
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 41 additions and 33 deletions

View File

@ -3,12 +3,10 @@ package com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.AccountRepository
import com.github.diegoberaldin.raccoonforlemmy.core.utils.network.NetworkManager
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
internal class DefaultIdentityRepository(
private val accountRepository: AccountRepository,
@ -16,25 +14,21 @@ internal class DefaultIdentityRepository(
private val networkManager: NetworkManager,
) : IdentityRepository {
private val scope = CoroutineScope(SupervisorJob())
override val authToken = MutableStateFlow<String?>(null)
override val isLogged = MutableStateFlow<Boolean?>(null)
init {
scope.launch {
val account = accountRepository.getActive()
if (account != null) {
authToken.value = account.jwt
} else {
authToken.value = ""
}
refreshLoggedState()
override suspend fun startup() = withContext(Dispatchers.IO) {
val account = accountRepository.getActive()
if (account != null) {
authToken.value = account.jwt
} else {
authToken.value = ""
}
refreshLoggedState()
}
override fun storeToken(jwt: String) {
authToken.value = jwt
refreshLoggedState()
}
override fun clearToken() {
@ -42,20 +36,18 @@ internal class DefaultIdentityRepository(
isLogged.value = false
}
override fun refreshLoggedState() {
scope.launch(Dispatchers.IO) {
val auth = authToken.value.orEmpty()
if (auth.isEmpty()) {
isLogged.value = false
override suspend fun refreshLoggedState() = withContext(Dispatchers.IO) {
val auth = authToken.value.orEmpty()
if (auth.isEmpty()) {
isLogged.value = false
} else {
val newIsLogged = if (networkManager.isNetworkAvailable()) {
val currentUser = siteRepository.getCurrentUser(auth)
currentUser != null
} else {
val newIsLogged = if (networkManager.isNetworkAvailable()) {
val currentUser = siteRepository.getCurrentUser(auth)
currentUser != null
} else {
null
}
isLogged.value = newIsLogged
null
}
isLogged.value = newIsLogged
}
}
}

View File

@ -7,11 +7,13 @@ interface IdentityRepository {
val authToken: StateFlow<String?>
val isLogged: StateFlow<Boolean?>
suspend fun startup()
fun storeToken(
jwt: String,
)
fun clearToken()
fun refreshLoggedState()
suspend fun refreshLoggedState()
}

View File

@ -25,7 +25,6 @@ internal class DefaultSwitchAccountUseCase(
accountRepository.setActive(oldActiveAccountId, false)
}
accountRepository.setActive(accountId, true)
identityRepository.clearToken()
notificationCenter.send(NotificationCenterEvent.Logout)
serviceProvider.changeInstance(instance)
identityRepository.storeToken(jwt)

View File

@ -1,6 +1,7 @@
package com.github.diegoberaldin.raccoonforlemmy
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.inbox.InboxCoordinator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
@ -10,6 +11,7 @@ import kotlinx.coroutines.launch
class MainViewModel(
private val inboxCoordinator: InboxCoordinator,
private val identityRepository: IdentityRepository,
) : MainScreenMviModel,
DefaultMviModel<MainScreenMviModel.Intent, MainScreenMviModel.UiState, MainScreenMviModel.Effect>(
initialState = MainScreenMviModel.UiState(),
@ -18,6 +20,8 @@ class MainViewModel(
override fun onStarted() {
super.onStarted()
scope?.launch(Dispatchers.IO) {
identityRepository.startup()
inboxCoordinator.totalUnread.onEach { unreadCount ->
emitEffect(MainScreenMviModel.Effect.UnreadItemsDetected(unreadCount))
}.launchIn(this)

View File

@ -10,6 +10,7 @@ internal val internalSharedModule = module {
factory<MainScreenMviModel> {
MainViewModel(
inboxCoordinator = get(),
identityRepository = get(),
)
}
single<DetailOpener> {

View File

@ -1,6 +1,8 @@
package com.github.diegoberaldin.raccoonforlemmy.unit.drawer
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationCenter
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationCenterEvent
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.AccountRepository
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.FavoriteCommunityRepository
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.MultiCommunityRepository
@ -38,6 +40,7 @@ class ModalDrawerViewModel(
private val apiConfigurationRepository: ApiConfigurationRepository,
private val settingsRepository: SettingsRepository,
private val favoriteCommunityRepository: FavoriteCommunityRepository,
private val notificationCenter: NotificationCenter,
) : ModalDrawerMviModel,
DefaultMviModel<ModalDrawerMviModel.Intent, ModalDrawerMviModel.UiState, ModalDrawerMviModel.Effect>(
initialState = ModalDrawerMviModel.UiState()
@ -60,6 +63,12 @@ class ModalDrawerViewModel(
refresh()
}.launchIn(this)
notificationCenter.subscribe(NotificationCenterEvent.Logout::class).onEach {
delay(250)
refreshUser()
refresh()
}.launchIn(this)
settingsRepository.currentSettings.onEach { settings ->
updateState {
it.copy(

View File

@ -15,6 +15,7 @@ val drawerModule = module {
multiCommunityRepository = get(),
settingsRepository = get(),
favoriteCommunityRepository = get(),
notificationCenter = get(),
)
}
}

View File

@ -92,6 +92,10 @@ class ProfileLoggedViewModel(
notificationCenter.subscribe(NotificationCenterEvent.Share::class).onEach { evt ->
shareHelper.share(evt.url)
}.launchIn(this)
notificationCenter.subscribe(NotificationCenterEvent.Logout::class).onEach {
delay(250)
refreshUser()
}.launchIn(this)
if (uiState.value.posts.isEmpty()) {
withContext(Dispatchers.IO) {
@ -193,7 +197,7 @@ class ProfileLoggedViewModel(
updateState {
it.copy(
user = user,
moderatedCommunityIds = moderatedCommunities.map { c -> c.id },
moderatedCommunityIds = moderatedCommunities.map { c -> c.id },
)
}
}

View File

@ -28,7 +28,6 @@ internal fun ProfileShortcutSection(
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
) {
SettingsRow(
modifier = modifier.padding(vertical = Spacing.xxs),
icon = Icons.Default.Bookmark,
title = LocalXmlStrings.current.navigationDrawerTitleBookmarks,
disclosureIndicator = true,
@ -36,7 +35,6 @@ internal fun ProfileShortcutSection(
)
SettingsRow(
modifier = Modifier.padding(vertical = Spacing.xxs),
icon = Icons.Default.SettingsApplications,
title = LocalXmlStrings.current.navigationDrawerTitleSubscriptions,
disclosureIndicator = true,
@ -44,7 +42,6 @@ internal fun ProfileShortcutSection(
)
SettingsRow(
modifier = Modifier.padding(vertical = Spacing.xxs),
icon = Icons.Default.Drafts,
title = LocalXmlStrings.current.navigationDrawerTitleDrafts,
disclosureIndicator = true,
@ -53,7 +50,6 @@ internal fun ProfileShortcutSection(
if (isMod) {
SettingsRow(
modifier = Modifier.padding(vertical = Spacing.xxs),
icon = Icons.AutoMirrored.Default.Message,
title = LocalXmlStrings.current.moderatorZoneTitle,
disclosureIndicator = true,