From 5a60708263550ffb62510725c8de194a0d3715cf Mon Sep 17 00:00:00 2001
From: Taras Smakula <tarassmakula@gmail.com>
Date: Fri, 15 Mar 2024 15:47:07 +0200
Subject: [PATCH] Create CircleFilterAccountDataManager

---
 .../feature/timeline/TimelineViewModel.kt     | 14 ++---
 .../filter/CircleFilterAccountDataManager.kt  | 53 +++++++++++++++++++
 .../gallery/media/PickMediaItemViewModel.kt   | 13 ++---
 .../feature/gallery/grid/GalleryViewModel.kt  |  9 ++--
 4 files changed, 72 insertions(+), 17 deletions(-)
 create mode 100644 core/src/main/java/org/futo/circles/core/feature/circles/filter/CircleFilterAccountDataManager.kt

diff --git a/app/src/main/java/org/futo/circles/feature/timeline/TimelineViewModel.kt b/app/src/main/java/org/futo/circles/feature/timeline/TimelineViewModel.kt
index 9f75a896c..d28a35a7e 100644
--- a/app/src/main/java/org/futo/circles/feature/timeline/TimelineViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/timeline/TimelineViewModel.kt
@@ -7,8 +7,8 @@ import kotlinx.coroutines.async
 import kotlinx.coroutines.awaitAll
 import org.futo.circles.core.base.SingleEventLiveData
 import org.futo.circles.core.extensions.Response
-import org.futo.circles.core.extensions.getOrThrow
 import org.futo.circles.core.extensions.launchBg
+import org.futo.circles.core.feature.circles.filter.CircleFilterAccountDataManager
 import org.futo.circles.core.feature.room.RoomNotificationsDataSource
 import org.futo.circles.core.feature.room.knoks.KnockRequestsDataSource
 import org.futo.circles.core.feature.timeline.BaseTimelineViewModel
@@ -39,11 +39,13 @@ class TimelineViewModel @Inject constructor(
     private val sendMessageDataSource: SendMessageDataSource,
     private val postOptionsDataSource: PostOptionsDataSource,
     private val userOptionsDataSource: UserOptionsDataSource,
-    private val readMessageDataSource: ReadMessageDataSource
-) : BaseTimelineViewModel(timelineDataSourceFactory.create(savedStateHandle.get<String>("timelineId") != null)) {
-
-    private val roomId: String = savedStateHandle.getOrThrow("roomId")
-    private val timelineId: String? = savedStateHandle["timelineId"]
+    private val readMessageDataSource: ReadMessageDataSource,
+    circleFilterAccountDataManager: CircleFilterAccountDataManager
+) : BaseTimelineViewModel(
+    savedStateHandle,
+    timelineDataSourceFactory.create(savedStateHandle.get<String>("timelineId") != null),
+    circleFilterAccountDataManager
+) {
 
     val session = MatrixSessionProvider.currentSession
     val profileLiveData = session?.userService()?.getUserLive(session.myUserId)
diff --git a/core/src/main/java/org/futo/circles/core/feature/circles/filter/CircleFilterAccountDataManager.kt b/core/src/main/java/org/futo/circles/core/feature/circles/filter/CircleFilterAccountDataManager.kt
new file mode 100644
index 000000000..4b72cd996
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/feature/circles/filter/CircleFilterAccountDataManager.kt
@@ -0,0 +1,53 @@
+package org.futo.circles.core.feature.circles.filter
+
+import org.futo.circles.core.extensions.createResult
+import org.futo.circles.core.provider.MatrixSessionProvider
+import org.matrix.android.sdk.api.session.getRoom
+import org.matrix.android.sdk.api.util.JsonDict
+import javax.inject.Inject
+
+class CircleFilterAccountDataManager @Inject constructor() {
+
+    private val session = MatrixSessionProvider.getSessionOrThrow()
+
+    fun getCircleFilterLive(circleId: String) = session.getRoom(circleId)?.roomAccountDataService()
+        ?.getLiveAccountDataEvent(CIRCLE_FILTER_EVENT_TYPE)
+
+    fun getCircleFilter(circleId: String): Set<String> {
+        val content = session.getRoom(circleId)?.roomAccountDataService()
+            ?.getAccountDataEvent(CIRCLE_FILTER_EVENT_TYPE)?.content ?: return getAllTimelinesIds(
+            circleId
+        )
+        return getEventContentAsSet(content, circleId)
+    }
+
+    fun getEventContentAsSet(content: JsonDict?, circleId: String): Set<String> {
+        content ?: return getAllTimelinesIds(circleId)
+        return (content[TIMELINES_KEY] as? List<*>)?.map { it.toString() }?.toSet()
+            ?: getAllTimelinesIds(circleId)
+    }
+
+    fun getAllTimelinesIds(circleId: String): Set<String> {
+        val children = session.getRoom(circleId)?.roomSummary()?.spaceChildren ?: emptyList()
+        return children.mapNotNull {
+            val timelineSummary =
+                session.getRoom(it.childRoomId)?.roomSummary()?.takeIf { summary ->
+                    summary.membership.isActive()
+                }
+            timelineSummary?.roomId
+        }.toSet()
+    }
+
+    suspend fun updateFilter(circleId: String, timelineIds: Set<String>) = createResult {
+        session.getRoom(circleId)?.roomAccountDataService()
+            ?.updateAccountData(
+                CIRCLE_FILTER_EVENT_TYPE,
+                mapOf(TIMELINES_KEY to timelineIds)
+            )
+    }
+
+    companion object {
+        private const val CIRCLE_FILTER_EVENT_TYPE = "m.circle.filter"
+        private const val TIMELINES_KEY = "timelines"
+    }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/feature/picker/gallery/media/PickMediaItemViewModel.kt b/core/src/main/java/org/futo/circles/core/feature/picker/gallery/media/PickMediaItemViewModel.kt
index 3d52fe475..bec1d1772 100644
--- a/core/src/main/java/org/futo/circles/core/feature/picker/gallery/media/PickMediaItemViewModel.kt
+++ b/core/src/main/java/org/futo/circles/core/feature/picker/gallery/media/PickMediaItemViewModel.kt
@@ -1,25 +1,26 @@
 package org.futo.circles.core.feature.picker.gallery.media
 
 import androidx.lifecycle.SavedStateHandle
-import androidx.lifecycle.asFlow
 import androidx.lifecycle.asLiveData
 import dagger.hilt.android.lifecycle.HiltViewModel
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
-import org.futo.circles.core.model.GalleryContentListItem
-import org.futo.circles.core.model.MediaContent
-import org.futo.circles.core.model.PostContentType
+import org.futo.circles.core.feature.circles.filter.CircleFilterAccountDataManager
 import org.futo.circles.core.feature.picker.gallery.PickGalleryMediaDialogFragment.Companion.IS_VIDEO_AVAILABLE
 import org.futo.circles.core.feature.timeline.BaseTimelineViewModel
 import org.futo.circles.core.feature.timeline.data_source.SingleTimelineDataSource
+import org.futo.circles.core.model.GalleryContentListItem
+import org.futo.circles.core.model.MediaContent
+import org.futo.circles.core.model.PostContentType
 import javax.inject.Inject
 
 @HiltViewModel
 class PickMediaItemViewModel @Inject constructor(
     savedStateHandle: SavedStateHandle,
-    timelineDataSource: SingleTimelineDataSource
-) : BaseTimelineViewModel(timelineDataSource) {
+    timelineDataSource: SingleTimelineDataSource,
+    circleFilterAccountDataManager: CircleFilterAccountDataManager
+) : BaseTimelineViewModel(savedStateHandle, timelineDataSource, circleFilterAccountDataManager) {
 
     private val isVideoAvailable: Boolean = savedStateHandle[IS_VIDEO_AVAILABLE] ?: true
 
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/gallery/grid/GalleryViewModel.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/gallery/grid/GalleryViewModel.kt
index 179a0c189..f0bbff3b8 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/gallery/grid/GalleryViewModel.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/gallery/grid/GalleryViewModel.kt
@@ -6,8 +6,8 @@ import androidx.lifecycle.asLiveData
 import androidx.lifecycle.map
 import dagger.hilt.android.lifecycle.HiltViewModel
 import org.futo.circles.core.base.SingleEventLiveData
-import org.futo.circles.core.extensions.getOrThrow
 import org.futo.circles.core.extensions.launchBg
+import org.futo.circles.core.feature.circles.filter.CircleFilterAccountDataManager
 import org.futo.circles.core.feature.timeline.BaseTimelineViewModel
 import org.futo.circles.core.feature.timeline.data_source.AccessLevelDataSource
 import org.futo.circles.core.feature.timeline.data_source.SingleTimelineDataSource
@@ -27,10 +27,9 @@ class GalleryViewModel @Inject constructor(
     private val sendMessageDataSource: SendMessageDataSource,
     private val mediaDataSource: PostContentDataSource,
     private val postOptionsDataSource: PostOptionsDataSource,
-    private val accessLevelDataSource: AccessLevelDataSource
-) : BaseTimelineViewModel(timelineDataSource) {
-
-    private val roomId: String = savedStateHandle.getOrThrow("roomId")
+    accessLevelDataSource: AccessLevelDataSource,
+    circleFilterAccountDataManager: CircleFilterAccountDataManager
+) : BaseTimelineViewModel(savedStateHandle, timelineDataSource, circleFilterAccountDataManager) {
 
     val accessLevelLiveData = accessLevelDataSource.accessLevelFlow.asLiveData()
 
-- 
GitLab