Move providers paywall to picker (#764)
Paywall on module creation suggests that OpenVPN modules are a paid feature.
This commit is contained in:
parent
639dee55ee
commit
ecb0348b90
|
@ -151,12 +151,12 @@ extension IAPManager {
|
|||
features.allSatisfy(eligibleFeatures.contains)
|
||||
}
|
||||
|
||||
// public func isEligible(forProvider providerName: ProviderName) -> Bool {
|
||||
// guard providerName != .oeck else {
|
||||
// return true
|
||||
// }
|
||||
// return isEligible(forFeature: providerName.product)
|
||||
// }
|
||||
public func isEligible(forProvider providerId: ProviderID) -> Bool {
|
||||
if providerId == .oeck {
|
||||
return true
|
||||
}
|
||||
return isEligible(for: .providers)
|
||||
}
|
||||
|
||||
public func isEligibleForFeedback() -> Bool {
|
||||
#if os(tvOS)
|
||||
|
|
|
@ -473,6 +473,10 @@ public enum Strings {
|
|||
/// Loading...
|
||||
public static let loading = Strings.tr("Localizable", "providers.last_updated.loading", fallback: "Loading...")
|
||||
}
|
||||
public enum Picker {
|
||||
/// Add more providers
|
||||
public static let purchase = Strings.tr("Localizable", "providers.picker.purchase", fallback: "Add more providers")
|
||||
}
|
||||
public enum Vpn {
|
||||
/// No servers
|
||||
public static let noServers = Strings.tr("Localizable", "providers.vpn.no_servers", fallback: "No servers")
|
||||
|
|
|
@ -175,7 +175,6 @@
|
|||
|
||||
"modules.general.sections.storage.footer" = "Profiles are stored to iCloud encrypted.";
|
||||
"modules.general.rows.icloud_sharing" = "Shared on iCloud";
|
||||
"modules.general.rows.icloud_sharing.purchase" = "Share on iCloud";
|
||||
|
||||
"modules.dns.servers.add" = "Add address";
|
||||
"modules.dns.search_domains.add" = "Add domain";
|
||||
|
@ -187,7 +186,6 @@
|
|||
"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";
|
||||
|
@ -213,7 +211,6 @@
|
|||
"modules.openvpn.randomize_endpoint" = "Randomize endpoint";
|
||||
"modules.openvpn.randomize_hostname" = "Randomize hostname";
|
||||
"modules.openvpn.credentials.interactive" = "Interactive";
|
||||
"modules.openvpn.credentials.interactive.purchase" = "Log in interactively";
|
||||
"modules.openvpn.credentials.interactive.footer" = "On-demand will be disabled.";
|
||||
"modules.openvpn.credentials.otp_method.approach.append" = "The OTP will be appended to the password.";
|
||||
"modules.openvpn.credentials.otp_method.approach.encode" = "The OTP will be encoded in Base64 with the password.";
|
||||
|
@ -242,6 +239,13 @@
|
|||
"ui.connection_status.on_demand_suffix" = " (on-demand)";
|
||||
"ui.profile_context.connect_to" = "Connect to...";
|
||||
|
||||
// MARK: - Paywalls
|
||||
|
||||
"modules.general.rows.icloud_sharing.purchase" = "Share on iCloud";
|
||||
"modules.on_demand.purchase" = "Add on-demand rules";
|
||||
"modules.openvpn.credentials.interactive.purchase" = "Log in interactively";
|
||||
"providers.picker.purchase" = "Add more providers";
|
||||
|
||||
// MARK: - Alerts
|
||||
|
||||
"alerts.iap.restricted.title" = "Restricted";
|
||||
|
|
|
@ -38,6 +38,9 @@ struct OpenVPNView: View, ModuleDraftEditing {
|
|||
|
||||
private let isServerPushed: Bool
|
||||
|
||||
@State
|
||||
private var paywallReason: PaywallReason?
|
||||
|
||||
init(serverConfiguration: OpenVPN.Configuration) {
|
||||
let module = OpenVPNModule.Builder(configurationBuilder: serverConfiguration.builder())
|
||||
let editor = ProfileEditor(modules: [module])
|
||||
|
@ -56,6 +59,7 @@ struct OpenVPNView: View, ModuleDraftEditing {
|
|||
var body: some View {
|
||||
contentView
|
||||
.moduleView(editor: editor, draft: draft.wrappedValue, withName: !isServerPushed)
|
||||
.modifier(PaywallModifier(reason: $paywallReason))
|
||||
.navigationDestination(for: Subroute.self, destination: destination)
|
||||
}
|
||||
}
|
||||
|
@ -82,6 +86,7 @@ private extension OpenVPNView {
|
|||
providerId: providerId,
|
||||
selectedEntity: providerEntity,
|
||||
isRequired: true,
|
||||
paywallReason: $paywallReason,
|
||||
entityDestination: Subroute.providerServer,
|
||||
providerRows: {
|
||||
moduleGroup(for: providerAccountRows)
|
||||
|
|
|
@ -113,7 +113,7 @@ private extension ProfileCoordinator {
|
|||
paywallReason = iapManager.paywallReason(forFeature: .routing)
|
||||
|
||||
case .openVPN, .wireGuard:
|
||||
paywallReason = iapManager.paywallReason(forFeature: .providers)
|
||||
break
|
||||
|
||||
case .onDemand:
|
||||
break
|
||||
|
|
|
@ -31,6 +31,9 @@ struct ProviderContentModifier<Entity, ProviderRows>: ViewModifier where Entity:
|
|||
@EnvironmentObject
|
||||
private var providerManager: ProviderManager
|
||||
|
||||
@EnvironmentObject
|
||||
private var iapManager: IAPManager
|
||||
|
||||
let apis: [APIMapper]
|
||||
|
||||
@Binding
|
||||
|
@ -40,6 +43,9 @@ struct ProviderContentModifier<Entity, ProviderRows>: ViewModifier where Entity:
|
|||
|
||||
let isRequired: Bool
|
||||
|
||||
@Binding
|
||||
var paywallReason: PaywallReason?
|
||||
|
||||
@ViewBuilder
|
||||
let providerRows: ProviderRows
|
||||
|
||||
|
@ -71,9 +77,14 @@ struct ProviderContentModifier<Entity, ProviderRows>: ViewModifier where Entity:
|
|||
private extension ProviderContentModifier {
|
||||
|
||||
#if os(iOS)
|
||||
@ViewBuilder
|
||||
var providerView: some View {
|
||||
Group {
|
||||
providerPicker
|
||||
purchaseButton
|
||||
}
|
||||
.themeSection()
|
||||
Group {
|
||||
if providerId != nil {
|
||||
providerRows
|
||||
refreshButton {
|
||||
|
@ -90,9 +101,13 @@ private extension ProviderContentModifier {
|
|||
.themeSection(footer: lastUpdatedString)
|
||||
}
|
||||
#else
|
||||
@ViewBuilder
|
||||
var providerView: some View {
|
||||
Group {
|
||||
Section {
|
||||
providerPicker
|
||||
purchaseButton
|
||||
}
|
||||
Section {
|
||||
if providerId != nil {
|
||||
providerRows
|
||||
HStack {
|
||||
|
@ -119,6 +134,15 @@ private extension ProviderContentModifier {
|
|||
)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
var purchaseButton: some View {
|
||||
if let reason = iapManager.paywallReason(forFeature: .providers) {
|
||||
Button(Strings.Providers.Picker.purchase) {
|
||||
paywallReason = reason
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshButton<Label>(label: () -> Label) -> some View where Label: View {
|
||||
Button(action: onRefreshInfrastructure, label: label)
|
||||
}
|
||||
|
@ -127,7 +151,7 @@ private extension ProviderContentModifier {
|
|||
providerManager
|
||||
.providers
|
||||
.filter {
|
||||
$0.supports(Entity.Configuration.self)
|
||||
iapManager.isEligible(forProvider: $0.id) && $0.supports(Entity.Configuration.self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,6 +222,7 @@ private extension ProviderContentModifier {
|
|||
providerId: .constant(.hideme),
|
||||
entityType: VPNEntity<OpenVPN.Configuration>.self,
|
||||
isRequired: false,
|
||||
paywallReason: .constant(nil),
|
||||
providerRows: {},
|
||||
onSelectProvider: { _, _, _ in }
|
||||
))
|
||||
|
|
|
@ -40,6 +40,9 @@ struct VPNProviderContentModifier<Configuration, Destination, ProviderRows>: Vie
|
|||
|
||||
let isRequired: Bool
|
||||
|
||||
@Binding
|
||||
var paywallReason: PaywallReason?
|
||||
|
||||
let entityDestination: Destination
|
||||
|
||||
@ViewBuilder
|
||||
|
@ -53,6 +56,7 @@ struct VPNProviderContentModifier<Configuration, Destination, ProviderRows>: Vie
|
|||
providerId: $providerId,
|
||||
entityType: VPNEntity<Configuration>.self,
|
||||
isRequired: isRequired,
|
||||
paywallReason: $paywallReason,
|
||||
providerRows: {
|
||||
providerEntityRow
|
||||
providerRows
|
||||
|
@ -96,6 +100,7 @@ private extension VPNProviderContentModifier {
|
|||
providerId: .constant(.hideme),
|
||||
selectedEntity: .constant(nil as VPNEntity<OpenVPN.Configuration>?),
|
||||
isRequired: false,
|
||||
paywallReason: .constant(nil),
|
||||
entityDestination: "Destination",
|
||||
providerRows: {
|
||||
Text("Other")
|
||||
|
|
Loading…
Reference in New Issue