From 5f0e39d5e48fe2f1b345adf7dc57d9453e97336a Mon Sep 17 00:00:00 2001 From: John Oberhauser Date: Thu, 20 Jun 2024 15:45:38 -0400 Subject: [PATCH] saving --- .../firefly/core/accounts/AccountsManager.kt | 23 ++++++++++++ core/repository/paging/build.gradle.kts | 2 +- .../HomeTimelineRemoteMediator.kt | 25 ++----------- .../usecase/mastodon/account/GetDomain.kt | 10 +++--- .../account/GetLoggedInUserAccountId.kt | 12 ++----- .../mastodon/auth/SwitchActiveAccount.kt | 13 +++---- feature/feed/build.gradle.kts | 1 + .../firefly/feature/feed/FeedViewModel.kt | 10 +++--- feature/post/build.gradle.kts | 1 + feature/settings/build.gradle.kts | 1 + .../account/AccountSettingsViewModel.kt | 35 +++++++++---------- .../settings/account/LoggedInAccount.kt | 10 +++--- feature/thread/build.gradle.kts | 1 + 13 files changed, 70 insertions(+), 74 deletions(-) diff --git a/core/accounts/src/main/kotlin/social/firefly/core/accounts/AccountsManager.kt b/core/accounts/src/main/kotlin/social/firefly/core/accounts/AccountsManager.kt index 72cd536b2..f975e02e9 100644 --- a/core/accounts/src/main/kotlin/social/firefly/core/accounts/AccountsManager.kt +++ b/core/accounts/src/main/kotlin/social/firefly/core/accounts/AccountsManager.kt @@ -101,4 +101,27 @@ class AccountsManager( ) ) } + + suspend fun setActiveAccount( + mastodonAccount: MastodonAccount, + ) { + activeAccountDao.upsert( + ActiveAccount( + accountType = AccountType.MASTODON, + accountId = mastodonAccount.accountId, + domain = mastodonAccount.domain, + ) + ) + } + + suspend fun updateLastSeenHomeStatusId( + mastodonAccount: MastodonAccount, + lastSeenStatusId: String, + ) { + mastodonAccountsDao.upsert( + mastodonAccount.copy( + lastSeenHomeStatusId = lastSeenStatusId, + ) + ) + } } \ No newline at end of file diff --git a/core/repository/paging/build.gradle.kts b/core/repository/paging/build.gradle.kts index 5cf73dc3a..d397e1d40 100644 --- a/core/repository/paging/build.gradle.kts +++ b/core/repository/paging/build.gradle.kts @@ -12,7 +12,7 @@ dependencies { implementation(project(":core:usecase:mastodon")) implementation(project(":core:common")) implementation(project(":core:model")) - implementation(project(":core:datastore")) + implementation(project(":core:accounts")) implementation(libs.androidx.paging.runtime) implementation(libs.jakewharton.timber) diff --git a/core/repository/paging/src/main/kotlin/social/firefly/core/repository/paging/remotemediators/HomeTimelineRemoteMediator.kt b/core/repository/paging/src/main/kotlin/social/firefly/core/repository/paging/remotemediators/HomeTimelineRemoteMediator.kt index 7ecb1d94b..7c4d9a4ad 100644 --- a/core/repository/paging/src/main/kotlin/social/firefly/core/repository/paging/remotemediators/HomeTimelineRemoteMediator.kt +++ b/core/repository/paging/src/main/kotlin/social/firefly/core/repository/paging/remotemediators/HomeTimelineRemoteMediator.kt @@ -4,17 +4,10 @@ import androidx.paging.ExperimentalPagingApi import androidx.paging.LoadType import androidx.paging.PagingState import androidx.paging.RemoteMediator -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.cancel import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.launch import social.firefly.common.Rel +import social.firefly.core.accounts.AccountsManager import social.firefly.core.database.model.entities.statusCollections.HomeTimelineStatusWrapper -import social.firefly.core.datastore.UserPreferencesDatastoreManager import social.firefly.core.model.Status import social.firefly.core.model.paging.MastodonPagedResponse import social.firefly.core.repository.mastodon.DatabaseDelegate @@ -30,7 +23,7 @@ class HomeTimelineRemoteMediator( private val saveStatusToDatabase: SaveStatusToDatabase, private val databaseDelegate: DatabaseDelegate, private val getInReplyToAccountNames: GetInReplyToAccountNames, - private val userPreferencesDatastoreManager: UserPreferencesDatastoreManager, + private val accountsManager: AccountsManager, ) : RemoteMediator() { private var firstRefreshHasHappened = false @@ -110,7 +103,6 @@ class HomeTimelineRemoteMediator( } } - @OptIn(ExperimentalCoroutinesApi::class) private suspend fun fetchRefresh( state: PagingState, ): MastodonPagedResponse { @@ -120,18 +112,7 @@ class HomeTimelineRemoteMediator( // If this is the first time we are loading the page, we need to start where // the user last left off. Grab the lastSeenHomeStatusId if (!firstRefreshHasHappened) { - val lastSeenId = CompletableDeferred() - with(CoroutineScope(coroutineContext)) { - launch { - userPreferencesDatastoreManager.activeUserDatastore.flatMapLatest { - it.lastSeenHomeStatusId - }.collectLatest { - lastSeenId.complete(it) - cancel() - } - } - } - olderThanId = lastSeenId.await() + olderThanId = accountsManager.getActiveAccount().lastSeenHomeStatusId } val mainResponse = timelineRepository.getHomeTimeline( diff --git a/core/usecase/mastodon/src/main/kotlin/social/firefly/core/usecase/mastodon/account/GetDomain.kt b/core/usecase/mastodon/src/main/kotlin/social/firefly/core/usecase/mastodon/account/GetDomain.kt index ee2a10214..1ffe34396 100644 --- a/core/usecase/mastodon/src/main/kotlin/social/firefly/core/usecase/mastodon/account/GetDomain.kt +++ b/core/usecase/mastodon/src/main/kotlin/social/firefly/core/usecase/mastodon/account/GetDomain.kt @@ -2,14 +2,12 @@ package social.firefly.core.usecase.mastodon.account import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flatMapLatest -import social.firefly.core.datastore.UserPreferencesDatastoreManager +import kotlinx.coroutines.flow.mapLatest +import social.firefly.core.accounts.AccountsManager class GetDomain( - private val userPreferencesDatastoreManager: UserPreferencesDatastoreManager, + private val accountsManager: AccountsManager, ) { @OptIn(ExperimentalCoroutinesApi::class) - operator fun invoke(): Flow = userPreferencesDatastoreManager.activeUserDatastore.flatMapLatest { - it.domain - } + operator fun invoke(): Flow = accountsManager.getActiveAccountFlow().mapLatest { it.domain } } \ No newline at end of file diff --git a/core/usecase/mastodon/src/main/kotlin/social/firefly/core/usecase/mastodon/account/GetLoggedInUserAccountId.kt b/core/usecase/mastodon/src/main/kotlin/social/firefly/core/usecase/mastodon/account/GetLoggedInUserAccountId.kt index 0f4053147..2fbe4cd06 100644 --- a/core/usecase/mastodon/src/main/kotlin/social/firefly/core/usecase/mastodon/account/GetLoggedInUserAccountId.kt +++ b/core/usecase/mastodon/src/main/kotlin/social/firefly/core/usecase/mastodon/account/GetLoggedInUserAccountId.kt @@ -1,22 +1,16 @@ package social.firefly.core.usecase.mastodon.account -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.runBlocking -import social.firefly.core.datastore.UserPreferencesDatastoreManager +import social.firefly.core.accounts.AccountsManager /** * Synchronously gets the account ID of the current logged in user */ class GetLoggedInUserAccountId( - private val userPreferencesDatastoreManager: UserPreferencesDatastoreManager, + private val accountsManager: AccountsManager, ) { - @OptIn(ExperimentalCoroutinesApi::class) operator fun invoke(): String = runBlocking { - userPreferencesDatastoreManager.activeUserDatastore.flatMapLatest { - it.accountId - }.first() + accountsManager.getActiveAccount().accountId } } diff --git a/core/usecase/mastodon/src/main/kotlin/social/firefly/core/usecase/mastodon/auth/SwitchActiveAccount.kt b/core/usecase/mastodon/src/main/kotlin/social/firefly/core/usecase/mastodon/auth/SwitchActiveAccount.kt index c94b9cda0..6780a98c7 100644 --- a/core/usecase/mastodon/src/main/kotlin/social/firefly/core/usecase/mastodon/auth/SwitchActiveAccount.kt +++ b/core/usecase/mastodon/src/main/kotlin/social/firefly/core/usecase/mastodon/auth/SwitchActiveAccount.kt @@ -1,29 +1,26 @@ package social.firefly.core.usecase.mastodon.auth import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.first import kotlinx.coroutines.withContext -import social.firefly.core.datastore.AppPreferencesDatastore -import social.firefly.core.datastore.UserPreferencesDatastoreManager +import social.firefly.core.accounts.AccountsManager import social.firefly.core.navigation.NavigationDestination import social.firefly.core.navigation.usecases.NavigateTo import social.firefly.core.repository.mastodon.DatabaseDelegate class SwitchActiveAccount( - private val userPreferencesDatastoreManager: UserPreferencesDatastoreManager, - private val appPreferencesDatastore: AppPreferencesDatastore, private val databaseDelegate: DatabaseDelegate, private val navigateTo: NavigateTo, + private val accountsManager: AccountsManager, ){ suspend operator fun invoke( accountId: String, domain: String, ) { - userPreferencesDatastoreManager.dataStores.value.find { - it.accountId.first() == accountId && it.domain.first() == domain + accountsManager.getAllAccounts().find { + it.accountId == accountId && it.domain == domain }?.let { - appPreferencesDatastore.saveActiveUserDatastoreFilename(it.fileName) + accountsManager.setActiveAccount(it) } withContext(Dispatchers.IO) { diff --git a/feature/feed/build.gradle.kts b/feature/feed/build.gradle.kts index 0f10dbf43..51fc1702e 100644 --- a/feature/feed/build.gradle.kts +++ b/feature/feed/build.gradle.kts @@ -21,6 +21,7 @@ dependencies { implementation(project(":core:ui:common")) implementation(project(":core:ui:postcard")) implementation(project(":core:usecase:mastodon")) + implementation(project(":core:accounts")) implementation(libs.androidx.paging.runtime) diff --git a/feature/feed/src/main/kotlin/social/firefly/feature/feed/FeedViewModel.kt b/feature/feed/src/main/kotlin/social/firefly/feature/feed/FeedViewModel.kt index 235d06efc..fc67df306 100644 --- a/feature/feed/src/main/kotlin/social/firefly/feature/feed/FeedViewModel.kt +++ b/feature/feed/src/main/kotlin/social/firefly/feature/feed/FeedViewModel.kt @@ -9,15 +9,14 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import org.koin.core.parameter.parametersOf import org.koin.java.KoinJavaComponent import social.firefly.common.utils.edit +import social.firefly.core.accounts.AccountsManager import social.firefly.core.analytics.FeedAnalytics import social.firefly.core.analytics.FeedLocation -import social.firefly.core.datastore.UserPreferencesDatastoreManager import social.firefly.core.navigation.BottomBarNavigationDestination import social.firefly.core.navigation.usecases.NavigateTo import social.firefly.core.repository.mastodon.TimelineRepository @@ -31,13 +30,13 @@ import social.firefly.core.usecase.mastodon.account.GetLoggedInUserAccountId @OptIn(ExperimentalPagingApi::class) class FeedViewModel( private val analytics: FeedAnalytics, - private val userPreferencesDatastoreManager: UserPreferencesDatastoreManager, homeTimelineRemoteMediator: HomeTimelineRemoteMediator, localTimelinePager: LocalTimelinePager, federatedTimelinePager: FederatedTimelinePager, private val timelineRepository: TimelineRepository, getLoggedInUserAccountId: GetLoggedInUserAccountId, private val navigateTo: NavigateTo, + private val accountsManager: AccountsManager, ) : ViewModel(), FeedInteractions { private val userAccountId: String = getLoggedInUserAccountId() @@ -114,7 +113,10 @@ class FeedViewModel( // save the last seen status no more than once per x seconds (SAVE_RATE) if (statusViewedJob == null) { statusViewedJob = viewModelScope.launch { - userPreferencesDatastoreManager.activeUserDatastore.first().saveLastSeenHomeStatusId(statusId) + accountsManager.updateLastSeenHomeStatusId( + mastodonAccount = accountsManager.getActiveAccount(), + lastSeenStatusId = statusId, + ) delay(SAVE_RATE) statusViewedJob = null } diff --git a/feature/post/build.gradle.kts b/feature/post/build.gradle.kts index de3bbd39c..2c0ea4bcf 100644 --- a/feature/post/build.gradle.kts +++ b/feature/post/build.gradle.kts @@ -19,6 +19,7 @@ dependencies { implementation(project(":core:analytics")) implementation(project(":core:ui:htmlcontent")) implementation(project(":core:share")) + implementation(project(":core:accounts")) implementation(libs.androidx.navigation.compose) implementation(libs.koin.core) diff --git a/feature/settings/build.gradle.kts b/feature/settings/build.gradle.kts index 0286f1409..afcdbdb52 100644 --- a/feature/settings/build.gradle.kts +++ b/feature/settings/build.gradle.kts @@ -25,6 +25,7 @@ dependencies { implementation(project(":core:ui:htmlcontent")) implementation(project(":core:usecase:mastodon")) implementation(project(":core:workmanager")) + implementation(project(":core:accounts")) implementation(libs.androidx.navigation.compose) implementation(libs.androidx.datastore) diff --git a/feature/settings/src/main/kotlin/social/firefly/feature/settings/account/AccountSettingsViewModel.kt b/feature/settings/src/main/kotlin/social/firefly/feature/settings/account/AccountSettingsViewModel.kt index f979ec3f8..a902c59a5 100644 --- a/feature/settings/src/main/kotlin/social/firefly/feature/settings/account/AccountSettingsViewModel.kt +++ b/feature/settings/src/main/kotlin/social/firefly/feature/settings/account/AccountSettingsViewModel.kt @@ -3,11 +3,10 @@ package social.firefly.feature.settings.account import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch +import social.firefly.core.accounts.AccountsManager import social.firefly.core.analytics.SettingsAnalytics -import social.firefly.core.datastore.UserPreferencesDatastoreManager import social.firefly.core.navigation.AuthNavigationDestination import social.firefly.core.navigation.usecases.NavigateTo import social.firefly.core.navigation.usecases.OpenLink @@ -24,31 +23,31 @@ class AccountSettingsViewModel( private val navigateTo: NavigateTo, private val switchActiveAccount: SwitchActiveAccount, private val logoutOfAllAccounts: LogoutOfAllAccounts, - userPreferencesDatastoreManager: UserPreferencesDatastoreManager, updateAllLoggedInAccounts: UpdateAllLoggedInAccounts, + private val accountsManager: AccountsManager, ) : ViewModel(), AccountSettingsInteractions { - val otherAccounts = userPreferencesDatastoreManager.dataStores.combine( - userPreferencesDatastoreManager.activeUserDatastore - ) { dataStores, activeDataStore -> - dataStores.filterNot { - it == activeDataStore - }.map { dataStore -> + val otherAccounts = accountsManager.getAllAccountsFlow().combine( + accountsManager.getActiveAccountFlow() + ) { otherAccounts, activeAccount -> + otherAccounts.filterNot { + it == activeAccount + }.map { account -> LoggedInAccount( - accountId = dataStore.accountId, - userName = dataStore.userName, - domain = dataStore.domain, - avatarUrl = dataStore.avatarUrl, + accountId = account.accountId, + userName = account.userName, + domain = account.domain, + avatarUrl = account.avatarUrl, ) } } - val activeAccount = userPreferencesDatastoreManager.activeUserDatastore.map { dataStore -> + val activeAccount = accountsManager.getActiveAccountFlow().map { account -> LoggedInAccount( - accountId = dataStore.accountId, - userName = dataStore.userName, - domain = dataStore.domain, - avatarUrl = dataStore.avatarUrl, + accountId = account.accountId, + userName = account.userName, + domain = account.domain, + avatarUrl = account.avatarUrl, ) } diff --git a/feature/settings/src/main/kotlin/social/firefly/feature/settings/account/LoggedInAccount.kt b/feature/settings/src/main/kotlin/social/firefly/feature/settings/account/LoggedInAccount.kt index 5840f7ad3..2308d0521 100644 --- a/feature/settings/src/main/kotlin/social/firefly/feature/settings/account/LoggedInAccount.kt +++ b/feature/settings/src/main/kotlin/social/firefly/feature/settings/account/LoggedInAccount.kt @@ -1,10 +1,8 @@ package social.firefly.feature.settings.account -import kotlinx.coroutines.flow.Flow - data class LoggedInAccount( - val accountId: Flow, - val userName: Flow, - val domain: Flow, - val avatarUrl: Flow, + val accountId: String, + val userName: String, + val domain: String, + val avatarUrl: String, ) diff --git a/feature/thread/build.gradle.kts b/feature/thread/build.gradle.kts index 916e3e034..c93945cc7 100644 --- a/feature/thread/build.gradle.kts +++ b/feature/thread/build.gradle.kts @@ -19,6 +19,7 @@ dependencies { implementation(project(":core:common")) implementation(project(":core:navigation")) implementation(project(":core:analytics")) + implementation(project(":core:accounts")) implementation(libs.androidx.paging.runtime)