Skip to content

Commit

Permalink
Add handlers and update docs (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
omaralbeik authored Oct 13, 2021
1 parent 04c9602 commit 6b92e72
Show file tree
Hide file tree
Showing 16 changed files with 424 additions and 121 deletions.
2 changes: 1 addition & 1 deletion Drops.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Drops'
s.version = '1.3.0'
s.version = '1.4.0'
s.summary = 'A µFramework for showing iOS 13 like system alerts'
s.description = <<-DESC
A µFramework for showing alerts like the one used when copying from pasteboard or connecting Apple pencil.
Expand Down
4 changes: 2 additions & 2 deletions Drops.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 1.3.0;
MARKETING_VERSION = 1.4.0;
PRODUCT_BUNDLE_IDENTIFIER = com.omaralbeik.drops;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
Expand Down Expand Up @@ -803,7 +803,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 1.3.0;
MARKETING_VERSION = 1.4.0;
PRODUCT_BUNDLE_IDENTIFIER = com.omaralbeik.drops;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ The [Swift Package Manager](https://swift.org/package-manager/) is a tool for ma

```swift
dependencies: [
.package(url: "https://github.com/omaralbeik/Drops.git", from: "1.3.0")
.package(url: "https://github.com/omaralbeik/Drops.git", from: "1.4.0")
]
```

Expand All @@ -134,7 +134,7 @@ $ swift build
To integrate Drops into your Xcode project using [CocoaPods](https://cocoapods.org), specify it in your Podfile:

```rb
pod 'Drops', :git => 'https://github.com/omaralbeik/Drops.git', :tag => '1.3.0'
pod 'Drops', :git => 'https://github.com/omaralbeik/Drops.git', :tag => '1.4.0'
```

### Carthage
Expand Down
12 changes: 7 additions & 5 deletions Sources/Drop.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,17 @@

import UIKit

@available(iOSApplicationExtension, unavailable)
/// An object representing a drop.
@available(iOSApplicationExtension, unavailable)
public struct Drop: ExpressibleByStringLiteral {
/// Create a new drop.
/// - Parameters:
/// - title: Title.
/// - titleNumberOfLines: Maximum number of lines that `title` can occupy. Defaults to `1`. A value of 0 means no limit.
/// - titleNumberOfLines: Maximum number of lines that `title` can occupy. Defaults to `1`.
/// A value of 0 means no limit.
/// - subtitle: Optional subtitle. Defaults to `nil`.
/// - subtitleNumberOfLines: Maximum number of lines that `subtitle` can occupy. Defaults to `1`. A value of 0 means no limit.
/// - subtitleNumberOfLines: Maximum number of lines that `subtitle` can occupy. Defaults to `1`.
/// A value of 0 means no limit.
/// - icon: Optional icon.
/// - action: Optional action.
/// - position: Position. Defaults to `Drop.Position.top`.
Expand Down Expand Up @@ -75,13 +77,13 @@ public struct Drop: ExpressibleByStringLiteral {

/// Title.
public var title: String

/// Maximum number of lines that `title` can occupy. Defaults to `1`. A value of 0 means no limit.
public var titleNumberOfLines: Int

/// Subtitle.
public var subtitle: String?

/// Maximum number of lines that `subtitle` can occupy. Defaults to `1`. A value of 0 means no limit.
public var subtitleNumberOfLines: Int

Expand Down
47 changes: 44 additions & 3 deletions Sources/Drops.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@

import UIKit

typealias AnimationCompletion = (_ completed: Bool) -> Void
internal typealias AnimationCompletion = (_ completed: Bool) -> Void

@available(iOSApplicationExtension, unavailable)
/// A shared class used to show and hide drops.
@available(iOSApplicationExtension, unavailable)
public final class Drops {
/// Handler.
public typealias DropHandler = (Drop) -> Void

// MARK: - Static

Expand All @@ -49,6 +51,30 @@ public final class Drops {
shared.hideAll()
}

/// A handler to be called before a drop is presented.
public static var willShowDrop: DropHandler? {
get { shared.willShowDrop }
set { shared.willShowDrop = newValue }
}

/// A handler to be called after a drop is presented.
public static var didShowDrop: DropHandler? {
get { shared.didShowDrop }
set { shared.didShowDrop = newValue }
}

/// A handler to be called before a drop is dismissed.
public static var willDismissDrop: DropHandler? {
get { shared.willDismissDrop }
set { shared.willDismissDrop = newValue }
}

/// A handler to be called after a drop is dismissed.
public static var didDismissDrop: DropHandler? {
get { shared.didDismissDrop }
set { shared.didDismissDrop = newValue }
}

// MARK: - Instance

/// Create a new instance with a custom delay between drops.
Expand All @@ -69,10 +95,12 @@ public final class Drops {
/// Hide currently shown drop.
public func hideCurrent() {
guard let current = current, !current.isHiding else { return }
willDismissDrop?(current.drop)
DispatchQueue.main.async {
current.hide(animated: true) { [weak self] completed in
guard completed, let self = self else { return }
self.dispatchQueue.sync {
self.didDismissDrop?(current.drop)
guard self.current === current else { return }
self.current = nil
}
Expand All @@ -88,6 +116,18 @@ public final class Drops {
}
}

/// A handler to be called before a drop is presented.
public var willShowDrop: DropHandler?

/// A handler to be called after a drop is presented.
public var didShowDrop: DropHandler?

/// A handler to be called before a drop is dismissed.
public var willDismissDrop: DropHandler?

/// A handler to be called after a drop is dismissed.
public var didDismissDrop: DropHandler?

// MARK: - Helpers

let delayBetweenDrops: TimeInterval
Expand Down Expand Up @@ -128,8 +168,9 @@ public final class Drops {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
guard let current = self.current else { return }

self.willShowDrop?(current.drop)
current.show { completed in
self.didShowDrop?(current.drop)
guard completed else {
self.dispatchQueue.sync {
self.hide(presenter: current)
Expand Down
4 changes: 2 additions & 2 deletions Tests/DropViewTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,13 @@ final class DropViewTests: XCTestCase {

waitForExpectations(timeout: 1)
}

func testLabelNumberOfLines() {
let drop1 = Drop(title: "Title")
let view1 = DropView(drop: drop1)
XCTAssertEqual(view1.titleLabel.numberOfLines, 1)
XCTAssertEqual(view1.subtitleLabel.numberOfLines, 1)

let drop2 = Drop(
title: "Title",
titleNumberOfLines: 3,
Expand Down
109 changes: 109 additions & 0 deletions Tests/DropsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,113 @@ final class DropsTests: XCTestCase {

XCTAssert(Drops.shared.queue.isEmpty)
}

func testHandlers() {
let drops = Drops(delayBetweenDrops: 0)
let expectedDrop = Drop(title: "Hello world!", duration: .seconds(0.1))

let willShowDropExp = expectation(description: "willShowDrop is called")
let didShowDropExp = expectation(description: "didShowDrop is called")
let willDismissDropExp = expectation(description: "willDismissDrop is called")
let didDismissDropExp = expectation(description: "didDismissDrop is called")

drops.willShowDrop = { drop in
XCTAssertEqual(drop, expectedDrop)
willShowDropExp.fulfill()
}

drops.didShowDrop = { drop in
XCTAssertEqual(drop, expectedDrop)
didShowDropExp.fulfill()
}

drops.willDismissDrop = { drop in
XCTAssertEqual(drop, expectedDrop)
willDismissDropExp.fulfill()
}

drops.didDismissDrop = { drop in
XCTAssertEqual(drop, expectedDrop)
didDismissDropExp.fulfill()
}

drops.show(expectedDrop)

waitForExpectations(timeout: 1)
}

func testStaticHandlers() {
let expectedDrop = Drop(title: "Hello world!", duration: .seconds(0.1))

let willShowDropExp = expectation(description: "willShowDrop is called")
let didShowDropExp = expectation(description: "didShowDrop is called")
let willDismissDropExp = expectation(description: "willDismissDrop is called")
let didDismissDropExp = expectation(description: "didDismissDrop is called")

Drops.willShowDrop = { drop in
XCTAssertEqual(drop, expectedDrop)
willShowDropExp.fulfill()
}

Drops.didShowDrop = { drop in
XCTAssertEqual(drop, expectedDrop)
didShowDropExp.fulfill()
}

Drops.willDismissDrop = { drop in
XCTAssertEqual(drop, expectedDrop)
willDismissDropExp.fulfill()
}

Drops.didDismissDrop = { drop in
XCTAssertEqual(drop, expectedDrop)
didDismissDropExp.fulfill()
}

Drops.show(expectedDrop)

waitForExpectations(timeout: 1)
}

func testStaticHandlersSettersAndGetters() {
Drops.willShowDrop = { _ in }
XCTAssertNotNil(Drops.shared.willShowDrop)
Drops.willShowDrop = nil
XCTAssertNil(Drops.shared.willShowDrop)

Drops.didShowDrop = { _ in }
XCTAssertNotNil(Drops.shared.didShowDrop)
Drops.didShowDrop = nil
XCTAssertNil(Drops.shared.didShowDrop)

Drops.willDismissDrop = { _ in }
XCTAssertNotNil(Drops.shared.willDismissDrop)
Drops.willDismissDrop = nil
XCTAssertNil(Drops.shared.willDismissDrop)

Drops.didDismissDrop = { _ in }
XCTAssertNotNil(Drops.shared.didDismissDrop)
Drops.didDismissDrop = nil
XCTAssertNil(Drops.shared.didDismissDrop)

Drops.shared.willShowDrop = { _ in }
XCTAssertNotNil(Drops.willShowDrop)
Drops.shared.willShowDrop = nil
XCTAssertNil(Drops.willShowDrop)

Drops.shared.didShowDrop = { _ in }
XCTAssertNotNil(Drops.didShowDrop)
Drops.shared.didShowDrop = nil
XCTAssertNil(Drops.didShowDrop)

Drops.shared.willDismissDrop = { _ in }
XCTAssertNotNil(Drops.willDismissDrop)
Drops.shared.willDismissDrop = nil
XCTAssertNil(Drops.willDismissDrop)

Drops.shared.didDismissDrop = { _ in }
XCTAssertNotNil(Drops.didDismissDrop)
Drops.shared.didDismissDrop = nil
XCTAssertNil(Drops.didDismissDrop)
}
}
Loading

0 comments on commit 6b92e72

Please sign in to comment.