mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-15 17:40:43 +00:00
ios, android: tell the buyer once a run when a swept purchase cannot be handed over (#7674)
This commit is contained in:
@@ -111,6 +111,8 @@ final class BadgeStore: ObservableObject {
|
||||
// set once presentUnfinished has read the store: until then, an Ask to Buy approved while the app was
|
||||
// closed, or a purchase it died before handing over, are both unknown, so canBuy refuses to buy again
|
||||
@Published private var reconciledOnce = false
|
||||
// the sweep has no buyer waiting and runs at four triggers, so a failure that cannot clear is told once a run
|
||||
private var sweepFailureShown = false
|
||||
private var transactionUpdates: Task<Void, Never>? = nil
|
||||
|
||||
private init() {}
|
||||
@@ -321,9 +323,17 @@ final class BadgeStore: ObservableObject {
|
||||
if !badgeOneTimeProductIds.contains(receipt.productId) {
|
||||
await receipt.transaction.finish()
|
||||
} else if receipt.signatureVerified {
|
||||
// no buyer to tell: the receipt stays unfinished and the next sweep hands it over again
|
||||
// the receipt stays unfinished, so the next sweep hands it over again
|
||||
do { try await handOver(receipt) } catch let error {
|
||||
logger.error("BadgeStore.reconcile: \(responseError(error))")
|
||||
await MainActor.run {
|
||||
// showAlert presents on the top view controller, which the launch sweep can precede;
|
||||
// an alert with nowhere to go must not spend the one this run gets
|
||||
if !sweepFailureShown, getTopViewController() != nil {
|
||||
sweepFailureShown = true
|
||||
showAlert(NSLocalizedString("Purchase error", comment: "alert title"), message: redeemErrorText(error, purchase: true))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-1
@@ -161,6 +161,8 @@ object BadgeStore {
|
||||
// set once presentUnfinished has read the store, or failed to: until then, a slow payment completed while
|
||||
// the app was closed, or a purchase it died before handing over, are both unknown, so canBuy refuses
|
||||
private val reconciledOnce = mutableStateOf(false)
|
||||
// the sweep has no buyer waiting and runs at four triggers, so a failure that cannot clear is told once a run
|
||||
private var sweepFailureShown = false
|
||||
|
||||
fun purchaseState(userId: Long?): BadgePurchaseState? {
|
||||
if (!badgeStoreAvailable) return null
|
||||
@@ -372,12 +374,22 @@ object BadgeStore {
|
||||
when (outcome) {
|
||||
is BadgePurchaseOutcome.Purchased ->
|
||||
if (outcome.receipt.productId !in badgeOneTimeProductIds) finish(outcome.receipt)
|
||||
// no buyer to tell: the purchase stays unfinished and the next sweep hands it over again
|
||||
// the purchase stays unfinished, so the next sweep hands it over again
|
||||
else try {
|
||||
handOver(outcome.receipt)
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
Log.e(TAG, "BadgeStore.reconcile: ${e.stackTraceToString()}")
|
||||
withContext(Dispatchers.Main) {
|
||||
if (!sweepFailureShown) {
|
||||
sweepFailureShown = true
|
||||
AlertManager.shared.showAlertMsg(
|
||||
title = generalGetString(MR.strings.badges_purchase_error),
|
||||
text = if (e is BadgeStoreError.ApiError) chatModel.controller.redeemErrorText(e.err, purchase = true)
|
||||
else "${generalGetString(MR.strings.error_prefix)}: ${e.message ?: e}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
is BadgePurchaseOutcome.Pending ->
|
||||
if (outcome.invoiceId != null) withContext(Dispatchers.Main) { waitingForApproval.value += outcome.invoiceId }
|
||||
|
||||
Reference in New Issue
Block a user