Show account unread count on account list in drawer
This commit is contained in:
parent
295b9d8d28
commit
886a5a0610
6 changed files with 101 additions and 7 deletions
2
app/ui/base/src/main/res/drawable/empty.xml
Normal file
2
app/ui/base/src/main/res/drawable/empty.xml
Normal file
|
@ -0,0 +1,2 @@
|
|||
<!-- for use as badge background where we only want the number and no shape -->
|
||||
<shape/>
|
|
@ -33,7 +33,7 @@ dependencies {
|
|||
implementation "de.cketti.library.changelog:ckchangelog-core:2.0.0-beta01"
|
||||
implementation "com.splitwise:tokenautocomplete:4.0.0-beta01"
|
||||
implementation "de.cketti.safecontentresolver:safe-content-resolver-v21:1.0.0"
|
||||
implementation 'com.mikepenz:materialdrawer:8.4.0'
|
||||
implementation 'com.mikepenz:materialdrawer:8.4.1'
|
||||
implementation 'com.mikepenz:materialdrawer-iconics:8.3.3'
|
||||
implementation 'com.mikepenz:fontawesome-typeface:5.9.0.0-kotlin@aar'
|
||||
implementation 'com.github.ByteHamster:SearchPreference:v2.0.0'
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.fsck.k9.mailstore.DisplayFolder
|
|||
import com.fsck.k9.mailstore.Folder
|
||||
import com.fsck.k9.ui.account.AccountImageLoader
|
||||
import com.fsck.k9.ui.account.AccountsViewModel
|
||||
import com.fsck.k9.ui.account.DisplayAccount
|
||||
import com.fsck.k9.ui.base.Theme
|
||||
import com.fsck.k9.ui.base.ThemeManager
|
||||
import com.fsck.k9.ui.folders.FolderIconProvider
|
||||
|
@ -68,6 +69,7 @@ class K9Drawer(private val parent: MessageList, savedInstanceState: Bundle?) : K
|
|||
private val headerView: AccountHeaderView = AccountHeaderView(parent).apply {
|
||||
attachToSliderView(this@K9Drawer.sliderView)
|
||||
dividerBelowHeader = false
|
||||
displayBadgesOnCurrentProfileImage = false
|
||||
}
|
||||
private val folderIconProvider: FolderIconProvider = FolderIconProvider(parent.theme)
|
||||
private val swipeRefreshLayout: SwipeRefreshLayout
|
||||
|
@ -120,7 +122,7 @@ class K9Drawer(private val parent: MessageList, savedInstanceState: Bundle?) : K
|
|||
|
||||
addFooterItems()
|
||||
|
||||
accountsViewModel.accountsLiveData.observeNotNull(parent) { accounts ->
|
||||
accountsViewModel.displayAccountsLiveData.observeNotNull(parent) { accounts ->
|
||||
setAccounts(accounts)
|
||||
}
|
||||
|
||||
|
@ -159,11 +161,12 @@ class K9Drawer(private val parent: MessageList, savedInstanceState: Bundle?) : K
|
|||
}
|
||||
}
|
||||
|
||||
private fun setAccounts(accounts: List<Account>) {
|
||||
private fun setAccounts(displayAccounts: List<DisplayAccount>) {
|
||||
val oldSelectedBackgroundColor = selectedBackgroundColor
|
||||
|
||||
var newActiveProfile: IProfile? = null
|
||||
val accountItems = accounts.map { account ->
|
||||
val accountItems = displayAccounts.map { accountAndUnread ->
|
||||
val account = accountAndUnread.account
|
||||
val drawerId = (account.accountNumber + 1 shl DRAWER_ACCOUNT_SHIFT).toLong()
|
||||
|
||||
val drawerColors = getDrawerColorsForAccount(account)
|
||||
|
@ -179,6 +182,12 @@ class K9Drawer(private val parent: MessageList, savedInstanceState: Bundle?) : K
|
|||
descriptionTextColor = selectedTextColor
|
||||
selectedColorInt = drawerColors.selectedColor
|
||||
icon = ImageHolder(createAccountImageUri(account))
|
||||
accountAndUnread.unreadCount.takeIf { it > 0 }?.let { unreadCount ->
|
||||
badgeText = unreadCount.toString()
|
||||
badgeStyle = BadgeStyle().apply {
|
||||
textColorStateList = selectedTextColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (account.uuid == openedAccountUuid) {
|
||||
|
|
|
@ -1,8 +1,86 @@
|
|||
package com.fsck.k9.ui.account
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.database.ContentObserver
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.asLiveData
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.AccountsChangeListener
|
||||
import com.fsck.k9.Preferences
|
||||
import com.fsck.k9.controller.UnreadMessageCountProvider
|
||||
import com.fsck.k9.provider.EmailProvider
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class AccountsViewModel(preferences: Preferences) : ViewModel() {
|
||||
val accountsLiveData = AccountsLiveData(preferences)
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class AccountsViewModel(
|
||||
val preferences: Preferences,
|
||||
val unreadMessageCountProvider: UnreadMessageCountProvider,
|
||||
private val contentResolver: ContentResolver
|
||||
) :
|
||||
ViewModel() {
|
||||
|
||||
private val accountsFlow: Flow<List<Account>> =
|
||||
callbackFlow {
|
||||
send(preferences.accounts)
|
||||
|
||||
val accountsChangeListener = AccountsChangeListener {
|
||||
launch {
|
||||
send(preferences.accounts)
|
||||
}
|
||||
}
|
||||
preferences.addOnAccountsChangeListener(accountsChangeListener)
|
||||
awaitClose {
|
||||
preferences.removeOnAccountsChangeListener(accountsChangeListener)
|
||||
}
|
||||
}.flowOn(Dispatchers.IO)
|
||||
|
||||
private val displayAccountFlow: Flow<List<DisplayAccount>> = accountsFlow
|
||||
.flatMapLatest { accounts ->
|
||||
|
||||
val unreadCountFlows: List<Flow<Int>> = accounts.map { account ->
|
||||
getUnreadCountFlow(account)
|
||||
}
|
||||
|
||||
combine(unreadCountFlows) { unreadCounts ->
|
||||
unreadCounts.mapIndexed { index, unreadCount ->
|
||||
DisplayAccount(account = accounts[index], unreadCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getUnreadCountFlow(account: Account): Flow<Int> {
|
||||
return callbackFlow {
|
||||
|
||||
val notificationUri = EmailProvider.getNotificationUri(account.uuid)
|
||||
|
||||
send(unreadMessageCountProvider.getUnreadMessageCount(account))
|
||||
|
||||
val contentObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
|
||||
override fun onChange(selfChange: Boolean) {
|
||||
launch {
|
||||
send(unreadMessageCountProvider.getUnreadMessageCount(account))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentResolver.registerContentObserver(notificationUri, false, contentObserver)
|
||||
|
||||
awaitClose {
|
||||
contentResolver.unregisterContentObserver(contentObserver)
|
||||
}
|
||||
}.flowOn(Dispatchers.IO)
|
||||
}
|
||||
|
||||
val displayAccountsLiveData: LiveData<List<DisplayAccount>> = displayAccountFlow.asLiveData()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package com.fsck.k9.ui.account
|
||||
|
||||
import com.fsck.k9.Account
|
||||
|
||||
data class DisplayAccount(val account: Account, val unreadCount: Int)
|
|
@ -4,7 +4,7 @@ import org.koin.androidx.viewmodel.dsl.viewModel
|
|||
import org.koin.dsl.module
|
||||
|
||||
val accountUiModule = module {
|
||||
viewModel { AccountsViewModel(preferences = get()) }
|
||||
viewModel { AccountsViewModel(preferences = get(), unreadMessageCountProvider = get(), contentResolver = get()) }
|
||||
factory { AccountImageLoader(accountFallbackImageProvider = get()) }
|
||||
factory { AccountFallbackImageProvider(context = get()) }
|
||||
factory { AccountImageModelLoaderFactory(contactPhotoLoader = get(), accountFallbackImageProvider = get()) }
|
||||
|
|
Loading…
Reference in a new issue