From d6c1059e997274c8ade3fe7d113612d9333933bd Mon Sep 17 00:00:00 2001 From: True Zhuanjia Date: Mon, 22 Jun 2026 00:53:01 +0800 Subject: [PATCH] improved iap workflow --- VoidLink/Input/PencilHandler.swift | 9 +- VoidLink/Localization/Localizable.xcstrings | 85 +++++++++++++++++-- VoidLink/Utility/IAPManager.swift | 29 ++++++- .../ViewControllers/SettingsViewController.m | 1 + 4 files changed, 109 insertions(+), 15 deletions(-) diff --git a/VoidLink/Input/PencilHandler.swift b/VoidLink/Input/PencilHandler.swift index d907bb6a..cd198fff 100644 --- a/VoidLink/Input/PencilHandler.swift +++ b/VoidLink/Input/PencilHandler.swift @@ -260,17 +260,18 @@ import UIKit let strokePhase = getStrokePhase(sampleIndex: self.strokeSampleIndex) + let forceMapping = pressureCurveEnabled ? self.strokeLUT.value(at: force) : force switch strokePhase { case .phase1: - targetForce = pencilTickEnabled ? 0 : self.strokeLUT.value(at: force) + targetForce = pencilTickEnabled ? 0 : forceMapping case .phase2: - targetForce = self.strokeLUT.value(at: force) + targetForce = forceMapping targetForce = max(targetForce,previousTargetForce) equalizedForce = targetForce*(phase2EqualizationStrength - equalizationStep*Float(strokeSampleIndex-phase1StrokeSampleIndexEnd-1)) case .phase3: - targetForce = self.strokeLUT.value(at: force) + targetForce = forceMapping } - targetForce = self.pressureCurveEnabled ? targetForce : force + targetForce = pencilTickEnabled ? targetForce : force previousForce = force previousTargetForce = targetForce diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index 68548f33..3512d9fb 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -513,6 +513,29 @@ } } }, + "[%@] has been restored" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "【%@】已恢复" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "「%@」已恢復" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "「%@」已恢復" + } + } + } + }, "%@ is currently running" : { "extractionState" : "manual", "localizations" : { @@ -715,7 +738,7 @@ }, "zh-HK" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "方向鍵" } } @@ -6612,19 +6635,42 @@ "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "绘画" + "value" : "绘画进阶套件" } }, "zh-Hant" : { "stringUnit" : { "state" : "translated", - "value" : "繪畫" + "value" : "繪畫進階套件" } }, "zh-HK" : { "stringUnit" : { "state" : "translated", - "value" : "繪畫" + "value" : "繪畫進階套件" + } + } + } + }, + "Drawing Toolkit already purchased" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "您已拥有【绘画进阶套件】" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "您已擁有「繪畫進階套件」" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "您已擁有「繪畫進階套件」" } } } @@ -10994,19 +11040,19 @@ "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "购买 [%@] 可解锁:\n- 专业级压力曲线工具。\n- 在远程绘图流程中提升笔触传输效率与响应表现,并支持用户自定义的双击及捏合键盘/鼠标快捷键。\n- 专属绘图相关的屏显按钮。\n以及更多功能..." + "value" : "购买 [%@] 可解锁:\n- 专业级笔压曲线工具。\n- 远程绘画笔迹传输、笔触响应性能优化。\n- 支持用户自定义的双击及捏合键盘/鼠标快捷键。\n- 专属绘图相关的屏显按钮。\n以及更多...\n未购买该套件不影响基础绘画功能。" } }, "zh-Hant" : { "stringUnit" : { "state" : "translated", - "value" : "解鎖 [%@] :\n- 專業級壓力曲線工具。\n- 在遠端繪圖流程中提升筆觸傳輸效率與響應表現,並支援使用者自訂的雙擊及捏合鍵盤/滑鼠快捷鍵。\n- 專屬繪圖相關的螢幕顯示按鈕。\n- 以及更多功能..." + "value" : "解鎖 [%@] :\n- 專業級筆壓曲線工具。\n- 最佳化遠端繪畫的筆跡傳輸與筆觸響應效能。\n- 並支援使用者自訂的雙擊及捏合鍵盤/滑鼠快捷鍵。\n- 專屬繪圖相關的螢幕顯示按鈕。\n以及更多...\n未購買此套件不影響基礎繪畫功能。" } }, "zh-HK" : { "stringUnit" : { "state" : "translated", - "value" : "解鎖 [%@] :\n- 專業級壓力曲線工具。\n- 在遠端繪圖流程中提升筆觸傳輸效率與響應表現,並支援使用者自訂的雙擊及捏合鍵盤/滑鼠快捷鍵。\n- 專屬繪圖相關的螢幕顯示按鈕。\n- 以及更多功能...\n基礎繪畫功能無需購買 [%@] 即可使用。" + "value" : "解鎖 [%@] :\n- 專業級筆壓曲線工具。\n- 最佳化遠端繪畫的筆跡傳輸與筆觸響應效能。\n- 並支援使用者自訂的雙擊及捏合鍵盤/滑鼠快捷鍵。\n- 專屬繪圖相關的螢幕顯示按鈕。\n以及更多...\n未購買此套件不影響基礎繪畫功能。" } } } @@ -16376,6 +16422,29 @@ } } }, + "Unable to detect purchased product: %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未检测到已购产品【%@】" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "未偵測到已購產品「%@」" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "未偵測到已購產品「%@」" + } + } + } + }, "Undo" : { "extractionState" : "manual", "localizations" : { @@ -17335,4 +17404,4 @@ } }, "version" : "1.1" -} +} \ No newline at end of file diff --git a/VoidLink/Utility/IAPManager.swift b/VoidLink/Utility/IAPManager.swift index 06db4cd7..9b1768c1 100644 --- a/VoidLink/Utility/IAPManager.swift +++ b/VoidLink/Utility/IAPManager.swift @@ -259,7 +259,6 @@ import UIKit } await transaction.finish() IAPManager.handlePurchaseSuccess(product) - NotificationCenter.default.post(name: product.purchaseSucceededNotification(), object: nil) case .unverified(_, let err): NotificationCenter.default.post(name: product.purchaseAbortedNotification(), object: PurchaseInterruption.unlockNow, userInfo:["interruption": PurchaseInterruption.unlockNow.rawValue]) await MainActor.run { @@ -279,6 +278,7 @@ import UIKit let dataMan = DataManager() let settings = dataMan.retrieveSettings() settings?.onscreenControls = 1 + settings?.pencilTickMode = NSNumber(value: PencilTickMode.ManualTick.rawValue) dataMan.saveData() let profileMan = OSCProfilesManager.sharedManager(.zero) var toolkitProfileIndex = profileMan.getIndex(byName: "Pencil Pro") @@ -288,6 +288,7 @@ import UIKit default: break } + NotificationCenter.default.post(name: product.purchaseSucceededNotification(), object: nil) } private func purchaseLegacy(_ product: AddOnProduct) { @@ -437,8 +438,30 @@ import UIKit do { if #available(iOS 15.0, *) { try await AppStore.sync() - } else { - // Fallback on earlier versions + 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]) diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index c5b7ff1e..6d945afd 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -3847,6 +3847,7 @@ BOOL isCustomResolution(int resolutionSelected) { - (void)pencilProPurchaseSucceeded:(NSNotification *)notification{ self.onScreenWidgetSelector.selectedSegmentIndex = OnScreenControlsLevelCustom; + self.pencilTickSelector.selectedSegmentIndex = ManualTick; } - (void)pencilTickIntervalSliderMoved:(UISlider* )sender{