Timeline: extract highlightedEventId on viewState instead of individual timeline item
This commit is contained in:
parent
aa40dcf05b
commit
6dab7aa555
6 changed files with 40 additions and 26 deletions
|
|
@ -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()
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue