Merge pull request #724 from vector-im/feature/bma/designIteration

Design iteration
This commit is contained in:
Benoit Marty 2023-06-29 18:57:44 +02:00 committed by GitHub
commit b292c3a29b
363 changed files with 1502 additions and 977 deletions

View file

@ -4,7 +4,9 @@
<w>backstack</w> <w>backstack</w>
<w>homeserver</w> <w>homeserver</w>
<w>kover</w> <w>kover</w>
<w>measurables</w>
<w>onboarding</w> <w>onboarding</w>
<w>placeables</w>
<w>showkase</w> <w>showkase</w>
<w>textfields</w> <w>textfields</w>
</words> </words>

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<inset
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@mipmap/ic_launcher_round"
android:insetTop="80dp"
android:insetRight="80dp"
android:insetBottom="80dp"
android:insetLeft="80dp" />

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (c) 2023 New Vector Ltd
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#00000000" />
</shape>

View file

@ -17,8 +17,8 @@
<resources> <resources>
<style name="Theme.ElementX.Splash" parent="Theme.SplashScreen"> <style name="Theme.ElementX.Splash" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/black</item> <item name="windowSplashScreenBackground">@color/splashscreen_bg_dark</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/splash_icon</item> <item name="windowSplashScreenAnimatedIcon">@drawable/transparent</item>
<item name="postSplashScreenTheme">@style/Theme.ElementX</item> <item name="postSplashScreenTheme">@style/Theme.ElementX</item>
</style> </style>

View file

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?><!--
<!--
~ Copyright (c) 2022 New Vector Ltd ~ Copyright (c) 2022 New Vector Ltd
~ ~
~ Licensed under the Apache License, Version 2.0 (the "License"); ~ Licensed under the Apache License, Version 2.0 (the "License");
@ -16,11 +15,8 @@
--> -->
<resources> <resources>
<color name="purple_200">#FFBB86FC</color> <!-- Must be equal to DarkDesignTokens.colorThemeBg -->
<color name="purple_500">#FF6200EE</color> <color name="splashscreen_bg_dark">#FF101317</color>
<color name="purple_700">#FF3700B3</color> <!-- Must be equal to LightDesignTokens.colorThemeBg -->
<color name="teal_200">#FF03DAC5</color> <color name="splashscreen_bg_light">#FFFFFFFF</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources> </resources>

View file

@ -16,9 +16,9 @@
--> -->
<resources> <resources>
<style name="Theme.ElementX.Splash" parent="Theme.SplashScreen.IconBackground"> <style name="Theme.ElementX.Splash" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/white</item> <item name="windowSplashScreenBackground">@color/splashscreen_bg_light</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/splash_icon</item> <item name="windowSplashScreenAnimatedIcon">@drawable/transparent</item>
<item name="postSplashScreenTheme">@style/Theme.ElementX</item> <item name="postSplashScreenTheme">@style/Theme.ElementX</item>
</style> </style>
<style name="Theme.ElementX" parent="Theme.Material3.Light" /> <style name="Theme.ElementX" parent="Theme.Material3.Light" />

View file

@ -32,7 +32,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
@ -50,14 +49,12 @@ import io.element.android.features.invitelist.impl.model.InviteSender
import io.element.android.libraries.designsystem.ElementTextStyles import io.element.android.libraries.designsystem.ElementTextStyles
import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom
import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight 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.Button
import io.element.android.libraries.designsystem.theme.components.OutlinedButton 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.components.Text
import io.element.android.libraries.designsystem.theme.noFontPadding import io.element.android.libraries.designsystem.theme.noFontPadding
import io.element.android.libraries.designsystem.theme.roomListUnreadIndicator
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
private val minHeight = 72.dp private val minHeight = 72.dp
@ -161,8 +158,7 @@ internal fun DefaultInviteSummaryRow(
} }
} }
val unreadIndicatorColor = if (invite.isNew) MaterialTheme.roomListUnreadIndicator() else Color.Transparent UnreadIndicatorAtom(isVisible = invite.isNew)
UnreadIndicatorAtom(color = unreadIndicatorColor)
} }
} }

View file

