Skip to content

Commit 0a834b7

Browse files
author
Anton Poltoratskyi
authored
Merge pull request #3 from AntonPoltoratskyi/feature/actions-interaction
Added ability to disable actions
2 parents f335056 + 67e06b7 commit 0a834b7

File tree

8 files changed

+72
-23
lines changed

8 files changed

+72
-23
lines changed

Example/NativeUIExample/Base.lproj/Main.storyboard

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
33
<device id="retina6_1" orientation="portrait" appearance="light"/>
44
<dependencies>
55
<deployment identifier="iOS"/>
6-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16086"/>
6+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
77
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
88
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
99
</dependencies>
@@ -28,6 +28,7 @@
2828
<segments>
2929
<segment title="Default"/>
3030
<segment title="Custom Content"/>
31+
<segment title="System"/>
3132
</segments>
3233
</segmentedControl>
3334
</subviews>

Example/NativeUIExample/ViewController.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ final class ViewController: UIViewController {
1414
enum Appearance: Int {
1515
case `default` = 0
1616
case custom = 1
17+
case system = 2
1718
}
1819

1920
@IBOutlet private var segmentedControl: UISegmentedControl!
@@ -53,6 +54,20 @@ final class ViewController: UIViewController {
5354
)
5455
let alert = AlertViewController(viewModel: viewModel)
5556
present(alert, animated: true)
57+
58+
case .system:
59+
let cancelAction = UIAlertAction(title: "Cancel", style: .default)
60+
let confirmAction = UIAlertAction(title: "Confirm", style: .default)
61+
62+
let alert = UIAlertController(
63+
title: "Your Title",
64+
message: "Your Message",
65+
preferredStyle: .alert
66+
)
67+
alert.addAction(cancelAction)
68+
alert.addAction(confirmAction)
69+
70+
present(alert, animated: true)
5671
}
5772
}
5873
}

Example/Podfile.lock

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
PODS:
2-
- NativeUI (0.0.3):
3-
- NativeUI/Core (= 0.0.3)
4-
- NativeUI/Alert (0.0.3):
2+
- NativeUI (1.0.1):
3+
- NativeUI/Core (= 1.0.1)
4+
- NativeUI/Alert (1.0.1):
55
- NativeUI/Utils
6-
- NativeUI/Core (0.0.3):
6+
- NativeUI/Core (1.0.1):
77
- NativeUI/Alert
8-
- NativeUI/Utils (0.0.3)
8+
- NativeUI/Utils (1.0.1)
99

1010
DEPENDENCIES:
1111
- NativeUI (from `../`)
@@ -15,8 +15,8 @@ EXTERNAL SOURCES:
1515
:path: "../"
1616

1717
SPEC CHECKSUMS:
18-
NativeUI: d89eeb004dd445bb67bef1579be654edffdd7a2e
18+
NativeUI: 6de137806356923678e5b124502c00246ed8a14a
1919

2020
PODFILE CHECKSUM: bb46d7bf1ae3b119e00a9331a12cd0a4b5cac170
2121

22-
COCOAPODS: 1.9.1
22+
COCOAPODS: 1.9.3

NativeUI.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "NativeUI"
3-
s.version = "1.0.0"
3+
s.version = "1.0.1"
44
s.summary = "Library that includes customizable replacements for native UIKit components"
55

66
s.description = <<-DESC

NativeUI.xcodeproj/project.pbxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@
8080
3AB073CE243A017A0092DF66 /* Alert.swift */,
8181
3AB073D1243A017A0092DF66 /* AlertViewController.swift */,
8282
3AB073D0243A017A0092DF66 /* AlertView.swift */,
83-
3AB073CD243A017A0092DF66 /* AlertPresentationAnimator.swift */,
8483
3AB073CF243A017A0092DF66 /* AlertActionSequenceView.swift */,
84+
3AB073CD243A017A0092DF66 /* AlertPresentationAnimator.swift */,
8585
);
8686
path = Alert;
8787
sourceTree = "<group>";

