TM-SGNL-iOS/Signal/Megaphones/UserInterface/RemoteMegaphone.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

190 lines
6.6 KiB
Swift

//
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import SignalServiceKit
import SignalUI
class RemoteMegaphone: MegaphoneView {
private let megaphoneModel: RemoteMegaphoneModel
init(
experienceUpgrade: ExperienceUpgrade,
remoteMegaphoneModel: RemoteMegaphoneModel,
fromViewController: UIViewController
) {
megaphoneModel = remoteMegaphoneModel
super.init(experienceUpgrade: experienceUpgrade)
titleText = megaphoneModel.translation.title
bodyText = megaphoneModel.translation.body
if let imageLocalUrl = megaphoneModel.translation.imageLocalUrl {
if let image = UIImage(contentsOfFile: imageLocalUrl.path) {
self.image = image
} else {
owsFailDebug("Expected local image, but image was not loaded!")
}
}
if let primary = megaphoneModel.presentablePrimaryAction {
let primaryButton = MegaphoneView.Button(title: primary.presentableText) { [weak self, weak fromViewController] in
guard
let self = self,
let fromViewController = fromViewController
else { return }
self.performAction(
primary.action,
fromViewController: fromViewController,
buttonDescriptor: "primary"
)
}
if let secondary = megaphoneModel.presentableSecondaryAction {
let secondaryButton = MegaphoneView.Button(title: secondary.presentableText) { [weak self, weak fromViewController] in
guard
let self = self,
let fromViewController = fromViewController
else { return }
self.performAction(
secondary.action,
fromViewController: fromViewController,
buttonDescriptor: "secondary"
)
}
setButtons(primary: primaryButton, secondary: secondaryButton)
} else {
setButtons(primary: primaryButton)
}
}
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: Perform actions
/// Perform the given action.
private func performAction(
_ action: RemoteMegaphoneModel.Manifest.Action,
fromViewController: UIViewController,
buttonDescriptor: String
) {
switch action {
case .snooze:
markAsSnoozedWithSneakyTransaction()
dismiss()
case .finish:
markAsCompleteWithSneakyTransaction()
dismiss()
case .donate:
let done = { [weak self] in
guard let self else { return }
// Snooze regardless of outcome.
self.markAsSnoozedWithSneakyTransaction()
self.dismiss(animated: false)
}
guard DonationUtilities.canDonateInAnyWay(
localNumber: DependenciesBridge.shared.tsAccountManager.localIdentifiersWithMaybeSneakyTransaction?.phoneNumber
) else {
done()
DonationViewsUtil.openDonateWebsite()
return
}
let donateVc = DonateViewController(preferredDonateMode: .oneTime) { finishResult in
let frontVc = { CurrentAppContext().frontmostViewController() }
switch finishResult {
case let .completedDonation(donateSheet, receiptCredentialSuccessMode):
donateSheet.dismiss(animated: true) {
guard
let frontVc = frontVc(),
let badgeThanksSheetPresenter = BadgeThanksSheetPresenter.loadWithSneakyTransaction(
successMode: receiptCredentialSuccessMode
)
else { return }
badgeThanksSheetPresenter.presentBadgeThanksAndClearSuccess(
fromViewController: frontVc
)
}
case let .monthlySubscriptionCancelled(donateSheet, toastText):
donateSheet.dismiss(animated: true) {
frontVc()?.presentToast(text: toastText)
}
}
}
let navController = OWSNavigationController(rootViewController: donateVc)
fromViewController.present(navController, animated: true, completion: done)
case .donateFriend:
let done = { [weak self] in
guard let self else { return }
// Snooze regardless of outcome.
self.markAsSnoozedWithSneakyTransaction()
self.dismiss(animated: false)
}
guard DonationUtilities.canDonate(
inMode: .gift,
localNumber: DependenciesBridge.shared.tsAccountManager.localIdentifiersWithMaybeSneakyTransaction?.phoneNumber
) else {
done()
DonationViewsUtil.openDonateWebsite()
return
}
let donateVc = BadgeGiftingChooseBadgeViewController()
let navController = OWSNavigationController(rootViewController: donateVc)
fromViewController.present(navController, animated: true, completion: done)
case .unrecognized(let actionId):
owsFailDebug("Unrecognized action with ID \(actionId) should never have made it into \(buttonDescriptor) button!")
dismiss()
}
}
}
// MARK: - Presentable actions
private extension RemoteMegaphoneModel {
struct PresentableAction {
let action: Manifest.Action
let presentableText: String
fileprivate init?(
action: Manifest.Action?,
presentableText: String?
) {
guard
let action = action,
let presentableText = presentableText
else {
return nil
}
self.action = action
self.presentableText = presentableText
}
}
var presentablePrimaryAction: PresentableAction? {
PresentableAction(
action: manifest.primaryAction,
presentableText: translation.primaryActionText
)
}
var presentableSecondaryAction: PresentableAction? {
PresentableAction(
action: manifest.secondaryAction,
presentableText: translation.secondaryActionText
)
}
}