From f57e82072f69c129a71193fd5c518fea72864c63 Mon Sep 17 00:00:00 2001 From: Kylmakalle Date: Fri, 7 Feb 2025 21:24:59 +0200 Subject: [PATCH] WIP: Paywall --- Swiftgram/SGDebugUI/BUILD | 4 +- Swiftgram/SGDebugUI/Sources/SGDebugUI.swift | 37 +++-- Swiftgram/SGIAP/BUILD | 3 +- Swiftgram/SGIAP/Sources/SGIAP.swift | 52 ++++-- Swiftgram/SGPayWall/BUILD | 23 +++ Swiftgram/SGPayWall/Sources/SGPayWall.swift | 150 ++++++++++++++++++ .../Sources/SGSwiftSignalKit.swift | 48 ++---- submodules/AccountContext/BUILD | 3 +- .../Sources/AccountContext.swift | 2 + submodules/TelegramUI/BUILD | 1 + .../TelegramUI/Sources/AppDelegate.swift | 24 ++- .../Sources/SharedAccountContext.swift | 16 +- 12 files changed, 299 insertions(+), 64 deletions(-) create mode 100644 Swiftgram/SGPayWall/BUILD create mode 100644 Swiftgram/SGPayWall/Sources/SGPayWall.swift diff --git a/Swiftgram/SGDebugUI/BUILD b/Swiftgram/SGDebugUI/BUILD index 9b8d6822dc..20d576aadf 100644 --- a/Swiftgram/SGDebugUI/BUILD +++ b/Swiftgram/SGDebugUI/BUILD @@ -30,6 +30,8 @@ swift_library( "//Swiftgram/SGSimpleSettings:SGSimpleSettings", "//Swiftgram/SGStrings:SGStrings", "//Swiftgram/SGSwiftUI:SGSwiftUI", + "//Swiftgram/SGIAP:SGIAP", + "//Swiftgram/SGPayWall:SGPayWall", "//submodules/LegacyUI:LegacyUI", "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/Postbox:Postbox", @@ -40,7 +42,7 @@ swift_library( "//submodules/PresentationDataUtils:PresentationDataUtils", "//submodules/OverlayStatusController:OverlayStatusController", "//submodules/AccountContext:AccountContext", - "//submodules/UndoUI:UndoUI", + "//submodules/UndoUI:UndoUI" ] + flex_dependency, visibility = [ "//visibility:public", diff --git a/Swiftgram/SGDebugUI/Sources/SGDebugUI.swift b/Swiftgram/SGDebugUI/Sources/SGDebugUI.swift index 82d0a59302..8986f0713b 100644 --- a/Swiftgram/SGDebugUI/Sources/SGDebugUI.swift +++ b/Swiftgram/SGDebugUI/Sources/SGDebugUI.swift @@ -14,6 +14,7 @@ import PresentationDataUtils // Optional import SGSimpleSettings import SGLogging +import SGPayWall import OverlayStatusController #if DEBUG import FLEX @@ -265,12 +266,14 @@ struct SessionBackupManagerView: View { wrapperController?.present(controller, in: .window(.root), with: nil) Task { - let (view, accountsWithInfo) = await combineLatest(signal, signal2).awaitable() - backupSessionsFromView(view, accountsWithInfo: accountsWithInfo.1) - withAnimation { - sessions = getBackedSessions() + if let result = try? await combineLatest(signal, signal2).awaitable() { + let (view, accountsWithInfo) = result + backupSessionsFromView(view, accountsWithInfo: accountsWithInfo.1) + withAnimation { + sessions = getBackedSessions() + } + controller.dismiss() } - controller.dismiss() } } @@ -833,13 +836,13 @@ private enum SGDebugControllerSection: Int32, SGItemListSection { private enum SGDebugDisclosureLink: String { case sessionBackupManager case messageFilter + case debugIAP } private enum SGDebugActions: String { case flexing case fileManager case clearRegDateCache - case debugIAP } private enum SGDebugToggles: String { @@ -863,7 +866,7 @@ private func SGDebugControllerEntries(presentationData: PresentationData) -> [SG #if DEBUG entries.append(.action(id: id.count, section: .base, actionType: .flexing, text: "FLEX", kind: .generic)) entries.append(.action(id: id.count, section: .base, actionType: .fileManager, text: "FileManager", kind: .generic)) - entries.append(.action(id: id.count, section: .base, actionType: .debugIAP, text: "Buy", kind: .generic)) + entries.append(.disclosure(id: id.count, section: .base, link: .debugIAP, text: "Pro")) #endif if SGSimpleSettings.shared.b { @@ -977,6 +980,22 @@ public func sgDebugController(context: AccountContext) -> ViewController { action: { _ in return false } ), nil) } + case .debugIAP: + #if DEBUG + if #available(iOS 13.0, *) { + if let sgIAPManager = context.sharedContext.SGIAP { + presentControllerImpl?(sgPayWallController(presentationData: presentationData, SGIAPManager: sgIAPManager), ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) + } + } else { + presentControllerImpl?(UndoOverlayController( + presentationData: presentationData, + content: .info(title: nil, text: "Update OS to access this feature", timeout: nil, customUndoText: nil), + elevatedLayout: false, + action: { _ in return false } + ), nil) + } + + #endif } }, action: { actionType in let presentationData = context.sharedContext.currentPresentationData.with { $0 } @@ -1022,10 +1041,6 @@ public func sgDebugController(context: AccountContext) -> ViewController { nil) } #endif - case .debugIAP: - #if DEBUG - preconditionFailure("IAP") - #endif } }) diff --git a/Swiftgram/SGIAP/BUILD b/Swiftgram/SGIAP/BUILD index bf7f27b0be..c80d97254b 100644 --- a/Swiftgram/SGIAP/BUILD +++ b/Swiftgram/SGIAP/BUILD @@ -12,7 +12,8 @@ swift_library( deps = [ "//Swiftgram/SGLogging:SGLogging", "//Swiftgram/SGConfig:SGConfig", - "//submodules/AppBundle:AppBundle" + "//submodules/AppBundle:AppBundle", + "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", ], visibility = [ "//visibility:public", diff --git a/Swiftgram/SGIAP/Sources/SGIAP.swift b/Swiftgram/SGIAP/Sources/SGIAP.swift index 777802d3fc..48f091437b 100644 --- a/Swiftgram/SGIAP/Sources/SGIAP.swift +++ b/Swiftgram/SGIAP/Sources/SGIAP.swift @@ -2,6 +2,7 @@ import StoreKit import SGConfig import SGLogging import AppBundle +import Combine private final class CurrencyFormatterEntry { public let symbol: String @@ -89,13 +90,16 @@ private func fractionalValueToCurrencyAmount(value: Double, currency: String) -> public extension Notification.Name { static let SGIAPHelperPurchaseNotification = Notification.Name("SGIAPPurchaseNotification") static let SGIAPHelperErrorNotification = Notification.Name("SGIAPErrorNotification") + static let SGIAPHelperProductsUpdatedNotification = Notification.Name("SGIAPProductsUpdatedNotification") } -public final class SGIAP: NSObject { +public final class SGIAPManager: NSObject { private var productRequest: SKProductsRequest? private var productsRequestCompletion: (([SKProduct]) -> Void)? private var purchaseCompletion: ((Bool, Error?) -> Void)? + public private(set) var availableProducts: [SGProduct] = [] + private var finishedSuccessfulTransactions = Set() public final class SGProduct: Equatable { private lazy var numberFormatter: NumberFormatter = { @@ -105,7 +109,7 @@ public final class SGIAP: NSObject { return numberFormatter }() - let skProduct: SKProduct + public let skProduct: SKProduct init(skProduct: SKProduct) { self.skProduct = skProduct @@ -198,7 +202,7 @@ public final class SGIAP: NSObject { } - public init(foo: Bool = false) { + public init(foo: Bool = false) { // I don't want to override init, idk why super.init() SKPaymentQueue.default().add(self) @@ -220,7 +224,7 @@ public final class SGIAP: NSObject { } private func requestProducts() { - SGLogger.shared.log("SGIAP", "Requesting products...") + SGLogger.shared.log("SGIAP", "Requesting products for \(SG_CONFIG.iaps.count) ids...") let productRequest = SKProductsRequest(productIdentifiers: Set(SG_CONFIG.iaps)) productRequest.delegate = self @@ -242,13 +246,18 @@ public final class SGIAP: NSObject { } } -extension SGIAP: SKProductsRequestDelegate { +extension SGIAPManager: SKProductsRequestDelegate { public func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { self.productRequest = nil DispatchQueue.main.async { let products = response.products - SGLogger.shared.log("SGIAP", "Received products \(products.map({ $0.productIdentifier }).joined(separator: ", "))") + SGLogger.shared.log("SGIAP", "Received products (\(products.count)): \(products.map({ $0.productIdentifier }).joined(separator: ", "))") + let currentlyAvailableProducts = self.availableProducts + self.availableProducts = products.map({ SGProduct(skProduct: $0) }) + if currentlyAvailableProducts != self.availableProducts { + NotificationCenter.default.post(name: .SGIAPHelperProductsUpdatedNotification, object: nil) + } } } @@ -258,13 +267,14 @@ extension SGIAP: SKProductsRequestDelegate { } } -extension SGIAP: SKPaymentTransactionObserver { +extension SGIAPManager: SKPaymentTransactionObserver { public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { SGLogger.shared.log("SGIAP", "paymentQueue transactions \(transactions.count)") for transaction in transactions { - SGLogger.shared.log("SGIAP", "Transaction state for \(transaction.payment.productIdentifier): \(transaction.transactionState)") + SGLogger.shared.log("SGIAP", "Transaction \(transaction.transactionIdentifier ?? "nil") state for product \(transaction.payment.productIdentifier): \(transaction.transactionState.description)") switch transaction.transactionState { case .purchased, .restored: + SGLogger.shared.log("SGIAP", "Sending SGIAPHelperPurchaseNotification for \(transaction.transactionIdentifier ?? "nil")") NotificationCenter.default.post(name: .SGIAPHelperPurchaseNotification, object: transaction) case .purchasing, .deferred: break @@ -272,11 +282,12 @@ extension SGIAP: SKPaymentTransactionObserver { if let transactionError = transaction.error as NSError?, let localizedDescription = transaction.error?.localizedDescription, transactionError.code != SKError.paymentCancelled.rawValue { - SGLogger.shared.log("SGIAP", "Transaction Error: \(localizedDescription)") + SGLogger.shared.log("SGIAP", "Transaction Error []: \(localizedDescription)") } + SGLogger.shared.log("SGIAP", "Sending SGIAPHelperErrorNotification for \(transaction.transactionIdentifier ?? "nil")") NotificationCenter.default.post(name: .SGIAPHelperErrorNotification, object: transaction) default: - SGLogger.shared.log("SGIAP", "Unknown transaction state \(transaction.transactionState). Finishing transaction.") + SGLogger.shared.log("SGIAP", "Unknown transaction \(transaction.transactionIdentifier ?? "nil") state \(transaction.transactionState). Finishing transaction.") SKPaymentQueue.default().finishTransaction(transaction) } } @@ -326,3 +337,24 @@ public func getPurchaceReceiptData() -> Data? { } return receiptData } + + +extension SKPaymentTransactionState { + var description: String { + switch self { + case .purchasing: + return "Purchasing" + case .purchased: + return "Purchased" + case .failed: + return "Failed" + case .restored: + return "Restored" + case .deferred: + return "Deferred" + @unknown default: + return "Unknown" + } + } +} + diff --git a/Swiftgram/SGPayWall/BUILD b/Swiftgram/SGPayWall/BUILD new file mode 100644 index 0000000000..955646d79e --- /dev/null +++ b/Swiftgram/SGPayWall/BUILD @@ -0,0 +1,23 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "SGPayWall", + module_name = "SGPayWall", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//Swiftgram/SGIAP:SGIAP", + "//Swiftgram/SGLogging:SGLogging", + "//Swiftgram/SGSimpleSettings:SGSimpleSettings", + "//Swiftgram/SGSwiftUI:SGSwiftUI", + "//Swiftgram/SGStrings:SGStrings", + "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/Swiftgram/SGPayWall/Sources/SGPayWall.swift b/Swiftgram/SGPayWall/Sources/SGPayWall.swift new file mode 100644 index 0000000000..e36f8ed0ec --- /dev/null +++ b/Swiftgram/SGPayWall/Sources/SGPayWall.swift @@ -0,0 +1,150 @@ +import Foundation +import SwiftUI +import SGSwiftUI +import SGIAP +import TelegramPresentationData +import LegacyUI +import Display +import SGConfig +// import SGStrings + + +struct SGPerk: Identifiable { + let id = UUID() + let title: String + let description: String + let icon: String +} + + + +@available(iOS 13.0, *) +struct SGPayWallView: View { + + weak var wrapperController: LegacyController? + let SGIAP: SGIAPManager + + let perks = [ + SGPerk(title: "Premium Features", description: "Access all premium features and tools", icon: "star.fill"), + SGPerk(title: "No Ads", description: "Enjoy an ad-free experience", icon: "banner.slash"), + SGPerk(title: "Cloud Sync", description: "Sync your data across all devices", icon: "cloud.fill"), + SGPerk(title: "Priority Support", description: "Get priority customer support", icon: "questionmark.circle.fill"), + SGPerk(title: "Advanced Stats", description: "Access detailed analytics and insights", icon: "chart.bar.fill"), + SGPerk(title: "Premium Features", description: "Access all premium features and tools", icon: "star.fill"), + SGPerk(title: "No Ads", description: "Enjoy an ad-free experience", icon: "banner.slash"), + SGPerk(title: "Cloud Sync", description: "Sync your data across all devices", icon: "cloud.fill"), + SGPerk(title: "Priority Support", description: "Get priority customer support", icon: "questionmark.circle.fill"), + SGPerk(title: "Advanced Stats", description: "Access detailed analytics and insights", icon: "chart.bar.fill"), + SGPerk(title: "Advanced Stats", description: "Access detailed analytics and insights", icon: "chart.bar.fill"), + SGPerk(title: "Premium Features", description: "Access all premium features and tools", icon: "star.fill"), + SGPerk(title: "No Ads", description: "Enjoy an ad-free experience", icon: "banner.slash"), + SGPerk(title: "Cloud Sync", description: "Sync your data across all devices", icon: "cloud.fill"), + SGPerk(title: "Priority Support", description: "Get priority customer support", icon: "questionmark.circle.fill"), + SGPerk(title: "Advanced Stats", description: "Access detailed analytics and insights", icon: "chart.bar.fill"), + ] + + var body: some View { + NavigationView { + VStack(spacing: 0) { + ScrollView { + VStack(spacing: 24) { + ForEach(perks) { perk in + HStack(spacing: 16) { + Image(systemName: perk.icon) + .font(.title) + .foregroundColor(.blue) + .frame(width: 32) + + VStack(alignment: .leading, spacing: 4) { + Text(perk.title) + .font(.headline) + Text(perk.description) + .font(.subheadline) + .foregroundColor(.secondary) + } + Spacer() + } + .padding(.horizontal) + } + } + .padding(.vertical, 24) + } + + VStack(spacing: 12) { + Button(action: { + for availableProduct in SGIAP.availableProducts { + if SG_CONFIG.iaps.contains(availableProduct.skProduct.productIdentifier ) { + SGIAP.purchaseProduct(availableProduct, completion: { _ in }) + } + } + SGIAP.buyProduct(product: product) + }) { + Text("Unlock Premium - $9.99") + .font(.headline) + .foregroundColor(.white) + .frame(maxWidth: .infinity) + .padding() + .background(Color.blue) + .cornerRadius(16) + } + + Button(action: { + SGIAP.restorePurchases(completion: { _ in }) + }) { + Text("Restore Purchases") + .font(.subheadline) + .foregroundColor(.blue) + } + } + .padding(24) + .background( + Rectangle() + .fill(Color(UIColor.systemBackground)) + .shadow(radius: 8, y: -4) + ) + }.navigationBarItems(trailing: closeButtonView) + + } + .colorScheme(.dark) + } + + private var closeButtonView: some View { + Button(action: { + wrapperController?.dismiss(animated: true) + }) { + if #available(iOS 15.0, *) { + Image(systemName: "xmark.circle.fill") + .font(.headline) + .symbolRenderingMode(.hierarchical) + .foregroundColor(.secondary) + } else { + Image(systemName: "xmark.circle.fill") + .font(.headline) + .foregroundColor(.secondary) + } + } + } +} + + + +@available(iOS 13.0, *) +public func sgPayWallController(presentationData: PresentationData? = nil, SGIAPManager: SGIAPManager) -> ViewController { + // let theme = presentationData?.theme ?? (UITraitCollection.current.userInterfaceStyle == .dark ? defaultDarkColorPresentationTheme : defaultPresentationTheme) + let theme = defaultDarkColorPresentationTheme + let strings = presentationData?.strings ?? defaultPresentationStrings + + let legacyController = LegacySwiftUIController( + presentation: .modal(animateIn: true), + theme: theme, + strings: strings + ) + // legacyController.displayNavigationBar = false + legacyController.statusBar.statusBarStyle = .White + legacyController.attemptNavigation = { _ in return false } + let swiftUIView = SGPayWallView(wrapperController: legacyController, SGIAP: SGIAPManager) + let controller = UIHostingController(rootView: swiftUIView, ignoreSafeArea: true) + legacyController.bind(controller: controller) + + return legacyController +} diff --git a/Swiftgram/SGSwiftSignalKit/Sources/SGSwiftSignalKit.swift b/Swiftgram/SGSwiftSignalKit/Sources/SGSwiftSignalKit.swift index 86022e876a..51b104adef 100644 --- a/Swiftgram/SGSwiftSignalKit/Sources/SGSwiftSignalKit.swift +++ b/Swiftgram/SGSwiftSignalKit/Sources/SGSwiftSignalKit.swift @@ -36,7 +36,11 @@ public struct SignalError: Error { } } -// Extension for Signals with Error types +public struct SignalCompleted: Error {} + +// Extension for Signals +// NoError can be marked a +// try? await signal.awaitable() extension Signal { @available(iOS 13.0, *) public func awaitable(file: String = #file, line: Int = #line) async throws -> T { @@ -57,46 +61,26 @@ extension Signal { disposable?.dispose() }, error: { error in - if let error = error as? Error { - continuation.resume(throwing: error) - } else { - continuation.resume(throwing: SignalError(error)) - } - disposable?.dispose() - }, - completed: { - disposable?.dispose() - } - ) - } - } -} - -// Extension for Signals with NoError -extension Signal where E == NoError { - @available(iOS 13.0, *) - public func awaitable(file: String = #file, line: Int = #line) async -> T { - return await withCheckedContinuation { continuation in - var disposable: Disposable? - let hasResumed = Atomic(value: false) - disposable = self.start( - next: { value in if !hasResumed.with({ $0 }) { let _ = hasResumed.swap(true) - continuation.resume(returning: value) + if let error = error as? Error { + continuation.resume(throwing: error) + } else { + continuation.resume(throwing: SignalError(error)) + } } else { #if DEBUG - // Consider using awaitableStream() or |> take(1) - assertionFailure("awaitable Signal emitted more than one value. \(file):\(line)") + // I don't even know what we should consider here. awaitableStream? + assertionFailure("awaitable Signal emitted an error after a value. \(file):\(line)") #endif } disposable?.dispose() }, - error: { _ in - // This will never be called for NoError - disposable?.dispose() - }, completed: { + if !hasResumed.with({ $0 }) { + let _ = hasResumed.swap(true) + continuation.resume(throwing: SignalCompleted()) + } disposable?.dispose() } ) diff --git a/submodules/AccountContext/BUILD b/submodules/AccountContext/BUILD index 1a7b23dbbe..fb83084f8a 100644 --- a/submodules/AccountContext/BUILD +++ b/submodules/AccountContext/BUILD @@ -1,7 +1,8 @@ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") sgdeps = [ - "//Swiftgram/SGSimpleSettings:SGSimpleSettings" + "//Swiftgram/SGSimpleSettings:SGSimpleSettings", + "//Swiftgram/SGIAP:SGIAP" ] swift_library( diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 19ecc29b16..73f5fc19cb 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -1,4 +1,5 @@ import SGSimpleSettings +import SGIAP import Foundation import UIKit import AsyncDisplayKit @@ -935,6 +936,7 @@ public protocol SharedAccountContext: AnyObject { var immediateExperimentalUISettings: ExperimentalUISettings { get } // MARK: Swiftgram var immediateSGStatus: SGStatus { get } + var SGIAP: SGIAPManager? { get } var currentInAppNotificationSettings: Atomic { get } var currentMediaInputSettings: Atomic { get } var currentStickerSettings: Atomic { get } diff --git a/submodules/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index 06237adcf6..951c3e9ef8 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -19,6 +19,7 @@ sgdeps = [ "//Swiftgram/SGDebugUI:SGDebugUI", "//Swiftgram/SGInputToolbar:SGInputToolbar", "//Swiftgram/SGIAP:SGIAP", + "//Swiftgram/SGPayWall:SGPayWall" # "//Swiftgram/SGContentAnalysis:SGContentAnalysis" ] diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift index c697365a23..a7ac1126e2 100644 --- a/submodules/TelegramUI/Sources/AppDelegate.swift +++ b/submodules/TelegramUI/Sources/AppDelegate.swift @@ -1348,6 +1348,12 @@ private func extractAccountManagerState(records: AccountRecordsView), NoError> = self.sharedContextPromise.get() @@ -3067,22 +3073,24 @@ extension AppDelegate { func setupIAP() { NotificationCenter.default.addObserver(forName: .SGIAPHelperPurchaseNotification, object: nil, queue: nil) { [weak self] notification in + SGLogger.shared.log("SGIAP", "Got SGIAPHelperPurchaseNotification") guard let strongSelf = self else { return } if let transaction = notification.object as? SKPaymentTransaction { let _ = (strongSelf.context.get() |> take(1) |> deliverOnMainQueue).start(next: { context in + SGLogger.shared.log("SGIAP", "Got context for SGIAPHelperPurchaseNotification") guard let context = context else { SGLogger.shared.log("SGIAP", "Empty app context (how?)") - SGLogger.shared.log("SGIAP", "Finishing transaction") + SGLogger.shared.log("SGIAP", "Finishing transaction \(transaction.transactionIdentifier ?? "nil")") SKPaymentQueue.default().finishTransaction(transaction) return } let _ = Task { await strongSelf.sendReceiptForVerification(primaryContext: context.context) await strongSelf.fetchSGStatus(primaryContext: context.context) - SGLogger.shared.log("SGIAP", "Finishing transaction") + SGLogger.shared.log("SGIAP", "Finishing transaction \(transaction.transactionIdentifier ?? "nil")") SKPaymentQueue.default().finishTransaction(transaction) } }) @@ -3100,7 +3108,7 @@ extension AppDelegate { SGSimpleSettings.shared.primaryUserId = String(primaryUserId) } - var primaryContext = await getContextForUserId(context: context, userId: primaryUserId).awaitable() + var primaryContext = try? await getContextForUserId(context: context, userId: primaryUserId).awaitable() if let primaryContext = primaryContext { SGLogger.shared.log("SGIAP", "Got primary context for user id: \(primaryContext.account.peerId.id._internalGetInt64Value())") return primaryContext @@ -3136,8 +3144,10 @@ extension AppDelegate { if let deviceToken, let apiToken { do { let _ = try await postSGReceipt(token: apiToken, - deviceToken: deviceToken, - encodedReceiptData: encodedReceiptData).awaitable() + deviceToken: deviceToken, + encodedReceiptData: encodedReceiptData).awaitable() + } catch let error as SignalCompleted { + let _ = error } catch { SGLogger.shared.log("SGIAP", "Error: \(error)") } @@ -3155,7 +3165,7 @@ extension AppDelegate { SGLogger.shared.log("SGIAP", "Asking user id \(userId) to keep connection: true") primaryContext.account.network.shouldKeepConnection.set(.single(true)) } - let iqtpResponse = await sgIqtpQuery(engine: primaryContext.engine, query: makeIqtpQuery(0, "s")).awaitable() + let iqtpResponse = try? await sgIqtpQuery(engine: primaryContext.engine, query: makeIqtpQuery(0, "s")).awaitable() guard let iqtpResponse = iqtpResponse else { SGLogger.shared.log("SGIAP", "IQTP response is nil!") // if !currentShouldKeepConnection { @@ -3165,7 +3175,7 @@ extension AppDelegate { return } SGLogger.shared.log("SGIAP", "Got IQTP response: \(iqtpResponse)") - let _ = await updateSGStatusInteractively(accountManager: primaryContext.sharedContext.accountManager, { value in + let _ = try? await updateSGStatusInteractively(accountManager: primaryContext.sharedContext.accountManager, { value in var value = value let newStatus: Int64 diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index e5d251f80a..820309927f 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -243,12 +243,13 @@ public final class SharedAccountContextImpl: SharedAccountContext { } private var experimentalUISettingsDisposable: Disposable? + // MARK: Swiftgram private var immediateSGStatusValue = Atomic(value: SGStatus.default) public var immediateSGStatus: SGStatus { return self.immediateSGStatusValue.with { $0 } } private var sgStatusDisposable: Disposable? - + public var SGIAP: SGIAPManager? public var presentGlobalController: (ViewController, Any?) -> Void = { _, _ in } public var presentCrossfadeController: () -> Void = {} @@ -485,6 +486,8 @@ public final class SharedAccountContextImpl: SharedAccountContext { let _ = immediateSGStatusValue.swap(settings) } }) + self.initSGIAP(isMainApp: applicationBindings.isMainApp) + // let _ = self.contactDataManager?.personNameDisplayOrder().start(next: { order in let _ = updateContactSettingsInteractively(accountManager: accountManager, { settings in @@ -3037,3 +3040,14 @@ private func peerInfoControllerImpl(context: AccountContext, updatedPresentation } return nil } + +// MARK: Swiftgram +extension SharedAccountContextImpl { + func initSGIAP(isMainApp: Bool) { + if isMainApp { + self.SGIAP = SGIAPManager() + } else { + self.SGIAP = nil + } + } +}