Restrict paywall to on-demand rules (#639)
Rather than whole module. Closes #638
This commit is contained in:
parent
a9fa6a2f62
commit
4877c2bd20
|
@ -32,7 +32,7 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "git@github.com:passepartoutvpn/passepartoutkit",
|
||||
"state" : {
|
||||
"revision" : "263bedc756d07eb107d7bfe3b50dbc5db28675d4"
|
||||
"revision" : "3d1a60be9722861f9de45e355d520bae33ac87a9"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -31,7 +31,7 @@ let package = Package(
|
|||
],
|
||||
dependencies: [
|
||||
// .package(url: "git@github.com:passepartoutvpn/passepartoutkit", from: "0.7.0"),
|
||||
.package(url: "git@github.com:passepartoutvpn/passepartoutkit", revision: "263bedc756d07eb107d7bfe3b50dbc5db28675d4"),
|
||||
.package(url: "git@github.com:passepartoutvpn/passepartoutkit", revision: "3d1a60be9722861f9de45e355d520bae33ac87a9"),
|
||||
// .package(path: "../../../passepartoutkit"),
|
||||
.package(url: "git@github.com:passepartoutvpn/passepartoutkit-openvpn-openssl", from: "0.6.0"),
|
||||
// .package(path: "../../../passepartoutkit-openvpn-openssl"),
|
||||
|
|
|
@ -30,11 +30,16 @@ extension IAPManager: ProfileProcessor {
|
|||
func processedProfile(_ profile: Profile) throws -> Profile {
|
||||
var builder = profile.builder()
|
||||
|
||||
// suppress on-demand module if not eligible
|
||||
// suppress on-demand rules if not eligible
|
||||
if !isEligible(for: .onDemand) {
|
||||
pp_log(.app, .notice, "Disable on-demand rules, not eligible")
|
||||
builder.modules.removeAll {
|
||||
$0 is OnDemandModule
|
||||
pp_log(.app, .notice, "Suppress on-demand rules, not eligible")
|
||||
|
||||
if let onDemandModuleIndex = builder.modules.firstIndex(where: { $0 is OnDemandModule }),
|
||||
let onDemandModule = builder.modules[onDemandModuleIndex] as? OnDemandModule {
|
||||
|
||||
var onDemandBuilder = onDemandModule.builder()
|
||||
onDemandBuilder.policy = .any
|
||||
builder.modules[onDemandModuleIndex] = onDemandBuilder.tryBuild()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -243,6 +243,8 @@ public enum Strings {
|
|||
public static let `protocol` = Strings.tr("Localizable", "global.protocol", fallback: "Protocol")
|
||||
/// Public key
|
||||
public static let publicKey = Strings.tr("Localizable", "global.public_key", fallback: "Public key")
|
||||
/// Purchase
|
||||
public static let purchase = Strings.tr("Localizable", "global.purchase", fallback: "Purchase")
|
||||
/// Delete
|
||||
public static let remove = Strings.tr("Localizable", "global.remove", fallback: "Delete")
|
||||
/// Restart
|
||||
|
@ -312,6 +314,8 @@ public enum Strings {
|
|||
public static let mobile = Strings.tr("Localizable", "modules.on_demand.mobile", fallback: "Mobile")
|
||||
/// Policy
|
||||
public static let policy = Strings.tr("Localizable", "modules.on_demand.policy", fallback: "Policy")
|
||||
/// Add on-demand rules
|
||||
public static let purchase = Strings.tr("Localizable", "modules.on_demand.purchase", fallback: "Add on-demand rules")
|
||||
public enum Policy {
|
||||
/// Activate the VPN %@.
|
||||
public static func footer(_ p1: Any) -> String {
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
"global.private_key" = "Private key";
|
||||
"global.protocol" = "Protocol";
|
||||
"global.public_key" = "Public key";
|
||||
"global.purchase" = "Purchase";
|
||||
"global.remove" = "Delete";
|
||||
"global.restart" = "Restart";
|
||||
"global.route" = "Route";
|
||||
|
@ -168,6 +169,7 @@
|
|||
"modules.ip.routes.excluded" = "Excluded routes";
|
||||
"modules.ip.routes.add_family" = "Add %@";
|
||||
|
||||
"modules.on_demand.purchase" = "Add on-demand rules";
|
||||
"modules.on_demand.policy" = "Policy";
|
||||
"modules.on_demand.policy.footer" = "Activate the VPN %@.";
|
||||
"modules.on_demand.policy.footer.any" = "in any network";
|
||||
|
|
|
@ -38,6 +38,9 @@ private struct OnDemandView: View {
|
|||
@EnvironmentObject
|
||||
private var theme: Theme
|
||||
|
||||
@EnvironmentObject
|
||||
private var iapManager: IAPManager
|
||||
|
||||
@ObservedObject
|
||||
private var editor: ProfileEditor
|
||||
|
||||
|
@ -46,6 +49,9 @@ private struct OnDemandView: View {
|
|||
@Binding
|
||||
private var draft: OnDemandModule.Builder
|
||||
|
||||
@State
|
||||
private var paywallReason: PaywallReason?
|
||||
|
||||
init(
|
||||
editor: ProfileEditor,
|
||||
original: OnDemandModule.Builder,
|
||||
|
@ -59,15 +65,10 @@ private struct OnDemandView: View {
|
|||
var body: some View {
|
||||
Group {
|
||||
enabledSection
|
||||
if draft.isEnabled {
|
||||
policySection
|
||||
if draft.policy != .any {
|
||||
networkSection
|
||||
wifiSection
|
||||
}
|
||||
}
|
||||
restrictedSection
|
||||
}
|
||||
.asModuleView(with: editor, draft: draft)
|
||||
.modifier(PaywallModifier(reason: $paywallReason))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,6 +85,28 @@ private extension OnDemandView {
|
|||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
var restrictedSection: some View {
|
||||
switch iapManager.paywallReason(forFeature: .onDemand) {
|
||||
case .purchase(let feature):
|
||||
Button(Strings.Modules.OnDemand.purchase) {
|
||||
paywallReason = .purchase(feature)
|
||||
}
|
||||
|
||||
case .restricted:
|
||||
EmptyView()
|
||||
|
||||
default:
|
||||
if draft.isEnabled {
|
||||
policySection
|
||||
if draft.policy != .any {
|
||||
networkSection
|
||||
wifiSection
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var policySection: some View {
|
||||
Picker(Strings.Modules.OnDemand.policy, selection: $draft.policy) {
|
||||
ForEach(Self.allPolicies, id: \.self) {
|
||||
|
|
|
@ -104,7 +104,7 @@ private extension ProfileCoordinator {
|
|||
func onNewModule(_ moduleType: ModuleType) {
|
||||
switch moduleType {
|
||||
case .onDemand:
|
||||
paywallReason = iapManager.paywallReason(forFeature: .onDemand)
|
||||
break
|
||||
|
||||
default:
|
||||
paywallReason = iapManager.paywallReason(forFeature: .networkSettings)
|
||||
|
|
|
@ -34,7 +34,7 @@ extension EditableModule where Self: ModuleViewProviding {
|
|||
moduleView(with: ProfileEditor(modules: [self]))
|
||||
.navigationTitle(title)
|
||||
}
|
||||
.environmentObject(Theme())
|
||||
.withMockEnvironment()
|
||||
}
|
||||
|
||||
@MainActor
|
||||
|
@ -42,6 +42,15 @@ extension EditableModule where Self: ModuleViewProviding {
|
|||
NavigationStack {
|
||||
content(ProfileEditor(modules: [self]), self)
|
||||
}
|
||||
.environmentObject(Theme())
|
||||
.withMockEnvironment()
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private extension View {
|
||||
func withMockEnvironment() -> some View {
|
||||
environmentObject(Theme())
|
||||
.environmentObject(IAPManager.mock)
|
||||
.environmentObject(ConnectionObserver.mock)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue