No need for UserProfilePresenterHelper anymore.

This commit is contained in:
Benoit Marty 2024-10-17 14:07:13 +02:00
parent 9b82c6df1c
commit 2c94df3647
2 changed files with 46 additions and 76 deletions

View file

@ -10,8 +10,10 @@ package io.element.android.features.userprofile.impl.root
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
@ -22,7 +24,6 @@ import io.element.android.features.createroom.api.StartDMAction
import io.element.android.features.userprofile.api.UserProfileEvents import io.element.android.features.userprofile.api.UserProfileEvents
import io.element.android.features.userprofile.api.UserProfileState import io.element.android.features.userprofile.api.UserProfileState
import io.element.android.features.userprofile.api.UserProfileState.ConfirmationDialog import io.element.android.features.userprofile.api.UserProfileState.ConfirmationDialog
import io.element.android.features.userprofile.shared.UserProfilePresenterHelper
import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
@ -31,6 +32,7 @@ import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
@ -47,10 +49,23 @@ class UserProfilePresenter @AssistedInject constructor(
fun create(userId: UserId): UserProfilePresenter fun create(userId: UserId): UserProfilePresenter
} }
private val userProfilePresenterHelper = UserProfilePresenterHelper( @Composable
userId = userId, fun getDmRoomId(): State<RoomId?> {
client = client, return produceState<RoomId?>(initialValue = null) {
) value = client.findDM(userId)
}
}
@Composable
fun getCanCall(roomId: RoomId?): State<Boolean> {
return produceState(initialValue = false, roomId) {
value = if (client.isMe(userId)) {
false
} else {
roomId?.let { client.getRoom(it)?.canUserJoinCall(client.sessionId)?.getOrNull() == true }.orFalse()
}
}
}
@Composable @Composable
override fun present(): UserProfileState { override fun present(): UserProfileState {
@ -60,8 +75,8 @@ class UserProfilePresenter @AssistedInject constructor(
var userProfile by remember { mutableStateOf<MatrixUser?>(null) } var userProfile by remember { mutableStateOf<MatrixUser?>(null) }
val startDmActionState: MutableState<AsyncAction<RoomId>> = remember { mutableStateOf(AsyncAction.Uninitialized) } val startDmActionState: MutableState<AsyncAction<RoomId>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
val isBlocked: MutableState<AsyncData<Boolean>> = remember { mutableStateOf(AsyncData.Uninitialized) } val isBlocked: MutableState<AsyncData<Boolean>> = remember { mutableStateOf(AsyncData.Uninitialized) }
val dmRoomId by userProfilePresenterHelper.getDmRoomId() val dmRoomId by getDmRoomId()
val canCall by userProfilePresenterHelper.getCanCall(dmRoomId) val canCall by getCanCall(dmRoomId)
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
client.ignoredUsersFlow client.ignoredUsersFlow
.map { ignoredUsers -> userId in ignoredUsers } .map { ignoredUsers -> userId in ignoredUsers }
@ -80,7 +95,7 @@ class UserProfilePresenter @AssistedInject constructor(
confirmationDialog = ConfirmationDialog.Block confirmationDialog = ConfirmationDialog.Block
} else { } else {
confirmationDialog = null confirmationDialog = null
userProfilePresenterHelper.blockUser(coroutineScope, isBlocked) coroutineScope.blockUser(isBlocked)
} }
} }
is UserProfileEvents.UnblockUser -> { is UserProfileEvents.UnblockUser -> {
@ -88,7 +103,7 @@ class UserProfilePresenter @AssistedInject constructor(
confirmationDialog = ConfirmationDialog.Unblock confirmationDialog = ConfirmationDialog.Unblock
} else { } else {
confirmationDialog = null confirmationDialog = null
userProfilePresenterHelper.unblockUser(coroutineScope, isBlocked) coroutineScope.unblockUser(isBlocked)
} }
} }
UserProfileEvents.ClearConfirmationDialog -> confirmationDialog = null UserProfileEvents.ClearConfirmationDialog -> confirmationDialog = null
@ -119,4 +134,26 @@ class UserProfilePresenter @AssistedInject constructor(
eventSink = ::handleEvents eventSink = ::handleEvents
) )
} }
private fun CoroutineScope.blockUser(
isBlockedState: MutableState<AsyncData<Boolean>>,
) = launch {
isBlockedState.value = AsyncData.Loading(false)
client.ignoreUser(userId)
.onFailure {
isBlockedState.value = AsyncData.Failure(it, false)
}
// Note: on success, ignoredUsersFlow will emit new item.
}
private fun CoroutineScope.unblockUser(
isBlockedState: MutableState<AsyncData<Boolean>>,
) = launch {
isBlockedState.value = AsyncData.Loading(true)
client.unignoreUser(userId)
.onFailure {
isBlockedState.value = AsyncData.Failure(it, true)
}
// Note: on success, ignoredUsersFlow will emit new item.
}
} }

View file

@ -1,67 +0,0 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.features.userprofile.shared
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.produceState
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
class UserProfilePresenterHelper(
private val userId: UserId,
private val client: MatrixClient,
) {
@Composable
fun getDmRoomId(): State<RoomId?> {
return produceState<RoomId?>(initialValue = null) {
value = client.findDM(userId)
}
}
@Composable
fun getCanCall(roomId: RoomId?): State<Boolean> {
return produceState(initialValue = false, roomId) {
value = if (client.isMe(userId)) {
false
} else {
roomId?.let { client.getRoom(it)?.canUserJoinCall(client.sessionId)?.getOrNull() == true }.orFalse()
}
}
}
fun blockUser(
scope: CoroutineScope,
isBlockedState: MutableState<AsyncData<Boolean>>,
) = scope.launch {
isBlockedState.value = AsyncData.Loading(false)
client.ignoreUser(userId)
.onFailure {
isBlockedState.value = AsyncData.Failure(it, false)
}
// Note: on success, ignoredUserList will be updated.
}
fun unblockUser(
scope: CoroutineScope,
isBlockedState: MutableState<AsyncData<Boolean>>,
) = scope.launch {
isBlockedState.value = AsyncData.Loading(true)
client.unignoreUser(userId)
.onFailure {
isBlockedState.value = AsyncData.Failure(it, true)
}
// Note: on success, ignoredUserList will be updated.
}
}