Fixing stack overflow with more than 200 zaps in a single note.

This commit is contained in:
Vitor Pamplona
2024-02-25 17:53:15 -05:00
parent 6a7d33e58f
commit de17aab7ab
3 changed files with 44 additions and 23 deletions
@@ -729,7 +729,7 @@ class Account(
zapResponseEvent.response(signer, onReady) zapResponseEvent.response(signer, onReady)
} }
fun calculateIfNoteWasZappedByAccount( suspend fun calculateIfNoteWasZappedByAccount(
zappedNote: Note?, zappedNote: Note?,
onWasZapped: () -> Unit, onWasZapped: () -> Unit,
) { ) {
@@ -56,6 +56,7 @@ import com.vitorpamplona.quartz.events.LiveActivitiesEvent
import com.vitorpamplona.quartz.events.LnZapEvent import com.vitorpamplona.quartz.events.LnZapEvent
import com.vitorpamplona.quartz.events.LnZapPaymentRequestEvent import com.vitorpamplona.quartz.events.LnZapPaymentRequestEvent
import com.vitorpamplona.quartz.events.LnZapPaymentResponseEvent import com.vitorpamplona.quartz.events.LnZapPaymentResponseEvent
import com.vitorpamplona.quartz.events.LnZapRequestEvent
import com.vitorpamplona.quartz.events.LongTextNoteEvent import com.vitorpamplona.quartz.events.LongTextNoteEvent
import com.vitorpamplona.quartz.events.PayInvoiceSuccessResponse import com.vitorpamplona.quartz.events.PayInvoiceSuccessResponse
import com.vitorpamplona.quartz.events.RepostEvent import com.vitorpamplona.quartz.events.RepostEvent
@@ -66,10 +67,13 @@ import com.vitorpamplona.quartz.utils.containsAny
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull
import java.math.BigDecimal import java.math.BigDecimal
import java.time.Instant import java.time.Instant
import java.time.ZoneId import java.time.ZoneId
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import kotlin.coroutines.resume
@Stable @Stable
class AddressableNote(val address: ATag) : Note(address.toTag()) { class AddressableNote(val address: ATag) : Note(address.toTag()) {
@@ -521,7 +525,7 @@ open class Note(val idHex: String) {
} }
} }
private fun recursiveIsZappedByCalculation( private suspend fun isZappedByCalculation(
option: Int?, option: Int?,
user: User, user: User,
account: Account, account: Account,
@@ -532,48 +536,65 @@ open class Note(val idHex: String) {
return return
} }
val next = remainingZapEvents.first() remainingZapEvents.forEach { next ->
val zapRequest = next.first.event as LnZapRequestEvent
val zapEvent = next.second?.event as? LnZapEvent
if (next.first.author?.pubkeyHex == user.pubkeyHex) { if (!zapRequest.isPrivateZap()) {
onWasZappedByAuthor() // public events
} else { if (zapRequest.pubKey == user.pubkeyHex && (option == null || option == zapEvent?.zappedPollOption())) {
account.decryptZapContentAuthor(next.first) {
if (
it.pubKey == user.pubkeyHex &&
(option == null || option == (it as? LnZapEvent)?.zappedPollOption())
) {
onWasZappedByAuthor() onWasZappedByAuthor()
return
}
} else {
// private events
// if has already decrypted
val privateZap = zapRequest.cachedPrivateZap()
if (privateZap != null) {
if (privateZap.pubKey == user.pubkeyHex && (option == null || option == zapEvent?.zappedPollOption())) {
onWasZappedByAuthor()
return
}
} else { } else {
recursiveIsZappedByCalculation( if (account.isWriteable()) {
option, val result =
user, withTimeoutOrNull(1000) {
account, suspendCancellableCoroutine { continuation ->
remainingZapEvents.minus(next), zapRequest.decryptPrivateZap(account.signer) {
onWasZappedByAuthor, continuation.resume(it)
) }
}
}
if (result?.pubKey == user.pubkeyHex && (option == null || option == zapEvent?.zappedPollOption())) {
onWasZappedByAuthor()
return
}
}
} }
} }
} }
} }
fun isZappedBy( suspend fun isZappedBy(
user: User, user: User,
account: Account, account: Account,
onWasZappedByAuthor: () -> Unit, onWasZappedByAuthor: () -> Unit,
) { ) {
recursiveIsZappedByCalculation(null, user, account, zaps.toList(), onWasZappedByAuthor) isZappedByCalculation(null, user, account, zaps.toList(), onWasZappedByAuthor)
if (account.userProfile() == user) { if (account.userProfile() == user) {
recursiveIsPaidByCalculation(account, zapPayments.toList(), onWasZappedByAuthor) recursiveIsPaidByCalculation(account, zapPayments.toList(), onWasZappedByAuthor)
} }
} }
fun isZappedBy( suspend fun isZappedBy(
option: Int?, option: Int?,
user: User, user: User,
account: Account, account: Account,
onWasZappedByAuthor: () -> Unit, onWasZappedByAuthor: () -> Unit,
) { ) {
recursiveIsZappedByCalculation(option, user, account, zaps.toList(), onWasZappedByAuthor) isZappedByCalculation(option, user, account, zaps.toList(), onWasZappedByAuthor)
} }
fun getReactionBy(user: User): String? { fun getReactionBy(user: User): String? {
@@ -209,7 +209,7 @@ class PollNoteViewModel : ViewModel() {
return false return false
} }
fun isPollOptionZappedBy( suspend fun isPollOptionZappedBy(
option: Int, option: Int,
user: User, user: User,
onWasZappedByAuthor: () -> Unit, onWasZappedByAuthor: () -> Unit,