summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj8
-rw-r--r--ios/MullvadVPN/ConsentContentView.swift145
-rw-r--r--ios/MullvadVPN/ConsentViewController.swift35
-rw-r--r--ios/MullvadVPN/ConsentViewController.xib146
4 files changed, 177 insertions, 157 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 133a2da18a..63276bead6 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -70,6 +70,7 @@
5840250222B1124600E4CFEC /* IPAddress+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250022B1124600E4CFEC /* IPAddress+Codable.swift */; };
5840250422B11AB700E4CFEC /* MullvadEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250322B11AB700E4CFEC /* MullvadEndpoint.swift */; };
5840250522B11AB700E4CFEC /* MullvadEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250322B11AB700E4CFEC /* MullvadEndpoint.swift */; };
+ 584592612639B4A200EF967F /* ConsentContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584592602639B4A200EF967F /* ConsentContentView.swift */; };
5845F842236CBACD00B2D93C /* PacketTunnelIpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5845F841236CBACD00B2D93C /* PacketTunnelIpc.swift */; };
5845F843236CBDAB00B2D93C /* PacketTunnelIpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5845F841236CBACD00B2D93C /* PacketTunnelIpc.swift */; };
584E96BC240FD4DA00D3334F /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A1AA8623F43901009F7EA6 /* Location.swift */; };
@@ -143,7 +144,6 @@
58A1AA8C23F5584C009F7EA6 /* ConnectionPanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A1AA8B23F5584B009F7EA6 /* ConnectionPanelView.swift */; };
58A8BE81239FBE62006B74AC /* IPEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58561C98239A5D1500BD6B5E /* IPEndpoint.swift */; };
58A99ED3240014A0006599E9 /* ConsentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A99ED2240014A0006599E9 /* ConsentViewController.swift */; };
- 58AB9DEC2501040C006C5526 /* ConsentViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 58AB9DEB2501040C006C5526 /* ConsentViewController.xib */; };
58AEEF652344A36000C9BBD5 /* KeychainError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58AEEF642344A36000C9BBD5 /* KeychainError.swift */; };
58AEEF662344A37400C9BBD5 /* KeychainError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58AEEF642344A36000C9BBD5 /* KeychainError.swift */; };
58AEEF6B2344A46200C9BBD5 /* TunnelSettingsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58AEEF6A2344A46200C9BBD5 /* TunnelSettingsManager.swift */; };
@@ -314,6 +314,7 @@
583DA21325FA4B5C00318683 /* LocationDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationDataSource.swift; sourceTree = "<group>"; };
5840250022B1124600E4CFEC /* IPAddress+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IPAddress+Codable.swift"; sourceTree = "<group>"; };
5840250322B11AB700E4CFEC /* MullvadEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MullvadEndpoint.swift; sourceTree = "<group>"; };
+ 584592602639B4A200EF967F /* ConsentContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsentContentView.swift; sourceTree = "<group>"; };
5845F841236CBACD00B2D93C /* PacketTunnelIpc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelIpc.swift; sourceTree = "<group>"; };
584B26F3237434D00073B10E /* RelaySelectorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelaySelectorTests.swift; sourceTree = "<group>"; };
5850366725A47AC700A43E93 /* IPAddressRange+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IPAddressRange+Codable.swift"; sourceTree = "<group>"; };
@@ -354,7 +355,6 @@
58A1AA8623F43901009F7EA6 /* Location.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Location.swift; sourceTree = "<group>"; };
58A1AA8B23F5584B009F7EA6 /* ConnectionPanelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionPanelView.swift; sourceTree = "<group>"; };
58A99ED2240014A0006599E9 /* ConsentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsentViewController.swift; sourceTree = "<group>"; };
- 58AB9DEB2501040C006C5526 /* ConsentViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ConsentViewController.xib; sourceTree = "<group>"; };
58AEEF642344A36000C9BBD5 /* KeychainError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainError.swift; sourceTree = "<group>"; };
58AEEF6A2344A46200C9BBD5 /* TunnelSettingsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelSettingsManager.swift; sourceTree = "<group>"; };
58B0A2A0238EE67E00BC001D /* MullvadVPNTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MullvadVPNTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -570,7 +570,7 @@
58CCA00F224249A1004F3011 /* ConnectViewController.swift */,
58B43C1825F77DB60002C8C3 /* ConnectMainContentView.swift */,
58A99ED2240014A0006599E9 /* ConsentViewController.swift */,
- 58AB9DEB2501040C006C5526 /* ConsentViewController.xib */,
+ 584592602639B4A200EF967F /* ConsentContentView.swift */,
5896AE83246D5889005B36CB /* CustomDateComponentsFormatting.swift */,
582BB1B0229569620055B6EF /* CustomNavigationBar.swift */,
58293FB625138B88005D0BB5 /* CustomNavigationController.swift */,
@@ -883,7 +883,6 @@
58F3C0A624A50157003E76BE /* relays.json in Resources */,
58CE5E6E224146210008646E /* LaunchScreen.storyboard in Resources */,
58CE5E6B224146210008646E /* Assets.xcassets in Resources */,
- 58AB9DEC2501040C006C5526 /* ConsentViewController.xib in Resources */,
58CE5E69224146200008646E /* Main.storyboard in Resources */,
58E5BC2624FEB6DB00A53A76 /* AccountViewController.xib in Resources */,
58B9814E24FEA70D00C0D59E /* WireguardKeysViewController.xib in Resources */,
@@ -1048,6 +1047,7 @@
5868BD33261DCD2600E6027F /* CustomSplitViewController.swift in Sources */,
5888AD7F2279B6BF0051EB06 /* RelayStatusIndicatorView.swift in Sources */,
58CCA01E2242787B004F3011 /* AccountTextField.swift in Sources */,
+ 584592612639B4A200EF967F /* ConsentContentView.swift in Sources */,
587AD7CA2342283900E93A53 /* Account.swift in Sources */,
58F840AF2464382C0044E708 /* KeychainItemRevision.swift in Sources */,
58293FB725138B88005D0BB5 /* CustomNavigationController.swift in Sources */,
diff --git a/ios/MullvadVPN/ConsentContentView.swift b/ios/MullvadVPN/ConsentContentView.swift
new file mode 100644
index 0000000000..9d870ba420
--- /dev/null
+++ b/ios/MullvadVPN/ConsentContentView.swift
@@ -0,0 +1,145 @@
+//
+// ConsentContentView.swift
+// MullvadVPN
+//
+// Created by pronebird on 28/04/2021.
+// Copyright © 2021 Mullvad VPN AB. All rights reserved.
+//
+
+import UIKit
+
+class ConsentContentView: UIView {
+
+ let titleLabel: UILabel = {
+ let titleLabel = UILabel()
+ titleLabel.translatesAutoresizingMaskIntoConstraints = false
+ titleLabel.font = UIFont.systemFont(ofSize: 24, weight: .bold)
+ titleLabel.numberOfLines = 0
+ titleLabel.textColor = .white
+ titleLabel.allowsDefaultTighteningForTruncation = true
+ titleLabel.text = NSLocalizedString("Do you agree to remaining anonymous?", comment: "")
+ titleLabel.lineBreakMode = .byWordWrapping
+ if #available(iOS 14.0, *) {
+ // Disable the new line break strategy used by UIKit that moves at least two words
+ // to the next line which makes the title look odd.
+ // See: https://stackoverflow.com/q/46200027/351305
+ titleLabel.lineBreakStrategy = []
+ }
+ return titleLabel
+ }()
+
+ let bodyLabel: UILabel = {
+ let localizedText = NSLocalizedString("""
+You have a right to privacy. That’s why we never store activity logs, don't ask for personal information, and encourage anonymous payments.
+
+In some situations, as outlined in our privacy policy, we might process personal data that you choose to send, for example if you email us.
+
+We strongly believe in retaining as little data as possible because we want you to remain anonymous.
+""", comment: "")
+
+ let bodyLabel = UILabel()
+ bodyLabel.translatesAutoresizingMaskIntoConstraints = false
+ bodyLabel.font = UIFont.systemFont(ofSize: 18)
+ bodyLabel.textColor = .white
+ bodyLabel.numberOfLines = 0
+ bodyLabel.text = localizedText
+ return bodyLabel
+ }()
+
+ let privacyPolicyLink: LinkButton = {
+ let button = LinkButton()
+ button.translatesAutoresizingMaskIntoConstraints = false
+ button.titleString = NSLocalizedString("Privacy policy", comment: "")
+ button.setImage(UIImage(named: "IconExtlink"), for: .normal)
+ return button
+ }()
+
+ let agreeButton: AppButton = {
+ let button = AppButton(style: .default)
+ button.translatesAutoresizingMaskIntoConstraints = false
+ button.setTitle(NSLocalizedString("Agree and continue", comment: ""), for: .normal)
+ return button
+ }()
+
+ let scrollView: UIScrollView = {
+ let scrollView = UIScrollView()
+ scrollView.translatesAutoresizingMaskIntoConstraints = false
+ return scrollView
+ }()
+
+ let scrollContentContainer: UIView = {
+ let contentView = UIView()
+ contentView.translatesAutoresizingMaskIntoConstraints = false
+ contentView.layoutMargins = UIMetrics.contentLayoutMargins
+ return contentView
+ }()
+
+ let footerContainer: UIView = {
+ let container = UIView()
+ container.translatesAutoresizingMaskIntoConstraints = false
+ container.layoutMargins = UIMetrics.contentLayoutMargins
+ container.backgroundColor = .secondaryColor
+ return container
+ }()
+
+ override init(frame: CGRect) {
+ super.init(frame: frame)
+
+ addSubviews()
+ }
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ // MARK: - Private
+
+ private func addSubviews() {
+ addSubview(scrollView)
+ addSubview(footerContainer)
+
+ scrollView.addSubview(scrollContentContainer)
+ [titleLabel, bodyLabel, privacyPolicyLink].forEach { scrollContentContainer.addSubview($0) }
+ footerContainer.addSubview(agreeButton)
+
+ scrollView.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
+ footerContainer.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
+
+ NSLayoutConstraint.activate([
+ scrollView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor),
+ scrollView.leadingAnchor.constraint(equalTo: leadingAnchor),
+ scrollView.trailingAnchor.constraint(equalTo: trailingAnchor),
+
+ scrollContentContainer.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
+ scrollContentContainer.topAnchor.constraint(equalTo: scrollView.topAnchor),
+ scrollContentContainer.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
+ scrollContentContainer.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
+ scrollContentContainer.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
+
+ footerContainer.topAnchor.constraint(equalTo: scrollView.bottomAnchor),
+ footerContainer.leadingAnchor.constraint(equalTo: leadingAnchor),
+ footerContainer.trailingAnchor.constraint(equalTo: trailingAnchor),
+ footerContainer.bottomAnchor.constraint(equalTo: bottomAnchor),
+
+ agreeButton.topAnchor.constraint(equalTo: footerContainer.layoutMarginsGuide.topAnchor),
+ agreeButton.leadingAnchor.constraint(equalTo: footerContainer.layoutMarginsGuide.leadingAnchor),
+ agreeButton.trailingAnchor.constraint(equalTo: footerContainer.layoutMarginsGuide.trailingAnchor),
+ agreeButton.bottomAnchor.constraint(equalTo: footerContainer.layoutMarginsGuide.bottomAnchor),
+
+ titleLabel.topAnchor.constraint(equalTo: scrollContentContainer.layoutMarginsGuide.topAnchor),
+ titleLabel.leadingAnchor.constraint(equalTo: scrollContentContainer.layoutMarginsGuide.leadingAnchor),
+ titleLabel.trailingAnchor.constraint(equalTo: scrollContentContainer.layoutMarginsGuide.trailingAnchor),
+
+ bodyLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 24),
+ bodyLabel.leadingAnchor.constraint(equalTo: scrollContentContainer.layoutMarginsGuide.leadingAnchor),
+ bodyLabel.trailingAnchor.constraint(equalTo: scrollContentContainer.layoutMarginsGuide.trailingAnchor),
+
+ privacyPolicyLink.topAnchor.constraint(equalTo: bodyLabel.bottomAnchor, constant: 24),
+ privacyPolicyLink.leadingAnchor.constraint(equalTo: scrollContentContainer.layoutMarginsGuide.leadingAnchor),
+ privacyPolicyLink.trailingAnchor.constraint(lessThanOrEqualTo: scrollContentContainer.layoutMarginsGuide.trailingAnchor),
+ privacyPolicyLink.bottomAnchor.constraint(equalTo: scrollContentContainer.layoutMarginsGuide.bottomAnchor),
+
+ ])
+ }
+
+}
diff --git a/ios/MullvadVPN/ConsentViewController.swift b/ios/MullvadVPN/ConsentViewController.swift
index e9f471aa8c..ab029ed1ec 100644
--- a/ios/MullvadVPN/ConsentViewController.swift
+++ b/ios/MullvadVPN/ConsentViewController.swift
@@ -19,25 +19,46 @@ class ConsentViewController: UIViewController, RootContainment, SFSafariViewCont
return .lightContent
}
- var preferredHeaderBarStyle: HeaderBarStyle {
- return .transparent
+ var preferredHeaderBarPresentation: HeaderBarPresentation {
+ return HeaderBarPresentation(style: .default, showsDivider: false)
}
var prefersHeaderBarHidden: Bool {
- return true
+ return false
}
- // MARK: - IBActions
+ // MARK: - View lifecycle
- @IBAction func handlePrivacyPolicyButton(_ sender: Any) {
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ let contentView = ConsentContentView()
+ contentView.translatesAutoresizingMaskIntoConstraints = false
+ contentView.agreeButton.addTarget(self, action: #selector(handleAgreeButton(_:)), for: .touchUpInside)
+ contentView.privacyPolicyLink.addTarget(self, action: #selector(handlePrivacyPolicyButton(_:)), for: .touchUpInside)
+
+ view.backgroundColor = .primaryColor
+ view.addSubview(contentView)
+
+ NSLayoutConstraint.activate([
+ contentView.topAnchor.constraint(equalTo: view.topAnchor),
+ contentView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
+ contentView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
+ contentView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
+ ])
+ }
+
+ // MARK: - Actions
+
+ @objc private func handlePrivacyPolicyButton(_ sender: Any) {
let safariController = SFSafariViewController(url: kPrivacyPolicyURL)
safariController.delegate = self
present(safariController, animated: true)
}
- @IBAction func handleAgreeAndContinueButton(_ sender: Any) {
- completionHandler?()
+ @objc private func handleAgreeButton(_ sender: Any) {
+ completionHandler?(self)
}
// MARK: - SFSafariViewControllerDelegate
diff --git a/ios/MullvadVPN/ConsentViewController.xib b/ios/MullvadVPN/ConsentViewController.xib
deleted file mode 100644
index 3345552936..0000000000
--- a/ios/MullvadVPN/ConsentViewController.xib
+++ /dev/null
@@ -1,146 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
- <device id="retina6_1" orientation="portrait" appearance="light"/>
- <dependencies>
- <deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
- <capability name="Named colors" minToolsVersion="9.0"/>
- <capability name="Safe area layout guides" minToolsVersion="9.0"/>
- <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
- </dependencies>
- <objects>
- <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ConsentViewController" customModule="MullvadVPN" customModuleProvider="target">
- <connections>
- <outlet property="view" destination="okw-Tg-2ad" id="WQ8-79-AH6"/>
- </connections>
- </placeholder>
- <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
- <view contentMode="scaleToFill" id="okw-Tg-2ad">
- <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
- <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <subviews>
- <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fbX-Lo-tij">
- <rect key="frame" x="0.0" y="0.0" width="414" height="792"/>
- <subviews>
- <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="11q-bQ-xwY" userLabel="Content view">
- <rect key="frame" x="0.0" y="0.0" width="414" height="558"/>
- <subviews>
- <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5Ub-SU-zLG" userLabel="Logo header">
- <rect key="frame" x="0.0" y="0.0" width="414" height="100"/>
- <subviews>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="LogoIcon" translatesAutoresizingMaskIntoConstraints="NO" id="4vX-y0-HN4">
- <rect key="frame" x="177" y="20" width="60" height="60"/>
- <constraints>
- <constraint firstAttribute="width" secondItem="4vX-y0-HN4" secondAttribute="height" multiplier="1:1" id="4h0-Vu-yGp"/>
- <constraint firstAttribute="width" constant="60" id="DiU-Y2-Isy"/>
- </constraints>
- </imageView>
- </subviews>
- <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <constraints>
- <constraint firstItem="4vX-y0-HN4" firstAttribute="top" secondItem="5Ub-SU-zLG" secondAttribute="top" constant="20" id="0Bk-LL-D0w"/>
- <constraint firstItem="4vX-y0-HN4" firstAttribute="centerX" secondItem="5Ub-SU-zLG" secondAttribute="centerX" id="G7a-zH-1ff"/>
- <constraint firstAttribute="bottom" secondItem="4vX-y0-HN4" secondAttribute="bottom" constant="20" id="iv9-ph-I49"/>
- </constraints>
- </view>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Do you agree to remaining anonymous?" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="64r-KN-ooC">
- <rect key="frame" x="20" y="100" width="374" height="57.5"/>
- <fontDescription key="fontDescription" type="boldSystem" pointSize="24"/>
- <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <nil key="highlightedColor"/>
- </label>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wh8-zG-jJA">
- <rect key="frame" x="20" y="181.5" width="374" height="334.5"/>
- <string key="text">You have a right to privacy. That’s why we never store activity logs, don't ask for personal information, and encourage anonymous payments.

In some situations, as outlined in our privacy policy, we might process personal data that you choose to send, for example if you email us.
-
We strongly believe in retaining as little data as possible because we want you to remain anonymous.
-</string>
- <fontDescription key="fontDescription" type="system" pointSize="20"/>
- <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <nil key="highlightedColor"/>
- </label>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="leading" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DsZ-mb-iQe" customClass="LinkButton" customModule="MullvadVPN" customModuleProvider="target">
- <rect key="frame" x="20" y="516" width="128" height="22"/>
- <fontDescription key="fontDescription" name=".AppleSystemUIFont" family=".AppleSystemUIFont" pointSize="18"/>
- <color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <state key="normal" title="Privacy Policy" image="IconExtlink"/>
- <connections>
- <action selector="handlePrivacyPolicyButton:" destination="-1" eventType="touchUpInside" id="Vid-Bc-rEi"/>
- </connections>
- </button>
- </subviews>
- <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <constraints>
- <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="DsZ-mb-iQe" secondAttribute="trailing" constant="20" symbolic="YES" id="4tG-3r-ao8"/>
- <constraint firstItem="wh8-zG-jJA" firstAttribute="top" secondItem="64r-KN-ooC" secondAttribute="bottom" constant="24" id="FLZ-Ye-Tpi"/>
- <constraint firstItem="DsZ-mb-iQe" firstAttribute="top" secondItem="wh8-zG-jJA" secondAttribute="bottom" id="I7w-FT-B6x"/>
- <constraint firstAttribute="trailing" secondItem="5Ub-SU-zLG" secondAttribute="trailing" id="Laz-Cj-wzQ"/>
- <constraint firstAttribute="trailing" secondItem="64r-KN-ooC" secondAttribute="trailing" constant="20" symbolic="YES" id="NEy-kj-Xa9"/>
- <constraint firstAttribute="bottom" secondItem="DsZ-mb-iQe" secondAttribute="bottom" constant="20" symbolic="YES" id="VEw-Go-ZgL"/>
- <constraint firstItem="DsZ-mb-iQe" firstAttribute="leading" secondItem="11q-bQ-xwY" secondAttribute="leading" constant="20" symbolic="YES" id="WZO-4C-eJL"/>
- <constraint firstItem="5Ub-SU-zLG" firstAttribute="leading" secondItem="11q-bQ-xwY" secondAttribute="leading" id="hVR-xg-zsg"/>
- <constraint firstAttribute="trailing" secondItem="wh8-zG-jJA" secondAttribute="trailing" constant="20" symbolic="YES" id="mKX-Gy-ThJ"/>
- <constraint firstItem="5Ub-SU-zLG" firstAttribute="top" secondItem="11q-bQ-xwY" secondAttribute="top" id="p0M-NJ-XvJ"/>
- <constraint firstItem="5Ub-SU-zLG" firstAttribute="bottom" secondItem="64r-KN-ooC" secondAttribute="top" id="qr7-pk-goS"/>
- <constraint firstItem="wh8-zG-jJA" firstAttribute="leading" secondItem="11q-bQ-xwY" secondAttribute="leading" constant="20" symbolic="YES" id="ugv-Jw-Z2N"/>
- <constraint firstItem="64r-KN-ooC" firstAttribute="leading" secondItem="11q-bQ-xwY" secondAttribute="leading" constant="20" symbolic="YES" id="yXI-Im-8ZF"/>
- </constraints>
- </view>
- </subviews>
- <constraints>
- <constraint firstAttribute="trailing" secondItem="11q-bQ-xwY" secondAttribute="trailing" id="2iy-GE-faC"/>
- <constraint firstAttribute="bottom" secondItem="11q-bQ-xwY" secondAttribute="bottom" id="NJz-kz-ei6"/>
- <constraint firstItem="11q-bQ-xwY" firstAttribute="width" secondItem="fbX-Lo-tij" secondAttribute="width" id="dPZ-ie-kV8"/>
- <constraint firstItem="11q-bQ-xwY" firstAttribute="top" secondItem="fbX-Lo-tij" secondAttribute="top" id="po9-I5-cIU"/>
- <constraint firstItem="11q-bQ-xwY" firstAttribute="leading" secondItem="fbX-Lo-tij" secondAttribute="leading" id="sin-cl-oOj"/>
- </constraints>
- </scrollView>
- <view contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FYK-e4-iEm" userLabel="Footer">
- <rect key="frame" x="0.0" y="792" width="414" height="104"/>
- <subviews>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7rE-vW-Iff" customClass="AppButton" customModule="MullvadVPN" customModuleProvider="target">
- <rect key="frame" x="20" y="24" width="374" height="22"/>
- <accessibility key="accessibilityConfiguration" identifier="AgreeButton"/>
- <state key="normal" title="Agree and continue" backgroundImage="DefaultButton">
- <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- </state>
- <connections>
- <action selector="handleAgreeAndContinueButton:" destination="-1" eventType="touchUpInside" id="GH7-Ie-FcB"/>
- </connections>
- </button>
- </subviews>
- <color key="backgroundColor" name="Secondary"/>
- <constraints>
- <constraint firstItem="7rE-vW-Iff" firstAttribute="trailing" secondItem="FYK-e4-iEm" secondAttribute="trailingMargin" id="1rH-JL-16T"/>
- <constraint firstItem="7rE-vW-Iff" firstAttribute="leading" secondItem="FYK-e4-iEm" secondAttribute="leadingMargin" id="StR-Pw-jiq"/>
- <constraint firstAttribute="bottomMargin" secondItem="7rE-vW-Iff" secondAttribute="bottom" id="r5T-I7-veu"/>
- <constraint firstItem="7rE-vW-Iff" firstAttribute="top" secondItem="FYK-e4-iEm" secondAttribute="topMargin" id="zpa-Wp-alT"/>
- </constraints>
- <edgeInsets key="layoutMargins" top="24" left="16" bottom="24" right="16"/>
- </view>
- </subviews>
- <color key="backgroundColor" name="Primary"/>
- <constraints>
- <constraint firstItem="fbX-Lo-tij" firstAttribute="leading" secondItem="okw-Tg-2ad" secondAttribute="leading" id="Dnd-7Z-TMw"/>
- <constraint firstAttribute="bottom" secondItem="FYK-e4-iEm" secondAttribute="bottom" id="R7i-8R-6DV"/>
- <constraint firstAttribute="trailing" secondItem="fbX-Lo-tij" secondAttribute="trailing" id="RYg-1F-lLB"/>
- <constraint firstItem="FYK-e4-iEm" firstAttribute="leading" secondItem="okw-Tg-2ad" secondAttribute="leading" id="agm-y6-aMX"/>
- <constraint firstItem="fbX-Lo-tij" firstAttribute="top" secondItem="okw-Tg-2ad" secondAttribute="top" id="cU9-ui-8N7"/>
- <constraint firstAttribute="trailing" secondItem="FYK-e4-iEm" secondAttribute="trailing" id="dVg-eg-gFM"/>
- <constraint firstItem="FYK-e4-iEm" firstAttribute="top" secondItem="fbX-Lo-tij" secondAttribute="bottom" id="dhh-eu-XGv"/>
- </constraints>
- <viewLayoutGuide key="safeArea" id="AcR-u0-2Ll"/>
- <point key="canvasLocation" x="139" y="153"/>
- </view>
- </objects>
- <resources>
- <image name="DefaultButton" width="9" height="9"/>
- <image name="IconExtlink" width="16" height="16"/>
- <image name="LogoIcon" width="253" height="253"/>
- <namedColor name="Primary">
- <color red="0.16078431372549021" green="0.30196078431372547" blue="0.45098039215686275" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- </namedColor>
- <namedColor name="Secondary">
- <color red="0.098039215686274508" green="0.1803921568627451" blue="0.27058823529411763" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- </namedColor>
- </resources>
-</document>