diff --git a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/MessagesReactionButton.kt b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/MessagesReactionButton.kt new file mode 100644 index 0000000000..dd8cb53fe1 --- /dev/null +++ b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/MessagesReactionButton.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2022 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.messages.timeline.components + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CornerSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +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 io.element.android.features.messages.timeline.model.AggregatedReaction +import io.element.android.features.messages.timeline.model.AggregatedReactionProvider +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +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.Text + +@Composable +fun MessagesReactionButton(reaction: AggregatedReaction, modifier: Modifier = Modifier) { + Surface( + modifier = modifier, + color = MaterialTheme.colorScheme.surfaceVariant, + border = BorderStroke(2.dp, MaterialTheme.colorScheme.background), + shape = RoundedCornerShape(corner = CornerSize(12.dp)), + ) { + Row( + modifier = Modifier.padding(vertical = 5.dp, horizontal = 8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + // TODO `reaction.isHighlighted` is not used. + Text(text = reaction.key, fontSize = 12.sp) + Spacer(modifier = Modifier.width(4.dp)) + Text(text = reaction.count, color = MaterialTheme.colorScheme.secondary, fontSize = 12.sp) + } + } +} + +@Preview +@Composable +internal fun MessagesReactionButtonLightPreview(@PreviewParameter(AggregatedReactionProvider::class) reaction: AggregatedReaction) = + ElementPreviewLight { ContentToPreview(reaction) } + +@Preview +@Composable +internal fun MessagesReactionButtonDarkPreview(@PreviewParameter(AggregatedReactionProvider::class) reaction: AggregatedReaction) = + ElementPreviewDark { ContentToPreview(reaction) } + +@Composable +private fun ContentToPreview(reaction: AggregatedReaction) { + MessagesReactionButton(reaction) +} diff --git a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemEncryptedView.kt b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemEncryptedView.kt index 9b2be79685..e8f2266a01 100644 --- a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemEncryptedView.kt +++ b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemEncryptedView.kt @@ -20,7 +20,11 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Warning import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview import io.element.android.features.messages.timeline.model.content.TimelineItemEncryptedContent +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import org.matrix.rustcomponents.sdk.EncryptedMessage @Composable fun TimelineItemEncryptedView( @@ -34,3 +38,22 @@ fun TimelineItemEncryptedView( modifier = modifier ) } + +@Preview +@Composable +internal fun TimelineItemEncryptedViewLightPreview() = + ElementPreviewLight { ContentToPreview() } + +@Preview +@Composable +internal fun TimelineItemEncryptedViewDarkPreview() = + ElementPreviewDark { ContentToPreview() } + +@Composable +private fun ContentToPreview() { + TimelineItemEncryptedView( + content = TimelineItemEncryptedContent( + encryptedMessage = EncryptedMessage.Unknown, + ) + ) +} diff --git a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemImageView.kt b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemImageView.kt index e497a52523..e93d216975 100644 --- a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemImageView.kt +++ b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemImageView.kt @@ -28,9 +28,15 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.painter.ColorPainter import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter import coil.compose.AsyncImage import coil.request.ImageRequest import io.element.android.features.messages.timeline.model.content.TimelineItemImageContent +import io.element.android.features.messages.timeline.model.content.TimelineItemImageContentProvider +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.preview.debugPlaceholderBackground @Composable fun TimelineItemImageView( @@ -48,7 +54,7 @@ fun TimelineItemImageView( .aspectRatio(content.aspectRatio), contentAlignment = Alignment.Center, ) { - var isLoading = rememberSaveable(content.imageMeta) { mutableStateOf(true) } + val isLoading = rememberSaveable(content.imageMeta) { mutableStateOf(true) } val context = LocalContext.current val model = ImageRequest.Builder(context) .data(content.imageMeta) @@ -57,9 +63,24 @@ fun TimelineItemImageView( AsyncImage( model = model, contentDescription = null, - placeholder = ColorPainter(MaterialTheme.colorScheme.surfaceVariant), + placeholder = debugPlaceholderBackground(ColorPainter(MaterialTheme.colorScheme.surfaceVariant)), contentScale = ContentScale.Crop, onSuccess = { isLoading.value = false }, ) } } + +@Preview +@Composable +internal fun TimelineItemImageViewLightPreview(@PreviewParameter(TimelineItemImageContentProvider::class) content: TimelineItemImageContent) = + ElementPreviewLight { ContentToPreview(content) } + +@Preview +@Composable +internal fun TimelineItemImageViewDarkPreview(@PreviewParameter(TimelineItemImageContentProvider::class) content: TimelineItemImageContent) = + ElementPreviewDark { ContentToPreview(content) } + +@Composable +private fun ContentToPreview(content: TimelineItemImageContent) { + TimelineItemImageView(content) +} diff --git a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemInformativeView.kt b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemInformativeView.kt index f0b6238a20..f4ea3d017b 100644 --- a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemInformativeView.kt +++ b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemInformativeView.kt @@ -65,11 +65,11 @@ fun TimelineItemInformativeView( @Preview @Composable -internal fun MatrixUserRowLightPreview() = ElementPreviewLight { ContentToPreview() } +internal fun TimelineItemInformativeViewLightPreview() = ElementPreviewLight { ContentToPreview() } @Preview @Composable -internal fun MatrixUserRowDarkPreview() = ElementPreviewDark { ContentToPreview() } +internal fun TimelineItemInformativeViewDarkPreview() = ElementPreviewDark { ContentToPreview() } @Composable private fun ContentToPreview() { diff --git a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemReactionsView.kt b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemReactionsView.kt index 50185bdb50..708c713306 100644 --- a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemReactionsView.kt +++ b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemReactionsView.kt @@ -16,24 +16,16 @@ package io.element.android.features.messages.timeline.components -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.CornerSize -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import com.google.accompanist.flowlayout.FlowRow -import io.element.android.features.messages.timeline.model.AggregatedReaction +import io.element.android.features.messages.timeline.model.AggregatedReactionProvider import io.element.android.features.messages.timeline.model.TimelineItemReactions -import io.element.android.libraries.designsystem.theme.components.Surface -import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import kotlinx.collections.immutable.toPersistentList @Composable fun TimelineItemReactionsView( @@ -52,21 +44,22 @@ fun TimelineItemReactionsView( } } +@Preview @Composable -fun MessagesReactionButton(reaction: AggregatedReaction, modifier: Modifier = Modifier) { - Surface( - modifier = modifier, - color = MaterialTheme.colorScheme.surfaceVariant, - border = BorderStroke(2.dp, MaterialTheme.colorScheme.background), - shape = RoundedCornerShape(corner = CornerSize(12.dp)), - ) { - Row( - modifier = Modifier.padding(vertical = 5.dp, horizontal = 8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text(text = reaction.key, fontSize = 12.sp) - Spacer(modifier = Modifier.width(4.dp)) - Text(text = reaction.count, color = MaterialTheme.colorScheme.secondary, fontSize = 12.sp) - } - } +internal fun TimelineItemReactionsViewLightPreview() = + ElementPreviewLight { ContentToPreview() } + +@Preview +@Composable +internal fun TimelineItemReactionsViewDarkPreview() = + ElementPreviewDark { ContentToPreview() } + +@Composable +private fun ContentToPreview() { + TimelineItemReactionsView( + reactionsState = TimelineItemReactions( + // Use values from AggregatedReactionProvider + reactions = AggregatedReactionProvider().values.toPersistentList() + ) + ) } diff --git a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemRedactedView.kt b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemRedactedView.kt index f752f88c4a..f50a841410 100644 --- a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemRedactedView.kt +++ b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemRedactedView.kt @@ -20,7 +20,10 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Delete import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview import io.element.android.features.messages.timeline.model.content.TimelineItemRedactedContent +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight @Composable fun TimelineItemRedactedView( @@ -34,3 +37,18 @@ fun TimelineItemRedactedView( modifier = modifier ) } + +@Preview +@Composable +internal fun TimelineItemRedactedViewLightPreview() = + ElementPreviewLight { ContentToPreview() } + +@Preview +@Composable +internal fun TimelineItemRedactedViewDarkPreview() = + ElementPreviewDark { ContentToPreview() } + +@Composable +private fun ContentToPreview() { + TimelineItemRedactedView(TimelineItemRedactedContent) +} diff --git a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemUnknownView.kt b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemUnknownView.kt index 396bb19cb6..2e52c5ec29 100644 --- a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemUnknownView.kt +++ b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/components/TimelineItemUnknownView.kt @@ -20,7 +20,10 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Info import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview import io.element.android.features.messages.timeline.model.content.TimelineItemUnknownContent +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight @Composable fun TimelineItemUnknownView( @@ -34,3 +37,18 @@ fun TimelineItemUnknownView( modifier = modifier ) } + +@Preview +@Composable +internal fun TimelineItemUnknownViewLightPreview() = + ElementPreviewLight { ContentToPreview() } + +@Preview +@Composable +internal fun TimelineItemUnknownViewDarkPreview() = + ElementPreviewDark { ContentToPreview() } + +@Composable +private fun ContentToPreview() { + TimelineItemUnknownView(TimelineItemUnknownContent) +} diff --git a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/model/AggregatedReactionProvider.kt b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/model/AggregatedReactionProvider.kt new file mode 100644 index 0000000000..3346d734da --- /dev/null +++ b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/model/AggregatedReactionProvider.kt @@ -0,0 +1,35 @@ +/* + * 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.messages.timeline.model + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider + +open class AggregatedReactionProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aAggregatedReaction(), + aAggregatedReaction().copy(count = "88"), + aAggregatedReaction().copy(isHighlighted = true), + aAggregatedReaction().copy(count = "88", isHighlighted = true), + ) +} + +fun aAggregatedReaction() = AggregatedReaction( + key = "👍", + count = "1", // TODO Why is it a String? + isHighlighted = false, +) diff --git a/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/model/content/TimelineItemImageContentProvider.kt b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/model/content/TimelineItemImageContentProvider.kt new file mode 100644 index 0000000000..27640a796c --- /dev/null +++ b/features/messages/src/main/kotlin/io/element/android/features/messages/timeline/model/content/TimelineItemImageContentProvider.kt @@ -0,0 +1,36 @@ +/* + * 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.messages.timeline.model.content + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.matrix.media.MediaResolver + +open class TimelineItemImageContentProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aTimelineItemImageContent(), + aTimelineItemImageContent().copy(aspectRatio = 1.0f), + aTimelineItemImageContent().copy(aspectRatio = 1.5f), + ) +} + +fun aTimelineItemImageContent() = TimelineItemImageContent( + body = "a body", + imageMeta = MediaResolver.Meta(source = null, kind = MediaResolver.Kind.Content), + blurhash = null, + aspectRatio = 0.5f, +) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/Images.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/Images.kt index f1fc1b21f0..4061c4486f 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/Images.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/Images.kt @@ -18,6 +18,7 @@ package io.element.android.libraries.designsystem.preview import androidx.annotation.DrawableRes import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.painterResource import io.element.android.libraries.designsystem.R @@ -27,14 +28,21 @@ import io.element.android.libraries.designsystem.R * but it does not render in preview. In the meantime, you can use this trick to have image. */ @Composable -fun debugPlaceholder(@DrawableRes debugPreview: Int) = if (LocalInspectionMode.current) { +fun debugPlaceholder( + @DrawableRes debugPreview: Int, + nonDebugPainter: Painter? = null, +) = if (LocalInspectionMode.current) { painterResource(id = debugPreview) } else { - null + nonDebugPainter } @Composable -fun debugPlaceholderBackground() = debugPlaceholder(debugPreview = R.drawable.sample_background) +fun debugPlaceholderBackground(nonDebugPainter: Painter? = null): Painter? { + return debugPlaceholder(debugPreview = R.drawable.sample_background, nonDebugPainter) +} @Composable -fun debugPlaceholderAvatar() = debugPlaceholder(debugPreview = R.drawable.sample_avatar) +fun debugPlaceholderAvatar(nonDebugPainter: Painter? = null): Painter? { + return debugPlaceholder(debugPreview = R.drawable.sample_avatar, nonDebugPainter) +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt index 2355330907..aaa5e35b16 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt @@ -89,12 +89,12 @@ fun MatrixUserRow( @Preview @Composable -fun MatrixUserRowLightPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = +internal fun MatrixUserRowLightPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = ElementPreviewLight { ContentToPreview(matrixUser) } @Preview @Composable -fun MatrixUserRowDarkPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = +internal fun MatrixUserRowDarkPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = ElementPreviewDark { ContentToPreview(matrixUser) } @Composable