SDK: get some better queries

This commit is contained in:
ganfra 2020-01-08 11:55:22 +01:00
parent 2dd2a8db6c
commit 9970d7ffa0
22 changed files with 192 additions and 58 deletions

View file

@ -20,6 +20,7 @@ import androidx.paging.PagedList
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.group.model.GroupSummary
import im.vector.matrix.android.api.session.pushers.Pusher
import im.vector.matrix.android.api.session.room.RoomSummaryQueryParams
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
import im.vector.matrix.android.api.session.sync.SyncState
@ -30,40 +31,43 @@ import io.reactivex.Single
class RxSession(private val session: Session) {
fun liveRoomSummaries(): Observable<List<RoomSummary>> {
return session.liveRoomSummaries().asObservable()
fun liveRoomSummaries(queryParams: RoomSummaryQueryParams): Observable<List<RoomSummary>> {
return session.getRoomSummariesLive(queryParams).asObservable()
.startWith(session.getRoomSummaries(queryParams))
}
fun liveGroupSummaries(): Observable<List<GroupSummary>> {
return session.liveGroupSummaries().asObservable()
return session.getGroupSummariesLive().asObservable()
.startWith(session.getGroupSummaries())
}
fun liveBreadcrumbs(): Observable<List<RoomSummary>> {
return session.liveBreadcrumbs().asObservable()
return session.getBreadcrumbsLive().asObservable()
.startWith(session.getBreadcrumbs())
}
fun liveSyncState(): Observable<SyncState> {
return session.syncState().asObservable()
return session.getSyncStateLive().asObservable()
}
fun livePushers(): Observable<List<Pusher>> {
return session.livePushers().asObservable()
return session.getPushersLive().asObservable()
}
fun liveUser(userId: String): Observable<Optional<User>> {
return session.liveUser(userId).asObservable().distinctUntilChanged()
return session.getUserLive(userId).asObservable().distinctUntilChanged()
}
fun liveUsers(): Observable<List<User>> {
return session.liveUsers().asObservable()
return session.getUsersLive().asObservable()
}
fun liveIgnoredUsers(): Observable<List<User>> {
return session.liveIgnoredUsers().asObservable()
return session.getIgnoredUsersLive().asObservable()
}
fun livePagedUsers(filter: String? = null): Observable<PagedList<User>> {
return session.livePagedUsers(filter).asObservable()
return session.getPagedUsersLive(filter).asObservable()
}
fun createRoom(roomParams: CreateRoomParams): Single<String> = singleBuilder {

View file

@ -107,7 +107,7 @@ interface Session :
* This method allows to listen the sync state.
* @return a [LiveData] of [SyncState].
*/
fun syncState(): LiveData<SyncState>
fun getSyncStateLive(): LiveData<SyncState>
/**
* This methods return true if an initial sync has been processed

View file

@ -38,9 +38,15 @@ interface GroupService {
*/
fun getGroupSummary(groupId: String): GroupSummary?
/**
* Get a list of group summaries.This list is a snapshot of the data.
* @return the list of [GroupSummary]
*/
fun getGroupSummaries(): List<GroupSummary>
/**
* Get a live list of group summaries. This list is refreshed as soon as the data changes.
* @return the [LiveData] of [GroupSummary]
*/
fun liveGroupSummaries(): LiveData<List<GroupSummary>>
fun getGroupSummariesLive(): LiveData<List<GroupSummary>>
}

View file

@ -58,7 +58,7 @@ interface PushersService {
const val EVENT_ID_ONLY = "event_id_only"
}
fun livePushers(): LiveData<List<Pusher>>
fun getPushersLive(): LiveData<List<Pusher>>
fun pushers() : List<Pusher>
}

View file

@ -56,5 +56,8 @@ interface Room :
*/
fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>>
/**
* A current snapshot of [RoomSummary] associated with the room
*/
fun roomSummary(): RoomSummary?
}

View file

