mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 21:32:34 +00:00
Merge branch 'develop' into feature/fga/set_user_status
This commit is contained in:
+10
-4
@@ -8,7 +8,9 @@
|
||||
|
||||
package io.element.android.libraries.designsystem.atomic.atoms
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.size
|
||||
@@ -34,14 +36,17 @@ fun UnreadIndicatorAtom(
|
||||
color: Color = ElementTheme.colors.unreadIndicator,
|
||||
isVisible: Boolean = true,
|
||||
contentDescription: String? = null,
|
||||
border: BorderStroke? = null,
|
||||
) {
|
||||
when {
|
||||
!isVisible -> Spacer(modifier = modifier.size(size))
|
||||
count != null && count >= 1 -> CounterAtom(
|
||||
count = count.toInt(),
|
||||
modifier = modifier.semantics {
|
||||
contentDescription?.let { this.contentDescription = it }
|
||||
},
|
||||
modifier = modifier
|
||||
.semantics {
|
||||
contentDescription?.let { this.contentDescription = it }
|
||||
}
|
||||
.then(if (border != null) Modifier.border(border, CircleShape) else Modifier),
|
||||
containerColor = color,
|
||||
contentColor = ElementTheme.colors.bgCanvasDefault,
|
||||
textStyle = ElementTheme.typography.fontBodySmMedium,
|
||||
@@ -53,7 +58,8 @@ fun UnreadIndicatorAtom(
|
||||
}
|
||||
.size(size)
|
||||
.clip(CircleShape)
|
||||
.background(color),
|
||||
.background(color)
|
||||
.then(if (border != null) Modifier.border(border, CircleShape) else Modifier),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-3
@@ -17,7 +17,8 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.material3.SheetValue
|
||||
import androidx.compose.material3.rememberBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
|
||||
@@ -39,7 +40,10 @@ fun SimpleModalBottomSheet(
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = onDismiss,
|
||||
modifier = modifier,
|
||||
sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true),
|
||||
sheetState = rememberBottomSheetState(
|
||||
initialValue = SheetValue.Hidden,
|
||||
enabledValues = setOf(SheetValue.Hidden, SheetValue.Expanded),
|
||||
),
|
||||
scrollable = false,
|
||||
) {
|
||||
Column(
|
||||
@@ -61,7 +65,7 @@ fun SimpleModalBottomSheet(
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun SimpleModalBottomSheetPreview() = ElementPreview {
|
||||
internal fun SimpleModalBottomSheetPreview() = ElementPreview(fillMaxSize = true) {
|
||||
SimpleModalBottomSheet(title = "A title", onDismiss = {}) {
|
||||
Text(
|
||||
text = LoremIpsum(20).values.first(),
|
||||
|
||||
+18
-28
@@ -6,25 +6,19 @@
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.atomic.organisms
|
||||
package io.element.android.libraries.designsystem.components.visuallist
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.atomic.molecules.InfoListItemMolecule
|
||||
import io.element.android.libraries.designsystem.atomic.molecules.InfoListItemPosition
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
@@ -32,14 +26,17 @@ import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
/**
|
||||
* Ref: https://www.figma.com/design/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?node-id=2001-140
|
||||
*/
|
||||
@Composable
|
||||
fun InfoListOrganism(
|
||||
items: ImmutableList<InfoListItem>,
|
||||
fun VisualList(
|
||||
items: ImmutableList<VisualListItemData>,
|
||||
modifier: Modifier = Modifier,
|
||||
backgroundColor: Color = ElementTheme.colors.bgSubtleSecondary,
|
||||
iconTint: Color = LocalContentColor.current,
|
||||
iconTint: Color = ElementTheme.colors.iconSecondary,
|
||||
iconSize: Dp = 20.dp,
|
||||
textStyle: TextStyle = LocalTextStyle.current,
|
||||
textStyle: TextStyle = ElementTheme.typography.fontBodyMdMedium,
|
||||
textColor: Color = ElementTheme.colors.textPrimary,
|
||||
verticalArrangement: Arrangement.Vertical = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
@@ -49,12 +46,12 @@ fun InfoListOrganism(
|
||||
) {
|
||||
for ((index, item) in items.withIndex()) {
|
||||
val position = when {
|
||||
items.size == 1 -> InfoListItemPosition.Single
|
||||
index == 0 -> InfoListItemPosition.Top
|
||||
index == items.size - 1 -> InfoListItemPosition.Bottom
|
||||
else -> InfoListItemPosition.Middle
|
||||
items.size == 1 -> VisualListItemPosition.Single
|
||||
index == 0 -> VisualListItemPosition.Top
|
||||
index == items.size - 1 -> VisualListItemPosition.Bottom
|
||||
else -> VisualListItemPosition.Middle
|
||||
}
|
||||
InfoListItemMolecule(
|
||||
VisualListItem(
|
||||
message = {
|
||||
if (item.message is AnnotatedString) {
|
||||
Text(
|
||||
@@ -96,22 +93,15 @@ fun InfoListOrganism(
|
||||
}
|
||||
}
|
||||
|
||||
data class InfoListItem(
|
||||
val message: CharSequence,
|
||||
@DrawableRes val iconId: Int? = null,
|
||||
val iconVector: ImageVector? = null,
|
||||
val iconComposable: @Composable () -> Unit = {},
|
||||
)
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun InfoListOrganismPreview() = ElementPreview {
|
||||
internal fun VisualListPreview() = ElementPreview {
|
||||
val items = persistentListOf(
|
||||
InfoListItem(message = "A top item"),
|
||||
InfoListItem(message = "A middle item"),
|
||||
InfoListItem(message = "A bottom item"),
|
||||
VisualListItemData(message = "A top item"),
|
||||
VisualListItemData(message = "A middle item"),
|
||||
VisualListItemData(message = "A bottom item"),
|
||||
)
|
||||
InfoListOrganism(
|
||||
VisualList(
|
||||
items = items,
|
||||
)
|
||||
}
|
||||
+20
-17
@@ -6,7 +6,7 @@
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.atomic.molecules
|
||||
package io.element.android.libraries.designsystem.components.visuallist
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@@ -27,10 +27,13 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
|
||||
/**
|
||||
* Ref: https://www.figma.com/design/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?node-id=2001-159
|
||||
*/
|
||||
@Composable
|
||||
fun InfoListItemMolecule(
|
||||
fun VisualListItem(
|
||||
message: @Composable () -> Unit,
|
||||
position: InfoListItemPosition,
|
||||
position: VisualListItemPosition,
|
||||
backgroundColor: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
icon: @Composable () -> Unit = {},
|
||||
@@ -38,10 +41,10 @@ fun InfoListItemMolecule(
|
||||
val radius = 14.dp
|
||||
val backgroundShape = remember(position) {
|
||||
when (position) {
|
||||
InfoListItemPosition.Single -> RoundedCornerShape(radius)
|
||||
InfoListItemPosition.Top -> RoundedCornerShape(topStart = radius, topEnd = radius)
|
||||
InfoListItemPosition.Middle -> RoundedCornerShape(0.dp)
|
||||
InfoListItemPosition.Bottom -> RoundedCornerShape(bottomStart = radius, bottomEnd = radius)
|
||||
VisualListItemPosition.Single -> RoundedCornerShape(radius)
|
||||
VisualListItemPosition.Top -> RoundedCornerShape(topStart = radius, topEnd = radius)
|
||||
VisualListItemPosition.Middle -> RoundedCornerShape(0.dp)
|
||||
VisualListItemPosition.Bottom -> RoundedCornerShape(bottomStart = radius, bottomEnd = radius)
|
||||
}
|
||||
}
|
||||
Row(
|
||||
@@ -61,42 +64,42 @@ fun InfoListItemMolecule(
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun InfoListItemMoleculePreview() {
|
||||
internal fun VisualListItemPreview() {
|
||||
ElementPreview {
|
||||
val color = ElementTheme.colors.bgSubtleSecondary
|
||||
Column(
|
||||
modifier = Modifier.padding(10.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
InfoListItemMolecule(
|
||||
VisualListItem(
|
||||
message = { Text("A single item") },
|
||||
icon = { Icon(imageVector = CompoundIcons.InfoSolid(), contentDescription = null) },
|
||||
position = InfoListItemPosition.Single,
|
||||
position = VisualListItemPosition.Single,
|
||||
backgroundColor = color,
|
||||
)
|
||||
InfoListItemMolecule(
|
||||
VisualListItem(
|
||||
message = { Text("A top item") },
|
||||
icon = { Icon(imageVector = CompoundIcons.InfoSolid(), contentDescription = null) },
|
||||
position = InfoListItemPosition.Top,
|
||||
position = VisualListItemPosition.Top,
|
||||
backgroundColor = color,
|
||||
)
|
||||
InfoListItemMolecule(
|
||||
VisualListItem(
|
||||
message = { Text("A middle item") },
|
||||
icon = { Icon(imageVector = CompoundIcons.InfoSolid(), contentDescription = null) },
|
||||
position = InfoListItemPosition.Middle,
|
||||
position = VisualListItemPosition.Middle,
|
||||
backgroundColor = color,
|
||||
)
|
||||
InfoListItemMolecule(
|
||||
VisualListItem(
|
||||
message = { Text("A bottom item") },
|
||||
icon = { Icon(imageVector = CompoundIcons.InfoSolid(), contentDescription = null) },
|
||||
position = InfoListItemPosition.Bottom,
|
||||
position = VisualListItemPosition.Bottom,
|
||||
backgroundColor = color,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class InfoListItemPosition {
|
||||
enum class VisualListItemPosition {
|
||||
Top,
|
||||
Middle,
|
||||
Bottom,
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.components.visuallist
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
|
||||
data class VisualListItemData(
|
||||
val message: CharSequence,
|
||||
@DrawableRes val iconId: Int? = null,
|
||||
val iconVector: ImageVector? = null,
|
||||
val iconComposable: @Composable () -> Unit = {},
|
||||
)
|
||||
+18
-2
@@ -10,8 +10,13 @@ package io.element.android.libraries.designsystem.preview
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.movableContentOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import coil3.annotation.ExperimentalCoilApi
|
||||
@@ -29,6 +34,7 @@ import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
fun ElementPreview(
|
||||
theme: Theme = if (isSystemInDarkTheme()) Theme.Dark else Theme.Light,
|
||||
showBackground: Boolean = true,
|
||||
fillMaxSize: Boolean = false,
|
||||
@DrawableRes
|
||||
drawableFallbackForImages: Int = CommonDrawables.sample_background,
|
||||
content: @Composable () -> Unit
|
||||
@@ -40,11 +46,21 @@ fun ElementPreview(
|
||||
}
|
||||
) {
|
||||
ElementTheme(theme = theme) {
|
||||
val movableContent = remember { movableContentOf { content() } }
|
||||
if (showBackground) {
|
||||
// If we have a proper contentColor applied we need a Surface instead of a Box
|
||||
Surface(content = content)
|
||||
Surface(
|
||||
modifier = if (fillMaxSize) Modifier.fillMaxSize() else Modifier,
|
||||
content = movableContent,
|
||||
)
|
||||
} else {
|
||||
content()
|
||||
if (fillMaxSize) {
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
movableContent()
|
||||
}
|
||||
} else {
|
||||
movableContent()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -11,12 +11,10 @@ package io.element.android.libraries.designsystem.preview
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.SheetState
|
||||
import androidx.compose.material3.SheetValue
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun sheetStateForPreview() = SheetState(
|
||||
skipPartiallyExpanded = true,
|
||||
enabledValues = setOf(SheetValue.Hidden, SheetValue.Expanded),
|
||||
positionalThreshold = { 0.5f },
|
||||
velocityThreshold = { 400f },
|
||||
initialValue = SheetValue.Expanded,
|
||||
|
||||
+5
-2
@@ -21,8 +21,9 @@ import androidx.compose.material3.BottomSheetDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SheetState
|
||||
import androidx.compose.material3.SheetValue
|
||||
import androidx.compose.material3.contentColorFor
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.material3.rememberBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.movableContentOf
|
||||
import androidx.compose.runtime.remember
|
||||
@@ -57,7 +58,9 @@ fun ModalBottomSheet(
|
||||
onDismissRequest: () -> Unit,
|
||||
scrollable: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
sheetState: SheetState = rememberModalBottomSheetState(),
|
||||
sheetState: SheetState = rememberBottomSheetState(
|
||||
initialValue = SheetValue.Hidden,
|
||||
),
|
||||
shape: Shape = BottomSheetDefaults.ExpandedShape,
|
||||
containerColor: Color = MaterialTheme.colorScheme.surface,
|
||||
contentColor: Color = contentColorFor(containerColor),
|
||||
|
||||
Reference in New Issue
Block a user