ErrorView.swift 6.57 KB
Newer Older
Henri Mägi's avatar
Henri Mägi committed
1
2
import UIKit

3
protocol ErrorViewProtocol: AnyObject {
Olev Abel's avatar
Olev Abel committed
4
  func setDP3TSDKVersion(sdkVersion: String)
5
6
}

Henri Mägi's avatar
Henri Mägi committed
7
final class ErrorView: UIView {
Olev Abel's avatar
Olev Abel committed
8
9
10
11
12
13
14
15
16
17
18
19
20
  private typealias ShadowStyle = Style.General.Object.Shadow
  private typealias ContainerStackStyle = Style.General.Object.ContainerStack
  private typealias StackViewStyle = Style.General.Object.StackView
  private typealias ButtonStyle = Style.General.Object.Button
  private typealias IconStyle = Style.General.Object.Icon
  private typealias HeaderLabelStyle = Style.General.Object.HeaderLabel
  private typealias LayoutStyle = Style.General.Layout
  private typealias SubLabelStyle = Style.General.Object.SubLabel
  private typealias DescriptionStyle = Style.General.Object.Description

  var errorMessage: String? {
    didSet {
      errorMessageLabel.attributedText = errorMessage?.withAttributes(
21
        .font(.ainoRegular(size: DescriptionStyle.FontSize.medium)),
Olev Abel's avatar
Olev Abel committed
22
23
24
        .color(Asset.mustkivi.color),
        .minimumLineHeight(DescriptionStyle.minimumLineHeight)
      )
Henri Mägi's avatar
Henri Mägi committed
25
    }
Olev Abel's avatar
Olev Abel committed
26
27
28
29
30
  }

  let tryAgainButton = AppButton(style: .blueBordered)
  let phoneTapGesture = UITapGestureRecognizer()

Olev Abel's avatar
Olev Abel committed
31
32
33
34
35
  var onContactTehikTapped: (() -> Void)? {
    didSet {
      contactTehikLabel.highlightTap = onContactTehikTapped
    }
  }
Olev Abel's avatar
Olev Abel committed
36

Olev Abel's avatar
Olev Abel committed
37
38
39
  private let contentView = UIView()
  private let errorMessageLabel = UILabel()
  private let versionLabel = VersionLabel()
Olev Abel's avatar
Olev Abel committed
40
  private let contactTehikLabel: BulletPointView
Olev Abel's avatar
Olev Abel committed
41
42
43
  private typealias Strings = L10n.Error

  init() {
Olev Abel's avatar
Olev Abel committed
44
45
    contactTehikLabel = BulletPointView(
      text: Strings.contactTEHIK(Constants.tehikEmail, Constants.tehikPhoneNumber),
Olev Abel's avatar
Olev Abel committed
46
      highlight: [.bold(Constants.tehikEmail), .link(Constants.tehikPhoneNumber)]
Olev Abel's avatar
Olev Abel committed
47
    )
Olev Abel's avatar
Olev Abel committed
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
    super.init(frame: .zero)
    setup()
    layout()
  }