@ -60,16 +60,28 @@ interface RoomService {
fun getRoomSummary(roomIdOrAlias: String): RoomSummary?
/**
* Get a live list of room summaries. This list is refreshed as soon as the data changes.
* @return the [LiveData] of [RoomSummary]
* Get a snapshot list of room summaries.
* @return the immutable list of [RoomSummary]
*/
fun liveRoomSummaries(): LiveData<List<RoomSummary>>
fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary>
/**
* Get a live list of room summaries. This list is refreshed as soon as the data changes.
* @return the [LiveData] of List[RoomSummary]
*/
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>>
/**
* Get a snapshot list of Breadcrumbs
* @return the immutable list of [RoomSummary]
*/
fun getBreadcrumbs(): List<RoomSummary>
/**
* Get a live list of Breadcrumbs
* @return the [LiveData] of [RoomSummary]
*/
fun liveBreadcrumbs(): LiveData<List<RoomSummary>>
fun getBreadcrumbsLive(): LiveData<List<RoomSummary>>
/**
* Inform the Matrix SDK that a room is displayed.

View file

@ -0,0 +1,38 @@
/*
* Copyright 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.room
import im.vector.matrix.android.api.session.room.model.Membership
/**
* This class can be used to filter room summaries to use with:
* [im.vector.matrix.android.api.session.room.Room] and [im.vector.matrix.android.api.session.room.RoomService]
*/
data class RoomSummaryQueryParams(
/**
* Set to true if you want only non null display name. True by default
*/
val filterDisplayName: Boolean = true,
/**
* Set to true if you want only non null canonical alias. False by default.
*/
val filterCanonicalAlias: Boolean = false,
/**
* Set the list of memberships you want to filter on. By default, all memberships.
*/
val memberships: List<Membership> = Membership.all()
)

View file

@ -48,5 +48,9 @@ enum class Membership(val value: String) {
fun activeMemberships(): List<Membership> {
return listOf(INVITE, JOIN)
}
fun all(): List<Membership>{
return values().asList()
}
}
}

View file

