diff --git a/app/src/main/java/org/futo/circles/feature/circles/list/CirclesListAdapter.kt b/app/src/main/java/org/futo/circles/feature/circles/list/CirclesListAdapter.kt index ffc2fb21a31ee7615649550df04d599600c1d8b2..497112a8fb87ed5858eb21df13c861c585992b68 100644 --- a/app/src/main/java/org/futo/circles/feature/circles/list/CirclesListAdapter.kt +++ b/app/src/main/java/org/futo/circles/feature/circles/list/CirclesListAdapter.kt @@ -34,7 +34,7 @@ class CirclesListAdapter( override fun onCreateViewHolder( parent: ViewGroup, viewType: Int - ) = when (CirclesListItemViewType.values()[viewType]) { + ) = when (CirclesListItemViewType.entries[viewType]) { CirclesListItemViewType.JoinedCircle -> JoinedCircleViewHolder( parent = parent, onCircleClicked = { position -> onRoomClicked(getItem(position)) } diff --git a/app/src/main/java/org/futo/circles/feature/groups/list/GroupsListAdapter.kt b/app/src/main/java/org/futo/circles/feature/groups/list/GroupsListAdapter.kt index 825a1af45a754a0fff16d56f419ff6de79d188d4..a2049aa0651e947d546cc350746efe588ae78629 100644 --- a/app/src/main/java/org/futo/circles/feature/groups/list/GroupsListAdapter.kt +++ b/app/src/main/java/org/futo/circles/feature/groups/list/GroupsListAdapter.kt @@ -33,7 +33,7 @@ class GroupsListAdapter( override fun onCreateViewHolder( parent: ViewGroup, viewType: Int - ) = when (GroupListItemViewType.values()[viewType]) { + ) = when (GroupListItemViewType.entries[viewType]) { GroupListItemViewType.JoinedGroup -> JoinedGroupViewHolder(parent = parent, onGroupClicked = { position -> onRoomClicked(getItem(position)) }) diff --git a/app/src/main/java/org/futo/circles/feature/home/HomeViewModel.kt b/app/src/main/java/org/futo/circles/feature/home/HomeViewModel.kt index 6a813ca6e74031d129b137ca9a1f718b3552ab6c..35106ce353dacfcebf6d514e51590704fdd93d47 100644 --- a/app/src/main/java/org/futo/circles/feature/home/HomeViewModel.kt +++ b/app/src/main/java/org/futo/circles/feature/home/HomeViewModel.kt @@ -10,7 +10,6 @@ import org.futo.circles.core.extensions.Response import org.futo.circles.core.extensions.createResult import org.futo.circles.core.extensions.launchBg import org.futo.circles.core.model.GROUP_TYPE -import org.futo.circles.core.feature.workspace.SharedCircleDataSource import org.futo.circles.core.model.LoadingData import org.futo.circles.feature.notifications.PushersManager import org.futo.circles.feature.notifications.ShortcutsHandler @@ -25,8 +24,7 @@ class HomeViewModel @Inject constructor( private val workspaceTasksProvider: WorkspaceTasksProvider, private val workspaceDataSource: ConfigureWorkspaceDataSource, roomAccountDataSource: RoomAccountDataSource, - shortcutsHandler: ShortcutsHandler, - sharedCircleDataSource: SharedCircleDataSource + shortcutsHandler: ShortcutsHandler ) : ViewModel() { val validateWorkspaceLoadingLiveData = SingleEventLiveData<LoadingData>() @@ -35,7 +33,6 @@ class HomeViewModel @Inject constructor( init { shortcutsHandler.observeRoomsAndBuildShortcuts(viewModelScope) - sharedCircleDataSource.observeAndAutoAcceptSharedSpaceInvites(viewModelScope) validateWorkspace() } diff --git a/app/src/main/java/org/futo/circles/feature/ignored/list/IgnoredUsersViewHolder.kt b/app/src/main/java/org/futo/circles/feature/ignored/list/IgnoredUsersViewHolder.kt index bbded269a084374e3da8375d51890b28b1d847df..f95099cac41385f3064d591193e1343c297dd6a3 100644 --- a/app/src/main/java/org/futo/circles/feature/ignored/list/IgnoredUsersViewHolder.kt +++ b/app/src/main/java/org/futo/circles/feature/ignored/list/IgnoredUsersViewHolder.kt @@ -3,6 +3,7 @@ package org.futo.circles.feature.ignored.list import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import org.futo.circles.core.base.list.ViewBindingHolder +import org.futo.circles.core.extensions.loadUserProfileIcon import org.futo.circles.core.extensions.onClick import org.futo.circles.core.model.CirclesUserSummary import org.futo.circles.databinding.ListItemPeopleIgnoredBinding @@ -21,6 +22,10 @@ class IgnoredUsersViewHolder( } fun bind(data: CirclesUserSummary) { - binding.userItem.bind(data) + with(binding) { + tvUserName.text = data.name + tvUserId.text = data.id + ivUserImage.loadUserProfileIcon(data.avatarUrl, data.id) + } } } \ No newline at end of file diff --git a/app/src/main/java/org/futo/circles/feature/people/PeopleDataSource.kt b/app/src/main/java/org/futo/circles/feature/people/PeopleDataSource.kt index 8aec2dbca7a8c390d448ee75f3b015ec34d2967f..a18cad47b407850bd03491cf73de871e29c750e8 100644 --- a/app/src/main/java/org/futo/circles/feature/people/PeopleDataSource.kt +++ b/app/src/main/java/org/futo/circles/feature/people/PeopleDataSource.kt @@ -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 diff --git a/app/src/main/java/org/futo/circles/feature/people/list/PeopleAdapter.kt b/app/src/main/java/org/futo/circles/feature/people/list/PeopleAdapter.kt index 6ae09bfa97f7e15a0c247c856f2a31315e886870..5a7c5aaae12dc893fcb815824ed05ffe4a356f2d 100644 --- a/app/src/main/java/org/futo/circles/feature/people/list/PeopleAdapter.kt +++ b/app/src/main/java/org/futo/circles/feature/people/list/PeopleAdapter.kt @@ -19,7 +19,7 @@ class PeopleAdapter( override fun getItemViewType(position: Int): Int = getItem(position).type.ordinal override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PeopleViewHolder { - return when (PeopleItemType.values()[viewType]) { + return when (PeopleItemType.entries[viewType]) { PeopleItemType.Header -> PeopleHeaderViewHolder(parent) PeopleItemType.RequestNotification -> FollowRequestNotificationViewHolder( parent = parent, onClicked = { onOpenRequestsClicked() } diff --git a/app/src/main/java/org/futo/circles/feature/people/list/PeopleViewHolder.kt b/app/src/main/java/org/futo/circles/feature/people/list/PeopleViewHolder.kt index 6cedc05405d98604b55252b157c974fb9800c2b2..ad76e1b906879bd80b95efed215650e14eded0c3 100644 --- a/app/src/main/java/org/futo/circles/feature/people/list/PeopleViewHolder.kt +++ b/app/src/main/java/org/futo/circles/feature/people/list/PeopleViewHolder.kt @@ -8,7 +8,10 @@ import org.futo.circles.core.base.list.ViewBindingHolder import org.futo.circles.core.base.list.context import org.futo.circles.core.databinding.ListItemInviteHeaderBinding import org.futo.circles.core.databinding.ListItemInviteNotificationBinding +import org.futo.circles.core.extensions.gone +import org.futo.circles.core.extensions.loadUserProfileIcon import org.futo.circles.core.extensions.onClick +import org.futo.circles.core.extensions.setIsVisible import org.futo.circles.databinding.ListItemPeopleDefaultBinding import org.futo.circles.model.PeopleHeaderItem import org.futo.circles.model.PeopleListItem @@ -35,11 +38,40 @@ class PeopleDefaultUserViewHolder( } override fun bind(data: PeopleListItem) { - (data as? PeopleUserListItem)?.let { binding.userItem.bind(it.user) } + val userItem = (data as? PeopleUserListItem) ?: return + if (userItem.isIgnored) setUnBlurClick(userItem) + with(binding) { + tvUserName.text = userItem.user.name + tvUserId.text = userItem.user.id + ivUserImage.loadUserProfileIcon( + userItem.user.avatarUrl, + userItem.user.id, + applyBlur = userItem.isIgnored + ) + tvIgnoredLabel.setIsVisible(userItem.isIgnored) + binding.tvShowProfileImage.setIsVisible(userItem.isIgnored) + } } override fun bindPayload(data: PeopleUserListItemPayload) { - data.user?.let { binding.userItem.bind(it) } + with(binding) { + data.user?.let { + tvUserName.text = it.name + tvUserId.text = it.id + ivUserImage.loadUserProfileIcon(it.avatarUrl, it.id) + } + } + } + + private fun setUnBlurClick(userItem: PeopleUserListItem) { + binding.ivUserImage.setOnClickListener { + binding.ivUserImage.loadUserProfileIcon( + userItem.user.avatarUrl, + userItem.user.id, + applyBlur = false + ) + binding.tvShowProfileImage.gone() + } } } @@ -59,7 +91,7 @@ class FollowRequestNotificationViewHolder( override fun bind(data: PeopleListItem) { if (data !is PeopleRequestNotificationListItem) return binding.tvInvitesMessage.text = - context.getString(R.string.show_follow_requests_format, data.requestsCount) + context.getString(R.string.show_connection_invites_format, data.requestsCount) } } diff --git a/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsDataSource.kt b/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsDataSource.kt index c6d1c96e2f0c4d0b80d0a117bb425b8bdcbb7a1e..5ec366f1c79cf4443341b02dacb0a9a400bd1443 100644 --- a/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsDataSource.kt +++ b/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsDataSource.kt @@ -32,7 +32,7 @@ class SelectRoomsDataSource @Inject constructor( private val ordinal = savedStateHandle.getOrThrow<Int>(SelectRoomsFragment.TYPE_ORDINAL) private val roomType: CircleRoomTypeArg = - CircleRoomTypeArg.values().firstOrNull { it.ordinal == ordinal } + CircleRoomTypeArg.entries.firstOrNull { it.ordinal == ordinal } ?: CircleRoomTypeArg.Circle private val session by lazy { MatrixSessionProvider.currentSession } diff --git a/app/src/main/java/org/futo/circles/feature/timeline/list/TimelineAdapter.kt b/app/src/main/java/org/futo/circles/feature/timeline/list/TimelineAdapter.kt index 5d6f5407f5bf9c95ab97ee7b6cfbc14660e57092..d94c4652a3e42f43828bc071c7a28f3dcc09921c 100644 --- a/app/src/main/java/org/futo/circles/feature/timeline/list/TimelineAdapter.kt +++ b/app/src/main/java/org/futo/circles/feature/timeline/list/TimelineAdapter.kt @@ -35,7 +35,7 @@ class TimelineAdapter( override fun getItemViewType(position: Int): Int = getItem(position).content.type.ordinal override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostViewHolder { - return when (PostContentType.values()[viewType]) { + return when (PostContentType.entries[viewType]) { PostContentType.POLL_CONTENT -> PollPostViewHolder( parent, postOptionsListener, isThread ) diff --git a/app/src/main/java/org/futo/circles/mapping/MatrixUserMapping.kt b/app/src/main/java/org/futo/circles/mapping/MatrixUserMapping.kt index 2dd4b77acb43c9357af18b314f4095024ccc02cd..5466958d537c4aedfb6edaec89a514e85d80ca75 100644 --- a/app/src/main/java/org/futo/circles/mapping/MatrixUserMapping.kt +++ b/app/src/main/java/org/futo/circles/mapping/MatrixUserMapping.kt @@ -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) diff --git a/app/src/main/java/org/futo/circles/mapping/RoomSummaryMapping.kt b/app/src/main/java/org/futo/circles/mapping/RoomSummaryMapping.kt index f818d5f4ceb595d9202a59132121f3a6657b262e..8ac47c5bbc00814a8bf979eb5fd573e53e61c1d5 100644 --- a/app/src/main/java/org/futo/circles/mapping/RoomSummaryMapping.kt +++ b/app/src/main/java/org/futo/circles/mapping/RoomSummaryMapping.kt @@ -1,7 +1,9 @@ package org.futo.circles.mapping +import org.futo.circles.core.extensions.getRoomOwner import org.futo.circles.core.mapping.toRoomInfo 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.model.JoinedCircleListItem import org.futo.circles.model.JoinedGroupListItem @@ -27,12 +29,17 @@ fun RoomSummary.toJoinedCircleListItem(isShared: Boolean = false) = JoinedCircle id = roomId, info = toRoomInfo(), isShared = isShared, - followingCount = spaceChildren?.size?.takeIf { it != 0 }?.minus(1) ?: 0, + followingCount = getFollowingCount(), followedByCount = getFollowersCount(), unreadCount = getCircleUnreadMessagesCount(), knockRequestsCount = getKnocksCount(getTimelineRoomFor(roomId)?.roomId ?: "") ) +private fun RoomSummary.getFollowingCount() = spaceChildren?.filter { + getJoinedRoomById(it.childRoomId) != null && + getRoomOwner(it.childRoomId)?.userId != MatrixSessionProvider.currentSession?.myUserId +}?.size ?: 0 + private fun RoomSummary.getFollowersCount(): Int = getTimelineRoomFor(roomId)?.roomSummary()?.otherMemberIds?.size ?: 0 diff --git a/app/src/main/java/org/futo/circles/model/PeopleListItem.kt b/app/src/main/java/org/futo/circles/model/PeopleListItem.kt index 1fa1cf1f763420eee4c414f423a3147696e17493..66127074edfaabef4601ea0f309122e234734474 100644 --- a/app/src/main/java/org/futo/circles/model/PeopleListItem.kt +++ b/app/src/main/java/org/futo/circles/model/PeopleListItem.kt @@ -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 } diff --git a/app/src/main/java/org/futo/circles/view/PeopleTabUserListItemView.kt b/app/src/main/java/org/futo/circles/view/PeopleTabUserListItemView.kt deleted file mode 100644 index 37815325cc0c77a1ddd11ba3f736ccbd78fad22a..0000000000000000000000000000000000000000 --- a/app/src/main/java/org/futo/circles/view/PeopleTabUserListItemView.kt +++ /dev/null @@ -1,25 +0,0 @@ -package org.futo.circles.view - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import androidx.constraintlayout.widget.ConstraintLayout -import org.futo.circles.core.extensions.loadUserProfileIcon -import org.futo.circles.core.model.CirclesUserSummary -import org.futo.circles.databinding.ViewPeopleTabUserListItemBinding - -class PeopleTabUserListItemView( - context: Context, - attrs: AttributeSet? = null -) : ConstraintLayout(context, attrs) { - - val binding = ViewPeopleTabUserListItemBinding.inflate(LayoutInflater.from(context), this) - - fun bind(user: CirclesUserSummary) { - with(binding) { - tvUserName.text = user.name - tvUserId.text = user.id - ivUserImage.loadUserProfileIcon(user.avatarUrl, user.id) - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/list_item_people_default.xml b/app/src/main/res/layout/list_item_people_default.xml index 18ece5ada327b399c38d8093c5fb1579b7cf8825..203038ffce2c6579c20734a7261c77cf6dfe21d9 100644 --- a/app/src/main/res/layout/list_item_people_default.xml +++ b/app/src/main/res/layout/list_item_people_default.xml @@ -1,14 +1,85 @@ <?xml version="1.0" encoding="utf-8"?> -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?selectableItemBackground" android:clickable="true" android:focusable="true"> - <org.futo.circles.view.PeopleTabUserListItemView - android:id="@+id/userItem" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> -</FrameLayout> \ No newline at end of file + <com.google.android.material.imageview.ShapeableImageView + android:id="@+id/ivUserImage" + android:layout_width="72dp" + android:layout_height="72dp" + android:layout_marginStart="8dp" + android:layout_marginTop="4dp" + android:layout_marginBottom="4dp" + android:scaleType="centerCrop" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent" + tools:background="@color/blue" /> + + <TextView + android:id="@+id/tvShowProfileImage" + style="@style/body" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:drawablePadding="-4dp" + android:text="@string/show" + android:textColor="@color/white" + android:visibility="gone" + app:drawableTint="@color/white" + app:drawableTopCompat="@drawable/ic_seen" + app:layout_constraintBottom_toBottomOf="@id/ivUserImage" + app:layout_constraintEnd_toEndOf="@id/ivUserImage" + app:layout_constraintStart_toStartOf="@id/ivUserImage" + app:layout_constraintTop_toTopOf="@id/ivUserImage" + tools:visibility="visible" /> + + <TextView + android:id="@+id/tvUserName" + style="@style/title2" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:ellipsize="end" + android:lines="1" + app:layout_constraintBottom_toTopOf="@id/tvUserId" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@id/ivUserImage" + app:layout_constraintTop_toTopOf="@id/ivUserImage" + app:layout_constraintVertical_chainStyle="packed" + tools:text="Android01" /> + + <TextView + android:id="@+id/tvUserId" + style="@style/subheadline" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:ellipsize="end" + android:lines="1" + app:layout_constraintBottom_toTopOf="@id/tvIgnoredLabel" + app:layout_constraintEnd_toEndOf="@id/tvUserName" + app:layout_constraintStart_toStartOf="@id/tvUserName" + app:layout_constraintTop_toBottomOf="@id/tvUserName" + tools:text="Android01@domain" /> + + <TextView + android:id="@+id/tvIgnoredLabel" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:text="@string/ignored" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="@id/ivUserImage" + app:layout_constraintEnd_toEndOf="@id/tvUserName" + app:layout_constraintStart_toStartOf="@id/tvUserName" + app:layout_constraintTop_toBottomOf="@id/tvUserId" + tools:visibility="visible" /> + + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/list_item_people_ignored.xml b/app/src/main/res/layout/list_item_people_ignored.xml index c137e471133bce62eced4768f5a97856aa3b45fe..52924510a5d04620ee3eda750307a3eaffb13c3c 100644 --- a/app/src/main/res/layout/list_item_people_ignored.xml +++ b/app/src/main/res/layout/list_item_people_ignored.xml @@ -1,19 +1,53 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingVertical="4dp"> - <org.futo.circles.view.PeopleTabUserListItemView - android:id="@+id/userItem" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginEnd="100dp" + <com.google.android.material.imageview.ShapeableImageView + android:id="@+id/ivUserImage" + android:layout_width="72dp" + android:layout_height="72dp" + android:layout_marginStart="8dp" + android:layout_marginTop="4dp" + android:layout_marginBottom="4dp" + android:scaleType="centerCrop" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toTopOf="parent" + app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent" + tools:background="@color/blue" /> + + <TextView + android:id="@+id/tvUserName" + style="@style/title2" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:ellipsize="end" + android:lines="1" + app:layout_constraintBottom_toTopOf="@id/tvUserId" + app:layout_constraintEnd_toStartOf="@id/btnUnIgnore" + app:layout_constraintStart_toEndOf="@id/ivUserImage" + app:layout_constraintTop_toTopOf="@id/ivUserImage" + app:layout_constraintVertical_chainStyle="packed" + tools:text="Android01" /> + + <TextView + android:id="@+id/tvUserId" + style="@style/subheadline" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:ellipsize="end" + android:lines="1" + app:layout_constraintBottom_toBottomOf="@id/ivUserImage" + app:layout_constraintEnd_toEndOf="@id/tvUserName" + app:layout_constraintStart_toStartOf="@id/tvUserName" + app:layout_constraintTop_toBottomOf="@id/tvUserName" + tools:text="Android01@domain" /> + <com.google.android.material.button.MaterialButton android:id="@+id/btnUnIgnore" diff --git a/app/src/main/res/layout/view_people_tab_user_list_item.xml b/app/src/main/res/layout/view_people_tab_user_list_item.xml deleted file mode 100644 index 05961383a06482e87facd8ff54ccacfd6bba315e..0000000000000000000000000000000000000000 --- a/app/src/main/res/layout/view_people_tab_user_list_item.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<merge xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="wrap_content" - tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"> - - <com.google.android.material.imageview.ShapeableImageView - android:id="@+id/ivUserImage" - android:layout_width="72dp" - android:layout_height="0dp" - android:layout_marginStart="8dp" - android:layout_marginTop="4dp" - android:layout_marginBottom="4dp" - android:scaleType="centerCrop" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintDimensionRatio="w,1:1" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" - app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent" - tools:background="@color/blue" /> - - <TextView - android:id="@+id/tvUserName" - style="@style/title2" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:layout_marginEnd="8dp" - android:ellipsize="end" - android:lines="1" - app:layout_constraintBottom_toTopOf="@id/tvUserId" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@id/ivUserImage" - app:layout_constraintTop_toTopOf="@id/ivUserImage" - app:layout_constraintVertical_chainStyle="packed" - tools:text="Android01" /> - - <TextView - android:id="@+id/tvUserId" - style="@style/subheadline" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:ellipsize="end" - android:lines="1" - app:layout_constraintBottom_toBottomOf="@id/ivUserImage" - app:layout_constraintEnd_toEndOf="@id/tvUserName" - app:layout_constraintStart_toStartOf="@id/tvUserName" - app:layout_constraintTop_toBottomOf="@id/tvUserName" - tools:text="Android01@domain" /> - -</merge> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0a7734f17b2c6d6319ce7e16ff7facb878f72f51..11fbb37d1a39926c98db6e9634b05efd0bba2194 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -202,7 +202,9 @@ <string name="media_usage_format">%s of %s used</string> <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="show_connection_invites_format">Show %d connection invites</string> + <string name="my_connections">My Connections</string> + <string name="ignored">Ignored</string> <!-- Rich text editor --> <string name="rich_text_editor_format_bold">Apply bold format</string> diff --git a/auth/src/main/java/org/futo/circles/auth/feature/active_sessions/list/ActiveSessionsAdapter.kt b/auth/src/main/java/org/futo/circles/auth/feature/active_sessions/list/ActiveSessionsAdapter.kt index d88137d2bf5b7fa44e5e8292a5992f5f5adfda67..3f1789e80792ca7b731b8c5b0043820d763f507f 100644 --- a/auth/src/main/java/org/futo/circles/auth/feature/active_sessions/list/ActiveSessionsAdapter.kt +++ b/auth/src/main/java/org/futo/circles/auth/feature/active_sessions/list/ActiveSessionsAdapter.kt @@ -27,7 +27,7 @@ class ActiveSessionsAdapter( } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ActiveSessionsViewHolder { - return when (ActiveSessionViewTypes.values()[viewType]) { + return when (ActiveSessionViewTypes.entries[viewType]) { ActiveSessionViewTypes.Header -> SessionHeaderViewHolder(parent) ActiveSessionViewTypes.Session -> SessionItemViewHolder( parent = parent, diff --git a/auth/src/main/java/org/futo/circles/auth/feature/workspace/list/WorkspaceTasksListAdapter.kt b/auth/src/main/java/org/futo/circles/auth/feature/workspace/list/WorkspaceTasksListAdapter.kt index 1e1a0e7d88d36a5e302d10ffa996e7dc7f2ef3d4..a45dac5068d10234b33bf9eb47535b7ff9bf20b2 100644 --- a/auth/src/main/java/org/futo/circles/auth/feature/workspace/list/WorkspaceTasksListAdapter.kt +++ b/auth/src/main/java/org/futo/circles/auth/feature/workspace/list/WorkspaceTasksListAdapter.kt @@ -20,7 +20,7 @@ class WorkspaceTasksListAdapter( override fun onCreateViewHolder( parent: ViewGroup, viewType: Int - ) = when (WorkspaceTaskViewType.values()[viewType]) { + ) = when (WorkspaceTaskViewType.entries[viewType]) { WorkspaceTaskViewType.Mandatory -> MandatoryWorkspaceTaskViewHolder(parent = parent) WorkspaceTaskViewType.Optional -> OptionalWorkspaceTaskViewHolder( diff --git a/core/src/main/java/org/futo/circles/core/extensions/ImageViewExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/ImageViewExtensions.kt index 66878e20a100fbff8eb885ddcebcde58e6c57b50..983ed2df4bfd2c0f0f0a7acbe668a196930f5bdd 100644 --- a/core/src/main/java/org/futo/circles/core/extensions/ImageViewExtensions.kt +++ b/core/src/main/java/org/futo/circles/core/extensions/ImageViewExtensions.kt @@ -80,13 +80,14 @@ fun ImageView.loadRoomProfileIcon( fun ImageView.loadUserProfileIcon( url: String?, userId: String, - session: Session? = null + session: Session? = null, + applyBlur: Boolean = false ) { post { val svgString = Jdenticon.toSvg(userId, measuredWidth) val svg = SVG.getFromString(svgString) val placeholder = PictureDrawable(svg.renderToPicture()) - loadMatrixImage(url, placeholder = placeholder, session = session) + loadMatrixImage(url, placeholder = placeholder, session = session, applyBlur = applyBlur) } } diff --git a/core/src/main/java/org/futo/circles/core/extensions/MatrixSessionExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/MatrixSessionExtensions.kt index ea448a20ba63f7ece318cdf8f808c5368d7fd424..67e55554721370de0706e6d316380531a4aa8c51 100644 --- a/core/src/main/java/org/futo/circles/core/extensions/MatrixSessionExtensions.kt +++ b/core/src/main/java/org/futo/circles/core/extensions/MatrixSessionExtensions.kt @@ -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) } + } diff --git a/core/src/main/java/org/futo/circles/core/extensions/MatrixUserRoleExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/MatrixUserRoleExtensions.kt index 989cef5076453f17632b79baee273ffb0a0be1e7..ffa74dc8f5be8bbc16c0aadcc4526ee52af3afc7 100644 --- a/core/src/main/java/org/futo/circles/core/extensions/MatrixUserRoleExtensions.kt +++ b/core/src/main/java/org/futo/circles/core/extensions/MatrixUserRoleExtensions.kt @@ -27,8 +27,8 @@ fun PowerLevelsContent.isCurrentUserAbleToPost(): Boolean { fun PowerLevelsContent.isCurrentUserOnlyAdmin(roomId: String): Boolean { val isAdmin = isCurrentUserAdmin() - val roomOwnersCount = getRoomOwners(roomId).size - return isAdmin && roomOwnersCount == 1 + val roomAdminsCount = getRoomAdmins(roomId).size + return isAdmin && roomAdminsCount == 1 } fun PowerLevelsContent.isCurrentUserAdmin(): Boolean { @@ -88,7 +88,7 @@ fun getCurrentUserPowerLevel(roomId: String): Int { return PowerLevelsHelper(powerLevelsContent).getUserPowerLevelValue(session.myUserId) } -fun getRoomOwners(roomId: String): List<RoomMemberSummary> { +fun getRoomAdmins(roomId: String): List<RoomMemberSummary> { val room = MatrixSessionProvider.currentSession?.getRoom(roomId) ?: return emptyList() val powerLevelsContent = getPowerLevelContent(roomId) ?: return emptyList() return room.membershipService().getRoomMembers(roomMemberQueryParams()) @@ -96,4 +96,13 @@ fun getRoomOwners(roomId: String): List<RoomMemberSummary> { powerLevelsContent.getUserPowerLevel(roomMemberSummary.userId) == Role.Admin.value && roomMemberSummary.membership.isActive() } +} + +fun getRoomOwner(roomId: String): RoomMemberSummary? { + val room = MatrixSessionProvider.currentSession?.getRoom(roomId) ?: return null + val creatorUserId = room.getStateEvent( + EventType.STATE_ROOM_CREATE, + QueryStringValue.IsEmpty + )?.senderId ?: return null + return room.membershipService().getRoomMember(creatorUserId) } \ No newline at end of file diff --git a/core/src/main/java/org/futo/circles/core/extensions/TimelineEventExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/TimelineEventExtensions.kt index 2f2de08c3b42bfd2e7b494c1a049dcc0965d0f5a..85b859b6d4ce8bd903668f7bb15b33a24e1dae92 100644 --- a/core/src/main/java/org/futo/circles/core/extensions/TimelineEventExtensions.kt +++ b/core/src/main/java/org/futo/circles/core/extensions/TimelineEventExtensions.kt @@ -12,5 +12,5 @@ fun TimelineEvent.getPostContentType(): PostContentType? { val messageType = if (root.getClearType() == EventType.MESSAGE) root.getClearContent() .toModel<MessageContent>()?.msgType else getLastMessageContent()?.msgType - return PostContentType.values().firstOrNull { it.typeKey == messageType } + return PostContentType.entries.firstOrNull { it.typeKey == messageType } } \ No newline at end of file diff --git a/core/src/main/java/org/futo/circles/core/feature/picker/helper/MediaPickerHelper.kt b/core/src/main/java/org/futo/circles/core/feature/picker/helper/MediaPickerHelper.kt index ed9932c065042c79aac4ddc5bee7b327b3097d62..1a39fb1f1fcafac17b6e4113caf97236cee69321 100644 --- a/core/src/main/java/org/futo/circles/core/feature/picker/helper/MediaPickerHelper.kt +++ b/core/src/main/java/org/futo/circles/core/feature/picker/helper/MediaPickerHelper.kt @@ -118,7 +118,7 @@ open class MediaPickerHelper( Array<PickGalleryMediaResultItem>::class.java ) }?.forEach { - when (MediaType.values()[it.mediaTypeOrdinal]) { + when (MediaType.entries[it.mediaTypeOrdinal]) { MediaType.Image -> onImageSelected?.invoke(itemId, Uri.parse(it.uriString)) MediaType.Video -> onVideoSelected?.invoke(Uri.parse(it.uriString)) } diff --git a/core/src/main/java/org/futo/circles/core/feature/room/RoomRelationsBuilder.kt b/core/src/main/java/org/futo/circles/core/feature/room/RoomRelationsBuilder.kt index 2886424e46d0b579f2d67a9f74940aaa4a1e8a0e..b1352636b32c5e036da86ff5459ba27503b2fabf 100644 --- a/core/src/main/java/org/futo/circles/core/feature/room/RoomRelationsBuilder.kt +++ b/core/src/main/java/org/futo/circles/core/feature/room/RoomRelationsBuilder.kt @@ -1,10 +1,10 @@ package org.futo.circles.core.feature.room -import org.futo.circles.core.extensions.getRoomOwners +import org.futo.circles.core.extensions.getRoomOwner +import org.futo.circles.core.feature.workspace.SpacesTreeAccountDataSource import org.futo.circles.core.model.CirclesRoom import org.futo.circles.core.provider.MatrixSessionProvider import org.futo.circles.core.utils.getJoinedRoomById -import org.futo.circles.core.feature.workspace.SpacesTreeAccountDataSource import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.getRoom import javax.inject.Inject @@ -31,7 +31,7 @@ class RoomRelationsBuilder @Inject constructor( suspend fun removeFromAllParents(childId: String) { session?.getRoom(childId)?.roomSummary()?.spaceParents?.forEach { val parentId = it.roomSummary?.roomId ?: "" - if (getRoomOwners(parentId).firstOrNull { it.userId == session?.myUserId } != null) + if (getRoomOwner(parentId)?.userId == session?.myUserId) removeRelations(childId, parentId) } } diff --git a/core/src/main/java/org/futo/circles/core/feature/room/leave/LeaveRoomDataSource.kt b/core/src/main/java/org/futo/circles/core/feature/room/leave/LeaveRoomDataSource.kt index 38e6810fc7f9a7047794340b7bb87c3d062b0f34..d29323958d4611ee9d3b98e3cedb45f53d6b747a 100644 --- a/core/src/main/java/org/futo/circles/core/feature/room/leave/LeaveRoomDataSource.kt +++ b/core/src/main/java/org/futo/circles/core/feature/room/leave/LeaveRoomDataSource.kt @@ -5,7 +5,7 @@ import dagger.hilt.android.scopes.ViewModelScoped import org.futo.circles.core.extensions.createResult import org.futo.circles.core.extensions.getCurrentUserPowerLevel import org.futo.circles.core.extensions.getOrThrow -import org.futo.circles.core.extensions.getRoomOwners +import org.futo.circles.core.extensions.getRoomAdmins import org.futo.circles.core.feature.room.RoomRelationsBuilder import org.futo.circles.core.provider.MatrixSessionProvider import org.futo.circles.core.utils.getTimelineRoomFor @@ -67,7 +67,7 @@ class LeaveRoomDataSource @Inject constructor( if (isSingleMember) return true val isUserOwner = getCurrentUserPowerLevel(roomId) == Role.Admin.value if (!isUserOwner) return true - val roomHasOneOwner = getRoomOwners(roomId).size == 1 - return !roomHasOneOwner + val roomHasOneAdmin = getRoomAdmins(roomId).size == 1 + return !roomHasOneAdmin } } \ No newline at end of file diff --git a/core/src/main/java/org/futo/circles/core/feature/room/manage_members/change_role/ChangeAccessLevelDataSource.kt b/core/src/main/java/org/futo/circles/core/feature/room/manage_members/change_role/ChangeAccessLevelDataSource.kt index 9c5427d0b746a971a31edabe141ec0961ba139a5..b7d17fbd59ca7f6ece8d5308c00ad135b58688bd 100644 --- a/core/src/main/java/org/futo/circles/core/feature/room/manage_members/change_role/ChangeAccessLevelDataSource.kt +++ b/core/src/main/java/org/futo/circles/core/feature/room/manage_members/change_role/ChangeAccessLevelDataSource.kt @@ -17,7 +17,7 @@ class ChangeAccessLevelDataSource @Inject constructor( private val levelValue: Int = savedStateHandle.getOrThrow("levelValue") private val myUserLevelValue: Int = savedStateHandle.getOrThrow("myUserLevelValue") - fun getRolesList() = AccessLevel.values().map { + fun getRolesList() = AccessLevel.entries.map { AccessLevelListItem( Role.fromValue(it.levelValue, Role.Default.value), it.levelValue == levelValue diff --git a/core/src/main/java/org/futo/circles/core/feature/room/manage_members/list/MembersListAdapter.kt b/core/src/main/java/org/futo/circles/core/feature/room/manage_members/list/MembersListAdapter.kt index d1809d518c77802badb602c5c93f634056dd645d..4241e6132c1f1688e7c17da929d074e2610b68dc 100644 --- a/core/src/main/java/org/futo/circles/core/feature/room/manage_members/list/MembersListAdapter.kt +++ b/core/src/main/java/org/futo/circles/core/feature/room/manage_members/list/MembersListAdapter.kt @@ -27,7 +27,7 @@ class GroupMembersListAdapter( } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ManageMembersViewHolder { - return when (ManageGroupMembersViewTypes.values()[viewType]) { + return when (ManageGroupMembersViewTypes.entries[viewType]) { ManageGroupMembersViewTypes.Header -> ManageMembersHeaderViewHolder(parent) ManageGroupMembersViewTypes.Member -> MemberViewHolder( parent = parent, diff --git a/core/src/main/java/org/futo/circles/core/feature/select_users/list/search/InviteMembersSearchListAdapter.kt b/core/src/main/java/org/futo/circles/core/feature/select_users/list/search/InviteMembersSearchListAdapter.kt index ccdb753136590a5034c49f5d307bc21ab0e69b6a..05a3f325b4c2d0b095b5dbd066bea0682470fc5f 100644 --- a/core/src/main/java/org/futo/circles/core/feature/select_users/list/search/InviteMembersSearchListAdapter.kt +++ b/core/src/main/java/org/futo/circles/core/feature/select_users/list/search/InviteMembersSearchListAdapter.kt @@ -22,7 +22,7 @@ class InviteMembersSearchListAdapter( } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): InviteMemberViewHolder { - return when (InviteListViewType.values()[viewType]) { + return when (InviteListViewType.entries[viewType]) { InviteListViewType.Header -> HeaderViewHolder(parent) InviteListViewType.User -> UserViewHolder( parent, diff --git a/core/src/main/java/org/futo/circles/core/feature/timeline/data_source/BaseTimelineDataSource.kt b/core/src/main/java/org/futo/circles/core/feature/timeline/data_source/BaseTimelineDataSource.kt index f14aa53d230f4343e28ffe3f21790fdb2c592275..e36237e289b89beeebecce8407dcf40dbede905f 100644 --- a/core/src/main/java/org/futo/circles/core/feature/timeline/data_source/BaseTimelineDataSource.kt +++ b/core/src/main/java/org/futo/circles/core/feature/timeline/data_source/BaseTimelineDataSource.kt @@ -58,7 +58,6 @@ abstract class BaseTimelineDataSource( startTimeline(listener) awaitClose() }.flowOn(Dispatchers.IO) - .debounce(150) .mapLatest { val items = timelineBuilder.build(it, isThread) if (it.isNotEmpty() && items.size <= LOAD_MORE_THRESHOLD) loadMore() diff --git a/core/src/main/java/org/futo/circles/core/feature/user/UserDataSource.kt b/core/src/main/java/org/futo/circles/core/feature/user/UserDataSource.kt index f0bebd5b87cdf31e0d2e7a0c107558d3dc3a6560..59c3b835a7d16a785d6eeca075236adce6a4dfd8 100644 --- a/core/src/main/java/org/futo/circles/core/feature/user/UserDataSource.kt +++ b/core/src/main/java/org/futo/circles/core/feature/user/UserDataSource.kt @@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import org.futo.circles.core.extensions.getOrThrow -import org.futo.circles.core.extensions.getRoomOwners +import org.futo.circles.core.extensions.getRoomOwner import org.futo.circles.core.feature.workspace.SharedCircleDataSource import org.futo.circles.core.model.TIMELINE_TYPE import org.futo.circles.core.model.TimelineHeaderItem @@ -90,6 +90,6 @@ class UserDataSource @Inject constructor( private fun isUsersCircleTimeline(summary: RoomSummary) = summary.roomType == TIMELINE_TYPE && summary.membership == Membership.JOIN && - getRoomOwners(summary.roomId).map { it.userId }.contains(userId) + getRoomOwner(summary.roomId)?.userId == userId } \ No newline at end of file diff --git a/core/src/main/java/org/futo/circles/core/feature/user/UserDialogFragment.kt b/core/src/main/java/org/futo/circles/core/feature/user/UserDialogFragment.kt index 2aa6f0500d8fcf675b232ed608ec318fc7f1639e..bfda58da06687ba4fbc69a4872a5889ff489c56a 100644 --- a/core/src/main/java/org/futo/circles/core/feature/user/UserDialogFragment.kt +++ b/core/src/main/java/org/futo/circles/core/feature/user/UserDialogFragment.kt @@ -26,6 +26,7 @@ import org.futo.circles.core.feature.user.list.UsersCirclesAdapter import org.futo.circles.core.model.IgnoreUser import org.futo.circles.core.model.UnfollowTimeline import org.futo.circles.core.model.UnfollowUser +import org.futo.circles.core.provider.MatrixSessionProvider import org.futo.circles.core.view.EmptyTabPlaceholderView import org.matrix.android.sdk.api.session.user.model.User @@ -131,7 +132,7 @@ class UserDialogFragment : BaseFullscreenDialogFragment(DialogFragmentUserBindin }) viewModel.isUserIgnoredLiveData?.observeData(this) { isUserIgnored = it - binding.toolbar.invalidateMenu() + setupMenu() } viewModel.unFollowUserLiveData.observeResponse(this, success = { onBackPressed() }) diff --git a/core/src/main/java/org/futo/circles/core/feature/user/list/UsersCirclesAdapter.kt b/core/src/main/java/org/futo/circles/core/feature/user/list/UsersCirclesAdapter.kt index b3e289626e8d78382923c91391bcc3997c007b07..408e0010eed654e8f115650bba5478d2460d6991 100644 --- a/core/src/main/java/org/futo/circles/core/feature/user/list/UsersCirclesAdapter.kt +++ b/core/src/main/java/org/futo/circles/core/feature/user/list/UsersCirclesAdapter.kt @@ -23,7 +23,7 @@ class UsersCirclesAdapter( override fun onCreateViewHolder( parent: ViewGroup, viewType: Int - ): UserTimelineViewHolder = when (values()[viewType]) { + ): UserTimelineViewHolder = when (TimelineViewType.entries[viewType]) { Header -> UserTimelineHeaderViewHolder(parent) Room -> UsersTimelineRoomViewHolder( parent, diff --git a/core/src/main/java/org/futo/circles/core/feature/workspace/SharedCircleDataSource.kt b/core/src/main/java/org/futo/circles/core/feature/workspace/SharedCircleDataSource.kt index 2b870de14efbf31213aaa84468a9d494ff42986c..900d9666415c83b3ce7f184f6104cc320c480712 100644 --- a/core/src/main/java/org/futo/circles/core/feature/workspace/SharedCircleDataSource.kt +++ b/core/src/main/java/org/futo/circles/core/feature/workspace/SharedCircleDataSource.kt @@ -1,17 +1,6 @@ package org.futo.circles.core.feature.workspace -import android.os.Build -import androidx.lifecycle.asFlow -import androidx.lifecycle.map -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.withContext -import org.futo.circles.core.extensions.getRoomOwners +import org.futo.circles.core.extensions.getRoomOwner import org.futo.circles.core.feature.room.RoomRelationsBuilder import org.futo.circles.core.model.PROFILE_SPACE_ACCOUNT_DATA_KEY import org.futo.circles.core.provider.MatrixSessionProvider @@ -19,10 +8,7 @@ import org.futo.circles.core.utils.getJoinedRoomById import org.futo.circles.core.utils.getTimelineRoomFor import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.getRoomSummary -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 javax.inject.Inject class SharedCircleDataSource @Inject constructor( @@ -44,24 +30,6 @@ class SharedCircleDataSource @Inject constructor( MatrixSessionProvider.getSessionOrThrow().roomService().leaveRoom(userSharedCircleId) } - fun observeAndAutoAcceptSharedSpaceInvites(coroutineScope: CoroutineScope): Job { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) return Job() - val session = MatrixSessionProvider.currentSession ?: return Job() - return session.roomService().getRoomSummariesLive( - roomSummaryQueryParams { - excludeType = null - memberships = listOf(Membership.INVITE) - }).map { it.filter { it.roomType == RoomType.SPACE }.map { it.roomId } } - .asFlow().onEach { roomsIds -> - withContext(Dispatchers.IO) { - roomsIds.forEach { acceptSharedCircleInvite(session, it) } - } - } - .flowOn(Dispatchers.Default) - .catch { } - .launchIn(coroutineScope) - } - suspend fun addToSharedCircles(timelineId: String) { getSharedCirclesSpaceId()?.let { roomRelationsBuilder.setRelations(timelineId, it) } } @@ -74,7 +42,7 @@ class SharedCircleDataSource @Inject constructor( val sharedCirclesSpaceId = getSharedCirclesSpaceId() ?: return null val userSharedCircleId = getJoinedRoomById(sharedCirclesSpaceId)?.roomSummary()?.spaceChildren?.firstOrNull { child -> - getRoomOwners(child.childRoomId).map { it.userId }.contains(userId) + getRoomOwner(child.childRoomId)?.userId == userId }?.childRoomId ?: return null return getJoinedRoomById(userSharedCircleId)?.roomSummary() } diff --git a/core/src/main/java/org/futo/circles/core/model/FollowingListItem.kt b/core/src/main/java/org/futo/circles/core/model/FollowingListItem.kt index 6166ab0ddc5c6616e4dc424c21708ee16433f5bd..a91f05c4c31d4ac39d4fb32fbfee444f2901f560 100644 --- a/core/src/main/java/org/futo/circles/core/model/FollowingListItem.kt +++ b/core/src/main/java/org/futo/circles/core/model/FollowingListItem.kt @@ -1,7 +1,7 @@ package org.futo.circles.core.model -import org.futo.circles.core.extensions.getRoomOwners import org.futo.circles.core.base.list.IdEntity +import org.futo.circles.core.extensions.getRoomOwner import org.futo.circles.core.mapping.nameOrId import org.futo.circles.core.utils.getTimelineRoomFor import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -20,7 +20,7 @@ fun RoomSummary.toFollowingListItem(circleId: String, followInCirclesCount: Int) FollowingListItem( id = roomId, name = nameOrId(), - ownerName = getRoomOwners(roomId).firstOrNull()?.displayName ?: "", + ownerName = getRoomOwner(roomId)?.displayName ?: "", avatarUrl = avatarUrl, updatedTime = latestPreviewableEvent?.root?.originServerTs ?: System.currentTimeMillis(), isMyTimeline = getTimelineRoomFor(circleId)?.roomId == roomId, diff --git a/core/src/main/java/org/futo/circles/core/model/ShareUrlTypeArg.kt b/core/src/main/java/org/futo/circles/core/model/ShareUrlTypeArg.kt index 9cc340fd5895270782cc8da35148a9c545aa9438..688e37ad5cc17aebd1b1b7ac4dd5425d9e42ecf1 100644 --- a/core/src/main/java/org/futo/circles/core/model/ShareUrlTypeArg.kt +++ b/core/src/main/java/org/futo/circles/core/model/ShareUrlTypeArg.kt @@ -10,6 +10,6 @@ enum class ShareUrlTypeArg(val typeKey: String) { fun shareUrlTypeArgFromType(type: String): ShareUrlTypeArg? { val urlType: ShareUrlTypeArg? = null - ShareUrlTypeArg.values().forEach { if (type == it.typeKey) return it } + ShareUrlTypeArg.entries.forEach { if (type == it.typeKey) return it } return urlType } \ No newline at end of file diff --git a/core/src/main/java/org/futo/circles/core/utils/RoomUtils.kt b/core/src/main/java/org/futo/circles/core/utils/RoomUtils.kt index ca975587a66db13ae8dd52a567b3824c656df24c..577707b8a37e52efd1dda0a2c7f988abce4a9f3a 100644 --- a/core/src/main/java/org/futo/circles/core/utils/RoomUtils.kt +++ b/core/src/main/java/org/futo/circles/core/utils/RoomUtils.kt @@ -1,5 +1,6 @@ package org.futo.circles.core.utils +import org.futo.circles.core.extensions.getRoomOwner import org.futo.circles.core.model.TIMELINE_TYPE import org.futo.circles.core.provider.MatrixSessionProvider import org.matrix.android.sdk.api.session.getRoom @@ -10,7 +11,9 @@ fun Room.getTimelineRoom(): Room? { val session = MatrixSessionProvider.currentSession ?: return null val childId = roomSummary()?.spaceChildren?.firstOrNull { val room = session.getRoom(it.childRoomId)?.roomSummary() - room?.inviterId == null && room?.roomType == TIMELINE_TYPE + room?.inviterId == null + && room?.roomType == TIMELINE_TYPE + && getRoomOwner(room.roomId)?.userId == MatrixSessionProvider.currentSession?.myUserId }?.childRoomId return childId?.let { session.getRoom(it) } } diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/PhotosListAdapter.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/PhotosListAdapter.kt index c4af0b5687f1dc23f6ca90aaba7815302fba3831..6350af574a2762c8643250bc18409d9309f7d916 100644 --- a/gallery/src/main/java/org/futo/circles/gallery/feature/PhotosListAdapter.kt +++ b/gallery/src/main/java/org/futo/circles/gallery/feature/PhotosListAdapter.kt @@ -24,7 +24,7 @@ class PhotosListAdapter( override fun onCreateViewHolder( parent: ViewGroup, viewType: Int - ) = when (GalleryListItemViewType.values()[viewType]) { + ) = when (GalleryListItemViewType.entries[viewType]) { GalleryListItemViewType.JoinedGallery -> JoinedGalleryViewHolder( parent = parent, onGalleryClicked = { position -> onRoomClicked(getItem(position)) }