Caching total Zaps

This commit is contained in:
Vitor Pamplona
2023-11-09 14:26:11 -05:00
parent 9377c902a1
commit 43d03bc109
6 changed files with 173 additions and 196 deletions
@@ -581,7 +581,7 @@ class Account(
fun calculateZappedAmount(zappedNote: Note?): BigDecimal { fun calculateZappedAmount(zappedNote: Note?): BigDecimal {
val privKey = zapPaymentRequest?.secret?.hexToByteArray() ?: keyPair.privKey val privKey = zapPaymentRequest?.secret?.hexToByteArray() ?: keyPair.privKey
val pubKey = zapPaymentRequest?.pubKeyHex?.hexToByteArray() val pubKey = zapPaymentRequest?.pubKeyHex?.hexToByteArray()
return zappedNote?.zappedAmount(privKey, pubKey) ?: BigDecimal.ZERO return zappedNote?.zappedAmountWithNWCPayments(privKey, pubKey) ?: BigDecimal.ZERO
} }
fun sendZapPaymentRequestFor(bolt11: String, zappedNote: Note?, onResponse: (Response?) -> Unit) { fun sendZapPaymentRequestFor(bolt11: String, zappedNote: Note?, onResponse: (Response?) -> Unit) {
@@ -86,6 +86,8 @@ open class Note(val idHex: String) {
private set private set
var zaps = mapOf<Note, Note?>() var zaps = mapOf<Note, Note?>()
private set private set
var zapsAmount: BigDecimal = BigDecimal.ZERO
var zapPayments = mapOf<Note, Note?>() var zapPayments = mapOf<Note, Note?>()
private set private set
@@ -265,6 +267,7 @@ open class Note(val idHex: String) {
reports = mapOf<User, List<Note>>() reports = mapOf<User, List<Note>>()
zaps = mapOf<Note, Note?>() zaps = mapOf<Note, Note?>()
zapPayments = mapOf<Note, Note?>() zapPayments = mapOf<Note, Note?>()
zapsAmount = BigDecimal.ZERO
relays = listOf<String>() relays = listOf<String>()
lastReactionsDownloadTime = emptyMap() lastReactionsDownloadTime = emptyMap()
@@ -311,9 +314,11 @@ open class Note(val idHex: String) {
fun removeZap(note: Note) { fun removeZap(note: Note) {
if (zaps[note] != null) { if (zaps[note] != null) {
zaps = zaps.minus(note) zaps = zaps.minus(note)
updateZapTotal()
liveSet?.innerZaps?.invalidateData() liveSet?.innerZaps?.invalidateData()
} else if (zaps.containsValue(note)) { } else if (zaps.containsValue(note)) {
zaps = zaps.filterValues { it != note } zaps = zaps.filterValues { it != note }
updateZapTotal()
liveSet?.innerZaps?.invalidateData() liveSet?.innerZaps?.invalidateData()
} }
} }
@@ -354,11 +359,13 @@ open class Note(val idHex: String) {
if (zapRequest !in zaps.keys) { if (zapRequest !in zaps.keys) {
val inserted = innerAddZap(zapRequest, zap) val inserted = innerAddZap(zapRequest, zap)
if (inserted) { if (inserted) {
updateZapTotal()
liveSet?.innerZaps?.invalidateData() liveSet?.innerZaps?.invalidateData()
} }
} else if (zaps[zapRequest] == null) { } else if (zaps[zapRequest] == null) {
val inserted = innerAddZap(zapRequest, zap) val inserted = innerAddZap(zapRequest, zap)
if (inserted) { if (inserted) {
updateZapTotal()
liveSet?.innerZaps?.invalidateData() liveSet?.innerZaps?.invalidateData()
} }
} }
@@ -478,44 +485,63 @@ open class Note(val idHex: String) {
}.flatten() }.flatten()
} }
fun zappedAmount(privKey: ByteArray?, walletServicePubkey: ByteArray?): BigDecimal { private fun updateZapTotal() {
// Regular Zap Receipts var sumOfAmounts = BigDecimal.ZERO
val completedZaps = zaps.asSequence()
.mapNotNull { it.value?.event } // Regular Zap Receipts
.filterIsInstance<LnZapEvent>() zaps.values.forEach {
.filter { it.amount != null } val noteEvent = it?.event
.associate { if (noteEvent is LnZapEvent) {
it.lnInvoice() to it.amount sumOfAmounts += noteEvent.amount ?: BigDecimal.ZERO
} }
.toMap() }
zapsAmount = sumOfAmounts
}
fun zappedAmountWithNWCPayments(privKey: ByteArray?, walletServicePubkey: ByteArray?): BigDecimal {
if (zapPayments.isEmpty()) return zapsAmount
var sumOfAmounts = zapsAmount
val invoiceSet = LinkedHashSet<String>(zaps.size + zapPayments.size)
zaps.forEach {
(it.value as? LnZapEvent)?.lnInvoice()?.let {
invoiceSet.add(it)
}
}
if (privKey != null && walletServicePubkey != null) {
zapPayments.forEach {
val noteEvent = (it.value?.event as? LnZapPaymentResponseEvent)?.response(
privKey,
walletServicePubkey
)
if (noteEvent is PayInvoiceSuccessResponse) {
val invoice = (it.key.event as? LnZapPaymentRequestEvent)?.lnInvoice(
privKey,
walletServicePubkey
)
val completedPayments = if (privKey != null && walletServicePubkey != null) {
// Payments confirmed by the User's Wallet
zapPayments
.asSequence()
.filter {
val response = (it.value?.event as? LnZapPaymentResponseEvent)?.response(privKey, walletServicePubkey)
response is PayInvoiceSuccessResponse
}
.associate {
val lnInvoice = (it.key.event as? LnZapPaymentRequestEvent)?.lnInvoice(privKey, walletServicePubkey)
val amount = try { val amount = try {
if (lnInvoice == null) { if (invoice == null) {
null null
} else { } else {
LnInvoiceUtil.getAmountInSats(lnInvoice) LnInvoiceUtil.getAmountInSats(invoice)
} }
} catch (e: java.lang.Exception) { } catch (e: java.lang.Exception) {
null null
} }
lnInvoice to amount
if (invoice != null && amount != null && !invoiceSet.contains(invoice)) {
invoiceSet.add(invoice)
sumOfAmounts += amount
}
} }
.toMap() }
} else {
emptyMap()
} }
return (completedZaps + completedPayments).values.filterNotNull().sumOf { it } return sumOfAmounts
} }
fun hasPledgeBy(user: User): Boolean { fun hasPledgeBy(user: User): Boolean {
@@ -626,6 +652,7 @@ open class Note(val idHex: String) {
boosts = emptyList() boosts = emptyList()
reports = emptyMap() reports = emptyMap()
zaps = emptyMap() zaps = emptyMap()
zapsAmount = BigDecimal.ZERO
} }
fun clearEOSE() { fun clearEOSE() {
@@ -205,11 +205,6 @@ fun CommentIcon(iconSize: Dp, tint: Color) {
) )
} }
@Composable
fun ViewCountIcon(iconSize: Dp, tint: Color = Color.Unspecified) {
ViewCountIcon(remember { Modifier.size(iconSize) }, tint)
}
@Composable @Composable
fun ViewCountIcon(modifier: Modifier, tint: Color = Color.Unspecified) { fun ViewCountIcon(modifier: Modifier, tint: Color = Color.Unspecified) {
Icon( Icon(
@@ -12,6 +12,7 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.togetherWith
import androidx.compose.animation.with import androidx.compose.animation.with
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.combinedClickable
@@ -44,6 +45,7 @@ import androidx.compose.runtime.MutableState
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
@@ -112,6 +114,7 @@ import kotlinx.collections.immutable.toImmutableMap
import kotlinx.collections.immutable.toImmutableSet import kotlinx.collections.immutable.toImmutableSet
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.math.BigDecimal import java.math.BigDecimal
import java.math.RoundingMode import java.math.RoundingMode
import java.text.DecimalFormat import java.text.DecimalFormat
@@ -195,60 +198,35 @@ private fun GenericInnerReactionRow(
six: @Composable () -> Unit six: @Composable () -> Unit
) { ) {
Row(verticalAlignment = CenterVertically, modifier = ReactionRowHeight) { Row(verticalAlignment = CenterVertically, modifier = ReactionRowHeight) {
val fullWeight = remember { Modifier.weight(1f) }
if (showReactionDetail) { if (showReactionDetail) {
Column( Row(
verticalArrangement = Arrangement.Center, verticalAlignment = CenterVertically,
modifier = ReactionRowExpandButton modifier = remember { ReactionRowExpandButton.then(fullWeight) }
) { ) {
Row(verticalAlignment = CenterVertically) { one()
one()
}
} }
} }
Column( Row(verticalAlignment = CenterVertically, modifier = fullWeight) {
verticalArrangement = Arrangement.Center, two()
modifier = remember { Modifier.weight(1f) }
) {
Row(verticalAlignment = CenterVertically) {
two()
}
} }
Column( Row(verticalAlignment = CenterVertically, modifier = fullWeight) {
verticalArrangement = Arrangement.Center, three()
modifier = remember { Modifier.weight(1f) }
) {
Row(verticalAlignment = CenterVertically) {
three()
}
} }
Column( Row(verticalAlignment = CenterVertically, modifier = fullWeight) {
verticalArrangement = Arrangement.Center, four()
modifier = remember { Modifier.weight(1f) }
) {
Row(verticalAlignment = CenterVertically) {
four()
}
} }
Column( Row(verticalAlignment = CenterVertically, modifier = fullWeight) {
verticalArrangement = Arrangement.Center, five()
modifier = remember { Modifier.weight(1f) }
) {
Row(verticalAlignment = CenterVertically) {
five()
}
} }
Column( Row(verticalAlignment = CenterVertically, modifier = fullWeight) {
verticalArrangement = Arrangement.Center, six()
modifier = remember { Modifier.weight(1f) }
) {
Row(verticalAlignment = CenterVertically) {
six()
}
} }
} }
} }
@@ -590,17 +568,12 @@ fun ReplyCounter(baseNote: Note, textColor: Color) {
SlidingAnimationCount(repliesState, textColor) SlidingAnimationCount(repliesState, textColor)
} }
@Composable
private fun SlidingAnimationCount(baseCount: MutableState<Int>, textColor: Color) {
SlidingAnimationCount(baseCount.value, textColor)
}
@OptIn(ExperimentalAnimationApi::class)
@Composable @Composable
private fun SlidingAnimationCount(baseCount: Int, textColor: Color) { private fun SlidingAnimationCount(baseCount: Int, textColor: Color) {
AnimatedContent<Int>( AnimatedContent<Int>(
targetState = baseCount, targetState = baseCount,
transitionSpec = AnimatedContentTransitionScope<Int>::transitionSpec transitionSpec = AnimatedContentTransitionScope<Int>::transitionSpec,
label = "SlidingAnimationCount"
) { count -> ) { count ->
TextCount(count, textColor) TextCount(count, textColor)
} }
@@ -612,11 +585,16 @@ private fun <S> AnimatedContentTransitionScope<S>.transitionSpec(): ContentTrans
} }
@ExperimentalAnimationApi @ExperimentalAnimationApi
val slideAnimation: ContentTransform = slideInVertically(animationSpec = tween(durationMillis = 100)) { height -> height } + fadeIn( val slideAnimation: ContentTransform =
animationSpec = tween(durationMillis = 100) (
) with slideOutVertically(animationSpec = tween(durationMillis = 100)) { height -> -height } + fadeOut( slideInVertically(animationSpec = tween(durationMillis = 100)) { height -> height } + fadeIn(
animationSpec = tween(durationMillis = 100) animationSpec = tween(durationMillis = 100)
) )
).togetherWith(
slideOutVertically(animationSpec = tween(durationMillis = 100)) { height -> -height } + fadeOut(
animationSpec = tween(durationMillis = 100)
)
)
@Composable @Composable
private fun TextCount(count: Int, textColor: Color) { private fun TextCount(count: Int, textColor: Color) {
@@ -630,11 +608,11 @@ private fun TextCount(count: Int, textColor: Color) {
} }
@Composable @Composable
@OptIn(ExperimentalAnimationApi::class)
private fun SlidingAnimationAmount(amount: MutableState<String>, textColor: Color) { private fun SlidingAnimationAmount(amount: MutableState<String>, textColor: Color) {
AnimatedContent( AnimatedContent(
targetState = amount.value, targetState = amount.value,
transitionSpec = AnimatedContentTransitionScope<String>::transitionSpec transitionSpec = AnimatedContentTransitionScope<String>::transitionSpec,
label = "SlidingAnimationAmount"
) { count -> ) { count ->
Text( Text(
text = count, text = count,
@@ -667,7 +645,9 @@ fun BoostReaction(
} }
} }
) { ) {
BoostIcon(baseNote, iconSize, grayTint, accountViewModel) ObserveBoostIcon(baseNote, accountViewModel) { hasBoosted ->
RepostedIcon(iconButtonModifier, if (hasBoosted) Color.Unspecified else grayTint)
}
if (wantsToBoost) { if (wantsToBoost) {
BoostTypeChoicePopup( BoostTypeChoicePopup(
@@ -692,20 +672,16 @@ fun BoostReaction(
} }
@Composable @Composable
fun BoostIcon(baseNote: Note, iconSize: Dp = Size20dp, grayTint: Color, accountViewModel: AccountViewModel) { fun ObserveBoostIcon(baseNote: Note, accountViewModel: AccountViewModel, inner: @Composable (Boolean) -> Unit) {
val iconTint by remember(baseNote) { val hasBoosted by remember(baseNote) {
baseNote.live().boosts.map { baseNote.live().boosts.map {
if (it.note.isBoostedBy(accountViewModel.userProfile())) Color.Unspecified else grayTint it.note.isBoostedBy(accountViewModel.userProfile())
}.distinctUntilChanged() }.distinctUntilChanged()
}.observeAsState( }.observeAsState(
if (baseNote.isBoostedBy(accountViewModel.userProfile())) Color.Unspecified else grayTint baseNote.isBoostedBy(accountViewModel.userProfile())
) )
val iconModifier = remember { inner(hasBoosted)
Modifier.size(iconSize)
}
RepostedIcon(iconModifier, iconTint)
} }
@Composable @Composable
@@ -760,10 +736,20 @@ fun LikeReaction(
} }
) )
) { ) {
LikeIcon(baseNote, iconFontSize, heartSize, grayTint, accountViewModel) ObserveLikeIcon(baseNote, accountViewModel) { reactionType ->
Crossfade(targetState = reactionType.value, label = "LikeIcon") {
if (it != null) {
RenderReactionType(it, heartSize, iconFontSize)
} else {
LikeIcon(heartSize, grayTint)
}
}
}
} }
LikeText(baseNote, grayTint) ObserveLikeText(baseNote) { reactionCount ->
SlidingAnimationCount(reactionCount, grayTint)
}
if (wantsToChangeReactionSymbol) { if (wantsToChangeReactionSymbol) {
UpdateReactionTypeDialog( UpdateReactionTypeDialog(
@@ -790,44 +776,26 @@ fun LikeReaction(
} }
@Composable @Composable
fun LikeIcon( fun ObserveLikeIcon(
baseNote: Note, baseNote: Note,
iconFontSize: TextUnit = Font14SP, accountViewModel: AccountViewModel,
iconSize: Dp = Size20dp, inner: @Composable (MutableState<String?>) -> Unit
grayTint: Color,
accountViewModel: AccountViewModel
) { ) {
val reactionType = remember(baseNote) { val reactionType = remember(baseNote) {
mutableStateOf<String?>(null) mutableStateOf<String?>(null)
} }
val scope = rememberCoroutineScope() val reactionsState by baseNote.live().reactions.observeAsState()
WatchReactionTypeForNote(baseNote, accountViewModel) { newReactionType -> LaunchedEffect(key1 = reactionsState) {
if (reactionType.value != newReactionType) { accountViewModel.loadReactionTo(reactionsState?.note) { newReactionType ->
scope.launch(Dispatchers.Main) { if (reactionType.value != newReactionType) {
reactionType.value = newReactionType reactionType.value = newReactionType
} }
} }
} }
Crossfade(targetState = reactionType) { inner(reactionType)
val value = it.value
if (value != null) {
RenderReactionType(value, iconSize, iconFontSize)
} else {
LikeIcon(iconSize, grayTint)
}
}
}
@Composable
private fun WatchReactionTypeForNote(baseNote: Note, accountViewModel: AccountViewModel, onNewReactionType: (String?) -> Unit) {
val reactionsState by baseNote.live().reactions.observeAsState()
LaunchedEffect(key1 = reactionsState) {
accountViewModel.loadReactionTo(reactionsState?.note, onNewReactionType)
}
} }
@Composable @Composable
@@ -863,10 +831,10 @@ private fun RenderReactionType(
} }
@Composable @Composable
fun LikeText(baseNote: Note, grayTint: Color) { fun ObserveLikeText(baseNote: Note, inner: @Composable (Int) -> Unit) {
val reactionCount by baseNote.live().reactionCount.observeAsState(0) val reactionCount by baseNote.live().reactionCount.observeAsState(0)
SlidingAnimationCount(reactionCount, grayTint) inner(reactionCount)
} }
private fun likeClick( private fun likeClick(
@@ -919,7 +887,7 @@ fun ZapReaction(
val context = LocalContext.current val context = LocalContext.current
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
var zappingProgress by remember { mutableStateOf(0f) } var zappingProgress by remember { mutableFloatStateOf(0f) }
Row( Row(
verticalAlignment = CenterVertically, verticalAlignment = CenterVertically,
@@ -942,7 +910,7 @@ fun ZapReaction(
onMultipleChoices = { onMultipleChoices = {
wantsToZap = true wantsToZap = true
}, },
onError = { title, message -> onError = { _, message ->
scope.launch { scope.launch {
zappingProgress = 0f zappingProgress = 0f
showErrorMessageDialog = message showErrorMessageDialog = message
@@ -973,7 +941,7 @@ fun ZapReaction(
wantsToZap = false wantsToZap = false
wantsToChangeZapAmount = true wantsToChangeZapAmount = true
}, },
onError = { title, message -> onError = { _, message ->
scope.launch { scope.launch {
zappingProgress = 0f zappingProgress = 0f
showErrorMessageDialog = message showErrorMessageDialog = message
@@ -1033,7 +1001,7 @@ fun ZapReaction(
if (wantsToSetCustomZap) { if (wantsToSetCustomZap) {
ZapCustomDialog( ZapCustomDialog(
onClose = { wantsToSetCustomZap = false }, onClose = { wantsToSetCustomZap = false },
onError = { title, message -> onError = { _, message ->
scope.launch { scope.launch {
zappingProgress = 0f zappingProgress = 0f
showErrorMessageDialog = message showErrorMessageDialog = message
@@ -1058,22 +1026,31 @@ fun ZapReaction(
CircularProgressIndicator( CircularProgressIndicator(
progress = animateFloatAsState( progress = animateFloatAsState(
targetValue = zappingProgress, targetValue = zappingProgress,
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
label = "ZapIconIndicator"
).value, ).value,
modifier = remember { Modifier.size(animationSize) }, modifier = remember { Modifier.size(animationSize) },
strokeWidth = 2.dp strokeWidth = 2.dp
) )
} else { } else {
ZapIcon( ObserveZapIcon(
baseNote, baseNote,
iconSize,
grayTint,
accountViewModel accountViewModel
) ) { wasZappedByLoggedInUser ->
Crossfade(targetState = wasZappedByLoggedInUser.value, label = "ZapIcon") {
if (it) {
ZappedIcon(iconSize)
} else {
ZapIcon(iconSize, grayTint)
}
}
}
} }
} }
ZapAmountText(baseNote, grayTint, accountViewModel) ObserveZapAmountText(baseNote, accountViewModel) { zapAmountTxt ->
SlidingAnimationAmount(zapAmountTxt, grayTint)
}
} }
private fun zapClick( private fun zapClick(
@@ -1115,98 +1092,72 @@ private fun zapClick(
} }
@Composable @Composable
private fun ZapIcon( private fun ObserveZapIcon(
baseNote: Note, baseNote: Note,
iconSize: Dp, accountViewModel: AccountViewModel,
grayTint: Color, inner: @Composable (MutableState<Boolean>) -> Unit
accountViewModel: AccountViewModel
) { ) {
val wasZappedByLoggedInUser = remember { mutableStateOf(false) } val wasZappedByLoggedInUser = remember { mutableStateOf(false) }
val scope = rememberCoroutineScope()
if (!wasZappedByLoggedInUser.value) { if (!wasZappedByLoggedInUser.value) {
WatchZapsForNote(baseNote, accountViewModel) { newWasZapped -> val zapsState by baseNote.live().zaps.observeAsState()
if (wasZappedByLoggedInUser.value != newWasZapped) {
scope.launch(Dispatchers.Main) { LaunchedEffect(key1 = zapsState) {
accountViewModel.calculateIfNoteWasZappedByAccount(baseNote) { newWasZapped ->
if (wasZappedByLoggedInUser.value != newWasZapped) {
wasZappedByLoggedInUser.value = newWasZapped wasZappedByLoggedInUser.value = newWasZapped
} }
} }
} }
} }
Crossfade(targetState = wasZappedByLoggedInUser) { inner(wasZappedByLoggedInUser)
if (it.value) {
ZappedIcon(iconSize)
} else {
ZapIcon(iconSize, grayTint)
}
}
} }
@Composable @Composable
private fun WatchZapsForNote(baseNote: Note, accountViewModel: AccountViewModel, onWasZapped: (Boolean) -> Unit) { private fun ObserveZapAmountText(
baseNote: Note,
accountViewModel: AccountViewModel,
inner: @Composable (MutableState<String>) -> Unit
) {
val zapAmountTxt = remember(baseNote) {
mutableStateOf(showAmount(baseNote.zapsAmount))
}
val zapsState by baseNote.live().zaps.observeAsState() val zapsState by baseNote.live().zaps.observeAsState()
LaunchedEffect(key1 = zapsState) { LaunchedEffect(key1 = zapsState) {
accountViewModel.calculateIfNoteWasZappedByAccount(baseNote, onWasZapped) accountViewModel.calculateZapAmount(baseNote) { newZapAmount ->
} if (zapAmountTxt.value != newZapAmount) {
} withContext(Dispatchers.Main) {
zapAmountTxt.value = newZapAmount
@Composable }
private fun ZapAmountText(
baseNote: Note,
grayTint: Color,
accountViewModel: AccountViewModel
) {
val zapAmountTxt = remember(baseNote) { mutableStateOf("") }
val scope = rememberCoroutineScope()
WatchZapAmountsForNote(baseNote, accountViewModel) { newZapAmount ->
if (zapAmountTxt.value != newZapAmount) {
scope.launch(Dispatchers.Main) {
zapAmountTxt.value = newZapAmount
} }
} }
} }
SlidingAnimationAmount(zapAmountTxt, grayTint) inner(zapAmountTxt)
}
@Composable
fun WatchZapAmountsForNote(baseNote: Note, accountViewModel: AccountViewModel, onZapAmount: (String) -> Unit) {
val zapsState by baseNote.live().zaps.observeAsState()
LaunchedEffect(key1 = zapsState) {
accountViewModel.calculateZapAmount(baseNote, onZapAmount)
}
} }
@Composable @Composable
fun ViewCountReaction( fun ViewCountReaction(
note: Note, note: Note,
grayTint: Color, grayTint: Color,
barChartSize: Dp = Size19dp, barChartModifier: Modifier = Modifier.size(Size19dp),
numberSize: Dp = Size24dp, numberSizeModifier: Modifier = Modifier.height(Size24dp),
viewCountColorFilter: ColorFilter viewCountColorFilter: ColorFilter
) { ) {
ViewCountIcon(barChartSize, grayTint) ViewCountIcon(barChartModifier, grayTint)
DrawViewCount(note, numberSize, viewCountColorFilter) DrawViewCount(note, numberSizeModifier, viewCountColorFilter)
} }
@Composable @Composable
private fun DrawViewCount( private fun DrawViewCount(
note: Note, note: Note,
numberSize: Dp = Size24dp, iconModifier: Modifier = Modifier,
viewCountColorFilter: ColorFilter viewCountColorFilter: ColorFilter
) { ) {
val context = LocalContext.current val context = LocalContext.current
val iconModifier = remember {
Modifier.height(numberSize)
}
AsyncImage( AsyncImage(
model = remember(note) { model = remember(note) {
ImageRequest.Builder(context) ImageRequest.Builder(context)
@@ -201,9 +201,13 @@ class AccountViewModel(val account: Account, val settings: SettingsState) : View
return account.calculateZappedAmount(zappedNote) return account.calculateZappedAmount(zappedNote)
} }
fun calculateZapAmount(zappedNote: Note, onZapAmount: (String) -> Unit) { suspend fun calculateZapAmount(zappedNote: Note, onZapAmount: suspend (String) -> Unit) {
viewModelScope.launch(Dispatchers.IO) { if (zappedNote.zapPayments.isNotEmpty()) {
onZapAmount(showAmount(account.calculateZappedAmount(zappedNote))) viewModelScope.launch(Dispatchers.IO) {
onZapAmount(showAmount(account.calculateZappedAmount(zappedNote)))
}
} else {
onZapAmount(showAmount(zappedNote.zapsAmount))
} }
} }
@@ -437,6 +437,6 @@ fun ReactionsColumn(baseNote: Note, accountViewModel: AccountViewModel, nav: (St
} }
LikeReaction(baseNote, grayTint = MaterialTheme.colorScheme.onBackground, accountViewModel, nav, iconSize = 40.dp, heartSize = Size35dp, 28.sp) LikeReaction(baseNote, grayTint = MaterialTheme.colorScheme.onBackground, accountViewModel, nav, iconSize = 40.dp, heartSize = Size35dp, 28.sp)
ZapReaction(baseNote, grayTint = MaterialTheme.colorScheme.onBackground, accountViewModel, iconSize = 40.dp, animationSize = Size35dp, nav = nav) ZapReaction(baseNote, grayTint = MaterialTheme.colorScheme.onBackground, accountViewModel, iconSize = 40.dp, animationSize = Size35dp, nav = nav)
ViewCountReaction(baseNote, grayTint = MaterialTheme.colorScheme.onBackground, barChartSize = 39.dp, viewCountColorFilter = MaterialTheme.colorScheme.onBackgroundColorFilter) ViewCountReaction(baseNote, grayTint = MaterialTheme.colorScheme.onBackground, barChartModifier = Modifier.size(39.dp), viewCountColorFilter = MaterialTheme.colorScheme.onBackgroundColorFilter)
} }
} }