@ -39,7 +39,6 @@ import androidx.compose.material.icons.outlined.AddReaction
import androidx.compose.material.ripple.rememberRipple import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SheetState
import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -48,6 +47,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
@ -86,8 +86,8 @@ fun ActionListView(
onEmojiReactionClicked: (String, TimelineItem.Event) -> Unit, onEmojiReactionClicked: (String, TimelineItem.Event) -> Unit,
onCustomReactionClicked: (TimelineItem.Event) -> Unit, onCustomReactionClicked: (TimelineItem.Event) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
sheetState: SheetState = rememberModalBottomSheetState()
) { ) {
val sheetState = rememberModalBottomSheetState()
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val targetItem = (state.target as? ActionListState.Target.Success)?.event val targetItem = (state.target as? ActionListState.Target.Success)?.event
@ -118,22 +118,21 @@ fun ActionListView(
} }
fun onDismiss() { fun onDismiss() {
sheetState.hide(coroutineScope) { state.eventSink(ActionListEvents.Clear)
state.eventSink(ActionListEvents.Clear)
}
} }
if (targetItem != null) { if (targetItem != null) {
ModalBottomSheet( ModalBottomSheet(
sheetState = sheetState, sheetState = sheetState,
onDismissRequest = ::onDismiss, onDismissRequest = ::onDismiss,
modifier = modifier,
) { ) {
SheetContent( SheetContent(
state = state, state = state,
onActionClicked = ::onItemActionClicked, onActionClicked = ::onItemActionClicked,
onEmojiReactionClicked = ::onEmojiReactionClicked, onEmojiReactionClicked = ::onEmojiReactionClicked,
onCustomReactionClicked = ::onCustomReactionClicked, onCustomReactionClicked = ::onCustomReactionClicked,
modifier = modifier modifier = Modifier
.padding(bottom = 32.dp) .padding(bottom = 32.dp)
// .navigationBarsPadding() - FIXME after https://issuetracker.google.com/issues/275849044 // .navigationBarsPadding() - FIXME after https://issuetracker.google.com/issues/275849044
// .imePadding() // .imePadding()
@ -191,7 +190,7 @@ private fun SheetContent(
}, },
text = { text = {
Text( Text(
text = action.title, text = stringResource(id = action.titleRes),
color = if (action.destructive) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary, color = if (action.destructive) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary,
) )
}, },

View file

@ -17,20 +17,22 @@
package io.element.android.features.messages.impl.actionlist.model package io.element.android.features.messages.impl.actionlist.model
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import io.element.android.libraries.designsystem.VectorIcons import io.element.android.libraries.designsystem.VectorIcons
import io.element.android.libraries.ui.strings.CommonStrings
@Immutable @Immutable
sealed class TimelineItemAction( sealed class TimelineItemAction(
val title: String, @StringRes val titleRes: Int,
@DrawableRes val icon: Int, @DrawableRes val icon: Int,
val destructive: Boolean = false val destructive: Boolean = false
) { ) {
object Forward : TimelineItemAction("Forward", VectorIcons.Forward) object Forward : TimelineItemAction(CommonStrings.action_forward, VectorIcons.Forward)
object Copy : TimelineItemAction("Copy", VectorIcons.Copy) object Copy : TimelineItemAction(CommonStrings.action_copy, VectorIcons.Copy)
object Redact : TimelineItemAction("Redact", VectorIcons.Delete, destructive = true) object Redact : TimelineItemAction(CommonStrings.action_remove, VectorIcons.Delete, destructive = true)
object Reply : TimelineItemAction("Reply", VectorIcons.Reply) object Reply : TimelineItemAction(CommonStrings.action_reply, VectorIcons.Reply)
object Edit : TimelineItemAction("Edit", VectorIcons.Edit) object Edit : TimelineItemAction(CommonStrings.action_edit, VectorIcons.Edit)
object Developer : TimelineItemAction("Developer", VectorIcons.DeveloperMode) object Developer : TimelineItemAction(CommonStrings.action_view_source, VectorIcons.DeveloperMode)
object ReportContent : TimelineItemAction("Report content", VectorIcons.ReportContent, destructive = true) object ReportContent : TimelineItemAction(CommonStrings.action_report_content, VectorIcons.ReportContent, destructive = true)
} }

View file

@ -44,6 +44,8 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Surface 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.Text
import io.element.android.libraries.designsystem.theme.messageFromMeBackground
import io.element.android.libraries.designsystem.theme.messageFromOtherBackground
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
private val BUBBLE_RADIUS = 12.dp private val BUBBLE_RADIUS = 12.dp
@ -97,14 +99,11 @@ fun MessageEventBubble(
} }
} }
val backgroundBubbleColor = if (state.isHighlighted) { // Ignore state.isHighlighted for now, we need a design decision on it.
ElementTheme.legacyColors.messageHighlightedBackground val backgroundBubbleColor = if (state.isMine) {
ElementTheme.colors.messageFromMeBackground
} else { } else {
if (state.isMine) { ElementTheme.colors.messageFromOtherBackground
ElementTheme.legacyColors.messageFromMeBackground
} else {
ElementTheme.legacyColors.messageFromOtherBackground
}
} }
val bubbleShape = bubbleShape() val bubbleShape = bubbleShape()
Box( Box(

View file

@ -41,18 +41,15 @@ private val CORNER_RADIUS = 8.dp
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun MessageStateEventContainer( fun MessageStateEventContainer(
isHighlighted: Boolean, @Suppress("UNUSED_PARAMETER") isHighlighted: Boolean,
interactionSource: MutableInteractionSource, interactionSource: MutableInteractionSource,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onClick: () -> Unit = {}, onClick: () -> Unit = {},
onLongClick: () -> Unit = {}, onLongClick: () -> Unit = {},
content: @Composable () -> Unit = {}, content: @Composable () -> Unit = {},
) { ) {
val backgroundColor = if (isHighlighted) { // Ignore isHighlighted for now, we need a design decision on it.
ElementTheme.legacyColors.messageHighlightedBackground val backgroundColor = Color.Transparent
} else {
Color.Companion.Transparent
}
val shape = RoundedCornerShape(CORNER_RADIUS) val shape = RoundedCornerShape(CORNER_RADIUS)
Surface( Surface(
modifier = modifier modifier = modifier

View file

@ -58,15 +58,19 @@ fun TimelineEventTimestampView(
val hasMessageSendingFailed = event.sendState is EventSendState.SendingFailed val hasMessageSendingFailed = event.sendState is EventSendState.SendingFailed
val isMessageEdited = (event.content as? TimelineItemTextBasedContent)?.isEdited.orFalse() val isMessageEdited = (event.content as? TimelineItemTextBasedContent)?.isEdited.orFalse()
val tint = if (hasMessageSendingFailed) MaterialTheme.colorScheme.error else null val tint = if (hasMessageSendingFailed) MaterialTheme.colorScheme.error else null
val clickModifier = if (hasMessageSendingFailed) {
Modifier.combinedClickable(
onClick = onClick,
onLongClick = onLongClick,
indication = rememberRipple(bounded = false),
interactionSource = MutableInteractionSource()
)
} else {
Modifier
}
Row( Row(
modifier = Modifier modifier = Modifier
.combinedClickable( .then(clickModifier)
onClick = onClick,
onLongClick = onLongClick,
enabled = true,
indication = rememberRipple(bounded = false),
interactionSource = MutableInteractionSource()
)
.padding(start = 16.dp) // Add extra padding for touch target size .padding(start = 16.dp) // Add extra padding for touch target size
.then(modifier), .then(modifier),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,

View file

@ -41,7 +41,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
@ -59,7 +58,6 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
import io.element.android.libraries.designsystem.ElementTextStyles
import io.element.android.libraries.designsystem.components.EqualWidthColumn import io.element.android.libraries.designsystem.components.EqualWidthColumn
import io.element.android.libraries.designsystem.components.avatar.Avatar 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.AvatarData
@ -71,6 +69,8 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.ImageMessageType import io.element.android.libraries.matrix.api.timeline.item.event.ImageMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo
import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent
import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
@ -268,7 +268,7 @@ private fun MessageEventBubbleContent(
} }
} else { } else {
Box(modifier) { Box(modifier) {
ContentView(modifier = contentModifier.padding(start = 12.dp, end = 12.dp, top = 8.dp, bottom = 8.dp)) ContentView(modifier = contentModifier)
TimelineEventTimestampView( TimelineEventTimestampView(
event = event, event = event,
onClick = onTimestampClicked, onClick = onTimestampClicked,
@ -316,7 +316,11 @@ private fun MessageEventBubbleContent(
val contentModifier = if (isMediaItem) { val contentModifier = if (isMediaItem) {
Modifier.clip(RoundedCornerShape(12.dp)) Modifier.clip(RoundedCornerShape(12.dp))
} else { } else {
Modifier if (inReplyToDetails != null) {
Modifier.padding(start = 12.dp, end = 12.dp, top = 0.dp, bottom = 8.dp)
} else {
Modifier.padding(start = 12.dp, end = 12.dp, top = 8.dp, bottom = 8.dp)
}
} }
ContentAndTimestampView( ContentAndTimestampView(
@ -363,20 +367,19 @@ private fun ReplyToContent(
} }
Column(verticalArrangement = Arrangement.SpaceBetween) { Column(verticalArrangement = Arrangement.SpaceBetween) {
Text( Text(
senderName, text = senderName,
style = ElementTextStyles.Regular.caption2.copy(fontWeight = FontWeight.Medium), style = ElementTheme.typography.fontBodySmMedium,
textAlign = TextAlign.Start, textAlign = TextAlign.Start,
color = MaterialTheme.colorScheme.primary, color = ElementTheme.materialColors.primary,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
Text( Text(
text = text.orEmpty(), text = text.orEmpty(),
style = ElementTextStyles.Regular.caption1, style = ElementTheme.typography.fontBodyMdRegular,
textAlign = TextAlign.Start, textAlign = TextAlign.Start,
color = ElementTheme.legacyColors.placeholder, color = ElementTheme.materialColors.secondary,
maxLines = 1, maxLines = 2,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
} }
@ -455,6 +458,76 @@ private fun ContentToPreview() {
} }
} }
@Preview
@Composable
internal fun TimelineItemEventRowWithReplyLightPreview() =
ElementPreviewLight { ContentToPreviewWithReply() }
@Preview
@Composable
internal fun TimelineItemEventRowWithReplyDarkPreview() =
ElementPreviewDark { ContentToPreviewWithReply() }
@Composable
private fun ContentToPreviewWithReply() {
Column {
sequenceOf(false, true).forEach {
val replyContent = if(it) {
// Short
"Message which are being replied."
} else {
// Long, to test 2 lines and ellipsis)
"Message which are being replied, and which was long enough to be displayed on two lines (only!)."
}
TimelineItemEventRow(
event = aTimelineItemEvent(
isMine = it,
content = aTimelineItemTextContent().copy(
body = "A long text which will be displayed on several lines and" +
" hopefully can be manually adjusted to test different behaviors."
),
inReplyTo = aInReplyToReady(replyContent)
),
isHighlighted = false,
onClick = {},
onLongClick = {},
onUserDataClick = {},
inReplyToClick = {},
onReactionClick = { _, _ -> },
onTimestampClicked = {},
)
TimelineItemEventRow(
event = aTimelineItemEvent(
isMine = it,
content = aTimelineItemImageContent().copy(
aspectRatio = 5f
),
inReplyTo = aInReplyToReady(replyContent)
),
isHighlighted = false,
onClick = {},
onLongClick = {},
onUserDataClick = {},
inReplyToClick = {},
onReactionClick = { _, _ -> },
onTimestampClicked = {},
)
}
}
}
private fun aInReplyToReady(
replyContent: String
): InReplyTo.Ready {
return InReplyTo.Ready(
eventId = EventId("\$event"),
content = MessageContent(replyContent, null, false, TextMessageType(replyContent, null)),
senderId = UserId("@Sender:domain"),
senderDisplayName = "Sender",
senderAvatarUrl = null,
)
}
@Preview @Preview
@Composable @Composable
internal fun TimelineItemEventRowTimestampLightPreview(@PreviewParameter(TimelineItemEventForTimestampViewProvider::class) event: TimelineItem.Event) = internal fun TimelineItemEventRowTimestampLightPreview(@PreviewParameter(TimelineItemEventForTimestampViewProvider::class) event: TimelineItem.Event) =

View file

@ -19,6 +19,7 @@ package io.element.android.features.messages.impl.timeline.components
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -50,6 +51,7 @@ fun TimelineItemStateEventRow(
Box( Box(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 8.dp)
.wrapContentHeight(), .wrapContentHeight(),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {

View file

@ -38,9 +38,7 @@ fun CustomReactionBottomSheet(
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
fun onDismiss() { fun onDismiss() {
sheetState.hide(coroutineScope) { state.eventSink(CustomReactionEvents.UpdateSelectedEvent(null))
state.eventSink(CustomReactionEvents.UpdateSelectedEvent(null))
}
} }
fun onEmojiSelectedDismiss(emoji: Emoji) { fun onEmojiSelectedDismiss(emoji: Emoji) {

View file

@ -51,3 +51,11 @@ fun TimelineItem.Event.toExtraPadding(): ExtraPadding {
// A space and a few unbreakable spaces // A space and a few unbreakable spaces
return ExtraPadding(" " + "\u00A0".repeat(strLen)) return ExtraPadding(" " + "\u00A0".repeat(strLen))
} }
fun ExtraPadding.strBigger(): String {
return if (str.isEmpty()) {
str
} else {
str + "\u00A0\u00A0\u00A0"
}
}

View file

@ -59,7 +59,8 @@ fun TimelineItemInformativeView(
fontStyle = FontStyle.Italic, fontStyle = FontStyle.Italic,
color = MaterialTheme.colorScheme.secondary, color = MaterialTheme.colorScheme.secondary,
fontSize = 14.sp, fontSize = 14.sp,
text = text + extraPadding.str // Since the font size is smaller, add more space to extra padding, to not overlap with the timestamp
text = text + extraPadding.strBigger()
) )
} }
} }

View file

@ -38,7 +38,6 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Surface 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.Text
@ -49,15 +48,12 @@ private val CORNER_RADIUS = 8.dp
fun GroupHeaderView( fun GroupHeaderView(
text: String, text: String,
isExpanded: Boolean, isExpanded: Boolean,
isHighlighted: Boolean, @Suppress("UNUSED_PARAMETER") isHighlighted: Boolean,
onClick: () -> Unit, onClick: () -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val backgroundColor = if (isHighlighted) { // Ignore isHighlighted for now, we need a design decision on it.
ElementTheme.legacyColors.messageHighlightedBackground val backgroundColor = Color.Companion.Transparent
} else {
Color.Companion.Transparent
}
val shape = RoundedCornerShape(CORNER_RADIUS) val shape = RoundedCornerShape(CORNER_RADIUS)
Box( Box(

View file

@ -25,7 +25,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ListItem import androidx.compose.material3.ListItem
import androidx.compose.material3.ListItemDefaults import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetState import androidx.compose.material3.SheetState
import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -40,6 +39,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.features.messages.impl.R import io.element.android.features.messages.impl.R
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Composable @Composable

View file

@ -38,8 +38,6 @@ import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material.icons.outlined.Person import androidx.compose.material.icons.outlined.Person
import androidx.compose.material.icons.outlined.PersonAddAlt import androidx.compose.material.icons.outlined.PersonAddAlt
import androidx.compose.material.icons.outlined.Share import androidx.compose.material.icons.outlined.Share
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -70,6 +68,9 @@ import io.element.android.libraries.designsystem.components.preferences.Preferen
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.preview.LargeHeightPreview import io.element.android.libraries.designsystem.preview.LargeHeightPreview
import io.element.android.libraries.designsystem.theme.components.DropdownMenu
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItemText
import io.element.android.libraries.designsystem.theme.components.Icon 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.IconButton
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
@ -192,12 +193,11 @@ internal fun RoomDetailsTopBar(
Icon(Icons.Default.MoreVert, "") Icon(Icons.Default.MoreVert, "")
} }
DropdownMenu( DropdownMenu(
modifier = Modifier.widthIn(200.dp),
expanded = showMenu, expanded = showMenu,
onDismissRequest = { showMenu = false }, onDismissRequest = { showMenu = false },
) { ) {
DropdownMenuItem( DropdownMenuItem(
text = { Text(stringResource(id = CommonStrings.action_edit)) }, text = { DropdownMenuItemText(stringResource(id = CommonStrings.action_edit)) },
onClick = { onClick = {
// Explicitly close the menu before handling the action, as otherwise it stays open during the // Explicitly close the menu before handling the action, as otherwise it stays open during the
// transition and renders really badly. // transition and renders really badly.

View file

@ -0,0 +1,91 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.roomlist.impl
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
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.res.stringResource
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.atomic.atoms.UnreadIndicatorAtom
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.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings
@Composable
fun InvitesEntryPointView(
onInvitesClicked: () -> Unit,
state: InvitesState,
modifier: Modifier = Modifier,
) {
Box(
modifier = modifier.fillMaxWidth(),
) {
Row(
modifier = Modifier
.clip(RoundedCornerShape(8.dp))
.clickable(role = Role.Button, onClick = onInvitesClicked)
.padding(start = 24.dp, end = 16.dp)
.align(Alignment.CenterEnd)
.heightIn(min = 40.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = stringResource(CommonStrings.action_invites_list),
style = ElementTheme.typography.fontBodyMdMedium,
)
if (state == InvitesState.NewInvites) {
Spacer(Modifier.width(8.dp))
UnreadIndicatorAtom()
}
}
}
}
@Preview
@Composable
internal fun InvitesEntryPointViewLightPreview(@PreviewParameter(InvitesStateProvider::class) state: InvitesState) =
ElementPreviewLight { ContentToPreview(state) }
@Preview
@Composable
internal fun InvitesEntryPointViewDarkPreview(@PreviewParameter(InvitesStateProvider::class) state: InvitesState) =
ElementPreviewDark { ContentToPreview(state) }
@Composable
private fun ContentToPreview(state: InvitesState) {
InvitesEntryPointView(
onInvitesClicked = {},
state = state,
)
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.roomlist.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
open class InvitesStateProvider : PreviewParameterProvider<InvitesState> {
override val values: Sequence<InvitesState>
get() = sequenceOf(
InvitesState.SeenInvites,
InvitesState.NewInvites,
)
}

View file

@ -17,18 +17,12 @@
package io.element.android.features.roomlist.impl package io.element.android.features.roomlist.impl
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
@ -42,17 +36,14 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.Velocity import androidx.compose.ui.unit.Velocity
import androidx.compose.ui.unit.dp 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.leaveroom.api.LeaveRoomView
import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorView import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorView
import io.element.android.features.roomlist.impl.components.RequestVerificationHeader import io.element.android.features.roomlist.impl.components.RequestVerificationHeader
@ -61,18 +52,15 @@ import io.element.android.features.roomlist.impl.components.RoomListTopBar
import io.element.android.features.roomlist.impl.components.RoomSummaryRow import io.element.android.features.roomlist.impl.components.RoomSummaryRow
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.roomlist.impl.search.RoomListSearchResultView import io.element.android.features.roomlist.impl.search.RoomListSearchResultView
import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight 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.Divider
import io.element.android.libraries.designsystem.theme.components.FloatingActionButton 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.Icon
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.LogCompositions import io.element.android.libraries.designsystem.utils.LogCompositions
import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.libraries.designsystem.R as DrawableR import io.element.android.libraries.designsystem.R as DrawableR
@Composable @Composable
@ -206,7 +194,7 @@ fun RoomListContent(
if (state.invitesState != InvitesState.NoInvites) { if (state.invitesState != InvitesState.NoInvites) {
item { item {
InvitesEntryPointView(onInvitesClicked, state) InvitesEntryPointView(onInvitesClicked, state.invitesState)
} }
} }
@ -251,38 +239,6 @@ fun RoomListContent(
) )
} }
@Composable
private fun InvitesEntryPointView(
onInvitesClicked: () -> Unit,
state: RoomListState,
modifier: Modifier = Modifier,
) {
Box(
modifier = modifier.fillMaxWidth(),
) {
Row(
modifier = Modifier
.clickable(role = Role.Button, onClick = onInvitesClicked)
.padding(horizontal = 16.dp)
.align(Alignment.CenterEnd)
.heightIn(min = 48.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = stringResource(CommonStrings.action_invites_list),
fontSize = 14.sp,
style = MaterialTheme.typography.bodyMedium,
)
if (state.invitesState == InvitesState.NewInvites) {
Spacer(Modifier.width(8.dp))
UnreadIndicatorAtom()
}
}
}
}
internal fun RoomListRoomSummary.contentType() = isPlaceholder internal fun RoomListRoomSummary.contentType() = isPlaceholder
@Preview @Preview

View file

@ -19,12 +19,10 @@ package io.element.android.features.roomlist.impl.components
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.BugReport
import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Share import androidx.compose.material.icons.outlined.BugReport
import androidx.compose.material3.DropdownMenu import androidx.compose.material.icons.outlined.Share
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
@ -48,6 +46,9 @@ import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.DropdownMenu
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItemText
import io.element.android.libraries.designsystem.theme.components.Icon 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.IconButton
import io.element.android.libraries.designsystem.theme.components.MediumTopAppBar import io.element.android.libraries.designsystem.theme.components.MediumTopAppBar
@ -58,6 +59,7 @@ 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.getAvatarData
import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.testtags.testTag import io.element.android.libraries.testtags.testTag
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -137,12 +139,20 @@ private fun DefaultRoomListTopBar(
IconButton( IconButton(
onClick = onSearchClicked, onClick = onSearchClicked,
) { ) {
Icon(Icons.Default.Search, contentDescription = stringResource(CommonStrings.action_search)) Icon(
imageVector = Icons.Default.Search,
tint = ElementTheme.materialColors.secondary,
contentDescription = stringResource(CommonStrings.action_search),
)
} }
IconButton( IconButton(
onClick = { showMenu = !showMenu } onClick = { showMenu = !showMenu }
) { ) {
Icon(Icons.Default.MoreVert, contentDescription = null) Icon(
imageVector = Icons.Default.MoreVert,
tint = ElementTheme.materialColors.secondary,
contentDescription = null,
)
} }
DropdownMenu( DropdownMenu(
expanded = showMenu, expanded = showMenu,
@ -153,16 +163,28 @@ private fun DefaultRoomListTopBar(
showMenu = false showMenu = false
onMenuActionClicked(RoomListMenuAction.InviteFriends) onMenuActionClicked(RoomListMenuAction.InviteFriends)
}, },
text = { Text(stringResource(id = CommonStrings.action_invite)) }, text = { DropdownMenuItemText(stringResource(id = CommonStrings.action_invite)) },
leadingIcon = { Icon(Icons.Default.Share, contentDescription = null) } leadingIcon = {
Icon(
Icons.Outlined.Share,
tint = ElementTheme.materialColors.secondary,
contentDescription = null,
)
}
) )
DropdownMenuItem( DropdownMenuItem(
onClick = { onClick = {
showMenu = false showMenu = false
onMenuActionClicked(RoomListMenuAction.ReportBug) onMenuActionClicked(RoomListMenuAction.ReportBug)
}, },
text = { Text(stringResource(id = CommonStrings.common_report_a_bug)) }, text = { DropdownMenuItemText(stringResource(id = CommonStrings.common_report_a_bug)) },
leadingIcon = { Icon(Icons.Default.BugReport, contentDescription = null) } leadingIcon = {
Icon(
Icons.Outlined.BugReport,
tint = ElementTheme.materialColors.secondary,
contentDescription = null,
)
}
) )
} }
}, },

View file

@ -36,6 +36,7 @@ import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.roomListPlaceholder
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
/** /**
@ -55,7 +56,7 @@ internal fun RoomSummaryPlaceholderRow(
modifier = Modifier modifier = Modifier
.size(AvatarSize.RoomListItem.dp) .size(AvatarSize.RoomListItem.dp)
.align(Alignment.CenterVertically) .align(Alignment.CenterVertically)
.background(color = ElementTheme.colors.textPlaceholder, shape = CircleShape) .background(color = ElementTheme.colors.roomListPlaceholder, shape = CircleShape)
) )
Column( Column(
modifier = Modifier modifier = Modifier

View file

@ -35,19 +35,16 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Outline import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Path import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryProvider import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryProvider
import io.element.android.libraries.core.extensions.orEmpty import io.element.android.libraries.core.extensions.orEmpty
@ -59,7 +56,8 @@ import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.roomListRoomMessage import io.element.android.libraries.designsystem.theme.roomListRoomMessage
import io.element.android.libraries.designsystem.theme.roomListRoomMessageDate import io.element.android.libraries.designsystem.theme.roomListRoomMessageDate
import io.element.android.libraries.designsystem.theme.roomListRoomName import io.element.android.libraries.designsystem.theme.roomListRoomName
import io.element.android.libraries.designsystem.theme.roomListUnreadIndicator import io.element.android.libraries.designsystem.theme.unreadIndicator
import io.element.android.libraries.theme.ElementTheme
internal val minHeight = 84.dp internal val minHeight = 84.dp
@ -136,9 +134,7 @@ private fun RowScope.NameAndTimestampRow(room: RoomListRoomSummary) {
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.padding(end = 16.dp), .padding(end = 16.dp),
fontSize = 16.sp, style = ElementTheme.typography.fontBodyLgMedium,
fontWeight = FontWeight.SemiBold,
style = MaterialTheme.typography.bodyMedium,
text = room.name, text = room.name,
color = MaterialTheme.roomListRoomName(), color = MaterialTheme.roomListRoomName(),
maxLines = 1, maxLines = 1,
@ -146,9 +142,13 @@ private fun RowScope.NameAndTimestampRow(room: RoomListRoomSummary) {
) )
// Timestamp // Timestamp
Text( Text(
fontSize = 12.sp,
text = room.timestamp ?: "", text = room.timestamp ?: "",
color = MaterialTheme.roomListRoomMessageDate(), style = ElementTheme.typography.fontBodySmRegular,
color = if (room.hasUnread) {
ElementTheme.colors.unreadIndicator
} else {
MaterialTheme.roomListRoomMessageDate()
},
) )
} }
@ -163,17 +163,15 @@ private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) {
.padding(end = 28.dp), .padding(end = 28.dp),
text = attributedLastMessage, text = attributedLastMessage,
color = MaterialTheme.roomListRoomMessage(), color = MaterialTheme.roomListRoomMessage(),
fontSize = 14.sp, style = ElementTheme.typography.fontBodyMdRegular,
style = MaterialTheme.typography.bodySmall, minLines = 2,
maxLines = 2, maxLines = 2,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
// Unread // Unread
val unreadIndicatorColor =
if (room.hasUnread) MaterialTheme.roomListUnreadIndicator() else Color.Transparent
UnreadIndicatorAtom( UnreadIndicatorAtom(
modifier = Modifier.padding(top = 3.dp), modifier = Modifier.padding(top = 3.dp),
color = unreadIndicatorColor, isVisible = room.hasUnread,
) )
} }

View file

@ -138,6 +138,7 @@ internal fun RoomListSearchResultContent(
.fillMaxWidth() .fillMaxWidth()
.focusRequester(focusRequester), .focusRequester(focusRequester),
value = filter, value = filter,
singleLine = true,
onValueChange = { state.eventSink(RoomListEvents.UpdateFilter(it)) }, onValueChange = { state.eventSink(RoomListEvents.UpdateFilter(it)) },
colors = TextFieldDefaults.colors( colors = TextFieldDefaults.colors(
focusedContainerColor = Color.Transparent, focusedContainerColor = Color.Transparent,

View file

@ -29,6 +29,7 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.roomListPlaceholder
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
@Composable @Composable
@ -36,7 +37,7 @@ fun PlaceholderAtom(
width: Dp, width: Dp,
height: Dp, height: Dp,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
color: Color = ElementTheme.colors.textPlaceholder, color: Color = ElementTheme.colors.roomListPlaceholder,
) { ) {
Box( Box(
modifier = modifier modifier = modifier

View file

@ -20,7 +20,6 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
@ -30,19 +29,21 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.roomListUnreadIndicator import io.element.android.libraries.designsystem.theme.unreadIndicator
import io.element.android.libraries.theme.ElementTheme
@Composable @Composable
fun UnreadIndicatorAtom( fun UnreadIndicatorAtom(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
size: Dp = 12.dp, size: Dp = 12.dp,
color: Color = MaterialTheme.roomListUnreadIndicator(), color: Color = ElementTheme.colors.unreadIndicator,
isVisible: Boolean = true,
) { ) {
Box( Box(
modifier = modifier modifier = modifier
.size(size) .size(size)
.clip(CircleShape) .clip(CircleShape)
.background(color) .background(if (isVisible) color else Color.Transparent)
) )
} }

View file

@ -27,10 +27,10 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.theme.ElementTheme
/** /**
* @param modifier Classical modifier. * @param modifier Classical modifier.
@ -87,7 +87,7 @@ private fun ContentToPreview() {
) { ) {
Text( Text(
text = "Content", text = "Content",
fontSize = 40.sp style = ElementTheme.typography.fontHeadingXlBold
) )
} }
}, },
@ -99,7 +99,7 @@ private fun ContentToPreview() {
) { ) {
Text( Text(
text = "Header", text = "Header",
fontSize = 40.sp style = ElementTheme.typography.fontHeadingXlBold
) )
} }
}, },
@ -111,7 +111,7 @@ private fun ContentToPreview() {
) { ) {
Text( Text(
text = "Footer", text = "Footer",
fontSize = 40.sp style = ElementTheme.typography.fontHeadingXlBold
) )
} }
} }

View file

@ -30,11 +30,11 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import io.element.android.libraries.designsystem.R import io.element.android.libraries.designsystem.R
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.theme.ElementTheme
/** /**
* Page for onboarding screens, with content and optional footer. * Page for onboarding screens, with content and optional footer.
@ -106,7 +106,7 @@ private fun ContentToPreview() {
) { ) {
Text( Text(
text = "Content", text = "Content",
fontSize = 40.sp style = ElementTheme.typography.fontHeadingXlBold
) )
} }
}, },
@ -118,7 +118,7 @@ private fun ContentToPreview() {
) { ) {
Text( Text(
text = "Footer", text = "Footer",
fontSize = 40.sp style = ElementTheme.typography.fontHeadingXlBold
) )
} }
} }

View file

@ -26,8 +26,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
@ -39,8 +37,7 @@ import io.element.android.libraries.designsystem.preview.PreviewGroup
import io.element.android.libraries.designsystem.preview.debugPlaceholderAvatar import io.element.android.libraries.designsystem.preview.debugPlaceholderAvatar
import io.element.android.libraries.designsystem.text.toSp import io.element.android.libraries.designsystem.text.toSp
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.theme.AvatarGradientEnd import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.theme.AvatarGradientStart
import timber.log.Timber import timber.log.Timber
@Composable @Composable
@ -89,16 +86,10 @@ private fun InitialsAvatar(
avatarData: AvatarData, avatarData: AvatarData,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val initialsGradient = Brush.linearGradient( // Use temporary color for default avatar background
listOf( val avatarColor = ElementTheme.colors.bgActionPrimaryDisabled
AvatarGradientStart,
AvatarGradientEnd,
),
start = Offset(0.0f, 100f),
end = Offset(100f, 0f)
)
Box( Box(
modifier.background(brush = initialsGradient), modifier.background(color = avatarColor),
) { ) {
Text( Text(
modifier = Modifier.align(Alignment.Center), modifier = Modifier.align(Alignment.Center),

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.designsystem.ruler
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
/**
* Horizontal ruler is a debug composable that displays a horizontal ruler.
* It can be used to display the horizontal ruler in the composable preview.
*/
@Composable
fun HorizontalRuler(
modifier: Modifier = Modifier,
) {
val baseColor = Color.Magenta
val alphaBaseColor = baseColor.copy(alpha = 0.2f)
Row(modifier = modifier.fillMaxWidth()) {
repeat(50) {
HorizontalRulerItem(1.dp, alphaBaseColor)
HorizontalRulerItem(2.dp, baseColor)
HorizontalRulerItem(1.dp, alphaBaseColor)
HorizontalRulerItem(2.dp, baseColor)
HorizontalRulerItem(5.dp, alphaBaseColor)
HorizontalRulerItem(2.dp, baseColor)
HorizontalRulerItem(1.dp, alphaBaseColor)
HorizontalRulerItem(2.dp, baseColor)
HorizontalRulerItem(1.dp, alphaBaseColor)
HorizontalRulerItem(10.dp, baseColor)
}
}
}
@Composable
private fun HorizontalRulerItem(height: Dp, color: Color) {
Spacer(
modifier = Modifier
.size(height = height, width = 1.dp)
.background(color = color)
)
}
@Preview
@Composable
internal fun HorizontalRulerLightPreview() =
ElementPreviewLight { ContentToPreview() }
@Preview
@Composable
internal fun HorizontalRulerDarkPreview() =
ElementPreviewDark { ContentToPreview() }
@Composable
private fun ContentToPreview() {
HorizontalRuler()
}

View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.designsystem.ruler
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
/**
* Vertical ruler is a debug composable that displays a vertical ruler.
* It can be used to display the vertical ruler in the composable preview.
*/
@Composable
fun VerticalRuler(
modifier: Modifier = Modifier,
) {
val baseColor = Color.Red
val alphaBaseColor = baseColor.copy(alpha = 0.2f)
Column(modifier = modifier.fillMaxHeight()) {
repeat(50) {
VerticalRulerItem(1.dp, alphaBaseColor)
VerticalRulerItem(2.dp, baseColor)
VerticalRulerItem(1.dp, alphaBaseColor)
VerticalRulerItem(2.dp, baseColor)
VerticalRulerItem(5.dp, alphaBaseColor)
VerticalRulerItem(2.dp, baseColor)
VerticalRulerItem(1.dp, alphaBaseColor)
VerticalRulerItem(2.dp, baseColor)
VerticalRulerItem(1.dp, alphaBaseColor)
VerticalRulerItem(10.dp, baseColor)
}
}
}
@Composable
private fun VerticalRulerItem(width: Dp, color: Color) {
Spacer(
modifier = Modifier
.size(height = 1.dp, width = width)
.background(color = color)
)
}
@Preview
@Composable
internal fun VerticalRulerLightPreview() =
ElementPreviewLight { ContentToPreview() }
@Preview
@Composable
internal fun VerticalRulerDarkPreview() =
ElementPreviewDark { ContentToPreview() }
@Composable
private fun ContentToPreview() {
VerticalRuler()
}

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.designsystem.ruler
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.OutlinedButton
import io.element.android.libraries.designsystem.theme.components.Text
/**
* Debug tool to add a vertical and a horizontal ruler on top of the content.
*/
@Composable
fun WithRulers(
modifier: Modifier = Modifier,
xRulersOffset: Dp = 0.dp,
yRulersOffset: Dp = 0.dp,
content: @Composable () -> Unit
) {
Layout(
modifier = modifier,
content = {
content()
VerticalRuler()
HorizontalRuler()
},
measurePolicy = { measurables, constraints ->
val placeables = measurables.map { it.measure(constraints) }
// Use layout size of the first item (the content)
layout(
width = placeables.first().width,
height = placeables.first().height
) {
placeables.forEachIndexed { index, placeable ->
if (index == 0) {
placeable.place(0, 0)
} else {
placeable.place(xRulersOffset.roundToPx(), yRulersOffset.roundToPx())
}
}
}
}
)
}
@Preview
@Composable
internal fun WithRulerLightPreview() =
ElementPreviewLight { ContentToPreview() }
@Preview
@Composable
internal fun WithRulerDarkPreview() =
ElementPreviewDark { ContentToPreview() }
@Composable
private fun ContentToPreview() {
WithRulers(xRulersOffset = 20.dp, yRulersOffset = 15.dp) {
OutlinedButton(onClick = {}) {
Text(text = "A Button with rulers on it!")
}
}
}

View file

@ -22,6 +22,8 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.theme.compound.generated.SemanticColors
import io.element.android.libraries.theme.previews.ColorListPreview import io.element.android.libraries.theme.previews.ColorListPreview
import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.persistentMapOf
@ -37,8 +39,31 @@ fun MaterialTheme.roomListRoomMessage() = colorScheme.secondary
@Composable @Composable
fun MaterialTheme.roomListRoomMessageDate() = colorScheme.secondary fun MaterialTheme.roomListRoomMessageDate() = colorScheme.secondary
@Composable val SemanticColors.unreadIndicator
fun MaterialTheme.roomListUnreadIndicator() = colorScheme.primary get() = iconAccentTertiary
val SemanticColors.roomListPlaceholder
get() = bgSubtleSecondary
// This color is not present in Semantic color, so put hard-coded value for now
val SemanticColors.messageFromMeBackground
get() = if (isLight) {
// We want LightDesignTokens.colorGray400
Color(0xFFE1E6EC)
} else {
// We want DarkDesignTokens.colorGray500
Color(0xFF323539)
}
// This color is not present in Semantic color, so put hard-coded value for now
val SemanticColors.messageFromOtherBackground
get() = if (isLight) {
// We want LightDesignTokens.colorGray300
Color(0xFFF0F2F5)
} else {
// We want DarkDesignTokens.colorGray400
Color(0xFF26282D)
}
@Preview @Preview
@Composable @Composable
@ -57,7 +82,10 @@ private fun ContentToPreview() {
"roomListRoomName" to MaterialTheme.roomListRoomName(), "roomListRoomName" to MaterialTheme.roomListRoomName(),
"roomListRoomMessage" to MaterialTheme.roomListRoomMessage(), "roomListRoomMessage" to MaterialTheme.roomListRoomMessage(),
"roomListRoomMessageDate" to MaterialTheme.roomListRoomMessageDate(), "roomListRoomMessageDate" to MaterialTheme.roomListRoomMessageDate(),
"roomListUnreadIndicator" to MaterialTheme.roomListUnreadIndicator(), "unreadIndicator" to ElementTheme.colors.unreadIndicator,
"roomListPlaceholder" to ElementTheme.colors.roomListPlaceholder,
"messageFromMeBackground" to ElementTheme.colors.messageFromMeBackground,
"messageFromOtherBackground" to ElementTheme.colors.messageFromOtherBackground,
) )
) )
} }

View file

@ -18,95 +18,6 @@ package io.element.android.libraries.designsystem.theme
import androidx.compose.ui.text.PlatformTextStyle import androidx.compose.ui.text.PlatformTextStyle
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
import com.airbnb.android.showkase.annotation.ShowkaseTypography
/**
* TODO Provide the typo to Material3 theme.
*/
@ShowkaseTypography(name = "H1", group = "Element")
val h1Default: TextStyle = TextStyle(
fontFamily = FontFamily.SansSerif,
fontWeight = FontWeight.Bold,
fontSize = 24.sp
)
@ShowkaseTypography(name = "Body1", group = "Element")
val body1Default: TextStyle = TextStyle(
fontFamily = FontFamily.SansSerif,
fontWeight = FontWeight.Normal,
fontSize = 16.sp
)
@ShowkaseTypography(name = "BodySmall", group = "Element")
val bodySmallDefault: TextStyle = TextStyle(
fontFamily = FontFamily.SansSerif,
fontWeight = FontWeight.Normal,
fontSize = 14.sp
)
@ShowkaseTypography(name = "bodyMedium", group = "Element")
val bodyMediumDefault: TextStyle = TextStyle(
fontFamily = FontFamily.SansSerif,
fontWeight = FontWeight.Normal,
fontSize = 18.sp
)
@ShowkaseTypography(name = "Body Large", group = "Element")
val bodyLargeDefault: TextStyle = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
)
@ShowkaseTypography(name = "Headline Small", group = "Element")
val headlineSmallDefault: TextStyle = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Bold,
fontSize = 24.sp,
lineHeight = 30.sp,
letterSpacing = 1.sp
)
@ShowkaseTypography(name = "Headline Medium", group = "Element")
val headlineMediumDefault: TextStyle = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Bold,
fontSize = 28.sp,
lineHeight = 34.sp,
letterSpacing = 1.sp
)
@ShowkaseTypography(name = "Headline Large", group = "Element")
val headlineLargeDefault: TextStyle = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Bold,
fontSize = 32.sp,
lineHeight = 38.sp,
letterSpacing = 1.sp
)
@ShowkaseTypography(name = "titleSmall", group = "Element")
val titleSmallDefault: TextStyle = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.5.sp
)
@ShowkaseTypography(name = "titleMedium", group = "Element")
val titleMediumDefault: TextStyle = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 18.sp,
lineHeight = 24.sp,
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 // 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. // compose, at which point this can be removed.

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.designsystem.theme.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.widthIn
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.PopupProperties
import io.element.android.libraries.theme.ElementTheme
private val minMenuWidth = 200.dp
@Composable
fun DropdownMenu(
expanded: Boolean,
onDismissRequest: () -> Unit,
modifier: Modifier = Modifier,
// By default add a 16.dp offset to the menu
offset: DpOffset = DpOffset(x = 16.dp, y = 0.dp),
properties: PopupProperties = PopupProperties(focusable = true),
content: @Composable ColumnScope.() -> Unit
) {
val bgColor = if (ElementTheme.isLightTheme) {
ElementTheme.materialColors.background
} else {
ElementTheme.colors.bgSubtlePrimary
}
androidx.compose.material3.DropdownMenu(
expanded = expanded,
onDismissRequest = onDismissRequest,
modifier = modifier
.background(color = bgColor)
.widthIn(min = minMenuWidth),
offset = offset,
properties = properties,
content = content
)
}

View file

@ -0,0 +1,84 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.designsystem.theme.components
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.BugReport
import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.MenuDefaults
import androidx.compose.material3.MenuItemColors
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
import io.element.android.libraries.designsystem.preview.PreviewGroup
import io.element.android.libraries.theme.ElementTheme
@Composable
fun DropdownMenuItem(
text: @Composable () -> Unit,
onClick: () -> Unit,
modifier: Modifier = Modifier,
leadingIcon: @Composable (() -> Unit)? = null,
trailingIcon: @Composable (() -> Unit)? = null,
enabled: Boolean = true,
colors: MenuItemColors = MenuDefaults.itemColors(),
contentPadding: PaddingValues = MenuDefaults.DropdownMenuItemContentPadding,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
) {
androidx.compose.material3.DropdownMenuItem(
text = text,
onClick = onClick,
modifier = modifier,
leadingIcon = leadingIcon,
trailingIcon = trailingIcon,
enabled = enabled,
colors = colors,
contentPadding = contentPadding,
interactionSource = interactionSource
)
}
@Composable
fun DropdownMenuItemText(
text: String,
modifier: Modifier = Modifier,
) {
Text(
text = text,
color = ElementTheme.materialColors.primary,
style = ElementTheme.typography.fontBodyLgRegular,
modifier = modifier,
)
}
@Preview(group = PreviewGroup.Menus)
@Composable
internal fun DropdownMenuItemPreview() = ElementThemedPreview { ContentToPreview() }
@Composable
private fun ContentToPreview() {
DropdownMenuItem(
text = { DropdownMenuItemText(text = "Item") },
onClick = {},
leadingIcon = { Icon(Icons.Default.BugReport, contentDescription = null) },
trailingIcon = { Icon(Icons.Default.Share, contentDescription = null) },
)
}

View file

@ -56,13 +56,18 @@ fun Text(
text: String, text: String,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
color: Color = Color.Unspecified, color: Color = Color.Unspecified,
// Will be removed, only style should be used
fontSize: TextUnit = TextUnit.Unspecified, fontSize: TextUnit = TextUnit.Unspecified,
fontStyle: FontStyle? = null, fontStyle: FontStyle? = null,
// Will be removed, only style should be used
fontWeight: FontWeight? = null, fontWeight: FontWeight? = null,
// Will be removed, only style should be used
fontFamily: FontFamily? = null, fontFamily: FontFamily? = null,
// Will be removed, only style should be used
letterSpacing: TextUnit = TextUnit.Unspecified, letterSpacing: TextUnit = TextUnit.Unspecified,
textDecoration: TextDecoration? = null, textDecoration: TextDecoration? = null,
textAlign: TextAlign? = null, textAlign: TextAlign? = null,
// Will be removed, only style should be used
lineHeight: TextUnit = TextUnit.Unspecified, lineHeight: TextUnit = TextUnit.Unspecified,
overflow: TextOverflow = TextOverflow.Clip, overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true, softWrap: Boolean = true,
@ -97,13 +102,18 @@ fun Text(
text: AnnotatedString, text: AnnotatedString,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
color: Color = Color.Unspecified, color: Color = Color.Unspecified,
// Will be removed, only style should be used
fontSize: TextUnit = TextUnit.Unspecified, fontSize: TextUnit = TextUnit.Unspecified,
fontStyle: FontStyle? = null, fontStyle: FontStyle? = null,
// Will be removed, only style should be used
fontWeight: FontWeight? = null, fontWeight: FontWeight? = null,
// Will be removed, only style should be used
fontFamily: FontFamily? = null, fontFamily: FontFamily? = null,
// Will be removed, only style should be used
letterSpacing: TextUnit = TextUnit.Unspecified, letterSpacing: TextUnit = TextUnit.Unspecified,
textDecoration: TextDecoration? = null, textDecoration: TextDecoration? = null,
textAlign: TextAlign? = null, textAlign: TextAlign? = null,
// Will be removed, only style should be used
lineHeight: TextUnit = TextUnit.Unspecified, lineHeight: TextUnit = TextUnit.Unspecified,
overflow: TextOverflow = TextOverflow.Clip, overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true, softWrap: Boolean = true,

View file

@ -19,8 +19,6 @@ package io.element.android.libraries.designsystem.theme.components.previews
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowRight import androidx.compose.material.icons.filled.ArrowRight
import androidx.compose.material.icons.filled.Favorite import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@ -30,6 +28,9 @@ import androidx.compose.ui.tooling.preview.Preview
import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.ElementThemedPreview
import io.element.android.libraries.designsystem.preview.PreviewGroup import io.element.android.libraries.designsystem.preview.PreviewGroup
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.DropdownMenu
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItemText
import io.element.android.libraries.designsystem.theme.components.Icon 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.components.Text
@ -59,7 +60,7 @@ internal fun MenuPreview() {
null null
} }
DropdownMenuItem( DropdownMenuItem(
text = { Text(text = "Item $i") }, text = { DropdownMenuItemText(text = "Item $i") },
onClick = { isExpanded = false }, onClick = { isExpanded = false },
leadingIcon = leadingIcon, leadingIcon = leadingIcon,
trailingIcon = trailingIcon, trailingIcon = trailingIcon,

View file

@ -16,6 +16,8 @@
package io.element.android.libraries.textcomposer package io.element.android.libraries.textcomposer
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
@ -44,11 +46,13 @@ import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
@ -58,9 +62,9 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
@ -81,8 +85,9 @@ import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.coroutines.android.awaitFrame
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable @Composable
fun TextComposer( fun TextComposer(
composerText: String?, composerText: String?,
@ -106,21 +111,31 @@ fun TextComposer(
AttachmentButton(onClick = onAddAttachment, modifier = Modifier.padding(vertical = 6.dp)) AttachmentButton(onClick = onAddAttachment, modifier = Modifier.padding(vertical = 6.dp))
Spacer(modifier = Modifier.width(12.dp)) Spacer(modifier = Modifier.width(12.dp))
var lineCount by remember { mutableStateOf(0) } var lineCount by remember { mutableStateOf(0) }
val roundedCorners = remember(lineCount, composerMode) { val roundedCornerSize = remember(lineCount, composerMode) {
if (lineCount > 1 || composerMode is MessageComposerMode.Special) { if (lineCount > 1 || composerMode is MessageComposerMode.Special) {
RoundedCornerShape(20.dp) 20.dp
} else { } else {
RoundedCornerShape(28.dp) 28.dp
} }
} }
val roundedCornerSizeState = animateDpAsState(
targetValue = roundedCornerSize,
animationSpec = tween(
durationMillis = 100,
)
)
val roundedCorners = RoundedCornerShape(roundedCornerSizeState.value)
val minHeight = 42.dp val minHeight = 42.dp
val bgColor = ElementTheme.colors.bgSubtleSecondary
// Change border color depending on focus
var hasFocus by remember { mutableStateOf(false) }
val borderColor = if (hasFocus) ElementTheme.colors.borderDisabled else bgColor
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.clip(roundedCorners) .clip(roundedCorners)
.background(MaterialTheme.colorScheme.surfaceVariant) .background(color = bgColor)
.border(1.dp, MaterialTheme.colorScheme.outlineVariant, roundedCorners) .border(1.dp, borderColor, roundedCorners)
) { ) {
if (composerMode is MessageComposerMode.Special) { if (composerMode is MessageComposerMode.Special) {
ComposerModeView(composerMode = composerMode, onResetComposerMode = onResetComposerMode) ComposerModeView(composerMode = composerMode, onResetComposerMode = onResetComposerMode)
@ -132,7 +147,10 @@ fun TextComposer(
.fillMaxWidth() .fillMaxWidth()
.heightIn(min = minHeight) .heightIn(min = minHeight)
.focusRequester(focusRequester) .focusRequester(focusRequester)
.onFocusEvent { onFocusChanged(it.hasFocus) }, .onFocusEvent {
hasFocus = it.hasFocus
onFocusChanged(it.hasFocus)
},
value = text, value = text,
onValueChange = { onComposerTextChange(it) }, onValueChange = { onComposerTextChange(it) },
onTextLayout = { onTextLayout = {
@ -156,16 +174,16 @@ fun TextComposer(
colors = TextFieldDefaults.colors( colors = TextFieldDefaults.colors(
unfocusedTextColor = MaterialTheme.colorScheme.secondary, unfocusedTextColor = MaterialTheme.colorScheme.secondary,
focusedTextColor = MaterialTheme.colorScheme.primary, focusedTextColor = MaterialTheme.colorScheme.primary,
unfocusedPlaceholderColor = MaterialTheme.colorScheme.secondary, unfocusedPlaceholderColor = ElementTheme.colors.textDisabled,
focusedPlaceholderColor = MaterialTheme.colorScheme.secondary, focusedPlaceholderColor = ElementTheme.colors.textDisabled,
unfocusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent,
focusedIndicatorColor = Color.Transparent, focusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent, disabledIndicatorColor = Color.Transparent,
errorIndicatorColor = Color.Transparent, errorIndicatorColor = Color.Transparent,
unfocusedContainerColor = MaterialTheme.colorScheme.surfaceVariant, unfocusedContainerColor = bgColor,
focusedContainerColor = MaterialTheme.colorScheme.surfaceVariant, focusedContainerColor = bgColor,
errorContainerColor = MaterialTheme.colorScheme.surfaceVariant, errorContainerColor = bgColor,
disabledContainerColor = MaterialTheme.colorScheme.surfaceVariant, disabledContainerColor = bgColor,
) )
) )
} }
@ -181,6 +199,18 @@ fun TextComposer(
} }
} }
} }
// Request focus when changing mode, and show keyboard.
val keyboard = LocalSoftwareKeyboardController.current
LaunchedEffect(composerMode) {
if (composerMode is MessageComposerMode.Special) {
focusRequester.requestFocus()
keyboard?.let {
awaitFrame()
it.show()
}
}
}
} }
@Composable @Composable
@ -212,29 +242,35 @@ private fun EditingModeView(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
Row( Row(
horizontalArrangement = Arrangement.spacedBy(6.dp), horizontalArrangement = Arrangement.spacedBy(5.dp),
verticalAlignment = Alignment.CenterVertically,
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 12.dp, vertical = 8.dp) .padding(start = 12.dp)
) { ) {
Icon( Icon(
resourceId = VectorIcons.Edit, resourceId = VectorIcons.Edit,
contentDescription = stringResource(CommonStrings.common_editing), contentDescription = stringResource(CommonStrings.common_editing),
tint = MaterialTheme.colorScheme.secondary, tint = ElementTheme.materialColors.secondary,
modifier = Modifier.size(16.dp), modifier = Modifier
.padding(vertical = 8.dp)
.size(16.dp),
) )
Text( Text(
stringResource(CommonStrings.common_editing), stringResource(CommonStrings.common_editing),
style = ElementTextStyles.Regular.caption2, style = ElementTheme.typography.fontBodySmRegular,
textAlign = TextAlign.Start, textAlign = TextAlign.Start,
color = MaterialTheme.colorScheme.secondary, color = ElementTheme.materialColors.secondary,
modifier = Modifier.weight(1f) modifier = Modifier
.padding(vertical = 8.dp)
.weight(1f)
) )
Icon( Icon(
imageVector = Icons.Default.Close, imageVector = Icons.Default.Close,
contentDescription = stringResource(CommonStrings.action_close), contentDescription = stringResource(CommonStrings.action_close),
tint = MaterialTheme.colorScheme.secondary, tint = ElementTheme.materialColors.secondary,
modifier = Modifier modifier = Modifier
.padding(top = 8.dp, bottom = 8.dp, start = 16.dp, end = 12.dp)
.size(16.dp) .size(16.dp)
.clickable( .clickable(
enabled = true, enabled = true,
@ -242,8 +278,7 @@ private fun EditingModeView(
interactionSource = MutableInteractionSource(), interactionSource = MutableInteractionSource(),
indication = rememberRipple(bounded = false) indication = rememberRipple(bounded = false)
), ),
)
)
} }
} }
@ -279,17 +314,16 @@ private fun ReplyToModeView(
Text( Text(
text = senderName, text = senderName,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
style = ElementTextStyles.Regular.caption2.copy(fontWeight = FontWeight.Medium), style = ElementTheme.typography.fontBodySmMedium,
textAlign = TextAlign.Start, textAlign = TextAlign.Start,
color = MaterialTheme.colorScheme.primary, color = ElementTheme.materialColors.primary,
) )
Text( Text(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
text = text.orEmpty(), text = text.orEmpty(),
style = ElementTextStyles.Regular.caption1, style = ElementTheme.typography.fontBodyMdRegular,
textAlign = TextAlign.Start, textAlign = TextAlign.Start,
color = MaterialTheme.colorScheme.secondary, color = ElementTheme.materialColors.secondary,
maxLines = if (attachmentThumbnailInfo != null) 1 else 2, maxLines = if (attachmentThumbnailInfo != null) 1 else 2,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
@ -316,24 +350,22 @@ private fun AttachmentButton(
onClick: () -> Unit, onClick: () -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
Box(modifier) { Surface(
Surface( modifier
Modifier .size(30.dp)
.size(30.dp) .clickable(onClick = onClick),
.clickable(true, onClick = onClick), shape = CircleShape,
shape = CircleShape, color = ElementTheme.colors.iconPrimary
color = MaterialTheme.colorScheme.primary ) {
) { Image(
Image( modifier = Modifier.size(12.5f.dp),
modifier = Modifier.size(12.5f.dp), painter = painterResource(R.drawable.ic_add_attachment),
painter = painterResource(R.drawable.ic_add_attachment), contentDescription = null,
contentDescription = null, contentScale = ContentScale.Inside,
contentScale = ContentScale.Inside, colorFilter = ColorFilter.tint(
colorFilter = ColorFilter.tint( LocalContentColor.current
LocalContentColor.current
)
) )
} )
} }
} }
@ -349,7 +381,7 @@ private fun BoxScope.SendButton(
Box( Box(
modifier = modifier modifier = modifier
.clip(CircleShape) .clip(CircleShape)
.background(if (canSendMessage) ElementTheme.legacyColors.accentColor else Color.Transparent) .background(if (canSendMessage) ElementTheme.colors.iconAccentTertiary else Color.Transparent)
.size(30.dp) .size(30.dp)
.align(Alignment.BottomEnd) .align(Alignment.BottomEnd)
.applyIf(composerMode !is MessageComposerMode.Edit, ifTrue = { .applyIf(composerMode !is MessageComposerMode.Edit, ifTrue = {
@ -376,7 +408,8 @@ private fun BoxScope.SendButton(
modifier = Modifier.size(16.dp), modifier = Modifier.size(16.dp),
resourceId = iconId, resourceId = iconId,
contentDescription = contentDescription, contentDescription = contentDescription,
tint = if (canSendMessage) Color.White else ElementTheme.legacyColors.quaternary // Exception here, we use Color.White instead of ElementTheme.colors.iconOnSolidPrimary
tint = if (canSendMessage) Color.White else ElementTheme.colors.iconDisabled
) )
} }
} }

View file

@ -37,9 +37,6 @@ import io.element.android.libraries.theme.compound.generated.SemanticColors
@Deprecated("Use SemanticColors instead") @Deprecated("Use SemanticColors instead")
@Stable @Stable
class ElementColors( class ElementColors(
messageFromMeBackground: Color,
messageFromOtherBackground: Color,
messageHighlightedBackground: Color,
quaternary: Color, quaternary: Color,
quinary: Color, quinary: Color,
gray300: Color, gray300: Color,
@ -47,13 +44,6 @@ class ElementColors(
placeholder: Color, placeholder: Color,
isLight: Boolean isLight: Boolean
) { ) {
var messageFromMeBackground by mutableStateOf(messageFromMeBackground)
private set
var messageFromOtherBackground by mutableStateOf(messageFromOtherBackground)
private set
var messageHighlightedBackground by mutableStateOf(messageHighlightedBackground)
private set
var quaternary by mutableStateOf(quaternary) var quaternary by mutableStateOf(quaternary)
private set private set
@ -73,9 +63,6 @@ class ElementColors(
private set private set
fun copy( fun copy(
messageFromMeBackground: Color = this.messageFromMeBackground,
messageFromOtherBackground: Color = this.messageFromOtherBackground,
messageHighlightedBackground: Color = this.messageHighlightedBackground,
quaternary: Color = this.quaternary, quaternary: Color = this.quaternary,
quinary: Color = this.quinary, quinary: Color = this.quinary,
gray300: Color = this.gray300, gray300: Color = this.gray300,
@ -83,9 +70,6 @@ class ElementColors(
placeholder: Color = this.placeholder, placeholder: Color = this.placeholder,
isLight: Boolean = this.isLight, isLight: Boolean = this.isLight,
) = ElementColors( ) = ElementColors(
messageFromMeBackground = messageFromMeBackground,
messageFromOtherBackground = messageFromOtherBackground,
messageHighlightedBackground = messageHighlightedBackground,
quaternary = quaternary, quaternary = quaternary,
quinary = quinary, quinary = quinary,
gray300 = gray300, gray300 = gray300,
@ -95,9 +79,6 @@ class ElementColors(
) )
fun updateColorsFrom(other: ElementColors) { fun updateColorsFrom(other: ElementColors) {
messageFromMeBackground = other.messageFromMeBackground
messageFromOtherBackground = other.messageFromOtherBackground
messageHighlightedBackground = other.messageHighlightedBackground
quaternary = other.quaternary quaternary = other.quaternary
quinary = other.quinary quinary = other.quinary
gray300 = other.gray300 gray300 = other.gray300
@ -108,9 +89,6 @@ class ElementColors(
} }
internal fun elementColorsLight() = ElementColors( internal fun elementColorsLight() = ElementColors(
messageFromMeBackground = SystemGrey5Light,
messageFromOtherBackground = SystemGrey6Light,
messageHighlightedBackground = Azure,
quaternary = Gray_100, quaternary = Gray_100,
quinary = Gray_50, quinary = Gray_50,
gray300 = LightDesignTokens.colorGray300, gray300 = LightDesignTokens.colorGray300,
@ -120,9 +98,6 @@ internal fun elementColorsLight() = ElementColors(
) )
internal fun elementColorsDark() = ElementColors( internal fun elementColorsDark() = ElementColors(
messageFromMeBackground = SystemGrey5Dark,
messageFromOtherBackground = SystemGrey6Dark,
messageHighlightedBackground = Azure,
quaternary = Gray_400, quaternary = Gray_400,
quinary = Gray_450, quinary = Gray_450,
gray300 = DarkDesignTokens.colorGray300, gray300 = DarkDesignTokens.colorGray300,

View file

@ -32,9 +32,6 @@ val LightGrey = Color(0x993C3C43)
@ShowkaseColor(name = "DarkGrey", group = "Material Design") @ShowkaseColor(name = "DarkGrey", group = "Material Design")
val DarkGrey = Color(0x99EBEBF5) val DarkGrey = Color(0x99EBEBF5)
val AvatarGradientStart = Color(0xFF4CA1AF)
val AvatarGradientEnd = Color(0xFFC4E0E5)
val SystemGreyLight = Color(0xFF8E8E93) val SystemGreyLight = Color(0xFF8E8E93)
val SystemGreyDark = Color(0xFF8E8E93) val SystemGreyDark = Color(0xFF8E8E93)
val SystemGrey2Light = Color(0xFFAEAEB2) val SystemGrey2Light = Color(0xFFAEAEB2)

View file

@ -89,7 +89,8 @@ internal val compoundColorsDark = SemanticColors(
textInfoPrimary = DarkDesignTokens.colorBlue900, textInfoPrimary = DarkDesignTokens.colorBlue900,
textOnSolidPrimary = DarkDesignTokens.colorThemeBg, textOnSolidPrimary = DarkDesignTokens.colorThemeBg,
bgSubtlePrimary = DarkDesignTokens.colorGray400, bgSubtlePrimary = DarkDesignTokens.colorGray400,
bgSubtleSecondary = DarkDesignTokens.colorBgSubtleSecondaryLevel0, // The value DarkDesignTokens.colorBgSubtleSecondaryLevel0 is defined to colorThemeBg, this is not correct, so override the value here until this is fixed,
bgSubtleSecondary = DarkDesignTokens.colorGray300, // DarkDesignTokens.colorBgSubtleSecondaryLevel0
bgCanvasDefault = DarkDesignTokens.colorBgCanvasDefaultLevel1, bgCanvasDefault = DarkDesignTokens.colorBgCanvasDefaultLevel1,
bgCanvasDisabled = DarkDesignTokens.colorGray200, bgCanvasDisabled = DarkDesignTokens.colorGray200,
bgActionPrimaryRest = DarkDesignTokens.colorGray1400, bgActionPrimaryRest = DarkDesignTokens.colorGray1400,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:14da396544c0accc0229fa249c43caa70d105482d34290edac22047891386ff7 oid sha256:db05c9dc303b03a8965e199981cb786491fcf814bf78244b3fc5b7e323807700
size 39928 size 28097

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:adabf8c147f6122a180db6f2b44fcd85b2b08ec6651acb7b3519e5a821045f4a oid sha256:bdb04dc4e9f047baa6209478c3083c80738e208938d2f25df282fb84dd3aecd0
size 39902 size 28855

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:cc235fc17b0eaaacf1a2dc6ec4759372d29cd4ba0741f7f6f57a9bb9a460c806 oid sha256:d8b15997a41e7ba655990243c5347aa87d59811a727b034a7b52e99b074e6648
size 101302 size 88860

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:7a6baba1197b01eb91e2dc6720482b97d9d0cdd5aaffa0d19d3e6b0860dadcf8 oid sha256:153fe6422f5248b250096a7ef51a2b89c970f47bca5a24d0938632d08f9e96e2
size 52502 size 46872

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:3eddd53d1e02f314d219ad3c7a935149a973ecf47603a3dd0492053f0e174668 oid sha256:e7642a1adb1faec60a301ee86bb34558ea71d15f4fbd3d5ddd5d1661249b725a
size 35977 size 25759

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:9db3469badeb7f71b5f9cb6df6b230158f8d383e48dae2b615e94b885b1f2145 oid sha256:b0457439922b1990f6fd72449c6f4042b72755e09ab9f3c9c8a8c03c9fc925eb
size 81076 size 63888

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:7ab609e664a3fb0f258b99414b799e591161876d348d1c35f03ece1a57d6dce1 oid sha256:98c56ef886a3d1b6b3109bb835e587176f4e420bb05057dc150c82153605f7d1
size 91478 size 67794

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:e00be325947e9ef638fdabd178b70da994a5b78f82ebfa199d469883b156e8bb oid sha256:f467065bb9c78d0e95a8a688bfc50edce522b2832c9a53e5a68899e843a988ca
size 35205 size 25859

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:f85f0a3b5bb3edd6d864a2a211437a278f6bb7a9b66367a9ed4d596f673dc197 oid sha256:a2ba6ed9981ea1ad3f0cdf76d600d6a51daf58a04f15c5bf23713c7f31e84b94
size 80258 size 65471

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:8defc1027b2a97aeca89c7f969d458afbcbb4f0ed3e4474046e1242ceec8d80d oid sha256:c1f75b3ada8d9462a23b7defd26ac16562ff6ccf9babfcc7330286712ceb805e
size 90196 size 69581

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:5847edfd77fe888d3da67fc27c72a9dd40b78ebede21483a48394ee5859197a7 oid sha256:8d04e77e3a7e7862f29868be068df658382ed7dec94fcea86665bbd5074591bd
size 93560 size 82804

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:1b42685b2852d5d45eee744a98dba74a5f26ddc1fb88960a7c23d4e335a75369 oid sha256:4f8de89448ff5f4f95c7611657e38e0ba75c2f503b82fb04f584f3116353ae51
size 95600 size 85954

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:8b275a7d15d76711cc2eaa00e819a573e50ddff699f82b2b0e65ec8489547732 oid sha256:b2567be3b27bb2ea979b7da492fb059e87b25c5938c07aacaa621a97685bacd5
size 22163 size 21095

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:5b7247bd672cf5a4ed121d65369c0825a01be379773ca696038eadf4f23269b7 oid sha256:300883c3e49ff5e655952cf2b5a0a194718fde9c6fd289c3125e4cd3609cea00
size 27606 size 26379

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:f6c09f5e6fb876196e5b6db3ea0f562a2ff04c48a5858a939f2765d41b1c4e13 oid sha256:e80d2a64eb4c39e117dbd3bdd6b1b45b19a99f8e1ccb905547f82096fae8510d
size 22314 size 21465

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:2eca0c7ce88cf3ccb13fc1a7f52c96922c417f8cfb951f25db91c20c1714771a oid sha256:1b91f0e2d72bf5b12430183ccb98cb30e1e0ab3859472c5a6368b5cca1ceb33c
size 28472 size 27574

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:d4479241e4fc5c15ec6c2122d1eaafd9f2fe79a9235fd25f215f850e0b852f03 oid sha256:4233e67a2f27e3e73924b9af5f43d0e877a397f4a2ee3f8d436a713e1d2b3c0c
size 31269 size 28738

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:9ea5f4da6a888551e2e91a8b594fcc090cf806a56df315c5607abcb5e4f12495 oid sha256:69b2702985d50fedbb720e86eef63c2734e328d8537c6a8f644fcf75c7e710a8
size 36839 size 32883

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:0f58fe221866c9d199645ef71cc5d38aa1fef67e49f74bed5e042ae5ce1f3a5d oid sha256:76681a4959008b8646273424cd50566d7c868620938e07849da596ccd3172781
size 36803 size 33020

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:aa16a4c974eaee9e02b734db508ab04f4ff87ef6d22ae64d0841e63ad37967e3 oid sha256:0052281199753556fd2d8ed411360ee15e5019e2ddd3ec2b1a9695c81be3a233
size 17760 size 14402

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:b0601334a2e45adfd5488e99175156a0e14fdb83fcc292173812fd4232ccc528 oid sha256:57878214b3949c4eaa782f763095e9e8234a979e0e7fe83fcf1e5083bfb32bf0
size 31374 size 28878

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:c13288bd03da93cdbc6969ef4b9a0a317da9802a1b02ce41cf305b42146a1f46 oid sha256:9482e9994ab5c2367d52811fa72559d9c1660e517b5d242e7d714f3e84ba03c5
size 32673 size 29271

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:0457a0275d880dc738fb60ae9e53b3d1d7630592d2107a0dd03b3cb80685b0cc oid sha256:9bb46ebec6a9fbdab74f9634d1c834c52c1f690183b3b360e24c79012ed3a192
size 37881 size 34823

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:e0ae1dba87aa070607268c0243f18301c7ebf0b23cebe91bc1b668eda9da0025 oid sha256:fca36d620adf924e4c6605832dea8df4f2b87e7ac472c98a5ffae0056816be8a
size 37867 size 34944

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:0bde7c2be2ae19012c6f8df9626bc0d912e2899239fe5527865980dbe02cfee7 oid sha256:9b202f4160bdb58a9e87cfc66f11a5aaf66a90591c978dfc797b3cf351c94103
size 17384 size 14396

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:79a9749e15d3875d95602a325f6238ad666d7acfa9256d6865c1b6492ec74cdf oid sha256:afc363e9509019637ad9a7b4120462e1b2679d02a4b815c5840a83336cb9616a
size 32815 size 29654

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:30856dd6b233c75f387d9160ee3700c21e197f1a17b85da8b654042a1b88601c oid sha256:6ab4fab7980768994954a4089ff32116f28ec46f89ed30474ab45239d39f448c
size 63741 size 52948

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:466ef043bc10bc265c928e12464c0d42007dd3f15dbca8f7e352169754c58ee2 oid sha256:20be7d313c5058ce7016ec573a9db05387df0dc4c41aab07200a2c3f55b35d55
size 46836 size 43832

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:f3bfe2e04da74cb561dddb85cdb36c31ebee2e05ab96fc821bb7d26133826d52 oid sha256:c6db133ab25a03de88c6153ce6adc58c834539b2c85e35c1438bb55cdb91abe5
size 47264 size 44271

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:1657e4438b39cbf720e2ec0d488a40e841e9c2b518e4f663dfe7cde0f9c862c2 oid sha256:bd2fd38fd3cf6eaa78de876cace7c614680108c3ed0eeb634ebaf9e004840f98
size 42308 size 37575

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:1657e4438b39cbf720e2ec0d488a40e841e9c2b518e4f663dfe7cde0f9c862c2 oid sha256:bd2fd38fd3cf6eaa78de876cace7c614680108c3ed0eeb634ebaf9e004840f98
size 42308 size 37575

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:dae7690e7f01647a4711b3940ca15549fe7ecf9043dd6ef2066b144561398608 oid sha256:04357ef36543729e5ed5794f3624194315080b9a5bc6024235a131e009e5a922
size 64708 size 55391

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:4b1407a9001ed72fcc8bbedafcdc9233d9c3e2bc7996fd8a4e549c4e7f8d6e1d oid sha256:506d061e8004745bf7c1472d1a96702ef9b47e60e99839e7cab8f16071b88b1d
size 48179 size 45813

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:630eb1ea4c3979e6e6ad4fcc48eaea723798c85ffb703670566957e42385ae98 oid sha256:3f58db0ddc56fc3e6178f4aafbdd0501a5bba129068420cab0c3b8cfadc33b50
size 48616 size 46244

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:66fc42a41b1e0c3abf2edb465f986f722d3558179bc3ebcbf0740e9bc794d62c oid sha256:289b4fb5dc4c0a27deec988f8810584162451c763760d1e9ee66da367f869c6e
size 43023 size 39173

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:66fc42a41b1e0c3abf2edb465f986f722d3558179bc3ebcbf0740e9bc794d62c oid sha256:289b4fb5dc4c0a27deec988f8810584162451c763760d1e9ee66da367f869c6e
size 43023 size 39173

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:7c3a97e67ebd54d043dfb09c773ab74e927c48517ce07cd87452c69bb96cb228 oid sha256:5ce2edea622636c3709d7da3d01c931a2ced65d31738d9cfc9e5f318a374ca30
size 38498 size 37850

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:af4ab5ef652b71f295d02d69f19e8dca81ef1929c6b6c5b85f66b53da62811fb oid sha256:aa58a3f5fa6ee6e9a7f89f87a64b7b43577fca75cd44193b521875c8d6a184e3
size 43427 size 43823

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:f28ac645ba2e330a8cdbdc8e26040a1f3c02e0e647975bfbed5e7dc175bd372b oid sha256:50cbc5955836725e0f58f2058e2c43cce0639c122036470fac58b89f3208c7f2
size 43769 size 44139

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:0e32044f02911fa178f7030eab11ccd04bd02f82811eb86aeb585d5116e76d75 oid sha256:e6787391e332dcf4dd0998c18447962a1ee03314e276f6b7d0a6bd6717f30f43
size 37682 size 38214

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:079c29fb8bc0bc1d8c8899a0ec13d997127d57d5d49ad04906247038f8b39d2f oid sha256:acaa3c96e40cd2d2d0cace906e87a6e36801a0836b1eff059a2f0a031e41ddd8
size 39196 size 38770

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:b5623e3f37e2aa89cdce2a8d1181c8f417fa05917bf62fc46b541b86d140a780 oid sha256:b0ac4827780ad236721b793b1d07a3f7ee514811ca3d8f29c8d447cdb99e739e
size 44611 size 45293

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:ce0bbe6be7ede759386ef4c56afef4f419ee0c6264bc80b22a3a2b563a170807 oid sha256:57f7684c300496d7c8ca31e500b2191b85e3bc2ecbce489e77f1c71edec3d877
size 45096 size 45790

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:9ccef4dc0eed428153c228253c198dcfb7ff5c18d6e6a44d31dff6ac548f4f61 oid sha256:fb973d123139c6da77e5b764cbca51866310ea81caf7057c584064677d2deff8
size 38558 size 39233

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:b75570c52aeecb3a377dbf54cc53b439b040ddd66f44b18ae358ee61887067bf oid sha256:245701b0b6fbb5f886af725435ea62ac2ed2164ae51cc74ed3560c49d5692144
size 30316 size 26585

Some files were not shown because too many files have changed in this diff Show more