NativeUI/Sources/Alert/Alert.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import UIKit
1010

1111
public struct Alert {
12-
public struct Action {
12+
public final class Action {
1313
public typealias Handler = (Alert.Action) -> Void
1414

1515
public enum Style {
@@ -19,11 +19,19 @@ public struct Alert {
1919
}
2020
public let title: String
2121
public let style: Style
22+
public var isEnabled: Bool {
23+
didSet {
24+
actionStateHandler?(isEnabled)
25+
}
26+
}
2227
public let handler: Handler?
2328

24-
public init(title: String, style: Style, handler: Handler? = nil) {
29+
var actionStateHandler: ((Bool) -> Void)?
30+
31+
public init(title: String, style: Style, isEnabled: Bool = true, handler: Handler? = nil) {
2532
self.title = title
2633
self.style = style
34+
self.isEnabled = isEnabled
2735
self.handler = handler
2836
}
2937
}
@@ -42,17 +50,21 @@ public struct Alert {
4250

4351
public let tintColor: UIColor?
4452

53+
public let disabledTintColor: UIColor?
54+
4555
public let actions: [Action]
4656

4757
public init(title: Text?,
4858
message: Text?,
4959
contentView: UIView? = nil,
5060
tintColor: UIColor? = nil,
61+
disabledTintColor: UIColor? = nil,
5162
actions: [Action]) {
5263
self.title = title
5364
self.message = message
5465
self.contentView = contentView
5566
self.tintColor = tintColor
67+
self.disabledTintColor = disabledTintColor
5668
self.actions = actions
5769
}
5870

@@ -62,23 +74,27 @@ public struct Alert {
6274
messageFont: UIFont = UIFont.systemFont(ofSize: 13, weight: .regular),
6375
contentView: UIView? = nil,
6476
tintColor: UIColor? = nil,
77+
disabledTintColor: UIColor? = nil,
6578
actions: [Action]) {
6679
self.init(title: title.map { .string($0, titleFont) },
6780
message: message.map { .string($0, messageFont) },
6881
contentView: contentView,
6982
tintColor: tintColor,
83+
disabledTintColor: disabledTintColor,
7084
actions: actions)
7185
}
7286

7387
public init(title: NSAttributedString?,
7488
message: NSAttributedString?,
7589
contentView: UIView? = nil,
7690
tintColor: UIColor? = nil,
91+
disabledTintColor: UIColor? = nil,
7792
actions: [Action]) {
7893
self.init(title: title.map { .attributedString($0) },
7994
message: message.map { .attributedString($0) },
8095
contentView: contentView,
8196
tintColor: tintColor,
97+
disabledTintColor: disabledTintColor,
8298
actions: actions)
8399
}
84100
}

NativeUI/Sources/Alert/AlertActionSequenceView.swift

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ protocol AlertActionSequenceViewDelegate: AnyObject {
1414

1515
struct AlertActionSequenceViewModel {
1616
let actions: [Alert.Action]
17+
let disabledTintColor: UIColor?
1718
let separatorColor: UIColor
1819
let separatorWidth: CGFloat
1920
}
@@ -34,6 +35,8 @@ final class AlertActionSequenceView: UIControl {
3435
}
3536
}
3637

38+
var isEnabled: Bool = true
39+
3740
private(set) lazy var titleLabel: UILabel = {
3841
let label = UILabel()
3942
label.translatesAutoresizingMaskIntoConstraints = false
@@ -104,15 +107,15 @@ final class AlertActionSequenceView: UIControl {
104107
}
105108

106109
if let action = viewModel.actions.first {
107-
let actionView = makeActionView(for: action)
110+
let actionView = makeActionView(for: action, disabledTintColor: viewModel.disabledTintColor)
108111
stackView.addArrangedSubview(actionView)
109112
}
110113

111114
for action in viewModel.actions.dropFirst() {
112115
let separator = makeButtonSeparatorView(viewModel: viewModel)
113116
stackView.addArrangedSubview(separator)
114117

115-
let actionView = makeActionView(for: action)
118+
let actionView = makeActionView(for: action, disabledTintColor: viewModel.disabledTintColor)
116119
stackView.addArrangedSubview(actionView)
117120

118121
if let firstActionView = stackView.arrangedSubviews.first(where: { $0 !== actionView }) {
@@ -121,25 +124,37 @@ final class AlertActionSequenceView: UIControl {
121124
}
122125
}
123126

124-
private func makeActionView(for action: Alert.Action) -> ActionView {
127+
private func makeActionView(for action: Alert.Action, disabledTintColor: UIColor?) -> ActionView {
125128
let actionView = ActionView()
126129
actionView.translatesAutoresizingMaskIntoConstraints = false
127130

131+
updateAppearance(for: actionView, action: action, disabledTintColor: disabledTintColor)
132+
133+
action.actionStateHandler = { [weak actionView, weak action, weak self] isEnabled in
134+
guard let actionView = actionView, let action = action else { return }
135+
self?.updateAppearance(for: actionView, action: action, disabledTintColor: disabledTintColor)
136+
}
137+
138+
return actionView
139+
}
140+
141+
private func updateAppearance(for actionView: ActionView, action: Alert.Action, disabledTintColor: UIColor?) {
142+
actionView.isEnabled = action.isEnabled
128143
actionView.titleLabel.text = action.title
129144

145+
let disabledTintColor = disabledTintColor ?? UIColor(white: 0.48, alpha: 0.8)
146+
130147
switch action.style {
131148
case .default:
132149
actionView.titleLabel.font = UIFont.systemFont(ofSize: 17, weight: .regular)
133-
actionView.titleLabel.textColor = tintColor
150+
actionView.titleLabel.textColor = action.isEnabled ? tintColor : disabledTintColor
134151
case .primary:
135152
actionView.titleLabel.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
136-
actionView.titleLabel.textColor = tintColor
153+
actionView.titleLabel.textColor = action.isEnabled ? tintColor : disabledTintColor
137154
case let .custom(font, textColor):
138155
actionView.titleLabel.font = font
139-
actionView.titleLabel.textColor = textColor
156+
actionView.titleLabel.textColor = action.isEnabled ? textColor : disabledTintColor
140157
}
141-
142-
return actionView
143158
}
144159

145160
private func makeButtonSeparatorView(viewModel: AlertActionSequenceViewModel) -> UIView {
@@ -189,7 +204,7 @@ final class AlertActionSequenceView: UIControl {
189204
guard let actionViewFrame = actionView.superview?.convert(actionView.frame, to: self) else {
190205
continue
191206
}
192-
let isHighlighted = actionViewFrame.contains(point)
207+
let isHighlighted = actionViewFrame.contains(point) && actionView.isEnabled
193208
actionView.isHighlighted = isHighlighted
194209

195210
if isHighlighted, highlightedView != actionView {
@@ -226,7 +241,8 @@ final class AlertActionSequenceView: UIControl {
226241

227242
@objc private func handleTap(on actionView: ActionView) {
228243
let index = stackView.arrangedSubviews
229-
.filter { $0 is ActionView }
244+
.compactMap { $0 as? ActionView }
245+
.filter { $0.isEnabled }
230246
.firstIndex(where: { $0 === actionView })
231247

232248
if let index = index {

NativeUI/Sources/Alert/AlertView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ final class AlertView: UIView {
193193

194194
let actionsViewModel = AlertActionSequenceViewModel(
195195
actions: viewModel.actions,
196+
disabledTintColor: viewModel.disabledTintColor,
196197
separatorColor: separatorColor,
197198
separatorWidth: Layout.separatorThickness
198199
)

0 commit comments

Comments
 (0)