Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added dialog to change app layout settings #6840

Merged
merged 4 commits into from
Aug 19, 2022

Conversation

fedrunov
Copy link
Contributor

Type of change

  • Feature
  • Bugfix
  • Technical
  • Other :

Content

adds a bottom sheet dialog with app layout settings

Motivation and context

part of #6502
closes #6506

Screenshots / GIFs

Light Dark Black
light dark black

Tests

  • open home
  • open context menu (3 dots in top right corner)
  • select "layout preferences"
  • change preferences

Tested devices

  • Physical
  • Emulator
  • OS version(s): 11

@fedrunov fedrunov requested review from a team, onurays, ericdecanini and amshakal and removed request for a team August 16, 2022 08:58
Copy link
Contributor

@ericdecanini ericdecanini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation looks good, but there are some code improvements I would strongly suggest

@@ -0,0 +1 @@
[App Layout] added dialog to configure app layout
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea using [App Layout]. I'll start doing this too

Comment on lines 28 to 32
companion object {
const val SETTINGS_PREFERENCES_HOME_RECENTS = "SETTINGS_PREFERENCES_HOME_RECENTS"
const val SETTINGS_PREFERENCES_HOME_FILTERS = "SETTINGS_PREFERENCES_HOME_FILTERS"
const val SETTINGS_PREFERENCES_USE_AZ_ORDER = "SETTINGS_PREFERENCES_USE_AZ_ORDER"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: Kotlin code style guidelines suggest that companion objects should be at the bottom of the class rather than the top

Comment on lines 49 to 51
fun areFiltersEnabled(): Boolean {
return preferences.getBoolean(SETTINGS_PREFERENCES_HOME_FILTERS, false)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: Many of these functions are single liners, maybe it's better to use this syntax:

Suggested change
fun areFiltersEnabled(): Boolean {
return preferences.getBoolean(SETTINGS_PREFERENCES_HOME_FILTERS, false)
}
fun areFiltersEnabled() = preferences.getBoolean(SETTINGS_PREFERENCES_HOME_FILTERS, false)

Comment on lines 205 to 209
favouritesFlow
.combine(dmsFLow) { hasFavourite, hasDm ->
hasFavourite to hasDm
}.combine(filtersPreferencesFlow) { (hasFavourite, hasDm), areFiltersEnabled ->
Triple(hasFavourite, hasDm, areFiltersEnabled)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use combine without any prefix to combine three flows in one go
https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/combine.html

Suggested change
favouritesFlow
.combine(dmsFLow) { hasFavourite, hasDm ->
hasFavourite to hasDm
}.combine(filtersPreferencesFlow) { (hasFavourite, hasDm), areFiltersEnabled ->
Triple(hasFavourite, hasDm, areFiltersEnabled)
combine(favouritesFlow, dmsFlow, filteresPreferencesFlow) { hasFavourite, hasDm, areFiltersEnabled ->
Triple(hasFavourite, hasDm, areFiltersEnabled)

Also note capitalisation on dmsFLow

}

views.homeLayoutSettingsRecents.setOnCheckedChangeListener { _, isChecked ->
preferences.setRecentsEnabled(isChecked)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we shouldn't change preferences before the user clicks to "Done" button. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@amshakal could you please verify?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I believe no changes should be made before the user hits 'DONE'

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is strange to me to have a "DONE" button on a BottomSheet. I would prefer to have the change effect live and visible to the background. For instance when disabling "Show recents", the user will have a direct feedback by seeing the breadcrumbs row vanish in the background. They can even play with the toggle several times. Since it's easy to revert the change, I would simply remove the DONE button. Else what would be done if the user dismiss the bottom sheet without clicking on DONE? Cancel the pending change? Not a good UX to me.

On Android settings and in app settings (preference screen), there is no DONE button, any changes are immediately taking effect. Better to do the same here IMHO.

CC @amshakal

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes are applied when user press DONE, so if user closes dialog in any other way this changes will just be lost. I don't have any strong opinion on this topic. I just felt that seeing changes in ui, while you switch options, feels more interactive, and since here it came with zero costs I decided to implement that way.

TLDR; Both options are good for me and there are no technical issues with both of them, so I let Amsha decide :)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we don't have done button in settings, we can be a bit more explicit with a bottom sheet. I couldn't find anything for or against it in the material guidelines.

I am open to having interactive options but since there is an overlay at the back anyway, the user won't really be able to see the changes properly.

Let's start with this simple approach and we can iterate on it incase it feels like an odd pattern.

I had a chat with Nikita around this. Benoit, if this feels like a massive blocker/anti pattern. I am more than happy to remove the DONE button.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess users are used to close bottom sheets either by swiping to the bottom or by clicking on the back button.

As a general guidelines, I think that Buttons on BottomSheet are not a good UX pattern. I do not see lots of Button in the example of BottomSheet here and also in all the apps I use on my phone.

I would definitely remove the DONE button.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. In that case Nikita, let's go with benoit's suggestion of removing the CTA. Sorry about the back and forth

Copy link
Contributor

@onurays onurays left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Can you please check my small remarks?

@@ -27,8 +27,7 @@ import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
import org.matrix.android.sdk.api.session.room.model.RoomSummary

class HomeFilteredRoomsController(
private val roomSummaryItemFactory: RoomSummaryItemFactory,
private val showFilters: Boolean,
private val roomSummaryItemFactory: RoomSummaryItemFactory
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add comma (,) at the end.


sealed class HomeRoomSection {
data class RoomSummaryData(
val list: LiveData<PagedList<RoomSummary>>,
val showFilters: Boolean,
val filtersData: SharedFlow<List<HomeRoomFilter>>
val filtersData: SharedFlow<Optional<List<HomeRoomFilter>>>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add comma (,) at the end.

private fun observePreferences() {
preferences.registerFiltersListener { areFiltersEnabled ->
viewModelScope.launch {
filtersPreferencesFlow.emit(areFiltersEnabled)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this triggering immediately right after you register the listener? If so, we don't need the below lines.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason it doesn't. If I remove that emit, it will not show filters until you change setting

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> DataStore :)

Copy link
Contributor

@onurays onurays left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update!

import im.vector.app.core.di.DefaultPreferences
import javax.inject.Inject

class HomeLayoutPreferences @Inject constructor(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be easier to use a DataStore rather than SharedPreferences. See VectorSessionStore or AnalyticsStore for some example.

@AndroidEntryPoint
class HomeLayoutSettingBottomDialogFragment : VectorBaseBottomSheetDialogFragment<BottomSheetHomeLayoutSettingsBinding>() {

@Inject lateinit var preferences: HomeLayoutPreferences
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be moved to a ViewModel, and the UI should be updated in the invalidate method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure we'll benefit from VM here. This dialog is too small and too specific to make it's part reusable and too simple to require separation of concerns. Having VM here will just increase amount of boilerplate and make it less easy to understand. We also have plenty of other dialogs without VMs and I did think it's because of reasons above. Did we change approach and now require to follow same pattern no matter of what?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it's a bit more boilerplate code, but the idea is to have the logic in the ViewModel also to unit test it. Views (Fragment, etc.) should only be responsible of displaying things.
I guess for this particular part it can stay like that. Maybe better to spend effort to use DataStore.

Copy link
Member

@bmarty bmarty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have made some more remarks, on the UX and on the impl.

@fedrunov fedrunov requested a review from bmarty August 18, 2022 11:54
android:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?colorSurface"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ⚠️ Possible overdraw: Root element paints background ?colorSurface with a theme that also paints a background (inferred theme is @style/Theme.Vector.Light)
  • ⚠️ Possible overdraw: Root element paints background ?colorSurface with a theme that also paints a background (inferred theme is @style/Theme.Vector.Light)

@sonarqubecloud
Copy link

SonarCloud Quality Gate failed.    Quality Gate failed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

0.0% 0.0% Coverage
0.0% 0.0% Duplication

Copy link
Member

@bmarty bmarty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update!

@fedrunov fedrunov merged commit 0629cae into develop Aug 19, 2022
@fedrunov fedrunov deleted the feature/nfe/edit_layout_config branch August 19, 2022 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

App Layout: layout settings screen
6 participants