Skip to content

Commit

Permalink
Merge pull request #35 from 3sidedcube/release/v2.2.0
Browse files Browse the repository at this point in the history
Release/v2.2.0
  • Loading branch information
BenShutt authored Aug 26, 2021
2 parents 07d8d56 + f2a0c56 commit 581cc2e
Show file tree
Hide file tree
Showing 21 changed files with 473 additions and 96 deletions.
2 changes: 1 addition & 1 deletion Example/ViewControllers/MessageViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class MessageViewController: UIViewController {

private lazy var messageStackView: MessageStackView = {
let messageStackView: MessageStackView = view.createMessageStackView()
messageStackView.messageConfiguation = MessageConfiguration(
messageStackView.messageConfiguration = MessageConfiguration(
backgroundColor: .systemGroupedBackground,
tintColor: .gray,
shadow: true,
Expand Down
3 changes: 2 additions & 1 deletion Example/ViewControllers/RootTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ class RootTableViewController: UITableViewController {
("Badge Message", BadgeMessageViewController.self, false),
("Message", MessageViewController.self, false),
("No Internet", NoInternetTabBarController.self, true),
("Shadow", ShadowViewController.self, false)
("Shadow", ShadowViewController.self, false),
("Toast", ToastViewController.self, false)
]

// MARK: - ViewController lifecycle
Expand Down
102 changes: 102 additions & 0 deletions Example/ViewControllers/ToastViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//
// ToastViewController.swift
// Example
//
// Created by Ben Shutt on 02/06/2021.
// Copyright © 2021 3 SIDED CUBE APP PRODUCTIONS LTD. All rights reserved.
//

import Foundation
import UIKit
import MessageStackView

/// `UIViewController` to test `Toast`
class ToastViewController: UIViewController {

/// `Toast` to post at the bottom of the screen
private lazy var toast = Toast()

/// `UIButton` to add to bottom to make sure it can be clicked when the toast is slowing
private lazy var button: UIButton = {
let button = UIButton()
button.setTitle(.buttonTitleClick, for: .normal)
button.setTitleColor(.systemBlue, for: .normal)
button.addTarget(
self,
action: #selector(buttonTouchUpInside),
for: .touchUpInside
)
return button
}()

// MARK: - ViewController lifecycle

override func viewDidLoad() {
super.viewDidLoad()

addButtonToBottomLeading()
addAndConstrainToast(toast)
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

toast.post(message: .shortMessage)
toast.postIfNotShowing(message: .shortMessage) // Shouldn't show
toast.post(message: .longMessage)
}

// MARK: - Subviews

private func addButtonToBottomLeading() {
view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
button.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 25),
button.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -15)
])
}

// MARK: - Actions

/// `sender` received `.touchUpInside` `UIControl.Event`
///
/// - Parameter sender: `UIButton` that invoked the action
@objc
private func buttonTouchUpInside(_ sender: UIButton) {
UIView.animate(
withDuration: 0.5,
delay: 0,
options: [.autoreverse],
animations: {
sender.setTitle(.buttonTitleClicked, for: .normal)
sender.transform = CGAffineTransform(scaleX: 2, y: 2)
}, completion: { _ in
sender.transform = .identity
sender.setTitle(.buttonTitleClick, for: .normal)
}
)
}
}

// MARK: - String + Text

