From 1bb2459277f010c5bd789bfa2ddd7e13c3192ba8 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Fri, 25 Aug 2023 15:08:10 -0400 Subject: [PATCH] Activates min/max values for polls --- .../ui/actions/NewPollVoteValueRange.kt | 80 +++++++------------ .../amethyst/ui/actions/NewPostView.kt | 2 + .../amethyst/ui/actions/NewPostViewModel.kt | 50 +++++++++++- app/src/main/res/values/strings.xml | 2 + 4 files changed, 80 insertions(+), 54 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPollVoteValueRange.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPollVoteValueRange.kt index f585f6e0a..f99259dc0 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPollVoteValueRange.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPollVoteValueRange.kt @@ -1,9 +1,11 @@ package com.vitorpamplona.amethyst.ui.actions import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.MaterialTheme import androidx.compose.material.OutlinedTextField @@ -11,8 +13,6 @@ import androidx.compose.material.Text import androidx.compose.material.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -21,51 +21,11 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer import com.vitorpamplona.amethyst.ui.theme.placeholderText @Composable fun NewPollVoteValueRange(pollViewModel: NewPostViewModel) { - var textMax by rememberSaveable { mutableStateOf("") } - var textMin by rememberSaveable { mutableStateOf("") } - - // check for zapMax amounts < 1 - pollViewModel.isValidvalueMaximum.value = true - if (textMax.isNotEmpty()) { - try { - val int = textMax.toInt() - if (int < 1) { - pollViewModel.isValidvalueMaximum.value = false - } else { pollViewModel.valueMaximum = int } - } catch (e: Exception) { pollViewModel.isValidvalueMaximum.value = false } - } - - // check for minZap amounts < 1 - pollViewModel.isValidvalueMinimum.value = true - if (textMin.isNotEmpty()) { - try { - val int = textMin.toInt() - if (int < 1) { - pollViewModel.isValidvalueMinimum.value = false - } else { pollViewModel.valueMinimum = int } - } catch (e: Exception) { pollViewModel.isValidvalueMinimum.value = false } - } - - // check for zapMin > zapMax - if (textMin.isNotEmpty() && textMax.isNotEmpty()) { - try { - val intMin = textMin.toInt() - val intMax = textMax.toInt() - - if (intMin > intMax) { - pollViewModel.isValidvalueMinimum.value = false - pollViewModel.isValidvalueMaximum.value = false - } - } catch (e: Exception) { - pollViewModel.isValidvalueMinimum.value = false - pollViewModel.isValidvalueMaximum.value = false - } - } - val colorInValid = TextFieldDefaults.outlinedTextFieldColors( focusedBorderColor = MaterialTheme.colors.error, unfocusedBorderColor = Color.Red @@ -80,10 +40,10 @@ fun NewPollVoteValueRange(pollViewModel: NewPostViewModel) { horizontalArrangement = Arrangement.Center ) { OutlinedTextField( - value = textMin, - onValueChange = { textMin = it }, + value = pollViewModel.valueMinimum?.toString() ?: "", + onValueChange = { pollViewModel.updateMinZapAmountForPoll(it) }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), - modifier = Modifier.width(150.dp), + modifier = Modifier.weight(1f), colors = if (pollViewModel.isValidvalueMinimum.value) colorValid else colorInValid, label = { Text( @@ -98,11 +58,14 @@ fun NewPollVoteValueRange(pollViewModel: NewPostViewModel) { ) } ) + + Spacer(modifier = DoubleHorzSpacer) + OutlinedTextField( - value = textMax, - onValueChange = { textMax = it }, + value = pollViewModel.valueMaximum?.toString() ?: "", + onValueChange = { pollViewModel.updateMaxZapAmountForPoll(it) }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), - modifier = Modifier.width(150.dp), + modifier = Modifier.weight(1f), colors = if (pollViewModel.isValidvalueMaximum.value) colorValid else colorInValid, label = { Text( @@ -118,10 +81,25 @@ fun NewPollVoteValueRange(pollViewModel: NewPostViewModel) { } ) } + + Row( + Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + Text( + text = stringResource(R.string.poll_zap_value_min_max_explainer), + color = MaterialTheme.colors.placeholderText, + modifier = Modifier.padding(vertical = 10.dp) + ) + } } @Preview @Composable fun NewPollVoteValueRangePreview() { - NewPollVoteValueRange(NewPostViewModel()) + Column( + modifier = Modifier.fillMaxWidth() + ) { + NewPollVoteValueRange(NewPostViewModel()) + } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt index e0b21fa77..fc43a4293 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt @@ -518,6 +518,8 @@ private fun PollField(postViewModel: NewPostViewModel) { NewPollOption(postViewModel, index) } + NewPollVoteValueRange(postViewModel) + Button( onClick = { postViewModel.pollOptions[postViewModel.pollOptions.size] = diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt index 340d1134e..1bcbdecaf 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt @@ -73,8 +73,8 @@ open class NewPostViewModel() : ViewModel() { var wantsPoll by mutableStateOf(false) var zapRecipients = mutableStateListOf() var pollOptions = newStateMapPollOptions() - var valueMaximum: Int? = null - var valueMinimum: Int? = null + var valueMaximum by mutableStateOf(null) + var valueMinimum by mutableStateOf(null) var consensusThreshold: Int? = null var closedAt: Int? = null @@ -494,7 +494,7 @@ open class NewPostViewModel() : ViewModel() { return message.text.isNotBlank() && !isUploadingImage && !wantsInvoice && (!wantsZapraiser || zapRaiserAmount != null) && (!wantsDirectMessage || !toUsers.text.isNullOrBlank()) && - (!wantsPoll || pollOptions.values.all { it.isNotEmpty() }) && + (!wantsPoll || (pollOptions.values.all { it.isNotEmpty() } && isValidvalueMinimum.value && isValidvalueMaximum.value)) && contentToAddUrl == null } @@ -612,6 +612,50 @@ open class NewPostViewModel() : ViewModel() { nip24 = !nip24 } } + + fun updateMinZapAmountForPoll(textMin: String) { + if (textMin.isNotEmpty()) { + try { + val int = textMin.toInt() + if (int < 1) { + valueMinimum = null + } else { + valueMinimum = int + } + } catch (e: Exception) {} + } else { + valueMinimum = null + } + + checkMinMax() + } + + fun updateMaxZapAmountForPoll(textMax: String) { + if (textMax.isNotEmpty()) { + try { + val int = textMax.toInt() + if (int < 1) { + valueMaximum = null + } else { + valueMaximum = int + } + } catch (e: Exception) {} + } else { + valueMaximum = null + } + + checkMinMax() + } + + fun checkMinMax() { + if ((valueMinimum ?: 0) > (valueMaximum ?: Int.MAX_VALUE)) { + isValidvalueMinimum.value = false + isValidvalueMaximum.value = false + } else { + isValidvalueMinimum.value = true + isValidvalueMaximum.value = true + } + } } enum class GeohashPrecision(val digits: Int) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 992ec266c..7bb0ea5dc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -551,4 +551,6 @@ Rules Update your status + + Votes are weighted by the zap amount. You can set a minimum amount to avoid spammers and a maximum amount to avoid a large zappers taking over the poll. Use the same amount in both fields to make sure every vote is valued the same amount. Leave it empty to accept any amount.