From c9afcd0c866dffd8b3f9503c52231ee88c11f593 Mon Sep 17 00:00:00 2001 From: jivesh Date: Sat, 4 May 2024 01:35:56 +0800 Subject: [PATCH 1/3] Add plus and minus buttons to sliders on reader preference view --- .../omnivore/feature/components/AddButton.kt | 45 +++++++++ .../feature/components/SliderWithPlusMinus.kt | 96 +++++++++++++++++++ .../feature/components/SubtractButton.kt | 45 +++++++++ .../feature/reader/ReaderPreferencesView.kt | 9 +- .../feature/reader/WebReaderViewModel.kt | 2 - 5 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/AddButton.kt create mode 100644 android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SliderWithPlusMinus.kt create mode 100644 android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SubtractButton.kt diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/AddButton.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/AddButton.kt new file mode 100644 index 000000000..2c0754512 --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/AddButton.kt @@ -0,0 +1,45 @@ +package app.omnivore.omnivore.feature.components + +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.IconButtonColors +import androidx.compose.material3.IconButtonDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier + +/** + * A plus-shaped button that can be used to represent an "add" action. + * Just a simple wrapper over IconButton with the Add icon. + * + * @param onClick Called when the button is clicked. + * @param modifier The modifier to apply to the button. + * @param enabled Whether the button is enabled. + * @param colors The colors to use for the button. + * @param interactionSource The [MutableInteractionSource] that backs this button. + */ +@Composable +fun AddButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + colors: IconButtonColors = IconButtonDefaults.iconButtonColors(), + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, +) { + IconButton( + onClick, + modifier, + enabled, + colors, + interactionSource + ) { + Icon( + imageVector = Icons.Default.Add, + contentDescription = "Add", + tint = if (enabled) colors.disabledContentColor else colors.disabledContentColor + ) + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SliderWithPlusMinus.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SliderWithPlusMinus.kt new file mode 100644 index 000000000..47a9ac3b6 --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SliderWithPlusMinus.kt @@ -0,0 +1,96 @@ +package app.omnivore.omnivore.feature.components + +import androidx.annotation.IntRange +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.Slider +import androidx.compose.material3.SliderColors +import androidx.compose.material3.SliderDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview + +/** + * A slider wrapper that adds a plus and minus button to adjust the slider value + * By default, moving the thumb on the slider will update the slider value immediately. + * The plus and minus buttons will adjust the slider value by the step size. + * The buttons are disabled when the slider value is at the minimum or maximum value. + * + * @param value The current value of the slider. + * @param onValueChange Called when the value changes. + * @param modifier The modifier to apply to the slider. + * @param enabled Whether the slider is enabled. + * @param valueRange The range of values the slider can take. + * @param steps The number of steps the slider should have. If 0, the slider will be continuous. + * @param onValueChangeFinished Called when the user stops interacting with the slider. + * @param colors The colors to use for the slider. + * @param interactionSource The [MutableInteractionSource] that backs this slider. + */ +@Composable +fun SliderWithPlusMinus( + value: Float, + onValueChange: (Float) -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + valueRange: ClosedFloatingPointRange = 0f..1f, + @IntRange(from = 0) + steps: Int = 0, + onValueChangeFinished: (() -> Unit)? = null, + colors: SliderColors = SliderDefaults.colors(), + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } +) { + var sliderValue by remember { mutableFloatStateOf(value) } + val sliderValueStepSize = (valueRange.endInclusive - valueRange.start) / steps + + return Row( + modifier = modifier + .fillMaxWidth() + ) { + SubtractButton( + onClick = { + sliderValue -= sliderValueStepSize + onValueChange(sliderValue) + }, + modifier = Modifier.weight(1F), + enabled = sliderValue > valueRange.start + ) + Slider( + value = sliderValue, + onValueChange = { + sliderValue = it + onValueChange(it) + }, + modifier = modifier.weight(18F), + enabled = enabled, + valueRange = valueRange, + steps = steps, + onValueChangeFinished = onValueChangeFinished, + colors = colors, + interactionSource = interactionSource + ) + AddButton( + onClick = { + sliderValue += sliderValueStepSize + onValueChange(sliderValue) + }, + modifier = Modifier.weight(1F), + enabled = sliderValue < valueRange.endInclusive + ) + } +} + +@Preview +@Composable +fun SliderWithPlusMinusPreview() { + SliderWithPlusMinus( + value = 0.5f, + onValueChange = {}, + valueRange = 0f..1f, + steps = 10 + ) +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SubtractButton.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SubtractButton.kt new file mode 100644 index 000000000..163c36515 --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SubtractButton.kt @@ -0,0 +1,45 @@ +package app.omnivore.omnivore.feature.components + +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Remove +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.IconButtonColors +import androidx.compose.material3.IconButtonDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier + +/** + * A minus-shaped button that can be used to represent a "subtract" or "remove" action. + * Just a simple wrapper over IconButton with the Remove icon. + * + * @param onClick Called when the button is clicked. + * @param modifier The modifier to apply to the button. + * @param enabled Whether the button is enabled. + * @param colors The colors to use for the button. + * @param interactionSource The [MutableInteractionSource] that backs this button. + */ +@Composable +fun SubtractButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + colors: IconButtonColors = IconButtonDefaults.iconButtonColors(), + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, +) { + IconButton( + onClick, + modifier, + enabled, + colors, + interactionSource + ) { + Icon( + imageVector = Icons.Default.Remove, + contentDescription = "Subtract", + tint = if (enabled) colors.disabledContentColor else colors.disabledContentColor + ) + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/ReaderPreferencesView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/ReaderPreferencesView.kt index b5bb20d2b..c796e97a0 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/ReaderPreferencesView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/ReaderPreferencesView.kt @@ -41,6 +41,7 @@ import androidx.compose.ui.unit.sp import androidx.lifecycle.compose.collectAsStateWithLifecycle import app.omnivore.omnivore.R import app.omnivore.omnivore.core.designsystem.component.SwitchPreferenceWidget +import app.omnivore.omnivore.feature.components.SliderWithPlusMinus import app.omnivore.omnivore.feature.theme.OmnivoreTheme @Composable @@ -145,7 +146,8 @@ fun ReaderPreferencesView( color = Color(red = 137, green = 137, blue = 137) ) ) - Slider( + + SliderWithPlusMinus( value = fontSizeSliderValue, onValueChange = { fontSizeSliderValue = it @@ -162,7 +164,8 @@ fun ReaderPreferencesView( color = Color(red = 137, green = 137, blue = 137) ) ) - Slider( + + SliderWithPlusMinus( value = marginSliderValue, onValueChange = { marginSliderValue = it @@ -179,7 +182,7 @@ fun ReaderPreferencesView( color = Color(red = 137, green = 137, blue = 137) ) ) - Slider( + SliderWithPlusMinus( value = lineSpacingSliderValue, onValueChange = { lineSpacingSliderValue = it diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderViewModel.kt index 31d4d8966..ac70346d2 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderViewModel.kt @@ -116,8 +116,6 @@ class WebReaderViewModel @Inject constructor( private val showHighlightColorPalette = MutableLiveData(false) val highlightColor = MutableLiveData(HighlightColor()) - var shouldUseVolumeRockerForScroll = true - fun loadItem(slug: String?, requestID: String?) { this.slug = slug if (isLoading || webReaderParamsLiveData.value != null) { From cd59eedcf042b5b31268e9ad512902ccc0ce93a8 Mon Sep 17 00:00:00 2001 From: jivesh Date: Sat, 4 May 2024 01:52:47 +0800 Subject: [PATCH 2/3] avoid divide by zero error? --- .../omnivore/feature/components/SliderWithPlusMinus.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SliderWithPlusMinus.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SliderWithPlusMinus.kt index 47a9ac3b6..cfc14ee28 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SliderWithPlusMinus.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SliderWithPlusMinus.kt @@ -45,7 +45,8 @@ fun SliderWithPlusMinus( interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } ) { var sliderValue by remember { mutableFloatStateOf(value) } - val sliderValueStepSize = (valueRange.endInclusive - valueRange.start) / steps + val sliderValueStepSize = if (steps == 0) 0f else + (valueRange.endInclusive - valueRange.start) / steps return Row( modifier = modifier From 702fb88fb7bad209737fcc75bb9b501a43debdde Mon Sep 17 00:00:00 2001 From: jivesh Date: Sat, 4 May 2024 01:56:59 +0800 Subject: [PATCH 3/3] make buttons more touchable --- .../omnivore/omnivore/feature/components/SliderWithPlusMinus.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SliderWithPlusMinus.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SliderWithPlusMinus.kt index cfc14ee28..5c1de379c 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SliderWithPlusMinus.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/components/SliderWithPlusMinus.kt @@ -66,7 +66,7 @@ fun SliderWithPlusMinus( sliderValue = it onValueChange(it) }, - modifier = modifier.weight(18F), + modifier = modifier.weight(10F), enabled = enabled, valueRange = valueRange, steps = steps,