From c971f18fc0d76c1cdbf47505570e68ea679fea2a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 21 Jan 2020 19:02:41 +0100 Subject: [PATCH] Add section header when displaying room list to share (#771) --- .../home/room/list/RoomListViewModel.kt | 72 +++++++----- .../home/room/list/RoomListViewState.kt | 15 ++- .../home/room/list/RoomSummaryController.kt | 107 +++++++++++------- .../features/share/IncomingShareActivity.kt | 4 +- vector/src/main/res/values/strings_riotX.xml | 3 + 5 files changed, 132 insertions(+), 69 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt index f2f563cf26..397df50c2b 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt @@ -26,6 +26,7 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.tag.RoomTag import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.utils.DataSource +import im.vector.riotx.features.home.RoomListDisplayMode import io.reactivex.schedulers.Schedulers import timber.log.Timber import javax.inject.Inject @@ -202,35 +203,54 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, } private fun buildRoomSummaries(rooms: List): RoomSummaries { - // Set up init size on directChats and groupRooms as they are the biggest ones - val invites = ArrayList() - val favourites = ArrayList() - val directChats = ArrayList(rooms.size) - val groupRooms = ArrayList(rooms.size) - val lowPriorities = ArrayList() - val serverNotices = ArrayList() + if (displayMode == RoomListDisplayMode.SHARE) { + val recentRooms = ArrayList(20) + val otherRooms = ArrayList(rooms.size) - rooms - .filter { roomListDisplayModeFilter.test(it) } - .forEach { room -> - val tags = room.tags.map { it.name } - when { - room.membership == Membership.INVITE -> invites.add(room) - tags.contains(RoomTag.ROOM_TAG_SERVER_NOTICE) -> serverNotices.add(room) - tags.contains(RoomTag.ROOM_TAG_FAVOURITE) -> favourites.add(room) - tags.contains(RoomTag.ROOM_TAG_LOW_PRIORITY) -> lowPriorities.add(room) - room.isDirect -> directChats.add(room) - else -> groupRooms.add(room) + rooms + .filter { roomListDisplayModeFilter.test(it) } + .forEach { room -> + when (room.breadcrumbsIndex) { + RoomSummary.NOT_IN_BREADCRUMBS -> otherRooms.add(room) + else -> recentRooms.add(room) + } } - } - return RoomSummaries().apply { - put(RoomCategory.INVITE, invites) - put(RoomCategory.FAVOURITE, favourites) - put(RoomCategory.DIRECT, directChats) - put(RoomCategory.GROUP, groupRooms) - put(RoomCategory.LOW_PRIORITY, lowPriorities) - put(RoomCategory.SERVER_NOTICE, serverNotices) + return RoomSummaries().apply { + put(RoomCategory.RECENT_ROOMS, recentRooms) + put(RoomCategory.OTHER_ROOMS, otherRooms) + } + } else { + // Set up init size on directChats and groupRooms as they are the biggest ones + val invites = ArrayList() + val favourites = ArrayList() + val directChats = ArrayList(rooms.size) + val groupRooms = ArrayList(rooms.size) + val lowPriorities = ArrayList() + val serverNotices = ArrayList() + + rooms + .filter { roomListDisplayModeFilter.test(it) } + .forEach { room -> + val tags = room.tags.map { it.name } + when { + room.membership == Membership.INVITE -> invites.add(room) + tags.contains(RoomTag.ROOM_TAG_SERVER_NOTICE) -> serverNotices.add(room) + tags.contains(RoomTag.ROOM_TAG_FAVOURITE) -> favourites.add(room) + tags.contains(RoomTag.ROOM_TAG_LOW_PRIORITY) -> lowPriorities.add(room) + room.isDirect -> directChats.add(room) + else -> groupRooms.add(room) + } + } + + return RoomSummaries().apply { + put(RoomCategory.INVITE, invites) + put(RoomCategory.FAVOURITE, favourites) + put(RoomCategory.DIRECT, directChats) + put(RoomCategory.GROUP, groupRooms) + put(RoomCategory.LOW_PRIORITY, lowPriorities) + put(RoomCategory.SERVER_NOTICE, serverNotices) + } } } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewState.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewState.kt index b41b4b9eeb..c127fa10e2 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewState.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewState.kt @@ -43,7 +43,10 @@ data class RoomListViewState( val isDirectRoomsExpanded: Boolean = true, val isGroupRoomsExpanded: Boolean = true, val isLowPriorityRoomsExpanded: Boolean = true, - val isServerNoticeRoomsExpanded: Boolean = true + val isServerNoticeRoomsExpanded: Boolean = true, + // For sharing + val isRecentExpanded: Boolean = true, + val isOtherExpanded: Boolean = true ) : MvRxState { constructor(args: RoomListParams) : this(displayMode = args.displayMode) @@ -56,6 +59,8 @@ data class RoomListViewState( RoomCategory.GROUP -> isGroupRoomsExpanded RoomCategory.LOW_PRIORITY -> isLowPriorityRoomsExpanded RoomCategory.SERVER_NOTICE -> isServerNoticeRoomsExpanded + RoomCategory.RECENT_ROOMS -> isRecentExpanded + RoomCategory.OTHER_ROOMS -> isOtherExpanded } } @@ -67,6 +72,8 @@ data class RoomListViewState( RoomCategory.GROUP -> copy(isGroupRoomsExpanded = !isGroupRoomsExpanded) RoomCategory.LOW_PRIORITY -> copy(isLowPriorityRoomsExpanded = !isLowPriorityRoomsExpanded) RoomCategory.SERVER_NOTICE -> copy(isServerNoticeRoomsExpanded = !isServerNoticeRoomsExpanded) + RoomCategory.RECENT_ROOMS -> copy(isRecentExpanded = !isRecentExpanded) + RoomCategory.OTHER_ROOMS -> copy(isOtherExpanded = !isOtherExpanded) } } @@ -86,7 +93,11 @@ enum class RoomCategory(@StringRes val titleRes: Int) { DIRECT(R.string.bottom_action_people_x), GROUP(R.string.bottom_action_rooms), LOW_PRIORITY(R.string.low_priority_header), - SERVER_NOTICE(R.string.system_alerts_header) + SERVER_NOTICE(R.string.system_alerts_header), + + // For Sharing + RECENT_ROOMS(R.string.room_list_sharing_header_recent_rooms), + OTHER_ROOMS(R.string.room_list_sharing_header_other_rooms) } fun RoomSummaries?.isNullOrEmpty(): Boolean { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryController.kt index 6ffe37cb15..c4afd442ab 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryController.kt @@ -59,39 +59,9 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri override fun buildModels() { val nonNullViewState = viewState ?: return when (nonNullViewState.displayMode) { - RoomListDisplayMode.FILTERED, - RoomListDisplayMode.SHARE -> { - buildFilteredRooms(nonNullViewState) - } - else -> { - var showHelp = false - val roomSummaries = nonNullViewState.asyncFilteredRooms() - roomSummaries?.forEach { (category, summaries) -> - if (summaries.isEmpty()) { - return@forEach - } else { - val isExpanded = nonNullViewState.isCategoryExpanded(category) - buildRoomCategory(nonNullViewState, summaries, category.titleRes, nonNullViewState.isCategoryExpanded(category)) { - listener?.onToggleRoomCategory(category) - } - if (isExpanded) { - buildRoomModels(summaries, - nonNullViewState.joiningRoomsIds, - nonNullViewState.joiningErrorRoomsIds, - nonNullViewState.rejectingRoomsIds, - nonNullViewState.rejectingErrorRoomsIds) - // Never set showHelp to true for invitation - if (category != RoomCategory.INVITE) { - showHelp = userPreferencesProvider.shouldShowLongClickOnRoomHelp() - } - } - } - } - - if (showHelp) { - buildLongClickHelp() - } - } + RoomListDisplayMode.FILTERED -> buildFilteredRooms(nonNullViewState) + RoomListDisplayMode.SHARE -> buildShareRooms(nonNullViewState) + else -> buildRooms(nonNullViewState) } } @@ -109,9 +79,69 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri viewState.rejectingRoomsIds, viewState.rejectingErrorRoomsIds) - when { - viewState.displayMode == RoomListDisplayMode.FILTERED -> addFilterFooter(viewState) - filteredSummaries.isEmpty() -> addEmptyFooter() + addFilterFooter(viewState) + } + + private fun buildShareRooms(viewState: RoomListViewState) { + var hasResult = false + val roomSummaries = viewState.asyncFilteredRooms() + + roomListNameFilter.filter = viewState.roomFilter + + roomSummaries?.forEach { (category, summaries) -> + val filteredSummaries = summaries + .filter { it.membership == Membership.JOIN && roomListNameFilter.test(it) } + + if (filteredSummaries.isEmpty()) { + return@forEach + } else { + hasResult = true + val isExpanded = viewState.isCategoryExpanded(category) + buildRoomCategory(viewState, emptyList(), category.titleRes, viewState.isCategoryExpanded(category)) { + listener?.onToggleRoomCategory(category) + } + if (isExpanded) { + buildRoomModels(filteredSummaries, + emptySet(), + emptySet(), + emptySet(), + emptySet() + ) + } + } + } + if (!hasResult) { + addNoResultItem() + } + } + + private fun buildRooms(viewState: RoomListViewState) { + var showHelp = false + val roomSummaries = viewState.asyncFilteredRooms() + roomSummaries?.forEach { (category, summaries) -> + if (summaries.isEmpty()) { + return@forEach + } else { + val isExpanded = viewState.isCategoryExpanded(category) + buildRoomCategory(viewState, summaries, category.titleRes, viewState.isCategoryExpanded(category)) { + listener?.onToggleRoomCategory(category) + } + if (isExpanded) { + buildRoomModels(summaries, + viewState.joiningRoomsIds, + viewState.joiningErrorRoomsIds, + viewState.rejectingRoomsIds, + viewState.rejectingErrorRoomsIds) + // Never set showHelp to true for invitation + if (category != RoomCategory.INVITE) { + showHelp = userPreferencesProvider.shouldShowLongClickOnRoomHelp() + } + } + } + } + + if (showHelp) { + buildLongClickHelp() } } @@ -130,7 +160,7 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri } } - private fun addEmptyFooter() { + private fun addNoResultItem() { noResultItem { id("no_result") text(stringProvider.getString(R.string.no_result_placeholder)) @@ -142,9 +172,6 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri @StringRes titleRes: Int, isExpanded: Boolean, mutateExpandedState: () -> Unit) { - if (summaries.isEmpty()) { - return - } // TODO should add some business logic later val unreadCount = if (summaries.isEmpty()) { 0 diff --git a/vector/src/main/java/im/vector/riotx/features/share/IncomingShareActivity.kt b/vector/src/main/java/im/vector/riotx/features/share/IncomingShareActivity.kt index e48c8246d2..3669a51937 100644 --- a/vector/src/main/java/im/vector/riotx/features/share/IncomingShareActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/share/IncomingShareActivity.kt @@ -44,7 +44,9 @@ class IncomingShareActivity : @Inject lateinit var sessionHolder: ActiveSessionHolder @Inject lateinit var incomingShareViewModelFactory: IncomingShareViewModel.Factory private lateinit var attachmentsHelper: AttachmentsHelper - private val incomingShareViewModel: IncomingShareViewModel by viewModel() + // Do not remove, even if not used, it instantiates the view model + @Suppress("unused") + private val viewModel: IncomingShareViewModel by viewModel() private val roomListFragment: RoomListFragment? get() { return supportFragmentManager.findFragmentById(R.id.shareRoomListFragmentContainer) as? RoomListFragment diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 4ca908128e..781912fbe5 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -34,6 +34,9 @@ Unignore + Recent rooms + Other rooms + Timeline