Improve settings UI

pull/2074/head
feby-saji 1 week ago
parent 4a5becfc88
commit 8d5d9f4af8

@ -28,22 +28,35 @@ import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.RadioButton
import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
@ -55,13 +68,11 @@ import androidx.compose.ui.window.DialogProperties
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
import com.google.protobuf.option
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTextButton
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
import com.google.samples.apps.nowinandroid.core.designsystem.theme.supportsDynamicTheming
import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig
import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig.DARK
import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig.FOLLOW_SYSTEM
import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig.LIGHT
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.ANDROID
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.DEFAULT
@ -70,6 +81,7 @@ import com.google.samples.apps.nowinandroid.feature.settings.impl.R.string
import com.google.samples.apps.nowinandroid.feature.settings.impl.SettingsUiState.Loading
import com.google.samples.apps.nowinandroid.feature.settings.impl.SettingsUiState.Success
@Composable
fun SettingsDialog(
onDismiss: () -> Unit,
@ -164,13 +176,14 @@ private fun ColumnScope.SettingsPanel(
onChangeDarkThemeConfig: (darkThemeConfig: DarkThemeConfig) -> Unit,
) {
SettingsDialogSectionTitle(text = stringResource(string.feature_settings_impl_theme))
Column(Modifier.selectableGroup()) {
SettingsDialogThemeChooserRow(
Row(Modifier.selectableGroup()) {
SettingsDialogThemeRadioBtn(
text = stringResource(string.feature_settings_impl_brand_default),
selected = settings.brand == DEFAULT,
onClick = { onChangeThemeBrand(DEFAULT) },
)
SettingsDialogThemeChooserRow(
Spacer(Modifier.width(20.dp))
SettingsDialogThemeRadioBtn(
text = stringResource(string.feature_settings_impl_brand_android),
selected = settings.brand == ANDROID,
onClick = { onChangeThemeBrand(ANDROID) },
@ -180,36 +193,65 @@ private fun ColumnScope.SettingsPanel(
Column {
SettingsDialogSectionTitle(text = stringResource(string.feature_settings_impl_dynamic_color_preference))
Column(Modifier.selectableGroup()) {
SettingsDialogThemeChooserRow(
text = stringResource(string.feature_settings_impl_dynamic_color_yes),
selected = settings.useDynamicColor,
onClick = { onChangeDynamicColorPreference(true) },
)
SettingsDialogThemeChooserRow(
text = stringResource(string.feature_settings_impl_dynamic_color_no),
selected = !settings.useDynamicColor,
onClick = { onChangeDynamicColorPreference(false) },
SettingsDialogThemeDynamicColorRow(
options = listOf( stringResource(string.feature_settings_impl_dynamic_color_yes), stringResource(string.feature_settings_impl_dynamic_color_no)),
selectedIndex = if (settings.useDynamicColor) 0 else 1,
onOptionSelected = { index ->
onChangeDynamicColorPreference(index == 0)
}
)
// SettingsDialogThemeChooserRow(
// text = stringResource(string.feature_settings_impl_dynamic_color_yes),
// selected = settings.useDynamicColor,
// onClick = { onChangeDynamicColorPreference(true) },
// )
// SettingsDialogThemeChooserRow(
// text = stringResource(string.feature_settings_impl_dynamic_color_no),
// selected = !settings.useDynamicColor,
// onClick = { onChangeDynamicColorPreference(false) },
// )
}
}
}
SettingsDialogSectionTitle(text = stringResource(string.feature_settings_impl_dark_mode_preference))
Column(Modifier.selectableGroup()) {
SettingsDialogThemeChooserRow(
text = stringResource(string.feature_settings_impl_dark_mode_config_system_default),
selected = settings.darkThemeConfig == FOLLOW_SYSTEM,
onClick = { onChangeDarkThemeConfig(FOLLOW_SYSTEM) },
)
SettingsDialogThemeChooserRow(
text = stringResource(string.feature_settings_impl_dark_mode_config_light),
selected = settings.darkThemeConfig == LIGHT,
onClick = { onChangeDarkThemeConfig(LIGHT) },
)
SettingsDialogThemeChooserRow(
text = stringResource(string.feature_settings_impl_dark_mode_config_dark),
selected = settings.darkThemeConfig == DARK,
onClick = { onChangeDarkThemeConfig(DARK) },
val darkModeOptions = listOf(
stringResource(string.feature_settings_impl_dark_mode_config_system_default),
stringResource(string.feature_settings_impl_dark_mode_config_light),
stringResource(string.feature_settings_impl_dark_mode_config_dark)
)
SettingsDialogThemeDarkModeRow(
options = darkModeOptions,
selectedIndex = when(settings.darkThemeConfig) {
DarkThemeConfig.FOLLOW_SYSTEM -> 0
DarkThemeConfig.LIGHT -> 1
DarkThemeConfig.DARK -> 2
},
onOptionSelected = { index ->val newConfig = when (index) {
0 -> DarkThemeConfig.FOLLOW_SYSTEM
1 -> DarkThemeConfig.LIGHT
else -> DarkThemeConfig.DARK
}
onChangeDarkThemeConfig(newConfig)}
)
// SettingsDialogThemeChooserRow(
// text = stringResource(string.feature_settings_impl_dark_mode_config_system_default),
// selected = settings.darkThemeConfig == FOLLOW_SYSTEM,
// onClick = { onChangeDarkThemeConfig(FOLLOW_SYSTEM) },
// )
// SettingsDialogThemeChooserRow(
// text = stringResource(string.feature_settings_impl_dark_mode_config_light),
// selected = settings.darkThemeConfig == LIGHT,
// onClick = { onChangeDarkThemeConfig(LIGHT) },
// )
// SettingsDialogThemeChooserRow(
// text = stringResource(string.feature_settings_impl_dark_mode_config_dark),
// selected = settings.darkThemeConfig == DARK,
// onClick = { onChangeDarkThemeConfig(DARK) },
// )
}
}
@ -223,20 +265,19 @@ private fun SettingsDialogSectionTitle(text: String) {
}
@Composable
fun SettingsDialogThemeChooserRow(
fun SettingsDialogThemeRadioBtn(
text: String,
selected: Boolean,
onClick: () -> Unit,
) {
Row(
Modifier
.fillMaxWidth()
.selectable(
selected = selected,
role = Role.RadioButton,
onClick = onClick,
)
.padding(12.dp),
.padding(5.dp),
verticalAlignment = Alignment.CenterVertically,
) {
RadioButton(
@ -248,6 +289,73 @@ fun SettingsDialogThemeChooserRow(
}
}
@Composable
fun SettingsDialogThemeDynamicColorRow( options :List<String>,
selectedIndex :Int,
onOptionSelected : (Int) -> Unit
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
options.forEachIndexed { index, stringId ->
val isSelected = index == selectedIndex
if (isSelected) {
Button(
onClick = { onOptionSelected(index) },
modifier = Modifier.weight(1f),
shape = CircleShape
) {
Spacer(Modifier.width(3.dp))
Text(text = stringId)
}
} else {
OutlinedButton(
onClick = { onOptionSelected(index) },
modifier = Modifier.weight(1f),
shape = CircleShape
) {
Spacer(Modifier.width(3.dp))
Text(text = stringId) }
}
}
}
}
@Composable
fun SettingsDialogThemeDarkModeRow(
options: List<String>,
selectedIndex: Int,
onOptionSelected: (Int) -> Unit
) {
SingleChoiceSegmentedButtonRow(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 1.dp)
) {
options.forEachIndexed { index, stringId ->
val isSelected = index == selectedIndex
SegmentedButton(
shape = SegmentedButtonDefaults.itemShape(index = index, count = options.size),
onClick = { onOptionSelected(index) },
selected = isSelected,
label = {
Text(text = stringId, maxLines = 1)
},
colors = SegmentedButtonDefaults.colors(
activeContainerColor = MaterialTheme.colorScheme.primary ,
activeContentColor = MaterialTheme.colorScheme.onPrimary,
inactiveContainerColor = Color.Transparent,
inactiveContentColor = MaterialTheme.colorScheme.onSurface
),
icon = {}
) }
}
}
@OptIn(ExperimentalLayoutApi::class)
@Composable
private fun LinksPanel() {
@ -285,39 +393,39 @@ private fun LinksPanel() {
}
}
@Preview
@Composable
private fun PreviewSettingsDialog() {
NiaTheme {
SettingsDialog(
onDismiss = {},
settingsUiState = Success(
UserEditableSettings(
brand = DEFAULT,
darkThemeConfig = FOLLOW_SYSTEM,
useDynamicColor = false,
),
),
onChangeThemeBrand = {},
onChangeDynamicColorPreference = {},
onChangeDarkThemeConfig = {},
)
}
}
//@Preview
//@Composable
//private fun PreviewSettingsDialog() {
// NiaTheme {
// SettingsDialog(
// onDismiss = {},
// settingsUiState = Success(
// UserEditableSettings(
// brand = DEFAULT,
// darkThemeConfig = DarkThemeConfig.FOLLOW_SYSTEM,
// useDynamicColor = false,
// ),
// ),
// onChangeThemeBrand = {},
// onChangeDynamicColorPreference = {},
// onChangeDarkThemeConfig = {},
// )
// }
//}
@Preview
@Composable
private fun PreviewSettingsDialogLoading() {
NiaTheme {
SettingsDialog(
onDismiss = {},
settingsUiState = Loading,
onChangeThemeBrand = {},
onChangeDynamicColorPreference = {},
onChangeDarkThemeConfig = {},
)
}
}
//@Preview
//@Composable
//private fun PreviewSettingsDialogLoading() {
// NiaTheme {
// SettingsDialog(
// onDismiss = {},
// settingsUiState = Loading,
// onChangeThemeBrand = {},
// onChangeDynamicColorPreference = {},
// onChangeDarkThemeConfig = {},
// )
// }
//}
private const val PRIVACY_POLICY_URL = "https://policies.google.com/privacy"
private const val BRAND_GUIDELINES_URL = "https://developer.android.com/distribute/marketing-tools/brand-guidelines"

@ -27,7 +27,7 @@
<string name="feature_settings_impl_brand_default">Default</string>
<string name="feature_settings_impl_brand_android">Android</string>
<string name="feature_settings_impl_dark_mode_preference">Dark mode preference</string>
<string name="feature_settings_impl_dark_mode_config_system_default">System default</string>
<string name="feature_settings_impl_dark_mode_config_system_default">System</string>
<string name="feature_settings_impl_dark_mode_config_light">Light</string>
<string name="feature_settings_impl_dark_mode_config_dark">Dark</string>
<string name="feature_settings_impl_dynamic_color_preference">Use Dynamic Color</string>

@ -2,8 +2,8 @@
accompanist = "0.37.0"
androidDesugarJdkLibs = "2.1.4"
# AGP and tools should be updated together
androidGradlePlugin = "9.0.0"
androidTools = "32.0.0"
androidGradlePlugin = "9.0.1"
androidTools = "32.0.1"
androidxActivity = "1.9.3"
androidxAppCompat = "1.7.0"
androidxBrowser = "1.8.0"

Loading…
Cancel
Save