mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-09-23 20:55:49 +02:00
validate user input for all poll fields,
add user's pubkey to recipients field, add poll field saveable texts to pollViewModel,
This commit is contained in:
@@ -39,6 +39,11 @@ fun NewPollView(onClose: () -> Unit, baseReplyTo: Note? = null, quote: Note? = n
|
||||
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
// if no recipients, add user's pubkey
|
||||
if (pollViewModel.zapRecipients.isEmpty()) {
|
||||
pollViewModel.zapRecipients.add(account.userProfile().pubkeyHex)
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
pollViewModel.load(account, baseReplyTo, quote)
|
||||
delay(100)
|
||||
@@ -109,7 +114,8 @@ fun NewPollView(onClose: () -> Unit, baseReplyTo: Note? = null, quote: Note? = n
|
||||
}
|
||||
|
||||
Text(stringResource(R.string.poll_heading_required))
|
||||
PollPrimaryDescription(pollViewModel = pollViewModel)
|
||||
PollRecipientsField(pollViewModel)
|
||||
PollPrimaryDescription(pollViewModel)
|
||||
pollViewModel.pollOptions.forEachIndexed { index, element ->
|
||||
PollOption(pollViewModel, index)
|
||||
}
|
||||
@@ -127,10 +133,9 @@ fun NewPollView(onClose: () -> Unit, baseReplyTo: Note? = null, quote: Note? = n
|
||||
)
|
||||
}
|
||||
Text(stringResource(R.string.poll_heading_optional))
|
||||
PollRecipientsField()
|
||||
PollVoteValueRange()
|
||||
PollConsensusThreshold()
|
||||
PollClosing()
|
||||
PollVoteValueRange(pollViewModel)
|
||||
PollConsensusThreshold(pollViewModel)
|
||||
PollClosing(pollViewModel)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -3,12 +3,18 @@ package com.vitorpamplona.amethyst.ui.actions
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.HexKey
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
|
||||
class NewPollViewModel : NewPostViewModel() {
|
||||
|
||||
var zapRecipients = mutableStateListOf<HexKey>()
|
||||
var pollOptions = mutableStateListOf("", "")
|
||||
var zapMax: Int? = null
|
||||
var zapMin: Int? = null
|
||||
var consensus: Int? = null
|
||||
var closedAfter: Int? = null
|
||||
|
||||
override fun load(account: Account, replyingTo: Note?, quote: Note?) {
|
||||
super.load(account, replyingTo, quote)
|
||||
@@ -32,13 +38,15 @@ class NewPollViewModel : NewPostViewModel() {
|
||||
|
||||
override fun sendPost() {
|
||||
super.sendPost()
|
||||
|
||||
// delete existing pollOptions
|
||||
pollOptions = mutableStateListOf("", "")
|
||||
}
|
||||
|
||||
override fun cancel() {
|
||||
// delete existing pollOptions
|
||||
pollOptions = mutableStateListOf("", "")
|
||||
|
||||
super.cancel()
|
||||
|
||||
pollOptions = mutableStateListOf("", "")
|
||||
}
|
||||
|
||||
override fun findUrlInMessage(): String? {
|
||||
|
@@ -8,22 +8,44 @@ import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.OutlinedTextField
|
||||
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
|
||||
import androidx.compose.ui.res.stringResource
|
||||
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.actions.NewPollViewModel
|
||||
|
||||
@Composable
|
||||
fun PollClosing() {
|
||||
fun PollClosing(pollViewModel: NewPollViewModel) {
|
||||
var text by rememberSaveable { mutableStateOf("") }
|
||||
|
||||
var isInputValid = true
|
||||
if (text.isNotEmpty()) {
|
||||
try {
|
||||
val int = text.toInt()
|
||||
if (int < 0) {
|
||||
isInputValid = false
|
||||
} else { pollViewModel.closedAfter = int }
|
||||
} catch (e: Exception) { isInputValid = false }
|
||||
}
|
||||
|
||||
val colorInValid = TextFieldDefaults.outlinedTextFieldColors(
|
||||
focusedBorderColor = MaterialTheme.colors.error,
|
||||
unfocusedBorderColor = Color.Red
|
||||
)
|
||||
val colorValid = TextFieldDefaults.outlinedTextFieldColors(
|
||||
focusedBorderColor = MaterialTheme.colors.primary,
|
||||
unfocusedBorderColor = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
||||
)
|
||||
|
||||
Row(
|
||||
Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
@@ -33,6 +55,7 @@ fun PollClosing() {
|
||||
onValueChange = { text = it },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
modifier = Modifier.width(150.dp),
|
||||
colors = if (isInputValid) colorValid else colorInValid,
|
||||
label = {
|
||||
Text(
|
||||
text = stringResource(R.string.poll_closing_time),
|
||||
@@ -52,5 +75,5 @@ fun PollClosing() {
|
||||
@Preview
|
||||
@Composable
|
||||
fun PollClosingPreview() {
|
||||
PollClosing()
|
||||
PollClosing(NewPollViewModel())
|
||||
}
|
||||
|
@@ -8,22 +8,44 @@ import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.OutlinedTextField
|
||||
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
|
||||
import androidx.compose.ui.res.stringResource
|
||||
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.actions.NewPollViewModel
|
||||
|
||||
@Composable
|
||||
fun PollConsensusThreshold() {
|
||||
fun PollConsensusThreshold(pollViewModel: NewPollViewModel) {
|
||||
var text by rememberSaveable { mutableStateOf("") }
|
||||
|
||||
var isInputValid = true
|
||||
if (text.isNotEmpty()) {
|
||||
try {
|
||||
val int = text.toInt()
|
||||
if (int < 0 || int > 100) {
|
||||
isInputValid = false
|
||||
} else { pollViewModel.consensus = int }
|
||||
} catch (e: Exception) { isInputValid = false }
|
||||
}
|
||||
|
||||
val colorInValid = TextFieldDefaults.outlinedTextFieldColors(
|
||||
focusedBorderColor = MaterialTheme.colors.error,
|
||||
unfocusedBorderColor = Color.Red
|
||||
)
|
||||
val colorValid = TextFieldDefaults.outlinedTextFieldColors(
|
||||
focusedBorderColor = MaterialTheme.colors.primary,
|
||||
unfocusedBorderColor = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
||||
)
|
||||
|
||||
Row(
|
||||
Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
@@ -33,6 +55,7 @@ fun PollConsensusThreshold() {
|
||||
onValueChange = { text = it },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
modifier = Modifier.width(150.dp),
|
||||
colors = if (isInputValid) colorValid else colorInValid,
|
||||
label = {
|
||||
Text(
|
||||
text = stringResource(R.string.poll_consensus_threshold),
|
||||
@@ -52,5 +75,5 @@ fun PollConsensusThreshold() {
|
||||
@Preview
|
||||
@Composable
|
||||
fun PollConsensusThresholdPreview() {
|
||||
PollConsensusThreshold()
|
||||
PollConsensusThreshold(NewPollViewModel())
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
@@ -15,6 +16,20 @@ import com.vitorpamplona.amethyst.ui.actions.NewPollViewModel
|
||||
|
||||
@Composable
|
||||
fun PollOption(pollViewModel: NewPollViewModel, optionIndex: Int) {
|
||||
var isInputValid = true
|
||||
if (pollViewModel.pollOptions[optionIndex].isEmpty()) {
|
||||
isInputValid = false
|
||||
}
|
||||
|
||||
val colorInValid = TextFieldDefaults.outlinedTextFieldColors(
|
||||
focusedBorderColor = MaterialTheme.colors.error,
|
||||
unfocusedBorderColor = Color.Red
|
||||
)
|
||||
val colorValid = TextFieldDefaults.outlinedTextFieldColors(
|
||||
focusedBorderColor = MaterialTheme.colors.primary,
|
||||
unfocusedBorderColor = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
||||
)
|
||||
|
||||
Row {
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
@@ -32,8 +47,8 @@ fun PollOption(pollViewModel: NewPollViewModel, optionIndex: Int) {
|
||||
text = stringResource(R.string.poll_option_description),
|
||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
||||
)
|
||||
}
|
||||
|
||||
},
|
||||
colors = if (isInputValid) colorValid else colorInValid
|
||||
)
|
||||
if (optionIndex > 1) {
|
||||
Button(
|
||||
|
@@ -1,13 +1,10 @@
|
||||
package com.vitorpamplona.amethyst.ui.components
|
||||
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
@@ -30,6 +27,20 @@ fun PollPrimaryDescription(pollViewModel: NewPollViewModel) {
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
val keyboardController = LocalSoftwareKeyboardController.current
|
||||
|
||||
var isInputValid = true
|
||||
if (pollViewModel.message.text.isEmpty()) {
|
||||
isInputValid = false
|
||||
}
|
||||
|
||||
val colorInValid = TextFieldDefaults.outlinedTextFieldColors(
|
||||
focusedBorderColor = MaterialTheme.colors.error,
|
||||
unfocusedBorderColor = Color.Red
|
||||
)
|
||||
val colorValid = TextFieldDefaults.outlinedTextFieldColors(
|
||||
focusedBorderColor = MaterialTheme.colors.primary,
|
||||
unfocusedBorderColor = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
value = pollViewModel.message,
|
||||
onValueChange = {
|
||||
@@ -47,11 +58,6 @@ fun PollPrimaryDescription(pollViewModel: NewPollViewModel) {
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp)
|
||||
.border(
|
||||
width = 1.dp,
|
||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||
shape = RoundedCornerShape(8.dp)
|
||||
)
|
||||
.focusRequester(focusRequester)
|
||||
.onFocusChanged {
|
||||
if (it.isFocused) {
|
||||
@@ -64,11 +70,7 @@ fun PollPrimaryDescription(pollViewModel: NewPollViewModel) {
|
||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
||||
)
|
||||
},
|
||||
colors = TextFieldDefaults
|
||||
.outlinedTextFieldColors(
|
||||
unfocusedBorderColor = Color.Transparent,
|
||||
focusedBorderColor = Color.Transparent
|
||||
),
|
||||
colors = if (isInputValid) colorValid else colorInValid,
|
||||
visualTransformation = UrlUserTagTransformation(MaterialTheme.colors.primary),
|
||||
textStyle = LocalTextStyle.current.copy(textDirection = TextDirection.Content)
|
||||
)
|
||||
|
@@ -5,23 +5,20 @@ import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.OutlinedTextField
|
||||
import androidx.compose.material.Text
|
||||
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.res.stringResource
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewPollViewModel
|
||||
|
||||
@Composable
|
||||
fun PollRecipientsField() {
|
||||
var text by rememberSaveable() { mutableStateOf("") }
|
||||
fun PollRecipientsField(pollViewModel: NewPollViewModel) {
|
||||
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
value = text,
|
||||
onValueChange = { text = it },
|
||||
value = pollViewModel.zapRecipients[0],
|
||||
onValueChange = { /* TODO */ },
|
||||
enabled = false, // TODO enable add recipients
|
||||
label = {
|
||||
Text(
|
||||
text = stringResource(R.string.poll_zap_recipients),
|
||||
|
@@ -8,32 +8,82 @@ import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.OutlinedTextField
|
||||
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
|
||||
import androidx.compose.ui.res.stringResource
|
||||
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.actions.NewPollViewModel
|
||||
|
||||
@Composable
|
||||
fun PollVoteValueRange() {
|
||||
var minText by rememberSaveable { mutableStateOf("") }
|
||||
var maxText by rememberSaveable { mutableStateOf("") }
|
||||
fun PollVoteValueRange(pollViewModel: NewPollViewModel) {
|
||||
var textMax by rememberSaveable { mutableStateOf("") }
|
||||
var textMin by rememberSaveable { mutableStateOf("") }
|
||||
|
||||
// check for zapMax amounts < 1
|
||||
var isMaxValid = true
|
||||
if (textMax.isNotEmpty()) {
|
||||
try {
|
||||
val int = textMax.toInt()
|
||||
if ( int < 1)
|
||||
isMaxValid = false
|
||||
else pollViewModel.zapMax = int
|
||||
} catch (e: Exception) { isMaxValid = false }
|
||||
}
|
||||
|
||||
// check for minZap amounts < 1
|
||||
var isMinValid = true
|
||||
if (textMin.isNotEmpty()) {
|
||||
try {
|
||||
val int = textMin.toInt()
|
||||
if ( int < 1)
|
||||
isMinValid = false
|
||||
else pollViewModel.zapMin = int
|
||||
} catch (e: Exception) { isMinValid = false }
|
||||
}
|
||||
|
||||
// check for zapMin > zapMax
|
||||
if (textMin.isNotEmpty() && textMax.isNotEmpty()) {
|
||||
try {
|
||||
val intMin = textMin.toInt()
|
||||
val intMax = textMax.toInt()
|
||||
|
||||
if ( intMin > intMax) {
|
||||
isMinValid = false
|
||||
isMaxValid = false
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
isMinValid = false
|
||||
isMaxValid = false
|
||||
}
|
||||
}
|
||||
|
||||
val colorInValid = TextFieldDefaults.outlinedTextFieldColors(
|
||||
focusedBorderColor = MaterialTheme.colors.error,
|
||||
unfocusedBorderColor = Color.Red)
|
||||
val colorValid = TextFieldDefaults.outlinedTextFieldColors(
|
||||
focusedBorderColor = MaterialTheme.colors.primary,
|
||||
unfocusedBorderColor = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
||||
)
|
||||
|
||||
Row(
|
||||
Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = minText,
|
||||
onValueChange = { minText = it },
|
||||
value = textMin,
|
||||
onValueChange = { textMin = it },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
modifier = Modifier.width(150.dp),
|
||||
colors = if (isMinValid) colorValid else colorInValid,
|
||||
label = {
|
||||
Text(
|
||||
text = stringResource(R.string.poll_zap_value_min),
|
||||
@@ -48,10 +98,11 @@ fun PollVoteValueRange() {
|
||||
}
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = maxText,
|
||||
onValueChange = { maxText = it },
|
||||
value = textMax,
|
||||
onValueChange = { textMax = it },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
modifier = Modifier.width(150.dp),
|
||||
colors = if (isMaxValid) colorValid else colorInValid,
|
||||
label = {
|
||||
Text(
|
||||
text = stringResource(R.string.poll_zap_value_max),
|
||||
@@ -71,5 +122,5 @@ fun PollVoteValueRange() {
|
||||
@Preview
|
||||
@Composable
|
||||
fun PollVoteValueRangePreview() {
|
||||
PollVoteValueRange()
|
||||
PollVoteValueRange(NewPollViewModel())
|
||||
}
|
||||
|
@@ -230,7 +230,7 @@
|
||||
<string name="poll_zap_value_min">Zap minimum</string>
|
||||
<string name="poll_zap_value_max">Zap maximum</string>
|
||||
<string name="poll_consensus_threshold">Consensus</string>
|
||||
<string name="poll_consensus_threshold_percent">%</string>
|
||||
<string name="poll_consensus_threshold_percent">(0–100)%</string>
|
||||
<string name="poll_zap_amount">sats</string>
|
||||
<string name="poll_closing_time">Close after</string>
|
||||
<string name="poll_closing_time_days">days</string>
|
||||
|
Reference in New Issue
Block a user