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
93456e8d44
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package io.element.android.libraries.designsystem
|
||||
|
||||
import androidx.compose.ui.text.PlatformTextStyle
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
|
|
@ -25,12 +26,14 @@ import androidx.compose.ui.unit.sp
|
|||
// TODO Remove
|
||||
object ElementTextStyles {
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
val Button = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontWeight = FontWeight.Medium,
|
||||
lineHeight = 22.sp,
|
||||
fontStyle = FontStyle.Normal,
|
||||
textAlign = TextAlign.Center,
|
||||
platformStyle = PlatformTextStyle(includeFontPadding = false)
|
||||
)
|
||||
|
||||
object Bold {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ package io.element.android.libraries.designsystem.components
|
|||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
|
|
@ -46,29 +47,10 @@ fun ProgressDialog(
|
|||
onDismissRequest = onDismiss,
|
||||
properties = DialogProperties(dismissOnBackPress = false, dismissOnClickOutside = false)
|
||||
) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
shape = RoundedCornerShape(8.dp)
|
||||
)
|
||||
) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
if (!text.isNullOrBlank()) {
|
||||
Text(
|
||||
text = text,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.padding(16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
ProgressDialogContent(
|
||||
modifier = modifier,
|
||||
text = text,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,22 +62,23 @@ private fun ProgressDialogContent(
|
|||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
shape = RoundedCornerShape(8.dp)
|
||||
)
|
||||
) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.padding(top = 38.dp, bottom = 32.dp, start = 40.dp, end = 40.dp)
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
if (!text.isNullOrBlank()) {
|
||||
Spacer(modifier = Modifier.height(22.dp))
|
||||
Text(
|
||||
text = text,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.padding(16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ fun Avatar(
|
|||
val commonModifier = modifier
|
||||
.size(avatarData.size.dp)
|
||||
.clip(CircleShape)
|
||||
if (avatarData.url == null) {
|
||||
if (avatarData.url.isNullOrBlank()) {
|
||||
InitialsAvatar(
|
||||
avatarData = avatarData,
|
||||
modifier = commonModifier,
|
||||
|
|
@ -72,7 +72,7 @@ private fun ImageAvatar(
|
|||
AsyncImage(
|
||||
model = avatarData,
|
||||
onError = {
|
||||
Timber.e("TAG", "Error $it\n${it.result}", it.result.throwable)
|
||||
Timber.e(it.result.throwable, "Error loading avatar $it\n${it.result}")
|
||||
},
|
||||
contentDescription = contentDescription,
|
||||
contentScale = ContentScale.Crop,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package io.element.android.libraries.designsystem.theme
|
||||
|
||||
import androidx.compose.ui.text.PlatformTextStyle
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
|
|
@ -107,3 +108,13 @@ val titleMediumDefault: TextStyle = TextStyle(
|
|||
letterSpacing = 0.5.sp
|
||||
)
|
||||
|
||||
// Temporary style for text that needs to be aligned without weird font padding issues. `includeFontPadding` will default to false in a future version of
|
||||
// compose, at which point this can be removed.
|
||||
//
|
||||
// Ref: https://medium.com/androiddevelopers/fixing-font-padding-in-compose-text-768cd232425b
|
||||
@Suppress("DEPRECATION")
|
||||
val noFontPadding: TextStyle = TextStyle(
|
||||
platformStyle = PlatformTextStyle(
|
||||
includeFontPadding = false
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import androidx.compose.foundation.lazy.items
|
|||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.ModalBottomSheetState
|
||||
import androidx.compose.material.ModalBottomSheetValue
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -35,10 +34,12 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.sp
|
||||
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.ModalBottomSheetLayout
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.matrix.ui.media.AvatarAction
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
@ -62,6 +63,7 @@ fun AvatarActionBottomSheet(
|
|||
ModalBottomSheetLayout(
|
||||
modifier = modifier,
|
||||
sheetState = modalBottomSheetState,
|
||||
displayHandle = true,
|
||||
sheetContent = {
|
||||
AvatarActionBottomSheetContent(
|
||||
actions = actions,
|
||||
|
|
@ -91,6 +93,7 @@ private fun AvatarActionBottomSheetContent(
|
|||
headlineContent = {
|
||||
Text(
|
||||
text = stringResource(action.titleResId),
|
||||
fontSize = 16.sp,
|
||||
color = if (action.destructive) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
},
|
||||
|
|
@ -98,7 +101,7 @@ private fun AvatarActionBottomSheetContent(
|
|||
Icon(
|
||||
imageVector = action.icon,
|
||||
contentDescription = stringResource(action.titleResId),
|
||||
tint = if (action.destructive) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary,
|
||||
tint = if (action.destructive) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.secondary,
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,12 +20,14 @@ import androidx.compose.foundation.clickable
|
|||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
|
|
@ -79,8 +81,10 @@ fun CheckableUserRow(
|
|||
)
|
||||
|
||||
Checkbox(
|
||||
modifier = Modifier
|
||||
.padding(end = 16.dp),
|
||||
checked = checked,
|
||||
onCheckedChange = onCheckedChange,
|
||||
onCheckedChange = null,
|
||||
enabled = enabled,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,11 @@
|
|||
|
||||
package io.element.android.libraries.matrix.ui.components
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
|
|
@ -38,6 +40,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
|||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.noFontPadding
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
||||
import io.element.android.libraries.matrix.ui.model.getBestName
|
||||
|
|
@ -46,7 +49,7 @@ import io.element.android.libraries.matrix.ui.model.getBestName
|
|||
fun MatrixUserRow(
|
||||
matrixUser: MatrixUser,
|
||||
modifier: Modifier = Modifier,
|
||||
avatarSize: AvatarSize = AvatarSize.MEDIUM,
|
||||
avatarSize: AvatarSize = AvatarSize.Custom(36.dp),
|
||||
) = UserRow(
|
||||
avatarData = matrixUser.getAvatarData(avatarSize),
|
||||
name = matrixUser.getBestName(),
|
||||
|
|
@ -71,25 +74,29 @@ fun UserRow(
|
|||
Avatar(avatarData)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(start = 12.dp),
|
||||
.padding(start = 12.dp)
|
||||
.fillMaxHeight(),
|
||||
verticalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
// Name
|
||||
Text(
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
fontWeight = FontWeight.Normal,
|
||||
text = name,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
style = noFontPadding,
|
||||
)
|
||||
// Id
|
||||
subtext?.let {
|
||||
Text(
|
||||
text = subtext,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
fontSize = 14.sp,
|
||||
fontSize = 12.sp,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = noFontPadding,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,16 +16,20 @@
|
|||
|
||||
package io.element.android.libraries.matrix.ui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
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.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
|
|
@ -38,7 +42,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
|||
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.IconButton
|
||||
import io.element.android.libraries.designsystem.theme.components.Surface
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
||||
|
|
@ -51,7 +55,9 @@ fun SelectedUser(
|
|||
modifier: Modifier = Modifier,
|
||||
onUserRemoved: (MatrixUser) -> Unit = {},
|
||||
) {
|
||||
Box(modifier = modifier.width(56.dp)) {
|
||||
Box(modifier = modifier
|
||||
.width(56.dp)
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
|
|
@ -63,18 +69,23 @@ fun SelectedUser(
|
|||
style = MaterialTheme.typography.bodyLarge,
|
||||
)
|
||||
}
|
||||
IconButton(
|
||||
Surface(
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.background(MaterialTheme.colorScheme.primary)
|
||||
.size(20.dp)
|
||||
.align(Alignment.TopEnd),
|
||||
onClick = { onUserRemoved(matrixUser) }
|
||||
.align(Alignment.TopEnd)
|
||||
.clickable(
|
||||
indication = rememberRipple(),
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
onClick = { onUserRemoved(matrixUser) }
|
||||
),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Close,
|
||||
contentDescription = stringResource(id = StringR.string.action_remove),
|
||||
tint = MaterialTheme.colorScheme.onPrimary,
|
||||
modifier = Modifier.padding(2.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,18 +16,27 @@
|
|||
|
||||
package io.element.android.libraries.matrix.ui.components
|
||||
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.Layout
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
|
|
@ -35,6 +44,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
|||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlin.math.floor
|
||||
|
||||
@Composable
|
||||
fun SelectedUsersList(
|
||||
|
|
@ -56,16 +66,64 @@ fun SelectedUsersList(
|
|||
}
|
||||
}
|
||||
|
||||
val rowWidth by remember {
|
||||
derivedStateOf {
|
||||
lazyListState.layoutInfo.viewportSize.width - lazyListState.layoutInfo.beforeContentPadding
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate spacing to show between each user. This is at least [minimumSpacing], and will grow to ensure that if the available space is filled with
|
||||
// users, the last visible user will be precisely half visible. This gives an obvious affordance that there are more entries and the list can be scrolled.
|
||||
// For efficiency, we assume that all the children are the same width. If they needed to be different sizes we'd have to do this calculation each time
|
||||
// they needed to be measured.
|
||||
val minimumSpacing = with(LocalDensity.current) { 24.dp.toPx() }
|
||||
val userWidth = with(LocalDensity.current) { 56.dp.toPx() }
|
||||
val userSpacing by remember {
|
||||
derivedStateOf {
|
||||
if (rowWidth == 0) {
|
||||
// The row hasn't yet been measured yet, so we don't know how big it is
|
||||
minimumSpacing
|
||||
} else {
|
||||
val userWidthWithSpacing = userWidth + minimumSpacing
|
||||
val maxVisibleUsers = rowWidth / userWidthWithSpacing
|
||||
|
||||
// Round down the number of visible users to end with a state where one is half visible
|
||||
val targetFraction = (userWidth / 2) / userWidthWithSpacing
|
||||
val targetUsers = floor(maxVisibleUsers - targetFraction) + targetFraction
|
||||
|
||||
// Work out how much extra spacing we need to reduce the number of users that much, then split it evenly amongst the visible users
|
||||
val extraSpacing = (maxVisibleUsers - targetUsers) * userWidthWithSpacing
|
||||
val extraSpacingPerUser = extraSpacing / floor(targetUsers)
|
||||
|
||||
minimumSpacing + extraSpacingPerUser
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyRow(
|
||||
state = lazyListState,
|
||||
modifier = modifier,
|
||||
modifier = modifier
|
||||
.fillMaxWidth(),
|
||||
contentPadding = contentPadding,
|
||||
horizontalArrangement = Arrangement.spacedBy(24.dp),
|
||||
) {
|
||||
items(selectedUsers.toList()) { matrixUser ->
|
||||
SelectedUser(
|
||||
matrixUser = matrixUser,
|
||||
onUserRemoved = onUserRemoved,
|
||||
itemsIndexed(selectedUsers.toList()) { index, matrixUser ->
|
||||
Layout(
|
||||
content = {
|
||||
SelectedUser(
|
||||
matrixUser = matrixUser,
|
||||
onUserRemoved = onUserRemoved,
|
||||
)
|
||||
},
|
||||
measurePolicy = { measurables, constraints ->
|
||||
val placeable = measurables.first().measure(constraints)
|
||||
val spacing = if (index == selectedUsers.lastIndex) 0f else userSpacing
|
||||
layout(
|
||||
width = (placeable.width + spacing).toInt(),
|
||||
height = placeable.height
|
||||
) {
|
||||
placeable.place(0, 0)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -81,7 +139,23 @@ internal fun SelectedUsersListDarkPreview() = ElementPreviewDark { ContentToPrev
|
|||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
SelectedUsersList(
|
||||
selectedUsers = aMatrixUserList().take(6).toImmutableList(),
|
||||
)
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
// Two users that will be visible with no scrolling
|
||||
SelectedUsersList(
|
||||
selectedUsers = aMatrixUserList().take(2).toImmutableList(),
|
||||
modifier = Modifier
|
||||
.width(200.dp)
|
||||
.border(1.dp, Color.Red)
|
||||
)
|
||||
|
||||
// Multiple users that don't fit, so will be spaced out per the measure policy
|
||||
for (i in 0..5) {
|
||||
SelectedUsersList(
|
||||
selectedUsers = aMatrixUserList().take(6).toImmutableList(),
|
||||
modifier = Modifier
|
||||
.width((200 + (i * 20)).dp)
|
||||
.border(1.dp, Color.Red)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,11 @@
|
|||
package io.element.android.libraries.matrix.ui.components
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
|
|
@ -39,10 +41,12 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.compose.ui.unit.sp
|
||||
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.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.theme.components.Checkbox
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.noFontPadding
|
||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
||||
import io.element.android.libraries.ui.strings.R
|
||||
|
||||
|
|
@ -62,7 +66,9 @@ fun UnresolvedUserRow(
|
|||
Avatar(avatarData)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(start = 12.dp),
|
||||
.padding(start = 12.dp)
|
||||
.fillMaxHeight(),
|
||||
verticalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
// ID
|
||||
Text(
|
||||
|
|
@ -72,10 +78,11 @@ fun UnresolvedUserRow(
|
|||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
style = noFontPadding,
|
||||
)
|
||||
|
||||
// Warning
|
||||
Row(modifier = Modifier.fillMaxWidth()) {
|
||||
Row(modifier = Modifier.fillMaxWidth().padding(top = 3.dp)) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Error,
|
||||
contentDescription = "",
|
||||
|
|
@ -121,8 +128,9 @@ fun CheckableUnresolvedUserRow(
|
|||
)
|
||||
|
||||
Checkbox(
|
||||
modifier = Modifier.padding(end = 16.dp),
|
||||
checked = checked,
|
||||
onCheckedChange = onCheckedChange,
|
||||
onCheckedChange = null,
|
||||
enabled = enabled,
|
||||
)
|
||||
}
|
||||
|
|
@ -142,9 +150,9 @@ internal fun CheckableUnresolvedUserRowPreview() =
|
|||
ElementThemedPreview {
|
||||
val matrixUser = aMatrixUser()
|
||||
Column {
|
||||
CheckableUnresolvedUserRow(false, matrixUser.getAvatarData(), matrixUser.userId.value)
|
||||
CheckableUnresolvedUserRow(true, matrixUser.getAvatarData(), matrixUser.userId.value)
|
||||
CheckableUnresolvedUserRow(false, matrixUser.getAvatarData(), matrixUser.userId.value, enabled = false)
|
||||
CheckableUnresolvedUserRow(true, matrixUser.getAvatarData(), matrixUser.userId.value, enabled = false)
|
||||
CheckableUnresolvedUserRow(false, matrixUser.getAvatarData(AvatarSize.Custom(36.dp)), matrixUser.userId.value)
|
||||
CheckableUnresolvedUserRow(true, matrixUser.getAvatarData(AvatarSize.Custom(36.dp)), matrixUser.userId.value)
|
||||
CheckableUnresolvedUserRow(false, matrixUser.getAvatarData(AvatarSize.Custom(36.dp)), matrixUser.userId.value, enabled = false)
|
||||
CheckableUnresolvedUserRow(true, matrixUser.getAvatarData(AvatarSize.Custom(36.dp)), matrixUser.userId.value, enabled = false)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@
|
|||
<string name="common_encryption_enabled">"Encryption enabled"</string>
|
||||
<string name="common_error">"Error"</string>
|
||||
<string name="common_file">"File"</string>
|
||||
<string name="common_file_saved_on_disk_android">"File saved to Downloads"</string>
|
||||
<string name="common_gif">"GIF"</string>
|
||||
<string name="common_image">"Image"</string>
|
||||
<string name="common_invite_unknown_profile">"We can’t validate this user’s Matrix ID. The invite might not be received."</string>
|
||||
|
|
@ -89,6 +90,7 @@
|
|||
<string name="common_report_a_bug">"Report a bug"</string>
|
||||
<string name="common_report_submitted">"Report submitted"</string>
|
||||
<string name="common_room_name">"Room name"</string>
|
||||
<string name="common_room_name_placeholder">"e.g. your project name"</string>
|
||||
<string name="common_search_for_someone">"Search for someone"</string>
|
||||
<string name="common_search_results">"Search results"</string>
|
||||
<string name="common_security">"Security"</string>
|
||||
|
|
@ -102,6 +104,7 @@
|
|||
<string name="common_success">"Success"</string>
|
||||
<string name="common_suggestions">"Suggestions"</string>
|
||||
<string name="common_topic">"Topic"</string>
|
||||
<string name="common_topic_placeholder">"What is this room about?"</string>
|
||||
<string name="common_unable_to_decrypt">"Unable to decrypt"</string>
|
||||
<string name="common_unable_to_invite_message">"We were unable to successfully send invites to one or more users."</string>
|
||||
<string name="common_unable_to_invite_title">"Unable to send invite(s)"</string>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,6 @@ import io.element.android.libraries.matrix.api.user.MatrixUser
|
|||
|
||||
interface UserListDataSource {
|
||||
//TODO should probably have a flow
|
||||
suspend fun search(query: String): List<MatrixUser>
|
||||
suspend fun search(query: String, count: Long): List<MatrixUser>
|
||||
suspend fun getProfile(userId: UserId): MatrixUser?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,16 +28,12 @@ import javax.inject.Inject
|
|||
class MatrixUserListDataSource @Inject constructor(
|
||||
private val client: MatrixClient
|
||||
) : UserListDataSource {
|
||||
override suspend fun search(query: String): List<MatrixUser> {
|
||||
val res = client.searchUsers(query, MAX_SEARCH_RESULTS)
|
||||
override suspend fun search(query: String, count: Long): List<MatrixUser> {
|
||||
val res = client.searchUsers(query, count)
|
||||
return res.getOrNull()?.results.orEmpty()
|
||||
}
|
||||
|
||||
override suspend fun getProfile(userId: UserId): MatrixUser? {
|
||||
return client.getProfile(userId).getOrNull()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MAX_SEARCH_RESULTS = 5L
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class MatrixUserRepository @Inject constructor(
|
|||
// Debounce
|
||||
delay(DEBOUNCE_TIME_MILLIS)
|
||||
|
||||
val results = dataSource.search(query).map { UserSearchResult(it) }.toMutableList()
|
||||
val results = dataSource.search(query, MAXIMUM_SEARCH_RESULTS).map { UserSearchResult(it) }.toMutableList()
|
||||
|
||||
// If the query is a user ID and the result doesn't contain that user ID, query the profile information explicitly
|
||||
if (isUserId && results.none { it.matrixUser.userId.value == query }) {
|
||||
|
|
@ -61,7 +61,8 @@ class MatrixUserRepository @Inject constructor(
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val DEBOUNCE_TIME_MILLIS = 500L
|
||||
private const val DEBOUNCE_TIME_MILLIS = 250L
|
||||
private const val MINIMUM_SEARCH_LENGTH = 3
|
||||
private const val MAXIMUM_SEARCH_RESULTS = 10L
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ internal class MatrixUserListDataSourceTest {
|
|||
)
|
||||
val dataSource = MatrixUserListDataSource(matrixClient)
|
||||
|
||||
val results = dataSource.search("test")
|
||||
val results = dataSource.search("test", 2)
|
||||
Truth.assertThat(results).containsExactly(
|
||||
aMatrixUserProfile(),
|
||||
aMatrixUserProfile(userId = A_USER_ID_2)
|
||||
|
|
@ -63,7 +63,7 @@ internal class MatrixUserListDataSourceTest {
|
|||
)
|
||||
val dataSource = MatrixUserListDataSource(matrixClient)
|
||||
|
||||
val results = dataSource.search("test")
|
||||
val results = dataSource.search("test", 2)
|
||||
Truth.assertThat(results).isEmpty()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class FakeUserListDataSource : UserListDataSource {
|
|||
private var searchResult: List<MatrixUser> = emptyList()
|
||||
private var profile: MatrixUser? = null
|
||||
|
||||
override suspend fun search(query: String): List<MatrixUser> = searchResult
|
||||
override suspend fun search(query: String, count: Long): List<MatrixUser> = searchResult.take(count.toInt())
|
||||
|
||||
override suspend fun getProfile(userId: UserId): MatrixUser? = profile
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:95ea8eb76135a05ff1248f87c906861fcde67432bea549f85b27c9fef24a63d7
|
||||
size 41912
|
||||
oid sha256:56c70ed35d2183ab9244b2cdcbccaf1979d1a862dd7f672ed7987bfd0ff726c9
|
||||
size 41511
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:51ee8709e885016afc333ea0e9f3277081dc5703a4c8fcbbe8ab1a5bbefc2e40
|
||||
size 39885
|
||||
oid sha256:9d4175df2f74fc5c074a2eea0e7a3f80ffcdfe438aff24db7864010894de8cb5
|
||||
size 39412
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8e7352789223e57f85c597a591ada117c903e06ed2df49719a98e793d128cd7b
|
||||
size 106579
|
||||
oid sha256:ba78d6c4836f018d6c048e6c1f14ed65a2e6ae00380054daad8eaa0fb4e1108a
|
||||
size 103095
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:815864d4c929c5f123bc830d367b4f983851412891a23329d03e58e7726e4280
|
||||
size 54198
|
||||
oid sha256:930409bc725dcb68db252b08d838856056fbbeb178c02ba6831e819cadc37528
|
||||
size 53181
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5c68cf2cd74c9eae988c2fce68460ce2188566c27206bd8454e8b131d7b65f7e
|
||||
size 37361
|
||||
oid sha256:92dd6bad4047f68312190d8923c111435a646cd83f5b52cdbce8c6ce48954dda
|
||||
size 36975
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fd898673d5b5c20d68cde9fc1294350798b45c131010648fe3be6f366df90c20
|
||||
size 87816
|
||||
oid sha256:d941ac36664583640991d6a310edf45b4f87d8285647d6aa661970dba3c365b4
|
||||
size 83119
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:04af6faf6e7efb06a6abe23cf49f8486a577f7afbf232af847ba9efb6ed62ce7
|
||||
size 102827
|
||||
oid sha256:99f4447da79ca0c37c7607fb673b6dfd29cb241ba30420adcc0399db170a5810
|
||||
size 98150
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d09b939e42eaba34d2f003571ea0eda96502fa04bd54ed6f08041ef1ea3e8552
|
||||
size 35143
|
||||
oid sha256:521895f59c73d907fc75a5d270598add33512f0a359274adb0b53f28954bb20b
|
||||
size 34704
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:93bce38b6b7031ff38d68a8751eb1cf49397803ba634f1ece711cc77b3acc38c
|
||||
size 84264
|
||||
oid sha256:12839404b6e9eaf8983ccf3e5773cd8c80174068e76924ad72b7b6429018b0b6
|
||||
size 79478
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fb8f6e1d2b368d57911410322543a5bb1cbb4abbff76507190abc8d7d1e04a52
|
||||
size 97755
|
||||
oid sha256:4115bdacc08b7c5bdb4c2859d131eaa0e84748d3f42e2de388ffef72131851a2
|
||||
size 93105
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:906e041d043f2bf604da80766d04b93a75e52b955d6db3496dcf3ae456acca13
|
||||
size 60877
|
||||
oid sha256:0d7a3255202968ab6a467b698ca41154b4564882ac3e45578ea36060a8c97583
|
||||
size 61586
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:befde6b8663f65b9ad0e6789ca21802ceca164f911f0de18a795e9c81b7c4fe5
|
||||
size 100278
|
||||
oid sha256:0bab25b90e451021883fcd388030ac054729d1ea28a2b4e9b6041f5a103f0a7b
|
||||
size 99914
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4032529e222fb9d14d4dc1fd215c8aae5d63326809df7cec449011d7904a60d2
|
||||
size 58355
|
||||
oid sha256:1a3a36f97c7c22d4113570ce8413de29c1d62e96d1d979851a66f051ca229e08
|
||||
size 59148
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2bf49968f5b07ca6798c4c8670a9e173ef3a511c6c60ed8d55d652bb042b8a8b
|
||||
size 96370
|
||||
oid sha256:b28cfcb8e238559bd7775507397307fef4e192bb9e1615a0b08f048e73a5e6dd
|
||||
size 96054
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:67c951e661c54a12d318f874c115768b30806f08e8e6e59bfedc107a968927d7
|
||||
size 21742
|
||||
oid sha256:dffe981836e1070a47cb815275752526e2e81a26ccc1658de8c503016f699afb
|
||||
size 21292
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b13d46300c7cdd3632ee39a6bfce92a5b9bfa44917b32928da313741965addc7
|
||||
size 8677
|
||||
oid sha256:88f8d524d6a22a05b013c8cdc73b909a4ca41938d0fdb41923381c2045e6b37f
|
||||
size 8990
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:58877acda18e78027ae01b4f627ad8ad2df731b865c3e8d534479c41def14c16
|
||||
size 21086
|
||||
oid sha256:1345fb49ea9a7ea7e31086af10755c222c2093ea59c62cf4c6ce291b98c08e5b
|
||||
size 20965
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:255e7caab6e7133239a186a421cf669649133704b15cddebe2dbc4ca9baca372
|
||||
size 8731
|
||||
oid sha256:f6ff5a856c3af2b85848a80e7d832ebbf737e7d5cf06105d5a01c1e6b3f1eeb7
|
||||
size 9115
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:732ea7939a85e877771298e082df8d39e49881c97e4a9085c7887341ce85e502
|
||||
size 22271
|
||||
oid sha256:7e20ba9c18742b91164f5d0bdbbfe41b3960ab67bf921c2d305cfd72fbe57e52
|
||||
size 33100
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5edcc6a91850f6217d850d5db6a539f356ee9e60fe662f46dbf4a65614450450
|
||||
size 25857
|
||||
oid sha256:3dfa909234ae27da447b12391d53657afd23ef0dd17cff4c8bb55ef1b9811432
|
||||
size 38347
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9f35a7a94121ce8a082c5e73434108e6fd73e6ef204c8e5ab887aacc2721e715
|
||||
size 16980
|
||||
oid sha256:7c1b9dc41e7f4abce90208ce21b2537d8522e1467afdc702735f2d3ab79ed265
|
||||
size 38320
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:77bcd34155ae0e32c3b38f4be655da52fb5c5da5fc9383a7379e80ed4519e7f5
|
||||
size 22565
|
||||
oid sha256:d9f210f49c4b9a17b01fffe23229afd6dc7909a50ff79732c4d7f169f6c6c558
|
||||
size 18098
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4782d54f26127fa3e8eb2674486c093036310febc29fc883731eddab158cad40
|
||||
size 33261
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:57ed6d0c0051a91172e0acc4136337899740de50dc30aa83d8d82835ea2bd97f
|
||||
size 21479
|
||||
oid sha256:d0741f10b79b3ba739a7d2f160e61df8ea30c7e90d5b03db66cf0fadae39637d
|
||||
size 31877
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:08f1465c078449fcd080455f58b98becd522ae22be308c4549a03c82d7eff03e
|
||||
size 25145
|
||||
oid sha256:f9e818b80358ed35dfe0b1b1d26b8e64a137aa6f2fbce02385cb3cc7900bd852
|
||||
size 37293
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7c57ccb1f27270234abaa6765c330a13dd98b81e291d9c50e67b14e2c3633832
|
||||
size 16192
|
||||
oid sha256:18dd6a307f1990b95cddba7e5ae199fc2c9746fdc49231ceb320558707c1ec1c
|
||||
size 37252
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bbddd7abaae52b60131036140bd28bbe0b3254ea45297ea1ddfb14e71679149c
|
||||
size 21789
|
||||
oid sha256:7c0e24c4fc71151ae8dc04a6213ecc15e0d25dbe6b1684d177086572aeff84c5
|
||||
size 17289
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:49048bedc855a3460f7a3e7c387481c53e4633ef4110f120c5f8ce649980a583
|
||||
size 32034
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fc812d7b9418a67040d8bd9a007444d611c00108662064baf79ae5805432f081
|
||||
size 56695
|
||||
oid sha256:4bddb1e4c74494ed89812a31e35c8d056a3109043fa817c1dbae13d522e56566
|
||||
size 66641
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4031fc3820333ed5b28f2356792b957bc38cba1559b599b0ac0fef66074252e0
|
||||
size 43572
|
||||
oid sha256:4d6e5e784a6ee50cbf767bc0da43b493e910ee2a7ace9890419916d23c1e11a3
|
||||
size 45461
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8936f72285c8a0f483080a4ff007703e40f187abfe0f67bb3ae33eb57901a1af
|
||||
size 44022
|
||||
oid sha256:f74cb8516eaf4d8f0e289f685d520bc130df21cbfc4fbc68eed001c4138c83b2
|
||||
size 45907
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6dd33c2e92caac62963ccc75c068aa2b27037fe075b48823d2a8b75c88b4f661
|
||||
size 39408
|
||||
oid sha256:360c2c69a3d03538f6f61847757a15e88051b38195cadcd33f9cf2e57638b3f1
|
||||
size 41761
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6dd33c2e92caac62963ccc75c068aa2b27037fe075b48823d2a8b75c88b4f661
|
||||
size 39408
|
||||
oid sha256:360c2c69a3d03538f6f61847757a15e88051b38195cadcd33f9cf2e57638b3f1
|
||||
size 41761
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e87dd78bba7e3fd682e647258d989e5d720b7a0e879d698f96611b98867cdaaf
|
||||
size 55009
|
||||
oid sha256:75f493a62614704c956b8be9351532bb431cc69e400adc9f1d536579b6dc731c
|
||||
size 64226
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dbd348146e2161e9b2a57af31d0ad48c44dd5f0274fbebfd885ea628235e08f9
|
||||
size 42903
|
||||
oid sha256:e96dae6cc767476bd60f23079776600449414a9423976b85c91c348ed065d7ae
|
||||
size 44877
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9c7eb8bd040fb4321ecf28b5e00619f5356f23e5b07f59feb3894dc6620b9643
|
||||
size 43335
|
||||
oid sha256:fd0bb44da30359d50cf5754768d58d75bf4489c9d6fe9c4d5c0d2f3fd9020541
|
||||
size 45302
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:63e2e25f5e92c1890dd23ccc8f0e9c352587c0ac1190c012e430c21b7b8d728e
|
||||
size 38709
|
||||
oid sha256:9654f73bd95d1b0d03dc6ea44d13c4910fb8e64a3c86644a11d5bc8591a4be8a
|
||||
size 41312
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:63e2e25f5e92c1890dd23ccc8f0e9c352587c0ac1190c012e430c21b7b8d728e
|
||||
size 38709
|
||||
oid sha256:9654f73bd95d1b0d03dc6ea44d13c4910fb8e64a3c86644a11d5bc8591a4be8a
|
||||
size 41312
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c37ec529bcec1a58e53fa21dd467fba2c3667a177dd9a49c7eb086b01e0c29a2
|
||||
size 9613
|
||||
oid sha256:ee403297e15204e165ec5dce90e3e93e95e8e1b2e2cbd03489b91c4c9a6de083
|
||||
size 10360
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7bb86dbb18a135602034c3e40c8f070b54051669522f0655235e5d4e2c3830b6
|
||||
size 8584
|
||||
oid sha256:33237fb8f262176e6f291a8ded90ab56600113c93bed188f6d4d01df950df53e
|
||||
size 9286
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ff5b9b385af291a3de025a4449f01d80078df3f447c2dea0873f7cade56b7ae7
|
||||
size 39733
|
||||
oid sha256:ac39dda453fbdf0f5cc3c6df2d9436a171c141c8be2ca2e2d2a2c7ee5d16b36f
|
||||
size 39650
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6ff9b924eacf7746fd91d5008c7ef2be5c2870d311d8bb629cda2551609f6c3a
|
||||
size 43339
|
||||
oid sha256:49ef94a7bd404fe5982f7319aa1c4f6b5d29d11675f53e192af85b4efb8c3517
|
||||
size 43267
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9f460575d657933a81e13a914570687d81869144ac327f10b503fbe22c8b3a59
|
||||
size 43344
|
||||
oid sha256:47942f38dd2afb38d0e1174bd155bb708f645b231b250525920f5abaa7074308
|
||||
size 43217
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:494167e5d7f96bf16b16f5b7c53b304dacf4015b31ce0cd51bfe9e05802664df
|
||||
size 48831
|
||||
oid sha256:b006f7768bbc48cf68e5d897920a14894496d0b2b84a1839a7158b45edea9a75
|
||||
size 48757
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e3e09d6d5a4c0ea8a0dd8ab2ac2b55bfd0fcfbd3f130098adfff5c42500b5013
|
||||
size 42442
|
||||
oid sha256:12702b2d71193e376f15df6f1a029531868b9651b70c40d2d738646f15980704
|
||||
size 42362
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:58b326bad20c368430626a15ca98a8c7af66597262bc42e5de585485f261b3c5
|
||||
size 42396
|
||||
oid sha256:a942ed49efc175776994cf58d511af3be8f878b30ed5b34ab3ae0d600f2e0db1
|
||||
size 42316
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ad6c6bdc7d4e4c405231c2c8944613ff151eb309e00821ac7eda107e853ed456
|
||||
size 37891
|
||||
oid sha256:d692cd9030e6193691e676de62f68a9241cebf220a1f6c7986e095370e25c547
|
||||
size 37839
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4cfd887060df1a1b7e12e3f47010e813678fec822595d90b19c51af99b42ab16
|
||||
size 41714
|
||||
oid sha256:716e20f80dd634feb58ee26247defdd8e390d268e9ec5d9767ad7b574d7ca2bc
|
||||
size 41581
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ede9377d3fbceae95a10e02cb1c033f9bbd53901137ef88ca52fdd4041737c70
|
||||
size 41695
|
||||
oid sha256:9658c925b80565109772111972a495d437bda9ae97a9d9327d92a44ff0a1b9d1
|
||||
size 41521
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6a976609ec6f5ce83388242db7a43ff6c062f84011ce7d2263e5ff8d23c64a96
|
||||
size 47912
|
||||
oid sha256:f0511bf277f5194a6d38cf13416c2b2a1c834bf216c511243351d2f9bfe1b7e3
|
||||
size 47857
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e0a065c5a4c0af748524b0600e1b5233023cdff0eaae8a2039649323e8a19fe3
|
||||
size 40635
|
||||
oid sha256:e248fa1785749f3a590576ed6f3c6899ad0042f71a80a4afdc7336981c7419a3
|
||||
size 40589
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dfa33ed990249e2d3e0097521bc51a3028bf51537736839a1301b54f99ad473b
|
||||
size 40598
|
||||
oid sha256:903df8ff5d3816a85e16a3ec46b2a98e742ba0fc0a317df829b0fca57f33d9aa
|
||||
size 40553
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dc30ecdc5f33bc07ebf3b8376078cfa2c0b3ef23c7e112b9e6e5726b42cc3fcf
|
||||
size 31578
|
||||
oid sha256:558f8f3b34e3a94a62460cca37396f94b0caa8197b7fbd49ce894382392f1899
|
||||
size 31512
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dc30ecdc5f33bc07ebf3b8376078cfa2c0b3ef23c7e112b9e6e5726b42cc3fcf
|
||||
size 31578
|
||||
oid sha256:558f8f3b34e3a94a62460cca37396f94b0caa8197b7fbd49ce894382392f1899
|
||||
size 31512
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c638430bd598a44e76ca0c00ea2b0ff4e9dc047cea19e83b742765ba15ef1607
|
||||
size 33317
|
||||
oid sha256:c4469faa61e68d951ed13b9cf324d11a99a1b041fb096bade2cd5d11c8185acc
|
||||
size 33232
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bc6250ce3b15adb28fcada6698fdb556d391ea3a6beeded279fc5f30c71418e3
|
||||
size 33333
|
||||
oid sha256:81125c72229ddb56f3c3e8b826de42f947f8739c3f372cad99917ee7d4db3b5c
|
||||
size 33318
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:085658106ddaecf65fea877669bba466ec947b0b05e77791a6ae48c9a83e1128
|
||||
size 29611
|
||||
oid sha256:cff519b372c22b623f72407e7c4113cfa24dae31fc517aea5de75bea9b4d61bf
|
||||
size 29616
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c638430bd598a44e76ca0c00ea2b0ff4e9dc047cea19e83b742765ba15ef1607
|
||||
size 33317
|
||||
oid sha256:c4469faa61e68d951ed13b9cf324d11a99a1b041fb096bade2cd5d11c8185acc
|
||||
size 33232
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:05de0afa4939c0ff67a9a613434f9f482a492f52c1ff29158865eec542c9a639
|
||||
size 25340
|
||||
oid sha256:78b278d94f46995b7d11719677b72c0804219b1c36072fd8e2ad6dfdb9de8aba
|
||||
size 25313
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e2ef182ba3721fa37c014dff57b49cbb7ee23d6becbc4ee60d81d44aff11a198
|
||||
size 30523
|
||||
oid sha256:ef34f0de8599a2c950690d1ef1d4c8f68419b137594177ed09cfe3715deb3767
|
||||
size 30490
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e2ef182ba3721fa37c014dff57b49cbb7ee23d6becbc4ee60d81d44aff11a198
|
||||
size 30523
|
||||
oid sha256:ef34f0de8599a2c950690d1ef1d4c8f68419b137594177ed09cfe3715deb3767
|
||||
size 30490
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue