Skip to content

Commit 0629cae

Browse files
authored
added dialog to change app layout settings (#6840)
1 parent 11b4ea5 commit 0629cae

12 files changed

+314
-37
lines changed

changelog.d/6506.wip

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[App Layout] added dialog to configure app layout

vector/src/main/java/im/vector/app/features/home/HomeActivity.kt

+10
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import im.vector.app.features.analytics.plan.MobileScreen
5656
import im.vector.app.features.analytics.plan.ViewRoom
5757
import im.vector.app.features.crypto.recover.SetupMode
5858
import im.vector.app.features.disclaimer.showDisclaimerDialog
59+
import im.vector.app.features.home.room.list.home.layout.HomeLayoutSettingBottomDialogFragment
5960
import im.vector.app.features.matrixto.MatrixToBottomSheet
6061
import im.vector.app.features.matrixto.OriginOfMatrixTo
6162
import im.vector.app.features.navigation.Navigator
@@ -283,6 +284,11 @@ class HomeActivity :
283284
.show(supportFragmentManager, "SPACE_SETTINGS")
284285
}
285286

287+
private fun showLayoutSettings() {
288+
HomeLayoutSettingBottomDialogFragment()
289+
.show(supportFragmentManager, "LAYOUT_SETTINGS")
290+
}
291+
286292
private fun openSpaceInvite(spaceId: String) {
287293
SpaceInviteBottomSheet.newInstance(spaceId)
288294
.show(supportFragmentManager, "SPACE_INVITE")
@@ -596,6 +602,10 @@ class HomeActivity :
596602
navigator.openSettings(this)
597603
true
598604
}
605+
R.id.menu_home_layout_settings -> {
606+
showLayoutSettings()
607+
true
608+
}
599609
R.id.menu_home_invite_friends -> {
600610
launchInviteFriends()
601611
true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) 2022 New Vector Ltd
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package im.vector.app.features.home.room.list.home
18+
19+
import android.content.Context
20+
import androidx.datastore.core.DataStore
21+
import androidx.datastore.preferences.core.Preferences
22+
import androidx.datastore.preferences.core.booleanPreferencesKey
23+
import androidx.datastore.preferences.core.edit
24+
import androidx.datastore.preferences.preferencesDataStore
25+
import kotlinx.coroutines.flow.Flow
26+
import kotlinx.coroutines.flow.distinctUntilChanged
27+
import kotlinx.coroutines.flow.map
28+
import org.matrix.android.sdk.api.extensions.orFalse
29+
import javax.inject.Inject
30+
31+
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "layout_preferences")
32+
33+
class HomeLayoutPreferencesStore @Inject constructor(
34+
private val context: Context
35+
) {
36+
37+
private val areRecentsEnbabled = booleanPreferencesKey("SETTINGS_PREFERENCES_HOME_RECENTS")
38+
private val areFiltersEnabled = booleanPreferencesKey("SETTINGS_PREFERENCES_HOME_FILTERS")
39+
private val isAZOrderingEnabled = booleanPreferencesKey("SETTINGS_PREFERENCES_USE_AZ_ORDER")
40+
41+
val areRecentsEnabledFlow: Flow<Boolean> = context.dataStore.data
42+
.map { preferences -> preferences[areRecentsEnbabled].orFalse() }
43+
.distinctUntilChanged()
44+
45+
val areFiltersEnabledFlow: Flow<Boolean> = context.dataStore.data
46+
.map { preferences -> preferences[areFiltersEnabled].orFalse() }
47+
.distinctUntilChanged()
48+
49+
val isAZOrderingEnabledFlow: Flow<Boolean> = context.dataStore.data
50+
.map { preferences -> preferences[isAZOrderingEnabled].orFalse() }
51+
.distinctUntilChanged()
52+
53+
suspend fun setRecentsEnabled(isEnabled: Boolean) {
54+
context.dataStore.edit { settings ->
55+
settings[areRecentsEnbabled] = isEnabled
56+
}
57+
}
58+
59+
suspend fun setFiltersEnabled(isEnabled: Boolean) {
60+
context.dataStore.edit { settings ->
61+
settings[areFiltersEnabled] = isEnabled
62+
}
63+
}
64+
65+
suspend fun setAZOrderingEnabled(isEnabled: Boolean) {
66+
context.dataStore.edit { settings ->
67+
settings[isAZOrderingEnabled] = isEnabled
68+
}
69+
}
70+
}

vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt

+13-2
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,15 @@ class HomeRoomListFragment @Inject constructor(
162162
}.launchIn(lifecycleScope)
163163

164164
views.roomListView.adapter = concatAdapter
165+
166+
// we need to force scroll when recents/filter tabs are added to make them visible
167+
concatAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
168+
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
169+
if (positionStart == 0) {
170+
layoutManager.scrollToPosition(0)
171+
}
172+
}
173+
})
165174
}
166175

167176
private fun setupFabs() {
@@ -205,6 +214,9 @@ class HomeRoomListFragment @Inject constructor(
205214
}
206215

207216
private fun setUpAdapters(sections: Set<HomeRoomSection>) {
217+
concatAdapter.adapters.forEach {
218+
concatAdapter.removeAdapter(it)
219+
}
208220
sections.forEach {
209221
concatAdapter.addAdapter(getAdapterForData(it))
210222
}
@@ -234,12 +246,11 @@ class HomeRoomListFragment @Inject constructor(
234246
is HomeRoomSection.RoomSummaryData -> {
235247
HomeFilteredRoomsController(
236248
roomSummaryItemFactory,
237-
showFilters = section.showFilters,
238249
).also { controller ->
239250
controller.listener = this
240251
controller.onFilterChanged = ::onRoomFilterChanged
241252
section.filtersData.onEach {
242-
controller.submitFiltersData(it)
253+
controller.submitFiltersData(it.getOrNull())
243254
}.launchIn(lifecycleScope)
244255
section.list.observe(viewLifecycleOwner) { list ->
245256
controller.submitList(list)

vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListViewModel.kt

+50-28
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import kotlinx.coroutines.flow.SharedFlow
3434
import kotlinx.coroutines.flow.asSharedFlow
3535
import kotlinx.coroutines.flow.combine
3636
import kotlinx.coroutines.flow.distinctUntilChanged
37+
import kotlinx.coroutines.flow.first
3738
import kotlinx.coroutines.flow.launchIn
3839
import kotlinx.coroutines.flow.map
3940
import kotlinx.coroutines.flow.onEach
@@ -53,12 +54,14 @@ import org.matrix.android.sdk.api.session.room.model.Membership
5354
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
5455
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
5556
import org.matrix.android.sdk.api.session.room.state.isPublic
57+
import org.matrix.android.sdk.api.util.Optional
5658
import org.matrix.android.sdk.flow.flow
5759

5860
class HomeRoomListViewModel @AssistedInject constructor(
5961
@Assisted initialState: HomeRoomListViewState,
6062
private val session: Session,
6163
private val spaceStateHandler: SpaceStateHandler,
64+
private val preferencesStore: HomeLayoutPreferencesStore,
6265
) : VectorViewModel<HomeRoomListViewState, HomeRoomListAction, HomeRoomListViewEvents>(initialState) {
6366

6467
@AssistedFactory
@@ -82,17 +85,30 @@ class HomeRoomListViewModel @AssistedInject constructor(
8285

8386
init {
8487
configureSections()
88+
observePreferences()
8589
}
8690

87-
private fun configureSections() {
91+
private fun observePreferences() {
92+
preferencesStore.areRecentsEnabledFlow.onEach {
93+
configureSections()
94+
}.launchIn(viewModelScope)
95+
96+
preferencesStore.isAZOrderingEnabledFlow.onEach {
97+
configureSections()
98+
}.launchIn(viewModelScope)
99+
}
100+
101+
private fun configureSections() = viewModelScope.launch {
88102
val newSections = mutableSetOf<HomeRoomSection>()
89103

90-
newSections.add(getRecentRoomsSection())
91-
newSections.add(getFilteredRoomsSection())
104+
val areSettingsEnabled = preferencesStore.areRecentsEnabledFlow.first()
92105

93-
viewModelScope.launch {
94-
_sections.emit(newSections)
106+
if (areSettingsEnabled) {
107+
newSections.add(getRecentRoomsSection())
95108
}
109+
newSections.add(getFilteredRoomsSection())
110+
111+
_sections.emit(newSections)
96112

97113
setState {
98114
copy(state = StateView.State.Content)
@@ -111,13 +127,17 @@ class HomeRoomListViewModel @AssistedInject constructor(
111127
)
112128
}
113129

114-
private fun getFilteredRoomsSection(): HomeRoomSection.RoomSummaryData {
130+
private suspend fun getFilteredRoomsSection(): HomeRoomSection.RoomSummaryData {
115131
val builder = RoomSummaryQueryParams.Builder().also {
116132
it.memberships = listOf(Membership.JOIN)
117133
}
118134

119135
val params = getFilteredQueryParams(HomeRoomFilter.ALL, builder.build())
120-
val sortOrder = RoomSortOrder.ACTIVITY // #6506
136+
val sortOrder = if (preferencesStore.isAZOrderingEnabledFlow.first()) {
137+
RoomSortOrder.NAME
138+
} else {
139+
RoomSortOrder.ACTIVITY
140+
}
121141

122142
val liveResults = session.roomService().getFilteredPagedRoomSummariesLive(
123143
params,
@@ -135,19 +155,18 @@ class HomeRoomListViewModel @AssistedInject constructor(
135155
.onEach { selectedSpaceOption ->
136156
val selectedSpace = selectedSpaceOption.orNull()
137157
liveResults.queryParams = liveResults.queryParams.copy(
138-
spaceFilter = selectedSpace?.roomId.toActiveSpaceOrNoFilter()
158+
spaceFilter = selectedSpace?.roomId.toActiveSpaceOrNoFilter()
139159
)
140160
}.launchIn(viewModelScope)
141161

142162
return HomeRoomSection.RoomSummaryData(
143163
list = liveResults.livePagedList,
144-
showFilters = true, // #6506
145164
filtersData = getFiltersDataFlow()
146165
)
147166
}
148167

149-
private fun getFiltersDataFlow(): SharedFlow<List<HomeRoomFilter>> {
150-
val flow = MutableSharedFlow<List<HomeRoomFilter>>(replay = 1)
168+
private fun getFiltersDataFlow(): SharedFlow<Optional<List<HomeRoomFilter>>> {
169+
val flow = MutableSharedFlow<Optional<List<HomeRoomFilter>>>(replay = 1)
151170

152171
val favouritesFlow = session.flow()
153172
.liveRoomSummaries(
@@ -168,25 +187,28 @@ class HomeRoomListViewModel @AssistedInject constructor(
168187
.map { it.isNotEmpty() }
169188
.distinctUntilChanged()
170189

171-
favouritesFlow.combine(dmsFLow) { hasFavourite, hasDm ->
172-
hasFavourite to hasDm
173-
}.onEach { (hasFavourite, hasDm) ->
174-
val filtersData = mutableListOf(
175-
HomeRoomFilter.ALL,
176-
HomeRoomFilter.UNREADS
177-
)
178-
if (hasFavourite) {
179-
filtersData.add(
180-
HomeRoomFilter.FAVOURITES
181-
)
182-
}
183-
if (hasDm) {
184-
filtersData.add(
185-
HomeRoomFilter.PEOPlE
190+
combine(favouritesFlow, dmsFLow, preferencesStore.areFiltersEnabledFlow) { hasFavourite, hasDm, areFiltersEnabled ->
191+
Triple(hasFavourite, hasDm, areFiltersEnabled)
192+
}.onEach { (hasFavourite, hasDm, areFiltersEnabled) ->
193+
if (areFiltersEnabled) {
194+
val filtersData = mutableListOf(
195+
HomeRoomFilter.ALL,
196+
HomeRoomFilter.UNREADS
186197
)
198+
if (hasFavourite) {
199+
filtersData.add(
200+
HomeRoomFilter.FAVOURITES
201+
)
202+
}
203+
if (hasDm) {
204+
filtersData.add(
205+
HomeRoomFilter.PEOPlE
206+
)
207+
}
208+
flow.emit(Optional.from(filtersData))
209+
} else {
210+
flow.emit(Optional.empty())
187211
}
188-
189-
flow.emit(filtersData)
190212
}.launchIn(viewModelScope)
191213

192214
return flow

vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomSection.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ import androidx.paging.PagedList
2121
import im.vector.app.features.home.room.list.home.filter.HomeRoomFilter
2222
import kotlinx.coroutines.flow.SharedFlow
2323
import org.matrix.android.sdk.api.session.room.model.RoomSummary
24+
import org.matrix.android.sdk.api.util.Optional
2425

2526
sealed class HomeRoomSection {
2627
data class RoomSummaryData(
2728
val list: LiveData<PagedList<RoomSummary>>,
28-
val showFilters: Boolean,
29-
val filtersData: SharedFlow<List<HomeRoomFilter>>
29+
val filtersData: SharedFlow<Optional<List<HomeRoomFilter>>>,
3030
) : HomeRoomSection()
3131

3232
data class RecentRoomsData(

vector/src/main/java/im/vector/app/features/home/room/list/home/filter/HomeFilteredRoomsController.kt

+2-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import org.matrix.android.sdk.api.session.room.model.RoomSummary
2828

2929
class HomeFilteredRoomsController(
3030
private val roomSummaryItemFactory: RoomSummaryItemFactory,
31-
private val showFilters: Boolean,
3231
) : PagedListEpoxyController<RoomSummary>(
3332
// Important it must match the PageList builder notify Looper
3433
modelBuildingHandler = createUIHandler()
@@ -48,7 +47,7 @@ class HomeFilteredRoomsController(
4847

4948
override fun addModels(models: List<EpoxyModel<*>>) {
5049
val host = this
51-
if (showFilters) {
50+
if (host.filtersData != null) {
5251
roomFilterHeaderItem {
5352
id("filter_header")
5453
filtersData(host.filtersData)
@@ -58,7 +57,7 @@ class HomeFilteredRoomsController(
5857
super.addModels(models)
5958
}
6059

61-
fun submitFiltersData(data: List<HomeRoomFilter>) {
60+
fun submitFiltersData(data: List<HomeRoomFilter>?) {
6261
this.filtersData = data
6362
requestForcedModelBuild()
6463
}

0 commit comments

Comments
 (0)