From 63a7fa0487f746c1e3a642f9e1f13c9cb03b52db Mon Sep 17 00:00:00 2001
From: Taras Smakula <tarassmakula@gmail.com>
Date: Wed, 12 Jun 2024 18:08:26 +0300
Subject: [PATCH] Show only not following circles in invite to follow me

---
 app/proguard-rules.pro                        |  1 +
 .../AcceptCircleInviteDialogFragment.kt       |  8 ++--
 .../share/circle/ShareWithCircleActivity.kt   |  6 +--
 .../share/group/ShareWithGroupActivity.kt     |  7 ++--
 .../InviteToFollowMeDialogFragment.kt         |  6 ++-
 .../room/select/SelectRoomsDataSource.kt      | 42 +++++++++++++------
 .../room/select/SelectRoomsFragment.kt        | 17 +++++---
 .../core/mapping/RoomSummaryMapping.kt        |  6 ++-
 .../circles/core/model/SelectRoomTypeArg.kt   | 11 +++++
 .../select/SelectGalleriesDataSource.kt       |  4 +-
 10 files changed, 74 insertions(+), 34 deletions(-)
 create mode 100644 core/src/main/java/org/futo/circles/core/model/SelectRoomTypeArg.kt

diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index c769b85c4..cf60c06c0 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -73,6 +73,7 @@ native <methods>;
 -keep class org.futo.circles.core.model.ShareUrlTypeArg
 -keep class org.futo.circles.model.PeopleCategoryTypeArg
 -keep class org.futo.circles.auth.model.ServerDomainArg
+-keep class org.futo.circles.core.model.SelectRoomTypeArg
 
 -keepattributes SourceFile,LineNumberTable        # Keep file names and line numbers.
 -keep public class * extends java.lang.Exception  # Optional: Keep custom exceptions.
diff --git a/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDialogFragment.kt b/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDialogFragment.kt
index 50f6bef12..f6fdb43f3 100644
--- a/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDialogFragment.kt
+++ b/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDialogFragment.kt
@@ -7,18 +7,18 @@ import androidx.fragment.app.viewModels
 import androidx.navigation.fragment.findNavController
 import dagger.hilt.android.AndroidEntryPoint
 import org.futo.circles.R
-import org.futo.circles.core.feature.room.select.interfaces.RoomsListener
 import org.futo.circles.core.base.fragment.BaseFullscreenDialogFragment
 import org.futo.circles.core.base.fragment.HasLoadingState
 import org.futo.circles.core.extensions.navigateSafe
 import org.futo.circles.core.extensions.observeResponse
 import org.futo.circles.core.extensions.onBackPressed
 import org.futo.circles.core.extensions.setIsVisible
+import org.futo.circles.core.feature.room.select.SelectRoomsFragment
+import org.futo.circles.core.feature.room.select.interfaces.RoomsListener
 import org.futo.circles.core.feature.room.select.interfaces.SelectRoomsListener
-import org.futo.circles.core.model.CircleRoomTypeArg
+import org.futo.circles.core.model.SelectRoomTypeArg
 import org.futo.circles.core.model.SelectableRoomListItem
 import org.futo.circles.databinding.DialogFragmentAcceptCircleInviteBinding
-import org.futo.circles.core.feature.room.select.SelectRoomsFragment
 
 @AndroidEntryPoint
 class AcceptCircleInviteDialogFragment :
@@ -29,7 +29,7 @@ class AcceptCircleInviteDialogFragment :
     override val fragment: Fragment = this
     private val viewModel by viewModels<AcceptCircleInviteViewModel>()
 
-    private val selectRoomsFragment by lazy { SelectRoomsFragment.create(CircleRoomTypeArg.Circle) }
+    private val selectRoomsFragment by lazy { SelectRoomsFragment.create(SelectRoomTypeArg.CirclesJoined) }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
diff --git a/app/src/main/java/org/futo/circles/feature/share/circle/ShareWithCircleActivity.kt b/app/src/main/java/org/futo/circles/feature/share/circle/ShareWithCircleActivity.kt
index 84e562f15..57d16e470 100644
--- a/app/src/main/java/org/futo/circles/feature/share/circle/ShareWithCircleActivity.kt
+++ b/app/src/main/java/org/futo/circles/feature/share/circle/ShareWithCircleActivity.kt
@@ -2,11 +2,11 @@ package org.futo.circles.feature.share.circle
 
 import dagger.hilt.android.AndroidEntryPoint
 import org.futo.circles.R
+import org.futo.circles.core.feature.room.select.SelectRoomsFragment
 import org.futo.circles.core.feature.room.select.interfaces.RoomsPicker
 import org.futo.circles.core.feature.share.BaseShareActivity
