Add section header when displaying room list to share (#771)

This commit is contained in:
Benoit Marty 2020-01-21 19:02:41 +01:00
parent 3c2fa40b58
commit c971f18fc0
5 changed files with 132 additions and 69 deletions

View File

@ -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.matrix.android.api.session.room.model.tag.RoomTag
import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.platform.VectorViewModel
import im.vector.riotx.core.utils.DataSource import im.vector.riotx.core.utils.DataSource
import im.vector.riotx.features.home.RoomListDisplayMode
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -202,35 +203,54 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState,
} }
private fun buildRoomSummaries(rooms: List<RoomSummary>): RoomSummaries { private fun buildRoomSummaries(rooms: List<RoomSummary>): RoomSummaries {
// Set up init size on directChats and groupRooms as they are the biggest ones if (displayMode == RoomListDisplayMode.SHARE) {
val invites = ArrayList<RoomSummary>() val recentRooms = ArrayList<RoomSummary>(20)
val favourites = ArrayList<RoomSummary>() val otherRooms = ArrayList<RoomSummary>(rooms.size)
val directChats = ArrayList<RoomSummary>(rooms.size)
val groupRooms = ArrayList<RoomSummary>(rooms.size)
val lowPriorities = ArrayList<RoomSummary>()
val serverNotices = ArrayList<RoomSummary>()
rooms rooms
.filter { roomListDisplayModeFilter.test(it) } .filter { roomListDisplayModeFilter.test(it) }
.forEach { room -> .forEach { room ->
val tags = room.tags.map { it.name } when (room.breadcrumbsIndex) {
when { RoomSummary.NOT_IN_BREADCRUMBS -> otherRooms.add(room)
room.membership == Membership.INVITE -> invites.add(room) else -> recentRooms.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 { return RoomSummaries().apply {
put(RoomCategory.INVITE, invites) put(RoomCategory.RECENT_ROOMS, recentRooms)
put(RoomCategory.FAVOURITE, favourites) put(RoomCategory.OTHER_ROOMS, otherRooms)
put(RoomCategory.DIRECT, directChats) }
put(RoomCategory.GROUP, groupRooms) } else {
put(RoomCategory.LOW_PRIORITY, lowPriorities) // Set up init size on directChats and groupRooms as they are the biggest ones
put(RoomCategory.SERVER_NOTICE, serverNotices) val invites = ArrayList<RoomSummary>()
val favourites = ArrayList<RoomSummary>()
val directChats = ArrayList<RoomSummary>(rooms.size)
val groupRooms = ArrayList<RoomSummary>(rooms.size)
val lowPriorities = ArrayList<RoomSummary>()
val serverNotices = ArrayList<RoomSummary>()
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)
}
} }
} }
} }

View File

@ -43,7 +43,10 @@ data class RoomListViewState(
val isDirectRoomsExpanded: Boolean = true, val isDirectRoomsExpanded: Boolean = true,
val isGroupRoomsExpanded: Boolean = true, val isGroupRoomsExpanded: Boolean = true,
val isLowPriorityRoomsExpanded: 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 { ) : MvRxState {
constructor(args: RoomListParams) : this(displayMode = args.displayMode) constructor(args: RoomListParams) : this(displayMode = args.displayMode)
@ -56,6 +59,8 @@ data class RoomListViewState(
RoomCategory.GROUP -> isGroupRoomsExpanded RoomCategory.GROUP -> isGroupRoomsExpanded
RoomCategory.LOW_PRIORITY -> isLowPriorityRoomsExpanded RoomCategory.LOW_PRIORITY -> isLowPriorityRoomsExpanded
RoomCategory.SERVER_NOTICE -> isServerNoticeRoomsExpanded 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.GROUP -> copy(isGroupRoomsExpanded = !isGroupRoomsExpanded)
RoomCategory.LOW_PRIORITY -> copy(isLowPriorityRoomsExpanded = !isLowPriorityRoomsExpanded) RoomCategory.LOW_PRIORITY -> copy(isLowPriorityRoomsExpanded = !isLowPriorityRoomsExpanded)
RoomCategory.SERVER_NOTICE -> copy(isServerNoticeRoomsExpanded = !isServerNoticeRoomsExpanded) 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), DIRECT(R.string.bottom_action_people_x),
GROUP(R.string.bottom_action_rooms), GROUP(R.string.bottom_action_rooms),
LOW_PRIORITY(R.string.low_priority_header), 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 { fun RoomSummaries?.isNullOrEmpty(): Boolean {

View File

@ -59,39 +59,9 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
override fun buildModels() { override fun buildModels() {
val nonNullViewState = viewState ?: return val nonNullViewState = viewState ?: return
when (nonNullViewState.displayMode) { when (nonNullViewState.displayMode) {
RoomListDisplayMode.FILTERED, RoomListDisplayMode.FILTERED -> buildFilteredRooms(nonNullViewState)
RoomListDisplayMode.SHARE -> { RoomListDisplayMode.SHARE -> buildShareRooms(nonNullViewState)
buildFilteredRooms(nonNullViewState) else -> buildRooms(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()
}
}
} }
} }
@ -109,9 +79,69 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
viewState.rejectingRoomsIds, viewState.rejectingRoomsIds,
viewState.rejectingErrorRoomsIds) viewState.rejectingErrorRoomsIds)
when { addFilterFooter(viewState)
viewState.displayMode == RoomListDisplayMode.FILTERED -> addFilterFooter(viewState) }
filteredSummaries.isEmpty() -> addEmptyFooter()
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 { noResultItem {
id("no_result") id("no_result")
text(stringProvider.getString(R.string.no_result_placeholder)) text(stringProvider.getString(R.string.no_result_placeholder))
@ -142,9 +172,6 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
@StringRes titleRes: Int, @StringRes titleRes: Int,
isExpanded: Boolean, isExpanded: Boolean,
mutateExpandedState: () -> Unit) { mutateExpandedState: () -> Unit) {
if (summaries.isEmpty()) {
return
}
// TODO should add some business logic later // TODO should add some business logic later
val unreadCount = if (summaries.isEmpty()) { val unreadCount = if (summaries.isEmpty()) {
0 0

View File

@ -44,7 +44,9 @@ class IncomingShareActivity :
@Inject lateinit var sessionHolder: ActiveSessionHolder @Inject lateinit var sessionHolder: ActiveSessionHolder
@Inject lateinit var incomingShareViewModelFactory: IncomingShareViewModel.Factory @Inject lateinit var incomingShareViewModelFactory: IncomingShareViewModel.Factory
private lateinit var attachmentsHelper: AttachmentsHelper 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? private val roomListFragment: RoomListFragment?
get() { get() {
return supportFragmentManager.findFragmentById(R.id.shareRoomListFragmentContainer) as? RoomListFragment return supportFragmentManager.findFragmentById(R.id.shareRoomListFragmentContainer) as? RoomListFragment

View File

@ -34,6 +34,9 @@
<string name="unignore">Unignore</string> <string name="unignore">Unignore</string>
<string name="room_list_sharing_header_recent_rooms">Recent rooms</string>
<string name="room_list_sharing_header_other_rooms">Other rooms</string>
<!-- Title for category in the settings which affect what is displayed in the timeline (ex: show read receipts, etc.) --> <!-- Title for category in the settings which affect what is displayed in the timeline (ex: show read receipts, etc.) -->
<string name="settings_category_timeline">Timeline</string> <string name="settings_category_timeline">Timeline</string>