Merge pull request #2907 from vitorpamplona/claude/improve-compose-settings-NKNWr

Refactor ComposeSettingsScreen to use unified tile components
This commit is contained in:
Vitor Pamplona
2026-05-14 20:05:38 -04:00
committed by GitHub
@@ -20,8 +20,9 @@
*/ */
package com.vitorpamplona.amethyst.ui.screen.loggedIn.settings package com.vitorpamplona.amethyst.ui.screen.loggedIn.settings
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
@@ -30,11 +31,13 @@ import androidx.compose.material3.Switch
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.model.BooleanType import com.vitorpamplona.amethyst.model.BooleanType
import com.vitorpamplona.amethyst.model.UiSettingsFlow import com.vitorpamplona.amethyst.model.UiSettingsFlow
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
@@ -42,10 +45,7 @@ import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.RowColSpacing import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
import com.vitorpamplona.amethyst.ui.theme.Size10dp
import com.vitorpamplona.amethyst.ui.theme.Size20dp
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonRow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@Composable @Composable
@@ -57,18 +57,12 @@ fun ComposeSettingsScreen(
topBar = { topBar = {
TopBarWithBackButton(stringRes(id = R.string.compose_settings), nav) TopBarWithBackButton(stringRes(id = R.string.compose_settings), nav)
}, },
) { ) { padding ->
Column(Modifier.padding(it)) { ComposeSettingsContent(
ComposeSettingsContent(accountViewModel.settings.uiSettingsFlow, accountViewModel) sharedPrefs = accountViewModel.settings.uiSettingsFlow,
} accountViewModel = accountViewModel,
} modifier = Modifier.padding(padding),
} )
@Preview(device = "spec:width=2160px,height=2340px,dpi=440")
@Composable
fun ComposeSettingsScreenPreview() {
ThemeComparisonRow {
ComposeSettingsContent(UiSettingsFlow(), mockAccountViewModel())
} }
} }
@@ -76,65 +70,99 @@ fun ComposeSettingsScreenPreview() {
fun ComposeSettingsContent( fun ComposeSettingsContent(
sharedPrefs: UiSettingsFlow, sharedPrefs: UiSettingsFlow,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
modifier: Modifier = Modifier,
) { ) {
Column( Column(
Modifier modifier =
.fillMaxSize() modifier
.padding(top = Size10dp, start = Size20dp, end = Size20dp) .verticalScroll(rememberScrollState())
.verticalScroll(rememberScrollState()), .padding(horizontal = 16.dp, vertical = 12.dp),
horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(20.dp),
verticalArrangement = RowColSpacing,
) { ) {
BooleanSwitchRow( SettingsSection(R.string.compose_settings) {
sharedPrefs.automaticallyCreateDrafts, BooleanSwitchTile(
R.string.auto_create_drafts_setting_title, flow = sharedPrefs.automaticallyCreateDrafts,
R.string.auto_create_drafts_setting_description, icon = MaterialSymbols.Drafts,
) title = R.string.auto_create_drafts_setting_title,
BooleanSwitchRow( description = R.string.auto_create_drafts_setting_description,
sharedPrefs.automaticallyProposeAiImprovements, )
R.string.ai_writing_setting_title, SettingsDivider()
R.string.ai_writing_setting_description, BooleanSwitchTile(
) flow = sharedPrefs.automaticallyProposeAiImprovements,
BooleanSwitchRow( icon = MaterialSymbols.AutoAwesome,
sharedPrefs.useTrackedBroadcasts, title = R.string.ai_writing_setting_title,
R.string.tracked_broadcasts_setting_title, description = R.string.ai_writing_setting_description,
R.string.tracked_broadcasts_setting_description, )
) SettingsDivider()
AddClientTagRow(accountViewModel) BooleanSwitchTile(
flow = sharedPrefs.useTrackedBroadcasts,
icon = MaterialSymbols.CellTower,
title = R.string.tracked_broadcasts_setting_title,
description = R.string.tracked_broadcasts_setting_description,
)
SettingsDivider()
AddClientTagTile(accountViewModel)
}
} }
} }
@Composable @Composable
private fun AddClientTagRow(accountViewModel: AccountViewModel) { private fun AddClientTagTile(accountViewModel: AccountViewModel) {
val addClientTag by accountViewModel.account.settings.syncedSettings.security val addClientTag by accountViewModel.account.settings.syncedSettings.security
.addClientTag .addClientTag
.collectAsStateWithLifecycle() .collectAsStateWithLifecycle()
SettingsRow( SwitchTile(
R.string.add_client_tag_title, icon = MaterialSymbols.Code,
R.string.add_client_tag_explainer, title = R.string.add_client_tag_title,
) { description = R.string.add_client_tag_explainer,
Switch( checked = addClientTag,
checked = addClientTag, onCheckedChange = accountViewModel::updateAddClientTag,
onCheckedChange = accountViewModel::updateAddClientTag, )
)
}
} }
@Composable @Composable
private fun BooleanSwitchRow( private fun BooleanSwitchTile(
flow: MutableStateFlow<BooleanType>, flow: MutableStateFlow<BooleanType>,
title: Int, icon: MaterialSymbol,
description: Int, @StringRes title: Int,
@StringRes description: Int,
) { ) {
val value by flow.collectAsState() val value by flow.collectAsState()
SettingsRow(title, description) { SwitchTile(
Switch( icon = icon,
checked = value == BooleanType.ALWAYS, title = title,
onCheckedChange = { isOn -> description = description,
flow.tryEmit(if (isOn) BooleanType.ALWAYS else BooleanType.NEVER) checked = value == BooleanType.ALWAYS,
}, onCheckedChange = { isOn ->
) flow.tryEmit(if (isOn) BooleanType.ALWAYS else BooleanType.NEVER)
},
)
}
@Composable
private fun SwitchTile(
icon: MaterialSymbol,
@StringRes title: Int,
@StringRes description: Int,
checked: Boolean,
onCheckedChange: (Boolean) -> Unit,
) {
SettingsControlRow(
icon = icon,
title = stringRes(title),
description = stringRes(description),
onClick = { onCheckedChange(!checked) },
) {
Switch(checked = checked, onCheckedChange = onCheckedChange)
}
}
@Preview(device = "spec:width=2160px,height=2340px,dpi=440")
@Composable
fun ComposeSettingsScreenPreview() {
ThemeComparisonColumn {
ComposeSettingsContent(UiSettingsFlow(), mockAccountViewModel())
} }
} }