mirror of
https://github.com/vector-im/riotX-android
synced 2025-10-05 15:52:47 +02:00
change (power level) : support new InfinitePowerLevel (first draft)
This commit is contained in:
@@ -120,6 +120,7 @@
|
|||||||
<string name="notice_widget_modified">%1$s modified %2$s widget</string>
|
<string name="notice_widget_modified">%1$s modified %2$s widget</string>
|
||||||
<string name="notice_widget_modified_by_you">You modified %1$s widget</string>
|
<string name="notice_widget_modified_by_you">You modified %1$s widget</string>
|
||||||
|
|
||||||
|
<string name="power_level_owner">Owner</string>
|
||||||
<string name="power_level_admin">Admin</string>
|
<string name="power_level_admin">Admin</string>
|
||||||
<string name="power_level_moderator">Moderator</string>
|
<string name="power_level_moderator">Moderator</string>
|
||||||
<string name="power_level_default">Default</string>
|
<string name="power_level_default">Default</string>
|
||||||
@@ -2383,6 +2384,7 @@
|
|||||||
<string name="room_member_power_level_invites">Invites</string>
|
<string name="room_member_power_level_invites">Invites</string>
|
||||||
<string name="room_member_power_level_users">Users</string>
|
<string name="room_member_power_level_users">Users</string>
|
||||||
|
|
||||||
|
<string name="room_member_power_level_owner_in">Owner in %1$s</string>
|
||||||
<string name="room_member_power_level_admin_in">Admin in %1$s</string>
|
<string name="room_member_power_level_admin_in">Admin in %1$s</string>
|
||||||
<string name="room_member_power_level_moderator_in">Moderator in %1$s</string>
|
<string name="room_member_power_level_moderator_in">Moderator in %1$s</string>
|
||||||
<string name="room_member_power_level_default_in">Default in %1$s</string>
|
<string name="room_member_power_level_default_in">Default in %1$s</string>
|
||||||
|
@@ -40,7 +40,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry
|
|||||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
import org.matrix.android.sdk.api.session.room.model.RoomType
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.RestrictedRoomPreset
|
import org.matrix.android.sdk.api.session.room.model.create.RestrictedRoomPreset
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
||||||
@@ -500,12 +500,12 @@ class SpaceHierarchyTest : InstrumentedTest {
|
|||||||
room.stateService().sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent!!)
|
room.stateService().sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent!!)
|
||||||
|
|
||||||
commonTestHelper.retryPeriodically {
|
commonTestHelper.retryPeriodically {
|
||||||
val powerLevelsHelper = aliceSession.getRoom(bobRoomId)!!
|
val roomPowerLevels = aliceSession.getRoom(bobRoomId)!!
|
||||||
.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
||||||
?.content
|
?.content
|
||||||
?.toModel<PowerLevelsContent>()
|
?.toModel<PowerLevelsContent>()
|
||||||
?.let { PowerLevelsHelper(it) }
|
?.let { RoomPowerLevels(it) }
|
||||||
powerLevelsHelper!!.isUserAllowedToSend(aliceSession.myUserId, true, EventType.STATE_SPACE_PARENT)
|
roomPowerLevels!!.isUserAllowedToSend(aliceSession.myUserId, true, EventType.STATE_SPACE_PARENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
aliceSession.spaceService().setSpaceParent(bobRoomId, spaceAInfo.spaceId, false, listOf(bobSession.sessionParams.homeServerHost ?: ""))
|
aliceSession.spaceService().setSpaceParent(bobRoomId, spaceAInfo.spaceId, false, listOf(bobSession.sessionParams.homeServerHost ?: ""))
|
||||||
|
@@ -16,8 +16,7 @@
|
|||||||
package org.matrix.android.sdk.api.session.pushrules
|
package org.matrix.android.sdk.api.session.pushrules
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
|
||||||
|
|
||||||
class SenderNotificationPermissionCondition(
|
class SenderNotificationPermissionCondition(
|
||||||
/**
|
/**
|
||||||
@@ -35,8 +34,7 @@ class SenderNotificationPermissionCondition(
|
|||||||
|
|
||||||
override fun technicalDescription() = "User power level <$key>"
|
override fun technicalDescription() = "User power level <$key>"
|
||||||
|
|
||||||
fun isSatisfied(event: Event, powerLevels: PowerLevelsContent): Boolean {
|
fun isSatisfied(event: Event, roomPowerLevels: RoomPowerLevels): Boolean {
|
||||||
val powerLevelsHelper = PowerLevelsHelper(powerLevels)
|
return event.senderId != null && roomPowerLevels.isUserAbleToTriggerNotification(event.senderId, key)
|
||||||
return event.senderId != null && powerLevelsHelper.getUserPowerLevelValue(event.senderId) >= powerLevels.notificationLevel(key)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,13 @@
|
|||||||
package org.matrix.android.sdk.api.session.room
|
package org.matrix.android.sdk.api.session.room
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.query.QueryStateEventValue
|
import org.matrix.android.sdk.api.query.QueryStateEventValue
|
||||||
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.create.getRoomCreateContentWithSender
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,3 +40,15 @@ fun Room.getTimelineEvent(eventId: String): TimelineEvent? =
|
|||||||
*/
|
*/
|
||||||
fun Room.getStateEvent(eventType: String, stateKey: QueryStateEventValue): Event? =
|
fun Room.getStateEvent(eventType: String, stateKey: QueryStateEventValue): Event? =
|
||||||
stateService().getStateEvent(eventType, stateKey)
|
stateService().getStateEvent(eventType, stateKey)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current RoomPowerLevels of the room.
|
||||||
|
*/
|
||||||
|
fun Room.getRoomPowerLevels(): RoomPowerLevels {
|
||||||
|
val powerLevelsContent = getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)?.content?.toModel<PowerLevelsContent>()
|
||||||
|
val roomCreateContent = getStateEvent(EventType.STATE_ROOM_CREATE, QueryStringValue.IsEmpty)?.getRoomCreateContentWithSender()
|
||||||
|
return RoomPowerLevels(
|
||||||
|
powerLevelsContent,
|
||||||
|
roomCreateContent
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@@ -18,7 +18,8 @@ package org.matrix.android.sdk.api.session.room.model
|
|||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent.Companion.NOTIFICATIONS_ROOM_KEY
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class representing the EventType.EVENT_TYPE_STATE_ROOM_POWER_LEVELS state event content.
|
* Class representing the EventType.EVENT_TYPE_STATE_ROOM_POWER_LEVELS state event content.
|
||||||
@@ -88,7 +89,7 @@ data class PowerLevelsContent(
|
|||||||
* Get the notification level for a dedicated key.
|
* Get the notification level for a dedicated key.
|
||||||
*
|
*
|
||||||
* @param key the notification key
|
* @param key the notification key
|
||||||
* @return the level, default to Moderator if the key is not found
|
* @return the level
|
||||||
*/
|
*/
|
||||||
fun notificationLevel(key: String): Int {
|
fun notificationLevel(key: String): Int {
|
||||||
return when (val value = notifications.orEmpty()[key]) {
|
return when (val value = notifications.orEmpty()[key]) {
|
||||||
@@ -96,10 +97,9 @@ data class PowerLevelsContent(
|
|||||||
is String -> value.toInt()
|
is String -> value.toInt()
|
||||||
is Double -> value.toInt()
|
is Double -> value.toInt()
|
||||||
is Int -> value
|
is Int -> value
|
||||||
else -> Role.Moderator.value
|
else -> defaultNotificationLevel(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/**
|
/**
|
||||||
* Key to use for content.notifications and get the level required to trigger an @room notification. Defaults to 50 if unspecified.
|
* Key to use for content.notifications and get the level required to trigger an @room notification. Defaults to 50 if unspecified.
|
||||||
@@ -108,11 +108,21 @@ data class PowerLevelsContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun defaultNotificationLevel(key: String): Int {
|
||||||
|
return when (key) {
|
||||||
|
NOTIFICATIONS_ROOM_KEY -> UserPowerLevel.Moderator.value
|
||||||
|
else -> UserPowerLevel.User.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Fallback to default value, defined in the Matrix specification
|
// Fallback to default value, defined in the Matrix specification
|
||||||
fun PowerLevelsContent.banOrDefault() = ban ?: Role.Moderator.value
|
fun PowerLevelsContent?.banOrDefault() = this?.ban ?: UserPowerLevel.Moderator.value
|
||||||
fun PowerLevelsContent.kickOrDefault() = kick ?: Role.Moderator.value
|
fun PowerLevelsContent?.kickOrDefault() = this?.kick ?: UserPowerLevel.Moderator.value
|
||||||
fun PowerLevelsContent.inviteOrDefault() = invite ?: Role.Moderator.value
|
fun PowerLevelsContent?.inviteOrDefault() = this?.invite ?: UserPowerLevel.User.value
|
||||||
fun PowerLevelsContent.redactOrDefault() = redact ?: Role.Moderator.value
|
fun PowerLevelsContent?.redactOrDefault() = this?.redact ?: UserPowerLevel.Moderator.value
|
||||||
fun PowerLevelsContent.eventsDefaultOrDefault() = eventsDefault ?: Role.Default.value
|
fun PowerLevelsContent?.eventsDefaultOrDefault() = this?.eventsDefault ?: UserPowerLevel.User.value
|
||||||
fun PowerLevelsContent.usersDefaultOrDefault() = usersDefault ?: Role.Default.value
|
fun PowerLevelsContent?.usersDefaultOrDefault() = this?.usersDefault ?: UserPowerLevel.User.value
|
||||||
fun PowerLevelsContent.stateDefaultOrDefault() = stateDefault ?: Role.Moderator.value
|
fun PowerLevelsContent?.stateDefaultOrDefault() = this?.stateDefault ?: UserPowerLevel.Moderator.value
|
||||||
|
|
||||||
|
fun PowerLevelsContent?.notificationLevelOrDefault(key: String) = this?.notificationLevel(key) ?: defaultNotificationLevel(key)
|
||||||
|
@@ -18,15 +18,39 @@ package org.matrix.android.sdk.api.session.room.model.create
|
|||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Content of a m.room.create type event.
|
* Content of a m.room.create type event.
|
||||||
*/
|
*/
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class RoomCreateContent(
|
data class RoomCreateContent(
|
||||||
|
// Creator should be replaced by the sender of the event
|
||||||
@Json(name = "creator") val creator: String? = null,
|
@Json(name = "creator") val creator: String? = null,
|
||||||
@Json(name = "room_version") val roomVersion: String? = null,
|
@Json(name = "room_version") val roomVersion: String? = null,
|
||||||
@Json(name = "predecessor") val predecessor: Predecessor? = null,
|
@Json(name = "predecessor") val predecessor: Predecessor? = null,
|
||||||
// Defines the room type, see #RoomType (user extensible)
|
// Defines the room type, see #RoomType (user extensible)
|
||||||
@Json(name = "type") val type: String? = null
|
@Json(name = "type") val type: String? = null,
|
||||||
|
@Json(name = "additional_creators") val additionalCreators: List<String>? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class RoomCreateContentWithSender(
|
||||||
|
val senderId: String,
|
||||||
|
val inner: RoomCreateContent
|
||||||
|
) {
|
||||||
|
val creators = setOf(senderId) + inner.additionalCreators.orEmpty().toSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Event.getRoomCreateContentWithSender(): RoomCreateContentWithSender? {
|
||||||
|
if (this.type != EventType.STATE_ROOM_CREATE) return null
|
||||||
|
val innerContent = getClearContent().toModel<RoomCreateContent>() ?: return null
|
||||||
|
val senderId = senderId ?: return null
|
||||||
|
return RoomCreateContentWithSender(senderId, innerContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun RoomCreateContent.explicitlyPrivilegeRoomCreators(): Boolean {
|
||||||
|
val supportedRoomVersions = listOf("org.matrix.hydra.11", "12")
|
||||||
|
return supportedRoomVersions.contains(roomVersion)
|
||||||
|
}
|
||||||
|
@@ -17,26 +17,22 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.session.room.powerlevels
|
package org.matrix.android.sdk.api.session.room.powerlevels
|
||||||
|
|
||||||
sealed class Role(open val value: Int) : Comparable<Role> {
|
enum class Role {
|
||||||
object Admin : Role(100)
|
Creator,
|
||||||
object Moderator : Role(50)
|
SuperAdmin,
|
||||||
object Default : Role(0)
|
Admin,
|
||||||
data class Custom(override val value: Int) : Role(value)
|
Moderator,
|
||||||
|
User;
|
||||||
|
|
||||||
override fun compareTo(other: Role): Int {
|
|
||||||
return value.compareTo(other.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
fun getSuggestedRole(userPowerLevel: UserPowerLevel): Role {
|
||||||
// Order matters, default value should be checked after defined roles
|
return when {
|
||||||
fun fromValue(value: Int, default: Int): Role {
|
userPowerLevel == UserPowerLevel.Infinite -> Creator
|
||||||
return when (value) {
|
userPowerLevel >= UserPowerLevel.SuperAdmin -> SuperAdmin
|
||||||
Admin.value -> Admin
|
userPowerLevel >= UserPowerLevel.Admin -> Admin
|
||||||
Moderator.value -> Moderator
|
userPowerLevel >= UserPowerLevel.Moderator -> Moderator
|
||||||
Default.value,
|
else -> User
|
||||||
default -> Default
|
|
||||||
else -> Custom(value)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,17 +19,23 @@ package org.matrix.android.sdk.api.session.room.powerlevels
|
|||||||
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.banOrDefault
|
import org.matrix.android.sdk.api.session.room.model.banOrDefault
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContentWithSender
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.create.explicitlyPrivilegeRoomCreators
|
||||||
import org.matrix.android.sdk.api.session.room.model.eventsDefaultOrDefault
|
import org.matrix.android.sdk.api.session.room.model.eventsDefaultOrDefault
|
||||||
import org.matrix.android.sdk.api.session.room.model.inviteOrDefault
|
import org.matrix.android.sdk.api.session.room.model.inviteOrDefault
|
||||||
import org.matrix.android.sdk.api.session.room.model.kickOrDefault
|
import org.matrix.android.sdk.api.session.room.model.kickOrDefault
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.notificationLevelOrDefault
|
||||||
import org.matrix.android.sdk.api.session.room.model.redactOrDefault
|
import org.matrix.android.sdk.api.session.room.model.redactOrDefault
|
||||||
import org.matrix.android.sdk.api.session.room.model.stateDefaultOrDefault
|
import org.matrix.android.sdk.api.session.room.model.stateDefaultOrDefault
|
||||||
import org.matrix.android.sdk.api.session.room.model.usersDefaultOrDefault
|
import org.matrix.android.sdk.api.session.room.model.usersDefaultOrDefault
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is an helper around PowerLevelsContent.
|
* This class is an helper around PowerLevelsContent and RoomCreateContent.
|
||||||
*/
|
*/
|
||||||
class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
class RoomPowerLevels(
|
||||||
|
val powerLevelsContent: PowerLevelsContent?,
|
||||||
|
private val roomCreateContent: RoomCreateContentWithSender?,
|
||||||
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the user power level of a dedicated user Id.
|
* Returns the user power level of a dedicated user Id.
|
||||||
@@ -37,10 +43,14 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
|||||||
* @param userId the user id
|
* @param userId the user id
|
||||||
* @return the power level
|
* @return the power level
|
||||||
*/
|
*/
|
||||||
fun getUserPowerLevelValue(userId: String): Int {
|
fun getUserPowerLevel(userId: String): UserPowerLevel {
|
||||||
return powerLevelsContent.users
|
if (shouldGiveInfinitePowerLevel(userId)) return UserPowerLevel.Infinite
|
||||||
|
if (powerLevelsContent == null) return UserPowerLevel.User
|
||||||
|
val value = powerLevelsContent.users
|
||||||
?.get(userId)
|
?.get(userId)
|
||||||
?: powerLevelsContent.usersDefaultOrDefault()
|
?: powerLevelsContent.usersDefaultOrDefault()
|
||||||
|
|
||||||
|
return UserPowerLevel.Value(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,9 +60,8 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
|||||||
* @return the power level
|
* @return the power level
|
||||||
*/
|
*/
|
||||||
fun getUserRole(userId: String): Role {
|
fun getUserRole(userId: String): Role {
|
||||||
val value = getUserPowerLevelValue(userId)
|
val value = getUserPowerLevel(userId)
|
||||||
// I think we should use powerLevelsContent.usersDefault, but Ganfra told me that it was like that on riot-Web
|
return Role.getSuggestedRole(value)
|
||||||
return Role.fromValue(value, powerLevelsContent.eventsDefaultOrDefault())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,14 +74,14 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
|||||||
*/
|
*/
|
||||||
fun isUserAllowedToSend(userId: String, isState: Boolean, eventType: String?): Boolean {
|
fun isUserAllowedToSend(userId: String, isState: Boolean, eventType: String?): Boolean {
|
||||||
return if (userId.isNotEmpty()) {
|
return if (userId.isNotEmpty()) {
|
||||||
val powerLevel = getUserPowerLevelValue(userId)
|
val powerLevel = getUserPowerLevel(userId)
|
||||||
val minimumPowerLevel = powerLevelsContent.events?.get(eventType)
|
val minimumPowerLevel = powerLevelsContent?.events?.get(eventType)
|
||||||
?: if (isState) {
|
?: if (isState) {
|
||||||
powerLevelsContent.stateDefaultOrDefault()
|
powerLevelsContent.stateDefaultOrDefault()
|
||||||
} else {
|
} else {
|
||||||
powerLevelsContent.eventsDefaultOrDefault()
|
powerLevelsContent.eventsDefaultOrDefault()
|
||||||
}
|
}
|
||||||
powerLevel >= minimumPowerLevel
|
powerLevel >= UserPowerLevel.Value(minimumPowerLevel)
|
||||||
} else false
|
} else false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,8 +91,8 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
|||||||
* @return true if able to invite
|
* @return true if able to invite
|
||||||
*/
|
*/
|
||||||
fun isUserAbleToInvite(userId: String): Boolean {
|
fun isUserAbleToInvite(userId: String): Boolean {
|
||||||
val powerLevel = getUserPowerLevelValue(userId)
|
val powerLevel = getUserPowerLevel(userId)
|
||||||
return powerLevel >= powerLevelsContent.inviteOrDefault()
|
return powerLevel >= UserPowerLevel.Value(powerLevelsContent.inviteOrDefault())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,8 +101,8 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
|||||||
* @return true if able to ban
|
* @return true if able to ban
|
||||||
*/
|
*/
|
||||||
fun isUserAbleToBan(userId: String): Boolean {
|
fun isUserAbleToBan(userId: String): Boolean {
|
||||||
val powerLevel = getUserPowerLevelValue(userId)
|
val powerLevel = getUserPowerLevel(userId)
|
||||||
return powerLevel >= powerLevelsContent.banOrDefault()
|
return powerLevel >= UserPowerLevel.Value(powerLevelsContent.banOrDefault())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -102,8 +111,8 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
|||||||
* @return true if able to kick
|
* @return true if able to kick
|
||||||
*/
|
*/
|
||||||
fun isUserAbleToKick(userId: String): Boolean {
|
fun isUserAbleToKick(userId: String): Boolean {
|
||||||
val powerLevel = getUserPowerLevelValue(userId)
|
val powerLevel = getUserPowerLevel(userId)
|
||||||
return powerLevel >= powerLevelsContent.kickOrDefault()
|
return powerLevel >= UserPowerLevel.Value(powerLevelsContent.kickOrDefault())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,7 +121,22 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
|||||||
* @return true if able to redact
|
* @return true if able to redact
|
||||||
*/
|
*/
|
||||||
fun isUserAbleToRedact(userId: String): Boolean {
|
fun isUserAbleToRedact(userId: String): Boolean {
|
||||||
val powerLevel = getUserPowerLevelValue(userId)
|
val powerLevel = getUserPowerLevel(userId)
|
||||||
return powerLevel >= powerLevelsContent.redactOrDefault()
|
return powerLevel >= UserPowerLevel.Value(powerLevelsContent.redactOrDefault())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isUserAbleToTriggerNotification(userId: String, notificationKey: String): Boolean {
|
||||||
|
val userPowerLevel = getUserPowerLevel(userId)
|
||||||
|
val notificationPowerLevel = UserPowerLevel.Value(powerLevelsContent.notificationLevelOrDefault(key = notificationKey))
|
||||||
|
return userPowerLevel >= notificationPowerLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shouldGiveInfinitePowerLevel(userId: String): Boolean {
|
||||||
|
if (roomCreateContent == null) return false
|
||||||
|
return if (roomCreateContent.inner.explicitlyPrivilegeRoomCreators()) {
|
||||||
|
roomCreateContent.creators.contains(userId)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.api.session.room.powerlevels
|
||||||
|
|
||||||
|
sealed interface UserPowerLevel : Comparable<UserPowerLevel> {
|
||||||
|
data object Infinite : UserPowerLevel
|
||||||
|
|
||||||
|
@JvmInline
|
||||||
|
value class Value(val value: Int) : UserPowerLevel
|
||||||
|
|
||||||
|
override fun compareTo(other: UserPowerLevel): Int {
|
||||||
|
return when (this) {
|
||||||
|
Infinite -> when (other) {
|
||||||
|
Infinite -> 0
|
||||||
|
is Value -> 1
|
||||||
|
}
|
||||||
|
is Value -> when (other) {
|
||||||
|
Infinite -> -1
|
||||||
|
is Value -> value.compareTo(other.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val User = Value(0)
|
||||||
|
val Moderator = Value(50)
|
||||||
|
val Admin = Value(100)
|
||||||
|
val SuperAdmin = Value(150)
|
||||||
|
}
|
||||||
|
}
|
@@ -17,15 +17,11 @@
|
|||||||
package org.matrix.android.sdk.internal.session.permalinks
|
package org.matrix.android.sdk.internal.session.permalinks
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixPatterns.getServerName
|
import org.matrix.android.sdk.api.MatrixPatterns.getServerName
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
|
||||||
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
|
||||||
import org.matrix.android.sdk.internal.di.UserId
|
import org.matrix.android.sdk.internal.di.UserId
|
||||||
import org.matrix.android.sdk.internal.session.room.RoomGetter
|
import org.matrix.android.sdk.internal.session.room.RoomGetter
|
||||||
|
import org.matrix.android.sdk.internal.session.room.powerlevels.getRoomPowerLevels
|
||||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -101,10 +97,7 @@ internal class ViaParameterFinder @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun userCanInvite(userId: String, roomId: String): Boolean {
|
fun userCanInvite(userId: String, roomId: String): Boolean {
|
||||||
val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
val roomPowerLevels = stateEventDataSource.getRoomPowerLevels(roomId)
|
||||||
?.content?.toModel<PowerLevelsContent>()
|
return roomPowerLevels.isUserAbleToInvite(userId)
|
||||||
?.let { PowerLevelsHelper(it) }
|
|
||||||
|
|
||||||
return powerLevelsHelper?.isUserAbleToInvite(userId) ?: false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,15 +24,20 @@ import org.matrix.android.sdk.api.session.pushrules.ContainsDisplayNameCondition
|
|||||||
import org.matrix.android.sdk.api.session.pushrules.EventMatchCondition
|
import org.matrix.android.sdk.api.session.pushrules.EventMatchCondition
|
||||||
import org.matrix.android.sdk.api.session.pushrules.RoomMemberCountCondition
|
import org.matrix.android.sdk.api.session.pushrules.RoomMemberCountCondition
|
||||||
import org.matrix.android.sdk.api.session.pushrules.SenderNotificationPermissionCondition
|
import org.matrix.android.sdk.api.session.pushrules.SenderNotificationPermissionCondition
|
||||||
|
import org.matrix.android.sdk.api.session.room.getRoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.getStateEvent
|
import org.matrix.android.sdk.api.session.room.getStateEvent
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.create.getRoomCreateContentWithSender
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.internal.di.UserId
|
import org.matrix.android.sdk.internal.di.UserId
|
||||||
import org.matrix.android.sdk.internal.session.room.RoomGetter
|
import org.matrix.android.sdk.internal.session.room.RoomGetter
|
||||||
|
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultConditionResolver @Inject constructor(
|
internal class DefaultConditionResolver @Inject constructor(
|
||||||
private val roomGetter: RoomGetter,
|
private val roomGetter: RoomGetter,
|
||||||
@UserId private val userId: String
|
@UserId private val userId: String,
|
||||||
|
private val stateEventDataSource: StateEventDataSource,
|
||||||
) : ConditionResolver {
|
) : ConditionResolver {
|
||||||
|
|
||||||
override fun resolveEventMatchCondition(
|
override fun resolveEventMatchCondition(
|
||||||
@@ -55,13 +60,8 @@ internal class DefaultConditionResolver @Inject constructor(
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
val roomId = event.roomId ?: return false
|
val roomId = event.roomId ?: return false
|
||||||
val room = roomGetter.getRoom(roomId) ?: return false
|
val room = roomGetter.getRoom(roomId) ?: return false
|
||||||
|
val roomPowerLevels = room.getRoomPowerLevels()
|
||||||
val powerLevelsContent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
return condition.isSatisfied(event, roomPowerLevels)
|
||||||
?.content
|
|
||||||
?.toModel<PowerLevelsContent>()
|
|
||||||
?: PowerLevelsContent()
|
|
||||||
|
|
||||||
return condition.isSatisfied(event, powerLevelsContent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resolveContainsDisplayNameCondition(
|
override fun resolveContainsDisplayNameCondition(
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
package org.matrix.android.sdk.internal.session.room
|
package org.matrix.android.sdk.internal.session.room
|
||||||
|
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationState
|
import org.matrix.android.sdk.api.session.crypto.verification.VerificationState
|
||||||
import org.matrix.android.sdk.api.session.events.model.AggregatedAnnotation
|
import org.matrix.android.sdk.api.session.events.model.AggregatedAnnotation
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
@@ -27,7 +26,6 @@ import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventCon
|
|||||||
import org.matrix.android.sdk.api.session.events.model.getRelationContent
|
import org.matrix.android.sdk.api.session.events.model.getRelationContent
|
||||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.ReferencesAggregatedContent
|
import org.matrix.android.sdk.api.session.room.model.ReferencesAggregatedContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent
|
||||||
@@ -36,7 +34,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
|
|||||||
import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponseContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponseContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.relation.ReactionContent
|
import org.matrix.android.sdk.api.session.room.model.relation.ReactionContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.internal.SessionManager
|
import org.matrix.android.sdk.internal.SessionManager
|
||||||
import org.matrix.android.sdk.internal.crypto.verification.toState
|
import org.matrix.android.sdk.internal.crypto.verification.toState
|
||||||
import org.matrix.android.sdk.internal.database.helper.findRootThreadEvent
|
import org.matrix.android.sdk.internal.database.helper.findRootThreadEvent
|
||||||
@@ -62,6 +60,7 @@ import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor
|
|||||||
import org.matrix.android.sdk.internal.session.room.aggregation.livelocation.LiveLocationAggregationProcessor
|
import org.matrix.android.sdk.internal.session.room.aggregation.livelocation.LiveLocationAggregationProcessor
|
||||||
import org.matrix.android.sdk.internal.session.room.aggregation.poll.PollAggregationProcessor
|
import org.matrix.android.sdk.internal.session.room.aggregation.poll.PollAggregationProcessor
|
||||||
import org.matrix.android.sdk.internal.session.room.aggregation.utd.EncryptedReferenceAggregationProcessor
|
import org.matrix.android.sdk.internal.session.room.aggregation.utd.EncryptedReferenceAggregationProcessor
|
||||||
|
import org.matrix.android.sdk.internal.session.room.powerlevels.getRoomPowerLevels
|
||||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||||
import org.matrix.android.sdk.internal.util.time.Clock
|
import org.matrix.android.sdk.internal.util.time.Clock
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@@ -216,9 +215,8 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
|
|||||||
}
|
}
|
||||||
in EventType.POLL_END.values -> {
|
in EventType.POLL_END.values -> {
|
||||||
sessionManager.getSessionComponent(sessionId)?.session()?.let { session ->
|
sessionManager.getSessionComponent(sessionId)?.session()?.let { session ->
|
||||||
getPowerLevelsHelper(event.roomId)?.let {
|
val roomPowerLevels = stateEventDataSource.getRoomPowerLevels(event.roomId)
|
||||||
pollAggregationProcessor.handlePollEndEvent(session, it, realm, event)
|
pollAggregationProcessor.handlePollEndEvent(session, roomPowerLevels, realm, event)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
in EventType.STATE_ROOM_BEACON_INFO.values -> {
|
in EventType.STATE_ROOM_BEACON_INFO.values -> {
|
||||||
@@ -381,12 +379,6 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPowerLevelsHelper(roomId: String): PowerLevelsHelper? {
|
|
||||||
return stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
|
||||||
?.content?.toModel<PowerLevelsContent>()
|
|
||||||
?.let { PowerLevelsHelper(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleInitialAggregatedRelations(
|
private fun handleInitialAggregatedRelations(
|
||||||
realm: Realm,
|
realm: Realm,
|
||||||
event: Event,
|
event: Event,
|
||||||
|
@@ -32,7 +32,7 @@ import org.matrix.android.sdk.api.session.room.model.VoteInfo
|
|||||||
import org.matrix.android.sdk.api.session.room.model.VoteSummary
|
import org.matrix.android.sdk.api.session.room.model.VoteSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponseContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponseContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
|
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
|
||||||
import org.matrix.android.sdk.internal.database.mapper.ContentMapper
|
import org.matrix.android.sdk.internal.database.mapper.ContentMapper
|
||||||
@@ -160,13 +160,13 @@ internal class DefaultPollAggregationProcessor @Inject constructor(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handlePollEndEvent(session: Session, powerLevelsHelper: PowerLevelsHelper, realm: Realm, event: Event): Boolean {
|
override fun handlePollEndEvent(session: Session, roomPowerLevels: RoomPowerLevels, realm: Realm, event: Event): Boolean {
|
||||||
val roomId = event.roomId ?: return false
|
val roomId = event.roomId ?: return false
|
||||||
val pollEventId = event.getRelationContent()?.eventId ?: return false
|
val pollEventId = event.getRelationContent()?.eventId ?: return false
|
||||||
val pollOwnerId = getPollEvent(session, roomId, pollEventId)?.root?.senderId
|
val pollOwnerId = getPollEvent(session, roomId, pollEventId)?.root?.senderId
|
||||||
val isPollOwner = pollOwnerId == event.senderId
|
val isPollOwner = pollOwnerId == event.senderId
|
||||||
|
|
||||||
if (!isPollOwner && !powerLevelsHelper.isUserAbleToRedact(event.senderId ?: "")) {
|
if (!isPollOwner && !roomPowerLevels.isUserAbleToRedact(event.senderId ?: "")) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.session.room.aggregation.poll
|
|||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
|
|
||||||
internal interface PollAggregationProcessor {
|
internal interface PollAggregationProcessor {
|
||||||
/**
|
/**
|
||||||
@@ -48,7 +48,7 @@ internal interface PollAggregationProcessor {
|
|||||||
*/
|
*/
|
||||||
fun handlePollEndEvent(
|
fun handlePollEndEvent(
|
||||||
session: Session,
|
session: Session,
|
||||||
powerLevelsHelper: PowerLevelsHelper,
|
roomPowerLevels: RoomPowerLevels,
|
||||||
realm: Realm,
|
realm: Realm,
|
||||||
event: Event
|
event: Event
|
||||||
): Boolean
|
): Boolean
|
||||||
|
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.internal.session.room.powerlevels
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.create.getRoomCreateContentWithSender
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
|
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||||
|
|
||||||
|
internal fun StateEventDataSource.getRoomPowerLevels(roomId: String): RoomPowerLevels {
|
||||||
|
val powerLevelsContent = getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
||||||
|
?.content?.toModel<PowerLevelsContent>()
|
||||||
|
val roomCreateContent = getStateEvent(roomId, EventType.STATE_ROOM_CREATE, QueryStringValue.IsEmpty)?.getRoomCreateContentWithSender()
|
||||||
|
return RoomPowerLevels(powerLevelsContent, roomCreateContent)
|
||||||
|
}
|
@@ -96,3 +96,4 @@ internal class StateEventDataSource @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,7 +34,8 @@ import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
|
|||||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
import org.matrix.android.sdk.api.session.room.model.RoomType
|
||||||
import org.matrix.android.sdk.api.session.room.model.VersioningState
|
import org.matrix.android.sdk.api.session.room.model.VersioningState
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContentWithSender
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||||
import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary
|
import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary
|
||||||
import org.matrix.android.sdk.api.session.sync.model.RoomSyncUnreadNotifications
|
import org.matrix.android.sdk.api.session.sync.model.RoomSyncUnreadNotifications
|
||||||
@@ -313,13 +314,25 @@ internal class RoomSummaryUpdater @Inject constructor(
|
|||||||
// check if sender can post child relation in parent?
|
// check if sender can post child relation in parent?
|
||||||
val senderId = parentInfo.stateEventSender
|
val senderId = parentInfo.stateEventSender
|
||||||
val parentRoomId = parentInfo.roomId
|
val parentRoomId = parentInfo.roomId
|
||||||
val powerLevelsHelper = CurrentStateEventEntity
|
val powerLevelsContent = CurrentStateEventEntity
|
||||||
.getOrNull(realm, parentRoomId, "", EventType.STATE_ROOM_POWER_LEVELS)
|
.getOrNull(realm, parentRoomId, "", EventType.STATE_ROOM_POWER_LEVELS)
|
||||||
?.root
|
?.root
|
||||||
?.let { ContentMapper.map(it.content).toModel<PowerLevelsContent>() }
|
?.let { ContentMapper.map(it.content).toModel<PowerLevelsContent>() }
|
||||||
?.let { PowerLevelsHelper(it) }
|
|
||||||
|
|
||||||
isValidRelation = powerLevelsHelper?.isUserAllowedToSend(senderId, true, EventType.STATE_SPACE_CHILD) ?: false
|
val roomCreateContent = CurrentStateEventEntity
|
||||||
|
.getOrNull(realm, parentRoomId, "", EventType.STATE_ROOM_CREATE)
|
||||||
|
?.root
|
||||||
|
?.let {
|
||||||
|
val content = ContentMapper.map(it.content).toModel<RoomCreateContent>()
|
||||||
|
val sender = it.sender
|
||||||
|
if (content != null && sender != null) {
|
||||||
|
RoomCreateContentWithSender(sender, content)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val roomPowerLevels = RoomPowerLevels(powerLevelsContent, roomCreateContent)
|
||||||
|
isValidRelation = roomPowerLevels.isUserAllowedToSend(senderId, true, EventType.STATE_SPACE_CHILD)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isValidRelation) {
|
if (isValidRelation) {
|
||||||
|
@@ -25,7 +25,8 @@ import org.matrix.android.sdk.api.session.events.model.toModel
|
|||||||
import org.matrix.android.sdk.api.session.homeserver.RoomVersionStatus
|
import org.matrix.android.sdk.api.session.homeserver.RoomVersionStatus
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.model.create.getRoomCreateContentWithSender
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.version.RoomVersionService
|
import org.matrix.android.sdk.api.session.room.version.RoomVersionService
|
||||||
import org.matrix.android.sdk.internal.session.homeserver.HomeServerCapabilitiesDataSource
|
import org.matrix.android.sdk.internal.session.homeserver.HomeServerCapabilitiesDataSource
|
||||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||||
@@ -71,11 +72,17 @@ internal class DefaultRoomVersionService @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun userMayUpgradeRoom(userId: String): Boolean {
|
override fun userMayUpgradeRoom(userId: String): Boolean {
|
||||||
val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
val powerLevelsContent = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
||||||
?.content?.toModel<PowerLevelsContent>()
|
?.content?.toModel<PowerLevelsContent>()
|
||||||
?.let { PowerLevelsHelper(it) }
|
|
||||||
|
|
||||||
return powerLevelsHelper?.isUserAllowedToSend(userId, true, EventType.STATE_ROOM_TOMBSTONE) ?: false
|
val roomCreateContent = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_CREATE, QueryStringValue.IsEmpty)
|
||||||
|
?.getRoomCreateContentWithSender()
|
||||||
|
|
||||||
|
val roomPowerLevels = RoomPowerLevels(
|
||||||
|
powerLevelsContent = powerLevelsContent,
|
||||||
|
roomCreateContent = roomCreateContent
|
||||||
|
)
|
||||||
|
return roomPowerLevels.isUserAllowedToSend(userId, true, EventType.STATE_ROOM_TOMBSTONE)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@@ -35,8 +35,9 @@ import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
|||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||||
import org.matrix.android.sdk.api.session.space.CreateSpaceParams
|
import org.matrix.android.sdk.api.session.space.CreateSpaceParams
|
||||||
import org.matrix.android.sdk.api.session.space.JoinSpaceResult
|
import org.matrix.android.sdk.api.session.space.JoinSpaceResult
|
||||||
import org.matrix.android.sdk.api.session.space.Space
|
import org.matrix.android.sdk.api.session.space.Space
|
||||||
@@ -47,11 +48,13 @@ import org.matrix.android.sdk.api.session.space.model.SpaceChildContent
|
|||||||
import org.matrix.android.sdk.api.session.space.model.SpaceChildSummaryEvent
|
import org.matrix.android.sdk.api.session.space.model.SpaceChildSummaryEvent
|
||||||
import org.matrix.android.sdk.api.session.space.model.SpaceParentContent
|
import org.matrix.android.sdk.api.session.space.model.SpaceParentContent
|
||||||
import org.matrix.android.sdk.api.session.space.peeking.SpacePeekResult
|
import org.matrix.android.sdk.api.session.space.peeking.SpacePeekResult
|
||||||
|
import org.matrix.android.sdk.api.session.user.model.User
|
||||||
import org.matrix.android.sdk.internal.di.UserId
|
import org.matrix.android.sdk.internal.di.UserId
|
||||||
import org.matrix.android.sdk.internal.session.room.RoomGetter
|
import org.matrix.android.sdk.internal.session.room.RoomGetter
|
||||||
import org.matrix.android.sdk.internal.session.room.SpaceGetter
|
import org.matrix.android.sdk.internal.session.room.SpaceGetter
|
||||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.leaving.LeaveRoomTask
|
import org.matrix.android.sdk.internal.session.room.membership.leaving.LeaveRoomTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.powerlevels.getRoomPowerLevels
|
||||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||||
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
||||||
import org.matrix.android.sdk.internal.session.space.peeking.PeekSpaceTask
|
import org.matrix.android.sdk.internal.session.space.peeking.PeekSpaceTask
|
||||||
@@ -83,7 +86,7 @@ internal class DefaultSpaceService @Inject constructor(
|
|||||||
if (isPublic) {
|
if (isPublic) {
|
||||||
this.roomAliasName = roomAliasLocalPart
|
this.roomAliasName = roomAliasLocalPart
|
||||||
this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy(
|
this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy(
|
||||||
invite = if (isPublic) Role.Default.value else Role.Moderator.value
|
invite = UserPowerLevel.User.value
|
||||||
)
|
)
|
||||||
this.preset = CreateRoomPreset.PRESET_PUBLIC_CHAT
|
this.preset = CreateRoomPreset.PRESET_PUBLIC_CHAT
|
||||||
this.historyVisibility = RoomHistoryVisibility.WORLD_READABLE
|
this.historyVisibility = RoomHistoryVisibility.WORLD_READABLE
|
||||||
@@ -253,15 +256,8 @@ internal class DefaultSpaceService @Inject constructor(
|
|||||||
if (roomSummaryDataSource.getRoomSummary(parentSpaceId)?.membership != Membership.JOIN) {
|
if (roomSummaryDataSource.getRoomSummary(parentSpaceId)?.membership != Membership.JOIN) {
|
||||||
throw UnsupportedOperationException("Cannot add canonical child if not member of parent")
|
throw UnsupportedOperationException("Cannot add canonical child if not member of parent")
|
||||||
}
|
}
|
||||||
val powerLevelsEvent = stateEventDataSource.getStateEvent(
|
val roomPowerLevels = stateEventDataSource.getRoomPowerLevels(parentSpaceId)
|
||||||
roomId = parentSpaceId,
|
if (!roomPowerLevels.isUserAllowedToSend(userId, true, EventType.STATE_SPACE_CHILD)) {
|
||||||
eventType = EventType.STATE_ROOM_POWER_LEVELS,
|
|
||||||
stateKey = QueryStringValue.IsEmpty
|
|
||||||
)
|
|
||||||
val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>()
|
|
||||||
?: throw UnsupportedOperationException("Cannot add canonical child, missing power level")
|
|
||||||
val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent)
|
|
||||||
if (!powerLevelsHelper.isUserAllowedToSend(userId, true, EventType.STATE_SPACE_CHILD)) {
|
|
||||||
throw UnsupportedOperationException("Cannot add canonical child, not enough power level")
|
throw UnsupportedOperationException("Cannot add canonical child, not enough power level")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,15 +30,13 @@ import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
|
|||||||
import org.matrix.android.sdk.api.session.events.model.Content
|
import org.matrix.android.sdk.api.session.events.model.Content
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
|
||||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
|
||||||
import org.matrix.android.sdk.api.session.widgets.WidgetManagementFailure
|
import org.matrix.android.sdk.api.session.widgets.WidgetManagementFailure
|
||||||
import org.matrix.android.sdk.api.session.widgets.model.Widget
|
import org.matrix.android.sdk.api.session.widgets.model.Widget
|
||||||
import org.matrix.android.sdk.internal.di.UserId
|
import org.matrix.android.sdk.internal.di.UserId
|
||||||
import org.matrix.android.sdk.internal.session.SessionScope
|
import org.matrix.android.sdk.internal.session.SessionScope
|
||||||
import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationManager
|
import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationManager
|
||||||
|
import org.matrix.android.sdk.internal.session.room.powerlevels.getRoomPowerLevels
|
||||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||||
import org.matrix.android.sdk.internal.session.user.accountdata.UserAccountDataDataSource
|
import org.matrix.android.sdk.internal.session.user.accountdata.UserAccountDataDataSource
|
||||||
import org.matrix.android.sdk.internal.session.widgets.helper.WidgetFactory
|
import org.matrix.android.sdk.internal.session.widgets.helper.WidgetFactory
|
||||||
@@ -200,12 +198,7 @@ internal class WidgetManager @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun hasPermissionsToHandleWidgets(roomId: String): Boolean {
|
fun hasPermissionsToHandleWidgets(roomId: String): Boolean {
|
||||||
val powerLevelsEvent = stateEventDataSource.getStateEvent(
|
val roomPowerLevels = stateEventDataSource.getRoomPowerLevels(roomId)
|
||||||
roomId = roomId,
|
return roomPowerLevels.isUserAllowedToSend(userId, true, EventType.STATE_ROOM_WIDGET_LEGACY)
|
||||||
eventType = EventType.STATE_ROOM_POWER_LEVELS,
|
|
||||||
stateKey = QueryStringValue.IsEmpty
|
|
||||||
)
|
|
||||||
val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>() ?: return false
|
|
||||||
return PowerLevelsHelper(powerLevelsContent).isUserAllowedToSend(userId, true, EventType.STATE_ROOM_WIDGET_LEGACY)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,7 @@ import org.matrix.android.sdk.api.session.Session
|
|||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.room.Room
|
import org.matrix.android.sdk.api.session.room.Room
|
||||||
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntity
|
import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntityFields
|
import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntityFields
|
||||||
import org.matrix.android.sdk.internal.database.model.PollResponseAggregatedSummaryEntity
|
import org.matrix.android.sdk.internal.database.model.PollResponseAggregatedSummaryEntity
|
||||||
@@ -255,9 +255,9 @@ class DefaultPollAggregationProcessorTest {
|
|||||||
every { room.getTimelineEvent(eventId) } returns if (hasExistingTimelineEvent) A_TIMELINE_EVENT else null
|
every { room.getTimelineEvent(eventId) } returns if (hasExistingTimelineEvent) A_TIMELINE_EVENT else null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mockRedactionPowerLevels(userId: String, isAbleToRedact: Boolean): PowerLevelsHelper {
|
private fun mockRedactionPowerLevels(userId: String, isAbleToRedact: Boolean): RoomPowerLevels {
|
||||||
val powerLevelsHelper = mockk<PowerLevelsHelper>()
|
val roomPowerLevels = mockk<RoomPowerLevels>()
|
||||||
every { powerLevelsHelper.isUserAbleToRedact(userId) } returns isAbleToRedact
|
every { roomPowerLevels.isUserAbleToRedact(userId) } returns isAbleToRedact
|
||||||
return powerLevelsHelper
|
return roomPowerLevels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -376,8 +376,8 @@ internal class DefaultCreateLocalRoomStateEventsTaskTest {
|
|||||||
powerLevelsContent.kick shouldBeEqualTo Role.Moderator.value
|
powerLevelsContent.kick shouldBeEqualTo Role.Moderator.value
|
||||||
powerLevelsContent.invite shouldBeEqualTo Role.Moderator.value
|
powerLevelsContent.invite shouldBeEqualTo Role.Moderator.value
|
||||||
powerLevelsContent.redact shouldBeEqualTo Role.Moderator.value
|
powerLevelsContent.redact shouldBeEqualTo Role.Moderator.value
|
||||||
powerLevelsContent.eventsDefault shouldBeEqualTo Role.Default.value
|
powerLevelsContent.eventsDefault shouldBeEqualTo Role.User.value
|
||||||
powerLevelsContent.usersDefault shouldBeEqualTo Role.Default.value
|
powerLevelsContent.usersDefault shouldBeEqualTo Role.User.value
|
||||||
powerLevelsContent.stateDefault shouldBeEqualTo Role.Moderator.value
|
powerLevelsContent.stateDefault shouldBeEqualTo Role.Moderator.value
|
||||||
// Guest access
|
// Guest access
|
||||||
result.find { it.type == EventType.STATE_ROOM_GUEST_ACCESS }
|
result.find { it.type == EventType.STATE_ROOM_GUEST_ACCESS }
|
||||||
|
@@ -110,7 +110,6 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachme
|
|||||||
import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
|
import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
|
||||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.tombstone.RoomTombstoneContent
|
import org.matrix.android.sdk.api.session.room.model.tombstone.RoomTombstoneContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
|
||||||
import org.matrix.android.sdk.api.session.room.read.ReadService
|
import org.matrix.android.sdk.api.session.room.read.ReadService
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
@@ -304,11 +303,11 @@ class TimelineViewModel @AssistedInject constructor(
|
|||||||
private fun observePowerLevel() {
|
private fun observePowerLevel() {
|
||||||
if (room == null) return
|
if (room == null) return
|
||||||
PowerLevelsFlowFactory(room).createFlow()
|
PowerLevelsFlowFactory(room).createFlow()
|
||||||
.onEach {
|
.onEach { powerLevels ->
|
||||||
val canInvite = PowerLevelsHelper(it).isUserAbleToInvite(session.myUserId)
|
val canInvite = powerLevels.isUserAbleToInvite(session.myUserId)
|
||||||
val isAllowedToManageWidgets = session.widgetService().hasPermissionsToHandleWidgets(room.roomId)
|
val isAllowedToManageWidgets = session.widgetService().hasPermissionsToHandleWidgets(room.roomId)
|
||||||
val isAllowedToStartWebRTCCall = PowerLevelsHelper(it).isUserAllowedToSend(session.myUserId, false, EventType.CALL_INVITE)
|
val isAllowedToStartWebRTCCall = powerLevels.isUserAllowedToSend(session.myUserId, false, EventType.CALL_INVITE)
|
||||||
val isAllowedToSetupEncryption = PowerLevelsHelper(it).isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_ENCRYPTION)
|
val isAllowedToSetupEncryption = powerLevels.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_ENCRYPTION)
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
canInvite = canInvite,
|
canInvite = canInvite,
|
||||||
|
@@ -69,7 +69,6 @@ import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
|||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithFormattedBody
|
import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithFormattedBody
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||||
import org.matrix.android.sdk.api.session.room.model.relation.shouldRenderInThread
|
import org.matrix.android.sdk.api.session.room.model.relation.shouldRenderInThread
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
|
||||||
import org.matrix.android.sdk.api.session.room.send.UserDraft
|
import org.matrix.android.sdk.api.session.room.send.UserDraft
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.getRelationContent
|
import org.matrix.android.sdk.api.session.room.timeline.getRelationContent
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.getTextEditableContent
|
import org.matrix.android.sdk.api.session.room.timeline.getTextEditableContent
|
||||||
@@ -183,7 +182,7 @@ class MessageComposerViewModel @AssistedInject constructor(
|
|||||||
PowerLevelsFlowFactory(room).createFlow(),
|
PowerLevelsFlowFactory(room).createFlow(),
|
||||||
room.flow().liveRoomSummary().unwrap()
|
room.flow().liveRoomSummary().unwrap()
|
||||||
) { pl, sum ->
|
) { pl, sum ->
|
||||||
val canSendMessage = PowerLevelsHelper(pl).isUserAllowedToSend(session.myUserId, false, EventType.MESSAGE)
|
val canSendMessage = pl.isUserAllowedToSend(session.myUserId, false, EventType.MESSAGE)
|
||||||
if (canSendMessage) {
|
if (canSendMessage) {
|
||||||
val isE2E = sum.isEncrypted
|
val isE2E = sum.isEncrypted
|
||||||
if (isE2E) {
|
if (isE2E) {
|
||||||
|
@@ -49,7 +49,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
|
|||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationRequestContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationRequestContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.hasBeenEdited
|
import org.matrix.android.sdk.api.session.room.timeline.hasBeenEdited
|
||||||
@@ -117,11 +117,10 @@ class MessageActionsViewModel @AssistedInject constructor(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
PowerLevelsFlowFactory(room).createFlow()
|
PowerLevelsFlowFactory(room).createFlow()
|
||||||
.onEach {
|
.onEach { roomPowerLevels ->
|
||||||
val powerLevelsHelper = PowerLevelsHelper(it)
|
val canReact = roomPowerLevels.isUserAllowedToSend(session.myUserId, false, EventType.REACTION)
|
||||||
val canReact = powerLevelsHelper.isUserAllowedToSend(session.myUserId, false, EventType.REACTION)
|
val canRedact = roomPowerLevels.isUserAbleToRedact(session.myUserId)
|
||||||
val canRedact = powerLevelsHelper.isUserAbleToRedact(session.myUserId)
|
val canSendMessage = roomPowerLevels.isUserAllowedToSend(session.myUserId, false, EventType.MESSAGE)
|
||||||
val canSendMessage = powerLevelsHelper.isUserAllowedToSend(session.myUserId, false, EventType.MESSAGE)
|
|
||||||
val permissions = ActionPermissions(canSendMessage = canSendMessage, canRedact = canRedact, canReact = canReact)
|
val permissions = ActionPermissions(canSendMessage = canSendMessage, canRedact = canRedact, canReact = canReact)
|
||||||
setState {
|
setState {
|
||||||
copy(actionPermissions = permissions)
|
copy(actionPermissions = permissions)
|
||||||
|
@@ -30,10 +30,11 @@ import org.matrix.android.sdk.api.session.events.model.EventType
|
|||||||
import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
|
import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
|
import org.matrix.android.sdk.api.session.room.getRoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.getStateEvent
|
import org.matrix.android.sdk.api.session.room.getStateEvent
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -303,9 +304,7 @@ class MergedHeaderItemFactory @Inject constructor(
|
|||||||
collapsedEventIds.removeAll(mergedEventIds)
|
collapsedEventIds.removeAll(mergedEventIds)
|
||||||
}
|
}
|
||||||
val mergeId = mergedEventIds.joinToString(separator = "_") { it.toString() }
|
val mergeId = mergedEventIds.joinToString(separator = "_") { it.toString() }
|
||||||
val powerLevelsHelper = activeSessionHolder.getSafeActiveSession()?.getRoom(event.roomId)
|
val roomPowerLevels = activeSessionHolder.getSafeActiveSession()?.getRoom(event.roomId)?.getRoomPowerLevels()
|
||||||
?.let { it.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)?.content?.toModel<PowerLevelsContent>() }
|
|
||||||
?.let { PowerLevelsHelper(it) }
|
|
||||||
val currentUserId = activeSessionHolder.getSafeActiveSession()?.myUserId ?: ""
|
val currentUserId = activeSessionHolder.getSafeActiveSession()?.myUserId ?: ""
|
||||||
val attributes = MergedRoomCreationItem.Attributes(
|
val attributes = MergedRoomCreationItem.Attributes(
|
||||||
isCollapsed = isCollapsed,
|
isCollapsed = isCollapsed,
|
||||||
@@ -320,10 +319,10 @@ class MergedHeaderItemFactory @Inject constructor(
|
|||||||
callback = callback,
|
callback = callback,
|
||||||
currentUserId = currentUserId,
|
currentUserId = currentUserId,
|
||||||
roomSummary = partialState.roomSummary,
|
roomSummary = partialState.roomSummary,
|
||||||
canInvite = powerLevelsHelper?.isUserAbleToInvite(currentUserId) ?: false,
|
canInvite = roomPowerLevels?.isUserAbleToInvite(currentUserId) ?: false,
|
||||||
canChangeAvatar = powerLevelsHelper?.isUserAllowedToSend(currentUserId, true, EventType.STATE_ROOM_AVATAR) ?: false,
|
canChangeAvatar = roomPowerLevels?.isUserAllowedToSend(currentUserId, true, EventType.STATE_ROOM_AVATAR) ?: false,
|
||||||
canChangeTopic = powerLevelsHelper?.isUserAllowedToSend(currentUserId, true, EventType.STATE_ROOM_TOPIC) ?: false,
|
canChangeTopic = roomPowerLevels?.isUserAllowedToSend(currentUserId, true, EventType.STATE_ROOM_TOPIC) ?: false,
|
||||||
canChangeName = powerLevelsHelper?.isUserAllowedToSend(currentUserId, true, EventType.STATE_ROOM_NAME) ?: false
|
canChangeName = roomPowerLevels?.isUserAllowedToSend(currentUserId, true, EventType.STATE_ROOM_NAME) ?: false
|
||||||
)
|
)
|
||||||
MergedRoomCreationItem_()
|
MergedRoomCreationItem_()
|
||||||
.id(mergeId)
|
.id(mergeId)
|
||||||
|
@@ -41,7 +41,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomThirdPartyInviteContent
|
|||||||
import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
|
import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.call.CallInviteContent
|
import org.matrix.android.sdk.api.session.room.model.call.CallInviteContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetContent
|
import org.matrix.android.sdk.api.session.widgets.model.WidgetContent
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@@ -122,8 +122,8 @@ class NoticeEventFormatter @Inject constructor(
|
|||||||
userIds.addAll(previousPowerLevelsContent.users.orEmpty().keys)
|
userIds.addAll(previousPowerLevelsContent.users.orEmpty().keys)
|
||||||
val diffs = ArrayList<String>()
|
val diffs = ArrayList<String>()
|
||||||
userIds.forEach { userId ->
|
userIds.forEach { userId ->
|
||||||
val from = PowerLevelsHelper(previousPowerLevelsContent).getUserRole(userId)
|
val from = RoomPowerLevels(previousPowerLevelsContent,null).getUserRole(userId)
|
||||||
val to = PowerLevelsHelper(powerLevelsContent).getUserRole(userId)
|
val to = RoomPowerLevels(powerLevelsContent, null).getUserRole(userId)
|
||||||
if (from != to) {
|
if (from != to) {
|
||||||
val fromStr = roleFormatter.format(from)
|
val fromStr = roleFormatter.format(from)
|
||||||
val toStr = roleFormatter.format(to)
|
val toStr = roleFormatter.format(to)
|
||||||
|
@@ -34,7 +34,7 @@ import org.matrix.android.sdk.api.session.Session
|
|||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.getUserOrDefault
|
import org.matrix.android.sdk.api.session.getUserOrDefault
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
@@ -75,11 +75,10 @@ class LocationSharingViewModel @AssistedInject constructor(
|
|||||||
private fun observePowerLevelsForLiveLocationSharing() {
|
private fun observePowerLevelsForLiveLocationSharing() {
|
||||||
PowerLevelsFlowFactory(room).createFlow()
|
PowerLevelsFlowFactory(room).createFlow()
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.setOnEach {
|
.setOnEach { roomPowerLevels ->
|
||||||
val powerLevelsHelper = PowerLevelsHelper(it)
|
|
||||||
val canShareLiveLocation = EventType.STATE_ROOM_BEACON_INFO.values
|
val canShareLiveLocation = EventType.STATE_ROOM_BEACON_INFO.values
|
||||||
.all { beaconInfoType ->
|
.all { beaconInfoType ->
|
||||||
powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, beaconInfoType)
|
roomPowerLevels.isUserAllowedToSend(session.myUserId, true, beaconInfoType)
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(canShareLiveLocation = canShareLiveLocation)
|
copy(canShareLiveLocation = canShareLiveLocation)
|
||||||
|
@@ -9,23 +9,40 @@ package im.vector.app.features.powerlevel
|
|||||||
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.room.Room
|
import org.matrix.android.sdk.api.session.room.Room
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.create.getRoomCreateContentWithSender
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.flow.mapOptional
|
import org.matrix.android.sdk.flow.mapOptional
|
||||||
import org.matrix.android.sdk.flow.unwrap
|
|
||||||
|
|
||||||
class PowerLevelsFlowFactory(private val room: Room) {
|
class PowerLevelsFlowFactory(private val room: Room) {
|
||||||
|
|
||||||
fun createFlow(): Flow<PowerLevelsContent> {
|
fun createFlow(): Flow<RoomPowerLevels> {
|
||||||
return room.flow()
|
val flowRoom = room.flow()
|
||||||
|
val powerLevelsFlow = flowRoom
|
||||||
.liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
.liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
||||||
.mapOptional { it.content.toModel<PowerLevelsContent>() }
|
.mapOptional { it.content.toModel<PowerLevelsContent>() }
|
||||||
.flowOn(Dispatchers.Default)
|
.flowOn(Dispatchers.Default)
|
||||||
.unwrap()
|
|
||||||
|
val roomCreateFlow = flowRoom
|
||||||
|
.liveStateEvent(EventType.STATE_ROOM_CREATE, QueryStringValue.IsEmpty)
|
||||||
|
.mapOptional { event ->
|
||||||
|
event.getRoomCreateContentWithSender()
|
||||||
|
}
|
||||||
|
.flowOn(Dispatchers.Default)
|
||||||
|
|
||||||
|
return combine(powerLevelsFlow, roomCreateFlow) { powerLevelsContent, roomCreateContent ->
|
||||||
|
RoomPowerLevels(
|
||||||
|
powerLevelsContent = powerLevelsContent.getOrNull(),
|
||||||
|
roomCreateContent = roomCreateContent.getOrNull()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
package im.vector.app.features.roommemberprofile
|
package im.vector.app.features.roommemberprofile
|
||||||
|
|
||||||
import im.vector.app.core.platform.VectorViewModelAction
|
import im.vector.app.core.platform.VectorViewModelAction
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||||
|
|
||||||
sealed class RoomMemberProfileAction : VectorViewModelAction {
|
sealed class RoomMemberProfileAction : VectorViewModelAction {
|
||||||
object RetryFetchingInfo : RoomMemberProfileAction()
|
object RetryFetchingInfo : RoomMemberProfileAction()
|
||||||
@@ -18,7 +19,7 @@ sealed class RoomMemberProfileAction : VectorViewModelAction {
|
|||||||
object InviteUser : RoomMemberProfileAction()
|
object InviteUser : RoomMemberProfileAction()
|
||||||
object VerifyUser : RoomMemberProfileAction()
|
object VerifyUser : RoomMemberProfileAction()
|
||||||
object ShareRoomMemberProfile : RoomMemberProfileAction()
|
object ShareRoomMemberProfile : RoomMemberProfileAction()
|
||||||
data class SetPowerLevel(val previousValue: Int, val newValue: Int, val askForValidation: Boolean) : RoomMemberProfileAction()
|
data class SetPowerLevel(val previousValue: UserPowerLevel, val newValue: UserPowerLevel.Value, val askForValidation: Boolean) : RoomMemberProfileAction()
|
||||||
data class SetUserColorOverride(val newColorSpec: String) : RoomMemberProfileAction()
|
data class SetUserColorOverride(val newColorSpec: String) : RoomMemberProfileAction()
|
||||||
data class OpenOrCreateDm(val userId: String) : RoomMemberProfileAction()
|
data class OpenOrCreateDm(val userId: String) : RoomMemberProfileAction()
|
||||||
}
|
}
|
||||||
|
@@ -17,8 +17,8 @@ import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
|
|||||||
import im.vector.lib.strings.CommonStrings
|
import im.vector.lib.strings.CommonStrings
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class RoomMemberProfileController @Inject constructor(
|
class RoomMemberProfileController @Inject constructor(
|
||||||
@@ -38,7 +38,7 @@ class RoomMemberProfileController @Inject constructor(
|
|||||||
fun onOverrideColorClicked()
|
fun onOverrideColorClicked()
|
||||||
fun onJumpToReadReceiptClicked()
|
fun onJumpToReadReceiptClicked()
|
||||||
fun onMentionClicked()
|
fun onMentionClicked()
|
||||||
fun onEditPowerLevel(currentRole: Role)
|
fun onEditPowerLevel(userPowerLevel: UserPowerLevel)
|
||||||
fun onKickClicked(isSpace: Boolean)
|
fun onKickClicked(isSpace: Boolean)
|
||||||
fun onBanClicked(isSpace: Boolean, isUserBanned: Boolean)
|
fun onBanClicked(isSpace: Boolean, isUserBanned: Boolean)
|
||||||
fun onCancelInviteClicked()
|
fun onCancelInviteClicked()
|
||||||
@@ -243,11 +243,10 @@ class RoomMemberProfileController @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun buildAdminSection(state: RoomMemberProfileViewState) {
|
private fun buildAdminSection(state: RoomMemberProfileViewState) {
|
||||||
val powerLevelsContent = state.powerLevelsContent ?: return
|
|
||||||
val powerLevelsStr = state.userPowerLevelString() ?: return
|
val powerLevelsStr = state.userPowerLevelString() ?: return
|
||||||
val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent)
|
val roomPowerLevels = state.roomPowerLevels ?: return
|
||||||
val userPowerLevel = powerLevelsHelper.getUserRole(state.userId)
|
val userPowerLevel = roomPowerLevels.getUserPowerLevel(state.userId)
|
||||||
val myPowerLevel = powerLevelsHelper.getUserRole(session.myUserId)
|
val myPowerLevel = roomPowerLevels.getUserPowerLevel(session.myUserId)
|
||||||
if ((!state.isMine && myPowerLevel <= userPowerLevel)) {
|
if ((!state.isMine && myPowerLevel <= userPowerLevel)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -51,7 +51,7 @@ import im.vector.app.features.roommemberprofile.powerlevel.EditPowerLevelDialogs
|
|||||||
import im.vector.lib.strings.CommonStrings
|
import im.vector.lib.strings.CommonStrings
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.UserVerificationLevel
|
import org.matrix.android.sdk.api.session.crypto.model.UserVerificationLevel
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -377,9 +377,9 @@ class RoomMemberProfileFragment :
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onEditPowerLevel(currentRole: Role) {
|
override fun onEditPowerLevel(userPowerLevel: UserPowerLevel) {
|
||||||
EditPowerLevelDialogs.showChoice(requireActivity(), CommonStrings.power_level_edit_title, currentRole) { newPowerLevel ->
|
EditPowerLevelDialogs.showChoice(requireActivity(), CommonStrings.power_level_edit_title, userPowerLevel) { newPowerLevel ->
|
||||||
viewModel.handle(RoomMemberProfileAction.SetPowerLevel(currentRole.value, newPowerLevel, true))
|
viewModel.handle(RoomMemberProfileAction.SetPowerLevel(userPowerLevel, newPowerLevel, true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
package im.vector.app.features.roommemberprofile
|
package im.vector.app.features.roommemberprofile
|
||||||
|
|
||||||
import im.vector.app.core.platform.VectorViewEvents
|
import im.vector.app.core.platform.VectorViewEvents
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transient events for RoomMemberProfile.
|
* Transient events for RoomMemberProfile.
|
||||||
@@ -22,8 +23,8 @@ sealed class RoomMemberProfileViewEvents : VectorViewEvents {
|
|||||||
object OnInviteActionSuccess : RoomMemberProfileViewEvents()
|
object OnInviteActionSuccess : RoomMemberProfileViewEvents()
|
||||||
object OnKickActionSuccess : RoomMemberProfileViewEvents()
|
object OnKickActionSuccess : RoomMemberProfileViewEvents()
|
||||||
object OnBanActionSuccess : RoomMemberProfileViewEvents()
|
object OnBanActionSuccess : RoomMemberProfileViewEvents()
|
||||||
data class ShowPowerLevelValidation(val currentValue: Int, val newValue: Int) : RoomMemberProfileViewEvents()
|
data class ShowPowerLevelValidation(val currentValue: UserPowerLevel, val newValue: UserPowerLevel.Value) : RoomMemberProfileViewEvents()
|
||||||
data class ShowPowerLevelDemoteWarning(val currentValue: Int, val newValue: Int) : RoomMemberProfileViewEvents()
|
data class ShowPowerLevelDemoteWarning(val currentValue: UserPowerLevel, val newValue: UserPowerLevel.Value) : RoomMemberProfileViewEvents()
|
||||||
|
|
||||||
data class StartVerification(
|
data class StartVerification(
|
||||||
val userId: String,
|
val userId: String,
|
||||||
|
@@ -42,9 +42,9 @@ import org.matrix.android.sdk.api.session.getRoom
|
|||||||
import org.matrix.android.sdk.api.session.room.Room
|
import org.matrix.android.sdk.api.session.room.Room
|
||||||
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomEncryptionAlgorithm
|
import org.matrix.android.sdk.api.session.room.model.RoomEncryptionAlgorithm
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
import org.matrix.android.sdk.api.session.room.model.RoomType
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
import org.matrix.android.sdk.api.session.user.model.User
|
import org.matrix.android.sdk.api.session.user.model.User
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
@@ -233,15 +233,15 @@ class RoomMemberProfileViewModel @AssistedInject constructor(
|
|||||||
if (room == null || action.previousValue == action.newValue) {
|
if (room == null || action.previousValue == action.newValue) {
|
||||||
return@withState
|
return@withState
|
||||||
}
|
}
|
||||||
val currentPowerLevelsContent = state.powerLevelsContent ?: return@withState
|
val roomPowerLevels = state.roomPowerLevels ?: return@withState
|
||||||
val myPowerLevel = PowerLevelsHelper(currentPowerLevelsContent).getUserPowerLevelValue(session.myUserId)
|
val myPowerLevel = roomPowerLevels.getUserPowerLevel(session.myUserId)
|
||||||
if (action.askForValidation && action.newValue >= myPowerLevel) {
|
if (action.askForValidation && action.newValue >= myPowerLevel) {
|
||||||
_viewEvents.post(RoomMemberProfileViewEvents.ShowPowerLevelValidation(action.previousValue, action.newValue))
|
_viewEvents.post(RoomMemberProfileViewEvents.ShowPowerLevelValidation(action.previousValue, action.newValue))
|
||||||
} else if (action.askForValidation && state.isMine) {
|
} else if (action.askForValidation && state.isMine) {
|
||||||
_viewEvents.post(RoomMemberProfileViewEvents.ShowPowerLevelDemoteWarning(action.previousValue, action.newValue))
|
_viewEvents.post(RoomMemberProfileViewEvents.ShowPowerLevelDemoteWarning(action.previousValue, action.newValue))
|
||||||
} else {
|
} else {
|
||||||
val newPowerLevelsContent = currentPowerLevelsContent
|
val newPowerLevelsContent = (roomPowerLevels.powerLevelsContent ?: PowerLevelsContent())
|
||||||
.setUserPowerLevel(state.userId, action.newValue)
|
.setUserPowerLevel(state.userId, action.newValue.value)
|
||||||
.toContent()
|
.toContent()
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
_viewEvents.post(RoomMemberProfileViewEvents.Loading())
|
_viewEvents.post(RoomMemberProfileViewEvents.Loading())
|
||||||
@@ -361,19 +361,17 @@ class RoomMemberProfileViewModel @AssistedInject constructor(
|
|||||||
|
|
||||||
private fun observeRoomSummaryAndPowerLevels(room: Room) {
|
private fun observeRoomSummaryAndPowerLevels(room: Room) {
|
||||||
val roomSummaryLive = room.flow().liveRoomSummary().unwrap()
|
val roomSummaryLive = room.flow().liveRoomSummary().unwrap()
|
||||||
val powerLevelsContentLive = PowerLevelsFlowFactory(room).createFlow()
|
val powerLevelsFlow = PowerLevelsFlowFactory(room).createFlow()
|
||||||
|
powerLevelsFlow
|
||||||
powerLevelsContentLive
|
.onEach { roomPowerLevels ->
|
||||||
.onEach {
|
|
||||||
val powerLevelsHelper = PowerLevelsHelper(it)
|
|
||||||
val permissions = ActionPermissions(
|
val permissions = ActionPermissions(
|
||||||
canKick = powerLevelsHelper.isUserAbleToKick(session.myUserId),
|
canKick = roomPowerLevels.isUserAbleToKick(session.myUserId),
|
||||||
canBan = powerLevelsHelper.isUserAbleToBan(session.myUserId),
|
canBan = roomPowerLevels.isUserAbleToBan(session.myUserId),
|
||||||
canInvite = powerLevelsHelper.isUserAbleToInvite(session.myUserId),
|
canInvite = roomPowerLevels.isUserAbleToInvite(session.myUserId),
|
||||||
canEditPowerLevel = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_POWER_LEVELS)
|
canEditPowerLevel = roomPowerLevels.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_POWER_LEVELS)
|
||||||
)
|
)
|
||||||
setState {
|
setState {
|
||||||
copy(powerLevelsContent = it, actionPermissions = permissions)
|
copy(roomPowerLevels = roomPowerLevels, actionPermissions = permissions)
|
||||||
}
|
}
|
||||||
}.launchIn(viewModelScope)
|
}.launchIn(viewModelScope)
|
||||||
|
|
||||||
@@ -388,14 +386,14 @@ class RoomMemberProfileViewModel @AssistedInject constructor(
|
|||||||
copy(isRoomEncrypted = false)
|
copy(isRoomEncrypted = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
roomSummaryLive.combine(powerLevelsContentLive) { roomSummary, powerLevelsContent ->
|
roomSummaryLive.combine(powerLevelsFlow) { roomSummary, roomPowerLevels ->
|
||||||
val roomName = roomSummary.toMatrixItem().getBestName()
|
val roomName = roomSummary.toMatrixItem().getBestName()
|
||||||
val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent)
|
when (roomPowerLevels.getUserRole(initialState.userId)) {
|
||||||
when (val userPowerLevel = powerLevelsHelper.getUserRole(initialState.userId)) {
|
Role.SuperAdmin,
|
||||||
|
Role.Creator,
|
||||||
Role.Admin -> stringProvider.getString(CommonStrings.room_member_power_level_admin_in, roomName)
|
Role.Admin -> stringProvider.getString(CommonStrings.room_member_power_level_admin_in, roomName)
|
||||||
Role.Moderator -> stringProvider.getString(CommonStrings.room_member_power_level_moderator_in, roomName)
|
Role.Moderator -> stringProvider.getString(CommonStrings.room_member_power_level_moderator_in, roomName)
|
||||||
Role.Default -> stringProvider.getString(CommonStrings.room_member_power_level_default_in, roomName)
|
Role.User -> stringProvider.getString(CommonStrings.room_member_power_level_default_in, roomName)
|
||||||
is Role.Custom -> stringProvider.getString(CommonStrings.room_member_power_level_custom_in, userPowerLevel.value, roomName)
|
|
||||||
}
|
}
|
||||||
}.execute {
|
}.execute {
|
||||||
copy(userPowerLevelString = it)
|
copy(userPowerLevelString = it)
|
||||||
|
@@ -12,7 +12,7 @@ import com.airbnb.mvrx.MavericksState
|
|||||||
import com.airbnb.mvrx.Uninitialized
|
import com.airbnb.mvrx.Uninitialized
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
|
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
|
|
||||||
data class RoomMemberProfileViewState(
|
data class RoomMemberProfileViewState(
|
||||||
@@ -24,7 +24,7 @@ data class RoomMemberProfileViewState(
|
|||||||
val isIgnored: Async<Boolean> = Uninitialized,
|
val isIgnored: Async<Boolean> = Uninitialized,
|
||||||
val isRoomEncrypted: Boolean = false,
|
val isRoomEncrypted: Boolean = false,
|
||||||
val isAlgorithmSupported: Boolean = true,
|
val isAlgorithmSupported: Boolean = true,
|
||||||
val powerLevelsContent: PowerLevelsContent? = null,
|
val roomPowerLevels: RoomPowerLevels? = null,
|
||||||
val userPowerLevelString: Async<String> = Uninitialized,
|
val userPowerLevelString: Async<String> = Uninitialized,
|
||||||
val userMatrixItem: Async<MatrixItem> = Uninitialized,
|
val userMatrixItem: Async<MatrixItem> = Uninitialized,
|
||||||
val userMXCrossSigningInfo: MXCrossSigningInfo? = null,
|
val userMXCrossSigningInfo: MXCrossSigningInfo? = null,
|
||||||
|
@@ -19,6 +19,7 @@ import im.vector.app.core.extensions.hideKeyboard
|
|||||||
import im.vector.app.databinding.DialogEditPowerLevelBinding
|
import im.vector.app.databinding.DialogEditPowerLevelBinding
|
||||||
import im.vector.lib.strings.CommonStrings
|
import im.vector.lib.strings.CommonStrings
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||||
|
|
||||||
object EditPowerLevelDialogs {
|
object EditPowerLevelDialogs {
|
||||||
|
|
||||||
@@ -26,21 +27,21 @@ object EditPowerLevelDialogs {
|
|||||||
fun showChoice(
|
fun showChoice(
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
@StringRes titleRes: Int,
|
@StringRes titleRes: Int,
|
||||||
currentRole: Role,
|
currentPowerLevel: UserPowerLevel,
|
||||||
listener: (Int) -> Unit
|
listener: (UserPowerLevel.Value) -> Unit
|
||||||
) {
|
) {
|
||||||
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_edit_power_level, null)
|
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_edit_power_level, null)
|
||||||
val views = DialogEditPowerLevelBinding.bind(dialogLayout)
|
val views = DialogEditPowerLevelBinding.bind(dialogLayout)
|
||||||
views.powerLevelRadioGroup.setOnCheckedChangeListener { _, checkedId ->
|
views.powerLevelRadioGroup.setOnCheckedChangeListener { _, checkedId ->
|
||||||
views.powerLevelCustomEditLayout.isVisible = checkedId == R.id.powerLevelCustomRadio
|
views.powerLevelCustomEditLayout.isVisible = checkedId == R.id.powerLevelCustomRadio
|
||||||
}
|
}
|
||||||
views.powerLevelCustomEdit.setText("${currentRole.value}")
|
val currentRole = Role.getSuggestedRole(currentPowerLevel)
|
||||||
|
|
||||||
when (currentRole) {
|
when (currentRole) {
|
||||||
|
Role.Creator -> views.powerLevelAdminRadio.isChecked = true
|
||||||
|
Role.SuperAdmin -> views.powerLevelAdminRadio.isChecked = true
|
||||||
Role.Admin -> views.powerLevelAdminRadio.isChecked = true
|
Role.Admin -> views.powerLevelAdminRadio.isChecked = true
|
||||||
Role.Moderator -> views.powerLevelModeratorRadio.isChecked = true
|
Role.Moderator -> views.powerLevelModeratorRadio.isChecked = true
|
||||||
Role.Default -> views.powerLevelDefaultRadio.isChecked = true
|
Role.User -> views.powerLevelDefaultRadio.isChecked = true
|
||||||
else -> views.powerLevelCustomRadio.isChecked = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialAlertDialogBuilder(activity)
|
MaterialAlertDialogBuilder(activity)
|
||||||
@@ -48,14 +49,14 @@ object EditPowerLevelDialogs {
|
|||||||
.setView(dialogLayout)
|
.setView(dialogLayout)
|
||||||
.setPositiveButton(CommonStrings.edit) { _, _ ->
|
.setPositiveButton(CommonStrings.edit) { _, _ ->
|
||||||
val newValue = when (views.powerLevelRadioGroup.checkedRadioButtonId) {
|
val newValue = when (views.powerLevelRadioGroup.checkedRadioButtonId) {
|
||||||
R.id.powerLevelAdminRadio -> Role.Admin.value
|
R.id.powerLevelAdminRadio -> UserPowerLevel.Admin
|
||||||
R.id.powerLevelModeratorRadio -> Role.Moderator.value
|
R.id.powerLevelModeratorRadio -> UserPowerLevel.Moderator
|
||||||
R.id.powerLevelDefaultRadio -> Role.Default.value
|
R.id.powerLevelDefaultRadio -> UserPowerLevel.User
|
||||||
else -> {
|
else -> null
|
||||||
views.powerLevelCustomEdit.text?.toString()?.toInt() ?: currentRole.value
|
}
|
||||||
}
|
if(newValue != null) {
|
||||||
|
listener(newValue)
|
||||||
}
|
}
|
||||||
listener(newValue)
|
|
||||||
}
|
}
|
||||||
.setNegativeButton(CommonStrings.action_cancel, null)
|
.setNegativeButton(CommonStrings.action_cancel, null)
|
||||||
.setOnKeyListener(DialogInterface.OnKeyListener
|
.setOnKeyListener(DialogInterface.OnKeyListener
|
||||||
|
@@ -39,7 +39,7 @@ import org.matrix.android.sdk.api.session.room.getStateEvent
|
|||||||
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.state.isPublic
|
import org.matrix.android.sdk.api.session.room.state.isPublic
|
||||||
import org.matrix.android.sdk.flow.FlowRoom
|
import org.matrix.android.sdk.flow.FlowRoom
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
@@ -115,9 +115,8 @@ class RoomProfileViewModel @AssistedInject constructor(
|
|||||||
private fun observePowerLevels() {
|
private fun observePowerLevels() {
|
||||||
val powerLevelsContentLive = PowerLevelsFlowFactory(room).createFlow()
|
val powerLevelsContentLive = PowerLevelsFlowFactory(room).createFlow()
|
||||||
powerLevelsContentLive
|
powerLevelsContentLive
|
||||||
.onEach {
|
.onEach { roomPowerLevels ->
|
||||||
val powerLevelsHelper = PowerLevelsHelper(it)
|
val canUpdateRoomState = roomPowerLevels.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_ENCRYPTION)
|
||||||
val canUpdateRoomState = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_ENCRYPTION)
|
|
||||||
setState {
|
setState {
|
||||||
copy(canUpdateRoomState = canUpdateRoomState)
|
copy(canUpdateRoomState = canUpdateRoomState)
|
||||||
}
|
}
|
||||||
@@ -158,10 +157,9 @@ class RoomProfileViewModel @AssistedInject constructor(
|
|||||||
private fun observePermissions() {
|
private fun observePermissions() {
|
||||||
PowerLevelsFlowFactory(room)
|
PowerLevelsFlowFactory(room)
|
||||||
.createFlow()
|
.createFlow()
|
||||||
.setOnEach {
|
.setOnEach { roomPowerLevels ->
|
||||||
val powerLevelsHelper = PowerLevelsHelper(it)
|
|
||||||
val permissions = RoomProfileViewState.ActionPermissions(
|
val permissions = RoomProfileViewState.ActionPermissions(
|
||||||
canEnableEncryption = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_ENCRYPTION)
|
canEnableEncryption = roomPowerLevels.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_ENCRYPTION)
|
||||||
)
|
)
|
||||||
copy(actionPermissions = permissions)
|
copy(actionPermissions = permissions)
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ import org.matrix.android.sdk.api.session.events.model.EventType
|
|||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.flow.mapOptional
|
import org.matrix.android.sdk.flow.mapOptional
|
||||||
import org.matrix.android.sdk.flow.unwrap
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
@@ -127,10 +127,9 @@ class RoomAliasViewModel @AssistedInject constructor(
|
|||||||
private fun observePowerLevel() {
|
private fun observePowerLevel() {
|
||||||
PowerLevelsFlowFactory(room)
|
PowerLevelsFlowFactory(room)
|
||||||
.createFlow()
|
.createFlow()
|
||||||
.onEach {
|
.onEach { roomPowerLevels ->
|
||||||
val powerLevelsHelper = PowerLevelsHelper(it)
|
|
||||||
val permissions = RoomAliasViewState.ActionPermissions(
|
val permissions = RoomAliasViewState.ActionPermissions(
|
||||||
canChangeCanonicalAlias = powerLevelsHelper.isUserAllowedToSend(
|
canChangeCanonicalAlias = roomPowerLevels.isUserAllowedToSend(
|
||||||
userId = session.myUserId,
|
userId = session.myUserId,
|
||||||
isState = true,
|
isState = true,
|
||||||
eventType = EventType.STATE_ROOM_CANONICAL_ALIAS
|
eventType = EventType.STATE_ROOM_CANONICAL_ALIAS
|
||||||
|
@@ -29,7 +29,7 @@ import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
|||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.flow.unwrap
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
|
|
||||||
@@ -62,12 +62,10 @@ class RoomBannedMemberListViewModel @AssistedInject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val powerLevelsContentLive = PowerLevelsFlowFactory(room).createFlow()
|
val powerLevelsFlow = PowerLevelsFlowFactory(room).createFlow()
|
||||||
|
powerLevelsFlow
|
||||||
powerLevelsContentLive
|
.setOnEach { roomPowerLevels ->
|
||||||
.setOnEach {
|
copy(canUserBan = roomPowerLevels.isUserAbleToBan(session.myUserId))
|
||||||
val powerLevelsHelper = PowerLevelsHelper(it)
|
|
||||||
copy(canUserBan = powerLevelsHelper.isUserAbleToBan(session.myUserId))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020-2024 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.roomprofile.members
|
||||||
|
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class RoomMemberListComparator @Inject constructor() : Comparator<RoomMemberWithPowerLevel> {
|
||||||
|
|
||||||
|
override fun compare(leftRoomMember: RoomMemberWithPowerLevel?, rightRoomMember: RoomMemberWithPowerLevel?): Int {
|
||||||
|
return when (leftRoomMember) {
|
||||||
|
null ->
|
||||||
|
when (rightRoomMember) {
|
||||||
|
null -> 0
|
||||||
|
else -> 1
|
||||||
|
}
|
||||||
|
else ->
|
||||||
|
when (rightRoomMember) {
|
||||||
|
null -> -1
|
||||||
|
else ->
|
||||||
|
when {
|
||||||
|
leftRoomMember.powerLevel > rightRoomMember.powerLevel -> 1
|
||||||
|
leftRoomMember.powerLevel < rightRoomMember.powerLevel -> -1
|
||||||
|
leftRoomMember.summary.displayName.isNullOrBlank() ->
|
||||||
|
when {
|
||||||
|
rightRoomMember.summary.displayName.isNullOrBlank() -> {
|
||||||
|
// No display names, compare ids
|
||||||
|
leftRoomMember.summary.userId.compareTo(rightRoomMember.summary.userId)
|
||||||
|
}
|
||||||
|
else -> 1
|
||||||
|
}
|
||||||
|
else ->
|
||||||
|
when {
|
||||||
|
rightRoomMember.summary.displayName.isNullOrBlank() -> -1
|
||||||
|
else -> {
|
||||||
|
when (leftRoomMember.summary.displayName) {
|
||||||
|
rightRoomMember.summary.displayName ->
|
||||||
|
// Same display name, compare id
|
||||||
|
leftRoomMember.summary.userId.compareTo(rightRoomMember.summary.userId)
|
||||||
|
else ->
|
||||||
|
leftRoomMember.summary.displayName!!.compareTo(rightRoomMember.summary.displayName!!, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -16,11 +16,13 @@ import im.vector.app.core.extensions.join
|
|||||||
import im.vector.app.core.resources.ColorProvider
|
import im.vector.app.core.resources.ColorProvider
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
|
import im.vector.app.features.roomprofile.permissions.RoleFormatter
|
||||||
import me.gujun.android.span.span
|
import me.gujun.android.span.span
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomThirdPartyInviteContent
|
import org.matrix.android.sdk.api.session.room.model.RoomThirdPartyInviteContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -29,7 +31,8 @@ class RoomMemberListController @Inject constructor(
|
|||||||
private val avatarRenderer: AvatarRenderer,
|
private val avatarRenderer: AvatarRenderer,
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val colorProvider: ColorProvider,
|
private val colorProvider: ColorProvider,
|
||||||
private val roomMemberSummaryFilter: RoomMemberSummaryFilter
|
private val roomMemberSummaryFilter: RoomMemberSummaryFilter,
|
||||||
|
private val roleFormatter: RoleFormatter,
|
||||||
) : TypedEpoxyController<RoomMemberListViewState>() {
|
) : TypedEpoxyController<RoomMemberListViewState>() {
|
||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
@@ -56,13 +59,13 @@ class RoomMemberListController @Inject constructor(
|
|||||||
.orEmpty()
|
.orEmpty()
|
||||||
var threePidInvitesDone = filteredThreePidInvites.isEmpty()
|
var threePidInvitesDone = filteredThreePidInvites.isEmpty()
|
||||||
|
|
||||||
for ((powerLevelCategory, roomMemberList) in roomMembersByPowerLevel) {
|
for ((category, roomMemberList) in roomMembersByPowerLevel) {
|
||||||
val filteredRoomMemberList = roomMemberList.filter { roomMemberSummaryFilter.test(it) }
|
val filteredRoomMemberList = roomMemberList.filter { roomMemberSummaryFilter.test(it.summary) }
|
||||||
if (filteredRoomMemberList.isEmpty()) {
|
if (filteredRoomMemberList.isEmpty()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (powerLevelCategory == RoomMemberListCategories.USER && !threePidInvitesDone) {
|
if (category == RoomMemberListCategories.USER && !threePidInvitesDone) {
|
||||||
// If there is no regular invite, display threepid invite before the regular user
|
// If there is no regular invite, display threepid invite before the regular user
|
||||||
buildProfileSection(
|
buildProfileSection(
|
||||||
stringProvider.getString(RoomMemberListCategories.INVITE.titleRes)
|
stringProvider.getString(RoomMemberListCategories.INVITE.titleRes)
|
||||||
@@ -73,20 +76,20 @@ class RoomMemberListController @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildProfileSection(
|
buildProfileSection(
|
||||||
stringProvider.getString(powerLevelCategory.titleRes)
|
stringProvider.getString(category.titleRes)
|
||||||
)
|
)
|
||||||
|
|
||||||
filteredRoomMemberList.join(
|
filteredRoomMemberList.join(
|
||||||
each = { _, roomMember ->
|
each = { _, roomMember ->
|
||||||
buildRoomMember(roomMember, powerLevelCategory, host, data)
|
buildRoomMember(roomMember, host, data)
|
||||||
},
|
},
|
||||||
between = { _, roomMemberBefore ->
|
between = { _, roomMemberBefore ->
|
||||||
dividerItem {
|
dividerItem {
|
||||||
id("divider_${roomMemberBefore.userId}")
|
id("divider_${roomMemberBefore.summary.userId}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (powerLevelCategory == RoomMemberListCategories.INVITE && !threePidInvitesDone) {
|
if (category == RoomMemberListCategories.INVITE && !threePidInvitesDone) {
|
||||||
// Display the threepid invite after the regular invite
|
// Display the threepid invite after the regular invite
|
||||||
dividerItem {
|
dividerItem {
|
||||||
id("divider_threepidinvites")
|
id("divider_threepidinvites")
|
||||||
@@ -108,24 +111,24 @@ class RoomMemberListController @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun buildRoomMember(
|
private fun buildRoomMember(
|
||||||
roomMember: RoomMemberSummary,
|
roomMember: RoomMemberWithPowerLevel,
|
||||||
powerLevelCategory: RoomMemberListCategories,
|
|
||||||
host: RoomMemberListController,
|
host: RoomMemberListController,
|
||||||
data: RoomMemberListViewState
|
data: RoomMemberListViewState
|
||||||
) {
|
) {
|
||||||
val powerLabel = stringProvider.getString(powerLevelCategory.titleRes)
|
val role = Role.getSuggestedRole(roomMember.powerLevel)
|
||||||
|
val powerLabel = roleFormatter.format(role)
|
||||||
|
|
||||||
profileMatrixItemWithPowerLevelWithPresence {
|
profileMatrixItemWithPowerLevelWithPresence {
|
||||||
id(roomMember.userId)
|
id(roomMember.summary.userId)
|
||||||
matrixItem(roomMember.toMatrixItem())
|
matrixItem(roomMember.summary.toMatrixItem())
|
||||||
avatarRenderer(host.avatarRenderer)
|
avatarRenderer(host.avatarRenderer)
|
||||||
userVerificationLevel(data.trustLevelMap.invoke()?.get(roomMember.userId))
|
userVerificationLevel(data.trustLevelMap.invoke()?.get(roomMember.summary.userId))
|
||||||
clickListener {
|
clickListener {
|
||||||
host.callback?.onRoomMemberClicked(roomMember)
|
host.callback?.onRoomMemberClicked(roomMember.summary)
|
||||||
}
|
}
|
||||||
showPresence(true)
|
showPresence(true)
|
||||||
userPresence(roomMember.userPresence)
|
userPresence(roomMember.summary.userPresence)
|
||||||
ignoredUser(roomMember.userId in data.ignoredUserIds)
|
ignoredUser(roomMember.summary.userId in data.ignoredUserIds)
|
||||||
powerLevelLabel(
|
powerLevelLabel(
|
||||||
span {
|
span {
|
||||||
span(powerLabel) {
|
span(powerLabel) {
|
||||||
|
@@ -31,22 +31,19 @@ import org.matrix.android.sdk.api.session.Session
|
|||||||
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.UserVerificationLevel
|
import org.matrix.android.sdk.api.session.crypto.model.UserVerificationLevel
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.flow.mapOptional
|
|
||||||
import org.matrix.android.sdk.flow.unwrap
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
class RoomMemberListViewModel @AssistedInject constructor(
|
class RoomMemberListViewModel @AssistedInject constructor(
|
||||||
@Assisted initialState: RoomMemberListViewState,
|
@Assisted initialState: RoomMemberListViewState,
|
||||||
private val roomMemberSummaryComparator: RoomMemberSummaryComparator,
|
private val roomMemberListComparator: RoomMemberListComparator,
|
||||||
private val session: Session
|
private val session: Session
|
||||||
) :
|
) :
|
||||||
VectorViewModel<RoomMemberListViewState, RoomMemberListAction, EmptyViewEvents>(initialState) {
|
VectorViewModel<RoomMemberListViewState, RoomMemberListAction, EmptyViewEvents>(initialState) {
|
||||||
@@ -75,14 +72,12 @@ class RoomMemberListViewModel @AssistedInject constructor(
|
|||||||
memberships = Membership.activeMemberships()
|
memberships = Membership.activeMemberships()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val powerLevelsFlow = PowerLevelsFlowFactory(room).createFlow()
|
||||||
combine(
|
combine(
|
||||||
roomFlow.liveRoomMembers(roomMemberQueryParams),
|
roomFlow.liveRoomMembers(roomMemberQueryParams),
|
||||||
roomFlow
|
powerLevelsFlow,
|
||||||
.liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
) { roomMembers, roomPowerLevels ->
|
||||||
.mapOptional { it.content.toModel<PowerLevelsContent>() }
|
buildRoomMemberSummaries(roomPowerLevels, roomMembers)
|
||||||
.unwrap()
|
|
||||||
) { roomMembers, powerLevelsContent ->
|
|
||||||
buildRoomMemberSummaries(powerLevelsContent, roomMembers)
|
|
||||||
}
|
}
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
copy(roomMemberSummaries = async)
|
copy(roomMemberSummaries = async)
|
||||||
@@ -143,10 +138,10 @@ class RoomMemberListViewModel @AssistedInject constructor(
|
|||||||
|
|
||||||
private fun observePowerLevel() {
|
private fun observePowerLevel() {
|
||||||
PowerLevelsFlowFactory(room).createFlow()
|
PowerLevelsFlowFactory(room).createFlow()
|
||||||
.onEach {
|
.onEach { roomPowerLevels ->
|
||||||
val permissions = ActionPermissions(
|
val permissions = ActionPermissions(
|
||||||
canInvite = PowerLevelsHelper(it).isUserAbleToInvite(session.myUserId),
|
canInvite = roomPowerLevels.isUserAbleToInvite(session.myUserId),
|
||||||
canRevokeThreePidInvite = PowerLevelsHelper(it).isUserAllowedToSend(
|
canRevokeThreePidInvite = roomPowerLevels.isUserAllowedToSend(
|
||||||
userId = session.myUserId,
|
userId = session.myUserId,
|
||||||
isState = true,
|
isState = true,
|
||||||
eventType = EventType.STATE_ROOM_THIRD_PARTY_INVITE
|
eventType = EventType.STATE_ROOM_THIRD_PARTY_INVITE
|
||||||
@@ -184,31 +179,34 @@ class RoomMemberListViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildRoomMemberSummaries(powerLevelsContent: PowerLevelsContent, roomMembers: List<RoomMemberSummary>): RoomMemberSummaries {
|
private fun buildRoomMemberSummaries(roomPowerLevels: RoomPowerLevels, roomMembers: List<RoomMemberSummary>): RoomMembersByRole {
|
||||||
val admins = ArrayList<RoomMemberSummary>()
|
val admins = ArrayList<RoomMemberWithPowerLevel>()
|
||||||
val moderators = ArrayList<RoomMemberSummary>()
|
val moderators = ArrayList<RoomMemberWithPowerLevel>()
|
||||||
val users = ArrayList<RoomMemberSummary>(roomMembers.size)
|
val users = ArrayList<RoomMemberWithPowerLevel>(roomMembers.size)
|
||||||
val customs = ArrayList<RoomMemberSummary>()
|
val invites = ArrayList<RoomMemberWithPowerLevel>()
|
||||||
val invites = ArrayList<RoomMemberSummary>()
|
|
||||||
val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent)
|
|
||||||
roomMembers
|
roomMembers
|
||||||
.forEach { roomMember ->
|
.forEach { roomMember ->
|
||||||
val userRole = powerLevelsHelper.getUserRole(roomMember.userId)
|
val powerLevel = roomPowerLevels.getUserPowerLevel(roomMember.userId)
|
||||||
|
val userRole = Role.getSuggestedRole(powerLevel)
|
||||||
|
val roomMemberWithPowerLevel = RoomMemberWithPowerLevel(
|
||||||
|
powerLevel = powerLevel,
|
||||||
|
summary = roomMember,
|
||||||
|
)
|
||||||
when {
|
when {
|
||||||
roomMember.membership == Membership.INVITE -> invites.add(roomMember)
|
roomMember.membership == Membership.INVITE -> invites.add(roomMemberWithPowerLevel)
|
||||||
userRole == Role.Admin -> admins.add(roomMember)
|
userRole == Role.SuperAdmin ||
|
||||||
userRole == Role.Moderator -> moderators.add(roomMember)
|
userRole == Role.Creator ||
|
||||||
userRole == Role.Default -> users.add(roomMember)
|
userRole == Role.Admin -> admins.add(roomMemberWithPowerLevel)
|
||||||
else -> customs.add(roomMember)
|
userRole == Role.Moderator -> moderators.add(roomMemberWithPowerLevel)
|
||||||
|
userRole == Role.User -> users.add(roomMemberWithPowerLevel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return listOf(
|
return listOf(
|
||||||
RoomMemberListCategories.ADMIN to admins.sortedWith(roomMemberSummaryComparator),
|
RoomMemberListCategories.ADMIN to admins.sortedWith(roomMemberListComparator),
|
||||||
RoomMemberListCategories.MODERATOR to moderators.sortedWith(roomMemberSummaryComparator),
|
RoomMemberListCategories.MODERATOR to moderators.sortedWith(roomMemberListComparator),
|
||||||
RoomMemberListCategories.CUSTOM to customs.sortedWith(roomMemberSummaryComparator),
|
RoomMemberListCategories.INVITE to invites.sortedWith(roomMemberListComparator),
|
||||||
RoomMemberListCategories.INVITE to invites.sortedWith(roomMemberSummaryComparator),
|
RoomMemberListCategories.USER to users.sortedWith(roomMemberListComparator)
|
||||||
RoomMemberListCategories.USER to users.sortedWith(roomMemberSummaryComparator)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,11 +18,12 @@ import org.matrix.android.sdk.api.session.crypto.model.UserVerificationLevel
|
|||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||||
|
|
||||||
data class RoomMemberListViewState(
|
data class RoomMemberListViewState(
|
||||||
val roomId: String,
|
val roomId: String,
|
||||||
val roomSummary: Async<RoomSummary> = Uninitialized,
|
val roomSummary: Async<RoomSummary> = Uninitialized,
|
||||||
val roomMemberSummaries: Async<RoomMemberSummaries> = Uninitialized,
|
val roomMemberSummaries: Async<RoomMembersByRole> = Uninitialized,
|
||||||
val areAllMembersLoaded: Boolean = false,
|
val areAllMembersLoaded: Boolean = false,
|
||||||
val ignoredUserIds: List<String> = emptyList(),
|
val ignoredUserIds: List<String> = emptyList(),
|
||||||
val filter: String = "",
|
val filter: String = "",
|
||||||
@@ -41,12 +42,16 @@ data class ActionPermissions(
|
|||||||
val canRevokeThreePidInvite: Boolean = false
|
val canRevokeThreePidInvite: Boolean = false
|
||||||
)
|
)
|
||||||
|
|
||||||
typealias RoomMemberSummaries = List<Pair<RoomMemberListCategories, List<RoomMemberSummary>>>
|
data class RoomMemberWithPowerLevel(
|
||||||
|
val powerLevel: UserPowerLevel,
|
||||||
|
val summary: RoomMemberSummary,
|
||||||
|
)
|
||||||
|
|
||||||
|
typealias RoomMembersByRole = List<Pair<RoomMemberListCategories, List<RoomMemberWithPowerLevel>>>
|
||||||
|
|
||||||
enum class RoomMemberListCategories(@StringRes val titleRes: Int) {
|
enum class RoomMemberListCategories(@StringRes val titleRes: Int) {
|
||||||
ADMIN(CommonStrings.room_member_power_level_admins),
|
ADMIN(CommonStrings.room_member_power_level_admins),
|
||||||
MODERATOR(CommonStrings.room_member_power_level_moderators),
|
MODERATOR(CommonStrings.room_member_power_level_moderators),
|
||||||
CUSTOM(CommonStrings.room_member_power_level_custom),
|
|
||||||
INVITE(CommonStrings.room_member_power_level_invites),
|
INVITE(CommonStrings.room_member_power_level_invites),
|
||||||
USER(CommonStrings.room_member_power_level_users)
|
USER(CommonStrings.room_member_power_level_users)
|
||||||
}
|
}
|
||||||
|
@@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020-2024 New Vector Ltd.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
* Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package im.vector.app.features.roomprofile.members
|
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class RoomMemberSummaryComparator @Inject constructor() : Comparator<RoomMemberSummary> {
|
|
||||||
|
|
||||||
override fun compare(leftRoomMemberSummary: RoomMemberSummary?, rightRoomMemberSummary: RoomMemberSummary?): Int {
|
|
||||||
return when (leftRoomMemberSummary) {
|
|
||||||
null ->
|
|
||||||
when (rightRoomMemberSummary) {
|
|
||||||
null -> 0
|
|
||||||
else -> 1
|
|
||||||
}
|
|
||||||
else ->
|
|
||||||
when (rightRoomMemberSummary) {
|
|
||||||
null -> -1
|
|
||||||
else ->
|
|
||||||
when {
|
|
||||||
leftRoomMemberSummary.displayName.isNullOrBlank() ->
|
|
||||||
when {
|
|
||||||
rightRoomMemberSummary.displayName.isNullOrBlank() -> {
|
|
||||||
// No display names, compare ids
|
|
||||||
leftRoomMemberSummary.userId.compareTo(rightRoomMemberSummary.userId)
|
|
||||||
}
|
|
||||||
else -> 1
|
|
||||||
}
|
|
||||||
else ->
|
|
||||||
when {
|
|
||||||
rightRoomMemberSummary.displayName.isNullOrBlank() -> -1
|
|
||||||
else -> {
|
|
||||||
when (leftRoomMemberSummary.displayName) {
|
|
||||||
rightRoomMemberSummary.displayName ->
|
|
||||||
// Same display name, compare id
|
|
||||||
leftRoomMemberSummary.userId.compareTo(rightRoomMemberSummary.userId)
|
|
||||||
else ->
|
|
||||||
leftRoomMemberSummary.displayName!!.compareTo(rightRoomMemberSummary.displayName!!, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -19,8 +19,9 @@ class RoleFormatter @Inject constructor(
|
|||||||
return when (role) {
|
return when (role) {
|
||||||
Role.Admin -> stringProvider.getString(CommonStrings.power_level_admin)
|
Role.Admin -> stringProvider.getString(CommonStrings.power_level_admin)
|
||||||
Role.Moderator -> stringProvider.getString(CommonStrings.power_level_moderator)
|
Role.Moderator -> stringProvider.getString(CommonStrings.power_level_moderator)
|
||||||
Role.Default -> stringProvider.getString(CommonStrings.power_level_default)
|
Role.User -> stringProvider.getString(CommonStrings.power_level_default)
|
||||||
is Role.Custom -> stringProvider.getString(CommonStrings.power_level_custom, role.value)
|
Role.Creator -> stringProvider.getString(CommonStrings.power_level_owner)
|
||||||
|
Role.SuperAdmin -> stringProvider.getString(CommonStrings.power_level_owner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,9 +8,10 @@
|
|||||||
package im.vector.app.features.roomprofile.permissions
|
package im.vector.app.features.roomprofile.permissions
|
||||||
|
|
||||||
import im.vector.app.core.platform.VectorViewModelAction
|
import im.vector.app.core.platform.VectorViewModelAction
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||||
|
|
||||||
sealed class RoomPermissionsAction : VectorViewModelAction {
|
sealed class RoomPermissionsAction : VectorViewModelAction {
|
||||||
object ToggleShowAllPermissions : RoomPermissionsAction()
|
object ToggleShowAllPermissions : RoomPermissionsAction()
|
||||||
|
|
||||||
data class UpdatePermission(val editablePermission: EditablePermission, val powerLevel: Int) : RoomPermissionsAction()
|
data class UpdatePermission(val editablePermission: EditablePermission, val powerLevel: UserPowerLevel.Value) : RoomPermissionsAction()
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,7 @@ import org.matrix.android.sdk.api.session.room.model.redactOrDefault
|
|||||||
import org.matrix.android.sdk.api.session.room.model.stateDefaultOrDefault
|
import org.matrix.android.sdk.api.session.room.model.stateDefaultOrDefault
|
||||||
import org.matrix.android.sdk.api.session.room.model.usersDefaultOrDefault
|
import org.matrix.android.sdk.api.session.room.model.usersDefaultOrDefault
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class RoomPermissionsController @Inject constructor(
|
class RoomPermissionsController @Inject constructor(
|
||||||
@@ -34,7 +35,7 @@ class RoomPermissionsController @Inject constructor(
|
|||||||
) : TypedEpoxyController<RoomPermissionsViewState>() {
|
) : TypedEpoxyController<RoomPermissionsViewState>() {
|
||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
fun onEditPermission(editablePermission: EditablePermission, currentRole: Role)
|
fun onEditPermission(editablePermission: EditablePermission, currentPowerLevel: UserPowerLevel)
|
||||||
fun toggleShowAllPermissions()
|
fun toggleShowAllPermissions()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +166,8 @@ class RoomPermissionsController @Inject constructor(
|
|||||||
editable: Boolean,
|
editable: Boolean,
|
||||||
isSpace: Boolean
|
isSpace: Boolean
|
||||||
) {
|
) {
|
||||||
val currentRole = getCurrentRole(editablePermission, content)
|
val currentPowerLevel = getPowerLevel(editablePermission, content)
|
||||||
|
val currentRole = Role.getSuggestedRole(currentPowerLevel)
|
||||||
buildProfileAction(
|
buildProfileAction(
|
||||||
id = editablePermission.labelResId.toString(),
|
id = editablePermission.labelResId.toString(),
|
||||||
title = stringProvider.getString(
|
title = stringProvider.getString(
|
||||||
@@ -177,12 +179,12 @@ class RoomPermissionsController @Inject constructor(
|
|||||||
action = {
|
action = {
|
||||||
callback
|
callback
|
||||||
?.takeIf { editable }
|
?.takeIf { editable }
|
||||||
?.onEditPermission(editablePermission, currentRole)
|
?.onEditPermission(editablePermission, currentPowerLevel)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCurrentRole(editablePermission: EditablePermission, content: PowerLevelsContent): Role {
|
private fun getPowerLevel(editablePermission: EditablePermission, content: PowerLevelsContent): UserPowerLevel.Value {
|
||||||
val value = when (editablePermission) {
|
val value = when (editablePermission) {
|
||||||
is EditablePermission.EventTypeEditablePermission -> content.events?.get(editablePermission.eventType) ?: content.stateDefaultOrDefault()
|
is EditablePermission.EventTypeEditablePermission -> content.events?.get(editablePermission.eventType) ?: content.stateDefaultOrDefault()
|
||||||
is EditablePermission.DefaultRole -> content.usersDefaultOrDefault()
|
is EditablePermission.DefaultRole -> content.usersDefaultOrDefault()
|
||||||
@@ -194,20 +196,6 @@ class RoomPermissionsController @Inject constructor(
|
|||||||
is EditablePermission.RemoveMessagesSentByOthers -> content.redactOrDefault()
|
is EditablePermission.RemoveMessagesSentByOthers -> content.redactOrDefault()
|
||||||
is EditablePermission.NotifyEveryone -> content.notificationLevel(PowerLevelsContent.NOTIFICATIONS_ROOM_KEY)
|
is EditablePermission.NotifyEveryone -> content.notificationLevel(PowerLevelsContent.NOTIFICATIONS_ROOM_KEY)
|
||||||
}
|
}
|
||||||
|
return UserPowerLevel.Value(value)
|
||||||
return Role.fromValue(
|
|
||||||
value,
|
|
||||||
when (editablePermission) {
|
|
||||||
is EditablePermission.EventTypeEditablePermission -> content.stateDefaultOrDefault()
|
|
||||||
is EditablePermission.DefaultRole -> Role.Default.value
|
|
||||||
is EditablePermission.SendMessages -> Role.Default.value
|
|
||||||
is EditablePermission.InviteUsers -> Role.Moderator.value
|
|
||||||
is EditablePermission.ChangeSettings -> Role.Moderator.value
|
|
||||||
is EditablePermission.KickUsers -> Role.Moderator.value
|
|
||||||
is EditablePermission.BanUsers -> Role.Moderator.value
|
|
||||||
is EditablePermission.RemoveMessagesSentByOthers -> Role.Moderator.value
|
|
||||||
is EditablePermission.NotifyEveryone -> Role.Moderator.value
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,7 @@ import im.vector.app.features.home.AvatarRenderer
|
|||||||
import im.vector.app.features.roommemberprofile.powerlevel.EditPowerLevelDialogs
|
import im.vector.app.features.roommemberprofile.powerlevel.EditPowerLevelDialogs
|
||||||
import im.vector.app.features.roomprofile.RoomProfileArgs
|
import im.vector.app.features.roomprofile.RoomProfileArgs
|
||||||
import im.vector.lib.strings.CommonStrings
|
import im.vector.lib.strings.CommonStrings
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -93,8 +93,8 @@ class RoomPermissionsFragment :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onEditPermission(editablePermission: EditablePermission, currentRole: Role) {
|
override fun onEditPermission(editablePermission: EditablePermission, currentPowerLevel: UserPowerLevel) {
|
||||||
EditPowerLevelDialogs.showChoice(requireActivity(), editablePermission.labelResId, currentRole) { newPowerLevel ->
|
EditPowerLevelDialogs.showChoice(requireActivity(), editablePermission.labelResId, currentPowerLevel) { newPowerLevel ->
|
||||||
viewModel.handle(RoomPermissionsAction.UpdatePermission(editablePermission, newPowerLevel))
|
viewModel.handle(RoomPermissionsAction.UpdatePermission(editablePermission, newPowerLevel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ package im.vector.app.features.roomprofile.permissions
|
|||||||
|
|
||||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||||
import com.airbnb.mvrx.Success
|
import com.airbnb.mvrx.Success
|
||||||
|
import com.airbnb.mvrx.Uninitialized
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
@@ -24,7 +25,6 @@ import org.matrix.android.sdk.api.session.events.model.EventType
|
|||||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.flow.unwrap
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
|
|
||||||
@@ -61,19 +61,23 @@ class RoomPermissionsViewModel @AssistedInject constructor(
|
|||||||
private fun observePowerLevel() {
|
private fun observePowerLevel() {
|
||||||
PowerLevelsFlowFactory(room)
|
PowerLevelsFlowFactory(room)
|
||||||
.createFlow()
|
.createFlow()
|
||||||
.onEach { powerLevelContent ->
|
.onEach { roomPowerLevels ->
|
||||||
val powerLevelsHelper = PowerLevelsHelper(powerLevelContent)
|
|
||||||
val permissions = RoomPermissionsViewState.ActionPermissions(
|
val permissions = RoomPermissionsViewState.ActionPermissions(
|
||||||
canChangePowerLevels = powerLevelsHelper.isUserAllowedToSend(
|
canChangePowerLevels = roomPowerLevels.isUserAllowedToSend(
|
||||||
userId = session.myUserId,
|
userId = session.myUserId,
|
||||||
isState = true,
|
isState = true,
|
||||||
eventType = EventType.STATE_ROOM_POWER_LEVELS
|
eventType = EventType.STATE_ROOM_POWER_LEVELS
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
val powerLevelsContent = roomPowerLevels.powerLevelsContent
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
actionPermissions = permissions,
|
actionPermissions = permissions,
|
||||||
currentPowerLevelsContent = Success(powerLevelContent)
|
currentPowerLevelsContent = if (powerLevelsContent != null) {
|
||||||
|
Success(powerLevelsContent)
|
||||||
|
} else {
|
||||||
|
Uninitialized
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}.launchIn(viewModelScope)
|
}.launchIn(viewModelScope)
|
||||||
@@ -94,26 +98,26 @@ class RoomPermissionsViewModel @AssistedInject constructor(
|
|||||||
|
|
||||||
private fun updatePermission(action: RoomPermissionsAction.UpdatePermission) {
|
private fun updatePermission(action: RoomPermissionsAction.UpdatePermission) {
|
||||||
withState { state ->
|
withState { state ->
|
||||||
val currentPowerLevel = state.currentPowerLevelsContent.invoke() ?: return@withState
|
val currentPowerLevelsContent = state.currentPowerLevelsContent.invoke() ?: return@withState
|
||||||
postLoading(true)
|
postLoading(true)
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
try {
|
try {
|
||||||
val newPowerLevelsContent = when (action.editablePermission) {
|
val newPowerLevelsContent = when (action.editablePermission) {
|
||||||
is EditablePermission.EventTypeEditablePermission -> currentPowerLevel.copy(
|
is EditablePermission.EventTypeEditablePermission -> currentPowerLevelsContent.copy(
|
||||||
events = currentPowerLevel.events.orEmpty().toMutableMap().apply {
|
events = currentPowerLevelsContent.events.orEmpty().toMutableMap().apply {
|
||||||
put(action.editablePermission.eventType, action.powerLevel)
|
put(action.editablePermission.eventType, action.powerLevel.value)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
is EditablePermission.DefaultRole -> currentPowerLevel.copy(usersDefault = action.powerLevel)
|
is EditablePermission.DefaultRole -> currentPowerLevelsContent.copy(usersDefault = action.powerLevel.value)
|
||||||
is EditablePermission.SendMessages -> currentPowerLevel.copy(eventsDefault = action.powerLevel)
|
is EditablePermission.SendMessages -> currentPowerLevelsContent.copy(eventsDefault = action.powerLevel.value)
|
||||||
is EditablePermission.InviteUsers -> currentPowerLevel.copy(invite = action.powerLevel)
|
is EditablePermission.InviteUsers -> currentPowerLevelsContent.copy(invite = action.powerLevel.value)
|
||||||
is EditablePermission.ChangeSettings -> currentPowerLevel.copy(stateDefault = action.powerLevel)
|
is EditablePermission.ChangeSettings -> currentPowerLevelsContent.copy(stateDefault = action.powerLevel.value)
|
||||||
is EditablePermission.KickUsers -> currentPowerLevel.copy(kick = action.powerLevel)
|
is EditablePermission.KickUsers -> currentPowerLevelsContent.copy(kick = action.powerLevel.value)
|
||||||
is EditablePermission.BanUsers -> currentPowerLevel.copy(ban = action.powerLevel)
|
is EditablePermission.BanUsers -> currentPowerLevelsContent.copy(ban = action.powerLevel.value)
|
||||||
is EditablePermission.RemoveMessagesSentByOthers -> currentPowerLevel.copy(redact = action.powerLevel)
|
is EditablePermission.RemoveMessagesSentByOthers -> currentPowerLevelsContent.copy(redact = action.powerLevel.value)
|
||||||
is EditablePermission.NotifyEveryone -> currentPowerLevel.copy(
|
is EditablePermission.NotifyEveryone -> currentPowerLevelsContent.copy(
|
||||||
notifications = currentPowerLevel.notifications.orEmpty().toMutableMap().apply {
|
notifications = currentPowerLevelsContent.notifications.orEmpty().toMutableMap().apply {
|
||||||
put(PowerLevelsContent.NOTIFICATIONS_ROOM_KEY, action.powerLevel)
|
put(PowerLevelsContent.NOTIFICATIONS_ROOM_KEY, action.powerLevel.value)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,6 @@ import org.matrix.android.sdk.api.session.room.model.RoomAvatarContent
|
|||||||
import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent
|
import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent
|
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
|
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.flow.mapOptional
|
import org.matrix.android.sdk.flow.mapOptional
|
||||||
import org.matrix.android.sdk.flow.unwrap
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
@@ -115,28 +114,26 @@ class RoomSettingsViewModel @AssistedInject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val powerLevelsContentLive = PowerLevelsFlowFactory(room).createFlow()
|
val powerLevelsFlow = PowerLevelsFlowFactory(room).createFlow()
|
||||||
|
powerLevelsFlow
|
||||||
powerLevelsContentLive
|
.onEach { roomPowerLevels ->
|
||||||
.onEach {
|
|
||||||
val powerLevelsHelper = PowerLevelsHelper(it)
|
|
||||||
val permissions = RoomSettingsViewState.ActionPermissions(
|
val permissions = RoomSettingsViewState.ActionPermissions(
|
||||||
canChangeAvatar = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_AVATAR),
|
canChangeAvatar = roomPowerLevels.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_AVATAR),
|
||||||
canChangeName = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_NAME),
|
canChangeName = roomPowerLevels.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_NAME),
|
||||||
canChangeTopic = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_TOPIC),
|
canChangeTopic = roomPowerLevels.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_TOPIC),
|
||||||
canChangeHistoryVisibility = powerLevelsHelper.isUserAllowedToSend(
|
canChangeHistoryVisibility = roomPowerLevels.isUserAllowedToSend(
|
||||||
session.myUserId, true,
|
session.myUserId, true,
|
||||||
EventType.STATE_ROOM_HISTORY_VISIBILITY
|
EventType.STATE_ROOM_HISTORY_VISIBILITY
|
||||||
),
|
),
|
||||||
canChangeJoinRule = powerLevelsHelper.isUserAllowedToSend(
|
canChangeJoinRule = roomPowerLevels.isUserAllowedToSend(
|
||||||
session.myUserId, true,
|
session.myUserId, true,
|
||||||
EventType.STATE_ROOM_JOIN_RULES
|
EventType.STATE_ROOM_JOIN_RULES
|
||||||
) &&
|
) &&
|
||||||
powerLevelsHelper.isUserAllowedToSend(
|
roomPowerLevels.isUserAllowedToSend(
|
||||||
session.myUserId, true,
|
session.myUserId, true,
|
||||||
EventType.STATE_ROOM_GUEST_ACCESS
|
EventType.STATE_ROOM_GUEST_ACCESS
|
||||||
),
|
),
|
||||||
canAddChildren = powerLevelsHelper.isUserAllowedToSend(
|
canAddChildren = roomPowerLevels.isUserAllowedToSend(
|
||||||
session.myUserId, true,
|
session.myUserId, true,
|
||||||
EventType.STATE_SPACE_CHILD
|
EventType.STATE_SPACE_CHILD
|
||||||
)
|
)
|
||||||
|
@@ -32,7 +32,6 @@ import org.matrix.android.sdk.api.session.events.model.EventType
|
|||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.getRoomSummary
|
import org.matrix.android.sdk.api.session.getRoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
@@ -74,20 +73,19 @@ class SpaceMenuViewModel @AssistedInject constructor(
|
|||||||
|
|
||||||
PowerLevelsFlowFactory(room)
|
PowerLevelsFlowFactory(room)
|
||||||
.createFlow()
|
.createFlow()
|
||||||
.onEach {
|
.onEach { roomPowerLevels ->
|
||||||
val powerLevelsHelper = PowerLevelsHelper(it)
|
|
||||||
|
|
||||||
val canInvite = powerLevelsHelper.isUserAbleToInvite(session.myUserId)
|
val canInvite = roomPowerLevels.isUserAbleToInvite(session.myUserId)
|
||||||
val canAddChild = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_SPACE_CHILD)
|
val canAddChild = roomPowerLevels.isUserAllowedToSend(session.myUserId, true, EventType.STATE_SPACE_CHILD)
|
||||||
|
|
||||||
val canChangeAvatar = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_AVATAR)
|
val canChangeAvatar = roomPowerLevels.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_AVATAR)
|
||||||
val canChangeName = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_NAME)
|
val canChangeName = roomPowerLevels.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_NAME)
|
||||||
val canChangeTopic = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_TOPIC)
|
val canChangeTopic = roomPowerLevels.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_TOPIC)
|
||||||
|
|
||||||
val isAdmin = powerLevelsHelper.getUserRole(session.myUserId) is Role.Admin
|
val isAdmin = roomPowerLevels.getUserRole(session.myUserId) == Role.Admin
|
||||||
val otherAdminCount = roomSummary?.otherMemberIds
|
val otherAdminCount = roomSummary?.otherMemberIds
|
||||||
?.map { powerLevelsHelper.getUserRole(it) }
|
?.map { roomPowerLevels.getUserRole(it) }
|
||||||
?.count { it is Role.Admin }
|
?.count { it == Role.Admin }
|
||||||
?: 0
|
?: 0
|
||||||
val isLastAdmin = isAdmin && otherAdminCount == 0
|
val isLastAdmin = isAdmin && otherAdminCount == 0
|
||||||
|
|
||||||
|
@@ -27,6 +27,7 @@ import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
|||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.RestrictedRoomPreset
|
import org.matrix.android.sdk.api.session.room.model.create.RestrictedRoomPreset
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
|
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||||
import org.matrix.android.sdk.api.session.space.CreateSpaceParams
|
import org.matrix.android.sdk.api.session.space.CreateSpaceParams
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -65,7 +66,7 @@ class CreateSpaceViewModelTask @Inject constructor(
|
|||||||
if (params.isPublic) {
|
if (params.isPublic) {
|
||||||
this.roomAliasName = params.spaceAlias
|
this.roomAliasName = params.spaceAlias
|
||||||
this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy(
|
this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy(
|
||||||
invite = Role.Default.value
|
invite = UserPowerLevel.User.value
|
||||||
)
|
)
|
||||||
this.preset = CreateRoomPreset.PRESET_PUBLIC_CHAT
|
this.preset = CreateRoomPreset.PRESET_PUBLIC_CHAT
|
||||||
this.historyVisibility = RoomHistoryVisibility.WORLD_READABLE
|
this.historyVisibility = RoomHistoryVisibility.WORLD_READABLE
|
||||||
@@ -79,7 +80,7 @@ class CreateSpaceViewModelTask @Inject constructor(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy(
|
this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy(
|
||||||
invite = Role.Moderator.value
|
invite = UserPowerLevel.Moderator.value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@@ -36,7 +36,6 @@ import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
|||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
import org.matrix.android.sdk.api.session.room.model.RoomType
|
||||||
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
|
||||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@@ -96,16 +95,14 @@ class SpaceDirectoryViewModel @AssistedInject constructor(
|
|||||||
private fun observePermissions() {
|
private fun observePermissions() {
|
||||||
val room = session.getRoom(initialState.spaceId) ?: return
|
val room = session.getRoom(initialState.spaceId) ?: return
|
||||||
|
|
||||||
val powerLevelsContentLive = PowerLevelsFlowFactory(room).createFlow()
|
val powerLevelsFlow = PowerLevelsFlowFactory(room).createFlow()
|
||||||
|
|
||||||
powerLevelsContentLive
|
powerLevelsFlow
|
||||||
.onEach {
|
.onEach { roomPowerLevels ->
|
||||||
val powerLevelsHelper = PowerLevelsHelper(it)
|
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
canAddRooms = powerLevelsHelper.isUserAllowedToSend(
|
canAddRooms = roomPowerLevels.isUserAllowedToSend(
|
||||||
session.myUserId, true,
|
userId = session.myUserId, isState = true, eventType = EventType.STATE_SPACE_CHILD
|
||||||
EventType.STATE_SPACE_CHILD
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -31,10 +31,11 @@ import org.matrix.android.sdk.api.session.Session
|
|||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
|
import org.matrix.android.sdk.api.session.room.getRoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.getStateEvent
|
import org.matrix.android.sdk.api.session.room.getStateEvent
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
@@ -50,14 +51,12 @@ class SpaceLeaveAdvancedViewModel @AssistedInject constructor(
|
|||||||
init {
|
init {
|
||||||
val space = session.getRoom(initialState.spaceId)
|
val space = session.getRoom(initialState.spaceId)
|
||||||
val spaceSummary = space?.roomSummary()
|
val spaceSummary = space?.roomSummary()
|
||||||
|
val roomPowerLevels = space?.getRoomPowerLevels()
|
||||||
val powerLevelsEvent = space?.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
roomPowerLevels?.let {
|
||||||
powerLevelsEvent?.content?.toModel<PowerLevelsContent>()?.let { powerLevelsContent ->
|
val isAdmin = roomPowerLevels.getUserRole(session.myUserId) == Role.Admin
|
||||||
val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent)
|
|
||||||
val isAdmin = powerLevelsHelper.getUserRole(session.myUserId) is Role.Admin
|
|
||||||
val otherAdminCount = spaceSummary?.otherMemberIds
|
val otherAdminCount = spaceSummary?.otherMemberIds
|
||||||
?.map { powerLevelsHelper.getUserRole(it) }
|
?.map { roomPowerLevels.getUserRole(it) }
|
||||||
?.count { it is Role.Admin }
|
?.count { it == Role.Admin }
|
||||||
?: 0
|
?: 0
|
||||||
val isLastAdmin = isAdmin && otherAdminCount == 0
|
val isLastAdmin = isAdmin && otherAdminCount == 0
|
||||||
setState {
|
setState {
|
||||||
|
@@ -54,7 +54,7 @@ class SpacePeopleListController @Inject constructor(
|
|||||||
memberSummaries.forEach { memberEntry ->
|
memberSummaries.forEach { memberEntry ->
|
||||||
|
|
||||||
val filtered = memberEntry.second
|
val filtered = memberEntry.second
|
||||||
.filter { roomMemberSummaryFilter.test(it) }
|
.filter { roomMemberSummaryFilter.test(it.summary) }
|
||||||
if (filtered.isNotEmpty()) {
|
if (filtered.isNotEmpty()) {
|
||||||
dividerItem {
|
dividerItem {
|
||||||
id("divider_type_${memberEntry.first.titleRes}")
|
id("divider_type_${memberEntry.first.titleRes}")
|
||||||
@@ -65,10 +65,10 @@ class SpacePeopleListController @Inject constructor(
|
|||||||
.join(
|
.join(
|
||||||
each = { _, roomMember ->
|
each = { _, roomMember ->
|
||||||
profileMatrixItemWithPowerLevel {
|
profileMatrixItemWithPowerLevel {
|
||||||
id(roomMember.userId)
|
id(roomMember.summary.userId)
|
||||||
matrixItem(roomMember.toMatrixItem())
|
matrixItem(roomMember.summary.toMatrixItem())
|
||||||
avatarRenderer(host.avatarRenderer)
|
avatarRenderer(host.avatarRenderer)
|
||||||
userVerificationLevel(data.trustLevelMap.invoke()?.get(roomMember.userId))
|
userVerificationLevel(data.trustLevelMap.invoke()?.get(roomMember.summary.userId))
|
||||||
.apply {
|
.apply {
|
||||||
val pl = host.toPowerLevelLabel(memberEntry.first)
|
val pl = host.toPowerLevelLabel(memberEntry.first)
|
||||||
if (memberEntry.first == RoomMemberListCategories.INVITE) {
|
if (memberEntry.first == RoomMemberListCategories.INVITE) {
|
||||||
@@ -106,13 +106,13 @@ class SpacePeopleListController @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
clickListener {
|
clickListener {
|
||||||
host.listener?.onSpaceMemberClicked(roomMember)
|
host.listener?.onSpaceMemberClicked(roomMember.summary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
between = { _, roomMemberBefore ->
|
between = { _, roomMemberBefore ->
|
||||||
dividerItem {
|
dividerItem {
|
||||||
id("divider_${roomMemberBefore.userId}")
|
id("divider_${roomMemberBefore.summary.userId}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@@ -23,7 +23,7 @@ import org.matrix.android.sdk.api.extensions.orFalse
|
|||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.getRoomSummary
|
import org.matrix.android.sdk.api.session.getRoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
|
|
||||||
class ShareSpaceViewModel @AssistedInject constructor(
|
class ShareSpaceViewModel @AssistedInject constructor(
|
||||||
@Assisted private val initialState: ShareSpaceViewState,
|
@Assisted private val initialState: ShareSpaceViewState,
|
||||||
@@ -52,11 +52,10 @@ class ShareSpaceViewModel @AssistedInject constructor(
|
|||||||
val room = session.getRoom(initialState.spaceId) ?: return
|
val room = session.getRoom(initialState.spaceId) ?: return
|
||||||
PowerLevelsFlowFactory(room)
|
PowerLevelsFlowFactory(room)
|
||||||
.createFlow()
|
.createFlow()
|
||||||
.onEach { powerLevelContent ->
|
.onEach { roomPowerLevels ->
|
||||||
val powerLevelsHelper = PowerLevelsHelper(powerLevelContent)
|
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
canInviteByMxId = powerLevelsHelper.isUserAbleToInvite(session.myUserId)
|
canInviteByMxId = roomPowerLevels.isUserAbleToInvite(session.myUserId)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -33,10 +33,11 @@ import org.matrix.android.sdk.api.session.events.model.toContent
|
|||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.room.Room
|
import org.matrix.android.sdk.api.session.room.Room
|
||||||
|
import org.matrix.android.sdk.api.session.room.getRoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.getStateEvent
|
import org.matrix.android.sdk.api.session.room.getStateEvent
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.flow.unwrap
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@@ -139,12 +140,8 @@ class StartVoiceBroadcastUseCase @Inject constructor(
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
fun assertHasEnoughPowerLevels(room: Room) {
|
fun assertHasEnoughPowerLevels(room: Room) {
|
||||||
val powerLevelsHelper = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
val roomPowerLevels = room.getRoomPowerLevels()
|
||||||
?.content
|
if (!roomPowerLevels.isUserAllowedToSend(session.myUserId, true, VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO)) {
|
||||||
?.toModel<PowerLevelsContent>()
|
|
||||||
?.let { PowerLevelsHelper(it) }
|
|
||||||
|
|
||||||
if (powerLevelsHelper?.isUserAllowedToSend(session.myUserId, true, VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO) != true) {
|
|
||||||
Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: no permission")
|
Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: no permission")
|
||||||
throw VoiceBroadcastFailure.RecordingError.NoPermission
|
throw VoiceBroadcastFailure.RecordingError.NoPermission
|
||||||
}
|
}
|
||||||
|
@@ -25,10 +25,11 @@ import org.matrix.android.sdk.api.session.events.model.EventType
|
|||||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
|
import org.matrix.android.sdk.api.session.room.getRoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.room.getStateEvent
|
import org.matrix.android.sdk.api.session.room.getStateEvent
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.widgets.WidgetPostAPIMediator
|
import org.matrix.android.sdk.api.session.widgets.WidgetPostAPIMediator
|
||||||
import org.matrix.android.sdk.api.util.JsonDict
|
import org.matrix.android.sdk.api.util.JsonDict
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@@ -146,13 +147,8 @@ class WidgetPostAPIHandler @AssistedInject constructor(
|
|||||||
|
|
||||||
Timber.d("## canSendEvent() : eventType $eventType isState $isState")
|
Timber.d("## canSendEvent() : eventType $eventType isState $isState")
|
||||||
|
|
||||||
val powerLevelsEvent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
val roomPowerLevels = room.getRoomPowerLevels()
|
||||||
val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>()
|
val canSend = roomPowerLevels.isUserAllowedToSend(session.myUserId, isState, eventType)
|
||||||
val canSend = if (powerLevelsContent == null) {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
PowerLevelsHelper(powerLevelsContent).isUserAllowedToSend(session.myUserId, isState, eventType)
|
|
||||||
}
|
|
||||||
if (canSend) {
|
if (canSend) {
|
||||||
Timber.d("## canSendEvent() returns true")
|
Timber.d("## canSendEvent() returns true")
|
||||||
widgetPostAPIMediator.sendBoolResponse(true, eventData)
|
widgetPostAPIMediator.sendBoolResponse(true, eventData)
|
||||||
|
@@ -19,9 +19,11 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
|||||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
|
||||||
import im.vector.app.features.widgets.permissions.WidgetPermissionsHelper
|
import im.vector.app.features.widgets.permissions.WidgetPermissionsHelper
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
@@ -31,7 +33,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
|
|||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||||
import org.matrix.android.sdk.api.session.widgets.WidgetManagementFailure
|
import org.matrix.android.sdk.api.session.widgets.WidgetManagementFailure
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.flow.mapOptional
|
import org.matrix.android.sdk.flow.mapOptional
|
||||||
@@ -102,11 +104,10 @@ class WidgetViewModel @AssistedInject constructor(
|
|||||||
if (room == null) {
|
if (room == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
room.flow().liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
PowerLevelsFlowFactory(room)
|
||||||
.mapOptional { it.content.toModel<PowerLevelsContent>() }
|
.createFlow()
|
||||||
.unwrap()
|
.map { roomPowerLevels ->
|
||||||
.map {
|
roomPowerLevels.isUserAllowedToSend(session.myUserId, true, null)
|
||||||
PowerLevelsHelper(it).isUserAllowedToSend(session.myUserId, true, null)
|
|
||||||
}
|
}
|
||||||
.setOnEach {
|
.setOnEach {
|
||||||
copy(canManageWidgets = it)
|
copy(canManageWidgets = it)
|
||||||
|
@@ -13,7 +13,7 @@ import com.airbnb.mvrx.test.MavericksTestRule
|
|||||||
import im.vector.app.features.roomprofile.RoomProfileArgs
|
import im.vector.app.features.roomprofile.RoomProfileArgs
|
||||||
import im.vector.app.features.roomprofile.members.RoomMemberListViewModel
|
import im.vector.app.features.roomprofile.members.RoomMemberListViewModel
|
||||||
import im.vector.app.features.roomprofile.members.RoomMemberListViewState
|
import im.vector.app.features.roomprofile.members.RoomMemberListViewState
|
||||||
import im.vector.app.features.roomprofile.members.RoomMemberSummaryComparator
|
import im.vector.app.features.roomprofile.members.RoomMemberListComparator
|
||||||
import im.vector.app.test.test
|
import im.vector.app.test.test
|
||||||
import im.vector.app.test.testCoroutineDispatchers
|
import im.vector.app.test.testCoroutineDispatchers
|
||||||
import io.mockk.coEvery
|
import io.mockk.coEvery
|
||||||
@@ -266,7 +266,7 @@ class MemberListViewModelTest {
|
|||||||
private fun createViewModel(): RoomMemberListViewModel {
|
private fun createViewModel(): RoomMemberListViewModel {
|
||||||
return RoomMemberListViewModel(
|
return RoomMemberListViewModel(
|
||||||
RoomMemberListViewState(args),
|
RoomMemberListViewState(args),
|
||||||
RoomMemberSummaryComparator(),
|
RoomMemberListComparator(),
|
||||||
fakeSession,
|
fakeSession,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user