room details : display the item to show request to join list

This commit is contained in:
ganfra 2024-11-25 16:33:34 +01:00
parent 1f94504a22
commit 39fd51888d
8 changed files with 71 additions and 2 deletions

View file

@ -141,6 +141,10 @@ class RoomDetailsFlowNode @AssistedInject constructor(
backstack.push(NavTarget.PinnedMessagesList) backstack.push(NavTarget.PinnedMessagesList)
} }
override fun openKnockRequestsList() {
// TODO open the knock requests list screen
}
override fun onJoinCall() { override fun onJoinCall() {
val inputs = CallType.RoomCall( val inputs = CallType.RoomCall(
sessionId = room.sessionId, sessionId = room.sessionId,

View file

@ -47,6 +47,7 @@ class RoomDetailsNode @AssistedInject constructor(
fun openPollHistory() fun openPollHistory()
fun openAdminSettings() fun openAdminSettings()
fun openPinnedMessagesList() fun openPinnedMessagesList()
fun openKnockRequestsList()
fun onJoinCall() fun onJoinCall()
} }
@ -111,6 +112,10 @@ class RoomDetailsNode @AssistedInject constructor(
callbacks.forEach { it.openPinnedMessagesList() } callbacks.forEach { it.openPinnedMessagesList() }
} }
private fun openKnockRequestsLists() {
callbacks.forEach { it.openKnockRequestsList() }
}
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val context = LocalContext.current val context = LocalContext.current
@ -140,7 +145,8 @@ class RoomDetailsNode @AssistedInject constructor(
openPollHistory = ::openPollHistory, openPollHistory = ::openPollHistory,
openAdminSettings = this::openAdminSettings, openAdminSettings = this::openAdminSettings,
onJoinCallClick = ::onJoinCall, onJoinCallClick = ::onJoinCall,
onPinnedMessagesClick = ::openPinnedMessages onPinnedMessagesClick = ::openPinnedMessages,
onKnockRequestsClick = ::openKnockRequestsLists
) )
} }
} }

View file

