mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-04-09 20:39:24 +02:00
Fixes Poll Caching problems.
This commit is contained in:
parent
600aab5e8d
commit
4d2a7bbc32
@ -1432,7 +1432,7 @@ fun RenderPoll(
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val noteEvent = note.event as? PollNoteEvent ?: return
|
||||
val eventContent = remember(note) { noteEvent.content() }
|
||||
val eventContent = noteEvent.content()
|
||||
|
||||
if (makeItShort && accountViewModel.isLoggedUser(note.author)) {
|
||||
Text(
|
||||
|
@ -68,7 +68,6 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Popup
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
@ -101,7 +100,7 @@ fun PollNote(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val pollViewModel: PollNoteViewModel = viewModel(key = "PollNoteViewModel")
|
||||
val pollViewModel: PollNoteViewModel = viewModel(key = "PollNoteViewModel${baseNote.idHex}")
|
||||
|
||||
pollViewModel.load(accountViewModel.account, baseNote)
|
||||
|
||||
@ -126,11 +125,9 @@ fun PollNote(
|
||||
) {
|
||||
WatchZapsAndUpdateTallies(baseNote, pollViewModel)
|
||||
|
||||
val tallies by pollViewModel.tallies.collectAsStateWithLifecycle()
|
||||
|
||||
tallies.forEach { poll_op ->
|
||||
pollViewModel.tallies.forEach { option ->
|
||||
OptionNote(
|
||||
poll_op,
|
||||
option,
|
||||
pollViewModel,
|
||||
baseNote,
|
||||
accountViewModel,
|
||||
@ -167,9 +164,9 @@ private fun OptionNote(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(vertical = 3.dp),
|
||||
) {
|
||||
if (!pollViewModel.canZap()) {
|
||||
if (!pollViewModel.canZap.value) {
|
||||
val color =
|
||||
if (poolOption.consensusThreadhold) {
|
||||
if (poolOption.consensusThreadhold.value) {
|
||||
Color.Green.copy(alpha = 0.32f)
|
||||
} else {
|
||||
MaterialTheme.colorScheme.mediumImportanceLink
|
||||
@ -181,8 +178,7 @@ private fun OptionNote(
|
||||
pollViewModel = pollViewModel,
|
||||
nonClickablePrepend = {
|
||||
RenderOptionAfterVote(
|
||||
poolOption.descriptor,
|
||||
poolOption.tally.toFloat(),
|
||||
poolOption,
|
||||
color,
|
||||
canPreview,
|
||||
tags,
|
||||
@ -220,8 +216,7 @@ private fun OptionNote(
|
||||
|
||||
@Composable
|
||||
private fun RenderOptionAfterVote(
|
||||
description: String,
|
||||
totalRatio: Float,
|
||||
poolOption: PollOption,
|
||||
color: Color,
|
||||
canPreview: Boolean,
|
||||
tags: ImmutableListOfLists<String>,
|
||||
@ -229,10 +224,9 @@ private fun RenderOptionAfterVote(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val totalPercentage = remember(totalRatio) { "${(totalRatio * 100).roundToInt()}%" }
|
||||
|
||||
Box(
|
||||
Modifier.fillMaxWidth(0.75f)
|
||||
Modifier
|
||||
.fillMaxWidth(0.75f)
|
||||
.clip(shape = QuoteBorder)
|
||||
.border(
|
||||
2.dp,
|
||||
@ -243,7 +237,9 @@ private fun RenderOptionAfterVote(
|
||||
LinearProgressIndicator(
|
||||
modifier = Modifier.matchParentSize(),
|
||||
color = color,
|
||||
progress = totalRatio,
|
||||
progress = {
|
||||
poolOption.tally.value.toFloat()
|
||||
},
|
||||
)
|
||||
|
||||
Row(
|
||||
@ -251,21 +247,31 @@ private fun RenderOptionAfterVote(
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.End,
|
||||
modifier = remember { Modifier.padding(horizontal = 10.dp).width(40.dp) },
|
||||
modifier =
|
||||
remember {
|
||||
Modifier
|
||||
.padding(horizontal = 10.dp)
|
||||
.width(45.dp)
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
text = totalPercentage,
|
||||
text = "${(poolOption.tally.value.toFloat() * 100).roundToInt()}%",
|
||||
fontWeight = FontWeight.Bold,
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = remember { Modifier.fillMaxWidth().padding(15.dp) },
|
||||
modifier =
|
||||
remember {
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 15.dp, horizontal = 10.dp)
|
||||
},
|
||||
) {
|
||||
TranslatableRichTextViewer(
|
||||
description,
|
||||
poolOption.descriptor,
|
||||
canPreview,
|
||||
remember { Modifier },
|
||||
Modifier,
|
||||
tags,
|
||||
backgroundColor,
|
||||
accountViewModel,
|
||||
@ -286,7 +292,8 @@ private fun RenderOptionBeforeVote(
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
Box(
|
||||
Modifier.fillMaxWidth(0.75f)
|
||||
Modifier
|
||||
.fillMaxWidth(0.75f)
|
||||
.clip(shape = QuoteBorder)
|
||||
.border(
|
||||
2.dp,
|
||||
@ -358,7 +365,7 @@ fun ZapVote(
|
||||
R.string.poll_unable_to_vote,
|
||||
R.string.poll_author_no_vote,
|
||||
)
|
||||
} else if (pollViewModel.isVoteAmountAtomic() && poolOption.zappedByLoggedIn) {
|
||||
} else if (pollViewModel.isVoteAmountAtomic() && poolOption.zappedByLoggedIn.value) {
|
||||
// only allow one vote per option when min==max, i.e. atomic vote amount specified
|
||||
accountViewModel.toast(
|
||||
R.string.poll_unable_to_vote,
|
||||
@ -443,7 +450,7 @@ fun ZapVote(
|
||||
|
||||
clickablePrepend()
|
||||
|
||||
if (poolOption.zappedByLoggedIn) {
|
||||
if (poolOption.zappedByLoggedIn.value) {
|
||||
zappingProgress = 1f
|
||||
Icon(
|
||||
imageVector = Icons.Default.Bolt,
|
||||
@ -471,8 +478,8 @@ fun ZapVote(
|
||||
}
|
||||
|
||||
// only show tallies after a user has zapped note
|
||||
if (!pollViewModel.canZap()) {
|
||||
val amountStr = remember(poolOption.zappedValue) { showAmount(poolOption.zappedValue) }
|
||||
if (!pollViewModel.canZap.value) {
|
||||
val amountStr = remember(poolOption.zappedValue.value) { showAmount(poolOption.zappedValue.value) }
|
||||
Text(
|
||||
text = amountStr,
|
||||
fontSize = Font14SP,
|
||||
|
@ -20,8 +20,9 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.note
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
@ -36,20 +37,18 @@ import com.vitorpamplona.quartz.events.VALUE_MAXIMUM
|
||||
import com.vitorpamplona.quartz.events.VALUE_MINIMUM
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
||||
@Immutable
|
||||
@Stable
|
||||
data class PollOption(
|
||||
val option: Int,
|
||||
val descriptor: String,
|
||||
val zappedValue: BigDecimal,
|
||||
val tally: BigDecimal,
|
||||
val consensusThreadhold: Boolean,
|
||||
val zappedByLoggedIn: Boolean,
|
||||
var zappedValue: MutableState<BigDecimal> = mutableStateOf(BigDecimal.ZERO),
|
||||
var tally: MutableState<BigDecimal> = mutableStateOf(BigDecimal.ZERO),
|
||||
var consensusThreadhold: MutableState<Boolean> = mutableStateOf(false),
|
||||
var zappedByLoggedIn: MutableState<Boolean> = mutableStateOf(false),
|
||||
)
|
||||
|
||||
@Stable
|
||||
@ -70,8 +69,8 @@ class PollNoteViewModel : ViewModel() {
|
||||
private var totalZapped: BigDecimal = BigDecimal.ZERO
|
||||
private var wasZappedByLoggedInAccount: Boolean = false
|
||||
|
||||
private val _tallies = MutableStateFlow<List<PollOption>>(emptyList())
|
||||
val tallies = _tallies.asStateFlow()
|
||||
var canZap = mutableStateOf(false)
|
||||
var tallies: List<PollOption> = emptyList()
|
||||
|
||||
fun load(
|
||||
acc: Account,
|
||||
@ -88,47 +87,44 @@ class PollNoteViewModel : ViewModel() {
|
||||
consensusThreshold =
|
||||
pollEvent?.getTagLong(CONSENSUS_THRESHOLD)?.toFloat()?.div(100)?.toBigDecimal()
|
||||
closedAt = pollEvent?.getTagLong(CLOSED_AT)
|
||||
|
||||
totalZapped = BigDecimal.ZERO
|
||||
wasZappedByLoggedInAccount = false
|
||||
|
||||
canZap.value = checkIfCanZap()
|
||||
|
||||
tallies = pollOptions?.keys?.map { option ->
|
||||
PollOption(
|
||||
option,
|
||||
pollOptions?.get(option) ?: "",
|
||||
)
|
||||
} ?: emptyList()
|
||||
}
|
||||
|
||||
fun refreshTallies() {
|
||||
viewModelScope.launch(Dispatchers.Default) {
|
||||
totalZapped = totalZapped()
|
||||
wasZappedByLoggedInAccount = false
|
||||
account?.calculateIfNoteWasZappedByAccount(pollNote) { wasZappedByLoggedInAccount = true }
|
||||
account?.calculateIfNoteWasZappedByAccount(pollNote) {
|
||||
wasZappedByLoggedInAccount = true
|
||||
canZap.value = checkIfCanZap()
|
||||
}
|
||||
|
||||
val newOptions =
|
||||
pollOptions?.keys?.map { option ->
|
||||
val zappedInOption = zappedPollOptionAmount(option)
|
||||
|
||||
val myTally =
|
||||
if (totalZapped.compareTo(BigDecimal.ZERO) > 0) {
|
||||
zappedInOption.divide(totalZapped, 2, RoundingMode.HALF_UP)
|
||||
} else {
|
||||
BigDecimal.ZERO
|
||||
}
|
||||
|
||||
val cachedZappedByLoggedIn =
|
||||
account?.userProfile()?.let { it1 -> cachedIsPollOptionZappedBy(option, it1) } ?: false
|
||||
|
||||
val consensus = consensusThreshold != null && myTally >= consensusThreshold!!
|
||||
|
||||
PollOption(
|
||||
option,
|
||||
pollOptions?.get(option) ?: "",
|
||||
zappedInOption,
|
||||
myTally,
|
||||
consensus,
|
||||
cachedZappedByLoggedIn,
|
||||
)
|
||||
}
|
||||
|
||||
_tallies.emit(
|
||||
newOptions ?: emptyList(),
|
||||
)
|
||||
tallies.forEach {
|
||||
it.zappedValue.value = zappedPollOptionAmount(it.option)
|
||||
it.tally.value =
|
||||
if (totalZapped.compareTo(BigDecimal.ZERO) > 0) {
|
||||
it.zappedValue.value.divide(totalZapped, 2, RoundingMode.HALF_UP)
|
||||
} else {
|
||||
BigDecimal.ZERO
|
||||
}
|
||||
it.consensusThreadhold.value = consensusThreshold != null && it.tally.value >= consensusThreshold!!
|
||||
it.zappedByLoggedIn.value = account?.userProfile()?.let { it1 -> cachedIsPollOptionZappedBy(it.option, it1) } ?: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun canZap(): Boolean {
|
||||
fun checkIfCanZap(): Boolean {
|
||||
val account = account ?: return false
|
||||
val note = pollNote ?: return false
|
||||
return account.userProfile() != note.author && !wasZappedByLoggedInAccount
|
||||
|
Loading…
x
Reference in New Issue
Block a user