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:
toadlyBroodle
2023-03-17 16:48:26 +09:00
parent 29c4c42547
commit f0b4660719
9 changed files with 169 additions and 45 deletions

View File

@@ -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)
}
}

View File

@@ -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? {

View File

@@ -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())
}

View File

@@ -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())
}

View File

@@ -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(

View File

@@ -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)
)

View File

@@ -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),

View File

@@ -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())
}

View File

@@ -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">(0100)%</string>
<string name="poll_zap_amount">sats</string>
<string name="poll_closing_time">Close after</string>
<string name="poll_closing_time_days">days</string>