Start implementing timeline

This commit is contained in:
ganfra
2022-11-07 12:36:03 +01:00
parent f14a02a68e
commit da8b307339
9 changed files with 289 additions and 23 deletions

View File

@@ -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)
}
}

View File

@@ -50,6 +50,11 @@ class MessagesViewModel(
)
}
}.launchIn(viewModelScope)
room.timeline().timelineItems()
.execute {
copy(timelineItems = it)
}
}
private suspend fun loadAvatarData(

View File

@@ -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")