- handle iap purchase on app launch

- localization fix
- iap workflow fixes
This commit is contained in:
True Zhuanjia committed 2026-06-22 12:30:17 +08:00
1 parent 98e8305c94
commit ca17c1cc66
6 files changed
+61 -66

No files matched your search

@@ -308,7 +308,7 @@ class OSCProfilesManager: NSObject {
let defaults = UserDefaults.standard let defaults = UserDefaults.standard
let needImportDefaultTemplates = defaults.object(forKey: Self.widgetProfileUpdatedKey) == nil let needImportDefaultTemplates = defaults.object(forKey: Self.widgetProfileUpdatedKey) == nil
if profiles.count == 0 || needImportDefaultTemplates { if (profiles.count == 0 || needImportDefaultTemplates) && !GenericUtils.pencilProPurchaseProcessedWithImportingWidgetTemplates {
importDefaultTemplates() importDefaultTemplates()
defaults.set(true, forKey: Self.widgetProfileUpdatedKey) defaults.set(true, forKey: Self.widgetProfileUpdatedKey)
defaults.synchronize() defaults.synchronize()
+1 -1
View File
@@ -1765,7 +1765,7 @@
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "= FPS Example (Keyboard & Mouse)" "value" : "FPS Example (Keyboard & Mouse)"
} }
}, },
"zh-Hans" : { "zh-Hans" : {
+14
View File
@@ -262,6 +262,20 @@ import UIKit
} }
} }
@objc static var pencilProPurchaseProcessedWithImportingWidgetTemplates: Bool = false
@objc static func handleAddOnProductPurchaseIntent(for product:AddOnProduct) {
let key = "addOnProduct_\(product.productId())_purchased"
let defaults = UserDefaults.standard
let purchased = defaults.bool(forKey: key)
if !purchased {
IAPManager.checkPurchaseInfo(product) { info in
if info.valid {
IAPManager.handlePurchaseSuccess(product)
defaults.set(true, forKey: key)
}
}
}
}
@objc static var hasTappedOnscreenGyroButton = false @objc static var hasTappedOnscreenGyroButton = false
@objc static func isFirstTappingOnscreenGyroButton() -> Bool { @objc static func isFirstTappingOnscreenGyroButton() -> Bool {
+37 -60
View File
@@ -282,7 +282,10 @@ import UIKit
dataMan.saveData() dataMan.saveData()
let profileMan = OSCProfilesManager.sharedManager(.zero) let profileMan = OSCProfilesManager.sharedManager(.zero)
var toolkitProfileIndex = profileMan.getIndex(byName: "Pencil Pro") var toolkitProfileIndex = profileMan.getIndex(byName: "Pencil Pro")
if toolkitProfileIndex == nil {profileMan.importDefaultTemplates()} if toolkitProfileIndex == nil {
profileMan.importDefaultTemplates()
GenericUtils.pencilProPurchaseProcessedWithImportingWidgetTemplates = true
}
toolkitProfileIndex = profileMan.getIndex(byName: "Pencil Pro") toolkitProfileIndex = profileMan.getIndex(byName: "Pencil Pro")
profileMan.setProfileToSelected(toolkitProfileIndex ?? 1) profileMan.setProfileToSelected(toolkitProfileIndex ?? 1)
default: default:
@@ -305,35 +308,44 @@ import UIKit
} }
// MARK: - Restore (StoreKit 2) // MARK: - Restore (StoreKit 2)
@objc static func restore(product: AddOnProduct, in viewController: UIViewController){
if #available(iOS 15.0, *) {
Task{
do {
try await AppStore.sync()
IAPManager.checkPurchaseInfo(product) { info in
if info.valid {
IAPManager.handlePurchaseSuccess(product)
AlertControllerUtil.showAlert(
in: viewController,
title: "",
message: LocalizationHelper.localizedString(forKey:"[%@] has been restored", product.productName()),
withCancel: false,
buttonTitle: "OK".localized,
countdown: 0
)
}
else {
NotificationCenter.default.post(name: product.purchaseAbortedNotification(), object: PurchaseInterruption.restore, userInfo:["interruption": PurchaseInterruption.restore.rawValue])
AlertControllerUtil.showAlert(
in: viewController,
title: "",
message: LocalizationHelper.localizedString(forKey:"Unable to detect purchased product: %@", product.productName()),
withCancel: false,
buttonTitle: "OK".localized,
countdown: 0
)
}
}
@objc public func restorePurchasesStoreKit2() { } catch {
if #available(iOS 15.0, *, *) { NotificationCenter.default.post(name: product.purchaseAbortedNotification(), object: PurchaseInterruption.restore, userInfo:["interruption": PurchaseInterruption.restore.rawValue])
Task { print("Restore failed: \(error)")
await restoreStoreKit2()
}
}
else{
restorePurchasesLegacy()
}
}
@available(iOS 15.0, *, *)
private func restoreStoreKit2() async {
for await result in Transaction.currentEntitlements {
if case .verified(let transaction) = result,
let adp = AddOnProduct.from(productId: transaction.productID) {
await MainActor.run {
self.delegate?.iapManagerDidRestore(adp)
} }
} }
} }
} }
private func restorePurchasesLegacy() {
SKPaymentQueue.default().restoreCompletedTransactions()
}
// MARK: - Listen update // MARK: - Listen update
@available(iOS 15.0, *, *) @available(iOS 15.0, *, *)
@@ -431,42 +443,7 @@ import UIKit
let restoreAction = UIAlertAction(title: LocalizationHelper.localizedString(forKey: "Restore Purchase"), style: .default) { _ in let restoreAction = UIAlertAction(title: LocalizationHelper.localizedString(forKey: "Restore Purchase"), style: .default) { _ in
if #available(iOS 13.0, *) { if #available(iOS 13.0, *) {
Task{ IAPManager.restore(product: .PencilProPack, in: viewController)
do {
if #available(iOS 15.0, *) {
try await AppStore.sync()
IAPManager.checkPurchaseInfo(product) { info in
if info.valid {
IAPManager.handlePurchaseSuccess(product)
AlertControllerUtil.showAlert(
in: viewController,
title: "",
message: LocalizationHelper.localizedString(forKey:"[%@] has been restored", product.productName()),
withCancel: false,
buttonTitle: "OK".localized,
countdown: 0
)
}
else {
NotificationCenter.default.post(name: product.purchaseAbortedNotification(), object: PurchaseInterruption.restore, userInfo:["interruption": PurchaseInterruption.restore.rawValue])
AlertControllerUtil.showAlert(
in: viewController,
title: "",
message: LocalizationHelper.localizedString(forKey:"Unable to detect purchased product: %@", product.productName()),
withCancel: false,
buttonTitle: "OK".localized,
countdown: 0
)
}
}
}
} catch {
NotificationCenter.default.post(name: product.purchaseAbortedNotification(), object: PurchaseInterruption.restore, userInfo:["interruption": PurchaseInterruption.restore.rawValue])
print("Restore failed: \(error)")
}
}
} else {
// Fallback on earlier versions
} }
} }
@@ -1875,10 +1875,12 @@ static NSMutableSet* hostList;
[self prewarmSoftKeyboard]; [self prewarmSoftKeyboard];
[IAPManager.shared fetchProducts];
[self changeDefaultSettings]; [self changeDefaultSettings];
[self updatePartialSettings]; [self updatePartialSettings];
[IAPManager.shared fetchProducts];
[GenericUtils handleAddOnProductPurchaseIntentFor:AddOnProductPencilProPack];
/* /*
if (@available(iOS 15.0, *)) { if (@available(iOS 15.0, *)) {
[IAPManager checkPurchaseInfo:AddOnProductPencilProPack completion:^(PurchaseInfo* info) { [IAPManager checkPurchaseInfo:AddOnProductPencilProPack completion:^(PurchaseInfo* info) {
@@ -3848,8 +3848,10 @@ BOOL isCustomResolution(int resolutionSelected) {
} }
- (void)pencilProPurchaseSucceeded:(NSNotification *)notification{ - (void)pencilProPurchaseSucceeded:(NSNotification *)notification{
self.onScreenWidgetSelector.selectedSegmentIndex = OnScreenControlsLevelCustom; dispatch_async(dispatch_get_main_queue(), ^{
self.pencilTickSelector.selectedSegmentIndex = ManualTick; self.onScreenWidgetSelector.selectedSegmentIndex = OnScreenControlsLevelCustom;
self.pencilTickSelector.selectedSegmentIndex = ManualTick;
});
} }
- (void)pencilTickIntervalSliderMoved:(UISlider* )sender{ - (void)pencilTickIntervalSliderMoved:(UISlider* )sender{