@ -38,6 +38,7 @@ import io.element.android.libraries.matrix.api.room.isDm
import io.element.android.libraries.matrix.api.room.powerlevels.canInvite import io.element.android.libraries.matrix.api.room.powerlevels.canInvite
import io.element.android.libraries.matrix.api.room.powerlevels.canSendState import io.element.android.libraries.matrix.api.room.powerlevels.canSendState
import io.element.android.libraries.matrix.api.room.roomNotificationSettings import io.element.android.libraries.matrix.api.room.roomNotificationSettings
import io.element.android.libraries.matrix.ui.room.canHandleKnockRequestsAsState
import io.element.android.libraries.matrix.ui.room.getCurrentRoomMember import io.element.android.libraries.matrix.ui.room.getCurrentRoomMember
import io.element.android.libraries.matrix.ui.room.getDirectRoomMember import io.element.android.libraries.matrix.ui.room.getDirectRoomMember
import io.element.android.libraries.matrix.ui.room.isOwnUserAdmin import io.element.android.libraries.matrix.ui.room.isOwnUserAdmin
@ -69,7 +70,7 @@ class RoomDetailsPresenter @Inject constructor(
val canShowNotificationSettings = remember { mutableStateOf(false) } val canShowNotificationSettings = remember { mutableStateOf(false) }
val roomInfo by room.roomInfoFlow.collectAsState(initial = null) val roomInfo by room.roomInfoFlow.collectAsState(initial = null)
val isUserAdmin = room.isOwnUserAdmin() val isUserAdmin = room.isOwnUserAdmin()
val syncUpdateFlow = room.syncUpdateFlow.collectAsState()
val roomAvatar by remember { derivedStateOf { roomInfo?.avatarUrl ?: room.avatarUrl } } val roomAvatar by remember { derivedStateOf { roomInfo?.avatarUrl ?: room.avatarUrl } }
val roomName by remember { derivedStateOf { (roomInfo?.name ?: room.displayName).trim() } } val roomName by remember { derivedStateOf { (roomInfo?.name ?: room.displayName).trim() } }
@ -90,6 +91,7 @@ class RoomDetailsPresenter @Inject constructor(
val membersState by room.membersStateFlow.collectAsState() val membersState by room.membersStateFlow.collectAsState()
val canInvite by getCanInvite(membersState) val canInvite by getCanInvite(membersState)
val canEditName by getCanSendState(membersState, StateEventType.ROOM_NAME) val canEditName by getCanSendState(membersState, StateEventType.ROOM_NAME)
val canEditAvatar by getCanSendState(membersState, StateEventType.ROOM_AVATAR) val canEditAvatar by getCanSendState(membersState, StateEventType.ROOM_AVATAR)
val canEditTopic by getCanSendState(membersState, StateEventType.ROOM_TOPIC) val canEditTopic by getCanSendState(membersState, StateEventType.ROOM_TOPIC)
@ -99,6 +101,8 @@ class RoomDetailsPresenter @Inject constructor(
val roomType by getRoomType(dmMember, currentMember) val roomType by getRoomType(dmMember, currentMember)
val roomCallState = roomCallStatePresenter.present() val roomCallState = roomCallStatePresenter.present()
val canHandleKnockRequests by room.canHandleKnockRequestsAsState(syncUpdateFlow.value)
val topicState = remember(canEditTopic, roomTopic, roomType) { val topicState = remember(canEditTopic, roomTopic, roomType) {
val topic = roomTopic val topic = roomTopic
@ -109,6 +113,12 @@ class RoomDetailsPresenter @Inject constructor(
} }
} }
val isKnockRequestsEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock).collectAsState(false)
val knockRequestsCount by remember { mutableStateOf(null) }
val canShowKnockRequests by remember {
derivedStateOf { isKnockRequestsEnabled && canHandleKnockRequests }
}
val roomNotificationSettingsState by room.roomNotificationSettingsStateFlow.collectAsState() val roomNotificationSettingsState by room.roomNotificationSettingsStateFlow.collectAsState()
fun handleEvents(event: RoomDetailsEvent) { fun handleEvents(event: RoomDetailsEvent) {
@ -153,10 +163,16 @@ class RoomDetailsPresenter @Inject constructor(
heroes = roomInfo?.heroes.orEmpty().toPersistentList(), heroes = roomInfo?.heroes.orEmpty().toPersistentList(),
canShowPinnedMessages = canShowPinnedMessages, canShowPinnedMessages = canShowPinnedMessages,
pinnedMessagesCount = pinnedMessagesCount, pinnedMessagesCount = pinnedMessagesCount,
canShowKnockRequests = canShowKnockRequests,
knockRequestsCount = knockRequestsCount,
eventSink = ::handleEvents, eventSink = ::handleEvents,
) )
} }
private fun getCanBan(membersState: MatrixRoomMembersState): Any {
TODO("Not yet implemented")
}
@Composable @Composable
private fun roomMemberDetailsPresenter(dmMemberState: RoomMember?) = remember(dmMemberState) { private fun roomMemberDetailsPresenter(dmMemberState: RoomMember?) = remember(dmMemberState) {
dmMemberState?.let { roomMember -> dmMemberState?.let { roomMember ->

View file

@ -41,6 +41,8 @@ data class RoomDetailsState(
val heroes: ImmutableList<MatrixUser>, val heroes: ImmutableList<MatrixUser>,
val canShowPinnedMessages: Boolean, val canShowPinnedMessages: Boolean,
val pinnedMessagesCount: Int?, val pinnedMessagesCount: Int?,
val canShowKnockRequests: Boolean,
val knockRequestsCount: Int?,
val eventSink: (RoomDetailsEvent) -> Unit val eventSink: (RoomDetailsEvent) -> Unit
) { ) {
val roomBadges = buildList { val roomBadges = buildList {

View file

@ -102,6 +102,8 @@ fun aRoomDetailsState(
heroes: List<MatrixUser> = emptyList(), heroes: List<MatrixUser> = emptyList(),
canShowPinnedMessages: Boolean = true, canShowPinnedMessages: Boolean = true,
pinnedMessagesCount: Int? = null, pinnedMessagesCount: Int? = null,
canShowKnockRequests: Boolean = false,
knockRequestsCount: Int? = null,
eventSink: (RoomDetailsEvent) -> Unit = {}, eventSink: (RoomDetailsEvent) -> Unit = {},
) = RoomDetailsState( ) = RoomDetailsState(
roomId = roomId, roomId = roomId,
@ -125,6 +127,8 @@ fun aRoomDetailsState(
heroes = heroes.toPersistentList(), heroes = heroes.toPersistentList(),
canShowPinnedMessages = canShowPinnedMessages, canShowPinnedMessages = canShowPinnedMessages,
pinnedMessagesCount = pinnedMessagesCount, pinnedMessagesCount = pinnedMessagesCount,
canShowKnockRequests = canShowKnockRequests,
knockRequestsCount = knockRequestsCount,
eventSink = eventSink eventSink = eventSink
) )

View file

@ -104,6 +104,7 @@ fun RoomDetailsView(
openAdminSettings: () -> Unit, openAdminSettings: () -> Unit,
onJoinCallClick: () -> Unit, onJoinCallClick: () -> Unit,
onPinnedMessagesClick: () -> Unit, onPinnedMessagesClick: () -> Unit,
onKnockRequestsClick: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
Scaffold( Scaffold(
@ -206,6 +207,12 @@ fun RoomDetailsView(
memberCount = state.memberCount, memberCount = state.memberCount,
openRoomMemberList = openRoomMemberList, openRoomMemberList = openRoomMemberList,
) )
if (state.canShowKnockRequests) {
KnockRequestsItem(
knockRequestsCount = state.knockRequestsCount,
onKnockRequestsClick = onKnockRequestsClick
)
}
} }
} }
@ -231,6 +238,20 @@ fun RoomDetailsView(
} }
} }
@Composable
private fun KnockRequestsItem(knockRequestsCount: Int?, onKnockRequestsClick: () -> Unit) {
ListItem(
headlineContent = { Text(stringResource(CommonStrings.screen_room_details_requests_to_join_title)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Notifications())),
trailingContent = if (knockRequestsCount == null || knockRequestsCount == 0) {
null
} else {
ListItemContent.Text(knockRequestsCount.toString())
},
onClick = onKnockRequestsClick,
)
}
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun RoomDetailsTopBar( private fun RoomDetailsTopBar(
@ -613,5 +634,6 @@ private fun ContentToPreview(state: RoomDetailsState) {
openAdminSettings = {}, openAdminSettings = {},
onJoinCallClick = {}, onJoinCallClick = {},
onPinnedMessagesClick = {}, onPinnedMessagesClick = {},
onKnockRequestsClick = {},
) )
} }

View file

@ -57,6 +57,13 @@ suspend fun MatrixRoom.canRedactOwn(): Result<Boolean> = canUserRedactOwn(sessio
*/ */
suspend fun MatrixRoom.canRedactOther(): Result<Boolean> = canUserRedactOther(sessionId) suspend fun MatrixRoom.canRedactOther(): Result<Boolean> = canUserRedactOther(sessionId)
/**
* Shortcut for checking if current user can handle knock requests.
*/
suspend fun MatrixRoom.canHandleKnockRequests(): Result<Boolean> = runCatching {
canInvite().getOrThrow() || canBan().getOrThrow() || canKick().getOrThrow()
}
/** /**
* Shortcut for calling [MatrixRoom.canUserPinUnpin] with our own user. * Shortcut for calling [MatrixRoom.canUserPinUnpin] with our own user.
*/ */

View file

@ -17,6 +17,7 @@ import io.element.android.libraries.matrix.api.room.MessageEventType
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.isDm import io.element.android.libraries.matrix.api.room.isDm
import io.element.android.libraries.matrix.api.room.powerlevels.canBan import io.element.android.libraries.matrix.api.room.powerlevels.canBan
import io.element.android.libraries.matrix.api.room.powerlevels.canHandleKnockRequests
import io.element.android.libraries.matrix.api.room.powerlevels.canInvite import io.element.android.libraries.matrix.api.room.powerlevels.canInvite
import io.element.android.libraries.matrix.api.room.powerlevels.canKick import io.element.android.libraries.matrix.api.room.powerlevels.canKick
import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther
@ -86,6 +87,13 @@ fun MatrixRoom.canBanAsState(updateKey: Long): State<Boolean> {
} }
} }
@Composable
fun MatrixRoom.canHandleKnockRequestsAsState(updateKey: Long): State<Boolean> {
return produceState(initialValue = false, key1 = updateKey) {
value = canHandleKnockRequests().getOrElse { false }
}
}
@Composable @Composable
fun MatrixRoom.userPowerLevelAsState(updateKey: Long): State<Long> { fun MatrixRoom.userPowerLevelAsState(updateKey: Long): State<Long> {
return produceState(initialValue = 0, key1 = updateKey) { return produceState(initialValue = 0, key1 = updateKey) {