Rewrite FoldersViewModel to use Flow
This commit is contained in:
parent
a36d7e9d78
commit
288486e247
5 changed files with 77 additions and 28 deletions
|
@ -29,6 +29,10 @@ object DI {
|
|||
fun <T : Any> get(clazz: Class<T>): T {
|
||||
return koinGet(clazz)
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> get(): T {
|
||||
return koinGet(T::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
interface EarlyInit
|
||||
|
|
|
@ -2,6 +2,9 @@ package com.fsck.k9.mailstore
|
|||
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.Account.FolderMode
|
||||
import com.fsck.k9.DI
|
||||
import com.fsck.k9.controller.MessagingController
|
||||
import com.fsck.k9.controller.SimpleMessagingListener
|
||||
import com.fsck.k9.mail.FolderClass
|
||||
import com.fsck.k9.preferences.AccountManager
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
|
@ -52,6 +55,42 @@ class FolderRepository(
|
|||
}.sortedWith(sortForDisplay)
|
||||
}
|
||||
|
||||
fun getDisplayFoldersFlow(account: Account, displayMode: FolderMode): Flow<List<DisplayFolder>> {
|
||||
val messagingController = DI.get<MessagingController>()
|
||||
|
||||
return callbackFlow {
|
||||
send(getDisplayFolders(account, displayMode))
|
||||
|
||||
val listener = object : SimpleMessagingListener() {
|
||||
override fun folderStatusChanged(statusChangedAccount: Account, folderId: Long) {
|
||||
if (statusChangedAccount.uuid == account.uuid) {
|
||||
launch {
|
||||
send(getDisplayFolders(account, displayMode))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
messagingController.addListener(listener)
|
||||
|
||||
awaitClose {
|
||||
messagingController.removeListener(listener)
|
||||
}
|
||||
}.buffer(capacity = Channel.CONFLATED)
|
||||
.distinctUntilChanged()
|
||||
.flowOn(ioDispatcher)
|
||||
}
|
||||
|
||||
fun getDisplayFoldersFlow(account: Account): Flow<List<DisplayFolder>> {
|
||||
return accountManager.getAccountFlow(account.uuid)
|
||||
.map { latestAccount ->
|
||||
AccountContainer(latestAccount, latestAccount.folderDisplayMode)
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest { (account, folderDisplayMode) ->
|
||||
getDisplayFoldersFlow(account, folderDisplayMode)
|
||||
}
|
||||
}
|
||||
|
||||
fun getFolder(account: Account, folderId: Long): Folder? {
|
||||
val messageStore = messageStoreManager.getMessageStore(account)
|
||||
return messageStore.getFolder(folderId) { folder ->
|
||||
|
@ -244,6 +283,11 @@ class FolderRepository(
|
|||
get() = if (syncClass == FolderClass.INHERITED) displayClass else syncClass
|
||||
}
|
||||
|
||||
private data class AccountContainer(
|
||||
val account: Account,
|
||||
val folderDisplayMode: FolderMode
|
||||
)
|
||||
|
||||
data class Folder(val id: Long, val name: String, val type: FolderType, val isLocalOnly: Boolean)
|
||||
|
||||
data class RemoteFolder(val id: Long, val serverId: String, val name: String, val type: FolderType)
|
||||
|
|
|
@ -94,6 +94,7 @@ class K9Drawer(private val parent: MessageList, savedInstanceState: Bundle?) : K
|
|||
private var folderBadgeStyle: BadgeStyle? = null
|
||||
private var openedAccountUuid: String? = null
|
||||
private var openedFolderId: Long? = null
|
||||
private var latestFolderList: List<DisplayFolder>? = null
|
||||
|
||||
val layout: DrawerLayout
|
||||
get() = drawer
|
||||
|
@ -292,7 +293,7 @@ class K9Drawer(private val parent: MessageList, savedInstanceState: Bundle?) : K
|
|||
|
||||
if (oldSelectedBackgroundColor != selectedBackgroundColor) {
|
||||
// Recreate list of folders with updated account color
|
||||
setUserFolders(foldersViewModel.getFolderListLiveData().value)
|
||||
setUserFolders(latestFolderList)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,6 +353,7 @@ class K9Drawer(private val parent: MessageList, savedInstanceState: Bundle?) : K
|
|||
}
|
||||
|
||||
private fun setUserFolders(folders: List<DisplayFolder>?) {
|
||||
this.latestFolderList = folders
|
||||
clearUserFolders()
|
||||
|
||||
var openedFolderDrawerId: Long = -1
|
||||
|
|
|
@ -1,42 +1,41 @@
|
|||
package com.fsck.k9.ui.folders
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.mailstore.DisplayFolder
|
||||
import com.fsck.k9.mailstore.FolderRepository
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class FoldersViewModel(private val foldersLiveDataFactory: FoldersLiveDataFactory) : ViewModel() {
|
||||
private var currentFoldersLiveData: FoldersLiveData? = null
|
||||
private val foldersLiveData = MediatorLiveData<List<DisplayFolder>>()
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class FoldersViewModel(private val folderRepository: FolderRepository) : ViewModel() {
|
||||
private val inputFlow = MutableSharedFlow<Account?>(replay = 1)
|
||||
private val foldersFlow = inputFlow
|
||||
.flatMapLatest { account ->
|
||||
if (account == null) {
|
||||
flowOf(emptyList())
|
||||
} else {
|
||||
folderRepository.getDisplayFoldersFlow(account)
|
||||
}
|
||||
}
|
||||
|
||||
fun getFolderListLiveData(): LiveData<List<DisplayFolder>> {
|
||||
return foldersLiveData
|
||||
return foldersFlow.asLiveData()
|
||||
}
|
||||
|
||||
fun loadFolders(account: Account) {
|
||||
if (currentFoldersLiveData?.account?.uuid == account.uuid) return
|
||||
viewModelScope.launch {
|
||||
// When switching accounts we want to remove the old list right away, not keep it until the new list
|
||||
// has been loaded.
|
||||
inputFlow.emit(null)
|
||||
|
||||
removeCurrentFoldersLiveData()
|
||||
|
||||
val liveData = foldersLiveDataFactory.create(account)
|
||||
currentFoldersLiveData = liveData
|
||||
|
||||
foldersLiveData.addSource(liveData) { items ->
|
||||
foldersLiveData.value = items
|
||||
}
|
||||
}
|
||||
|
||||
fun stopLoadingFolders() {
|
||||
removeCurrentFoldersLiveData()
|
||||
foldersLiveData.value = null
|
||||
}
|
||||
|
||||
private fun removeCurrentFoldersLiveData() {
|
||||
currentFoldersLiveData?.let {
|
||||
foldersLiveData.value = emptyList()
|
||||
currentFoldersLiveData = null
|
||||
foldersLiveData.removeSource(it)
|
||||
inputFlow.emit(account)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,5 +8,5 @@ val foldersUiModule = module {
|
|||
single { FolderNameFormatterFactory() }
|
||||
factory { (context: Context) -> FolderNameFormatter(context.resources) }
|
||||
single { FoldersLiveDataFactory(get(), get(), get()) }
|
||||
viewModel { FoldersViewModel(get()) }
|
||||
viewModel { FoldersViewModel(folderRepository = get()) }
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue