Design fixes for room detail, dm & room member detail screens (#363)

* Design fixes for room detail, dm & room member detail screens.

* Record new screenshots, improve RoomDetailsStateProvider.

* Move MainActionButton to its own component in the design system.
This commit is contained in:
Jorge Martin Espinosa 2023-05-02 16:02:51 +02:00 committed by GitHub
parent ca6a47edcd
commit d4c311545d
33 changed files with 198 additions and 87 deletions

View file

@ -70,7 +70,6 @@ class MessagesPresenter @Inject constructor(
}
val networkConnectionStatus by networkMonitor.connectivity.collectAsState(initial = networkMonitor.currentConnectivityStatus)
println(networkConnectionStatus)
LaunchedEffect(syncUpdateFlow) {
roomAvatar.value =

View file

@ -17,6 +17,7 @@
package io.element.android.features.roomdetails.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.roomdetails.impl.members.details.aRoomMemberDetailsState
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.RoomMember
@ -30,8 +31,8 @@ open class RoomDetailsStateProvider : PreviewParameterProvider<RoomDetailsState>
aRoomDetailsState().copy(isEncrypted = false),
aRoomDetailsState().copy(roomAlias = null),
aRoomDetailsState().copy(memberCount = Async.Failure(Throwable())),
aRoomDetailsState().copy(roomType = RoomDetailsType.Dm(aDmRoomMember()), roomName = "Daniel"),
aRoomDetailsState().copy(roomType = RoomDetailsType.Dm(aDmRoomMember(isIgnored = true)), roomName = "Daniel"),
aDmRoomDetailsState().copy(roomName = "Daniel"),
aDmRoomDetailsState(isDmMemberIgnored = true).copy(roomName = "Daniel"),
// Add other state here
)
}
@ -74,3 +75,7 @@ fun aRoomDetailsState() = RoomDetailsState(
roomMemberDetailsState = null,
eventSink = {}
)
fun aDmRoomDetailsState(isDmMemberIgnored: Boolean = false) = aRoomDetailsState().copy(
roomType = RoomDetailsType.Dm(aDmRoomMember(isIgnored = isDmMemberIgnored)), roomMemberDetailsState = aRoomMemberDetailsState()
)

View file

