mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-02-16 12:00:03 +03:00
Using flow to show items counter
This commit is contained in:
parent
c7dae341c0
commit
0aaa650ac3
8 changed files with 56 additions and 47 deletions
|
@ -58,6 +58,7 @@ ext.libs = [
|
||||||
'lifecycleCommon' : "androidx.lifecycle:lifecycle-common:$lifecycle",
|
'lifecycleCommon' : "androidx.lifecycle:lifecycle-common:$lifecycle",
|
||||||
'lifecycleLivedata' : "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle",
|
'lifecycleLivedata' : "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle",
|
||||||
'lifecycleProcess' : "androidx.lifecycle:lifecycle-process:$lifecycle",
|
'lifecycleProcess' : "androidx.lifecycle:lifecycle-process:$lifecycle",
|
||||||
|
'lifecycleRuntimeKtx' : "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle",
|
||||||
'datastore' : "androidx.datastore:datastore:1.0.0",
|
'datastore' : "androidx.datastore:datastore:1.0.0",
|
||||||
'datastorepreferences' : "androidx.datastore:datastore-preferences:1.0.0",
|
'datastorepreferences' : "androidx.datastore:datastore-preferences:1.0.0",
|
||||||
'pagingRuntimeKtx' : "androidx.paging:paging-runtime-ktx:2.1.2",
|
'pagingRuntimeKtx' : "androidx.paging:paging-runtime-ktx:2.1.2",
|
||||||
|
@ -141,4 +142,4 @@ ext.libs = [
|
||||||
'timberJunitRule' : "net.lachlanmckee:timber-junit-rule:1.0.1",
|
'timberJunitRule' : "net.lachlanmckee:timber-junit-rule:1.0.1",
|
||||||
'junit' : "junit:junit:4.13.2"
|
'junit' : "junit:junit:4.13.2"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
|
@ -73,9 +73,6 @@ android {
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "11"
|
jvmTarget = "11"
|
||||||
freeCompilerArgs += [
|
|
||||||
"-Xopt-in=kotlin.RequiresOptIn"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|
|
@ -29,8 +29,10 @@ import io.realm.kotlin.toFlow
|
||||||
import io.realm.kotlin.where
|
import io.realm.kotlin.where
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||||
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
|
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
|
||||||
import org.matrix.android.sdk.api.query.RoomCategoryFilter
|
import org.matrix.android.sdk.api.query.RoomCategoryFilter
|
||||||
import org.matrix.android.sdk.api.query.isNormalized
|
import org.matrix.android.sdk.api.query.isNormalized
|
||||||
|
@ -63,7 +65,8 @@ internal class RoomSummaryDataSource @Inject constructor(
|
||||||
@SessionDatabase private val monarchy: Monarchy,
|
@SessionDatabase private val monarchy: Monarchy,
|
||||||
private val realmSessionProvider: RealmSessionProvider,
|
private val realmSessionProvider: RealmSessionProvider,
|
||||||
private val roomSummaryMapper: RoomSummaryMapper,
|
private val roomSummaryMapper: RoomSummaryMapper,
|
||||||
private val queryStringValueProcessor: QueryStringValueProcessor
|
private val queryStringValueProcessor: QueryStringValueProcessor,
|
||||||
|
private val coroutineDispatchers: MatrixCoroutineDispatchers
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun getRoomSummary(roomIdOrAlias: String): RoomSummary? {
|
fun getRoomSummary(roomIdOrAlias: String): RoomSummary? {
|
||||||
|
@ -237,28 +240,16 @@ internal class RoomSummaryDataSource @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
// fun getCountFlow(queryParams: RoomSummaryQueryParams): Flow<Int> = callbackFlow {
|
|
||||||
// val realmResult = realmSessionProvider.withRealm { realm ->
|
|
||||||
// roomSummariesQuery(realm, queryParams).findAllAsync()
|
|
||||||
// }
|
|
||||||
// val changeListener = RealmChangeListener<RealmResults<RoomSummaryEntity>> {
|
|
||||||
// trySendBlocking(it.size)
|
|
||||||
// .onFailure { throwable -> Timber.e(throwable) }
|
|
||||||
// }
|
|
||||||
// realmResult.addChangeListener(changeListener)
|
|
||||||
// awaitClose { realmResult.removeChangeListener(changeListener) }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fun getCountFlow(queryParams: RoomSummaryQueryParams): Flow<Int> =
|
fun getCountFlow(queryParams: RoomSummaryQueryParams): Flow<Int> =
|
||||||
// TODO handle properly threads and dispatchers otherwise use livedata of monarchy
|
|
||||||
realmSessionProvider
|
realmSessionProvider
|
||||||
.withRealm { realm -> roomSummariesQuery(realm, queryParams).findAllAsync() }
|
.withRealm { realm -> roomSummariesQuery(realm, queryParams).findAllAsync() }
|
||||||
.toFlow()
|
.toFlow()
|
||||||
|
// need to create the flow on a context dispatcher with a thread with attached Looper
|
||||||
|
.flowOn(coroutineDispatchers.main)
|
||||||
.map { it.size }
|
.map { it.size }
|
||||||
.flowOn(Dispatchers.IO)
|
.flowOn(coroutineDispatchers.io)
|
||||||
|
.distinctUntilChanged()
|
||||||
|
|
||||||
// TODO should we improve how we update notification count with flow ??
|
|
||||||
fun getNotificationCountForRooms(queryParams: RoomSummaryQueryParams): RoomAggregateNotificationCount {
|
fun getNotificationCountForRooms(queryParams: RoomSummaryQueryParams): RoomAggregateNotificationCount {
|
||||||
var notificationCount: RoomAggregateNotificationCount? = null
|
var notificationCount: RoomAggregateNotificationCount? = null
|
||||||
monarchy.doWithRealm { realm ->
|
monarchy.doWithRealm { realm ->
|
||||||
|
|
|
@ -355,6 +355,7 @@ dependencies {
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
implementation libs.androidx.lifecycleLivedata
|
implementation libs.androidx.lifecycleLivedata
|
||||||
implementation libs.androidx.lifecycleProcess
|
implementation libs.androidx.lifecycleProcess
|
||||||
|
implementation libs.androidx.lifecycleRuntimeKtx
|
||||||
|
|
||||||
implementation libs.androidx.datastore
|
implementation libs.androidx.datastore
|
||||||
implementation libs.androidx.datastorepreferences
|
implementation libs.androidx.datastorepreferences
|
||||||
|
|
|
@ -23,6 +23,8 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.flowWithLifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.ConcatAdapter
|
import androidx.recyclerview.widget.ConcatAdapter
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
@ -50,8 +52,10 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA
|
||||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
||||||
import im.vector.app.features.home.room.list.widget.NotifsFabMenuView
|
import im.vector.app.features.home.room.list.widget.NotifsFabMenuView
|
||||||
import im.vector.app.features.notifications.NotificationDrawerManager
|
import im.vector.app.features.notifications.NotificationDrawerManager
|
||||||
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import org.matrix.android.sdk.api.extensions.orTrue
|
import org.matrix.android.sdk.api.extensions.orTrue
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
|
@ -287,11 +291,14 @@ class RoomListFragment @Inject constructor(
|
||||||
))
|
))
|
||||||
checkEmptyState()
|
checkEmptyState()
|
||||||
}
|
}
|
||||||
// TODO use flow if possible ?
|
lifecycleScope.launch {
|
||||||
section.itemCount.observe(viewLifecycleOwner) { count ->
|
section.itemCount
|
||||||
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy(
|
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
|
||||||
itemCount = count
|
.collect { count ->
|
||||||
))
|
sectionAdapter.updateSection(
|
||||||
|
sectionAdapter.roomsSectionData.copy(itemCount = count)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
section.notificationCount.observe(viewLifecycleOwner) { counts ->
|
section.notificationCount.observe(viewLifecycleOwner) { counts ->
|
||||||
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy(
|
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy(
|
||||||
|
@ -332,11 +339,14 @@ class RoomListFragment @Inject constructor(
|
||||||
isLoading = false))
|
isLoading = false))
|
||||||
checkEmptyState()
|
checkEmptyState()
|
||||||
}
|
}
|
||||||
// TODO use flow instead ?
|
lifecycleScope.launch {
|
||||||
section.itemCount.observe(viewLifecycleOwner) { count ->
|
section.itemCount
|
||||||
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy(
|
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
|
||||||
itemCount = count
|
.collect { count ->
|
||||||
))
|
sectionAdapter.updateSection(
|
||||||
|
sectionAdapter.roomsSectionData.copy(itemCount = count)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
section.notificationCount.observe(viewLifecycleOwner) { counts ->
|
section.notificationCount.observe(viewLifecycleOwner) { counts ->
|
||||||
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy(
|
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy(
|
||||||
|
|
|
@ -68,11 +68,18 @@ class RoomListSectionBuilderGroup(
|
||||||
it.memberships = Membership.activeMemberships()
|
it.memberships = Membership.activeMemberships()
|
||||||
},
|
},
|
||||||
{ qpm ->
|
{ qpm ->
|
||||||
|
// TODO find a way to show the filtered rooms count ?
|
||||||
val name = stringProvider.getString(R.string.bottom_action_rooms)
|
val name = stringProvider.getString(R.string.bottom_action_rooms)
|
||||||
session.getFilteredPagedRoomSummariesLive(qpm)
|
session.getFilteredPagedRoomSummariesLive(qpm)
|
||||||
.let { updatableFilterLivePageResult ->
|
.let { updatableFilterLivePageResult ->
|
||||||
onUpdatable(updatableFilterLivePageResult)
|
onUpdatable(updatableFilterLivePageResult)
|
||||||
sections.add(RoomsSection(name, updatableFilterLivePageResult.livePagedList))
|
sections.add(
|
||||||
|
RoomsSection(
|
||||||
|
sectionName = name,
|
||||||
|
livePages = updatableFilterLivePageResult.livePagedList,
|
||||||
|
itemCount = session.getRoomCountFlow(qpm)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -242,7 +249,6 @@ class RoomListSectionBuilderGroup(
|
||||||
@StringRes nameRes: Int,
|
@StringRes nameRes: Int,
|
||||||
notifyOfLocalEcho: Boolean = false,
|
notifyOfLocalEcho: Boolean = false,
|
||||||
query: (RoomSummaryQueryParams.Builder) -> Unit) {
|
query: (RoomSummaryQueryParams.Builder) -> Unit) {
|
||||||
// TODO check when this class is used: difference with RoomListSectionBuilderSpace ?
|
|
||||||
withQueryParams(
|
withQueryParams(
|
||||||
{ query.invoke(it) },
|
{ query.invoke(it) },
|
||||||
{ roomQueryParams ->
|
{ roomQueryParams ->
|
||||||
|
@ -252,7 +258,6 @@ class RoomListSectionBuilderGroup(
|
||||||
activeSpaceUpdaters.add(it)
|
activeSpaceUpdaters.add(it)
|
||||||
}.livePagedList
|
}.livePagedList
|
||||||
.let { livePagedList ->
|
.let { livePagedList ->
|
||||||
// TODO should we improve this ?
|
|
||||||
// use it also as a source to update count
|
// use it also as a source to update count
|
||||||
livePagedList.asFlow()
|
livePagedList.asFlow()
|
||||||
.onEach {
|
.onEach {
|
||||||
|
@ -267,7 +272,8 @@ class RoomListSectionBuilderGroup(
|
||||||
RoomsSection(
|
RoomsSection(
|
||||||
sectionName = name,
|
sectionName = name,
|
||||||
livePages = livePagedList,
|
livePages = livePagedList,
|
||||||
notifyOfLocalEcho = notifyOfLocalEcho
|
notifyOfLocalEcho = notifyOfLocalEcho,
|
||||||
|
itemCount = session.getRoomCountFlow(roomQueryParams)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ import kotlinx.coroutines.flow.flatMapLatest
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
|
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
|
||||||
|
@ -87,11 +88,18 @@ class RoomListSectionBuilderSpace(
|
||||||
it.memberships = Membership.activeMemberships()
|
it.memberships = Membership.activeMemberships()
|
||||||
},
|
},
|
||||||
{ qpm ->
|
{ qpm ->
|
||||||
|
// TODO find a way to show the filtered rooms count ?
|
||||||
val name = stringProvider.getString(R.string.bottom_action_rooms)
|
val name = stringProvider.getString(R.string.bottom_action_rooms)
|
||||||
session.getFilteredPagedRoomSummariesLive(qpm)
|
session.getFilteredPagedRoomSummariesLive(qpm)
|
||||||
.let { updatableFilterLivePageResult ->
|
.let { updatableFilterLivePageResult ->
|
||||||
onUpdatable(updatableFilterLivePageResult)
|
onUpdatable(updatableFilterLivePageResult)
|
||||||
sections.add(RoomsSection(name, updatableFilterLivePageResult.livePagedList))
|
sections.add(
|
||||||
|
RoomsSection(
|
||||||
|
sectionName = name,
|
||||||
|
livePages = updatableFilterLivePageResult.livePagedList,
|
||||||
|
itemCount = session.getRoomCountFlow(qpm)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -261,7 +269,8 @@ class RoomListSectionBuilderSpace(
|
||||||
RoomsSection(
|
RoomsSection(
|
||||||
sectionName = stringProvider.getString(R.string.suggested_header),
|
sectionName = stringProvider.getString(R.string.suggested_header),
|
||||||
liveSuggested = liveSuggestedRooms,
|
liveSuggested = liveSuggestedRooms,
|
||||||
notifyOfLocalEcho = false
|
notifyOfLocalEcho = false,
|
||||||
|
itemCount = suggestedRoomsFlow.map { suggestions -> suggestions.size }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -374,7 +383,6 @@ class RoomListSectionBuilderSpace(
|
||||||
// use it also as a source to update count
|
// use it also as a source to update count
|
||||||
livePagedList.asFlow()
|
livePagedList.asFlow()
|
||||||
.onEach {
|
.onEach {
|
||||||
// TODO should we improve this ?
|
|
||||||
Timber.v("Thread space list: ${Thread.currentThread()}")
|
Timber.v("Thread space list: ${Thread.currentThread()}")
|
||||||
sections.find { it.sectionName == name }
|
sections.find { it.sectionName == name }
|
||||||
?.notificationCount
|
?.notificationCount
|
||||||
|
@ -395,16 +403,11 @@ class RoomListSectionBuilderSpace(
|
||||||
RoomsSection(
|
RoomsSection(
|
||||||
sectionName = name,
|
sectionName = name,
|
||||||
livePages = livePagedList,
|
livePages = livePagedList,
|
||||||
notifyOfLocalEcho = notifyOfLocalEcho
|
notifyOfLocalEcho = notifyOfLocalEcho,
|
||||||
|
itemCount = session.getRoomCountFlow(roomQueryParams)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO extract into a dedicated private method
|
|
||||||
session.getRoomCountFlow(roomQueryParams)
|
|
||||||
.onEach { count -> sections.find { section -> section.sectionName == name }?.itemCount?.postValue(count) }
|
|
||||||
.flowOn(Dispatchers.Default)
|
|
||||||
.launchIn(viewModelScope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -19,6 +19,7 @@ package im.vector.app.features.home.room.list
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.paging.PagedList
|
import androidx.paging.PagedList
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
|
import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
|
||||||
|
|
||||||
|
@ -30,8 +31,7 @@ data class RoomsSection(
|
||||||
val liveList: LiveData<List<RoomSummary>>? = null,
|
val liveList: LiveData<List<RoomSummary>>? = null,
|
||||||
val liveSuggested: LiveData<SuggestedRoomInfo>? = null,
|
val liveSuggested: LiveData<SuggestedRoomInfo>? = null,
|
||||||
val isExpanded: MutableLiveData<Boolean> = MutableLiveData(true),
|
val isExpanded: MutableLiveData<Boolean> = MutableLiveData(true),
|
||||||
// TODO expose a Flow<Int> instead ?
|
val itemCount: Flow<Int>,
|
||||||
val itemCount: MutableLiveData<Int> = MutableLiveData(0),
|
|
||||||
val notificationCount: MutableLiveData<RoomAggregateNotificationCount> = MutableLiveData(RoomAggregateNotificationCount(0, 0)),
|
val notificationCount: MutableLiveData<RoomAggregateNotificationCount> = MutableLiveData(RoomAggregateNotificationCount(0, 0)),
|
||||||
val notifyOfLocalEcho: Boolean = false
|
val notifyOfLocalEcho: Boolean = false
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue