169 lines
7.1 KiB
Swift
169 lines
7.1 KiB
Swift
//
|
|
// Copyright 2022 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import Foundation
|
|
public import SignalServiceKit
|
|
|
|
extension ConversationViewController {
|
|
|
|
public 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)
|
|
}
|
|
|
|
public func willShakeGift(_ messageUniqueId: String) -> Bool {
|
|
let (justInserted, _) = self.viewState.shakenGiftMessageIds.insert(messageUniqueId)
|
|
return justInserted
|
|
}
|
|
|
|
public 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
|
|
}
|
|
SSKEnvironment.shared.databaseStorageRef.asyncWrite { transaction in
|
|
outgoingMessage.anyUpdateOutgoingMessage(transaction: transaction) {
|
|
$0.giftBadge?.redemptionState = .opened
|
|
}
|
|
|
|
SSKEnvironment.shared.receiptManagerRef.outgoingGiftWasOpened(outgoingMessage, transaction: transaction)
|
|
}
|
|
}
|
|
|
|
public 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: BadgeIssueSheetState.Mode
|
|
if isRedeemed {
|
|
let hasCurrentSubscription = DonationSubscriptionManager.probablyHasCurrentSubscription()
|
|
mode = .giftBadgeExpired(hasCurrentSubscription: hasCurrentSubscription)
|
|
} else {
|
|
let fullName = SSKEnvironment.shared.databaseStorageRef.read { transaction -> String in
|
|
let authorAddress = incomingMessage.authorAddress
|
|
return SSKEnvironment.shared.contactManagerRef.displayName(for: authorAddress, tx: transaction).resolvedValue()
|
|
}
|
|
mode = .giftNotRedeemed(fullName: fullName)
|
|
}
|
|
let sheet = BadgeIssueSheet(badge: profileBadge, mode: mode)
|
|
sheet.delegate = self
|
|
return sheet
|
|
}
|
|
if isRedeemed {
|
|
let shortName = SSKEnvironment.shared.databaseStorageRef.read { transaction -> String in
|
|
let authorAddress = incomingMessage.authorAddress
|
|
return SSKEnvironment.shared.contactManagerRef.displayName(for: authorAddress, tx: transaction).resolvedValue(useShortNameIfAvailable: true)
|
|
}
|
|
return BadgeGiftingAlreadyRedeemedSheet(badge: profileBadge, shortName: shortName)
|
|
}
|
|
return self.giftRedemptionSheet(incomingMessage: incomingMessage, profileBadge: profileBadge)
|
|
}
|
|
|
|
private func giftRedemptionSheet(incomingMessage: TSIncomingMessage, profileBadge: ProfileBadge) -> UIViewController {
|
|
let authorAddress = incomingMessage.authorAddress
|
|
let shortName = SSKEnvironment.shared.databaseStorageRef.read { transaction in
|
|
SSKEnvironment.shared.contactManagerRef.displayName(for: authorAddress, tx: transaction).resolvedValue(useShortNameIfAvailable: true)
|
|
}
|
|
return BadgeThanksSheet(
|
|
newBadge: profileBadge,
|
|
thanksType: .giftReceived(
|
|
shortName: shortName,
|
|
notNowAction: { [weak self] in self?.showRedeemBadgeLaterText() },
|
|
incomingMessage: incomingMessage
|
|
),
|
|
oldBadgesSnapshot: .current()
|
|
)
|
|
}
|
|
|
|
private func showRedeemBadgeLaterText() {
|
|
let text = OWSLocalizedString(
|
|
"DONATION_ON_BEHALF_OF_A_FRIEND_REDEEM_BADGE_LATER",
|
|
comment: "When you receive a badge as a result of a donation from a friend, a screen is shown. This toast is shown when dismissing that screen if you do not redeem the badge."
|
|
)
|
|
self.presentToastCVC(text)
|
|
}
|
|
|
|
}
|
|
|
|
extension ConversationViewController: BadgeIssueSheetDelegate {
|
|
func badgeIssueSheetActionTapped(_ action: BadgeIssueSheetAction) {
|
|
switch action {
|
|
case .dismiss:
|
|
break
|
|
case .openDonationView:
|
|
let appSettings = AppSettingsViewController.inModalNavigationController(appReadiness: appReadiness)
|
|
let donateViewController = DonateViewController(preferredDonateMode: .oneTime) { [weak self] finishResult in
|
|
switch finishResult {
|
|
case let .completedDonation(donateSheet, receiptCredentialSuccessMode):
|
|
donateSheet.dismiss(animated: true) { [weak self] in
|
|
guard
|
|
let self,
|
|
let badgeThanksSheetPresenter = BadgeThanksSheetPresenter.loadWithSneakyTransaction(
|
|
successMode: receiptCredentialSuccessMode
|
|
)
|
|
else { return }
|
|
|
|
badgeThanksSheetPresenter.presentBadgeThanksAndClearSuccess(
|
|
fromViewController: self
|
|
)
|
|
}
|
|
case let .monthlySubscriptionCancelled(donateSheet, toastText):
|
|
donateSheet.dismiss(animated: true) { [weak self] in
|
|
guard let self = self else { return }
|
|
self.view.presentToast(text: toastText, fromViewController: self)
|
|
}
|
|
}
|
|
}
|
|
appSettings.viewControllers += [
|
|
DonationSettingsViewController(),
|
|
donateViewController
|
|
]
|
|
self.presentFormSheet(appSettings, animated: true, completion: nil)
|
|
}
|
|
}
|
|
}
|