This change should have no user impact. `DonationViewController` is now `DonationSettingsViewController`. I think this is a better name on its own, but it'll seem even better after upcoming change.
153 lines
5.9 KiB
Swift
153 lines
5.9 KiB
Swift
//
|
|
// Copyright 2022 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import Foundation
|
|
import SignalMessaging
|
|
import SignalServiceKit
|
|
|
|
extension ConversationViewController {
|
|
|
|
func willWrapGift(_ messageUniqueId: String) -> Bool {
|
|
// If a gift is unwrapped at roughly the same we're reloading the
|
|
// conversation for an unrelated reason, there's a chance we'll try to
|
|
// re-wrap a gift that was just unwrapped. This provides an opportunity to
|
|
// override that behavior.
|
|
return !self.viewState.unwrappedGiftMessageIds.contains(messageUniqueId)
|
|
}
|
|
|
|
func willShakeGift(_ messageUniqueId: String) -> Bool {
|
|
let (justInserted, _) = self.viewState.shakenGiftMessageIds.insert(messageUniqueId)
|
|
return justInserted
|
|
}
|
|
|
|
func willUnwrapGift(_ itemViewModel: CVItemViewModelImpl) {
|
|
self.viewState.unwrappedGiftMessageIds.insert(itemViewModel.interaction.uniqueId)
|
|
self.markGiftAsOpened(itemViewModel.interaction)
|
|
}
|
|
|
|
private func markGiftAsOpened(_ interaction: TSInteraction) {
|
|
guard let outgoingMessage = interaction as? TSOutgoingMessage else {
|
|
return
|
|
}
|
|
guard outgoingMessage.giftBadge?.redemptionState == .pending else {
|
|
return
|
|
}
|
|
self.databaseStorage.asyncWrite { transaction in
|
|
outgoingMessage.anyUpdateOutgoingMessage(transaction: transaction) {
|
|
$0.giftBadge?.redemptionState = .opened
|
|
}
|
|
|
|
self.receiptManager.outgoingGiftWasOpened(outgoingMessage, transaction: transaction)
|
|
}
|
|
}
|
|
|
|
func didTapGiftBadge(_ itemViewModel: CVItemViewModelImpl, profileBadge: ProfileBadge, isExpired: Bool, isRedeemed: Bool) {
|
|
AssertIsOnMainThread()
|
|
|
|
let viewControllerToPresent: UIViewController
|
|
|
|
switch itemViewModel.interaction {
|
|
case let incomingMessage as TSIncomingMessage:
|
|
viewControllerToPresent = self.incomingGiftSheet(
|
|
incomingMessage: incomingMessage,
|
|
profileBadge: profileBadge,
|
|
isExpired: isExpired,
|
|
isRedeemed: isRedeemed
|
|
)
|
|
|
|
case is TSOutgoingMessage:
|
|
guard let thread = thread as? TSContactThread else {
|
|
owsFailDebug("Clicked a gift badge that wasn't in a contact thread")
|
|
return
|
|
}
|
|
|
|
viewControllerToPresent = BadgeGiftingThanksSheet(thread: thread, badge: profileBadge)
|
|
|
|
default:
|
|
owsFailDebug("Tapped on gift that's not a message")
|
|
return
|
|
}
|
|
|
|
self.present(viewControllerToPresent, animated: true)
|
|
}
|
|
|
|
private func incomingGiftSheet(
|
|
incomingMessage: TSIncomingMessage,
|
|
profileBadge: ProfileBadge,
|
|
isExpired: Bool,
|
|
isRedeemed: Bool
|
|
) -> UIViewController {
|
|
if isExpired {
|
|
let mode: BadgeExpirationSheetState.Mode
|
|
if isRedeemed {
|
|
let hasCurrentSubscription = self.databaseStorage.read { transaction -> Bool in
|
|
self.subscriptionManager.hasCurrentSubscription(transaction: transaction)
|
|
}
|
|
mode = .giftBadgeExpired(hasCurrentSubscription: hasCurrentSubscription)
|
|
} else {
|
|
let fullName = self.databaseStorage.read { transaction -> String in
|
|
let authorAddress = incomingMessage.authorAddress
|
|
return self.contactsManager.displayName(for: authorAddress, transaction: transaction)
|
|
}
|
|
mode = .giftNotRedeemed(fullName: fullName)
|
|
}
|
|
let sheet = BadgeExpirationSheet(badge: profileBadge, mode: mode)
|
|
sheet.delegate = self
|
|
return sheet
|
|
}
|
|
if isRedeemed {
|
|
let fullName = self.databaseStorage.read { transaction -> String in
|
|
let authorAddress = incomingMessage.authorAddress
|
|
return self.contactsManager.displayName(for: authorAddress, transaction: transaction)
|
|
}
|
|
return BadgeGiftingAlreadyRedeemedSheet(badge: profileBadge, fullName: fullName)
|
|
}
|
|
return self.giftRedemptionSheet(incomingMessage: incomingMessage, profileBadge: profileBadge)
|
|
}
|
|
|
|
private func giftRedemptionSheet(incomingMessage: TSIncomingMessage, profileBadge: ProfileBadge) -> UIViewController {
|
|
let (shortName, fullName) = self.databaseStorage.read { transaction -> (String, String) in
|
|
let authorAddress = incomingMessage.authorAddress
|
|
return (
|
|
self.contactsManager.shortDisplayName(for: authorAddress, transaction: transaction),
|
|
self.contactsManager.displayName(for: authorAddress, transaction: transaction)
|
|
)
|
|
}
|
|
return BadgeThanksSheet(badge: profileBadge, type: .gift(
|
|
shortName: shortName,
|
|
fullName: fullName,
|
|
notNowAction: { [weak self] in self?.showRedeemBadgeLaterText() },
|
|
incomingMessage: incomingMessage
|
|
))
|
|
}
|
|
|
|
private func showRedeemBadgeLaterText() {
|
|
let text = NSLocalizedString(
|
|
"BADGE_GIFTING_REDEEM_LATER",
|
|
comment: "A toast that appears at the bottom of the screen after tapping 'Not Now' when redeeming a gift."
|
|
)
|
|
self.presentToastCVC(text)
|
|
}
|
|
|
|
}
|
|
|
|
extension ConversationViewController: BadgeExpirationSheetDelegate {
|
|
func badgeExpirationSheetActionTapped(_ action: BadgeExpirationSheetAction) {
|
|
switch action {
|
|
case .dismiss:
|
|
break
|
|
case .openSubscriptionsView:
|
|
let appSettings = AppSettingsViewController.inModalNavigationController()
|
|
appSettings.viewControllers += [
|
|
DonationSettingsViewController(),
|
|
SubscriptionViewController()
|
|
]
|
|
self.presentFormSheet(appSettings, animated: true, completion: nil)
|
|
case .openBoostView:
|
|
owsFailDebug("Not supported")
|
|
}
|
|
}
|
|
}
|