diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceChildContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceChildContent.kt index e7936d00e5..0c33cfa1e6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceChildContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceChildContent.kt @@ -22,7 +22,6 @@ import com.squareup.moshi.JsonClass /** * "content": { * "via": ["example.com"], - * "present": true, * "order": "abcd", * "default": true * } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt index 0dce2d2c67..dae2c0838e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt @@ -323,6 +323,31 @@ internal class RoomSummaryUpdater @Inject constructor( // we need also to filter DMs... // it's more annoying as based on if the other members belong the space or not + RoomSummaryEntity.where(realm) + .equalTo(RoomSummaryEntityFields.IS_DIRECT, true) + .process(RoomSummaryEntityFields.MEMBERSHIP_STR, Membership.activeMemberships()) + .findAll() + .forEach { dmRoom -> + val relatedSpaces = lookupMap.keys + .filter { it.roomType == RoomType.SPACE } + .filter { + dmRoom.otherMemberIds.toList().intersect(it.otherMemberIds.toList()).isNotEmpty() + } + .map { it.roomId } + .distinct() + val flattenRelated = mutableListOf().apply { + addAll(relatedSpaces) + relatedSpaces.map { flattenSpaceParents[it] }.forEach { + if (it != null) addAll(it) + } + }.distinct() + if (flattenRelated.isEmpty()) { + dmRoom.flattenParentIds = null + } else { + dmRoom.flattenParentIds = "|${flattenRelated.joinToString("|")}|" + } +// Timber.v("## SPACES: flatten of ${dmRoom.otherMemberIds.joinToString(",")} is ${dmRoom.flattenParentIds}") + } // LEGACY GROUPS // lets mark rooms that belongs to groups diff --git a/vector/src/main/java/im/vector/app/AppStateHandler.kt b/vector/src/main/java/im/vector/app/AppStateHandler.kt index 747ca62193..1f090c89ab 100644 --- a/vector/src/main/java/im/vector/app/AppStateHandler.kt +++ b/vector/src/main/java/im/vector/app/AppStateHandler.kt @@ -20,10 +20,15 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.OnLifecycleEvent import arrow.core.Option +import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.utils.BehaviorDataSource +import im.vector.app.features.spaces.ALL_COMMUNITIES_GROUP_ID import im.vector.app.features.ui.UiStateRepository import io.reactivex.disposables.CompositeDisposable +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixPatterns +import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject import javax.inject.Singleton @@ -36,30 +41,51 @@ import javax.inject.Singleton @Singleton class AppStateHandler @Inject constructor( sessionDataSource: ActiveSessionDataSource, - private val uiStateRepository: UiStateRepository + private val uiStateRepository: UiStateRepository, + private val activeSessionHolder: ActiveSessionHolder ) : LifecycleObserver { private val compositeDisposable = CompositeDisposable() - val selectedSpaceDataSource = BehaviorDataSource>(Option.empty()) + private val selectedSpaceDataSource = BehaviorDataSource>(Option.empty()) + + val selectedSpaceObservable = selectedSpaceDataSource.observe() + + fun setCurrentSpace(space: RoomSummary?) { + if (space == selectedSpaceDataSource.currentValue?.orNull()) return + selectedSpaceDataSource.post(space?.let { Option.just(it) } ?: Option.empty()) + if (space != null && space.roomId != ALL_COMMUNITIES_GROUP_ID) { + GlobalScope.launch { + tryOrNull { + activeSessionHolder.getSafeActiveSession()?.getRoom(space.roomId)?.loadRoomMembersIfNeeded() + } + } + } + } init { // restore current space from ui state sessionDataSource.currentValue?.orNull()?.let { session -> uiStateRepository.getSelectedSpace(session.sessionId)?.let { selectedSpaceId -> session.getRoomSummary(selectedSpaceId)?.let { - selectedSpaceDataSource.post(Option.just(it)) + setCurrentSpace(it) } } } } - fun safeActiveSpaceId() : String? { + fun safeActiveSpaceId(): String? { return selectedSpaceDataSource.currentValue?.orNull()?.roomId?.takeIf { MatrixPatterns.isRoomId(it) } } + fun safeActiveSpace(): RoomSummary? { + return selectedSpaceDataSource.currentValue?.orNull()?.takeIf { + MatrixPatterns.isRoomId(it.roomId) + } + } + @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun entersForeground() { } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt index 0cf57d272c..8aa58632b3 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt @@ -149,8 +149,7 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho } private fun observeSelectedSpaceStore() { - appStateHandler.selectedSpaceDataSource - .observe() + appStateHandler.selectedSpaceObservable .subscribe { setState { copy(spaceSummary = it) @@ -160,7 +159,7 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho } private fun observeRoomSummaries() { - appStateHandler.selectedSpaceDataSource.observe().distinctUntilChanged().switchMap { + appStateHandler.selectedSpaceObservable.distinctUntilChanged().switchMap { session.getPagedRoomSummariesLive( roomSummaryQueryParams { memberships = Membership.activeMemberships() diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/GroupRoomListSectionBuilder.kt b/vector/src/main/java/im/vector/app/features/home/room/list/GroupRoomListSectionBuilder.kt index 6448705979..7c994666a9 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/GroupRoomListSectionBuilder.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/GroupRoomListSectionBuilder.kt @@ -113,7 +113,9 @@ class GroupRoomListSectionBuilder( return sections } - private fun buildRoomsSections(sections: MutableList, activeSpaceAwareQueries: MutableList, actualGroupId: String?) { + private fun buildRoomsSections(sections: MutableList, + activeSpaceAwareQueries: MutableList, + actualGroupId: String?) { addSection( sections, activeSpaceAwareQueries, diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt index a58bee709b..7f213336f8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt @@ -74,7 +74,7 @@ class RoomListViewModel @Inject constructor( init { observeMembershipChanges() - appStateHandler.selectedSpaceDataSource.observe() + appStateHandler.selectedSpaceObservable .distinctUntilChanged() .map { it.orNull() } .distinctUntilChanged() diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/SpaceRoomListSectionBuilder.kt b/vector/src/main/java/im/vector/app/features/home/room/list/SpaceRoomListSectionBuilder.kt index 49be503c80..426c29a622 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/SpaceRoomListSectionBuilder.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/SpaceRoomListSectionBuilder.kt @@ -40,8 +40,6 @@ import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult 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.roomSummaryQueryParams import org.matrix.android.sdk.rx.asObservable class SpaceRoomListSectionBuilder( @@ -104,7 +102,7 @@ class SpaceRoomListSectionBuilder( } } - appStateHandler.selectedSpaceDataSource.observe() + appStateHandler.selectedSpaceObservable .distinctUntilChanged() .subscribe { activeSpaceOption -> val selectedSpace = activeSpaceOption.orNull() @@ -179,7 +177,7 @@ class SpaceRoomListSectionBuilder( // add suggested rooms val suggestedRoomsObservable = // MutableLiveData>() - appStateHandler.selectedSpaceDataSource.observe() + appStateHandler.selectedSpaceObservable .distinctUntilChanged() .switchMap { activeSpaceOption -> val selectedSpace = activeSpaceOption.orNull() @@ -243,46 +241,57 @@ class SpaceRoomListSectionBuilder( it.roomTagQueryFilter = RoomTagQueryFilter(true, null, null) } - // For DMs we still need some post query filter :/ - // It's probably less important as home is not filtering at all - val dmList = MutableLiveData>() - Observables.combineLatest( - session.getRoomSummariesLive( - roomSummaryQueryParams { - memberships = listOf(Membership.JOIN) - roomCategoryFilter = RoomCategoryFilter.ONLY_DM - } - ).asObservable(), - appStateHandler.selectedSpaceDataSource.observe() - - ) { rooms, currentSpaceOption -> - val currentSpace = currentSpaceOption.orNull() - .takeIf { - // the +ALL trick is annoying, should find a way to fix that at the source! - MatrixPatterns.isRoomId(it?.roomId) - } - if (currentSpace == null) { - rooms - } else { - rooms.filter { - it.otherMemberIds - .intersect(currentSpace.otherMemberIds) - .isNotEmpty() - } - } - }.subscribe { - dmList.postValue(it) - }.also { - onDisposable.invoke(it) + addSection(sections, + activeSpaceAwareQueries, + R.string.bottom_action_people_x, + false, + RoomListViewModel.SpaceFilterStrategy.NOT_IF_ALL + ) { + it.memberships = listOf(Membership.JOIN) + it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM + it.roomTagQueryFilter = RoomTagQueryFilter(false, null, null) } - sections.add( - RoomsSection( - sectionName = stringProvider.getString(R.string.bottom_action_people_x), - liveList = dmList, - notifyOfLocalEcho = false - ) - ) +// // For DMs we still need some post query filter :/ +// // It's probably less important as home is not filtering at all +// val dmList = MutableLiveData>() +// Observables.combineLatest( +// session.getRoomSummariesLive( +// roomSummaryQueryParams { +// memberships = listOf(Membership.JOIN) +// roomCategoryFilter = RoomCategoryFilter.ONLY_DM +// } +// ).asObservable(), +// appStateHandler.selectedSpaceDataSource.observe() +// +// ) { rooms, currentSpaceOption -> +// val currentSpace = currentSpaceOption.orNull() +// .takeIf { +// // the +ALL trick is annoying, should find a way to fix that at the source! +// MatrixPatterns.isRoomId(it?.roomId) +// } +// if (currentSpace == null) { +// rooms +// } else { +// rooms.filter { +// it.otherMemberIds +// .intersect(currentSpace.otherMemberIds) +// .isNotEmpty() +// } +// } +// }.subscribe { +// dmList.postValue(it) +// }.also { +// onDisposable.invoke(it) +// } +// +// sections.add( +// RoomsSection( +// sectionName = stringProvider.getString(R.string.bottom_action_people_x), +// liveList = dmList, +// notifyOfLocalEcho = false +// ) +// ) } private fun addSection(sections: MutableList, diff --git a/vector/src/main/java/im/vector/app/features/media/BaseAttachmentProvider.kt b/vector/src/main/java/im/vector/app/features/media/BaseAttachmentProvider.kt index d3ab39abef..53996171a5 100644 --- a/vector/src/main/java/im/vector/app/features/media/BaseAttachmentProvider.kt +++ b/vector/src/main/java/im/vector/app/features/media/BaseAttachmentProvider.kt @@ -155,7 +155,7 @@ abstract class BaseAttachmentProvider( target.onVideoURLReady(info.uid, data.url) } else { target.onVideoFileLoading(info.uid) - GlobalScope.launch { + GlobalScope.launch(Dispatchers.Main) { val result = runCatching { fileService.downloadFile( fileName = data.filename, diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index ce178a1358..c033cc40fa 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -29,7 +29,6 @@ import androidx.core.app.ActivityOptionsCompat import androidx.core.app.TaskStackBuilder import androidx.core.util.Pair import androidx.core.view.ViewCompat -import arrow.core.Option import im.vector.app.AppStateHandler import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder @@ -114,7 +113,7 @@ class DefaultNavigator @Inject constructor( sessionHolder.getSafeActiveSession()?.spaceService()?.getSpace(spaceId)?.spaceSummary()?.let { Timber.d("## Nav: Switching to space $spaceId / ${it.name}") - appStateHandler.selectedSpaceDataSource.post(Option.just(it)) + appStateHandler.setCurrentSpace(it) } ?: kotlin.run { Timber.d("## Nav: Failed to switch to space $spaceId") } @@ -252,7 +251,7 @@ class DefaultNavigator @Inject constructor( } override fun openRoomDirectory(context: Context, initialFilter: String) { - val selectedSpace = appStateHandler.selectedSpaceDataSource.currentValue?.orNull()?.let { + val selectedSpace = appStateHandler.safeActiveSpace()?.let { sessionHolder.getSafeActiveSession()?.getRoomSummary(it.roomId) } if (selectedSpace == null) { @@ -276,9 +275,7 @@ class DefaultNavigator @Inject constructor( } override fun openInviteUsersToRoom(context: Context, roomId: String) { - val selectedSpace = appStateHandler.selectedSpaceDataSource.currentValue?.orNull()?.let { - sessionHolder.getSafeActiveSession()?.getRoomSummary(it.roomId) - } + val selectedSpace = appStateHandler.safeActiveSpace() if (vectorPreferences.labSpaces() && selectedSpace != null) { // let user decides if he does it from space or room (context as? AppCompatActivity)?.supportFragmentManager?.let { fm -> diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpacesListViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/SpacesListViewModel.kt index f82923b570..8889a76f9b 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpacesListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpacesListViewModel.kt @@ -17,7 +17,6 @@ package im.vector.app.features.spaces import androidx.lifecycle.viewModelScope -import arrow.core.Option import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext @@ -68,8 +67,7 @@ class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: Sp init { observeSpaceSummaries() observeSelectionState() - appStateHandler.selectedSpaceDataSource - .observe() + appStateHandler.selectedSpaceObservable .subscribe { if (currentGroupId != it.orNull()?.roomId) { setState { @@ -90,8 +88,7 @@ class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: Sp currentGroupId = spaceSummary.roomId _viewEvents.post(SpaceListViewEvents.OpenSpace) } - val optionGroup = Option.just(spaceSummary) - appStateHandler.selectedSpaceDataSource.post(optionGroup) + appStateHandler.setCurrentSpace(spaceSummary) } else { // If selected group is null we force to default. It can happens when leaving the selected group. setState {