Merge branch 'develop' into feature/fga/room_navigation
This commit is contained in:
commit
73f276ba8e
447 changed files with 3318 additions and 1374 deletions
|
|
@ -34,6 +34,7 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage
|
||||
import io.element.android.libraries.designsystem.R
|
||||
import io.element.android.libraries.designsystem.modifiers.blurCompat
|
||||
import io.element.android.libraries.designsystem.modifiers.blurredShapeShadow
|
||||
|
|
@ -171,6 +172,7 @@ internal fun ElementLogoAtomLargeNoBlurShadowPreview() = ElementPreview {
|
|||
ContentToPreview(ElementLogoAtomSize.Large, useBlurredShadow = false)
|
||||
}
|
||||
|
||||
@ExcludeFromCoverage
|
||||
@Composable
|
||||
private fun ContentToPreview(elementLogoAtomSize: ElementLogoAtomSize, useBlurredShadow: Boolean = true) {
|
||||
Box(
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ fun InfoListItemMolecule(
|
|||
color = backgroundColor,
|
||||
shape = backgroundShape,
|
||||
)
|
||||
.padding(vertical = 12.dp, horizontal = 20.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
.padding(vertical = 12.dp, horizontal = 18.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
icon()
|
||||
message()
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import io.element.android.libraries.designsystem.theme.components.Text
|
|||
|
||||
/**
|
||||
* @param modifier Classical modifier.
|
||||
* @param background optional background component.
|
||||
* @param topBar optional topBar.
|
||||
* @param header optional header.
|
||||
* @param footer optional footer.
|
||||
|
|
@ -42,6 +43,7 @@ import io.element.android.libraries.designsystem.theme.components.Text
|
|||
@Composable
|
||||
fun HeaderFooterPage(
|
||||
modifier: Modifier = Modifier,
|
||||
background: @Composable () -> Unit = {},
|
||||
topBar: @Composable () -> Unit = {},
|
||||
header: @Composable () -> Unit = {},
|
||||
footer: @Composable () -> Unit = {},
|
||||
|
|
@ -51,25 +53,28 @@ fun HeaderFooterPage(
|
|||
modifier = modifier,
|
||||
topBar = topBar,
|
||||
) { padding ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(padding)
|
||||
.consumeWindowInsets(padding)
|
||||
.padding(all = 20.dp),
|
||||
) {
|
||||
// Header
|
||||
header()
|
||||
// Content
|
||||
Box {
|
||||
background()
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxWidth(),
|
||||
.padding(all = 20.dp)
|
||||
.padding(padding)
|
||||
.consumeWindowInsets(padding)
|
||||
) {
|
||||
content()
|
||||
}
|
||||
// Footer
|
||||
Box(modifier = Modifier.padding(horizontal = 16.dp)) {
|
||||
footer()
|
||||
// Header
|
||||
header()
|
||||
// Content
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxWidth(),
|
||||
) {
|
||||
content()
|
||||
}
|
||||
// Footer
|
||||
Box(modifier = Modifier.padding(horizontal = 16.dp)) {
|
||||
footer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2024 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.components
|
||||
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.BlendMode
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.LinearGradientShader
|
||||
import androidx.compose.ui.graphics.ShaderBrush
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
|
||||
/**
|
||||
* Gradient background for FTUE (onboarding) screens.
|
||||
*/
|
||||
@Suppress("ModifierMissing")
|
||||
@Composable
|
||||
fun OnboardingBackground() {
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
val isLightTheme = ElementTheme.isLightTheme
|
||||
Canvas(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(220.dp)
|
||||
.align(Alignment.BottomCenter)
|
||||
) {
|
||||
val gradientBrush = ShaderBrush(
|
||||
LinearGradientShader(
|
||||
from = Offset(0f, size.height / 2f),
|
||||
to = Offset(size.width, size.height / 2f),
|
||||
colors = listOf(
|
||||
Color(0xFF0DBDA8),
|
||||
if (isLightTheme) Color(0xC90D5CBD) else Color(0xFF0D5CBD),
|
||||
)
|
||||
)
|
||||
)
|
||||
val eraseBrush = ShaderBrush(
|
||||
LinearGradientShader(
|
||||
from = Offset(size.width / 2f, 0f),
|
||||
to = Offset(size.width / 2f, size.height * 2f),
|
||||
colors = listOf(
|
||||
Color(0xFF000000),
|
||||
Color(0x00000000),
|
||||
)
|
||||
)
|
||||
)
|
||||
drawWithLayer {
|
||||
drawRect(brush = gradientBrush, size = size)
|
||||
drawRect(brush = gradientBrush, size = size, blendMode = BlendMode.Overlay)
|
||||
drawRect(brush = eraseBrush, size = size, blendMode = BlendMode.DstOut)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun OnboardingBackgroundPreview() {
|
||||
ElementPreview {
|
||||
OnboardingBackground()
|
||||
}
|
||||
}
|
||||
|
|
@ -23,16 +23,21 @@ import androidx.compose.foundation.layout.Row
|
|||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.semantics.clearAndSetSemantics
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import coil.compose.AsyncImage
|
||||
import coil.compose.AsyncImagePainter
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.compose.SubcomposeAsyncImageContent
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.colors.AvatarColorsProvider
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
|
|
@ -71,16 +76,34 @@ private fun ImageAvatar(
|
|||
modifier: Modifier = Modifier,
|
||||
contentDescription: String? = null,
|
||||
) {
|
||||
AsyncImage(
|
||||
model = avatarData,
|
||||
onError = {
|
||||
Timber.e(it.result.throwable, "Error loading avatar $it\n${it.result}")
|
||||
},
|
||||
contentDescription = contentDescription,
|
||||
contentScale = ContentScale.Crop,
|
||||
placeholder = debugPlaceholderAvatar(),
|
||||
modifier = modifier
|
||||
)
|
||||
if (LocalInspectionMode.current) {
|
||||
// For compose previews, use debugPlaceholderAvatar()
|
||||
// instead of falling back to initials avatar on load failure
|
||||
AsyncImage(
|
||||
model = avatarData,
|
||||
contentDescription = contentDescription,
|
||||
placeholder = debugPlaceholderAvatar(),
|
||||
modifier = modifier
|
||||
)
|
||||
} else {
|
||||
SubcomposeAsyncImage(
|
||||
model = avatarData,
|
||||
contentDescription = contentDescription,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = modifier
|
||||
) {
|
||||
when (val state = painter.state) {
|
||||
is AsyncImagePainter.State.Success -> SubcomposeAsyncImageContent()
|
||||
is AsyncImagePainter.State.Error -> {
|
||||
SideEffect {
|
||||
Timber.e(state.result.throwable, "Error loading avatar $state\n${state.result}")
|
||||
}
|
||||
InitialsAvatar(avatarData = avatarData)
|
||||
}
|
||||
else -> InitialsAvatar(avatarData = avatarData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage
|
||||
import io.element.android.libraries.designsystem.atomic.atoms.RedIndicatorAtom
|
||||
import io.element.android.libraries.designsystem.components.preferences.components.PreferenceIcon
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
|
|
@ -162,6 +163,7 @@ internal fun PreferenceTextWithEndBadgeDarkPreview() = ElementPreviewDark {
|
|||
ContentToPreview(showEndBadge = true)
|
||||
}
|
||||
|
||||
@ExcludeFromCoverage
|
||||
@Composable
|
||||
private fun ContentToPreview(showEndBadge: Boolean) {
|
||||
Column(
|
||||
|
|
|
|||
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* 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.modifiers
|
||||
|
||||
import androidx.compose.animation.core.animateFloat
|
||||
import androidx.compose.animation.core.updateTransition
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.draw.drawWithCache
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Path
|
||||
import androidx.compose.ui.graphics.drawscope.clipPath
|
||||
import androidx.compose.ui.platform.debugInspectorInfo
|
||||
import kotlin.math.sqrt
|
||||
|
||||
// Note: these modifiers come from https://gist.github.com/darvld/eb3844474baf2f3fc6d3ab44a4b4b5f8
|
||||
|
||||
/**
|
||||
* A modifier that clips the composable content using an animated circle. The circle will
|
||||
* expand/shrink with an animation whenever [visible] changes.
|
||||
*
|
||||
* For more fine-grained control over the transition, see this method's overload, which allows passing
|
||||
* a [State] object to control the progress of the reveal animation.
|
||||
*
|
||||
* By default, the circle is centered in the content, but custom positions may be specified using
|
||||
* [revealFrom]. Specified offsets should be between 0 (left/top) and 1 (right/bottom).*/
|
||||
fun Modifier.circularReveal(
|
||||
visible: Boolean,
|
||||
showScrim: Boolean = false,
|
||||
revealFrom: Offset = Offset(0.5f, 0.5f),
|
||||
): Modifier = composed(
|
||||
factory = {
|
||||
val factor = updateTransition(visible, label = "Visibility")
|
||||
.animateFloat(label = "revealFactor") { if (it) 1f else 0f }
|
||||
|
||||
circularReveal(factor, showScrim, revealFrom)
|
||||
},
|
||||
inspectorInfo = debugInspectorInfo {
|
||||
name = "circularReveal"
|
||||
properties["visible"] = visible
|
||||
properties["revealFrom"] = revealFrom
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* A modifier that clips the composable content using a circular shape. The radius of the circle
|
||||
* will be determined by the [transitionProgress].
|
||||
*
|
||||
* The values of the progress should be between 0 and 1.
|
||||
*
|
||||
* By default, the circle is centered in the content, but custom positions may be specified using
|
||||
* [revealFrom]. Specified offsets should be between 0 (left/top) and 1 (right/bottom).
|
||||
* */
|
||||
fun Modifier.circularReveal(
|
||||
transitionProgress: State<Float>,
|
||||
showScrim: Boolean = false,
|
||||
revealFrom: Offset = Offset(0.5f, 0.5f)
|
||||
): Modifier {
|
||||
return drawWithCache {
|
||||
val path = Path()
|
||||
val center = revealFrom.mapTo(size)
|
||||
val radius = calculateRadius(revealFrom, size)
|
||||
val scrimColor = if (showScrim) {
|
||||
Color.Gray
|
||||
} else {
|
||||
Color.Transparent
|
||||
}
|
||||
|
||||
path.addOval(Rect(center, radius * transitionProgress.value))
|
||||
|
||||
onDrawWithContent {
|
||||
if (showScrim) {
|
||||
drawRect(scrimColor, alpha = transitionProgress.value * 0.75f)
|
||||
}
|
||||
clipPath(path) { this@onDrawWithContent.drawContent() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Offset.mapTo(size: Size): Offset {
|
||||
return Offset(x * size.width, y * size.height)
|
||||
}
|
||||
|
||||
private fun calculateRadius(normalizedOrigin: Offset, size: Size) = with(normalizedOrigin) {
|
||||
val x = (if (x > 0.5f) x else 1 - x) * size.width
|
||||
val y = (if (y > 0.5f) y else 1 - y) * size.height
|
||||
|
||||
sqrt(x * x + y * y)
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (c) 2024 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.modifiers
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.LayoutModifier
|
||||
import androidx.compose.ui.layout.Measurable
|
||||
import androidx.compose.ui.layout.MeasureResult
|
||||
import androidx.compose.ui.layout.MeasureScope
|
||||
import androidx.compose.ui.platform.InspectorInfo
|
||||
import androidx.compose.ui.platform.InspectorValueInfo
|
||||
import androidx.compose.ui.platform.debugInspectorInfo
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Constraints
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Makes the content square in size.
|
||||
*
|
||||
* This is achieved by cropping incoming max constraints to the largest possible square size
|
||||
* and measuring the content using resulting constraints.
|
||||
* Next the size of layout is decided based on largest dimension of the measured content.
|
||||
* Finally the content is placed inside the square layout according to specified [position].
|
||||
*
|
||||
* If no square exists that falls within the size range of the incoming constraints,
|
||||
* the content will be laid out as usual, as if the modifier was not applied.
|
||||
*
|
||||
* @param position The fraction of the content's position inside its square layout.
|
||||
* It determines the point on the axis that was extended to make a square.
|
||||
* Typically you'd want to use values between `0` and `1`, inclusive, where `0`
|
||||
* will place the content at the "start" of the square, `0.5` in the middle, and `1` at the "end".
|
||||
*/
|
||||
@Stable
|
||||
fun Modifier.squareSize(
|
||||
position: Float = 0.5f,
|
||||
): Modifier =
|
||||
this.then(
|
||||
when {
|
||||
position == 0.5f -> SquareSizeCenter
|
||||
else -> createSquareSizeModifier(position = position)
|
||||
}
|
||||
)
|
||||
|
||||
private val SquareSizeCenter = createSquareSizeModifier(position = 0.5f)
|
||||
|
||||
private class SquareSizeModifier(
|
||||
private val position: Float,
|
||||
inspectorInfo: InspectorInfo.() -> Unit,
|
||||
) : LayoutModifier, InspectorValueInfo(inspectorInfo) {
|
||||
override fun MeasureScope.measure(
|
||||
measurable: Measurable,
|
||||
constraints: Constraints,
|
||||
): MeasureResult {
|
||||
val maxSquare = min(constraints.maxWidth, constraints.maxHeight)
|
||||
val minSquare = max(constraints.minWidth, constraints.minHeight)
|
||||
val squareExists = minSquare <= maxSquare
|
||||
|
||||
val resolvedConstraints = constraints
|
||||
.takeUnless { squareExists }
|
||||
?: constraints.copy(maxWidth = maxSquare, maxHeight = maxSquare)
|
||||
|
||||
val placeable = measurable.measure(resolvedConstraints)
|
||||
|
||||
return if (squareExists) {
|
||||
val size = max(placeable.width, placeable.height)
|
||||
layout(size, size) {
|
||||
val x = ((size - placeable.width) * position).toInt()
|
||||
val y = ((size - placeable.height) * position).toInt()
|
||||
placeable.placeRelative(x, y)
|
||||
}
|
||||
} else {
|
||||
layout(placeable.width, placeable.height) {
|
||||
placeable.placeRelative(0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
if (other !is SquareSizeModifier) return false
|
||||
|
||||
if (position != other.position) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return position.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("ModifierFactoryExtensionFunction", "ModifierFactoryReturnType")
|
||||
private fun createSquareSizeModifier(
|
||||
position: Float,
|
||||
) =
|
||||
SquareSizeModifier(
|
||||
position = position,
|
||||
inspectorInfo = debugInspectorInfo {
|
||||
name = "squareSize"
|
||||
properties["position"] = position
|
||||
},
|
||||
)
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun SquareSizeModifierLargeWidthPreview() {
|
||||
ElementPreview {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(32.dp)
|
||||
.background(Color.Gray)
|
||||
.squareSize(position = 0.25f)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(Color.Black)
|
||||
.size(100.dp, 10.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun SquareSizeModifierLargeHeightPreview() {
|
||||
ElementPreview {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(32.dp)
|
||||
.background(Color.Gray)
|
||||
.squareSize(position = 0.75f)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(Color.Black)
|
||||
.size(10.dp, 100.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun SquareSizeModifierInsideSquarePreview() {
|
||||
ElementPreview {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(32.dp)
|
||||
.size(120.dp)
|
||||
.background(Color.Gray),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(Color.Black)
|
||||
.width(100.dp)
|
||||
.squareSize(position = 0.75f)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,7 @@ import androidx.compose.ui.unit.Dp
|
|||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage
|
||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||
|
|
@ -269,6 +270,7 @@ internal fun SearchBarActiveWithContentPreview() = ElementThemedPreview {
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@ExcludeFromCoverage
|
||||
private fun ContentToPreview(
|
||||
query: String = "",
|
||||
active: Boolean = false,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue