Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
signalapp
GitHub Repository: signalapp/Signal-iOS
Path: blob/main/Signal/src/ViewControllers/Donations/DonationPaymentDetailsViewController+GiftDonation.swift
1 views
//
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

import Foundation
import SignalServiceKit

extension DonationPaymentDetailsViewController {
    /// Make a gift donation.
    ///
    /// See also: code for other payment methods, such as Apple Pay.
    func giftDonation(
        with creditOrDebitCard: Stripe.PaymentMethod.CreditOrDebitCard,
        in thread: TSContactThread,
        messageText: String,
    ) {
        Logger.info("[Gifting] Starting gift donation with credit/debit card")

        Task {
            do {
                try await DonationViewsUtil.wrapInProgressView(
                    from: self,
                    operation: {
                        try await throwIfAlreadySendingGift(threadUniqueId: thread.uniqueId)

                        let preparedPayment = try await DonationViewsUtil.Gifts.prepareToPay(
                            amount: self.donationAmount,
                            creditOrDebitCard: creditOrDebitCard,
                        )

                        guard await DonationViewsUtil.Gifts.showSafetyNumberConfirmationIfNecessary(for: thread) else {
                            throw DonationViewsUtil.Gifts.SendGiftError.userCanceledBeforeChargeCompleted
                        }

                        try await DonationViewsUtil.Gifts.startJob(
                            amount: self.donationAmount,
                            preparedPayment: preparedPayment,
                            thread: thread,
                            messageText: messageText,
                            databaseStorage: SSKEnvironment.shared.databaseStorageRef,
                            blockingManager: SSKEnvironment.shared.blockingManagerRef,
                        )
                    },
                )
                Logger.info("[Gifting] Gifting card donation finished")
                self.onFinished(nil)
            } catch {
                owsPrecondition(error is DonationViewsUtil.Gifts.SendGiftError)
                Logger.warn("[Gifting] Gifting card donation failed")
                self.onFinished(error)
            }
        }
    }

    private nonisolated func throwIfAlreadySendingGift(threadUniqueId: String) async throws {
        try SSKEnvironment.shared.databaseStorageRef.read { transaction in
            try DonationViewsUtil.Gifts.throwIfAlreadySendingGift(
                threadId: threadUniqueId,
                transaction: transaction,
            )
        }
    }
}