From e38d4353bfb6da68fd8c659925924853a8663448 Mon Sep 17 00:00:00 2001 From: Toni Rico Date: Thu, 18 Jul 2024 13:07:43 +0200 Subject: [PATCH] Move to pass a lambda parameter for action handler --- RevenueCat.xcodeproj/project.pbxproj | 8 +-- .../Data/CustomerCenterAction.swift | 22 ++++++++ .../Data/CustomerCenterActionHandler.swift | 45 ----------------- .../ViewModels/CustomerCenterViewModel.swift | 6 +-- .../ManageSubscriptionsViewModel.swift | 8 +-- .../UI/Views/SamplePaywallsList.swift | 50 ++++++++----------- 6 files changed, 53 insertions(+), 86 deletions(-) create mode 100644 RevenueCatUI/CustomerCenter/Data/CustomerCenterAction.swift delete mode 100644 RevenueCatUI/CustomerCenter/Data/CustomerCenterActionHandler.swift diff --git a/RevenueCat.xcodeproj/project.pbxproj b/RevenueCat.xcodeproj/project.pbxproj index 95518ff5c2..0158e603bd 100644 --- a/RevenueCat.xcodeproj/project.pbxproj +++ b/RevenueCat.xcodeproj/project.pbxproj @@ -12,7 +12,7 @@ 1E473B682AC43254008B07F9 /* StoreMessageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E473B672AC43254008B07F9 /* StoreMessageType.swift */; }; 1E568B512ACC6A8300D3C12F /* StoreMessageTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E568B502ACC6A8300D3C12F /* StoreMessageTypeTests.swift */; }; 1E5F8F6E2C4515430041EECD /* View+PresentCustomerCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E5F8F6D2C4515430041EECD /* View+PresentCustomerCenter.swift */; }; - 1E5F8F782C46BBD90041EECD /* CustomerCenterActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E5F8F772C46BBD90041EECD /* CustomerCenterActionHandler.swift */; }; + 1E5F8F782C46BBD90041EECD /* CustomerCenterAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E5F8F772C46BBD90041EECD /* CustomerCenterAction.swift */; }; 1E99F81F2AC5917F0023E26E /* StoreMessagesHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E99F81D2AC5917F0023E26E /* StoreMessagesHelperTests.swift */; }; 2C0B98CD2797070B00C5874F /* PromotionalOffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C0B98CC2797070B00C5874F /* PromotionalOffer.swift */; }; 2C6CC1162B8D2B6900432E4D /* PurchasesSyncAttributesAndOfferingsIfNeededTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C6CC1152B8D2B6800432E4D /* PurchasesSyncAttributesAndOfferingsIfNeededTests.swift */; }; @@ -1050,7 +1050,7 @@ 1E473B692AC46908008B07F9 /* MockStoreMessagesHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockStoreMessagesHelper.swift; sourceTree = ""; }; 1E568B502ACC6A8300D3C12F /* StoreMessageTypeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreMessageTypeTests.swift; sourceTree = ""; }; 1E5F8F6D2C4515430041EECD /* View+PresentCustomerCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+PresentCustomerCenter.swift"; sourceTree = ""; }; - 1E5F8F772C46BBD90041EECD /* CustomerCenterActionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomerCenterActionHandler.swift; sourceTree = ""; }; + 1E5F8F772C46BBD90041EECD /* CustomerCenterAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomerCenterAction.swift; sourceTree = ""; }; 1E99F81D2AC5917F0023E26E /* StoreMessagesHelperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreMessagesHelperTests.swift; sourceTree = ""; }; 2C0B98CC2797070B00C5874F /* PromotionalOffer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromotionalOffer.swift; sourceTree = ""; }; 2C646C282A0EBD0300E5936E /* CI-Snapshots.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = "CI-Snapshots.xctestplan"; path = "Tests/TestPlans/CI-Snapshots.xctestplan"; sourceTree = ""; }; @@ -2559,7 +2559,7 @@ 353756542C382C2800A1B8D6 /* CustomerCenterError.swift */, 35C200AE2C39252D00B9778B /* FeedbackSurveyData.swift */, 353756552C382C2800A1B8D6 /* SubscriptionInformation.swift */, - 1E5F8F772C46BBD90041EECD /* CustomerCenterActionHandler.swift */, + 1E5F8F772C46BBD90041EECD /* CustomerCenterAction.swift */, ); path = Data; sourceTree = ""; @@ -5165,7 +5165,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1E5F8F782C46BBD90041EECD /* CustomerCenterActionHandler.swift in Sources */, + 1E5F8F782C46BBD90041EECD /* CustomerCenterAction.swift in Sources */, 887A60CC2C1D037000E1A461 /* PaywallFontProvider.swift in Sources */, 887A60B82C1D037000E1A461 /* Template1View.swift in Sources */, 887A60C62C1D037000E1A461 /* LoadingPaywallView.swift in Sources */, diff --git a/RevenueCatUI/CustomerCenter/Data/CustomerCenterAction.swift b/RevenueCatUI/CustomerCenter/Data/CustomerCenterAction.swift new file mode 100644 index 0000000000..d915c73b34 --- /dev/null +++ b/RevenueCatUI/CustomerCenter/Data/CustomerCenterAction.swift @@ -0,0 +1,22 @@ +import RevenueCat + +/// Typealias for handler for Customer center actions +public typealias CustomerCenterActionHandler = @MainActor @Sendable (CustomerCenterAction) -> Void + +/// Represents an event the customer may perform during the Customer Center flow +public enum CustomerCenterAction { + /// Purchase of a promotional offer is completed. + case purchaseCompleted(_ customerInfo: CustomerInfo) + /// Starting the restoration process + case restoreStarted + /// Restore errored out + case restoreFailed(_ error: Error) + /// Restore completed successfully + case restoreCompleted(_ customerInfo: CustomerInfo) + /// Going to display manage subscription page, whether for cancellation or changing plans. + case showingManageSubscriptions + /// Starting refund request process + case refundRequestStarted(_ productId: String) + /// Refund request process finished, with result provided. + case refundRequestCompleted(_ refundRequestStatus: RefundRequestStatus) +} diff --git a/RevenueCatUI/CustomerCenter/Data/CustomerCenterActionHandler.swift b/RevenueCatUI/CustomerCenter/Data/CustomerCenterActionHandler.swift deleted file mode 100644 index 3924f2c3b2..0000000000 --- a/RevenueCatUI/CustomerCenter/Data/CustomerCenterActionHandler.swift +++ /dev/null @@ -1,45 +0,0 @@ -import Foundation -import RevenueCat - -/// Allows to be notified of certain events the customer may perform during the Customer Center flow -public protocol CustomerCenterActionHandler { - - /// This will be called after a purchase of a promotional offer is completed. - func onPurchaseCompleted(_ customerInfo: CustomerInfo) - - /// This will be called right before starting the restoration process - func onRestoreStarted() - - /// This will be called after a restore errors out - func onRestoreFailed(_ error: Error) - - /// This will be called after a successful restoration process - func onRestoreCompleted(_ customerInfo: CustomerInfo) - - /// This will be called right before displaying the manage subscription page, - /// which may happen for cancellations or changing plans - func onShowManageSubscriptions() - - /// This will be called right before starting the refund request flow - func onRefundRequestStarted(_ productId: String) - - /// This will be called right after the refund request flow, indicating the result of said flow - func onRefundRequestCompleted(_ refundRequestStatus: RefundRequestStatus) - -} - -// swiftlint:disable missing_docs - -public extension CustomerCenterActionHandler { - - func onPurchaseCompleted(_ customerInfo: CustomerInfo) {} - func onRestoreStarted() {} - func onRestoreFailed(_ error: Error) {} - func onRestoreCompleted(_ customerInfo: CustomerInfo) {} - func onShowManageSubscriptions() {} - func onRefundRequestStarted(_ productId: String) {} - func onRefundRequestCompleted(_ refundRequestStatus: RefundRequestStatus) {} - -} - -// swiftlint:enable missing_docs diff --git a/RevenueCatUI/CustomerCenter/ViewModels/CustomerCenterViewModel.swift b/RevenueCatUI/CustomerCenter/ViewModels/CustomerCenterViewModel.swift index 07caba1e94..08f35e9bfd 100644 --- a/RevenueCatUI/CustomerCenter/ViewModels/CustomerCenterViewModel.swift +++ b/RevenueCatUI/CustomerCenter/ViewModels/CustomerCenterViewModel.swift @@ -118,14 +118,14 @@ import RevenueCat } func performRestore() async -> RestorePurchasesAlert.AlertType { - self.customerCenterActionHandler?.onRestoreStarted() + self.customerCenterActionHandler?(.restoreStarted) do { let customerInfo = try await Purchases.shared.restorePurchases() - self.customerCenterActionHandler?.onRestoreCompleted(customerInfo) + self.customerCenterActionHandler?(.restoreCompleted(customerInfo)) let hasEntitlements = customerInfo.entitlements.active.count > 0 return hasEntitlements ? .purchasesRecovered : .purchasesNotFound } catch { - self.customerCenterActionHandler?.onRestoreFailed(error) + self.customerCenterActionHandler?(.restoreFailed(error)) return .purchasesNotFound } } diff --git a/RevenueCatUI/CustomerCenter/ViewModels/ManageSubscriptionsViewModel.swift b/RevenueCatUI/CustomerCenter/ViewModels/ManageSubscriptionsViewModel.swift index f25dbff801..d9cc2e3813 100644 --- a/RevenueCatUI/CustomerCenter/ViewModels/ManageSubscriptionsViewModel.swift +++ b/RevenueCatUI/CustomerCenter/ViewModels/ManageSubscriptionsViewModel.swift @@ -146,9 +146,9 @@ class ManageSubscriptionsViewModel: ObservableObject { do { guard let subscriptionInformation = self.subscriptionInformation else { return } let productId = subscriptionInformation.productIdentifier - self.customerCenterActionHandler?.onRefundRequestStarted(productId) + self.customerCenterActionHandler?(.refundRequestStarted(productId)) let status = try await self.purchasesProvider.beginRefundRequest(forProduct: productId) - self.customerCenterActionHandler?.onRefundRequestCompleted(status) + self.customerCenterActionHandler?(.refundRequestCompleted(status)) switch status { case .error: self.refundRequestStatusMessage = String(localized: "Error when requesting refund, try again") @@ -158,13 +158,13 @@ class ManageSubscriptionsViewModel: ObservableObject { self.refundRequestStatusMessage = String(localized: "Refund canceled") } } catch { - self.customerCenterActionHandler?.onRefundRequestCompleted(.error) + self.customerCenterActionHandler?(.refundRequestCompleted(.error)) self.refundRequestStatusMessage = String(localized: "An error occurred while processing the refund request.") } case .changePlans, .cancel: do { - self.customerCenterActionHandler?.onShowManageSubscriptions() + self.customerCenterActionHandler?(.showingManageSubscriptions) try await purchasesProvider.showManageSubscriptions() } catch { self.state = .error(error) diff --git a/Tests/TestingApps/PaywallsTester/PaywallsTester/UI/Views/SamplePaywallsList.swift b/Tests/TestingApps/PaywallsTester/PaywallsTester/UI/Views/SamplePaywallsList.swift index 58982db8bb..05cb2eba7b 100644 --- a/Tests/TestingApps/PaywallsTester/PaywallsTester/UI/Views/SamplePaywallsList.swift +++ b/Tests/TestingApps/PaywallsTester/PaywallsTester/UI/Views/SamplePaywallsList.swift @@ -152,7 +152,7 @@ struct SamplePaywallsList: View { .frame(maxWidth: .infinity) .buttonStyle(.plain) #if os(iOS) - .presentCustomerCenter(isPresented: self.$presentingCustomerCenter, customerCenterActionHandler: self) { + .presentCustomerCenter(isPresented: self.$presentingCustomerCenter, customerCenterActionHandler: self.handleCustomerCenterAction) { self.presentingCustomerCenter = false } #endif @@ -199,36 +199,26 @@ private struct TemplateLabel: View { #if os(iOS) -extension SamplePaywallsList: CustomerCenterActionHandler { - - func onRestoreCompleted(_ customerInfo: RevenueCat.CustomerInfo) { - print("CustomerCenter: onRestoreCompleted") - } - - func onPurchaseCompleted(_ customerInfo: RevenueCat.CustomerInfo) { - print("CustomerCenter: onPurchaseCompleted") - } - - func onRestoreFailed(_ error: any Error) { - print("CustomerCenter: onRestoreFailed") - } - - func onShowManageSubscriptions() { - print("CustomerCenter: onShowManageSubscriptions") - } - - func onRefundRequestStarted(_ productId: String) { - print("CustomerCenter: onRefundRequestStarted") - } - - func onRefundRequestCompleted(_ refundRequestStatus: RevenueCat.RefundRequestStatus) { - print("CustomerCenter: onRefundRequestCompleted. Result: \(refundRequestStatus)") - } - - func onRestoreStarted() { - print("CustomerCenter: onRestoreStarted") +extension SamplePaywallsList { + + func handleCustomerCenterAction(action: CustomerCenterAction) { + switch action { + case .restoreCompleted(_): + print("CustomerCenter: restoreCompleted") + case .purchaseCompleted(_): + print("CustomerCenter: purchaseCompleted") + case .restoreStarted: + print("CustomerCenter: restoreStarted") + case .restoreFailed(_): + print("CustomerCenter: restoreFailed") + case .showingManageSubscriptions: + print("CustomerCenter: showingManageSubscriptions") + case .refundRequestStarted(let productId): + print("CustomerCenter: refundRequestStarted. ProductId: \(productId)") + case .refundRequestCompleted(let status): + print("CustomerCenter: refundRequestCompleted. Result: \(status)") + } } - } #endif