Merge pull request #519 from vector-im/misc/cjs/create-join-design-feedback
Design tweaks for create/join rooms
This commit is contained in:
commit
c457d74954
183 changed files with 653 additions and 488 deletions
|
|
@ -16,15 +16,26 @@
|
|||
|
||||
package io.element.android.features.createroom.impl.components
|
||||
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.surfaceColorAtElevation
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.theme.components.Divider
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBar
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
|
|
@ -49,6 +60,8 @@ fun SearchUserBar(
|
|||
onUserSelected: (MatrixUser) -> Unit = {},
|
||||
onUserDeselected: (MatrixUser) -> Unit = {},
|
||||
) {
|
||||
val columnState = rememberLazyListState()
|
||||
|
||||
SearchBar(
|
||||
query = query,
|
||||
onQueryChange = onTextChanged,
|
||||
|
|
@ -59,19 +72,38 @@ fun SearchUserBar(
|
|||
showBackButton = showBackButton,
|
||||
contentPrefix = {
|
||||
if (isMultiSelectionEnabled && active && selectedUsers.isNotEmpty()) {
|
||||
// We want the selected users to behave a bit like a top bar - when the list below is scrolled, the colour
|
||||
// should change to indicate elevation.
|
||||
|
||||
val elevation = remember {
|
||||
derivedStateOf {
|
||||
if (columnState.canScrollBackward) {
|
||||
4.dp
|
||||
} else {
|
||||
0.dp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val appBarContainerColor by animateColorAsState(
|
||||
targetValue = MaterialTheme.colorScheme.surfaceColorAtElevation(elevation.value),
|
||||
animationSpec = spring(stiffness = Spring.StiffnessMediumLow)
|
||||
)
|
||||
|
||||
SelectedUsersList(
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
selectedUsers = selectedUsers,
|
||||
autoScroll = true,
|
||||
onUserRemoved = onUserDeselected,
|
||||
modifier = Modifier.background(appBarContainerColor)
|
||||
)
|
||||
}
|
||||
},
|
||||
resultState = state,
|
||||
resultHandler = { users ->
|
||||
LazyColumn {
|
||||
LazyColumn(state = columnState) {
|
||||
if (isMultiSelectionEnabled) {
|
||||
items(users) { searchResult ->
|
||||
itemsIndexed(users) { index, searchResult ->
|
||||
SearchMultipleUsersResultItem(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
searchResult = searchResult,
|
||||
|
|
@ -84,14 +116,20 @@ fun SearchUserBar(
|
|||
}
|
||||
}
|
||||
)
|
||||
if (index < users.lastIndex) {
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
items(users) { searchResult ->
|
||||
itemsIndexed(users) { index, searchResult ->
|
||||
SearchSingleUserResultItem(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
searchResult = searchResult,
|
||||
onClick = { onUserSelected(searchResult.matrixUser) }
|
||||
)
|
||||
if (index < users.lastIndex) {
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ fun ConfigureRoomView(
|
|||
)
|
||||
if (state.config.invites.isNotEmpty()) {
|
||||
SelectedUsersList(
|
||||
modifier = Modifier.padding(bottom = 16.dp),
|
||||
contentPadding = PaddingValues(horizontal = 24.dp),
|
||||
selectedUsers = state.config.invites,
|
||||
onUserRemoved = {
|
||||
|
|
@ -226,7 +227,7 @@ fun RoomNameWithAvatar(
|
|||
LabelledTextField(
|
||||
label = stringResource(R.string.screen_create_room_room_name_label),
|
||||
value = roomName,
|
||||
placeholder = stringResource(R.string.screen_create_room_room_name_placeholder),
|
||||
placeholder = stringResource(StringR.string.common_room_name_placeholder),
|
||||
singleLine = true,
|
||||
onValueChange = onRoomNameChanged,
|
||||
)
|
||||
|
|
@ -243,7 +244,7 @@ fun RoomTopic(
|
|||
modifier = modifier,
|
||||
label = stringResource(R.string.screen_create_room_topic_label),
|
||||
value = topic,
|
||||
placeholder = stringResource(R.string.screen_create_room_topic_placeholder),
|
||||
placeholder = stringResource(StringR.string.common_topic_placeholder),
|
||||
onValueChange = onTopicChanged,
|
||||
maxLines = 3,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -26,14 +26,15 @@ import androidx.compose.foundation.layout.consumeWindowInsets
|
|||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
|
@ -142,7 +143,11 @@ fun CreateRoomRootViewTopBar(
|
|||
},
|
||||
actions = {
|
||||
IconButton(onClick = onClosePressed) {
|
||||
Icon(imageVector = Icons.Default.Close, contentDescription = stringResource(id = StringR.string.action_close))
|
||||
Icon(
|
||||
imageVector = Icons.Default.Close,
|
||||
contentDescription = stringResource(id = StringR.string.action_close),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
@ -157,7 +162,7 @@ fun CreateRoomActionButtonsList(
|
|||
Column(modifier = modifier) {
|
||||
CreateRoomActionButton(
|
||||
iconRes = DrawableR.drawable.ic_groups,
|
||||
text = stringResource(id = StringR.string.action_create_a_room),
|
||||
text = stringResource(id = R.string.screen_create_room_action_create_room),
|
||||
onClick = onNewRoomClicked,
|
||||
)
|
||||
CreateRoomActionButton(
|
||||
|
|
@ -185,11 +190,16 @@ fun CreateRoomActionButton(
|
|||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.alpha(0.5f), // FIXME align on Design system theme (removing alpha should be fine)
|
||||
modifier = Modifier.size(24.dp),
|
||||
tint = MaterialTheme.colorScheme.secondary,
|
||||
resourceId = iconRes,
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(text = text)
|
||||
Text(
|
||||
text = text,
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Normal
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@
|
|||
<string name="screen_create_room_public_option_description">"Zprávy nejsou šifrované a může si je přečíst kdokoli. Šifrování můžete povolit později."</string>
|
||||
<string name="screen_create_room_public_option_title">"Veřejná místnost (kdokoli)"</string>
|
||||
<string name="screen_create_room_room_name_label">"Název místnosti"</string>
|
||||
<string name="screen_create_room_room_name_placeholder">"např. Produktový sprint"</string>
|
||||
<string name="screen_create_room_topic_label">"Téma (nepovinné)"</string>
|
||||
<string name="screen_create_room_topic_placeholder">"O čem je tato místnost?"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"Při pokusu o zahájení chatu došlo k chybě"</string>
|
||||
<string name="screen_create_room_title">"Vytvořit místnost"</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@
|
|||
<string name="screen_create_room_public_option_description">"Nachrichten sind nicht verschlüsselt und jeder kann sie lesen. Du kannst die Verschlüsselung zu einem späteren Zeitpunkt aktivieren."</string>
|
||||
<string name="screen_create_room_public_option_title">"Öffentlicher Raum (jeder)"</string>
|
||||
<string name="screen_create_room_room_name_label">"Raumname"</string>
|
||||
<string name="screen_create_room_room_name_placeholder">"z.B. Produkt-Sprint"</string>
|
||||
<string name="screen_create_room_topic_label">"Thema (optional)"</string>
|
||||
<string name="screen_create_room_topic_placeholder">"Worum geht es in diesem Raum?"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"Beim Versuch, einen Chat zu starten, ist ein Fehler aufgetreten"</string>
|
||||
<string name="screen_create_room_title">"Raum erstellen"</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@
|
|||
<string name="screen_create_room_public_option_description">"Les messages ne sont pas chiffrés et n\'importe qui peut les lire. Vous pouvez activer le chiffrement ultérieurement."</string>
|
||||
<string name="screen_create_room_public_option_title">"Salle publique (n’importe qui)"</string>
|
||||
<string name="screen_create_room_room_name_label">"Nom de la salle"</string>
|
||||
<string name="screen_create_room_room_name_placeholder">"Ex: Sprint Produit"</string>
|
||||
<string name="screen_create_room_topic_label">"Sujet (optionnel)"</string>
|
||||
<string name="screen_create_room_topic_placeholder">"De quoi parle cette salle ?"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"Une erreur s\'est produite lors de la tentative de démarrage d\'une discussion"</string>
|
||||
<string name="screen_create_room_title">"Créer une salle"</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@
|
|||
<string name="screen_create_room_public_option_description">"Mesajele nu sunt criptate și oricine le poate citi. Puteți activa criptarea la o dată ulterioară."</string>
|
||||
<string name="screen_create_room_public_option_title">"Cameră publică (oricine)"</string>
|
||||
<string name="screen_create_room_room_name_label">"Numele camerei"</string>
|
||||
<string name="screen_create_room_room_name_placeholder">"e.g. Mici și Cozonaci"</string>
|
||||
<string name="screen_create_room_topic_label">"Subiect (opțional)"</string>
|
||||
<string name="screen_create_room_topic_placeholder">"Despre ce este această cameră?"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"A apărut o eroare la încercarea începerii conversației"</string>
|
||||
<string name="screen_create_room_title">"Creați o cameră"</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@
|
|||
<string name="screen_create_room_public_option_description">"Messages are not encrypted and anyone can read them. You can enable encryption at a later date."</string>
|
||||
<string name="screen_create_room_public_option_title">"Public room (anyone)"</string>
|
||||
<string name="screen_create_room_room_name_label">"Room name"</string>
|
||||
<string name="screen_create_room_room_name_placeholder">"e.g. Product Sprint"</string>
|
||||
<string name="screen_create_room_topic_label">"Topic (optional)"</string>
|
||||
<string name="screen_create_room_topic_placeholder">"What is this room about?"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"An error occurred when trying to start a chat"</string>
|
||||
<string name="screen_create_room_title">"Create a room"</string>
|
||||
</resources>
|
||||
|
|
@ -24,7 +24,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -42,6 +42,7 @@ import io.element.android.libraries.designsystem.components.dialogs.Confirmation
|
|||
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Divider
|
||||
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
|
||||
|
|
@ -81,6 +82,9 @@ fun InviteListView(
|
|||
ConfirmationDialog(
|
||||
content = stringResource(contentResource, state.declineConfirmationDialog.name),
|
||||
title = stringResource(titleResource),
|
||||
submitText = stringResource(StringR.string.action_decline),
|
||||
cancelText = stringResource(StringR.string.action_cancel),
|
||||
emphasizeSubmitButton = true,
|
||||
onSubmitClicked = { state.eventSink(InviteListEvents.ConfirmDeclineInvite) },
|
||||
onDismiss = { state.eventSink(InviteListEvents.CancelDeclineInvite) }
|
||||
)
|
||||
|
|
@ -143,14 +147,18 @@ fun InviteListContent(
|
|||
LazyColumn(
|
||||
modifier = Modifier.weight(1f)
|
||||
) {
|
||||
items(
|
||||
itemsIndexed(
|
||||
items = state.inviteList,
|
||||
) { invite ->
|
||||
) { index, invite ->
|
||||
InviteSummaryRow(
|
||||
invite = invite,
|
||||
onAcceptClicked = { state.eventSink(InviteListEvents.AcceptInvite(invite)) },
|
||||
onDeclineClicked = { state.eventSink(InviteListEvents.DeclineInvite(invite)) },
|
||||
)
|
||||
|
||||
if (index != state.inviteList.lastIndex) {
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@
|
|||
package io.element.android.features.invitelist.impl.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
|
|
@ -31,23 +31,18 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.text.InlineTextContent
|
||||
import androidx.compose.foundation.text.appendInlineContent
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.Placeholder
|
||||
import androidx.compose.ui.text.PlaceholderVerticalAlign
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -64,8 +59,8 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
|||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedButton
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.noFontPadding
|
||||
import io.element.android.libraries.designsystem.theme.roomListUnreadIndicator
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
private val minHeight = 72.dp
|
||||
|
|
@ -104,23 +99,27 @@ internal fun DefaultInviteSummaryRow(
|
|||
verticalAlignment = Alignment.Top
|
||||
) {
|
||||
Avatar(
|
||||
invite.roomAvatarData,
|
||||
invite.roomAvatarData.copy(size = AvatarSize.Custom(52.dp)),
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(start = 12.dp, end = 4.dp)
|
||||
.padding(start = 16.dp, end = 4.dp)
|
||||
.alignByBaseline()
|
||||
.weight(1f)
|
||||
) {
|
||||
val bonusPadding = if (invite.isNew) 12.dp else 0.dp
|
||||
|
||||
// Name
|
||||
Text(
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
fontWeight = FontWeight.Medium,
|
||||
text = invite.roomName,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = noFontPadding,
|
||||
modifier = Modifier.padding(end = bonusPadding),
|
||||
)
|
||||
|
||||
// ID or Alias
|
||||
|
|
@ -131,7 +130,8 @@ internal fun DefaultInviteSummaryRow(
|
|||
text = it,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier.padding(end = bonusPadding),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -145,8 +145,8 @@ internal fun DefaultInviteSummaryRow(
|
|||
OutlinedButton(
|
||||
content = { Text(stringResource(StringR.string.action_decline), style = ElementTextStyles.Button) },
|
||||
onClick = onDeclineClicked,
|
||||
modifier = Modifier.weight(1f),
|
||||
contentPadding = PaddingValues(horizontal = 24.dp, vertical = 7.dp),
|
||||
modifier = Modifier.weight(1f).heightIn(max = 36.dp),
|
||||
contentPadding = PaddingValues(horizontal = 24.dp, vertical = 0.dp),
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
|
|
@ -154,8 +154,8 @@ internal fun DefaultInviteSummaryRow(
|
|||
Button(
|
||||
content = { Text(stringResource(StringR.string.action_accept), style = ElementTextStyles.Button) },
|
||||
onClick = onAcceptClicked,
|
||||
modifier = Modifier.weight(1f),
|
||||
contentPadding = PaddingValues(horizontal = 24.dp, vertical = 7.dp),
|
||||
modifier = Modifier.weight(1f).heightIn(max = 36.dp),
|
||||
contentPadding = PaddingValues(horizontal = 24.dp, vertical = 0.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -173,45 +173,36 @@ internal fun DefaultInviteSummaryRow(
|
|||
|
||||
@Composable
|
||||
private fun SenderRow(sender: InviteSender) {
|
||||
Text(
|
||||
text = buildAnnotatedString {
|
||||
val placeholder = "$"
|
||||
val text = stringResource(R.string.screen_invites_invited_you, placeholder)
|
||||
val nameIndex = text.indexOf(placeholder)
|
||||
|
||||
// Text before the placeholder
|
||||
append(text.take(nameIndex))
|
||||
|
||||
// Avatar and display name
|
||||
appendInlineContent("avatar")
|
||||
withStyle(SpanStyle(fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.primary)) {
|
||||
append(sender.displayName)
|
||||
}
|
||||
|
||||
// Text after the placeholder
|
||||
append(text.drop(nameIndex + placeholder.length))
|
||||
},
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
modifier = Modifier.padding(top = 6.dp),
|
||||
inlineContent = persistentMapOf(
|
||||
"avatar" to InlineTextContent(
|
||||
with(LocalDensity.current) {
|
||||
Placeholder(20.dp.toSp(), 20.dp.toSp(), PlaceholderVerticalAlign.Center)
|
||||
}
|
||||
) {
|
||||
Box(
|
||||
Modifier
|
||||
.fillMaxHeight()
|
||||
.padding(end = 4.dp)
|
||||
) {
|
||||
Avatar(
|
||||
avatarData = sender.avatarData.copy(size = AvatarSize.Custom(16.dp)),
|
||||
modifier = Modifier.align(Alignment.Center)
|
||||
)
|
||||
}
|
||||
}
|
||||
) {
|
||||
Avatar(
|
||||
avatarData = sender.avatarData.copy(size = AvatarSize.Custom(16.dp)),
|
||||
)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.screen_invites_invited_you, sender.displayName, sender.userId.value).let { text ->
|
||||
val senderNameStart = LocalContext.current.getString(R.string.screen_invites_invited_you).indexOf("%1\$s")
|
||||
AnnotatedString(
|
||||
text = text,
|
||||
spanStyles = listOf(
|
||||
AnnotatedString.Range(
|
||||
SpanStyle(
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
),
|
||||
start = senderNameStart,
|
||||
end = senderNameStart + sender.displayName.length
|
||||
)
|
||||
)
|
||||
)
|
||||
},
|
||||
style = noFontPadding,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Normal,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ open class InviteListInviteSummaryProvider : PreviewParameterProvider<InviteList
|
|||
override val values: Sequence<InviteListInviteSummary>
|
||||
get() = sequenceOf(
|
||||
aInviteListInviteSummary(),
|
||||
aInviteListInviteSummary().copy(roomAlias = "#someroom:example.com"),
|
||||
aInviteListInviteSummary().copy(roomAlias = "#someroom-with-a-long-alias:example.com"),
|
||||
aInviteListInviteSummary().copy(roomAlias = "#someroom-with-a-long-alias:example.com", isNew = true),
|
||||
aInviteListInviteSummary().copy(roomName = "Alice", sender = null),
|
||||
aInviteListInviteSummary().copy(isNew = true)
|
||||
)
|
||||
|
|
@ -32,9 +33,9 @@ open class InviteListInviteSummaryProvider : PreviewParameterProvider<InviteList
|
|||
|
||||
fun aInviteListInviteSummary() = InviteListInviteSummary(
|
||||
roomId = RoomId("!room1:example.com"),
|
||||
roomName = "Some room",
|
||||
roomName = "Some room with a long name that will truncate",
|
||||
sender = InviteSender(
|
||||
userId = UserId("@alice:example.org"),
|
||||
displayName = "Alice"
|
||||
userId = UserId("@alice-with-a-long-mxid:example.org"),
|
||||
displayName = "Alice with a long name"
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,5 +5,4 @@
|
|||
<string name="screen_invites_decline_direct_chat_message">"Möchten Sie den Chat mit %1$s wirklich ablehnen?"</string>
|
||||
<string name="screen_invites_decline_direct_chat_title">"Chat ablehnen"</string>
|
||||
<string name="screen_invites_empty_list">"Keine Einladungen"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s hat dich eingeladen"</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_invites_invited_you">"%1$s te invitó."</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_invites_empty_list">"Aucune invitation"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s vous a invité."</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_invites_invited_you">"%1$s ti ha invitato"</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -5,5 +5,4 @@
|
|||
<string name="screen_invites_decline_direct_chat_message">"Sigur doriți să refuzați conversațiile cu %1$s?"</string>
|
||||
<string name="screen_invites_decline_direct_chat_title">"Refuzați conversația"</string>
|
||||
<string name="screen_invites_empty_list">"Nicio invitație"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s v-a invitat"</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@
|
|||
<string name="screen_invites_decline_direct_chat_message">"Are you sure you want to decline to chat with %1$s?"</string>
|
||||
<string name="screen_invites_decline_direct_chat_title">"Decline chat"</string>
|
||||
<string name="screen_invites_empty_list">"No Invites"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s invited you"</string>
|
||||
</resources>
|
||||
<string name="screen_invites_invited_you">"%1$s (%2$s) invited you"</string>
|
||||
</resources>
|
||||
|
|
@ -26,7 +26,7 @@ open class RoomDetailsEditStateProvider : PreviewParameterProvider<RoomDetailsEd
|
|||
get() = sequenceOf(
|
||||
aRoomDetailsEditState(),
|
||||
aRoomDetailsEditState().copy(roomTopic = ""),
|
||||
aRoomDetailsEditState().copy(roomAvatarUrl = Uri.EMPTY),
|
||||
aRoomDetailsEditState().copy(roomAvatarUrl = Uri.parse("example://uri")),
|
||||
aRoomDetailsEditState().copy(canChangeName = true, canChangeTopic = false, canChangeAvatar = true, saveButtonEnabled = false),
|
||||
aRoomDetailsEditState().copy(canChangeName = false, canChangeTopic = true, canChangeAvatar = false, saveButtonEnabled = false),
|
||||
aRoomDetailsEditState().copy(saveAction = Async.Loading()),
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ fun RoomDetailsEditView(
|
|||
LabelledTextField(
|
||||
label = stringResource(id = R.string.screen_room_details_room_name_label),
|
||||
value = state.roomName,
|
||||
placeholder = stringResource(id = R.string.screen_room_details_room_name_placeholder),
|
||||
placeholder = stringResource(StringR.string.common_room_name_placeholder),
|
||||
singleLine = true,
|
||||
onValueChange = { state.eventSink(RoomDetailsEditEvents.UpdateRoomName(it)) },
|
||||
)
|
||||
|
|
@ -160,9 +160,9 @@ fun RoomDetailsEditView(
|
|||
|
||||
if (state.canChangeTopic) {
|
||||
LabelledTextField(
|
||||
label = stringResource(id = StringR.string.common_topic),
|
||||
label = stringResource(StringR.string.common_topic),
|
||||
value = state.roomTopic,
|
||||
placeholder = stringResource(id = R.string.screen_room_details_topic_placeholder),
|
||||
placeholder = stringResource(StringR.string.common_topic_placeholder),
|
||||
maxLines = 10,
|
||||
onValueChange = { state.eventSink(RoomDetailsEditEvents.UpdateRoomTopic(it)) },
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import androidx.compose.foundation.layout.consumeWindowInsets
|
|||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -40,6 +40,7 @@ import io.element.android.libraries.designsystem.components.button.BackButton
|
|||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.CenterAlignedTopAppBar
|
||||
import io.element.android.libraries.designsystem.theme.components.Divider
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBar
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
|
|
@ -181,7 +182,7 @@ private fun RoomInviteMembersSearchBar(
|
|||
)
|
||||
|
||||
LazyColumn {
|
||||
items(results) { invitableUser ->
|
||||
itemsIndexed(results) { index, invitableUser ->
|
||||
if (invitableUser.isUnresolved && !invitableUser.isAlreadyInvited && !invitableUser.isAlreadyJoined) {
|
||||
CheckableUnresolvedUserRow(
|
||||
checked = invitableUser.isSelected,
|
||||
|
|
@ -208,6 +209,10 @@ private fun RoomInviteMembersSearchBar(
|
|||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
|
||||
if (index < results.lastIndex) {
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ private fun LazyListScope.roomMemberListSection(
|
|||
Text(
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
text = headerText(),
|
||||
fontSize = 16.sp,
|
||||
style = ElementTextStyles.Regular.callout,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
textAlign = TextAlign.Start,
|
||||
|
|
|
|||
|
|
@ -12,10 +12,9 @@
|
|||
<string name="screen_room_details_edition_error_title">"Unable to update room"</string>
|
||||
<string name="screen_room_details_encryption_enabled_subtitle">"Messages are secured with locks. Only you and the recipients have the unique keys to unlock them."</string>
|
||||
<string name="screen_room_details_encryption_enabled_title">"Message encryption enabled"</string>
|
||||
<string name="screen_room_details_invite_people_title">"Invite people"</string>
|
||||
<string name="screen_room_details_room_name_label">"Room name"</string>
|
||||
<string name="screen_room_details_room_name_placeholder">"e.g. Product Sprint"</string>
|
||||
<string name="screen_room_details_share_room_title">"Share room"</string>
|
||||
<string name="screen_room_details_topic_placeholder">"What is this room about?"</string>
|
||||
<string name="screen_room_details_updating_room">"Updating room…"</string>
|
||||
<string name="screen_room_member_list_pending_header_title">"Pending"</string>
|
||||
<string name="screen_room_member_list_room_members_header_title">"Room members"</string>
|
||||
|
|
@ -25,7 +24,6 @@
|
|||
<string name="screen_dm_details_unblock_alert_action">"Unblock"</string>
|
||||
<string name="screen_dm_details_unblock_alert_description">"On unblocking the user, you will be able to see all messages by them again."</string>
|
||||
<string name="screen_dm_details_unblock_user">"Unblock user"</string>
|
||||
<string name="screen_room_details_invite_people_title">"Invite friends to Element"</string>
|
||||
<string name="screen_room_details_leave_room_title">"Leave room"</string>
|
||||
<string name="screen_room_details_people_title">"People"</string>
|
||||
<string name="screen_room_details_security_title">"Security"</string>
|
||||
|
|
|
|||
|
|
@ -29,10 +29,12 @@ import androidx.compose.foundation.layout.consumeWindowInsets
|
|||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
|
|
@ -51,16 +53,19 @@ import androidx.compose.runtime.derivedStateOf
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.Velocity
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.features.leaveroom.api.LeaveRoomView
|
||||
import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorView
|
||||
import io.element.android.features.roomlist.impl.components.RoomListTopBar
|
||||
|
|
@ -72,12 +77,13 @@ 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.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.Divider
|
||||
import io.element.android.libraries.designsystem.theme.components.FloatingActionButton
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.Surface
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextButton
|
||||
import io.element.android.libraries.designsystem.theme.noFontPadding
|
||||
import io.element.android.libraries.designsystem.theme.roomListUnreadIndicator
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
|
@ -230,37 +236,48 @@ fun RoomListContent(
|
|||
|
||||
if (state.invitesState != InvitesState.NoInvites) {
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.End, modifier = Modifier.fillMaxSize()) {
|
||||
TextButton(
|
||||
content = {
|
||||
Text(stringResource(StringR.string.action_invites_list))
|
||||
|
||||
if (state.invitesState == InvitesState.NewInvites) {
|
||||
Spacer(Modifier.size(8.dp))
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(12.dp)
|
||||
.clip(CircleShape)
|
||||
.background(MaterialTheme.roomListUnreadIndicator())
|
||||
)
|
||||
}
|
||||
},
|
||||
onClick = onInvitesClicked,
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.End,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.clickable(role = Role.Button, onClick = onInvitesClicked)
|
||||
.heightIn(min = 48.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(StringR.string.action_invites_list),
|
||||
fontSize = 14.sp,
|
||||
style = noFontPadding,
|
||||
)
|
||||
|
||||
if (state.invitesState == InvitesState.NewInvites) {
|
||||
Spacer(Modifier.width(8.dp))
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(12.dp)
|
||||
.clip(CircleShape)
|
||||
.background(MaterialTheme.roomListUnreadIndicator())
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(Modifier.width(16.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
items(
|
||||
itemsIndexed(
|
||||
items = state.roomList,
|
||||
contentType = { room -> room.contentType() },
|
||||
) { room ->
|
||||
contentType = { _, room -> room.contentType() },
|
||||
) { index, room ->
|
||||
RoomSummaryRow(
|
||||
room = room,
|
||||
onClick = ::onRoomClicked,
|
||||
onLongClick = onRoomLongClicked,
|
||||
)
|
||||
if (index != state.roomList.lastIndex) {
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue