diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2023-05-30 11:18:02 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2023-05-30 11:18:02 +0200 |
| commit | 8ccf23e5029ad51d2d462b769d89b3c7da952636 (patch) | |
| tree | b9647f0f996b95c0feb9a0a64117bf387617cb08 | |
| parent | a90f516f561b739016b33dc3b3832f34e6c7e951 (diff) | |
| parent | e06aacee9366c0620243d34c4e92f68714240768 (diff) | |
| download | mullvadvpn-8ccf23e5029ad51d2d462b769d89b3c7da952636.tar.xz mullvadvpn-8ccf23e5029ad51d2d462b769d89b3c7da952636.zip | |
Merge branch 'notification-hide-action-button-when-noaction'
4 files changed, 68 insertions, 79 deletions
diff --git a/ios/MullvadVPN/Extensions/NSLayoutConstraint+Helpers.swift b/ios/MullvadVPN/Extensions/NSLayoutConstraint+Helpers.swift index 3a41101a96..7301c17aa4 100644 --- a/ios/MullvadVPN/Extensions/NSLayoutConstraint+Helpers.swift +++ b/ios/MullvadVPN/Extensions/NSLayoutConstraint+Helpers.swift @@ -9,6 +9,7 @@ import UIKit extension NSLayoutConstraint { + /// Sets constraint priority and returns `self` func withPriority(_ priority: UILayoutPriority) -> Self { self.priority = priority return self diff --git a/ios/MullvadVPN/Notifications/UI/NotificationBannerView.swift b/ios/MullvadVPN/Notifications/UI/NotificationBannerView.swift index 5562db43fd..dc2055765b 100644 --- a/ios/MullvadVPN/Notifications/UI/NotificationBannerView.swift +++ b/ios/MullvadVPN/Notifications/UI/NotificationBannerView.swift @@ -9,19 +9,10 @@ import UIKit final class NotificationBannerView: UIView { - private static let indicatorViewSize = CGSize(width: 12, height: 12) - private static let buttonSize = CGSize(width: 18, height: 18) - - private let backgroundView: UIVisualEffectView = { - let effect = UIBlurEffect(style: .dark) - let visualEffectView = UIVisualEffectView(effect: effect) - visualEffectView.translatesAutoresizingMaskIntoConstraints = false - return visualEffectView - }() + private let backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .dark)) private let titleLabel: UILabel = { let textLabel = UILabel() - textLabel.translatesAutoresizingMaskIntoConstraints = false textLabel.font = UIFont.systemFont(ofSize: 17, weight: .bold) textLabel.textColor = UIColor.InAppNotificationBanner.titleColor textLabel.numberOfLines = 0 @@ -35,7 +26,6 @@ final class NotificationBannerView: UIView { private let bodyLabel: UILabel = { let textLabel = UILabel() - textLabel.translatesAutoresizingMaskIntoConstraints = false textLabel.font = UIFont.systemFont(ofSize: 17) textLabel.textColor = UIColor.InAppNotificationBanner.bodyColor textLabel.numberOfLines = 0 @@ -49,24 +39,29 @@ final class NotificationBannerView: UIView { private let indicatorView: UIView = { let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false view.backgroundColor = .dangerColor - view.layer.cornerRadius = NotificationBannerView.indicatorViewSize.width * 0.5 + view.layer.cornerRadius = UIMetrics.InAppBannerNotification.indicatorSize.width * 0.5 view.layer.cornerCurve = .circular return view }() private let wrapperView: UIView = { let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.directionalLayoutMargins = UIMetrics.inAppBannerNotificationLayoutMargins + view.directionalLayoutMargins = UIMetrics.InAppBannerNotification.layoutMargins return view }() + private lazy var bodyStackView: UIStackView = { + let stackView = UIStackView(arrangedSubviews: [bodyLabel, actionButton]) + stackView.alignment = .top + stackView.distribution = .fill + stackView.spacing = UIStackView.spacingUseSystem + return stackView + }() + private let actionButton: IncreasedHitButton = { - let button = IncreasedHitButton() + let button = IncreasedHitButton(type: .system) button.tintColor = UIColor.InAppNotificationBanner.actionButtonColor - button.translatesAutoresizingMaskIntoConstraints = false return button }() @@ -90,65 +85,67 @@ final class NotificationBannerView: UIView { var action: InAppNotificationAction? { didSet { - actionButton.setImage(action?.image, for: .normal) - actionButton.addTarget(self, action: #selector(didPress), for: .touchUpInside) + let image = action?.image + let showsAction = image != nil + + actionButton.setImage(image, for: .normal) + actionButton.isHidden = !showsAction } } override init(frame: CGRect) { super.init(frame: frame) - for subview in [titleLabel, bodyLabel, indicatorView, actionButton] { - wrapperView.addSubview(subview) - } + addActionHandlers() + addSubviews() + addConstraints() + } - backgroundView.contentView.addSubview(wrapperView) - addSubview(backgroundView) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } - NSLayoutConstraint.activate([ - backgroundView.topAnchor.constraint(equalTo: topAnchor), - backgroundView.leadingAnchor.constraint(equalTo: leadingAnchor), - backgroundView.trailingAnchor.constraint(equalTo: trailingAnchor), - backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor), + private func addActionHandlers() { + actionButton.addTarget(self, action: #selector(handleActionTap), for: .touchUpInside) + } + + private func addSubviews() { + wrapperView.addConstrainedSubviews([titleLabel, indicatorView, bodyStackView]) + backgroundView.contentView.addConstrainedSubviews([wrapperView]) { + wrapperView.pinEdgesToSuperview() + } + addConstrainedSubviews([backgroundView]) { + backgroundView.pinEdgesToSuperview() + } + } - wrapperView.topAnchor.constraint(equalTo: backgroundView.contentView.topAnchor), - wrapperView.leadingAnchor.constraint(equalTo: backgroundView.contentView.leadingAnchor), - wrapperView.trailingAnchor - .constraint(equalTo: backgroundView.contentView.trailingAnchor), - wrapperView.bottomAnchor.constraint(equalTo: backgroundView.contentView.bottomAnchor), + private func addConstraints() { + let actionButtonPriority: UILayoutPriority = .defaultHigh + 1 + actionButton.setContentCompressionResistancePriority(actionButtonPriority, for: .horizontal) + actionButton.setContentCompressionResistancePriority(actionButtonPriority, for: .vertical) + actionButton.setContentHuggingPriority(actionButtonPriority, for: .horizontal) + actionButton.setContentHuggingPriority(actionButtonPriority, for: .vertical) + NSLayoutConstraint.activate([ indicatorView.bottomAnchor.constraint(equalTo: titleLabel.firstBaselineAnchor), - indicatorView.leadingAnchor - .constraint(equalTo: wrapperView.layoutMarginsGuide.leadingAnchor), - indicatorView.widthAnchor.constraint(equalToConstant: Self.indicatorViewSize.width), - indicatorView.heightAnchor.constraint(equalToConstant: Self.indicatorViewSize.height), + indicatorView.leadingAnchor.constraint(equalTo: wrapperView.layoutMarginsGuide.leadingAnchor), + indicatorView.widthAnchor + .constraint(equalToConstant: UIMetrics.InAppBannerNotification.indicatorSize.width), + indicatorView.heightAnchor + .constraint(equalToConstant: UIMetrics.InAppBannerNotification.indicatorSize.height), titleLabel.topAnchor.constraint(equalTo: wrapperView.layoutMarginsGuide.topAnchor), - titleLabel.leadingAnchor.constraint( - equalToSystemSpacingAfter: indicatorView.trailingAnchor, - multiplier: 1 - ), + titleLabel.leadingAnchor.constraint(equalToSystemSpacingAfter: indicatorView.trailingAnchor, multiplier: 1), + titleLabel.trailingAnchor.constraint(equalTo: wrapperView.layoutMarginsGuide.trailingAnchor), - bodyLabel.topAnchor.constraint( - equalToSystemSpacingBelow: titleLabel.bottomAnchor, - multiplier: 1 - ), - bodyLabel.leadingAnchor.constraint(equalTo: titleLabel.leadingAnchor), - bodyLabel.bottomAnchor.constraint(equalTo: wrapperView.layoutMarginsGuide.bottomAnchor), - - actionButton.leadingAnchor.constraint(equalTo: bodyLabel.trailingAnchor), - actionButton.topAnchor.constraint(equalTo: bodyLabel.topAnchor), - actionButton.trailingAnchor.constraint(equalTo: wrapperView.layoutMarginsGuide.trailingAnchor), - actionButton.widthAnchor.constraint(equalToConstant: NotificationBannerView.buttonSize.width), - actionButton.heightAnchor.constraint(equalToConstant: NotificationBannerView.buttonSize.height), + bodyStackView.topAnchor.constraint(equalToSystemSpacingBelow: titleLabel.bottomAnchor, multiplier: 1), + bodyStackView.leadingAnchor.constraint(equalTo: titleLabel.leadingAnchor), + bodyStackView.trailingAnchor.constraint(equalTo: titleLabel.trailingAnchor), + bodyStackView.bottomAnchor.constraint(equalTo: wrapperView.layoutMarginsGuide.bottomAnchor), ]) } - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - @objc private func didPress() { + @objc private func handleActionTap() { action?.handler?() } } diff --git a/ios/MullvadVPN/UI appearance/UIColor+Palette.swift b/ios/MullvadVPN/UI appearance/UIColor+Palette.swift index aff21edac2..3cf705cdc3 100644 --- a/ios/MullvadVPN/UI appearance/UIColor+Palette.swift +++ b/ios/MullvadVPN/UI appearance/UIColor+Palette.swift @@ -118,7 +118,7 @@ extension UIColor { static let titleColor = UIColor.white static let bodyColor = UIColor(white: 1.0, alpha: 0.6) - static let actionButtonColor = UIColor(white: 1.0, alpha: 0.6) + static let actionButtonColor = UIColor(white: 1.0, alpha: 0.8) } // Common colors diff --git a/ios/MullvadVPN/UI appearance/UIMetrics.swift b/ios/MullvadVPN/UI appearance/UIMetrics.swift index 9f7d91153f..22359687ce 100644 --- a/ios/MullvadVPN/UI appearance/UIMetrics.swift +++ b/ios/MullvadVPN/UI appearance/UIMetrics.swift @@ -22,31 +22,22 @@ extension UIMetrics { static let rowViewLayoutMargins = NSDirectionalEdgeInsets(top: 16, leading: 24, bottom: 16, trailing: 24) /// Common layout margins for settings cell presentation - static let settingsCellLayoutMargins = NSDirectionalEdgeInsets( - top: 16, - leading: 24, - bottom: 16, - trailing: 12 - ) + static let settingsCellLayoutMargins = NSDirectionalEdgeInsets(top: 16, leading: 24, bottom: 16, trailing: 12) /// Common layout margins for location cell presentation - static let selectLocationCellLayoutMargins = NSDirectionalEdgeInsets( - top: 16, - leading: 28, - bottom: 16, - trailing: 12 - ) + static let selectLocationCellLayoutMargins = NSDirectionalEdgeInsets(top: 16, leading: 28, bottom: 16, trailing: 12) /// Common cell indentation width static let cellIndentationWidth: CGFloat = 16 - /// Layout margins for in-app notification banner presentation - static let inAppBannerNotificationLayoutMargins = NSDirectionalEdgeInsets( - top: 16, - leading: 24, - bottom: 16, - trailing: 24 - ) + /// Group of constants related to in-app notifications banner. + enum InAppBannerNotification { + /// Layout margins for contents presented within the banner. + static let layoutMargins = NSDirectionalEdgeInsets(top: 16, leading: 24, bottom: 16, trailing: 24) + + /// Size of little round severity indicator. + static let indicatorSize = CGSize(width: 12, height: 12) + } /// Spacing used in stack views of buttons static let interButtonSpacing: CGFloat = 16 |
