mirror of
https://github.com/passepartoutvpn/passepartout-apple.git
synced 2025-02-16 12:52:11 +00:00
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",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "git@github.com:passepartoutvpn/passepartoutkit",
|
"location" : "git@github.com:passepartoutvpn/passepartoutkit",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "263bedc756d07eb107d7bfe3b50dbc5db28675d4"
|
"revision" : "3d1a60be9722861f9de45e355d520bae33ac87a9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -31,7 +31,7 @@ let package = Package(
|
|||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
// .package(url: "git@github.com:passepartoutvpn/passepartoutkit", from: "0.7.0"),
|
// .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(path: "../../../passepartoutkit"),
|
||||||
.package(url: "git@github.com:passepartoutvpn/passepartoutkit-openvpn-openssl", from: "0.6.0"),
|
.package(url: "git@github.com:passepartoutvpn/passepartoutkit-openvpn-openssl", from: "0.6.0"),
|
||||||
// .package(path: "../../../passepartoutkit-openvpn-openssl"),
|
// .package(path: "../../../passepartoutkit-openvpn-openssl"),
|
||||||
|
@ -30,11 +30,16 @@ extension IAPManager: ProfileProcessor {
|
|||||||
func processedProfile(_ profile: Profile) throws -> Profile {
|
func processedProfile(_ profile: Profile) throws -> Profile {
|
||||||
var builder = profile.builder()
|
var builder = profile.builder()
|
||||||
|
|
||||||
// suppress on-demand module if not eligible
|
// suppress on-demand rules if not eligible
|
||||||
if !isEligible(for: .onDemand) {
|
if !isEligible(for: .onDemand) {
|
||||||
pp_log(.app, .notice, "Disable on-demand rules, not eligible")
|
pp_log(.app, .notice, "Suppress on-demand rules, not eligible")
|
||||||
builder.modules.removeAll {
|
|
||||||
$0 is OnDemandModule
|
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 static let `protocol` = Strings.tr("Localizable", "global.protocol", fallback: "Protocol")
|
||||||
/// Public key
|
/// Public key
|
||||||
public static let publicKey = Strings.tr("Localizable", "global.public_key", fallback: "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
|
/// Delete
|
||||||
public static let remove = Strings.tr("Localizable", "global.remove", fallback: "Delete")
|
public static let remove = Strings.tr("Localizable", "global.remove", fallback: "Delete")
|
||||||
/// Restart
|
/// Restart
|
||||||
@ -312,6 +314,8 @@ public enum Strings {
|
|||||||
public static let mobile = Strings.tr("Localizable", "modules.on_demand.mobile", fallback: "Mobile")
|
public static let mobile = Strings.tr("Localizable", "modules.on_demand.mobile", fallback: "Mobile")
|
||||||
/// Policy
|
/// Policy
|
||||||
public static let policy = Strings.tr("Localizable", "modules.on_demand.policy", fallback: "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 {
|
public enum Policy {
|
||||||
/// Activate the VPN %@.
|
/// Activate the VPN %@.
|
||||||
public static func footer(_ p1: Any) -> String {
|
public static func footer(_ p1: Any) -> String {
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
"global.private_key" = "Private key";
|
"global.private_key" = "Private key";
|
||||||
"global.protocol" = "Protocol";
|
"global.protocol" = "Protocol";
|
||||||
"global.public_key" = "Public key";
|
"global.public_key" = "Public key";
|
||||||
|
"global.purchase" = "Purchase";
|
||||||
"global.remove" = "Delete";
|
"global.remove" = "Delete";
|
||||||
"global.restart" = "Restart";
|
"global.restart" = "Restart";
|
||||||
"global.route" = "Route";
|
"global.route" = "Route";
|
||||||
@ -168,6 +169,7 @@
|
|||||||
"modules.ip.routes.excluded" = "Excluded routes";
|
"modules.ip.routes.excluded" = "Excluded routes";
|
||||||
"modules.ip.routes.add_family" = "Add %@";
|
"modules.ip.routes.add_family" = "Add %@";
|
||||||
|
|
||||||
|
"modules.on_demand.purchase" = "Add on-demand rules";
|
||||||
"modules.on_demand.policy" = "Policy";
|
"modules.on_demand.policy" = "Policy";
|
||||||
"modules.on_demand.policy.footer" = "Activate the VPN %@.";
|
"modules.on_demand.policy.footer" = "Activate the VPN %@.";
|
||||||
"modules.on_demand.policy.footer.any" = "in any network";
|
"modules.on_demand.policy.footer.any" = "in any network";
|
||||||
|
@ -38,6 +38,9 @@ private struct OnDemandView: View {
|
|||||||
@EnvironmentObject
|
@EnvironmentObject
|
||||||
private var theme: Theme
|
private var theme: Theme
|
||||||
|
|
||||||
|
@EnvironmentObject
|
||||||
|
private var iapManager: IAPManager
|
||||||
|
|
||||||
@ObservedObject
|
@ObservedObject
|
||||||
private var editor: ProfileEditor
|
private var editor: ProfileEditor
|
||||||
|
|
||||||
@ -46,6 +49,9 @@ private struct OnDemandView: View {
|
|||||||
@Binding
|
@Binding
|
||||||
private var draft: OnDemandModule.Builder
|
private var draft: OnDemandModule.Builder
|
||||||
|
|
||||||
|
@State
|
||||||
|
private var paywallReason: PaywallReason?
|
||||||
|
|
||||||
init(
|
init(
|
||||||
editor: ProfileEditor,
|
editor: ProfileEditor,
|
||||||
original: OnDemandModule.Builder,
|
original: OnDemandModule.Builder,
|
||||||
@ -59,15 +65,10 @@ private struct OnDemandView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
enabledSection
|
enabledSection
|
||||||
if draft.isEnabled {
|
restrictedSection
|
||||||
policySection
|
|
||||||
if draft.policy != .any {
|
|
||||||
networkSection
|
|
||||||
wifiSection
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.asModuleView(with: editor, draft: draft)
|
.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 {
|
var policySection: some View {
|
||||||
Picker(Strings.Modules.OnDemand.policy, selection: $draft.policy) {
|
Picker(Strings.Modules.OnDemand.policy, selection: $draft.policy) {
|
||||||
ForEach(Self.allPolicies, id: \.self) {
|
ForEach(Self.allPolicies, id: \.self) {
|
||||||
|
@ -104,7 +104,7 @@ private extension ProfileCoordinator {
|
|||||||
func onNewModule(_ moduleType: ModuleType) {
|
func onNewModule(_ moduleType: ModuleType) {
|
||||||
switch moduleType {
|
switch moduleType {
|
||||||
case .onDemand:
|
case .onDemand:
|
||||||
paywallReason = iapManager.paywallReason(forFeature: .onDemand)
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
paywallReason = iapManager.paywallReason(forFeature: .networkSettings)
|
paywallReason = iapManager.paywallReason(forFeature: .networkSettings)
|
||||||
|
@ -34,7 +34,7 @@ extension EditableModule where Self: ModuleViewProviding {
|
|||||||
moduleView(with: ProfileEditor(modules: [self]))
|
moduleView(with: ProfileEditor(modules: [self]))
|
||||||
.navigationTitle(title)
|
.navigationTitle(title)
|
||||||
}
|
}
|
||||||
.environmentObject(Theme())
|
.withMockEnvironment()
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
@ -42,6 +42,15 @@ extension EditableModule where Self: ModuleViewProviding {
|
|||||||
NavigationStack {
|
NavigationStack {
|
||||||
content(ProfileEditor(modules: [self]), self)
|
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
Block a user