Merge pull request #3995 from element-hq/feature/fga/requests_to_join_list
feat(knock_requests_list) : implement design
This commit is contained in:
commit
eae73ac2b9
49 changed files with 1031 additions and 20 deletions
|
|
@ -22,6 +22,7 @@ import im.vector.app.features.analytics.plan.Interaction
|
|||
import io.element.android.anvilannotations.ContributesNode
|
||||
import io.element.android.features.call.api.CallType
|
||||
import io.element.android.features.call.api.ElementCallEntryPoint
|
||||
import io.element.android.features.knockrequests.api.list.KnockRequestsListEntryPoint
|
||||
import io.element.android.features.messages.api.MessagesEntryPoint
|
||||
import io.element.android.features.poll.api.history.PollHistoryEntryPoint
|
||||
import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint
|
||||
|
|
@ -56,6 +57,7 @@ class RoomDetailsFlowNode @AssistedInject constructor(
|
|||
private val room: MatrixRoom,
|
||||
private val analyticsService: AnalyticsService,
|
||||
private val messagesEntryPoint: MessagesEntryPoint,
|
||||
private val knockRequestsListEntryPoint: KnockRequestsListEntryPoint,
|
||||
private val mediaViewerEntryPoint: MediaViewerEntryPoint,
|
||||
) : BaseFlowNode<RoomDetailsFlowNode.NavTarget>(
|
||||
backstack = BackStack(
|
||||
|
|
@ -101,6 +103,9 @@ class RoomDetailsFlowNode @AssistedInject constructor(
|
|||
|
||||
@Parcelize
|
||||
data object PinnedMessagesList : NavTarget
|
||||
|
||||
@Parcelize
|
||||
data object KnockRequestsList : NavTarget
|
||||
}
|
||||
|
||||
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
||||
|
|
@ -139,6 +144,10 @@ class RoomDetailsFlowNode @AssistedInject constructor(
|
|||
backstack.push(NavTarget.PinnedMessagesList)
|
||||
}
|
||||
|
||||
override fun openKnockRequestsList() {
|
||||
backstack.push(NavTarget.KnockRequestsList)
|
||||
}
|
||||
|
||||
override fun onJoinCall() {
|
||||
val inputs = CallType.RoomCall(
|
||||
sessionId = room.sessionId,
|
||||
|
|
@ -243,6 +252,9 @@ class RoomDetailsFlowNode @AssistedInject constructor(
|
|||
.callback(callback)
|
||||
.build()
|
||||
}
|
||||
NavTarget.KnockRequestsList -> {
|
||||
knockRequestsListEntryPoint.createNode(this, buildContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class RoomDetailsNode @AssistedInject constructor(
|
|||
fun openPollHistory()
|
||||
fun openAdminSettings()
|
||||
fun openPinnedMessagesList()
|
||||
fun openKnockRequestsList()
|
||||
fun onJoinCall()
|
||||
}
|
||||
|
||||
|
|
@ -111,6 +112,10 @@ class RoomDetailsNode @AssistedInject constructor(
|
|||
callbacks.forEach { it.openPinnedMessagesList() }
|
||||
}
|
||||
|
||||
private fun openKnockRequestsLists() {
|
||||
callbacks.forEach { it.openKnockRequestsList() }
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun View(modifier: Modifier) {
|
||||
val context = LocalContext.current
|
||||
|
|
@ -140,7 +145,8 @@ class RoomDetailsNode @AssistedInject constructor(
|
|||
openPollHistory = ::openPollHistory,
|
||||
openAdminSettings = this::openAdminSettings,
|
||||
onJoinCallClick = ::onJoinCall,
|
||||
onPinnedMessagesClick = ::openPinnedMessages
|
||||
onPinnedMessagesClick = ::openPinnedMessages,
|
||||
onKnockRequestsClick = ::openKnockRequestsLists,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.canSendState
|
||||
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.getDirectRoomMember
|
||||
import io.element.android.libraries.matrix.ui.room.isOwnUserAdmin
|
||||
|
|
@ -69,7 +70,7 @@ class RoomDetailsPresenter @Inject constructor(
|
|||
val canShowNotificationSettings = remember { mutableStateOf(false) }
|
||||
val roomInfo by room.roomInfoFlow.collectAsState(initial = null)
|
||||
val isUserAdmin = room.isOwnUserAdmin()
|
||||
|
||||
val syncUpdateFlow = room.syncUpdateFlow.collectAsState()
|
||||
val roomAvatar by remember { derivedStateOf { roomInfo?.avatarUrl ?: room.avatarUrl } }
|
||||
|
||||
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 canInvite by getCanInvite(membersState)
|
||||
|
||||
val canEditName by getCanSendState(membersState, StateEventType.ROOM_NAME)
|
||||
val canEditAvatar by getCanSendState(membersState, StateEventType.ROOM_AVATAR)
|
||||
val canEditTopic by getCanSendState(membersState, StateEventType.ROOM_TOPIC)
|
||||
|
|
@ -99,6 +101,8 @@ class RoomDetailsPresenter @Inject constructor(
|
|||
val roomType by getRoomType(dmMember, currentMember)
|
||||
val roomCallState = roomCallStatePresenter.present()
|
||||
|
||||
val canHandleKnockRequests by room.canHandleKnockRequestsAsState(syncUpdateFlow.value)
|
||||
|
||||
val topicState = remember(canEditTopic, roomTopic, roomType) {
|
||||
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()
|
||||
|
||||
fun handleEvents(event: RoomDetailsEvent) {
|
||||
|
|
@ -153,6 +163,8 @@ class RoomDetailsPresenter @Inject constructor(
|
|||
heroes = roomInfo?.heroes.orEmpty().toPersistentList(),
|
||||
canShowPinnedMessages = canShowPinnedMessages,
|
||||
pinnedMessagesCount = pinnedMessagesCount,
|
||||
canShowKnockRequests = canShowKnockRequests,
|
||||
knockRequestsCount = knockRequestsCount,
|
||||
eventSink = ::handleEvents,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ data class RoomDetailsState(
|
|||
val heroes: ImmutableList<MatrixUser>,
|
||||
val canShowPinnedMessages: Boolean,
|
||||
val pinnedMessagesCount: Int?,
|
||||
val canShowKnockRequests: Boolean,
|
||||
val knockRequestsCount: Int?,
|
||||
val eventSink: (RoomDetailsEvent) -> Unit
|
||||
) {
|
||||
val roomBadges = buildList {
|
||||
|
|
|
|||
|
|
@ -102,6 +102,8 @@ fun aRoomDetailsState(
|
|||
heroes: List<MatrixUser> = emptyList(),
|
||||
canShowPinnedMessages: Boolean = true,
|
||||
pinnedMessagesCount: Int? = null,
|
||||
canShowKnockRequests: Boolean = false,
|
||||
knockRequestsCount: Int? = null,
|
||||
eventSink: (RoomDetailsEvent) -> Unit = {},
|
||||
) = RoomDetailsState(
|
||||
roomId = roomId,
|
||||
|
|
@ -125,6 +127,8 @@ fun aRoomDetailsState(
|
|||
heroes = heroes.toPersistentList(),
|
||||
canShowPinnedMessages = canShowPinnedMessages,
|
||||
pinnedMessagesCount = pinnedMessagesCount,
|
||||
canShowKnockRequests = canShowKnockRequests,
|
||||
knockRequestsCount = knockRequestsCount,
|
||||
eventSink = eventSink
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ fun RoomDetailsView(
|
|||
openAdminSettings: () -> Unit,
|
||||
onJoinCallClick: () -> Unit,
|
||||
onPinnedMessagesClick: () -> Unit,
|
||||
onKnockRequestsClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Scaffold(
|
||||
|
|
@ -206,6 +207,12 @@ fun RoomDetailsView(
|
|||
memberCount = state.memberCount,
|
||||
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(R.string.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)
|
||||
@Composable
|
||||
private fun RoomDetailsTopBar(
|
||||
|
|
@ -525,7 +546,7 @@ private fun PinnedMessagesItem(
|
|||
) {
|
||||
val analyticsService = LocalAnalyticsService.current
|
||||
ListItem(
|
||||
headlineContent = { Text(stringResource(CommonStrings.screen_room_details_pinned_events_row_title)) },
|
||||
headlineContent = { Text(stringResource(R.string.screen_room_details_pinned_events_row_title)) },
|
||||
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Pin())),
|
||||
trailingContent =
|
||||
if (pinnedMessagesCount == null) {
|
||||
|
|
@ -613,5 +634,6 @@ private fun ContentToPreview(state: RoomDetailsState) {
|
|||
openAdminSettings = {},
|
||||
onJoinCallClick = {},
|
||||
onPinnedMessagesClick = {},
|
||||
onKnockRequestsClick = {},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,9 +49,12 @@
|
|||
<string name="screen_room_details_invite_people_title">"Invite people"</string>
|
||||
<string name="screen_room_details_leave_conversation_title">"Leave conversation"</string>
|
||||
<string name="screen_room_details_leave_room_title">"Leave room"</string>
|
||||
<string name="screen_room_details_media_gallery_title">"Media and files"</string>
|
||||
<string name="screen_room_details_notification_mode_custom">"Custom"</string>
|
||||
<string name="screen_room_details_notification_mode_default">"Default"</string>
|
||||
<string name="screen_room_details_notification_title">"Notifications"</string>
|
||||
<string name="screen_room_details_pinned_events_row_title">"Pinned messages"</string>
|
||||
<string name="screen_room_details_requests_to_join_title">"Requests to join"</string>
|
||||
<string name="screen_room_details_roles_and_permissions">"Roles and permissions"</string>
|
||||
<string name="screen_room_details_room_name_label">"Room name"</string>
|
||||
<string name="screen_room_details_security_title">"Security"</string>
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ class RoomDetailsViewTest {
|
|||
),
|
||||
onPinnedMessagesClick = callback,
|
||||
)
|
||||
rule.clickOn(CommonStrings.screen_room_details_pinned_events_row_title)
|
||||
rule.clickOn(R.string.screen_room_details_pinned_events_row_title)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -253,6 +253,21 @@ class RoomDetailsViewTest {
|
|||
rule.clickOn(R.string.screen_room_details_leave_room_title)
|
||||
eventsRecorder.assertSingle(RoomDetailsEvent.LeaveRoom)
|
||||
}
|
||||
|
||||
@Config(qualifiers = "h1024dp")
|
||||
@Test
|
||||
fun `click on knock requests invokes expected callback`() {
|
||||
ensureCalledOnce { callback ->
|
||||
rule.setRoomDetailView(
|
||||
state = aRoomDetailsState(
|
||||
eventSink = EventsRecorder(expectEvents = false),
|
||||
canShowKnockRequests = true,
|
||||
),
|
||||
onKnockRequestsClick = callback,
|
||||
)
|
||||
rule.clickOn(R.string.screen_room_details_requests_to_join_title)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomDetailView(
|
||||
|
|
@ -270,6 +285,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomD
|
|||
openAdminSettings: () -> Unit = EnsureNeverCalled(),
|
||||
onJoinCallClick: () -> Unit = EnsureNeverCalled(),
|
||||
onPinnedMessagesClick: () -> Unit = EnsureNeverCalled(),
|
||||
onKnockRequestsClick: () -> Unit = EnsureNeverCalled(),
|
||||
) {
|
||||
setContent {
|
||||
RoomDetailsView(
|
||||
|
|
@ -285,6 +301,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomD
|
|||
openAdminSettings = openAdminSettings,
|
||||
onJoinCallClick = onJoinCallClick,
|
||||
onPinnedMessagesClick = onPinnedMessagesClick,
|
||||
onKnockRequestsClick = onKnockRequestsClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue