Skip to content

Commit

Permalink
Merge pull request #3 from AntonPoltoratskyi/feature/actions-interaction
Browse files Browse the repository at this point in the history
Added ability to disable actions
  • Loading branch information
devpolant committed Aug 15, 2020
2 parents f335056 + 67e06b7 commit 0a834b7
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 23 deletions.
5 changes: 3 additions & 2 deletions Example/NativeUIExample/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<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">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16086"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
Expand All @@ -28,6 +28,7 @@
<segments>
<segment title="Default"/>
<segment title="Custom Content"/>
<segment title="System"/>
</segments>
</segmentedControl>
</subviews>
Expand Down
15 changes: 15 additions & 0 deletions Example/NativeUIExample/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ final class ViewController: UIViewController {
enum Appearance: Int {
case `default` = 0
case custom = 1
case system = 2
}

@IBOutlet private var segmentedControl: UISegmentedControl!
Expand Down Expand Up @@ -53,6 +54,20 @@ final class ViewController: UIViewController {
)
let alert = AlertViewController(viewModel: viewModel)
present(alert, animated: true)

case .system:
let cancelAction = UIAlertAction(title: "Cancel", style: .default)
let confirmAction = UIAlertAction(title: "Confirm", style: .default)

let alert = UIAlertController(
title: "Your Title",
message: "Your Message",
preferredStyle: .alert
)
alert.addAction(cancelAction)
alert.addAction(confirmAction)

present(alert, animated: true)
}
}
}
14 changes: 7 additions & 7 deletions Example/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
PODS:
- NativeUI (0.0.3):
- NativeUI/Core (= 0.0.3)
- NativeUI/Alert (0.0.3):
- NativeUI (1.0.1):
- NativeUI/Core (= 1.0.1)
- NativeUI/Alert (1.0.1):
- NativeUI/Utils
- NativeUI/Core (0.0.3):
- NativeUI/Core (1.0.1):
- NativeUI/Alert
- NativeUI/Utils (0.0.3)
- NativeUI/Utils (1.0.1)

DEPENDENCIES:
- NativeUI (from `../`)
Expand All @@ -15,8 +15,8 @@ EXTERNAL SOURCES:
:path: "../"

SPEC CHECKSUMS:
NativeUI: d89eeb004dd445bb67bef1579be654edffdd7a2e
NativeUI: 6de137806356923678e5b124502c00246ed8a14a

PODFILE CHECKSUM: bb46d7bf1ae3b119e00a9331a12cd0a4b5cac170

COCOAPODS: 1.9.1
COCOAPODS: 1.9.3
2 changes: 1 addition & 1 deletion NativeUI.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "NativeUI"
s.version = "1.0.0"
s.version = "1.0.1"
s.summary = "Library that includes customizable replacements for native UIKit components"

s.description = <<-DESC
Expand Down
2 changes: 1 addition & 1 deletion NativeUI.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@
3AB073CE243A017A0092DF66 /* Alert.swift */,
3AB073D1243A017A0092DF66 /* AlertViewController.swift */,
3AB073D0243A017A0092DF66 /* AlertView.swift */,
3AB073CD243A017A0092DF66 /* AlertPresentationAnimator.swift */,
3AB073CF243A017A0092DF66 /* AlertActionSequenceView.swift */,
3AB073CD243A017A0092DF66 /* AlertPresentationAnimator.swift */,
);
path = Alert;
sourceTree = "<group>";
Expand Down
20 changes: 18 additions & 2 deletions NativeUI/Sources/Alert/Alert.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import UIKit

