Start implementing logic for room summary list

This commit is contained in:
ganfra 2022-10-28 20:17:18 +02:00
parent 7975ea16e4
commit a609433a50
20 changed files with 423 additions and 119 deletions

View file

@ -12,17 +12,19 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.compose.collectAsState
import com.airbnb.mvrx.compose.mavericksViewModel
import io.element.android.x.ui.theme.components.Avatar
import org.matrix.rustcomponents.sdk.Room
import io.element.android.x.designsystem.components.Avatar
import io.element.android.x.matrix.core.RoomId
import io.element.android.x.matrix.room.RoomSummary
@Composable
fun RoomListScreen(
viewModel: RoomListViewModel = mavericksViewModel(),
onRoomClicked: (String) -> Unit = { },
onLogoutClicked: () -> Unit = { },
onRoomClicked: (RoomId) -> Unit = { }
) {
val state by viewModel.collectAsState()
RoomListContent(state, onRoomClicked, onLogoutClicked)
@ -31,8 +33,8 @@ fun RoomListScreen(
@Composable
fun RoomListContent(
state: RoomListViewState,
onRoomClicked: (String) -> Unit,
onLogoutClicked: () -> Unit
onRoomClicked: (RoomId) -> Unit,
onLogoutClicked: () -> Unit,
) {
Surface(color = MaterialTheme.colorScheme.background) {
Column(
@ -62,7 +64,8 @@ fun RoomListTopBar(state: RoomListViewState, onLogoutClicked: () -> Unit) {
TopAppBar(
title = {
Row(
modifier = Modifier.fillMaxWidth()
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
val matrixUser = state.user
Avatar(data = matrixUser.avatarData)
@ -83,19 +86,24 @@ fun RoomListTopBar(state: RoomListViewState, onLogoutClicked: () -> Unit) {
@Composable
private fun RoomItem(
modifier: Modifier = Modifier,
room: Room,
onClick: (String) -> Unit
room: RoomSummary,
onClick: (RoomId) -> Unit
) {
if (room !is RoomSummary.Filled) {
return
}
val details = room.details
Row(verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.clickable {
onClick(room.id())
onClick(room.details.roomId)
}
.fillMaxWidth()
.padding(horizontal = 8.dp)
) {
Column(modifier = modifier.padding(8.dp)) {
Text(text = "Room: ${room.name() ?: room.id()}")
Text(text = if (room.isDirect()) "Direct" else "Room")
Text(fontSize = 18.sp, text = details.name.orEmpty())
Text(text = details.lastMessage?.toString().orEmpty(), maxLines = 2)
}
}
}

View file

@ -4,19 +4,14 @@ import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MavericksViewModel
import com.airbnb.mvrx.Success
import io.element.android.x.core.data.tryOrNull
import io.element.android.x.matrix.MatrixClient
import io.element.android.x.matrix.MatrixInstance
import kotlinx.coroutines.launch
import org.matrix.rustcomponents.sdk.Room
import org.matrix.rustcomponents.sdk.StoppableSpawn
import org.matrix.rustcomponents.sdk.UpdateSummary
import org.matrix.rustcomponents.sdk.mediaSourceFromUrl
class RoomListViewModel(initialState: RoomListViewState) :
MavericksViewModel<RoomListViewState>(initialState), MatrixClient.SlidingSyncListener {
MavericksViewModel<RoomListViewState>(initialState) {
private var sync: StoppableSpawn? = null
private val matrix = MatrixInstance.getInstance()
init {
@ -33,18 +28,26 @@ class RoomListViewModel(initialState: RoomListViewState) :
private fun handleInit() {
viewModelScope.launch {
val client = getClient()
val url = client.avatarUrl()
val mediaSource = mediaSourceFromUrl(url)
client.startSync()
val userAvatarUrl = client.loadUserAvatarURLString().getOrNull()
val userDisplayName = client.loadUserDisplayName().getOrNull()
val avatarData = userAvatarUrl?.let {
mediaSourceFromUrl(it)
}?.let {
client.loadMediaContentForSource(it)
}
setState {
copy(
user = MatrixUser(
username = tryOrNull { client.username() } ?: "Room list",
avatarUrl = mediaSource.url(),
avatarData = client.loadMedia2(url)
username = userDisplayName,
avatarUrl = userAvatarUrl,
avatarData = avatarData?.getOrNull()
)
)
}
sync = client.slidingSync(listener = this@RoomListViewModel)
client.roomSummaryDataSource().roomSummaries().execute {
copy(rooms = it)
}
}
}
@ -64,31 +67,7 @@ class RoomListViewModel(initialState: RoomListViewState) :
return matrix.restoreSession()!!
}
override fun onSyncUpdate(
summary: UpdateSummary,
rooms: List<Room>
) = withState { state ->
val list = state.rooms().orEmpty().toMutableList()
rooms.forEach { room ->
// Either replace or add the room
val idx = list.indexOfFirst { it.id() == room.id() }
if (idx == -1) {
list.add(room)
} else {
list[idx] = room
}
}
setState {
copy(
rooms = Success(list),
summary = Success(summary)
)
}
}
override fun onCleared() {
super.onCleared()
sync?.cancel()
}
}

View file

@ -3,13 +3,13 @@ package io.element.android.x.features.roomlist
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.Uninitialized
import io.element.android.x.matrix.room.RoomSummary
import org.matrix.rustcomponents.sdk.Room
import org.matrix.rustcomponents.sdk.UpdateSummary
data class RoomListViewState(
val user: MatrixUser = MatrixUser(),
val rooms: Async<List<Room>> = Uninitialized,
val summary: Async<UpdateSummary> = Uninitialized,
val rooms: Async<List<RoomSummary>> = Uninitialized,
val canLoadMore: Boolean = false,
val logoutAction: Async<Unit> = Uninitialized,
) : MavericksState