From 2b3b60819e9ec69b13241e8d423197231038fa69 Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Fri, 8 Dec 2023 18:20:25 -0600 Subject: [PATCH] Automatically dismisses web view if user completes Patreon checkout flow --- .../Operations/VerifyAppPledgeOperation.swift | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/AltStore/Operations/VerifyAppPledgeOperation.swift b/AltStore/Operations/VerifyAppPledgeOperation.swift index b7e97db2..e621f86c 100644 --- a/AltStore/Operations/VerifyAppPledgeOperation.swift +++ b/AltStore/Operations/VerifyAppPledgeOperation.swift @@ -6,6 +6,8 @@ // Copyright © 2023 Riley Testut. All rights reserved. // +import Combine + import AltStoreCore class VerifyAppPledgeOperation: ResultOperation @@ -16,6 +18,8 @@ class VerifyAppPledgeOperation: ResultOperation private let presentingViewController: UIViewController? private var openPatreonPageContinuation: CheckedContinuation? + private var cancellable: AnyCancellable? + init(storeApp: StoreApp, presentingViewController: UIViewController?) { self.storeApp = storeApp @@ -57,9 +61,12 @@ class VerifyAppPledgeOperation: ResultOperation let patreonURL = await self.$storeApp.perform({ _ in source.patreonURL }) else { throw error } - let checkoutURL: URL + let components = URLComponents(url: patreonURL, resolvingAgainstBaseURL: false) + let lastPathComponent = components?.path.components(separatedBy: "/").last - let username = patreonURL.lastPathComponent + let checkoutURL: URL + + let username = lastPathComponent ?? patreonURL.lastPathComponent if !username.isEmpty, let url = URL(string: "https://www.patreon.com/join/" + username) { // Prefer /join URL over campaign homepage. @@ -221,6 +228,23 @@ private extension VerifyAppPledgeOperation let navigationController = UINavigationController(rootViewController: webViewController) presentingViewController.present(navigationController, animated: true) + + // Automatically dismiss if user completes checkout flow. + self.cancellable = webViewController.webView.publisher(for: \.url, options: [.new]) + .compactMap { $0 } + .compactMap { URLComponents(url: $0, resolvingAgainstBaseURL: false) } + .compactMap { components in + let lastPathComponent = components.path.components(separatedBy: "/").last + return lastPathComponent?.lowercased() + } + .filter { $0 == "membership" } + .receive(on: RunLoop.main) + .sink { [weak self] url in + guard let continuation = self?.openPatreonPageContinuation else { return } + self?.openPatreonPageContinuation = nil + + continuation.resume() + } await withCheckedContinuation { continuation in self.openPatreonPageContinuation = continuation @@ -230,6 +254,8 @@ private extension VerifyAppPledgeOperation await PatreonAPI.shared.saveAuthCookies() navigationController.dismiss(animated: true) + + self.cancellable = nil } }