diff options
| -rw-r--r-- | ios/MullvadVPN.xcodeproj/project.pbxproj | 4 | ||||
| -rw-r--r-- | ios/MullvadVPN/HeaderBarView.swift | 56 | ||||
| -rw-r--r-- | ios/MullvadVPN/HeaderBarView.xib | 61 | ||||
| -rw-r--r-- | ios/MullvadVPN/RootContainerViewController.swift | 25 |
4 files changed, 48 insertions, 98 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index de75dd4a2f..de3226aa5d 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -188,7 +188,6 @@ 58F3C09C249B99DD003E76BE /* Curve25519.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F3C09B249B99DD003E76BE /* Curve25519.swift */; }; 58F3C09D249B99DD003E76BE /* Curve25519.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F3C09B249B99DD003E76BE /* Curve25519.swift */; }; 58F3C0A0249BBF1E003E76BE /* DiffableDataSources in Frameworks */ = {isa = PBXBuildFile; productRef = 58F3C09F249BBF1E003E76BE /* DiffableDataSources */; }; - 58F3C0A2249CA1E0003E76BE /* HeaderBarView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 58F3C0A1249CA1E0003E76BE /* HeaderBarView.xib */; }; 58F3C0A4249CB069003E76BE /* HeaderBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F3C0A3249CB069003E76BE /* HeaderBarView.swift */; }; 58F3C0A624A50157003E76BE /* relays.json in Resources */ = {isa = PBXBuildFile; fileRef = 58F3C0A524A50155003E76BE /* relays.json */; }; 58F3C0A724A50C02003E76BE /* relays.json in Resources */ = {isa = PBXBuildFile; fileRef = 58F3C0A524A50155003E76BE /* relays.json */; }; @@ -372,7 +371,6 @@ 58F3C097249B978C003E76BE /* x25519.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = x25519.h; sourceTree = "<group>"; }; 58F3C098249B978C003E76BE /* x25519.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = x25519.c; sourceTree = "<group>"; }; 58F3C09B249B99DD003E76BE /* Curve25519.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Curve25519.swift; sourceTree = "<group>"; }; - 58F3C0A1249CA1E0003E76BE /* HeaderBarView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HeaderBarView.xib; sourceTree = "<group>"; }; 58F3C0A3249CB069003E76BE /* HeaderBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderBarView.swift; sourceTree = "<group>"; }; 58F3C0A524A50155003E76BE /* relays.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = relays.json; sourceTree = "<group>"; }; 58F840AE2464382C0044E708 /* KeychainItemRevision.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainItemRevision.swift; sourceTree = "<group>"; }; @@ -541,7 +539,6 @@ 58B9EB142489139B00095626 /* DisplayChainedError.swift */, 5873884C239E6D7E00E96C4E /* EmbeddedViewContainerView.swift */, 58F3C0A3249CB069003E76BE /* HeaderBarView.swift */, - 58F3C0A1249CA1E0003E76BE /* HeaderBarView.xib */, 58FD5BF32428C67600112C88 /* InAppPurchaseButton.swift */, 58CE5E6F224146210008646E /* Info.plist */, 5840250022B1124600E4CFEC /* IpAddress+Codable.swift */, @@ -833,7 +830,6 @@ buildActionMask = 2147483647; files = ( 58907D9324D167B400CFC3F5 /* DisconnectSplitButton.xib in Resources */, - 58F3C0A2249CA1E0003E76BE /* HeaderBarView.xib in Resources */, 58F3C0A624A50157003E76BE /* relays.json in Resources */, 58CE5E6E224146210008646E /* LaunchScreen.storyboard in Resources */, 58CE5E6B224146210008646E /* Assets.xcassets in Resources */, diff --git a/ios/MullvadVPN/HeaderBarView.swift b/ios/MullvadVPN/HeaderBarView.swift index be92076190..55e2c16070 100644 --- a/ios/MullvadVPN/HeaderBarView.swift +++ b/ios/MullvadVPN/HeaderBarView.swift @@ -10,31 +10,51 @@ import Foundation import UIKit class HeaderBarView: UIView { - @IBOutlet var contentView: UIView! - @IBOutlet var settingsButton: UIButton! + let logoImageView = UIImageView(image: UIImage(named: "LogoIcon")) - init(bundle: Bundle?) { - super.init(frame: .zero) + lazy var titleLabel: UILabel = { + let titleLabel = UILabel() + titleLabel.text = "MULLVAD VPN" + titleLabel.font = UIFont.boldSystemFont(ofSize: 24) + titleLabel.textColor = UIColor.white.withAlphaComponent(0.8) + return titleLabel + }() - loadFromNib(bundle: bundle) - } + lazy var settingsButton: UIButton = { + let settingsButton = UIButton(type: .custom) + settingsButton.setImage(UIImage(named: "IconSettings"), for: .normal) + return settingsButton + }() - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + override init(frame: CGRect) { + super.init(frame: frame) + + layoutMargins = UIEdgeInsets(top: 20, left: 12, bottom: 0, right: 16) - private func loadFromNib(bundle: Bundle?) { - let nib = UINib(nibName: "HeaderBarView", bundle: bundle) - _ = nib.instantiate(withOwner: self, options: nil) + let constraints = [ + logoImageView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), + logoImageView.centerYAnchor.constraint(equalTo: titleLabel.centerYAnchor), + logoImageView.widthAnchor.constraint(equalToConstant: 44), + logoImageView.heightAnchor.constraint(equalTo: logoImageView.widthAnchor, multiplier: 1), - let constraints = [contentView.leadingAnchor.constraint(equalTo: leadingAnchor), - contentView.trailingAnchor.constraint(equalTo: trailingAnchor), - contentView.topAnchor.constraint(equalTo: topAnchor), - contentView.bottomAnchor.constraint(equalTo: bottomAnchor)] + titleLabel.leadingAnchor.constraint(equalTo: logoImageView.trailingAnchor, constant: 8), + titleLabel.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: 22), + layoutMarginsGuide.bottomAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 22), - contentView.translatesAutoresizingMaskIntoConstraints = false - addSubview(contentView) + settingsButton.leadingAnchor.constraint(greaterThanOrEqualTo: titleLabel.trailingAnchor, constant: 8), + settingsButton.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), + settingsButton.centerYAnchor.constraint(equalTo: titleLabel.centerYAnchor) + ] + + for view in [logoImageView, titleLabel, settingsButton] { + view.translatesAutoresizingMaskIntoConstraints = false + addSubview(view) + } NSLayoutConstraint.activate(constraints) } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/ios/MullvadVPN/HeaderBarView.xib b/ios/MullvadVPN/HeaderBarView.xib deleted file mode 100644 index ab524ecbb1..0000000000 --- a/ios/MullvadVPN/HeaderBarView.xib +++ /dev/null @@ -1,61 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16096" 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="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> - </dependencies> - <objects> - <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="HeaderBarView" customModule="MullvadVPN" customModuleProvider="target"> - <connections> - <outlet property="contentView" destination="ov3-nw-UAQ" id="xIt-HC-BNQ"/> - <outlet property="settingsButton" destination="TCH-Bw-nMr" id="g2X-ry-UC8"/> - </connections> - </placeholder> - <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> - <view contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="ov3-nw-UAQ"> - <rect key="frame" x="0.0" y="0.0" width="414" height="107"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> - <subviews> - <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="LogoIcon" translatesAutoresizingMaskIntoConstraints="NO" id="ZOX-0C-1fD"> - <rect key="frame" x="20" y="41.5" width="44" height="44"/> - <constraints> - <constraint firstAttribute="width" secondItem="ZOX-0C-1fD" secondAttribute="height" multiplier="1:1" id="2q1-l2-vu7"/> - <constraint firstAttribute="width" constant="44" id="tDk-Mj-nnP"/> - </constraints> - </imageView> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TCH-Bw-nMr"> - <rect key="frame" x="370" y="51.5" width="24" height="24"/> - <accessibility key="accessibilityConfiguration" identifier="SettingsButton"/> - <state key="normal" image="IconSettings"/> - </button> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="MULLVAD VPN" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qnt-qI-YIW"> - <rect key="frame" x="72" y="42" width="168" height="43"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="24"/> - <color key="textColor" white="1" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <nil key="highlightedColor"/> - </label> - </subviews> - <constraints> - <constraint firstAttribute="bottomMargin" secondItem="Qnt-qI-YIW" secondAttribute="bottom" constant="22" id="C4h-d6-8jh"/> - <constraint firstItem="TCH-Bw-nMr" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Qnt-qI-YIW" secondAttribute="trailing" constant="8" symbolic="YES" id="auJ-gc-6ue"/> - <constraint firstItem="Qnt-qI-YIW" firstAttribute="leading" secondItem="ZOX-0C-1fD" secondAttribute="trailing" constant="8" id="cD3-Tp-tkQ"/> - <constraint firstItem="TCH-Bw-nMr" firstAttribute="centerY" secondItem="Qnt-qI-YIW" secondAttribute="centerY" id="dAi-dp-MzM"/> - <constraint firstItem="ZOX-0C-1fD" firstAttribute="centerY" secondItem="Qnt-qI-YIW" secondAttribute="centerY" id="gut-cS-uB1"/> - <constraint firstAttribute="trailingMargin" secondItem="TCH-Bw-nMr" secondAttribute="trailing" id="qSf-ZX-xQs"/> - <constraint firstItem="Qnt-qI-YIW" firstAttribute="top" secondItem="ov3-nw-UAQ" secondAttribute="topMargin" constant="22" id="rTh-9P-ArN"/> - <constraint firstItem="ZOX-0C-1fD" firstAttribute="leading" secondItem="ov3-nw-UAQ" secondAttribute="leadingMargin" id="urJ-3h-lgX"/> - </constraints> - <nil key="simulatedTopBarMetrics"/> - <nil key="simulatedBottomBarMetrics"/> - <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> - <edgeInsets key="layoutMargins" top="20" left="12" bottom="0.0" right="16"/> - <point key="canvasLocation" x="84.057971014492765" y="-652.56696428571422"/> - </view> - </objects> - <resources> - <image name="IconSettings" width="24" height="24"/> - <image name="LogoIcon" width="253" height="253"/> - </resources> -</document> diff --git a/ios/MullvadVPN/RootContainerViewController.swift b/ios/MullvadVPN/RootContainerViewController.swift index 0c8ff7e40e..51229183a6 100644 --- a/ios/MullvadVPN/RootContainerViewController.swift +++ b/ios/MullvadVPN/RootContainerViewController.swift @@ -47,7 +47,7 @@ class RootContainerViewController: UIViewController { return viewControllers.last } - private let headerBarView = HeaderBarView(bundle: nil) + private let headerBarView = HeaderBarView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) private let transitionContainer = UIView(frame: UIScreen.main.bounds) private(set) var headerBarStyle = HeaderBarStyle.default @@ -201,6 +201,10 @@ class RootContainerViewController: UIViewController { ] headerBarView.translatesAutoresizingMaskIntoConstraints = false + + // Prevent automatic layout margins adjustment as we manually control them. + headerBarView.insetsLayoutMarginsFromSafeArea = false + headerBarView.settingsButton.addTarget( self, action: #selector(handleSettingsButtonTap), @@ -344,27 +348,18 @@ class RootContainerViewController: UIViewController { private func updateHeaderBarLayoutMarginsIfNeeded() { let offsetTop = view.safeAreaInsets.top - additionalSafeAreaInsets.top - var layoutMargins = headerBarView.layoutMargins - layoutMargins.top = offsetTop - - if layoutMargins != headerBarView.layoutMargins { - headerBarView.layoutMargins = layoutMargins + if headerBarView.layoutMargins.top != offsetTop { + headerBarView.layoutMargins.top = offsetTop } } /// Updates additional safe area insets to push the child views below the header bar private func updateAdditionalSafeAreaInsetsIfNeeded() { - var safeAreaInsets = additionalSafeAreaInsets - // Reset top inset if header bar is invisible - if headerBarHidden { - safeAreaInsets.top = 0 - } else { - safeAreaInsets.top = headerBarView.frame.height - } + let insetTop = headerBarHidden ? 0 : headerBarView.frame.height - if additionalSafeAreaInsets != safeAreaInsets { - additionalSafeAreaInsets = safeAreaInsets + if additionalSafeAreaInsets.top != insetTop { + additionalSafeAreaInsets.top = insetTop } } |