-import org.futo.circles.core.model.CircleRoomTypeArg
+import org.futo.circles.core.model.SelectRoomTypeArg
 import org.futo.circles.core.utils.getTimelineRoomFor
-import org.futo.circles.core.feature.room.select.SelectRoomsFragment
 
 @AndroidEntryPoint
 class ShareWithCircleActivity : BaseShareActivity() {
@@ -14,7 +14,7 @@ class ShareWithCircleActivity : BaseShareActivity() {
     override val titleResId: Int = R.string.share_with_circle
 
     override val roomsPicker: RoomsPicker =
-        SelectRoomsFragment.create(CircleRoomTypeArg.Circle)
+        SelectRoomsFragment.create(SelectRoomTypeArg.CirclesJoined)
 
     override fun getShareRoomsIds(): List<String> =
         roomsPicker.getSelectedRooms().mapNotNull { getTimelineRoomFor(it.id)?.roomId }
diff --git a/app/src/main/java/org/futo/circles/feature/share/group/ShareWithGroupActivity.kt b/app/src/main/java/org/futo/circles/feature/share/group/ShareWithGroupActivity.kt
index 41fee17a7..2e386653f 100644
--- a/app/src/main/java/org/futo/circles/feature/share/group/ShareWithGroupActivity.kt
+++ b/app/src/main/java/org/futo/circles/feature/share/group/ShareWithGroupActivity.kt
@@ -2,17 +2,18 @@ package org.futo.circles.feature.share.group
 
 import dagger.hilt.android.AndroidEntryPoint
 import org.futo.circles.R
+import org.futo.circles.core.feature.room.select.SelectRoomsFragment
 import org.futo.circles.core.feature.room.select.interfaces.RoomsPicker
 import org.futo.circles.core.feature.share.BaseShareActivity
-import org.futo.circles.core.model.CircleRoomTypeArg
-import org.futo.circles.core.feature.room.select.SelectRoomsFragment
+import org.futo.circles.core.model.SelectRoomTypeArg
 
 @AndroidEntryPoint
 class ShareWithGroupActivity : BaseShareActivity() {
 
     override val titleResId: Int = R.string.share_with_group
 
-    override val roomsPicker: RoomsPicker = SelectRoomsFragment.create(CircleRoomTypeArg.Group)
+    override val roomsPicker: RoomsPicker =
+        SelectRoomsFragment.create(SelectRoomTypeArg.GroupsJoined)
 
     override fun getShareRoomsIds(): List<String> = roomsPicker.getSelectedRooms().map { it.id }
 
diff --git a/core/src/main/java/org/futo/circles/core/feature/invite_to_follow/InviteToFollowMeDialogFragment.kt b/core/src/main/java/org/futo/circles/core/feature/invite_to_follow/InviteToFollowMeDialogFragment.kt
index e35f2c3b8..9d016a4d3 100644
--- a/core/src/main/java/org/futo/circles/core/feature/invite_to_follow/InviteToFollowMeDialogFragment.kt
+++ b/core/src/main/java/org/futo/circles/core/feature/invite_to_follow/InviteToFollowMeDialogFragment.kt
@@ -20,7 +20,7 @@ import org.futo.circles.core.extensions.showSuccess
 import org.futo.circles.core.feature.room.select.SelectRoomsFragment
 import org.futo.circles.core.feature.room.select.interfaces.RoomsListener
 import org.futo.circles.core.feature.room.select.interfaces.SelectRoomsListener
-import org.futo.circles.core.model.CircleRoomTypeArg
+import org.futo.circles.core.model.SelectRoomTypeArg
 import org.futo.circles.core.model.SelectableRoomListItem
 
 @AndroidEntryPoint
@@ -33,7 +33,9 @@ class InviteToFollowMeDialogFragment :
     private val args: InviteToFollowMeDialogFragmentArgs by navArgs()
     private val viewModel by viewModels<InviteToFollowMeViewModel>()
 
-    private val selectRoomsFragment by lazy { SelectRoomsFragment.create(CircleRoomTypeArg.Circle) }
+    private val selectRoomsFragment by lazy {
+        SelectRoomsFragment.create(SelectRoomTypeArg.MyCircleNotJoinedByUser, args.userId)
+    }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
diff --git a/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsDataSource.kt b/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsDataSource.kt
index ad184af93..6461cede0 100644
--- a/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsDataSource.kt
+++ b/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsDataSource.kt
@@ -13,11 +13,12 @@ import kotlinx.coroutines.flow.flowOn
 import org.futo.circles.core.extensions.getOrThrow
 import org.futo.circles.core.feature.workspace.SpacesTreeAccountDataSource
 import org.futo.circles.core.mapping.toSelectableRoomListItem
-import org.futo.circles.core.model.CircleRoomTypeArg
+import org.futo.circles.core.model.SelectRoomTypeArg
 import org.futo.circles.core.model.SelectableRoomListItem
 import org.futo.circles.core.utils.getGalleriesLiveData
 import org.futo.circles.core.utils.getGroupsLiveData
 import org.futo.circles.core.utils.getSpacesLiveData
+import org.futo.circles.core.utils.getTimelineRoomFor
 import org.matrix.android.sdk.api.session.room.model.Membership
 import org.matrix.android.sdk.api.session.room.model.RoomSummary
 import javax.inject.Inject
@@ -29,9 +30,11 @@ class SelectRoomsDataSource @Inject constructor(
 ) {
 
     private val ordinal = savedStateHandle.getOrThrow<Int>(SelectRoomsFragment.TYPE_ORDINAL)
-    private val roomType: CircleRoomTypeArg =
-        CircleRoomTypeArg.entries.firstOrNull { it.ordinal == ordinal }
-            ?: CircleRoomTypeArg.Circle
+    private val roomType: SelectRoomTypeArg =
+        SelectRoomTypeArg.entries.firstOrNull { it.ordinal == ordinal }
+            ?: SelectRoomTypeArg.CirclesJoined
+
+    private val filterUserId: String? = savedStateHandle[SelectRoomsFragment.USER_ID]
 
     private val selectedRoomsFlow = MutableStateFlow<List<SelectableRoomListItem>>(emptyList())
     val roomsFlow = getMergedRoomsListFlow()
@@ -47,16 +50,17 @@ class SelectRoomsDataSource @Inject constructor(
         }.flowOn(Dispatchers.IO).distinctUntilChanged()
 
     private fun getRoomsFlowWithType(): Flow<List<RoomSummary>> = when (roomType) {
-        CircleRoomTypeArg.Circle -> getSpacesLiveData(listOf(Membership.JOIN)).map { summaries ->
-            val joinedCirclesIds = spacesTreeAccountDataSource.getJoinedCirclesIds()
-            summaries.mapNotNull { summary ->
-                if (joinedCirclesIds.contains(summary.roomId)) summary
-                else null
-            }
+        SelectRoomTypeArg.CirclesJoined -> getSpacesLiveData(listOf(Membership.JOIN)).map { summaries ->
+            filterAllMyCirclesRoomSummaries(summaries)
         }.asFlow()
 
-        CircleRoomTypeArg.Group -> getGroupsLiveData(listOf(Membership.JOIN)).asFlow()
-        CircleRoomTypeArg.Photo -> getGalleriesLiveData(listOf(Membership.JOIN)).asFlow()
+        SelectRoomTypeArg.MyCircleNotJoinedByUser -> getSpacesLiveData(listOf(Membership.JOIN)).map { summaries ->
+            filterAllMyCirclesRoomSummaries(summaries).filter { !isUserJoinedToCircle(it) }
+        }.asFlow()
+
+        SelectRoomTypeArg.GroupsJoined -> getGroupsLiveData(listOf(Membership.JOIN)).asFlow()
+
+        SelectRoomTypeArg.PhotosJoined -> getGalleriesLiveData(listOf(Membership.JOIN)).asFlow()
     }
 
     fun getSelectedRooms() = selectedRoomsFlow.value.filter { it.isSelected }
@@ -68,6 +72,20 @@ class SelectRoomsDataSource @Inject constructor(
         selectedRoomsFlow.value = list
     }
 
+    private fun filterAllMyCirclesRoomSummaries(allJoinedSpacesSummaries: List<RoomSummary>): List<RoomSummary> {
+        val joinedCirclesIds = spacesTreeAccountDataSource.getJoinedCirclesIds()
+        return allJoinedSpacesSummaries.mapNotNull { summary ->
+            if (joinedCirclesIds.contains(summary.roomId)) summary
+            else null
+        }
+    }
+
+    private fun isUserJoinedToCircle(circleSpaceSummary: RoomSummary): Boolean {
+        val timeline = getTimelineRoomFor(circleSpaceSummary.roomId)
+        val member = timeline?.membershipService()?.getRoomMember(filterUserId ?: "")
+        return member?.membership == Membership.JOIN
+    }
+
     private fun List<SelectableRoomListItem>.containsWithId(id: String) =
         firstOrNull { it.id == id } != null
 }
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsFragment.kt b/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsFragment.kt
index b111ed43a..192ec0202 100644
--- a/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsFragment.kt
+++ b/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsFragment.kt
@@ -11,12 +11,12 @@ import org.futo.circles.core.base.fragment.BaseBindingFragment
 import org.futo.circles.core.databinding.FragmentSelectRoomsBinding
 import org.futo.circles.core.extensions.observeData
 import org.futo.circles.core.extensions.setIsVisible
-import org.futo.circles.core.model.CircleRoomTypeArg
-import org.futo.circles.core.feature.room.select.list.SelectRoomsAdapter
-import org.futo.circles.core.feature.room.select.list.SelectedChipsRoomsAdapter
 import org.futo.circles.core.feature.room.select.interfaces.RoomsListener
 import org.futo.circles.core.feature.room.select.interfaces.RoomsPicker
 import org.futo.circles.core.feature.room.select.interfaces.SelectRoomsListener
+import org.futo.circles.core.feature.room.select.list.SelectRoomsAdapter
+import org.futo.circles.core.feature.room.select.list.SelectedChipsRoomsAdapter
+import org.futo.circles.core.model.SelectRoomTypeArg
 
 @AndroidEntryPoint
 class SelectRoomsFragment :
@@ -70,8 +70,13 @@ class SelectRoomsFragment :
 
     companion object {
         const val TYPE_ORDINAL = "type_ordinal"
-        fun create(roomType: CircleRoomTypeArg) = SelectRoomsFragment().apply {
-            arguments = bundleOf(TYPE_ORDINAL to roomType.ordinal)
-        }
+        const val USER_ID = "userId"
+        fun create(roomType: SelectRoomTypeArg, userId: String? = null) =
+            SelectRoomsFragment().apply {
+                arguments = bundleOf(
+                    TYPE_ORDINAL to roomType.ordinal,
+                    USER_ID to userId
+                )
+            }
     }
 }
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt b/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt
index 76772f3e0..166497ae6 100644
--- a/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt
+++ b/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt
@@ -6,7 +6,9 @@ import org.futo.circles.core.extensions.notEmptyDisplayName
 import org.futo.circles.core.model.CircleRoomTypeArg
 import org.futo.circles.core.model.JoinedGalleryListItem
 import org.futo.circles.core.model.RoomInfo
+import org.futo.circles.core.model.SelectRoomTypeArg
 import org.futo.circles.core.model.SelectableRoomListItem
+import org.futo.circles.core.model.isCircle
 import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
 import org.matrix.android.sdk.api.session.room.model.RoomSummary
 import org.matrix.android.sdk.api.session.user.model.User
@@ -15,13 +17,13 @@ fun RoomSummary.nameOrId() =
     displayName.takeIf { it.isNotEmpty() } ?: name.takeIf { it.isNotEmpty() } ?: roomId
 
 fun RoomSummary.toSelectableRoomListItem(
-    roomTypeArg: CircleRoomTypeArg,
+    roomTypeArg: SelectRoomTypeArg,
     selected: Boolean = false
 ) = SelectableRoomListItem(
     id = roomId,
     info = RoomInfo(
         nameOrId(),
-        if (roomTypeArg == CircleRoomTypeArg.Circle) getCircleAvatarUrl() else avatarUrl
+        if (roomTypeArg.isCircle()) getCircleAvatarUrl() else avatarUrl
     ),
     isSelected = selected
 )
diff --git a/core/src/main/java/org/futo/circles/core/model/SelectRoomTypeArg.kt b/core/src/main/java/org/futo/circles/core/model/SelectRoomTypeArg.kt
new file mode 100644
index 000000000..d936a220f
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/model/SelectRoomTypeArg.kt
@@ -0,0 +1,11 @@
+package org.futo.circles.core.model
+
+enum class SelectRoomTypeArg {
+    CirclesJoined,
+    GroupsJoined,
+    PhotosJoined,
+    MyCircleNotJoinedByUser
+}
+
+fun SelectRoomTypeArg.isCircle() =
+    this == SelectRoomTypeArg.CirclesJoined || this == SelectRoomTypeArg.MyCircleNotJoinedByUser
\ No newline at end of file
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesDataSource.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesDataSource.kt
index e12de59d4..2091288ae 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesDataSource.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesDataSource.kt
@@ -2,7 +2,7 @@ package org.futo.circles.gallery.feature.select
 
 import androidx.lifecycle.MutableLiveData
 import org.futo.circles.core.mapping.toSelectableRoomListItem
-import org.futo.circles.core.model.CircleRoomTypeArg
+import org.futo.circles.core.model.SelectRoomTypeArg
 import org.futo.circles.core.model.SelectableRoomListItem
 import org.futo.circles.core.utils.getGalleries
 import org.matrix.android.sdk.api.session.room.model.Membership
@@ -14,7 +14,7 @@ class SelectGalleriesDataSource @Inject constructor() {
 
     private fun getInitialGalleriesList(): List<SelectableRoomListItem> =
         getGalleries(membershipFilter = listOf(Membership.JOIN)).map {
-            it.toSelectableRoomListItem(CircleRoomTypeArg.Photo)
+            it.toSelectableRoomListItem(SelectRoomTypeArg.PhotosJoined)
         }
 
     fun toggleGallerySelect(gallery: SelectableRoomListItem) {
-- 
GitLab