Skip to content

Commit

Permalink
Make automatic closing of action button configurable (jjochen#231)
Browse files Browse the repository at this point in the history
* Make automatic closing of action button configurable

* improve related tests in JJFloatingActionButtonSpec
  • Loading branch information
jjochen authored and zalexej committed Mar 6, 2020
1 parent da38c28 commit 6718b81
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 24 deletions.
101 changes: 79 additions & 22 deletions Example/Tests/JJFloatingActionButtonSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ class JJFloatingActionButtonSpec: QuickSpec {

it("does not open") {
actionButton.open(animated: false)
expect(actionButton.buttonState).to(equal(JJFloatingActionButtonState.closed))
expect(actionButton.buttonState) == .closed
}

it("does not open when tapped") {
actionButton.sendActions(for: .touchUpInside)
expect(actionButton.buttonState).toNotEventually(equal(JJFloatingActionButtonState.open))
expect(actionButton.buttonState) == .closed
}

it("looks correct by default") {
Expand Down Expand Up @@ -206,14 +206,15 @@ class JJFloatingActionButtonSpec: QuickSpec {

it("opens when tapped") {
actionButton.sendActions(for: .touchUpInside)
expect(actionButton.buttonState).toEventually(equal(JJFloatingActionButtonState.open))
expect(actionButton.buttonState) == .opening
expect(actionButton.buttonState).toEventually(equal(.open))
}

it("opens when tapped twice") {
actionButton.sendActions(for: .touchUpInside)
actionButton.sendActions(for: .touchUpInside)
expect(actionButton.buttonState).toEventually(equal(JJFloatingActionButtonState.opening))
expect(actionButton.buttonState).toEventually(equal(JJFloatingActionButtonState.open))
expect(actionButton.buttonState) == .opening
expect(actionButton.buttonState).toEventually(equal(.open))
}

context("and is opened") {
Expand All @@ -222,7 +223,7 @@ class JJFloatingActionButtonSpec: QuickSpec {
}

it("has state open") {
expect(actionButton.buttonState) == JJFloatingActionButtonState.open
expect(actionButton.buttonState) == .open
}

it("items look correct") {
Expand All @@ -246,7 +247,7 @@ class JJFloatingActionButtonSpec: QuickSpec {

it("can't be opened again") {
actionButton.open(animated: true)
expect(actionButton.buttonState) != JJFloatingActionButtonState.opening
expect(actionButton.buttonState) != .opening
}

context("and overlay is tapped") {
Expand All @@ -255,7 +256,8 @@ class JJFloatingActionButtonSpec: QuickSpec {
}

it("closes") {
expect(actionButton.buttonState).toEventually(equal(JJFloatingActionButtonState.closed))
expect(actionButton.buttonState) == .closing
expect(actionButton.buttonState).toEventually(equal(.closed))
}
}

Expand All @@ -265,11 +267,13 @@ class JJFloatingActionButtonSpec: QuickSpec {
}

it("closes") {
expect(actionButton.buttonState).toEventually(equal(JJFloatingActionButtonState.closed))
expect(actionButton.buttonState) == .closing
expect(actionButton.buttonState).toEventually(equal(.closed))
}

it("does not perform action") {
expect(action).toNotEventually(equal("done!"))
waitUntil(timeout: 1.5)
expect(action) != "done!"
}
}

Expand All @@ -280,13 +284,57 @@ class JJFloatingActionButtonSpec: QuickSpec {
}

it("closes") {
expect(actionButton.buttonState).toEventually(equal(JJFloatingActionButtonState.closed))
expect(actionButton.buttonState) == .closing
expect(actionButton.buttonState).toEventually(equal(.closed))
}

it("performs action") {
expect(action).toEventually(equal("done!"))
}
}

context("with closeAutomatically disabled") {
beforeEach {
actionButton.closeAutomatically = false
}

context("and item is tapped") {
beforeEach {
let item = actionButton.items[0]
item.sendActions(for: .touchUpInside)
}

it("stays open") {
expect(actionButton.buttonState) == .open
}

it("performs action") {
expect(action).toEventually(equal("done!"))
}
}
}

context("with closeAutomatically enabled") {
beforeEach {
actionButton.closeAutomatically = true
}

context("and item is tapped") {
beforeEach {
let item = actionButton.items[0]
item.sendActions(for: .touchUpInside)
}

it("closes") {
expect(actionButton.buttonState) == .closing
expect(actionButton.buttonState).toEventually(equal(.closed))
}

it("performs action") {
expect(action).toEventually(equal("done!"))
}
}
}
}

context("and is opened and closed") {
Expand All @@ -301,7 +349,7 @@ class JJFloatingActionButtonSpec: QuickSpec {

it("can't be closed again") {
actionButton.close(animated: true)
expect(actionButton.buttonState) != JJFloatingActionButtonState.closing
expect(actionButton.buttonState) != .closing
}
}

Expand All @@ -311,11 +359,11 @@ class JJFloatingActionButtonSpec: QuickSpec {
}

it("has state opening") {
expect(actionButton.buttonState) == JJFloatingActionButtonState.opening
expect(actionButton.buttonState) == .opening
}

it("has eventually state open") {
expect(actionButton.buttonState).toEventually(equal(JJFloatingActionButtonState.open))
expect(actionButton.buttonState).toEventually(equal(.open))
}
}

Expand All @@ -326,11 +374,11 @@ class JJFloatingActionButtonSpec: QuickSpec {
}

it("has state closing") {
expect(actionButton.buttonState) == JJFloatingActionButtonState.closing
expect(actionButton.buttonState) == .closing
}

it("has eventually state closed") {
expect(actionButton.buttonState).toEventually(equal(JJFloatingActionButtonState.closed))
expect(actionButton.buttonState).toEventually(equal(.closed))
}
}

Expand Down Expand Up @@ -392,8 +440,8 @@ class JJFloatingActionButtonSpec: QuickSpec {
actionButton.sendActions(for: .touchUpInside)
}

it("does not open") {
expect(actionButton.buttonState).toNotEventually(equal(JJFloatingActionButtonState.open))
it("stays closed") {
expect(actionButton.buttonState) == .closed
}

it("performs action") {
Expand All @@ -407,7 +455,7 @@ class JJFloatingActionButtonSpec: QuickSpec {
}

it("has state closed") {
expect(actionButton.buttonState) == JJFloatingActionButtonState.closed
expect(actionButton.buttonState) == .closed
}

it("looks correct") {
Expand All @@ -422,7 +470,7 @@ class JJFloatingActionButtonSpec: QuickSpec {
}

it("opens") {
expect(actionButton.buttonState) == JJFloatingActionButtonState.open
expect(actionButton.buttonState) == .open
}

it("looks correct") {
Expand All @@ -446,9 +494,9 @@ class JJFloatingActionButtonSpec: QuickSpec {
actionButton.addItem(title: "item 2", image: #imageLiteral(resourceName: "Baloon").withRenderingMode(.alwaysTemplate))
}

it("does not open when tapped") {
it("stays closed") {
actionButton.sendActions(for: .touchUpInside)
expect(actionButton.buttonState).toNotEventually(equal(JJFloatingActionButtonState.open))
expect(actionButton.buttonState) == .closed
}
}
}
Expand Down Expand Up @@ -519,3 +567,12 @@ class JJFloatingActionButtonSpec: QuickSpec {
}
}
}

func waitUntil(timeout: TimeInterval = AsyncDefaults.Timeout) {
waitUntil(timeout: timeout + 1, action: { done in
DispatchQueue.global().async {
Thread.sleep(forTimeInterval: timeout)
done()
}
})
}
15 changes: 13 additions & 2 deletions Sources/JJFloatingActionButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ import UIKit
@objc public var itemAnimationConfiguration: JJItemAnimationConfiguration = .popUp()

/// When enabled and only one action item is added, the floating action button will not open,
/// but the action from the action item will be executed direclty when the button is tapped.
/// but the action from the action item will be executed directly when the button is tapped.
/// Also the image of the floating action button will be replaced with the one from the action item.
///
/// Default is `true`.
Expand All @@ -173,6 +173,15 @@ import UIKit
}
}

/// When enabled, the floating action button will close after an action item was tapped,
/// otherwise the action button will stay open and has to be closed explicitly.
///
/// Default is `true`.
///
/// - SeeAlso: `close`
///
@objc @IBInspectable public var closeAutomatically: Bool = true

/// The current state of the floating action button.
/// Possible values are
/// - `.opening`
Expand Down Expand Up @@ -526,7 +535,9 @@ fileprivate extension JJFloatingActionButton {
}

@objc func itemWasTapped(sender: JJActionItem) {
close()
if closeAutomatically {
close()
}
sender.callAction()
}

Expand Down

0 comments on commit 6718b81

Please sign in to comment.