From 87fafd9451bab81832c4e6ecd8793330c4e22644 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Tue, 19 Mar 2024 19:30:49 -0400 Subject: [PATCH] Reducing the amount of co-routines being launched in each LiveData update. --- .../amethyst/ui/note/ReactionsRow.kt | 52 +++++++------- .../ui/screen/loggedIn/AccountViewModel.kt | 68 +++++++++++-------- 2 files changed, 69 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt index 49c4f39bd..8fde12944 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt @@ -67,6 +67,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue @@ -98,6 +99,7 @@ import coil.request.CachePolicy import coil.request.ImageRequest import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.model.zap import com.vitorpamplona.amethyst.service.ZapPaymentHandler import com.vitorpamplona.amethyst.ui.actions.NewPostView import com.vitorpamplona.amethyst.ui.components.GenericLoadable @@ -663,11 +665,11 @@ fun TextCount( @Composable fun SlidingAnimationAmount( - amount: MutableState, + amount: String, textColor: Color, ) { AnimatedContent( - targetState = amount.value, + targetState = amount, transitionSpec = AnimatedContentTransitionScope::transitionSpec, label = "SlidingAnimationAmount", ) { count -> @@ -788,7 +790,7 @@ fun LikeReaction( ), ) { ObserveLikeIcon(baseNote, accountViewModel) { reactionType -> - Crossfade(targetState = reactionType.value, label = "LikeIcon") { + Crossfade(targetState = reactionType, label = "LikeIcon") { if (it != null) { RenderReactionType(it, heartSizeModifier, iconFontSize) } else { @@ -826,19 +828,17 @@ fun LikeReaction( fun ObserveLikeIcon( baseNote: Note, accountViewModel: AccountViewModel, - inner: @Composable (MutableState) -> Unit, + inner: @Composable (String?) -> Unit, ) { - val reactionType = remember(baseNote) { mutableStateOf(null) } - val reactionsState by baseNote.live().reactions.observeAsState() - LaunchedEffect(key1 = reactionsState) { - accountViewModel.loadReactionTo(reactionsState?.note) { newReactionType -> - if (reactionType.value != newReactionType) { - reactionType.value = newReactionType + val reactionType by + produceState(initialValue = null as String?, key1 = reactionsState) { + val newReactionType = accountViewModel.loadReactionTo(reactionsState?.note) + if (value != newReactionType) { + value = newReactionType } } - } inner(reactionType) } @@ -1119,9 +1119,11 @@ fun ObserveZapIcon( val zapsState by baseNote.live().zaps.observeAsState() LaunchedEffect(key1 = zapsState) { - accountViewModel.calculateIfNoteWasZappedByAccount(baseNote) { newWasZapped -> - if (wasZappedByLoggedInUser.value != newWasZapped) { - wasZappedByLoggedInUser.value = newWasZapped + if (zapsState?.note?.zapPayments?.isNotEmpty() == true || zapsState?.note?.zaps?.isNotEmpty() == true) { + accountViewModel.calculateIfNoteWasZappedByAccount(baseNote) { newWasZapped -> + if (wasZappedByLoggedInUser.value != newWasZapped) { + wasZappedByLoggedInUser.value = newWasZapped + } } } } @@ -1134,20 +1136,24 @@ fun ObserveZapIcon( fun ObserveZapAmountText( baseNote: Note, accountViewModel: AccountViewModel, - inner: @Composable (MutableState) -> Unit, + inner: @Composable (String) -> Unit, ) { - val zapAmountTxt = remember(baseNote) { mutableStateOf(showAmount(baseNote.zapsAmount)) } val zapsState by baseNote.live().zaps.observeAsState() - LaunchedEffect(key1 = zapsState) { - accountViewModel.calculateZapAmount(baseNote) { newZapAmount -> - if (zapAmountTxt.value != newZapAmount) { - zapAmountTxt.value = newZapAmount + if (zapsState?.note?.zapPayments?.isNotEmpty() == true) { + val zapAmountTxt by + produceState(initialValue = showAmount(baseNote.zapsAmount), key1 = baseNote) { + accountViewModel.calculateZapAmount(baseNote) { newZapAmount -> + if (value != newZapAmount) { + value = newZapAmount + } + } } - } - } - inner(zapAmountTxt) + inner(zapAmountTxt) + } else { + inner(showAmount(zapsState?.note?.zapsAmount)) + } } @Composable diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index 394f662c4..7e5f9d8a4 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -221,21 +221,21 @@ class AccountViewModel(val account: Account, val settings: SettingsState) : View viewModelScope.launch(Dispatchers.IO) { account.delete(account.boostsTo(note)) } } - fun calculateIfNoteWasZappedByAccount( + suspend fun calculateIfNoteWasZappedByAccount( zappedNote: Note, onWasZapped: (Boolean) -> Unit, ) { - viewModelScope.launch(Dispatchers.Default) { + withContext(Dispatchers.IO) { account.calculateIfNoteWasZappedByAccount(zappedNote) { onWasZapped(true) } } } - fun calculateZapAmount( + suspend fun calculateZapAmount( zappedNote: Note, onZapAmount: (String) -> Unit, ) { if (zappedNote.zapPayments.isNotEmpty()) { - viewModelScope.launch(Dispatchers.IO) { + withContext(Dispatchers.IO) { account.calculateZappedAmount(zappedNote) { onZapAmount(showAmount(it)) } } } else { @@ -243,28 +243,45 @@ class AccountViewModel(val account: Account, val settings: SettingsState) : View } } - fun calculateZapraiser( + suspend fun calculateZapraiser( zappedNote: Note, onZapraiserStatus: (ZapraiserStatus) -> Unit, ) { - viewModelScope.launch(Dispatchers.IO) { - val zapraiserAmount = zappedNote.event?.zapraiserAmount() ?: 0 - account.calculateZappedAmount(zappedNote) { newZapAmount -> - var percentage = newZapAmount.div(zapraiserAmount.toBigDecimal()).toFloat() + val zapraiserAmount = zappedNote.event?.zapraiserAmount() ?: 0 + if (zappedNote.zapPayments.isNotEmpty()) { + withContext(Dispatchers.IO) { + account.calculateZappedAmount(zappedNote) { newZapAmount -> + var percentage = newZapAmount.div(zapraiserAmount.toBigDecimal()).toFloat() - if (percentage > 1) { - percentage = 1f - } - - val newZapraiserProgress = percentage - val newZapraiserLeft = - if (percentage > 0.99) { - "0" - } else { - showAmount((zapraiserAmount * (1 - percentage)).toBigDecimal()) + if (percentage > 1) { + percentage = 1f } - onZapraiserStatus(ZapraiserStatus(newZapraiserProgress, newZapraiserLeft)) + + val newZapraiserProgress = percentage + val newZapraiserLeft = + if (percentage > 0.99) { + "0" + } else { + showAmount((zapraiserAmount * (1 - percentage)).toBigDecimal()) + } + onZapraiserStatus(ZapraiserStatus(newZapraiserProgress, newZapraiserLeft)) + } } + } else { + var percentage = zappedNote.zapsAmount.div(zapraiserAmount.toBigDecimal()).toFloat() + + if (percentage > 1) { + percentage = 1f + } + + val newZapraiserProgress = percentage + val newZapraiserLeft = + if (percentage > 0.99) { + "0" + } else { + showAmount((zapraiserAmount * (1 - percentage)).toBigDecimal()) + } + onZapraiserStatus(ZapraiserStatus(newZapraiserProgress, newZapraiserLeft)) } } @@ -776,15 +793,10 @@ class AccountViewModel(val account: Account, val settings: SettingsState) : View viewModelScope.launch(Dispatchers.IO) { UrlCachedPreviewer.previewInfo(url, onResult) } } - fun loadReactionTo( - note: Note?, - onNewReactionType: (String?) -> Unit, - ) { - if (note == null) return + suspend fun loadReactionTo(note: Note?): String? { + if (note == null) return null - viewModelScope.launch(Dispatchers.Default) { - onNewReactionType(note.getReactionBy(userProfile())) - } + return note.getReactionBy(userProfile()) } fun verifyNip05(