diff --git a/app/src/main/java/org/futo/circles/feature/people/category/PeopleCategoryDataSource.kt b/app/src/main/java/org/futo/circles/feature/people/category/PeopleCategoryDataSource.kt new file mode 100644 index 0000000000000000000000000000000000000000..f3797f438b6a357112e2daca416f876fcfc1cf53 --- /dev/null +++ b/app/src/main/java/org/futo/circles/feature/people/category/PeopleCategoryDataSource.kt @@ -0,0 +1,106 @@ +package org.futo.circles.feature.people.category + +import androidx.lifecycle.asFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map +import org.futo.circles.core.extensions.getKnownUsersFlow +import org.futo.circles.core.extensions.getRoomOwner +import org.futo.circles.core.feature.workspace.SharedCircleDataSource +import org.futo.circles.core.feature.workspace.SpacesTreeAccountDataSource +import org.futo.circles.core.model.CIRCLES_SPACE_ACCOUNT_DATA_KEY +import org.futo.circles.core.provider.MatrixSessionProvider +import org.futo.circles.core.utils.getJoinedRoomById +import org.futo.circles.core.utils.getTimelineRoomFor +import org.futo.circles.mapping.toPeopleIgnoredListItem +import org.futo.circles.mapping.toPeopleUserListItem +import org.futo.circles.model.PeopleCategoryTypeArg +import org.matrix.android.sdk.api.session.getUserOrDefault +import org.matrix.android.sdk.api.session.room.model.RoomSummary +import org.matrix.android.sdk.api.session.user.model.User +import javax.inject.Inject + +class PeopleCategoryDataSource @Inject constructor( + private val spacesTreeAccountDataSource: SpacesTreeAccountDataSource, + private val sharedCircleDataSource: SharedCircleDataSource +) { + + private val session = MatrixSessionProvider.getSessionOrThrow() + + fun getUsersListByCategoryFlow(categoryType: PeopleCategoryTypeArg) = when (categoryType) { + PeopleCategoryTypeArg.Ignored -> getIgnoredUserFlow().map { list -> list.map { it.toPeopleIgnoredListItem() } } + else -> combine( + session.getKnownUsersFlow(), + getIgnoredUserFlow() + ) { knowUsers, ignoredUsers -> + val ignoreUserIds = ignoredUsers.map { it.userId } + val userByCategory = when (categoryType) { + PeopleCategoryTypeArg.Connections -> getMyConnections(knowUsers) + PeopleCategoryTypeArg.Followers -> getFollowers() + PeopleCategoryTypeArg.Following -> getPeopleImFollowing() + else -> getOtherUsers( + knowUsers, + getMyConnections(knowUsers), + getFollowers(), + getPeopleImFollowing() + ) + } + userByCategory.map { it.toPeopleUserListItem(ignoreUserIds.contains(it.userId)) } + } + } + + + fun getProfileRoomId() = sharedCircleDataSource.getSharedCirclesSpaceId() ?: "" + + fun getIgnoredUserFlow() = session.userService().getIgnoredUsersLive().asFlow() + + //All the joined members (except me) in all of my circle timeline rooms + fun getFollowers(): List<User> { + val myCirclesSpace = getMyCirclesSpaceSummary() ?: return emptyList() + val myTimelinesFollowersIds = myCirclesSpace.spaceChildren?.mapNotNull { + getTimelineRoomFor(it.childRoomId)?.roomSummary()?.otherMemberIds + }?.flatMap { it.toSet() } ?: emptyList() + + return myTimelinesFollowersIds.map { session.getUserOrDefault(it) } + } + + //All the creators of all the timeline rooms that I'm following in my circles + fun getPeopleImFollowing(): List<User> { + val myCirclesSpace = getMyCirclesSpaceSummary() ?: return emptyList() + val peopleIamFollowingIds = myCirclesSpace.spaceChildren?.mapNotNull { + getJoinedRoomById(it.childRoomId)?.roomSummary()?.spaceChildren?.mapNotNull { + getRoomOwner(it.childRoomId)?.userId?.takeIf { it != session.myUserId } + } + }?.flatMap { it.toSet() } ?: emptyList() + + return peopleIamFollowingIds.map { session.getUserOrDefault(it) } + } + + fun getMyConnections(knowUsers: List<User>) = knowUsers.filter { isConnection(it.userId) } + + fun getOtherUsers( + knowUsers: List<User>, + connections: List<User>, + followers: List<User>, + following: List<User> + ): List<User> { + val knownIds = knowUsers.map { it.userId } + val connectionsIds = connections.map { it.userId } + val followersUsersIds = followers.map { it.userId } + val followingUsersIds = following.map { it.userId } + + val otherMemberIds = + knownIds - connectionsIds.toSet() - followersUsersIds.toSet() - followingUsersIds.toSet() + + return otherMemberIds.map { session.getUserOrDefault(it) } + } + + private fun isConnection(userId: String) = + sharedCircleDataSource.getSharedCircleFor(userId) != null + + private fun getMyCirclesSpaceSummary(): RoomSummary? { + val circlesSpaceId = spacesTreeAccountDataSource.getRoomIdByKey( + CIRCLES_SPACE_ACCOUNT_DATA_KEY + ) ?: "" + return getJoinedRoomById(circlesSpaceId)?.roomSummary() + } +} \ No newline at end of file