Skip to content

Commit

Permalink
Enable widget wifi property alignment configuration & set default bac…
Browse files Browse the repository at this point in the history
…k to right aligned
  • Loading branch information
w2sv committed Dec 28, 2024
1 parent f73efc8 commit 19d191b
Show file tree
Hide file tree
Showing 23 changed files with 285 additions and 125 deletions.
8 changes: 8 additions & 0 deletions .idea/deploymentTargetSelector.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

@Composable
fun SliderRow(
fun ArrowRightLabelContentRow(
label: String,
slider: @Composable () -> Unit,
content: @Composable () -> Unit,
modifier: Modifier = Modifier
) {
Row(
Expand All @@ -29,7 +29,7 @@ fun SliderRow(
KeyboardArrowRightIcon(modifier = Modifier.padding(end = 8.dp))
Text(label, modifier = Modifier.weight(0.4f), maxLines = 2)
Box(modifier = Modifier.weight(0.6f), contentAlignment = Alignment.Center) {
slider()
content()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.w2sv.androidutils.os.dynamicColorsSupported
import com.w2sv.domain.model.FontSize
import com.w2sv.domain.model.PropertyValueAlignment
import com.w2sv.domain.model.WidgetColoring
import com.w2sv.kotlinutils.enumEntryByOrdinal
import com.w2sv.wifiwidget.R
import com.w2sv.wifiwidget.ui.designsystem.ArrowRightLabelContentRow
import com.w2sv.wifiwidget.ui.designsystem.HomeScreenCardBackground
import com.w2sv.wifiwidget.ui.designsystem.KeyboardArrowRightIcon
import com.w2sv.wifiwidget.ui.designsystem.SliderRow
import com.w2sv.wifiwidget.ui.designsystem.SliderWithLabel
import com.w2sv.wifiwidget.ui.designsystem.ThemeSelectionRow
import com.w2sv.wifiwidget.ui.designsystem.UseDynamicColorsRow
Expand All @@ -55,101 +56,162 @@ fun AppearanceConfiguration(
setOpacity: (Float) -> Unit,
fontSize: FontSize,
setFontSize: (FontSize) -> Unit,
propertyValueAlignment: PropertyValueAlignment,
setPropertyValueAlignment: (PropertyValueAlignment) -> Unit,
showCustomColorConfigurationDialog: (ColorPickerDialogData) -> Unit,
modifier: Modifier = Modifier
) {
Column(modifier = modifier) {
SingleChoiceSegmentedButtonRow(
ColoringConfiguration(
coloringConfig = coloringConfig,
setColoringConfig = setColoringConfig,
showCustomColorConfigurationDialog = showCustomColorConfigurationDialog,
modifier = Modifier
.padding(bottom = verticalPadding)
.align(Alignment.CenterHorizontally)
) {
coloringConfig.styles.forEachIndexed { i, style ->
SegmentedButton(
selected = style.javaClass == coloringConfig.appliedStyle.javaClass,
onClick = {
if (style.javaClass != coloringConfig.appliedStyle.javaClass) {
setColoringConfig(coloringConfig.copy(isCustomSelected = style is WidgetColoring.Style.Custom))
)
BackgroundOpacitySliderRow(
opacity = opacity,
setOpacity = setOpacity,
modifier = Modifier
.fillMaxWidth()
.padding(top = verticalPadding)
)
FontSizeSliderRow(
fontSize = fontSize,
setFontSize = setFontSize,
modifier = Modifier
.fillMaxWidth()
.padding(top = verticalPadding)
)
ArrowRightLabelContentRow(
stringResource(R.string.value_alignment),
content = {
SingleChoiceSegmentedButtonRow {
PropertyValueAlignment.entries.forEach {
SegmentedButton(
selected = it == propertyValueAlignment,
onClick = { setPropertyValueAlignment(it) },
shape = SegmentedButtonDefaults.itemShape(
index = it.ordinal,
count = 2
)
) {
Text(it.name)
}
},
colors = SegmentedButtonDefaults.colors(
inactiveContainerColor = HomeScreenCardBackground
),
shape = SegmentedButtonDefaults.itemShape(
index = i,
count = 2
)
) {
Text(text = stringResource(id = style.labelRes))
}
}
},
modifier = Modifier
.fillMaxWidth()
.padding(vertical = verticalPadding)
)
}
}

@Composable
private fun FontSizeSliderRow(
fontSize: FontSize,
setFontSize: (FontSize) -> Unit,
modifier: Modifier = Modifier
) {
val context: Context = LocalContext.current
ArrowRightLabelContentRow(
label = stringResource(id = R.string.font_size),
content = {
SliderWithLabel(
value = fontSize.ordinal.toFloat(),
steps = remember { FontSize.entries.size - 2 },
makeLabel = remember { { context.getString(enumEntryByOrdinal<FontSize>(it.roundToInt()).labelRes) } },
onValueChanged = remember { { setFontSize(enumEntryByOrdinal(it.roundToInt())) } },
contentDescription = stringResource(id = R.string.font_size_slider_cd),
valueRange = remember { 0f.rangeTo((FontSize.entries.size - 1).toFloat()) }
)
},
modifier = modifier
)
}

@Composable
private fun BackgroundOpacitySliderRow(
opacity: Float,
setOpacity: (Float) -> Unit,
modifier: Modifier = Modifier
) {
ArrowRightLabelContentRow(
label = stringResource(R.string.background_opacity),
content = {
SliderWithLabel(
value = opacity,
steps = 9,
makeLabel = remember { { "${(it * 100).roundToInt()}%" } },
onValueChanged = setOpacity,
contentDescription = stringResource(id = R.string.opacity_slider_cd)
)
},
modifier = modifier
)
}

@Composable
private fun ColoringConfiguration(
coloringConfig: WidgetColoring.Config,
setColoringConfig: (WidgetColoring.Config) -> Unit,
showCustomColorConfigurationDialog: (ColorPickerDialogData) -> Unit,
modifier: Modifier = Modifier
) {
SingleChoiceSegmentedButtonRow(modifier = modifier) {
coloringConfig.styles.forEachIndexed { i, style ->
SegmentedButton(
selected = style.javaClass == coloringConfig.appliedStyle.javaClass,
onClick = {
if (style.javaClass != coloringConfig.appliedStyle.javaClass) {
setColoringConfig(coloringConfig.copy(isCustomSelected = style is WidgetColoring.Style.Custom))
}
},
colors = SegmentedButtonDefaults.colors(
inactiveContainerColor = HomeScreenCardBackground
),
shape = SegmentedButtonDefaults.itemShape(
index = i,
count = 2
)
) {
Text(text = stringResource(id = style.labelRes))
}
}
}

val styleConfigurationModifier =
Modifier
.nestedContentBackground()
.padding(horizontal = 16.dp, vertical = 12.dp)
val styleConfigurationModifier =
Modifier
.nestedContentBackground()
.padding(horizontal = 16.dp, vertical = 12.dp)

AnimatedContent(
targetState = coloringConfig.isCustomSelected,
label = ""
) { isCustomStyleSelected ->
when (isCustomStyleSelected) {
false -> {
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
PresetColoringConfiguration(
data = coloringConfig.preset,
setData = remember { { setColoringConfig(coloringConfig.copy(preset = it)) } },
modifier = styleConfigurationModifier.fillMaxWidth(0.9f)
)
}
AnimatedContent(
targetState = coloringConfig.isCustomSelected,
label = ""
) { isCustomStyleSelected ->
when (isCustomStyleSelected) {
false -> {
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
PresetColoringConfiguration(
data = coloringConfig.preset,
setData = remember { { setColoringConfig(coloringConfig.copy(preset = it)) } },
modifier = styleConfigurationModifier.fillMaxWidth(0.9f)
)
}
}

true -> {
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
CustomColorConfiguration(
data = coloringConfig.custom,
showCustomColorConfigurationDialog = showCustomColorConfigurationDialog,
modifier = styleConfigurationModifier.fillMaxWidth(0.7f)
)
}
true -> {
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
CustomColorConfiguration(
data = coloringConfig.custom,
showCustomColorConfigurationDialog = showCustomColorConfigurationDialog,
modifier = styleConfigurationModifier.fillMaxWidth(0.7f)
)
}
}
}

SliderRow(
label = stringResource(R.string.background_opacity),
slider = {
SliderWithLabel(
value = opacity,
steps = 9,
makeLabel = remember { { "${(it * 100).roundToInt()}%" } },
onValueChanged = setOpacity,
contentDescription = stringResource(id = R.string.opacity_slider_cd)
)
},
modifier = Modifier
.fillMaxWidth()
.padding(top = verticalPadding)
)

val context: Context = LocalContext.current
SliderRow(
label = stringResource(id = R.string.font_size),
slider = {
SliderWithLabel(
value = fontSize.ordinal.toFloat(),
steps = remember { FontSize.entries.size - 2 },
makeLabel = remember { { context.getString(enumEntryByOrdinal<FontSize>(it.roundToInt()).labelRes) } },
onValueChanged = remember { { setFontSize(enumEntryByOrdinal(it.roundToInt())) } },
contentDescription = stringResource(id = R.string.font_size_slider_cd),
valueRange = remember { 0f.rangeTo((FontSize.entries.size - 1).toFloat()) }
)
},
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 6.dp)
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ fun rememberWidgetConfigurationCardProperties(
{ widgetConfiguration.fontSize.value = it }
},
showCustomColorConfigurationDialog = showCustomColorConfigurationDialog,
propertyValueAlignment = widgetConfiguration.propertyValueAlignment.collectAsStateWithLifecycle().value,
setPropertyValueAlignment = remember {
{
widgetConfiguration.propertyValueAlignment.value = it
}
},
modifier = Modifier
.padding(horizontal = 16.dp)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.w2sv.wifiwidget.ui.screens.widgetconfiguration.model
import androidx.compose.runtime.Stable
import com.w2sv.domain.model.FontSize
import com.w2sv.domain.model.LocationParameter
import com.w2sv.domain.model.PropertyValueAlignment
import com.w2sv.domain.model.WidgetBottomBarElement
import com.w2sv.domain.model.WidgetColoring
import com.w2sv.domain.model.WidgetRefreshingParameter
Expand All @@ -21,6 +22,7 @@ class ReversibleWidgetConfiguration(
val coloringConfig: ReversibleStateFlow<WidgetColoring.Config>,
val opacity: ReversibleStateFlow<Float>,
val fontSize: ReversibleStateFlow<FontSize>,
val propertyValueAlignment: ReversibleStateFlow<PropertyValueAlignment>,
val wifiProperties: ReversibleStateMap<WifiProperty, Boolean>,
val orderedWifiProperties: ReversibleStateFlow<List<WifiProperty>>,
val ipSubProperties: ReversibleStateMap<WifiProperty.IP.SubProperty, Boolean>,
Expand All @@ -35,6 +37,7 @@ class ReversibleWidgetConfiguration(
coloringConfig,
opacity,
fontSize,
propertyValueAlignment,
wifiProperties,
orderedWifiProperties,
ipSubProperties,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ class WidgetViewModel @Inject constructor(
scope = viewModelScope,
started = SharingStarted.Eagerly
),
propertyValueAlignment = repository.propertyValueAlignment.reversibleStateFlow(
scope = viewModelScope,
started = SharingStarted.Eagerly
),
wifiProperties = repository.wifiPropertyEnablementMap.reversibleStateMap(scope = viewModelScope),
orderedWifiProperties = repository.orderedWifiProperties.reversibleStateFlow(
scope = viewModelScope,
Expand All @@ -119,7 +123,7 @@ class WidgetViewModel @Inject constructor(
locationParameters = repository.locationParameters.reversibleStateMap(scope = viewModelScope),
scope = viewModelScope,
onStateSynced = {
WifiWidgetProvider.triggerDataRefresh(context).log { "Triggered widget data refresh " }
WifiWidgetProvider.triggerDataRefresh(context).log { "Triggered widget data refresh" }
delay(500) // To allow fab buttons to disappear before emission of snackbar
sharedSnackbarVisuals.emit {
AppSnackbarVisuals(
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,5 @@
<string name="show_dropdown_menu">Show dropdown menu</string>
<string name="okay">Okay!</string>
<string name="property_reordering_discovery_dialog_text">You can change the order in which the properties appear on the widget by long-clicking on a property and moving it to a different position.</string>
<string name="value_alignment">Value alignment</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.w2sv.datastoreutils.preferences.map.DataStoreEntry
import com.w2sv.datastoreutils.preferences.map.DataStoreFlowMap
import com.w2sv.domain.model.FontSize
import com.w2sv.domain.model.LocationParameter
import com.w2sv.domain.model.PropertyValueAlignment
import com.w2sv.domain.model.WidgetBottomBarElement
import com.w2sv.domain.model.WidgetColoring
import com.w2sv.domain.model.WidgetRefreshingParameter
Expand Down Expand Up @@ -50,6 +51,11 @@ internal class WidgetRepositoryImpl @Inject constructor(
default = { FontSize.Small }
)

override val propertyValueAlignment = enumDataStoreFlow(
key = intPreferencesKey("propertyValueAlignment"),
default = { PropertyValueAlignment.Right }
)

// ================
// Maps
// ================
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.w2sv.domain.model

import androidx.annotation.StringRes
import com.w2sv.core.domain.R

enum class PropertyValueAlignment(@StringRes override val labelRes: Int) : WidgetProperty {
Left(R.string.left),
Right(R.string.right)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.w2sv.datastoreutils.datastoreflow.DataStoreFlow
import com.w2sv.datastoreutils.preferences.map.DataStoreFlowMap
import com.w2sv.domain.model.FontSize
import com.w2sv.domain.model.LocationParameter
import com.w2sv.domain.model.PropertyValueAlignment
import com.w2sv.domain.model.WidgetBottomBarElement
import com.w2sv.domain.model.WidgetColoring
import com.w2sv.domain.model.WidgetRefreshingParameter
Expand All @@ -17,6 +18,7 @@ interface WidgetRepository {

val opacity: DataStoreFlow<Float>
val fontSize: DataStoreFlow<FontSize>
val propertyValueAlignment: DataStoreFlow<PropertyValueAlignment>

val sortedEnabledWifiProperties: Flow<List<WifiProperty>>
val wifiPropertyEnablementMap: DataStoreFlowMap<WifiProperty, Boolean>
Expand Down
Loading

0 comments on commit 19d191b

Please sign in to comment.