Merge pull request #5640 from k9mail/remove_FoldersLiveData
Remove FoldersLiveData
This commit is contained in:
commit
a40189167c
11 changed files with 120 additions and 145 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
|
||||
|
|
|
@ -7,7 +7,6 @@ import android.os.Bundle
|
|||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.Account.FolderMode
|
||||
|
@ -20,7 +19,6 @@ import com.fsck.k9.ui.R
|
|||
import com.fsck.k9.ui.base.K9Activity
|
||||
import com.fsck.k9.ui.folders.FolderIconProvider
|
||||
import com.fsck.k9.ui.folders.FolderNameFormatter
|
||||
import com.fsck.k9.ui.folders.FoldersLiveData
|
||||
import com.mikepenz.fastadapter.FastAdapter
|
||||
import com.mikepenz.fastadapter.adapters.ItemAdapter
|
||||
import java.util.Locale
|
||||
|
@ -42,11 +40,6 @@ class ChooseFolderActivity : K9Activity() {
|
|||
private var scrollToFolderId: Long? = null
|
||||
private var messageReference: String? = null
|
||||
private var showDisplayableOnly = false
|
||||
private var foldersLiveData: FoldersLiveData? = null
|
||||
|
||||
private val folderListObserver = Observer<List<DisplayFolder>> { folders ->
|
||||
updateFolderList(folders)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -60,12 +53,14 @@ class ChooseFolderActivity : K9Activity() {
|
|||
|
||||
initializeFolderList()
|
||||
|
||||
viewModel.getFolders().observe(this) { folders ->
|
||||
updateFolderList(folders)
|
||||
}
|
||||
|
||||
val savedDisplayMode = savedInstanceState?.getString(STATE_DISPLAY_MODE)?.let { FolderMode.valueOf(it) }
|
||||
val displayMode = savedDisplayMode ?: getInitialDisplayMode()
|
||||
|
||||
foldersLiveData = viewModel.getFolders(account, displayMode).apply {
|
||||
observe(this@ChooseFolderActivity, folderListObserver)
|
||||
}
|
||||
viewModel.setDisplayMode(account, displayMode)
|
||||
}
|
||||
|
||||
private fun decodeArguments(savedInstanceState: Bundle?): Boolean {
|
||||
|
@ -137,7 +132,7 @@ class ChooseFolderActivity : K9Activity() {
|
|||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
scrollToFolderId?.let { folderId -> outState.putLong(STATE_SCROLL_TO_FOLDER_ID, folderId) }
|
||||
outState.putString(STATE_DISPLAY_MODE, foldersLiveData?.displayMode?.name)
|
||||
outState.putString(STATE_DISPLAY_MODE, viewModel.currentDisplayMode?.name)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
|
@ -181,10 +176,7 @@ class ChooseFolderActivity : K9Activity() {
|
|||
}
|
||||
|
||||
private fun setDisplayMode(displayMode: FolderMode) {
|
||||
foldersLiveData?.removeObserver(folderListObserver)
|
||||
foldersLiveData = viewModel.getFolders(account, displayMode).apply {
|
||||
observe(this@ChooseFolderActivity, folderListObserver)
|
||||
}
|
||||
viewModel.setDisplayMode(account, displayMode)
|
||||
}
|
||||
|
||||
private fun returnResult(folderId: Long, displayName: String) {
|
||||
|
|
|
@ -1,22 +1,39 @@
|
|||
package com.fsck.k9.ui.choosefolder
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.Account.FolderMode
|
||||
import com.fsck.k9.ui.folders.FoldersLiveData
|
||||
import com.fsck.k9.ui.folders.FoldersLiveDataFactory
|
||||
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.launch
|
||||
|
||||
class ChooseFolderViewModel(private val foldersLiveDataFactory: FoldersLiveDataFactory) : ViewModel() {
|
||||
private var foldersLiveData: FoldersLiveData? = null
|
||||
|
||||
fun getFolders(account: Account, displayMode: FolderMode): FoldersLiveData {
|
||||
val liveData = foldersLiveData
|
||||
if (liveData != null && liveData.account.uuid == account.uuid && liveData.displayMode == displayMode) {
|
||||
return liveData
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class ChooseFolderViewModel(private val folderRepository: FolderRepository) : ViewModel() {
|
||||
private val inputFlow = MutableSharedFlow<DisplayMode>(replay = 1)
|
||||
private val foldersFlow = inputFlow
|
||||
.flatMapLatest { (account, displayMode) ->
|
||||
folderRepository.getDisplayFoldersFlow(account, displayMode)
|
||||
}
|
||||
|
||||
return foldersLiveDataFactory.create(account, displayMode).also {
|
||||
foldersLiveData = it
|
||||
var currentDisplayMode: FolderMode? = null
|
||||
private set
|
||||
|
||||
fun getFolders(): LiveData<List<DisplayFolder>> {
|
||||
return foldersFlow.asLiveData()
|
||||
}
|
||||
|
||||
fun setDisplayMode(account: Account, displayMode: FolderMode) {
|
||||
currentDisplayMode = displayMode
|
||||
viewModelScope.launch {
|
||||
inputFlow.emit(DisplayMode(account, displayMode))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private data class DisplayMode(val account: Account, val displayMode: FolderMode)
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
package com.fsck.k9.ui.folders
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.Account.FolderMode
|
||||
import com.fsck.k9.AccountsChangeListener
|
||||
import com.fsck.k9.Preferences
|
||||
import com.fsck.k9.controller.MessagingController
|
||||
import com.fsck.k9.controller.SimpleMessagingListener
|
||||
import com.fsck.k9.mailstore.DisplayFolder
|
||||
import com.fsck.k9.mailstore.FolderRepository
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class FoldersLiveData(
|
||||
private val folderRepository: FolderRepository,
|
||||
private val messagingController: MessagingController,
|
||||
private val preferences: Preferences,
|
||||
val account: Account,
|
||||
val displayMode: FolderMode?
|
||||
) : LiveData<List<DisplayFolder>>() {
|
||||
|
||||
private val messagingListener = object : SimpleMessagingListener() {
|
||||
override fun folderStatusChanged(account: Account, folderId: Long) {
|
||||
if (account.uuid == this@FoldersLiveData.account.uuid) {
|
||||
loadFoldersAsync()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val accountsListener = AccountsChangeListener {
|
||||
loadFoldersAsync()
|
||||
}
|
||||
|
||||
private fun loadFoldersAsync() {
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
val displayFolders = withContext(Dispatchers.IO) {
|
||||
folderRepository.getDisplayFolders(account, displayMode)
|
||||
}
|
||||
value = displayFolders
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActive() {
|
||||
super.onActive()
|
||||
messagingController.addListener(messagingListener)
|
||||
preferences.addOnAccountsChangeListener(accountsListener)
|
||||
loadFoldersAsync()
|
||||
}
|
||||
|
||||
override fun onInactive() {
|
||||
super.onInactive()
|
||||
messagingController.removeListener(messagingListener)
|
||||
preferences.removeOnAccountsChangeListener(accountsListener)
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package com.fsck.k9.ui.folders
|
||||
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.Account.FolderMode
|
||||
import com.fsck.k9.Preferences
|
||||
import com.fsck.k9.controller.MessagingController
|
||||
import com.fsck.k9.mailstore.FolderRepository
|
||||
|
||||
class FoldersLiveDataFactory(
|
||||
private val folderRepository: FolderRepository,
|
||||
private val messagingController: MessagingController,
|
||||
private val preferences: Preferences
|
||||
) {
|
||||
fun create(account: Account, displayMode: FolderMode? = null): FoldersLiveData {
|
||||
return FoldersLiveData(folderRepository, messagingController, preferences, account, displayMode)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,5 @@ import org.koin.dsl.module
|
|||
val foldersUiModule = module {
|
||||
single { FolderNameFormatterFactory() }
|
||||
factory { (context: Context) -> FolderNameFormatter(context.resources) }
|
||||
single { FoldersLiveDataFactory(get(), get(), get()) }
|
||||
viewModel { FoldersViewModel(get()) }
|
||||
viewModel { FoldersViewModel(folderRepository = get()) }
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@ import org.koin.androidx.viewmodel.dsl.viewModel
|
|||
import org.koin.dsl.module
|
||||
|
||||
val manageFoldersUiModule = module {
|
||||
viewModel { ManageFoldersViewModel(foldersLiveDataFactory = get()) }
|
||||
viewModel { ManageFoldersViewModel(folderRepository = get()) }
|
||||
viewModel { FolderSettingsViewModel(preferences = get(), folderRepository = get(), messagingController = get()) }
|
||||
}
|
||||
|
|
|
@ -1,21 +1,14 @@
|
|||
package com.fsck.k9.ui.managefolders
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.asLiveData
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.ui.folders.FoldersLiveData
|
||||
import com.fsck.k9.ui.folders.FoldersLiveDataFactory
|
||||
import com.fsck.k9.mailstore.DisplayFolder
|
||||
import com.fsck.k9.mailstore.FolderRepository
|
||||
|
||||
class ManageFoldersViewModel(private val foldersLiveDataFactory: FoldersLiveDataFactory) : ViewModel() {
|
||||
private var foldersLiveData: FoldersLiveData? = null
|
||||
|
||||
fun getFolders(account: Account): FoldersLiveData {
|
||||
val liveData = foldersLiveData
|
||||
if (liveData != null && liveData.account.uuid == account.uuid) {
|
||||
return liveData
|
||||
}
|
||||
|
||||
return foldersLiveDataFactory.create(account).also {
|
||||
foldersLiveData = it
|
||||
}
|
||||
class ManageFoldersViewModel(private val folderRepository: FolderRepository) : ViewModel() {
|
||||
fun getFolders(account: Account): LiveData<List<DisplayFolder>> {
|
||||
return folderRepository.getDisplayFoldersFlow(account).asLiveData()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue