Activates min/max values for polls

This commit is contained in:
Vitor Pamplona
2023-08-25 15:08:10 -04:00
parent 6b39562925
commit 1bb2459277
4 changed files with 80 additions and 54 deletions
@@ -1,9 +1,11 @@
package com.vitorpamplona.amethyst.ui.actions package com.vitorpamplona.amethyst.ui.actions
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth 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.foundation.text.KeyboardOptions
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedTextField import androidx.compose.material.OutlinedTextField
@@ -11,8 +13,6 @@ import androidx.compose.material.Text
import androidx.compose.material.TextFieldDefaults import androidx.compose.material.TextFieldDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color 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.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.placeholderText import com.vitorpamplona.amethyst.ui.theme.placeholderText
@Composable @Composable
fun NewPollVoteValueRange(pollViewModel: NewPostViewModel) { 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( val colorInValid = TextFieldDefaults.outlinedTextFieldColors(
focusedBorderColor = MaterialTheme.colors.error, focusedBorderColor = MaterialTheme.colors.error,
unfocusedBorderColor = Color.Red unfocusedBorderColor = Color.Red
@@ -80,10 +40,10 @@ fun NewPollVoteValueRange(pollViewModel: NewPostViewModel) {
horizontalArrangement = Arrangement.Center horizontalArrangement = Arrangement.Center
) { ) {
OutlinedTextField( OutlinedTextField(
value = textMin, value = pollViewModel.valueMinimum?.toString() ?: "",
onValueChange = { textMin = it }, onValueChange = { pollViewModel.updateMinZapAmountForPoll(it) },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
modifier = Modifier.width(150.dp), modifier = Modifier.weight(1f),
colors = if (pollViewModel.isValidvalueMinimum.value) colorValid else colorInValid, colors = if (pollViewModel.isValidvalueMinimum.value) colorValid else colorInValid,
label = { label = {
Text( Text(
@@ -98,11 +58,14 @@ fun NewPollVoteValueRange(pollViewModel: NewPostViewModel) {
) )
} }
) )
Spacer(modifier = DoubleHorzSpacer)
OutlinedTextField( OutlinedTextField(
value = textMax, value = pollViewModel.valueMaximum?.toString() ?: "",
onValueChange = { textMax = it }, onValueChange = { pollViewModel.updateMaxZapAmountForPoll(it) },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
modifier = Modifier.width(150.dp), modifier = Modifier.weight(1f),
colors = if (pollViewModel.isValidvalueMaximum.value) colorValid else colorInValid, colors = if (pollViewModel.isValidvalueMaximum.value) colorValid else colorInValid,
label = { label = {
Text( 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 @Preview
@Composable @Composable
fun NewPollVoteValueRangePreview() { fun NewPollVoteValueRangePreview() {
Column(
modifier = Modifier.fillMaxWidth()
) {
NewPollVoteValueRange(NewPostViewModel()) NewPollVoteValueRange(NewPostViewModel())
} }
}
@@ -518,6 +518,8 @@ private fun PollField(postViewModel: NewPostViewModel) {
NewPollOption(postViewModel, index) NewPollOption(postViewModel, index)
} }
NewPollVoteValueRange(postViewModel)
Button( Button(
onClick = { onClick = {
postViewModel.pollOptions[postViewModel.pollOptions.size] = postViewModel.pollOptions[postViewModel.pollOptions.size] =
@@ -73,8 +73,8 @@ open class NewPostViewModel() : ViewModel() {
var wantsPoll by mutableStateOf(false) var wantsPoll by mutableStateOf(false)
var zapRecipients = mutableStateListOf<HexKey>() var zapRecipients = mutableStateListOf<HexKey>()
var pollOptions = newStateMapPollOptions() var pollOptions = newStateMapPollOptions()
var valueMaximum: Int? = null var valueMaximum by mutableStateOf<Int?>(null)
var valueMinimum: Int? = null var valueMinimum by mutableStateOf<Int?>(null)
var consensusThreshold: Int? = null var consensusThreshold: Int? = null
var closedAt: Int? = null var closedAt: Int? = null
@@ -494,7 +494,7 @@ open class NewPostViewModel() : ViewModel() {
return message.text.isNotBlank() && !isUploadingImage && !wantsInvoice && return message.text.isNotBlank() && !isUploadingImage && !wantsInvoice &&
(!wantsZapraiser || zapRaiserAmount != null) && (!wantsZapraiser || zapRaiserAmount != null) &&
(!wantsDirectMessage || !toUsers.text.isNullOrBlank()) && (!wantsDirectMessage || !toUsers.text.isNullOrBlank()) &&
(!wantsPoll || pollOptions.values.all { it.isNotEmpty() }) && (!wantsPoll || (pollOptions.values.all { it.isNotEmpty() } && isValidvalueMinimum.value && isValidvalueMaximum.value)) &&
contentToAddUrl == null contentToAddUrl == null
} }
@@ -612,6 +612,50 @@ open class NewPostViewModel() : ViewModel() {
nip24 = !nip24 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) { enum class GeohashPrecision(val digits: Int) {
+2
View File
@@ -551,4 +551,6 @@
<string name="rules">Rules</string> <string name="rules">Rules</string>
<string name="status_update">Update your status</string> <string name="status_update">Update your status</string>
<string name="poll_zap_value_min_max_explainer">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.</string>
</resources> </resources>