12 Commits

Author SHA1 Message Date
Jordan Pichler b2f5bd7d16 Add completion block to present function (#94) 2020-04-21 11:16:30 -07:00
Tosin Afolabi b012aecb6b bump version number. 2020-03-30 12:33:24 -07:00
Stephen Sowole 22b4ddd47e [PanModal] Track all dismiss events through panModalPresentable callbacks (#91) 2020-03-25 00:34:58 -07:00
Stephen Sowole 17a8231f20 Update README.md 2020-03-24 17:10:08 -07:00
Stephen Sowole 1819113e97 [ReadMe] Add link to Swift Package Manager 2020-02-27 09:10:21 -08:00
Stephen Sowole 208640e03e [PanModal] Round frame positions for comparison (#83) 2020-02-24 15:20:26 -08:00
Stephen Sowole f02439dc0c [PanModal] Fix issue with incorrect returned bottom offset value (#84) 2020-02-24 15:20:14 -08:00
Kyohei Ito 047415090a Fix Background dimming animation broken (#77) 2020-02-24 14:02:45 -08:00
Abdullah Selek 1e7c0534fc Use keyPath to read UIApplication.shared. (#81) 2020-02-12 13:02:33 -06:00
Tosin Afolabi 7f07cdff27 Initial SPM Support 2019-11-11 10:52:18 -08:00
Nikita Nikitsky 45f8dfcf19 Add support for Swift Package Manager (#55) 2019-11-11 10:49:59 -08:00
Tosin Afolabi 5d2b0977bd Swift 5.0 Support 2019-11-11 10:26:03 -08:00
17 changed files with 119 additions and 36 deletions
+22
View File
@@ -0,0 +1,22 @@
// swift-tools-version:5.1
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "PanModal",
platforms: [.iOS(.v10)],
products: [
.library(
name: "PanModal",
targets: ["PanModal"]),
],
dependencies: [],
targets: [
.target(
name: "PanModal",
dependencies: [],
path: "PanModal")
],
swiftLanguageVersions: [.version("5.0")]
)
+2 -2
View File
@@ -8,7 +8,7 @@
Pod::Spec.new do |s|
s.name = 'PanModal'
s.version = '1.2.4'
s.version = '1.2.7'
s.summary = 'PanModal is an elegant and highly customizable presentation API for constructing bottom sheet modals on iOS.'
# This description is used to generate tags and improve search results.
@@ -24,6 +24,6 @@ Pod::Spec.new do |s|
s.source = { :git => 'https://github.com/slackhq/PanModal.git', :tag => s.version.to_s }
s.social_media_url = 'https://twitter.com/slackhq'
s.ios.deployment_target = '10.0'
s.swift_version = '4.2'
s.swift_version = '5.0'
s.source_files = 'PanModal/**/*.{swift,h,m}'
end
+2
View File
@@ -5,6 +5,7 @@
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
//
#if os(iOS)
import UIKit
/**
@@ -36,3 +37,4 @@ struct PanModalAnimator {
completion: completion)
}
}
#endif
@@ -5,6 +5,7 @@
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
//
#if os(iOS)
import UIKit
/**
@@ -168,3 +169,4 @@ extension PanModalPresentationAnimator: UIViewControllerAnimatedTransitioning {
}
}
#endif
@@ -5,6 +5,7 @@
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
//
#if os(iOS)
import UIKit
/**
@@ -112,7 +113,7 @@ open class PanModalPresentationController: UIPresentationController {
}
view.didTap = { [weak self] _ in
if self?.presentable?.allowsTapToDismiss == true {
self?.dismissPresentedViewController()
self?.presentedViewController.dismiss(animated: true)
}
}
return view
@@ -191,7 +192,14 @@ open class PanModalPresentationController: UIPresentationController {
})
}
override public func presentationTransitionDidEnd(_ completed: Bool) {
if completed { return }
backgroundView.removeFromSuperview()
}
override public func dismissalTransitionWillBegin() {
presentable?.panModalWillDismiss()
guard let coordinator = presentedViewController.transitionCoordinator else {
backgroundView.dimState = .off
@@ -209,10 +217,10 @@ open class PanModalPresentationController: UIPresentationController {
})
}
override public func presentationTransitionDidEnd(_ completed: Bool) {
if completed { return }
backgroundView.removeFromSuperview()
override public func dismissalTransitionDidEnd(_ completed: Bool) {
if !completed { return }
presentable?.panModalDidDismiss()
}
/**
@@ -310,7 +318,7 @@ private extension PanModalPresentationController {
var isPresentedViewAnchored: Bool {
if !isPresentedViewAnimating
&& extendsPanScrolling
&& presentedView.frame.minY <= anchoredYPosition {
&& presentedView.frame.minY.rounded() <= anchoredYPosition.rounded() {
return true
}
@@ -366,7 +374,8 @@ private extension PanModalPresentationController {
if ![shortFormYPosition, longFormYPosition].contains(panFrame.origin.y) {
// if the container is already in the correct position, no need to adjust positioning
// (rotations & size changes cause positioning to be out of sync)
adjust(toYPosition: panFrame.origin.y - panFrame.height + frame.height)
let yPosition = panFrame.origin.y - panFrame.height + frame.height
presentedView.frame.origin.y = max(yPosition, anchoredYPosition)
}
panContainerView.frame.origin.x = frame.origin.x
presentedViewController.view.frame = CGRect(origin: .zero, size: adjustedSize)
@@ -514,7 +523,7 @@ private extension PanModalPresentationController {
transition(to: .shortForm)
} else {
dismissPresentedViewController()
presentedViewController.dismiss(animated: true)
}
} else {
@@ -532,7 +541,7 @@ private extension PanModalPresentationController {
transition(to: .shortForm)
} else {
dismissPresentedViewController()
presentedViewController.dismiss(animated: true)
}
}
}
@@ -671,16 +680,6 @@ private extension PanModalPresentationController {
else { return number }
return nearestVal
}
/**
Dismiss presented view
*/
func dismissPresentedViewController() {
presentable?.panModalWillDismiss()
presentedViewController.dismiss(animated: true) { [weak self] in
self?.presentable?.panModalDidDismiss()
}
}
}
// MARK: - UIScrollView Observer
@@ -890,3 +889,4 @@ private extension UIScrollView {
return isDragging && !isDecelerating || isTracking
}
}
#endif
@@ -5,6 +5,7 @@
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
//
#if os(iOS)
import UIKit
/**
@@ -77,3 +78,4 @@ extension PanModalPresentationDelegate: UIAdaptivePresentationControllerDelegate
}
}
#endif
@@ -5,6 +5,7 @@
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
//
#if os(iOS)
import UIKit
/**
@@ -40,3 +41,4 @@ public enum PanModalHeight: Equatable {
*/
case intrinsicHeight
}
#endif
@@ -5,6 +5,7 @@
// Copyright © 2018 Tiny Speck, Inc. All rights reserved.
//
#if os(iOS)
import UIKit
/**
@@ -124,3 +125,4 @@ public extension PanModalPresentable where Self: UIViewController {
}
}
#endif
@@ -5,6 +5,7 @@
// Copyright © 2018 Tiny Speck, Inc. All rights reserved.
//
#if os(iOS)
import UIKit
/**
@@ -26,7 +27,11 @@ extension PanModalPresentable where Self: UIViewController {
Gives us the safe area inset from the top.
*/
var topLayoutOffset: CGFloat {
return UIApplication.shared.keyWindow?.rootViewController?.topLayoutGuide.length ?? 0
guard let rootVC = rootViewController
else { return 0}
if #available(iOS 11.0, *) { return rootVC.view.safeAreaInsets.top } else { return rootVC.topLayoutGuide.length }
}
/**
@@ -34,7 +39,11 @@ extension PanModalPresentable where Self: UIViewController {
Gives us the safe area inset from the bottom.
*/
var bottomLayoutOffset: CGFloat {
return UIApplication.shared.keyWindow?.rootViewController?.bottomLayoutGuide.length ?? 0
guard let rootVC = rootViewController
else { return 0}
if #available(iOS 11.0, *) { return rootVC.view.safeAreaInsets.bottom } else { return rootVC.bottomLayoutGuide.length }
}
/**
@@ -99,4 +108,13 @@ extension PanModalPresentable where Self: UIViewController {
}
}
private var rootViewController: UIViewController? {
guard let application = UIApplication.value(forKeyPath: #keyPath(UIApplication.shared)) as? UIApplication
else { return nil }
return application.keyWindow?.rootViewController
}
}
#endif
@@ -5,6 +5,7 @@
// Copyright © 2018 Tiny Speck, Inc. All rights reserved.
//
#if os(iOS)
import UIKit
/**
@@ -59,3 +60,4 @@ public extension PanModalPresentable where Self: UIViewController {
}
}
#endif
@@ -5,6 +5,7 @@
// Copyright © 2017 Tiny Speck, Inc. All rights reserved.
//
#if os(iOS)
import UIKit
/**
@@ -233,3 +234,4 @@ public protocol PanModalPresentable: AnyObject {
*/
func panModalDidDismiss()
}
#endif
+6 -1
View File
@@ -5,6 +5,7 @@
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
//
#if os(iOS)
import UIKit
/**
@@ -28,6 +29,10 @@ protocol PanModalPresenter: AnyObject {
/**
Presents a view controller that conforms to the PanModalPresentable protocol
*/
func presentPanModal(_ viewControllerToPresent: PanModalPresentable.LayoutType, sourceView: UIView?, sourceRect: CGRect)
func presentPanModal(_ viewControllerToPresent: PanModalPresentable.LayoutType,
sourceView: UIView?,
sourceRect: CGRect,
completion: (() -> Void)?)
}
#endif
@@ -5,6 +5,7 @@
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
//
#if os(iOS)
import UIKit
/**
@@ -34,10 +35,14 @@ extension UIViewController: PanModalPresenter {
- viewControllerToPresent: The view controller to be presented
- sourceView: The view containing the anchor rectangle for the popover.
- sourceRect: The rectangle in the specified view in which to anchor the popover.
- completion: The block to execute after the presentation finishes. You may specify nil for this parameter.
- Note: sourceView & sourceRect are only required for presentation on an iPad.
*/
public func presentPanModal(_ viewControllerToPresent: PanModalPresentable.LayoutType, sourceView: UIView? = nil, sourceRect: CGRect = .zero) {
public func presentPanModal(_ viewControllerToPresent: PanModalPresentable.LayoutType,
sourceView: UIView? = nil,
sourceRect: CGRect = .zero,
completion: (() -> Void)? = nil) {
/**
Here, we deliberately do not check for size classes. More info in `PanModalPresentationDelegate`
@@ -54,7 +59,8 @@ extension UIViewController: PanModalPresenter {
viewControllerToPresent.transitioningDelegate = PanModalPresentationDelegate.default
}
present(viewControllerToPresent, animated: true, completion: nil)
present(viewControllerToPresent, animated: true, completion: completion)
}
}
#endif
+2
View File
@@ -5,6 +5,7 @@
// Copyright © 2017 Tiny Speck, Inc. All rights reserved.
//
#if os(iOS)
import UIKit
/**
@@ -72,3 +73,4 @@ public class DimmedView: UIView {
}
}
#endif
+2
View File
@@ -5,6 +5,7 @@
// Copyright © 2018 Tiny Speck, Inc. All rights reserved.
//
#if os(iOS)
import UIKit
/**
@@ -40,3 +41,4 @@ extension UIView {
}
}
#endif
+8 -6
View File
@@ -629,7 +629,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.slack.PanModal;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -658,7 +658,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.slack.PanModal;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -679,7 +679,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = slack.PanModalTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PanModalDemo.app/PanModalDemo";
};
@@ -699,7 +699,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = slack.PanModalTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PanModalDemo.app/PanModalDemo";
};
@@ -763,6 +763,7 @@
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
@@ -817,6 +818,7 @@
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
@@ -837,7 +839,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = com.PanModal;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -858,7 +860,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = com.PanModal;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
+16 -4
View File
@@ -1,15 +1,13 @@
### PanModal is an elegant and highly customizable presentation API for constructing bottom sheet modals on iOS.
Read our <a href="https://slack.engineering/panmodal-better-support-for-thumb-accessibility-on-slack-mobile-52b2a7596031" target="_blank">blog</a> on how Slack is getting more :thumbsup: with PanModal
<p align="center">
<img src="https://github.com/slackhq/PanModal/raw/master/Screenshots/panModal.gif" width="30%" height="30%" alt="Screenshot Preview" />
</p>
<p align="center">
<img src="https://img.shields.io/badge/Platform-iOS_10+-green.svg" alt="Platform: iOS 10.0+" />
<a href="https://developer.apple.com/swift" target="_blank"><img src="https://img.shields.io/badge/Language-Swift_4-blueviolet.svg" alt="Language: Swift 4" /></a>
<a href="https://developer.apple.com/swift" target="_blank"><img src="https://img.shields.io/badge/Language-Swift_5-blueviolet.svg" alt="Language: Swift 5" /></a>
<a href="https://cocoapods.org/pods/PanModal" target="_blank"><img src="https://img.shields.io/badge/CocoaPods-v1.0-red.svg" alt="CocoaPods compatible" /></a>
<a href="https://github.com/Carthage/Carthage" target="_blank"><img src="https://img.shields.io/badge/Carthage-compatible-blue.svg" alt="Carthage compatible" /></a>
<img src="https://img.shields.io/badge/License-MIT-green.svg" alt="License: MIT" />
@@ -26,6 +24,12 @@ Read our <a href="https://slack.engineering/panmodal-better-support-for-thumb-ac
• <a href="#license">License</a>
</p>
<p align="center">
Read our <a href="https://slack.engineering/panmodal-better-support-for-thumb-accessibility-on-slack-mobile-52b2a7596031" target="_blank">blog</a> on how Slack is getting more :thumbsup: with PanModal
Swift 4.2 support can be found on the `Swift4.2` branch.
</p>
## Features
* Supports any type of `UIViewController`
@@ -50,6 +54,14 @@ pod 'PanModal'
github "slackhq/PanModal"
```
* <a href="https://swift.org/package-manager/" target="_blank">Swift Package Manager</a>:
```swift
dependencies: [
.package(url: "https://github.com/slackhq/PanModal.git", .exact("1.2.6")),
],
```
## Usage
PanModal was designed to be used effortlessly. Simply call `presentPanModal` in the same way you would expect to present a `UIViewController`
@@ -135,7 +147,7 @@ We will only be fixing critical bugs, thus, for any non-critical issues or featu
## Authors
[Stephen Sowole](https://github.com/tun57) • [Tosin Afolabi](https://github.com/tosinaf)
[Stephen Sowole](https://github.com/ste57) • [Tosin Afolabi](https://github.com/tosinaf)
## License