diff --git a/library/ui-strings/src/main/res/values/strings_sc.xml b/library/ui-strings/src/main/res/values/strings_sc.xml
index 3d16118bab..066f4911c2 100644
--- a/library/ui-strings/src/main/res/values/strings_sc.xml
+++ b/library/ui-strings/src/main/res/values/strings_sc.xml
@@ -200,4 +200,7 @@
When changing the system language, also change the app\'s language
Element\'s new simplified layout with optional tabs
+
+ Unread
+
diff --git a/matrix-sdk-android/src/main/java/de/spiritcroc/android/sdk/internal/database/migration/MigrateScSessionTo007.kt b/matrix-sdk-android/src/main/java/de/spiritcroc/android/sdk/internal/database/migration/MigrateScSessionTo007.kt
new file mode 100644
index 0000000000..6e68dd0b84
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/de/spiritcroc/android/sdk/internal/database/migration/MigrateScSessionTo007.kt
@@ -0,0 +1,26 @@
+package de.spiritcroc.android.sdk.internal.database.migration
+
+import de.spiritcroc.android.sdk.internal.util.database.ScRealmMigrator
+import io.realm.DynamicRealm
+import org.matrix.android.sdk.api.extensions.tryOrNull
+import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
+import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
+
+internal class MigrateScSessionTo007(realm: DynamicRealm) : ScRealmMigrator(realm, 7) {
+
+ override fun doMigrate(realm: DynamicRealm) {
+ realm.schema.get("RoomSummaryEntity")
+ ?.addField(RoomSummaryEntityFields.TREAT_AS_UNREAD_LEVEL, Int::class.java)
+ ?.transform { obj ->
+ val unreadCount = tryOrNull { obj.getInt(RoomSummaryEntityFields.UNREAD_COUNT) }
+ val treatAsUnreadLevel = RoomSummaryEntity.calculateUnreadLevel(
+ obj.getInt(RoomSummaryEntityFields.HIGHLIGHT_COUNT),
+ obj.getInt(RoomSummaryEntityFields.NOTIFICATION_COUNT),
+ obj.getBoolean(RoomSummaryEntityFields.MARKED_UNREAD),
+ unreadCount
+ )
+ obj.setInt(RoomSummaryEntityFields.TREAT_AS_UNREAD_LEVEL, treatAsUnreadLevel)
+ }
+ ?.addIndex(RoomSummaryEntityFields.TREAT_AS_UNREAD_LEVEL)
+ }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSortOrder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSortOrder.kt
index 9368ad6bf4..25f1bf20de 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSortOrder.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSortOrder.kt
@@ -30,6 +30,11 @@ enum class RoomSortOrder {
*/
ACTIVITY,
+ /**
+ * Show unread above read
+ */
+ UNREAD_AND_ACTIVITY,
+
/**
* Sort room list by room priority and last activity: favorite room first, low priority room last,
* then descending last activity.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
index 4ebdbadafd..f406909627 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
@@ -22,6 +22,7 @@ import de.spiritcroc.android.sdk.internal.database.migration.MigrateScSessionTo0
import de.spiritcroc.android.sdk.internal.database.migration.MigrateScSessionTo004
import de.spiritcroc.android.sdk.internal.database.migration.MigrateScSessionTo005
import de.spiritcroc.android.sdk.internal.database.migration.MigrateScSessionTo006
+import de.spiritcroc.android.sdk.internal.database.migration.MigrateScSessionTo007
import io.realm.DynamicRealm
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo001
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo002
@@ -80,7 +81,7 @@ internal class RealmSessionStoreMigration @Inject constructor(
companion object {
// SC-specific DB changes on top of Element
- private val scSchemaVersion = 6L
+ private val scSchemaVersion = 7L
private val scSchemaVersionOffset = (1L shl 12)
val schemaVersion = 37L +
@@ -144,5 +145,6 @@ internal class RealmSessionStoreMigration @Inject constructor(
if (oldScVersion <= 3) MigrateScSessionTo004(realm).perform()
if (oldScVersion <= 4) MigrateScSessionTo005(realm).perform()
if (oldScVersion <= 5) MigrateScSessionTo006(realm).perform()
+ if (oldScVersion <= 6) MigrateScSessionTo007(realm).perform()
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt
index 6c1fd61a5f..c7e2d4303c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt
@@ -21,6 +21,7 @@ import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.Index
import io.realm.annotations.PrimaryKey
+import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
import org.matrix.android.sdk.api.session.room.model.Membership
@@ -122,16 +123,19 @@ internal open class RoomSummaryEntity(
var notificationCount: Int = 0
set(value) {
if (value != field) field = value
+ updateTreatAsUnread()
}
var highlightCount: Int = 0
set(value) {
if (value != field) field = value
+ updateTreatAsUnread()
}
var unreadCount: Int? = null
set(value) {
if (value != field) field = value
+ updateTreatAsUnread()
}
/* -> safeUnreadCount
get() {
@@ -193,9 +197,25 @@ internal open class RoomSummaryEntity(
var markedUnread: Boolean = false
set(value) {
- if (value != field) field = value
+ if (value != field) {
+ field = value
+ updateTreatAsUnread()
+ }
}
+ /**
+ * SchildiChat: Helper var so we can sort depending on how "unread" a chat is: mentions > {notifications, marked unread} > unreads > all read
+ * Make sure to call `updateTreatAsUnread()` when necessary.
+ */
+ @Index
+ private var treatAsUnreadLevel: Int = calculateUnreadLevel()
+ private fun updateTreatAsUnread() {
+ treatAsUnreadLevel = calculateUnreadLevel()
+ }
+ private fun calculateUnreadLevel(): Int {
+ return calculateUnreadLevel(highlightCount, notificationCount, markedUnread, unreadCount)
+ }
+
private var tags: RealmList = RealmList()
fun tags(): List = tags
@@ -377,7 +397,23 @@ internal open class RoomSummaryEntity(
}
}
- companion object
+ companion object {
+ private const val UNREAD_LEVEL_HIGHLIGHT = 4
+ private const val UNREAD_LEVEL_NOTIFIED = 3
+ private const val UNREAD_LEVEL_MARKED_UNREAD = UNREAD_LEVEL_NOTIFIED
+ private const val UNREAD_LEVEL_SILENT_UNREAD = 1
+ private const val UNREAD_LEVEL_NONE = 0
+
+ fun calculateUnreadLevel(highlightCount: Int, notificationCount: Int, markedUnread: Boolean, unreadCount: Int?): Int {
+ return when {
+ highlightCount > 0 -> UNREAD_LEVEL_HIGHLIGHT
+ notificationCount > 0 -> UNREAD_LEVEL_NOTIFIED
+ markedUnread -> UNREAD_LEVEL_MARKED_UNREAD
+ unreadCount?.let { it > 0 }.orFalse() -> UNREAD_LEVEL_SILENT_UNREAD
+ else -> UNREAD_LEVEL_NONE
+ }
+ }
+ }
// Keep sync with RoomSummary.scHasUnreadMessages!
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryRoomOrderProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryRoomOrderProcessor.kt
index 8df0482993..04dba256d7 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryRoomOrderProcessor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryRoomOrderProcessor.kt
@@ -30,6 +30,11 @@ internal fun RealmQuery.process(sortOrder: RoomSortOrder): Re
RoomSortOrder.ACTIVITY -> {
sort(RoomSummaryEntityFields.LAST_ACTIVITY_TIME, Sort.DESCENDING)
}
+ RoomSortOrder.UNREAD_AND_ACTIVITY -> {
+ sort(
+ arrayOf(RoomSummaryEntityFields.TREAT_AS_UNREAD_LEVEL, RoomSummaryEntityFields.LAST_ACTIVITY_TIME),
+ arrayOf(Sort.DESCENDING, Sort.DESCENDING))
+ }
RoomSortOrder.PRIORITY_AND_ACTIVITY -> {
sort(
arrayOf(
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
index cde3f58f30..606ed240bf 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
@@ -23,8 +23,10 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
+import androidx.core.content.edit
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
+import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
@@ -74,6 +76,7 @@ import im.vector.app.features.workers.signout.ServerBackupStatusAction
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
+import org.matrix.android.sdk.api.session.room.RoomSortOrder
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import timber.log.Timber
import javax.inject.Inject
@@ -124,6 +127,7 @@ class HomeDetailFragment :
private var pagerTab: HomeTab? = null
private var pagerPagingEnabled: Boolean = false
private var previousSelectedSpacePair: Pair? = null
+ private var roomSortOrderSettings: RoomSortOrderSettings? = null
override fun getMenuRes() = R.menu.room_list
@@ -133,14 +137,64 @@ class HomeDetailFragment :
viewModel.handle(HomeDetailAction.MarkAllRoomsRead)
true
}
+ R.id.menu_room_sort_order_activity -> {
+ storeRoomSortOrder(RoomSortOrder.ACTIVITY)
+ updateViewPager()
+ true
+ }
+ R.id.menu_room_sort_order_unread -> {
+ storeRoomSortOrder(RoomSortOrder.UNREAD_AND_ACTIVITY)
+ updateViewPager()
+ true
+ }
else -> false
}
}
+ private fun currentEffectiveSpace(): String? {
+ return if (pagerPagingEnabled) {
+ getSpaceIdForPageIndex(views.roomListContainerPager.currentItem)
+ } else {
+ SPACE_ID_FOLLOW_APP
+ }
+ }
+
+ private fun storeRoomSortOrder(roomSortOrder: RoomSortOrder) {
+ val sharedPreferences = context?.let { PreferenceManager.getDefaultSharedPreferences(it) } ?: return
+ val space = currentEffectiveSpace()
+ val pref = if (space == null) VectorPreferences.SETTINGS_ROOM_SORT_ORDER_NULL else VectorPreferences.SETTINGS_ROOM_SORT_ORDER_NON_NULL
+ sharedPreferences.edit {
+ putString(pref, roomSortOrder.toString())
+ }
+ }
+
+ private fun updateViewPager() {
+ withState(viewModel) {
+ val selectedSpace = it.selectedSpaceIgnoreSwipe ?: return@withState
+ spaceStateHandler.persistSelectedSpace()
+ setupViewPager(selectedSpace, it.rootSpacesOrdered, it.currentTab)
+ }
+ }
+
override fun handlePrepareMenu(menu: Menu) {
withState(viewModel) { state ->
val isRoomList = state.currentTab is HomeTab.RoomList
menu.findItem(R.id.menu_home_mark_all_as_read).isVisible = isRoomList && hasUnreadRooms
+ menu.findItem(R.id.menu_room_sort_order).isVisible = true
+
+ // Room sort order
+ val space = currentEffectiveSpace()
+ val roomSortOrder =
+ if (space == null) {
+ roomSortOrderSettings?.nullSpace
+ } else {
+ roomSortOrderSettings?.space
+ }
+ when (roomSortOrder) {
+ RoomSortOrder.ACTIVITY -> menu.findItem(R.id.menu_room_sort_order_activity).isChecked = true
+ RoomSortOrder.UNREAD_AND_ACTIVITY -> menu.findItem(R.id.menu_room_sort_order_unread).isChecked = true
+ else -> Unit
+ }
}
}
@@ -605,10 +659,11 @@ class HomeDetailFragment :
views.spaceBarRecyclerView.isVisible = false
}
val safeSpaces = if (pagingEnabled) unsafeSpaces else listOf()
+ val newRoomSortOrderSettings = loadRoomSortOrderSettings()
// Check if we need to recreate the adapter for a new tab
if (oldAdapter != null) {
- val changed = pagerTab != tab || pagerSpaces != safeSpaces || pagerPagingEnabled != pagingEnabled
- viewPagerDimber.i{ "has changed: $changed (${pagerTab != tab} ${pagerSpaces != safeSpaces} ${pagerPagingEnabled != pagingEnabled} $selectedIndex ${selectedSpacePair.second} ${views.roomListContainerPager.currentItem}) | $safeSpaces" }
+ val changed = pagerTab != tab || pagerSpaces != safeSpaces || pagerPagingEnabled != pagingEnabled || roomSortOrderSettings != newRoomSortOrderSettings
+ viewPagerDimber.i{ "has changed: $changed (${pagerTab != tab} ${pagerSpaces != safeSpaces} ${pagerPagingEnabled != pagingEnabled} ${roomSortOrderSettings != newRoomSortOrderSettings} $selectedIndex ${selectedSpacePair.second} ${views.roomListContainerPager.currentItem}) | $safeSpaces" }
if (!changed) {
// No need to re-setup pager, just check for selected page
if (pagingEnabled) {
@@ -653,6 +708,7 @@ class HomeDetailFragment :
spaceStateHandler.persistSelectedSpace()
pagerSpaces = safeSpaces
pagerTab = tab
+ roomSortOrderSettings = newRoomSortOrderSettings
if (pagerPagingEnabled != pagingEnabled) {
pagerPagingEnabled = pagingEnabled
// Update counts which depend on pagerPagingEnabled
@@ -691,10 +747,10 @@ class HomeDetailFragment :
val params = if (pagingEnabled) {
val spaceId = getSpaceIdForPageIndex(position)
viewPagerDimber.i{"Home pager: position $position -> space $spaceId"}
- RoomListParams(tab.displayMode, spaceId).toMvRxBundle()
+ RoomListParams(tab.displayMode, spaceId, getRoomSortOrder(spaceId)).toMvRxBundle()
} else {
viewPagerDimber.i{"Home pager: paging disabled; position $position -> follow"}
- RoomListParams(tab.displayMode, SPACE_ID_FOLLOW_APP).toMvRxBundle()
+ RoomListParams(tab.displayMode, SPACE_ID_FOLLOW_APP, getRoomSortOrder(SPACE_ID_FOLLOW_APP)).toMvRxBundle()
}
childFragmentManager.fragmentFactory.instantiate(activity!!.classLoader, RoomListFragment::class.java.name).apply {
arguments = params
@@ -753,6 +809,26 @@ class HomeDetailFragment :
return if (position == 0) null else spaces[position-1]
}
+ data class RoomSortOrderSettings(val nullSpace: RoomSortOrder, val space: RoomSortOrder)
+
+ private fun loadRoomSortOrderSettings(): RoomSortOrderSettings? {
+ val sharedPreferences = context?.let { PreferenceManager.getDefaultSharedPreferences(it) } ?: return null
+ val default = RoomSortOrder.ACTIVITY
+ return RoomSortOrderSettings(
+ tryOrNull { sharedPreferences.getString(VectorPreferences.SETTINGS_ROOM_SORT_ORDER_NULL, null)?.let { RoomSortOrder.valueOf(it) } } ?: default,
+ tryOrNull { sharedPreferences.getString(VectorPreferences.SETTINGS_ROOM_SORT_ORDER_NON_NULL, null)?.let { RoomSortOrder.valueOf(it) } } ?: default,
+ )
+ }
+
+ private fun getRoomSortOrder(space: String?): RoomSortOrder {
+ return (
+ if (space == null)
+ roomSortOrderSettings?.nullSpace
+ else
+ roomSortOrderSettings?.space
+ ) ?: RoomSortOrder.ACTIVITY
+ }
+
private fun createDialPadFragment(): Fragment {
val fragment = childFragmentManager.fragmentFactory.instantiate(vectorBaseActivity.classLoader, DialPadFragment::class.java.name)
return (fragment as DialPadFragment).apply {
diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
index fe3e3c2af8..caee2102d8 100644
--- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
@@ -123,6 +123,7 @@ class NewHomeDetailFragment :
val isRoomList = state.currentTab is HomeTab.RoomList
menu.findItem(R.id.menu_home_mark_all_as_read).isVisible = isRoomList && hasUnreadRooms
menu.findItem(R.id.menu_home_dialpad).isVisible = state.showDialPadTab
+ menu.findItem(R.id.menu_room_sort_order).isVisible = false
}
}
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 805e6c79de..6d82da7577 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
@@ -68,6 +68,8 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.extensions.orTrue
+import org.matrix.android.sdk.api.extensions.tryOrNull
+import org.matrix.android.sdk.api.session.room.RoomSortOrder
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
@@ -77,7 +79,8 @@ import javax.inject.Inject
@Parcelize
data class RoomListParams(
val displayMode: RoomListDisplayMode,
- val explicitSpaceId: String? = SPACE_ID_FOLLOW_APP
+ val explicitSpaceId: String? = SPACE_ID_FOLLOW_APP,
+ val roomSortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY
) : Parcelable
@AndroidEntryPoint
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt
index 3f15eeb8c0..7ff7012361 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt
@@ -51,6 +51,7 @@ import org.matrix.android.sdk.api.query.toActiveSpaceOrNoFilter
import org.matrix.android.sdk.api.query.toActiveSpaceOrOrphanRooms
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.getRoomSummary
+import org.matrix.android.sdk.api.session.room.RoomSortOrder
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
@@ -82,28 +83,28 @@ class RoomListSectionBuilder(
private val dimber = Dimber("ViewPager", DbgUtil.DBG_VIEW_PAGER)
- fun buildSections(mode: RoomListDisplayMode, explicitSpaceId: String?): List {
+ fun buildSections(mode: RoomListDisplayMode, explicitSpaceId: String?, sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): List {
dimber.i { "Build sections for $mode, $explicitSpaceId" }
val sections = mutableListOf()
val activeSpaceAwareQueries = mutableListOf()
when (mode) {
RoomListDisplayMode.PEOPLE -> {
// 4 sections Invites / Fav / Dms / Low Priority
- buildDmSections(sections, activeSpaceAwareQueries, explicitSpaceId)
+ buildDmSections(sections, activeSpaceAwareQueries, explicitSpaceId, sortOrder)
}
RoomListDisplayMode.ROOMS -> {
// 6 sections invites / Fav / Rooms / Low Priority / Server notice / Suggested rooms
- buildRoomsSections(sections, activeSpaceAwareQueries, explicitSpaceId)
+ buildRoomsSections(sections, activeSpaceAwareQueries, explicitSpaceId, sortOrder)
}
RoomListDisplayMode.ALL -> {
- buildUnifiedSections(sections, activeSpaceAwareQueries, explicitSpaceId)
+ buildUnifiedSections(sections, activeSpaceAwareQueries, explicitSpaceId, sortOrder)
}
RoomListDisplayMode.FILTERED -> {
// Used when searching for rooms
buildFilteredSection(sections)
}
RoomListDisplayMode.NOTIFICATIONS -> {
- buildNotificationsSection(sections, activeSpaceAwareQueries, explicitSpaceId)
+ buildNotificationsSection(sections, activeSpaceAwareQueries, explicitSpaceId, sortOrder)
}
}
@@ -125,13 +126,14 @@ class RoomListSectionBuilder(
return sections
}
- private fun buildUnifiedSections(sections: MutableList, activeSpaceAwareQueries: MutableList, explicitSpaceId: String?) {
+ private fun buildUnifiedSections(sections: MutableList, activeSpaceAwareQueries: MutableList, explicitSpaceId: String?, sortOrder: RoomSortOrder) {
addSection(
sections = sections,
activeSpaceUpdaters = activeSpaceAwareQueries,
nameRes = R.string.invitations_header,
notifyOfLocalEcho = true,
explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder,
spaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL,
countRoomAsNotif = true
) {
@@ -149,6 +151,7 @@ class RoomListSectionBuilder(
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL
},
explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder
) {
it.memberships = listOf(Membership.JOIN)
it.roomTagQueryFilter = RoomTagQueryFilter(true, null, null)
@@ -160,6 +163,7 @@ class RoomListSectionBuilder(
nameRes = R.string.normal_priority_header,
notifyOfLocalEcho = false,
explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
@@ -176,6 +180,7 @@ class RoomListSectionBuilder(
nameRes = R.string.low_priority_header,
notifyOfLocalEcho = false,
explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
@@ -192,6 +197,7 @@ class RoomListSectionBuilder(
nameRes = R.string.system_alerts_header,
notifyOfLocalEcho = false,
explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
@@ -208,7 +214,8 @@ class RoomListSectionBuilder(
private fun buildRoomsSections(
sections: MutableList,
activeSpaceAwareQueries: MutableList,
- explicitSpaceId: String?
+ explicitSpaceId: String?,
+ sortOrder: RoomSortOrder
) {
if (autoAcceptInvites.showInvites()) {
addSection(
@@ -217,6 +224,7 @@ class RoomListSectionBuilder(
nameRes = R.string.invitations_header,
notifyOfLocalEcho = true,
explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder,
spaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL,
countRoomAsNotif = true
) {
@@ -236,6 +244,7 @@ class RoomListSectionBuilder(
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL
},
explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder
) {
it.memberships = listOf(Membership.JOIN)
it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS
@@ -248,6 +257,7 @@ class RoomListSectionBuilder(
nameRes = R.string.bottom_action_rooms,
notifyOfLocalEcho = false,
explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
@@ -265,6 +275,7 @@ class RoomListSectionBuilder(
nameRes = R.string.low_priority_header,
notifyOfLocalEcho = false,
explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
@@ -282,6 +293,7 @@ class RoomListSectionBuilder(
nameRes = R.string.system_alerts_header,
notifyOfLocalEcho = false,
explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
@@ -366,7 +378,8 @@ class RoomListSectionBuilder(
private fun buildDmSections(
sections: MutableList,
activeSpaceAwareQueries: MutableList,
- explicitSpaceId: String?
+ explicitSpaceId: String?,
+ sortOrder: RoomSortOrder
) {
if (autoAcceptInvites.showInvites()) {
addSection(
@@ -375,6 +388,7 @@ class RoomListSectionBuilder(
nameRes = R.string.invitations_header,
notifyOfLocalEcho = true,
explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
@@ -397,7 +411,8 @@ class RoomListSectionBuilder(
} else {
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL
},
- explicitSpaceId = explicitSpaceId
+ explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder
) {
it.memberships = listOf(Membership.JOIN)
it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM
@@ -414,7 +429,8 @@ class RoomListSectionBuilder(
} else {
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL
},
- explicitSpaceId = explicitSpaceId
+ explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder
) {
it.memberships = listOf(Membership.JOIN)
it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM
@@ -431,7 +447,8 @@ class RoomListSectionBuilder(
} else {
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL
},
- explicitSpaceId = explicitSpaceId
+ explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder
) {
it.memberships = listOf(Membership.JOIN)
it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM
@@ -451,7 +468,8 @@ class RoomListSectionBuilder(
private fun buildNotificationsSection(
sections: MutableList,
activeSpaceAwareQueries: MutableList,
- explicitSpaceId: String?
+ explicitSpaceId: String?,
+ sortOrder: RoomSortOrder
) {
if (autoAcceptInvites.showInvites()) {
addSection(
@@ -460,6 +478,7 @@ class RoomListSectionBuilder(
nameRes = R.string.invitations_header,
notifyOfLocalEcho = true,
explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
@@ -477,6 +496,7 @@ class RoomListSectionBuilder(
nameRes = R.string.bottom_action_rooms,
notifyOfLocalEcho = false,
explicitSpaceId = explicitSpaceId,
+ sortOrder = sortOrder,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
@@ -522,6 +542,7 @@ class RoomListSectionBuilder(
spaceFilterStrategy: RoomListViewModel.SpaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.NONE,
countRoomAsNotif: Boolean = false,
explicitSpaceId: String?,
+ sortOrder: RoomSortOrder,
query: (RoomSummaryQueryParams.Builder) -> Unit
) {
withQueryParams(query) { roomQueryParams ->
@@ -537,7 +558,8 @@ class RoomListSectionBuilder(
val name = stringProvider.getString(nameRes)
val filteredPagedRoomSummariesLive = session.roomService().getFilteredPagedRoomSummariesLive(
roomQueryParams.process(spaceFilterStrategy, spaceStateHandler.explicitOrSafeActiveSpaceId(explicitSpaceId)),
- pagedListConfig
+ pagedListConfig,
+ sortOrder
)
when (spaceFilterStrategy) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL -> {
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 0d5837bfb4..97e4b57ca3 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
@@ -47,6 +47,7 @@ import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.getRoomSummary
+import org.matrix.android.sdk.api.session.room.RoomSortOrder
import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho
@@ -152,8 +153,8 @@ class RoomListViewModel @AssistedInject constructor(
)
val sections: List by lazy {
- viewPagerDimber.i { "Build sections for ${initialState.displayMode}, ${initialState.explicitSpaceId}" }
- roomListSectionBuilder.buildSections(initialState.displayMode, initialState.explicitSpaceId)
+ viewPagerDimber.i { "Build sections for ${initialState.displayMode}, ${initialState.explicitSpaceId} ${initialState.roomSortOrder}" }
+ roomListSectionBuilder.buildSections(initialState.displayMode, initialState.explicitSpaceId, initialState.roomSortOrder)
}
override fun handle(action: RoomListAction) {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewState.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewState.kt
index f9e8887b2b..615d729fd9 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewState.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewState.kt
@@ -20,6 +20,7 @@ import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.Uninitialized
import im.vector.app.features.home.RoomListDisplayMode
+import org.matrix.android.sdk.api.session.room.RoomSortOrder
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
@@ -32,8 +33,9 @@ data class RoomListViewState(
val currentUserName: String? = null,
val asyncSelectedSpace: Async = Uninitialized,
// In comparison to currentRoomGrouping, the explicit space id fixes a filter method that should not change afterwards
- val explicitSpaceId: String? = null
+ val explicitSpaceId: String? = null,
+ val roomSortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY,
) : MavericksState {
- constructor(args: RoomListParams) : this(displayMode = args.displayMode, explicitSpaceId = args.explicitSpaceId)
+ constructor(args: RoomListParams) : this(displayMode = args.displayMode, explicitSpaceId = args.explicitSpaceId, roomSortOrder = args.roomSortOrder)
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt
index d7586e19e0..196dbeda0d 100755
--- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt
@@ -248,6 +248,8 @@ class VectorPreferences @Inject constructor(
private const val SETTINGS_SPACE_BACK_NAVIGATION = "SETTINGS_SPACE_BACK_NAVIGATION"
const val SETTINGS_FOLLOW_SYSTEM_LOCALE = "SETTINGS_FOLLOW_SYSTEM_LOCALE"
const val SETTINGS_FORCE_ALLOW_BACKGROUND_SYNC = "SETTINGS_FORCE_ALLOW_BACKGROUND_SYNC"
+ const val SETTINGS_ROOM_SORT_ORDER_NULL = "SETTINGS_ROOM_SORT_ORDER_NULL"
+ const val SETTINGS_ROOM_SORT_ORDER_NON_NULL = "SETTINGS_ROOM_SORT_ORDER_NON_NULL"
private const val DID_ASK_TO_ENABLE_SESSION_PUSH = "DID_ASK_TO_ENABLE_SESSION_PUSH"
diff --git a/vector/src/main/res/menu/room_list.xml b/vector/src/main/res/menu/room_list.xml
index ad375d241b..e3868e5dec 100644
--- a/vector/src/main/res/menu/room_list.xml
+++ b/vector/src/main/res/menu/room_list.xml
@@ -14,4 +14,21 @@
android:visible="false"
app:showAsAction="never"
tools:visible="true" />
+
+ -
+
+