mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-22 09:25:49 +03:00
Room member list: group by power level
This commit is contained in:
parent
81712ae736
commit
171ec4fbdc
43 changed files with 498 additions and 324 deletions
|
@ -22,3 +22,9 @@ import io.reactivex.Observable
|
|||
fun <T : Any> Observable<Optional<T>>.unwrap(): Observable<T> {
|
||||
return filter { it.hasValue() }.map { it.get() }
|
||||
}
|
||||
|
||||
fun <T : Any, U : Any> Observable<Optional<T>>.mapOptional(fn: (T) -> U?): Observable<Optional<U>> {
|
||||
return map {
|
||||
it.map(fn)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
|
||||
package im.vector.matrix.rx
|
||||
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.room.Room
|
||||
import im.vector.matrix.android.api.session.room.members.RoomMemberQueryParams
|
||||
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
||||
import im.vector.matrix.android.api.session.room.model.ReadReceipt
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.matrix.android.api.session.room.notification.RoomNotificationState
|
||||
import im.vector.matrix.android.api.session.room.send.UserDraft
|
||||
|
@ -37,7 +38,7 @@ class RxRoom(private val room: Room) {
|
|||
.startWith(room.roomSummary().toOptional())
|
||||
}
|
||||
|
||||
fun liveRoomMembers(queryParams: RoomMemberQueryParams): Observable<List<RoomMember>> {
|
||||
fun liveRoomMembers(queryParams: RoomMemberQueryParams): Observable<List<RoomMemberSummary>> {
|
||||
return room.getRoomMembersLive(queryParams).asObservable()
|
||||
.startWith(room.getRoomMembers(queryParams))
|
||||
}
|
||||
|
@ -52,6 +53,11 @@ class RxRoom(private val room: Room) {
|
|||
.startWith(room.getTimeLineEvent(eventId).toOptional())
|
||||
}
|
||||
|
||||
fun liveStateEvent(eventType: String): Observable<Optional<Event>> {
|
||||
return room.getStateEventLive(eventType).asObservable()
|
||||
.startWith(room.getStateEvent(eventType).toOptional())
|
||||
}
|
||||
|
||||
fun liveReadMarker(): Observable<Optional<String>> {
|
||||
return room.getReadMarkerLive().asObservable()
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import im.vector.matrix.android.api.session.events.model.Event
|
|||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.api.session.events.model.toContent
|
||||
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.RoomMemberSummary
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||
import kotlin.random.Random
|
||||
|
@ -63,7 +63,7 @@ object RoomDataHelper {
|
|||
}
|
||||
|
||||
fun createFakeRoomMemberEvent(): Event {
|
||||
val roomMember = RoomMember(Membership.JOIN, "Fake name #${Random.nextLong()}").toContent()
|
||||
val roomMember = RoomMemberSummary(Membership.JOIN, "Fake name #${Random.nextLong()}").toContent()
|
||||
return createFakeEvent(EventType.STATE_ROOM_MEMBER, roomMember)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
package im.vector.matrix.android.api.pushrules
|
||||
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.room.model.PowerLevels
|
||||
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
|
||||
import im.vector.matrix.android.api.session.room.powerlevers.PowerLevelsHelper
|
||||
|
||||
class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.sender_notification_permission) {
|
||||
|
||||
|
@ -28,7 +29,8 @@ class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.se
|
|||
return "User power level <$key>"
|
||||
}
|
||||
|
||||
fun isSatisfied(event: Event, powerLevels: PowerLevels): Boolean {
|
||||
return event.senderId != null && powerLevels.getUserPowerLevel(event.senderId) >= powerLevels.notificationLevel(key)
|
||||
fun isSatisfied(event: Event, powerLevels: PowerLevelsContent): Boolean {
|
||||
val powerLevelsHelper = PowerLevelsHelper(powerLevels)
|
||||
return event.senderId != null && powerLevelsHelper.getUserPowerLevel(event.senderId) >= powerLevelsHelper.notificationLevel(key)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ package im.vector.matrix.android.api.session.room.members
|
|||
|
||||
import androidx.lifecycle.LiveData
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
|
||||
/**
|
||||
|
@ -38,21 +38,21 @@ interface MembershipService {
|
|||
*
|
||||
* @return the roomMember with userId or null
|
||||
*/
|
||||
fun getRoomMember(userId: String): RoomMember?
|
||||
fun getRoomMember(userId: String): RoomMemberSummary?
|
||||
|
||||
/**
|
||||
* Return all the roomMembers of the room with params
|
||||
* @param queryParams the params to query for
|
||||
* @return a roomMember list.
|
||||
*/
|
||||
fun getRoomMembers(queryParams: RoomMemberQueryParams): List<RoomMember>
|
||||
fun getRoomMembers(queryParams: RoomMemberQueryParams): List<RoomMemberSummary>
|
||||
|
||||
/**
|
||||
* Return all the roomMembers of the room filtered by memberships
|
||||
* @param queryParams the params to query for
|
||||
* @return a [LiveData] of roomMember list.
|
||||
*/
|
||||
fun getRoomMembersLive(queryParams: RoomMemberQueryParams): LiveData<List<RoomMember>>
|
||||
fun getRoomMembersLive(queryParams: RoomMemberQueryParams): LiveData<List<RoomMemberSummary>>
|
||||
|
||||
fun getNumberOfJoinedMembers(): Int
|
||||
|
||||
|
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
* Copyright 2019 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.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
|
||||
/**
|
||||
* Class representing the EventType.EVENT_TYPE_STATE_ROOM_POWER_LEVELS state event content.
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class PowerLevels(
|
||||
@Json(name = "ban") val ban: Int = 50,
|
||||
@Json(name = "kick") val kick: Int = 50,
|
||||
@Json(name = "invite") val invite: Int = 50,
|
||||
@Json(name = "redact") val redact: Int = 50,
|
||||
@Json(name = "events_default") val eventsDefault: Int = 0,
|
||||
@Json(name = "events") val events: MutableMap<String, Int> = HashMap(),
|
||||
@Json(name = "users_default") val usersDefault: Int = 0,
|
||||
@Json(name = "users") val users: MutableMap<String, Int> = HashMap(),
|
||||
@Json(name = "state_default") val stateDefault: Int = 50,
|
||||
@Json(name = "notifications") val notifications: Map<String, Any> = HashMap()
|
||||
) {
|
||||
|
||||
/**
|
||||
* Returns the user power level of a dedicated user Id
|
||||
*
|
||||
* @param userId the user id
|
||||
* @return the power level
|
||||
*/
|
||||
fun getUserPowerLevel(userId: String): Int {
|
||||
return users.getOrElse(userId) { usersDefault }
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the user power levels of a dedicated user id
|
||||
*
|
||||
* @param userId the user
|
||||
* @param powerLevel the new power level
|
||||
*/
|
||||
fun setUserPowerLevel(userId: String, powerLevel: Int) {
|
||||
users[userId] = powerLevel
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if an user can send an event of type 'eventTypeString'.
|
||||
*
|
||||
* @param eventTypeString the event type (in Event.EVENT_TYPE_XXX values)
|
||||
* @param userId the user id
|
||||
* @return true if the user can send the event
|
||||
*/
|
||||
fun maySendEventOfType(eventTypeString: String, userId: String): Boolean {
|
||||
return if (eventTypeString.isNotEmpty() && userId.isNotEmpty()) {
|
||||
getUserPowerLevel(userId) >= minimumPowerLevelForSendingEventAsMessage(eventTypeString)
|
||||
} else false
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if an user can send a room message.
|
||||
*
|
||||
* @param userId the user id
|
||||
* @return true if the user can send a room message
|
||||
*/
|
||||
fun maySendMessage(userId: String): Boolean {
|
||||
return maySendEventOfType(EventType.MESSAGE, userId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to get the minimum power level the user must have to send an event of the given type
|
||||
* as a message.
|
||||
*
|
||||
* @param eventTypeString the type of event (in Event.EVENT_TYPE_XXX values)
|
||||
* @return the required minimum power level.
|
||||
*/
|
||||
fun minimumPowerLevelForSendingEventAsMessage(eventTypeString: String?): Int {
|
||||
return events[eventTypeString] ?: eventsDefault
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to get the minimum power level the user must have to send an event of the given type
|
||||
* as a state event.
|
||||
*
|
||||
* @param eventTypeString the type of event (in Event.EVENT_TYPE_STATE_ values).
|
||||
* @return the required minimum power level.
|
||||
*/
|
||||
fun minimumPowerLevelForSendingEventAsStateEvent(eventTypeString: String?): Int {
|
||||
return events[eventTypeString] ?: stateDefault
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification level for a dedicated key.
|
||||
*
|
||||
* @param key the notification key
|
||||
* @return the level
|
||||
*/
|
||||
fun notificationLevel(key: String): Int {
|
||||
val valAsVoid = notifications[key] ?: return 50
|
||||
|
||||
// the first implementation was a string value
|
||||
return if (valAsVoid is String) {
|
||||
valAsVoid.toInt()
|
||||
} else {
|
||||
valAsVoid as Int
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright 2019 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.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.api.session.room.powerlevers.PowerLevelsConstants
|
||||
|
||||
/**
|
||||
* Class representing the EventType.EVENT_TYPE_STATE_ROOM_POWER_LEVELS state event content.
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class PowerLevelsContent(
|
||||
@Json(name = "ban") val ban: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
|
||||
@Json(name = "kick") val kick: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
|
||||
@Json(name = "invite") val invite: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
|
||||
@Json(name = "redact") val redact: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
|
||||
@Json(name = "events_default") val eventsDefault: Int = PowerLevelsConstants.DEFAULT_ROOM_USER_LEVEL,
|
||||
@Json(name = "events") val events: MutableMap<String, Int> = HashMap(),
|
||||
@Json(name = "users_default") val usersDefault: Int = PowerLevelsConstants.DEFAULT_ROOM_USER_LEVEL,
|
||||
@Json(name = "users") val users: MutableMap<String, Int> = HashMap(),
|
||||
@Json(name = "state_default") val stateDefault: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
|
||||
@Json(name = "notifications") val notifications: Map<String, Any> = HashMap()
|
||||
)
|
|
@ -19,7 +19,7 @@ package im.vector.matrix.android.api.session.room.model
|
|||
/**
|
||||
* Class representing a simplified version of EventType.STATE_ROOM_MEMBER state event content
|
||||
*/
|
||||
data class RoomMember(
|
||||
data class RoomMemberSummary(
|
||||
val membership: Membership,
|
||||
val userId: String,
|
||||
val displayName: String? = null,
|
|
@ -24,7 +24,7 @@ import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
|||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.api.session.events.model.toContent
|
||||
import im.vector.matrix.android.api.session.room.model.PowerLevels
|
||||
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
|
||||
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
||||
import im.vector.matrix.android.internal.auth.data.ThreePidMedium
|
||||
|
@ -113,7 +113,7 @@ class CreateRoomParams {
|
|||
* The power level content to override in the default power level event
|
||||
*/
|
||||
@Json(name = "power_level_content_override")
|
||||
var powerLevelContentOverride: PowerLevels? = null
|
||||
var powerLevelContentOverride: PowerLevelsContent? = null
|
||||
|
||||
/**
|
||||
* Add the crypto algorithm to the room creation parameters.
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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.powerlevers
|
||||
|
||||
object PowerLevelsConstants {
|
||||
|
||||
const val DEFAULT_ROOM_ADMIN_LEVEL = 100
|
||||
const val DEFAULT_ROOM_MODERATOR_LEVEL = 50
|
||||
const val DEFAULT_ROOM_USER_LEVEL = 0
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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.powerlevers
|
||||
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
|
||||
|
||||
/**
|
||||
* This class is an helper around PowerLevelsContent.
|
||||
*/
|
||||
class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
||||
|
||||
/**
|
||||
* Returns the user power level of a dedicated user Id
|
||||
*
|
||||
* @param userId the user id
|
||||
* @return the power level
|
||||
*/
|
||||
fun getUserPowerLevel(userId: String): Int {
|
||||
return powerLevelsContent.users.getOrElse(userId) {
|
||||
powerLevelsContent.usersDefault
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if an user can send an event of a certain type
|
||||
*
|
||||
* @param eventType the event type to check for
|
||||
* @param userId the user id
|
||||
* @return true if the user can send this type of event
|
||||
*/
|
||||
fun isAllowedToSend(eventType: String, userId: String): Boolean {
|
||||
return if (eventType.isNotEmpty() && userId.isNotEmpty()) {
|
||||
val powerLevel = getUserPowerLevel(userId)
|
||||
val minimumPowerLevel = powerLevelsContent.events[eventType]
|
||||
?: if (EventType.isStateEvent(eventType)) {
|
||||
powerLevelsContent.stateDefault
|
||||
} else {
|
||||
powerLevelsContent.eventsDefault
|
||||
}
|
||||
powerLevel >= minimumPowerLevel
|
||||
} else false
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the notification level for a dedicated key.
|
||||
*
|
||||
* @param key the notification key
|
||||
* @return the level
|
||||
*/
|
||||
fun notificationLevel(key: String): Int {
|
||||
val value = powerLevelsContent.notifications[key]
|
||||
?: return PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL
|
||||
return when (value) {
|
||||
// the first implementation was a string value
|
||||
is String -> value.toInt()
|
||||
is Int -> value
|
||||
else -> PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,8 +16,10 @@
|
|||
|
||||
package im.vector.matrix.android.api.session.room.state
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
|
||||
interface StateService {
|
||||
|
||||
|
@ -27,4 +29,6 @@ interface StateService {
|
|||
fun updateTopic(topic: String, callback: MatrixCallback<Unit>)
|
||||
|
||||
fun getStateEvent(eventType: String): Event?
|
||||
|
||||
fun getStateEventLive(eventType: String): LiveData<Optional<Event>>
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ package im.vector.matrix.android.api.util
|
|||
|
||||
import im.vector.matrix.android.BuildConfig
|
||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom
|
||||
import im.vector.matrix.android.api.session.user.model.User
|
||||
|
@ -147,4 +147,4 @@ fun GroupSummary.toMatrixItem() = MatrixItem.GroupItem(groupId, displayName, ava
|
|||
fun RoomSummary.toMatrixItem() = MatrixItem.RoomItem(roomId, displayName, avatarUrl)
|
||||
fun RoomSummary.toRoomAliasMatrixItem() = MatrixItem.RoomAliasItem(canonicalAlias ?: roomId, displayName, avatarUrl)
|
||||
fun PublicRoom.toMatrixItem() = MatrixItem.RoomItem(roomId, name, avatarUrl)
|
||||
fun RoomMember.toMatrixItem() = MatrixItem.UserItem(userId, displayName, avatarUrl)
|
||||
fun RoomMemberSummary.toMatrixItem() = MatrixItem.UserItem(userId, displayName, avatarUrl)
|
||||
|
|
|
@ -27,6 +27,14 @@ data class Optional<T : Any> constructor(private val value: T?) {
|
|||
return value
|
||||
}
|
||||
|
||||
fun <U : Any> map(fn: (T) -> U?): Optional<U> {
|
||||
return if (value == null) {
|
||||
from(null)
|
||||
} else {
|
||||
from(fn(value))
|
||||
}
|
||||
}
|
||||
|
||||
fun getOrElse(fn: () -> T): T {
|
||||
return value ?: fn()
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ import im.vector.matrix.android.api.session.events.model.toModel
|
|||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibilityContent
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||
import im.vector.matrix.android.internal.crypto.actions.MegolmSessionDataImporter
|
||||
import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction
|
||||
import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting
|
||||
|
@ -64,7 +64,7 @@ import im.vector.matrix.android.internal.di.MoshiProvider
|
|||
import im.vector.matrix.android.internal.extensions.foldToCallback
|
||||
import im.vector.matrix.android.internal.session.SessionScope
|
||||
import im.vector.matrix.android.internal.session.room.membership.LoadRoomMembersTask
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
||||
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||
import im.vector.matrix.android.internal.task.configureWith
|
||||
|
@ -697,9 +697,9 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
&& shouldEncryptForInvitedMembers(roomId)
|
||||
|
||||
userIds = if (encryptForInvitedMembers) {
|
||||
RoomMembers(realm, roomId).getActiveRoomMemberIds()
|
||||
RoomMemberHelper(realm, roomId).getActiveRoomMemberIds()
|
||||
} else {
|
||||
RoomMembers(realm, roomId).getJoinedRoomMemberIds()
|
||||
RoomMemberHelper(realm, roomId).getJoinedRoomMemberIds()
|
||||
}
|
||||
}
|
||||
return userIds
|
||||
|
@ -722,7 +722,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
return
|
||||
}
|
||||
event.stateKey?.let { userId ->
|
||||
val roomMember: RoomMember? = event.content.toModel()
|
||||
val roomMember: RoomMemberSummary? = event.content.toModel()
|
||||
val membership = roomMember?.membership
|
||||
if (membership == Membership.JOIN) {
|
||||
// make sure we are tracking the deviceList for this user.
|
||||
|
|
|
@ -24,7 +24,7 @@ import im.vector.matrix.android.internal.database.model.RoomEntity
|
|||
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
||||
import im.vector.matrix.android.internal.database.query.fastContains
|
||||
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
||||
|
||||
internal fun RoomEntity.deleteOnCascade(chunkEntity: ChunkEntity) {
|
||||
chunks.remove(chunkEntity)
|
||||
|
@ -59,7 +59,7 @@ internal fun RoomEntity.addSendingEvent(event: Event) {
|
|||
val eventEntity = event.toEntity(roomId).apply {
|
||||
this.sendState = SendState.UNSENT
|
||||
}
|
||||
val roomMembers = RoomMembers(realm, roomId)
|
||||
val roomMembers = RoomMemberHelper(realm, roomId)
|
||||
val myUser = roomMembers.getLastRoomMember(senderId)
|
||||
val localId = TimelineEventEntity.nextId(realm)
|
||||
val timelineEventEntity = TimelineEventEntity(localId).also {
|
||||
|
|
|
@ -26,7 +26,7 @@ import im.vector.matrix.android.internal.database.query.prev
|
|||
import im.vector.matrix.android.internal.database.query.where
|
||||
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
||||
import im.vector.matrix.android.internal.session.SessionScope
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
||||
import io.realm.RealmList
|
||||
import io.realm.RealmQuery
|
||||
import javax.inject.Inject
|
||||
|
@ -128,7 +128,7 @@ internal class TimelineEventSenderVisitor @Inject constructor() {
|
|||
ContentMapper.map(senderRoomMemberContent).toModel<RoomMemberContent>()?.also {
|
||||
result.senderAvatar = it.avatarUrl
|
||||
result.senderName = it.displayName
|
||||
result.isUniqueDisplayName = RoomMembers(realm, roomId).isUniqueDisplayName(it.displayName)
|
||||
result.isUniqueDisplayName = RoomMemberHelper(realm, roomId).isUniqueDisplayName(it.displayName)
|
||||
}
|
||||
// We try to fallback on prev content if we got a room member state events with null fields
|
||||
if (root?.type == EventType.STATE_ROOM_MEMBER) {
|
||||
|
@ -138,7 +138,7 @@ internal class TimelineEventSenderVisitor @Inject constructor() {
|
|||
}
|
||||
if (result.senderName == null && it.displayName != null) {
|
||||
result.senderName = it.displayName
|
||||
result.isUniqueDisplayName = RoomMembers(realm, roomId).isUniqueDisplayName(it.displayName)
|
||||
result.isUniqueDisplayName = RoomMemberHelper(realm, roomId).isUniqueDisplayName(it.displayName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,21 +16,21 @@
|
|||
|
||||
package im.vector.matrix.android.internal.database.mapper
|
||||
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
|
||||
|
||||
internal object RoomMemberMapper {
|
||||
internal object RoomMemberSummaryMapper {
|
||||
|
||||
fun map(roomMemberEntity: RoomMemberEntity): RoomMember {
|
||||
return RoomMember(
|
||||
userId = roomMemberEntity.userId,
|
||||
avatarUrl = roomMemberEntity.avatarUrl,
|
||||
displayName = roomMemberEntity.displayName,
|
||||
membership = roomMemberEntity.membership
|
||||
fun map(roomMemberSummaryEntity: RoomMemberSummaryEntity): RoomMemberSummary {
|
||||
return RoomMemberSummary(
|
||||
userId = roomMemberSummaryEntity.userId,
|
||||
avatarUrl = roomMemberSummaryEntity.avatarUrl,
|
||||
displayName = roomMemberSummaryEntity.displayName,
|
||||
membership = roomMemberSummaryEntity.membership
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun RoomMemberEntity.asDomain(): RoomMember {
|
||||
return RoomMemberMapper.map(this)
|
||||
internal fun RoomMemberSummaryEntity.asDomain(): RoomMemberSummary {
|
||||
return RoomMemberSummaryMapper.map(this)
|
||||
}
|
|
@ -21,13 +21,13 @@ import io.realm.RealmObject
|
|||
import io.realm.annotations.Index
|
||||
import io.realm.annotations.PrimaryKey
|
||||
|
||||
internal open class RoomMemberEntity(@PrimaryKey var primaryKey: String = "",
|
||||
@Index var userId: String = "",
|
||||
@Index var roomId: String = "",
|
||||
var displayName: String? = null,
|
||||
var avatarUrl: String? = null ,
|
||||
var reason: String? = null,
|
||||
var isDirect: Boolean = false
|
||||
internal open class RoomMemberSummaryEntity(@PrimaryKey var primaryKey: String = "",
|
||||
@Index var userId: String = "",
|
||||
@Index var roomId: String = "",
|
||||
var displayName: String? = null,
|
||||
var avatarUrl: String? = null,
|
||||
var reason: String? = null,
|
||||
var isDirect: Boolean = false
|
||||
) : RealmObject() {
|
||||
|
||||
private var membershipStr: String = Membership.NONE.name
|
|
@ -50,6 +50,6 @@ import io.realm.annotations.RealmModule
|
|||
UserDraftsEntity::class,
|
||||
DraftEntity::class,
|
||||
HomeServerCapabilitiesEntity::class,
|
||||
RoomMemberEntity::class
|
||||
RoomMemberSummaryEntity::class
|
||||
])
|
||||
internal class SessionRealmModule
|
||||
|
|
|
@ -60,20 +60,7 @@ internal fun EventEntity.Companion.types(realm: Realm,
|
|||
return query
|
||||
}
|
||||
|
||||
internal fun RealmQuery<EventEntity>.next(from: Int? = null, strict: Boolean = true): EventEntity? {
|
||||
if (from != null) {
|
||||
if (strict) {
|
||||
this.greaterThan(EventEntityFields.STATE_INDEX, from)
|
||||
} else {
|
||||
this.greaterThanOrEqualTo(EventEntityFields.STATE_INDEX, from)
|
||||
}
|
||||
}
|
||||
return this
|
||||
.sort(EventEntityFields.STATE_INDEX, Sort.ASCENDING)
|
||||
.findFirst()
|
||||
}
|
||||
|
||||
internal fun RealmQuery<EventEntity>.prev(since: Int? = null, strict: Boolean = false): EventEntity? {
|
||||
internal fun RealmQuery<EventEntity>.descending(since: Int? = null, strict: Boolean = false): RealmQuery<EventEntity> {
|
||||
if (since != null) {
|
||||
if (strict) {
|
||||
this.lessThan(EventEntityFields.STATE_INDEX, since)
|
||||
|
@ -81,9 +68,26 @@ internal fun RealmQuery<EventEntity>.prev(since: Int? = null, strict: Boolean =
|
|||
this.lessThanOrEqualTo(EventEntityFields.STATE_INDEX, since)
|
||||
}
|
||||
}
|
||||
return this
|
||||
.sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING)
|
||||
.findFirst()
|
||||
return this.sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING)
|
||||
}
|
||||
|
||||
internal fun RealmQuery<EventEntity>.ascending(from: Int? = null, strict: Boolean = true): RealmQuery<EventEntity> {
|
||||
if (from != null) {
|
||||
if (strict) {
|
||||
this.greaterThan(EventEntityFields.STATE_INDEX, from)
|
||||
} else {
|
||||
this.greaterThanOrEqualTo(EventEntityFields.STATE_INDEX, from)
|
||||
}
|
||||
}
|
||||
return this.sort(EventEntityFields.STATE_INDEX, Sort.ASCENDING)
|
||||
}
|
||||
|
||||
internal fun RealmQuery<EventEntity>.next(from: Int? = null, strict: Boolean = true): EventEntity? {
|
||||
return this.ascending(from, strict).findFirst()
|
||||
}
|
||||
|
||||
internal fun RealmQuery<EventEntity>.prev(since: Int? = null, strict: Boolean = false): EventEntity? {
|
||||
return descending(since, strict).findFirst()
|
||||
}
|
||||
|
||||
internal fun RealmList<EventEntity>.find(eventId: String): EventEntity? {
|
||||
|
|
|
@ -16,19 +16,19 @@
|
|||
|
||||
package im.vector.matrix.android.internal.database.query
|
||||
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntityFields
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntityFields
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmQuery
|
||||
import io.realm.kotlin.where
|
||||
|
||||
internal fun RoomMemberEntity.Companion.where(realm: Realm, roomId: String, userId: String? = null): RealmQuery<RoomMemberEntity> {
|
||||
internal fun RoomMemberSummaryEntity.Companion.where(realm: Realm, roomId: String, userId: String? = null): RealmQuery<RoomMemberSummaryEntity> {
|
||||
val query = realm
|
||||
.where<RoomMemberEntity>()
|
||||
.equalTo(RoomMemberEntityFields.ROOM_ID, roomId)
|
||||
.where<RoomMemberSummaryEntity>()
|
||||
.equalTo(RoomMemberSummaryEntityFields.ROOM_ID, roomId)
|
||||
|
||||
if (userId != null) {
|
||||
query.equalTo(RoomMemberEntityFields.USER_ID, userId)
|
||||
query.equalTo(RoomMemberSummaryEntityFields.USER_ID, userId)
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
|
|
@ -22,11 +22,11 @@ import im.vector.matrix.android.api.session.events.model.toModel
|
|||
import im.vector.matrix.android.api.session.room.model.RoomAvatarContent
|
||||
import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntityFields
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntityFields
|
||||
import im.vector.matrix.android.internal.database.query.prev
|
||||
import im.vector.matrix.android.internal.database.query.where
|
||||
import im.vector.matrix.android.internal.di.UserId
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class RoomAvatarResolver @Inject constructor(private val monarchy: Monarchy,
|
||||
|
@ -45,13 +45,13 @@ internal class RoomAvatarResolver @Inject constructor(private val monarchy: Mona
|
|||
if (!res.isNullOrEmpty()) {
|
||||
return@doWithRealm
|
||||
}
|
||||
val roomMembers = RoomMembers(realm, roomId)
|
||||
val roomMembers = RoomMemberHelper(realm, roomId)
|
||||
val members = roomMembers.queryActiveRoomMembersEvent().findAll()
|
||||
// detect if it is a room with no more than 2 members (i.e. an alone or a 1:1 chat)
|
||||
if (members.size == 1) {
|
||||
res = members.firstOrNull()?.avatarUrl
|
||||
} else if (members.size == 2) {
|
||||
val firstOtherMember = members.where().notEqualTo(RoomMemberEntityFields.USER_ID, userId).findFirst()
|
||||
val firstOtherMember = members.where().notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId).findFirst()
|
||||
res = firstOtherMember?.avatarUrl
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ import im.vector.matrix.android.internal.database.query.prev
|
|||
import im.vector.matrix.android.internal.database.query.where
|
||||
import im.vector.matrix.android.internal.di.UserId
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomDisplayNameResolver
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
||||
import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary
|
||||
import im.vector.matrix.android.internal.session.sync.model.RoomSyncUnreadNotifications
|
||||
import io.realm.Realm
|
||||
|
@ -114,9 +114,9 @@ internal class RoomSummaryUpdater @Inject constructor(@UserId private val userId
|
|||
roomSummaryEntity.isEncrypted = encryptionEvent != null
|
||||
|
||||
if (updateMembers) {
|
||||
val otherRoomMembers = RoomMembers(realm, roomId)
|
||||
val otherRoomMembers = RoomMemberHelper(realm, roomId)
|
||||
.queryRoomMembersEvent()
|
||||
.notEqualTo(RoomMemberEntityFields.USER_ID, userId)
|
||||
.notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
|
||||
.findAll()
|
||||
.asSequence()
|
||||
.map { it.userId }
|
||||
|
|
|
@ -24,11 +24,11 @@ import im.vector.matrix.android.api.MatrixCallback
|
|||
import im.vector.matrix.android.api.session.room.members.MembershipService
|
||||
import im.vector.matrix.android.api.session.room.members.RoomMemberQueryParams
|
||||
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.RoomMemberSummary
|
||||
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.database.model.RoomMemberSummaryEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntityFields
|
||||
import im.vector.matrix.android.internal.query.process
|
||||
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
|
||||
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
|
||||
|
@ -62,14 +62,14 @@ internal class DefaultMembershipService @AssistedInject constructor(@Assisted pr
|
|||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
override fun getRoomMember(userId: String): RoomMember? {
|
||||
override fun getRoomMember(userId: String): RoomMemberSummary? {
|
||||
val roomMemberEntity = monarchy.fetchCopied {
|
||||
RoomMembers(it, roomId).getLastRoomMember(userId)
|
||||
RoomMemberHelper(it, roomId).getLastRoomMember(userId)
|
||||
}
|
||||
return roomMemberEntity?.asDomain()
|
||||
}
|
||||
|
||||
override fun getRoomMembers(queryParams: RoomMemberQueryParams): List<RoomMember> {
|
||||
override fun getRoomMembers(queryParams: RoomMemberQueryParams): List<RoomMemberSummary> {
|
||||
return monarchy.fetchAllMappedSync(
|
||||
{
|
||||
roomMembersQuery(it, queryParams)
|
||||
|
@ -80,7 +80,7 @@ internal class DefaultMembershipService @AssistedInject constructor(@Assisted pr
|
|||
)
|
||||
}
|
||||
|
||||
override fun getRoomMembersLive(queryParams: RoomMemberQueryParams): LiveData<List<RoomMember>> {
|
||||
override fun getRoomMembersLive(queryParams: RoomMemberQueryParams): LiveData<List<RoomMemberSummary>> {
|
||||
return monarchy.findAllMappedWithChanges(
|
||||
{
|
||||
roomMembersQuery(it, queryParams)
|
||||
|
@ -91,15 +91,15 @@ internal class DefaultMembershipService @AssistedInject constructor(@Assisted pr
|
|||
)
|
||||
}
|
||||
|
||||
private fun roomMembersQuery(realm: Realm, queryParams: RoomMemberQueryParams): RealmQuery<RoomMemberEntity> {
|
||||
return RoomMembers(realm, roomId).queryRoomMembersEvent()
|
||||
.process(RoomMemberEntityFields.MEMBERSHIP_STR, queryParams.memberships)
|
||||
.process(RoomMemberEntityFields.DISPLAY_NAME, queryParams.displayName)
|
||||
private fun roomMembersQuery(realm: Realm, queryParams: RoomMemberQueryParams): RealmQuery<RoomMemberSummaryEntity> {
|
||||
return RoomMemberHelper(realm, roomId).queryRoomMembersEvent()
|
||||
.process(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
|
||||
.process(RoomMemberSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
|
||||
}
|
||||
|
||||
override fun getNumberOfJoinedMembers(): Int {
|
||||
return Realm.getInstance(monarchy.realmConfiguration).use {
|
||||
RoomMembers(it, roomId).getNumberOfJoinedMembers()
|
||||
RoomMemberHelper(it, roomId).getNumberOfJoinedMembers()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
|||
import im.vector.matrix.android.internal.database.model.*
|
||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||
import im.vector.matrix.android.internal.database.query.prev
|
||||
import im.vector.matrix.android.internal.database.query.where
|
||||
|
@ -75,7 +75,7 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
|
|||
return@doWithRealm
|
||||
}
|
||||
|
||||
val roomMembers = RoomMembers(realm, roomId)
|
||||
val roomMembers = RoomMemberHelper(realm, roomId)
|
||||
val activeMembers = roomMembers.queryActiveRoomMembersEvent().findAll()
|
||||
|
||||
if (roomEntity?.membership == Membership.INVITE) {
|
||||
|
@ -83,7 +83,7 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
|
|||
val inviterId = inviteMeEvent?.sender
|
||||
name = if (inviterId != null) {
|
||||
activeMembers.where()
|
||||
.equalTo(RoomMemberEntityFields.USER_ID, inviterId)
|
||||
.equalTo(RoomMemberSummaryEntityFields.USER_ID, inviterId)
|
||||
.findFirst()
|
||||
?.displayName
|
||||
} else {
|
||||
|
@ -91,7 +91,7 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
|
|||
}
|
||||
} else if (roomEntity?.membership == Membership.JOIN) {
|
||||
val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst()
|
||||
val otherMembersSubset: List<RoomMemberEntity> = if (roomSummary?.heroes?.isNotEmpty() == true) {
|
||||
val otherMembersSubset: List<RoomMemberSummaryEntity> = if (roomSummary?.heroes?.isNotEmpty() == true) {
|
||||
roomSummary.heroes.mapNotNull { userId ->
|
||||
roomMembers.getLastRoomMember(userId)?.takeIf {
|
||||
it.membership == Membership.INVITE || it.membership == Membership.JOIN
|
||||
|
@ -99,7 +99,7 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
|
|||
}
|
||||
} else {
|
||||
activeMembers.where()
|
||||
.notEqualTo(RoomMemberEntityFields.USER_ID, userId)
|
||||
.notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
|
||||
.limit(3)
|
||||
.findAll()
|
||||
.createSnapshot()
|
||||
|
@ -123,14 +123,14 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
|
|||
return name ?: roomId
|
||||
}
|
||||
|
||||
private fun resolveRoomMemberName(roomMember: RoomMemberEntity?,
|
||||
roomMembers: RoomMembers): String? {
|
||||
if (roomMember == null) return null
|
||||
val isUnique = roomMembers.isUniqueDisplayName(roomMember.displayName)
|
||||
private fun resolveRoomMemberName(roomMemberSummary: RoomMemberSummaryEntity?,
|
||||
roomMemberHelper: RoomMemberHelper): String? {
|
||||
if (roomMemberSummary == null) return null
|
||||
val isUnique = roomMemberHelper.isUniqueDisplayName(roomMemberSummary.displayName)
|
||||
return if (isUnique) {
|
||||
roomMember.displayName
|
||||
roomMemberSummary.displayName
|
||||
} else {
|
||||
"${roomMember.displayName} (${roomMember.userId})"
|
||||
"${roomMemberSummary.displayName} (${roomMemberSummary.userId})"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,13 @@
|
|||
package im.vector.matrix.android.internal.session.room.membership
|
||||
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberContent
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
|
||||
|
||||
internal object RoomMemberEntityFactory {
|
||||
|
||||
fun create(roomId: String, userId: String, roomMember: RoomMemberContent): RoomMemberEntity {
|
||||
fun create(roomId: String, userId: String, roomMember: RoomMemberContent): RoomMemberSummaryEntity {
|
||||
val primaryKey = "${roomId}_$userId"
|
||||
return RoomMemberEntity(
|
||||
return RoomMemberSummaryEntity(
|
||||
primaryKey = primaryKey,
|
||||
userId = userId,
|
||||
roomId = roomId,
|
||||
|
|
|
@ -20,7 +20,7 @@ import im.vector.matrix.android.api.session.events.model.EventType
|
|||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
import im.vector.matrix.android.internal.database.model.*
|
||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||
import im.vector.matrix.android.internal.database.query.where
|
||||
import io.realm.Realm
|
||||
|
@ -32,8 +32,8 @@ import io.realm.Sort
|
|||
* It allows to get the live membership of a user.
|
||||
*/
|
||||
|
||||
internal class RoomMembers(private val realm: Realm,
|
||||
private val roomId: String
|
||||
internal class RoomMemberHelper(private val realm: Realm,
|
||||
private val roomId: String
|
||||
) {
|
||||
|
||||
private val roomSummary: RoomSummaryEntity? by lazy {
|
||||
|
@ -48,8 +48,8 @@ internal class RoomMembers(private val realm: Realm,
|
|||
.findFirst()
|
||||
}
|
||||
|
||||
fun getLastRoomMember(userId: String): RoomMemberEntity? {
|
||||
return RoomMemberEntity
|
||||
fun getLastRoomMember(userId: String): RoomMemberSummaryEntity? {
|
||||
return RoomMemberSummaryEntity
|
||||
.where(realm, roomId, userId)
|
||||
.findFirst()
|
||||
}
|
||||
|
@ -66,26 +66,26 @@ internal class RoomMembers(private val realm: Realm,
|
|||
.size == 1
|
||||
}
|
||||
|
||||
fun queryRoomMembersEvent(): RealmQuery<RoomMemberEntity> {
|
||||
return RoomMemberEntity.where(realm, roomId)
|
||||
fun queryRoomMembersEvent(): RealmQuery<RoomMemberSummaryEntity> {
|
||||
return RoomMemberSummaryEntity.where(realm, roomId)
|
||||
}
|
||||
|
||||
fun queryJoinedRoomMembersEvent(): RealmQuery<RoomMemberEntity> {
|
||||
fun queryJoinedRoomMembersEvent(): RealmQuery<RoomMemberSummaryEntity> {
|
||||
return queryRoomMembersEvent()
|
||||
.equalTo(RoomMemberEntityFields.MEMBERSHIP_STR, Membership.JOIN.name)
|
||||
.equalTo(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, Membership.JOIN.name)
|
||||
}
|
||||
|
||||
fun queryInvitedRoomMembersEvent(): RealmQuery<RoomMemberEntity> {
|
||||
fun queryInvitedRoomMembersEvent(): RealmQuery<RoomMemberSummaryEntity> {
|
||||
return queryRoomMembersEvent()
|
||||
.equalTo(RoomMemberEntityFields.MEMBERSHIP_STR, Membership.INVITE.name)
|
||||
.equalTo(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, Membership.INVITE.name)
|
||||
}
|
||||
|
||||
fun queryActiveRoomMembersEvent(): RealmQuery<RoomMemberEntity> {
|
||||
fun queryActiveRoomMembersEvent(): RealmQuery<RoomMemberSummaryEntity> {
|
||||
return queryRoomMembersEvent()
|
||||
.beginGroup()
|
||||
.equalTo(RoomMemberEntityFields.MEMBERSHIP_STR, Membership.INVITE.name)
|
||||
.equalTo(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, Membership.INVITE.name)
|
||||
.or()
|
||||
.equalTo(RoomMemberEntityFields.MEMBERSHIP_STR, Membership.JOIN.name)
|
||||
.equalTo(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, Membership.JOIN.name)
|
||||
.endGroup()
|
||||
}
|
||||
|
|
@ -16,25 +16,34 @@
|
|||
|
||||
package im.vector.matrix.android.internal.session.room.state
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.api.session.room.state.StateService
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
import im.vector.matrix.android.api.util.toOptional
|
||||
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
|
||||
import im.vector.matrix.android.internal.database.query.descending
|
||||
import im.vector.matrix.android.internal.database.query.prev
|
||||
import im.vector.matrix.android.internal.database.query.where
|
||||
import im.vector.matrix.android.internal.di.SessionDatabase
|
||||
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 im.vector.matrix.android.internal.util.fetchCopyMap
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmConfiguration
|
||||
|
||||
internal class DefaultStateService @AssistedInject constructor(@Assisted private val roomId: String,
|
||||
@SessionDatabase
|
||||
private val realmConfiguration: RealmConfiguration,
|
||||
private val monarchy: Monarchy,
|
||||
private val taskExecutor: TaskExecutor,
|
||||
private val sendStateTask: SendStateTask
|
||||
) : StateService {
|
||||
|
@ -45,11 +54,21 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private
|
|||
}
|
||||
|
||||
override fun getStateEvent(eventType: String): Event? {
|
||||
return Realm.getInstance(realmConfiguration).use { realm ->
|
||||
return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
|
||||
EventEntity.where(realm, roomId, eventType).prev()?.asDomain()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStateEventLive(eventType: String): LiveData<Optional<Event>> {
|
||||
val liveData = monarchy.findAllMappedWithChanges(
|
||||
{ realm -> EventEntity.where(realm, roomId, eventType).descending()},
|
||||
{ it.asDomain() }
|
||||
)
|
||||
return Transformations.map(liveData) { results ->
|
||||
results.firstOrNull().toOptional()
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateTopic(topic: String, callback: MatrixCallback<Unit>) {
|
||||
val params = SendStateTask.Params(roomId,
|
||||
EventType.STATE_ROOM_TOPIC,
|
||||
|
|
|
@ -28,7 +28,7 @@ import im.vector.matrix.android.internal.database.query.getDirectRooms
|
|||
import im.vector.matrix.android.internal.database.query.getOrCreate
|
||||
import im.vector.matrix.android.internal.database.query.where
|
||||
import im.vector.matrix.android.internal.di.UserId
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
||||
import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync
|
||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.*
|
||||
import im.vector.matrix.android.internal.session.user.accountdata.DirectChatsHelper
|
||||
|
@ -69,7 +69,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(private val monarc
|
|||
var hasUpdate = false
|
||||
monarchy.doWithRealm { realm ->
|
||||
invites.forEach { (roomId, _) ->
|
||||
val myUserStateEvent = RoomMembers(realm, roomId).getLastStateEvent(userId)
|
||||
val myUserStateEvent = RoomMemberHelper(realm, roomId).getLastStateEvent(userId)
|
||||
val inviterId = myUserStateEvent?.sender
|
||||
val myUserRoomMember: RoomMemberContent? = myUserStateEvent?.let { it.asDomain().content?.toModel() }
|
||||
val isDirect = myUserRoomMember?.isDirect
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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.riotx.core.epoxy.profiles
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.airbnb.epoxy.EpoxyController
|
||||
import im.vector.riotx.core.epoxy.DividerItem_
|
||||
|
||||
fun EpoxyController.buildProfileSection(title: String) {
|
||||
profileItemSection {
|
||||
id("section_$title")
|
||||
title(title)
|
||||
}
|
||||
}
|
||||
|
||||
fun EpoxyController.buildProfileAction(
|
||||
id: String,
|
||||
title: String,
|
||||
subtitle: String? = null,
|
||||
@DrawableRes icon: Int = 0,
|
||||
destructive: Boolean = false,
|
||||
divider: Boolean = true,
|
||||
action: () -> Unit
|
||||
) {
|
||||
|
||||
profileItemAction {
|
||||
iconRes(icon)
|
||||
id("action_$id")
|
||||
subtitle(subtitle)
|
||||
destructive(destructive)
|
||||
title(title)
|
||||
listener { _ ->
|
||||
action()
|
||||
}
|
||||
}
|
||||
|
||||
DividerItem_()
|
||||
.id("divider_$title")
|
||||
.addIf(divider, this)
|
||||
}
|
|
@ -17,20 +17,20 @@
|
|||
package im.vector.riotx.features.autocomplete.member
|
||||
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||
import im.vector.matrix.android.api.util.toMatrixItem
|
||||
import im.vector.riotx.features.autocomplete.AutocompleteClickListener
|
||||
import im.vector.riotx.features.autocomplete.autocompleteMatrixItem
|
||||
import im.vector.riotx.features.home.AvatarRenderer
|
||||
import javax.inject.Inject
|
||||
|
||||
class AutocompleteMemberController @Inject constructor() : TypedEpoxyController<List<RoomMember>>() {
|
||||
class AutocompleteMemberController @Inject constructor() : TypedEpoxyController<List<RoomMemberSummary>>() {
|
||||
|
||||
var listener: AutocompleteClickListener<RoomMember>? = null
|
||||
var listener: AutocompleteClickListener<RoomMemberSummary>? = null
|
||||
|
||||
@Inject lateinit var avatarRenderer: AvatarRenderer
|
||||
|
||||
override fun buildModels(data: List<RoomMember>?) {
|
||||
override fun buildModels(data: List<RoomMemberSummary>?) {
|
||||
if (data.isNullOrEmpty()) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -25,14 +25,14 @@ import im.vector.matrix.android.api.query.QueryStringValue
|
|||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.room.members.roomMemberQueryParams
|
||||
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.RoomMemberSummary
|
||||
import im.vector.riotx.features.autocomplete.AutocompleteClickListener
|
||||
|
||||
class AutocompleteMemberPresenter @AssistedInject constructor(context: Context,
|
||||
@Assisted val roomId: String,
|
||||
private val session: Session,
|
||||
private val controller: AutocompleteMemberController
|
||||
) : RecyclerViewPresenter<RoomMember>(context), AutocompleteClickListener<RoomMember> {
|
||||
) : RecyclerViewPresenter<RoomMemberSummary>(context), AutocompleteClickListener<RoomMemberSummary> {
|
||||
|
||||
private val room = session.getRoom(roomId)!!
|
||||
|
||||
|
@ -51,7 +51,7 @@ class AutocompleteMemberPresenter @AssistedInject constructor(context: Context,
|
|||
return controller.adapter
|
||||
}
|
||||
|
||||
override fun onItemClick(t: RoomMember) {
|
||||
override fun onItemClick(t: RoomMemberSummary) {
|
||||
dispatchClick(t)
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import com.otaliastudios.autocomplete.CharPolicy
|
|||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.matrix.android.api.util.MatrixItem
|
||||
import im.vector.matrix.android.api.util.toMatrixItem
|
||||
|
@ -108,13 +108,13 @@ class AutoCompleter @AssistedInject constructor(
|
|||
|
||||
private fun setupMembers(backgroundDrawable: ColorDrawable, editText: EditText) {
|
||||
val autocompleteMemberPresenter = autocompleteMemberPresenterFactory.create(roomId)
|
||||
Autocomplete.on<RoomMember>(editText)
|
||||
Autocomplete.on<RoomMemberSummary>(editText)
|
||||
.with(CharPolicy('@', true))
|
||||
.with(autocompleteMemberPresenter)
|
||||
.with(ELEVATION)
|
||||
.with(backgroundDrawable)
|
||||
.with(object : AutocompleteCallback<RoomMember> {
|
||||
override fun onPopupItemClicked(editable: Editable, item: RoomMember): Boolean {
|
||||
.with(object : AutocompleteCallback<RoomMemberSummary> {
|
||||
override fun onPopupItemClicked(editable: Editable, item: RoomMemberSummary): Boolean {
|
||||
insertMatrixItem(editText, editable, "@", item.toMatrixItem())
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ import im.vector.matrix.android.api.session.events.model.toModel
|
|||
import im.vector.matrix.android.api.session.file.FileService
|
||||
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilities
|
||||
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.RoomMemberSummary
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||
|
@ -210,7 +210,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
|||
invisibleEventsObservable.accept(action)
|
||||
}
|
||||
|
||||
fun getMember(userId: String): RoomMember? {
|
||||
fun getMember(userId: String): RoomMemberSummary? {
|
||||
return room.getRoomMember(userId)
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.airbnb.mvrx.Async
|
|||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||
import im.vector.matrix.android.api.session.sync.SyncState
|
||||
|
|
|
@ -23,6 +23,8 @@ import com.airbnb.epoxy.TypedEpoxyController
|
|||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.epoxy.DividerItem_
|
||||
import im.vector.riotx.core.epoxy.dividerItem
|
||||
import im.vector.riotx.core.epoxy.profiles.buildProfileAction
|
||||
import im.vector.riotx.core.epoxy.profiles.buildProfileSection
|
||||
import im.vector.riotx.core.epoxy.profiles.profileItemAction
|
||||
import im.vector.riotx.core.epoxy.profiles.profileItemSection
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
|
@ -50,13 +52,13 @@ class RoomProfileController @Inject constructor(private val stringProvider: Stri
|
|||
val roomSummary = data.roomSummary()
|
||||
|
||||
// Security
|
||||
buildSection(stringProvider.getString(R.string.room_profile_section_security))
|
||||
buildProfileSection(stringProvider.getString(R.string.room_profile_section_security))
|
||||
val learnMoreSubtitle = if (data.isEncrypted) {
|
||||
R.string.room_profile_encrypted_subtitle
|
||||
} else {
|
||||
R.string.room_profile_not_encrypted_subtitle
|
||||
}
|
||||
buildAction(
|
||||
buildProfileAction(
|
||||
id = "learn_more",
|
||||
title = stringProvider.getString(R.string.room_profile_section_security_learn_more),
|
||||
subtitle = stringProvider.getString(learnMoreSubtitle),
|
||||
|
@ -64,33 +66,33 @@ class RoomProfileController @Inject constructor(private val stringProvider: Stri
|
|||
)
|
||||
|
||||
// More
|
||||
buildSection(stringProvider.getString(R.string.room_profile_section_more))
|
||||
buildAction(
|
||||
buildProfileSection(stringProvider.getString(R.string.room_profile_section_more))
|
||||
buildProfileAction(
|
||||
id = "settings",
|
||||
title = stringProvider.getString(R.string.room_profile_section_more_settings),
|
||||
icon = R.drawable.ic_room_profile_settings,
|
||||
action = { callback?.onSettingsClicked() }
|
||||
)
|
||||
buildAction(
|
||||
buildProfileAction(
|
||||
id = "notifications",
|
||||
title = stringProvider.getString(R.string.room_profile_section_more_notifications),
|
||||
icon = R.drawable.ic_room_profile_notification,
|
||||
action = { callback?.onNotificationsClicked() }
|
||||
)
|
||||
val numberOfMembers = roomSummary?.joinedMembersCount?.toString() ?: "-"
|
||||
buildAction(
|
||||
buildProfileAction(
|
||||
id = "member_list",
|
||||
title = stringProvider.getString(R.string.room_profile_section_more_member_list, numberOfMembers),
|
||||
icon = R.drawable.ic_room_profile_member_list,
|
||||
action = { callback?.onMemberListClicked() }
|
||||
)
|
||||
buildAction(
|
||||
buildProfileAction(
|
||||
id = "uploads",
|
||||
title = stringProvider.getString(R.string.room_profile_section_more_uploads),
|
||||
icon = R.drawable.ic_room_profile_uploads,
|
||||
action = { callback?.onUploadsClicked() }
|
||||
)
|
||||
buildAction(
|
||||
buildProfileAction(
|
||||
id = "leave",
|
||||
title = stringProvider.getString(R.string.room_profile_section_more_leave),
|
||||
divider = false,
|
||||
|
@ -99,38 +101,6 @@ class RoomProfileController @Inject constructor(private val stringProvider: Stri
|
|||
)
|
||||
}
|
||||
|
||||
private fun buildSection(title: String) {
|
||||
profileItemSection {
|
||||
id("section_$title")
|
||||
title(title)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildAction(
|
||||
id: String,
|
||||
title: String,
|
||||
subtitle: String? = null,
|
||||
@DrawableRes icon: Int = 0,
|
||||
destructive: Boolean = false,
|
||||
divider: Boolean = true,
|
||||
action: () -> Unit
|
||||
) {
|
||||
|
||||
profileItemAction {
|
||||
iconRes(icon)
|
||||
id("action_$id")
|
||||
subtitle(subtitle)
|
||||
destructive(destructive)
|
||||
title(title)
|
||||
listener { _ ->
|
||||
action()
|
||||
}
|
||||
}
|
||||
|
||||
DividerItem_()
|
||||
.id("divider_$title")
|
||||
.addIf(divider, this)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -17,33 +17,48 @@
|
|||
package im.vector.riotx.features.roomprofile.members
|
||||
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||
import im.vector.matrix.android.api.util.toMatrixItem
|
||||
import im.vector.riotx.core.epoxy.profiles.profileItemAction
|
||||
import im.vector.riotx.core.epoxy.profiles.buildProfileSection
|
||||
import im.vector.riotx.core.epoxy.profiles.profileMatrixItem
|
||||
import im.vector.riotx.features.autocomplete.autocompleteMatrixItem
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
import im.vector.riotx.features.home.AvatarRenderer
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomMemberListController @Inject constructor(private val avatarRenderer: AvatarRenderer) : TypedEpoxyController<RoomMemberListViewState>() {
|
||||
class RoomMemberListController @Inject constructor(private val avatarRenderer: AvatarRenderer,
|
||||
private val stringProvider: StringProvider) : TypedEpoxyController<RoomMemberListViewState>() {
|
||||
|
||||
interface Callback {
|
||||
fun onRoomMemberClicked(roomMember: RoomMember)
|
||||
fun onRoomMemberClicked(roomMember: RoomMemberSummary)
|
||||
}
|
||||
|
||||
var callback: Callback? = null
|
||||
|
||||
init {
|
||||
setData(null)
|
||||
}
|
||||
|
||||
override fun buildModels(data: RoomMemberListViewState?) {
|
||||
data?.roomMembers?.invoke()?.forEach { roomMember ->
|
||||
profileMatrixItem {
|
||||
id(roomMember.userId)
|
||||
matrixItem(roomMember.toMatrixItem())
|
||||
avatarRenderer(avatarRenderer)
|
||||
clickListener { _ ->
|
||||
callback?.onRoomMemberClicked(roomMember)
|
||||
val roomMembersByPowerLevel = data?.roomMemberSummaries?.invoke() ?: return
|
||||
for ((powerLevelCategory, roomMemberList) in roomMembersByPowerLevel) {
|
||||
if (roomMemberList.isEmpty()) {
|
||||
continue
|
||||
}
|
||||
buildProfileSection(
|
||||
stringProvider.getString(powerLevelCategory.titleRes)
|
||||
)
|
||||
roomMemberList.forEach { roomMember ->
|
||||
profileMatrixItem {
|
||||
id(roomMember.userId)
|
||||
matrixItem(roomMember.toMatrixItem())
|
||||
avatarRenderer(avatarRenderer)
|
||||
clickListener { _ ->
|
||||
callback?.onRoomMemberClicked(roomMember)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import android.view.View
|
|||
import com.airbnb.mvrx.args
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||
import im.vector.matrix.android.api.util.toMatrixItem
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.extensions.cleanup
|
||||
|
@ -63,7 +63,7 @@ class RoomMemberListFragment @Inject constructor(
|
|||
renderRoomSummary(viewState)
|
||||
}
|
||||
|
||||
override fun onRoomMemberClicked(roomMember: RoomMember) {
|
||||
override fun onRoomMemberClicked(roomMember: RoomMemberSummary) {
|
||||
navigator.openRoomMemberProfile(roomMember.userId, roomId = roomProfileArgs.roomId, context = requireActivity())
|
||||
}
|
||||
|
||||
|
|
|
@ -23,14 +23,20 @@ import com.squareup.inject.assisted.Assisted
|
|||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.query.QueryStringValue
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.api.session.events.model.toModel
|
||||
import im.vector.matrix.android.api.session.room.members.roomMemberQueryParams
|
||||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||
import im.vector.matrix.android.api.session.room.powerlevers.PowerLevelsConstants
|
||||
import im.vector.matrix.android.api.session.room.powerlevers.PowerLevelsHelper
|
||||
import im.vector.matrix.rx.mapOptional
|
||||
import im.vector.matrix.rx.rx
|
||||
import im.vector.matrix.rx.unwrap
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import im.vector.riotx.core.utils.DataSource
|
||||
import im.vector.riotx.core.utils.PublishDataSource
|
||||
import im.vector.riotx.features.roomprofile.RoomProfileViewEvents
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.functions.BiFunction
|
||||
|
||||
class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState: RoomMemberListViewState,
|
||||
private val session: Session)
|
||||
|
@ -53,10 +59,32 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState
|
|||
private val room = session.getRoom(initialState.roomId)!!
|
||||
|
||||
init {
|
||||
observeRoomMembers()
|
||||
observeRoomMemberSummaries()
|
||||
observeRoomSummary()
|
||||
}
|
||||
|
||||
private fun observeRoomMemberSummaries() {
|
||||
val roomMemberQueryParams = roomMemberQueryParams {
|
||||
displayName = QueryStringValue.IsNotEmpty
|
||||
memberships = Membership.activeMemberships()
|
||||
}
|
||||
Observable
|
||||
.combineLatest<List<RoomMemberSummary>, PowerLevelsContent, RoomMemberSummaries>(
|
||||
room.rx().liveRoomMembers(roomMemberQueryParams),
|
||||
room.rx()
|
||||
.liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS)
|
||||
.mapOptional { it.content.toModel<PowerLevelsContent>() }
|
||||
.unwrap(),
|
||||
BiFunction { roomMembers, powerLevelsContent ->
|
||||
buildRoomMemberSummaries(powerLevelsContent, roomMembers)
|
||||
}
|
||||
)
|
||||
.execute { async ->
|
||||
copy(roomMemberSummaries = async)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun observeRoomSummary() {
|
||||
room.rx().liveRoomSummary()
|
||||
.unwrap()
|
||||
|
@ -65,16 +93,33 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState
|
|||
}
|
||||
}
|
||||
|
||||
private fun observeRoomMembers() {
|
||||
val queryParams = roomMemberQueryParams {
|
||||
displayName = QueryStringValue.IsNotEmpty
|
||||
memberships = Membership.activeMemberships()
|
||||
}
|
||||
room.rx()
|
||||
.liveRoomMembers(queryParams)
|
||||
.execute {
|
||||
copy(roomMembers = it)
|
||||
|
||||
private fun buildRoomMemberSummaries(powerLevelsContent: PowerLevelsContent, roomMembers: List<RoomMemberSummary>): RoomMemberSummaries {
|
||||
val admins = ArrayList<RoomMemberSummary>()
|
||||
val moderators = ArrayList<RoomMemberSummary>()
|
||||
val users = ArrayList<RoomMemberSummary>(roomMembers.size)
|
||||
val customs = ArrayList<RoomMemberSummary>()
|
||||
val invites = ArrayList<RoomMemberSummary>()
|
||||
val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent)
|
||||
roomMembers
|
||||
.forEach { roomMember ->
|
||||
val memberPowerLevel = powerLevelsHelper.getUserPowerLevel(roomMember.userId)
|
||||
when {
|
||||
roomMember.membership == Membership.INVITE -> invites.add(roomMember)
|
||||
memberPowerLevel == PowerLevelsConstants.DEFAULT_ROOM_ADMIN_LEVEL -> admins.add(roomMember)
|
||||
memberPowerLevel == PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL -> moderators.add(roomMember)
|
||||
memberPowerLevel == PowerLevelsConstants.DEFAULT_ROOM_USER_LEVEL -> users.add(roomMember)
|
||||
else -> customs.add(roomMember)
|
||||
}
|
||||
}
|
||||
|
||||
return mapOf(
|
||||
PowerLevelCategory.ADMIN to admins,
|
||||
PowerLevelCategory.MODERATOR to moderators,
|
||||
PowerLevelCategory.CUSTOM to customs,
|
||||
PowerLevelCategory.INVITE to invites,
|
||||
PowerLevelCategory.USER to users
|
||||
)
|
||||
}
|
||||
|
||||
override fun handle(action: RoomMemberListAction) {
|
||||
|
|
|
@ -16,19 +16,31 @@
|
|||
|
||||
package im.vector.riotx.features.roomprofile.members
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.features.roomprofile.RoomProfileArgs
|
||||
|
||||
data class RoomMemberListViewState(
|
||||
val roomId: String,
|
||||
val roomSummary: Async<RoomSummary> = Uninitialized,
|
||||
val roomMembers: Async<List<RoomMember>> = Uninitialized
|
||||
val roomMemberSummaries: Async<RoomMemberSummaries> = Uninitialized
|
||||
) : MvRxState {
|
||||
|
||||
constructor(args: RoomProfileArgs) : this(roomId = args.roomId)
|
||||
|
||||
}
|
||||
|
||||
typealias RoomMemberSummaries = Map<PowerLevelCategory, List<RoomMemberSummary>>
|
||||
|
||||
enum class PowerLevelCategory(@StringRes val titleRes: Int) {
|
||||
ADMIN(R.string.room_member_power_level_admins),
|
||||
MODERATOR(R.string.room_member_power_level_moderators),
|
||||
CUSTOM(R.string.room_member_power_level_custom),
|
||||
INVITE(R.string.room_member_power_level_invites),
|
||||
USER(R.string.room_member_power_level_users)
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
style="@style/VectorAppBarLayoutStyle"
|
||||
android:layout_width="match_parent"
|
||||
app:contentScrim="?riotx_background"
|
||||
app:scrimAnimationDuration="400"
|
||||
app:scrimAnimationDuration="250"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
|
||||
app:titleEnabled="false"
|
||||
|
|
|
@ -35,4 +35,10 @@
|
|||
<string name="room_profile_section_more_leave">Leave Room</string>
|
||||
<string name="room_profile_leaving_room">"Leaving the room..."</string>
|
||||
|
||||
<string name="room_member_power_level_admins">Admins</string>
|
||||
<string name="room_member_power_level_moderators">Moderators</string>
|
||||
<string name="room_member_power_level_custom">Custom</string>
|
||||
<string name="room_member_power_level_invites">Invites</string>
|
||||
<string name="room_member_power_level_users">Users</string>
|
||||
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue