Don't pass RoomMember to Node but a UserId instead
This commit is contained in:
parent
64c50d4468
commit
4b9f2fdae0
12 changed files with 52 additions and 63 deletions
|
|
@ -59,7 +59,7 @@ class RoomDetailsFlowNode @AssistedInject constructor(
|
|||
object RoomMemberList : NavTarget
|
||||
|
||||
@Parcelize
|
||||
data class RoomMemberDetails(val roomMember: RoomMember) : NavTarget
|
||||
data class RoomMemberDetails(val roomMemberId: UserId) : NavTarget
|
||||
}
|
||||
|
||||
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
||||
|
|
@ -74,14 +74,14 @@ class RoomDetailsFlowNode @AssistedInject constructor(
|
|||
}
|
||||
NavTarget.RoomMemberList -> {
|
||||
val roomMemberListCallback = object : RoomMemberListNode.Callback {
|
||||
override fun openRoomMemberDetails(roomMember: RoomMember) {
|
||||
backstack.push(NavTarget.RoomMemberDetails(roomMember))
|
||||
override fun openRoomMemberDetails(roomMemberId: UserId) {
|
||||
backstack.push(NavTarget.RoomMemberDetails(roomMemberId))
|
||||
}
|
||||
}
|
||||
createNode<RoomMemberListNode>(buildContext, listOf(roomMemberListCallback))
|
||||
}
|
||||
is NavTarget.RoomMemberDetails -> {
|
||||
createNode<RoomMemberDetailsNode>(buildContext, listOf(RoomMemberDetailsNode.Inputs(navTarget.roomMember)))
|
||||
createNode<RoomMemberDetailsNode>(buildContext, listOf(RoomMemberDetailsNode.Inputs(navTarget.roomMemberId)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ class RoomDetailsPresenter @Inject constructor(
|
|||
@Composable
|
||||
private fun roomMemberDetailsPresenter(dmMemberState: RoomMember?) = remember(dmMemberState) {
|
||||
dmMemberState?.let { roomMember ->
|
||||
roomMembersDetailsPresenterFactory.create(roomMember)
|
||||
roomMembersDetailsPresenterFactory.create(roomMember.userId)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import io.element.android.features.roomdetails.impl.members.details.RoomMemberDe
|
|||
import io.element.android.features.userlist.api.UserListDataSource
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
import javax.inject.Named
|
||||
|
|
@ -48,8 +49,8 @@ object RoomMemberProvidesModule {
|
|||
room: MatrixRoom,
|
||||
): RoomMemberDetailsPresenter.Factory {
|
||||
return object : RoomMemberDetailsPresenter.Factory {
|
||||
override fun create(roomMember: RoomMember): RoomMemberDetailsPresenter {
|
||||
return RoomMemberDetailsPresenter(matrixClient, room, roomMember)
|
||||
override fun create(roomMemberId: UserId): RoomMemberDetailsPresenter {
|
||||
return RoomMemberDetailsPresenter(matrixClient, room, roomMemberId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import dagger.assisted.Assisted
|
|||
import dagger.assisted.AssistedInject
|
||||
import io.element.android.anvilannotations.ContributesNode
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
|
||||
@ContributesNode(RoomScope::class)
|
||||
|
|
@ -36,14 +37,14 @@ class RoomMemberListNode @AssistedInject constructor(
|
|||
) : Node(buildContext, plugins = plugins) {
|
||||
|
||||
interface Callback : Plugin {
|
||||
fun openRoomMemberDetails(roomMember: RoomMember)
|
||||
fun openRoomMemberDetails(roomMemberId: UserId)
|
||||
}
|
||||
|
||||
private val callbacks = plugins<Callback>()
|
||||
|
||||
private fun openRoomMemberDetails(roomMember: RoomMember) {
|
||||
private fun openRoomMemberDetails(roomMemberId: UserId) {
|
||||
callbacks.forEach {
|
||||
it.openRoomMemberDetails(roomMember)
|
||||
it.openRoomMemberDetails(roomMemberId)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import androidx.compose.runtime.LaunchedEffect
|
|||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import io.element.android.features.userlist.api.SelectionMode
|
||||
import io.element.android.features.userlist.api.UserListDataSource
|
||||
import io.element.android.features.userlist.api.UserListDataStore
|
||||
|
|
@ -61,33 +60,20 @@ class RoomMemberListPresenter @Inject constructor(
|
|||
|
||||
@Composable
|
||||
override fun present(): RoomMemberListState {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val userListState = userListPresenter.present()
|
||||
val allUsers = remember { mutableStateOf<Async<ImmutableList<MatrixUser>>>(Async.Loading()) }
|
||||
val selectedMember: MutableState<RoomMember?> = remember {
|
||||
mutableStateOf(null)
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
withContext(coroutineDispatchers.io) {
|
||||
allUsers.value = Async.Success(userListDataSource.search("").toImmutableList())
|
||||
}
|
||||
}
|
||||
|
||||
fun handleEvents(roomMemberListEvents: RoomMemberListEvents) {
|
||||
when (roomMemberListEvents) {
|
||||
is RoomMemberListEvents.SelectUser -> coroutineScope.loadRoomMember(roomMemberListEvents.user, selectedMember)
|
||||
}
|
||||
}
|
||||
return RoomMemberListState(
|
||||
allUsers = allUsers.value,
|
||||
userListState = userListState,
|
||||
selectedRoomMember = selectedMember.value,
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
|
||||
private fun CoroutineScope.loadRoomMember(user: MatrixUser, selectedMember: MutableState<RoomMember?>) = launch(coroutineDispatchers.io) {
|
||||
selectedMember.value = room.getMemberFlow(user.id).firstOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,4 @@ import kotlinx.collections.immutable.ImmutableList
|
|||
data class RoomMemberListState(
|
||||
val allUsers: Async<ImmutableList<MatrixUser>>,
|
||||
val userListState: UserListState,
|
||||
val selectedRoomMember: RoomMember? = null,
|
||||
val eventSink: (RoomMemberListEvents) -> Unit,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -39,5 +39,4 @@ internal fun aRoomMemberListState(
|
|||
RoomMemberListState(
|
||||
userListState = aUserListState().copy(searchResults = searchResults),
|
||||
allUsers = allUsers,
|
||||
eventSink = {}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import androidx.compose.foundation.lazy.rememberLazyListState
|
|||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
|
|
@ -52,7 +51,7 @@ import io.element.android.libraries.designsystem.theme.components.CenterAlignedT
|
|||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
|
|
@ -61,17 +60,11 @@ fun RoomMemberListView(
|
|||
state: RoomMemberListState,
|
||||
modifier: Modifier = Modifier,
|
||||
onBackPressed: () -> Unit = {},
|
||||
onMemberSelected: (RoomMember) -> Unit = {},
|
||||
onMemberSelected: (UserId) -> Unit = {},
|
||||
) {
|
||||
|
||||
LaunchedEffect(state.selectedRoomMember) {
|
||||
if (state.selectedRoomMember != null) {
|
||||
onMemberSelected(state.selectedRoomMember)
|
||||
}
|
||||
}
|
||||
|
||||
fun onUserSelected(user: MatrixUser) {
|
||||
state.eventSink(RoomMemberListEvents.SelectUser(user))
|
||||
onMemberSelected(user.id)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ import io.element.android.libraries.androidutils.system.startSharePlainTextInten
|
|||
import io.element.android.libraries.architecture.NodeInputs
|
||||
import io.element.android.libraries.architecture.inputs
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
import timber.log.Timber
|
||||
import io.element.android.libraries.androidutils.R as AndroidUtilsR
|
||||
|
||||
|
|
@ -43,18 +43,18 @@ class RoomMemberDetailsNode @AssistedInject constructor(
|
|||
) : Node(buildContext, plugins = plugins) {
|
||||
|
||||
data class Inputs(
|
||||
val member: RoomMember,
|
||||
val roomMemberId: UserId,
|
||||
) : NodeInputs
|
||||
|
||||
private val inputs = inputs<Inputs>()
|
||||
private val presenter = presenterFactory.create(inputs.member)
|
||||
private val presenter = presenterFactory.create(inputs.roomMemberId)
|
||||
|
||||
@Composable
|
||||
override fun View(modifier: Modifier) {
|
||||
val context = LocalContext.current
|
||||
|
||||
fun onShareUser() {
|
||||
val permalinkResult = PermalinkBuilder.permalinkForUser(inputs.member.userId)
|
||||
val permalinkResult = PermalinkBuilder.permalinkForUser(inputs.roomMemberId)
|
||||
permalinkResult.onSuccess { permalink ->
|
||||
startSharePlainTextIntent(
|
||||
context = context,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package io.element.android.features.roomdetails.impl.members.details
|
|||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.produceState
|
||||
|
|
@ -28,29 +29,33 @@ import dagger.assisted.Assisted
|
|||
import dagger.assisted.AssistedInject
|
||||
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsState.ConfirmationDialog
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
import io.element.android.libraries.matrix.api.room.getMemberFlow
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class RoomMemberDetailsPresenter @AssistedInject constructor(
|
||||
private val client: MatrixClient,
|
||||
private val room: MatrixRoom,
|
||||
@Assisted private val roomMember: RoomMember,
|
||||
@Assisted private val roomMemberId: UserId,
|
||||
) : Presenter<RoomMemberDetailsState> {
|
||||
|
||||
interface Factory {
|
||||
fun create(roomMember: RoomMember): RoomMemberDetailsPresenter
|
||||
fun create(roomMemberId: UserId): RoomMemberDetailsPresenter
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun present(): RoomMemberDetailsState {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
var confirmationDialog by remember { mutableStateOf<ConfirmationDialog?>(null) }
|
||||
val isBlocked = remember { mutableStateOf(roomMember.isIgnored) }
|
||||
val roomMember by room.getMemberFlow(roomMemberId).collectAsState(initial = null)
|
||||
|
||||
val isBlocked = remember(roomMember?.isIgnored) {
|
||||
mutableStateOf(roomMember?.isIgnored.orFalse())
|
||||
}
|
||||
|
||||
fun handleEvents(event: RoomMemberDetailsEvents) {
|
||||
when (event) {
|
||||
|
|
@ -59,7 +64,7 @@ class RoomMemberDetailsPresenter @AssistedInject constructor(
|
|||
confirmationDialog = ConfirmationDialog.Block
|
||||
} else {
|
||||
confirmationDialog = null
|
||||
coroutineScope.blockUser(roomMember.userId, isBlocked)
|
||||
coroutineScope.blockUser(roomMemberId, isBlocked)
|
||||
}
|
||||
}
|
||||
is RoomMemberDetailsEvents.UnblockUser -> {
|
||||
|
|
@ -67,41 +72,50 @@ class RoomMemberDetailsPresenter @AssistedInject constructor(
|
|||
confirmationDialog = ConfirmationDialog.Unblock
|
||||
} else {
|
||||
confirmationDialog = null
|
||||
coroutineScope.unblockUser(roomMember.userId, isBlocked)
|
||||
coroutineScope.unblockUser(roomMemberId, isBlocked)
|
||||
}
|
||||
}
|
||||
RoomMemberDetailsEvents.ClearConfirmationDialog -> confirmationDialog = null
|
||||
}
|
||||
}
|
||||
|
||||
val userName by produceState(initialValue = roomMember.displayName) {
|
||||
room.userDisplayName(roomMember.userId).onSuccess { displayName ->
|
||||
val userName by produceState(initialValue = roomMember?.displayName) {
|
||||
room.userDisplayName(roomMemberId).onSuccess { displayName ->
|
||||
if (displayName != null) value = displayName
|
||||
}
|
||||
}
|
||||
|
||||
val userAvatar by produceState(initialValue = roomMember.avatarUrl) {
|
||||
room.userAvatarUrl(roomMember.userId).onSuccess { avatarUrl ->
|
||||
val userAvatar by produceState(initialValue = roomMember?.avatarUrl) {
|
||||
room.userAvatarUrl(roomMemberId).onSuccess { avatarUrl ->
|
||||
if (avatarUrl != null) value = avatarUrl
|
||||
}
|
||||
}
|
||||
|
||||
return RoomMemberDetailsState(
|
||||
userId = roomMember.userId.value,
|
||||
userId = roomMemberId.value,
|
||||
userName = userName,
|
||||
avatarUrl = userAvatar,
|
||||
isBlocked = isBlocked.value,
|
||||
displayConfirmationDialog = confirmationDialog,
|
||||
isCurrentUser = roomMember.userId == client.sessionId,
|
||||
isCurrentUser = roomMember?.userId == client.sessionId,
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
|
||||
private fun CoroutineScope.blockUser(userId: UserId, isBlockedState: MutableState<Boolean>) = launch {
|
||||
client.ignoreUser(userId).onSuccess { isBlockedState.value = true }
|
||||
client.ignoreUser(userId)
|
||||
.map {
|
||||
isBlockedState.value = true
|
||||
room.updateMembers()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun CoroutineScope.unblockUser(userId: UserId, isBlockedState: MutableState<Boolean>) = launch {
|
||||
client.unignoreUser(userId).onSuccess { isBlockedState.value = false }
|
||||
client.unignoreUser(userId)
|
||||
.map {
|
||||
isBlockedState.value = false
|
||||
room.updateMembers()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@ class RoomDetailsPresenterTests {
|
|||
|
||||
private fun aRoomDetailsPresenter(room: MatrixRoom): RoomDetailsPresenter {
|
||||
val roomMemberDetailsPresenterFactory = object : RoomMemberDetailsPresenter.Factory {
|
||||
override fun create(roomMember: RoomMember): RoomMemberDetailsPresenter {
|
||||
return RoomMemberDetailsPresenter(aMatrixClient(), room, roomMember)
|
||||
override fun create(roomMemberId: UserId): RoomMemberDetailsPresenter {
|
||||
return RoomMemberDetailsPresenter(aMatrixClient(), room, roomMemberId)
|
||||
}
|
||||
}
|
||||
return RoomDetailsPresenter(room, roomMembershipObserver, testCoroutineDispatchers, roomMemberDetailsPresenterFactory)
|
||||
|
|
|
|||
|
|
@ -16,11 +16,8 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.room
|
||||
|
||||
import android.os.Parcelable
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class RoomMember(
|
||||
val userId: UserId,
|
||||
val displayName: String?,
|
||||
|
|
@ -30,7 +27,7 @@ data class RoomMember(
|
|||
val powerLevel: Long,
|
||||
val normalizedPowerLevel: Long,
|
||||
val isIgnored: Boolean,
|
||||
) : Parcelable
|
||||
)
|
||||
|
||||
enum class RoomMembershipState {
|
||||
BAN, INVITE, JOIN, KNOCK, LEAVE
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue