Commit 3f89f8ab authored by Jose Blaya's avatar Jose Blaya
Browse files

GDPR view

parent 21c2335b
......@@ -248,6 +248,7 @@
843C67C32122EA13005A3FDA /* AccountInfoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 843C67C12122E714005A3FDA /* AccountInfoTests.swift */; };
84D5DA702126CE2900F753F8 /* QRCameraScannerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D5DA6F2126CE2900F753F8 /* QRCameraScannerViewController.swift */; };
A6680249A33738280B9AD733 /* Pods_PIALibrary_PIALibraryHost_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 566B62D4C21DD5A90EF1BAE6 /* Pods_PIALibrary_PIALibraryHost_iOS.framework */; };
DD0DE84B22327981002A6E82 /* GDPRViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD0DE84922327981002A6E82 /* GDPRViewController.swift */; };
DD58F4BB21AEB99C00D043F7 /* GlossToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD58F4BA21AEB99C00D043F7 /* GlossToken.swift */; };
DD58F4BD21AEF76100D043F7 /* String+Components.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD58F4BC21AEF76100D043F7 /* String+Components.swift */; };
DDA4A7BE21F5C31400A02ACD /* IKEv2Profile.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA4A7BD21F5C31400A02ACD /* IKEv2Profile.swift */; };
......@@ -495,6 +496,7 @@
8BF83242A6BD73CE080CEE2A /* Pods-PIALibrary-PIALibraryHost-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PIALibrary-PIALibraryHost-iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-PIALibrary-PIALibraryHost-iOS/Pods-PIALibrary-PIALibraryHost-iOS.release.xcconfig"; sourceTree = "<group>"; };
BB47885FCCA9DDFF53237D2C /* Pods-PIALibrary-PIALibraryTests-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PIALibrary-PIALibraryTests-iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-PIALibrary-PIALibraryTests-iOS/Pods-PIALibrary-PIALibraryTests-iOS.release.xcconfig"; sourceTree = "<group>"; };
D9FDC8980713EDCEDD51B936 /* Pods-PIALibrary-PIALibrary-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PIALibrary-PIALibrary-iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PIALibrary-PIALibrary-iOS/Pods-PIALibrary-PIALibrary-iOS.debug.xcconfig"; sourceTree = "<group>"; };
DD0DE84922327981002A6E82 /* GDPRViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GDPRViewController.swift; sourceTree = "<group>"; };
DD58F4BA21AEB99C00D043F7 /* GlossToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlossToken.swift; sourceTree = "<group>"; };
DD58F4BC21AEF76100D043F7 /* String+Components.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Components.swift"; sourceTree = "<group>"; };
DDA4A7BD21F5C31400A02ACD /* IKEv2Profile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IKEv2Profile.swift; sourceTree = "<group>"; };
......@@ -790,6 +792,7 @@
0EB8C05C1F9CD38A005857E4 /* Theme.swift */,
0E5BCBFE20172C8300E3E4B4 /* Theme+LightPalette.swift */,
0EB8C05B1F9CD38A005857E4 /* WelcomePageViewController.swift */,
DD0DE84922327981002A6E82 /* GDPRViewController.swift */,
);
path = iOS;
sourceTree = "<group>";
......@@ -1593,6 +1596,7 @@
0EA8072420A18C6B0033EC1A /* RedeemViewController.swift in Sources */,
0EE261E01FEFD69F00E11955 /* Notification+Library.swift in Sources */,
0EFEB4C22007784A00F81029 /* PIATunnelProfile.swift in Sources */,
DD0DE84B22327981002A6E82 /* GDPRViewController.swift in Sources */,
0E392DBB1FE34B5A0002160D /* NSString+URL.m in Sources */,
0E2ADCCA1FE06D7A00BB170C /* Array+Math.swift in Sources */,
0E2ADD331FE1472F00BB170C /* VPNStatus.swift in Sources */,
......
......@@ -870,6 +870,7 @@ You will not be charged during this process.</string>
<outlet property="viewFooter" destination="Exp-5c-eqJ" id="Q9B-Qj-wvD"/>
<outlet property="viewLogin" destination="oSa-0z-U2f" id="XSw-0P-5nh"/>
<segue destination="9jt-8I-K8i" kind="presentation" identifier="SignupViaPurchaseSegue" id="Kkc-iF-rn9"/>
<segue destination="xQL-OM-cwV" kind="presentation" identifier="PresentGDPRTermsSegue" id="ZMg-Fi-w39"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="9BK-Ic-1BU" userLabel="First Responder" sceneMemberID="firstResponder"/>
......@@ -1351,6 +1352,96 @@ You will not be charged during this process.</string>
</objects>
<point key="canvasLocation" x="3238" y="-1901"/>
</scene>
<!--View Controller-->
<scene sceneID="4TJ-4j-R3Q">
<objects>
<viewController storyboardIdentifier="GDPRViewController" useStoryboardIdentifierAsRestorationIdentifier="YES" id="xQL-OM-cwV" customClass="GDPRViewController" customModule="PIALibrary" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="pIn-Lf-5da">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="LPK-Tp-Mtt">
<rect key="frame" x="19" y="75" width="337" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="Dkq-4e-YBc">
<rect key="frame" x="19" y="100.5" width="337" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="HQu-Fx-XH6">
<rect key="frame" x="19" y="140" width="337" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="xGR-vs-ZVT">
<rect key="frame" x="19" y="165.5" width="337" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xXw-fU-POW">
<rect key="frame" x="19" y="598" width="337" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="hem-Ha-mSY"/>
</constraints>
<state key="normal" title="Button"/>
<connections>
<action selector="accept:" destination="xQL-OM-cwV" eventType="touchUpInside" id="L4y-US-V02"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="EB9-Th-qDf">
<rect key="frame" x="5" y="25" width="44" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="CIs-x3-XXQ"/>
<constraint firstAttribute="width" constant="44" id="MnZ-pb-0AA"/>
</constraints>
<inset key="imageEdgeInsets" minX="10" minY="10" maxX="10" maxY="10"/>
<state key="normal" image="close-icon"/>
<connections>
<action selector="reject:" destination="xQL-OM-cwV" eventType="touchUpInside" id="uRa-Cc-Fu3"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="Lbf-Ia-Vn0" firstAttribute="bottom" secondItem="xXw-fU-POW" secondAttribute="bottom" constant="19" id="0cn-Jn-rrf"/>
<constraint firstItem="LPK-Tp-Mtt" firstAttribute="leading" secondItem="Lbf-Ia-Vn0" secondAttribute="leading" constant="19" id="9ul-At-xhl"/>
<constraint firstItem="xXw-fU-POW" firstAttribute="leading" secondItem="Lbf-Ia-Vn0" secondAttribute="leading" constant="19" id="LpM-0D-0MF"/>
<constraint firstItem="Lbf-Ia-Vn0" firstAttribute="trailing" secondItem="xGR-vs-ZVT" secondAttribute="trailing" constant="19" id="RWE-Mt-QgO"/>
<constraint firstItem="xGR-vs-ZVT" firstAttribute="leading" secondItem="Lbf-Ia-Vn0" secondAttribute="leading" constant="19" id="SU0-oK-ync"/>
<constraint firstItem="Dkq-4e-YBc" firstAttribute="top" secondItem="LPK-Tp-Mtt" secondAttribute="bottom" constant="5" id="T81-nQ-BFZ"/>
<constraint firstItem="Lbf-Ia-Vn0" firstAttribute="trailing" secondItem="HQu-Fx-XH6" secondAttribute="trailing" constant="19" id="avu-pd-ZvF"/>
<constraint firstItem="Lbf-Ia-Vn0" firstAttribute="trailing" secondItem="Dkq-4e-YBc" secondAttribute="trailing" constant="19" id="b5Q-i4-HvZ"/>
<constraint firstItem="EB9-Th-qDf" firstAttribute="top" secondItem="Lbf-Ia-Vn0" secondAttribute="top" constant="5" id="cP9-4c-48J"/>
<constraint firstItem="EB9-Th-qDf" firstAttribute="leading" secondItem="Lbf-Ia-Vn0" secondAttribute="leading" constant="5" id="gPP-9p-aRT"/>
<constraint firstItem="xGR-vs-ZVT" firstAttribute="top" secondItem="HQu-Fx-XH6" secondAttribute="bottom" constant="5" id="iJZ-c3-nT1"/>
<constraint firstItem="Lbf-Ia-Vn0" firstAttribute="trailing" secondItem="xXw-fU-POW" secondAttribute="trailing" constant="19" id="mS4-gI-CS5"/>
<constraint firstItem="Dkq-4e-YBc" firstAttribute="leading" secondItem="Lbf-Ia-Vn0" secondAttribute="leading" constant="19" id="oJt-y9-Lza"/>
<constraint firstItem="Lbf-Ia-Vn0" firstAttribute="trailing" secondItem="LPK-Tp-Mtt" secondAttribute="trailing" constant="19" id="oxU-yy-ur0"/>
<constraint firstItem="HQu-Fx-XH6" firstAttribute="leading" secondItem="Lbf-Ia-Vn0" secondAttribute="leading" constant="19" id="sAp-ji-FRW"/>
<constraint firstItem="HQu-Fx-XH6" firstAttribute="top" secondItem="Dkq-4e-YBc" secondAttribute="bottom" constant="19" id="uAR-Kl-4ur"/>
<constraint firstItem="xXw-fU-POW" firstAttribute="top" relation="greaterThanOrEqual" secondItem="xGR-vs-ZVT" secondAttribute="bottom" constant="10" id="ylM-Q1-LYK"/>
<constraint firstItem="LPK-Tp-Mtt" firstAttribute="top" secondItem="Lbf-Ia-Vn0" secondAttribute="top" constant="55" id="zNl-Hp-iGl"/>
</constraints>
<viewLayoutGuide key="safeArea" id="Lbf-Ia-Vn0"/>
</view>
<connections>
<outlet property="acceptButton" destination="xXw-fU-POW" id="xI7-CF-rSG"/>
<outlet property="closeButton" destination="EB9-Th-qDf" id="Opb-Li-zvl"/>
<outlet property="labelCollectDescription" destination="Dkq-4e-YBc" id="OOr-0S-oSj"/>
<outlet property="labelCollectTitle" destination="LPK-Tp-Mtt" id="Deb-rk-5hc"/>
<outlet property="labelUseDataDescription" destination="xGR-vs-ZVT" id="7Qg-0H-pFe"/>
<outlet property="labelUseDataTitle" destination="HQu-Fx-XH6" id="a9e-NP-iBV"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="jZd-JB-308" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
<resources>
<image name="close-icon" width="50" height="50"/>
......@@ -1358,6 +1449,6 @@ You will not be charged during this process.</string>
<image name="qr-code" width="325" height="325"/>
</resources>
<inferredMetricsTieBreakers>
<segue reference="EEe-nI-dHO"/>
<segue reference="Kkc-iF-rn9"/>
</inferredMetricsTieBreakers>
</document>
......@@ -62,3 +62,10 @@
"camera.access.error.title" = "Camera not available";
"camera.access.error.message" = "Your device does not support scanning QR codes. Please use a device with a camera.";
"camera.access.denied.message" = "Enable camera access so you can scan QR codes to redeem a gift card.";
"gdpr.collect.data.title" = "Personal information we collect";
"gdpr.collect.data.description" = "E-mail Address for the purposes of account management and protection from abuse.\n\nPayment Data for the purposes of processing payments as required by our third-party payment processors. Note that we do not save your full credit card details.";
"gdpr.usage.data.title" = "Uses of personal information collected by us";
"gdpr.usage.data.description" = "E-mail address is used to send subscription information, payment confirmations, customer correspondence, and Private Internet Access promotional offers only.\n\nPayment data is used to manage client signups, payments, and cancellations.";
"gdpr.accept.button.title" = "Agree and continue";
//
// GDPRViewController.swift
// PIALibrary-iOS
//
// Created by Jose Antonio Blaya Garcia on 08/03/2019.
// Copyright © 2019 London Trust Media. All rights reserved.
//
import UIKit
public protocol GDPRDelegate: class {
func gdprViewWasAccepted()
func gdprViewWasRejected()
}
class GDPRViewController: AutolayoutViewController {
@IBOutlet private weak var labelCollectTitle: UILabel!
@IBOutlet private weak var labelCollectDescription: UILabel!
@IBOutlet private weak var labelUseDataTitle: UILabel!
@IBOutlet private weak var labelUseDataDescription: UILabel!
@IBOutlet private weak var acceptButton: UIButton!
@IBOutlet private weak var closeButton: UIButton!
weak var delegate: GDPRDelegate? = nil
override func viewDidLoad() {
super.viewDidLoad()
self.labelCollectTitle.text = L10n.Welcome.Gdpr.Collect.Data.title
self.labelCollectDescription.text = L10n.Welcome.Gdpr.Collect.Data.description
self.labelUseDataTitle.text = L10n.Welcome.Gdpr.Usage.Data.title
self.labelUseDataDescription.text = L10n.Welcome.Gdpr.Usage.Data.description
self.acceptButton.setTitle(L10n.Welcome.Gdpr.Accept.Button.title, for: [])
}
// MARK: Restylable
override func viewShouldRestyle() {
super.viewShouldRestyle()
Theme.current.applyTitle(labelCollectTitle, appearance: .dark)
Theme.current.applyTitle(labelUseDataTitle, appearance: .dark)
Theme.current.applySmallInfo(labelCollectDescription, appearance: .dark)
Theme.current.applySmallInfo(labelUseDataDescription, appearance: .dark)
Theme.current.applyTextButton(acceptButton)
acceptButton.titleLabel?.font = Theme.current.typeface.mediumFont(size: 15.0)
acceptButton.backgroundColor = Theme.current.palette.emphasis
acceptButton.setTitleColor(Theme.current.palette.solidButtonText, for: [])
acceptButton.layer.cornerRadius = 4.0
}
@IBAction func accept(_ sender: Any) {
if let delegate = delegate {
delegate.gdprViewWasAccepted()
}
dismissModal()
}
@IBAction func reject(_ sender: Any) {
if let delegate = delegate {
delegate.gdprViewWasRejected()
}
dismissModal()
}
}
......@@ -40,6 +40,8 @@ class PurchaseViewController: AutolayoutViewController, WelcomeChild {
var omitsSiblingLink = false
var termsAndConditionsAgreed = false
weak var completionDelegate: WelcomeCompletionDelegate?
private var allPlans: [PurchasePlan] = [.dummy, .dummy]
......@@ -142,6 +144,7 @@ class PurchaseViewController: AutolayoutViewController, WelcomeChild {
}
@IBAction private func signUp(_ sender: Any?) {
guard !buttonPurchase.isRunningActivity else {
return
}
......@@ -159,6 +162,13 @@ class PurchaseViewController: AutolayoutViewController, WelcomeChild {
return
}
guard termsAndConditionsAgreed else {
//present term and conditions
self.performSegue(withIdentifier: StoryboardSegue.Welcome.presentGDPRTermsSegue.rawValue,
sender: nil)
return
}
let plan = allPlans[planIndex]
guard !plan.isDummy else {
let alert = Macros.alert(
......@@ -245,6 +255,11 @@ class PurchaseViewController: AutolayoutViewController, WelcomeChild {
vc.signupRequest = SignupRequest(email: email, transaction: signupTransaction)
vc.preset = preset
vc.completionDelegate = completionDelegate
} else if (segue.identifier == StoryboardSegue.Welcome.presentGDPRTermsSegue.rawValue) {
let gdprViewController = segue.destination as! GDPRViewController
gdprViewController.delegate = self
}
}
......@@ -326,3 +341,16 @@ extension PurchaseViewController: UITextFieldDelegate {
return true
}
}
extension PurchaseViewController: GDPRDelegate {
func gdprViewWasAccepted() {
self.termsAndConditionsAgreed = true
self.signUp(nil)
}
func gdprViewWasRejected() {
self.termsAndConditionsAgreed = false
}
}
......@@ -20,6 +20,7 @@ internal enum StoryboardSegue {
case unwindInternetUnreachableSegueIdentifier = "UnwindInternetUnreachableSegueIdentifier"
}
internal enum Welcome: String, SegueType {
case presentGDPRTermsSegue = "PresentGDPRTermsSegue"
case signupQRCameraScannerSegue = "SignupQRCameraScannerSegue"
case signupViaPurchaseSegue = "SignupViaPurchaseSegue"
case signupViaRecoverSegue = "SignupViaRecoverSegue"
......
......@@ -122,6 +122,30 @@ internal enum L10n {
}
}
}
internal enum Gdpr {
internal enum Accept {
internal enum Button {
/// Agree and continue
internal static let title = L10n.tr("Welcome", "gdpr.accept.button.title")
}
}
internal enum Collect {
internal enum Data {
/// E-mail Address for the purposes of account management and protection from abuse.\n\nPayment Data for the purposes of processing payments as required by our third-party payment processors. Note that we do not save your full credit card details.
internal static let description = L10n.tr("Welcome", "gdpr.collect.data.description")
/// Personal information we collect
internal static let title = L10n.tr("Welcome", "gdpr.collect.data.title")
}
}
internal enum Usage {
internal enum Data {
/// E-mail address is used to send subscription information, payment confirmations, customer correspondence, and Private Internet Access promotional offers only.\n\nPayment data is used to manage client signups, payments, and cancellations.
internal static let description = L10n.tr("Welcome", "gdpr.usage.data.description")
/// Uses of personal information collected by us
internal static let title = L10n.tr("Welcome", "gdpr.usage.data.title")
}
}
}
internal enum Iap {
internal enum Error {
/// Error
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment