Merge pull request #6045 from element-hq/feature/fga/invite_people_suggestions
Add suggestions section to InvitePeopleView
This commit is contained in:
commit
dd68db3fc1
17 changed files with 239 additions and 60 deletions
|
|
@ -85,6 +85,13 @@ interface BaseRoom : Closeable {
|
|||
*/
|
||||
suspend fun getUpdatedMember(userId: UserId): Result<RoomMember>
|
||||
|
||||
/**
|
||||
* Gets the direct room member, if any.
|
||||
* This is a convenience method for getting the other member in a direct message room.
|
||||
* Returns null if the room is not a dm or if the member cannot be found.
|
||||
*/
|
||||
suspend fun getDirectRoomMember(): RoomMember?
|
||||
|
||||
/**
|
||||
* Adds the room to the sync subscription list.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -17,10 +17,7 @@ import kotlin.coroutines.CoroutineContext
|
|||
* It does filter through the already known members, it doesn't perform additional requests.
|
||||
*/
|
||||
suspend fun BaseRoom.filterMembers(query: String, coroutineContext: CoroutineContext): List<RoomMember> = withContext(coroutineContext) {
|
||||
val roomMembersState = membersStateFlow.value
|
||||
val activeRoomMembers = roomMembersState.roomMembers()
|
||||
?.filter { it.membership.isActive() }
|
||||
.orEmpty()
|
||||
val activeRoomMembers = membersStateFlow.value.activeRoomMembers()
|
||||
val filteredMembers = if (query.isBlank()) {
|
||||
activeRoomMembers
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -11,48 +11,35 @@ package io.element.android.libraries.matrix.api.room.recent
|
|||
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 io.element.android.libraries.matrix.api.room.BaseRoom
|
||||
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
|
||||
import io.element.android.libraries.matrix.api.room.isDm
|
||||
import io.element.android.libraries.matrix.api.room.toMatrixUser
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import kotlinx.coroutines.flow.first
|
||||
|
||||
private const val MAX_RECENT_DIRECT_ROOMS_TO_RETURN = 5
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
|
||||
data class RecentDirectRoom(
|
||||
val roomId: RoomId,
|
||||
val matrixUser: MatrixUser,
|
||||
)
|
||||
|
||||
suspend fun MatrixClient.getRecentDirectRooms(
|
||||
maxNumberOfResults: Int = MAX_RECENT_DIRECT_ROOMS_TO_RETURN,
|
||||
): List<RecentDirectRoom> {
|
||||
val result = mutableListOf<RecentDirectRoom>()
|
||||
/**
|
||||
* Returns a [Flow] of [RecentDirectRoom] from recently visited DM rooms.
|
||||
* The flow emits items lazily, allowing callers to filter and take only what they need.
|
||||
* Use [kotlinx.coroutines.flow.take] to limit results and stop iteration early.
|
||||
*/
|
||||
fun MatrixClient.getRecentDirectRooms(): Flow<RecentDirectRoom> = flow {
|
||||
val foundUserIds = mutableSetOf<UserId>()
|
||||
getRecentlyVisitedRooms().getOrNull()?.let { roomIds ->
|
||||
roomIds
|
||||
.mapNotNull { roomId -> getRoom(roomId) }
|
||||
.filter { it.isDm() && it.isJoined() }
|
||||
.map { room ->
|
||||
val otherUser = room.getMembers().getOrNull()
|
||||
?.firstOrNull { it.userId != sessionId }
|
||||
?.takeIf { foundUserIds.add(it.userId) }
|
||||
?.toMatrixUser()
|
||||
if (otherUser != null) {
|
||||
result.add(
|
||||
RecentDirectRoom(room.roomId, otherUser)
|
||||
)
|
||||
// Return early to avoid useless computation
|
||||
if (result.size >= maxNumberOfResults) {
|
||||
return@map
|
||||
}
|
||||
val recentlyVisitedRooms = getRecentlyVisitedRooms().getOrDefault(emptyList())
|
||||
for (roomId in recentlyVisitedRooms) {
|
||||
getRoom(roomId)?.use { room ->
|
||||
val info = room.info()
|
||||
if (info.isDm && info.currentUserMembership == CurrentUserMembership.JOINED) {
|
||||
val otherUser = room.getDirectRoomMember()?.toMatrixUser()
|
||||
if (otherUser != null && foundUserIds.add(otherUser.userId)) {
|
||||
emit(RecentDirectRoom(room.roomId, otherUser))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
suspend fun BaseRoom.isJoined(): Boolean {
|
||||
return roomInfoFlow.first().currentUserMembership == CurrentUserMembership.JOINED
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.api.room.RoomMember
|
|||
import io.element.android.libraries.matrix.api.room.RoomMembersState
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||
import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
|
||||
import io.element.android.libraries.matrix.api.room.isDm
|
||||
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions
|
||||
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues
|
||||
import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom
|
||||
|
|
@ -112,6 +113,20 @@ class RustBaseRoom(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getDirectRoomMember(): RoomMember? = withContext(roomDispatcher) {
|
||||
runCatchingExceptions {
|
||||
if (info().isDm) {
|
||||
innerRoom.membersNoSync().use { members ->
|
||||
members.nextChunk(members.len())
|
||||
?.map(RoomMemberMapper::map)
|
||||
?.firstOrNull { roomMember -> roomMember.userId != sessionId && roomMember.membership.isActive() }
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
override suspend fun getUpdatedMember(userId: UserId): Result<RoomMember> = withContext(roomDispatcher) {
|
||||
runCatchingExceptions {
|
||||
RoomMemberMapper.map(innerRoom.member(userId.value))
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ class FakeBaseRoom(
|
|||
private val leaveRoomLambda: () -> Result<Unit> = { lambdaError() },
|
||||
private var updateMembersResult: () -> Unit = { lambdaError() },
|
||||
private val getMembersResult: (Int) -> Result<List<RoomMember>> = { lambdaError() },
|
||||
private val getDirectRoomMemberResult: () -> RoomMember? = { null },
|
||||
private val saveComposerDraftLambda: (ComposerDraft) -> Result<Unit> = { _: ComposerDraft -> Result.success(Unit) },
|
||||
private val loadComposerDraftLambda: () -> Result<ComposerDraft?> = { Result.success<ComposerDraft?>(null) },
|
||||
private val clearComposerDraftLambda: () -> Result<Unit> = { Result.success(Unit) },
|
||||
|
|
@ -90,6 +91,10 @@ class FakeBaseRoom(
|
|||
return getMembersResult(limit)
|
||||
}
|
||||
|
||||
override suspend fun getDirectRoomMember(): RoomMember? {
|
||||
return getDirectRoomMemberResult()
|
||||
}
|
||||
|
||||
override suspend fun subscribeToSync() {
|
||||
subscribeToSyncLambda()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue