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 9f75a896c98b095fef1f644d5e8982379e0129e3..d28a35a7e92cc3a7ffaaa4b5777256095e19c6fe 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 0000000000000000000000000000000000000000..4b72cd9967d442a2aa1c83232d31838960b27db8 --- /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 3d52fe475553b3061e9ad21561fd234ff4ff4ce3..bec1d17722bc635f48e5c3ae76f69bbde83f21f7 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 179a0c1894c00c40772323dfe03bfd5bc0b7da54..f0bbff3b8345419e21fcd619f5041b93cb8d2c61 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()