Skip to content
Snippets Groups Projects
Commit 2b59ad04 authored by Taras's avatar Taras
Browse files

Change people tab categories

parent d50542c1
No related branches found
No related tags found
No related merge requests found
......@@ -8,23 +8,32 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.withContext
import org.futo.circles.core.extensions.getRoomOwner
import org.futo.circles.core.feature.room.knoks.KnockRequestsDataSource
import org.futo.circles.core.feature.select_users.SearchUserDataSource
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.toPeopleUserListItem
import org.futo.circles.model.PeopleHeaderItem
import org.futo.circles.model.PeopleItemType
import org.futo.circles.model.PeopleListItem
import org.futo.circles.model.PeopleRequestNotificationListItem
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.RoomType
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
import org.matrix.android.sdk.api.session.user.model.User
import javax.inject.Inject
class PeopleDataSource @Inject constructor(
private val searchUserDataSource: SearchUserDataSource,
private val sharedCircleDataSource: SharedCircleDataSource,
private val knockRequestsDataSource: KnockRequestsDataSource
private val knockRequestsDataSource: KnockRequestsDataSource,
private val spacesTreeAccountDataSource: SpacesTreeAccountDataSource
) {
private val session = MatrixSessionProvider.currentSession
......@@ -35,18 +44,28 @@ class PeopleDataSource @Inject constructor(
it.size
}?.asFlow() ?: flowOf()
private fun getProfileSpaceInvitesCountFlow() = session?.roomService()?.getRoomSummariesLive(
roomSummaryQueryParams {
excludeType = null
memberships = listOf(Membership.INVITE)
})?.map { it.filter { it.roomType == RoomType.SPACE } }?.map { it.size }
?.asFlow() ?: flowOf()
suspend fun getPeopleList(query: String) = combine(
searchUserDataSource.searchKnownUsers(query),
searchUserDataSource.searchSuggestions(query),
getIgnoredUserFlow(),
getKnockRequestCountFlow()
) { knowUsers, suggestions, ignoredUsers, requestsCount ->
getKnockRequestCountFlow(),
getProfileSpaceInvitesCountFlow()
) { knowUsers, suggestions, ignoredUsers, knocksCount, profileInvitesCount ->
withContext(Dispatchers.IO) {
buildList(
knowUsers,
suggestions,
ignoredUsers,
requestsCount
knocksCount,
profileInvitesCount
)
}
}.distinctUntilChanged()
......@@ -63,54 +82,100 @@ class PeopleDataSource @Inject constructor(
knowUsers: List<User>,
suggestions: List<User>,
ignoredUsers: List<User>,
requestsCount: Int
knocksCount: Int,
profileInvitesCount: Int
): List<PeopleListItem> {
val knownIds = knowUsers.map { it.userId }
val ignoredUsersIds = ignoredUsers.map { it.userId }.toSet()
val uniqueItemsList = mutableListOf<PeopleListItem>().apply {
addAll(knowUsers.map { it.toPeopleUserListItem(getKnownUserItemType(it.userId)) })
addAll(suggestions.map { it.toPeopleUserListItem(PeopleItemType.Suggestion) })
}
.distinctBy { it.id }
.filterNot { it.id == session?.myUserId || ignoredUsersIds.contains(it.id) }
val followingUsersIds = getPeopleImFollowingIds()
val followersUsersIds = getFollowersIds()
val connectionsIds =
knowUsers.mapNotNull { if (isConnection(it.userId)) it.userId else null }
val otherMemberIds =
knownIds - connectionsIds.toSet() - followersUsersIds.toSet() - followingUsersIds.toSet()
val uniqueSuggestions = suggestions.filter { !knownIds.contains(it.userId) }
val requestsCount = knocksCount + profileInvitesCount
return mutableListOf<PeopleListItem>().apply {
if (requestsCount > 0)
add(PeopleRequestNotificationListItem(requestsCount))
addSection(
PeopleHeaderItem.friends,
uniqueItemsList.filter { it.type == PeopleItemType.Friend }
PeopleHeaderItem.connections,
knowUsers.mapNotNull {
if (connectionsIds.contains(it.userId)) it.toPeopleUserListItem(
PeopleItemType.Connection,
ignoredUsersIds.contains(it.userId)
) else null
}
)
addSection(
PeopleHeaderItem.followingUsersHeader,
uniqueItemsList.filter { it.type == PeopleItemType.Following }
knowUsers.mapNotNull {
if (followingUsersIds.contains(it.userId)) it.toPeopleUserListItem(
PeopleItemType.Following,
ignoredUsersIds.contains(it.userId)
) else null
}
)
addSection(
PeopleHeaderItem.followersUsersHeader,
uniqueItemsList.filter { it.type == PeopleItemType.Follower }
knowUsers.mapNotNull {
if (followersUsersIds.contains(it.userId)) it.toPeopleUserListItem(
PeopleItemType.Follower,
ignoredUsersIds.contains(it.userId)
) else null
}
)
addSection(
PeopleHeaderItem.knownUsersHeader,
uniqueItemsList.filter { it.type == PeopleItemType.Known }
PeopleHeaderItem.othersHeader,
knowUsers.mapNotNull {
if (otherMemberIds.contains(it.userId)) it.toPeopleUserListItem(
PeopleItemType.Others,
ignoredUsersIds.contains(it.userId)
) else null
}
)
addSection(
PeopleHeaderItem.suggestions,
uniqueItemsList.filter { it.type == PeopleItemType.Suggestion }
uniqueSuggestions.map {
it.toPeopleUserListItem(
PeopleItemType.Suggestion,
ignoredUsersIds.contains(it.userId)
)
}
)
}
}
private fun getKnownUserItemType(userId: String): PeopleItemType {
val isFollower = isMyFollower(userId)
val amIFollowing = amIFollowing(userId)
val isFriend = isFollower && amIFollowing
//All the joined members (except me) in all of my circle timeline rooms
private fun getFollowersIds(): List<String> {
val myCirclesSpace = getMyCirclesSpaceSummary() ?: return emptyList()
val myTimelinesFollowers = myCirclesSpace.spaceChildren?.mapNotNull {
getTimelineRoomFor(it.childRoomId)?.roomSummary()?.otherMemberIds
}?.flatMap { it.toSet() } ?: emptyList()
return when {
isFriend -> PeopleItemType.Friend
amIFollowing -> PeopleItemType.Following
isFollower -> PeopleItemType.Follower
else -> PeopleItemType.Known
}
return myTimelinesFollowers
}
//All the creators of all the timeline rooms that I'm following in my circles
private fun getPeopleImFollowingIds(): List<String> {
val myCirclesSpace = getMyCirclesSpaceSummary() ?: return emptyList()
val peopleIamFollowing = myCirclesSpace.spaceChildren?.mapNotNull {
getJoinedRoomById(it.childRoomId)?.roomSummary()?.spaceChildren?.mapNotNull {
getRoomOwner(it.childRoomId)?.userId?.takeIf { it != session?.myUserId }
}
}?.flatMap { it.toSet() } ?: emptyList()
return peopleIamFollowing
}
private fun getMyCirclesSpaceSummary(): RoomSummary? {
val circlesSpaceId = spacesTreeAccountDataSource.getRoomIdByKey(
CIRCLES_SPACE_ACCOUNT_DATA_KEY
) ?: ""
return getJoinedRoomById(circlesSpaceId)?.roomSummary()
}
private fun MutableList<PeopleListItem>.addSection(
......@@ -123,13 +188,7 @@ class PeopleDataSource @Inject constructor(
}
}
private fun isMyFollower(userId: String): Boolean {
val mySharedCircleMembers =
session?.getRoom(profileRoomId)?.roomSummary()?.otherMemberIds ?: emptyList()
return mySharedCircleMembers.contains(userId)
}
private fun amIFollowing(userId: String) =
private fun isConnection(userId: String) =
sharedCircleDataSource.getSharedCircleFor(userId) != null
}
\ No newline at end of file
......@@ -6,7 +6,7 @@ import org.futo.circles.model.PeopleUserListItem
import org.matrix.android.sdk.api.session.user.model.User
fun User.toPeopleUserListItem(type: PeopleItemType) =
PeopleUserListItem(toCirclesUserSummary(), type)
fun User.toPeopleUserListItem(type: PeopleItemType, isIgnored: Boolean) =
PeopleUserListItem(toCirclesUserSummary(), type, isIgnored)
......@@ -4,7 +4,7 @@ import org.futo.circles.R
import org.futo.circles.core.base.list.IdEntity
import org.futo.circles.core.model.CirclesUserSummary
enum class PeopleItemType { Header, Friend, Following, Follower, RequestNotification, Known, Suggestion }
enum class PeopleItemType { Header, Connection, Following, Follower, RequestNotification, Others, Suggestion }
sealed class PeopleListItem(
open val type: PeopleItemType
) : IdEntity<String>
......@@ -15,17 +15,19 @@ data class PeopleHeaderItem(
override val id: String = titleRes.toString()
companion object {
val friends = PeopleHeaderItem(org.futo.circles.auth.R.string.friends)
val followersUsersHeader = PeopleHeaderItem(R.string.followers)
val followingUsersHeader = PeopleHeaderItem(org.futo.circles.core.R.string.following)
val knownUsersHeader = PeopleHeaderItem(R.string.known_users)
val connections = PeopleHeaderItem(R.string.my_connections)
val followersUsersHeader = PeopleHeaderItem(org.futo.circles.core.R.string.my_followers)
val followingUsersHeader =
PeopleHeaderItem(org.futo.circles.core.R.string.people_i_m_following)
val othersHeader = PeopleHeaderItem(org.futo.circles.core.R.string.others)
val suggestions = PeopleHeaderItem(R.string.suggestions)
}
}
class PeopleUserListItem(
val user: CirclesUserSummary,
override val type: PeopleItemType
override val type: PeopleItemType,
val isIgnored: Boolean
) : PeopleListItem(type) {
override val id: String = user.id
}
......
......@@ -203,6 +203,7 @@
<string name="group_invites_notification_format">Show %d Group invitations</string>
<string name="circle_invites_notification_format">Show %d Circle invitations</string>
<string name="show_follow_requests_format">Show %d follow requests</string>
<string name="my_connections">My Connections</string>
<!-- Rich text editor -->
<string name="rich_text_editor_format_bold">Apply bold format</string>
......
......@@ -54,16 +54,17 @@ suspend fun Session.getOrFetchUser(userId: String): User =
getUser(userId) ?: userService().resolveUser(userId)
fun Session.getKnownUsersFlow() = roomService().getRoomSummariesLive(roomSummaryQueryParams {
memberships = listOf(Membership.JOIN)
}).asFlow()
.mapLatest { roomSummaries ->
val knowUsers = mutableSetOf<User>()
roomSummaries.forEach { summary ->
val joinedMembersIds = getRoom(summary.roomId)?.membershipService()
?.getRoomMembers(roomMemberQueryParams {
memberships = listOf(Membership.JOIN)
})?.map { it.userId } ?: emptyList()
joinedMembersIds.forEach { knowUsers.add(getOrFetchUser(it)) }
}
knowUsers.toList().filterNot { getUserIdsToExclude().contains(it.userId) }
excludeType = null
memberships = listOf(Membership.JOIN)
}).asFlow()
.mapLatest { roomSummaries ->
val knowUsers = mutableSetOf<User>()
roomSummaries.forEach { summary ->
val joinedMembersIds = getRoom(summary.roomId)?.membershipService()
?.getRoomMembers(roomMemberQueryParams {
memberships = listOf(Membership.JOIN)
})?.map { it.userId } ?: emptyList()
joinedMembersIds.forEach { knowUsers.add(getOrFetchUser(it)) }
}
knowUsers.toList().filterNot { getUserIdsToExclude().contains(it.userId) }
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment