From 601179016c5141e83a8b7c8b6807eef848ac2e52 Mon Sep 17 00:00:00 2001
From: Taras Smakula <tarassmakula@gmail.com>
Date: Fri, 29 Sep 2023 15:41:10 +0300
Subject: [PATCH] Implement people space relations

---
 .../core/workspace/SharedCircleDataSource.kt  | 61 +++++++++++++++++--
 1 file changed, 56 insertions(+), 5 deletions(-)

diff --git a/core/src/main/java/org/futo/circles/core/workspace/SharedCircleDataSource.kt b/core/src/main/java/org/futo/circles/core/workspace/SharedCircleDataSource.kt
index e7253a585..0ed778a34 100644
--- a/core/src/main/java/org/futo/circles/core/workspace/SharedCircleDataSource.kt
+++ b/core/src/main/java/org/futo/circles/core/workspace/SharedCircleDataSource.kt
@@ -1,12 +1,26 @@
 package org.futo.circles.core.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.model.PROFILE_SPACE_ACCOUNT_DATA_KEY
 import org.futo.circles.core.provider.MatrixSessionProvider
 import org.futo.circles.core.room.RoomRelationsBuilder
+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
@@ -19,6 +33,34 @@ class SharedCircleDataSource @Inject constructor(
     fun getSharedCirclesSpaceId() =
         spacesTreeAccountDataSource.getRoomIdByKey(PROFILE_SPACE_ACCOUNT_DATA_KEY)
 
+    suspend fun unfollowUsersSharedCircle(userId: String) {
+        val userSharedCircleId =
+            getSharedCircleFor(userId)?.roomId ?: throw IllegalArgumentException("User's profile not found")
+        val mySharedCircleId = getSharedCirclesSpaceId()
+            ?: throw IllegalArgumentException("Workspace configuration failure")
+
+        roomRelationsBuilder.removeRelations(userSharedCircleId, mySharedCircleId)
+        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) }
     }
@@ -27,11 +69,14 @@ class SharedCircleDataSource @Inject constructor(
         getSharedCirclesSpaceId()?.let { roomRelationsBuilder.removeRelations(timelineId, it) }
     }
 
-    fun getSharedCircleFor(userId: String) = MatrixSessionProvider.currentSession?.roomService()
-        ?.getRoomSummaries(roomSummaryQueryParams { excludeType = null })?.firstOrNull { summary ->
-            summary.roomType == RoomType.SPACE && summary.membership == Membership.JOIN &&
-                    getRoomOwners(summary.roomId).map { it.userId }.contains(userId)
-        }
+    fun getSharedCircleFor(userId: String): RoomSummary? {
+        val sharedCirclesSpaceId = getSharedCirclesSpaceId() ?: return null
+        val userSharedCircleId =
+            getJoinedRoomById(sharedCirclesSpaceId)?.roomSummary()?.spaceChildren?.firstOrNull { child ->
+                getRoomOwners(child.childRoomId).map { it.userId }.contains(userId)
+            }?.childRoomId ?: return null
+        return getJoinedRoomById(userSharedCircleId)?.roomSummary()
+    }
 
     fun getSharedCirclesTimelinesIds() = getSharedCirclesSpaceId()?.let {
         MatrixSessionProvider.currentSession?.getRoomSummary(it)?.spaceChildren?.map { it.childRoomId }
@@ -41,4 +86,10 @@ class SharedCircleDataSource @Inject constructor(
         val timelineId = getTimelineRoomFor(circleId)?.roomId
         return sharedCirclesTimelineIds.contains(timelineId)
     }
+
+    private suspend fun acceptSharedCircleInvite(session: Session, roomId: String) {
+        session.roomService().joinRoom(roomId)
+        val sharedCirclesSpaceId = getSharedCirclesSpaceId() ?: return
+        roomRelationsBuilder.setRelations(roomId, sharedCirclesSpaceId)
+    }
 }
\ No newline at end of file
-- 
GitLab