Encapsulate calculation of former products
Use an interface (BuildProducts) that makes understandable and easily extensibile how some in-app products are inferred by build number.
This commit is contained in:
parent
ed81e374aa
commit
99e48119f7
|
@ -7,6 +7,7 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0E0392772818732D00827C10 /* BuildProducts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0392762818732D00827C10 /* BuildProducts.swift */; };
|
||||
0E065F112813269500062CAF /* WelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E065F102813269500062CAF /* WelcomeView.swift */; };
|
||||
0E0BD27327B2EA2C00583AC5 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0BD27227B2EA2C00583AC5 /* MainView.swift */; };
|
||||
0E0BD27627B2EB2200583AC5 /* DonateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0BD27527B2EB2200583AC5 /* DonateView.swift */; };
|
||||
|
@ -188,6 +189,7 @@
|
|||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0E0392762818732D00827C10 /* BuildProducts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildProducts.swift; sourceTree = "<group>"; };
|
||||
0E065F102813269500062CAF /* WelcomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeView.swift; sourceTree = "<group>"; };
|
||||
0E0BD27227B2EA2C00583AC5 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
|
||||
0E0BD27527B2EB2200583AC5 /* DonateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DonateView.swift; sourceTree = "<group>"; };
|
||||
|
@ -506,6 +508,7 @@
|
|||
0E92781227E7CD530057BB81 /* InApp */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0E0392762818732D00827C10 /* BuildProducts.swift */,
|
||||
0EB17EA327D2263700D473B5 /* LocalProduct.swift */,
|
||||
0E53249627D26B51002565C3 /* ProductManager.swift */,
|
||||
);
|
||||
|
@ -904,6 +907,7 @@
|
|||
0E35C09A280E95BB0071FA35 /* ProviderProfileAvailability.swift in Sources */,
|
||||
0E5349C827C176D100C71BB3 /* EndpointView+WireGuard.swift in Sources */,
|
||||
0EBC076027EC587900208AD9 /* SwiftGen+Strings.swift in Sources */,
|
||||
0E0392772818732D00827C10 /* BuildProducts.swift in Sources */,
|
||||
0E5683B927C2825D00EAF1CD /* DiagnosticsView.swift in Sources */,
|
||||
0E71ACFD27C1321A00F85C4B /* ActivityView.swift in Sources */,
|
||||
0E44689627B051C300A14CE4 /* ProfileView.swift in Sources */,
|
||||
|
|
|
@ -112,11 +112,10 @@ class AppContext {
|
|||
|
||||
// app
|
||||
|
||||
productManager = ProductManager(.init(
|
||||
productManager = ProductManager(
|
||||
appType: Constants.InApp.appType,
|
||||
lastFullVersionBuild: Constants.InApp.lastFullVersionBuild,
|
||||
lastNetworkSettingsBuild: Constants.InApp.lastNetworkSettingsBuild
|
||||
))
|
||||
buildProducts: Constants.InApp.buildProducts
|
||||
)
|
||||
intentsManager = IntentsManager()
|
||||
reviewer = Reviewer()
|
||||
|
||||
|
|
|
@ -71,12 +71,22 @@ extension Constants {
|
|||
}
|
||||
|
||||
#if targetEnvironment(macCatalyst)
|
||||
static let lastFullVersionBuild: (Int, LocalProduct) = (0, .fullVersion_macOS)
|
||||
static let buildProducts = BuildProducts {
|
||||
if $0 <= 3000 {
|
||||
return [.networkSettings]
|
||||
}
|
||||
return []
|
||||
}
|
||||
#else
|
||||
static let lastFullVersionBuild: (Int, LocalProduct) = (2016, .fullVersion_iOS)
|
||||
static let buildProducts = BuildProducts {
|
||||
if $0 <= 2016 {
|
||||
return [.fullVersion_iOS]
|
||||
} else if $0 <= 3000 {
|
||||
return [.networkSettings]
|
||||
}
|
||||
return []
|
||||
}
|
||||
#endif
|
||||
|
||||
static let lastNetworkSettingsBuild = 2999
|
||||
|
||||
private static var isBeta: Bool {
|
||||
#if targetEnvironment(simulator)
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// BuildProducts.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 4/26/22.
|
||||
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct BuildProducts {
|
||||
private let productsAtBuild: (Int) -> [LocalProduct]
|
||||
|
||||
init(productsAtBuild: @escaping (Int) -> [LocalProduct]) {
|
||||
self.productsAtBuild = productsAtBuild
|
||||
}
|
||||
|
||||
func products(atBuild build: Int) -> [LocalProduct] {
|
||||
productsAtBuild(build)
|
||||
}
|
||||
|
||||
func hasProduct(_ product: LocalProduct, atBuild build: Int) -> Bool {
|
||||
productsAtBuild(build).contains(product)
|
||||
}
|
||||
}
|
|
@ -43,26 +43,10 @@ class ProductManager: NSObject, ObservableObject {
|
|||
|
||||
case fullVersion = 2
|
||||
}
|
||||
|
||||
struct Configuration {
|
||||
let appType: AppType
|
||||
|
||||
let lastFullVersionBuild: (Int, LocalProduct)
|
||||
|
||||
let lastNetworkSettingsBuild: Int
|
||||
|
||||
init(
|
||||
appType: AppType,
|
||||
lastFullVersionBuild: (Int, LocalProduct),
|
||||
lastNetworkSettingsBuild: Int
|
||||
) {
|
||||
self.appType = appType
|
||||
self.lastFullVersionBuild = lastFullVersionBuild
|
||||
self.lastNetworkSettingsBuild = lastNetworkSettingsBuild
|
||||
}
|
||||
}
|
||||
|
||||
let cfg: Configuration
|
||||
let appType: AppType
|
||||
|
||||
let buildProducts: BuildProducts
|
||||
|
||||
@Published private(set) var isRefreshingProducts = false
|
||||
|
||||
|
@ -82,8 +66,10 @@ class ProductManager: NSObject, ObservableObject {
|
|||
|
||||
private var refreshRequest: SKReceiptRefreshRequest?
|
||||
|
||||
init(_ cfg: Configuration) {
|
||||
self.cfg = cfg
|
||||
init(appType: AppType, buildProducts: BuildProducts) {
|
||||
self.appType = appType
|
||||
self.buildProducts = buildProducts
|
||||
|
||||
products = []
|
||||
inApp = InApp()
|
||||
purchasedAppBuild = nil
|
||||
|
@ -195,7 +181,7 @@ class ProductManager: NSObject, ObservableObject {
|
|||
}
|
||||
|
||||
private func isFullVersion() -> Bool {
|
||||
if cfg.appType == .fullVersion {
|
||||
if appType == .fullVersion {
|
||||
return true
|
||||
}
|
||||
if isCurrentPlatformVersion() {
|
||||
|
@ -206,7 +192,7 @@ class ProductManager: NSObject, ObservableObject {
|
|||
|
||||
func isEligible(forFeature feature: LocalProduct) -> Bool {
|
||||
if let purchasedAppBuild = purchasedAppBuild {
|
||||
if feature == .networkSettings && purchasedAppBuild <= cfg.lastNetworkSettingsBuild {
|
||||
if feature == .networkSettings && buildProducts.hasProduct(.networkSettings, atBuild: purchasedAppBuild) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -222,7 +208,7 @@ class ProductManager: NSObject, ObservableObject {
|
|||
}
|
||||
|
||||
func isEligibleForFeedback() -> Bool {
|
||||
return cfg.appType == .beta || !purchasedFeatures.isEmpty
|
||||
return appType == .beta || !purchasedFeatures.isEmpty
|
||||
}
|
||||
|
||||
func hasPurchased(_ product: LocalProduct) -> Bool {
|
||||
|
@ -256,9 +242,9 @@ class ProductManager: NSObject, ObservableObject {
|
|||
if let buildNumber = purchasedAppBuild {
|
||||
pp_log.debug("Original purchased build: \(buildNumber)")
|
||||
|
||||
// treat former purchases as full versions
|
||||
if buildNumber <= cfg.lastFullVersionBuild.0 {
|
||||
purchasedFeatures.insert(cfg.lastFullVersionBuild.1)
|
||||
// assume some purchases by build number
|
||||
buildProducts.products(atBuild: buildNumber).forEach {
|
||||
purchasedFeatures.insert($0)
|
||||
}
|
||||
}
|
||||
if let iapReceipts = receipt.inAppPurchaseReceipts {
|
||||
|
|
|
@ -51,7 +51,7 @@ struct PaywallView: View {
|
|||
|
||||
var body: some View {
|
||||
Group {
|
||||
if productManager.cfg.appType == .beta {
|
||||
if productManager.appType == .beta {
|
||||
BetaView()
|
||||
} else {
|
||||
PurchaseView(
|
||||
|
|
Loading…
Reference in New Issue