|
|
|
|
@ -34,19 +34,27 @@ 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.material3.AlertDialog
|
|
|
|
|
import androidx.compose.material3.Button
|
|
|
|
|
import androidx.compose.material3.HorizontalDivider
|
|
|
|
|
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
|
|
|
|
|
import androidx.compose.ui.platform.LocalWindowInfo
|
|
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
|
|
import androidx.compose.ui.semantics.Role
|
|
|
|
|
import androidx.compose.ui.tooling.preview.Preview
|
|
|
|
|
@ -59,9 +67,6 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTextB
|
|
|
|
|
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 +75,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,
|
|
|
|
|
@ -105,7 +111,7 @@ fun SettingsDialog(
|
|
|
|
|
*/
|
|
|
|
|
AlertDialog(
|
|
|
|
|
properties = DialogProperties(usePlatformDefaultWidth = false),
|
|
|
|
|
modifier = Modifier.widthIn(max = configuration.screenWidthDp.dp - 80.dp),
|
|
|
|
|
modifier = Modifier.widthIn(max = LocalWindowInfo.current.containerSize.width.dp - 80.dp),
|
|
|
|
|
onDismissRequest = { onDismiss() },
|
|
|
|
|
title = {
|
|
|
|
|
Text(
|
|
|
|
|
@ -164,13 +170,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,35 +187,38 @@ 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)
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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) },
|
|
|
|
|
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)
|
|
|
|
|
)
|
|
|
|
|
SettingsDialogThemeChooserRow(
|
|
|
|
|
text = stringResource(string.feature_settings_impl_dark_mode_config_dark),
|
|
|
|
|
selected = settings.darkThemeConfig == DARK,
|
|
|
|
|
onClick = { onChangeDarkThemeConfig(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)}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -223,20 +233,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 +257,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() {
|
|
|
|
|
@ -294,7 +370,7 @@ private fun PreviewSettingsDialog() {
|
|
|
|
|
settingsUiState = Success(
|
|
|
|
|
UserEditableSettings(
|
|
|
|
|
brand = DEFAULT,
|
|
|
|
|
darkThemeConfig = FOLLOW_SYSTEM,
|
|
|
|
|
darkThemeConfig = DarkThemeConfig.FOLLOW_SYSTEM,
|
|
|
|
|
useDynamicColor = false,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
|