Timeline: extract highlightedEventId on viewState instead of individual timeline item

This commit is contained in:
ganfra 2022-12-02 14:37:25 +01:00
parent aa40dcf05b
commit 6dab7aa555
6 changed files with 40 additions and 26 deletions

View file

@ -27,7 +27,6 @@ class MessageTimelineItemStateFactory(
) {
suspend fun create(
timelineItems: List<MatrixTimelineItem>,
highlightedEventId: String? = null,
): List<MessagesTimelineItemState> =
withContext(dispatcher) {
val messagesTimelineItemState = ArrayList<MessagesTimelineItemState>()
@ -39,7 +38,6 @@ class MessageTimelineItemStateFactory(
currentTimelineItem,
index,
timelineItems,
highlightedEventId
)
}
is MatrixTimelineItem.Virtual -> MessagesTimelineItemState.Virtual(
@ -56,7 +54,6 @@ class MessageTimelineItemStateFactory(
currentTimelineItem: MatrixTimelineItem.Event,
index: Int,
timelineItems: List<MatrixTimelineItem>,
highlightedEventId: String?,
): MessagesTimelineItemState.MessageEvent {
val currentSender = currentTimelineItem.event.sender()
val groupPosition =
@ -76,7 +73,6 @@ class MessageTimelineItemStateFactory(
senderAvatar = senderAvatarData,
content = currentTimelineItem.computeContent(),
isMine = currentTimelineItem.event.isOwn(),
isHighlighted = currentTimelineItem.event.eventId().orEmpty() == highlightedEventId,
groupPosition = groupPosition,
reactionsState = currentTimelineItem.computeReactionsState()
)

View file

@ -53,10 +53,10 @@ private val COMPOSER_HEIGHT = 112.dp
@Composable
fun MessagesScreen(
roomId: String,
onBackPressed: () -> Unit
onBackPressed: () -> Unit,
viewModel: MessagesViewModel = mavericksViewModel(argsFactory = { roomId }),
composerViewModel: MessageComposerViewModel = mavericksViewModel(argsFactory = { roomId })
) {
val viewModel: MessagesViewModel = mavericksViewModel(argsFactory = { roomId })
val composerViewModel: MessageComposerViewModel = mavericksViewModel(argsFactory = { roomId })
fun onSendMessage(textMessage: String) {
viewModel.sendMessage(textMessage)
@ -74,11 +74,13 @@ fun MessagesScreen(
val hasMoreToLoad by viewModel.collectAsState(MessagesViewState::hasMoreToLoad)
val snackBarContent by viewModel.collectAsState(MessagesViewState::snackbarContent)
val composerMode by viewModel.collectAsState(MessagesViewState::composerMode)
val highlightedEventId by viewModel.collectAsState(MessagesViewState::highlightedEventId)
val composerFullScreen by composerViewModel.collectAsState(MessageComposerViewState::isFullScreen)
val composerCanSendMessage by composerViewModel.collectAsState(MessageComposerViewState::isSendButtonVisible)
val composerText by composerViewModel.collectAsState(MessageComposerViewState::text)
val snackbarHostState = remember { SnackbarHostState() }
MessagesScreenContent(
roomTitle = roomTitle,
roomAvatar = roomAvatar,
timelineItems = timelineItems().orEmpty(),
@ -90,6 +92,7 @@ fun MessagesScreen(
onComposerFullScreenChange = composerViewModel::onComposerFullScreenChange,
onComposerTextChange = composerViewModel::updateText,
composerMode = composerMode,
highlightedEventId = highlightedEventId,
onCloseSpecialMode = viewModel::setNormalMode,
composerCanSendMessage = composerCanSendMessage,
composerText = composerText,
@ -148,6 +151,7 @@ fun MessagesScreenContent(
onComposerFullScreenChange: () -> Unit,
onComposerTextChange: (CharSequence) -> Unit,
composerMode: MessageComposerMode,
highlightedEventId: String?,
onCloseSpecialMode: () -> Unit,
composerCanSendMessage: Boolean,
composerText: StableCharSequence?,
@ -171,6 +175,7 @@ fun MessagesScreenContent(
onSendMessage = onSendMessage,
onClick = onClick,
onLongClick = onLongClick,
highlightedEventId = highlightedEventId,
composerMode = composerMode,
onCloseSpecialMode = onCloseSpecialMode,
composerFullScreen = composerFullScreen,
@ -193,6 +198,7 @@ fun MessagesContent(
onClick: (MessagesTimelineItemState.MessageEvent) -> Unit,
onLongClick: (MessagesTimelineItemState.MessageEvent) -> Unit,
composerMode: MessageComposerMode,
highlightedEventId: String?,
onCloseSpecialMode: () -> Unit,
composerFullScreen: Boolean,
onComposerFullScreenChange: () -> Unit,
@ -211,6 +217,7 @@ fun MessagesContent(
TimelineItems(
lazyListState = lazyListState,
timelineItems = timelineItems,
highlightedEventId = highlightedEventId,
hasMoreToLoad = hasMoreToLoad,
onReachedLoadMore = onReachedLoadMore,
modifier = Modifier.weight(1f),
@ -279,6 +286,7 @@ fun MessagesTopAppBar(
fun TimelineItems(
lazyListState: LazyListState,
timelineItems: List<MessagesTimelineItemState>,
highlightedEventId: String?,
modifier: Modifier = Modifier,
hasMoreToLoad: Boolean = false,
onClick: (MessagesTimelineItemState.MessageEvent) -> Unit = {},
@ -300,6 +308,7 @@ fun TimelineItems(
) { timelineItem ->
TimelineItemRow(
timelineItem = timelineItem,
isHighlighted = timelineItem.key() == highlightedEventId,
onClick = onClick,
onLongClick = onLongClick
)
@ -337,6 +346,7 @@ private fun MessagesTimelineItemState.contentType(): Int {
@Composable
fun TimelineItemRow(
timelineItem: MessagesTimelineItemState,
isHighlighted: Boolean,
onClick: (MessagesTimelineItemState.MessageEvent) -> Unit,
onLongClick: (MessagesTimelineItemState.MessageEvent) -> Unit,
) {
@ -344,6 +354,7 @@ fun TimelineItemRow(
is MessagesTimelineItemState.Virtual -> return
is MessagesTimelineItemState.MessageEvent -> MessageEventRow(
messageEvent = timelineItem,
isHighlighted = isHighlighted,
onClick = { onClick(timelineItem) },
onLongClick = { onLongClick(timelineItem) }
)
@ -353,6 +364,7 @@ fun TimelineItemRow(
@Composable
fun MessageEventRow(
messageEvent: MessagesTimelineItemState.MessageEvent,
isHighlighted: Boolean,
onClick: () -> Unit,
onLongClick: () -> Unit,
modifier: Modifier = Modifier
@ -385,7 +397,7 @@ fun MessageEventRow(
groupPosition = messageEvent.groupPosition,
isMine = messageEvent.isMine,
interactionSource = interactionSource,
isHighlighted = messageEvent.isHighlighted,
isHighlighted = isHighlighted,
onClick = onClick,
onLongClick = onLongClick,
modifier = Modifier
@ -584,6 +596,7 @@ fun TimelineItemsPreview(
groupPosition = MessagesItemGroupPosition.Last
),
),
highlightedEventId = null,
hasMoreToLoad = true,
)
}

View file

@ -18,7 +18,9 @@ import io.element.android.x.matrix.room.MatrixRoom
import io.element.android.x.matrix.timeline.MatrixTimeline
import io.element.android.x.textcomposer.MessageComposerMode
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import timber.log.Timber
@ -127,7 +129,8 @@ class MessagesViewModel(
private fun setComposerMode(mode: MessageComposerMode) {
setState {
copy(
composerMode = mode
composerMode = mode,
highlightedEventId = mode.relatedEventId
)
}
}
@ -189,20 +192,9 @@ class MessagesViewModel(
}
}.launchIn(viewModelScope)
combine(
timeline.timelineItems(),
stateFlow.map {
when (it.composerMode) {
is MessageComposerMode.Normal -> null
is MessageComposerMode.Edit -> it.composerMode.eventId
is MessageComposerMode.Quote -> null
is MessageComposerMode.Reply -> it.composerMode.eventId
}
}
.distinctUntilChanged()
) { timelineItems, highlightedEventId ->
messageTimelineItemStateFactory.create(timelineItems, highlightedEventId)
}
timeline
.timelineItems()
.map(messageTimelineItemStateFactory::create)
.execute {
copy(timelineItems = it)
}

View file

@ -16,7 +16,6 @@ sealed interface MessagesTimelineItemState {
val content: MessagesTimelineItemContent,
val sentTime: String = "",
val isMine: Boolean = false,
val isHighlighted: Boolean = false,
val groupPosition: MessagesItemGroupPosition = MessagesItemGroupPosition.None,
val reactionsState: MessagesItemReactionState
) : MessagesTimelineItemState {

View file

@ -1,11 +1,13 @@
package io.element.android.x.features.messages.model
import androidx.compose.runtime.Stable
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.Uninitialized
import io.element.android.x.designsystem.components.avatar.AvatarData
import io.element.android.x.textcomposer.MessageComposerMode
@Stable
data class MessagesViewState(
val roomId: String,
val roomName: String? = null,
@ -14,7 +16,7 @@ data class MessagesViewState(
val hasMoreToLoad: Boolean = true,
val itemActionsSheetState: Async<MessagesItemActionsSheetState> = Uninitialized,
val snackbarContent: String? = null,
// TODO Highlight item in reply / edit in the timeline
val highlightedEventId: String? = null,
val composerMode: MessageComposerMode = MessageComposerMode.Normal(""),
) : MavericksState {

View file

@ -33,4 +33,16 @@ sealed interface MessageComposerMode {
override val eventId: String,
override val defaultContent: CharSequence
) : Special(eventId, defaultContent)
val relatedEventId: String?
get() = when (this) {
is Normal -> null
is Edit -> eventId
is Quote -> eventId
is Reply -> eventId
}
}