  @available(*, unavailable)
  required init?(coder _: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  private func setup() {
    backgroundColor = Asset.pahkla.color

    contentView.backgroundColor = .white

    contentView.layer.shadowColor = ShadowStyle.color.cgColor
    contentView.layer.shadowOpacity = ShadowStyle.opacity
    contentView.layer.shadowOffset = ShadowStyle.offset
    contentView.layer.shadowRadius = ShadowStyle.radius

    errorMessageLabel.numberOfLines = 0

    tryAgainButton.setTitle(Strings.tryAgainButton.uppercased(), for: .normal)
    contentView.addGestureRecognizer(phoneTapGesture)
    phoneTapGesture.delegate = self
  }

  private func layout() {
    let scrollView = UIScrollView()
    addSubview(scrollView)
    scrollView.autoPinEdgesToSuperviewEdges()

    let container = UIView()
    scrollView.addSubview(container)
    container.autoPinEdgesToSuperviewEdges(with: LayoutStyle.ContentInset.smallTop)
    container.autoMatch(.width, to: .width, of: self)

    let containerStack = UIStackView(arrangedSubviews: [createheaderView(), contentView])
    containerStack.axis = .vertical
    containerStack.isLayoutMarginsRelativeArrangement = true
    containerStack.layoutMargins = ContainerStackStyle.margins
    container.addSubview(containerStack)
    containerStack.autoPinEdge(toSuperviewEdge: .top)
    containerStack.autoPinEdge(toSuperviewEdge: .bottom)
    containerStack.autoAlignAxis(toSuperviewAxis: .vertical)
    containerStack
      .autoMatch(.width, to: .width, of: container, withMultiplier: 1,
                 relation: .lessThanOrEqual)
    containerStack.autoSetDimension(.width, toSize: ContainerStackStyle.width, relation: .lessThanOrEqual)

    let contentStack = UIStackView(arrangedSubviews: [
      createTopSection(),
      Divider(),
101
      createBottomSection()
Olev Abel's avatar
Olev Abel committed
102
103
104
105
106
107
108
109
110
111
112
113
114
115
    ])
    contentStack.axis = .vertical
    contentView.addSubview(contentStack)
    contentStack.autoPinEdgesToSuperviewEdges()

    tryAgainButton.autoSetDimension(.height, toSize: ButtonStyle.Height.medium)
  }

  func createTopSection() -> UIView {
    let stackView = UIStackView(arrangedSubviews: [
      BulletPointView(
        text: Strings.tryAgain(Strings.tryAgainTime),
        highlight: [.bold(Strings.tryAgainTime)]
      ),
116
      contactTehikLabel
Olev Abel's avatar
Olev Abel committed
117
118
119
120
121
122
123
124
125
126
127
128
    ])
    stackView.spacing = StackViewStyle.Spacing.small
    stackView.axis = .vertical
    stackView.isLayoutMarginsRelativeArrangement = true
    stackView.layoutMargins = StackViewStyle.margins
    return stackView
  }

  private func createBottomSection() -> UIView {
    let headerLabel = UILabel()
    headerLabel.numberOfLines = 0
    headerLabel.attributedText = Strings.errorHeading.withAttributes(
Olev Abel's avatar
Olev Abel committed
129
      .font(.ainoBold(size: SubLabelStyle.FontSize.medium))
Henri Mägi's avatar
Henri Mägi committed
130
131
    )

Olev Abel's avatar
Olev Abel committed
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
    versionLabel.layoutMargins = StackViewStyle.margins
    let versionStackView = UIStackView(arrangedSubviews: [versionLabel])
    versionStackView.axis = .horizontal
    versionStackView.alignment = .center
    versionStackView.isLayoutMarginsRelativeArrangement = true
    versionStackView.layoutMargins = StackViewStyle.margins
    let stackView =
      UIStackView(arrangedSubviews: [headerLabel, errorMessageLabel, tryAgainButton, versionStackView])
    stackView.spacing = StackViewStyle.Spacing.medium
    stackView.setCustomSpacing(StackViewStyle.Spacing.extraLarge, after: errorMessageLabel)
    stackView.axis = .vertical
    stackView.isLayoutMarginsRelativeArrangement = true
    stackView.layoutMargins = StackViewStyle.largeBottomMargins
    return stackView
  }

  private func createheaderView() -> UIView {
    let view = UIView()
    view.backgroundColor = Asset.pink.color
    let icon = UIImageView(image: Asset.attention.image)
    icon.tintColor = .white
    icon.autoSetDimensions(to: .init(width: IconStyle.width, height: IconStyle.height))
    let label = UILabel()
    label.attributedText = Strings.title.withAttributes(
      .color(.white),
Olev Abel's avatar
Olev Abel committed
157
      .font(.ainoHeadline(size: HeaderLabelStyle.FontSize.large))
Olev Abel's avatar
Olev Abel committed
158
    )
Henri Mägi's avatar
Henri Mägi committed
159

Olev Abel's avatar
Olev Abel committed
160
161
162
163
164
165
166
167
168
    let stackView = UIStackView(arrangedSubviews: [icon, label])
    stackView.spacing = StackViewStyle.Spacing.mediumLarge
    stackView.isLayoutMarginsRelativeArrangement = true
    stackView.layoutMargins = StackViewStyle.largeBottomMargins
    stackView.alignment = .center
    view.addSubview(stackView)
    stackView.autoPinEdgesToSuperviewEdges()
    return view
  }
Henri Mägi's avatar
Henri Mägi committed
169
170
171
}

extension ErrorView: UIGestureRecognizerDelegate {
Olev Abel's avatar
Olev Abel committed
172
173
174
175
176
177
178
  override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    contactTehikLabel.label
      .rectFor(text: Constants.tehikPhoneNumber)?
      .insetBy(dx: LayoutStyle.Margin.negative, dy: LayoutStyle.Margin.negative)
      .contains(gestureRecognizer.location(in: contactTehikLabel))
      ?? false
  }
Henri Mägi's avatar
Henri Mägi committed
179
}
180
181

extension ErrorView: ErrorViewProtocol {
Olev Abel's avatar
Olev Abel committed
182
183
184
  func setDP3TSDKVersion(sdkVersion: String) {
    versionLabel.setText(sdkVersion: sdkVersion)
  }
185
}