Start implementing timeline
This commit is contained in:
@@ -3,18 +3,28 @@
|
||||
package io.element.android.x.features.messages
|
||||
|
||||
import Avatar
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.airbnb.mvrx.compose.collectAsState
|
||||
import com.airbnb.mvrx.compose.mavericksViewModel
|
||||
import io.element.android.x.core.data.LogCompositions
|
||||
import io.element.android.x.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.x.features.messages.model.MessagesViewState
|
||||
import io.element.android.x.matrix.timeline.MatrixTimelineItem
|
||||
|
||||
@Composable
|
||||
fun MessagesScreen(roomId: String) {
|
||||
@@ -22,19 +32,19 @@ fun MessagesScreen(roomId: String) {
|
||||
LogCompositions(tag = "MessagesScreen", msg = "Root")
|
||||
val roomTitle by viewModel.collectAsState(MessagesViewState::roomName)
|
||||
val roomAvatar by viewModel.collectAsState(MessagesViewState::roomAvatar)
|
||||
MessagesContent(roomTitle, roomAvatar)
|
||||
val timelineItems by viewModel.collectAsState(MessagesViewState::timelineItems)
|
||||
MessagesContent(roomTitle, roomAvatar, timelineItems().orEmpty())
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MessagesContent(
|
||||
roomTitle: String?,
|
||||
roomAvatar: AvatarData?
|
||||
roomAvatar: AvatarData?,
|
||||
timelineItems: List<MatrixTimelineItem>,
|
||||
) {
|
||||
val appBarState = rememberTopAppBarState()
|
||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(appBarState)
|
||||
LogCompositions(tag = "RoomListScreen", msg = "Content")
|
||||
LogCompositions(tag = "MessagesScreen", msg = "Content")
|
||||
val lazyListState = rememberLazyListState()
|
||||
Scaffold(
|
||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
navigationIcon = {
|
||||
@@ -48,10 +58,81 @@ fun MessagesContent(
|
||||
)
|
||||
},
|
||||
content = { padding ->
|
||||
Box(modifier = Modifier.padding(padding))
|
||||
TimelineItems(
|
||||
padding = padding,
|
||||
lazyListState = lazyListState,
|
||||
timelineItems = timelineItems
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TimelineItems(
|
||||
padding: PaddingValues,
|
||||
lazyListState: LazyListState,
|
||||
timelineItems: List<MatrixTimelineItem>
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.padding(padding)
|
||||
.fillMaxSize(),
|
||||
state = lazyListState,
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.Bottom,
|
||||
reverseLayout = true
|
||||
) {
|
||||
items(timelineItems) { timelineItem ->
|
||||
TimelineItemRow(timelineItem = timelineItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TimelineItemRow(
|
||||
timelineItem: MatrixTimelineItem
|
||||
) {
|
||||
when (timelineItem) {
|
||||
MatrixTimelineItem.Other -> return
|
||||
MatrixTimelineItem.Virtual -> return
|
||||
is MatrixTimelineItem.Event -> {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(
|
||||
onClick = { },
|
||||
indication = rememberRipple(),
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
),
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp)
|
||||
.height(IntrinsicSize.Min),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
fontSize = 14.sp,
|
||||
text = timelineItem.event.raw() ?: "",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun MessagesLoadingMoreIndicator() {
|
||||
Box(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.padding(8.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
CircularProgressIndicator(strokeWidth = 2.dp, color = MaterialTheme.colorScheme.primary)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,11 @@ class MessagesViewModel(
|
||||
)
|
||||
}
|
||||
}.launchIn(viewModelScope)
|
||||
|
||||
room.timeline().timelineItems()
|
||||
.execute {
|
||||
copy(timelineItems = it)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadAvatarData(
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package io.element.android.x.features.messages.model
|
||||
|
||||
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.matrix.timeline.MatrixTimelineItem
|
||||
|
||||
data class MessagesViewState(
|
||||
val roomId: String,
|
||||
val roomName: String? = null,
|
||||
val roomAvatar: AvatarData? = null
|
||||
val roomAvatar: AvatarData? = null,
|
||||
val timelineItems: Async<List<MatrixTimelineItem>> = Uninitialized
|
||||
) : MavericksState {
|
||||
|
||||
@Suppress("unused")
|
||||
|
||||
Reference in New Issue
Block a user