summaryrefslogtreecommitdiffhomepage
path: root/ios/MullvadVPN/View controllers/RedeemVoucher/LogoutDialogueView.swift
blob: 4a00caebaa0ecb6514d454ffb4080d5930b5b6f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//
//  LogoutDialogueView.swift
//  MullvadVPN
//
//  Created by Mojgan on 2023-08-29.
//  Copyright © 2025 Mullvad VPN AB. All rights reserved.
//

import UIKit

class LogoutDialogueView: UIView {
    private let containerView: UIView = {
        let view = UIView()
        view.backgroundColor = .secondaryColor
        view.layer.cornerRadius = 11
        view.directionalLayoutMargins = UIMetrics.CustomAlert.containerMargins
        view.clipsToBounds = true
        return view
    }()

    private let messageLabel: UILabel = {
        let label = UILabel()
        let message = NSMutableAttributedString(
            string: NSLocalizedString(
                "It looks like you’ve entered an account number instead of a voucher code. "
                    + "If you would like to change the active account, please log out first.",
                comment: ""
            )
        )
        message.apply(paragraphStyle: .alert)

        label.attributedText = message
        label.font = .preferredFont(forTextStyle: .callout, weight: .semibold)
        label.numberOfLines = .zero
        label.textColor = .white

        return label
    }()

    private let logoutButton: AppButton = {
        let button = AppButton(style: .danger)
        button.setTitle(NSLocalizedString("Log out", comment: ""), for: .normal)
        return button
    }()

    private var showConstraint: NSLayoutConstraint?
    private var hideConstraint: NSLayoutConstraint?
    private var didRequestToLogOut: (LogoutDialogueView) -> Void

    var isLoading = true {
        didSet {
            logoutButton.isEnabled = !isLoading
        }
    }

    override var isHidden: Bool {
        willSet {
            if newValue == true {
                fadeOut()
            } else {
                fadeIn()
            }
        }
    }

    init(didRequestToLogOut: @escaping (LogoutDialogueView) -> Void) {
        self.didRequestToLogOut = didRequestToLogOut
        super.init(frame: .zero)
        setupAppearance()
        configureUI()
        addActions()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupAppearance() {
        containerView.layer.cornerRadius = 11
        containerView.backgroundColor = .primaryColor
    }

    private func configureUI() {
        addConstrainedSubviews([containerView]) {
            containerView.pinEdgesToSuperview(.all().excluding(.bottom))
        }

        containerView.addConstrainedSubviews([messageLabel, logoutButton]) {
            messageLabel.pinEdgesToSuperviewMargins(.all().excluding(.bottom))
            logoutButton.pinEdgesToSuperviewMargins(.all().excluding(.top))
            logoutButton.topAnchor.constraint(
                equalTo: messageLabel.bottomAnchor,
                constant: UIMetrics.padding16
            ).withPriority(.defaultHigh)
        }

        showConstraint = containerView.bottomAnchor.constraint(equalTo: bottomAnchor)
        hideConstraint = containerView.bottomAnchor.constraint(equalTo: topAnchor)
        hideConstraint?.isActive = true
    }

    private func addActions() {
        logoutButton.addTarget(self, action: #selector(logout), for: .touchUpInside)
    }

    @objc private func logout() {
        didRequestToLogOut(self)
    }

    private func fadeIn() {
        guard hideConstraint?.isActive == true else { return }
        showConstraint?.isActive = true
        hideConstraint?.isActive = false
        animateWith(
            animations: {
                self.containerView.alpha = 1.0
            }, duration: 0.3, delay: 0.2)
    }

    private func fadeOut() {
        guard showConstraint?.isActive == true else { return }
        showConstraint?.isActive = false
        hideConstraint?.isActive = true
        animateWith(
            animations: {
                self.containerView.alpha = 0.0
            }, duration: 0.0, delay: 0.0)
    }

    private func animateWith(
        animations: @escaping () -> Void,
        duration: TimeInterval,
        delay: TimeInterval
    ) {
        UIView.animate(
            withDuration: duration,
            delay: delay,
            options: .curveEaseInOut,
            animations: {
                animations()
                self.layoutIfNeeded()
            },
            completion: nil
        )
    }
}