Read receipt: Rework how the feature flag is used.
tom
This commit is contained in:
parent
75eb2bbd25
commit
e15610441b
12 changed files with 59 additions and 46 deletions
|
|
@ -147,9 +147,10 @@ class TimelinePresenter @Inject constructor(
|
||||||
timelineItemsFactory.replaceWith(
|
timelineItemsFactory.replaceWith(
|
||||||
timelineItems = it,
|
timelineItems = it,
|
||||||
roomMembers = if (readReceiptsEnabled) {
|
roomMembers = if (readReceiptsEnabled) {
|
||||||
membersState.roomMembers()
|
membersState.roomMembers().orEmpty()
|
||||||
} else {
|
} else {
|
||||||
null
|
// Give an empty list to not affect performance
|
||||||
|
emptyList()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -166,6 +167,7 @@ class TimelinePresenter @Inject constructor(
|
||||||
userHasPermissionToSendMessage = userHasPermissionToSendMessage,
|
userHasPermissionToSendMessage = userHasPermissionToSendMessage,
|
||||||
paginationState = paginationState,
|
paginationState = paginationState,
|
||||||
timelineItems = timelineItems,
|
timelineItems = timelineItems,
|
||||||
|
showReadReceipts = readReceiptsEnabled,
|
||||||
hasNewItems = hasNewItems.value,
|
hasNewItems = hasNewItems.value,
|
||||||
sessionState = sessionState,
|
sessionState = sessionState,
|
||||||
eventSink = ::handleEvents
|
eventSink = ::handleEvents
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import kotlinx.collections.immutable.ImmutableList
|
||||||
@Immutable
|
@Immutable
|
||||||
data class TimelineState(
|
data class TimelineState(
|
||||||
val timelineItems: ImmutableList<TimelineItem>,
|
val timelineItems: ImmutableList<TimelineItem>,
|
||||||
|
val showReadReceipts: Boolean,
|
||||||
val highlightedEventId: EventId?,
|
val highlightedEventId: EventId?,
|
||||||
val userHasPermissionToSendMessage: Boolean,
|
val userHasPermissionToSendMessage: Boolean,
|
||||||
val paginationState: MatrixTimeline.PaginationState,
|
val paginationState: MatrixTimeline.PaginationState,
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package io.element.android.features.messages.impl.timeline
|
package io.element.android.features.messages.impl.timeline
|
||||||
|
|
||||||
|
import io.element.android.features.messages.impl.timeline.model.ReadReceiptData
|
||||||
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||||
import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
|
import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
|
||||||
import io.element.android.features.messages.impl.timeline.model.TimelineItemReactions
|
import io.element.android.features.messages.impl.timeline.model.TimelineItemReactions
|
||||||
|
|
@ -44,6 +45,7 @@ import kotlin.random.Random
|
||||||
|
|
||||||
fun aTimelineState(timelineItems: ImmutableList<TimelineItem> = persistentListOf()) = TimelineState(
|
fun aTimelineState(timelineItems: ImmutableList<TimelineItem> = persistentListOf()) = TimelineState(
|
||||||
timelineItems = timelineItems,
|
timelineItems = timelineItems,
|
||||||
|
showReadReceipts = false,
|
||||||
paginationState = MatrixTimeline.PaginationState(
|
paginationState = MatrixTimeline.PaginationState(
|
||||||
isBackPaginating = false,
|
isBackPaginating = false,
|
||||||
hasMoreToLoadBackwards = true,
|
hasMoreToLoadBackwards = true,
|
||||||
|
|
@ -124,7 +126,7 @@ internal fun aTimelineItemEvent(
|
||||||
isThreaded: Boolean = false,
|
isThreaded: Boolean = false,
|
||||||
debugInfo: TimelineItemDebugInfo = aTimelineItemDebugInfo(),
|
debugInfo: TimelineItemDebugInfo = aTimelineItemDebugInfo(),
|
||||||
timelineItemReactions: TimelineItemReactions = aTimelineItemReactions(),
|
timelineItemReactions: TimelineItemReactions = aTimelineItemReactions(),
|
||||||
readReceiptState: TimelineItemReadReceipts = TimelineItemReadReceipts.Hidden,
|
readReceiptState: TimelineItemReadReceipts = aTimelineItemReadReceipts(),
|
||||||
): TimelineItem.Event {
|
): TimelineItem.Event {
|
||||||
return TimelineItem.Event(
|
return TimelineItem.Event(
|
||||||
id = UUID.randomUUID().toString(),
|
id = UUID.randomUUID().toString(),
|
||||||
|
|
@ -176,6 +178,12 @@ internal fun aTimelineItemDebugInfo(
|
||||||
model, originalJson, latestEditedJson
|
model, originalJson, latestEditedJson
|
||||||
)
|
)
|
||||||
|
|
||||||
|
internal fun aTimelineItemReadReceipts(): TimelineItemReadReceipts {
|
||||||
|
return TimelineItemReadReceipts(
|
||||||
|
receipts = emptyList<ReadReceiptData>().toImmutableList(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun aGroupedEvents(id: Long = 0): TimelineItem.GroupedEvents {
|
fun aGroupedEvents(id: Long = 0): TimelineItem.GroupedEvents {
|
||||||
val event = aTimelineItemEvent(
|
val event = aTimelineItemEvent(
|
||||||
isMine = true,
|
isMine = true,
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@ fun TimelineView(
|
||||||
) { timelineItem ->
|
) { timelineItem ->
|
||||||
TimelineItemRow(
|
TimelineItemRow(
|
||||||
timelineItem = timelineItem,
|
timelineItem = timelineItem,
|
||||||
|
showReadReceipts = state.showReadReceipts,
|
||||||
highlightedItem = state.highlightedEventId?.value,
|
highlightedItem = state.highlightedEventId?.value,
|
||||||
userHasPermissionToSendMessage = state.userHasPermissionToSendMessage,
|
userHasPermissionToSendMessage = state.userHasPermissionToSendMessage,
|
||||||
onClick = onMessageClicked,
|
onClick = onMessageClicked,
|
||||||
|
|
@ -171,6 +172,7 @@ fun TimelineView(
|
||||||
@Composable
|
@Composable
|
||||||
private fun TimelineItemRow(
|
private fun TimelineItemRow(
|
||||||
timelineItem: TimelineItem,
|
timelineItem: TimelineItem,
|
||||||
|
showReadReceipts: Boolean,
|
||||||
highlightedItem: String?,
|
highlightedItem: String?,
|
||||||
userHasPermissionToSendMessage: Boolean,
|
userHasPermissionToSendMessage: Boolean,
|
||||||
sessionState: SessionState,
|
sessionState: SessionState,
|
||||||
|
|
@ -208,6 +210,7 @@ private fun TimelineItemRow(
|
||||||
} else {
|
} else {
|
||||||
TimelineItemEventRow(
|
TimelineItemEventRow(
|
||||||
event = timelineItem,
|
event = timelineItem,
|
||||||
|
showReadReceipts = showReadReceipts,
|
||||||
isHighlighted = highlightedItem == timelineItem.identifier(),
|
isHighlighted = highlightedItem == timelineItem.identifier(),
|
||||||
canReply = userHasPermissionToSendMessage && timelineItem.content.canBeRepliedTo(),
|
canReply = userHasPermissionToSendMessage && timelineItem.content.canBeRepliedTo(),
|
||||||
onClick = { onClick(timelineItem) },
|
onClick = { onClick(timelineItem) },
|
||||||
|
|
@ -248,6 +251,7 @@ private fun TimelineItemRow(
|
||||||
timelineItem.events.forEach { subGroupEvent ->
|
timelineItem.events.forEach { subGroupEvent ->
|
||||||
TimelineItemRow(
|
TimelineItemRow(
|
||||||
timelineItem = subGroupEvent,
|
timelineItem = subGroupEvent,
|
||||||
|
showReadReceipts = showReadReceipts,
|
||||||
highlightedItem = highlightedItem,
|
highlightedItem = highlightedItem,
|
||||||
sessionState = sessionState,
|
sessionState = sessionState,
|
||||||
userHasPermissionToSendMessage = false,
|
userHasPermissionToSendMessage = false,
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,6 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
|
||||||
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.aTimelineItemPollContent
|
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.features.messages.impl.timeline.model.event.aTimelineItemTextContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.receipts
|
|
||||||
import io.element.android.libraries.designsystem.colors.AvatarColorsProvider
|
import io.element.android.libraries.designsystem.colors.AvatarColorsProvider
|
||||||
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
|
||||||
|
|
@ -117,6 +116,7 @@ import kotlin.math.roundToInt
|
||||||
@Composable
|
@Composable
|
||||||
fun TimelineItemEventRow(
|
fun TimelineItemEventRow(
|
||||||
event: TimelineItem.Event,
|
event: TimelineItem.Event,
|
||||||
|
showReadReceipts: Boolean,
|
||||||
isHighlighted: Boolean,
|
isHighlighted: Boolean,
|
||||||
canReply: Boolean,
|
canReply: Boolean,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
|
|
@ -177,6 +177,7 @@ fun TimelineItemEventRow(
|
||||||
state = state.draggableState,
|
state = state.draggableState,
|
||||||
),
|
),
|
||||||
event = event,
|
event = event,
|
||||||
|
showReadReceipts = showReadReceipts,
|
||||||
isHighlighted = isHighlighted,
|
isHighlighted = isHighlighted,
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
|
@ -195,6 +196,7 @@ fun TimelineItemEventRow(
|
||||||
} else {
|
} else {
|
||||||
TimelineItemEventRowContent(
|
TimelineItemEventRowContent(
|
||||||
event = event,
|
event = event,
|
||||||
|
showReadReceipts = showReadReceipts,
|
||||||
isHighlighted = isHighlighted,
|
isHighlighted = isHighlighted,
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
|
@ -238,6 +240,7 @@ private fun SwipeSensitivity(
|
||||||
@Composable
|
@Composable
|
||||||
private fun TimelineItemEventRowContent(
|
private fun TimelineItemEventRowContent(
|
||||||
event: TimelineItem.Event,
|
event: TimelineItem.Event,
|
||||||
|
showReadReceipts: Boolean,
|
||||||
isHighlighted: Boolean,
|
isHighlighted: Boolean,
|
||||||
interactionSource: MutableInteractionSource,
|
interactionSource: MutableInteractionSource,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
|
|
@ -336,21 +339,23 @@ private fun TimelineItemEventRowContent(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read receipts / Send state
|
// Read receipts / Send state
|
||||||
TimelineItemReadReceiptView(
|
if (showReadReceipts) {
|
||||||
state = ReadReceiptViewState(
|
TimelineItemReadReceiptView(
|
||||||
sendState = event.localSendState,
|
state = ReadReceiptViewState(
|
||||||
receipts = event.readReceiptState.receipts(),
|
sendState = event.localSendState,
|
||||||
),
|
receipts = event.readReceiptState.receipts,
|
||||||
onReadReceiptsClicked = onReadReceiptsClicked,
|
),
|
||||||
modifier = Modifier
|
onReadReceiptsClicked = onReadReceiptsClicked,
|
||||||
.constrainAs(readReceipts) {
|
modifier = Modifier
|
||||||
if (event.reactionsState.reactions.isNotEmpty()) {
|
.constrainAs(readReceipts) {
|
||||||
top.linkTo(reactions.bottom, margin = 4.dp)
|
if (event.reactionsState.reactions.isNotEmpty()) {
|
||||||
} else {
|
top.linkTo(reactions.bottom, margin = 4.dp)
|
||||||
top.linkTo(message.bottom, margin = 4.dp)
|
} else {
|
||||||
|
top.linkTo(message.bottom, margin = 4.dp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -679,6 +684,7 @@ internal fun TimelineItemEventRowPreview() = ElementPreview {
|
||||||
),
|
),
|
||||||
groupPosition = TimelineItemGroupPosition.First,
|
groupPosition = TimelineItemGroupPosition.First,
|
||||||
),
|
),
|
||||||
|
showReadReceipts = false,
|
||||||
isHighlighted = false,
|
isHighlighted = false,
|
||||||
canReply = true,
|
canReply = true,
|
||||||
onClick = {},
|
onClick = {},
|
||||||
|
|
@ -701,6 +707,7 @@ internal fun TimelineItemEventRowPreview() = ElementPreview {
|
||||||
),
|
),
|
||||||
groupPosition = TimelineItemGroupPosition.Last,
|
groupPosition = TimelineItemGroupPosition.Last,
|
||||||
),
|
),
|
||||||
|
showReadReceipts = false,
|
||||||
isHighlighted = false,
|
isHighlighted = false,
|
||||||
canReply = true,
|
canReply = true,
|
||||||
onClick = {},
|
onClick = {},
|
||||||
|
|
@ -741,6 +748,7 @@ internal fun TimelineItemEventRowWithReplyPreview() = ElementPreview {
|
||||||
inReplyTo = aInReplyToReady(replyContent),
|
inReplyTo = aInReplyToReady(replyContent),
|
||||||
groupPosition = TimelineItemGroupPosition.First,
|
groupPosition = TimelineItemGroupPosition.First,
|
||||||
),
|
),
|
||||||
|
showReadReceipts = false,
|
||||||
isHighlighted = false,
|
isHighlighted = false,
|
||||||
canReply = true,
|
canReply = true,
|
||||||
onClick = {},
|
onClick = {},
|
||||||
|
|
@ -765,6 +773,7 @@ internal fun TimelineItemEventRowWithReplyPreview() = ElementPreview {
|
||||||
isThreaded = true,
|
isThreaded = true,
|
||||||
groupPosition = TimelineItemGroupPosition.Last,
|
groupPosition = TimelineItemGroupPosition.Last,
|
||||||
),
|
),
|
||||||
|
showReadReceipts = false,
|
||||||
isHighlighted = false,
|
isHighlighted = false,
|
||||||
canReply = true,
|
canReply = true,
|
||||||
onClick = {},
|
onClick = {},
|
||||||
|
|
@ -817,6 +826,7 @@ internal fun TimelineItemEventRowTimestampPreview(
|
||||||
reactionsState = aTimelineItemReactions(count = 0),
|
reactionsState = aTimelineItemReactions(count = 0),
|
||||||
senderDisplayName = if (useDocument) "Document case" else "Text case",
|
senderDisplayName = if (useDocument) "Document case" else "Text case",
|
||||||
),
|
),
|
||||||
|
showReadReceipts = false,
|
||||||
isHighlighted = false,
|
isHighlighted = false,
|
||||||
canReply = true,
|
canReply = true,
|
||||||
onClick = {},
|
onClick = {},
|
||||||
|
|
@ -850,6 +860,7 @@ internal fun TimelineItemEventRowWithManyReactionsPreview() = ElementPreview {
|
||||||
),
|
),
|
||||||
timelineItemReactions = aTimelineItemReactions(count = 20),
|
timelineItemReactions = aTimelineItemReactions(count = 20),
|
||||||
),
|
),
|
||||||
|
showReadReceipts = false,
|
||||||
isHighlighted = false,
|
isHighlighted = false,
|
||||||
canReply = true,
|
canReply = true,
|
||||||
onClick = {},
|
onClick = {},
|
||||||
|
|
@ -876,6 +887,7 @@ internal fun TimelineItemEventRowLongSenderNamePreview() = ElementPreviewLight {
|
||||||
event = aTimelineItemEvent(
|
event = aTimelineItemEvent(
|
||||||
senderDisplayName = "a long sender display name to test single line and ellipsis at the end of the line",
|
senderDisplayName = "a long sender display name to test single line and ellipsis at the end of the line",
|
||||||
),
|
),
|
||||||
|
showReadReceipts = false,
|
||||||
isHighlighted = false,
|
isHighlighted = false,
|
||||||
canReply = true,
|
canReply = true,
|
||||||
onClick = {},
|
onClick = {},
|
||||||
|
|
@ -898,6 +910,7 @@ internal fun TimelineItemEventRowLongSenderNamePreview() = ElementPreviewLight {
|
||||||
internal fun TimelineItemEventTimestampBelowPreview() = ElementPreviewLight {
|
internal fun TimelineItemEventTimestampBelowPreview() = ElementPreviewLight {
|
||||||
TimelineItemEventRow(
|
TimelineItemEventRow(
|
||||||
event = aTimelineItemEvent(content = aTimelineItemPollContent()),
|
event = aTimelineItemEvent(content = aTimelineItemPollContent()),
|
||||||
|
showReadReceipts = false,
|
||||||
isHighlighted = false,
|
isHighlighted = false,
|
||||||
canReply = true,
|
canReply = true,
|
||||||
onClick = {},
|
onClick = {},
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.features.messages.impl.timeline.model.receipts
|
|
||||||
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.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
|
|
@ -93,7 +92,7 @@ private fun ColumnScope.ReadReceiptBottomSheetContent(
|
||||||
Text(text = stringResource(id = CommonStrings.common_seen_by))
|
Text(text = stringResource(id = CommonStrings.common_seen_by))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
val receipts = state.selectedEvent?.readReceiptState?.receipts().orEmpty()
|
val receipts = state.selectedEvent?.readReceiptState?.receipts.orEmpty()
|
||||||
receipts.forEach {
|
receipts.forEach {
|
||||||
val userId = UserId(it.avatarData.id)
|
val userId = UserId(it.avatarData.id)
|
||||||
MatrixUserRow(
|
MatrixUserRow(
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ class ReadReceiptBottomSheetStateProvider : PreviewParameterProvider<ReadReceipt
|
||||||
.map { readReceiptViewState ->
|
.map { readReceiptViewState ->
|
||||||
ReadReceiptBottomSheetState(
|
ReadReceiptBottomSheetState(
|
||||||
selectedEvent = aTimelineItemEvent(
|
selectedEvent = aTimelineItemEvent(
|
||||||
readReceiptState = TimelineItemReadReceipts.ReadReceipts(
|
readReceiptState = TimelineItemReadReceipts(
|
||||||
receipts = readReceiptViewState.receipts.map { readReceiptData ->
|
receipts = readReceiptViewState.receipts.map { readReceiptData ->
|
||||||
readReceiptData
|
readReceiptData
|
||||||
.copy(avatarData = readReceiptData.avatarData.copy(id = "@${readReceiptData.avatarData.id}:localhost"))
|
.copy(avatarData = readReceiptData.avatarData.copy(id = "@${readReceiptData.avatarData.id}:localhost"))
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ class TimelineItemsFactory @Inject constructor(
|
||||||
|
|
||||||
suspend fun replaceWith(
|
suspend fun replaceWith(
|
||||||
timelineItems: List<MatrixTimelineItem>,
|
timelineItems: List<MatrixTimelineItem>,
|
||||||
roomMembers: List<RoomMember>?,
|
roomMembers: List<RoomMember>,
|
||||||
) = withContext(dispatchers.computation) {
|
) = withContext(dispatchers.computation) {
|
||||||
lock.withLock {
|
lock.withLock {
|
||||||
diffCacheUpdater.updateWith(timelineItems)
|
diffCacheUpdater.updateWith(timelineItems)
|
||||||
|
|
@ -77,7 +77,7 @@ class TimelineItemsFactory @Inject constructor(
|
||||||
|
|
||||||
private suspend fun buildAndEmitTimelineItemStates(
|
private suspend fun buildAndEmitTimelineItemStates(
|
||||||
timelineItems: List<MatrixTimelineItem>,
|
timelineItems: List<MatrixTimelineItem>,
|
||||||
roomMembers: List<RoomMember>?,
|
roomMembers: List<RoomMember>,
|
||||||
) {
|
) {
|
||||||
val newTimelineItemStates = ArrayList<TimelineItem>()
|
val newTimelineItemStates = ArrayList<TimelineItem>()
|
||||||
for (index in diffCache.indices().reversed()) {
|
for (index in diffCache.indices().reversed()) {
|
||||||
|
|
@ -97,7 +97,7 @@ class TimelineItemsFactory @Inject constructor(
|
||||||
private suspend fun buildAndCacheItem(
|
private suspend fun buildAndCacheItem(
|
||||||
timelineItems: List<MatrixTimelineItem>,
|
timelineItems: List<MatrixTimelineItem>,
|
||||||
index: Int,
|
index: Int,
|
||||||
roomMembers: List<RoomMember>?,
|
roomMembers: List<RoomMember>,
|
||||||
): TimelineItem? {
|
): TimelineItem? {
|
||||||
val timelineItemState =
|
val timelineItemState =
|
||||||
when (val currentTimelineItem = timelineItems[index]) {
|
when (val currentTimelineItem = timelineItems[index]) {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ class TimelineItemEventFactory @Inject constructor(
|
||||||
currentTimelineItem: MatrixTimelineItem.Event,
|
currentTimelineItem: MatrixTimelineItem.Event,
|
||||||
index: Int,
|
index: Int,
|
||||||
timelineItems: List<MatrixTimelineItem>,
|
timelineItems: List<MatrixTimelineItem>,
|
||||||
roomMembers: List<RoomMember>?,
|
roomMembers: List<RoomMember>,
|
||||||
): TimelineItem.Event {
|
): TimelineItem.Event {
|
||||||
val currentSender = currentTimelineItem.event.sender
|
val currentSender = currentTimelineItem.event.sender
|
||||||
val groupPosition =
|
val groupPosition =
|
||||||
|
|
@ -132,10 +132,9 @@ class TimelineItemEventFactory @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MatrixTimelineItem.Event.computeReadReceiptState(
|
private fun MatrixTimelineItem.Event.computeReadReceiptState(
|
||||||
roomMembers: List<RoomMember>?,
|
roomMembers: List<RoomMember>,
|
||||||
): TimelineItemReadReceipts {
|
): TimelineItemReadReceipts {
|
||||||
if (roomMembers == null) return TimelineItemReadReceipts.Hidden
|
return TimelineItemReadReceipts(
|
||||||
return TimelineItemReadReceipts.ReadReceipts(
|
|
||||||
receipts = event.receipts
|
receipts = event.receipts
|
||||||
.map { receipt ->
|
.map { receipt ->
|
||||||
val roomMember = roomMembers.find { it.userId == receipt.userId }
|
val roomMember = roomMembers.find { it.userId == receipt.userId }
|
||||||
|
|
|
||||||
|
|
@ -18,25 +18,12 @@ package io.element.android.features.messages.impl.timeline.model
|
||||||
|
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
|
||||||
|
|
||||||
sealed interface TimelineItemReadReceipts {
|
data class TimelineItemReadReceipts(
|
||||||
/**
|
val receipts: ImmutableList<ReadReceiptData>,
|
||||||
* Value when the feature is disabled.
|
)
|
||||||
*/
|
|
||||||
data object Hidden : TimelineItemReadReceipts
|
|
||||||
|
|
||||||
data class ReadReceipts(
|
|
||||||
val receipts: ImmutableList<ReadReceiptData>,
|
|
||||||
) : TimelineItemReadReceipts
|
|
||||||
}
|
|
||||||
|
|
||||||
data class ReadReceiptData(
|
data class ReadReceiptData(
|
||||||
val avatarData: AvatarData,
|
val avatarData: AvatarData,
|
||||||
val formattedDate: String,
|
val formattedDate: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun TimelineItemReadReceipts.receipts(): ImmutableList<ReadReceiptData> = when (this) {
|
|
||||||
TimelineItemReadReceipts.Hidden -> persistentListOf()
|
|
||||||
is TimelineItemReadReceipts.ReadReceipts -> receipts
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ internal fun aMessageEvent(
|
||||||
sentTime = "",
|
sentTime = "",
|
||||||
isMine = isMine,
|
isMine = isMine,
|
||||||
reactionsState = aTimelineItemReactions(count = 0),
|
reactionsState = aTimelineItemReactions(count = 0),
|
||||||
readReceiptState = TimelineItemReadReceipts.ReadReceipts(emptyList<ReadReceiptData>().toImmutableList()),
|
readReceiptState = TimelineItemReadReceipts(emptyList<ReadReceiptData>().toImmutableList()),
|
||||||
localSendState = sendState,
|
localSendState = sendState,
|
||||||
inReplyTo = inReplyTo,
|
inReplyTo = inReplyTo,
|
||||||
debugInfo = debugInfo,
|
debugInfo = debugInfo,
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ class TimelineItemGrouperTest {
|
||||||
senderDisplayName = "",
|
senderDisplayName = "",
|
||||||
content = TimelineItemStateEventContent(body = "a state event"),
|
content = TimelineItemStateEventContent(body = "a state event"),
|
||||||
reactionsState = aTimelineItemReactions(count = 0),
|
reactionsState = aTimelineItemReactions(count = 0),
|
||||||
readReceiptState = TimelineItemReadReceipts.ReadReceipts(emptyList<ReadReceiptData>().toImmutableList()),
|
readReceiptState = TimelineItemReadReceipts(emptyList<ReadReceiptData>().toImmutableList()),
|
||||||
localSendState = LocalEventSendState.Sent(AN_EVENT_ID),
|
localSendState = LocalEventSendState.Sent(AN_EVENT_ID),
|
||||||
inReplyTo = null,
|
inReplyTo = null,
|
||||||
isThreaded = false,
|
isThreaded = false,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue