Skip to content

Settings Screen: Java/XML to Kotlin/Compose migration - #56

Open
m4pl wants to merge 18 commits into
GrapheneOS:mainfrom
m4pl:task/41-settings-compose
Open

Settings Screen: Java/XML to Kotlin/Compose migration#56
m4pl wants to merge 18 commits into
GrapheneOS:mainfrom
m4pl:task/41-settings-compose

Conversation

@m4pl

@m4pl m4pl commented Aug 8, 2026

Copy link
Copy Markdown

Closes #41

Screenshots

Before After
Screenshot_20260808_150454 Screenshot_20260808_150312

Video

Screen_recording_20260808_150325.mp4

@m4pl
m4pl requested review from RankoR, inthewaves and sdsantos August 8, 2026 13:08

@sdsantos sdsantos left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

UI things I found:

  1. I never see the snackbar messages after an Import finishes. Is it only broadcasted in special circumstances?

  2. I feel the Settings cells should be lighter and not darker than the background. It helps having a greater contrast with the cell description (onSurfaceVariant). Here's an example from the latest Google Messaging app:

Messaging New Contacts

Their space between cells is also slightly lower (1 vs 2 dp), which I find pleasant. And also the top padding is slightly lower (8 vs 16 dp). But I'm not 100% sure those are improvements to be honest.

@@ -0,0 +1,95 @@
package com.android.contacts.ui.settings.about.ui

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not sure this needs the extra ui package.

),
) {
SettingsCell(
title = stringResource(R.string.about_build_version),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's a new requirement, but I always feel build / version numbers should always be at least selectable, if not copy-able.

Comment on lines +5 to +6
sealed interface Host : SettingsEffect
sealed interface Message : SettingsEffect

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice approach, hadn't seen it before 👍

) { currentRoute ->
when (currentRoute) {
SettingsNavRoute.Main -> {
SettingsMainScreen(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Naming is definitely hard.

SettingsScreen > SettingsContent > SettingsMainScreen feels a bit weird to me, but do we have an alternative name for this parent Screens than hold navigation inside for other screens? Or maybe we call the inner screens Panes like for adaptive layouts?

Comment on lines +151 to +152
displaySettingsRepository.setSortOrder(sortOrder)
refreshState()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This we're writing the Repository ourselves here, we could also make them reactive instead: return a flow, and the flow automatically updates on a set.

@M00NJ

M00NJ commented Aug 11, 2026

Copy link
Copy Markdown

Sorry for barging in here. I'd just like to comment on this, since I noticed similar things while making mockups for #37.

I feel the Settings cells should be lighter and not darker than the background. It helps having a greater contrast with the cell description (onSurfaceVariant). Here's an example from the latest Google Messaging app:

The way it is now is in accordance to the MD3E guidelines. Google themself don't always stick to them however and their implementation is inconsistent across their apps. I'd suggest going with the Material Design guidelines over Google's reference when in question. Apart from that I would argue, that there's more separation and emphasis on each settings item here, giving the screen more structure, compared to Google's implementation. Contrast is still sufficient if you ask me.

Their space between cells is also slightly lower (1 vs 2 dp), which I find pleasant.

I think this might be an optical illusion as a result of the color roles being reversed here.

@sdsantos

Copy link
Copy Markdown
Contributor

Sorry for barging in here. I'd just like to comment on this, since I noticed similar things while making mockups for #37.

I feel the Settings cells should be lighter and not darker than the background. It helps having a greater contrast with the cell description (onSurfaceVariant). Here's an example from the latest Google Messaging app:

The way it is now is in accordance to the MD3E guidelines. Google themself don't always stick to them however and their implementation is inconsistent across their apps. I'd suggest going with the Material Design guidelines over Google's reference when in question. Apart from that I would argue, that there's more separation and emphasis on each settings item here, giving the screen more structure, compared to Google's implementation. Contrast is still sufficient if you ask me.

I feel even the MD3E guidelines has examples with both approaches, that's why I started looking at concrete apps. But you are right that in general the Color guideline is Background (outside) > SurfaceContainer (inside). Maybe I should switch here as well then (#33), since I was matching the Google Contacts app.

But maybe we can tone it down a bit? We're defaulting to surfaceContainerHigh on the cells, when a surfaceContainer would do just fine. I feel we just need the Lows and Highs when we have more hierarchies?

I tested the text color contrast with the accessibility scanner and onSurfaceVariant passes, so I guess although there's less contrast, it's enough as you said.

Their space between cells is also slightly lower (1 vs 2 dp), which I find pleasant.

I think this might be an optical illusion as a result of the color roles being reversed here.

Could be yeah. In the guidelines I only find a mention to a List segment gap of 2dp.

@sdsantos

Copy link
Copy Markdown
Contributor

I also noticed the scroll position it's not kept when returning from AboutScreen to the MainSettingsScreen. Not a big deal, but I sort of expected it.

@M00NJ

M00NJ commented Aug 12, 2026

Copy link
Copy Markdown

I feel even the MD3E guidelines has examples with both approaches, that's why I started looking at concrete apps.

Yes, it seems not completely clear cut. I also looked around for more examples. The new Gallery app for example matches the current state. Interestingly the systems settings match the current behavior in dark mode, but in light mode it's reversed and matches Google Messagings implementation.

But maybe we can tone it down a bit? We're defaulting to surfaceContainerHigh on the cells, when a surfaceContainer would do just fine. I feel we just need the Lows and Highs when we have more hierarchies?

I wouldn't recommend that. There's quite a bit of thought in those color roles and it might not matter for this screen, but if you want to apply this evenly across all screens and apps, you might end up in a situation where these color roles where reserved for other components and on screen and now you'd have to change those components as well to retain a hierarchy. So I think it's better to pick between the default behavior, how it is now and Google Messagings implementation. Neither is a bad choice, though I would personally lean towards the current one.

@m4pl
m4pl force-pushed the task/41-settings-compose branch from 04c125c to 8ba0c2d Compare August 14, 2026 21:08

@RankoR RankoR left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also:

  • AppCompat dialogs crash under Theme.Compose, worth adding <item name="alertDialogTheme">@style/ContactsAlertDialogThemeAppCompat</item> to theme
  • accompanist-drawablepainter and kotlin-parcelize seem to be dead dependencies now
  • lint-baseline.xml references deleted files

private val profile: StateFlow<ProfileData?> = profileRepository.observeProfile()
.stateIn(
scope = viewModelScope,
started = SharingStarted.Eagerly,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe WhileSubscribed(STATE_STOP_TIMEOUT_MILLIS)?

buildVersion = uiState.buildVersion,
onBuildVersionLongClick = { onAction(Action.BuildVersionLongClicked) },
onLicensesClick = { onAction(Action.LicensesClicked) },
onNavigateBack = { route = SettingsNavRoute.Main },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No snackbarHostState here

effectHandler: SettingsEffectHandler,
onNavigateBack: () -> Unit,
modifier: Modifier = Modifier,
screenModel: SettingsScreenModel = viewModel<SettingsViewModel>(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should be hiltViewModel<SettingsViewModel>() I guess

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.

Rewrite settings screen to Compose

4 participants