misc(power level) : clean up code

This commit is contained in:
ganfra 2025-12-10 11:26:07 +01:00
parent b32157f99e
commit 0befce4743
16 changed files with 19 additions and 30 deletions

View file

@ -99,6 +99,7 @@ import timber.log.Timber
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
import io.element.android.libraries.core.mimetype.MimeTypes.Any as AnyMimeTypes import io.element.android.libraries.core.mimetype.MimeTypes.Any as AnyMimeTypes
@Suppress("LargeClass")
@AssistedInject @AssistedInject
class MessageComposerPresenter( class MessageComposerPresenter(
@Assisted private val navigator: MessagesNavigator, @Assisted private val navigator: MessagesNavigator,
@ -397,7 +398,7 @@ class MessageComposerPresenter(
val currentUserId = room.sessionId val currentUserId = room.sessionId
suspend fun canSendRoomMention(): Boolean { suspend fun canSendRoomMention(): Boolean {
val userCanSendAtRoom = room.roomPermissions().use(false){ perms -> val userCanSendAtRoom = room.roomPermissions().use(false) { perms ->
perms.canOwnUserTriggerRoomNotification() perms.canOwnUserTriggerRoomNotification()
} }
return !room.isDm() && userCanSendAtRoom return !room.isDm() && userCanSendAtRoom

View file

@ -39,7 +39,6 @@ import io.element.android.features.poll.api.actions.EndPollAction
import io.element.android.features.poll.api.actions.SendPollResponseAction import io.element.android.features.poll.api.actions.SendPollResponseAction
import io.element.android.features.roomcall.api.RoomCallState import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.di.annotations.SessionCoroutineScope
import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlagService
@ -96,6 +95,7 @@ class TimelinePresenter(
private val analyticsService: AnalyticsService, private val analyticsService: AnalyticsService,
) : Presenter<TimelineState> { ) : Presenter<TimelineState> {
private val tag = "TimelinePresenter" private val tag = "TimelinePresenter"
@AssistedFactory @AssistedFactory
interface Factory { interface Factory {
fun create( fun create(

View file

@ -1234,13 +1234,13 @@ class MessagesPresenterTest {
canPinUnpin: Boolean = true, canPinUnpin: Boolean = true,
) = FakeRoomPermissions( ) = FakeRoomPermissions(
canSendState = { type -> canSendState = { type ->
when(type){ when (type) {
StateEventType.CALL_MEMBER -> canStartCall StateEventType.CALL_MEMBER -> canStartCall
else -> lambdaError() else -> lambdaError()
} }
}, },
canSendMessage = { type -> canSendMessage = { type ->
when(type){ when (type) {
MessageEventType.RoomMessage -> canSendMessage MessageEventType.RoomMessage -> canSendMessage
MessageEventType.Reaction -> canSendReaction MessageEventType.Reaction -> canSendReaction
else -> lambdaError() else -> lambdaError()

View file

@ -22,8 +22,6 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatch
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.sync.SyncService
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
@ -41,7 +39,6 @@ import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.assert
import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.lambda.value
import io.element.android.tests.testutils.test import io.element.android.tests.testutils.test

View file

@ -8,8 +8,6 @@
package io.element.android.features.messages.impl.timeline package io.element.android.features.messages.impl.timeline
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.ReceiveTurbine import app.cash.turbine.ReceiveTurbine
import app.cash.turbine.test import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
@ -37,7 +35,6 @@ import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.core.asEventId import io.element.android.libraries.matrix.api.core.asEventId
import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.ReceiptType
@ -988,7 +985,7 @@ class TimelinePresenterTest {
canPinUnpin: Boolean = false, canPinUnpin: Boolean = false,
) = FakeRoomPermissions( ) = FakeRoomPermissions(
canSendMessage = { type -> canSendMessage = { type ->
when(type){ when (type) {
MessageEventType.RoomMessage -> canSendMessage MessageEventType.RoomMessage -> canSendMessage
MessageEventType.Reaction -> canSendReaction MessageEventType.Reaction -> canSendReaction
else -> lambdaError() else -> lambdaError()

View file

@ -13,7 +13,6 @@ import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions
import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.AN_AVATAR_URL

View file

@ -634,7 +634,7 @@ class RoomDetailsPresenterTest {
canChangeTopic: Boolean = true, canChangeTopic: Boolean = true,
canChangeAvatar: Boolean = true, canChangeAvatar: Boolean = true,
canChangePowerLevels: Boolean = true, canChangePowerLevels: Boolean = true,
) : RoomPermissions{ ): RoomPermissions {
return FakeRoomPermissions( return FakeRoomPermissions(
canInvite = canInvite, canInvite = canInvite,
canKick = canKick, canKick = canKick,
@ -656,5 +656,4 @@ class RoomDetailsPresenterTest {
} }
) )
} }
} }

View file

@ -12,7 +12,6 @@ import com.google.common.truth.Truth.assertThat
import io.element.android.features.roommembermoderation.api.RoomMemberModerationState import io.element.android.features.roommembermoderation.api.RoomMemberModerationState
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.room.RoomMembershipState
@ -181,7 +180,6 @@ class RoomMemberListPresenterTest {
} }
} }
@Test @Test
fun `present - RoomMemberSelected will open the moderation options`() = runTest { fun `present - RoomMemberSelected will open the moderation options`() = runTest {
val presenter = createPresenter( val presenter = createPresenter(

View file

@ -14,7 +14,7 @@ data class RoomDetailsEditPermissions(
val canEditName: Boolean, val canEditName: Boolean,
val canEditTopic: Boolean, val canEditTopic: Boolean,
val canEditAvatar: Boolean, val canEditAvatar: Boolean,
){ ) {
val hasAny = canEditName || val hasAny = canEditName ||
canEditTopic || canEditTopic ||
canEditAvatar canEditAvatar

View file

@ -59,7 +59,6 @@ class RoomDetailsEditPresenter(
@Composable @Composable
override fun present(): RoomDetailsEditState { override fun present(): RoomDetailsEditState {
val cameraPermissionState = cameraPermissionPresenter.present() val cameraPermissionState = cameraPermissionPresenter.present()
val roomSyncUpdateFlow = room.syncUpdateFlow.collectAsState()
val roomInfo by room.roomInfoFlow.collectAsState() val roomInfo by room.roomInfoFlow.collectAsState()
val roomAvatarUri = roomInfo.avatarUrl val roomAvatarUri = roomInfo.avatarUrl
var roomAvatarUriEdited by rememberSaveable { mutableStateOf<String?>(null) } var roomAvatarUriEdited by rememberSaveable { mutableStateOf<String?>(null) }
@ -94,7 +93,7 @@ class RoomDetailsEditPresenter(
} }
} }
val permissions by room.permissionsAsState(RoomDetailsEditPermissions.DEFAULT){perms -> val permissions by room.permissionsAsState(RoomDetailsEditPermissions.DEFAULT) { perms ->
perms.roomDetailsEditPermissions() perms.roomDetailsEditPermissions()
} }

View file

@ -76,7 +76,7 @@ class UserProfilePresenter(
roomId roomId
?.let { client.getRoom(it) } ?.let { client.getRoom(it) }
?.use { room -> ?.use { room ->
room.roomPermissions().use(false){ perms -> perms.canCall()} room.roomPermissions().use(false) { perms -> perms.canCall() }
} }
.orFalse() .orFalse()
} }

View file

@ -18,7 +18,6 @@ import io.element.android.libraries.matrix.api.room.StateEventType
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import timber.log.Timber
/** /**
* Provides information about the permissions of users in a room. * Provides information about the permissions of users in a room.
@ -150,7 +149,15 @@ fun <T> Result<RoomPermissions>.use(default: T, block: (RoomPermissions) -> T):
fun <T> BaseRoom.permissionsFlow(default: T, block: (RoomPermissions) -> T): Flow<T> { fun <T> BaseRoom.permissionsFlow(default: T, block: (RoomPermissions) -> T): Flow<T> {
return roomInfoFlow return roomInfoFlow
.map { info -> info.roomPowerLevels } .map { info ->
// If the user is a privileged creator, we return a constant hashcode to avoid recomputing permissions
// each time the power levels change (as they have all permissions).
if (info.privilegedCreatorRole && info.creators.contains(sessionId)) {
Long.MAX_VALUE
} else {
info.roomPowerLevels?.hashCode() ?: 0L
}
}
.distinctUntilChanged() .distinctUntilChanged()
.map { .map {
roomPermissions().use(default, block) roomPermissions().use(default, block)
@ -160,7 +167,6 @@ fun <T> BaseRoom.permissionsFlow(default: T, block: (RoomPermissions) -> T): Flo
@Composable @Composable
fun <T> BaseRoom.permissionsAsState(default: T, block: (RoomPermissions) -> T): State<T> { fun <T> BaseRoom.permissionsAsState(default: T, block: (RoomPermissions) -> T): State<T> {
return remember(this, default, block) { return remember(this, default, block) {
Timber.d("Computing permissionsAsState for room $roomId with default=$default")
permissionsFlow(default, block) permissionsFlow(default, block)
}.collectAsState(default) }.collectAsState(default)
} }

View file

@ -18,12 +18,10 @@ import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.ThreadId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues

View file

@ -15,11 +15,9 @@ import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.ThreadId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues

View file

@ -32,7 +32,6 @@ data class FakeRoomPermissions(
private val canUserSendMessage: (UserId, MessageEventType) -> Boolean = { _, _ -> false }, private val canUserSendMessage: (UserId, MessageEventType) -> Boolean = { _, _ -> false },
private val canUserSendState: (UserId, StateEventType) -> Boolean = { _, _ -> false }, private val canUserSendState: (UserId, StateEventType) -> Boolean = { _, _ -> false },
) : RoomPermissions { ) : RoomPermissions {
override fun canOwnUserBan(): Boolean = canBan override fun canOwnUserBan(): Boolean = canBan
override fun canOwnUserInvite(): Boolean = canInvite override fun canOwnUserInvite(): Boolean = canInvite
override fun canOwnUserKick(): Boolean = canKick override fun canOwnUserKick(): Boolean = canKick
@ -57,4 +56,3 @@ data class FakeRoomPermissions(
// no-op for the fake // no-op for the fake
} }
} }

View file

@ -207,7 +207,6 @@ class MediaGalleryPresenter(
CommonStrings.error_unknown CommonStrings.error_unknown
} }
} }
} }
private fun GroupedMediaItems?.find(eventId: EventId?): MediaItem.Event? { private fun GroupedMediaItems?.find(eventId: EventId?): MediaItem.Event? {