private extension String {

static let buttonTitleClick = """
Click Me
"""

static let buttonTitleClicked = """
Clicked!
"""

static let shortMessage = """
This is a toast!
"""

static let longMessage = """
This is a long toast to test how the text wraps when the width \
of the text is greater than the width of the screen
"""
}
34 changes: 29 additions & 5 deletions MessageStackView.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
B81AEE5024FFF27A0068CE23 /* ShadowLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B81AEE4F24FFF27A0068CE23 /* ShadowLayer.swift */; };
B81AEE5224FFFB2E0068CE23 /* ParentShadowLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B81AEE5124FFFB2E0068CE23 /* ParentShadowLayer.swift */; };
B81AEE5425003F270068CE23 /* ShadowViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B81AEE5325003F270068CE23 /* ShadowViewController.swift */; };
B82405672668F6A200E4178B /* EdgeLayoutGuide.swift in Sources */ = {isa = PBXBuildFile; fileRef = B82405662668F6A200E4178B /* EdgeLayoutGuide.swift */; };
B83CACB12667D5CE008FB755 /* Order.swift in Sources */ = {isa = PBXBuildFile; fileRef = B83CACB02667D5CE008FB755 /* Order.swift */; };
B83CACB32667D97E008FB755 /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = B83CACB22667D97E008FB755 /* Toast.swift */; };
B83CACB52667DA8A008FB755 /* ToastViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B83CACB42667DA8A008FB755 /* ToastViewController.swift */; };
B872BE8725A3874C0031D619 /* UIImageView+Hidden.swift in Sources */ = {isa = PBXBuildFile; fileRef = B872BE8625A3874C0031D619 /* UIImageView+Hidden.swift */; };
B872BE9125A387570031D619 /* UILabel+Hidden.swift in Sources */ = {isa = PBXBuildFile; fileRef = B872BE9025A387570031D619 /* UILabel+Hidden.swift */; };
B875C98925126EB200FA05B5 /* UIViewController+System.swift in Sources */ = {isa = PBXBuildFile; fileRef = B875C98825126EB200FA05B5 /* UIViewController+System.swift */; };
Expand Down Expand Up @@ -172,6 +176,10 @@
B81AEE4F24FFF27A0068CE23 /* ShadowLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShadowLayer.swift; sourceTree = "<group>"; };
B81AEE5124FFFB2E0068CE23 /* ParentShadowLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParentShadowLayer.swift; sourceTree = "<group>"; };
B81AEE5325003F270068CE23 /* ShadowViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShadowViewController.swift; sourceTree = "<group>"; };
B82405662668F6A200E4178B /* EdgeLayoutGuide.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EdgeLayoutGuide.swift; sourceTree = "<group>"; };
B83CACB02667D5CE008FB755 /* Order.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Order.swift; sourceTree = "<group>"; };
B83CACB22667D97E008FB755 /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = "<group>"; };
B83CACB42667DA8A008FB755 /* ToastViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastViewController.swift; sourceTree = "<group>"; };
B872BE8625A3874C0031D619 /* UIImageView+Hidden.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageView+Hidden.swift"; sourceTree = "<group>"; };
B872BE9025A387570031D619 /* UILabel+Hidden.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+Hidden.swift"; sourceTree = "<group>"; };
B875C98825126EB200FA05B5 /* UIViewController+System.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+System.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -313,6 +321,18 @@
path = Shadow;
sourceTree = "<group>";
};
B82405682668F8EB00E4178B /* UIView */ = {
isa = PBXGroup;
children = (
OBJ_25 /* UIView+Animation.swift */,
OBJ_26 /* UIView+Extensions.swift */,
OBJ_28 /* UIView+SafeArea.swift */,
OBJ_29 /* UIView+Shadow.swift */,
OBJ_30 /* UIView+ShadowComponents.swift */,
);
path = UIView;
sourceTree = "<group>";
};
B872BE8525A3873F0031D619 /* Hidden */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -369,6 +389,7 @@
B8BB087924C4BC46000E2E87 /* MessageViewController.swift */,
B87CC99C24CC263E002B697C /* NoInternetTabBarController.swift */,
B81AEE5325003F270068CE23 /* ShadowViewController.swift */,
B83CACB42667DA8A008FB755 /* ToastViewController.swift */,
);
path = ViewControllers;
sourceTree = "<group>";
Expand Down Expand Up @@ -414,6 +435,7 @@
OBJ_13 /* CenterConstraints.swift */,
OBJ_14 /* Constrainable.swift */,
OBJ_15 /* EdgeConstraints.swift */,
B82405662668F6A200E4178B /* EdgeLayoutGuide.swift */,
OBJ_16 /* MessageLayout.swift */,
OBJ_17 /* SizeConstraints.swift */,
);
Expand All @@ -423,18 +445,14 @@
OBJ_18 /* Extensions */ = {
isa = PBXGroup;
children = (
B82405682668F8EB00E4178B /* UIView */,
B872BE8525A3873F0031D619 /* Hidden */,
OBJ_19 /* CALayer+Animation.swift */,
OBJ_20 /* CGRect+Extensions.swift */,
OBJ_21 /* DispatchQueue+Extensions.swift */,
OBJ_22 /* String+Extensions.swift */,
OBJ_23 /* UIApplication+StatusBar.swift */,
OBJ_24 /* UIEdgeInsets+Extensions.swift */,
OBJ_25 /* UIView+Animation.swift */,
OBJ_26 /* UIView+Extensions.swift */,
OBJ_28 /* UIView+SafeArea.swift */,
OBJ_29 /* UIView+Shadow.swift */,
OBJ_30 /* UIView+ShadowComponents.swift */,
B87CC94B24C9F5A3002B697C /* Array+Extensions.swift */,
B8BCDA8424CD8EB10067F26C /* UIApplication+KeyWindow.swift */,
B81AEE4B24FFEE520068CE23 /* FloatingPoint+Equals.swift */,
Expand Down Expand Up @@ -519,6 +537,7 @@
OBJ_54 /* PostAnimation.swift */,
OBJ_55 /* Queue.swift */,
B80B92AA2527324400F97364 /* Vector3.swift */,
B83CACB02667D5CE008FB755 /* Order.swift */,
);
path = Models;
sourceTree = "<group>";
Expand Down Expand Up @@ -595,6 +614,7 @@
OBJ_74 /* MessageStackView.swift */,
OBJ_75 /* PostView.swift */,
B8F1C76224D8198E007C2712 /* ApplicationPostView.swift */,
B83CACB22667D97E008FB755 /* Toast.swift */,
);
path = PostView;
sourceTree = "<group>";
Expand Down Expand Up @@ -812,6 +832,7 @@
B8BB088424C4BC46000E2E87 /* WindowViewController.swift in Sources */,
B8BB088724C4BC46000E2E87 /* MessageViewController.swift in Sources */,
B8BB088224C4BC46000E2E87 /* RootTableViewController.swift in Sources */,
B83CACB52667DA8A008FB755 /* ToastViewController.swift in Sources */,
B87CC99D24CC263E002B697C /* NoInternetTabBarController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -854,6 +875,7 @@
OBJ_99 /* DispatchQueue+Extensions.swift in Sources */,
OBJ_100 /* String+Extensions.swift in Sources */,
OBJ_101 /* UIApplication+StatusBar.swift in Sources */,
B83CACB32667D97E008FB755 /* Toast.swift in Sources */,
OBJ_102 /* UIEdgeInsets+Extensions.swift in Sources */,
OBJ_103 /* UIView+Animation.swift in Sources */,
B8BCDA8C24CDB55B0067F26C /* UIViewController+Lifecycle.m in Sources */,
Expand All @@ -874,8 +896,10 @@
B8F1C76324D8198E007C2712 /* ApplicationPostView.swift in Sources */,
B81727F024D6CC9F0062282B /* PostViewController.swift in Sources */,
B8E1CEEF2500F88C002BFE77 /* NeuomorphicShadow.swift in Sources */,
B83CACB12667D5CE008FB755 /* Order.swift in Sources */,
OBJ_115 /* BadgeMessageView.swift in Sources */,
OBJ_116 /* BadgeMessageViewable.swift in Sources */,
B82405672668F6A200E4178B /* EdgeLayoutGuide.swift in Sources */,
OBJ_117 /* Poster+BadgeMessage.swift in Sources */,
OBJ_118 /* Message.swift in Sources */,
B81AEE4E24FFF2650068CE23 /* ShadowView.swift in Sources */,
Expand Down
18 changes: 12 additions & 6 deletions Sources/Constraints/EdgeConstraints.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,26 +64,32 @@ struct EdgeConstraints: Constrainable {

extension UIView {

/// Construct `EdgeConstraints` `NSLayoutConstraint`s from
/// `self` to `view`
/// Construct `EdgeConstraints` `NSLayoutConstraint`s from `self` to `view`
///
/// - Parameters:
/// - view: `UIView` to constrain to
/// - insets: `UIEdgeInsets` to inset
/// - safeAreaLayoutGuide: `Bool` constrain to `view`'s `safeAreaLayoutGuide`
/// - activate: Activate the `NSLayoutConstraint`s
@discardableResult
func edgeConstraints(
to view: UIView,
insets: UIEdgeInsets = .zero,
safeAreaLayoutGuide: Bool = false,
activate: Bool = true
) -> EdgeConstraints {
translatesAutoresizingMaskIntoConstraints = false

// `EdgeLayoutGuide` of `view` to constrain `self` to
let viewLayoutGuide: EdgeLayoutGuide =
safeAreaLayoutGuide ? view.safeAreaLayoutGuide : view

// Create `NSLayoutConstraint`s to the edge anchors
var edgeConstraints = EdgeConstraints(
leading: leadingAnchor.constraint(equalTo: view.leadingAnchor),
top: topAnchor.constraint(equalTo: view.topAnchor),
trailing: trailingAnchor.constraint(equalTo: view.trailingAnchor),
bottom: bottomAnchor.constraint(equalTo: view.bottomAnchor)
leading: leadingAnchor.constraint(equalTo: viewLayoutGuide.leadingAnchor),
top: topAnchor.constraint(equalTo: viewLayoutGuide.topAnchor),
trailing: trailingAnchor.constraint(equalTo: viewLayoutGuide.trailingAnchor),
bottom: bottomAnchor.constraint(equalTo: viewLayoutGuide.bottomAnchor)
)

// Set `UIEdgeInsets` as provided
Expand Down
33 changes: 33 additions & 0 deletions Sources/Constraints/EdgeLayoutGuide.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// LayoutGuide.swift
// MessageStackView
//
// Created by Ben Shutt on 03/06/2021.
// Copyright © 2021 3 SIDED CUBE APP PRODUCTIONS LTD. All rights reserved.
//

import Foundation

/// Edge layout guide
protocol EdgeLayoutGuide {

/// Leading anchor in X
var leadingAnchor: NSLayoutXAxisAnchor { get }

/// Top anchor in Y
var topAnchor: NSLayoutYAxisAnchor { get }

/// Trailing anchor in X
var trailingAnchor: NSLayoutXAxisAnchor { get }

/// Bottom anchor in Y
var bottomAnchor: NSLayoutYAxisAnchor { get }
}

// MARK: - UIView + EdgeLayoutGuide

extension UIView: EdgeLayoutGuide {}

// MARK: - UILayoutGuide + EdgeLayoutGuide

extension UILayoutGuide: EdgeLayoutGuide {}
19 changes: 17 additions & 2 deletions Sources/Constraints/MessageLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,27 @@ public enum MessageLayout: Int {
case bottom
}

// MARK: - Order

public extension MessageLayout {

/// Map to `Order`
func toOrder() -> Order {
switch self {
case .top: return .topToBottom
case .bottom: return .bottomToTop
}
}
}

// MARK: - NSLayoutConstraint

public extension MessageLayout {

/// Constrain `subview` to `superview` based on `self` (`MessageLayout`).
/// - Parameters:
/// - subview: `UIView` to add as a subview to `superview`
/// - superview: `UIView` superivew of `subview`
/// - superview: `UIView` superview of `subview`
/// - safeAnchors: Constrain to safe anchors
func constrain(
subview: UIView,
Expand Down Expand Up @@ -100,7 +113,9 @@ public extension UIView {

// Constrain `self`
layout.constrain(
subview: self, to: view, safeAnchors: constrainToSafeArea
subview: self,
to: view,
safeAnchors: constrainToSafeArea
)

// Trigger a layout cycle
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
35 changes: 35 additions & 0 deletions Sources/Models/Order.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// Order.swift
// MessageStackView
//
// Created by Ben Shutt on 02/06/2021.
// Copyright © 2021 3 SIDED CUBE APP PRODUCTIONS LTD. All rights reserved.
//

import Foundation

/// How posted `UIView`s are ordered.
/// E.g. the order of the `arrangedSubviews`.
public enum Order {

/// Natural order of `UIStackView`s. Posted `UIView`s get appended to the
/// `arrangedSubviews` array appearing below/after the previous.
case topToBottom

/// Reverse order of `UIStackView`s. Posted `UIView`s get inserted at the start of the
/// `arrangedSubviews` array appearing above/before the previous.
case bottomToTop
}

// MARK: - Extensions

public extension Order {

/// Other `Order` (opposite direction)
var switched: Self {
switch self {
case .topToBottom: return .bottomToTop
case .bottomToTop: return .topToBottom
}
}
}
Loading

0 comments on commit 581cc2e

Please sign in to comment.