move PollNote logic to PollNoteViewModel,
fix PollNoteEvent tag getter funs for the final fucking time (hopefully)!, only show option amounts if user has zapped poll note, make poll options wider
This commit is contained in:
@@ -36,17 +36,20 @@ class PollNoteEvent(
|
||||
.forEach { map[it[1].toInt()] = it[2] }
|
||||
return map
|
||||
}
|
||||
fun valueMaximum(): Int? = tags.filter { it.firstOrNull() == VALUE_MAXIMUM }
|
||||
.getOrNull(1)?.getOrNull(1)?.toInt()
|
||||
|
||||
fun valueMinimum(): Int? = tags.filter { it.firstOrNull() == VALUE_MINIMUM }
|
||||
.getOrNull(1)?.getOrNull(1)?.toInt()
|
||||
fun getTagInt(property: String): Int? {
|
||||
val tagList = tags.filter {
|
||||
it.firstOrNull() == property
|
||||
}
|
||||
val tag = tagList.getOrNull(0)
|
||||
val s = tag?.getOrNull(1)
|
||||
|
||||
fun consensusThreshold(): Int? = tags.filter { it.firstOrNull() == CONSENSUS_THRESHOLD }
|
||||
.getOrNull(1)?.getOrNull(1)?.toInt()
|
||||
|
||||
fun closedAt(): Int? = tags.filter { it.firstOrNull() == CLOSED_AT }
|
||||
.getOrNull(1)?.getOrNull(1)?.toInt()
|
||||
return if (s.isNullOrBlank() || s == "null") {
|
||||
null
|
||||
} else {
|
||||
s.toInt()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val kind = 6969
|
||||
|
||||
@@ -26,10 +26,10 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.service.model.PollNoteEvent
|
||||
import com.vitorpamplona.amethyst.ui.components.TranslateableRichTextViewer
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
@@ -44,10 +44,10 @@ fun PollNote(
|
||||
accountViewModel: AccountViewModel,
|
||||
navController: NavController
|
||||
) {
|
||||
val pollEvent = note.event as PollNoteEvent
|
||||
val consensusThreshold = pollEvent.consensusThreshold()
|
||||
val pollViewModel: PollNoteViewModel = viewModel()
|
||||
pollViewModel.load(note)
|
||||
|
||||
pollEvent.pollOptions().forEach { poll_op ->
|
||||
pollViewModel.pollEvent?.pollOptions()?.forEach { poll_op ->
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
@@ -56,16 +56,16 @@ fun PollNote(
|
||||
poll_op.value,
|
||||
canPreview,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.width(250.dp)
|
||||
.border(BorderStroke(1.dp, MaterialTheme.colors.onSurface.copy(alpha = 0.32f)))
|
||||
.padding(4.dp),
|
||||
pollEvent.tags(),
|
||||
pollViewModel.pollEvent?.tags(),
|
||||
backgroundColor,
|
||||
accountViewModel,
|
||||
navController
|
||||
)
|
||||
|
||||
ZapVote(note, accountViewModel, poll_op.key)
|
||||
ZapVote(note, accountViewModel, pollViewModel, poll_op.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,7 @@ fun PollNote(
|
||||
fun ZapVote(
|
||||
baseNote: Note,
|
||||
accountViewModel: AccountViewModel,
|
||||
pollViewModel: PollNoteViewModel,
|
||||
pollOption: Int,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
@@ -89,15 +90,6 @@ fun ZapVote(
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
val pollEvent = baseNote.event as PollNoteEvent
|
||||
val valueMaximum = pollEvent.valueMaximum()
|
||||
val valueMinimum = pollEvent.valueMinimum()
|
||||
|
||||
val isPollClosed: Boolean = pollEvent.closedAt()?.let { // allow 2 minute leeway for zap to propagate
|
||||
baseNote.createdAt()?.plus(it * (86400 + 120))!! > Date().time / 1000
|
||||
} == true
|
||||
val isVoteAmountAtomic = valueMaximum != null && valueMinimum != null && valueMinimum == valueMaximum
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
@@ -117,7 +109,7 @@ fun ZapVote(
|
||||
)
|
||||
.show()
|
||||
}
|
||||
} else if (isPollClosed) {
|
||||
} else if (pollViewModel.isPollClosed) {
|
||||
scope.launch {
|
||||
Toast
|
||||
.makeText(
|
||||
@@ -127,10 +119,10 @@ fun ZapVote(
|
||||
)
|
||||
.show()
|
||||
}
|
||||
} else if (isVoteAmountAtomic) {
|
||||
} else if (pollViewModel.isVoteAmountAtomic) {
|
||||
accountViewModel.zap(
|
||||
baseNote,
|
||||
valueMaximum!!.toLong() * 1000,
|
||||
pollViewModel.valueMaximum!!.toLong() * 1000,
|
||||
pollOption,
|
||||
"",
|
||||
context
|
||||
@@ -152,9 +144,8 @@ fun ZapVote(
|
||||
ZapVoteAmountChoicePopup(
|
||||
baseNote,
|
||||
accountViewModel,
|
||||
pollViewModel,
|
||||
pollOption,
|
||||
valueMinimum,
|
||||
valueMaximum,
|
||||
onDismiss = {
|
||||
wantsToZap = false
|
||||
},
|
||||
@@ -183,12 +174,14 @@ fun ZapVote(
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
showAmount(zappedNote?.zappedPollOptionAmount(pollOption)),
|
||||
fontSize = 14.sp,
|
||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||
modifier = modifier
|
||||
)
|
||||
if (zappedNote?.isZappedBy(account.userProfile()) == true) {
|
||||
Text(
|
||||
showAmount(zappedNote.zappedPollOptionAmount(pollOption)),
|
||||
fontSize = 14.sp,
|
||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@@ -196,9 +189,8 @@ fun ZapVote(
|
||||
fun ZapVoteAmountChoicePopup(
|
||||
baseNote: Note,
|
||||
accountViewModel: AccountViewModel,
|
||||
pollViewModel: PollNoteViewModel,
|
||||
pollOption: Int,
|
||||
valueMinimum: Int?,
|
||||
valueMaximum: Int?,
|
||||
onDismiss: () -> Unit,
|
||||
onError: (text: String) -> Unit
|
||||
) {
|
||||
@@ -206,43 +198,6 @@ fun ZapVoteAmountChoicePopup(
|
||||
|
||||
var textAmount by rememberSaveable { mutableStateOf("") }
|
||||
|
||||
val placeHolderText = if (valueMinimum == null && valueMaximum == null) {
|
||||
stringResource(R.string.sats)
|
||||
} else if (valueMinimum == null) {
|
||||
"1—$valueMaximum " + stringResource(R.string.sats)
|
||||
} else if (valueMaximum == null) {
|
||||
">$valueMinimum " + stringResource(R.string.sats)
|
||||
} else {
|
||||
"$valueMinimum—$valueMaximum " + stringResource(R.string.sats)
|
||||
}
|
||||
|
||||
val amount = if (textAmount.isEmpty()) { null } else {
|
||||
try {
|
||||
textAmount.toLong()
|
||||
} catch (e: Exception) { null }
|
||||
}
|
||||
|
||||
var isValidAmount = false
|
||||
if (amount == null) {
|
||||
isValidAmount = false
|
||||
} else if (valueMinimum == null && valueMaximum == null) {
|
||||
if (amount > 0) {
|
||||
isValidAmount = true
|
||||
}
|
||||
} else if (valueMinimum == null) {
|
||||
if (amount > 0 && amount <= valueMaximum!!) {
|
||||
isValidAmount = true
|
||||
}
|
||||
} else if (valueMaximum == null) {
|
||||
if (amount >= valueMinimum) {
|
||||
isValidAmount = true
|
||||
}
|
||||
} else {
|
||||
if ((valueMinimum <= amount) && (amount <= valueMaximum)) {
|
||||
isValidAmount = true
|
||||
}
|
||||
}
|
||||
|
||||
val colorInValid = TextFieldDefaults.outlinedTextFieldColors(
|
||||
focusedBorderColor = MaterialTheme.colors.error,
|
||||
unfocusedBorderColor = Color.Red
|
||||
@@ -266,12 +221,14 @@ fun ZapVoteAmountChoicePopup(
|
||||
modifier = Modifier
|
||||
.padding(10.dp)
|
||||
) {
|
||||
val amount = pollViewModel.amount(textAmount)
|
||||
|
||||
OutlinedTextField(
|
||||
value = textAmount,
|
||||
onValueChange = { textAmount = it },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
modifier = Modifier.width(150.dp),
|
||||
colors = if (isValidAmount) colorValid else colorInValid,
|
||||
colors = if (pollViewModel.isValidAmount(amount)) colorValid else colorInValid,
|
||||
label = {
|
||||
Text(
|
||||
text = stringResource(R.string.poll_zap_amount),
|
||||
@@ -280,7 +237,7 @@ fun ZapVoteAmountChoicePopup(
|
||||
},
|
||||
placeholder = {
|
||||
Text(
|
||||
text = placeHolderText,
|
||||
text = pollViewModel.voteAmountPlaceHolderText(context),
|
||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
||||
)
|
||||
}
|
||||
@@ -288,7 +245,7 @@ fun ZapVoteAmountChoicePopup(
|
||||
|
||||
Button(
|
||||
modifier = Modifier.padding(horizontal = 3.dp),
|
||||
enabled = isValidAmount,
|
||||
enabled = pollViewModel.isValidAmount(amount),
|
||||
onClick = {
|
||||
if (amount != null) {
|
||||
accountViewModel.zap(
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.vitorpamplona.amethyst.ui.note
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.service.model.*
|
||||
import java.util.*
|
||||
|
||||
class PollNoteViewModel : ViewModel() {
|
||||
var account: Account? = null
|
||||
var pollNote: Note? = null
|
||||
|
||||
var pollEvent: PollNoteEvent? = null
|
||||
var valueMaximum: Int? = null
|
||||
var valueMinimum: Int? = null
|
||||
var closedAt: Int? = null
|
||||
var consensusThreshold: Int? = null
|
||||
|
||||
fun load(note: Note?) {
|
||||
pollNote = note
|
||||
pollEvent = pollNote?.event as PollNoteEvent
|
||||
valueMaximum = pollEvent?.getTagInt(VALUE_MAXIMUM)
|
||||
valueMinimum = pollEvent?.getTagInt(VALUE_MINIMUM)
|
||||
consensusThreshold = pollEvent?.getTagInt(CONSENSUS_THRESHOLD)
|
||||
closedAt = pollEvent?.getTagInt(CLOSED_AT)
|
||||
}
|
||||
|
||||
val isPollClosed: Boolean = closedAt?.let { // allow 2 minute leeway for zap to propagate
|
||||
pollNote?.createdAt()?.plus(it * (86400 + 120))!! > Date().time / 1000
|
||||
} == true
|
||||
|
||||
val isVoteAmountAtomic = valueMaximum != null && valueMinimum != null && valueMinimum == valueMaximum
|
||||
|
||||
fun voteAmountPlaceHolderText(ctx: Context): String = if (valueMinimum == null && valueMaximum == null) {
|
||||
ctx.getString(R.string.sats)
|
||||
} else if (valueMinimum == null) {
|
||||
"1—$valueMaximum " + ctx.getString(R.string.sats)
|
||||
} else if (valueMaximum == null) {
|
||||
">$valueMinimum " + ctx.getString(R.string.sats)
|
||||
} else {
|
||||
"$valueMinimum—$valueMaximum " + ctx.getString(R.string.sats)
|
||||
}
|
||||
|
||||
fun amount(textAmount: String) = if (textAmount.isEmpty()) { null } else {
|
||||
try {
|
||||
textAmount.toLong()
|
||||
} catch (e: Exception) { null }
|
||||
}
|
||||
|
||||
fun isValidAmount(amount: Long?): Boolean {
|
||||
if (amount == null) {
|
||||
return false
|
||||
} else if (valueMinimum == null && valueMaximum == null) {
|
||||
if (amount > 0) {
|
||||
return true
|
||||
}
|
||||
} else if (valueMinimum == null) {
|
||||
if (amount > 0 && amount <= valueMaximum!!) {
|
||||
return true
|
||||
}
|
||||
} else if (valueMaximum == null) {
|
||||
if (amount >= valueMinimum!!) {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if ((valueMinimum!! <= amount) && (amount <= valueMaximum!!)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user