Merge pull request #1866 from vector-im/feature/bma/morePreview

More preview on TimelineItemEventRow
This commit is contained in:
Benoit Marty
2023-11-24 17:21:53 +01:00
committed by GitHub
256 changed files with 589 additions and 256 deletions

View File

@@ -0,0 +1,46 @@
/*
* 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.impl.timeline.components
import androidx.compose.runtime.Composable
import io.element.android.features.messages.impl.timeline.model.TimelineItem
// For previews
@Composable
internal fun ATimelineItemEventRow(
event: TimelineItem.Event,
showReadReceipts: Boolean = false,
isLastOutgoingMessage: Boolean = false,
isHighlighted: Boolean = false,
) = TimelineItemEventRow(
event = event,
showReadReceipts = showReadReceipts,
isLastOutgoingMessage = isLastOutgoingMessage,
isHighlighted = isHighlighted,
canReply = true,
onClick = {},
onLongClick = {},
onUserDataClick = {},
inReplyToClick = {},
onReactionClick = { _, _ -> },
onReactionLongClick = { _, _ -> },
onMoreReactionsClick = {},
onReadReceiptClick = {},
onSwipeToReply = {},
onTimestampClicked = {},
eventSink = {},
)

View File

@@ -53,8 +53,6 @@ import androidx.compose.ui.platform.ViewConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
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.IntOffset
import androidx.compose.ui.unit.dp
@@ -63,7 +61,6 @@ import androidx.constraintlayout.compose.ConstrainScope
import androidx.constraintlayout.compose.ConstraintLayout
import io.element.android.features.messages.impl.timeline.TimelineEvents
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView
import io.element.android.features.messages.impl.timeline.components.event.toExtraPadding
import io.element.android.features.messages.impl.timeline.components.receipt.ReadReceiptViewState
@@ -75,17 +72,14 @@ import io.element.android.features.messages.impl.timeline.model.bubble.BubbleSta
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent
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.aTimelineItemPollContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
import io.element.android.libraries.designsystem.colors.AvatarColorsProvider
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.AvatarData
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.swipe.SwipeableActionsState
import io.element.android.libraries.designsystem.swipe.rememberSwipeableActionsState
@@ -101,7 +95,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.ImageMessageT
import io.element.android.libraries.matrix.api.timeline.item.event.LocationMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent
import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
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.VoiceMessageType
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail
@@ -110,7 +103,6 @@ import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.coroutines.launch
import org.jsoup.Jsoup
import kotlin.math.abs
import kotlin.math.roundToInt
@@ -696,7 +688,7 @@ private fun textForInReplyTo(inReplyTo: InReplyToDetails): String {
internal fun TimelineItemEventRowPreview() = ElementPreview {
Column {
sequenceOf(false, true).forEach {
TimelineItemEventRow(
ATimelineItemEventRow(
event = aTimelineItemEvent(
isMine = it,
content = aTimelineItemTextContent().copy(
@@ -705,23 +697,8 @@ internal fun TimelineItemEventRowPreview() = ElementPreview {
),
groupPosition = TimelineItemGroupPosition.First,
),
showReadReceipts = false,
isLastOutgoingMessage = false,
isHighlighted = false,
canReply = true,
onClick = {},
onLongClick = {},
onUserDataClick = {},
inReplyToClick = {},
onReactionClick = { _, _ -> },
onReactionLongClick = { _, _ -> },
onMoreReactionsClick = {},
onReadReceiptClick = {},
onTimestampClicked = {},
onSwipeToReply = {},
eventSink = {},
)
TimelineItemEventRow(
ATimelineItemEventRow(
event = aTimelineItemEvent(
isMine = it,
content = aTimelineItemImageContent().copy(
@@ -729,230 +706,7 @@ internal fun TimelineItemEventRowPreview() = ElementPreview {
),
groupPosition = TimelineItemGroupPosition.Last,
),
showReadReceipts = false,
isLastOutgoingMessage = false,
isHighlighted = false,
canReply = true,
onClick = {},
onLongClick = {},
onUserDataClick = {},
inReplyToClick = {},
onReactionClick = { _, _ -> },
onReactionLongClick = { _, _ -> },
onMoreReactionsClick = {},
onReadReceiptClick = {},
onTimestampClicked = {},
onSwipeToReply = {},
eventSink = {},
)
}
}
}
@PreviewsDayNight
@Composable
internal fun TimelineItemEventRowWithReplyPreview() = ElementPreview {
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 = aInReplyToDetails(replyContent),
groupPosition = TimelineItemGroupPosition.First,
),
showReadReceipts = false,
isLastOutgoingMessage = false,
isHighlighted = false,
canReply = true,
onClick = {},
onLongClick = {},
onUserDataClick = {},
inReplyToClick = {},
onReactionClick = { _, _ -> },
onReactionLongClick = { _, _ -> },
onMoreReactionsClick = {},
onReadReceiptClick = {},
onTimestampClicked = {},
onSwipeToReply = {},
eventSink = {},
)
TimelineItemEventRow(
event = aTimelineItemEvent(
isMine = it,
content = aTimelineItemImageContent().copy(
aspectRatio = 5f
),
inReplyTo = aInReplyToDetails(replyContent),
isThreaded = true,
groupPosition = TimelineItemGroupPosition.Last,
),
showReadReceipts = false,
isLastOutgoingMessage = false,
isHighlighted = false,
canReply = true,
onClick = {},
onLongClick = {},
onUserDataClick = {},
inReplyToClick = {},
onReactionClick = { _, _ -> },
onReactionLongClick = { _, _ -> },
onMoreReactionsClick = {},
onReadReceiptClick = {},
onTimestampClicked = {},
onSwipeToReply = {},
eventSink = {},
)
}
}
}
private fun aInReplyToDetails(
replyContent: String,
): InReplyToDetails {
return InReplyToDetails(
eventId = EventId("\$event"),
eventContent = MessageContent(replyContent, null, false, false, TextMessageType(replyContent, null)),
senderId = UserId("@Sender:domain"),
senderDisplayName = "Sender",
senderAvatarUrl = null,
textContent = replyContent,
)
}
@PreviewsDayNight
@Composable
internal fun TimelineItemEventRowTimestampPreview(
@PreviewParameter(TimelineItemEventForTimestampViewProvider::class) event: TimelineItem.Event
) = ElementPreview {
Column {
val oldContent = event.content as TimelineItemTextContent
listOf(
"Text",
"Text longer, displayed on 1 line",
"Text which should be rendered on several lines",
).forEach { str ->
listOf(false, true).forEach { useDocument ->
TimelineItemEventRow(
event = event.copy(
content = oldContent.copy(
body = str,
htmlDocument = if (useDocument) Jsoup.parse(str) else null,
),
reactionsState = aTimelineItemReactions(count = 0),
senderDisplayName = if (useDocument) "Document case" else "Text case",
),
showReadReceipts = false,
isLastOutgoingMessage = false,
isHighlighted = false,
canReply = true,
onClick = {},
onLongClick = {},
onUserDataClick = {},
inReplyToClick = {},
onReactionClick = { _, _ -> },
onReactionLongClick = { _, _ -> },
onMoreReactionsClick = {},
onReadReceiptClick = {},
onTimestampClicked = {},
onSwipeToReply = {},
eventSink = {},
)
}
}
}
}
@PreviewsDayNight
@Composable
internal fun TimelineItemEventRowWithManyReactionsPreview() = ElementPreview {
Column {
listOf(false, true).forEach { isMine ->
TimelineItemEventRow(
event = aTimelineItemEvent(
isMine = isMine,
content = aTimelineItemTextContent().copy(
body = "A couple of multi-line messages with many reactions attached." +
" One sent by me and another from someone else."
),
timelineItemReactions = aTimelineItemReactions(count = 20),
),
showReadReceipts = false,
isLastOutgoingMessage = false,
isHighlighted = false,
canReply = true,
onClick = {},
onLongClick = {},
onUserDataClick = {},
inReplyToClick = {},
onReactionClick = { _, _ -> },
onReactionLongClick = { _, _ -> },
onMoreReactionsClick = {},
onReadReceiptClick = {},
onSwipeToReply = {},
onTimestampClicked = {},
eventSink = {},
)
}
}
}
// Note: no need for light/dark variant for this preview
@Preview
@Composable
internal fun TimelineItemEventRowLongSenderNamePreview() = ElementPreviewLight {
TimelineItemEventRow(
event = aTimelineItemEvent(
senderDisplayName = "a long sender display name to test single line and ellipsis at the end of the line",
),
showReadReceipts = false,
isLastOutgoingMessage = false,
isHighlighted = false,
canReply = true,
onClick = {},
onLongClick = {},
onUserDataClick = {},
inReplyToClick = {},
onReactionClick = { _, _ -> },
onReactionLongClick = { _, _ -> },
onMoreReactionsClick = {},
onReadReceiptClick = {},
onSwipeToReply = {},
onTimestampClicked = {},
eventSink = {},
)
}
// Note: no need for light/dark variant for this preview, we only look at the timestamp position
@Preview
@Composable
internal fun TimelineItemEventTimestampBelowPreview() = ElementPreviewLight {
TimelineItemEventRow(
event = aTimelineItemEvent(content = aTimelineItemPollContent()),
showReadReceipts = false,
isLastOutgoingMessage = false,
isHighlighted = false,
canReply = true,
onClick = {},
onLongClick = {},
onUserDataClick = {},
inReplyToClick = {},
onReactionClick = { _, _ -> },
onReactionLongClick = { _, _ -> },
onMoreReactionsClick = {},
onReadReceiptClick = {},
onSwipeToReply = {},
onTimestampClicked = {},
eventSink = {},
)
}

View File

@@ -0,0 +1,33 @@
/*
* 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.impl.timeline.components
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
// Note: no need for light/dark variant for this preview
@Preview
@Composable
internal fun TimelineItemEventRowLongSenderNamePreview() = ElementPreviewLight {
ATimelineItemEventRow(
event = aTimelineItemEvent(
senderDisplayName = "a long sender display name to test single line and ellipsis at the end of the line",
),
)
}

View File

@@ -0,0 +1,55 @@
/*
* 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.impl.timeline.components
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import org.jsoup.Jsoup
@PreviewsDayNight
@Composable
internal fun TimelineItemEventRowTimestampPreview(
@PreviewParameter(TimelineItemEventForTimestampViewProvider::class) event: TimelineItem.Event
) = ElementPreview {
Column {
val oldContent = event.content as TimelineItemTextContent
listOf(
"Text",
"Text longer, displayed on 1 line",
"Text which should be rendered on several lines",
).forEach { str ->
listOf(false, true).forEach { useDocument ->
ATimelineItemEventRow(
event = event.copy(
content = oldContent.copy(
body = str,
htmlDocument = if (useDocument) Jsoup.parse(str) else null,
),
reactionsState = aTimelineItemReactions(count = 0),
senderDisplayName = if (useDocument) "Document case" else "Text case",
),
)
}
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* 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.impl.timeline.components
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
@PreviewsDayNight
@Composable
internal fun TimelineItemEventRowWithManyReactionsPreview() = ElementPreview {
Column {
listOf(false, true).forEach { isMine ->
ATimelineItemEventRow(
event = aTimelineItemEvent(
isMine = isMine,
content = aTimelineItemTextContent().copy(
body = "A couple of multi-line messages with many reactions attached." +
" One sent by me and another from someone else."
),
timelineItemReactions = aTimelineItemReactions(count = 20),
),
)
}
}
}

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.features.messages.impl.timeline.components
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
import io.element.android.features.messages.impl.timeline.components.receipt.ReadReceiptViewState
import io.element.android.features.messages.impl.timeline.components.receipt.ReadReceiptViewStateForTimelineItemEventRowProvider
import io.element.android.features.messages.impl.timeline.model.TimelineItemReadReceipts
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
// Note: I add to reduce the size of the fun name, or it does not compile.
// Previous name: TimelineItemEventRowWithSendingStateAndReadReceiptPreview
@PreviewsDayNight
@Composable
internal fun TimelineItemEventRowWithRRPreview(
@PreviewParameter(ReadReceiptViewStateForTimelineItemEventRowProvider::class) state: ReadReceiptViewState,
) = ElementPreview {
Column {
// A message from someone else
ATimelineItemEventRow(
event = aTimelineItemEvent(
isMine = false,
sendState = null,
content = aTimelineItemTextContent().copy(
body = "A message from someone else"
),
timelineItemReactions = aTimelineItemReactions(count = 0),
readReceiptState = TimelineItemReadReceipts(state.receipts),
),
showReadReceipts = true,
isLastOutgoingMessage = false,
)
// A message from current user
ATimelineItemEventRow(
event = aTimelineItemEvent(
isMine = true,
sendState = state.sendState,
content = aTimelineItemTextContent().copy(
body = "A message from me"
),
timelineItemReactions = aTimelineItemReactions(count = 0),
readReceiptState = TimelineItemReadReceipts(state.receipts),
),
showReadReceipts = true,
isLastOutgoingMessage = false,
)
// Another message from current user
ATimelineItemEventRow(
event = aTimelineItemEvent(
isMine = true,
sendState = state.sendState,
content = aTimelineItemTextContent().copy(
body = "A last message from me"
),
timelineItemReactions = aTimelineItemReactions(count = 0),
readReceiptState = TimelineItemReadReceipts(state.receipts),
),
showReadReceipts = true,
isLastOutgoingMessage = true,
)
}
}

View File

@@ -0,0 +1,161 @@
/*
* 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.impl.timeline.components
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
import io.element.android.features.messages.impl.timeline.model.InReplyToDetails
import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
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.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.poll.PollKind
import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.EventContent
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.LocationMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent
import io.element.android.libraries.matrix.api.timeline.item.event.MessageType
import io.element.android.libraries.matrix.api.timeline.item.event.NoticeMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
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.VoiceMessageType
@PreviewsDayNight
@Composable
internal fun TimelineItemEventRowWithReplyPreview(
@PreviewParameter(InReplyToDetailsProvider::class) inReplyToDetails: InReplyToDetails,
) = ElementPreview {
Column {
sequenceOf(false, true).forEach {
ATimelineItemEventRow(
event = aTimelineItemEvent(
isMine = it,
timelineItemReactions = aTimelineItemReactions(count = 0),
content = aTimelineItemTextContent().copy(
body = "A reply."
),
inReplyTo = inReplyToDetails,
groupPosition = TimelineItemGroupPosition.First,
),
)
ATimelineItemEventRow(
event = aTimelineItemEvent(
isMine = it,
timelineItemReactions = aTimelineItemReactions(count = 0),
content = aTimelineItemImageContent().copy(
aspectRatio = 5f
),
inReplyTo = inReplyToDetails,
isThreaded = true,
groupPosition = TimelineItemGroupPosition.Last,
),
)
}
}
}
class InReplyToDetailsProvider : PreviewParameterProvider<InReplyToDetails> {
override val values: Sequence<InReplyToDetails>
get() = sequenceOf(
aMessageContent(
body = "Message which are being replied.",
type = TextMessageType("Message which are being replied.", null)
),
aMessageContent(
body = "Message which are being replied, and which was long enough to be displayed on two lines (only!).",
type = TextMessageType("Message which are being replied, and which was long enough to be displayed on two lines (only!).", null)
),
aMessageContent(
body = "Video",
type = VideoMessageType("Video", MediaSource("url"), null),
),
aMessageContent(
body = "Audio",
type = AudioMessageType("Audio", MediaSource("url"), null),
),
aMessageContent(
body = "Voice",
type = VoiceMessageType("Voice", MediaSource("url"), null, null),
),
aMessageContent(
body = "Image",
type = ImageMessageType("Image", MediaSource("url"), null),
),
aMessageContent(
body = "File",
type = FileMessageType("File", MediaSource("url"), null),
),
aMessageContent(
body = "Location",
type = LocationMessageType("Location", "geo:1,2", null),
),
aMessageContent(
body = "Notice",
type = NoticeMessageType("Notice", null),
),
aMessageContent(
body = "Emote",
type = EmoteMessageType("Emote", null),
),
PollContent(
question = "Poll which are being replied.",
kind = PollKind.Disclosed,
maxSelections = 1u,
answers = emptyList(),
votes = emptyMap(),
endTime = null
),
).map {
aInReplyToDetails(
eventContent = it,
)
}
private fun aMessageContent(
body: String,
type: MessageType,
) = MessageContent(
body = body,
inReplyTo = null,
isEdited = false,
isThreaded = false,
type = type,
)
private fun aInReplyToDetails(
eventContent: EventContent,
) = InReplyToDetails(
eventId = EventId("\$event"),
eventContent = eventContent,
senderId = UserId("@Sender:domain"),
senderDisplayName = "Sender",
senderAvatarUrl = null,
textContent = (eventContent as? MessageContent)?.body.orEmpty(),
)
}

View File

@@ -0,0 +1,32 @@
/*
* 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.impl.timeline.components
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
// Note: no need for light/dark variant for this preview, we only look at the timestamp position
@Preview
@Composable
internal fun TimelineItemEventTimestampBelowPreview() = ElementPreviewLight {
ATimelineItemEventRow(
event = aTimelineItemEvent(content = aTimelineItemPollContent()),
)
}

View File

@@ -0,0 +1,47 @@
/*
* 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.impl.timeline.components.receipt
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.messages.impl.timeline.model.ReadReceiptData
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
class ReadReceiptViewStateForTimelineItemEventRowProvider :
PreviewParameterProvider<ReadReceiptViewState> {
override val values: Sequence<ReadReceiptViewState>
get() = sequenceOf(
aReadReceiptViewState(
sendState = LocalEventSendState.NotSentYet
),
aReadReceiptViewState(
sendState = LocalEventSendState.Sent(EventId("\$eventId")),
),
aReadReceiptViewState(
sendState = LocalEventSendState.Sent(EventId("\$eventId")),
receipts = mutableListOf<ReadReceiptData>().apply {
repeat(5) {
add(
aReadReceiptData(
it
)
)
}
},
),
)
}

View File

@@ -54,7 +54,7 @@ class ReadReceiptViewStateProvider : PreviewParameterProvider<ReadReceiptViewSta
)
}
private fun aReadReceiptViewState(
internal fun aReadReceiptViewState(
sendState: LocalEventSendState? = null,
isLastOutgoingMessage: Boolean = true,
receipts: List<ReadReceiptData> = emptyList(),
@@ -64,7 +64,7 @@ private fun aReadReceiptViewState(
receipts = receipts.toImmutableList(),
)
private fun aReadReceiptData(
internal fun aReadReceiptData(
index: Int,
avatarData: AvatarData = anAvatarData(
id = "$index",

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