@ -16,8 +16,10 @@
package io.element.android.features.roomdetails.impl
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@ -45,7 +47,7 @@ import androidx.compose.ui.unit.dp
import io.element.android.features.roomdetails.blockuser.BlockUserDialogs
import io.element.android.features.roomdetails.blockuser.BlockUserSection
import io.element.android.features.roomdetails.impl.members.details.RoomMemberHeaderSection
import io.element.android.features.roomdetails.impl.members.details.RoomMemberShareSection
import io.element.android.features.roomdetails.impl.members.details.RoomMemberMainActionsSection
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.architecture.isLoading
import io.element.android.libraries.designsystem.ElementTextStyles
@ -60,6 +62,7 @@ import io.element.android.libraries.designsystem.components.preferences.Preferen
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.LocalColors
import io.element.android.libraries.designsystem.components.button.MainActionButton
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
@ -99,7 +102,7 @@ fun RoomDetailsView(
roomName = state.roomName,
roomAlias = state.roomAlias
)
RoomShareSection(onShareRoom = onShareRoom)
MainActionsSection(onShareRoom = onShareRoom)
}
is RoomDetailsType.Dm -> {
val member = state.roomType.roomMember
@ -108,9 +111,10 @@ fun RoomDetailsView(
userId = member.userId.value,
userName = state.roomName
)
RoomMemberShareSection(onShareUser = ::onShareMember)
RoomMemberMainActionsSection(onShareUser = ::onShareMember)
}
}
Spacer(Modifier.height(26.dp))
if (state.roomTopic != null) {
TopicSection(roomTopic = state.roomTopic)
@ -129,21 +133,16 @@ fun RoomDetailsView(
SecuritySection()
}
when (state.roomType) {
RoomDetailsType.Room -> {
OtherActionsSection(onLeaveRoom = {
state.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = true))
})
}
is RoomDetailsType.Dm -> {
if (state.roomMemberDetailsState != null) {
val roomMemberState = state.roomMemberDetailsState
BlockUserSection(roomMemberState)
BlockUserDialogs(roomMemberState)
}
}
if (state.roomType is RoomDetailsType.Dm && state.roomMemberDetailsState != null) {
val roomMemberState = state.roomMemberDetailsState
BlockUserSection(roomMemberState)
BlockUserDialogs(roomMemberState)
}
OtherActionsSection(onLeaveRoom = {
state.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = true))
})
if (state.displayLeaveRoomWarning != null) {
ConfirmLeaveRoomDialog(
leaveRoomWarning = state.displayLeaveRoomWarning,
@ -163,13 +162,9 @@ fun RoomDetailsView(
}
@Composable
internal fun RoomShareSection(onShareRoom: () -> Unit, modifier: Modifier = Modifier) {
PreferenceCategory(modifier = modifier) {
PreferenceText(
title = stringResource(R.string.screen_room_details_share_room_title),
icon = Icons.Outlined.Share,
onClick = onShareRoom,
)
internal fun MainActionsSection(onShareRoom: () -> Unit, modifier: Modifier = Modifier) {
Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
MainActionButton(title = stringResource(R.string.screen_room_details_share_room_title), icon = Icons.Outlined.Share, onClick = onShareRoom)
}
}

View file

@ -16,8 +16,10 @@
package io.element.android.features.roomdetails.impl.members.details
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@ -27,7 +29,6 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Block
import androidx.compose.material.icons.outlined.ChatBubbleOutline
import androidx.compose.material.icons.outlined.Share
import androidx.compose.material3.ExperimentalMaterial3Api
@ -41,18 +42,16 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.features.roomdetails.blockuser.BlockUserDialogs
import io.element.android.features.roomdetails.blockuser.BlockUserSection
import io.element.android.features.roomdetails.impl.R
import io.element.android.libraries.designsystem.ElementTextStyles
import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.LocalColors
import io.element.android.libraries.designsystem.components.button.MainActionButton
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
@ -83,7 +82,9 @@ fun RoomMemberDetailsView(
userName = state.userName,
)
RoomMemberShareSection(onShareUser = onShareUser)
RoomMemberMainActionsSection(onShareUser = onShareUser)
Spacer(modifier = Modifier.height(26.dp))
SendMessageSection(onSendMessage = {
// TODO implement send DM
@ -117,18 +118,14 @@ internal fun RoomMemberHeaderSection(
Spacer(modifier = Modifier.height(6.dp))
}
Text(userId, style = ElementTextStyles.Regular.body, color = MaterialTheme.colorScheme.secondary)
Spacer(Modifier.height(32.dp))
Spacer(Modifier.height(40.dp))
}
}
@Composable
internal fun RoomMemberShareSection(onShareUser: () -> Unit, modifier: Modifier = Modifier) {
PreferenceCategory(modifier = modifier) {
PreferenceText(
title = stringResource(StringR.string.action_share),
icon = Icons.Outlined.Share,
onClick = onShareUser,
)
internal fun RoomMemberMainActionsSection(onShareUser: () -> Unit, modifier: Modifier = Modifier) {
Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
MainActionButton(title = stringResource(StringR.string.action_share), icon = Icons.Outlined.Share, onClick = onShareUser)
}
}

View file

@ -0,0 +1,103 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.designsystem.components.button
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Share
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.ElementTextStyles
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text
@Composable
fun MainActionButton(
title: String,
icon: ImageVector,
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
contentDescription: String = title,
) {
val ripple = rememberRipple(bounded = false)
val interactionSource = MutableInteractionSource()
Column(
modifier.clickable(
enabled = enabled,
interactionSource = interactionSource,
onClick = onClick,
indication = ripple
),
horizontalAlignment = Alignment.CenterHorizontally,
) {
val tintColor = if (enabled) LocalContentColor.current else MaterialTheme.colorScheme.secondary
Icon(
icon,
contentDescription = contentDescription,
tint = tintColor,
)
Spacer(modifier = Modifier.height(14.dp))
Text(
title,
style = ElementTextStyles.Regular.bodyMD.copy(fontWeight = FontWeight.Medium),
color = tintColor,
)
}
}
@Preview
@Composable
internal fun MainActionButtonLightPreview() {
ElementPreviewLight {
ContentsToPreview()
}
}
@Preview
@Composable
internal fun MainActionButtonDarkPreview() {
ElementPreviewDark {
ContentsToPreview()
}
}
@Composable
private fun ContentsToPreview() {
Row(Modifier.padding(10.dp)) {
MainActionButton(title = "Share", icon = Icons.Outlined.Share, onClick = { })
Spacer(modifier = Modifier.width(20.dp))
MainActionButton(title = "Share", icon = Icons.Outlined.Share, onClick = { }, enabled = false)
}
}

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d8c78efed997712873719636ff1f8479d38d317e443c5d4340346d4328de9c0d
size 28744
oid sha256:dff0e2357ef0b08f415859b25470fed31dd80c5578e8fbe483ab8650d8f9aadb
size 28803

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f237e773fa1a627776786a1484eae790cf1b7401ef45aa8025471dc5e980f99f
size 26223
oid sha256:a895c48d5fcff6bf605f4c7518468b42390130843c096a135c185d368c1b01ef
size 26246

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e52089ad9c1703034e8f4550479322c8d08a2353bdf8472c69091ed4c3ed32b6
size 29677
oid sha256:2bab9b94040850e9a0b9a15332e5e088f95b6a77ef31b6b08dc40d5f8e94ae7d
size 29679

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d8c78efed997712873719636ff1f8479d38d317e443c5d4340346d4328de9c0d
size 28744
oid sha256:dff0e2357ef0b08f415859b25470fed31dd80c5578e8fbe483ab8650d8f9aadb
size 28803

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d8c78efed997712873719636ff1f8479d38d317e443c5d4340346d4328de9c0d
size 28744
oid sha256:dff0e2357ef0b08f415859b25470fed31dd80c5578e8fbe483ab8650d8f9aadb
size 28803

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2f62537b4aa79f501908d1fff9d269139e88db5f6dbaedcf63670a4f71b47bff
size 28303
oid sha256:66d548cfe055f06ba42adabd08f31a54097d6c61decf4f2ddd8f4bd142d60f07
size 28208

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bb5cf00996e3c43f6c3a20f37c8e83fd4445ffe7e03f8cded23edf89f7f01856
size 25716
oid sha256:ca695e57d1ca585652544576a80cbb027e212842d727c83bf5e39adac599389e
size 25663

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6754266a962dc5692cc89201c0feef7dfabc68fad000ccdf1196b7b0274c4917
size 28771
oid sha256:821c488d20c689230903245d64eb5740272ce6d568787f78bcd7e8875da371f7
size 28743

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2f62537b4aa79f501908d1fff9d269139e88db5f6dbaedcf63670a4f71b47bff
size 28303
oid sha256:66d548cfe055f06ba42adabd08f31a54097d6c61decf4f2ddd8f4bd142d60f07
size 28208

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2f62537b4aa79f501908d1fff9d269139e88db5f6dbaedcf63670a4f71b47bff
size 28303
oid sha256:66d548cfe055f06ba42adabd08f31a54097d6c61decf4f2ddd8f4bd142d60f07
size 28208

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:98b3a3f4f688e338ef551a62a7ff274be52df49f2073c2db61abe3ce204bd1b4
size 73278
oid sha256:7a3b23895b133b7bba7300fbf31fd70daa83f558e29e8c09dfc7789ce0bc04d6
size 61861

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9be790757cab81d0486c09ef13e356778b909b4c4779db096e99720133568dc4
size 55722
oid sha256:2ec1e7b0d875b40ed29c4b7154897dfcae671995be4e53c41d04e2aa8526baef
size 55474

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:13530e652603ff4a7f8a9ea7675dfef777aa7a24649066e2f3c8813dd75a5b9a
size 55680
oid sha256:9a9a2c829d91a75e157694bfbfc5e93d20cc9c7d41f2c9d015c2a926585f42b8
size 55509

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c067ef1c3905a0111dea3ebede4c990b2c3952b48284229fa6c0bd98e0767890
size 69571
oid sha256:41206b3d92a2ac7999116e8b720497d4d7ffea49f970fcf1c682ebefafbc7442
size 68873

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e79967506d4722d756d65e9db042671c8af3dda186a8db6c1b470c891435f86a
size 72759
oid sha256:330d9b83aefb14bb040c5e9908ec92a6860e1d3875eca3597a2f375574806d4b
size 61313

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a8a9186d741d251dc8bdf6bcf71d395e8c057c310585aeb8911609eaaacce842
size 64550
oid sha256:d3a1afc10771257294d9f22d26ed8a81d04cd4b1f31d9fb9fc1065a8216230a9
size 67658

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a8a9186d741d251dc8bdf6bcf71d395e8c057c310585aeb8911609eaaacce842
size 64550
oid sha256:d3a1afc10771257294d9f22d26ed8a81d04cd4b1f31d9fb9fc1065a8216230a9
size 67658

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0dd97b2c66da4f2a539a13d185a3116754dedc1617b0fffcb01d71c81b071fe3
size 67084
oid sha256:e403d076b9d28e7fd06493399d4b7c405d99f329fb1a298c41fb445a1e9ec466
size 57215

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a8ecd0f0f1d27e63d772f7e4b976d613b887887dd765b92599ddb66898d6fb4e
size 52730
oid sha256:c4645d0aa7b30029d9c6fcc670e12a2e0c39380cdb86a1205d998622e11571e4
size 52410

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ef9243323fdcddd884a634d2c611987527ec1c8a2e8c7fac89adec5a4d2c2791
size 51814
oid sha256:80252c527c91e15e405e06805cfc85d7109c788555a0f15aaefed659156f547b
size 51289

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4993533f1ca5bd0ac4c6afddd672fd3a54085b0dd84dceb78b5c8766603e5755
size 64003
oid sha256:262fa3d35ac62ec46df5e0438182471ae3e4b93979ed3164530f68c2d9171eec
size 63182

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:10bb54d9ec1d433c1b45091c73d9415b6843d7d39dfcba044ca5f8057d0002d6
size 66485
oid sha256:4ad7fa57cdc744700cfc385c1d0eaf8effdaa32427e9bf59eff363e34c6e3215
size 56670

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:94a589b556a750485fd61af6446457c98c5f112d0d013cd78016b88a8829e6a8
size 58643
oid sha256:cb8dc0ca3fa34ffa40ea43934ee00d0c48c9b7ce721274763c093eee83d8cff9
size 62187

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:94a589b556a750485fd61af6446457c98c5f112d0d013cd78016b88a8829e6a8
size 58643
oid sha256:cb8dc0ca3fa34ffa40ea43934ee00d0c48c9b7ce721274763c093eee83d8cff9
size 62187

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e0e874e4125a6d1fc151a124d8fa17277b6d23341d6af0b952974ef4f245e460
size 9380

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6bb805e95f324ffbc81cee4f8a0797bd6dca17e8031abc9c51e9fafc03a5d3df
size 8929

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e0e874e4125a6d1fc151a124d8fa17277b6d23341d6af0b952974ef4f245e460
size 9380

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6bb805e95f324ffbc81cee4f8a0797bd6dca17e8031abc9c51e9fafc03a5d3df
size 8929