diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt index 05bf9a8a84..8323c3b155 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt @@ -84,7 +84,8 @@ class RoomListFragment @Inject constructor( data class SectionKey( val name: String, - val isExpanded: Boolean + val isExpanded: Boolean, + val notifyOfLocalEcho: Boolean ) data class SectionAdapterInfo( @@ -116,6 +117,14 @@ class RoomListFragment @Inject constructor( .observe() .subscribe { handleQuickActions(it) } .disposeOnDestroyView() + + roomListViewModel.selectSubscribe(viewLifecycleOwner, RoomListViewState::roomMembershipChanges) { ms -> + // it's for invites local echo + adapterInfosList.filter { it.section.notifyOfLocalEcho } + .onEach { + it.contentAdapter.roomChangeMembershipStates = ms + } + } } private fun refreshCollapseStates() { @@ -267,7 +276,8 @@ class RoomListFragment @Inject constructor( SectionAdapterInfo( SectionKey( name = section.sectionName, - isExpanded = section.isExpanded.value.orTrue() + isExpanded = section.isExpanded.value.orTrue(), + notifyOfLocalEcho = section.notifyOfLocalEcho ), sectionAdapter, contentAdapter 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 76e8b1adaf..21e4e5830c 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 @@ -38,6 +38,7 @@ import org.matrix.android.sdk.api.query.RoomTagQueryFilter import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.room.RoomCategoryFilter import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams +import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState 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.tag.RoomTag @@ -46,6 +47,7 @@ import org.matrix.android.sdk.api.session.room.state.isPublic import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount import org.matrix.android.sdk.internal.session.room.UpdatableFilterLivePageResult import org.matrix.android.sdk.rx.asObservable +import org.matrix.android.sdk.rx.rx import timber.log.Timber import javax.inject.Inject @@ -60,6 +62,19 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, private var updatableQuery: UpdatableFilterLivePageResult? = null + init { + observeMembershipChanges() + } + + private fun observeMembershipChanges() { + session.rx() + .liveRoomChangeMembershipState() + .subscribe { + setState { copy(roomMembershipChanges = it) } + } + .disposeOnClear() + } + companion object : MvRxViewModelFactory { @JvmStatic @@ -74,14 +89,15 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, val livePages: LiveData>, val isExpanded: MutableLiveData = MutableLiveData(true), val notificationCount: MutableLiveData = - MutableLiveData(RoomAggregateNotificationCount(0, 0)) + MutableLiveData(RoomAggregateNotificationCount(0, 0)), + val notifyOfLocalEcho: Boolean = false ) val sections: List by lazy { val sections = mutableListOf() if (initialState.displayMode == RoomListDisplayMode.PEOPLE) { - addSection(sections, R.string.invitations_header) { + addSection(sections, R.string.invitations_header, true) { it.memberships = listOf(Membership.INVITE) it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM } @@ -98,7 +114,7 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, } } else if (initialState.displayMode == RoomListDisplayMode.ROOMS) { - addSection(sections, R.string.invitations_header) { + addSection(sections, R.string.invitations_header, true) { it.memberships = listOf(Membership.INVITE) it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS } @@ -138,16 +154,15 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, } } } else if (initialState.displayMode == RoomListDisplayMode.NOTIFICATIONS) { - withQueryParams({ - it.memberships = Membership.activeMemberships() + + addSection(sections, R.string.invitations_header, true) { + it.memberships = listOf(Membership.INVITE) + it.roomCategoryFilter = RoomCategoryFilter.ALL + } + + addSection(sections, R.string.bottom_action_rooms, true) { + it.memberships = listOf(Membership.JOIN) it.roomCategoryFilter = RoomCategoryFilter.ONLY_WITH_NOTIFICATIONS - }) { qpm -> - val name = stringProvider.getString(R.string.bottom_action_rooms) - session.getFilteredPagedRoomSummariesLive(qpm) - .let { livePagedList -> - updatableQuery = livePagedList - sections.add(RoomsSection(name, livePagedList.livePagedList)) - } } } @@ -167,7 +182,10 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, }.exhaustive } - private fun addSection(sections: MutableList, @StringRes nameRes: Int, query: (RoomSummaryQueryParams.Builder) -> Unit) { + private fun addSection(sections: MutableList, + @StringRes nameRes: Int, + notifyOfLocalEcho: Boolean = false, + query: (RoomSummaryQueryParams.Builder) -> Unit) { withQueryParams({ query.invoke(it) }) { roomQueryParams -> @@ -185,7 +203,13 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, ?.postValue(session.getNotificationCountForRooms(roomQueryParams)) }.disposeOnClear() - sections.add(RoomsSection(name, livePagedList)) + sections.add( + RoomsSection( + sectionName = name, + livePages = livePagedList, + notifyOfLocalEcho = notifyOfLocalEcho + ) + ) } } } @@ -238,6 +262,19 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, return@withState } + // quick echo + setState { + copy( + roomMembershipChanges = roomMembershipChanges.mapValues { + if (it.key == roomId) { + ChangeMembershipState.Joining + } else { + it.value + } + } + ) + } + val room = session.getRoom(roomId) ?: return@withState viewModelScope.launch { try { diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedController.kt index 75171dad39..38137e0033 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedController.kt @@ -18,24 +18,19 @@ package im.vector.app.features.home.room.list import com.airbnb.epoxy.EpoxyModel import com.airbnb.epoxy.paging.PagedListEpoxyController -import im.vector.app.core.resources.StringProvider -import im.vector.app.core.resources.UserPreferencesProvider import im.vector.app.core.utils.createUIHandler +import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject -class RoomSummaryPagedControllerFactory @Inject constructor(private val stringProvider: StringProvider, - private val userPreferencesProvider: UserPreferencesProvider, - private val roomSummaryItemFactory: RoomSummaryItemFactory) { +class RoomSummaryPagedControllerFactory @Inject constructor(private val roomSummaryItemFactory: RoomSummaryItemFactory) { fun createRoomSummaryPagedController(): RoomSummaryPagedController { - return RoomSummaryPagedController(stringProvider, userPreferencesProvider, roomSummaryItemFactory) + return RoomSummaryPagedController(roomSummaryItemFactory) } } -class RoomSummaryPagedController constructor(private val stringProvider: StringProvider, - private val userPreferencesProvider: UserPreferencesProvider, - private val roomSummaryItemFactory: RoomSummaryItemFactory) +class RoomSummaryPagedController constructor(private val roomSummaryItemFactory: RoomSummaryItemFactory) : PagedListEpoxyController( // Important it must match the PageList builder notify Looper modelBuildingHandler = createUIHandler() @@ -43,9 +38,16 @@ class RoomSummaryPagedController constructor(private val stringProvider: StringP var listener: RoomListListener? = null + var roomChangeMembershipStates: Map? = null + set(value) { + field = value + // ideally we could search for visible models and update only those + requestForcedModelBuild() + } + override fun buildItemModel(currentPosition: Int, item: RoomSummary?): EpoxyModel<*> { val unwrappedItem = item - // for place holder if enabled + // for place holder if enabled ?: return roomSummaryItemFactory.createRoomItem( RoomSummary( roomId = "null_item_pos_$currentPosition", @@ -57,7 +59,7 @@ class RoomSummaryPagedController constructor(private val stringProvider: StringP // GenericItem_().apply { id("null_item_pos_$currentPosition") } - return roomSummaryItemFactory.create(unwrappedItem, emptyMap(), emptySet(), listener) + return roomSummaryItemFactory.create(unwrappedItem, roomChangeMembershipStates ?: emptyMap(), emptySet(), listener) } // override fun onModelBound(holder: EpoxyViewHolder, boundModel: EpoxyModel<*>, position: Int, previouslyBoundModel: EpoxyModel<*>?) {