Signal-iOS/Signal/src/ViewControllers/ConversationView/ConversationViewController+GiftBadges.swift
Evan Hahn c8bc2cde2e Improve name of donation settings view controller
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.
2022-10-26 14:12:48 -05:00

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")
}
}
}