@ -50,25 +50,25 @@ interface UserService {
* @param userId the userId to look for.
* @return a LiveData of user with userId
*/
fun liveUser(userId: String): LiveData<Optional<User>>
fun getUserLive(userId: String): LiveData<Optional<User>>
/**
* Observe a live list of users sorted alphabetically
* @return a Livedata of users
*/
fun liveUsers(): LiveData<List<User>>
fun getUsersLive(): LiveData<List<User>>
/**
* Observe a live [PagedList] of users sorted alphabetically. You can filter the users.
* @param filter the filter. It will look into userId and displayName.
* @return a Livedata of users
*/
fun livePagedUsers(filter: String? = null): LiveData<PagedList<User>>
fun getPagedUsersLive(filter: String? = null): LiveData<PagedList<User>>
/**
* Get list of ignored users
*/
fun liveIgnoredUsers(): LiveData<List<User>>
fun getIgnoredUsersLive(): LiveData<List<User>>
/**
* Ignore users

View file

@ -156,7 +156,7 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
syncTaskSequencer.close()
}
override fun syncState(): LiveData<SyncState> {
override fun getSyncStateLive(): LiveData<SyncState> {
return getSyncThread().liveState()
}

View file

@ -26,6 +26,8 @@ import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
import im.vector.matrix.android.internal.database.model.GroupSummaryEntityFields
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.util.fetchCopyMap
import io.realm.Realm
import io.realm.RealmQuery
import javax.inject.Inject
internal class DefaultGroupService @Inject constructor(private val monarchy: Monarchy) : GroupService {
@ -41,10 +43,22 @@ internal class DefaultGroupService @Inject constructor(private val monarchy: Mon
)
}
override fun liveGroupSummaries(): LiveData<List<GroupSummary>> {
return monarchy.findAllMappedWithChanges(
{ realm -> GroupSummaryEntity.where(realm).isNotEmpty(GroupSummaryEntityFields.DISPLAY_NAME) },
override fun getGroupSummaries(): List<GroupSummary> {
return monarchy.fetchAllMappedSync(
{ groupSummariesQuery(it) },
{ it.asDomain() }
)
}
override fun getGroupSummariesLive(): LiveData<List<GroupSummary>> {
return monarchy.findAllMappedWithChanges(
{ groupSummariesQuery(it) },
{ it.asDomain() }
)
}
private fun groupSummariesQuery(realm: Realm): RealmQuery<GroupSummaryEntity> {
return GroupSummaryEntity.where(realm).isNotEmpty(GroupSummaryEntityFields.DISPLAY_NAME)
}
}

View file

@ -86,7 +86,7 @@ internal class DefaultPusherService @Inject constructor(private val context: Con
.executeBy(taskExecutor)
}
override fun livePushers(): LiveData<List<Pusher>> {
override fun getPushersLive(): LiveData<List<Pusher>> {
return monarchy.findAllMappedWithChanges(
{ realm -> PusherEntity.where(realm) },
{ it.asDomain() }

View file

@ -21,6 +21,7 @@ import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.api.session.room.RoomSummaryQueryParams
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.model.VersioningState
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
@ -41,6 +42,7 @@ import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.util.fetchCopyMap
import io.realm.Realm
import io.realm.RealmQuery
import javax.inject.Inject
internal class DefaultRoomService @Inject constructor(private val monarchy: Monarchy,
@ -86,30 +88,63 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona
})
}
override fun liveRoomSummaries(): LiveData<List<RoomSummary>> {
return monarchy.findAllMappedWithChanges(
{ realm ->
RoomSummaryEntity.where(realm)
.isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME)
.notEqualTo(RoomSummaryEntityFields.VERSIONING_STATE_STR, VersioningState.UPGRADED_ROOM_JOINED.name)
},
override fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary> {
return monarchy.fetchAllMappedSync(
{ roomSummariesQuery(it, queryParams) },
{ roomSummaryMapper.map(it) }
)
}
override fun liveBreadcrumbs(): LiveData<List<RoomSummary>> {
override fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> {
return monarchy.findAllMappedWithChanges(
{ realm ->
RoomSummaryEntity.where(realm)
.isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME)
.notEqualTo(RoomSummaryEntityFields.VERSIONING_STATE_STR, VersioningState.UPGRADED_ROOM_JOINED.name)
.greaterThan(RoomSummaryEntityFields.BREADCRUMBS_INDEX, RoomSummaryEntity.NOT_IN_BREADCRUMBS)
.sort(RoomSummaryEntityFields.BREADCRUMBS_INDEX)
},
{ roomSummariesQuery(it, queryParams) },
{ roomSummaryMapper.map(it) }
)
}
private fun roomSummariesQuery(realm: Realm, queryParams: RoomSummaryQueryParams): RealmQuery<RoomSummaryEntity> {
val query = RoomSummaryEntity.where(realm)
if (queryParams.filterCanonicalAlias) {
query.isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME)
}
if (queryParams.filterCanonicalAlias) {
query.isNotEmpty(RoomSummaryEntityFields.CANONICAL_ALIAS)
}
val lastMembership = queryParams.memberships.lastOrNull()
query.beginGroup()
for (membership in queryParams.memberships) {
query.equalTo(RoomSummaryEntityFields.MEMBERSHIP_STR, membership.name)
if (membership != lastMembership) {
query.or()
}
}
query.endGroup()
query.notEqualTo(RoomSummaryEntityFields.VERSIONING_STATE_STR, VersioningState.UPGRADED_ROOM_JOINED.name)
return query
}
override fun getBreadcrumbs(): List<RoomSummary> {
return monarchy.fetchAllMappedSync(
{ breadcrumbsQuery(it) },
{ roomSummaryMapper.map(it) }
)
}
override fun getBreadcrumbsLive(): LiveData<List<RoomSummary>> {
return monarchy.findAllMappedWithChanges(
{ breadcrumbsQuery(it) },
{ roomSummaryMapper.map(it) }
)
}
private fun breadcrumbsQuery(realm: Realm): RealmQuery<RoomSummaryEntity> {
return RoomSummaryEntity.where(realm)
.isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME)
.notEqualTo(RoomSummaryEntityFields.VERSIONING_STATE_STR, VersioningState.UPGRADED_ROOM_JOINED.name)
.greaterThan(RoomSummaryEntityFields.BREADCRUMBS_INDEX, RoomSummaryEntity.NOT_IN_BREADCRUMBS)
.sort(RoomSummaryEntityFields.BREADCRUMBS_INDEX)
}
override fun onRoomDisplayed(roomId: String): Cancelable {
return updateBreadcrumbsTask
.configureWith(UpdateBreadcrumbsTask.Params(roomId))

View file

@ -26,6 +26,8 @@ import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.RoomMember
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
import im.vector.matrix.android.internal.database.model.RoomMemberEntityFields
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
import im.vector.matrix.android.internal.session.room.membership.leaving.LeaveRoomTask
@ -33,6 +35,7 @@ import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.util.fetchCopied
import io.realm.Realm
import io.realm.RealmQuery
internal class DefaultMembershipService @AssistedInject constructor(@Assisted private val roomId: String,
private val monarchy: Monarchy,
@ -67,7 +70,7 @@ internal class DefaultMembershipService @AssistedInject constructor(@Assisted pr
override fun getRoomMembers(memberships: List<Membership>): List<RoomMember> {
return monarchy.fetchAllMappedSync(
{
RoomMembers(it, roomId).queryRoomMembersEvent()
roomMembersQuery(it, memberships)
},
{
it.asDomain()
@ -78,7 +81,7 @@ internal class DefaultMembershipService @AssistedInject constructor(@Assisted pr
override fun getRoomMembersLive(memberships: List<Membership>): LiveData<List<RoomMember>> {
return monarchy.findAllMappedWithChanges(
{
RoomMembers(it, roomId).queryRoomMembersEvent()
roomMembersQuery(it, memberships)
},
{
it.asDomain()
@ -86,6 +89,20 @@ internal class DefaultMembershipService @AssistedInject constructor(@Assisted pr
)
}
private fun roomMembersQuery(realm: Realm, memberships: List<Membership>): RealmQuery<RoomMemberEntity> {
val query = RoomMembers(realm, roomId).queryRoomMembersEvent()
val lastMembership = memberships.lastOrNull()
query.beginGroup()
for (membership in memberships) {
query.equalTo(RoomMemberEntityFields.MEMBERSHIP_STR, membership.name)
if (membership != lastMembership) {
query.or()
}
}
query.endGroup()
return query
}
override fun getNumberOfJoinedMembers(): Int {
return Realm.getInstance(monarchy.realmConfiguration).use {
RoomMembers(it, roomId).getNumberOfJoinedMembers()

View file

@ -112,7 +112,7 @@ abstract class SyncService : Service() {
try {
syncTask.execute(params)
// Start sync if we were doing an initial sync and the syncThread is not launched yet
if (isInitialSync && session.syncState().value == SyncState.Idle) {
if (isInitialSync && session.getSyncStateLive().value == SyncState.Idle) {
val isForeground = !backgroundDetectionObserver.isInBackground
session.startSync(isForeground)
}

View file

@ -70,7 +70,7 @@ internal class DefaultUserService @Inject constructor(private val monarchy: Mona
return userEntity.asDomain()
}
override fun liveUser(userId: String): LiveData<Optional<User>> {
override fun getUserLive(userId: String): LiveData<Optional<User>> {
val liveData = monarchy.findAllMappedWithChanges(
{ UserEntity.where(it, userId) },
{ it.asDomain() }
@ -80,7 +80,7 @@ internal class DefaultUserService @Inject constructor(private val monarchy: Mona
}
}
override fun liveUsers(): LiveData<List<User>> {
override fun getUsersLive(): LiveData<List<User>> {
return monarchy.findAllMappedWithChanges(
{ realm ->
realm.where(UserEntity::class.java)
@ -91,7 +91,7 @@ internal class DefaultUserService @Inject constructor(private val monarchy: Mona
)
}
override fun livePagedUsers(filter: String?): LiveData<PagedList<User>> {
override fun getPagedUsersLive(filter: String?): LiveData<PagedList<User>> {
realmDataSourceFactory.updateQuery { realm ->
val query = realm.where(UserEntity::class.java)
if (filter.isNullOrEmpty()) {
@ -121,7 +121,7 @@ internal class DefaultUserService @Inject constructor(private val monarchy: Mona
.executeBy(taskExecutor)
}
override fun liveIgnoredUsers(): LiveData<List<User>> {
override fun getIgnoredUsersLive(): LiveData<List<User>> {
return monarchy.findAllMappedWithChanges(
{ realm ->
realm.where(IgnoredUserEntity::class.java)

View file

@ -21,6 +21,7 @@ import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import arrow.core.Option
import im.vector.matrix.android.api.session.group.model.GroupSummary
import im.vector.matrix.android.api.session.room.RoomSummaryQueryParams
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.rx.rx
import im.vector.riotx.features.home.HomeRoomListDataSource
@ -65,7 +66,7 @@ class AppStateHandler @Inject constructor(
sessionDataSource.observe()
.observeOn(AndroidSchedulers.mainThread())
.switchMap {
it.orNull()?.rx()?.liveRoomSummaries()
it.orNull()?.rx()?.liveRoomSummaries(RoomSummaryQueryParams())
?: Observable.just(emptyList())
}
.throttleLast(300, TimeUnit.MILLISECONDS),

View file

@ -40,7 +40,7 @@ class HomeDrawerFragment @Inject constructor(
if (savedInstanceState == null) {
replaceChildFragment(R.id.homeDrawerGroupListContainer, GroupListFragment::class.java)
}
session.liveUser(session.myUserId).observeK(this) { optionalUser ->
session.getUserLive(session.myUserId).observeK(viewLifecycleOwner) { optionalUser ->
val user = optionalUser?.getOrNull()
if (user != null) {
avatarRenderer.render(user.toMatrixItem(), homeDrawerHeaderAvatarView)

View file

@ -25,6 +25,7 @@ import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.group.model.GroupSummary
import im.vector.matrix.android.api.session.room.RoomSummaryQueryParams
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.RoomMember
import im.vector.matrix.android.api.session.room.model.RoomSummary
@ -114,7 +115,7 @@ class TextComposerViewModel @AssistedInject constructor(@Assisted initialState:
private fun observeRoomsQuery() {
Observable.combineLatest<List<RoomSummary>, Option<AutocompleteQuery>, List<RoomSummary>>(
session.rx().liveRoomSummaries(),
session.rx().liveRoomSummaries(RoomSummaryQueryParams(filterCanonicalAlias = true)),
roomsQueryObservable.throttleLast(300, TimeUnit.MILLISECONDS),
BiFunction { roomSummaries, query ->
val filter = query.orNull() ?: ""

View file

@ -24,6 +24,7 @@ import com.squareup.inject.assisted.AssistedInject
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.failure.Failure
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.room.RoomSummaryQueryParams
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoomsFilter
import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoomsParams
@ -81,11 +82,9 @@ class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState:
private fun observeJoinedRooms() {
session
.rx()
.liveRoomSummaries()
.liveRoomSummaries(RoomSummaryQueryParams(memberships = listOf(Membership.JOIN)))
.subscribe { list ->
val joinedRoomIds = list
// Keep only joined room
?.filter { it.membership == Membership.JOIN }
?.map { it.roomId }
?.toSet()
?: emptySet()

View file

@ -23,6 +23,7 @@ import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.room.RoomSummaryQueryParams
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.rx.rx
import im.vector.riotx.core.platform.VectorViewModel
@ -55,12 +56,10 @@ class RoomPreviewViewModel @AssistedInject constructor(@Assisted initialState: R
private fun observeJoinedRooms() {
session
.rx()
.liveRoomSummaries()
.liveRoomSummaries(RoomSummaryQueryParams(memberships = listOf(Membership.JOIN)))
.subscribe { list ->
withState { state ->
val isRoomJoined = list
// Keep only joined room
?.filter { it.membership == Membership.JOIN }
?.map { it.roomId }
?.toList()
?.contains(state.roomId) == true

View file

@ -22,6 +22,7 @@ import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.ViewModelContext
import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
import im.vector.matrix.android.api.session.room.RoomSummaryQueryParams
import im.vector.matrix.rx.rx
import im.vector.riotx.ActiveSessionDataSource
import im.vector.riotx.core.platform.EmptyAction
@ -62,7 +63,7 @@ class IncomingShareViewModel @AssistedInject constructor(@Assisted initialState:
sessionObservableStore.observe()
.observeOn(AndroidSchedulers.mainThread())
.switchMap {
it.orNull()?.rx()?.liveRoomSummaries()
it.orNull()?.rx()?.liveRoomSummaries(RoomSummaryQueryParams())
?: Observable.just(emptyList())
}
.throttleLast(300, TimeUnit.MILLISECONDS)