Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the Voucher view more comforming to designs #5165

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@
A9D99BA52A1F808900DE27D3 /* RelayCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 063F02732902B63F001FA09F /* RelayCache.framework */; };
A9D99BA62A1F809C00DE27D3 /* libRelaySelector.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5898D29829017DAC00EB5EBA /* libRelaySelector.a */; };
A9D99BA92A1F81B700DE27D3 /* MullvadTransport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A97F1F412A1F4E1A00ECEFDE /* MullvadTransport.framework */; };
A9E034642ABB302000E59A5A /* UIEdgeInsets+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9E034632ABB302000E59A5A /* UIEdgeInsets+Extensions.swift */; };
A9EC20E62A5C488D0040D56E /* Haversine.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9EC20E52A5C488D0040D56E /* Haversine.swift */; };
A9EC20E82A5D3A8C0040D56E /* CoordinatesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9EC20E72A5D3A8C0040D56E /* CoordinatesTests.swift */; };
A9EC20F02A5D79ED0040D56E /* TunnelObfuscation.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5840231F2A406BF5007B27AC /* TunnelObfuscation.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
Expand Down Expand Up @@ -1438,6 +1439,7 @@
A9CF11FC2A0518E7001D9565 /* AddressCacheTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressCacheTests.swift; sourceTree = "<group>"; };
A9D96B192A8247C100A5C673 /* MigrationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationManager.swift; sourceTree = "<group>"; };
A9D99B9F2A1F7F3A00DE27D3 /* TransportProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransportProvider.swift; sourceTree = "<group>"; };
A9E034632ABB302000E59A5A /* UIEdgeInsets+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIEdgeInsets+Extensions.swift"; sourceTree = "<group>"; };
A9EC20E52A5C488D0040D56E /* Haversine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Haversine.swift; sourceTree = "<group>"; };
A9EC20E72A5D3A8C0040D56E /* CoordinatesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoordinatesTests.swift; sourceTree = "<group>"; };
A9EC20F32A5D96030040D56E /* Midpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Midpoint.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2073,8 +2075,9 @@
583FE02729C1ADF7006E85F9 /* UI appearance */ = {
isa = PBXGroup;
children = (
585CA70E25F8C44600B47C62 /* UIMetrics.swift */,
58CCA0152242560B004F3011 /* UIColor+Palette.swift */,
A9E034632ABB302000E59A5A /* UIEdgeInsets+Extensions.swift */,
585CA70E25F8C44600B47C62 /* UIMetrics.swift */,
);
path = "UI appearance";
sourceTree = "<group>";
Expand Down Expand Up @@ -4045,6 +4048,7 @@
58CE5E64224146200008646E /* AppDelegate.swift in Sources */,
F0DA87492A9CBA9F006044F1 /* AccountDeviceRow.swift in Sources */,
5878A27329091D6D0096FC88 /* TunnelBlockObserver.swift in Sources */,
A9E034642ABB302000E59A5A /* UIEdgeInsets+Extensions.swift in Sources */,
58E0A98827C8F46300FE6BDD /* Tunnel.swift in Sources */,
58ACF64F26567A7100ACE4B7 /* CustomSwitchContainer.swift in Sources */,
58EE2E3A272FF814003BFF93 /* SettingsDataSource.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,16 @@ public class CreateAccountVoucherCoordinator: Coordinator {
self.navigationController = navigationController
self.interactor = interactor

var layoutMargins = navigationController.view.layoutMargins.toDirectionalInsets
layoutMargins.top += UIMetrics.contentLayoutMargins.top
layoutMargins.bottom += UIMetrics.contentLayoutMargins.bottom

viewController = RedeemVoucherViewController(
configuration: RedeemVoucherViewConfiguration(adjustViewWhenKeyboardAppears: true),
configuration: RedeemVoucherViewConfiguration(
adjustViewWhenKeyboardAppears: true,
shouldUseCompactStyle: false,
layoutMargins: layoutMargins
),
interactor: interactor
)
}
Expand Down
6 changes: 5 additions & 1 deletion ios/MullvadVPN/Coordinators/ProfileVoucherCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ final class ProfileVoucherCoordinator: Coordinator, Presentable {
) {
self.navigationController = navigationController
viewController = RedeemVoucherViewController(
configuration: RedeemVoucherViewConfiguration(adjustViewWhenKeyboardAppears: false),
configuration: RedeemVoucherViewConfiguration(
adjustViewWhenKeyboardAppears: false,
shouldUseCompactStyle: true,
layoutMargins: UIMetrics.SettingsRedeemVoucher.contentLayoutMargins
),
interactor: interactor
)
}
Expand Down
21 changes: 21 additions & 0 deletions ios/MullvadVPN/UI appearance/UIEdgeInsets+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// UIEdgeInsets+Extensions.swift
// MullvadVPN
//
// Created by Marco Nikic on 2023-09-20.
// Copyright © 2023 Mullvad VPN AB. All rights reserved.
//

import Foundation
import UIKit

extension UIEdgeInsets {
var toDirectionalInsets: NSDirectionalEdgeInsets {
NSDirectionalEdgeInsets(
top: top,
leading: left,
bottom: bottom,
trailing: right
)
}
}
4 changes: 3 additions & 1 deletion ios/MullvadVPN/UI appearance/UIMetrics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ enum UIMetrics {
enum SettingsRedeemVoucher {
static let cornerRadius = 8.0
static let preferredContentSize = CGSize(width: 280, height: 260)
static let contentLayoutMargins = NSDirectionalEdgeInsets(top: 16, leading: 0, bottom: 16, trailing: 0)
static let contentLayoutMargins = NSDirectionalEdgeInsets(top: 16, leading: 16, bottom: 16, trailing: 16)
static let successfulRedeemMargins = NSDirectionalEdgeInsets(top: 16, leading: 8, bottom: 16, trailing: 8)
}

enum AccountDeletion {
Expand Down Expand Up @@ -130,6 +131,7 @@ extension UIMetrics {
/// Various paddings used throughout the app to visually separate elements in StackViews
static let padding4: CGFloat = 4
static let padding8: CGFloat = 8
static let padding10: CGFloat = 10
static let padding16: CGFloat = 16
static let padding24: CGFloat = 24
static let padding32: CGFloat = 32
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,18 @@ class AddCreditSucceededViewController: UIViewController, RootContainment {

override func viewDidLoad() {
super.viewDidLoad()
addSubviews()
addConstraints()
configureUI()
addDismissButtonHandler()
}

private func addSubviews() {
for subview in [statusImageView, titleLabel, messageLabel, dismissButton] {
view.addSubview(subview)
private func configureUI() {
let contentHolderView = UIView(frame: .zero)

view.addConstrainedSubviews([contentHolderView]) {
contentHolderView.pinEdgesToSuperview(.all(UIMetrics.SettingsRedeemVoucher.successfulRedeemMargins))
}
}

private func addConstraints() {
view.addConstrainedSubviews([statusImageView, titleLabel, messageLabel, dismissButton]) {
contentHolderView.addConstrainedSubviews([statusImageView, titleLabel, messageLabel, dismissButton]) {
statusImageView.pinEdgesToSuperviewMargins(PinnableEdges([.top(0)]))
statusImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class LogoutDialogueView: UIView {

private let messageLabel: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .callout, weight: .light)
label.font = .preferredFont(forTextStyle: .callout, weight: .semibold)
label.numberOfLines = .zero
label.lineBreakMode = .byWordWrapping
label.textColor = .white
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,33 @@ final class RedeemVoucherContentView: UIView {
return contentHolderView
}()

private let titleLabel: UILabel = {
private let voucherTextFieldHeight: CGFloat = 54

private let title: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .body)
label.font = .preferredFont(forTextStyle: .title1, weight: .bold).withSize(32)
label.text = NSLocalizedString(
"REDEEM_VOUCHER_TITLE",
tableName: "RedeemVoucher",
value: "Redeem voucher",
comment: ""
)
label.textColor = .white
label.numberOfLines = 0
return label
}()

private let enterVoucherLabel: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .body, weight: .semibold).withSize(15)

label.text = NSLocalizedString(
"REDEEM_VOUCHER_INSTRUCTION",
tableName: "RedeemVoucher",
value: "Enter voucher code",
comment: ""
)
label.textColor = .white
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
return label
}()
Expand All @@ -61,7 +77,6 @@ final class RedeemVoucherContentView: UIView {

private let activityIndicator: SpinnerActivityIndicatorView = {
let activityIndicator = SpinnerActivityIndicatorView(style: .medium)
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
activityIndicator.tintColor = .white
activityIndicator.setContentHuggingPriority(.defaultHigh, for: .horizontal)
activityIndicator.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
Expand All @@ -70,7 +85,7 @@ final class RedeemVoucherContentView: UIView {

private let statusLabel: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .body)
label.font = .systemFont(ofSize: 13, weight: .semibold)
label.numberOfLines = 2
label.lineBreakMode = .byWordWrapping
label.textColor = .red
Expand Down Expand Up @@ -111,32 +126,36 @@ final class RedeemVoucherContentView: UIView {

private lazy var statusStack: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [activityIndicator, statusLabel])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .horizontal
stackView.spacing = UIMetrics.padding8
return stackView
}()

private lazy var voucherCodeStackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [
titleLabel,
var arrangedSubviews = [
enterVoucherLabel,
textField,
statusStack,
logoutViewForAccountNumberIsEntered,
])
stackView.translatesAutoresizingMaskIntoConstraints = false
]

if configuration.shouldUseCompactStyle == false {
arrangedSubviews.insert(title, at: 0)
}

let stackView = UIStackView(arrangedSubviews: arrangedSubviews)
stackView.axis = .vertical
stackView.setCustomSpacing(UIMetrics.padding16, after: titleLabel)
stackView.setCustomSpacing(UIMetrics.padding8, after: title)
stackView.setCustomSpacing(UIMetrics.padding16, after: enterVoucherLabel)
stackView.setCustomSpacing(UIMetrics.padding8, after: textField)
stackView.setCustomSpacing(UIMetrics.padding16, after: statusLabel)
stackView.setCustomSpacing(UIMetrics.padding24, after: statusStack)
stackView.setCustomSpacing(UIMetrics.padding10, after: statusStack)
stackView.setContentHuggingPriority(.defaultLow, for: .vertical)

return stackView
}()

private lazy var buttonsStackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [redeemButton, cancelButton])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.spacing = UIMetrics.padding16
stackView.setContentCompressionResistancePriority(.required, for: .vertical)
Expand Down Expand Up @@ -238,9 +257,7 @@ final class RedeemVoucherContentView: UIView {
}

required init?(coder: NSCoder) {
self.configuration = RedeemVoucherViewConfiguration(adjustViewWhenKeyboardAppears: true)
super.init(coder: coder)
commonInit()
fatalError("init(coder:) has not been implemented")
}

private func commonInit() {
Expand All @@ -260,13 +277,13 @@ final class RedeemVoucherContentView: UIView {

private func configureUI() {
addConstrainedSubviews([scrollView]) {
scrollView.pinEdgesToSuperviewMargins()
scrollView.pinEdgesToSuperview(.all(configuration.layoutMargins))
}

scrollView.addConstrainedSubviews([contentHolderView]) {
contentHolderView.pinEdgesToSuperview()
contentHolderView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: 1.0)
contentHolderView.heightAnchor.constraint(greaterThanOrEqualTo: scrollView.heightAnchor, multiplier: 1.0)
contentHolderView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
contentHolderView.heightAnchor.constraint(greaterThanOrEqualTo: scrollView.heightAnchor)
}
contentHolderView.addConstrainedSubviews([voucherCodeStackView, buttonsStackView]) {
voucherCodeStackView.pinEdgesToSuperview(.all().excluding(.bottom))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
//

import Foundation
import UIKit

struct RedeemVoucherViewConfiguration {
let adjustViewWhenKeyboardAppears: Bool
/// Hides the title when set to `true`.
let shouldUseCompactStyle: Bool
/// Custom margins to use for the compact style.
let layoutMargins: NSDirectionalEdgeInsets
}
Loading