public struct Alert {
public struct Action {
public final class Action {
public typealias Handler = (Alert.Action) -> Void

public enum Style {
Expand All @@ -19,11 +19,19 @@ public struct Alert {
}
public let title: String
public let style: Style
public var isEnabled: Bool {
didSet {
actionStateHandler?(isEnabled)
}
}
public let handler: Handler?

public init(title: String, style: Style, handler: Handler? = nil) {
var actionStateHandler: ((Bool) -> Void)?

public init(title: String, style: Style, isEnabled: Bool = true, handler: Handler? = nil) {
self.title = title
self.style = style
self.isEnabled = isEnabled
self.handler = handler
}
}
Expand All @@ -42,17 +50,21 @@ public struct Alert {

public let tintColor: UIColor?

public let disabledTintColor: UIColor?

public let actions: [Action]

public init(title: Text?,
message: Text?,
contentView: UIView? = nil,
tintColor: UIColor? = nil,
disabledTintColor: UIColor? = nil,
actions: [Action]) {
self.title = title
self.message = message
self.contentView = contentView
self.tintColor = tintColor
self.disabledTintColor = disabledTintColor
self.actions = actions
}

Expand All @@ -62,23 +74,27 @@ public struct Alert {
messageFont: UIFont = UIFont.systemFont(ofSize: 13, weight: .regular),
contentView: UIView? = nil,
tintColor: UIColor? = nil,
disabledTintColor: UIColor? = nil,
actions: [Action]) {
self.init(title: title.map { .string($0, titleFont) },
message: message.map { .string($0, messageFont) },
contentView: contentView,
tintColor: tintColor,
disabledTintColor: disabledTintColor,
actions: actions)
}

public init(title: NSAttributedString?,
message: NSAttributedString?,
contentView: UIView? = nil,
tintColor: UIColor? = nil,
disabledTintColor: UIColor? = nil,
actions: [Action]) {
self.init(title: title.map { .attributedString($0) },
message: message.map { .attributedString($0) },
contentView: contentView,
tintColor: tintColor,
disabledTintColor: disabledTintColor,
actions: actions)
}
}
36 changes: 26 additions & 10 deletions NativeUI/Sources/Alert/AlertActionSequenceView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ protocol AlertActionSequenceViewDelegate: AnyObject {

struct AlertActionSequenceViewModel {
let actions: [Alert.Action]
let disabledTintColor: UIColor?
let separatorColor: UIColor
let separatorWidth: CGFloat
}
Expand All @@ -34,6 +35,8 @@ final class AlertActionSequenceView: UIControl {
}
}

var isEnabled: Bool = true

private(set) lazy var titleLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
Expand Down Expand Up @@ -104,15 +107,15 @@ final class AlertActionSequenceView: UIControl {
}

if let action = viewModel.actions.first {
let actionView = makeActionView(for: action)
let actionView = makeActionView(for: action, disabledTintColor: viewModel.disabledTintColor)
stackView.addArrangedSubview(actionView)
}

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

let actionView = makeActionView(for: action)
let actionView = makeActionView(for: action, disabledTintColor: viewModel.disabledTintColor)
stackView.addArrangedSubview(actionView)

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

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

updateAppearance(for: actionView, action: action, disabledTintColor: disabledTintColor)

action.actionStateHandler = { [weak actionView, weak action, weak self] isEnabled in
guard let actionView = actionView, let action = action else { return }
self?.updateAppearance(for: actionView, action: action, disabledTintColor: disabledTintColor)
}

return actionView
}

private func updateAppearance(for actionView: ActionView, action: Alert.Action, disabledTintColor: UIColor?) {
actionView.isEnabled = action.isEnabled
actionView.titleLabel.text = action.title

let disabledTintColor = disabledTintColor ?? UIColor(white: 0.48, alpha: 0.8)

switch action.style {
case .default:
actionView.titleLabel.font = UIFont.systemFont(ofSize: 17, weight: .regular)
actionView.titleLabel.textColor = tintColor
actionView.titleLabel.textColor = action.isEnabled ? tintColor : disabledTintColor
case .primary:
actionView.titleLabel.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
actionView.titleLabel.textColor = tintColor
actionView.titleLabel.textColor = action.isEnabled ? tintColor : disabledTintColor
case let .custom(font, textColor):
actionView.titleLabel.font = font
actionView.titleLabel.textColor = textColor
actionView.titleLabel.textColor = action.isEnabled ? textColor : disabledTintColor
}

return actionView
}

private func makeButtonSeparatorView(viewModel: AlertActionSequenceViewModel) -> UIView {
Expand Down Expand Up @@ -189,7 +204,7 @@ final class AlertActionSequenceView: UIControl {
guard let actionViewFrame = actionView.superview?.convert(actionView.frame, to: self) else {
continue
}
let isHighlighted = actionViewFrame.contains(point)
let isHighlighted = actionViewFrame.contains(point) && actionView.isEnabled
actionView.isHighlighted = isHighlighted

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

@objc private func handleTap(on actionView: ActionView) {
let index = stackView.arrangedSubviews
.filter { $0 is ActionView }
.compactMap { $0 as? ActionView }
.filter { $0.isEnabled }
.firstIndex(where: { $0 === actionView })

if let index = index {
Expand Down
1 change: 1 addition & 0 deletions NativeUI/Sources/Alert/AlertView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ final class AlertView: UIView {

let actionsViewModel = AlertActionSequenceViewModel(
actions: viewModel.actions,
disabledTintColor: viewModel.disabledTintColor,
separatorColor: separatorColor,
separatorWidth: Layout.separatorThickness
)
Expand Down

0 comments on commit 0a834b7

Please sign in to comment.