From 346d60edbe4908590fdcdc20275863e5602cd53c Mon Sep 17 00:00:00 2001 From: Canh Tran <7752679+canhth@users.noreply.github.com> Date: Wed, 28 Oct 2020 20:55:41 +0700 Subject: [PATCH 01/77] Support disable `becomeKeyWindow` from SwiftMessages.Config (#430) * Support disable becomeKeyWindow from Config * Remove `windowScene` reference in uninstall WindowViewController (iOS >13) --- SwiftMessages/Presenter.swift | 2 +- SwiftMessages/WindowViewController.swift | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index 80509e06..328190f7 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -434,7 +434,7 @@ class Presenter: NSObject { } private var becomeKeyWindow: Bool { - if config.becomeKeyWindow == .some(true) { return true } + if let becomeKeyWindow = config.becomeKeyWindow { return becomeKeyWindow } switch config.dimMode { case .gray, .color, .blur: // Should become key window in modal presentation style diff --git a/SwiftMessages/WindowViewController.swift b/SwiftMessages/WindowViewController.swift index 4e9ade81..bcac52ce 100644 --- a/SwiftMessages/WindowViewController.swift +++ b/SwiftMessages/WindowViewController.swift @@ -55,6 +55,9 @@ open class WindowViewController: UIViewController } func uninstall() { + if #available(iOS 13, *) { + window?.windowScene = nil + } window?.isHidden = true window = nil } From 5bf49193be5b65be689f65ae5f1e444529af689f Mon Sep 17 00:00:00 2001 From: kenji21 <r.bergoin@openium.fr> Date: Mon, 30 Nov 2020 17:36:06 +0100 Subject: [PATCH 02/77] Fix Unknown class in IB file (#437) --- SwiftMessages/Resources/CardView.xib | 6 +++--- SwiftMessages/Resources/CenteredView.xib | 8 ++++---- SwiftMessages/Resources/TabView.xib | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/SwiftMessages/Resources/CardView.xib b/SwiftMessages/Resources/CardView.xib index 6a8f997c..425a6961 100644 --- a/SwiftMessages/Resources/CardView.xib +++ b/SwiftMessages/Resources/CardView.xib @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17126"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> @@ -13,7 +13,7 @@ <rect key="frame" x="0.0" y="0.0" width="510" height="160"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="A7b-0a-fJG" userLabel="Corner rounding view" customClass="CornerRoundingView" customModule="SwiftMessages" customModuleProvider="target"> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="A7b-0a-fJG" userLabel="Corner rounding view" customClass="CornerRoundingView" customModule="SwiftMessages"> <rect key="frame" x="20" y="44" width="470" height="82"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="SU0-uJ-4pP" userLabel="Content view"> diff --git a/SwiftMessages/Resources/CenteredView.xib b/SwiftMessages/Resources/CenteredView.xib index 9d6ebb38..a9fda2be 100644 --- a/SwiftMessages/Resources/CenteredView.xib +++ b/SwiftMessages/Resources/CenteredView.xib @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17126"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> @@ -13,7 +13,7 @@ <rect key="frame" x="0.0" y="0.0" width="434" height="272"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Mj-jC-BX6" userLabel="Background view" customClass="CornerRoundingView" customModule="SwiftMessages" customModuleProvider="target"> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Mj-jC-BX6" userLabel="Background view" customClass="CornerRoundingView" customModule="SwiftMessages"> <rect key="frame" x="20" y="44" width="394" height="194"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="700" axis="vertical" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="YST-yc-0HK" userLabel="Content view"> @@ -32,7 +32,7 @@ <rect key="frame" x="160.5" y="55.5" width="33" height="0.0"/> </imageView> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="700" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="[Title]" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ggW-gB-SWF"> - <rect key="frame" x="153" y="65.5" width="48" height="20.5"/> + <rect key="frame" x="153" y="65.5" width="48.5" height="20.5"/> <accessibility key="accessibilityConfiguration"> <bool key="isElement" value="NO"/> </accessibility> diff --git a/SwiftMessages/Resources/TabView.xib b/SwiftMessages/Resources/TabView.xib index 5be0fc88..141467c1 100644 --- a/SwiftMessages/Resources/TabView.xib +++ b/SwiftMessages/Resources/TabView.xib @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17126"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> @@ -13,7 +13,7 @@ <rect key="frame" x="0.0" y="0.0" width="600" height="123"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8l1-Wp-omF" userLabel="Corner rounding view" customClass="CornerRoundingView" customModule="SwiftMessages" customModuleProvider="target"> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8l1-Wp-omF" userLabel="Corner rounding view" customClass="CornerRoundingView" customModule="SwiftMessages"> <rect key="frame" x="20" y="0.0" width="560" height="123"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="bdc-by-rjM" userLabel="Content view"> From a035a11816f8aef1c6f7d7f2fc243c1421c75dd4 Mon Sep 17 00:00:00 2001 From: Mickey <knox@users.noreply.github.com> Date: Thu, 3 Dec 2020 16:04:48 +0100 Subject: [PATCH 03/77] FIX 'shared' is unavailable in application extensions for iOS (#440) --- SwiftMessages/Presenter.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index 328190f7..bff7f984 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -102,7 +102,12 @@ class Presenter: NSObject { private var windowScene: UIWindowScene? { switch config.presentationContext { case .windowScene(let scene, _): return scene - default: return UIApplication.shared.keyWindow?.windowScene + default: + #if SWIFTMESSAGES_APP_EXTENSIONS + return nil + #else + return UIApplication.shared.keyWindow?.windowScene + #endif } } From ff910b85c919d9ede604b5c13d1a9d8c252ebcb8 Mon Sep 17 00:00:00 2001 From: Seyed Mojtaba Hosseini Zeidabadi <ca.chairman@gmail.com> Date: Tue, 15 Dec 2020 17:45:01 +0330 Subject: [PATCH 04/77] Ignoring the SafeArea for margins is now possible. (#442) Co-authored-by: Seyed Mojtaba Hosseini Zeidabadi <chenzook@gmail.com> --- SwiftMessages/BaseView.swift | 3 ++ .../MarginAdjustable+Animation.swift | 38 ++++++++++--------- SwiftMessages/MarginAdjustable.swift | 4 ++ 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/SwiftMessages/BaseView.swift b/SwiftMessages/BaseView.swift index 15a37236..9480b87d 100644 --- a/SwiftMessages/BaseView.swift +++ b/SwiftMessages/BaseView.swift @@ -210,6 +210,9 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable { } } + /// Start margins from the safe area. + open var respectSafeArea: Bool = true + /// IBInspectable access to layoutMarginAdditions.top @IBInspectable open var topLayoutMarginAddition: CGFloat = 0 diff --git a/SwiftMessages/MarginAdjustable+Animation.swift b/SwiftMessages/MarginAdjustable+Animation.swift index 3829a70c..4794ea34 100644 --- a/SwiftMessages/MarginAdjustable+Animation.swift +++ b/SwiftMessages/MarginAdjustable+Animation.swift @@ -11,26 +11,28 @@ import UIKit extension MarginAdjustable where Self: UIView { public func defaultMarginAdjustment(context: AnimationContext) -> UIEdgeInsets { var layoutMargins: UIEdgeInsets = layoutMarginAdditions - var safeAreaInsets: UIEdgeInsets - if #available(iOS 11, *) { - insetsLayoutMarginsFromSafeArea = false - safeAreaInsets = self.safeAreaInsets - } else { - #if SWIFTMESSAGES_APP_EXTENSIONS - let application: UIApplication? = nil - #else - let application: UIApplication? = UIApplication.shared - #endif - if !context.safeZoneConflicts.isDisjoint(with: [.statusBar]), - let app = application, - app.statusBarOrientation == .portrait || app.statusBarOrientation == .portraitUpsideDown { - let frameInWindow = convert(bounds, to: window) - let top = max(0, 20 - frameInWindow.minY) - safeAreaInsets = UIEdgeInsets(top: top, left: 0, bottom: 0, right: 0) + var safeAreaInsets: UIEdgeInsets = { + guard respectSafeArea else { return .zero } + if #available(iOS 11, *) { + insetsLayoutMarginsFromSafeArea = false + return self.safeAreaInsets } else { - safeAreaInsets = .zero + #if SWIFTMESSAGES_APP_EXTENSIONS + let application: UIApplication? = nil + #else + let application: UIApplication? = UIApplication.shared + #endif + if !context.safeZoneConflicts.isDisjoint(with: [.statusBar]), + let app = application, + app.statusBarOrientation == .portrait || app.statusBarOrientation == .portraitUpsideDown { + let frameInWindow = convert(bounds, to: window) + let top = max(0, 20 - frameInWindow.minY) + return UIEdgeInsets(top: top, left: 0, bottom: 0, right: 0) + } else { + return .zero + } } - } + }() if !context.safeZoneConflicts.isDisjoint(with: .overStatusBar) { safeAreaInsets.top = 0 } diff --git a/SwiftMessages/MarginAdjustable.swift b/SwiftMessages/MarginAdjustable.swift index 1b064bb4..86fe9017 100644 --- a/SwiftMessages/MarginAdjustable.swift +++ b/SwiftMessages/MarginAdjustable.swift @@ -33,6 +33,10 @@ public protocol MarginAdjustable { /// the additional margin is not added. var collapseLayoutMarginAdditions: Bool { get set } + + /// Start margins from the safe area. + var respectSafeArea: Bool { get set } + var bounceAnimationOffset: CGFloat { get set } } From f7297cc4e9acfaf6710cada80a396d58ff8de5b3 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Tue, 15 Dec 2020 08:34:04 -0600 Subject: [PATCH 05/77] Update change log --- CHANGELOG.md | 12 ++++++++++++ SwiftMessages.podspec | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5f48083..782d684a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,18 @@ # Change Log All notable changes to this project will be documented in this file. +## 8.0.4 + +### Features + +* #442 Added `MarginAdjustable.respectSafeArea` option to exclude safe area from layout margins. +* #430 Support disable `becomeKeyWindow` from SwiftMessages.Config. This is a workaround for potential issues with apps that display additional windows. + +### Fixes + +* #437 Revert to explicitly specifying "SwiftMessages" as the module in nib files. +* #440 Fix crash when using SwiftMessages in app extension + ## 8.0.3 ### Features diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 2c7f04e9..ff51a2c3 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '8.0.3' + spec.version = '8.0.4' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } From 243fa7596818e3a96a7f0563453b3f35a674a5fb Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sun, 20 Dec 2020 11:41:34 -0600 Subject: [PATCH 06/77] Restore key window on dismissal --- CHANGELOG.md | 6 ++++++ README.md | 9 ++++++--- SwiftMessages.podspec | 2 +- SwiftMessages/WindowViewController.swift | 18 +++++++++++++----- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 782d684a..c1bf3071 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change Log All notable changes to this project will be documented in this file. +## 8.0.5 + +### FeaturesFixes + +* #446 Restore previous key window on dismissal if the message assumed key window status. + ## 8.0.4 ### Features diff --git a/README.md b/README.md index a73472c0..c46c84cf 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ SwiftMessages is a very flexible view and view controller presentation library for iOS. -Message views and view controllers can be displayed at the top, bottom, or center of the screen, over or under the status bar, or behind navigation bars and tab bars. There are interactive dismiss gestures including a fun, physics-based one. Multiple background dimming modes. And a lot more! +Message views and view controllers can be displayed at the top, bottom, or center of the screen, or behind navigation bars and tab bars. There are interactive dismiss gestures including a fun, physics-based one. Multiple background dimming modes. And a lot more! In addition to the numerous configuration options, SwiftMessages provides several good-looking layouts and themes. But SwiftMessages is also designer-friendly, which means you can fully and easily customize the view: @@ -135,10 +135,13 @@ var config = SwiftMessages.Config() // Slide up from the bottom. config.presentationStyle = .bottom -// Display in a window at the specified window level: UIWindow.Level.statusBar -// displays over the status bar while UIWindow.Level.normal displays under. +// Display in a window at the specified window level. config.presentationContext = .window(windowLevel: .statusBar) +Note that, as of iOS 13, it is no longer possible to cover the status bar +regardless of the window level. A workaround is to hide the status bar instead. +config.prefersStatusBarHidden = true + // Disable the default auto-hiding behavior. config.duration = .forever diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index ff51a2c3..d23d5a22 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '8.0.4' + spec.version = '8.0.5' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } diff --git a/SwiftMessages/WindowViewController.swift b/SwiftMessages/WindowViewController.swift index bcac52ce..e186b613 100644 --- a/SwiftMessages/WindowViewController.swift +++ b/SwiftMessages/WindowViewController.swift @@ -10,11 +10,6 @@ import UIKit open class WindowViewController: UIViewController { - fileprivate var window: UIWindow? - - let windowLevel: UIWindow.Level - let config: SwiftMessages.Config - override open var shouldAutorotate: Bool { return config.shouldAutorotate } @@ -41,6 +36,9 @@ open class WindowViewController: UIViewController @available(iOS 13, *) func install(becomeKey: Bool, scene: UIWindowScene?) { window?.windowScene = scene + if becomeKey { + previousKeyWindow = UIApplication.shared.keyWindow + } show(becomeKey: becomeKey, frame: scene?.coordinateSpace.bounds) } @@ -60,6 +58,7 @@ open class WindowViewController: UIViewController } window?.isHidden = true window = nil + previousKeyWindow?.makeKeyAndVisible() } required public init?(coder aDecoder: NSCoder) { @@ -73,6 +72,15 @@ open class WindowViewController: UIViewController open override var prefersStatusBarHidden: Bool { return config.prefersStatusBarHidden ?? super.prefersStatusBarHidden } + + // MARK: - Variables + + let windowLevel: UIWindow.Level + + private var window: UIWindow? + private weak var previousKeyWindow: UIWindow? + + private let config: SwiftMessages.Config } extension WindowViewController { From 08355297737d697223946a87e85747b9aa2ff454 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 26 Dec 2020 12:09:08 -0600 Subject: [PATCH 07/77] Add ability to show view controllers in a new window --- CHANGELOG.md | 18 ++++- SwiftMessages.podspec | 2 +- SwiftMessages.xcodeproj/project.pbxproj | 68 ++++++++++++------- ...r+Utils.swift => CALayer+Extensions.swift} | 2 +- ...wift => MarginAdjustable+Extensions.swift} | 2 +- ...+Utils.swift => NSBundle+Extensions.swift} | 2 +- ...ft => NSLayoutConstraint+Extensions.swift} | 2 +- SwiftMessages/Presenter.swift | 51 +++----------- .../SwiftMessages.Config+Extensions.swift | 44 ++++++++++++ SwiftMessages/SwiftMessages.swift | 2 +- SwiftMessages/SwiftMessagesSegue.swift | 16 +++-- ...ls.swift => UIEdgeInsets+Extensions.swift} | 2 +- ...wift => UIViewController+Extensions.swift} | 6 +- SwiftMessages/WindowViewController.swift | 44 ++++++------ 14 files changed, 158 insertions(+), 103 deletions(-) rename SwiftMessages/{CALayer+Utils.swift => CALayer+Extensions.swift} (93%) rename SwiftMessages/{MarginAdjustable+Animation.swift => MarginAdjustable+Extensions.swift} (98%) rename SwiftMessages/{NSBundle+Utils.swift => NSBundle+Extensions.swift} (97%) rename SwiftMessages/{NSLayoutConstraint+Utils.swift => NSLayoutConstraint+Extensions.swift} (88%) create mode 100644 SwiftMessages/SwiftMessages.Config+Extensions.swift rename SwiftMessages/{UIEdgeInsets+Utils.swift => UIEdgeInsets+Extensions.swift} (96%) rename SwiftMessages/{UIViewController+Utils.swift => UIViewController+Extensions.swift} (94%) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1bf3071..562de4be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,23 @@ # Change Log All notable changes to this project will be documented in this file. +## 9.0.0 + +### Features + +* #447 Add the ability to show view controller in a new window with `SwiftMessagesSegue`. +This capability is available when using `SwiftMessagesSegue` programmatically by supplying +an instance of `WindowViewController` as the segue's source view controller. + +### Changes + +* This release has minor breaking changes in the `WindowViewController` initializers. +The `windowLevel` is no longer accepted as an argument because the `config` parameter +should specify the window level in the `presentationContext` property. + ## 8.0.5 -### FeaturesFixes +### Fixes * #446 Restore previous key window on dismissal if the message assumed key window status. @@ -11,7 +25,7 @@ All notable changes to this project will be documented in this file. ### Features -* #442 Added `MarginAdjustable.respectSafeArea` option to exclude safe area from layout margins. +* #442 Add `MarginAdjustable.respectSafeArea` option to exclude safe area from layout margins. * #430 Support disable `becomeKeyWindow` from SwiftMessages.Config. This is a workaround for potential issues with apps that display additional windows. ### Fixes diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index d23d5a22..22b2d781 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '8.0.5' + spec.version = '9.0.0' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 71c4392d..4eef9ad5 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -7,12 +7,13 @@ objects = { /* Begin PBXBuildFile section */ - 220655121FAF82B600F4E00F /* MarginAdjustable+Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 220655111FAF82B600F4E00F /* MarginAdjustable+Animation.swift */; }; - 224FB69921153B440081D4DE /* CALayer+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224FB69821153B440081D4DE /* CALayer+Utils.swift */; }; - 225304622290C76E00A03ACF /* NSLayoutConstraint+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225304612290C76E00A03ACF /* NSLayoutConstraint+Utils.swift */; }; + 220655121FAF82B600F4E00F /* MarginAdjustable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */; }; + 220D386E2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 220D386D2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift */; }; + 224FB69921153B440081D4DE /* CALayer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224FB69821153B440081D4DE /* CALayer+Extensions.swift */; }; + 225304622290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225304612290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift */; }; 225304662293000C00A03ACF /* KeyboardTrackingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225304652293000C00A03ACF /* KeyboardTrackingView.swift */; }; 2270044B1FAFA6DD0045DDC3 /* PhysicsAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2270044A1FAFA6DD0045DDC3 /* PhysicsAnimation.swift */; }; - 22774BA020B5EF2A00813732 /* UIEdgeInsets+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Utils.swift */; }; + 22774BA020B5EF2A00813732 /* UIEdgeInsets+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */; }; 227BA6D920BF224A00E5A843 /* SwiftMessagesSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 227BA6D820BF224A00E5A843 /* SwiftMessagesSegue.swift */; }; 228DF5261FACAC51004F8A39 /* errorIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5231FACAC51004F8A39 /* errorIcon.png */; }; 228DF5271FACAC51004F8A39 /* errorIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5241FACAC51004F8A39 /* errorIcon@2x.png */; }; @@ -71,8 +72,8 @@ 86BBA9001D5E040600FE8F16 /* PassthroughView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AAF8171D54F0650031EE32 /* PassthroughView.swift */; }; 86BBA9011D5E040600FE8F16 /* PassthroughWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AAF8191D54F0850031EE32 /* PassthroughWindow.swift */; }; 86BBA9021D5E040600FE8F16 /* WindowViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8644955C1D4FAF7C0056EB2A /* WindowViewController.swift */; }; - 86BBA9031D5E040600FE8F16 /* UIViewController+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AAF81B1D551FE60031EE32 /* UIViewController+Utils.swift */; }; - 86BBA9041D5E040600FE8F16 /* NSBundle+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 862C0CB01D5911C100D06168 /* NSBundle+Utils.swift */; }; + 86BBA9031D5E040600FE8F16 /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AAF81B1D551FE60031EE32 /* UIViewController+Extensions.swift */; }; + 86BBA9041D5E040600FE8F16 /* NSBundle+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 862C0CB01D5911C100D06168 /* NSBundle+Extensions.swift */; }; 86BBA9051D5E040C00FE8F16 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AAF82C1D580F410031EE32 /* Theme.swift */; }; 86BBA9061D5E040C00FE8F16 /* Identifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 864495551D4F7C390056EB2A /* Identifiable.swift */; }; 86BBA9071D5E040C00FE8F16 /* MarginAdjustable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AAF81D1D5549680031EE32 /* MarginAdjustable.swift */; }; @@ -92,12 +93,13 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 220655111FAF82B600F4E00F /* MarginAdjustable+Animation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarginAdjustable+Animation.swift"; sourceTree = "<group>"; }; - 224FB69821153B440081D4DE /* CALayer+Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CALayer+Utils.swift"; sourceTree = "<group>"; }; - 225304612290C76E00A03ACF /* NSLayoutConstraint+Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraint+Utils.swift"; sourceTree = "<group>"; }; + 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarginAdjustable+Extensions.swift"; sourceTree = "<group>"; }; + 220D386D2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftMessages.Config+Extensions.swift"; sourceTree = "<group>"; }; + 224FB69821153B440081D4DE /* CALayer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CALayer+Extensions.swift"; sourceTree = "<group>"; }; + 225304612290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraint+Extensions.swift"; sourceTree = "<group>"; }; 225304652293000C00A03ACF /* KeyboardTrackingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardTrackingView.swift; sourceTree = "<group>"; }; 2270044A1FAFA6DD0045DDC3 /* PhysicsAnimation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhysicsAnimation.swift; sourceTree = "<group>"; }; - 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIEdgeInsets+Utils.swift"; sourceTree = "<group>"; }; + 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIEdgeInsets+Extensions.swift"; sourceTree = "<group>"; }; 227BA6D820BF224A00E5A843 /* SwiftMessagesSegue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftMessagesSegue.swift; sourceTree = "<group>"; }; 228DF5231FACAC51004F8A39 /* errorIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = errorIcon.png; path = Resources/errorIcon.png; sourceTree = "<group>"; }; 228DF5241FACAC51004F8A39 /* errorIcon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "errorIcon@2x.png"; path = "Resources/errorIcon@2x.png"; sourceTree = "<group>"; }; @@ -145,7 +147,7 @@ 22E307FE1E74C5B100E35893 /* AccessibleMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessibleMessage.swift; sourceTree = "<group>"; }; 22F27950210CE25900273E7F /* CornerRoundingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerRoundingView.swift; sourceTree = "<group>"; }; 862C0C6A1D58E93300D06168 /* SwiftMessages.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; path = SwiftMessages.podspec; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 862C0CB01D5911C100D06168 /* NSBundle+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSBundle+Utils.swift"; sourceTree = "<group>"; }; + 862C0CB01D5911C100D06168 /* NSBundle+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSBundle+Extensions.swift"; sourceTree = "<group>"; }; 862C0CDA1D5A397F00D06168 /* MessageView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MessageView.xib; path = Resources/MessageView.xib; sourceTree = "<group>"; }; 862C0CDB1D5A397F00D06168 /* StatusLine.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = StatusLine.xib; path = Resources/StatusLine.xib; sourceTree = "<group>"; }; 864495551D4F7C390056EB2A /* Identifiable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Identifiable.swift; sourceTree = "<group>"; }; @@ -158,7 +160,7 @@ 867E21931D4D50BB00594A41 /* Presenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Presenter.swift; sourceTree = "<group>"; }; 86AAF8171D54F0650031EE32 /* PassthroughView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassthroughView.swift; sourceTree = "<group>"; }; 86AAF8191D54F0850031EE32 /* PassthroughWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassthroughWindow.swift; sourceTree = "<group>"; }; - 86AAF81B1D551FE60031EE32 /* UIViewController+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Utils.swift"; sourceTree = "<group>"; }; + 86AAF81B1D551FE60031EE32 /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extensions.swift"; sourceTree = "<group>"; }; 86AAF81D1D5549680031EE32 /* MarginAdjustable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarginAdjustable.swift; sourceTree = "<group>"; }; 86AAF82A1D580DD70031EE32 /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; }; 86AAF82C1D580F410031EE32 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; }; @@ -190,13 +192,33 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 220D38672597A94C00BB2B88 /* Extensions */ = { + isa = PBXGroup; + children = ( + 224FB69821153B440081D4DE /* CALayer+Extensions.swift */, + 862C0CB01D5911C100D06168 /* NSBundle+Extensions.swift */, + 86AAF81B1D551FE60031EE32 /* UIViewController+Extensions.swift */, + 225304612290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift */, + 220D386D2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift */, + ); + name = Extensions; + sourceTree = "<group>"; + }; + 220D38682597A9FD00BB2B88 /* Extensions */ = { + isa = PBXGroup; + children = ( + 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */, + 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */, + ); + name = Extensions; + sourceTree = "<group>"; + }; 2244656C1EF1D62700C50413 /* Animations */ = { isa = PBXGroup; children = ( 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */, 2270044A1FAFA6DD0045DDC3 /* PhysicsAnimation.swift */, 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */, - 220655111FAF82B600F4E00F /* MarginAdjustable+Animation.swift */, ); name = Animations; sourceTree = "<group>"; @@ -277,7 +299,6 @@ 86AAF82A1D580DD70031EE32 /* Error.swift */, 2298C2061EE480D000E2DDC1 /* Animator.swift */, 2298C2041EE47DC900E2DDC1 /* Weak.swift */, - 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Utils.swift */, 22F27950210CE25900273E7F /* CornerRoundingView.swift */, 225304652293000C00A03ACF /* KeyboardTrackingView.swift */, ); @@ -312,10 +333,7 @@ 86AAF8171D54F0650031EE32 /* PassthroughView.swift */, 22E01F631E74EC8B00ACE19A /* MaskingView.swift */, 86AAF8191D54F0850031EE32 /* PassthroughWindow.swift */, - 86AAF81B1D551FE60031EE32 /* UIViewController+Utils.swift */, - 224FB69821153B440081D4DE /* CALayer+Utils.swift */, - 862C0CB01D5911C100D06168 /* NSBundle+Utils.swift */, - 225304612290C76E00A03ACF /* NSLayoutConstraint+Utils.swift */, + 220D38672597A94C00BB2B88 /* Extensions */, ); name = Internal; sourceTree = "<group>"; @@ -329,6 +347,7 @@ 2244656C1EF1D62700C50413 /* Animations */, 22D4779B20BF1C54005D0D71 /* View Controllers */, 864495571D4F7C490056EB2A /* Base */, + 220D38682597A9FD00BB2B88 /* Extensions */, 867E218E1D4D3DFD00594A41 /* Internal */, 86B48B031D5A41E500063E2B /* Support */, ); @@ -507,23 +526,24 @@ buildActionMask = 2147483647; files = ( 225304662293000C00A03ACF /* KeyboardTrackingView.swift in Sources */, - 22774BA020B5EF2A00813732 /* UIEdgeInsets+Utils.swift in Sources */, + 22774BA020B5EF2A00813732 /* UIEdgeInsets+Extensions.swift in Sources */, 86BBA8FC1D5E03F100FE8F16 /* MessageView.swift in Sources */, 86BBA9061D5E040C00FE8F16 /* Identifiable.swift in Sources */, 22F27951210CE25900273E7F /* CornerRoundingView.swift in Sources */, 86BBA9011D5E040600FE8F16 /* PassthroughWindow.swift in Sources */, 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */, - 86BBA9031D5E040600FE8F16 /* UIViewController+Utils.swift in Sources */, - 224FB69921153B440081D4DE /* CALayer+Utils.swift in Sources */, + 86BBA9031D5E040600FE8F16 /* UIViewController+Extensions.swift in Sources */, + 224FB69921153B440081D4DE /* CALayer+Extensions.swift in Sources */, 22E01F641E74EC8B00ACE19A /* MaskingView.swift in Sources */, 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */, 86BBA9001D5E040600FE8F16 /* PassthroughView.swift in Sources */, 22DFC9181F00674E001B1CA1 /* PhysicsPanHandler.swift in Sources */, 227BA6D920BF224A00E5A843 /* SwiftMessagesSegue.swift in Sources */, - 220655121FAF82B600F4E00F /* MarginAdjustable+Animation.swift in Sources */, + 220655121FAF82B600F4E00F /* MarginAdjustable+Extensions.swift in Sources */, 22E307FF1E74C5B100E35893 /* AccessibleMessage.swift in Sources */, + 220D386E2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift in Sources */, 2270044B1FAFA6DD0045DDC3 /* PhysicsAnimation.swift in Sources */, - 86BBA9041D5E040600FE8F16 /* NSBundle+Utils.swift in Sources */, + 86BBA9041D5E040600FE8F16 /* NSBundle+Extensions.swift in Sources */, 86BBA8FD1D5E03F800FE8F16 /* SwiftMessages.swift in Sources */, 86BBA9021D5E040600FE8F16 /* WindowViewController.swift in Sources */, 86BBA8FF1D5E040600FE8F16 /* Presenter.swift in Sources */, @@ -531,7 +551,7 @@ 86BBA9081D5E040C00FE8F16 /* Error.swift in Sources */, 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */, 86589D471D64B6E40041676C /* BaseView.swift in Sources */, - 225304622290C76E00A03ACF /* NSLayoutConstraint+Utils.swift in Sources */, + 225304622290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift in Sources */, 86BBA9071D5E040C00FE8F16 /* MarginAdjustable.swift in Sources */, 867BED211D622793005212E3 /* BackgroundViewable.swift in Sources */, ); diff --git a/SwiftMessages/CALayer+Utils.swift b/SwiftMessages/CALayer+Extensions.swift similarity index 93% rename from SwiftMessages/CALayer+Utils.swift rename to SwiftMessages/CALayer+Extensions.swift index ce0c35ff..e0b32f55 100644 --- a/SwiftMessages/CALayer+Utils.swift +++ b/SwiftMessages/CALayer+Extensions.swift @@ -1,5 +1,5 @@ // -// CALayer+Utils.swift +// CALayer+Extensions.swift // SwiftMessages // // Created by Timothy Moose on 8/3/18. diff --git a/SwiftMessages/MarginAdjustable+Animation.swift b/SwiftMessages/MarginAdjustable+Extensions.swift similarity index 98% rename from SwiftMessages/MarginAdjustable+Animation.swift rename to SwiftMessages/MarginAdjustable+Extensions.swift index 4794ea34..b6277885 100644 --- a/SwiftMessages/MarginAdjustable+Animation.swift +++ b/SwiftMessages/MarginAdjustable+Extensions.swift @@ -1,5 +1,5 @@ // -// MarginAdjustable+Animation.swift +// MarginAdjustable+Extensions.swift // SwiftMessages // // Created by Timothy Moose on 11/5/17. diff --git a/SwiftMessages/NSBundle+Utils.swift b/SwiftMessages/NSBundle+Extensions.swift similarity index 97% rename from SwiftMessages/NSBundle+Utils.swift rename to SwiftMessages/NSBundle+Extensions.swift index e79df1ad..fdfb08b7 100644 --- a/SwiftMessages/NSBundle+Utils.swift +++ b/SwiftMessages/NSBundle+Extensions.swift @@ -1,5 +1,5 @@ // -// NSBundle+Utils.swift +// NSBundle+Extensions.swift // SwiftMessages // // Created by Timothy Moose on 8/8/16. diff --git a/SwiftMessages/NSLayoutConstraint+Utils.swift b/SwiftMessages/NSLayoutConstraint+Extensions.swift similarity index 88% rename from SwiftMessages/NSLayoutConstraint+Utils.swift rename to SwiftMessages/NSLayoutConstraint+Extensions.swift index 55a3fdb3..01f678dc 100644 --- a/SwiftMessages/NSLayoutConstraint+Utils.swift +++ b/SwiftMessages/NSLayoutConstraint+Extensions.swift @@ -1,5 +1,5 @@ // -// NSLayoutConstraint+Utils.swift +// NSLayoutConstraint+Extensions.swift // SwiftMessages // // Created by Timothy Moose on 5/18/19. diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index bff7f984..e16c076e 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -98,19 +98,6 @@ class Presenter: NSObject { private weak var delegate: PresenterDelegate? private var presentationContext = PresentationContext.viewController(Weak<UIViewController>(value: nil)) - @available (iOS 13.0, *) - private var windowScene: UIWindowScene? { - switch config.presentationContext { - case .windowScene(let scene, _): return scene - default: - #if SWIFTMESSAGES_APP_EXTENSIONS - return nil - #else - return UIApplication.shared.keyWindow?.windowScene - #endif - } - } - private var interactivelyHidden = false; // MARK: - Showing and hiding @@ -245,9 +232,9 @@ class Presenter: NSObject { guard let window = maskingView.window else { return [] } let windowLevel: UIWindow.Level = { if let vc = presentationContext.viewControllerValue() as? WindowViewController { - return vc.windowLevel + return vc.config.windowLevel ?? .normal } - return UIWindow.Level.normal + return .normal }() // TODO `underNavigationBar` and `underTabBar` should look up the presentation context's hierarchy // TODO for cases where both should be true (probably not an issue for typical height messages, though). @@ -260,7 +247,7 @@ class Presenter: NSObject { return false }() if #available(iOS 11, *) { - if windowLevel > UIWindow.Level.normal { + if windowLevel > .normal { // TODO seeing `maskingView.safeAreaInsets.top` value of 20 on // iPhone 8 with status bar window level. This seems like an iOS bug since // the message view's window is above the status bar. Applying a special rule @@ -304,8 +291,8 @@ class Presenter: NSObject { private func getPresentationContext() throws -> PresentationContext { - func newWindowViewController(_ windowLevel: UIWindow.Level) -> UIViewController { - let viewController = WindowViewController.newInstance(windowLevel: windowLevel, config: config) + func newWindowViewController() -> UIViewController { + let viewController = WindowViewController.newInstance(config: config) return viewController } @@ -321,11 +308,11 @@ class Presenter: NSObject { throw SwiftMessagesError.noRootViewController } #endif - case .window(let level): - let viewController = newWindowViewController(level) + case .window: + let viewController = newWindowViewController() return .viewController(Weak(value: viewController)) - case .windowScene(_, let level): - let viewController = newWindowViewController(level) + case .windowScene: + let viewController = newWindowViewController() return .viewController(Weak(value: viewController)) case .viewController(let viewController): let viewController = viewController.sm_selectPresentationContextBottomUp(config) @@ -426,29 +413,11 @@ class Presenter: NSObject { } guard let containerView = presentationContext.viewValue() else { return } - if let windowViewController = presentationContext.viewControllerValue() as? WindowViewController { - if #available(iOS 13, *) { - windowViewController.install(becomeKey: becomeKeyWindow, scene: windowScene) - } else { - windowViewController.install(becomeKey: becomeKeyWindow) - } - } + (presentationContext.viewControllerValue() as? WindowViewController)?.install() installMaskingView(containerView: containerView) installInteractive() installAccessibility() } - - private var becomeKeyWindow: Bool { - if let becomeKeyWindow = config.becomeKeyWindow { return becomeKeyWindow } - switch config.dimMode { - case .gray, .color, .blur: - // Should become key window in modal presentation style - // for proper VoiceOver handling. - return true - case .none: - return false - } - } } diff --git a/SwiftMessages/SwiftMessages.Config+Extensions.swift b/SwiftMessages/SwiftMessages.Config+Extensions.swift new file mode 100644 index 00000000..5c7f1b54 --- /dev/null +++ b/SwiftMessages/SwiftMessages.Config+Extensions.swift @@ -0,0 +1,44 @@ +// +// SwiftMessages.Config+Extensions.swift +// SwiftMessages +// +// Created by Timothy Moose on 12/26/20. +// Copyright © 2020 SwiftKick Mobile. All rights reserved. +// + +import Foundation + +extension SwiftMessages.Config { + var windowLevel: UIWindow.Level? { + switch presentationContext { + case .window(let level): return level + case .windowScene(_, let level): return level + default: return nil + } + } + + @available (iOS 13.0, *) + var windowScene: UIWindowScene? { + switch presentationContext { + case .windowScene(let scene, _): return scene + default: + #if SWIFTMESSAGES_APP_EXTENSIONS + return nil + #else + return UIApplication.shared.keyWindow?.windowScene + #endif + } + } + + var shouldBecomeKeyWindow: Bool { + if let becomeKeyWindow = becomeKeyWindow { return becomeKeyWindow } + switch dimMode { + case .gray, .color, .blur: + // Should become key window in modal presentation style + // for proper VoiceOver handling. + return true + case .none: + return false + } + } +} diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index 0b8dab57..d5e6ba93 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -353,7 +353,7 @@ open class SwiftMessages { `WindowViewController` is needed. Use this if you need to supply a custom subclass of `WindowViewController`. */ - public var windowViewController: ((_ windowLevel: UIWindow.Level?, _ config: SwiftMessages.Config) -> WindowViewController)? + public var windowViewController: ((_ config: SwiftMessages.Config) -> WindowViewController)? /** Supply an instance of `KeyboardTrackingView` to have the message view avoid the keyboard. diff --git a/SwiftMessages/SwiftMessagesSegue.swift b/SwiftMessages/SwiftMessagesSegue.swift index b7a060c9..cccfb597 100644 --- a/SwiftMessages/SwiftMessagesSegue.swift +++ b/SwiftMessages/SwiftMessagesSegue.swift @@ -34,17 +34,19 @@ import UIKit dismiss(animated: true, completion: nil) + To display the view controller in a new window, supply an instance of `WindowViewController` as the `source`. + It is not necessary to retain `segue` because it retains itself until dismissal. However, you can retain it if you plan to `perform()` more than once. + note: Some additional details: 1. Your view controller's view will be embedded in a `SwiftMessages.BaseView` in order to - utilize some SwiftMessages features. This view can be accessed and configured via the - `SwiftMessagesSegue.messageView` property. For example, you may configure a default drop - shadow by calling `segue.messageView.configureDropShadow()`. + utilize some SwiftMessages features. This view can be accessed and configured via the + `SwiftMessagesSegue.messageView` property. For example, you may configure a default drop + shadow by calling `segue.messageView.configureDropShadow()`. 2. SwiftMessagesSegue provides static default view controller sizing based on device. - However, it is recommended that you specify sizing appropriate for your content using - one of the following methods. + However, it is recommended that you specify sizing appropriate for your content using + one of the following methods. 1. Define sufficient width and height constraints in your view controller. 2. Set `preferredContentSize` (a.k.a "Use Preferred Explicit Size" in Interface Builder's attribute inspector). Zeros are ignored, e.g. `CGSize(width: 0, height: 350)` only @@ -197,6 +199,7 @@ open class SwiftMessagesSegue: UIStoryboardSegue { }() override open func perform() { + (source as? WindowViewController)?.install() selfRetainer = self if overrideModalPresentationStyle { destination.modalPresentationStyle = .custom @@ -286,10 +289,11 @@ extension SwiftMessagesSegue: UIViewControllerTransitioningDelegate { if let completeTransition = self.hider.completeTransition { completeTransition(true) } else { - // Case where message is interinally hidden by SwiftMessages, such as with a + // Case where message is internally hidden by SwiftMessages, such as with a // dismiss gesture, rather than by view controller dismissal. source.dismiss(animated: false, completion: nil) } + (source as? WindowViewController)?.uninstall() self.selfRetainer = nil default: break } diff --git a/SwiftMessages/UIEdgeInsets+Utils.swift b/SwiftMessages/UIEdgeInsets+Extensions.swift similarity index 96% rename from SwiftMessages/UIEdgeInsets+Utils.swift rename to SwiftMessages/UIEdgeInsets+Extensions.swift index bb8420bf..19bbe4e3 100644 --- a/SwiftMessages/UIEdgeInsets+Utils.swift +++ b/SwiftMessages/UIEdgeInsets+Extensions.swift @@ -1,5 +1,5 @@ // -// UIEdgeInsets+Utils.swift +// UIEdgeInsets+Extensions.swift // SwiftMessages // // Created by Timothy Moose on 5/23/18. diff --git a/SwiftMessages/UIViewController+Utils.swift b/SwiftMessages/UIViewController+Extensions.swift similarity index 94% rename from SwiftMessages/UIViewController+Utils.swift rename to SwiftMessages/UIViewController+Extensions.swift index bc1a407d..7fbd4dd1 100644 --- a/SwiftMessages/UIViewController+Utils.swift +++ b/SwiftMessages/UIViewController+Extensions.swift @@ -1,5 +1,5 @@ // -// UIViewController+Utils.swift +// UIViewController+Extensions.swift // SwiftMessages // // Created by Timothy Moose on 8/5/16. @@ -19,7 +19,7 @@ extension UIViewController { } else if case .bottom? = topBottomStyle, let tabBarController = sm_selectTabBarControllerTopDown() { return tabBarController } - return WindowViewController.newInstance(windowLevel: self.view.window?.windowLevel, config: config) + return WindowViewController.newInstance(config: config) } fileprivate func sm_selectNavigationControllerTopDown() -> UINavigationController? { @@ -71,7 +71,7 @@ extension UIViewController { if let parent = self.parent { return parent.sm_selectPresentationContextBottomUp(config) } else { - return WindowViewController.newInstance(windowLevel: self.view.window?.windowLevel, config: config) + return WindowViewController.newInstance(config: config) } } return self diff --git a/SwiftMessages/WindowViewController.swift b/SwiftMessages/WindowViewController.swift index e186b613..78e80356 100644 --- a/SwiftMessages/WindowViewController.swift +++ b/SwiftMessages/WindowViewController.swift @@ -13,9 +13,12 @@ open class WindowViewController: UIViewController override open var shouldAutorotate: Bool { return config.shouldAutorotate } - - public init(windowLevel: UIWindow.Level?, config: SwiftMessages.Config) { - self.windowLevel = windowLevel ?? UIWindow.Level.normal + + convenience public init() { + self.init(config: SwiftMessages.Config()) + } + + public init(config: SwiftMessages.Config) { self.config = config let view = PassthroughView() let window = PassthroughWindow(hitTestView: view) @@ -23,25 +26,28 @@ open class WindowViewController: UIViewController super.init(nibName: nil, bundle: nil) self.view = view window.rootViewController = self - window.windowLevel = windowLevel ?? UIWindow.Level.normal + window.windowLevel = config.windowLevel ?? UIWindow.Level.normal if #available(iOS 13, *) { window.overrideUserInterfaceStyle = config.overrideUserInterfaceStyle } } - - func install(becomeKey: Bool) { - show(becomeKey: becomeKey) - } - @available(iOS 13, *) - func install(becomeKey: Bool, scene: UIWindowScene?) { - window?.windowScene = scene - if becomeKey { - previousKeyWindow = UIApplication.shared.keyWindow + func install() { + if #available(iOS 13, *) { + window?.windowScene = config.windowScene + if config.shouldBecomeKeyWindow { + previousKeyWindow = UIApplication.shared.keyWindow + } + show( + becomeKey: config.shouldBecomeKeyWindow, + frame: config.windowScene?.coordinateSpace.bounds + ) + } else { + show(becomeKey: config.shouldBecomeKeyWindow) } - show(becomeKey: becomeKey, frame: scene?.coordinateSpace.bounds) + } - + private func show(becomeKey: Bool, frame: CGRect? = nil) { guard let window = window else { return } window.frame = frame ?? UIScreen.main.bounds @@ -75,16 +81,14 @@ open class WindowViewController: UIViewController // MARK: - Variables - let windowLevel: UIWindow.Level - private var window: UIWindow? private weak var previousKeyWindow: UIWindow? - private let config: SwiftMessages.Config + let config: SwiftMessages.Config } extension WindowViewController { - static func newInstance(windowLevel: UIWindow.Level?, config: SwiftMessages.Config) -> WindowViewController { - return config.windowViewController?(windowLevel, config) ?? WindowViewController(windowLevel: windowLevel, config: config) + static func newInstance(config: SwiftMessages.Config) -> WindowViewController { + return config.windowViewController?(config) ?? WindowViewController(config: config) } } From 51f3adf1b979215f9de59921288098ce49d53e52 Mon Sep 17 00:00:00 2001 From: Seyed Mojtaba Hosseini Zeidabadi <ca.chairman@gmail.com> Date: Sun, 27 Dec 2020 11:50:35 +0330 Subject: [PATCH 08/77] Update ViewControllers.md Add a section to describe how to use a `WindowViewController` as the source --- ViewControllers.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ViewControllers.md b/ViewControllers.md index 0c87c946..f28d695d 100644 --- a/ViewControllers.md +++ b/ViewControllers.md @@ -23,6 +23,18 @@ let segue = SwiftMessagesSegue(identifier: nil, source: self, destination: desti segue.perform() ```` +#### Present the controller on top of all controllers + +If you don't know the presenter or you don't want to pass it as a source like when you have a completely separated message controller, you can pass a `WindowViewController` as the **source** argument of the segue. Also, You can set the `windowLevel` and other configurations by passing a config: `SwiftMessages.Config` instance as the argument of the `WindowViewController`: + +```swift +let destinationVC = ... // make a reference to a destination view controller +let sourceVC = WindowViewController(config: SwiftMessages.defaultConfig) // The `config` can be any custom `SwiftMessages.Config` instance +let segue = SwiftMessagesSegue(identifier: nil, source: self, destination: destinationVC) +... // do any configuration here +segue.perform() +``` + To dismiss, call the UIKit API on the presenting view controller: ````swift From e5d09441bd840d243119029de753e2ff06f6e0a6 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sun, 27 Dec 2020 11:10:21 -0600 Subject: [PATCH 09/77] Adjust documentation --- SwiftMessages/SwiftMessagesSegue.swift | 11 ++++++++-- ViewControllers.md | 28 ++++++++++++++++---------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/SwiftMessages/SwiftMessagesSegue.swift b/SwiftMessages/SwiftMessagesSegue.swift index cccfb597..d4cba417 100644 --- a/SwiftMessages/SwiftMessagesSegue.swift +++ b/SwiftMessages/SwiftMessagesSegue.swift @@ -34,11 +34,18 @@ import UIKit dismiss(animated: true, completion: nil) - To display the view controller in a new window, supply an instance of `WindowViewController` as the `source`. - It is not necessary to retain `segue` because it retains itself until dismissal. However, you can retain it if you plan to `perform()` more than once. + #### Present the controller on top of all controllers + + If you don't know the presenter or you don't want to pass it as a source, like when you + have a completely separated message controller, you can pass a `WindowViewController` + as the `source` argument of the segue's initializer. + + By default, the window will be shown in the current window scene at `.normal` window level. + However, these parameters can be customized by initializing the view controller with a `SwiftMessages.Config` that has the `SwiftMessages.Config.presentationContext` set to either `.window` or `.windowScene`: + + note: Some additional details: 1. Your view controller's view will be embedded in a `SwiftMessages.BaseView` in order to utilize some SwiftMessages features. This view can be accessed and configured via the diff --git a/ViewControllers.md b/ViewControllers.md index f28d695d..85b63106 100644 --- a/ViewControllers.md +++ b/ViewControllers.md @@ -23,26 +23,32 @@ let segue = SwiftMessagesSegue(identifier: nil, source: self, destination: desti segue.perform() ```` +To dismiss, call the UIKit API on the presenting view controller: + +````swift +dismiss(animated: true, completion: nil) +```` + +It is not necessary to retain `segue` because it retains itself until dismissal. However, you can retain it if you plan to `perform()` more than once. + #### Present the controller on top of all controllers -If you don't know the presenter or you don't want to pass it as a source like when you have a completely separated message controller, you can pass a `WindowViewController` as the **source** argument of the segue. Also, You can set the `windowLevel` and other configurations by passing a config: `SwiftMessages.Config` instance as the argument of the `WindowViewController`: +If you don't know the presenter or you don't want to pass it as a source, like when you +have a completely separated message controller, you can pass a `WindowViewController` +as the `source` argument of the segue's initializer. + +By default, the window will be shown in the current window scene at `.normal` window level. +However, these parameters can be customized by initializing the view controller with a `SwiftMessages.Config` that has the `SwiftMessages.Config.presentationContext` set to either `.window` or `.windowScene`: ```swift let destinationVC = ... // make a reference to a destination view controller -let sourceVC = WindowViewController(config: SwiftMessages.defaultConfig) // The `config` can be any custom `SwiftMessages.Config` instance +var config = SwiftMessages.defaultConfig +config.presentationContext = .windowScene(...) // specify the window properties +let sourceVC = WindowViewController(config: config) let segue = SwiftMessagesSegue(identifier: nil, source: self, destination: destinationVC) -... // do any configuration here segue.perform() ``` -To dismiss, call the UIKit API on the presenting view controller: - -````swift -dismiss(animated: true, completion: nil) -```` - -It is not necessary to retain `segue` because it retains itself until dismissal. However, you can retain it if you plan to `perform()` more than once. - ### Configuration `SwiftMessagesSegue` generally requires configuration to achieve specific layouts and optional behaviors. There are a few good ways to do this: From 03a5812870cd96bac71fbfac4a5c345d753b8ea0 Mon Sep 17 00:00:00 2001 From: Eric Marchand <59135882+mesopelagique@users.noreply.github.com> Date: Sat, 2 Jan 2021 17:33:49 +0100 Subject: [PATCH 10/77] Fix compilation with SwiftPM using exact import (#450) --- SwiftMessages/SwiftMessages.Config+Extensions.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftMessages/SwiftMessages.Config+Extensions.swift b/SwiftMessages/SwiftMessages.Config+Extensions.swift index 5c7f1b54..2dfe7ae4 100644 --- a/SwiftMessages/SwiftMessages.Config+Extensions.swift +++ b/SwiftMessages/SwiftMessages.Config+Extensions.swift @@ -6,7 +6,7 @@ // Copyright © 2020 SwiftKick Mobile. All rights reserved. // -import Foundation +import UIKit extension SwiftMessages.Config { var windowLevel: UIWindow.Level? { From 40551ba1846a7b65c8339b94db9fc3ef84a36584 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sun, 17 Jan 2021 14:15:46 -0600 Subject: [PATCH 11/77] Fix app extension crash --- SwiftMessages/WindowViewController.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SwiftMessages/WindowViewController.swift b/SwiftMessages/WindowViewController.swift index 78e80356..65b85854 100644 --- a/SwiftMessages/WindowViewController.swift +++ b/SwiftMessages/WindowViewController.swift @@ -36,7 +36,9 @@ open class WindowViewController: UIViewController if #available(iOS 13, *) { window?.windowScene = config.windowScene if config.shouldBecomeKeyWindow { + #if !SWIFTMESSAGES_APP_EXTENSIONS previousKeyWindow = UIApplication.shared.keyWindow + #endif } show( becomeKey: config.shouldBecomeKeyWindow, @@ -45,7 +47,6 @@ open class WindowViewController: UIViewController } else { show(becomeKey: config.shouldBecomeKeyWindow) } - } private func show(becomeKey: Bool, frame: CGRect? = nil) { From 74de8becfd5b77bcdfa87da4eedac7f03e7d243a Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sun, 17 Jan 2021 14:19:58 -0600 Subject: [PATCH 12/77] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 562de4be..239b08f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ an instance of `WindowViewController` as the segue's source view controller. The `windowLevel` is no longer accepted as an argument because the `config` parameter should specify the window level in the `presentationContext` property. +### Fixes + +* #451 Fix app extension crash + ## 8.0.5 ### Fixes From fbfbf3c1e6b0d152be878627e7f54904d921a7f6 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 13 Feb 2021 17:45:37 -0600 Subject: [PATCH 13/77] BoundaryInsets prototype --- SwiftMessages.podspec | 6 +-- SwiftMessages.xcodeproj/project.pbxproj | 12 +++-- SwiftMessages/Animator.swift | 8 +++- SwiftMessages/BaseView.swift | 9 +++- SwiftMessages/BoundaryInsets.swift | 41 ++++++++++++++++ SwiftMessages/TopBottomAnimation.swift | 63 ++++++++++++++++++++++++- 6 files changed, 127 insertions(+), 12 deletions(-) create mode 100644 SwiftMessages/BoundaryInsets.swift diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 22b2d781..130843c5 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,14 +1,14 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.0.0' + spec.version = '9.1.0' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } spec.summary = 'A very flexible message bar for iOS written in Swift.' spec.source = {:git => 'https://github.com/SwiftKickMobile/SwiftMessages.git', :tag => spec.version} - spec.platform = :ios, '9.0' + spec.platform = :ios, '11.0' spec.swift_version = '5.0' - spec.ios.deployment_target = '9.0' + spec.ios.deployment_target = '11.0' spec.framework = 'UIKit' spec.requires_arc = true spec.default_subspec = 'App' diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 4eef9ad5..6cff54bf 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -51,6 +51,7 @@ 228DF5681FAD0806004F8A39 /* infoIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */; }; 228DF5691FAD0806004F8A39 /* successIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5481FAD0805004F8A39 /* successIconLight.png */; }; 228DF56A1FAD0806004F8A39 /* infoIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */; }; + 2290944825D88A05002E8111 /* BoundaryInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290944725D88A05002E8111 /* BoundaryInsets.swift */; }; 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */; }; @@ -137,6 +138,7 @@ 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = infoIconSubtle.png; path = Resources/infoIconSubtle.png; sourceTree = "<group>"; }; 228DF5481FAD0805004F8A39 /* successIconLight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = successIconLight.png; path = Resources/successIconLight.png; sourceTree = "<group>"; }; 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; + 2290944725D88A05002E8111 /* BoundaryInsets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoundaryInsets.swift; sourceTree = "<group>"; }; 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = "<group>"; }; @@ -298,6 +300,7 @@ 22E307FE1E74C5B100E35893 /* AccessibleMessage.swift */, 86AAF82A1D580DD70031EE32 /* Error.swift */, 2298C2061EE480D000E2DDC1 /* Animator.swift */, + 2290944725D88A05002E8111 /* BoundaryInsets.swift */, 2298C2041EE47DC900E2DDC1 /* Weak.swift */, 22F27950210CE25900273E7F /* CornerRoundingView.swift */, 225304652293000C00A03ACF /* KeyboardTrackingView.swift */, @@ -530,6 +533,7 @@ 86BBA8FC1D5E03F100FE8F16 /* MessageView.swift in Sources */, 86BBA9061D5E040C00FE8F16 /* Identifiable.swift in Sources */, 22F27951210CE25900273E7F /* CornerRoundingView.swift in Sources */, + 2290944825D88A05002E8111 /* BoundaryInsets.swift in Sources */, 86BBA9011D5E040600FE8F16 /* PassthroughWindow.swift in Sources */, 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */, 86BBA9031D5E040600FE8F16 /* UIViewController+Extensions.swift in Sources */, @@ -625,7 +629,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.1; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -677,7 +681,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.1; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -699,7 +703,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; INFOPLIST_FILE = SwiftMessages/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -727,7 +731,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; INFOPLIST_FILE = SwiftMessages/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/SwiftMessages/Animator.swift b/SwiftMessages/Animator.swift index 35981f09..b4ca56f6 100644 --- a/SwiftMessages/Animator.swift +++ b/SwiftMessages/Animator.swift @@ -44,13 +44,17 @@ public struct SafeZoneConflicts: OptionSet { } public class AnimationContext { - public let messageView: UIView public let containerView: UIView public let safeZoneConflicts: SafeZoneConflicts public let interactiveHide: Bool - init(messageView: UIView, containerView: UIView, safeZoneConflicts: SafeZoneConflicts, interactiveHide: Bool) { + internal init( + messageView: UIView, + containerView: UIView, + safeZoneConflicts: SafeZoneConflicts, + interactiveHide: Bool + ) { self.messageView = messageView self.containerView = containerView self.safeZoneConflicts = safeZoneConflicts diff --git a/SwiftMessages/BaseView.swift b/SwiftMessages/BaseView.swift index 9480b87d..93c9df96 100644 --- a/SwiftMessages/BaseView.swift +++ b/SwiftMessages/BaseView.swift @@ -14,7 +14,7 @@ import UIKit of the optional SwiftMessages protocols and provides some convenience functions and a configurable tap handler. Message views do not need to inherit from `BaseVew`. */ -open class BaseView: UIView, BackgroundViewable, MarginAdjustable { +open class BaseView: UIView, BackgroundViewable, MarginAdjustable, HasBoundaryInsets { /* MARK: - IB outlets @@ -229,6 +229,13 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable { @IBInspectable open var bounceAnimationOffset: CGFloat = 5 + /* + MARK: - HasBoundaryInsets + */ + + /// Configure the view's inset from the superview or save area + public var boundaryInsets = BoundaryInsets() + /* MARK: - Setting the height */ diff --git a/SwiftMessages/BoundaryInsets.swift b/SwiftMessages/BoundaryInsets.swift new file mode 100644 index 00000000..f3d1da60 --- /dev/null +++ b/SwiftMessages/BoundaryInsets.swift @@ -0,0 +1,41 @@ +// +// BoundaryInsets.swift +// SwiftMessages +// +// Created by Timothy Moose on 2/13/21. +// Copyright © 2021 SwiftKick Mobile. All rights reserved. +// + +import QuartzCore + +public protocol HasBoundaryInsets { + var boundaryInsets: BoundaryInsets { get } +} + +/// Insets used for specifying view sizing options in terms of insets from the containing superview or safe area. +public struct BoundaryInsets { + + public enum Boundary { + case superview + case safeArea + case margin + } + + /// An abstract dimension used for specifying the message view's size + public enum Dimension { + + /// Dimensions should be determined automatically + case automatic + + /// Dimension should maintain an absolute margin to the given boundary. + case absoluteMargin(CGFloat, with: Boundary) + + /// Dimension should maintain a relative margin to the given boundary. + case relativeMargin(CGFloat, with: Boundary) + } + + public var top: Dimension = .automatic + public var bottom: Dimension = .automatic + public var leading: Dimension = .automatic + public var trailing: Dimension = .automatic +} diff --git a/SwiftMessages/TopBottomAnimation.swift b/SwiftMessages/TopBottomAnimation.swift index d9f1f3a4..0a7dc19e 100644 --- a/SwiftMessages/TopBottomAnimation.swift +++ b/SwiftMessages/TopBottomAnimation.swift @@ -19,6 +19,8 @@ public class TopBottomAnimation: NSObject, Animator { public let style: Style + open var heightDimension: Dimension? + open var showDuration: TimeInterval = 0.4 open var hideDuration: TimeInterval = 0.2 @@ -90,11 +92,68 @@ public class TopBottomAnimation: NSObject, Animator { container.addSubview(view) view.leadingAnchor.constraint(equalTo: container.leadingAnchor).isActive = true view.trailingAnchor.constraint(equalTo: container.trailingAnchor).isActive = true + let boundaryInsets = (view as? HasBoundaryInsets)?.boundaryInsets ?? BoundaryInsets() switch style { case .top: - view.topAnchor.constraint(equalTo: container.topAnchor, constant: -bounceOffset).with(priority: UILayoutPriority(200)).isActive = true + view.topAnchor.constraint( + equalTo: container.topAnchor, + constant: -bounceOffset + ).with(priority: .defaultHigh).isActive = true + switch boundaryInsets.bottom { + case .automatic: + break + case .absoluteMargin(let dimension, let boundary): + let otherAnchor: NSLayoutYAxisAnchor + switch boundary { + case .superview: otherAnchor = container.bottomAnchor + case .safeArea: otherAnchor = container.safeAreaLayoutGuide.bottomAnchor + case .margin: otherAnchor = container.layoutMarginsGuide.bottomAnchor + } + view.bottomAnchor.constraint(equalTo: otherAnchor, constant: -dimension) + .with(priority: .defaultHigh) + .isActive = true + case .relativeMargin(let dimension, let boundary): + let otherAnchor: NSLayoutDimension! + switch boundary { + case .superview: otherAnchor = container.heightAnchor + case .safeArea: otherAnchor = container.safeAreaLayoutGuide.heightAnchor + case .margin: otherAnchor = container.layoutMarginsGuide.heightAnchor + } + view.heightAnchor.constraint( + equalTo: otherAnchor, + multiplier: 1 - dimension + ).with(priority: .defaultHigh).isActive = true + } case .bottom: - view.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: bounceOffset).with(priority: UILayoutPriority(200)).isActive = true + view.bottomAnchor.constraint( + equalTo: container.bottomAnchor, + constant: bounceOffset + ).with(priority: .defaultHigh).isActive = true + switch boundaryInsets.top { + case .automatic: + break + case .absoluteMargin(let dimension, let boundary): + let otherAnchor: NSLayoutYAxisAnchor + switch boundary { + case .superview: otherAnchor = container.topAnchor + case .safeArea: otherAnchor = container.safeAreaLayoutGuide.topAnchor + case .margin: otherAnchor = container.layoutMarginsGuide.topAnchor + } + view.topAnchor.constraint(equalTo: otherAnchor, constant: dimension) + .with(priority: .defaultHigh) + .isActive = true + case .relativeMargin(let dimension, let boundary): + let otherAnchor: NSLayoutDimension! + switch boundary { + case .superview: otherAnchor = container.heightAnchor + case .safeArea: otherAnchor = container.safeAreaLayoutGuide.heightAnchor + case .margin: otherAnchor = container.layoutMarginsGuide.heightAnchor + } + view.heightAnchor.constraint( + equalTo: otherAnchor, + multiplier: 1 - dimension + ).with(priority: .defaultHigh).isActive = true + } } // Important to layout now in order to get the right safe area insets container.layoutIfNeeded() From 0ee863a30c17b907d2f0290f277a50c949bb48b1 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 13 Feb 2021 17:56:50 -0600 Subject: [PATCH 14/77] Keep support for iOS 10 --- SwiftMessages.podspec | 4 ++-- SwiftMessages.xcodeproj/project.pbxproj | 8 +++---- SwiftMessages/TopBottomAnimation.swift | 28 +++++++++++++++++++++---- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 130843c5..aad0b316 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -6,9 +6,9 @@ Pod::Spec.new do |spec| spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } spec.summary = 'A very flexible message bar for iOS written in Swift.' spec.source = {:git => 'https://github.com/SwiftKickMobile/SwiftMessages.git', :tag => spec.version} - spec.platform = :ios, '11.0' + spec.platform = :ios, '10.0' spec.swift_version = '5.0' - spec.ios.deployment_target = '11.0' + spec.ios.deployment_target = '10.0' spec.framework = 'UIKit' spec.requires_arc = true spec.default_subspec = 'App' diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 6cff54bf..f60b5a73 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -629,7 +629,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -681,7 +681,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -703,7 +703,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; INFOPLIST_FILE = SwiftMessages/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -731,7 +731,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; INFOPLIST_FILE = SwiftMessages/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/SwiftMessages/TopBottomAnimation.swift b/SwiftMessages/TopBottomAnimation.swift index 0a7dc19e..78c0d84a 100644 --- a/SwiftMessages/TopBottomAnimation.swift +++ b/SwiftMessages/TopBottomAnimation.swift @@ -106,7 +106,12 @@ public class TopBottomAnimation: NSObject, Animator { let otherAnchor: NSLayoutYAxisAnchor switch boundary { case .superview: otherAnchor = container.bottomAnchor - case .safeArea: otherAnchor = container.safeAreaLayoutGuide.bottomAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = container.safeAreaLayoutGuide.bottomAnchor + } else { + otherAnchor = container.layoutMarginsGuide.bottomAnchor + } case .margin: otherAnchor = container.layoutMarginsGuide.bottomAnchor } view.bottomAnchor.constraint(equalTo: otherAnchor, constant: -dimension) @@ -116,7 +121,12 @@ public class TopBottomAnimation: NSObject, Animator { let otherAnchor: NSLayoutDimension! switch boundary { case .superview: otherAnchor = container.heightAnchor - case .safeArea: otherAnchor = container.safeAreaLayoutGuide.heightAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = container.safeAreaLayoutGuide.heightAnchor + } else { + otherAnchor = container.layoutMarginsGuide.heightAnchor + } case .margin: otherAnchor = container.layoutMarginsGuide.heightAnchor } view.heightAnchor.constraint( @@ -136,7 +146,12 @@ public class TopBottomAnimation: NSObject, Animator { let otherAnchor: NSLayoutYAxisAnchor switch boundary { case .superview: otherAnchor = container.topAnchor - case .safeArea: otherAnchor = container.safeAreaLayoutGuide.topAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = container.safeAreaLayoutGuide.topAnchor + } else { + otherAnchor = container.layoutMarginsGuide.topAnchor + } case .margin: otherAnchor = container.layoutMarginsGuide.topAnchor } view.topAnchor.constraint(equalTo: otherAnchor, constant: dimension) @@ -146,7 +161,12 @@ public class TopBottomAnimation: NSObject, Animator { let otherAnchor: NSLayoutDimension! switch boundary { case .superview: otherAnchor = container.heightAnchor - case .safeArea: otherAnchor = container.safeAreaLayoutGuide.heightAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = container.safeAreaLayoutGuide.heightAnchor + } else { + otherAnchor = container.layoutMarginsGuide.heightAnchor + } case .margin: otherAnchor = container.layoutMarginsGuide.heightAnchor } view.heightAnchor.constraint( From 46ad7377bc1a4191e9967f5f083b8a362510468b Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 13 Feb 2021 18:19:10 -0600 Subject: [PATCH 15/77] Consider nav bar behavior in preferred content size --- SwiftMessages/SwiftMessagesSegue.swift | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/SwiftMessages/SwiftMessagesSegue.swift b/SwiftMessages/SwiftMessagesSegue.swift index d4cba417..8fa696ed 100644 --- a/SwiftMessages/SwiftMessagesSegue.swift +++ b/SwiftMessages/SwiftMessagesSegue.swift @@ -359,8 +359,16 @@ extension SwiftMessagesSegue { segue.messageView.installBackgroundVerticalView(segue.containerView) } let toVC = transitionContext.viewController(forKey: .to) + + // Nav controller automatically includes height of nav bar in, + // the `preferredContentSize` and our logic needs to consider this. + var navInset: CGFloat = 0 + if let nav = toVC as? UINavigationController { + navInset = nav.navigationBar.frame.height + } + if let preferredHeight = toVC?.preferredContentSize.height, - preferredHeight > 0 { + preferredHeight - navInset > 0 { segue.containerView.heightAnchor.constraint(equalToConstant: preferredHeight).with(priority: UILayoutPriority(rawValue: 951)).isActive = true } if let preferredWidth = toVC?.preferredContentSize.width, From 5b5973b5249a7228fc798ebe72f983a27517adb4 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sun, 14 Feb 2021 15:57:00 -0600 Subject: [PATCH 16/77] Add sizing options --- Demo/Demo/ViewControllersViewController.swift | 1 + SwiftMessages.xcodeproj/project.pbxproj | 16 +- SwiftMessages/Animator.swift | 4 +- SwiftMessages/BaseView.swift | 107 ++++----- SwiftMessages/BoundaryInsets.swift | 41 ---- SwiftMessages/MaskingView.swift | 213 +++++++++++++++++- SwiftMessages/MessageSizeable.swift | 65 ++++++ SwiftMessages/MessageSizing.swift | 13 ++ SwiftMessages/Resources/CardView.xib | 25 +- SwiftMessages/Resources/CenteredView.xib | 27 +-- SwiftMessages/Resources/TabView.xib | 25 +- SwiftMessages/SwiftMessagesSegue.swift | 8 +- SwiftMessages/TopBottomAnimation.swift | 104 ++------- .../UILayoutPriority+Extensions.swift | 18 ++ 14 files changed, 404 insertions(+), 263 deletions(-) delete mode 100644 SwiftMessages/BoundaryInsets.swift create mode 100644 SwiftMessages/MessageSizeable.swift create mode 100644 SwiftMessages/MessageSizing.swift create mode 100644 SwiftMessages/UILayoutPriority+Extensions.swift diff --git a/Demo/Demo/ViewControllersViewController.swift b/Demo/Demo/ViewControllersViewController.swift index 6fb14eeb..f3339ebc 100644 --- a/Demo/Demo/ViewControllersViewController.swift +++ b/Demo/Demo/ViewControllersViewController.swift @@ -47,6 +47,7 @@ class SwiftMessagesBottomCardSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) configure(layout: .bottomCard) + messageView.messageSize.width = .relative(0.75, from: .superview) } } diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index f60b5a73..1efdfa4c 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -51,7 +51,9 @@ 228DF5681FAD0806004F8A39 /* infoIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */; }; 228DF5691FAD0806004F8A39 /* successIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5481FAD0805004F8A39 /* successIconLight.png */; }; 228DF56A1FAD0806004F8A39 /* infoIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */; }; - 2290944825D88A05002E8111 /* BoundaryInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290944725D88A05002E8111 /* BoundaryInsets.swift */; }; + 2290944825D88A05002E8111 /* MessageSizeable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290944725D88A05002E8111 /* MessageSizeable.swift */; }; + 2290957825D9BC9F002E8111 /* MessageSizing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290957725D9BC9F002E8111 /* MessageSizing.swift */; }; + 2290958125D9D407002E8111 /* UILayoutPriority+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */; }; 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */; }; @@ -138,7 +140,9 @@ 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = infoIconSubtle.png; path = Resources/infoIconSubtle.png; sourceTree = "<group>"; }; 228DF5481FAD0805004F8A39 /* successIconLight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = successIconLight.png; path = Resources/successIconLight.png; sourceTree = "<group>"; }; 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; - 2290944725D88A05002E8111 /* BoundaryInsets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoundaryInsets.swift; sourceTree = "<group>"; }; + 2290944725D88A05002E8111 /* MessageSizeable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSizeable.swift; sourceTree = "<group>"; }; + 2290957725D9BC9F002E8111 /* MessageSizing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSizing.swift; sourceTree = "<group>"; }; + 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILayoutPriority+Extensions.swift"; sourceTree = "<group>"; }; 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = "<group>"; }; @@ -211,6 +215,7 @@ children = ( 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */, 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */, + 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */, ); name = Extensions; sourceTree = "<group>"; @@ -296,11 +301,12 @@ 8644955C1D4FAF7C0056EB2A /* WindowViewController.swift */, 867BED201D622793005212E3 /* BackgroundViewable.swift */, 864495551D4F7C390056EB2A /* Identifiable.swift */, + 2290944725D88A05002E8111 /* MessageSizeable.swift */, + 2290957725D9BC9F002E8111 /* MessageSizing.swift */, 86AAF81D1D5549680031EE32 /* MarginAdjustable.swift */, 22E307FE1E74C5B100E35893 /* AccessibleMessage.swift */, 86AAF82A1D580DD70031EE32 /* Error.swift */, 2298C2061EE480D000E2DDC1 /* Animator.swift */, - 2290944725D88A05002E8111 /* BoundaryInsets.swift */, 2298C2041EE47DC900E2DDC1 /* Weak.swift */, 22F27950210CE25900273E7F /* CornerRoundingView.swift */, 225304652293000C00A03ACF /* KeyboardTrackingView.swift */, @@ -533,7 +539,7 @@ 86BBA8FC1D5E03F100FE8F16 /* MessageView.swift in Sources */, 86BBA9061D5E040C00FE8F16 /* Identifiable.swift in Sources */, 22F27951210CE25900273E7F /* CornerRoundingView.swift in Sources */, - 2290944825D88A05002E8111 /* BoundaryInsets.swift in Sources */, + 2290944825D88A05002E8111 /* MessageSizeable.swift in Sources */, 86BBA9011D5E040600FE8F16 /* PassthroughWindow.swift in Sources */, 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */, 86BBA9031D5E040600FE8F16 /* UIViewController+Extensions.swift in Sources */, @@ -556,8 +562,10 @@ 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */, 86589D471D64B6E40041676C /* BaseView.swift in Sources */, 225304622290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift in Sources */, + 2290957825D9BC9F002E8111 /* MessageSizing.swift in Sources */, 86BBA9071D5E040C00FE8F16 /* MarginAdjustable.swift in Sources */, 867BED211D622793005212E3 /* BackgroundViewable.swift in Sources */, + 2290958125D9D407002E8111 /* UILayoutPriority+Extensions.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/SwiftMessages/Animator.swift b/SwiftMessages/Animator.swift index b4ca56f6..d3ec0af7 100644 --- a/SwiftMessages/Animator.swift +++ b/SwiftMessages/Animator.swift @@ -45,13 +45,13 @@ public struct SafeZoneConflicts: OptionSet { public class AnimationContext { public let messageView: UIView - public let containerView: UIView + public let containerView: UIView & MessageSizing public let safeZoneConflicts: SafeZoneConflicts public let interactiveHide: Bool internal init( messageView: UIView, - containerView: UIView, + containerView: UIView & MessageSizing, safeZoneConflicts: SafeZoneConflicts, interactiveHide: Bool ) { diff --git a/SwiftMessages/BaseView.swift b/SwiftMessages/BaseView.swift index 93c9df96..2ae86a45 100644 --- a/SwiftMessages/BaseView.swift +++ b/SwiftMessages/BaseView.swift @@ -14,7 +14,7 @@ import UIKit of the optional SwiftMessages protocols and provides some convenience functions and a configurable tap handler. Message views do not need to inherit from `BaseVew`. */ -open class BaseView: UIView, BackgroundViewable, MarginAdjustable, HasBoundaryInsets { +open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeable { /* MARK: - IB outlets @@ -97,20 +97,28 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, HasBoundaryIn } addSubview(backgroundView) self.backgroundView = backgroundView - backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor).with(priority: UILayoutPriority(rawValue: 950)).isActive = true - backgroundView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: insets.top).with(priority: UILayoutPriority(rawValue: 900)).isActive = true - backgroundView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor, constant: -insets.bottom).with(priority: UILayoutPriority(rawValue: 900)).isActive = true - backgroundView.heightAnchor.constraint(equalToConstant: 350).with(priority: UILayoutPriority(rawValue: 200)).isActive = true - layoutConstraints = [ - backgroundView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: insets.left).with(priority: UILayoutPriority(rawValue: 900)), - backgroundView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: -insets.right).with(priority: UILayoutPriority(rawValue: 900)), - ] - regularWidthLayoutConstraints = [ - backgroundView.leftAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.leftAnchor, constant: insets.left).with(priority: UILayoutPriority(rawValue: 900)), - backgroundView.rightAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.rightAnchor, constant: -insets.right).with(priority: UILayoutPriority(rawValue: 900)), - backgroundView.widthAnchor.constraint(lessThanOrEqualToConstant: 500).with(priority: UILayoutPriority(rawValue: 950)), - backgroundView.widthAnchor.constraint(equalToConstant: 500).with(priority: UILayoutPriority(rawValue: 200)), - ] + NSLayoutConstraint.activate([ + backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor) + .with(priority: .belowMessageSizeable), + backgroundView.topAnchor.constraint( + equalTo: layoutMarginsGuide.topAnchor, + constant: insets.top + ).with(priority: .belowMessageSizeable), + backgroundView.bottomAnchor.constraint( + equalTo: layoutMarginsGuide.bottomAnchor, + constant: -insets.bottom + ).with(priority: .belowMessageSizeable), + backgroundView.heightAnchor.constraint(equalToConstant: 350) + .with(priority: UILayoutPriority(rawValue: 200)), + backgroundView.leftAnchor.constraint( + equalTo: layoutMarginsGuide.leftAnchor, + constant: insets.left + ).with(priority: .belowMessageSizeable), + backgroundView.rightAnchor.constraint( + equalTo: layoutMarginsGuide.rightAnchor, + constant: -insets.right + ).with(priority: .belowMessageSizeable), + ]) installTapRecognizer() } @@ -131,20 +139,23 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, HasBoundaryIn } addSubview(backgroundView) self.backgroundView = backgroundView - backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor).with(priority: UILayoutPriority(rawValue: 950)).isActive = true - backgroundView.topAnchor.constraint(equalTo: topAnchor, constant: insets.top).with(priority: UILayoutPriority(rawValue: 1000)).isActive = true - backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -insets.bottom).with(priority: UILayoutPriority(rawValue: 1000)).isActive = true - backgroundView.heightAnchor.constraint(equalToConstant: 350).with(priority: UILayoutPriority(rawValue: 200)).isActive = true - layoutConstraints = [ - backgroundView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: insets.left).with(priority: UILayoutPriority(rawValue: 900)), - backgroundView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: -insets.right).with(priority: UILayoutPriority(rawValue: 900)), - ] - regularWidthLayoutConstraints = [ - backgroundView.leftAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.leftAnchor, constant: insets.left).with(priority: UILayoutPriority(rawValue: 900)), - backgroundView.rightAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.rightAnchor, constant: -insets.right).with(priority: UILayoutPriority(rawValue: 900)), - backgroundView.widthAnchor.constraint(lessThanOrEqualToConstant: 500).with(priority: UILayoutPriority(rawValue: 950)), - backgroundView.widthAnchor.constraint(equalToConstant: 500).with(priority: UILayoutPriority(rawValue: 200)), - ] + NSLayoutConstraint.activate([ + backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor) + .with(priority: .belowMessageSizeable), + backgroundView.topAnchor.constraint(equalTo: topAnchor, constant: insets.top) + .with(priority: .required), + backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -insets.bottom) + .with(priority: .required), + backgroundView.heightAnchor.constraint(equalToConstant: 350) + .with(priority: UILayoutPriority(rawValue: 200)), + backgroundView.leftAnchor.constraint( + equalTo: layoutMarginsGuide.leftAnchor, constant: insets.left + ).with(priority: .belowMessageSizeable), + backgroundView.rightAnchor.constraint( + equalTo: layoutMarginsGuide.rightAnchor, + constant: -insets.right + ).with(priority: .belowMessageSizeable), + ]) installTapRecognizer() } @@ -190,6 +201,14 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, HasBoundaryIn return super.point(inside: point, with: event) } + // MARK: - MessageSizeable + + /// Configure the view's size + public var messageSize = MessageSize() + + /// Configure the view's insets from the container + public var messageInsets = MessageInsets() + /* MARK: - MarginAdjustable @@ -229,13 +248,6 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, HasBoundaryIn @IBInspectable open var bounceAnimationOffset: CGFloat = 5 - /* - MARK: - HasBoundaryInsets - */ - - /// Configure the view's inset from the superview or save area - public var boundaryInsets = BoundaryInsets() - /* MARK: - Setting the height */ @@ -264,29 +276,6 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, HasBoundaryIn } private var backgroundHeightConstraint: NSLayoutConstraint? - - /* - Mark: - Layout - */ - - open override func updateConstraints() { - super.updateConstraints() - let on: [NSLayoutConstraint] - let off: [NSLayoutConstraint] - switch traitCollection.horizontalSizeClass { - case .regular: - on = regularWidthLayoutConstraints - off = layoutConstraints - default: - on = layoutConstraints - off = regularWidthLayoutConstraints - } - on.forEach { $0.isActive = true } - off.forEach { $0.isActive = false } - } - - private var layoutConstraints: [NSLayoutConstraint] = [] - private var regularWidthLayoutConstraints: [NSLayoutConstraint] = [] } /* diff --git a/SwiftMessages/BoundaryInsets.swift b/SwiftMessages/BoundaryInsets.swift deleted file mode 100644 index f3d1da60..00000000 --- a/SwiftMessages/BoundaryInsets.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// BoundaryInsets.swift -// SwiftMessages -// -// Created by Timothy Moose on 2/13/21. -// Copyright © 2021 SwiftKick Mobile. All rights reserved. -// - -import QuartzCore - -public protocol HasBoundaryInsets { - var boundaryInsets: BoundaryInsets { get } -} - -/// Insets used for specifying view sizing options in terms of insets from the containing superview or safe area. -public struct BoundaryInsets { - - public enum Boundary { - case superview - case safeArea - case margin - } - - /// An abstract dimension used for specifying the message view's size - public enum Dimension { - - /// Dimensions should be determined automatically - case automatic - - /// Dimension should maintain an absolute margin to the given boundary. - case absoluteMargin(CGFloat, with: Boundary) - - /// Dimension should maintain a relative margin to the given boundary. - case relativeMargin(CGFloat, with: Boundary) - } - - public var top: Dimension = .automatic - public var bottom: Dimension = .automatic - public var leading: Dimension = .automatic - public var trailing: Dimension = .automatic -} diff --git a/SwiftMessages/MaskingView.swift b/SwiftMessages/MaskingView.swift index 0ce4c428..889ac9de 100644 --- a/SwiftMessages/MaskingView.swift +++ b/SwiftMessages/MaskingView.swift @@ -8,8 +8,31 @@ import UIKit +// TODO SIZE - need a version of this logic to limit views to 500pt on regular size class by default. +// regularWidthLayoutConstraints = [ +// backgroundView.leftAnchor.constraint( +// greaterThanOrEqualTo: layoutMarginsGuide.leftAnchor, +// constant: insets.left +// ).with(priority: .belowMessageSizeable), +// backgroundView.rightAnchor.constraint( +// lessThanOrEqualTo: layoutMarginsGuide.rightAnchor, +// constant: -insets.right +// ).with(priority: .belowMessageSizeable), +// backgroundView.widthAnchor.constraint(lessThanOrEqualToConstant: 500) +// .with(priority: .belowMessageSizeable), +// backgroundView.widthAnchor.constraint(equalToConstant: 500) +// .with(priority: UILayoutPriority(rawValue: 200)), +// ] -class MaskingView: PassthroughView { +class MaskingView: PassthroughView, MessageSizing { + + func install(sizeableView: MessageSizeable & UIView) { + self.sizeableView?.removeFromSuperview() + self.sizeableView = sizeableView + sizeableView.translatesAutoresizingMaskIntoConstraints = false + addSubview(sizeableView) + setNeedsUpdateConstraints() + } func install(keyboardTrackingView: KeyboardTrackingView) { self.keyboardTrackingView = keyboardTrackingView @@ -50,15 +73,30 @@ class MaskingView: PassthroughView { init() { super.init(frame: CGRect.zero) - clipsToBounds = true + postInit() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) + postInit() + } + + private func postInit() { clipsToBounds = true + addLayoutGuide(messageInsetsGuide) + } + + override var bounds: CGRect { + didSet { + guard bounds != oldValue else { return } + setNeedsUpdateConstraints() + } } private var keyboardTrackingView: KeyboardTrackingView? + private var cachedConstraints: [NSLayoutConstraint] = [] + private let messageInsetsGuide = UILayoutGuide() + private var sizeableView: (MessageSizeable & UIView)? override func addSubview(_ view: UIView) { super.addSubview(view) @@ -67,4 +105,175 @@ class MaskingView: PassthroughView { view != backgroundView else { return } keyboardTrackingView.topAnchor.constraint(greaterThanOrEqualTo: view.bottomAnchor).with(priority: UILayoutPriority(250)).isActive = true } + + override func updateConstraints() { + super.updateConstraints() + NSLayoutConstraint.deactivate(cachedConstraints) + cachedConstraints = [] + if let top = sizeableView?.messageInsets.top { update(top: top) } + if let bottom = sizeableView?.messageInsets.bottom { update(bottom: bottom) } + if let leading = sizeableView?.messageInsets.leading { update(leading: leading) } + if let trailing = sizeableView?.messageInsets.trailing { update(trailing: trailing) } + if let sizeableView = sizeableView { update(sizeableView: sizeableView) } + NSLayoutConstraint.activate(cachedConstraints) + } + + private func update(top: MessageInsets.Dimension) { + let length: CGFloat + switch top { + case .absoluteMargin(let dimension, _): + length = dimension + case .relativeMargin(let percentage, _): + length = bounds.height * percentage + } + let otherAnchor: NSLayoutYAxisAnchor + switch top.boundary { + case .superview: otherAnchor = topAnchor + case .margin: otherAnchor = layoutMarginsGuide.topAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = safeAreaLayoutGuide.topAnchor + } else { + otherAnchor = layoutMarginsGuide.topAnchor + } + } + cachedConstraints.append( + messageInsetsGuide.topAnchor.constraint(equalTo: otherAnchor, constant: length) + .with(priority: .messageInset) + ) + } + + private func update(bottom: MessageInsets.Dimension) { + let length: CGFloat + switch bottom { + case .absoluteMargin(let dimension, _): + length = dimension + case .relativeMargin(let percentage, _): + length = bounds.height * percentage + } + let otherAnchor: NSLayoutYAxisAnchor + switch bottom.boundary { + case .superview: otherAnchor = bottomAnchor + case .margin: otherAnchor = layoutMarginsGuide.bottomAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = safeAreaLayoutGuide.bottomAnchor + } else { + otherAnchor = layoutMarginsGuide.bottomAnchor + } + } + cachedConstraints.append( + messageInsetsGuide.bottomAnchor.constraint(equalTo: otherAnchor, constant: -length) + .with(priority: .messageInset) + ) + } + + private func update(leading: MessageInsets.Dimension) { + let length: CGFloat + switch leading { + case .absoluteMargin(let dimension, _): + length = dimension + case .relativeMargin(let percentage, _): + length = bounds.width * percentage + } + let otherAnchor: NSLayoutXAxisAnchor + switch leading.boundary { + case .superview: otherAnchor = leadingAnchor + case .margin: otherAnchor = layoutMarginsGuide.leadingAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = safeAreaLayoutGuide.leadingAnchor + } else { + otherAnchor = layoutMarginsGuide.leadingAnchor + } + } + cachedConstraints.append( + messageInsetsGuide.leadingAnchor.constraint(equalTo: otherAnchor, constant: length) + .with(priority: .messageInset) + ) + } + + private func update(trailing: MessageInsets.Dimension) { + let length: CGFloat + switch trailing { + case .absoluteMargin(let dimension, _): + length = dimension + case .relativeMargin(let percentage, _): + length = bounds.width * percentage + } + let otherAnchor: NSLayoutXAxisAnchor + switch trailing.boundary { + case .superview: otherAnchor = trailingAnchor + case .margin: otherAnchor = layoutMarginsGuide.trailingAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = safeAreaLayoutGuide.trailingAnchor + } else { + otherAnchor = layoutMarginsGuide.trailingAnchor + } + } + cachedConstraints.append( + messageInsetsGuide.trailingAnchor.constraint(equalTo: otherAnchor, constant: -length) + .with(priority: .messageInset) + ) + } + + private func update(sizeableView view: MessageSizeable & UIView) { + cachedConstraints += [ + messageInsetsGuide.topAnchor.constraint(equalTo: view.topAnchor), + messageInsetsGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor), + messageInsetsGuide.leadingAnchor.constraint(equalTo: view.leadingAnchor), + messageInsetsGuide.trailingAnchor.constraint(equalTo: view.trailingAnchor), + ] + if let width = view.messageSize.width { + let length = self.length(for: width, extractor: { $0.width }) + cachedConstraints.append( + view.widthAnchor.constraint(equalToConstant: length) + .with(priority: .messageSize) + ) + } + if let height = view.messageSize.height { + let length = self.length(for: height, extractor: { $0.height }) + cachedConstraints.append( + view.heightAnchor.constraint(equalToConstant: length) + .with(priority: .messageSize) + ) + } + } + + private func length( + for dimension: MessageSize.Dimension, + extractor: (CGRect) -> CGFloat + ) -> CGFloat { + switch dimension { + case .absolute(let dimension): + return dimension + case .absoluteMargin(let margin, let boundary): + let insets: UIEdgeInsets + switch boundary { + case .superview: insets = .zero + case .margin: insets = layoutMargins + case .safeArea: + if #available(iOS 11.0, *) { + insets = safeAreaInsets + } else { + insets = layoutMargins + } + } + return extractor(bounds.inset(by: insets)) - margin * 2 + case .relative(let percentage, let boundary): + let insets: UIEdgeInsets + switch boundary { + case .superview: insets = .zero + case .margin: insets = layoutMargins + case .safeArea: + if #available(iOS 11.0, *) { + insets = safeAreaInsets + } else { + insets = layoutMargins + } + } + return extractor(bounds.inset(by: insets)) * percentage + } + } } diff --git a/SwiftMessages/MessageSizeable.swift b/SwiftMessages/MessageSizeable.swift new file mode 100644 index 00000000..662f1839 --- /dev/null +++ b/SwiftMessages/MessageSizeable.swift @@ -0,0 +1,65 @@ +// +// BoundaryInsets.swift +// SwiftMessages +// +// Created by Timothy Moose on 2/13/21. +// Copyright © 2021 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +public protocol MessageSizeable { + var messageSize: MessageSize { get } + var messageInsets: MessageInsets { get } +} + +public enum MessageBoundary { + case superview + case safeArea + case margin +} + +/// Insets used for specifying view sizing options in terms of insets from the containing superview or safe area. +public struct MessageInsets { + + public enum Dimension { + + /// Dimension should maintain an absolute margin to the given container boundary. + case absoluteMargin(CGFloat, from: MessageBoundary) + + /// Dimension should maintain a relative margin to the given container boundary. + case relativeMargin(CGFloat, from: MessageBoundary) + } + + public var top: Dimension? + public var bottom: Dimension? + public var leading: Dimension? + public var trailing: Dimension? +} + +public struct MessageSize { + + public enum Dimension { + + /// Dimensions should be an absolute length + case absolute(CGFloat) + + /// Dimension should maintain an absolute length to the given container boundary. + case absoluteMargin(CGFloat, from: MessageBoundary) + + /// Dimension should maintain a relative margin to the given boundary. + case relative(CGFloat, from: MessageBoundary) + } + + public var width: Dimension? + public var height: Dimension? +} + +extension MessageInsets.Dimension { + var boundary: MessageBoundary { + switch self { + case .absoluteMargin(_, let boundary): return boundary + case .relativeMargin(_, let boundary): return boundary + } + } +} diff --git a/SwiftMessages/MessageSizing.swift b/SwiftMessages/MessageSizing.swift new file mode 100644 index 00000000..b4c47dd3 --- /dev/null +++ b/SwiftMessages/MessageSizing.swift @@ -0,0 +1,13 @@ +// +// MessageSizing.swift +// SwiftMessages +// +// Created by Timothy Moose on 2/14/21. +// Copyright © 2021 SwiftKick Mobile. All rights reserved. +// + +import Foundation + +public protocol MessageSizing { + func install(sizeableView: MessageSizeable & UIView) +} diff --git a/SwiftMessages/Resources/CardView.xib b/SwiftMessages/Resources/CardView.xib index 425a6961..f3ad1df4 100644 --- a/SwiftMessages/Resources/CardView.xib +++ b/SwiftMessages/Resources/CardView.xib @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> @@ -70,7 +70,6 @@ <constraint firstAttribute="trailing" secondItem="SU0-uJ-4pP" secondAttribute="trailing" constant="20" id="QN2-NH-rWA"/> <constraint firstItem="SU0-uJ-4pP" firstAttribute="top" secondItem="A7b-0a-fJG" secondAttribute="top" constant="20" id="S9l-zM-0wc"/> <constraint firstAttribute="bottom" secondItem="SU0-uJ-4pP" secondAttribute="bottom" constant="20" id="YMg-LN-n7f"/> - <constraint firstAttribute="width" relation="lessThanOrEqual" priority="900" constant="500" id="lOa-jP-2uX"/> <constraint firstItem="SU0-uJ-4pP" firstAttribute="leading" secondItem="A7b-0a-fJG" secondAttribute="leading" constant="20" id="nYJ-Ok-uhC"/> </constraints> <userDefinedRuntimeAttributes> @@ -78,25 +77,13 @@ <real key="value" value="15"/> </userDefinedRuntimeAttribute> </userDefinedRuntimeAttributes> - <variation key="default"> - <mask key="constraints"> - <exclude reference="lOa-jP-2uX"/> - </mask> - </variation> - <variation key="widthClass=regular"> - <mask key="constraints"> - <include reference="lOa-jP-2uX"/> - </mask> - </variation> </view> </subviews> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <constraints> - <constraint firstItem="A7b-0a-fJG" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="uEa-1P-F1Y" secondAttribute="leadingMargin" priority="900" id="LWV-wo-Jec"/> <constraint firstAttribute="trailingMargin" secondItem="A7b-0a-fJG" secondAttribute="trailing" priority="900" id="O6e-Yz-cwK"/> <constraint firstItem="A7b-0a-fJG" firstAttribute="leading" secondItem="uEa-1P-F1Y" secondAttribute="leadingMargin" priority="900" id="RiR-2q-ZY5"/> <constraint firstItem="A7b-0a-fJG" firstAttribute="centerX" secondItem="uEa-1P-F1Y" secondAttribute="centerX" priority="950" id="jLv-ud-1WD"/> - <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="A7b-0a-fJG" secondAttribute="trailing" priority="900" id="lGg-Ey-I5f"/> <constraint firstItem="A7b-0a-fJG" firstAttribute="top" secondItem="uEa-1P-F1Y" secondAttribute="topMargin" id="yAH-C4-oUg"/> <constraint firstAttribute="bottomMargin" secondItem="A7b-0a-fJG" secondAttribute="bottom" id="ygs-aa-zj3"/> </constraints> @@ -119,18 +106,10 @@ </userDefinedRuntimeAttribute> <userDefinedRuntimeAttribute type="boolean" keyPath="collapseLayoutMarginAdditions" value="YES"/> </userDefinedRuntimeAttributes> - <variation key="default"> - <mask key="constraints"> - <exclude reference="LWV-wo-Jec"/> - <exclude reference="lGg-Ey-I5f"/> - </mask> - </variation> <variation key="widthClass=regular"> <mask key="constraints"> - <include reference="LWV-wo-Jec"/> <exclude reference="O6e-Yz-cwK"/> <exclude reference="RiR-2q-ZY5"/> - <include reference="lGg-Ey-I5f"/> </mask> </variation> <connections> diff --git a/SwiftMessages/Resources/CenteredView.xib b/SwiftMessages/Resources/CenteredView.xib index a9fda2be..b61242cc 100644 --- a/SwiftMessages/Resources/CenteredView.xib +++ b/SwiftMessages/Resources/CenteredView.xib @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> @@ -32,7 +32,7 @@ <rect key="frame" x="160.5" y="55.5" width="33" height="0.0"/> </imageView> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="700" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="[Title]" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ggW-gB-SWF"> - <rect key="frame" x="153" y="65.5" width="48.5" height="20.5"/> + <rect key="frame" x="153" y="65.5" width="48" height="20.5"/> <accessibility key="accessibilityConfiguration"> <bool key="isElement" value="NO"/> </accessibility> @@ -69,7 +69,6 @@ <constraint firstAttribute="bottom" secondItem="YST-yc-0HK" secondAttribute="bottom" constant="20" id="Vsy-Y9-qzf"> <variation key="widthClass=regular" constant="30"/> </constraint> - <constraint firstAttribute="width" relation="lessThanOrEqual" priority="900" constant="500" id="Y89-EE-TtG"/> <constraint firstItem="YST-yc-0HK" firstAttribute="top" secondItem="0Mj-jC-BX6" secondAttribute="top" constant="20" id="yRl-kK-cQH"> <variation key="widthClass=regular" constant="30"/> </constraint> @@ -79,16 +78,6 @@ <real key="value" value="15"/> </userDefinedRuntimeAttribute> </userDefinedRuntimeAttributes> - <variation key="default"> - <mask key="constraints"> - <exclude reference="Y89-EE-TtG"/> - </mask> - </variation> - <variation key="widthClass=regular"> - <mask key="constraints"> - <exclude reference="Y89-EE-TtG"/> - </mask> - </variation> </view> </subviews> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> @@ -96,10 +85,8 @@ <constraint firstItem="0Mj-jC-BX6" firstAttribute="top" secondItem="g5x-hF-D0u" secondAttribute="topMargin" id="GWI-aH-o7P"/> <constraint firstItem="0Mj-jC-BX6" firstAttribute="centerX" secondItem="g5x-hF-D0u" secondAttribute="centerX" priority="950" id="XqM-pB-dF4"/> <constraint firstItem="0Mj-jC-BX6" firstAttribute="leading" secondItem="g5x-hF-D0u" secondAttribute="leadingMargin" priority="900" id="bQ3-k8-0v0"/> - <constraint firstItem="0Mj-jC-BX6" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="g5x-hF-D0u" secondAttribute="leadingMargin" priority="900" id="iGY-na-87c"/> <constraint firstAttribute="trailingMargin" secondItem="0Mj-jC-BX6" secondAttribute="trailing" priority="900" id="rSj-h2-U7z"/> <constraint firstAttribute="bottomMargin" secondItem="0Mj-jC-BX6" secondAttribute="bottom" id="wRH-k8-J8S"/> - <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="0Mj-jC-BX6" secondAttribute="trailing" priority="900" id="xAq-z5-Gur"/> </constraints> <nil key="simulatedTopBarMetrics"/> <nil key="simulatedBottomBarMetrics"/> @@ -122,18 +109,10 @@ </userDefinedRuntimeAttribute> <userDefinedRuntimeAttribute type="boolean" keyPath="collapseLayoutMarginAdditions" value="YES"/> </userDefinedRuntimeAttributes> - <variation key="default"> - <mask key="constraints"> - <exclude reference="iGY-na-87c"/> - <exclude reference="xAq-z5-Gur"/> - </mask> - </variation> <variation key="widthClass=regular"> <mask key="constraints"> <exclude reference="bQ3-k8-0v0"/> - <include reference="iGY-na-87c"/> <exclude reference="rSj-h2-U7z"/> - <include reference="xAq-z5-Gur"/> </mask> </variation> <connections> diff --git a/SwiftMessages/Resources/TabView.xib b/SwiftMessages/Resources/TabView.xib index 141467c1..e572aa41 100644 --- a/SwiftMessages/Resources/TabView.xib +++ b/SwiftMessages/Resources/TabView.xib @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> @@ -69,7 +69,6 @@ <constraints> <constraint firstItem="bdc-by-rjM" firstAttribute="leading" secondItem="8l1-Wp-omF" secondAttribute="leading" priority="900" constant="20" id="ZeN-Yg-DDA"/> <constraint firstAttribute="trailing" secondItem="bdc-by-rjM" secondAttribute="trailing" priority="900" constant="20" id="Zuf-gb-AgS"/> - <constraint firstAttribute="width" relation="lessThanOrEqual" priority="900" constant="500" id="eE4-1F-BxM"/> </constraints> <edgeInsets key="layoutMargins" top="0.0" left="0.0" bottom="0.0" right="0.0"/> <userDefinedRuntimeAttributes> @@ -78,27 +77,15 @@ </userDefinedRuntimeAttribute> <userDefinedRuntimeAttribute type="boolean" keyPath="roundsLeadingCorners" value="YES"/> </userDefinedRuntimeAttributes> - <variation key="default"> - <mask key="constraints"> - <exclude reference="eE4-1F-BxM"/> - </mask> - </variation> - <variation key="widthClass=regular"> - <mask key="constraints"> - <include reference="eE4-1F-BxM"/> - </mask> - </variation> </view> </subviews> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstItem="8l1-Wp-omF" firstAttribute="centerX" secondItem="Kgd-fq-RpT" secondAttribute="centerX" priority="950" id="7tH-rr-EQZ"/> - <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="8l1-Wp-omF" secondAttribute="trailing" priority="900" id="Auy-Yk-HhC"/> <constraint firstItem="bdc-by-rjM" firstAttribute="top" secondItem="Kgd-fq-RpT" secondAttribute="topMargin" id="ORK-bM-dJT"/> <constraint firstItem="8l1-Wp-omF" firstAttribute="top" secondItem="Kgd-fq-RpT" secondAttribute="top" id="WBW-gJ-lIP"/> <constraint firstAttribute="bottom" secondItem="8l1-Wp-omF" secondAttribute="bottom" id="cYv-6k-QSZ"/> <constraint firstAttribute="bottomMargin" secondItem="bdc-by-rjM" secondAttribute="bottom" id="foq-FY-TKq"/> - <constraint firstItem="8l1-Wp-omF" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Kgd-fq-RpT" secondAttribute="leadingMargin" priority="900" id="pRc-fu-AhN"/> <constraint firstItem="8l1-Wp-omF" firstAttribute="leading" secondItem="Kgd-fq-RpT" secondAttribute="leadingMargin" priority="900" id="tVC-3b-F2x"/> <constraint firstItem="8l1-Wp-omF" firstAttribute="trailing" secondItem="Kgd-fq-RpT" secondAttribute="trailingMargin" priority="900" id="uZe-cg-8cw"/> </constraints> @@ -121,16 +108,8 @@ </userDefinedRuntimeAttribute> <userDefinedRuntimeAttribute type="boolean" keyPath="collapseLayoutMarginAdditions" value="NO"/> </userDefinedRuntimeAttributes> - <variation key="default"> - <mask key="constraints"> - <exclude reference="Auy-Yk-HhC"/> - <exclude reference="pRc-fu-AhN"/> - </mask> - </variation> <variation key="widthClass=regular"> <mask key="constraints"> - <include reference="Auy-Yk-HhC"/> - <include reference="pRc-fu-AhN"/> <exclude reference="tVC-3b-F2x"/> <exclude reference="uZe-cg-8cw"/> </mask> diff --git a/SwiftMessages/SwiftMessagesSegue.swift b/SwiftMessages/SwiftMessagesSegue.swift index 8fa696ed..f20491bc 100644 --- a/SwiftMessages/SwiftMessagesSegue.swift +++ b/SwiftMessages/SwiftMessagesSegue.swift @@ -369,11 +369,15 @@ extension SwiftMessagesSegue { if let preferredHeight = toVC?.preferredContentSize.height, preferredHeight - navInset > 0 { - segue.containerView.heightAnchor.constraint(equalToConstant: preferredHeight).with(priority: UILayoutPriority(rawValue: 951)).isActive = true + segue.containerView.heightAnchor.constraint(equalToConstant: preferredHeight) + .with(priority: .belowMessageSizeable - 1) + .isActive = true } if let preferredWidth = toVC?.preferredContentSize.width, preferredWidth > 0 { - segue.containerView.widthAnchor.constraint(equalToConstant: preferredWidth).with(priority: UILayoutPriority(rawValue: 951)).isActive = true + segue.containerView.widthAnchor.constraint(equalToConstant: preferredWidth) + .with(priority: .belowMessageSizeable - 1) + .isActive = true } segue.presenter.config.presentationContext = .view(transitionContainer) segue.messenger.show(presenter: segue.presenter) diff --git a/SwiftMessages/TopBottomAnimation.swift b/SwiftMessages/TopBottomAnimation.swift index 78c0d84a..0a91fc3f 100644 --- a/SwiftMessages/TopBottomAnimation.swift +++ b/SwiftMessages/TopBottomAnimation.swift @@ -88,92 +88,30 @@ public class TopBottomAnimation: NSObject, Animator { if let adjustable = context.messageView as? MarginAdjustable { bounceOffset = adjustable.bounceAnimationOffset } - view.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(view) - view.leadingAnchor.constraint(equalTo: container.leadingAnchor).isActive = true - view.trailingAnchor.constraint(equalTo: container.trailingAnchor).isActive = true - let boundaryInsets = (view as? HasBoundaryInsets)?.boundaryInsets ?? BoundaryInsets() + if let sizeableView = view as? MessageSizeable & UIView { + container.install(sizeableView: sizeableView) + } else { + view.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(view) + } + // Horizontal constraints + do { + view.leadingAnchor.constraint(equalTo: container.leadingAnchor) + .with(priority: .belowMessageSizeable - 1) + .isActive = true + view.centerXAnchor.constraint(equalTo: container.centerXAnchor) + .with(priority: .belowMessageSizeable) + .isActive = true + } switch style { case .top: - view.topAnchor.constraint( - equalTo: container.topAnchor, - constant: -bounceOffset - ).with(priority: .defaultHigh).isActive = true - switch boundaryInsets.bottom { - case .automatic: - break - case .absoluteMargin(let dimension, let boundary): - let otherAnchor: NSLayoutYAxisAnchor - switch boundary { - case .superview: otherAnchor = container.bottomAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = container.safeAreaLayoutGuide.bottomAnchor - } else { - otherAnchor = container.layoutMarginsGuide.bottomAnchor - } - case .margin: otherAnchor = container.layoutMarginsGuide.bottomAnchor - } - view.bottomAnchor.constraint(equalTo: otherAnchor, constant: -dimension) - .with(priority: .defaultHigh) - .isActive = true - case .relativeMargin(let dimension, let boundary): - let otherAnchor: NSLayoutDimension! - switch boundary { - case .superview: otherAnchor = container.heightAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = container.safeAreaLayoutGuide.heightAnchor - } else { - otherAnchor = container.layoutMarginsGuide.heightAnchor - } - case .margin: otherAnchor = container.layoutMarginsGuide.heightAnchor - } - view.heightAnchor.constraint( - equalTo: otherAnchor, - multiplier: 1 - dimension - ).with(priority: .defaultHigh).isActive = true - } + view.topAnchor.constraint(equalTo: container.topAnchor, constant: -bounceOffset) + .with(priority: .belowMessageSizeable) + .isActive = true case .bottom: - view.bottomAnchor.constraint( - equalTo: container.bottomAnchor, - constant: bounceOffset - ).with(priority: .defaultHigh).isActive = true - switch boundaryInsets.top { - case .automatic: - break - case .absoluteMargin(let dimension, let boundary): - let otherAnchor: NSLayoutYAxisAnchor - switch boundary { - case .superview: otherAnchor = container.topAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = container.safeAreaLayoutGuide.topAnchor - } else { - otherAnchor = container.layoutMarginsGuide.topAnchor - } - case .margin: otherAnchor = container.layoutMarginsGuide.topAnchor - } - view.topAnchor.constraint(equalTo: otherAnchor, constant: dimension) - .with(priority: .defaultHigh) - .isActive = true - case .relativeMargin(let dimension, let boundary): - let otherAnchor: NSLayoutDimension! - switch boundary { - case .superview: otherAnchor = container.heightAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = container.safeAreaLayoutGuide.heightAnchor - } else { - otherAnchor = container.layoutMarginsGuide.heightAnchor - } - case .margin: otherAnchor = container.layoutMarginsGuide.heightAnchor - } - view.heightAnchor.constraint( - equalTo: otherAnchor, - multiplier: 1 - dimension - ).with(priority: .defaultHigh).isActive = true - } + view.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: bounceOffset) + .with(priority: .belowMessageSizeable) + .isActive = true } // Important to layout now in order to get the right safe area insets container.layoutIfNeeded() diff --git a/SwiftMessages/UILayoutPriority+Extensions.swift b/SwiftMessages/UILayoutPriority+Extensions.swift new file mode 100644 index 00000000..1fd3ab88 --- /dev/null +++ b/SwiftMessages/UILayoutPriority+Extensions.swift @@ -0,0 +1,18 @@ +// +// UILayoutPriority+Extensions.swift +// SwiftMessages +// +// Created by Timothy Moose on 2/14/21. +// Copyright © 2021 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +/// The priority used for `MessageSizeable` constraints +public extension UILayoutPriority { + static let aboveMessageSizeable: UILayoutPriority = messageInset + 1 + static let belowMessageSizeable: UILayoutPriority = messageSize - 1 + static let messageSize: UILayoutPriority = UILayoutPriority(900) + static let messageInset: UILayoutPriority = UILayoutPriority(901) +} + From 3883abc3f4918aaea605a8f7450c81675a9ebf65 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Fri, 19 Feb 2021 15:20:50 -0600 Subject: [PATCH 17/77] Expand scope of new sizing API --- Demo/Demo/Base.lproj/Main.storyboard | 398 ++++++++++++------ Demo/Demo/ViewControllersViewController.swift | 78 +++- SwiftMessages.xcodeproj/project.pbxproj | 12 +- SwiftMessages/Animator.swift | 4 +- SwiftMessages/BaseView.swift | 109 +++-- SwiftMessages/CornerRoundingView.swift | 4 +- SwiftMessages/Layout.swift | 91 ++++ SwiftMessages/MaskingView.swift | 307 +++++++++++--- SwiftMessages/MessageSizeable.swift | 65 --- SwiftMessages/MessageSizing.swift | 13 - SwiftMessages/PhysicsAnimation.swift | 37 +- SwiftMessages/Presenter.swift | 4 +- SwiftMessages/SwiftMessagesSegue.swift | 210 +++++---- SwiftMessages/TopBottomAnimation.swift | 133 ++++-- .../UILayoutPriority+Extensions.swift | 18 +- .../UIViewController+Extensions.swift | 6 +- 16 files changed, 1019 insertions(+), 470 deletions(-) create mode 100644 SwiftMessages/Layout.swift delete mode 100644 SwiftMessages/MessageSizeable.swift delete mode 100644 SwiftMessages/MessageSizing.swift diff --git a/Demo/Demo/Base.lproj/Main.storyboard b/Demo/Demo/Base.lproj/Main.storyboard index 08ab75d2..f8968f69 100644 --- a/Demo/Demo/Base.lproj/Main.storyboard +++ b/Demo/Demo/Base.lproj/Main.storyboard @@ -1,8 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="JQZ-C5-7mw"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="JQZ-C5-7mw"> <device id="retina4_7" orientation="portrait" appearance="light"/> <dependencies> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15508"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/> + <capability name="System colors in document resources" minToolsVersion="11.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> @@ -30,7 +31,7 @@ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="j4a-wU-637"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> <prototypes> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="TitleBody" rowHeight="80" id="2n5-7h-3B5" userLabel="TitleBody Cell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> <rect key="frame" x="0.0" y="28" width="375" height="80"/> @@ -47,7 +48,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Body" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Gpd-DA-5jT"> <rect key="frame" x="26" y="45" width="323" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -81,7 +82,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Explore many of the SwiftMessages configuration options." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Siq-Fh-MNa"> <rect key="frame" x="26" y="45" width="304" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -116,7 +117,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Present modal view controllers with SwiftMessages animations." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sCg-K7-URy"> <rect key="frame" x="26" y="45" width="304" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -151,7 +152,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Present modal view controllers with SwiftMessages animations." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="T5Q-9f-KQC"> <rect key="frame" x="26" y="45" width="304" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -185,7 +186,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hide a message based on equal number of show() and hideCounted(id:) calls." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ie4-WM-pe4"> <rect key="frame" x="26" y="45" width="304" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -223,7 +224,7 @@ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="none" allowsSelection="NO" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="XwA-eF-0LG"> <rect key="frame" x="0.0" y="0.0" width="375" height="1200"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> <sections> <tableViewSection headerTitle="Presentation" id="ifN-uy-lWX"> <cells> @@ -641,7 +642,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Button" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dRM-c4-ORW"> <rect key="frame" x="69" y="0.0" width="72.5" height="4.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -655,7 +656,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PfQ-eZ-O0L"> <rect key="frame" x="69" y="0.0" width="72.5" height="4.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -674,7 +675,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Icon" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XKN-W4-1jq"> <rect key="frame" x="69" y="0.0" width="72.5" height="4.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -688,7 +689,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Body" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DGg-y8-Ln9"> <rect key="frame" x="69" y="0.0" width="72.5" height="4.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -810,115 +811,255 @@ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="mGe-El-haJ"> - <rect key="frame" x="46" y="84" width="283" height="494"/> + <rect key="frame" x="31" y="59" width="313" height="284"/> <subviews> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DrN-Ei-Pg7"> - <rect key="frame" x="0.0" y="0.0" width="283" height="62"/> - <color key="backgroundColor" red="0.16470588235294117" green="0.6588235294117647" blue="0.98039215686274506" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> - <state key="normal" title="Top Message"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopSegue" customModule="Demo" customModuleProvider="target" id="7xS-Ca-mnb"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GeC-SP-rSC"> - <rect key="frame" x="0.0" y="72" width="283" height="62"/> - <color key="backgroundColor" red="0.1647058824" green="0.6588235294" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> - <state key="normal" title="Bottom Message"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomSegue" customModule="Demo" customModuleProvider="target" id="6Yg-dE-eXA"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DGn-eY-EEX"> - <rect key="frame" x="0.0" y="144" width="283" height="62"/> - <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> - <state key="normal" title="Top Card"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopCardSegue" customModule="Demo" customModuleProvider="target" id="qLf-js-3Ls"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZQs-MK-vK3"> - <rect key="frame" x="0.0" y="216" width="283" height="62"/> - <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> - <state key="normal" title="Bottom Card"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomCardSegue" customModule="Demo" customModuleProvider="target" id="TBl-s0-9vL"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kux-aE-Bdv" userLabel="Top Tab"> - <rect key="frame" x="0.0" y="288" width="283" height="62"/> - <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000067" blue="0.62082127703967116" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> - <state key="normal" title="Top Tab"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopTabSegue" customModule="Demo" customModuleProvider="target" id="p7Y-6q-gfK"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dMQ-xF-RwV" userLabel="Bottom Tab"> - <rect key="frame" x="0.0" y="360" width="283" height="62"/> - <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000001" blue="0.620821277" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> - <state key="normal" title="Bottom Tab"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomTabSegue" customModule="Demo" customModuleProvider="target" id="EaG-Ea-U3j"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CDi-Gu-bE2" userLabel="Centered"> - <rect key="frame" x="0.0" y="432" width="283" height="62"/> - <color key="backgroundColor" red="1" green="0.46653546191345963" blue="0.015686274510000042" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> - <state key="normal" title="Centered"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesCenteredSegue" customModule="Demo" customModuleProvider="target" id="had-cE-9YN"/> - </connections> - </button> + <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="duT-dC-cRi"> + <rect key="frame" x="0.0" y="0.0" width="313" height="32"/> + <subviews> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DrN-Ei-Pg7"> + <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> + <color key="backgroundColor" red="0.16470588235294117" green="0.6588235294117647" blue="0.98039215686274506" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Top"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopSegue" customModule="Demo" customModuleProvider="target" id="7xS-Ca-mnb"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GeC-SP-rSC"> + <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> + <color key="backgroundColor" red="0.1647058824" green="0.6588235294" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Bottom"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomSegue" customModule="Demo" customModuleProvider="target" id="6Yg-dE-eXA"/> + </connections> + </button> + </subviews> + </stackView> + <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" id="edP-BU-APQ"> + <rect key="frame" x="0.0" y="42" width="313" height="32"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <subviews> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="khy-PR-9ic"> + <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> + <color key="backgroundColor" red="0.1647058824" green="0.6588235294" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Leading"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesLeadingSegue" customModule="Demo" customModuleProvider="target" id="vqC-mA-oKl"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IYU-GH-7Bu"> + <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> + <color key="backgroundColor" red="0.1647058824" green="0.6588235294" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Trailing"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTrailingSegue" customModule="Demo" customModuleProvider="target" id="Htu-Pa-8Bb"/> + </connections> + </button> + </subviews> + </stackView> + <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" id="RIf-X4-6Nf"> + <rect key="frame" x="0.0" y="84" width="313" height="32"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <subviews> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DGn-eY-EEX"> + <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> + <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Top Card"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopCardSegue" customModule="Demo" customModuleProvider="target" id="qLf-js-3Ls"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZQs-MK-vK3"> + <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> + <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Bottom Card"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomCardSegue" customModule="Demo" customModuleProvider="target" id="TBl-s0-9vL"/> + </connections> + </button> + </subviews> + </stackView> + <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" id="4Lv-io-Ckq"> + <rect key="frame" x="0.0" y="126" width="313" height="32"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <subviews> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="RLv-JB-1Kv"> + <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> + <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Leading Card"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesLeadingCardSegue" customModule="Demo" customModuleProvider="target" id="ijQ-PY-fOg"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VoG-71-V86"> + <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> + <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Trailing Card"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTrailingCardSegue" customModule="Demo" customModuleProvider="target" id="eyV-wa-br5"/> + </connections> + </button> + </subviews> + </stackView> + <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" id="cco-7a-QYG"> + <rect key="frame" x="0.0" y="168" width="313" height="32"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <subviews> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kux-aE-Bdv" userLabel="Top Tab"> + <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> + <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000067" blue="0.62082127703967116" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Top Tab"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopTabSegue" customModule="Demo" customModuleProvider="target" id="p7Y-6q-gfK"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dMQ-xF-RwV" userLabel="Bottom Tab"> + <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> + <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000001" blue="0.620821277" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Bottom Tab"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomTabSegue" customModule="Demo" customModuleProvider="target" id="EaG-Ea-U3j"/> + </connections> + </button> + </subviews> + </stackView> + <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" id="p3M-fI-UAT"> + <rect key="frame" x="0.0" y="210" width="313" height="32"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <subviews> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wPG-Jy-nyC"> + <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> + <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000001" blue="0.620821277" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Leading Tab"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesLeadingTabSegue" customModule="Demo" customModuleProvider="target" id="IIr-OL-eMR"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SR9-3n-RLT"> + <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> + <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000001" blue="0.620821277" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Trailing Tab"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTrailingTabSegue" customModule="Demo" customModuleProvider="target" id="LC0-Bk-8Ad"/> + </connections> + </button> + </subviews> + </stackView> + <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" id="Cqr-gB-ufD"> + <rect key="frame" x="0.0" y="252" width="313" height="32"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <subviews> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CDi-Gu-bE2" userLabel="Centered"> + <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> + <color key="backgroundColor" red="1" green="0.46653546191345963" blue="0.015686274510000042" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Centered"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesCenteredSegue" customModule="Demo" customModuleProvider="target" id="had-cE-9YN"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="WGh-db-dXZ" userLabel="Centered"> + <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <color key="backgroundColor" red="1" green="0.4665354619" blue="0.015686274510000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> + <state key="normal" title="Off-Centered"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesOffCenteredSegue" customModule="Demo" customModuleProvider="target" id="abD-oU-7qa"/> + </connections> + </button> + </subviews> + </stackView> </subviews> </stackView> </subviews> - <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> <constraints> - <constraint firstItem="mGe-El-haJ" firstAttribute="top" secondItem="WeL-Zn-0tj" secondAttribute="bottom" constant="40" id="6TI-R1-eMQ"/> - <constraint firstItem="mGe-El-haJ" firstAttribute="leading" secondItem="YlT-hO-kIK" secondAttribute="leadingMargin" constant="30" id="LqT-Kn-3v7"/> - <constraint firstItem="LAn-az-eMU" firstAttribute="top" secondItem="mGe-El-haJ" secondAttribute="bottom" constant="40" id="jWn-cy-X7E"/> - <constraint firstAttribute="trailingMargin" secondItem="mGe-El-haJ" secondAttribute="trailing" constant="30" id="xEo-4G-PBe"/> + <constraint firstItem="mGe-El-haJ" firstAttribute="top" secondItem="WeL-Zn-0tj" secondAttribute="bottom" constant="15" id="6TI-R1-eMQ"/> + <constraint firstItem="mGe-El-haJ" firstAttribute="leading" secondItem="YlT-hO-kIK" secondAttribute="leadingMargin" constant="15" id="LqT-Kn-3v7"/> + <constraint firstItem="LAn-az-eMU" firstAttribute="top" secondItem="mGe-El-haJ" secondAttribute="bottom" constant="15" id="jWn-cy-X7E"/> + <constraint firstAttribute="trailingMargin" secondItem="mGe-El-haJ" secondAttribute="trailing" constant="15" id="xEo-4G-PBe"/> </constraints> </view> </viewController> @@ -931,7 +1072,7 @@ <objects> <navigationController id="dHK-y5-h16" sceneMemberID="viewController"> <tabBarItem key="tabBarItem" title="Item" id="lRD-YW-2WT"/> - <value key="contentSizeForViewInPopover" type="size" width="0.0" height="250"/> + <navigationItem key="navigationItem" id="kWv-kG-kDP"/> <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="eD6-og-rzJ"> <rect key="frame" x="0.0" y="0.0" width="375" height="44"/> <autoresizingMask key="autoresizingMask"/> @@ -951,7 +1092,7 @@ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="veg-5v-Pex"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> <sections> <tableViewSection id="CqX-XV-4eD"> <cells> @@ -1049,18 +1190,19 @@ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Nothing to see here." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2bv-DK-h4b"> - <rect key="frame" x="109.5" y="345" width="156" height="21"/> + <rect key="frame" x="110.5" y="345" width="154.5" height="21"/> <fontDescription key="fontDescription" type="system" pointSize="17"/> <nil key="textColor"/> <nil key="highlightedColor"/> </label> </subviews> - <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> <constraints> <constraint firstItem="2bv-DK-h4b" firstAttribute="centerX" secondItem="0Cn-7n-ODp" secondAttribute="centerX" id="1aC-Jw-Zyl"/> <constraint firstItem="2bv-DK-h4b" firstAttribute="centerY" secondItem="0Cn-7n-ODp" secondAttribute="centerYWithinMargins" id="93w-dz-NPV"/> </constraints> </view> + <navigationItem key="navigationItem" id="rP6-sY-fmZ"/> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="mU1-MA-hwk" userLabel="First Responder" sceneMemberID="firstResponder"/> </objects> @@ -1084,11 +1226,17 @@ <point key="canvasLocation" x="473" y="305"/> </scene> </scenes> - <resources> - <image name="iconSwiftMessages" width="38" height="31"/> - </resources> <inferredMetricsTieBreakers> <segue reference="h5n-Vv-Q3y"/> - <segue reference="EaG-Ea-U3j"/> + <segue reference="abD-oU-7qa"/> </inferredMetricsTieBreakers> + <resources> + <image name="iconSwiftMessages" width="38" height="31"/> + <systemColor name="secondaryLabelColor"> + <color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + </systemColor> + <systemColor name="systemBackgroundColor"> + <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + </systemColor> + </resources> </document> diff --git a/Demo/Demo/ViewControllersViewController.swift b/Demo/Demo/ViewControllersViewController.swift index f3339ebc..733dc07d 100644 --- a/Demo/Demo/ViewControllersViewController.swift +++ b/Demo/Demo/ViewControllersViewController.swift @@ -19,27 +19,39 @@ class SwiftMessagesTopSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) configure(layout: .topMessage) + messageView.layout.size.height = .absolute(300) } } -class SwiftMessagesTopCardSegue: SwiftMessagesSegue { +class SwiftMessagesBottomSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) - configure(layout: .topCard) + configure(layout: .bottomMessage) + messageView.layout.size.height = .absolute(300) } } -class SwiftMessagesTopTabSegue: SwiftMessagesSegue { +class SwiftMessagesLeadingSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) - configure(layout: .topTab) + configure(layout: .leadingMessage) + messageView.layout.size.width = .absolute(300) } } -class SwiftMessagesBottomSegue: SwiftMessagesSegue { +class SwiftMessagesTrailingSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) - configure(layout: .bottomMessage) + configure(layout: .trailingMessage) + messageView.layout.size.width = .absolute(300) + } +} + +class SwiftMessagesTopCardSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .topCard) + messageView.layout.size.height = .absolute(300) } } @@ -47,7 +59,31 @@ class SwiftMessagesBottomCardSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) configure(layout: .bottomCard) - messageView.messageSize.width = .relative(0.75, from: .superview) + messageView.layout.size.height = .absolute(300) + } +} + +class SwiftMessagesLeadingCardSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .leadingCard) + messageView.layout.size.width = .absolute(300) + } +} + +class SwiftMessagesTrailingCardSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .trailingCard) + messageView.layout.size.width = .absolute(300) + } +} + +class SwiftMessagesTopTabSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .topTab) + messageView.layout.size.height = .absolute(300) } } @@ -55,6 +91,23 @@ class SwiftMessagesBottomTabSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) configure(layout: .bottomTab) + messageView.layout.size.height = .absolute(300) + } +} + +class SwiftMessagesLeadingTabSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .leadingTab) + messageView.layout.size.width = .absolute(300) + } +} + +class SwiftMessagesTrailingTabSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .trailingTab) + messageView.layout.size.width = .absolute(300) } } @@ -62,5 +115,16 @@ class SwiftMessagesCenteredSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) configure(layout: .centered) + messageView.layout.size.height = .absolute(300) + } +} + +class SwiftMessagesOffCenteredSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .centered) + messageView.layout.insets.top = .absolute(0, from: .safeArea) + messageView.layout.center.x = .relative(0.33, in: .safeArea) + messageView.layout.size.height = .absolute(300) } } diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 1efdfa4c..47ac1180 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -51,8 +51,7 @@ 228DF5681FAD0806004F8A39 /* infoIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */; }; 228DF5691FAD0806004F8A39 /* successIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5481FAD0805004F8A39 /* successIconLight.png */; }; 228DF56A1FAD0806004F8A39 /* infoIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */; }; - 2290944825D88A05002E8111 /* MessageSizeable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290944725D88A05002E8111 /* MessageSizeable.swift */; }; - 2290957825D9BC9F002E8111 /* MessageSizing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290957725D9BC9F002E8111 /* MessageSizing.swift */; }; + 2290944825D88A05002E8111 /* Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290944725D88A05002E8111 /* Layout.swift */; }; 2290958125D9D407002E8111 /* UILayoutPriority+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */; }; 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; @@ -140,8 +139,7 @@ 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = infoIconSubtle.png; path = Resources/infoIconSubtle.png; sourceTree = "<group>"; }; 228DF5481FAD0805004F8A39 /* successIconLight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = successIconLight.png; path = Resources/successIconLight.png; sourceTree = "<group>"; }; 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; - 2290944725D88A05002E8111 /* MessageSizeable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSizeable.swift; sourceTree = "<group>"; }; - 2290957725D9BC9F002E8111 /* MessageSizing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSizing.swift; sourceTree = "<group>"; }; + 2290944725D88A05002E8111 /* Layout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Layout.swift; sourceTree = "<group>"; }; 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILayoutPriority+Extensions.swift"; sourceTree = "<group>"; }; 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; @@ -301,8 +299,7 @@ 8644955C1D4FAF7C0056EB2A /* WindowViewController.swift */, 867BED201D622793005212E3 /* BackgroundViewable.swift */, 864495551D4F7C390056EB2A /* Identifiable.swift */, - 2290944725D88A05002E8111 /* MessageSizeable.swift */, - 2290957725D9BC9F002E8111 /* MessageSizing.swift */, + 2290944725D88A05002E8111 /* Layout.swift */, 86AAF81D1D5549680031EE32 /* MarginAdjustable.swift */, 22E307FE1E74C5B100E35893 /* AccessibleMessage.swift */, 86AAF82A1D580DD70031EE32 /* Error.swift */, @@ -539,7 +536,7 @@ 86BBA8FC1D5E03F100FE8F16 /* MessageView.swift in Sources */, 86BBA9061D5E040C00FE8F16 /* Identifiable.swift in Sources */, 22F27951210CE25900273E7F /* CornerRoundingView.swift in Sources */, - 2290944825D88A05002E8111 /* MessageSizeable.swift in Sources */, + 2290944825D88A05002E8111 /* Layout.swift in Sources */, 86BBA9011D5E040600FE8F16 /* PassthroughWindow.swift in Sources */, 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */, 86BBA9031D5E040600FE8F16 /* UIViewController+Extensions.swift in Sources */, @@ -562,7 +559,6 @@ 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */, 86589D471D64B6E40041676C /* BaseView.swift in Sources */, 225304622290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift in Sources */, - 2290957825D9BC9F002E8111 /* MessageSizing.swift in Sources */, 86BBA9071D5E040C00FE8F16 /* MarginAdjustable.swift in Sources */, 867BED211D622793005212E3 /* BackgroundViewable.swift in Sources */, 2290958125D9D407002E8111 /* UILayoutPriority+Extensions.swift in Sources */, diff --git a/SwiftMessages/Animator.swift b/SwiftMessages/Animator.swift index d3ec0af7..292ea395 100644 --- a/SwiftMessages/Animator.swift +++ b/SwiftMessages/Animator.swift @@ -45,13 +45,13 @@ public struct SafeZoneConflicts: OptionSet { public class AnimationContext { public let messageView: UIView - public let containerView: UIView & MessageSizing + public let containerView: UIView & LayoutInstalling public let safeZoneConflicts: SafeZoneConflicts public let interactiveHide: Bool internal init( messageView: UIView, - containerView: UIView & MessageSizing, + containerView: UIView & LayoutInstalling, safeZoneConflicts: SafeZoneConflicts, interactiveHide: Bool ) { diff --git a/SwiftMessages/BaseView.swift b/SwiftMessages/BaseView.swift index 2ae86a45..cdde9008 100644 --- a/SwiftMessages/BaseView.swift +++ b/SwiftMessages/BaseView.swift @@ -14,7 +14,7 @@ import UIKit of the optional SwiftMessages protocols and provides some convenience functions and a configurable tap handler. Message views do not need to inherit from `BaseVew`. */ -open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeable { +open class BaseView: UIView, BackgroundViewable, MarginAdjustable, LayoutDefining { /* MARK: - IB outlets @@ -63,6 +63,7 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeab */ /** + TODO SIZE - update documentation A convenience function for installing a content view as a subview of `backgroundView` and pinning the edges to `backgroundView` with the specified `insets`. @@ -82,6 +83,7 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeab } /** + TODO SIZE - update documentation - insets removed A convenience function for installing a background view and pinning to the layout margins. This is useful for creating programatic layouts where the background view needs to be inset from the message view's edges (like a card-style layout). @@ -90,7 +92,7 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeab assigned to the `backgroundView` property. - Parameter insets: The amount to inset the content view from the margins. Default is zero inset. */ - open func installBackgroundView(_ backgroundView: UIView, insets: UIEdgeInsets = UIEdgeInsets.zero) { + open func installBackgroundView(_ backgroundView: UIView) { backgroundView.translatesAutoresizingMaskIntoConstraints = false if backgroundView != self { backgroundView.removeFromSuperview() @@ -100,65 +102,57 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeab NSLayoutConstraint.activate([ backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor) .with(priority: .belowMessageSizeable), - backgroundView.topAnchor.constraint( - equalTo: layoutMarginsGuide.topAnchor, - constant: insets.top - ).with(priority: .belowMessageSizeable), - backgroundView.bottomAnchor.constraint( - equalTo: layoutMarginsGuide.bottomAnchor, - constant: -insets.bottom - ).with(priority: .belowMessageSizeable), - backgroundView.heightAnchor.constraint(equalToConstant: 350) - .with(priority: UILayoutPriority(rawValue: 200)), - backgroundView.leftAnchor.constraint( - equalTo: layoutMarginsGuide.leftAnchor, - constant: insets.left - ).with(priority: .belowMessageSizeable), - backgroundView.rightAnchor.constraint( - equalTo: layoutMarginsGuide.rightAnchor, - constant: -insets.right - ).with(priority: .belowMessageSizeable), - ]) - installTapRecognizer() - } - - /** - A convenience function for installing a background view and pinning to the horizontal - layout margins and to the vertical edges. This is useful for creating programatic layouts where - the background view needs to be inset from the message view's horizontal edges (like a tab-style layout). - - - Parameter backgroundView: The view to be installed as a subview and - assigned to the `backgroundView` property. - - Parameter insets: The amount to inset the content view from the horizontal margins and vertical edges. - Default is zero inset. - */ - open func installBackgroundVerticalView(_ backgroundView: UIView, insets: UIEdgeInsets = UIEdgeInsets.zero) { - backgroundView.translatesAutoresizingMaskIntoConstraints = false - if backgroundView != self { - backgroundView.removeFromSuperview() - } - addSubview(backgroundView) - self.backgroundView = backgroundView - NSLayoutConstraint.activate([ - backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor) + backgroundView.topAnchor.constraint(equalTo: topAnchor) + .with(priority: .belowMessageSizeable), + backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor) .with(priority: .belowMessageSizeable), - backgroundView.topAnchor.constraint(equalTo: topAnchor, constant: insets.top) - .with(priority: .required), - backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -insets.bottom) - .with(priority: .required), backgroundView.heightAnchor.constraint(equalToConstant: 350) .with(priority: UILayoutPriority(rawValue: 200)), - backgroundView.leftAnchor.constraint( - equalTo: layoutMarginsGuide.leftAnchor, constant: insets.left - ).with(priority: .belowMessageSizeable), - backgroundView.rightAnchor.constraint( - equalTo: layoutMarginsGuide.rightAnchor, - constant: -insets.right - ).with(priority: .belowMessageSizeable), + backgroundView.leadingAnchor.constraint(equalTo: leadingAnchor) + .with(priority: .belowMessageSizeable), + backgroundView.trailingAnchor.constraint(equalTo: trailingAnchor) + .with(priority: .belowMessageSizeable), ]) installTapRecognizer() } +// /** +// A convenience function for installing a background view and pinning to the horizontal +// layout margins and to the vertical edges. This is useful for creating programatic layouts where +// the background view needs to be inset from the message view's horizontal edges (like a tab-style layout). +// +// - Parameter backgroundView: The view to be installed as a subview and +// assigned to the `backgroundView` property. +// - Parameter insets: The amount to inset the content view from the horizontal margins and vertical edges. +// Default is zero inset. +// */ +// open func installBackgroundVerticalView(_ backgroundView: UIView, insets: UIEdgeInsets = UIEdgeInsets.zero) { +// backgroundView.translatesAutoresizingMaskIntoConstraints = false +// if backgroundView != self { +// backgroundView.removeFromSuperview() +// } +// addSubview(backgroundView) +// self.backgroundView = backgroundView +// NSLayoutConstraint.activate([ +// backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor) +// .with(priority: .belowMessageSizeable), +// backgroundView.topAnchor.constraint(equalTo: topAnchor, constant: insets.top) +// .with(priority: .required), +// backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -insets.bottom) +// .with(priority: .required), +// backgroundView.heightAnchor.constraint(equalToConstant: 350) +// .with(priority: UILayoutPriority(rawValue: 200)), +// backgroundView.leftAnchor.constraint( +// equalTo: layoutMarginsGuide.leftAnchor, constant: insets.left +// ).with(priority: .belowMessageSizeable), +// backgroundView.rightAnchor.constraint( +// equalTo: layoutMarginsGuide.rightAnchor, +// constant: -insets.right +// ).with(priority: .belowMessageSizeable), +// ]) +// installTapRecognizer() +// } + /* MARK: - Tap handler */ @@ -203,11 +197,8 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeab // MARK: - MessageSizeable - /// Configure the view's size - public var messageSize = MessageSize() - - /// Configure the view's insets from the container - public var messageInsets = MessageInsets() + /// Configure the view's layout + public var layout = Layout() /* MARK: - MarginAdjustable diff --git a/SwiftMessages/CornerRoundingView.swift b/SwiftMessages/CornerRoundingView.swift index 398b731c..7db484fb 100644 --- a/SwiftMessages/CornerRoundingView.swift +++ b/SwiftMessages/CornerRoundingView.swift @@ -24,12 +24,12 @@ open class CornerRoundingView: UIView { /// rounded. For example, the layout in TabView.xib rounds the bottom corners /// when displayed from the top and the top corners when displayed from the bottom. /// When this property is `true`, the `roundedCorners` property will be overwritten - /// by relevant animators (e.g. `TopBottomAnimation`). + /// by relevant animators (e.g. `EdgeAnimation`). @IBInspectable open var roundsLeadingCorners: Bool = false /// Specifies which corners should be rounded. When `roundsLeadingCorners = true`, relevant - /// relevant animators (e.g. `TopBottomAnimation`) will overwrite the value of this property. + /// relevant animators (e.g. `EdgeAnimation`) will overwrite the value of this property. open var roundedCorners: UIRectCorner = [.allCorners] { didSet { updateMaskPath() diff --git a/SwiftMessages/Layout.swift b/SwiftMessages/Layout.swift new file mode 100644 index 00000000..4afcf7b7 --- /dev/null +++ b/SwiftMessages/Layout.swift @@ -0,0 +1,91 @@ +// +// BoundaryInsets.swift +// SwiftMessages +// +// Created by Timothy Moose on 2/13/21. +// Copyright © 2021 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +public protocol LayoutDefining { + var layout: Layout { get } +} + +public protocol LayoutInstalling { + func install(layoutDefiningView: LayoutDefining & UIView) +} + +public struct Layout { + + public var size = Size() + public var insets = Insets() + public var center = Center() + public var min = Layout() + public var max = Layout() + + public enum Boundary { + case superview + case safeArea + case margin + } + + public struct Size { + + public enum Dimension { + case absolute(CGFloat) + case relative(CGFloat, to: Boundary) + } + + public var width: Dimension? + public var height: Dimension? + } + + public struct Insets { + + public enum Dimension { + case absolute(CGFloat, from: Boundary) + case relative(CGFloat, from: Boundary) + } + + public var top: Dimension? + public var bottom: Dimension? + public var leading: Dimension? + public var trailing: Dimension? + } + + public struct Center { + + public enum Dimension { + case absolute(CGFloat, in: Boundary) + case relative(CGFloat, in: Boundary) + } + + public var x: Dimension? + public var y: Dimension? + } + + public struct Layout { + public var size = Size() + public var insets = Insets() + public var center = Center() + } +} + +extension Layout.Insets.Dimension { + var boundary: Layout.Boundary { + switch self { + case .absolute(_, let boundary): return boundary + case .relative(_, let boundary): return boundary + } + } +} + +extension Layout.Center.Dimension { + var boundary: Layout.Boundary { + switch self { + case .absolute(_, let boundary): return boundary + case .relative(_, let boundary): return boundary + } + } +} diff --git a/SwiftMessages/MaskingView.swift b/SwiftMessages/MaskingView.swift index 889ac9de..81301994 100644 --- a/SwiftMessages/MaskingView.swift +++ b/SwiftMessages/MaskingView.swift @@ -24,13 +24,13 @@ import UIKit // .with(priority: UILayoutPriority(rawValue: 200)), // ] -class MaskingView: PassthroughView, MessageSizing { +class MaskingView: PassthroughView, LayoutInstalling { - func install(sizeableView: MessageSizeable & UIView) { - self.sizeableView?.removeFromSuperview() - self.sizeableView = sizeableView - sizeableView.translatesAutoresizingMaskIntoConstraints = false - addSubview(sizeableView) + func install(layoutDefiningView: UIView & LayoutDefining) { + self.layoutDefiningView?.removeFromSuperview() + self.layoutDefiningView = layoutDefiningView + layoutDefiningView.translatesAutoresizingMaskIntoConstraints = false + addSubview(layoutDefiningView) setNeedsUpdateConstraints() } @@ -96,7 +96,7 @@ class MaskingView: PassthroughView, MessageSizing { private var keyboardTrackingView: KeyboardTrackingView? private var cachedConstraints: [NSLayoutConstraint] = [] private let messageInsetsGuide = UILayoutGuide() - private var sizeableView: (MessageSizeable & UIView)? + private var layoutDefiningView: (LayoutDefining & UIView)? override func addSubview(_ view: UIView) { super.addSubview(view) @@ -110,20 +110,35 @@ class MaskingView: PassthroughView, MessageSizing { super.updateConstraints() NSLayoutConstraint.deactivate(cachedConstraints) cachedConstraints = [] - if let top = sizeableView?.messageInsets.top { update(top: top) } - if let bottom = sizeableView?.messageInsets.bottom { update(bottom: bottom) } - if let leading = sizeableView?.messageInsets.leading { update(leading: leading) } - if let trailing = sizeableView?.messageInsets.trailing { update(trailing: trailing) } - if let sizeableView = sizeableView { update(sizeableView: sizeableView) } + if let layoutDefiningView = layoutDefiningView { + let layout = layoutDefiningView.layout + add(insets: layout.insets, relation: .equal) + add(insets: layout.min.insets, relation: .min) + add(insets: layout.max.insets, relation: .max) + add(layoutDefiningView: layoutDefiningView) + } NSLayoutConstraint.activate(cachedConstraints) } - private func update(top: MessageInsets.Dimension) { + private enum ConstraintRelation { + case equal + case min + case max + } + + private func add(insets: Layout.Insets, relation: ConstraintRelation) { + if let top = insets.top { add(top: top, relation: relation) } + if let bottom = insets.bottom { add(bottom: bottom, relation: relation) } + if let leading = insets.leading { add(leading: leading, relation: relation) } + if let trailing = insets.trailing { add(trailing: trailing, relation: relation) } + } + + private func add(top: Layout.Insets.Dimension, relation: ConstraintRelation) { let length: CGFloat switch top { - case .absoluteMargin(let dimension, _): + case .absolute(let dimension, _): length = dimension - case .relativeMargin(let percentage, _): + case .relative(let percentage, _): length = bounds.height * percentage } let otherAnchor: NSLayoutYAxisAnchor @@ -137,18 +152,20 @@ class MaskingView: PassthroughView, MessageSizing { otherAnchor = layoutMarginsGuide.topAnchor } } - cachedConstraints.append( - messageInsetsGuide.topAnchor.constraint(equalTo: otherAnchor, constant: length) - .with(priority: .messageInset) + add( + anchor: messageInsetsGuide.topAnchor, + otherAnchor: otherAnchor, + constant: length, + relation: relation ) } - private func update(bottom: MessageInsets.Dimension) { + private func add(bottom: Layout.Insets.Dimension, relation: ConstraintRelation) { let length: CGFloat switch bottom { - case .absoluteMargin(let dimension, _): + case .absolute(let dimension, _): length = dimension - case .relativeMargin(let percentage, _): + case .relative(let percentage, _): length = bounds.height * percentage } let otherAnchor: NSLayoutYAxisAnchor @@ -162,18 +179,20 @@ class MaskingView: PassthroughView, MessageSizing { otherAnchor = layoutMarginsGuide.bottomAnchor } } - cachedConstraints.append( - messageInsetsGuide.bottomAnchor.constraint(equalTo: otherAnchor, constant: -length) - .with(priority: .messageInset) + add( + anchor: otherAnchor, + otherAnchor: messageInsetsGuide.bottomAnchor, + constant: length, + relation: relation ) } - private func update(leading: MessageInsets.Dimension) { + private func add(leading: Layout.Insets.Dimension, relation: ConstraintRelation) { let length: CGFloat switch leading { - case .absoluteMargin(let dimension, _): + case .absolute(let dimension, _): length = dimension - case .relativeMargin(let percentage, _): + case .relative(let percentage, _): length = bounds.width * percentage } let otherAnchor: NSLayoutXAxisAnchor @@ -187,18 +206,20 @@ class MaskingView: PassthroughView, MessageSizing { otherAnchor = layoutMarginsGuide.leadingAnchor } } - cachedConstraints.append( - messageInsetsGuide.leadingAnchor.constraint(equalTo: otherAnchor, constant: length) - .with(priority: .messageInset) + add( + anchor: messageInsetsGuide.leadingAnchor, + otherAnchor: otherAnchor, + constant: length, + relation: relation ) } - private func update(trailing: MessageInsets.Dimension) { + private func add(trailing: Layout.Insets.Dimension, relation: ConstraintRelation) { let length: CGFloat switch trailing { - case .absoluteMargin(let dimension, _): + case .absolute(let dimension, _): length = dimension - case .relativeMargin(let percentage, _): + case .relative(let percentage, _): length = bounds.width * percentage } let otherAnchor: NSLayoutXAxisAnchor @@ -212,55 +233,193 @@ class MaskingView: PassthroughView, MessageSizing { otherAnchor = layoutMarginsGuide.trailingAnchor } } - cachedConstraints.append( - messageInsetsGuide.trailingAnchor.constraint(equalTo: otherAnchor, constant: -length) - .with(priority: .messageInset) + add( + anchor: otherAnchor, + otherAnchor: messageInsetsGuide.trailingAnchor, + constant: length, + relation: relation ) } - private func update(sizeableView view: MessageSizeable & UIView) { + private func add( + anchor: NSLayoutXAxisAnchor, + otherAnchor: NSLayoutXAxisAnchor, + constant: CGFloat, + relation: ConstraintRelation + ) { + let constraint: NSLayoutConstraint + switch relation { + case .equal: + constraint = anchor + .constraint(equalTo: otherAnchor, constant: constant) + .with(priority: .messageInsets) + case .min: + constraint = anchor + .constraint(greaterThanOrEqualTo: otherAnchor, constant: constant) + .with(priority: .messageInsetsBounds) + case .max: + constraint = anchor + .constraint(lessThanOrEqualTo: otherAnchor, constant: constant) + .with(priority: .messageInsetsBounds) + } + cachedConstraints.append(constraint) + } + + private func add( + anchor: NSLayoutYAxisAnchor, + otherAnchor: NSLayoutYAxisAnchor, + constant: CGFloat, + relation: ConstraintRelation + ) { + let constraint: NSLayoutConstraint + switch relation { + case .equal: + constraint = anchor + .constraint(equalTo: otherAnchor, constant: constant) + .with(priority: .messageInsets) + case .min: + constraint = anchor + .constraint(greaterThanOrEqualTo: otherAnchor, constant: constant) + .with(priority: .messageInsetsBounds) + case .max: + constraint = anchor + .constraint(lessThanOrEqualTo: otherAnchor, constant: constant) + .with(priority: .messageInsetsBounds) + } + cachedConstraints.append(constraint) + } + + private func add(layoutDefiningView view: LayoutDefining & UIView) { cachedConstraints += [ messageInsetsGuide.topAnchor.constraint(equalTo: view.topAnchor), messageInsetsGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor), messageInsetsGuide.leadingAnchor.constraint(equalTo: view.leadingAnchor), messageInsetsGuide.trailingAnchor.constraint(equalTo: view.trailingAnchor), ] - if let width = view.messageSize.width { - let length = self.length(for: width, extractor: { $0.width }) - cachedConstraints.append( - view.widthAnchor.constraint(equalToConstant: length) + add(layoutDefiningView: view, size: view.layout.size, relation: .equal) + add(layoutDefiningView: view, size: view.layout.min.size, relation: .min) + add(layoutDefiningView: view, size: view.layout.max.size, relation: .max) + add(layoutDefiningView: view, center: view.layout.center, relation: .equal) + add(layoutDefiningView: view, center: view.layout.min.center, relation: .min) + add(layoutDefiningView: view, center: view.layout.max.center, relation: .max) + } + + private func add( + layoutDefiningView view: LayoutDefining & UIView, + size: Layout.Size, + relation: ConstraintRelation + ) { + if let width = size.width { + let length = self.length(for: width) { $0.width } + let constraint: NSLayoutConstraint + switch relation { + case .equal: + constraint = view.widthAnchor.constraint(equalToConstant: length) .with(priority: .messageSize) - ) + case .min: + constraint = view.widthAnchor.constraint(greaterThanOrEqualToConstant: length) + .with(priority: .messageSizeBounds) + case .max: + constraint = view.widthAnchor.constraint(lessThanOrEqualToConstant: length) + .with(priority: .messageSizeBounds) + } + cachedConstraints.append(constraint) } - if let height = view.messageSize.height { - let length = self.length(for: height, extractor: { $0.height }) - cachedConstraints.append( - view.heightAnchor.constraint(equalToConstant: length) + if let height = size.height { + let length = self.length(for: height) { $0.height } + let constraint: NSLayoutConstraint + switch relation { + case .equal: + constraint = view.heightAnchor.constraint(equalToConstant: length) .with(priority: .messageSize) - ) + case .min: + constraint = view.heightAnchor.constraint(greaterThanOrEqualToConstant: length) + .with(priority: .messageSizeBounds) + case .max: + constraint = view.heightAnchor.constraint(lessThanOrEqualToConstant: length) + .with(priority: .messageSizeBounds) + } + cachedConstraints.append(constraint) + } + } + + + private func add( + layoutDefiningView view: LayoutDefining & UIView, + center: Layout.Center, + relation: ConstraintRelation + ) { + if let x = center.x { + let length = self.length(for: x) { ($0.minX, $0.maxX) } + let otherAnchor: NSLayoutXAxisAnchor + switch x.boundary { + case .superview: otherAnchor = leadingAnchor + case .margin: otherAnchor = layoutMarginsGuide.leadingAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = safeAreaLayoutGuide.leadingAnchor + } else { + otherAnchor = layoutMarginsGuide.leadingAnchor + } + } + let constraint: NSLayoutConstraint + switch relation { + case .equal: + constraint = view.centerXAnchor.constraint(equalTo: otherAnchor, constant: length) + .with(priority: .messageCenter) + case .min: + constraint = view.centerXAnchor.constraint( + greaterThanOrEqualTo: otherAnchor, + constant: length + ).with(priority: .messageSizeBounds) + case .max: + constraint = view.centerXAnchor.constraint( + lessThanOrEqualTo: otherAnchor, + constant: length + ).with(priority: .messageSizeBounds) + } + cachedConstraints.append(constraint) + } + if let y = center.y { + let length = self.length(for: y) { ($0.minY, $0.maxY) } + let otherAnchor: NSLayoutYAxisAnchor + switch y.boundary { + case .superview: otherAnchor = topAnchor + case .margin: otherAnchor = layoutMarginsGuide.topAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = safeAreaLayoutGuide.topAnchor + } else { + otherAnchor = layoutMarginsGuide.topAnchor + } + } + let constraint: NSLayoutConstraint + switch relation { + case .equal: + constraint = view.centerYAnchor.constraint(equalTo: otherAnchor, constant: length) + .with(priority: .messageCenter) + case .min: + constraint = view.centerYAnchor.constraint( + greaterThanOrEqualTo: otherAnchor, + constant: length + ).with(priority: .messageSizeBounds) + case .max: + constraint = view.centerYAnchor.constraint( + lessThanOrEqualTo: otherAnchor, + constant: length + ).with(priority: .messageSizeBounds) + } + cachedConstraints.append(constraint) } } private func length( - for dimension: MessageSize.Dimension, + for dimension: Layout.Size.Dimension, extractor: (CGRect) -> CGFloat ) -> CGFloat { switch dimension { case .absolute(let dimension): return dimension - case .absoluteMargin(let margin, let boundary): - let insets: UIEdgeInsets - switch boundary { - case .superview: insets = .zero - case .margin: insets = layoutMargins - case .safeArea: - if #available(iOS 11.0, *) { - insets = safeAreaInsets - } else { - insets = layoutMargins - } - } - return extractor(bounds.inset(by: insets)) - margin * 2 case .relative(let percentage, let boundary): let insets: UIEdgeInsets switch boundary { @@ -276,4 +435,30 @@ class MaskingView: PassthroughView, MessageSizing { return extractor(bounds.inset(by: insets)) * percentage } } + + private func length( + for dimension: Layout.Center.Dimension, + extractor: (CGRect) -> (CGFloat, CGFloat) + ) -> CGFloat { + let insets: UIEdgeInsets + switch dimension.boundary { + case .superview: insets = .zero + case .margin: insets = layoutMargins + case .safeArea: + if #available(iOS 11.0, *) { + insets = safeAreaInsets + } else { + insets = layoutMargins + } + } + let insetBounds = bounds.inset(by: insets) + switch dimension { + case .absolute(let dimension, _): + let (min, _) = extractor(insetBounds) + return min + dimension + case .relative(let percentage, _): + let (min, max) = extractor(insetBounds) + return min + (max - min) * percentage + } + } } diff --git a/SwiftMessages/MessageSizeable.swift b/SwiftMessages/MessageSizeable.swift deleted file mode 100644 index 662f1839..00000000 --- a/SwiftMessages/MessageSizeable.swift +++ /dev/null @@ -1,65 +0,0 @@ -// -// BoundaryInsets.swift -// SwiftMessages -// -// Created by Timothy Moose on 2/13/21. -// Copyright © 2021 SwiftKick Mobile. All rights reserved. -// - -import UIKit - -public protocol MessageSizeable { - var messageSize: MessageSize { get } - var messageInsets: MessageInsets { get } -} - -public enum MessageBoundary { - case superview - case safeArea - case margin -} - -/// Insets used for specifying view sizing options in terms of insets from the containing superview or safe area. -public struct MessageInsets { - - public enum Dimension { - - /// Dimension should maintain an absolute margin to the given container boundary. - case absoluteMargin(CGFloat, from: MessageBoundary) - - /// Dimension should maintain a relative margin to the given container boundary. - case relativeMargin(CGFloat, from: MessageBoundary) - } - - public var top: Dimension? - public var bottom: Dimension? - public var leading: Dimension? - public var trailing: Dimension? -} - -public struct MessageSize { - - public enum Dimension { - - /// Dimensions should be an absolute length - case absolute(CGFloat) - - /// Dimension should maintain an absolute length to the given container boundary. - case absoluteMargin(CGFloat, from: MessageBoundary) - - /// Dimension should maintain a relative margin to the given boundary. - case relative(CGFloat, from: MessageBoundary) - } - - public var width: Dimension? - public var height: Dimension? -} - -extension MessageInsets.Dimension { - var boundary: MessageBoundary { - switch self { - case .absoluteMargin(_, let boundary): return boundary - case .relativeMargin(_, let boundary): return boundary - } - } -} diff --git a/SwiftMessages/MessageSizing.swift b/SwiftMessages/MessageSizing.swift deleted file mode 100644 index b4c47dd3..00000000 --- a/SwiftMessages/MessageSizing.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// MessageSizing.swift -// SwiftMessages -// -// Created by Timothy Moose on 2/14/21. -// Copyright © 2021 SwiftKick Mobile. All rights reserved. -// - -import Foundation - -public protocol MessageSizing { - func install(sizeableView: MessageSizeable & UIView) -} diff --git a/SwiftMessages/PhysicsAnimation.swift b/SwiftMessages/PhysicsAnimation.swift index 0fb976c5..46f3d1ef 100644 --- a/SwiftMessages/PhysicsAnimation.swift +++ b/SwiftMessages/PhysicsAnimation.swift @@ -70,18 +70,41 @@ public class PhysicsAnimation: NSObject, Animator { messageView = view containerView = container self.context = context - view.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(view) + if let layoutDefiningView = view as? LayoutDefining & UIView { + container.install(layoutDefiningView: layoutDefiningView) + } else { + view.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(view) + } switch placement { case .center: - view.centerYAnchor.constraint(equalTo: container.centerYAnchor).with(priority: UILayoutPriority(200)).isActive = true + view.centerYAnchor.constraint(equalTo: container.centerYAnchor) + .with(priority: UILayoutPriority(200)).isActive = true case .top: - view.topAnchor.constraint(equalTo: container.topAnchor).with(priority: UILayoutPriority(200)).isActive = true + view.topAnchor.constraint(equalTo: container.topAnchor) + .with(priority: UILayoutPriority(200)).isActive = true case .bottom: - view.bottomAnchor.constraint(equalTo: container.bottomAnchor).with(priority: UILayoutPriority(200)).isActive = true + view.bottomAnchor.constraint(equalTo: container.bottomAnchor) + .with(priority: UILayoutPriority(200)).isActive = true } - NSLayoutConstraint(item: view, attribute: .leading, relatedBy: .equal, toItem: container, attribute: .leading, multiplier: 1, constant: 0).isActive = true - NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: container, attribute: .trailing, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint( + item: view, + attribute: .leading, + relatedBy: .equal, + toItem: container, + attribute: .leading, + multiplier: 1, + constant: 0 + ).with(priority: .belowMessageSizeable).isActive = true + NSLayoutConstraint( + item: view, + attribute: .trailing, + relatedBy: .equal, + toItem: container, + attribute: .trailing, + multiplier: 1, + constant: 0 + ).with(priority: .belowMessageSizeable).isActive = true // Important to layout now in order to get the right safe area insets container.layoutIfNeeded() adjustMargins() diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index e16c076e..25fc11c7 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -105,9 +105,9 @@ class Presenter: NSObject { private static func animator(forPresentationStyle style: SwiftMessages.PresentationStyle, delegate: AnimationDelegate) -> Animator { switch style { case .top: - return TopBottomAnimation(style: .top, delegate: delegate) + return EdgeAnimation(style: .top, delegate: delegate) case .bottom: - return TopBottomAnimation(style: .bottom, delegate: delegate) + return EdgeAnimation(style: .bottom, delegate: delegate) case .center: return PhysicsAnimation(delegate: delegate) case .custom(let animator): diff --git a/SwiftMessages/SwiftMessagesSegue.swift b/SwiftMessages/SwiftMessagesSegue.swift index f20491bc..8013ccd0 100644 --- a/SwiftMessages/SwiftMessagesSegue.swift +++ b/SwiftMessages/SwiftMessagesSegue.swift @@ -69,60 +69,50 @@ import UIKit open class SwiftMessagesSegue: UIStoryboardSegue { /** - Specifies one of the pre-defined layouts, mirroring a subset of `MessageView.Layout`. + Specifies one of the pre-defined layout configurations. */ public enum Layout { - /// The standard message view layout on top. + /// The standard message view layout that slides down from the top edge. case topMessage - /// The standard message view layout on bottom. + /// The standard message view layout that slides up from the bottom edge. case bottomMessage - /// A floating card-style view with rounded corners on top - case topCard + /// The standard message view layout that slides in from the leading edge. + case leadingMessage - /// A floating tab-style view with rounded corners on bottom - case topTab + /// The standard message view layout that slides in from the trailing edge. + case trailingMessage - /// A floating card-style view with rounded corners on bottom + /// A floating card-style view with rounded corners that slides down from the top edge. + case topCard + + /// A floating card-style view with rounded corners that slides up from the bottom edge. case bottomCard - /// A floating tab-style view with rounded corners on top + /// A floating card-style view with rounded corners that slides in from the leading edge. + case leadingCard + + /// A floating card-style view with rounded corners that slides in from the trailing edge. + case trailingCard + + /// A floating tab-style view with rounded leading corners that slides down from the top edge. + case topTab + + /// A floating tab-style view with rounded leading corners that slides up from the bottom edge. case bottomTab + /// A floating tab-style view with rounded leading corners that slides in from the leading edge. + case leadingTab + + /// A floating tab-style view with rounded leading corners that slides in from the traling edge. + case trailingTab + /// A floating card-style view typically used with `.center` presentation style. case centered } - /** - Specifies how the view controller's view is installed into the - containing message view. - */ - public enum Containment { - - /** - The view controller's view is installed for edge-to-edge display, extending into the safe areas - to the device edges. This is done by calling `messageView.installContentView(:insets:)` - See that method's documentation for additional details. - */ - case content - - /** - The view controller's view is installed for card-style layouts, inset from the margins - and avoiding safe areas. This is done by calling `messageView.installBackgroundView(:insets:)`. - See that method's documentation for details. - */ - case background - - /** - The view controller's view is installed for tab-style layouts, inset from the side margins, but extending - to the device edge on the top or bottom. This is done by calling `messageView.installBackgroundVerticalView(:insets:)`. - See that method's documentation for details. - */ - case backgroundVertical - } - /// The presentation style to use. See the SwiftMessages.PresentationStyle for details. public var presentationStyle: SwiftMessages.PresentationStyle { get { return messenger.defaultConfig.presentationStyle } @@ -174,17 +164,11 @@ open class SwiftMessagesSegue: UIStoryboardSegue { /** The view controller's view is embedded in `containerView` before being installed into - `messageView`. This view provides configurable squircle (round) corners (see the parent + `messageView`. This view provides configurable continuous rounded corners (see the parent class `CornerRoundingView`). */ public var containerView: CornerRoundingView = CornerRoundingView() - /** - Specifies how the view controller's view is installed into the - containing message view. See `Containment` for details. - */ - public var containment: Containment = .content - /** Supply an instance of `KeyboardTrackingView` to have the message view avoid the keyboard. */ @@ -228,57 +212,130 @@ extension SwiftMessagesSegue { /// A convenience method for configuring some pre-defined layouts that mirror a subset of `MessageView.Layout`. public func configure(layout: Layout) { messageView.bounceAnimationOffset = 0 - containment = .content containerView.cornerRadius = 0 containerView.roundsLeadingCorners = false messageView.configureDropShadow() switch layout { case .topMessage: - messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) - messageView.collapseLayoutMarginAdditions = false - let animation = TopBottomAnimation(style: .top) +// TODO SIZE are these layout margin settings still relevant? +// messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) +// messageView.collapseLayoutMarginAdditions = false + let animation = EdgeAnimation(style: .top) animation.springDamping = 1 presentationStyle = .custom(animator: animation) case .bottomMessage: - messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) - messageView.collapseLayoutMarginAdditions = false - let animation = TopBottomAnimation(style: .bottom) +// messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) +// messageView.collapseLayoutMarginAdditions = false + let animation = EdgeAnimation(style: .bottom) + animation.springDamping = 1 + presentationStyle = .custom(animator: animation) + case .leadingMessage: +// messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) +// messageView.collapseLayoutMarginAdditions = false + let animation = EdgeAnimation(style: .leading) + animation.springDamping = 1 + presentationStyle = .custom(animator: animation) + case .trailingMessage: +// messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) +// messageView.collapseLayoutMarginAdditions = false + let animation = EdgeAnimation(style: .trailing) animation.springDamping = 1 presentationStyle = .custom(animator: animation) case .topCard: - containment = .background - messageView.layoutMarginAdditions = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) - messageView.collapseLayoutMarginAdditions = true + messageView.layout.insets.top = .absolute(0, from: .safeArea) + messageView.layout.insets.leading = .absolute(0, from: .safeArea) + messageView.layout.insets.trailing = .absolute(0, from: .safeArea) + messageView.layout.min.insets.top = .absolute(10, from: .superview) + messageView.layout.min.insets.leading = .absolute(10, from: .superview) + messageView.layout.min.insets.trailing = .absolute(10, from: .superview) + messageView.layout.min.insets.bottom = .absolute(10, from: .safeArea) containerView.cornerRadius = 15 presentationStyle = .top case .bottomCard: - containment = .background - messageView.layoutMarginAdditions = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) - messageView.collapseLayoutMarginAdditions = true + messageView.layout.insets.bottom = .absolute(0, from: .safeArea) + messageView.layout.insets.leading = .absolute(0, from: .safeArea) + messageView.layout.insets.trailing = .absolute(0, from: .safeArea) + messageView.layout.min.insets.bottom = .absolute(10, from: .superview) + messageView.layout.min.insets.leading = .absolute(10, from: .superview) + messageView.layout.min.insets.trailing = .absolute(10, from: .superview) + messageView.layout.min.insets.top = .absolute(10, from: .safeArea) containerView.cornerRadius = 15 presentationStyle = .bottom + case .leadingCard: + messageView.layout.insets.leading = .absolute(0, from: .safeArea) + messageView.layout.insets.top = .absolute(0, from: .safeArea) + messageView.layout.insets.bottom = .absolute(0, from: .safeArea) + messageView.layout.min.insets.leading = .absolute(10, from: .superview) + messageView.layout.min.insets.top = .absolute(10, from: .superview) + messageView.layout.min.insets.bottom = .absolute(10, from: .superview) + messageView.layout.min.insets.trailing = .absolute(10, from: .safeArea) + containerView.cornerRadius = 15 + let animation = EdgeAnimation(style: .leading) + presentationStyle = .custom(animator: animation) + case .trailingCard: + messageView.layout.insets.trailing = .absolute(0, from: .safeArea) + messageView.layout.insets.top = .absolute(0, from: .safeArea) + messageView.layout.insets.bottom = .absolute(0, from: .safeArea) + messageView.layout.min.insets.trailing = .absolute(10, from: .superview) + messageView.layout.min.insets.top = .absolute(10, from: .superview) + messageView.layout.min.insets.bottom = .absolute(10, from: .superview) + messageView.layout.min.insets.leading = .absolute(10, from: .safeArea) + containerView.cornerRadius = 15 + let animation = EdgeAnimation(style: .trailing) + presentationStyle = .custom(animator: animation) case .topTab: - containment = .backgroundVertical - messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 10, bottom: 20, right: 10) - messageView.collapseLayoutMarginAdditions = true + messageView.layout.insets.top = .absolute(0, from: .superview) + messageView.layout.insets.leading = .absolute(0, from: .safeArea) + messageView.layout.insets.trailing = .absolute(0, from: .safeArea) + messageView.layout.min.insets.leading = .absolute(10, from: .superview) + messageView.layout.min.insets.trailing = .absolute(10, from: .superview) + messageView.layout.min.insets.bottom = .absolute(10, from: .safeArea) containerView.cornerRadius = 15 containerView.roundsLeadingCorners = true - let animation = TopBottomAnimation(style: .top) + let animation = EdgeAnimation(style: .top) animation.springDamping = 1 presentationStyle = .custom(animator: animation) case .bottomTab: - containment = .backgroundVertical - messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 10, bottom: 20, right: 10) - messageView.collapseLayoutMarginAdditions = true + messageView.layout.insets.bottom = .absolute(0, from: .superview) + messageView.layout.insets.leading = .absolute(0, from: .safeArea) + messageView.layout.insets.trailing = .absolute(0, from: .safeArea) + messageView.layout.min.insets.leading = .absolute(10, from: .superview) + messageView.layout.min.insets.trailing = .absolute(10, from: .superview) + messageView.layout.min.insets.top = .absolute(10, from: .safeArea) containerView.cornerRadius = 15 containerView.roundsLeadingCorners = true - let animation = TopBottomAnimation(style: .bottom) + let animation = EdgeAnimation(style: .bottom) + animation.springDamping = 1 + presentationStyle = .custom(animator: animation) + case .leadingTab: + messageView.layout.insets.leading = .absolute(0, from: .superview) + messageView.layout.insets.top = .absolute(0, from: .safeArea) + messageView.layout.insets.bottom = .absolute(0, from: .safeArea) + messageView.layout.min.insets.top = .absolute(10, from: .superview) + messageView.layout.min.insets.bottom = .absolute(10, from: .superview) + messageView.layout.min.insets.trailing = .absolute(10, from: .safeArea) + containerView.cornerRadius = 15 + containerView.roundsLeadingCorners = true + let animation = EdgeAnimation(style: .leading) + animation.springDamping = 1 + presentationStyle = .custom(animator: animation) + case .trailingTab: + messageView.layout.insets.trailing = .absolute(0, from: .superview) + messageView.layout.insets.top = .absolute(0, from: .safeArea) + messageView.layout.insets.bottom = .absolute(0, from: .safeArea) + messageView.layout.min.insets.top = .absolute(10, from: .superview) + messageView.layout.min.insets.bottom = .absolute(10, from: .superview) + messageView.layout.min.insets.leading = .absolute(10, from: .safeArea) + containerView.cornerRadius = 15 + containerView.roundsLeadingCorners = true + let animation = EdgeAnimation(style: .trailing) animation.springDamping = 1 presentationStyle = .custom(animator: animation) case .centered: - containment = .background - messageView.layoutMarginAdditions = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) - messageView.collapseLayoutMarginAdditions = true + messageView.layout.min.insets.top = .absolute(10, from: .safeArea) + messageView.layout.min.insets.bottom = .absolute(10, from: .safeArea) + messageView.layout.min.insets.leading = .absolute(10, from: .safeArea) + messageView.layout.min.insets.trailing = .absolute(10, from: .safeArea) containerView.cornerRadius = 15 presentationStyle = .center } @@ -343,21 +400,12 @@ extension SwiftMessagesSegue { } completeTransition = transitionContext.completeTransition let transitionContainer = transitionContext.containerView - toView.translatesAutoresizingMaskIntoConstraints = false - segue.containerView.addSubview(toView) - segue.containerView.topAnchor.constraint(equalTo: toView.topAnchor).isActive = true - segue.containerView.bottomAnchor.constraint(equalTo: toView.bottomAnchor).isActive = true - segue.containerView.leadingAnchor.constraint(equalTo: toView.leadingAnchor).isActive = true - segue.containerView.trailingAnchor.constraint(equalTo: toView.trailingAnchor).isActive = true - // Install the `toView` into the message view. - switch segue.containment { - case .content: - segue.messageView.installContentView(segue.containerView) - case .background: + // Install the background and content views + do { segue.messageView.installBackgroundView(segue.containerView) - case .backgroundVertical: - segue.messageView.installBackgroundVerticalView(segue.containerView) + segue.messageView.installContentView(toView) } + let toVC = transitionContext.viewController(forKey: .to) // Nav controller automatically includes height of nav bar in, diff --git a/SwiftMessages/TopBottomAnimation.swift b/SwiftMessages/TopBottomAnimation.swift index 0a91fc3f..f8afc781 100644 --- a/SwiftMessages/TopBottomAnimation.swift +++ b/SwiftMessages/TopBottomAnimation.swift @@ -8,19 +8,22 @@ import UIKit -public class TopBottomAnimation: NSObject, Animator { +@available(*, deprecated, message: "Class renamed to `EdgeAnimation` to reflect new ability to do leading and trailing animations.") +public typealias TopBottomAnimation = EdgeAnimation + +public class EdgeAnimation: NSObject, Animator { public enum Style { case top case bottom + case leading + case trailing } public weak var delegate: AnimationDelegate? public let style: Style - open var heightDimension: Dimension? - open var showDuration: TimeInterval = 0.4 open var hideDuration: TimeInterval = 0.2 @@ -68,6 +71,10 @@ public class TopBottomAnimation: NSObject, Animator { view.transform = CGAffineTransform(translationX: 0, y: -view.frame.height) case .bottom: view.transform = CGAffineTransform(translationX: 0, y: view.frame.maxY + view.frame.height) + case .leading: // TODO SIZE do proper leading and trailing + view.transform = CGAffineTransform(translationX: -view.frame.width, y: 0) + case .trailing: + view.transform = CGAffineTransform(translationX: view.frame.maxX + view.frame.width, y: 0) } }, completion: { completed in #if SWIFTMESSAGES_APP_EXTENSIONS @@ -88,41 +95,66 @@ public class TopBottomAnimation: NSObject, Animator { if let adjustable = context.messageView as? MarginAdjustable { bounceOffset = adjustable.bounceAnimationOffset } - if let sizeableView = view as? MessageSizeable & UIView { - container.install(sizeableView: sizeableView) + if let layoutDefiningView = view as? LayoutDefining & UIView { + container.install(layoutDefiningView: layoutDefiningView) } else { view.translatesAutoresizingMaskIntoConstraints = false container.addSubview(view) } // Horizontal constraints do { - view.leadingAnchor.constraint(equalTo: container.leadingAnchor) - .with(priority: .belowMessageSizeable - 1) - .isActive = true - view.centerXAnchor.constraint(equalTo: container.centerXAnchor) - .with(priority: .belowMessageSizeable) - .isActive = true } switch style { case .top: - view.topAnchor.constraint(equalTo: container.topAnchor, constant: -bounceOffset) - .with(priority: .belowMessageSizeable) - .isActive = true + NSLayoutConstraint.activate([ + view.leadingAnchor.constraint(equalTo: container.leadingAnchor) + .with(priority: .belowMessageSizeable - 1), + view.centerXAnchor.constraint(equalTo: container.centerXAnchor) + .with(priority: .belowMessageSizeable), + view.topAnchor.constraint(equalTo: container.topAnchor, constant: -bounceOffset) + .with(priority: .belowMessageSizeable) + ]) case .bottom: - view.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: bounceOffset) - .with(priority: .belowMessageSizeable) - .isActive = true + NSLayoutConstraint.activate([ + view.leadingAnchor.constraint(equalTo: container.leadingAnchor) + .with(priority: .belowMessageSizeable - 1), + view.centerXAnchor.constraint(equalTo: container.centerXAnchor) + .with(priority: .belowMessageSizeable), + view.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: bounceOffset) + .with(priority: .belowMessageSizeable) + ]) + case .leading: + NSLayoutConstraint.activate([ + view.topAnchor.constraint(equalTo: container.topAnchor) + .with(priority: .belowMessageSizeable - 1), + view.centerYAnchor.constraint(equalTo: container.centerYAnchor) + .with(priority: .belowMessageSizeable), + view.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: -bounceOffset) + .with(priority: .belowMessageSizeable) + ]) + case .trailing: + NSLayoutConstraint.activate([ + view.topAnchor.constraint(equalTo: container.topAnchor) + .with(priority: .belowMessageSizeable - 1), + view.centerYAnchor.constraint(equalTo: container.centerYAnchor) + .with(priority: .belowMessageSizeable), + view.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: bounceOffset) + .with(priority: .belowMessageSizeable) + ]) } // Important to layout now in order to get the right safe area insets container.layoutIfNeeded() adjustMargins() container.layoutIfNeeded() - let animationDistance = view.frame.height switch style { case .top: - view.transform = CGAffineTransform(translationX: 0, y: -animationDistance) + view.transform = CGAffineTransform(translationX: 0, y: -view.frame.height) case .bottom: - view.transform = CGAffineTransform(translationX: 0, y: animationDistance) + view.transform = CGAffineTransform(translationX: 0, y: view.frame.height) + case .leading: + view.transform = CGAffineTransform(translationX: -view.frame.width, y: 0) + case .trailing: + view.transform = CGAffineTransform(translationX: view.frame.width, y: 0) } if context.interactiveHide { if let view = view as? BackgroundViewable { @@ -139,6 +171,10 @@ public class TopBottomAnimation: NSObject, Animator { cornerRoundingView.roundedCorners = [.bottomLeft, .bottomRight] case .bottom: cornerRoundingView.roundedCorners = [.topLeft, .topRight] + case .leading: + cornerRoundingView.roundedCorners = [.topRight, .bottomRight] + case .trailing: + cornerRoundingView.roundedCorners = [.topLeft, .bottomLeft] } } } @@ -156,6 +192,10 @@ public class TopBottomAnimation: NSObject, Animator { layoutMargins.top += bounceOffset case .bottom: layoutMargins.bottom += bounceOffset + case .leading: + layoutMargins.left += bounceOffset + case .trailing: + layoutMargins.right += bounceOffset } adjustable.layoutMargins = layoutMargins } @@ -191,21 +231,39 @@ public class TopBottomAnimation: NSObject, Animator { fileprivate var rubberBanding = false fileprivate var closeSpeed: CGFloat = 0.0 fileprivate var closePercent: CGFloat = 0.0 - fileprivate var panTranslationY: CGFloat = 0.0 + fileprivate var panTranslation: CGFloat = 0.0 @objc func pan(_ pan: UIPanGestureRecognizer) { switch pan.state { case .changed: guard let view = messageView else { return } - let height = view.bounds.height - bounceOffset - if height <= 0 { return } + let length: CGFloat + switch style { + case .top, .bottom: + length = view.bounds.height - bounceOffset + case .leading, .trailing: + length = view.bounds.width - bounceOffset + } + if length <= 0 { return } var velocity = pan.velocity(in: view) var translation = pan.translation(in: view) - if case .top = style { + switch style { + case .top: velocity.y *= -1.0 translation.y *= -1.0 + case .leading: + velocity.x *= -1.0 + translation.x *= -1.0 + case .bottom, .trailing: + break + } + var translationAmount: CGFloat + switch style { + case .top, .bottom: + translationAmount = translation.y >= 0 ? translation.y : -pow(abs(translation.y), 0.7) + case .leading, .trailing: + translationAmount = translation.x >= 0 ? translation.x : -pow(abs(translation.x), 0.7) } - var translationAmount = translation.y >= 0 ? translation.y : -pow(abs(translation.y), 0.7) if !closing { // Turn on rubber banding if background view is inset from message view. if let background = (messageView as? BackgroundViewable)?.backgroundView, background != view { @@ -214,6 +272,10 @@ public class TopBottomAnimation: NSObject, Animator { rubberBanding = background.frame.minY > 0 case .bottom: rubberBanding = background.frame.maxY < view.bounds.height + case .leading: + rubberBanding = background.frame.minX > 0 + case .trailing: + rubberBanding = background.frame.maxX < view.bounds.width } } if !rubberBanding && translationAmount < 0 { return } @@ -226,19 +288,30 @@ public class TopBottomAnimation: NSObject, Animator { view.transform = CGAffineTransform(translationX: 0, y: -translationAmount) case .bottom: view.transform = CGAffineTransform(translationX: 0, y: translationAmount) + case .leading: + view.transform = CGAffineTransform(translationX: -translationAmount, y: 0) + case .trailing: + view.transform = CGAffineTransform(translationX: translationAmount, y: 0) + } + switch style { + case .top, .bottom: + closeSpeed = velocity.y + closePercent = translation.y / length + panTranslation = translation.y + case .leading, .trailing: + closeSpeed = velocity.x + closePercent = translation.x / length + panTranslation = translation.x } - closeSpeed = velocity.y - closePercent = translation.y / height - panTranslationY = translation.y case .ended, .cancelled: - if closeSpeed > closeSpeedThreshold || closePercent > closePercentThreshold || panTranslationY > closeAbsoluteThreshold { + if closeSpeed > closeSpeedThreshold || closePercent > closePercentThreshold || panTranslation > closeAbsoluteThreshold { delegate?.hide(animator: self) } else { closing = false rubberBanding = false closeSpeed = 0.0 closePercent = 0.0 - panTranslationY = 0.0 + panTranslation = 0.0 showAnimation(completion: { (completed) in self.delegate?.panEnded(animator: self) }) diff --git a/SwiftMessages/UILayoutPriority+Extensions.swift b/SwiftMessages/UILayoutPriority+Extensions.swift index 1fd3ab88..ae6dc07e 100644 --- a/SwiftMessages/UILayoutPriority+Extensions.swift +++ b/SwiftMessages/UILayoutPriority+Extensions.swift @@ -9,10 +9,18 @@ import UIKit /// The priority used for `MessageSizeable` constraints -public extension UILayoutPriority { - static let aboveMessageSizeable: UILayoutPriority = messageInset + 1 - static let belowMessageSizeable: UILayoutPriority = messageSize - 1 - static let messageSize: UILayoutPriority = UILayoutPriority(900) - static let messageInset: UILayoutPriority = UILayoutPriority(901) +extension UILayoutPriority { + /// A constraint priority higher than those used for `MessageSizeable` + public static let aboveMessageSizeable: UILayoutPriority = messageInsetsBounds + 1 + + /// A constraint priority lower than those used for `MessageSizeable` + public static let belowMessageSizeable: UILayoutPriority = messageCenter - 1 + + static let messageCenter: UILayoutPriority = UILayoutPriority(900) + static let messageSize: UILayoutPriority = UILayoutPriority(901) + static let messageInsets: UILayoutPriority = UILayoutPriority(902) + static let messageCenterBounds: UILayoutPriority = UILayoutPriority(903) + static let messageSizeBounds: UILayoutPriority = UILayoutPriority(904) + static let messageInsetsBounds: UILayoutPriority = UILayoutPriority(905) } diff --git a/SwiftMessages/UIViewController+Extensions.swift b/SwiftMessages/UIViewController+Extensions.swift index 7fbd4dd1..6cedc0d5 100644 --- a/SwiftMessages/UIViewController+Extensions.swift +++ b/SwiftMessages/UIViewController+Extensions.swift @@ -87,14 +87,14 @@ extension UIViewController { } extension SwiftMessages.PresentationStyle { - /// A temporary workaround to allow custom presentation contexts using `TopBottomAnimation` + /// A temporary workaround to allow custom presentation contexts using `EdgeAnimation` /// to display properly behind bars. THe long term solution is to refactor all of the /// presentation context logic to work with safe area insets. - var topBottomStyle: TopBottomAnimation.Style? { + var topBottomStyle: EdgeAnimation.Style? { switch self { case .top: return .top case .bottom: return .bottom - case .custom(let animator): return (animator as? TopBottomAnimation)?.style + case .custom(let animator): return (animator as? EdgeAnimation)?.style case .center: return nil } } From e7d7e00c2d7f34bf0405c28e853564195bf369c3 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 20 Feb 2021 12:13:47 -0600 Subject: [PATCH 18/77] Adjust edge animation timing --- SwiftMessages.xcodeproj/project.pbxproj | 8 ++++---- ...{TopBottomAnimation.swift => EdgeAnimation.swift} | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) rename SwiftMessages/{TopBottomAnimation.swift => EdgeAnimation.swift} (97%) diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 47ac1180..23a9f5fe 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -55,7 +55,7 @@ 2290958125D9D407002E8111 /* UILayoutPriority+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */; }; 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; - 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */; }; + 2298C2091EE486E300E2DDC1 /* EdgeAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* EdgeAnimation.swift */; }; 22DFC9161EFF30F6001B1CA1 /* CenteredView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */; }; 22DFC9181F00674E001B1CA1 /* PhysicsPanHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */; }; 22E01F641E74EC8B00ACE19A /* MaskingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22E01F631E74EC8B00ACE19A /* MaskingView.swift */; }; @@ -143,7 +143,7 @@ 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILayoutPriority+Extensions.swift"; sourceTree = "<group>"; }; 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; - 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = "<group>"; }; + 2298C2081EE486E300E2DDC1 /* EdgeAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EdgeAnimation.swift; sourceTree = "<group>"; }; 22A2EA6E24EC6CFA00BB2540 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; }; 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = CenteredView.xib; path = Resources/CenteredView.xib; sourceTree = "<group>"; }; 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsPanHandler.swift; sourceTree = "<group>"; }; @@ -221,7 +221,7 @@ 2244656C1EF1D62700C50413 /* Animations */ = { isa = PBXGroup; children = ( - 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */, + 2298C2081EE486E300E2DDC1 /* EdgeAnimation.swift */, 2270044A1FAFA6DD0045DDC3 /* PhysicsAnimation.swift */, 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */, ); @@ -556,7 +556,7 @@ 86BBA8FF1D5E040600FE8F16 /* Presenter.swift in Sources */, 86BBA9051D5E040C00FE8F16 /* Theme.swift in Sources */, 86BBA9081D5E040C00FE8F16 /* Error.swift in Sources */, - 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */, + 2298C2091EE486E300E2DDC1 /* EdgeAnimation.swift in Sources */, 86589D471D64B6E40041676C /* BaseView.swift in Sources */, 225304622290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift in Sources */, 86BBA9071D5E040C00FE8F16 /* MarginAdjustable.swift in Sources */, diff --git a/SwiftMessages/TopBottomAnimation.swift b/SwiftMessages/EdgeAnimation.swift similarity index 97% rename from SwiftMessages/TopBottomAnimation.swift rename to SwiftMessages/EdgeAnimation.swift index f8afc781..21039378 100644 --- a/SwiftMessages/TopBottomAnimation.swift +++ b/SwiftMessages/EdgeAnimation.swift @@ -1,5 +1,5 @@ // -// TopBottomAnimation.swift +// EdgeAnimation.swift // SwiftMessages // // Created by Timothy Moose on 6/4/17. @@ -24,9 +24,9 @@ public class EdgeAnimation: NSObject, Animator { public let style: Style - open var showDuration: TimeInterval = 0.4 + open var showDuration: TimeInterval = 0.35 - open var hideDuration: TimeInterval = 0.2 + open var hideDuration: TimeInterval = 0.25 open var springDamping: CGFloat = 0.8 @@ -65,7 +65,7 @@ public class EdgeAnimation: NSObject, Animator { NotificationCenter.default.removeObserver(self) let view = context.messageView self.context = context - UIView.animate(withDuration: hideDuration, delay: 0, options: [.beginFromCurrentState, .curveEaseIn], animations: { + UIView.animate(withDuration: hideDuration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: [.beginFromCurrentState]) { switch self.style { case .top: view.transform = CGAffineTransform(translationX: 0, y: -view.frame.height) @@ -76,14 +76,14 @@ public class EdgeAnimation: NSObject, Animator { case .trailing: view.transform = CGAffineTransform(translationX: view.frame.maxX + view.frame.width, y: 0) } - }, completion: { completed in + } completion: { completed in #if SWIFTMESSAGES_APP_EXTENSIONS completion(completed) #else // Fix #131 by always completing if application isn't active. completion(completed || UIApplication.shared.applicationState != .active) #endif - }) + } } func install(context: AnimationContext) { From 46347dad9944042bbdf0ba315ee977146d0ef932 Mon Sep 17 00:00:00 2001 From: Seyed Mojtaba Hosseini Zeidabadi <ca.chairman@gmail.com> Date: Mon, 22 Feb 2021 17:36:37 +0330 Subject: [PATCH 19/77] Fix all comments misspellings. (#456) * Fix all comments misspellings. * Fix spell of `additionalAccessibilityElements`. Co-authored-by: Seyed Mojtaba Hosseini Zeidabadi <chenzook@gmail.com> --- SwiftMessages/AccessibleMessage.swift | 2 +- SwiftMessages/Animator.swift | 10 +++++----- SwiftMessages/Identifiable.swift | 2 +- SwiftMessages/MessageView.swift | 8 ++++---- SwiftMessages/Presenter.swift | 4 ++-- SwiftMessages/SwiftMessages.swift | 6 +++--- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/SwiftMessages/AccessibleMessage.swift b/SwiftMessages/AccessibleMessage.swift index 47a628ae..d540ecea 100644 --- a/SwiftMessages/AccessibleMessage.swift +++ b/SwiftMessages/AccessibleMessage.swift @@ -16,5 +16,5 @@ import Foundation public protocol AccessibleMessage { var accessibilityMessage: String? { get } var accessibilityElement: NSObject? { get } - var additonalAccessibilityElements: [NSObject]? { get } + var additionalAccessibilityElements: [NSObject]? { get } } diff --git a/SwiftMessages/Animator.swift b/SwiftMessages/Animator.swift index 292ea395..3897dd1f 100644 --- a/SwiftMessages/Animator.swift +++ b/SwiftMessages/Animator.swift @@ -18,7 +18,7 @@ public protocol AnimationDelegate: class { /** An option set representing the known types of safe area conflicts - that could require margin adustments on the message view in order to + that could require margin adjustments on the message view in order to get the layouts to look right. */ public struct SafeZoneConflicts: OptionSet { @@ -71,12 +71,12 @@ public protocol Animator: class { func hide(context: AnimationContext, completion: @escaping AnimationCompletion) - /// The show animation duration. If the animation duration is unknown, such as if using `UIDynamnicAnimator`, - /// then profide an estimate. This value is used by `SwiftMessagesSegue`. + /// The show animation duration. If the animation duration is unknown, such as if using `UIDynamicAnimator`, + /// then provide an estimate. This value is used by `SwiftMessagesSegue`. var showDuration: TimeInterval { get } - /// The hide animation duration. If the animation duration is unknown, such as if using `UIDynamnicAnimator`, - /// then profide an estimate. This value is used by `SwiftMessagesSegue`. + /// The hide animation duration. If the animation duration is unknown, such as if using `UIDynamicAnimator`, + /// then provide an estimate. This value is used by `SwiftMessagesSegue`. var hideDuration: TimeInterval { get } } diff --git a/SwiftMessages/Identifiable.swift b/SwiftMessages/Identifiable.swift index cd288492..4594b2d0 100644 --- a/SwiftMessages/Identifiable.swift +++ b/SwiftMessages/Identifiable.swift @@ -14,7 +14,7 @@ import Foundation representation of the content of the message view. For example, `MessageView`, combines the title and message body text. - This protocol is optional. Messave views that don't adopt `Identifiable` will not + This protocol is optional. Message views that don't adopt `Identifiable` will not have duplicates removed. */ public protocol Identifiable { diff --git a/SwiftMessages/MessageView.swift b/SwiftMessages/MessageView.swift index 7bc1b462..d9be31d9 100644 --- a/SwiftMessages/MessageView.swift +++ b/SwiftMessages/MessageView.swift @@ -88,7 +88,7 @@ open class MessageView: BaseView, Identifiable, AccessibleMessage { /** An optional prefix for the `accessibilityMessage` that can - be used to futher clarify the message for VoiceOver. For example, + be used to further clarify the message for VoiceOver. For example, the view's background color or icon might convey that a message is a warning, in which case one may specify the value "warning". */ @@ -108,7 +108,7 @@ open class MessageView: BaseView, Identifiable, AccessibleMessage { return backgroundView } - open var additonalAccessibilityElements: [NSObject]? { + open var additionalAccessibilityElements: [NSObject]? { var elements: [NSObject] = [] func getAccessibleSubviews(view: UIView) { for subview in view.subviews { @@ -206,7 +206,7 @@ extension MessageView { /* MARK: - Layout adjustments - This extention provides a few convenience functions for adjusting the layout. + This extension provides a few convenience functions for adjusting the layout. */ extension MessageView { @@ -236,7 +236,7 @@ extension MessageView { /* MARK: - Theming - This extention provides a few convenience functions for setting styles, + This extension provides a few convenience functions for setting styles, colors and icons. You are encouraged to write your own such functions if these don't exactly meet your needs. */ diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index 25fc11c7..c4e5549f 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -175,7 +175,7 @@ class Presenter: NSObject { private func showAccessibilityFocus() { guard let accessibleMessage = view as? AccessibleMessage, - let focus = accessibleMessage.accessibilityElement ?? accessibleMessage.additonalAccessibilityElements?.first else { return } + let focus = accessibleMessage.accessibilityElement ?? accessibleMessage.additionalAccessibilityElements?.first else { return } UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: focus) } @@ -388,7 +388,7 @@ class Presenter: NSObject { } elements.append(element) } - if let additional = accessibleMessage.additonalAccessibilityElements { + if let additional = accessibleMessage.additionalAccessibilityElements { elements += additional } } else { diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index d5e6ba93..dfae859c 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -55,8 +55,8 @@ open class SwiftMessages { appropriate one is found. Otherwise, it is displayed in a new window at level `UIWindow.Level.normal`. Use this option to automatically display under bars, where applicable. Because this option involves a top-down - search, an approrpiate context might not be found when the view controller - heirarchy incorporates custom containers. If this is the case, the + search, an appropriate context might not be found when the view controller + hierarchy incorporates custom containers. If this is the case, the .ViewController option can provide a more targeted context. */ case automatic @@ -87,7 +87,7 @@ open class SwiftMessages { appropriate one is found using the given view controller as a starting point and searching up the parent view controller chain. Otherwise, it is displayed in the given view controller's view. This option can be used - for targeted placement in a view controller heirarchy. + for targeted placement in a view controller hierarchy. */ case viewController(_: UIViewController) From cc1b635513ebd9f350b41a172ec418dc3593494f Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Mon, 22 Feb 2021 08:17:53 -0600 Subject: [PATCH 20/77] Add absoluteInsets size option --- SwiftMessages/Layout.swift | 11 +++++++++++ SwiftMessages/MaskingView.swift | 16 +++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/SwiftMessages/Layout.swift b/SwiftMessages/Layout.swift index 4afcf7b7..0d02fa6c 100644 --- a/SwiftMessages/Layout.swift +++ b/SwiftMessages/Layout.swift @@ -35,6 +35,7 @@ public struct Layout { public enum Dimension { case absolute(CGFloat) case relative(CGFloat, to: Boundary) + case absoluteInsets(CGFloat, to: Boundary) } public var width: Dimension? @@ -81,6 +82,16 @@ extension Layout.Insets.Dimension { } } +extension Layout.Size.Dimension { + var boundary: Layout.Boundary? { + switch self { + case .absolute(_): return nil + case .relative(_, let boundary): return boundary + case .absoluteInsets(_, let boundary): return boundary + } + } +} + extension Layout.Center.Dimension { var boundary: Layout.Boundary { switch self { diff --git a/SwiftMessages/MaskingView.swift b/SwiftMessages/MaskingView.swift index 81301994..08c31d20 100644 --- a/SwiftMessages/MaskingView.swift +++ b/SwiftMessages/MaskingView.swift @@ -417,10 +417,8 @@ class MaskingView: PassthroughView, LayoutInstalling { for dimension: Layout.Size.Dimension, extractor: (CGRect) -> CGFloat ) -> CGFloat { - switch dimension { - case .absolute(let dimension): - return dimension - case .relative(let percentage, let boundary): + let insetBounds: CGRect = { + guard let boundary = dimension.boundary else { return .zero } let insets: UIEdgeInsets switch boundary { case .superview: insets = .zero @@ -432,7 +430,15 @@ class MaskingView: PassthroughView, LayoutInstalling { insets = layoutMargins } } - return extractor(bounds.inset(by: insets)) * percentage + return bounds.inset(by: insets) + }() + switch dimension { + case .absolute(let dimension): + return dimension + case .relative(let percentage, _): + return extractor(insetBounds) * percentage + case .absoluteInsets(let dimension, _): + return extractor(insetBounds) - dimension * 2 } } From f3a0aca1111e891841e44227ec6a1d0d11b7de9d Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Mon, 22 Feb 2021 08:21:56 -0600 Subject: [PATCH 21/77] Fix arg name --- SwiftMessages/Layout.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftMessages/Layout.swift b/SwiftMessages/Layout.swift index 0d02fa6c..83100822 100644 --- a/SwiftMessages/Layout.swift +++ b/SwiftMessages/Layout.swift @@ -35,7 +35,7 @@ public struct Layout { public enum Dimension { case absolute(CGFloat) case relative(CGFloat, to: Boundary) - case absoluteInsets(CGFloat, to: Boundary) + case absoluteInsets(CGFloat, from: Boundary) } public var width: Dimension? From 4408c09c863b1c6af4d053fe17fd532a4f96b237 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Mon, 22 Feb 2021 08:33:49 -0600 Subject: [PATCH 22/77] Public Layout initializer --- SwiftMessages/Layout.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SwiftMessages/Layout.swift b/SwiftMessages/Layout.swift index 83100822..09c2c16f 100644 --- a/SwiftMessages/Layout.swift +++ b/SwiftMessages/Layout.swift @@ -24,6 +24,8 @@ public struct Layout { public var min = Layout() public var max = Layout() + public init() {} + public enum Boundary { case superview case safeArea From 851e798a027bab1457eb1afae49c55705eaf7bec Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Thu, 11 Mar 2021 14:17:50 -0600 Subject: [PATCH 23/77] Stop using deprecated keyWindow API --- SwiftMessages.xcodeproj/project.pbxproj | 4 ++++ SwiftMessages/Presenter.swift | 2 +- .../SwiftMessages.Config+Extensions.swift | 2 +- SwiftMessages/UIWindow+Extensions.swift | 24 +++++++++++++++++++ SwiftMessages/WindowViewController.swift | 2 +- 5 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 SwiftMessages/UIWindow+Extensions.swift diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 4eef9ad5..b80cc86b 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -54,6 +54,7 @@ 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */; }; + 229F778125FAB1E9008C2ACB /* UIWindow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */; }; 22DFC9161EFF30F6001B1CA1 /* CenteredView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */; }; 22DFC9181F00674E001B1CA1 /* PhysicsPanHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */; }; 22E01F641E74EC8B00ACE19A /* MaskingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22E01F631E74EC8B00ACE19A /* MaskingView.swift */; }; @@ -140,6 +141,7 @@ 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = "<group>"; }; + 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+Extensions.swift"; sourceTree = "<group>"; }; 22A2EA6E24EC6CFA00BB2540 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; }; 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = CenteredView.xib; path = Resources/CenteredView.xib; sourceTree = "<group>"; }; 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsPanHandler.swift; sourceTree = "<group>"; }; @@ -209,6 +211,7 @@ children = ( 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */, 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */, + 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */, ); name = Extensions; sourceTree = "<group>"; @@ -546,6 +549,7 @@ 86BBA9041D5E040600FE8F16 /* NSBundle+Extensions.swift in Sources */, 86BBA8FD1D5E03F800FE8F16 /* SwiftMessages.swift in Sources */, 86BBA9021D5E040600FE8F16 /* WindowViewController.swift in Sources */, + 229F778125FAB1E9008C2ACB /* UIWindow+Extensions.swift in Sources */, 86BBA8FF1D5E040600FE8F16 /* Presenter.swift in Sources */, 86BBA9051D5E040C00FE8F16 /* Theme.swift in Sources */, 86BBA9081D5E040C00FE8F16 /* Error.swift in Sources */, diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index e16c076e..43b19ee7 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -301,7 +301,7 @@ class Presenter: NSObject { #if SWIFTMESSAGES_APP_EXTENSIONS throw SwiftMessagesError.noRootViewController #else - if let rootViewController = UIApplication.shared.keyWindow?.rootViewController { + if let rootViewController = UIWindow.keyWindow?.rootViewController { let viewController = rootViewController.sm_selectPresentationContextTopDown(config) return .viewController(Weak(value: viewController)) } else { diff --git a/SwiftMessages/SwiftMessages.Config+Extensions.swift b/SwiftMessages/SwiftMessages.Config+Extensions.swift index 2dfe7ae4..9682b5b9 100644 --- a/SwiftMessages/SwiftMessages.Config+Extensions.swift +++ b/SwiftMessages/SwiftMessages.Config+Extensions.swift @@ -25,7 +25,7 @@ extension SwiftMessages.Config { #if SWIFTMESSAGES_APP_EXTENSIONS return nil #else - return UIApplication.shared.keyWindow?.windowScene + return UIWindow.keyWindow?.windowScene #endif } } diff --git a/SwiftMessages/UIWindow+Extensions.swift b/SwiftMessages/UIWindow+Extensions.swift new file mode 100644 index 00000000..ff5239a8 --- /dev/null +++ b/SwiftMessages/UIWindow+Extensions.swift @@ -0,0 +1,24 @@ +// +// UIWindow+Extensions.swift +// SwiftMessages +// +// Created by Timothy Moose on 3/11/21. +// Copyright © 2021 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +extension UIWindow { + static var keyWindow: UIWindow? { + if #available(iOS 13.0, *) { + return UIApplication.shared.connectedScenes + .filter { $0.activationState == .foregroundActive } + .compactMap { $0 as? UIWindowScene } + .first?.windows + .filter { $0.isKeyWindow } + .first + } else { + return UIApplication.shared.keyWindow + } + } +} diff --git a/SwiftMessages/WindowViewController.swift b/SwiftMessages/WindowViewController.swift index 65b85854..5e61af1d 100644 --- a/SwiftMessages/WindowViewController.swift +++ b/SwiftMessages/WindowViewController.swift @@ -37,7 +37,7 @@ open class WindowViewController: UIViewController window?.windowScene = config.windowScene if config.shouldBecomeKeyWindow { #if !SWIFTMESSAGES_APP_EXTENSIONS - previousKeyWindow = UIApplication.shared.keyWindow + previousKeyWindow = UIWindow.keyWindow #endif } show( From eeb685398f4cea6f8c54e63bd87a0d81393cc515 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Thu, 11 Mar 2021 14:34:30 -0600 Subject: [PATCH 24/77] Improve key window restoration logic --- SwiftMessages/WindowViewController.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/SwiftMessages/WindowViewController.swift b/SwiftMessages/WindowViewController.swift index 5e61af1d..96b30095 100644 --- a/SwiftMessages/WindowViewController.swift +++ b/SwiftMessages/WindowViewController.swift @@ -35,11 +35,9 @@ open class WindowViewController: UIViewController func install() { if #available(iOS 13, *) { window?.windowScene = config.windowScene - if config.shouldBecomeKeyWindow { - #if !SWIFTMESSAGES_APP_EXTENSIONS - previousKeyWindow = UIWindow.keyWindow - #endif - } + #if !SWIFTMESSAGES_APP_EXTENSIONS + previousKeyWindow = UIWindow.keyWindow + #endif show( becomeKey: config.shouldBecomeKeyWindow, frame: config.windowScene?.coordinateSpace.bounds @@ -60,12 +58,14 @@ open class WindowViewController: UIViewController } func uninstall() { + if window?.isKeyWindow == true { + previousKeyWindow?.makeKeyAndVisible() + } if #available(iOS 13, *) { window?.windowScene = nil } window?.isHidden = true window = nil - previousKeyWindow?.makeKeyAndVisible() } required public init?(coder aDecoder: NSCoder) { From 76d7971c95f4f8461b36ca82b801f775994b9a1d Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Thu, 18 Mar 2021 11:20:17 -0500 Subject: [PATCH 25/77] Update podspec --- CHANGELOG.md | 6 ++++++ SwiftMessages.podspec | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 239b08f7..8beecbfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change Log All notable changes to this project will be documented in this file. +## 9.0.1 + +### Fixes + +* #455 #458 Restore key window after message is interacted with. When a message becomes the key window, such as if the user interacts with the message, iOS does not automatically restore the previous key window when the message is dismissed. SwiftMessages has some logic in `WindowViewController` to restore the key window. This change makes that logic more robust. + ## 9.0.0 ### Features diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 22b2d781..f9fafd91 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.0.0' + spec.version = '9.0.1' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } From c63e64e8a8988f0885e3ee23fb1e50f9b6cbd584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emre=20=C3=87ift=C3=A7i?= <emre.ciftci@cci.com.tr> Date: Sun, 21 Mar 2021 20:51:39 +0300 Subject: [PATCH 26/77] refactor(MessageView): remove redundant words for `button` (#461) --- SwiftMessages/MessageView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftMessages/MessageView.swift b/SwiftMessages/MessageView.swift index d9be31d9..e844b074 100644 --- a/SwiftMessages/MessageView.swift +++ b/SwiftMessages/MessageView.swift @@ -55,7 +55,7 @@ open class MessageView: BaseView, Identifiable, AccessibleMessage { /// An optional button. This buttons' `.TouchUpInside` event will automatically /// invoke the optional `buttonTapHandler`, but its fine to add other target - /// action handlers can be added. + /// action handlers. @IBOutlet open var button: UIButton? { didSet { if let old = oldValue { From ba6c3e7284a531965feff058ba36784f30017843 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Wed, 24 Mar 2021 10:52:15 -0500 Subject: [PATCH 27/77] Fix app extension compile error when using CocoaPods --- CHANGELOG.md | 6 + SwiftMessages.podspec | 2 +- SwiftMessages/UIWindow+Extensions.swift | 2 + iMessageDemo/Podfile | 19 + iMessageDemo/Podfile.lock | 16 + .../Local Podspecs/SwiftMessages.podspec.json | 49 + iMessageDemo/Pods/Manifest.lock | 16 + .../Pods/Pods.xcodeproj/project.pbxproj | 1188 +++++++++++++++++ .../Pods-iMessageDemo-Info.plist | 26 + ...ods-iMessageDemo-acknowledgements.markdown | 14 + .../Pods-iMessageDemo-acknowledgements.plist | 46 + .../Pods-iMessageDemo-dummy.m | 5 + ...mo-frameworks-Debug-input-files.xcfilelist | 2 + ...o-frameworks-Debug-output-files.xcfilelist | 1 + ...-frameworks-Release-input-files.xcfilelist | 2 + ...frameworks-Release-output-files.xcfilelist | 1 + .../Pods-iMessageDemo-frameworks.sh | 185 +++ .../Pods-iMessageDemo-umbrella.h | 16 + .../Pods-iMessageDemo.debug.xcconfig | 14 + .../Pods-iMessageDemo.modulemap | 6 + .../Pods-iMessageDemo.release.xcconfig | 14 + .../Pods-iMessageExtensionDemo-Info.plist | 26 + ...ageExtensionDemo-acknowledgements.markdown | 14 + ...essageExtensionDemo-acknowledgements.plist | 46 + .../Pods-iMessageExtensionDemo-dummy.m | 5 + .../Pods-iMessageExtensionDemo-umbrella.h | 16 + .../Pods-iMessageExtensionDemo.debug.xcconfig | 13 + .../Pods-iMessageExtensionDemo.modulemap | 6 + ...ods-iMessageExtensionDemo.release.xcconfig | 13 + ...dle-SwiftMessages-SwiftMessages-Info.plist | 24 + ...ges_SwiftMessages-SwiftMessages-Info.plist | 24 + .../SwiftMessages/SwiftMessages-Info.plist | 26 + .../SwiftMessages/SwiftMessages-dummy.m | 5 + .../SwiftMessages/SwiftMessages-prefix.pch | 12 + .../SwiftMessages/SwiftMessages-umbrella.h | 16 + .../SwiftMessages.debug.xcconfig | 15 + .../SwiftMessages/SwiftMessages.modulemap | 6 + .../SwiftMessages.release.xcconfig | 15 + .../iMessageDemo.xcodeproj/project.pbxproj | 166 +-- .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + 41 files changed, 2020 insertions(+), 76 deletions(-) create mode 100644 iMessageDemo/Podfile create mode 100644 iMessageDemo/Podfile.lock create mode 100644 iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json create mode 100644 iMessageDemo/Pods/Manifest.lock create mode 100644 iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-acknowledgements.markdown create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-acknowledgements.plist create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-dummy.m create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-input-files.xcfilelist create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-output-files.xcfilelist create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-input-files.xcfilelist create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-output-files.xcfilelist create mode 100755 iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-umbrella.h create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.debug.xcconfig create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.modulemap create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.release.xcconfig create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.markdown create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.plist create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-dummy.m create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-umbrella.h create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.debug.xcconfig create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.modulemap create mode 100644 iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.release.xcconfig create mode 100644 iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages-SwiftMessages-Info.plist create mode 100644 iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist create mode 100644 iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist create mode 100644 iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-dummy.m create mode 100644 iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-prefix.pch create mode 100644 iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-umbrella.h create mode 100644 iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.debug.xcconfig create mode 100644 iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.modulemap create mode 100644 iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.release.xcconfig create mode 100644 iMessageDemo/iMessageDemo.xcworkspace/contents.xcworkspacedata create mode 100644 iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/CHANGELOG.md b/CHANGELOG.md index 8beecbfb..08f50bbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change Log All notable changes to this project will be documented in this file. +## 9.0.2 + +### Fixes + +* Fix app extension compile error when using CocoaPods. + ## 9.0.1 ### Fixes diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index f9fafd91..820b4e9a 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.0.1' + spec.version = '9.0.2' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } diff --git a/SwiftMessages/UIWindow+Extensions.swift b/SwiftMessages/UIWindow+Extensions.swift index ff5239a8..d98c6caf 100644 --- a/SwiftMessages/UIWindow+Extensions.swift +++ b/SwiftMessages/UIWindow+Extensions.swift @@ -9,6 +9,7 @@ import UIKit extension UIWindow { + #if !SWIFTMESSAGES_APP_EXTENSIONS static var keyWindow: UIWindow? { if #available(iOS 13.0, *) { return UIApplication.shared.connectedScenes @@ -21,4 +22,5 @@ extension UIWindow { return UIApplication.shared.keyWindow } } + #endif } diff --git a/iMessageDemo/Podfile b/iMessageDemo/Podfile new file mode 100644 index 00000000..7c45a63f --- /dev/null +++ b/iMessageDemo/Podfile @@ -0,0 +1,19 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'iMessageDemo' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + # Pods for iMessageDemo + +end + +target 'iMessageExtensionDemo' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + # Pods for iMessageExtensionDemo + pod 'SwiftMessages/AppExtension', :path => "../" + +end diff --git a/iMessageDemo/Podfile.lock b/iMessageDemo/Podfile.lock new file mode 100644 index 00000000..552070e5 --- /dev/null +++ b/iMessageDemo/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - SwiftMessages/AppExtension (9.0.1) + +DEPENDENCIES: + - SwiftMessages/AppExtension (from `../`) + +EXTERNAL SOURCES: + SwiftMessages: + :path: "../" + +SPEC CHECKSUMS: + SwiftMessages: b71f53eb919887c0273bf43cbc002bd4f0cfb3d6 + +PODFILE CHECKSUM: 4cfafdad7d8903d0f4cfadbe05660bcdeff7c9e6 + +COCOAPODS: 1.10.0 diff --git a/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json b/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json new file mode 100644 index 00000000..72a5b097 --- /dev/null +++ b/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json @@ -0,0 +1,49 @@ +{ + "name": "SwiftMessages", + "version": "9.0.1", + "license": { + "type": "MIT" + }, + "homepage": "https://github.com/SwiftKickMobile/SwiftMessages", + "authors": { + "Timothy Moose": "tim@swiftkick.it" + }, + "summary": "A very flexible message bar for iOS written in Swift.", + "source": { + "git": "https://github.com/SwiftKickMobile/SwiftMessages.git", + "tag": "9.0.1" + }, + "platforms": { + "ios": "9.0" + }, + "swift_versions": "5.0", + "frameworks": "UIKit", + "requires_arc": true, + "default_subspecs": "App", + "subspecs": [ + { + "name": "App", + "source_files": "SwiftMessages/**/*.swift", + "resource_bundles": { + "SwiftMessages": [ + "SwiftMessages/Resources/*.*" + ] + } + }, + { + "name": "AppExtension", + "source_files": "SwiftMessages/**/*.swift", + "exclude_files": "SwiftMessages/**/SegueConvenienceClasses.swift", + "resource_bundles": { + "SwiftMessages_SwiftMessages": [ + "SwiftMessages/Resources/**/*.*" + ] + }, + "pod_target_xcconfig": { + "SWIFT_ACTIVE_COMPILATION_CONDITIONS": "SWIFTMESSAGES_APP_EXTENSIONS", + "GCC_PREPROCESSOR_DEFINITIONS": "SWIFTMESSAGES_APP_EXTENSIONS=1" + } + } + ], + "swift_version": "5.0" +} diff --git a/iMessageDemo/Pods/Manifest.lock b/iMessageDemo/Pods/Manifest.lock new file mode 100644 index 00000000..552070e5 --- /dev/null +++ b/iMessageDemo/Pods/Manifest.lock @@ -0,0 +1,16 @@ +PODS: + - SwiftMessages/AppExtension (9.0.1) + +DEPENDENCIES: + - SwiftMessages/AppExtension (from `../`) + +EXTERNAL SOURCES: + SwiftMessages: + :path: "../" + +SPEC CHECKSUMS: + SwiftMessages: b71f53eb919887c0273bf43cbc002bd4f0cfb3d6 + +PODFILE CHECKSUM: 4cfafdad7d8903d0f4cfadbe05660bcdeff7c9e6 + +COCOAPODS: 1.10.0 diff --git a/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj b/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 00000000..468092a5 --- /dev/null +++ b/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,1188 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 00468531530F8A70E3D83622BD482026 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E6941E59EF0D89949E3DF3D89488430 /* Weak.swift */; }; + 0303F738260F2C9BAE20B79DE84E82BC /* PhysicsPanHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2337E6D5F621F3CE9A1E3761984EBE87 /* PhysicsPanHandler.swift */; }; + 0B42A04122166EAD384BCE37FD450FAF /* MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8901520225CE89F44E6DE88688F29C10 /* MessageView.swift */; }; + 0CE00BF7FB0F6376D89B0AFF1CFD7510 /* PassthroughView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C557E1DC95AFA417E94ED01301F9F2 /* PassthroughView.swift */; }; + 0E7AE1B3CE2734B39ACCE812B4320B44 /* MarginAdjustable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B91AD9D9E743D17D553D48103BE27C46 /* MarginAdjustable+Extensions.swift */; }; + 138A7742F76993FB9EE3555FD2808562 /* successIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = A80433B71162112A79043CB64261DB51 /* successIconLight.png */; }; + 16047C447B00FAA7F42764EC4167C33B /* NSLayoutConstraint+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0970322A5DD8B4A8373C35ED051DE156 /* NSLayoutConstraint+Extensions.swift */; }; + 1F4159921A25C7B2A0E9C587387D829C /* errorIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1B04615682E8B787C964824435BC6616 /* errorIconLight@2x.png */; }; + 1F6162906845BE72A5BCDAF14D6E14B9 /* warningIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 4512DEEA328AB0AAA95D77C84C89E02C /* warningIconSubtle.png */; }; + 2181E713FC7C00EE871FDA6CB62C7E8C /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5607E285A85AC7163B0B8FD447FD27E /* Theme.swift */; }; + 2558CABB502ED605BC21DCFC55A9C0B7 /* MessageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = AE62AA801971C530345349D18AFCCB82 /* MessageView.xib */; }; + 2B23A9DFDAACFE9C0AD5EB6899E63475 /* infoIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4FE466AC4123CDAE9FDA9FCF4FB9CC60 /* infoIconSubtle@2x.png */; }; + 33785D52B8888C2EA02BD0495408E352 /* successIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A865FFBAE49EF66A35CB9D709E8D7E /* successIconLight@3x.png */; }; + 3505AB28DBFA49FBE5C8250F3E067E60 /* KeyboardTrackingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536660614870EA0E051BF6BDDF495798 /* KeyboardTrackingView.swift */; }; + 365594AAFDD4EE947EB33E6E86A8578E /* errorIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = A850F76D7E3FEDC20FFB877454069171 /* errorIconSubtle.png */; }; + 425F2D4CE95436680D77C263FF15221B /* SwiftMessages_SwiftMessages.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages_SwiftMessages.bundle */; }; + 4267FACE20717FF3F51C2ACAB8C395A4 /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0D0E8B0020635F606875DD02735C502 /* BaseView.swift */; }; + 44150A4B5B2D251FCBB6CA07DC9872B5 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 267E35F9851AAE50DFB8FA0DCA7F2980 /* Animator.swift */; }; + 447E8A096C1ABD2E0AC9674E65A827E3 /* warningIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 0259757860B26C6072E2640B84EC6D45 /* warningIcon.png */; }; + 44C0F194D748EE88027414A5B2094E9B /* successIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8155ED78358FA5CF39089176FBDE501 /* successIcon@3x.png */; }; + 461760E2818D72B948B60B4835E7B1ED /* NSBundle+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FCF161BD9F1C2CAAFBCADE5E59BD3FD /* NSBundle+Extensions.swift */; }; + 462CDC24C5C8DD6905C4112B6B4BD2ED /* successIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = FC73E6C784AF6CA1F956F57F82ED2803 /* successIcon.png */; }; + 46CCA4DDFDBBDD2A9426BB96C08E4255 /* Pods-iMessageExtensionDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F40CA14AD738DD186B4DA8FD14AE5BD /* Pods-iMessageExtensionDemo-dummy.m */; }; + 492F085489FCAB0EEBE74B098F7D3F4D /* StatusLine.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7A6801849037A728E9BC50E06CE8AD2F /* StatusLine.xib */; }; + 4C78ED4E1780F5609E25CE03429C1DE4 /* errorIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 848251807107C20960A3DABAB27F7475 /* errorIconLight@3x.png */; }; + 4DB5D1FB08693DDDC32BCF19CC1B1AA0 /* warningIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 874D31DE863C88B1D699E1EBFBE0641B /* warningIconLight@2x.png */; }; + 4E703B2A80C64CF1142872BE31263940 /* errorIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 0892E032AE12339D1AD84BDCC78A3C07 /* errorIconLight.png */; }; + 4E9CCFC43646B6CDBE3B787AB09A0147 /* CardView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 42F1E753E61B6EDED3908AC66994649C /* CardView.xib */; }; + 5260BD3289BAC54A20457099C4A57EFF /* errorIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 9D1FEAC04417D847EDC10783E054988F /* errorIcon.png */; }; + 52F4ED7F78829270B2AFE5EDBA9EEE2F /* UIEdgeInsets+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9A13E69643D651322647C28E3F9E9C9 /* UIEdgeInsets+Extensions.swift */; }; + 560A2B1056FEFE42AC6524A2A1742CA2 /* Pods-iMessageExtensionDemo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CAB201AD00CAB811B045E2FFB5C03A8 /* Pods-iMessageExtensionDemo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 57072960EA4F0D307171ED90697D3FAF /* TabView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B7FD0618783A3E6B90D3A3323633959F /* TabView.xib */; }; + 5720D965B3CE67653082137053FBEC9C /* infoIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C110C924ED12D2D32ECC27503018A31 /* infoIconLight.png */; }; + 5750C24C3A9CAE11C7E36B37434912D0 /* MaskingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CF61FDEFE095F0486E9914F2262ADB9 /* MaskingView.swift */; }; + 5DF3F4808ED4A6932839C11A5D742B93 /* successIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 54B278C80D821C120FA70ABB6CAF1F46 /* successIconSubtle@3x.png */; }; + 6320AE79D41E8D1F52AF66A670542561 /* CornerRoundingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F8D7902822221456B697BB41111E450 /* CornerRoundingView.swift */; }; + 64595C731B826EB19E9757D524E0BF76 /* warningIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2CFBBC25592C97C925B6F81B53BE57CB /* warningIcon@3x.png */; }; + 683A7897D1E9A73F4717198B1C054D29 /* errorIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 60268FE48AA4DC9FD5060B1E5CE68453 /* errorIcon@2x.png */; }; + 6A539682FDDA0E5DA23E1B5F2BA133C1 /* errorIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6DEAADC09FEB1A8D5B90108103EE478 /* errorIcon@3x.png */; }; + 6C7DAA6A68AFDACD67F2C127CEF4DD6F /* UIWindow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 397C8F928170138667B9326F9655D75D /* UIWindow+Extensions.swift */; }; + 755DA479621A9D2BB8B84540DE648A7A /* warningIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 667DECE93ABCC6869A071FFEB0F83EA5 /* warningIconSubtle@3x.png */; }; + 7ACCA07CCFD868899D61F4B4AE5774DB /* infoIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B7213B7DC5432DA2B272F25E17AA364 /* infoIconSubtle@3x.png */; }; + 7BC52E6F0D9D19B05E62E623E53FCE82 /* Pods-iMessageDemo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D0ECE831FB5E0EE1D68E837671320C7 /* Pods-iMessageDemo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7E5ADF1F3B6849D5A0DF8E2B9C1861C5 /* PhysicsAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE3BED1799B2F867F5C984C2A051E36A /* PhysicsAnimation.swift */; }; + 8148CD8F2B38FB38B7B9CCC12E93ECFB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; + 89ACEF0F9E524BD21D6C2460FEC375F8 /* warningIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = ED86D7B42F55040DCE162653FB3C7EDB /* warningIconSubtle@2x.png */; }; + 966B9C1EE6B73E430F03D51A4FD26D20 /* MarginAdjustable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6C56947CAF8EFCC7858E1E2F1273427 /* MarginAdjustable.swift */; }; + 9CEE0E569456D932AA34329D2038DF98 /* SwiftMessagesSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFFDB7DDC6B6B064B9D12281E2531BFA /* SwiftMessagesSegue.swift */; }; + 9E3D4CA932041E99B6FD56D4E79A726F /* SwiftMessages-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C614EECDDFE644AF0BF7CB16A3D74404 /* SwiftMessages-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9FFE65CB6E825ECAE4838D53E7BA4C06 /* infoIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4412F313361EFEE7A0193533A5AC5999 /* infoIconLight@3x.png */; }; + A11E7A379B288CCA3AE6785B83FA4316 /* AccessibleMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDDAF8A2C45FDDDFD5AFA59203137551 /* AccessibleMessage.swift */; }; + A1734DB0A8A558B2397AF54E63F64416 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8341EF04E2B20C2BF6D4AF2240F80A56 /* Error.swift */; }; + A9EB0C8E49AB748B05CF7941ACAF8475 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; + AC4F13F50EB63B484292D67692BC1F9D /* successIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 1DC54BB09EFDFEDE11F484FE73BEDC60 /* successIconSubtle.png */; }; + B2862C6DDAA6543BB2C8F4541F044564 /* SwiftMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3216CF40D770C387D45C3B4AF2CC9E0 /* SwiftMessages.swift */; }; + B2CC8FF0F9FF3FE929180CDB32B69F18 /* infoIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F7004673F1B51EEC365B32F0E060E564 /* infoIcon@2x.png */; }; + B42A7A38C8014DBDE2632B909F71C355 /* successIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 62755A788F910CA88887B6F63BBC545F /* successIcon@2x.png */; }; + B60094A8D1343B7351F0EF9C51F2F0DB /* infoIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 337B3108412E3812254B85BCC4F90EB8 /* infoIcon@3x.png */; }; + BB16D1E73A5D6B27DC4212926986107F /* warningIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BFEF746702215C33B51BEE64C4E48F0A /* warningIcon@2x.png */; }; + BBFE3BAFFCE67F4EACE0C67A7B7FFC3A /* successIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0B3A169D83BDA3613A661845D1607FC0 /* successIconSubtle@2x.png */; }; + BC4618CE535404A9540D4D110B5767A1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 396FCF260E9C2B3F11080A91E3D72334 /* TopBottomAnimation.swift */; }; + BDCF9C5E4F88B2B0AB6D4595E5A281E1 /* successIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F898B2AC5C3404C266BBCA3B6D22B5E4 /* successIconLight@2x.png */; }; + C384FB76A48C06F7581D0F7850F2F4F1 /* Pods-iMessageDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 14BF989232A1D55A0FDAAB70B5A8E1BF /* Pods-iMessageDemo-dummy.m */; }; + C3CDAED707B153A58674CB1AC4A33FB2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; + C4598A458697C49C961BFDCD090B3A8F /* infoIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 06F2F626BE8417F1806CC5B17F210C90 /* infoIconSubtle.png */; }; + C5FFE932D5EBE2CC8F2ABFEA893D8E9C /* infoIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 70E7AB099F856140EF93D5B94A967418 /* infoIcon.png */; }; + C6E73F201545CF5ED055C69CD4DB2EFF /* warningIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C17CFEF9B761A322945F74D86CA88036 /* warningIconLight@3x.png */; }; + C8F46E0A5853739D3F632B4828FDE9CC /* PassthroughWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 382E6375390EBB09F829519F8ACCB7D7 /* PassthroughWindow.swift */; }; + CCF5CC8F6022DFD410DDCC99A90D58B0 /* warningIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 79E38069364BC5DF4EA88F352E28B242 /* warningIconLight.png */; }; + D49E06426C51C49E9058371138972A69 /* CALayer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B5EF40CEC1F6DB23F428DC159D4BC2 /* CALayer+Extensions.swift */; }; + D61D59BCDFD2C3C7993CFE883DE60692 /* infoIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6516EE9BFCB9C53C151359F9D0247562 /* infoIconLight@2x.png */; }; + D8BDC20F1566606BF64001B6E96B14B6 /* errorIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 453BC098B6A052020C40DE576F684C7B /* errorIconSubtle@3x.png */; }; + D9077478C2FCD7C3DD1EBE9373281728 /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15C4C88778A19C193D1EC77FA77BAE4C /* UIViewController+Extensions.swift */; }; + E88597F65A00A5AF50EEF2ABA2392B2F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */; }; + E94E8711BDDA31B178AA032D3346C307 /* BackgroundViewable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAB58A9F688DD39112E6CDF20C8969C0 /* BackgroundViewable.swift */; }; + EDA146BF3FF59593677F8B2AA785D8A5 /* errorIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3C313FB1D33EF4B477FD5D3D6179A8BE /* errorIconSubtle@2x.png */; }; + F27E3EEAFDDAA6CB4E7407D6A46DAA5D /* CenteredView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3DF091E68C4659506DB08B0876BD274C /* CenteredView.xib */; }; + F50FE2EE47422AD39AC8F7F115081E7E /* SwiftMessages.Config+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3C32E945AE3E6394EF85CD6BEC714B4 /* SwiftMessages.Config+Extensions.swift */; }; + F5642C087197B9033252FF10FBA92B59 /* WindowViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8566413BFA3FE6827E63E30515C9B3 /* WindowViewController.swift */; }; + FA6CA270F521DF68A75E527954A2DDAD /* SwiftMessages-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A2F9031B7FA82A17F04D4403091DF836 /* SwiftMessages-dummy.m */; }; + FCB6832EB4D32EF085E770E8B4A9BC2C /* Identifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C0DE01AB7D0935933E7AFBDF2945814 /* Identifiable.swift */; }; + FF01BC94FADD5A72282AEE043DF523A7 /* Presenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A965DD26246DCA8CE39FBAB348ABA24 /* Presenter.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 141E78A8858DBF8B2695DFEDCBDF5158 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1FC5E8328653C350899229BDF89FACE5; + remoteInfo = "SwiftMessages-SwiftMessages_SwiftMessages"; + }; + 4DB1DDB02425E67ED85C70C3B138E205 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAB613A18652334F6BFC5F27BADF515D; + remoteInfo = SwiftMessages; + }; + 900F05D1477FFAB64FF410CBB6B9B74D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAB613A18652334F6BFC5F27BADF515D; + remoteInfo = SwiftMessages; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0259757860B26C6072E2640B84EC6D45 /* warningIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIcon.png; path = SwiftMessages/Resources/warningIcon.png; sourceTree = "<group>"; }; + 06F2F626BE8417F1806CC5B17F210C90 /* infoIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconSubtle.png; path = SwiftMessages/Resources/infoIconSubtle.png; sourceTree = "<group>"; }; + 0892E032AE12339D1AD84BDCC78A3C07 /* errorIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconLight.png; path = SwiftMessages/Resources/errorIconLight.png; sourceTree = "<group>"; }; + 093D5BBE2A96A1A7AC0432A3AB933576 /* Pods-iMessageDemo-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageDemo-Info.plist"; sourceTree = "<group>"; }; + 0970322A5DD8B4A8373C35ED051DE156 /* NSLayoutConstraint+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSLayoutConstraint+Extensions.swift"; path = "SwiftMessages/NSLayoutConstraint+Extensions.swift"; sourceTree = "<group>"; }; + 0A8566413BFA3FE6827E63E30515C9B3 /* WindowViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WindowViewController.swift; path = SwiftMessages/WindowViewController.swift; sourceTree = "<group>"; }; + 0B3A169D83BDA3613A661845D1607FC0 /* successIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@2x.png"; path = "SwiftMessages/Resources/successIconSubtle@2x.png"; sourceTree = "<group>"; }; + 1341BB7116EC50FDF7062C6A91DEDF49 /* Pods-iMessageExtensionDemo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageExtensionDemo-acknowledgements.plist"; sourceTree = "<group>"; }; + 14BF989232A1D55A0FDAAB70B5A8E1BF /* Pods-iMessageDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-iMessageDemo-dummy.m"; sourceTree = "<group>"; }; + 15C4C88778A19C193D1EC77FA77BAE4C /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Extensions.swift"; path = "SwiftMessages/UIViewController+Extensions.swift"; sourceTree = "<group>"; }; + 19B5EF40CEC1F6DB23F428DC159D4BC2 /* CALayer+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CALayer+Extensions.swift"; path = "SwiftMessages/CALayer+Extensions.swift"; sourceTree = "<group>"; }; + 1B04615682E8B787C964824435BC6616 /* errorIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@2x.png"; path = "SwiftMessages/Resources/errorIconLight@2x.png"; sourceTree = "<group>"; }; + 1DC54BB09EFDFEDE11F484FE73BEDC60 /* successIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconSubtle.png; path = SwiftMessages/Resources/successIconSubtle.png; sourceTree = "<group>"; }; + 2337E6D5F621F3CE9A1E3761984EBE87 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsPanHandler.swift; path = SwiftMessages/PhysicsPanHandler.swift; sourceTree = "<group>"; }; + 267E35F9851AAE50DFB8FA0DCA7F2980 /* Animator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Animator.swift; path = SwiftMessages/Animator.swift; sourceTree = "<group>"; }; + 2B6B36CBE6DC07B2F005E30EA2B121CB /* LICENSE.md */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE.md; sourceTree = "<group>"; }; + 2B7213B7DC5432DA2B272F25E17AA364 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "SwiftMessages/Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; + 2CFBBC25592C97C925B6F81B53BE57CB /* warningIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@3x.png"; path = "SwiftMessages/Resources/warningIcon@3x.png"; sourceTree = "<group>"; }; + 2D0ECE831FB5E0EE1D68E837671320C7 /* Pods-iMessageDemo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-iMessageDemo-umbrella.h"; sourceTree = "<group>"; }; + 2E6941E59EF0D89949E3DF3D89488430 /* Weak.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Weak.swift; path = SwiftMessages/Weak.swift; sourceTree = "<group>"; }; + 337B3108412E3812254B85BCC4F90EB8 /* infoIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@3x.png"; path = "SwiftMessages/Resources/infoIcon@3x.png"; sourceTree = "<group>"; }; + 346718C2C7A108C86535F89FEB0EC176 /* SwiftMessages.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SwiftMessages.modulemap; sourceTree = "<group>"; }; + 382E6375390EBB09F829519F8ACCB7D7 /* PassthroughWindow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughWindow.swift; path = SwiftMessages/PassthroughWindow.swift; sourceTree = "<group>"; }; + 396FCF260E9C2B3F11080A91E3D72334 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TopBottomAnimation.swift; path = SwiftMessages/TopBottomAnimation.swift; sourceTree = "<group>"; }; + 397C8F928170138667B9326F9655D75D /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIWindow+Extensions.swift"; path = "SwiftMessages/UIWindow+Extensions.swift"; sourceTree = "<group>"; }; + 3C313FB1D33EF4B477FD5D3D6179A8BE /* errorIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@2x.png"; path = "SwiftMessages/Resources/errorIconSubtle@2x.png"; sourceTree = "<group>"; }; + 3DF091E68C4659506DB08B0876BD274C /* CenteredView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CenteredView.xib; path = SwiftMessages/Resources/CenteredView.xib; sourceTree = "<group>"; }; + 42F1E753E61B6EDED3908AC66994649C /* CardView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CardView.xib; path = SwiftMessages/Resources/CardView.xib; sourceTree = "<group>"; }; + 4412F313361EFEE7A0193533A5AC5999 /* infoIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@3x.png"; path = "SwiftMessages/Resources/infoIconLight@3x.png"; sourceTree = "<group>"; }; + 4512DEEA328AB0AAA95D77C84C89E02C /* warningIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconSubtle.png; path = SwiftMessages/Resources/warningIconSubtle.png; sourceTree = "<group>"; }; + 453BC098B6A052020C40DE576F684C7B /* errorIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@3x.png"; path = "SwiftMessages/Resources/errorIconSubtle@3x.png"; sourceTree = "<group>"; }; + 4824F23D80FF9070A5F8A452DB11EB9A /* SwiftMessages.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SwiftMessages.framework; path = SwiftMessages.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4F8D7902822221456B697BB41111E450 /* CornerRoundingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CornerRoundingView.swift; path = SwiftMessages/CornerRoundingView.swift; sourceTree = "<group>"; }; + 4FE466AC4123CDAE9FDA9FCF4FB9CC60 /* infoIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@2x.png"; path = "SwiftMessages/Resources/infoIconSubtle@2x.png"; sourceTree = "<group>"; }; + 536660614870EA0E051BF6BDDF495798 /* KeyboardTrackingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KeyboardTrackingView.swift; path = SwiftMessages/KeyboardTrackingView.swift; sourceTree = "<group>"; }; + 54B278C80D821C120FA70ABB6CAF1F46 /* successIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@3x.png"; path = "SwiftMessages/Resources/successIconSubtle@3x.png"; sourceTree = "<group>"; }; + 5C0DE01AB7D0935933E7AFBDF2945814 /* Identifiable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Identifiable.swift; path = SwiftMessages/Identifiable.swift; sourceTree = "<group>"; }; + 5CAB201AD00CAB811B045E2FFB5C03A8 /* Pods-iMessageExtensionDemo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-iMessageExtensionDemo-umbrella.h"; sourceTree = "<group>"; }; + 60268FE48AA4DC9FD5060B1E5CE68453 /* errorIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@2x.png"; path = "SwiftMessages/Resources/errorIcon@2x.png"; sourceTree = "<group>"; }; + 62755A788F910CA88887B6F63BBC545F /* successIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@2x.png"; path = "SwiftMessages/Resources/successIcon@2x.png"; sourceTree = "<group>"; }; + 6489B2A759075E9DC1D1406734F45B5F /* Pods-iMessageExtensionDemo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iMessageExtensionDemo.modulemap"; sourceTree = "<group>"; }; + 6516EE9BFCB9C53C151359F9D0247562 /* infoIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@2x.png"; path = "SwiftMessages/Resources/infoIconLight@2x.png"; sourceTree = "<group>"; }; + 667DECE93ABCC6869A071FFEB0F83EA5 /* warningIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@3x.png"; path = "SwiftMessages/Resources/warningIconSubtle@3x.png"; sourceTree = "<group>"; }; + 6E9D4A0FDDEEDDC5A1A63D89B43C1F18 /* SwiftMessages.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.debug.xcconfig; sourceTree = "<group>"; }; + 70E7AB099F856140EF93D5B94A967418 /* infoIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIcon.png; path = SwiftMessages/Resources/infoIcon.png; sourceTree = "<group>"; }; + 7241B2130D211F0832CCE4928CBB6486 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = "<group>"; }; + 72A865FFBAE49EF66A35CB9D709E8D7E /* successIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@3x.png"; path = "SwiftMessages/Resources/successIconLight@3x.png"; sourceTree = "<group>"; }; + 79E38069364BC5DF4EA88F352E28B242 /* warningIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconLight.png; path = SwiftMessages/Resources/warningIconLight.png; sourceTree = "<group>"; }; + 7A6801849037A728E9BC50E06CE8AD2F /* StatusLine.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = StatusLine.xib; path = SwiftMessages/Resources/StatusLine.xib; sourceTree = "<group>"; }; + 7A965DD26246DCA8CE39FBAB348ABA24 /* Presenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Presenter.swift; path = SwiftMessages/Presenter.swift; sourceTree = "<group>"; }; + 7CC6A596A9C1659D8E93222DA4144414 /* Pods-iMessageExtensionDemo-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageExtensionDemo-Info.plist"; sourceTree = "<group>"; }; + 7F40CA14AD738DD186B4DA8FD14AE5BD /* Pods-iMessageExtensionDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-iMessageExtensionDemo-dummy.m"; sourceTree = "<group>"; }; + 7FCF161BD9F1C2CAAFBCADE5E59BD3FD /* NSBundle+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSBundle+Extensions.swift"; path = "SwiftMessages/NSBundle+Extensions.swift"; sourceTree = "<group>"; }; + 820B743874F7AC9F9E3970D68E2E60FA /* Pods-iMessageDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageDemo.release.xcconfig"; sourceTree = "<group>"; }; + 8341EF04E2B20C2BF6D4AF2240F80A56 /* Error.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Error.swift; path = SwiftMessages/Error.swift; sourceTree = "<group>"; }; + 848251807107C20960A3DABAB27F7475 /* errorIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@3x.png"; path = "SwiftMessages/Resources/errorIconLight@3x.png"; sourceTree = "<group>"; }; + 874D31DE863C88B1D699E1EBFBE0641B /* warningIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@2x.png"; path = "SwiftMessages/Resources/warningIconLight@2x.png"; sourceTree = "<group>"; }; + 8901520225CE89F44E6DE88688F29C10 /* MessageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageView.swift; path = SwiftMessages/MessageView.swift; sourceTree = "<group>"; }; + 8D54691037F1CA4653B76F0558E2AA82 /* Pods-iMessageExtensionDemo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-iMessageExtensionDemo-acknowledgements.markdown"; sourceTree = "<group>"; }; + 90F364E0C9A6EFE24680868D0BD293F1 /* SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SwiftMessages-Info.plist"; sourceTree = "<group>"; }; + 915DE2E4E300BAD440BE13F72E49D731 /* Pods-iMessageDemo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageDemo-acknowledgements.plist"; sourceTree = "<group>"; }; + 9C110C924ED12D2D32ECC27503018A31 /* infoIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconLight.png; path = SwiftMessages/Resources/infoIconLight.png; sourceTree = "<group>"; }; + 9CF61FDEFE095F0486E9914F2262ADB9 /* MaskingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MaskingView.swift; path = SwiftMessages/MaskingView.swift; sourceTree = "<group>"; }; + 9D1FEAC04417D847EDC10783E054988F /* errorIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIcon.png; path = SwiftMessages/Resources/errorIcon.png; sourceTree = "<group>"; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + A0D0E8B0020635F606875DD02735C502 /* BaseView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BaseView.swift; path = SwiftMessages/BaseView.swift; sourceTree = "<group>"; }; + A2F9031B7FA82A17F04D4403091DF836 /* SwiftMessages-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SwiftMessages-dummy.m"; sourceTree = "<group>"; }; + A3C32E945AE3E6394EF85CD6BEC714B4 /* SwiftMessages.Config+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "SwiftMessages.Config+Extensions.swift"; path = "SwiftMessages/SwiftMessages.Config+Extensions.swift"; sourceTree = "<group>"; }; + A80433B71162112A79043CB64261DB51 /* successIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconLight.png; path = SwiftMessages/Resources/successIconLight.png; sourceTree = "<group>"; }; + A850F76D7E3FEDC20FFB877454069171 /* errorIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconSubtle.png; path = SwiftMessages/Resources/errorIconSubtle.png; sourceTree = "<group>"; }; + A9A13E69643D651322647C28E3F9E9C9 /* UIEdgeInsets+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIEdgeInsets+Extensions.swift"; path = "SwiftMessages/UIEdgeInsets+Extensions.swift"; sourceTree = "<group>"; }; + AE62AA801971C530345349D18AFCCB82 /* MessageView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = MessageView.xib; path = SwiftMessages/Resources/MessageView.xib; sourceTree = "<group>"; }; + AE7AEA9CE6B44DCC96AE4E68FA644DAA /* Pods-iMessageExtensionDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageExtensionDemo.release.xcconfig"; sourceTree = "<group>"; }; + AFC41396FB1BD59C9A69EE1DD82E47C2 /* Pods_iMessageDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_iMessageDemo.framework; path = "Pods-iMessageDemo.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + AFFDB7DDC6B6B064B9D12281E2531BFA /* SwiftMessagesSegue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessagesSegue.swift; path = SwiftMessages/SwiftMessagesSegue.swift; sourceTree = "<group>"; }; + B6DEAADC09FEB1A8D5B90108103EE478 /* errorIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@3x.png"; path = "SwiftMessages/Resources/errorIcon@3x.png"; sourceTree = "<group>"; }; + B7FD0618783A3E6B90D3A3323633959F /* TabView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = TabView.xib; path = SwiftMessages/Resources/TabView.xib; sourceTree = "<group>"; }; + B91AD9D9E743D17D553D48103BE27C46 /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "MarginAdjustable+Extensions.swift"; path = "SwiftMessages/MarginAdjustable+Extensions.swift"; sourceTree = "<group>"; }; + B99CBDE49D6502CF64EB9059C005BF31 /* Pods-iMessageDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageDemo.debug.xcconfig"; sourceTree = "<group>"; }; + BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages_SwiftMessages.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = SwiftMessages_SwiftMessages.bundle; path = "SwiftMessages-SwiftMessages_SwiftMessages.bundle"; sourceTree = BUILT_PRODUCTS_DIR; }; + BF61E78F8E8EE539F4A63C5A9D43AC15 /* Pods-iMessageDemo-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-iMessageDemo-frameworks.sh"; sourceTree = "<group>"; }; + BFEF746702215C33B51BEE64C4E48F0A /* warningIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@2x.png"; path = "SwiftMessages/Resources/warningIcon@2x.png"; sourceTree = "<group>"; }; + C17CFEF9B761A322945F74D86CA88036 /* warningIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@3x.png"; path = "SwiftMessages/Resources/warningIconLight@3x.png"; sourceTree = "<group>"; }; + C306ACAFEE157959D78E71DBBBD675DC /* Pods-iMessageExtensionDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageExtensionDemo.debug.xcconfig"; sourceTree = "<group>"; }; + C3216CF40D770C387D45C3B4AF2CC9E0 /* SwiftMessages.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessages.swift; path = SwiftMessages/SwiftMessages.swift; sourceTree = "<group>"; }; + C614EECDDFE644AF0BF7CB16A3D74404 /* SwiftMessages-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-umbrella.h"; sourceTree = "<group>"; }; + C6C56947CAF8EFCC7858E1E2F1273427 /* MarginAdjustable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MarginAdjustable.swift; path = SwiftMessages/MarginAdjustable.swift; sourceTree = "<group>"; }; + C7FE39695CB7C6997ACA39C8680B414A /* SwiftMessages.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = SwiftMessages.podspec; sourceTree = "<group>"; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + C8155ED78358FA5CF39089176FBDE501 /* successIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@3x.png"; path = "SwiftMessages/Resources/successIcon@3x.png"; sourceTree = "<group>"; }; + C9D915B60769D3C45A0DA3A5BA9514B8 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; sourceTree = "<group>"; }; + CAB58A9F688DD39112E6CDF20C8969C0 /* BackgroundViewable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BackgroundViewable.swift; path = SwiftMessages/BackgroundViewable.swift; sourceTree = "<group>"; }; + CBC3F501D8BC852716D085B3022E68CA /* Pods_iMessageExtensionDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_iMessageExtensionDemo.framework; path = "Pods-iMessageExtensionDemo.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + CC9152C843976F18EF9AE005786DCC80 /* Pods-iMessageDemo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iMessageDemo.modulemap"; sourceTree = "<group>"; }; + D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + D5607E285A85AC7163B0B8FD447FD27E /* Theme.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Theme.swift; path = SwiftMessages/Theme.swift; sourceTree = "<group>"; }; + D7C557E1DC95AFA417E94ED01301F9F2 /* PassthroughView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughView.swift; path = SwiftMessages/PassthroughView.swift; sourceTree = "<group>"; }; + E070773539E02C11297794CC4CB839D6 /* SwiftMessages.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.release.xcconfig; sourceTree = "<group>"; }; + E473E4F019E816262A61B7F5E8B42373 /* Pods-iMessageDemo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-iMessageDemo-acknowledgements.markdown"; sourceTree = "<group>"; }; + EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + ED86D7B42F55040DCE162653FB3C7EDB /* warningIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@2x.png"; path = "SwiftMessages/Resources/warningIconSubtle@2x.png"; sourceTree = "<group>"; }; + EDDAF8A2C45FDDDFD5AFA59203137551 /* AccessibleMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibleMessage.swift; path = SwiftMessages/AccessibleMessage.swift; sourceTree = "<group>"; }; + F7004673F1B51EEC365B32F0E060E564 /* infoIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@2x.png"; path = "SwiftMessages/Resources/infoIcon@2x.png"; sourceTree = "<group>"; }; + F898B2AC5C3404C266BBCA3B6D22B5E4 /* successIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@2x.png"; path = "SwiftMessages/Resources/successIconLight@2x.png"; sourceTree = "<group>"; }; + FC73E6C784AF6CA1F956F57F82ED2803 /* successIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIcon.png; path = SwiftMessages/Resources/successIcon.png; sourceTree = "<group>"; }; + FCDC8870EA94B5B1E966D34D2B1FA5FE /* SwiftMessages-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-prefix.pch"; sourceTree = "<group>"; }; + FE3BED1799B2F867F5C984C2A051E36A /* PhysicsAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsAnimation.swift; path = SwiftMessages/PhysicsAnimation.swift; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 495E35DFE0854ABB7E2A238D1CFC4550 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C3CDAED707B153A58674CB1AC4A33FB2 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C3AABE927CAF3C6135B4D37CA433F885 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F2C6C6F4FCF31DEB85ADCA0DE9EF6EEC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A9EB0C8E49AB748B05CF7941ACAF8475 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA7AA2A57B110DEF3C1F616FA77A05A7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8148CD8F2B38FB38B7B9CCC12E93ECFB /* Foundation.framework in Frameworks */, + E88597F65A00A5AF50EEF2ABA2392B2F /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 59DA5C1F72E1D5BABC43EACBA672C3BA /* iOS */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + 423F06E259421657656F08FC805160BA /* Products */ = { + isa = PBXGroup; + children = ( + AFC41396FB1BD59C9A69EE1DD82E47C2 /* Pods_iMessageDemo.framework */, + CBC3F501D8BC852716D085B3022E68CA /* Pods_iMessageExtensionDemo.framework */, + 4824F23D80FF9070A5F8A452DB11EB9A /* SwiftMessages.framework */, + BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages_SwiftMessages.bundle */, + ); + name = Products; + sourceTree = "<group>"; + }; + 59DA5C1F72E1D5BABC43EACBA672C3BA /* iOS */ = { + isa = PBXGroup; + children = ( + EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */, + D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */, + ); + name = iOS; + sourceTree = "<group>"; + }; + 8F3CF4AFB0CA47B3BFE1C68E51CDF0A9 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 9A912CA1E54EADE1787311C1DF7E8F2E /* Pods-iMessageDemo */, + BD13800F87C70DC802DBC0C37E8C5E99 /* Pods-iMessageExtensionDemo */, + ); + name = "Targets Support Files"; + sourceTree = "<group>"; + }; + 9A632FB0C8554E0688B34926AF9C52DB /* SwiftMessages */ = { + isa = PBXGroup; + children = ( + AD776BCEA093D43499821A6E4251BF03 /* AppExtension */, + A58DF9B1678B5C3CCA8A840C72186044 /* Pod */, + B3699CF01F28F4B75166BA983453EAF3 /* Support Files */, + ); + name = SwiftMessages; + path = ../..; + sourceTree = "<group>"; + }; + 9A912CA1E54EADE1787311C1DF7E8F2E /* Pods-iMessageDemo */ = { + isa = PBXGroup; + children = ( + CC9152C843976F18EF9AE005786DCC80 /* Pods-iMessageDemo.modulemap */, + E473E4F019E816262A61B7F5E8B42373 /* Pods-iMessageDemo-acknowledgements.markdown */, + 915DE2E4E300BAD440BE13F72E49D731 /* Pods-iMessageDemo-acknowledgements.plist */, + 14BF989232A1D55A0FDAAB70B5A8E1BF /* Pods-iMessageDemo-dummy.m */, + BF61E78F8E8EE539F4A63C5A9D43AC15 /* Pods-iMessageDemo-frameworks.sh */, + 093D5BBE2A96A1A7AC0432A3AB933576 /* Pods-iMessageDemo-Info.plist */, + 2D0ECE831FB5E0EE1D68E837671320C7 /* Pods-iMessageDemo-umbrella.h */, + B99CBDE49D6502CF64EB9059C005BF31 /* Pods-iMessageDemo.debug.xcconfig */, + 820B743874F7AC9F9E3970D68E2E60FA /* Pods-iMessageDemo.release.xcconfig */, + ); + name = "Pods-iMessageDemo"; + path = "Target Support Files/Pods-iMessageDemo"; + sourceTree = "<group>"; + }; + A58DF9B1678B5C3CCA8A840C72186044 /* Pod */ = { + isa = PBXGroup; + children = ( + 2B6B36CBE6DC07B2F005E30EA2B121CB /* LICENSE.md */, + 7241B2130D211F0832CCE4928CBB6486 /* README.md */, + C7FE39695CB7C6997ACA39C8680B414A /* SwiftMessages.podspec */, + ); + name = Pod; + sourceTree = "<group>"; + }; + AD776BCEA093D43499821A6E4251BF03 /* AppExtension */ = { + isa = PBXGroup; + children = ( + EDDAF8A2C45FDDDFD5AFA59203137551 /* AccessibleMessage.swift */, + 267E35F9851AAE50DFB8FA0DCA7F2980 /* Animator.swift */, + CAB58A9F688DD39112E6CDF20C8969C0 /* BackgroundViewable.swift */, + A0D0E8B0020635F606875DD02735C502 /* BaseView.swift */, + 19B5EF40CEC1F6DB23F428DC159D4BC2 /* CALayer+Extensions.swift */, + 42F1E753E61B6EDED3908AC66994649C /* CardView.xib */, + 3DF091E68C4659506DB08B0876BD274C /* CenteredView.xib */, + 4F8D7902822221456B697BB41111E450 /* CornerRoundingView.swift */, + 8341EF04E2B20C2BF6D4AF2240F80A56 /* Error.swift */, + 9D1FEAC04417D847EDC10783E054988F /* errorIcon.png */, + 60268FE48AA4DC9FD5060B1E5CE68453 /* errorIcon@2x.png */, + B6DEAADC09FEB1A8D5B90108103EE478 /* errorIcon@3x.png */, + 0892E032AE12339D1AD84BDCC78A3C07 /* errorIconLight.png */, + 1B04615682E8B787C964824435BC6616 /* errorIconLight@2x.png */, + 848251807107C20960A3DABAB27F7475 /* errorIconLight@3x.png */, + A850F76D7E3FEDC20FFB877454069171 /* errorIconSubtle.png */, + 3C313FB1D33EF4B477FD5D3D6179A8BE /* errorIconSubtle@2x.png */, + 453BC098B6A052020C40DE576F684C7B /* errorIconSubtle@3x.png */, + 5C0DE01AB7D0935933E7AFBDF2945814 /* Identifiable.swift */, + 70E7AB099F856140EF93D5B94A967418 /* infoIcon.png */, + F7004673F1B51EEC365B32F0E060E564 /* infoIcon@2x.png */, + 337B3108412E3812254B85BCC4F90EB8 /* infoIcon@3x.png */, + 9C110C924ED12D2D32ECC27503018A31 /* infoIconLight.png */, + 6516EE9BFCB9C53C151359F9D0247562 /* infoIconLight@2x.png */, + 4412F313361EFEE7A0193533A5AC5999 /* infoIconLight@3x.png */, + 06F2F626BE8417F1806CC5B17F210C90 /* infoIconSubtle.png */, + 4FE466AC4123CDAE9FDA9FCF4FB9CC60 /* infoIconSubtle@2x.png */, + 2B7213B7DC5432DA2B272F25E17AA364 /* infoIconSubtle@3x.png */, + 536660614870EA0E051BF6BDDF495798 /* KeyboardTrackingView.swift */, + C6C56947CAF8EFCC7858E1E2F1273427 /* MarginAdjustable.swift */, + B91AD9D9E743D17D553D48103BE27C46 /* MarginAdjustable+Extensions.swift */, + 9CF61FDEFE095F0486E9914F2262ADB9 /* MaskingView.swift */, + 8901520225CE89F44E6DE88688F29C10 /* MessageView.swift */, + AE62AA801971C530345349D18AFCCB82 /* MessageView.xib */, + 7FCF161BD9F1C2CAAFBCADE5E59BD3FD /* NSBundle+Extensions.swift */, + 0970322A5DD8B4A8373C35ED051DE156 /* NSLayoutConstraint+Extensions.swift */, + D7C557E1DC95AFA417E94ED01301F9F2 /* PassthroughView.swift */, + 382E6375390EBB09F829519F8ACCB7D7 /* PassthroughWindow.swift */, + FE3BED1799B2F867F5C984C2A051E36A /* PhysicsAnimation.swift */, + 2337E6D5F621F3CE9A1E3761984EBE87 /* PhysicsPanHandler.swift */, + 7A965DD26246DCA8CE39FBAB348ABA24 /* Presenter.swift */, + 7A6801849037A728E9BC50E06CE8AD2F /* StatusLine.xib */, + FC73E6C784AF6CA1F956F57F82ED2803 /* successIcon.png */, + 62755A788F910CA88887B6F63BBC545F /* successIcon@2x.png */, + C8155ED78358FA5CF39089176FBDE501 /* successIcon@3x.png */, + A80433B71162112A79043CB64261DB51 /* successIconLight.png */, + F898B2AC5C3404C266BBCA3B6D22B5E4 /* successIconLight@2x.png */, + 72A865FFBAE49EF66A35CB9D709E8D7E /* successIconLight@3x.png */, + 1DC54BB09EFDFEDE11F484FE73BEDC60 /* successIconSubtle.png */, + 0B3A169D83BDA3613A661845D1607FC0 /* successIconSubtle@2x.png */, + 54B278C80D821C120FA70ABB6CAF1F46 /* successIconSubtle@3x.png */, + C3216CF40D770C387D45C3B4AF2CC9E0 /* SwiftMessages.swift */, + A3C32E945AE3E6394EF85CD6BEC714B4 /* SwiftMessages.Config+Extensions.swift */, + AFFDB7DDC6B6B064B9D12281E2531BFA /* SwiftMessagesSegue.swift */, + B7FD0618783A3E6B90D3A3323633959F /* TabView.xib */, + D5607E285A85AC7163B0B8FD447FD27E /* Theme.swift */, + 396FCF260E9C2B3F11080A91E3D72334 /* TopBottomAnimation.swift */, + A9A13E69643D651322647C28E3F9E9C9 /* UIEdgeInsets+Extensions.swift */, + 15C4C88778A19C193D1EC77FA77BAE4C /* UIViewController+Extensions.swift */, + 397C8F928170138667B9326F9655D75D /* UIWindow+Extensions.swift */, + 0259757860B26C6072E2640B84EC6D45 /* warningIcon.png */, + BFEF746702215C33B51BEE64C4E48F0A /* warningIcon@2x.png */, + 2CFBBC25592C97C925B6F81B53BE57CB /* warningIcon@3x.png */, + 79E38069364BC5DF4EA88F352E28B242 /* warningIconLight.png */, + 874D31DE863C88B1D699E1EBFBE0641B /* warningIconLight@2x.png */, + C17CFEF9B761A322945F74D86CA88036 /* warningIconLight@3x.png */, + 4512DEEA328AB0AAA95D77C84C89E02C /* warningIconSubtle.png */, + ED86D7B42F55040DCE162653FB3C7EDB /* warningIconSubtle@2x.png */, + 667DECE93ABCC6869A071FFEB0F83EA5 /* warningIconSubtle@3x.png */, + 2E6941E59EF0D89949E3DF3D89488430 /* Weak.swift */, + 0A8566413BFA3FE6827E63E30515C9B3 /* WindowViewController.swift */, + ); + name = AppExtension; + sourceTree = "<group>"; + }; + B3699CF01F28F4B75166BA983453EAF3 /* Support Files */ = { + isa = PBXGroup; + children = ( + C9D915B60769D3C45A0DA3A5BA9514B8 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */, + 346718C2C7A108C86535F89FEB0EC176 /* SwiftMessages.modulemap */, + A2F9031B7FA82A17F04D4403091DF836 /* SwiftMessages-dummy.m */, + 90F364E0C9A6EFE24680868D0BD293F1 /* SwiftMessages-Info.plist */, + FCDC8870EA94B5B1E966D34D2B1FA5FE /* SwiftMessages-prefix.pch */, + C614EECDDFE644AF0BF7CB16A3D74404 /* SwiftMessages-umbrella.h */, + 6E9D4A0FDDEEDDC5A1A63D89B43C1F18 /* SwiftMessages.debug.xcconfig */, + E070773539E02C11297794CC4CB839D6 /* SwiftMessages.release.xcconfig */, + ); + name = "Support Files"; + path = "iMessageDemo/Pods/Target Support Files/SwiftMessages"; + sourceTree = "<group>"; + }; + BD13800F87C70DC802DBC0C37E8C5E99 /* Pods-iMessageExtensionDemo */ = { + isa = PBXGroup; + children = ( + 6489B2A759075E9DC1D1406734F45B5F /* Pods-iMessageExtensionDemo.modulemap */, + 8D54691037F1CA4653B76F0558E2AA82 /* Pods-iMessageExtensionDemo-acknowledgements.markdown */, + 1341BB7116EC50FDF7062C6A91DEDF49 /* Pods-iMessageExtensionDemo-acknowledgements.plist */, + 7F40CA14AD738DD186B4DA8FD14AE5BD /* Pods-iMessageExtensionDemo-dummy.m */, + 7CC6A596A9C1659D8E93222DA4144414 /* Pods-iMessageExtensionDemo-Info.plist */, + 5CAB201AD00CAB811B045E2FFB5C03A8 /* Pods-iMessageExtensionDemo-umbrella.h */, + C306ACAFEE157959D78E71DBBBD675DC /* Pods-iMessageExtensionDemo.debug.xcconfig */, + AE7AEA9CE6B44DCC96AE4E68FA644DAA /* Pods-iMessageExtensionDemo.release.xcconfig */, + ); + name = "Pods-iMessageExtensionDemo"; + path = "Target Support Files/Pods-iMessageExtensionDemo"; + sourceTree = "<group>"; + }; + C5AAA95D48373FAC474F6EFCC1749444 /* Development Pods */ = { + isa = PBXGroup; + children = ( + 9A632FB0C8554E0688B34926AF9C52DB /* SwiftMessages */, + ); + name = "Development Pods"; + sourceTree = "<group>"; + }; + CF1408CF629C7361332E53B88F7BD30C = { + isa = PBXGroup; + children = ( + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + C5AAA95D48373FAC474F6EFCC1749444 /* Development Pods */, + 1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */, + 423F06E259421657656F08FC805160BA /* Products */, + 8F3CF4AFB0CA47B3BFE1C68E51CDF0A9 /* Targets Support Files */, + ); + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 96A1C098516CB9F20C4BE19860673FA7 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 560A2B1056FEFE42AC6524A2A1742CA2 /* Pods-iMessageExtensionDemo-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AEC231A576EA094C9EF913D75BA2D69C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 7BC52E6F0D9D19B05E62E623E53FCE82 /* Pods-iMessageDemo-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B534C45C1A426DF58D21D75F281F983A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 9E3D4CA932041E99B6FD56D4E79A726F /* SwiftMessages-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1FC5E8328653C350899229BDF89FACE5 /* SwiftMessages-SwiftMessages_SwiftMessages */ = { + isa = PBXNativeTarget; + buildConfigurationList = 57E1F5473FEF9FC2401E805CCF8188C3 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages_SwiftMessages" */; + buildPhases = ( + 5FA15A9B2968910DC30C1AC895A5397A /* Sources */, + C3AABE927CAF3C6135B4D37CA433F885 /* Frameworks */, + F8808FE568E0B01931D6216DF79110B1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "SwiftMessages-SwiftMessages_SwiftMessages"; + productName = "SwiftMessages-SwiftMessages_SwiftMessages"; + productReference = BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages_SwiftMessages.bundle */; + productType = "com.apple.product-type.bundle"; + }; + 2757367020CF4EA7726D56118C89F6AE /* Pods-iMessageExtensionDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = ED0C46CBFB7B22526D6F384198E16114 /* Build configuration list for PBXNativeTarget "Pods-iMessageExtensionDemo" */; + buildPhases = ( + 96A1C098516CB9F20C4BE19860673FA7 /* Headers */, + 26079E47AEA7D168B2259F29AF1AE73B /* Sources */, + 495E35DFE0854ABB7E2A238D1CFC4550 /* Frameworks */, + B1A8F08DE3F2C1EF1D63EF29C9D3D327 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + BB9BD3F204FD8449B62AD70E23DABC13 /* PBXTargetDependency */, + ); + name = "Pods-iMessageExtensionDemo"; + productName = "Pods-iMessageExtensionDemo"; + productReference = CBC3F501D8BC852716D085B3022E68CA /* Pods_iMessageExtensionDemo.framework */; + productType = "com.apple.product-type.framework"; + }; + DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */ = { + isa = PBXNativeTarget; + buildConfigurationList = ABCC3636B5EAEBE6D60D155704F40EBC /* Build configuration list for PBXNativeTarget "SwiftMessages" */; + buildPhases = ( + B534C45C1A426DF58D21D75F281F983A /* Headers */, + ABE787B29A89D2BB29F92EAE5C8526CF /* Sources */, + FA7AA2A57B110DEF3C1F616FA77A05A7 /* Frameworks */, + C69D4A2DC76A80BD6D45A9BE85B2EEB1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 03EC5F5CF0CAA96E132B778FB51EBCE9 /* PBXTargetDependency */, + ); + name = SwiftMessages; + productName = SwiftMessages; + productReference = 4824F23D80FF9070A5F8A452DB11EB9A /* SwiftMessages.framework */; + productType = "com.apple.product-type.framework"; + }; + E2AECC8B9DD9E437C7DD0FD0FFC881F3 /* Pods-iMessageDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 20A82A14E31D7EFF5BE9B60529162F4B /* Build configuration list for PBXNativeTarget "Pods-iMessageDemo" */; + buildPhases = ( + AEC231A576EA094C9EF913D75BA2D69C /* Headers */, + 41C8F9B8F0E317E193B01E8DC96E6F02 /* Sources */, + F2C6C6F4FCF31DEB85ADCA0DE9EF6EEC /* Frameworks */, + 61DB2F41473C1B8FEA6385AA240E2586 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 3CF465B66D2B58FC406E66E621CBCB11 /* PBXTargetDependency */, + ); + name = "Pods-iMessageDemo"; + productName = "Pods-iMessageDemo"; + productReference = AFC41396FB1BD59C9A69EE1DD82E47C2 /* Pods_iMessageDemo.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BFDFE7DC352907FC980B868725387E98 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1100; + }; + buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = CF1408CF629C7361332E53B88F7BD30C; + productRefGroup = 423F06E259421657656F08FC805160BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + E2AECC8B9DD9E437C7DD0FD0FFC881F3 /* Pods-iMessageDemo */, + 2757367020CF4EA7726D56118C89F6AE /* Pods-iMessageExtensionDemo */, + DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */, + 1FC5E8328653C350899229BDF89FACE5 /* SwiftMessages-SwiftMessages_SwiftMessages */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 61DB2F41473C1B8FEA6385AA240E2586 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B1A8F08DE3F2C1EF1D63EF29C9D3D327 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C69D4A2DC76A80BD6D45A9BE85B2EEB1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 425F2D4CE95436680D77C263FF15221B /* SwiftMessages_SwiftMessages.bundle in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F8808FE568E0B01931D6216DF79110B1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4E9CCFC43646B6CDBE3B787AB09A0147 /* CardView.xib in Resources */, + F27E3EEAFDDAA6CB4E7407D6A46DAA5D /* CenteredView.xib in Resources */, + 5260BD3289BAC54A20457099C4A57EFF /* errorIcon.png in Resources */, + 683A7897D1E9A73F4717198B1C054D29 /* errorIcon@2x.png in Resources */, + 6A539682FDDA0E5DA23E1B5F2BA133C1 /* errorIcon@3x.png in Resources */, + 4E703B2A80C64CF1142872BE31263940 /* errorIconLight.png in Resources */, + 1F4159921A25C7B2A0E9C587387D829C /* errorIconLight@2x.png in Resources */, + 4C78ED4E1780F5609E25CE03429C1DE4 /* errorIconLight@3x.png in Resources */, + 365594AAFDD4EE947EB33E6E86A8578E /* errorIconSubtle.png in Resources */, + EDA146BF3FF59593677F8B2AA785D8A5 /* errorIconSubtle@2x.png in Resources */, + D8BDC20F1566606BF64001B6E96B14B6 /* errorIconSubtle@3x.png in Resources */, + C5FFE932D5EBE2CC8F2ABFEA893D8E9C /* infoIcon.png in Resources */, + B2CC8FF0F9FF3FE929180CDB32B69F18 /* infoIcon@2x.png in Resources */, + B60094A8D1343B7351F0EF9C51F2F0DB /* infoIcon@3x.png in Resources */, + 5720D965B3CE67653082137053FBEC9C /* infoIconLight.png in Resources */, + D61D59BCDFD2C3C7993CFE883DE60692 /* infoIconLight@2x.png in Resources */, + 9FFE65CB6E825ECAE4838D53E7BA4C06 /* infoIconLight@3x.png in Resources */, + C4598A458697C49C961BFDCD090B3A8F /* infoIconSubtle.png in Resources */, + 2B23A9DFDAACFE9C0AD5EB6899E63475 /* infoIconSubtle@2x.png in Resources */, + 7ACCA07CCFD868899D61F4B4AE5774DB /* infoIconSubtle@3x.png in Resources */, + 2558CABB502ED605BC21DCFC55A9C0B7 /* MessageView.xib in Resources */, + 492F085489FCAB0EEBE74B098F7D3F4D /* StatusLine.xib in Resources */, + 462CDC24C5C8DD6905C4112B6B4BD2ED /* successIcon.png in Resources */, + B42A7A38C8014DBDE2632B909F71C355 /* successIcon@2x.png in Resources */, + 44C0F194D748EE88027414A5B2094E9B /* successIcon@3x.png in Resources */, + 138A7742F76993FB9EE3555FD2808562 /* successIconLight.png in Resources */, + BDCF9C5E4F88B2B0AB6D4595E5A281E1 /* successIconLight@2x.png in Resources */, + 33785D52B8888C2EA02BD0495408E352 /* successIconLight@3x.png in Resources */, + AC4F13F50EB63B484292D67692BC1F9D /* successIconSubtle.png in Resources */, + BBFE3BAFFCE67F4EACE0C67A7B7FFC3A /* successIconSubtle@2x.png in Resources */, + 5DF3F4808ED4A6932839C11A5D742B93 /* successIconSubtle@3x.png in Resources */, + 57072960EA4F0D307171ED90697D3FAF /* TabView.xib in Resources */, + 447E8A096C1ABD2E0AC9674E65A827E3 /* warningIcon.png in Resources */, + BB16D1E73A5D6B27DC4212926986107F /* warningIcon@2x.png in Resources */, + 64595C731B826EB19E9757D524E0BF76 /* warningIcon@3x.png in Resources */, + CCF5CC8F6022DFD410DDCC99A90D58B0 /* warningIconLight.png in Resources */, + 4DB5D1FB08693DDDC32BCF19CC1B1AA0 /* warningIconLight@2x.png in Resources */, + C6E73F201545CF5ED055C69CD4DB2EFF /* warningIconLight@3x.png in Resources */, + 1F6162906845BE72A5BCDAF14D6E14B9 /* warningIconSubtle.png in Resources */, + 89ACEF0F9E524BD21D6C2460FEC375F8 /* warningIconSubtle@2x.png in Resources */, + 755DA479621A9D2BB8B84540DE648A7A /* warningIconSubtle@3x.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 26079E47AEA7D168B2259F29AF1AE73B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 46CCA4DDFDBBDD2A9426BB96C08E4255 /* Pods-iMessageExtensionDemo-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 41C8F9B8F0E317E193B01E8DC96E6F02 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C384FB76A48C06F7581D0F7850F2F4F1 /* Pods-iMessageDemo-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5FA15A9B2968910DC30C1AC895A5397A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + ABE787B29A89D2BB29F92EAE5C8526CF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A11E7A379B288CCA3AE6785B83FA4316 /* AccessibleMessage.swift in Sources */, + 44150A4B5B2D251FCBB6CA07DC9872B5 /* Animator.swift in Sources */, + E94E8711BDDA31B178AA032D3346C307 /* BackgroundViewable.swift in Sources */, + 4267FACE20717FF3F51C2ACAB8C395A4 /* BaseView.swift in Sources */, + D49E06426C51C49E9058371138972A69 /* CALayer+Extensions.swift in Sources */, + 6320AE79D41E8D1F52AF66A670542561 /* CornerRoundingView.swift in Sources */, + A1734DB0A8A558B2397AF54E63F64416 /* Error.swift in Sources */, + FCB6832EB4D32EF085E770E8B4A9BC2C /* Identifiable.swift in Sources */, + 3505AB28DBFA49FBE5C8250F3E067E60 /* KeyboardTrackingView.swift in Sources */, + 0E7AE1B3CE2734B39ACCE812B4320B44 /* MarginAdjustable+Extensions.swift in Sources */, + 966B9C1EE6B73E430F03D51A4FD26D20 /* MarginAdjustable.swift in Sources */, + 5750C24C3A9CAE11C7E36B37434912D0 /* MaskingView.swift in Sources */, + 0B42A04122166EAD384BCE37FD450FAF /* MessageView.swift in Sources */, + 461760E2818D72B948B60B4835E7B1ED /* NSBundle+Extensions.swift in Sources */, + 16047C447B00FAA7F42764EC4167C33B /* NSLayoutConstraint+Extensions.swift in Sources */, + 0CE00BF7FB0F6376D89B0AFF1CFD7510 /* PassthroughView.swift in Sources */, + C8F46E0A5853739D3F632B4828FDE9CC /* PassthroughWindow.swift in Sources */, + 7E5ADF1F3B6849D5A0DF8E2B9C1861C5 /* PhysicsAnimation.swift in Sources */, + 0303F738260F2C9BAE20B79DE84E82BC /* PhysicsPanHandler.swift in Sources */, + FF01BC94FADD5A72282AEE043DF523A7 /* Presenter.swift in Sources */, + FA6CA270F521DF68A75E527954A2DDAD /* SwiftMessages-dummy.m in Sources */, + F50FE2EE47422AD39AC8F7F115081E7E /* SwiftMessages.Config+Extensions.swift in Sources */, + B2862C6DDAA6543BB2C8F4541F044564 /* SwiftMessages.swift in Sources */, + 9CEE0E569456D932AA34329D2038DF98 /* SwiftMessagesSegue.swift in Sources */, + 2181E713FC7C00EE871FDA6CB62C7E8C /* Theme.swift in Sources */, + BC4618CE535404A9540D4D110B5767A1 /* TopBottomAnimation.swift in Sources */, + 52F4ED7F78829270B2AFE5EDBA9EEE2F /* UIEdgeInsets+Extensions.swift in Sources */, + D9077478C2FCD7C3DD1EBE9373281728 /* UIViewController+Extensions.swift in Sources */, + 6C7DAA6A68AFDACD67F2C127CEF4DD6F /* UIWindow+Extensions.swift in Sources */, + 00468531530F8A70E3D83622BD482026 /* Weak.swift in Sources */, + F5642C087197B9033252FF10FBA92B59 /* WindowViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 03EC5F5CF0CAA96E132B778FB51EBCE9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "SwiftMessages-SwiftMessages_SwiftMessages"; + target = 1FC5E8328653C350899229BDF89FACE5 /* SwiftMessages-SwiftMessages_SwiftMessages */; + targetProxy = 141E78A8858DBF8B2695DFEDCBDF5158 /* PBXContainerItemProxy */; + }; + 3CF465B66D2B58FC406E66E621CBCB11 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftMessages; + target = DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */; + targetProxy = 4DB1DDB02425E67ED85C70C3B138E205 /* PBXContainerItemProxy */; + }; + BB9BD3F204FD8449B62AD70E23DABC13 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftMessages; + target = DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */; + targetProxy = 900F05D1477FFAB64FF410CBB6B9B74D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 24D1D8F3B822E3083FF435C91CB434FD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6E9D4A0FDDEEDDC5A1A63D89B43C1F18 /* SwiftMessages.debug.xcconfig */; + buildSettings = { + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SwiftMessages"; + IBSC_MODULE = SwiftMessages; + INFOPLIST_FILE = "Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = SwiftMessages_SwiftMessages; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + 6427804744C4054555383985007A0B6C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + 74556EDEC03158A3009CA84D67369133 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + 7C5AE2DF0A930DD6AC66390486478632 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E070773539E02C11297794CC4CB839D6 /* SwiftMessages.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SwiftMessages/SwiftMessages-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SwiftMessages/SwiftMessages-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/SwiftMessages/SwiftMessages.modulemap"; + PRODUCT_MODULE_NAME = SwiftMessages; + PRODUCT_NAME = SwiftMessages; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 891563622FB1DE05CD4905BE16203F07 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C306ACAFEE157959D78E71DBBBD675DC /* Pods-iMessageExtensionDemo.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + A1CD8FCA9657A138B144BC1F2AABADD3 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AE7AEA9CE6B44DCC96AE4E68FA644DAA /* Pods-iMessageExtensionDemo.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + BCFFE899A2E9C1DF0CA120A3F3CECECC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E070773539E02C11297794CC4CB839D6 /* SwiftMessages.release.xcconfig */; + buildSettings = { + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SwiftMessages"; + IBSC_MODULE = SwiftMessages; + INFOPLIST_FILE = "Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = SwiftMessages_SwiftMessages; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; + C9423D1E13393A1A8BC54BE4E87A96AD /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 820B743874F7AC9F9E3970D68E2E60FA /* Pods-iMessageDemo.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + F069CD2F5774D5082336F140E5F68B3A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6E9D4A0FDDEEDDC5A1A63D89B43C1F18 /* SwiftMessages.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SwiftMessages/SwiftMessages-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SwiftMessages/SwiftMessages-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/SwiftMessages/SwiftMessages.modulemap"; + PRODUCT_MODULE_NAME = SwiftMessages; + PRODUCT_NAME = SwiftMessages; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + FCA0FCAB93E530D2C6BED8D3910FEB4A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B99CBDE49D6502CF64EB9059C005BF31 /* Pods-iMessageDemo.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 20A82A14E31D7EFF5BE9B60529162F4B /* Build configuration list for PBXNativeTarget "Pods-iMessageDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FCA0FCAB93E530D2C6BED8D3910FEB4A /* Debug */, + C9423D1E13393A1A8BC54BE4E87A96AD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6427804744C4054555383985007A0B6C /* Debug */, + 74556EDEC03158A3009CA84D67369133 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 57E1F5473FEF9FC2401E805CCF8188C3 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages_SwiftMessages" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 24D1D8F3B822E3083FF435C91CB434FD /* Debug */, + BCFFE899A2E9C1DF0CA120A3F3CECECC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + ABCC3636B5EAEBE6D60D155704F40EBC /* Build configuration list for PBXNativeTarget "SwiftMessages" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F069CD2F5774D5082336F140E5F68B3A /* Debug */, + 7C5AE2DF0A930DD6AC66390486478632 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + ED0C46CBFB7B22526D6F384198E16114 /* Build configuration list for PBXNativeTarget "Pods-iMessageExtensionDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 891563622FB1DE05CD4905BE16203F07 /* Debug */, + A1CD8FCA9657A138B144BC1F2AABADD3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; +} diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist new file mode 100644 index 00000000..2243fe6e --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>${PRODUCT_BUNDLE_IDENTIFIER}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>FMWK</string> + <key>CFBundleShortVersionString</key> + <string>1.0.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>${CURRENT_PROJECT_VERSION}</string> + <key>NSPrincipalClass</key> + <string></string> +</dict> +</plist> diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-acknowledgements.markdown b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-acknowledgements.markdown new file mode 100644 index 00000000..cfe94293 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-acknowledgements.markdown @@ -0,0 +1,14 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## SwiftMessages + +Copyright (c) 2016 SwiftKick Mobile LLC + + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Generated by CocoaPods - https://cocoapods.org diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-acknowledgements.plist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-acknowledgements.plist new file mode 100644 index 00000000..25aea9b0 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-acknowledgements.plist @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>PreferenceSpecifiers</key> + <array> + <dict> + <key>FooterText</key> + <string>This application makes use of the following third party libraries:</string> + <key>Title</key> + <string>Acknowledgements</string> + <key>Type</key> + <string>PSGroupSpecifier</string> + </dict> + <dict> + <key>FooterText</key> + <string>Copyright (c) 2016 SwiftKick Mobile LLC + + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</string> + <key>License</key> + <string>MIT</string> + <key>Title</key> + <string>SwiftMessages</string> + <key>Type</key> + <string>PSGroupSpecifier</string> + </dict> + <dict> + <key>FooterText</key> + <string>Generated by CocoaPods - https://cocoapods.org</string> + <key>Title</key> + <string></string> + <key>Type</key> + <string>PSGroupSpecifier</string> + </dict> + </array> + <key>StringsTable</key> + <string>Acknowledgements</string> + <key>Title</key> + <string>Acknowledgements</string> +</dict> +</plist> diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-dummy.m b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-dummy.m new file mode 100644 index 00000000..2d3a72b7 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-dummy.m @@ -0,0 +1,5 @@ +#import <Foundation/Foundation.h> +@interface PodsDummy_Pods_iMessageDemo : NSObject +@end +@implementation PodsDummy_Pods_iMessageDemo +@end diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-input-files.xcfilelist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-input-files.xcfilelist new file mode 100644 index 00000000..c2649f16 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-input-files.xcfilelist @@ -0,0 +1,2 @@ +${PODS_ROOT}/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh +${BUILT_PRODUCTS_DIR}/SwiftMessages/SwiftMessages.framework \ No newline at end of file diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-output-files.xcfilelist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-output-files.xcfilelist new file mode 100644 index 00000000..7e50d50f --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-output-files.xcfilelist @@ -0,0 +1 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftMessages.framework \ No newline at end of file diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-input-files.xcfilelist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-input-files.xcfilelist new file mode 100644 index 00000000..c2649f16 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-input-files.xcfilelist @@ -0,0 +1,2 @@ +${PODS_ROOT}/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh +${BUILT_PRODUCTS_DIR}/SwiftMessages/SwiftMessages.framework \ No newline at end of file diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-output-files.xcfilelist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-output-files.xcfilelist new file mode 100644 index 00000000..7e50d50f --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-output-files.xcfilelist @@ -0,0 +1 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftMessages.framework \ No newline at end of file diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh new file mode 100755 index 00000000..c735166d --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh @@ -0,0 +1,185 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" +BCSYMBOLMAP_DIR="BCSymbolMaps" + + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then + # Locate and install any .bcsymbolmaps if present, and remove them from the .framework before the framework is copied + find "${source}/${BCSYMBOLMAP_DIR}" -name "*.bcsymbolmap"|while read f; do + echo "Installing $f" + install_bcsymbolmap "$f" "$destination" + rm "$f" + done + rmdir "${source}/${BCSYMBOLMAP_DIR}" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + warn_missing_arch=${2:-true} + if [ -r "$source" ]; then + # Copy the dSYM into the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .dSYM "$source")" + binary_name="$(ls "$source/Contents/Resources/DWARF")" + binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" + + # Strip invalid architectures from the dSYM. + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then + strip_invalid_archs "$binary" "$warn_missing_arch" + fi + if [[ $STRIP_BINARY_RETVAL == 0 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" + fi + fi +} + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + warn_missing_arch=${2:-true} + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + if [[ "$warn_missing_arch" == "true" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + fi + STRIP_BINARY_RETVAL=1 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=0 +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identity + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/SwiftMessages/SwiftMessages.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/SwiftMessages/SwiftMessages.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-umbrella.h b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-umbrella.h new file mode 100644 index 00000000..2e129a27 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import <UIKit/UIKit.h> +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_iMessageDemoVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_iMessageDemoVersionString[]; + diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.debug.xcconfig b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.debug.xcconfig new file mode 100644 index 00000000..7d10f708 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.debug.xcconfig @@ -0,0 +1,14 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages/SwiftMessages.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -framework "UIKit" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.modulemap b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.modulemap new file mode 100644 index 00000000..980c725a --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.modulemap @@ -0,0 +1,6 @@ +framework module Pods_iMessageDemo { + umbrella header "Pods-iMessageDemo-umbrella.h" + + export * + module * { export * } +} diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.release.xcconfig b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.release.xcconfig new file mode 100644 index 00000000..7d10f708 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.release.xcconfig @@ -0,0 +1,14 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages/SwiftMessages.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -framework "UIKit" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist new file mode 100644 index 00000000..2243fe6e --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>${PRODUCT_BUNDLE_IDENTIFIER}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>FMWK</string> + <key>CFBundleShortVersionString</key> + <string>1.0.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>${CURRENT_PROJECT_VERSION}</string> + <key>NSPrincipalClass</key> + <string></string> +</dict> +</plist> diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.markdown b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.markdown new file mode 100644 index 00000000..cfe94293 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.markdown @@ -0,0 +1,14 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## SwiftMessages + +Copyright (c) 2016 SwiftKick Mobile LLC + + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Generated by CocoaPods - https://cocoapods.org diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.plist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.plist new file mode 100644 index 00000000..25aea9b0 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.plist @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>PreferenceSpecifiers</key> + <array> + <dict> + <key>FooterText</key> + <string>This application makes use of the following third party libraries:</string> + <key>Title</key> + <string>Acknowledgements</string> + <key>Type</key> + <string>PSGroupSpecifier</string> + </dict> + <dict> + <key>FooterText</key> + <string>Copyright (c) 2016 SwiftKick Mobile LLC + + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</string> + <key>License</key> + <string>MIT</string> + <key>Title</key> + <string>SwiftMessages</string> + <key>Type</key> + <string>PSGroupSpecifier</string> + </dict> + <dict> + <key>FooterText</key> + <string>Generated by CocoaPods - https://cocoapods.org</string> + <key>Title</key> + <string></string> + <key>Type</key> + <string>PSGroupSpecifier</string> + </dict> + </array> + <key>StringsTable</key> + <string>Acknowledgements</string> + <key>Title</key> + <string>Acknowledgements</string> +</dict> +</plist> diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-dummy.m b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-dummy.m new file mode 100644 index 00000000..a9fef241 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-dummy.m @@ -0,0 +1,5 @@ +#import <Foundation/Foundation.h> +@interface PodsDummy_Pods_iMessageExtensionDemo : NSObject +@end +@implementation PodsDummy_Pods_iMessageExtensionDemo +@end diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-umbrella.h b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-umbrella.h new file mode 100644 index 00000000..b45e1cf3 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import <UIKit/UIKit.h> +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_iMessageExtensionDemoVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_iMessageExtensionDemoVersionString[]; + diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.debug.xcconfig b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.debug.xcconfig new file mode 100644 index 00000000..c23e4e35 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.debug.xcconfig @@ -0,0 +1,13 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages/SwiftMessages.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -framework "UIKit" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.modulemap b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.modulemap new file mode 100644 index 00000000..ab391867 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.modulemap @@ -0,0 +1,6 @@ +framework module Pods_iMessageExtensionDemo { + umbrella header "Pods-iMessageExtensionDemo-umbrella.h" + + export * + module * { export * } +} diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.release.xcconfig b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.release.xcconfig new file mode 100644 index 00000000..c23e4e35 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.release.xcconfig @@ -0,0 +1,13 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages/SwiftMessages.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -framework "UIKit" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages-SwiftMessages-Info.plist b/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages-SwiftMessages-Info.plist new file mode 100644 index 00000000..35c2f997 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages-SwiftMessages-Info.plist @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleIdentifier</key> + <string>${PRODUCT_BUNDLE_IDENTIFIER}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>9.0.1</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>NSPrincipalClass</key> + <string></string> +</dict> +</plist> diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist b/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist new file mode 100644 index 00000000..35c2f997 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleIdentifier</key> + <string>${PRODUCT_BUNDLE_IDENTIFIER}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>9.0.1</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>NSPrincipalClass</key> + <string></string> +</dict> +</plist> diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist new file mode 100644 index 00000000..2687f6bd --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>${PRODUCT_BUNDLE_IDENTIFIER}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>FMWK</string> + <key>CFBundleShortVersionString</key> + <string>9.0.1</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>${CURRENT_PROJECT_VERSION}</string> + <key>NSPrincipalClass</key> + <string></string> +</dict> +</plist> diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-dummy.m b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-dummy.m new file mode 100644 index 00000000..dc460b82 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-dummy.m @@ -0,0 +1,5 @@ +#import <Foundation/Foundation.h> +@interface PodsDummy_SwiftMessages : NSObject +@end +@implementation PodsDummy_SwiftMessages +@end diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-prefix.pch b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import <UIKit/UIKit.h> +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-umbrella.h b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-umbrella.h new file mode 100644 index 00000000..9aa634f0 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import <UIKit/UIKit.h> +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double SwiftMessagesVersionNumber; +FOUNDATION_EXPORT const unsigned char SwiftMessagesVersionString[]; + diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.debug.xcconfig b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.debug.xcconfig new file mode 100644 index 00000000..9bbd3c8d --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.debug.xcconfig @@ -0,0 +1,15 @@ +APPLICATION_EXTENSION_API_ONLY = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 SWIFTMESSAGES_APP_EXTENSIONS=1 +OTHER_LDFLAGS = $(inherited) -framework "UIKit" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFTMESSAGES_APP_EXTENSIONS +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.modulemap b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.modulemap new file mode 100644 index 00000000..96306d64 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.modulemap @@ -0,0 +1,6 @@ +framework module SwiftMessages { + umbrella header "SwiftMessages-umbrella.h" + + export * + module * { export * } +} diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.release.xcconfig b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.release.xcconfig new file mode 100644 index 00000000..9bbd3c8d --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.release.xcconfig @@ -0,0 +1,15 @@ +APPLICATION_EXTENSION_API_ONLY = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 SWIFTMESSAGES_APP_EXTENSIONS=1 +OTHER_LDFLAGS = $(inherited) -framework "UIKit" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFTMESSAGES_APP_EXTENSIONS +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iMessageDemo/iMessageDemo.xcodeproj/project.pbxproj b/iMessageDemo/iMessageDemo.xcodeproj/project.pbxproj index 05863d63..ff0e9049 100644 --- a/iMessageDemo/iMessageDemo.xcodeproj/project.pbxproj +++ b/iMessageDemo/iMessageDemo.xcodeproj/project.pbxproj @@ -13,9 +13,8 @@ 2272F21921080DD600AD190C /* iMessageExtensionDemo.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 2272F20A21080DD500AD190C /* iMessageExtensionDemo.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 2272F21F2108113F00AD190C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2272F21E2108113F00AD190C /* Main.storyboard */; }; 2272F221210811BE00AD190C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2272F220210811BE00AD190C /* LaunchScreen.storyboard */; }; - 22B96AF4213D94CC00357CB5 /* SwiftMessages.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22FE3FE9211941FD0017303D /* SwiftMessages.framework */; }; - 22FE3FFD211944040017303D /* SwiftMessages.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22FE3FE9211941FD0017303D /* SwiftMessages.framework */; }; - 22FE3FFE211944040017303D /* SwiftMessages.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 22FE3FE9211941FD0017303D /* SwiftMessages.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 76D3135B88AA54ECC98CBD36 /* Pods_iMessageDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73DC8D5C3B1552230D960BF7 /* Pods_iMessageDemo.framework */; }; + F49106CE51DB9708982AF779 /* Pods_iMessageExtensionDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E1E18BC615CEA5704F4B5FB /* Pods_iMessageExtensionDemo.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -26,34 +25,6 @@ remoteGlobalIDString = 2272F20921080DD500AD190C; remoteInfo = iMessageExtensionDemo; }; - 22FE3FE8211941FD0017303D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 22FE3FE2211941FD0017303D /* SwiftMessages.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 86B48AEC1D5A41C900063E2B; - remoteInfo = SwiftMessages; - }; - 22FE3FEC211941FD0017303D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 22FE3FE2211941FD0017303D /* SwiftMessages.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 86B48AF51D5A41C900063E2B; - remoteInfo = SwiftMessagesTests; - }; - 22FE3FFB211942A50017303D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 22FE3FE2211941FD0017303D /* SwiftMessages.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 86B48AEB1D5A41C900063E2B; - remoteInfo = SwiftMessages; - }; - 22FE3FFF211944040017303D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 22FE3FE2211941FD0017303D /* SwiftMessages.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 86B48AEB1D5A41C900063E2B; - remoteInfo = SwiftMessages; - }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -74,7 +45,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 22FE3FFE211944040017303D /* SwiftMessages.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -82,6 +52,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 212D588BA5EE4E8BF07B02D8 /* Pods-iMessageExtensionDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iMessageExtensionDemo.release.xcconfig"; path = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.release.xcconfig"; sourceTree = "<group>"; }; + 21DDEA06F4193D7F35B70A53 /* Pods-iMessageDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iMessageDemo.release.xcconfig"; path = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.release.xcconfig"; sourceTree = "<group>"; }; 2272F1F121080DAE00AD190C /* iMessageDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iMessageDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 2272F1F421080DAE00AD190C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 2272F20021080DB200AD190C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; @@ -92,7 +64,10 @@ 2272F21621080DD600AD190C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 2272F21E2108113F00AD190C /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; }; 2272F220210811BE00AD190C /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; }; - 22FE3FE2211941FD0017303D /* SwiftMessages.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SwiftMessages.xcodeproj; path = ../SwiftMessages.xcodeproj; sourceTree = "<group>"; }; + 4E1E18BC615CEA5704F4B5FB /* Pods_iMessageExtensionDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_iMessageExtensionDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 73DC8D5C3B1552230D960BF7 /* Pods_iMessageDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_iMessageDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 76B6E320915B554B5D628DFC /* Pods-iMessageDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iMessageDemo.debug.xcconfig"; path = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.debug.xcconfig"; sourceTree = "<group>"; }; + EE094075BD5252DAD69071F9 /* Pods-iMessageExtensionDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iMessageExtensionDemo.debug.xcconfig"; path = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.debug.xcconfig"; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -100,7 +75,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 22FE3FFD211944040017303D /* SwiftMessages.framework in Frameworks */, + 76D3135B88AA54ECC98CBD36 /* Pods_iMessageDemo.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -108,7 +83,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 22B96AF4213D94CC00357CB5 /* SwiftMessages.framework in Frameworks */, + F49106CE51DB9708982AF779 /* Pods_iMessageExtensionDemo.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -122,7 +97,7 @@ 2272F20E21080DD500AD190C /* iMessageExtensionDemo */, 2272F20B21080DD500AD190C /* Frameworks */, 2272F1F221080DAE00AD190C /* Products */, - 22FE3FE2211941FD0017303D /* SwiftMessages.xcodeproj */, + C99B3449FCA583CA3ECDC53C /* Pods */, ); sourceTree = "<group>"; }; @@ -150,6 +125,8 @@ isa = PBXGroup; children = ( 2272F20C21080DD500AD190C /* Messages.framework */, + 73DC8D5C3B1552230D960BF7 /* Pods_iMessageDemo.framework */, + 4E1E18BC615CEA5704F4B5FB /* Pods_iMessageExtensionDemo.framework */, ); name = Frameworks; sourceTree = "<group>"; @@ -164,13 +141,16 @@ path = iMessageExtensionDemo; sourceTree = "<group>"; }; - 22FE3FE3211941FD0017303D /* Products */ = { + C99B3449FCA583CA3ECDC53C /* Pods */ = { isa = PBXGroup; children = ( - 22FE3FE9211941FD0017303D /* SwiftMessages.framework */, - 22FE3FED211941FD0017303D /* SwiftMessagesTests.xctest */, + 76B6E320915B554B5D628DFC /* Pods-iMessageDemo.debug.xcconfig */, + 21DDEA06F4193D7F35B70A53 /* Pods-iMessageDemo.release.xcconfig */, + EE094075BD5252DAD69071F9 /* Pods-iMessageExtensionDemo.debug.xcconfig */, + 212D588BA5EE4E8BF07B02D8 /* Pods-iMessageExtensionDemo.release.xcconfig */, ); - name = Products; + name = Pods; + path = Pods; sourceTree = "<group>"; }; /* End PBXGroup section */ @@ -180,17 +160,18 @@ isa = PBXNativeTarget; buildConfigurationList = 2272F20321080DB200AD190C /* Build configuration list for PBXNativeTarget "iMessageDemo" */; buildPhases = ( + C9C10288A07806AC55B5E4B3 /* [CP] Check Pods Manifest.lock */, 2272F1ED21080DAE00AD190C /* Sources */, 2272F1EE21080DAE00AD190C /* Frameworks */, 2272F1EF21080DAE00AD190C /* Resources */, 2272F21D21080DD600AD190C /* Embed App Extensions */, 22FE4001211944040017303D /* Embed Frameworks */, + 77C3B4728FB9FC385B4279B6 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( 2272F21821080DD600AD190C /* PBXTargetDependency */, - 22FE4000211944040017303D /* PBXTargetDependency */, ); name = iMessageDemo; productName = iMessageDemo; @@ -201,6 +182,7 @@ isa = PBXNativeTarget; buildConfigurationList = 2272F21A21080DD600AD190C /* Build configuration list for PBXNativeTarget "iMessageExtensionDemo" */; buildPhases = ( + 7FD245EE0E3D4F436FEB306E /* [CP] Check Pods Manifest.lock */, 2272F20621080DD500AD190C /* Sources */, 2272F20721080DD500AD190C /* Frameworks */, 2272F20821080DD500AD190C /* Resources */, @@ -208,7 +190,6 @@ buildRules = ( ); dependencies = ( - 22FE3FFC211942A50017303D /* PBXTargetDependency */, ); name = iMessageExtensionDemo; productName = iMessageExtensionDemo; @@ -244,12 +225,6 @@ mainGroup = 2272F1E821080DAE00AD190C; productRefGroup = 2272F1F221080DAE00AD190C /* Products */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 22FE3FE3211941FD0017303D /* Products */; - ProjectRef = 22FE3FE2211941FD0017303D /* SwiftMessages.xcodeproj */; - }, - ); projectRoot = ""; targets = ( 2272F1F021080DAE00AD190C /* iMessageDemo */, @@ -258,23 +233,6 @@ }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - 22FE3FE9211941FD0017303D /* SwiftMessages.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = SwiftMessages.framework; - remoteRef = 22FE3FE8211941FD0017303D /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 22FE3FED211941FD0017303D /* SwiftMessagesTests.xctest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = SwiftMessagesTests.xctest; - remoteRef = 22FE3FEC211941FD0017303D /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXResourcesBuildPhase section */ 2272F1EF21080DAE00AD190C /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -295,6 +253,70 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 77C3B4728FB9FC385B4279B6 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 7FD245EE0E3D4F436FEB306E /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-iMessageExtensionDemo-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + C9C10288A07806AC55B5E4B3 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-iMessageDemo-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 2272F1ED21080DAE00AD190C /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -320,16 +342,6 @@ target = 2272F20921080DD500AD190C /* iMessageExtensionDemo */; targetProxy = 2272F21721080DD600AD190C /* PBXContainerItemProxy */; }; - 22FE3FFC211942A50017303D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = SwiftMessages; - targetProxy = 22FE3FFB211942A50017303D /* PBXContainerItemProxy */; - }; - 22FE4000211944040017303D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = SwiftMessages; - targetProxy = 22FE3FFF211944040017303D /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -460,6 +472,7 @@ }; 2272F20421080DB200AD190C /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 76B6E320915B554B5D628DFC /* Pods-iMessageDemo.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; @@ -478,6 +491,7 @@ }; 2272F20521080DB200AD190C /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 21DDEA06F4193D7F35B70A53 /* Pods-iMessageDemo.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; @@ -496,6 +510,7 @@ }; 2272F21B21080DD600AD190C /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = EE094075BD5252DAD69071F9 /* Pods-iMessageExtensionDemo.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon"; CODE_SIGN_STYLE = Automatic; @@ -516,6 +531,7 @@ }; 2272F21C21080DD600AD190C /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 212D588BA5EE4E8BF07B02D8 /* Pods-iMessageExtensionDemo.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon"; CODE_SIGN_STYLE = Automatic; diff --git a/iMessageDemo/iMessageDemo.xcworkspace/contents.xcworkspacedata b/iMessageDemo/iMessageDemo.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..d69114e3 --- /dev/null +++ b/iMessageDemo/iMessageDemo.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "group:iMessageDemo.xcodeproj"> + </FileRef> + <FileRef + location = "group:Pods/Pods.xcodeproj"> + </FileRef> +</Workspace> diff --git a/iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEDidComputeMac32BitWarning</key> + <true/> +</dict> +</plist> From b750f852e690ad3e81687b1a0b1a67c9e2d19653 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 10 Apr 2021 16:30:45 -0500 Subject: [PATCH 28/77] Revert "refactor(MessageView): remove redundant words for `button` (#461)" This reverts commit c63e64e8a8988f0885e3ee23fb1e50f9b6cbd584. --- SwiftMessages/MessageView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftMessages/MessageView.swift b/SwiftMessages/MessageView.swift index e844b074..d9be31d9 100644 --- a/SwiftMessages/MessageView.swift +++ b/SwiftMessages/MessageView.swift @@ -55,7 +55,7 @@ open class MessageView: BaseView, Identifiable, AccessibleMessage { /// An optional button. This buttons' `.TouchUpInside` event will automatically /// invoke the optional `buttonTapHandler`, but its fine to add other target - /// action handlers. + /// action handlers can be added. @IBOutlet open var button: UIButton? { didSet { if let old = oldValue { From 699e0cdc24098eb79081309e1c8560ede96a757c Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 10 Apr 2021 16:30:59 -0500 Subject: [PATCH 29/77] Revert "Public Layout initializer" This reverts commit 4408c09c863b1c6af4d053fe17fd532a4f96b237. --- SwiftMessages/Layout.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/SwiftMessages/Layout.swift b/SwiftMessages/Layout.swift index 09c2c16f..83100822 100644 --- a/SwiftMessages/Layout.swift +++ b/SwiftMessages/Layout.swift @@ -24,8 +24,6 @@ public struct Layout { public var min = Layout() public var max = Layout() - public init() {} - public enum Boundary { case superview case safeArea From 6dd1a1c007daff122402e4de101f459429c5f8f3 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 10 Apr 2021 16:31:09 -0500 Subject: [PATCH 30/77] Revert "Fix arg name" This reverts commit f3a0aca1111e891841e44227ec6a1d0d11b7de9d. --- SwiftMessages/Layout.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftMessages/Layout.swift b/SwiftMessages/Layout.swift index 83100822..0d02fa6c 100644 --- a/SwiftMessages/Layout.swift +++ b/SwiftMessages/Layout.swift @@ -35,7 +35,7 @@ public struct Layout { public enum Dimension { case absolute(CGFloat) case relative(CGFloat, to: Boundary) - case absoluteInsets(CGFloat, from: Boundary) + case absoluteInsets(CGFloat, to: Boundary) } public var width: Dimension? From c79f3b4133e11a7584176056e52771aa04ea0cd3 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 10 Apr 2021 16:31:18 -0500 Subject: [PATCH 31/77] Revert "Add absoluteInsets size option" This reverts commit cc1b635513ebd9f350b41a172ec418dc3593494f. --- SwiftMessages/Layout.swift | 11 ----------- SwiftMessages/MaskingView.swift | 16 +++++----------- 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/SwiftMessages/Layout.swift b/SwiftMessages/Layout.swift index 0d02fa6c..4afcf7b7 100644 --- a/SwiftMessages/Layout.swift +++ b/SwiftMessages/Layout.swift @@ -35,7 +35,6 @@ public struct Layout { public enum Dimension { case absolute(CGFloat) case relative(CGFloat, to: Boundary) - case absoluteInsets(CGFloat, to: Boundary) } public var width: Dimension? @@ -82,16 +81,6 @@ extension Layout.Insets.Dimension { } } -extension Layout.Size.Dimension { - var boundary: Layout.Boundary? { - switch self { - case .absolute(_): return nil - case .relative(_, let boundary): return boundary - case .absoluteInsets(_, let boundary): return boundary - } - } -} - extension Layout.Center.Dimension { var boundary: Layout.Boundary { switch self { diff --git a/SwiftMessages/MaskingView.swift b/SwiftMessages/MaskingView.swift index 08c31d20..81301994 100644 --- a/SwiftMessages/MaskingView.swift +++ b/SwiftMessages/MaskingView.swift @@ -417,8 +417,10 @@ class MaskingView: PassthroughView, LayoutInstalling { for dimension: Layout.Size.Dimension, extractor: (CGRect) -> CGFloat ) -> CGFloat { - let insetBounds: CGRect = { - guard let boundary = dimension.boundary else { return .zero } + switch dimension { + case .absolute(let dimension): + return dimension + case .relative(let percentage, let boundary): let insets: UIEdgeInsets switch boundary { case .superview: insets = .zero @@ -430,15 +432,7 @@ class MaskingView: PassthroughView, LayoutInstalling { insets = layoutMargins } } - return bounds.inset(by: insets) - }() - switch dimension { - case .absolute(let dimension): - return dimension - case .relative(let percentage, _): - return extractor(insetBounds) * percentage - case .absoluteInsets(let dimension, _): - return extractor(insetBounds) - dimension * 2 + return extractor(bounds.inset(by: insets)) * percentage } } From 856f4da5e4c100d3b178cd9619587ddaad35dbe2 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 10 Apr 2021 16:32:27 -0500 Subject: [PATCH 32/77] Revert "Adjust edge animation timing" This reverts commit e7d7e00c2d7f34bf0405c28e853564195bf369c3. # Conflicts: # SwiftMessages.xcodeproj/project.pbxproj --- SwiftMessages.xcodeproj/project.pbxproj | 10 ++++------ ...{EdgeAnimation.swift => TopBottomAnimation.swift} | 12 ++++++------ 2 files changed, 10 insertions(+), 12 deletions(-) rename SwiftMessages/{EdgeAnimation.swift => TopBottomAnimation.swift} (97%) diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index c9e779ae..9c9e8ee8 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -55,8 +55,7 @@ 2290958125D9D407002E8111 /* UILayoutPriority+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */; }; 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; - 2298C2091EE486E300E2DDC1 /* EdgeAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* EdgeAnimation.swift */; }; - 229F778125FAB1E9008C2ACB /* UIWindow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */; }; + 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */; }; 22DFC9161EFF30F6001B1CA1 /* CenteredView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */; }; 22DFC9181F00674E001B1CA1 /* PhysicsPanHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */; }; 22E01F641E74EC8B00ACE19A /* MaskingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22E01F631E74EC8B00ACE19A /* MaskingView.swift */; }; @@ -144,8 +143,7 @@ 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILayoutPriority+Extensions.swift"; sourceTree = "<group>"; }; 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; - 2298C2081EE486E300E2DDC1 /* EdgeAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EdgeAnimation.swift; sourceTree = "<group>"; }; - 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+Extensions.swift"; sourceTree = "<group>"; }; + 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = "<group>"; }; 22A2EA6E24EC6CFA00BB2540 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; }; 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = CenteredView.xib; path = Resources/CenteredView.xib; sourceTree = "<group>"; }; 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsPanHandler.swift; sourceTree = "<group>"; }; @@ -224,7 +222,7 @@ 2244656C1EF1D62700C50413 /* Animations */ = { isa = PBXGroup; children = ( - 2298C2081EE486E300E2DDC1 /* EdgeAnimation.swift */, + 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */, 2270044A1FAFA6DD0045DDC3 /* PhysicsAnimation.swift */, 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */, ); @@ -560,7 +558,7 @@ 86BBA8FF1D5E040600FE8F16 /* Presenter.swift in Sources */, 86BBA9051D5E040C00FE8F16 /* Theme.swift in Sources */, 86BBA9081D5E040C00FE8F16 /* Error.swift in Sources */, - 2298C2091EE486E300E2DDC1 /* EdgeAnimation.swift in Sources */, + 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */, 86589D471D64B6E40041676C /* BaseView.swift in Sources */, 225304622290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift in Sources */, 86BBA9071D5E040C00FE8F16 /* MarginAdjustable.swift in Sources */, diff --git a/SwiftMessages/EdgeAnimation.swift b/SwiftMessages/TopBottomAnimation.swift similarity index 97% rename from SwiftMessages/EdgeAnimation.swift rename to SwiftMessages/TopBottomAnimation.swift index 21039378..f8afc781 100644 --- a/SwiftMessages/EdgeAnimation.swift +++ b/SwiftMessages/TopBottomAnimation.swift @@ -1,5 +1,5 @@ // -// EdgeAnimation.swift +// TopBottomAnimation.swift // SwiftMessages // // Created by Timothy Moose on 6/4/17. @@ -24,9 +24,9 @@ public class EdgeAnimation: NSObject, Animator { public let style: Style - open var showDuration: TimeInterval = 0.35 + open var showDuration: TimeInterval = 0.4 - open var hideDuration: TimeInterval = 0.25 + open var hideDuration: TimeInterval = 0.2 open var springDamping: CGFloat = 0.8 @@ -65,7 +65,7 @@ public class EdgeAnimation: NSObject, Animator { NotificationCenter.default.removeObserver(self) let view = context.messageView self.context = context - UIView.animate(withDuration: hideDuration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: [.beginFromCurrentState]) { + UIView.animate(withDuration: hideDuration, delay: 0, options: [.beginFromCurrentState, .curveEaseIn], animations: { switch self.style { case .top: view.transform = CGAffineTransform(translationX: 0, y: -view.frame.height) @@ -76,14 +76,14 @@ public class EdgeAnimation: NSObject, Animator { case .trailing: view.transform = CGAffineTransform(translationX: view.frame.maxX + view.frame.width, y: 0) } - } completion: { completed in + }, completion: { completed in #if SWIFTMESSAGES_APP_EXTENSIONS completion(completed) #else // Fix #131 by always completing if application isn't active. completion(completed || UIApplication.shared.applicationState != .active) #endif - } + }) } func install(context: AnimationContext) { From 0d7584e671f1ca72f6bae83349cfbb60633a0fa9 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 10 Apr 2021 16:32:43 -0500 Subject: [PATCH 33/77] Revert "Expand scope of new sizing API" This reverts commit 3883abc3f4918aaea605a8f7450c81675a9ebf65. --- Demo/Demo/Base.lproj/Main.storyboard | 398 ++++++------------ Demo/Demo/ViewControllersViewController.swift | 78 +--- SwiftMessages.xcodeproj/project.pbxproj | 12 +- SwiftMessages/Animator.swift | 4 +- SwiftMessages/BaseView.swift | 109 ++--- SwiftMessages/CornerRoundingView.swift | 4 +- SwiftMessages/Layout.swift | 91 ---- SwiftMessages/MaskingView.swift | 307 +++----------- SwiftMessages/MessageSizeable.swift | 65 +++ SwiftMessages/MessageSizing.swift | 13 + SwiftMessages/PhysicsAnimation.swift | 37 +- SwiftMessages/Presenter.swift | 4 +- SwiftMessages/SwiftMessagesSegue.swift | 210 ++++----- SwiftMessages/TopBottomAnimation.swift | 133 ++---- .../UILayoutPriority+Extensions.swift | 18 +- .../UIViewController+Extensions.swift | 6 +- 16 files changed, 470 insertions(+), 1019 deletions(-) delete mode 100644 SwiftMessages/Layout.swift create mode 100644 SwiftMessages/MessageSizeable.swift create mode 100644 SwiftMessages/MessageSizing.swift diff --git a/Demo/Demo/Base.lproj/Main.storyboard b/Demo/Demo/Base.lproj/Main.storyboard index f8968f69..08ab75d2 100644 --- a/Demo/Demo/Base.lproj/Main.storyboard +++ b/Demo/Demo/Base.lproj/Main.storyboard @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="JQZ-C5-7mw"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="JQZ-C5-7mw"> <device id="retina4_7" orientation="portrait" appearance="light"/> <dependencies> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/> - <capability name="System colors in document resources" minToolsVersion="11.0"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15508"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> @@ -31,7 +30,7 @@ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="j4a-wU-637"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> <prototypes> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="TitleBody" rowHeight="80" id="2n5-7h-3B5" userLabel="TitleBody Cell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> <rect key="frame" x="0.0" y="28" width="375" height="80"/> @@ -48,7 +47,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Body" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Gpd-DA-5jT"> <rect key="frame" x="26" y="45" width="323" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor"/> + <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> </subviews> @@ -82,7 +81,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Explore many of the SwiftMessages configuration options." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Siq-Fh-MNa"> <rect key="frame" x="26" y="45" width="304" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor"/> + <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> </subviews> @@ -117,7 +116,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Present modal view controllers with SwiftMessages animations." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sCg-K7-URy"> <rect key="frame" x="26" y="45" width="304" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor"/> + <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> </subviews> @@ -152,7 +151,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Present modal view controllers with SwiftMessages animations." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="T5Q-9f-KQC"> <rect key="frame" x="26" y="45" width="304" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor"/> + <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> </subviews> @@ -186,7 +185,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hide a message based on equal number of show() and hideCounted(id:) calls." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ie4-WM-pe4"> <rect key="frame" x="26" y="45" width="304" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor"/> + <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> </subviews> @@ -224,7 +223,7 @@ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="none" allowsSelection="NO" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="XwA-eF-0LG"> <rect key="frame" x="0.0" y="0.0" width="375" height="1200"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> <sections> <tableViewSection headerTitle="Presentation" id="ifN-uy-lWX"> <cells> @@ -642,7 +641,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Button" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dRM-c4-ORW"> <rect key="frame" x="69" y="0.0" width="72.5" height="4.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor"/> + <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> </subviews> @@ -656,7 +655,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PfQ-eZ-O0L"> <rect key="frame" x="69" y="0.0" width="72.5" height="4.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor"/> + <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> </subviews> @@ -675,7 +674,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Icon" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XKN-W4-1jq"> <rect key="frame" x="69" y="0.0" width="72.5" height="4.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor"/> + <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> </subviews> @@ -689,7 +688,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Body" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DGg-y8-Ln9"> <rect key="frame" x="69" y="0.0" width="72.5" height="4.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor"/> + <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> </subviews> @@ -811,255 +810,115 @@ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="mGe-El-haJ"> - <rect key="frame" x="31" y="59" width="313" height="284"/> + <rect key="frame" x="46" y="84" width="283" height="494"/> <subviews> - <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="duT-dC-cRi"> - <rect key="frame" x="0.0" y="0.0" width="313" height="32"/> - <subviews> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DrN-Ei-Pg7"> - <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> - <color key="backgroundColor" red="0.16470588235294117" green="0.6588235294117647" blue="0.98039215686274506" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Top"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopSegue" customModule="Demo" customModuleProvider="target" id="7xS-Ca-mnb"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GeC-SP-rSC"> - <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> - <color key="backgroundColor" red="0.1647058824" green="0.6588235294" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Bottom"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomSegue" customModule="Demo" customModuleProvider="target" id="6Yg-dE-eXA"/> - </connections> - </button> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" id="edP-BU-APQ"> - <rect key="frame" x="0.0" y="42" width="313" height="32"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> - <subviews> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="khy-PR-9ic"> - <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> - <color key="backgroundColor" red="0.1647058824" green="0.6588235294" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Leading"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesLeadingSegue" customModule="Demo" customModuleProvider="target" id="vqC-mA-oKl"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IYU-GH-7Bu"> - <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> - <color key="backgroundColor" red="0.1647058824" green="0.6588235294" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Trailing"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTrailingSegue" customModule="Demo" customModuleProvider="target" id="Htu-Pa-8Bb"/> - </connections> - </button> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" id="RIf-X4-6Nf"> - <rect key="frame" x="0.0" y="84" width="313" height="32"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> - <subviews> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DGn-eY-EEX"> - <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> - <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Top Card"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopCardSegue" customModule="Demo" customModuleProvider="target" id="qLf-js-3Ls"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZQs-MK-vK3"> - <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> - <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Bottom Card"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomCardSegue" customModule="Demo" customModuleProvider="target" id="TBl-s0-9vL"/> - </connections> - </button> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" id="4Lv-io-Ckq"> - <rect key="frame" x="0.0" y="126" width="313" height="32"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> - <subviews> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="RLv-JB-1Kv"> - <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> - <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Leading Card"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesLeadingCardSegue" customModule="Demo" customModuleProvider="target" id="ijQ-PY-fOg"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VoG-71-V86"> - <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> - <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Trailing Card"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTrailingCardSegue" customModule="Demo" customModuleProvider="target" id="eyV-wa-br5"/> - </connections> - </button> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" id="cco-7a-QYG"> - <rect key="frame" x="0.0" y="168" width="313" height="32"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> - <subviews> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kux-aE-Bdv" userLabel="Top Tab"> - <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> - <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000067" blue="0.62082127703967116" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Top Tab"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopTabSegue" customModule="Demo" customModuleProvider="target" id="p7Y-6q-gfK"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dMQ-xF-RwV" userLabel="Bottom Tab"> - <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> - <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000001" blue="0.620821277" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Bottom Tab"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomTabSegue" customModule="Demo" customModuleProvider="target" id="EaG-Ea-U3j"/> - </connections> - </button> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" id="p3M-fI-UAT"> - <rect key="frame" x="0.0" y="210" width="313" height="32"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> - <subviews> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wPG-Jy-nyC"> - <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> - <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000001" blue="0.620821277" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Leading Tab"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesLeadingTabSegue" customModule="Demo" customModuleProvider="target" id="IIr-OL-eMR"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SR9-3n-RLT"> - <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> - <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000001" blue="0.620821277" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Trailing Tab"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTrailingTabSegue" customModule="Demo" customModuleProvider="target" id="LC0-Bk-8Ad"/> - </connections> - </button> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" id="Cqr-gB-ufD"> - <rect key="frame" x="0.0" y="252" width="313" height="32"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> - <subviews> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CDi-Gu-bE2" userLabel="Centered"> - <rect key="frame" x="0.0" y="0.0" width="151.5" height="32"/> - <color key="backgroundColor" red="1" green="0.46653546191345963" blue="0.015686274510000042" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Centered"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesCenteredSegue" customModule="Demo" customModuleProvider="target" id="had-cE-9YN"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="WGh-db-dXZ" userLabel="Centered"> - <rect key="frame" x="161.5" y="0.0" width="151.5" height="32"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> - <color key="backgroundColor" red="1" green="0.4665354619" blue="0.015686274510000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> - <state key="normal" title="Off-Centered"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="10"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesOffCenteredSegue" customModule="Demo" customModuleProvider="target" id="abD-oU-7qa"/> - </connections> - </button> - </subviews> - </stackView> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DrN-Ei-Pg7"> + <rect key="frame" x="0.0" y="0.0" width="283" height="62"/> + <color key="backgroundColor" red="0.16470588235294117" green="0.6588235294117647" blue="0.98039215686274506" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Top Message"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopSegue" customModule="Demo" customModuleProvider="target" id="7xS-Ca-mnb"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GeC-SP-rSC"> + <rect key="frame" x="0.0" y="72" width="283" height="62"/> + <color key="backgroundColor" red="0.1647058824" green="0.6588235294" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Bottom Message"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomSegue" customModule="Demo" customModuleProvider="target" id="6Yg-dE-eXA"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DGn-eY-EEX"> + <rect key="frame" x="0.0" y="144" width="283" height="62"/> + <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Top Card"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopCardSegue" customModule="Demo" customModuleProvider="target" id="qLf-js-3Ls"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZQs-MK-vK3"> + <rect key="frame" x="0.0" y="216" width="283" height="62"/> + <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Bottom Card"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomCardSegue" customModule="Demo" customModuleProvider="target" id="TBl-s0-9vL"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kux-aE-Bdv" userLabel="Top Tab"> + <rect key="frame" x="0.0" y="288" width="283" height="62"/> + <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000067" blue="0.62082127703967116" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Top Tab"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopTabSegue" customModule="Demo" customModuleProvider="target" id="p7Y-6q-gfK"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dMQ-xF-RwV" userLabel="Bottom Tab"> + <rect key="frame" x="0.0" y="360" width="283" height="62"/> + <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000001" blue="0.620821277" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Bottom Tab"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomTabSegue" customModule="Demo" customModuleProvider="target" id="EaG-Ea-U3j"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CDi-Gu-bE2" userLabel="Centered"> + <rect key="frame" x="0.0" y="432" width="283" height="62"/> + <color key="backgroundColor" red="1" green="0.46653546191345963" blue="0.015686274510000042" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Centered"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesCenteredSegue" customModule="Demo" customModuleProvider="target" id="had-cE-9YN"/> + </connections> + </button> </subviews> </stackView> </subviews> - <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> <constraints> - <constraint firstItem="mGe-El-haJ" firstAttribute="top" secondItem="WeL-Zn-0tj" secondAttribute="bottom" constant="15" id="6TI-R1-eMQ"/> - <constraint firstItem="mGe-El-haJ" firstAttribute="leading" secondItem="YlT-hO-kIK" secondAttribute="leadingMargin" constant="15" id="LqT-Kn-3v7"/> - <constraint firstItem="LAn-az-eMU" firstAttribute="top" secondItem="mGe-El-haJ" secondAttribute="bottom" constant="15" id="jWn-cy-X7E"/> - <constraint firstAttribute="trailingMargin" secondItem="mGe-El-haJ" secondAttribute="trailing" constant="15" id="xEo-4G-PBe"/> + <constraint firstItem="mGe-El-haJ" firstAttribute="top" secondItem="WeL-Zn-0tj" secondAttribute="bottom" constant="40" id="6TI-R1-eMQ"/> + <constraint firstItem="mGe-El-haJ" firstAttribute="leading" secondItem="YlT-hO-kIK" secondAttribute="leadingMargin" constant="30" id="LqT-Kn-3v7"/> + <constraint firstItem="LAn-az-eMU" firstAttribute="top" secondItem="mGe-El-haJ" secondAttribute="bottom" constant="40" id="jWn-cy-X7E"/> + <constraint firstAttribute="trailingMargin" secondItem="mGe-El-haJ" secondAttribute="trailing" constant="30" id="xEo-4G-PBe"/> </constraints> </view> </viewController> @@ -1072,7 +931,7 @@ <objects> <navigationController id="dHK-y5-h16" sceneMemberID="viewController"> <tabBarItem key="tabBarItem" title="Item" id="lRD-YW-2WT"/> - <navigationItem key="navigationItem" id="kWv-kG-kDP"/> + <value key="contentSizeForViewInPopover" type="size" width="0.0" height="250"/> <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="eD6-og-rzJ"> <rect key="frame" x="0.0" y="0.0" width="375" height="44"/> <autoresizingMask key="autoresizingMask"/> @@ -1092,7 +951,7 @@ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="veg-5v-Pex"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> <sections> <tableViewSection id="CqX-XV-4eD"> <cells> @@ -1190,19 +1049,18 @@ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Nothing to see here." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2bv-DK-h4b"> - <rect key="frame" x="110.5" y="345" width="154.5" height="21"/> + <rect key="frame" x="109.5" y="345" width="156" height="21"/> <fontDescription key="fontDescription" type="system" pointSize="17"/> <nil key="textColor"/> <nil key="highlightedColor"/> </label> </subviews> - <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> <constraints> <constraint firstItem="2bv-DK-h4b" firstAttribute="centerX" secondItem="0Cn-7n-ODp" secondAttribute="centerX" id="1aC-Jw-Zyl"/> <constraint firstItem="2bv-DK-h4b" firstAttribute="centerY" secondItem="0Cn-7n-ODp" secondAttribute="centerYWithinMargins" id="93w-dz-NPV"/> </constraints> </view> - <navigationItem key="navigationItem" id="rP6-sY-fmZ"/> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="mU1-MA-hwk" userLabel="First Responder" sceneMemberID="firstResponder"/> </objects> @@ -1226,17 +1084,11 @@ <point key="canvasLocation" x="473" y="305"/> </scene> </scenes> - <inferredMetricsTieBreakers> - <segue reference="h5n-Vv-Q3y"/> - <segue reference="abD-oU-7qa"/> - </inferredMetricsTieBreakers> <resources> <image name="iconSwiftMessages" width="38" height="31"/> - <systemColor name="secondaryLabelColor"> - <color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> - </systemColor> - <systemColor name="systemBackgroundColor"> - <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - </systemColor> </resources> + <inferredMetricsTieBreakers> + <segue reference="h5n-Vv-Q3y"/> + <segue reference="EaG-Ea-U3j"/> + </inferredMetricsTieBreakers> </document> diff --git a/Demo/Demo/ViewControllersViewController.swift b/Demo/Demo/ViewControllersViewController.swift index 733dc07d..f3339ebc 100644 --- a/Demo/Demo/ViewControllersViewController.swift +++ b/Demo/Demo/ViewControllersViewController.swift @@ -19,31 +19,6 @@ class SwiftMessagesTopSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) configure(layout: .topMessage) - messageView.layout.size.height = .absolute(300) - } -} - -class SwiftMessagesBottomSegue: SwiftMessagesSegue { - override public init(identifier: String?, source: UIViewController, destination: UIViewController) { - super.init(identifier: identifier, source: source, destination: destination) - configure(layout: .bottomMessage) - messageView.layout.size.height = .absolute(300) - } -} - -class SwiftMessagesLeadingSegue: SwiftMessagesSegue { - override public init(identifier: String?, source: UIViewController, destination: UIViewController) { - super.init(identifier: identifier, source: source, destination: destination) - configure(layout: .leadingMessage) - messageView.layout.size.width = .absolute(300) - } -} - -class SwiftMessagesTrailingSegue: SwiftMessagesSegue { - override public init(identifier: String?, source: UIViewController, destination: UIViewController) { - super.init(identifier: identifier, source: source, destination: destination) - configure(layout: .trailingMessage) - messageView.layout.size.width = .absolute(300) } } @@ -51,31 +26,6 @@ class SwiftMessagesTopCardSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) configure(layout: .topCard) - messageView.layout.size.height = .absolute(300) - } -} - -class SwiftMessagesBottomCardSegue: SwiftMessagesSegue { - override public init(identifier: String?, source: UIViewController, destination: UIViewController) { - super.init(identifier: identifier, source: source, destination: destination) - configure(layout: .bottomCard) - messageView.layout.size.height = .absolute(300) - } -} - -class SwiftMessagesLeadingCardSegue: SwiftMessagesSegue { - override public init(identifier: String?, source: UIViewController, destination: UIViewController) { - super.init(identifier: identifier, source: source, destination: destination) - configure(layout: .leadingCard) - messageView.layout.size.width = .absolute(300) - } -} - -class SwiftMessagesTrailingCardSegue: SwiftMessagesSegue { - override public init(identifier: String?, source: UIViewController, destination: UIViewController) { - super.init(identifier: identifier, source: source, destination: destination) - configure(layout: .trailingCard) - messageView.layout.size.width = .absolute(300) } } @@ -83,31 +33,28 @@ class SwiftMessagesTopTabSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) configure(layout: .topTab) - messageView.layout.size.height = .absolute(300) } } -class SwiftMessagesBottomTabSegue: SwiftMessagesSegue { +class SwiftMessagesBottomSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) - configure(layout: .bottomTab) - messageView.layout.size.height = .absolute(300) + configure(layout: .bottomMessage) } } -class SwiftMessagesLeadingTabSegue: SwiftMessagesSegue { +class SwiftMessagesBottomCardSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) - configure(layout: .leadingTab) - messageView.layout.size.width = .absolute(300) + configure(layout: .bottomCard) + messageView.messageSize.width = .relative(0.75, from: .superview) } } -class SwiftMessagesTrailingTabSegue: SwiftMessagesSegue { +class SwiftMessagesBottomTabSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) - configure(layout: .trailingTab) - messageView.layout.size.width = .absolute(300) + configure(layout: .bottomTab) } } @@ -115,16 +62,5 @@ class SwiftMessagesCenteredSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) configure(layout: .centered) - messageView.layout.size.height = .absolute(300) - } -} - -class SwiftMessagesOffCenteredSegue: SwiftMessagesSegue { - override public init(identifier: String?, source: UIViewController, destination: UIViewController) { - super.init(identifier: identifier, source: source, destination: destination) - configure(layout: .centered) - messageView.layout.insets.top = .absolute(0, from: .safeArea) - messageView.layout.center.x = .relative(0.33, in: .safeArea) - messageView.layout.size.height = .absolute(300) } } diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 9c9e8ee8..823f37b4 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -51,7 +51,8 @@ 228DF5681FAD0806004F8A39 /* infoIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */; }; 228DF5691FAD0806004F8A39 /* successIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5481FAD0805004F8A39 /* successIconLight.png */; }; 228DF56A1FAD0806004F8A39 /* infoIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */; }; - 2290944825D88A05002E8111 /* Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290944725D88A05002E8111 /* Layout.swift */; }; + 2290944825D88A05002E8111 /* MessageSizeable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290944725D88A05002E8111 /* MessageSizeable.swift */; }; + 2290957825D9BC9F002E8111 /* MessageSizing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290957725D9BC9F002E8111 /* MessageSizing.swift */; }; 2290958125D9D407002E8111 /* UILayoutPriority+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */; }; 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; @@ -139,7 +140,8 @@ 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = infoIconSubtle.png; path = Resources/infoIconSubtle.png; sourceTree = "<group>"; }; 228DF5481FAD0805004F8A39 /* successIconLight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = successIconLight.png; path = Resources/successIconLight.png; sourceTree = "<group>"; }; 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; - 2290944725D88A05002E8111 /* Layout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Layout.swift; sourceTree = "<group>"; }; + 2290944725D88A05002E8111 /* MessageSizeable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSizeable.swift; sourceTree = "<group>"; }; + 2290957725D9BC9F002E8111 /* MessageSizing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSizing.swift; sourceTree = "<group>"; }; 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILayoutPriority+Extensions.swift"; sourceTree = "<group>"; }; 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; @@ -300,7 +302,8 @@ 8644955C1D4FAF7C0056EB2A /* WindowViewController.swift */, 867BED201D622793005212E3 /* BackgroundViewable.swift */, 864495551D4F7C390056EB2A /* Identifiable.swift */, - 2290944725D88A05002E8111 /* Layout.swift */, + 2290944725D88A05002E8111 /* MessageSizeable.swift */, + 2290957725D9BC9F002E8111 /* MessageSizing.swift */, 86AAF81D1D5549680031EE32 /* MarginAdjustable.swift */, 22E307FE1E74C5B100E35893 /* AccessibleMessage.swift */, 86AAF82A1D580DD70031EE32 /* Error.swift */, @@ -537,7 +540,7 @@ 86BBA8FC1D5E03F100FE8F16 /* MessageView.swift in Sources */, 86BBA9061D5E040C00FE8F16 /* Identifiable.swift in Sources */, 22F27951210CE25900273E7F /* CornerRoundingView.swift in Sources */, - 2290944825D88A05002E8111 /* Layout.swift in Sources */, + 2290944825D88A05002E8111 /* MessageSizeable.swift in Sources */, 86BBA9011D5E040600FE8F16 /* PassthroughWindow.swift in Sources */, 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */, 86BBA9031D5E040600FE8F16 /* UIViewController+Extensions.swift in Sources */, @@ -561,6 +564,7 @@ 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */, 86589D471D64B6E40041676C /* BaseView.swift in Sources */, 225304622290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift in Sources */, + 2290957825D9BC9F002E8111 /* MessageSizing.swift in Sources */, 86BBA9071D5E040C00FE8F16 /* MarginAdjustable.swift in Sources */, 867BED211D622793005212E3 /* BackgroundViewable.swift in Sources */, 2290958125D9D407002E8111 /* UILayoutPriority+Extensions.swift in Sources */, diff --git a/SwiftMessages/Animator.swift b/SwiftMessages/Animator.swift index 3897dd1f..29a4552f 100644 --- a/SwiftMessages/Animator.swift +++ b/SwiftMessages/Animator.swift @@ -45,13 +45,13 @@ public struct SafeZoneConflicts: OptionSet { public class AnimationContext { public let messageView: UIView - public let containerView: UIView & LayoutInstalling + public let containerView: UIView & MessageSizing public let safeZoneConflicts: SafeZoneConflicts public let interactiveHide: Bool internal init( messageView: UIView, - containerView: UIView & LayoutInstalling, + containerView: UIView & MessageSizing, safeZoneConflicts: SafeZoneConflicts, interactiveHide: Bool ) { diff --git a/SwiftMessages/BaseView.swift b/SwiftMessages/BaseView.swift index cdde9008..2ae86a45 100644 --- a/SwiftMessages/BaseView.swift +++ b/SwiftMessages/BaseView.swift @@ -14,7 +14,7 @@ import UIKit of the optional SwiftMessages protocols and provides some convenience functions and a configurable tap handler. Message views do not need to inherit from `BaseVew`. */ -open class BaseView: UIView, BackgroundViewable, MarginAdjustable, LayoutDefining { +open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeable { /* MARK: - IB outlets @@ -63,7 +63,6 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, LayoutDefinin */ /** - TODO SIZE - update documentation A convenience function for installing a content view as a subview of `backgroundView` and pinning the edges to `backgroundView` with the specified `insets`. @@ -83,7 +82,6 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, LayoutDefinin } /** - TODO SIZE - update documentation - insets removed A convenience function for installing a background view and pinning to the layout margins. This is useful for creating programatic layouts where the background view needs to be inset from the message view's edges (like a card-style layout). @@ -92,7 +90,7 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, LayoutDefinin assigned to the `backgroundView` property. - Parameter insets: The amount to inset the content view from the margins. Default is zero inset. */ - open func installBackgroundView(_ backgroundView: UIView) { + open func installBackgroundView(_ backgroundView: UIView, insets: UIEdgeInsets = UIEdgeInsets.zero) { backgroundView.translatesAutoresizingMaskIntoConstraints = false if backgroundView != self { backgroundView.removeFromSuperview() @@ -102,56 +100,64 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, LayoutDefinin NSLayoutConstraint.activate([ backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor) .with(priority: .belowMessageSizeable), - backgroundView.topAnchor.constraint(equalTo: topAnchor) - .with(priority: .belowMessageSizeable), - backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor) - .with(priority: .belowMessageSizeable), + backgroundView.topAnchor.constraint( + equalTo: layoutMarginsGuide.topAnchor, + constant: insets.top + ).with(priority: .belowMessageSizeable), + backgroundView.bottomAnchor.constraint( + equalTo: layoutMarginsGuide.bottomAnchor, + constant: -insets.bottom + ).with(priority: .belowMessageSizeable), backgroundView.heightAnchor.constraint(equalToConstant: 350) .with(priority: UILayoutPriority(rawValue: 200)), - backgroundView.leadingAnchor.constraint(equalTo: leadingAnchor) - .with(priority: .belowMessageSizeable), - backgroundView.trailingAnchor.constraint(equalTo: trailingAnchor) - .with(priority: .belowMessageSizeable), + backgroundView.leftAnchor.constraint( + equalTo: layoutMarginsGuide.leftAnchor, + constant: insets.left + ).with(priority: .belowMessageSizeable), + backgroundView.rightAnchor.constraint( + equalTo: layoutMarginsGuide.rightAnchor, + constant: -insets.right + ).with(priority: .belowMessageSizeable), ]) installTapRecognizer() } -// /** -// A convenience function for installing a background view and pinning to the horizontal -// layout margins and to the vertical edges. This is useful for creating programatic layouts where -// the background view needs to be inset from the message view's horizontal edges (like a tab-style layout). -// -// - Parameter backgroundView: The view to be installed as a subview and -// assigned to the `backgroundView` property. -// - Parameter insets: The amount to inset the content view from the horizontal margins and vertical edges. -// Default is zero inset. -// */ -// open func installBackgroundVerticalView(_ backgroundView: UIView, insets: UIEdgeInsets = UIEdgeInsets.zero) { -// backgroundView.translatesAutoresizingMaskIntoConstraints = false -// if backgroundView != self { -// backgroundView.removeFromSuperview() -// } -// addSubview(backgroundView) -// self.backgroundView = backgroundView -// NSLayoutConstraint.activate([ -// backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor) -// .with(priority: .belowMessageSizeable), -// backgroundView.topAnchor.constraint(equalTo: topAnchor, constant: insets.top) -// .with(priority: .required), -// backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -insets.bottom) -// .with(priority: .required), -// backgroundView.heightAnchor.constraint(equalToConstant: 350) -// .with(priority: UILayoutPriority(rawValue: 200)), -// backgroundView.leftAnchor.constraint( -// equalTo: layoutMarginsGuide.leftAnchor, constant: insets.left -// ).with(priority: .belowMessageSizeable), -// backgroundView.rightAnchor.constraint( -// equalTo: layoutMarginsGuide.rightAnchor, -// constant: -insets.right -// ).with(priority: .belowMessageSizeable), -// ]) -// installTapRecognizer() -// } + /** + A convenience function for installing a background view and pinning to the horizontal + layout margins and to the vertical edges. This is useful for creating programatic layouts where + the background view needs to be inset from the message view's horizontal edges (like a tab-style layout). + + - Parameter backgroundView: The view to be installed as a subview and + assigned to the `backgroundView` property. + - Parameter insets: The amount to inset the content view from the horizontal margins and vertical edges. + Default is zero inset. + */ + open func installBackgroundVerticalView(_ backgroundView: UIView, insets: UIEdgeInsets = UIEdgeInsets.zero) { + backgroundView.translatesAutoresizingMaskIntoConstraints = false + if backgroundView != self { + backgroundView.removeFromSuperview() + } + addSubview(backgroundView) + self.backgroundView = backgroundView + NSLayoutConstraint.activate([ + backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor) + .with(priority: .belowMessageSizeable), + backgroundView.topAnchor.constraint(equalTo: topAnchor, constant: insets.top) + .with(priority: .required), + backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -insets.bottom) + .with(priority: .required), + backgroundView.heightAnchor.constraint(equalToConstant: 350) + .with(priority: UILayoutPriority(rawValue: 200)), + backgroundView.leftAnchor.constraint( + equalTo: layoutMarginsGuide.leftAnchor, constant: insets.left + ).with(priority: .belowMessageSizeable), + backgroundView.rightAnchor.constraint( + equalTo: layoutMarginsGuide.rightAnchor, + constant: -insets.right + ).with(priority: .belowMessageSizeable), + ]) + installTapRecognizer() + } /* MARK: - Tap handler @@ -197,8 +203,11 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, LayoutDefinin // MARK: - MessageSizeable - /// Configure the view's layout - public var layout = Layout() + /// Configure the view's size + public var messageSize = MessageSize() + + /// Configure the view's insets from the container + public var messageInsets = MessageInsets() /* MARK: - MarginAdjustable diff --git a/SwiftMessages/CornerRoundingView.swift b/SwiftMessages/CornerRoundingView.swift index 7db484fb..398b731c 100644 --- a/SwiftMessages/CornerRoundingView.swift +++ b/SwiftMessages/CornerRoundingView.swift @@ -24,12 +24,12 @@ open class CornerRoundingView: UIView { /// rounded. For example, the layout in TabView.xib rounds the bottom corners /// when displayed from the top and the top corners when displayed from the bottom. /// When this property is `true`, the `roundedCorners` property will be overwritten - /// by relevant animators (e.g. `EdgeAnimation`). + /// by relevant animators (e.g. `TopBottomAnimation`). @IBInspectable open var roundsLeadingCorners: Bool = false /// Specifies which corners should be rounded. When `roundsLeadingCorners = true`, relevant - /// relevant animators (e.g. `EdgeAnimation`) will overwrite the value of this property. + /// relevant animators (e.g. `TopBottomAnimation`) will overwrite the value of this property. open var roundedCorners: UIRectCorner = [.allCorners] { didSet { updateMaskPath() diff --git a/SwiftMessages/Layout.swift b/SwiftMessages/Layout.swift deleted file mode 100644 index 4afcf7b7..00000000 --- a/SwiftMessages/Layout.swift +++ /dev/null @@ -1,91 +0,0 @@ -// -// BoundaryInsets.swift -// SwiftMessages -// -// Created by Timothy Moose on 2/13/21. -// Copyright © 2021 SwiftKick Mobile. All rights reserved. -// - -import UIKit - -public protocol LayoutDefining { - var layout: Layout { get } -} - -public protocol LayoutInstalling { - func install(layoutDefiningView: LayoutDefining & UIView) -} - -public struct Layout { - - public var size = Size() - public var insets = Insets() - public var center = Center() - public var min = Layout() - public var max = Layout() - - public enum Boundary { - case superview - case safeArea - case margin - } - - public struct Size { - - public enum Dimension { - case absolute(CGFloat) - case relative(CGFloat, to: Boundary) - } - - public var width: Dimension? - public var height: Dimension? - } - - public struct Insets { - - public enum Dimension { - case absolute(CGFloat, from: Boundary) - case relative(CGFloat, from: Boundary) - } - - public var top: Dimension? - public var bottom: Dimension? - public var leading: Dimension? - public var trailing: Dimension? - } - - public struct Center { - - public enum Dimension { - case absolute(CGFloat, in: Boundary) - case relative(CGFloat, in: Boundary) - } - - public var x: Dimension? - public var y: Dimension? - } - - public struct Layout { - public var size = Size() - public var insets = Insets() - public var center = Center() - } -} - -extension Layout.Insets.Dimension { - var boundary: Layout.Boundary { - switch self { - case .absolute(_, let boundary): return boundary - case .relative(_, let boundary): return boundary - } - } -} - -extension Layout.Center.Dimension { - var boundary: Layout.Boundary { - switch self { - case .absolute(_, let boundary): return boundary - case .relative(_, let boundary): return boundary - } - } -} diff --git a/SwiftMessages/MaskingView.swift b/SwiftMessages/MaskingView.swift index 81301994..889ac9de 100644 --- a/SwiftMessages/MaskingView.swift +++ b/SwiftMessages/MaskingView.swift @@ -24,13 +24,13 @@ import UIKit // .with(priority: UILayoutPriority(rawValue: 200)), // ] -class MaskingView: PassthroughView, LayoutInstalling { +class MaskingView: PassthroughView, MessageSizing { - func install(layoutDefiningView: UIView & LayoutDefining) { - self.layoutDefiningView?.removeFromSuperview() - self.layoutDefiningView = layoutDefiningView - layoutDefiningView.translatesAutoresizingMaskIntoConstraints = false - addSubview(layoutDefiningView) + func install(sizeableView: MessageSizeable & UIView) { + self.sizeableView?.removeFromSuperview() + self.sizeableView = sizeableView + sizeableView.translatesAutoresizingMaskIntoConstraints = false + addSubview(sizeableView) setNeedsUpdateConstraints() } @@ -96,7 +96,7 @@ class MaskingView: PassthroughView, LayoutInstalling { private var keyboardTrackingView: KeyboardTrackingView? private var cachedConstraints: [NSLayoutConstraint] = [] private let messageInsetsGuide = UILayoutGuide() - private var layoutDefiningView: (LayoutDefining & UIView)? + private var sizeableView: (MessageSizeable & UIView)? override func addSubview(_ view: UIView) { super.addSubview(view) @@ -110,35 +110,20 @@ class MaskingView: PassthroughView, LayoutInstalling { super.updateConstraints() NSLayoutConstraint.deactivate(cachedConstraints) cachedConstraints = [] - if let layoutDefiningView = layoutDefiningView { - let layout = layoutDefiningView.layout - add(insets: layout.insets, relation: .equal) - add(insets: layout.min.insets, relation: .min) - add(insets: layout.max.insets, relation: .max) - add(layoutDefiningView: layoutDefiningView) - } + if let top = sizeableView?.messageInsets.top { update(top: top) } + if let bottom = sizeableView?.messageInsets.bottom { update(bottom: bottom) } + if let leading = sizeableView?.messageInsets.leading { update(leading: leading) } + if let trailing = sizeableView?.messageInsets.trailing { update(trailing: trailing) } + if let sizeableView = sizeableView { update(sizeableView: sizeableView) } NSLayoutConstraint.activate(cachedConstraints) } - private enum ConstraintRelation { - case equal - case min - case max - } - - private func add(insets: Layout.Insets, relation: ConstraintRelation) { - if let top = insets.top { add(top: top, relation: relation) } - if let bottom = insets.bottom { add(bottom: bottom, relation: relation) } - if let leading = insets.leading { add(leading: leading, relation: relation) } - if let trailing = insets.trailing { add(trailing: trailing, relation: relation) } - } - - private func add(top: Layout.Insets.Dimension, relation: ConstraintRelation) { + private func update(top: MessageInsets.Dimension) { let length: CGFloat switch top { - case .absolute(let dimension, _): + case .absoluteMargin(let dimension, _): length = dimension - case .relative(let percentage, _): + case .relativeMargin(let percentage, _): length = bounds.height * percentage } let otherAnchor: NSLayoutYAxisAnchor @@ -152,20 +137,18 @@ class MaskingView: PassthroughView, LayoutInstalling { otherAnchor = layoutMarginsGuide.topAnchor } } - add( - anchor: messageInsetsGuide.topAnchor, - otherAnchor: otherAnchor, - constant: length, - relation: relation + cachedConstraints.append( + messageInsetsGuide.topAnchor.constraint(equalTo: otherAnchor, constant: length) + .with(priority: .messageInset) ) } - private func add(bottom: Layout.Insets.Dimension, relation: ConstraintRelation) { + private func update(bottom: MessageInsets.Dimension) { let length: CGFloat switch bottom { - case .absolute(let dimension, _): + case .absoluteMargin(let dimension, _): length = dimension - case .relative(let percentage, _): + case .relativeMargin(let percentage, _): length = bounds.height * percentage } let otherAnchor: NSLayoutYAxisAnchor @@ -179,20 +162,18 @@ class MaskingView: PassthroughView, LayoutInstalling { otherAnchor = layoutMarginsGuide.bottomAnchor } } - add( - anchor: otherAnchor, - otherAnchor: messageInsetsGuide.bottomAnchor, - constant: length, - relation: relation + cachedConstraints.append( + messageInsetsGuide.bottomAnchor.constraint(equalTo: otherAnchor, constant: -length) + .with(priority: .messageInset) ) } - private func add(leading: Layout.Insets.Dimension, relation: ConstraintRelation) { + private func update(leading: MessageInsets.Dimension) { let length: CGFloat switch leading { - case .absolute(let dimension, _): + case .absoluteMargin(let dimension, _): length = dimension - case .relative(let percentage, _): + case .relativeMargin(let percentage, _): length = bounds.width * percentage } let otherAnchor: NSLayoutXAxisAnchor @@ -206,20 +187,18 @@ class MaskingView: PassthroughView, LayoutInstalling { otherAnchor = layoutMarginsGuide.leadingAnchor } } - add( - anchor: messageInsetsGuide.leadingAnchor, - otherAnchor: otherAnchor, - constant: length, - relation: relation + cachedConstraints.append( + messageInsetsGuide.leadingAnchor.constraint(equalTo: otherAnchor, constant: length) + .with(priority: .messageInset) ) } - private func add(trailing: Layout.Insets.Dimension, relation: ConstraintRelation) { + private func update(trailing: MessageInsets.Dimension) { let length: CGFloat switch trailing { - case .absolute(let dimension, _): + case .absoluteMargin(let dimension, _): length = dimension - case .relative(let percentage, _): + case .relativeMargin(let percentage, _): length = bounds.width * percentage } let otherAnchor: NSLayoutXAxisAnchor @@ -233,193 +212,55 @@ class MaskingView: PassthroughView, LayoutInstalling { otherAnchor = layoutMarginsGuide.trailingAnchor } } - add( - anchor: otherAnchor, - otherAnchor: messageInsetsGuide.trailingAnchor, - constant: length, - relation: relation + cachedConstraints.append( + messageInsetsGuide.trailingAnchor.constraint(equalTo: otherAnchor, constant: -length) + .with(priority: .messageInset) ) } - private func add( - anchor: NSLayoutXAxisAnchor, - otherAnchor: NSLayoutXAxisAnchor, - constant: CGFloat, - relation: ConstraintRelation - ) { - let constraint: NSLayoutConstraint - switch relation { - case .equal: - constraint = anchor - .constraint(equalTo: otherAnchor, constant: constant) - .with(priority: .messageInsets) - case .min: - constraint = anchor - .constraint(greaterThanOrEqualTo: otherAnchor, constant: constant) - .with(priority: .messageInsetsBounds) - case .max: - constraint = anchor - .constraint(lessThanOrEqualTo: otherAnchor, constant: constant) - .with(priority: .messageInsetsBounds) - } - cachedConstraints.append(constraint) - } - - private func add( - anchor: NSLayoutYAxisAnchor, - otherAnchor: NSLayoutYAxisAnchor, - constant: CGFloat, - relation: ConstraintRelation - ) { - let constraint: NSLayoutConstraint - switch relation { - case .equal: - constraint = anchor - .constraint(equalTo: otherAnchor, constant: constant) - .with(priority: .messageInsets) - case .min: - constraint = anchor - .constraint(greaterThanOrEqualTo: otherAnchor, constant: constant) - .with(priority: .messageInsetsBounds) - case .max: - constraint = anchor - .constraint(lessThanOrEqualTo: otherAnchor, constant: constant) - .with(priority: .messageInsetsBounds) - } - cachedConstraints.append(constraint) - } - - private func add(layoutDefiningView view: LayoutDefining & UIView) { + private func update(sizeableView view: MessageSizeable & UIView) { cachedConstraints += [ messageInsetsGuide.topAnchor.constraint(equalTo: view.topAnchor), messageInsetsGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor), messageInsetsGuide.leadingAnchor.constraint(equalTo: view.leadingAnchor), messageInsetsGuide.trailingAnchor.constraint(equalTo: view.trailingAnchor), ] - add(layoutDefiningView: view, size: view.layout.size, relation: .equal) - add(layoutDefiningView: view, size: view.layout.min.size, relation: .min) - add(layoutDefiningView: view, size: view.layout.max.size, relation: .max) - add(layoutDefiningView: view, center: view.layout.center, relation: .equal) - add(layoutDefiningView: view, center: view.layout.min.center, relation: .min) - add(layoutDefiningView: view, center: view.layout.max.center, relation: .max) - } - - private func add( - layoutDefiningView view: LayoutDefining & UIView, - size: Layout.Size, - relation: ConstraintRelation - ) { - if let width = size.width { - let length = self.length(for: width) { $0.width } - let constraint: NSLayoutConstraint - switch relation { - case .equal: - constraint = view.widthAnchor.constraint(equalToConstant: length) + if let width = view.messageSize.width { + let length = self.length(for: width, extractor: { $0.width }) + cachedConstraints.append( + view.widthAnchor.constraint(equalToConstant: length) .with(priority: .messageSize) - case .min: - constraint = view.widthAnchor.constraint(greaterThanOrEqualToConstant: length) - .with(priority: .messageSizeBounds) - case .max: - constraint = view.widthAnchor.constraint(lessThanOrEqualToConstant: length) - .with(priority: .messageSizeBounds) - } - cachedConstraints.append(constraint) + ) } - if let height = size.height { - let length = self.length(for: height) { $0.height } - let constraint: NSLayoutConstraint - switch relation { - case .equal: - constraint = view.heightAnchor.constraint(equalToConstant: length) + if let height = view.messageSize.height { + let length = self.length(for: height, extractor: { $0.height }) + cachedConstraints.append( + view.heightAnchor.constraint(equalToConstant: length) .with(priority: .messageSize) - case .min: - constraint = view.heightAnchor.constraint(greaterThanOrEqualToConstant: length) - .with(priority: .messageSizeBounds) - case .max: - constraint = view.heightAnchor.constraint(lessThanOrEqualToConstant: length) - .with(priority: .messageSizeBounds) - } - cachedConstraints.append(constraint) - } - } - - - private func add( - layoutDefiningView view: LayoutDefining & UIView, - center: Layout.Center, - relation: ConstraintRelation - ) { - if let x = center.x { - let length = self.length(for: x) { ($0.minX, $0.maxX) } - let otherAnchor: NSLayoutXAxisAnchor - switch x.boundary { - case .superview: otherAnchor = leadingAnchor - case .margin: otherAnchor = layoutMarginsGuide.leadingAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = safeAreaLayoutGuide.leadingAnchor - } else { - otherAnchor = layoutMarginsGuide.leadingAnchor - } - } - let constraint: NSLayoutConstraint - switch relation { - case .equal: - constraint = view.centerXAnchor.constraint(equalTo: otherAnchor, constant: length) - .with(priority: .messageCenter) - case .min: - constraint = view.centerXAnchor.constraint( - greaterThanOrEqualTo: otherAnchor, - constant: length - ).with(priority: .messageSizeBounds) - case .max: - constraint = view.centerXAnchor.constraint( - lessThanOrEqualTo: otherAnchor, - constant: length - ).with(priority: .messageSizeBounds) - } - cachedConstraints.append(constraint) - } - if let y = center.y { - let length = self.length(for: y) { ($0.minY, $0.maxY) } - let otherAnchor: NSLayoutYAxisAnchor - switch y.boundary { - case .superview: otherAnchor = topAnchor - case .margin: otherAnchor = layoutMarginsGuide.topAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = safeAreaLayoutGuide.topAnchor - } else { - otherAnchor = layoutMarginsGuide.topAnchor - } - } - let constraint: NSLayoutConstraint - switch relation { - case .equal: - constraint = view.centerYAnchor.constraint(equalTo: otherAnchor, constant: length) - .with(priority: .messageCenter) - case .min: - constraint = view.centerYAnchor.constraint( - greaterThanOrEqualTo: otherAnchor, - constant: length - ).with(priority: .messageSizeBounds) - case .max: - constraint = view.centerYAnchor.constraint( - lessThanOrEqualTo: otherAnchor, - constant: length - ).with(priority: .messageSizeBounds) - } - cachedConstraints.append(constraint) + ) } } private func length( - for dimension: Layout.Size.Dimension, + for dimension: MessageSize.Dimension, extractor: (CGRect) -> CGFloat ) -> CGFloat { switch dimension { case .absolute(let dimension): return dimension + case .absoluteMargin(let margin, let boundary): + let insets: UIEdgeInsets + switch boundary { + case .superview: insets = .zero + case .margin: insets = layoutMargins + case .safeArea: + if #available(iOS 11.0, *) { + insets = safeAreaInsets + } else { + insets = layoutMargins + } + } + return extractor(bounds.inset(by: insets)) - margin * 2 case .relative(let percentage, let boundary): let insets: UIEdgeInsets switch boundary { @@ -435,30 +276,4 @@ class MaskingView: PassthroughView, LayoutInstalling { return extractor(bounds.inset(by: insets)) * percentage } } - - private func length( - for dimension: Layout.Center.Dimension, - extractor: (CGRect) -> (CGFloat, CGFloat) - ) -> CGFloat { - let insets: UIEdgeInsets - switch dimension.boundary { - case .superview: insets = .zero - case .margin: insets = layoutMargins - case .safeArea: - if #available(iOS 11.0, *) { - insets = safeAreaInsets - } else { - insets = layoutMargins - } - } - let insetBounds = bounds.inset(by: insets) - switch dimension { - case .absolute(let dimension, _): - let (min, _) = extractor(insetBounds) - return min + dimension - case .relative(let percentage, _): - let (min, max) = extractor(insetBounds) - return min + (max - min) * percentage - } - } } diff --git a/SwiftMessages/MessageSizeable.swift b/SwiftMessages/MessageSizeable.swift new file mode 100644 index 00000000..662f1839 --- /dev/null +++ b/SwiftMessages/MessageSizeable.swift @@ -0,0 +1,65 @@ +// +// BoundaryInsets.swift +// SwiftMessages +// +// Created by Timothy Moose on 2/13/21. +// Copyright © 2021 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +public protocol MessageSizeable { + var messageSize: MessageSize { get } + var messageInsets: MessageInsets { get } +} + +public enum MessageBoundary { + case superview + case safeArea + case margin +} + +/// Insets used for specifying view sizing options in terms of insets from the containing superview or safe area. +public struct MessageInsets { + + public enum Dimension { + + /// Dimension should maintain an absolute margin to the given container boundary. + case absoluteMargin(CGFloat, from: MessageBoundary) + + /// Dimension should maintain a relative margin to the given container boundary. + case relativeMargin(CGFloat, from: MessageBoundary) + } + + public var top: Dimension? + public var bottom: Dimension? + public var leading: Dimension? + public var trailing: Dimension? +} + +public struct MessageSize { + + public enum Dimension { + + /// Dimensions should be an absolute length + case absolute(CGFloat) + + /// Dimension should maintain an absolute length to the given container boundary. + case absoluteMargin(CGFloat, from: MessageBoundary) + + /// Dimension should maintain a relative margin to the given boundary. + case relative(CGFloat, from: MessageBoundary) + } + + public var width: Dimension? + public var height: Dimension? +} + +extension MessageInsets.Dimension { + var boundary: MessageBoundary { + switch self { + case .absoluteMargin(_, let boundary): return boundary + case .relativeMargin(_, let boundary): return boundary + } + } +} diff --git a/SwiftMessages/MessageSizing.swift b/SwiftMessages/MessageSizing.swift new file mode 100644 index 00000000..b4c47dd3 --- /dev/null +++ b/SwiftMessages/MessageSizing.swift @@ -0,0 +1,13 @@ +// +// MessageSizing.swift +// SwiftMessages +// +// Created by Timothy Moose on 2/14/21. +// Copyright © 2021 SwiftKick Mobile. All rights reserved. +// + +import Foundation + +public protocol MessageSizing { + func install(sizeableView: MessageSizeable & UIView) +} diff --git a/SwiftMessages/PhysicsAnimation.swift b/SwiftMessages/PhysicsAnimation.swift index 46f3d1ef..0fb976c5 100644 --- a/SwiftMessages/PhysicsAnimation.swift +++ b/SwiftMessages/PhysicsAnimation.swift @@ -70,41 +70,18 @@ public class PhysicsAnimation: NSObject, Animator { messageView = view containerView = container self.context = context - if let layoutDefiningView = view as? LayoutDefining & UIView { - container.install(layoutDefiningView: layoutDefiningView) - } else { - view.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(view) - } + view.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(view) switch placement { case .center: - view.centerYAnchor.constraint(equalTo: container.centerYAnchor) - .with(priority: UILayoutPriority(200)).isActive = true + view.centerYAnchor.constraint(equalTo: container.centerYAnchor).with(priority: UILayoutPriority(200)).isActive = true case .top: - view.topAnchor.constraint(equalTo: container.topAnchor) - .with(priority: UILayoutPriority(200)).isActive = true + view.topAnchor.constraint(equalTo: container.topAnchor).with(priority: UILayoutPriority(200)).isActive = true case .bottom: - view.bottomAnchor.constraint(equalTo: container.bottomAnchor) - .with(priority: UILayoutPriority(200)).isActive = true + view.bottomAnchor.constraint(equalTo: container.bottomAnchor).with(priority: UILayoutPriority(200)).isActive = true } - NSLayoutConstraint( - item: view, - attribute: .leading, - relatedBy: .equal, - toItem: container, - attribute: .leading, - multiplier: 1, - constant: 0 - ).with(priority: .belowMessageSizeable).isActive = true - NSLayoutConstraint( - item: view, - attribute: .trailing, - relatedBy: .equal, - toItem: container, - attribute: .trailing, - multiplier: 1, - constant: 0 - ).with(priority: .belowMessageSizeable).isActive = true + NSLayoutConstraint(item: view, attribute: .leading, relatedBy: .equal, toItem: container, attribute: .leading, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: container, attribute: .trailing, multiplier: 1, constant: 0).isActive = true // Important to layout now in order to get the right safe area insets container.layoutIfNeeded() adjustMargins() diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index 1ba7aa68..11243f54 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -105,9 +105,9 @@ class Presenter: NSObject { private static func animator(forPresentationStyle style: SwiftMessages.PresentationStyle, delegate: AnimationDelegate) -> Animator { switch style { case .top: - return EdgeAnimation(style: .top, delegate: delegate) + return TopBottomAnimation(style: .top, delegate: delegate) case .bottom: - return EdgeAnimation(style: .bottom, delegate: delegate) + return TopBottomAnimation(style: .bottom, delegate: delegate) case .center: return PhysicsAnimation(delegate: delegate) case .custom(let animator): diff --git a/SwiftMessages/SwiftMessagesSegue.swift b/SwiftMessages/SwiftMessagesSegue.swift index 8013ccd0..f20491bc 100644 --- a/SwiftMessages/SwiftMessagesSegue.swift +++ b/SwiftMessages/SwiftMessagesSegue.swift @@ -69,50 +69,60 @@ import UIKit open class SwiftMessagesSegue: UIStoryboardSegue { /** - Specifies one of the pre-defined layout configurations. + Specifies one of the pre-defined layouts, mirroring a subset of `MessageView.Layout`. */ public enum Layout { - /// The standard message view layout that slides down from the top edge. + /// The standard message view layout on top. case topMessage - /// The standard message view layout that slides up from the bottom edge. + /// The standard message view layout on bottom. case bottomMessage - /// The standard message view layout that slides in from the leading edge. - case leadingMessage - - /// The standard message view layout that slides in from the trailing edge. - case trailingMessage - - /// A floating card-style view with rounded corners that slides down from the top edge. + /// A floating card-style view with rounded corners on top case topCard - /// A floating card-style view with rounded corners that slides up from the bottom edge. - case bottomCard - - /// A floating card-style view with rounded corners that slides in from the leading edge. - case leadingCard - - /// A floating card-style view with rounded corners that slides in from the trailing edge. - case trailingCard - - /// A floating tab-style view with rounded leading corners that slides down from the top edge. + /// A floating tab-style view with rounded corners on bottom case topTab - /// A floating tab-style view with rounded leading corners that slides up from the bottom edge. - case bottomTab - - /// A floating tab-style view with rounded leading corners that slides in from the leading edge. - case leadingTab + /// A floating card-style view with rounded corners on bottom + case bottomCard - /// A floating tab-style view with rounded leading corners that slides in from the traling edge. - case trailingTab + /// A floating tab-style view with rounded corners on top + case bottomTab /// A floating card-style view typically used with `.center` presentation style. case centered } + /** + Specifies how the view controller's view is installed into the + containing message view. + */ + public enum Containment { + + /** + The view controller's view is installed for edge-to-edge display, extending into the safe areas + to the device edges. This is done by calling `messageView.installContentView(:insets:)` + See that method's documentation for additional details. + */ + case content + + /** + The view controller's view is installed for card-style layouts, inset from the margins + and avoiding safe areas. This is done by calling `messageView.installBackgroundView(:insets:)`. + See that method's documentation for details. + */ + case background + + /** + The view controller's view is installed for tab-style layouts, inset from the side margins, but extending + to the device edge on the top or bottom. This is done by calling `messageView.installBackgroundVerticalView(:insets:)`. + See that method's documentation for details. + */ + case backgroundVertical + } + /// The presentation style to use. See the SwiftMessages.PresentationStyle for details. public var presentationStyle: SwiftMessages.PresentationStyle { get { return messenger.defaultConfig.presentationStyle } @@ -164,11 +174,17 @@ open class SwiftMessagesSegue: UIStoryboardSegue { /** The view controller's view is embedded in `containerView` before being installed into - `messageView`. This view provides configurable continuous rounded corners (see the parent + `messageView`. This view provides configurable squircle (round) corners (see the parent class `CornerRoundingView`). */ public var containerView: CornerRoundingView = CornerRoundingView() + /** + Specifies how the view controller's view is installed into the + containing message view. See `Containment` for details. + */ + public var containment: Containment = .content + /** Supply an instance of `KeyboardTrackingView` to have the message view avoid the keyboard. */ @@ -212,130 +228,57 @@ extension SwiftMessagesSegue { /// A convenience method for configuring some pre-defined layouts that mirror a subset of `MessageView.Layout`. public func configure(layout: Layout) { messageView.bounceAnimationOffset = 0 + containment = .content containerView.cornerRadius = 0 containerView.roundsLeadingCorners = false messageView.configureDropShadow() switch layout { case .topMessage: -// TODO SIZE are these layout margin settings still relevant? -// messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) -// messageView.collapseLayoutMarginAdditions = false - let animation = EdgeAnimation(style: .top) + messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) + messageView.collapseLayoutMarginAdditions = false + let animation = TopBottomAnimation(style: .top) animation.springDamping = 1 presentationStyle = .custom(animator: animation) case .bottomMessage: -// messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) -// messageView.collapseLayoutMarginAdditions = false - let animation = EdgeAnimation(style: .bottom) - animation.springDamping = 1 - presentationStyle = .custom(animator: animation) - case .leadingMessage: -// messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) -// messageView.collapseLayoutMarginAdditions = false - let animation = EdgeAnimation(style: .leading) - animation.springDamping = 1 - presentationStyle = .custom(animator: animation) - case .trailingMessage: -// messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) -// messageView.collapseLayoutMarginAdditions = false - let animation = EdgeAnimation(style: .trailing) + messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) + messageView.collapseLayoutMarginAdditions = false + let animation = TopBottomAnimation(style: .bottom) animation.springDamping = 1 presentationStyle = .custom(animator: animation) case .topCard: - messageView.layout.insets.top = .absolute(0, from: .safeArea) - messageView.layout.insets.leading = .absolute(0, from: .safeArea) - messageView.layout.insets.trailing = .absolute(0, from: .safeArea) - messageView.layout.min.insets.top = .absolute(10, from: .superview) - messageView.layout.min.insets.leading = .absolute(10, from: .superview) - messageView.layout.min.insets.trailing = .absolute(10, from: .superview) - messageView.layout.min.insets.bottom = .absolute(10, from: .safeArea) + containment = .background + messageView.layoutMarginAdditions = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) + messageView.collapseLayoutMarginAdditions = true containerView.cornerRadius = 15 presentationStyle = .top case .bottomCard: - messageView.layout.insets.bottom = .absolute(0, from: .safeArea) - messageView.layout.insets.leading = .absolute(0, from: .safeArea) - messageView.layout.insets.trailing = .absolute(0, from: .safeArea) - messageView.layout.min.insets.bottom = .absolute(10, from: .superview) - messageView.layout.min.insets.leading = .absolute(10, from: .superview) - messageView.layout.min.insets.trailing = .absolute(10, from: .superview) - messageView.layout.min.insets.top = .absolute(10, from: .safeArea) + containment = .background + messageView.layoutMarginAdditions = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) + messageView.collapseLayoutMarginAdditions = true containerView.cornerRadius = 15 presentationStyle = .bottom - case .leadingCard: - messageView.layout.insets.leading = .absolute(0, from: .safeArea) - messageView.layout.insets.top = .absolute(0, from: .safeArea) - messageView.layout.insets.bottom = .absolute(0, from: .safeArea) - messageView.layout.min.insets.leading = .absolute(10, from: .superview) - messageView.layout.min.insets.top = .absolute(10, from: .superview) - messageView.layout.min.insets.bottom = .absolute(10, from: .superview) - messageView.layout.min.insets.trailing = .absolute(10, from: .safeArea) - containerView.cornerRadius = 15 - let animation = EdgeAnimation(style: .leading) - presentationStyle = .custom(animator: animation) - case .trailingCard: - messageView.layout.insets.trailing = .absolute(0, from: .safeArea) - messageView.layout.insets.top = .absolute(0, from: .safeArea) - messageView.layout.insets.bottom = .absolute(0, from: .safeArea) - messageView.layout.min.insets.trailing = .absolute(10, from: .superview) - messageView.layout.min.insets.top = .absolute(10, from: .superview) - messageView.layout.min.insets.bottom = .absolute(10, from: .superview) - messageView.layout.min.insets.leading = .absolute(10, from: .safeArea) - containerView.cornerRadius = 15 - let animation = EdgeAnimation(style: .trailing) - presentationStyle = .custom(animator: animation) case .topTab: - messageView.layout.insets.top = .absolute(0, from: .superview) - messageView.layout.insets.leading = .absolute(0, from: .safeArea) - messageView.layout.insets.trailing = .absolute(0, from: .safeArea) - messageView.layout.min.insets.leading = .absolute(10, from: .superview) - messageView.layout.min.insets.trailing = .absolute(10, from: .superview) - messageView.layout.min.insets.bottom = .absolute(10, from: .safeArea) + containment = .backgroundVertical + messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 10, bottom: 20, right: 10) + messageView.collapseLayoutMarginAdditions = true containerView.cornerRadius = 15 containerView.roundsLeadingCorners = true - let animation = EdgeAnimation(style: .top) + let animation = TopBottomAnimation(style: .top) animation.springDamping = 1 presentationStyle = .custom(animator: animation) case .bottomTab: - messageView.layout.insets.bottom = .absolute(0, from: .superview) - messageView.layout.insets.leading = .absolute(0, from: .safeArea) - messageView.layout.insets.trailing = .absolute(0, from: .safeArea) - messageView.layout.min.insets.leading = .absolute(10, from: .superview) - messageView.layout.min.insets.trailing = .absolute(10, from: .superview) - messageView.layout.min.insets.top = .absolute(10, from: .safeArea) + containment = .backgroundVertical + messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 10, bottom: 20, right: 10) + messageView.collapseLayoutMarginAdditions = true containerView.cornerRadius = 15 containerView.roundsLeadingCorners = true - let animation = EdgeAnimation(style: .bottom) - animation.springDamping = 1 - presentationStyle = .custom(animator: animation) - case .leadingTab: - messageView.layout.insets.leading = .absolute(0, from: .superview) - messageView.layout.insets.top = .absolute(0, from: .safeArea) - messageView.layout.insets.bottom = .absolute(0, from: .safeArea) - messageView.layout.min.insets.top = .absolute(10, from: .superview) - messageView.layout.min.insets.bottom = .absolute(10, from: .superview) - messageView.layout.min.insets.trailing = .absolute(10, from: .safeArea) - containerView.cornerRadius = 15 - containerView.roundsLeadingCorners = true - let animation = EdgeAnimation(style: .leading) - animation.springDamping = 1 - presentationStyle = .custom(animator: animation) - case .trailingTab: - messageView.layout.insets.trailing = .absolute(0, from: .superview) - messageView.layout.insets.top = .absolute(0, from: .safeArea) - messageView.layout.insets.bottom = .absolute(0, from: .safeArea) - messageView.layout.min.insets.top = .absolute(10, from: .superview) - messageView.layout.min.insets.bottom = .absolute(10, from: .superview) - messageView.layout.min.insets.leading = .absolute(10, from: .safeArea) - containerView.cornerRadius = 15 - containerView.roundsLeadingCorners = true - let animation = EdgeAnimation(style: .trailing) + let animation = TopBottomAnimation(style: .bottom) animation.springDamping = 1 presentationStyle = .custom(animator: animation) case .centered: - messageView.layout.min.insets.top = .absolute(10, from: .safeArea) - messageView.layout.min.insets.bottom = .absolute(10, from: .safeArea) - messageView.layout.min.insets.leading = .absolute(10, from: .safeArea) - messageView.layout.min.insets.trailing = .absolute(10, from: .safeArea) + containment = .background + messageView.layoutMarginAdditions = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) + messageView.collapseLayoutMarginAdditions = true containerView.cornerRadius = 15 presentationStyle = .center } @@ -400,12 +343,21 @@ extension SwiftMessagesSegue { } completeTransition = transitionContext.completeTransition let transitionContainer = transitionContext.containerView - // Install the background and content views - do { + toView.translatesAutoresizingMaskIntoConstraints = false + segue.containerView.addSubview(toView) + segue.containerView.topAnchor.constraint(equalTo: toView.topAnchor).isActive = true + segue.containerView.bottomAnchor.constraint(equalTo: toView.bottomAnchor).isActive = true + segue.containerView.leadingAnchor.constraint(equalTo: toView.leadingAnchor).isActive = true + segue.containerView.trailingAnchor.constraint(equalTo: toView.trailingAnchor).isActive = true + // Install the `toView` into the message view. + switch segue.containment { + case .content: + segue.messageView.installContentView(segue.containerView) + case .background: segue.messageView.installBackgroundView(segue.containerView) - segue.messageView.installContentView(toView) + case .backgroundVertical: + segue.messageView.installBackgroundVerticalView(segue.containerView) } - let toVC = transitionContext.viewController(forKey: .to) // Nav controller automatically includes height of nav bar in, diff --git a/SwiftMessages/TopBottomAnimation.swift b/SwiftMessages/TopBottomAnimation.swift index f8afc781..0a91fc3f 100644 --- a/SwiftMessages/TopBottomAnimation.swift +++ b/SwiftMessages/TopBottomAnimation.swift @@ -8,22 +8,19 @@ import UIKit -@available(*, deprecated, message: "Class renamed to `EdgeAnimation` to reflect new ability to do leading and trailing animations.") -public typealias TopBottomAnimation = EdgeAnimation - -public class EdgeAnimation: NSObject, Animator { +public class TopBottomAnimation: NSObject, Animator { public enum Style { case top case bottom - case leading - case trailing } public weak var delegate: AnimationDelegate? public let style: Style + open var heightDimension: Dimension? + open var showDuration: TimeInterval = 0.4 open var hideDuration: TimeInterval = 0.2 @@ -71,10 +68,6 @@ public class EdgeAnimation: NSObject, Animator { view.transform = CGAffineTransform(translationX: 0, y: -view.frame.height) case .bottom: view.transform = CGAffineTransform(translationX: 0, y: view.frame.maxY + view.frame.height) - case .leading: // TODO SIZE do proper leading and trailing - view.transform = CGAffineTransform(translationX: -view.frame.width, y: 0) - case .trailing: - view.transform = CGAffineTransform(translationX: view.frame.maxX + view.frame.width, y: 0) } }, completion: { completed in #if SWIFTMESSAGES_APP_EXTENSIONS @@ -95,66 +88,41 @@ public class EdgeAnimation: NSObject, Animator { if let adjustable = context.messageView as? MarginAdjustable { bounceOffset = adjustable.bounceAnimationOffset } - if let layoutDefiningView = view as? LayoutDefining & UIView { - container.install(layoutDefiningView: layoutDefiningView) + if let sizeableView = view as? MessageSizeable & UIView { + container.install(sizeableView: sizeableView) } else { view.translatesAutoresizingMaskIntoConstraints = false container.addSubview(view) } // Horizontal constraints do { + view.leadingAnchor.constraint(equalTo: container.leadingAnchor) + .with(priority: .belowMessageSizeable - 1) + .isActive = true + view.centerXAnchor.constraint(equalTo: container.centerXAnchor) + .with(priority: .belowMessageSizeable) + .isActive = true } switch style { case .top: - NSLayoutConstraint.activate([ - view.leadingAnchor.constraint(equalTo: container.leadingAnchor) - .with(priority: .belowMessageSizeable - 1), - view.centerXAnchor.constraint(equalTo: container.centerXAnchor) - .with(priority: .belowMessageSizeable), - view.topAnchor.constraint(equalTo: container.topAnchor, constant: -bounceOffset) - .with(priority: .belowMessageSizeable) - ]) + view.topAnchor.constraint(equalTo: container.topAnchor, constant: -bounceOffset) + .with(priority: .belowMessageSizeable) + .isActive = true case .bottom: - NSLayoutConstraint.activate([ - view.leadingAnchor.constraint(equalTo: container.leadingAnchor) - .with(priority: .belowMessageSizeable - 1), - view.centerXAnchor.constraint(equalTo: container.centerXAnchor) - .with(priority: .belowMessageSizeable), - view.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: bounceOffset) - .with(priority: .belowMessageSizeable) - ]) - case .leading: - NSLayoutConstraint.activate([ - view.topAnchor.constraint(equalTo: container.topAnchor) - .with(priority: .belowMessageSizeable - 1), - view.centerYAnchor.constraint(equalTo: container.centerYAnchor) - .with(priority: .belowMessageSizeable), - view.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: -bounceOffset) - .with(priority: .belowMessageSizeable) - ]) - case .trailing: - NSLayoutConstraint.activate([ - view.topAnchor.constraint(equalTo: container.topAnchor) - .with(priority: .belowMessageSizeable - 1), - view.centerYAnchor.constraint(equalTo: container.centerYAnchor) - .with(priority: .belowMessageSizeable), - view.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: bounceOffset) - .with(priority: .belowMessageSizeable) - ]) + view.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: bounceOffset) + .with(priority: .belowMessageSizeable) + .isActive = true } // Important to layout now in order to get the right safe area insets container.layoutIfNeeded() adjustMargins() container.layoutIfNeeded() + let animationDistance = view.frame.height switch style { case .top: - view.transform = CGAffineTransform(translationX: 0, y: -view.frame.height) + view.transform = CGAffineTransform(translationX: 0, y: -animationDistance) case .bottom: - view.transform = CGAffineTransform(translationX: 0, y: view.frame.height) - case .leading: - view.transform = CGAffineTransform(translationX: -view.frame.width, y: 0) - case .trailing: - view.transform = CGAffineTransform(translationX: view.frame.width, y: 0) + view.transform = CGAffineTransform(translationX: 0, y: animationDistance) } if context.interactiveHide { if let view = view as? BackgroundViewable { @@ -171,10 +139,6 @@ public class EdgeAnimation: NSObject, Animator { cornerRoundingView.roundedCorners = [.bottomLeft, .bottomRight] case .bottom: cornerRoundingView.roundedCorners = [.topLeft, .topRight] - case .leading: - cornerRoundingView.roundedCorners = [.topRight, .bottomRight] - case .trailing: - cornerRoundingView.roundedCorners = [.topLeft, .bottomLeft] } } } @@ -192,10 +156,6 @@ public class EdgeAnimation: NSObject, Animator { layoutMargins.top += bounceOffset case .bottom: layoutMargins.bottom += bounceOffset - case .leading: - layoutMargins.left += bounceOffset - case .trailing: - layoutMargins.right += bounceOffset } adjustable.layoutMargins = layoutMargins } @@ -231,39 +191,21 @@ public class EdgeAnimation: NSObject, Animator { fileprivate var rubberBanding = false fileprivate var closeSpeed: CGFloat = 0.0 fileprivate var closePercent: CGFloat = 0.0 - fileprivate var panTranslation: CGFloat = 0.0 + fileprivate var panTranslationY: CGFloat = 0.0 @objc func pan(_ pan: UIPanGestureRecognizer) { switch pan.state { case .changed: guard let view = messageView else { return } - let length: CGFloat - switch style { - case .top, .bottom: - length = view.bounds.height - bounceOffset - case .leading, .trailing: - length = view.bounds.width - bounceOffset - } - if length <= 0 { return } + let height = view.bounds.height - bounceOffset + if height <= 0 { return } var velocity = pan.velocity(in: view) var translation = pan.translation(in: view) - switch style { - case .top: + if case .top = style { velocity.y *= -1.0 translation.y *= -1.0 - case .leading: - velocity.x *= -1.0 - translation.x *= -1.0 - case .bottom, .trailing: - break - } - var translationAmount: CGFloat - switch style { - case .top, .bottom: - translationAmount = translation.y >= 0 ? translation.y : -pow(abs(translation.y), 0.7) - case .leading, .trailing: - translationAmount = translation.x >= 0 ? translation.x : -pow(abs(translation.x), 0.7) } + var translationAmount = translation.y >= 0 ? translation.y : -pow(abs(translation.y), 0.7) if !closing { // Turn on rubber banding if background view is inset from message view. if let background = (messageView as? BackgroundViewable)?.backgroundView, background != view { @@ -272,10 +214,6 @@ public class EdgeAnimation: NSObject, Animator { rubberBanding = background.frame.minY > 0 case .bottom: rubberBanding = background.frame.maxY < view.bounds.height - case .leading: - rubberBanding = background.frame.minX > 0 - case .trailing: - rubberBanding = background.frame.maxX < view.bounds.width } } if !rubberBanding && translationAmount < 0 { return } @@ -288,30 +226,19 @@ public class EdgeAnimation: NSObject, Animator { view.transform = CGAffineTransform(translationX: 0, y: -translationAmount) case .bottom: view.transform = CGAffineTransform(translationX: 0, y: translationAmount) - case .leading: - view.transform = CGAffineTransform(translationX: -translationAmount, y: 0) - case .trailing: - view.transform = CGAffineTransform(translationX: translationAmount, y: 0) - } - switch style { - case .top, .bottom: - closeSpeed = velocity.y - closePercent = translation.y / length - panTranslation = translation.y - case .leading, .trailing: - closeSpeed = velocity.x - closePercent = translation.x / length - panTranslation = translation.x } + closeSpeed = velocity.y + closePercent = translation.y / height + panTranslationY = translation.y case .ended, .cancelled: - if closeSpeed > closeSpeedThreshold || closePercent > closePercentThreshold || panTranslation > closeAbsoluteThreshold { + if closeSpeed > closeSpeedThreshold || closePercent > closePercentThreshold || panTranslationY > closeAbsoluteThreshold { delegate?.hide(animator: self) } else { closing = false rubberBanding = false closeSpeed = 0.0 closePercent = 0.0 - panTranslation = 0.0 + panTranslationY = 0.0 showAnimation(completion: { (completed) in self.delegate?.panEnded(animator: self) }) diff --git a/SwiftMessages/UILayoutPriority+Extensions.swift b/SwiftMessages/UILayoutPriority+Extensions.swift index ae6dc07e..1fd3ab88 100644 --- a/SwiftMessages/UILayoutPriority+Extensions.swift +++ b/SwiftMessages/UILayoutPriority+Extensions.swift @@ -9,18 +9,10 @@ import UIKit /// The priority used for `MessageSizeable` constraints -extension UILayoutPriority { - /// A constraint priority higher than those used for `MessageSizeable` - public static let aboveMessageSizeable: UILayoutPriority = messageInsetsBounds + 1 - - /// A constraint priority lower than those used for `MessageSizeable` - public static let belowMessageSizeable: UILayoutPriority = messageCenter - 1 - - static let messageCenter: UILayoutPriority = UILayoutPriority(900) - static let messageSize: UILayoutPriority = UILayoutPriority(901) - static let messageInsets: UILayoutPriority = UILayoutPriority(902) - static let messageCenterBounds: UILayoutPriority = UILayoutPriority(903) - static let messageSizeBounds: UILayoutPriority = UILayoutPriority(904) - static let messageInsetsBounds: UILayoutPriority = UILayoutPriority(905) +public extension UILayoutPriority { + static let aboveMessageSizeable: UILayoutPriority = messageInset + 1 + static let belowMessageSizeable: UILayoutPriority = messageSize - 1 + static let messageSize: UILayoutPriority = UILayoutPriority(900) + static let messageInset: UILayoutPriority = UILayoutPriority(901) } diff --git a/SwiftMessages/UIViewController+Extensions.swift b/SwiftMessages/UIViewController+Extensions.swift index 6cedc0d5..7fbd4dd1 100644 --- a/SwiftMessages/UIViewController+Extensions.swift +++ b/SwiftMessages/UIViewController+Extensions.swift @@ -87,14 +87,14 @@ extension UIViewController { } extension SwiftMessages.PresentationStyle { - /// A temporary workaround to allow custom presentation contexts using `EdgeAnimation` + /// A temporary workaround to allow custom presentation contexts using `TopBottomAnimation` /// to display properly behind bars. THe long term solution is to refactor all of the /// presentation context logic to work with safe area insets. - var topBottomStyle: EdgeAnimation.Style? { + var topBottomStyle: TopBottomAnimation.Style? { switch self { case .top: return .top case .bottom: return .bottom - case .custom(let animator): return (animator as? EdgeAnimation)?.style + case .custom(let animator): return (animator as? TopBottomAnimation)?.style case .center: return nil } } From 616353c33a8d2a0ce241b3f1b4f43e9172328059 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 10 Apr 2021 16:33:13 -0500 Subject: [PATCH 34/77] Revert "Add sizing options" This reverts commit 5b5973b5249a7228fc798ebe72f983a27517adb4. # Conflicts: # SwiftMessages.xcodeproj/project.pbxproj --- Demo/Demo/ViewControllersViewController.swift | 1 - SwiftMessages.xcodeproj/project.pbxproj | 17 +- SwiftMessages/Animator.swift | 4 +- SwiftMessages/BaseView.swift | 107 +++++---- SwiftMessages/BoundaryInsets.swift | 41 ++++ SwiftMessages/MaskingView.swift | 213 +----------------- SwiftMessages/MessageSizeable.swift | 65 ------ SwiftMessages/MessageSizing.swift | 13 -- SwiftMessages/Resources/CardView.xib | 25 +- SwiftMessages/Resources/CenteredView.xib | 27 ++- SwiftMessages/Resources/TabView.xib | 25 +- SwiftMessages/SwiftMessagesSegue.swift | 8 +- SwiftMessages/TopBottomAnimation.swift | 104 +++++++-- .../UILayoutPriority+Extensions.swift | 18 -- 14 files changed, 263 insertions(+), 405 deletions(-) create mode 100644 SwiftMessages/BoundaryInsets.swift delete mode 100644 SwiftMessages/MessageSizeable.swift delete mode 100644 SwiftMessages/MessageSizing.swift delete mode 100644 SwiftMessages/UILayoutPriority+Extensions.swift diff --git a/Demo/Demo/ViewControllersViewController.swift b/Demo/Demo/ViewControllersViewController.swift index f3339ebc..6fb14eeb 100644 --- a/Demo/Demo/ViewControllersViewController.swift +++ b/Demo/Demo/ViewControllersViewController.swift @@ -47,7 +47,6 @@ class SwiftMessagesBottomCardSegue: SwiftMessagesSegue { override public init(identifier: String?, source: UIViewController, destination: UIViewController) { super.init(identifier: identifier, source: source, destination: destination) configure(layout: .bottomCard) - messageView.messageSize.width = .relative(0.75, from: .superview) } } diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 823f37b4..f5296fde 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -51,9 +51,7 @@ 228DF5681FAD0806004F8A39 /* infoIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */; }; 228DF5691FAD0806004F8A39 /* successIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5481FAD0805004F8A39 /* successIconLight.png */; }; 228DF56A1FAD0806004F8A39 /* infoIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */; }; - 2290944825D88A05002E8111 /* MessageSizeable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290944725D88A05002E8111 /* MessageSizeable.swift */; }; - 2290957825D9BC9F002E8111 /* MessageSizing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290957725D9BC9F002E8111 /* MessageSizing.swift */; }; - 2290958125D9D407002E8111 /* UILayoutPriority+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */; }; + 2290944825D88A05002E8111 /* BoundaryInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290944725D88A05002E8111 /* BoundaryInsets.swift */; }; 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */; }; @@ -140,9 +138,7 @@ 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = infoIconSubtle.png; path = Resources/infoIconSubtle.png; sourceTree = "<group>"; }; 228DF5481FAD0805004F8A39 /* successIconLight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = successIconLight.png; path = Resources/successIconLight.png; sourceTree = "<group>"; }; 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; - 2290944725D88A05002E8111 /* MessageSizeable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSizeable.swift; sourceTree = "<group>"; }; - 2290957725D9BC9F002E8111 /* MessageSizing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSizing.swift; sourceTree = "<group>"; }; - 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILayoutPriority+Extensions.swift"; sourceTree = "<group>"; }; + 2290944725D88A05002E8111 /* BoundaryInsets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoundaryInsets.swift; sourceTree = "<group>"; }; 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = "<group>"; }; @@ -215,8 +211,6 @@ children = ( 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */, 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */, - 2290958025D9D407002E8111 /* UILayoutPriority+Extensions.swift */, - 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */, ); name = Extensions; sourceTree = "<group>"; @@ -302,12 +296,11 @@ 8644955C1D4FAF7C0056EB2A /* WindowViewController.swift */, 867BED201D622793005212E3 /* BackgroundViewable.swift */, 864495551D4F7C390056EB2A /* Identifiable.swift */, - 2290944725D88A05002E8111 /* MessageSizeable.swift */, - 2290957725D9BC9F002E8111 /* MessageSizing.swift */, 86AAF81D1D5549680031EE32 /* MarginAdjustable.swift */, 22E307FE1E74C5B100E35893 /* AccessibleMessage.swift */, 86AAF82A1D580DD70031EE32 /* Error.swift */, 2298C2061EE480D000E2DDC1 /* Animator.swift */, + 2290944725D88A05002E8111 /* BoundaryInsets.swift */, 2298C2041EE47DC900E2DDC1 /* Weak.swift */, 22F27950210CE25900273E7F /* CornerRoundingView.swift */, 225304652293000C00A03ACF /* KeyboardTrackingView.swift */, @@ -540,7 +533,7 @@ 86BBA8FC1D5E03F100FE8F16 /* MessageView.swift in Sources */, 86BBA9061D5E040C00FE8F16 /* Identifiable.swift in Sources */, 22F27951210CE25900273E7F /* CornerRoundingView.swift in Sources */, - 2290944825D88A05002E8111 /* MessageSizeable.swift in Sources */, + 2290944825D88A05002E8111 /* BoundaryInsets.swift in Sources */, 86BBA9011D5E040600FE8F16 /* PassthroughWindow.swift in Sources */, 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */, 86BBA9031D5E040600FE8F16 /* UIViewController+Extensions.swift in Sources */, @@ -564,10 +557,8 @@ 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */, 86589D471D64B6E40041676C /* BaseView.swift in Sources */, 225304622290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift in Sources */, - 2290957825D9BC9F002E8111 /* MessageSizing.swift in Sources */, 86BBA9071D5E040C00FE8F16 /* MarginAdjustable.swift in Sources */, 867BED211D622793005212E3 /* BackgroundViewable.swift in Sources */, - 2290958125D9D407002E8111 /* UILayoutPriority+Extensions.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/SwiftMessages/Animator.swift b/SwiftMessages/Animator.swift index 29a4552f..b95bcaf9 100644 --- a/SwiftMessages/Animator.swift +++ b/SwiftMessages/Animator.swift @@ -45,13 +45,13 @@ public struct SafeZoneConflicts: OptionSet { public class AnimationContext { public let messageView: UIView - public let containerView: UIView & MessageSizing + public let containerView: UIView public let safeZoneConflicts: SafeZoneConflicts public let interactiveHide: Bool internal init( messageView: UIView, - containerView: UIView & MessageSizing, + containerView: UIView, safeZoneConflicts: SafeZoneConflicts, interactiveHide: Bool ) { diff --git a/SwiftMessages/BaseView.swift b/SwiftMessages/BaseView.swift index 2ae86a45..93c9df96 100644 --- a/SwiftMessages/BaseView.swift +++ b/SwiftMessages/BaseView.swift @@ -14,7 +14,7 @@ import UIKit of the optional SwiftMessages protocols and provides some convenience functions and a configurable tap handler. Message views do not need to inherit from `BaseVew`. */ -open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeable { +open class BaseView: UIView, BackgroundViewable, MarginAdjustable, HasBoundaryInsets { /* MARK: - IB outlets @@ -97,28 +97,20 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeab } addSubview(backgroundView) self.backgroundView = backgroundView - NSLayoutConstraint.activate([ - backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor) - .with(priority: .belowMessageSizeable), - backgroundView.topAnchor.constraint( - equalTo: layoutMarginsGuide.topAnchor, - constant: insets.top - ).with(priority: .belowMessageSizeable), - backgroundView.bottomAnchor.constraint( - equalTo: layoutMarginsGuide.bottomAnchor, - constant: -insets.bottom - ).with(priority: .belowMessageSizeable), - backgroundView.heightAnchor.constraint(equalToConstant: 350) - .with(priority: UILayoutPriority(rawValue: 200)), - backgroundView.leftAnchor.constraint( - equalTo: layoutMarginsGuide.leftAnchor, - constant: insets.left - ).with(priority: .belowMessageSizeable), - backgroundView.rightAnchor.constraint( - equalTo: layoutMarginsGuide.rightAnchor, - constant: -insets.right - ).with(priority: .belowMessageSizeable), - ]) + backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor).with(priority: UILayoutPriority(rawValue: 950)).isActive = true + backgroundView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: insets.top).with(priority: UILayoutPriority(rawValue: 900)).isActive = true + backgroundView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor, constant: -insets.bottom).with(priority: UILayoutPriority(rawValue: 900)).isActive = true + backgroundView.heightAnchor.constraint(equalToConstant: 350).with(priority: UILayoutPriority(rawValue: 200)).isActive = true + layoutConstraints = [ + backgroundView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: insets.left).with(priority: UILayoutPriority(rawValue: 900)), + backgroundView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: -insets.right).with(priority: UILayoutPriority(rawValue: 900)), + ] + regularWidthLayoutConstraints = [ + backgroundView.leftAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.leftAnchor, constant: insets.left).with(priority: UILayoutPriority(rawValue: 900)), + backgroundView.rightAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.rightAnchor, constant: -insets.right).with(priority: UILayoutPriority(rawValue: 900)), + backgroundView.widthAnchor.constraint(lessThanOrEqualToConstant: 500).with(priority: UILayoutPriority(rawValue: 950)), + backgroundView.widthAnchor.constraint(equalToConstant: 500).with(priority: UILayoutPriority(rawValue: 200)), + ] installTapRecognizer() } @@ -139,23 +131,20 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeab } addSubview(backgroundView) self.backgroundView = backgroundView - NSLayoutConstraint.activate([ - backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor) - .with(priority: .belowMessageSizeable), - backgroundView.topAnchor.constraint(equalTo: topAnchor, constant: insets.top) - .with(priority: .required), - backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -insets.bottom) - .with(priority: .required), - backgroundView.heightAnchor.constraint(equalToConstant: 350) - .with(priority: UILayoutPriority(rawValue: 200)), - backgroundView.leftAnchor.constraint( - equalTo: layoutMarginsGuide.leftAnchor, constant: insets.left - ).with(priority: .belowMessageSizeable), - backgroundView.rightAnchor.constraint( - equalTo: layoutMarginsGuide.rightAnchor, - constant: -insets.right - ).with(priority: .belowMessageSizeable), - ]) + backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor).with(priority: UILayoutPriority(rawValue: 950)).isActive = true + backgroundView.topAnchor.constraint(equalTo: topAnchor, constant: insets.top).with(priority: UILayoutPriority(rawValue: 1000)).isActive = true + backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -insets.bottom).with(priority: UILayoutPriority(rawValue: 1000)).isActive = true + backgroundView.heightAnchor.constraint(equalToConstant: 350).with(priority: UILayoutPriority(rawValue: 200)).isActive = true + layoutConstraints = [ + backgroundView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: insets.left).with(priority: UILayoutPriority(rawValue: 900)), + backgroundView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: -insets.right).with(priority: UILayoutPriority(rawValue: 900)), + ] + regularWidthLayoutConstraints = [ + backgroundView.leftAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.leftAnchor, constant: insets.left).with(priority: UILayoutPriority(rawValue: 900)), + backgroundView.rightAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.rightAnchor, constant: -insets.right).with(priority: UILayoutPriority(rawValue: 900)), + backgroundView.widthAnchor.constraint(lessThanOrEqualToConstant: 500).with(priority: UILayoutPriority(rawValue: 950)), + backgroundView.widthAnchor.constraint(equalToConstant: 500).with(priority: UILayoutPriority(rawValue: 200)), + ] installTapRecognizer() } @@ -201,14 +190,6 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeab return super.point(inside: point, with: event) } - // MARK: - MessageSizeable - - /// Configure the view's size - public var messageSize = MessageSize() - - /// Configure the view's insets from the container - public var messageInsets = MessageInsets() - /* MARK: - MarginAdjustable @@ -248,6 +229,13 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeab @IBInspectable open var bounceAnimationOffset: CGFloat = 5 + /* + MARK: - HasBoundaryInsets + */ + + /// Configure the view's inset from the superview or save area + public var boundaryInsets = BoundaryInsets() + /* MARK: - Setting the height */ @@ -276,6 +264,29 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, MessageSizeab } private var backgroundHeightConstraint: NSLayoutConstraint? + + /* + Mark: - Layout + */ + + open override func updateConstraints() { + super.updateConstraints() + let on: [NSLayoutConstraint] + let off: [NSLayoutConstraint] + switch traitCollection.horizontalSizeClass { + case .regular: + on = regularWidthLayoutConstraints + off = layoutConstraints + default: + on = layoutConstraints + off = regularWidthLayoutConstraints + } + on.forEach { $0.isActive = true } + off.forEach { $0.isActive = false } + } + + private var layoutConstraints: [NSLayoutConstraint] = [] + private var regularWidthLayoutConstraints: [NSLayoutConstraint] = [] } /* diff --git a/SwiftMessages/BoundaryInsets.swift b/SwiftMessages/BoundaryInsets.swift new file mode 100644 index 00000000..f3d1da60 --- /dev/null +++ b/SwiftMessages/BoundaryInsets.swift @@ -0,0 +1,41 @@ +// +// BoundaryInsets.swift +// SwiftMessages +// +// Created by Timothy Moose on 2/13/21. +// Copyright © 2021 SwiftKick Mobile. All rights reserved. +// + +import QuartzCore + +public protocol HasBoundaryInsets { + var boundaryInsets: BoundaryInsets { get } +} + +/// Insets used for specifying view sizing options in terms of insets from the containing superview or safe area. +public struct BoundaryInsets { + + public enum Boundary { + case superview + case safeArea + case margin + } + + /// An abstract dimension used for specifying the message view's size + public enum Dimension { + + /// Dimensions should be determined automatically + case automatic + + /// Dimension should maintain an absolute margin to the given boundary. + case absoluteMargin(CGFloat, with: Boundary) + + /// Dimension should maintain a relative margin to the given boundary. + case relativeMargin(CGFloat, with: Boundary) + } + + public var top: Dimension = .automatic + public var bottom: Dimension = .automatic + public var leading: Dimension = .automatic + public var trailing: Dimension = .automatic +} diff --git a/SwiftMessages/MaskingView.swift b/SwiftMessages/MaskingView.swift index 889ac9de..0ce4c428 100644 --- a/SwiftMessages/MaskingView.swift +++ b/SwiftMessages/MaskingView.swift @@ -8,31 +8,8 @@ import UIKit -// TODO SIZE - need a version of this logic to limit views to 500pt on regular size class by default. -// regularWidthLayoutConstraints = [ -// backgroundView.leftAnchor.constraint( -// greaterThanOrEqualTo: layoutMarginsGuide.leftAnchor, -// constant: insets.left -// ).with(priority: .belowMessageSizeable), -// backgroundView.rightAnchor.constraint( -// lessThanOrEqualTo: layoutMarginsGuide.rightAnchor, -// constant: -insets.right -// ).with(priority: .belowMessageSizeable), -// backgroundView.widthAnchor.constraint(lessThanOrEqualToConstant: 500) -// .with(priority: .belowMessageSizeable), -// backgroundView.widthAnchor.constraint(equalToConstant: 500) -// .with(priority: UILayoutPriority(rawValue: 200)), -// ] -class MaskingView: PassthroughView, MessageSizing { - - func install(sizeableView: MessageSizeable & UIView) { - self.sizeableView?.removeFromSuperview() - self.sizeableView = sizeableView - sizeableView.translatesAutoresizingMaskIntoConstraints = false - addSubview(sizeableView) - setNeedsUpdateConstraints() - } +class MaskingView: PassthroughView { func install(keyboardTrackingView: KeyboardTrackingView) { self.keyboardTrackingView = keyboardTrackingView @@ -73,30 +50,15 @@ class MaskingView: PassthroughView, MessageSizing { init() { super.init(frame: CGRect.zero) - postInit() + clipsToBounds = true } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) - postInit() - } - - private func postInit() { clipsToBounds = true - addLayoutGuide(messageInsetsGuide) - } - - override var bounds: CGRect { - didSet { - guard bounds != oldValue else { return } - setNeedsUpdateConstraints() - } } private var keyboardTrackingView: KeyboardTrackingView? - private var cachedConstraints: [NSLayoutConstraint] = [] - private let messageInsetsGuide = UILayoutGuide() - private var sizeableView: (MessageSizeable & UIView)? override func addSubview(_ view: UIView) { super.addSubview(view) @@ -105,175 +67,4 @@ class MaskingView: PassthroughView, MessageSizing { view != backgroundView else { return } keyboardTrackingView.topAnchor.constraint(greaterThanOrEqualTo: view.bottomAnchor).with(priority: UILayoutPriority(250)).isActive = true } - - override func updateConstraints() { - super.updateConstraints() - NSLayoutConstraint.deactivate(cachedConstraints) - cachedConstraints = [] - if let top = sizeableView?.messageInsets.top { update(top: top) } - if let bottom = sizeableView?.messageInsets.bottom { update(bottom: bottom) } - if let leading = sizeableView?.messageInsets.leading { update(leading: leading) } - if let trailing = sizeableView?.messageInsets.trailing { update(trailing: trailing) } - if let sizeableView = sizeableView { update(sizeableView: sizeableView) } - NSLayoutConstraint.activate(cachedConstraints) - } - - private func update(top: MessageInsets.Dimension) { - let length: CGFloat - switch top { - case .absoluteMargin(let dimension, _): - length = dimension - case .relativeMargin(let percentage, _): - length = bounds.height * percentage - } - let otherAnchor: NSLayoutYAxisAnchor - switch top.boundary { - case .superview: otherAnchor = topAnchor - case .margin: otherAnchor = layoutMarginsGuide.topAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = safeAreaLayoutGuide.topAnchor - } else { - otherAnchor = layoutMarginsGuide.topAnchor - } - } - cachedConstraints.append( - messageInsetsGuide.topAnchor.constraint(equalTo: otherAnchor, constant: length) - .with(priority: .messageInset) - ) - } - - private func update(bottom: MessageInsets.Dimension) { - let length: CGFloat - switch bottom { - case .absoluteMargin(let dimension, _): - length = dimension - case .relativeMargin(let percentage, _): - length = bounds.height * percentage - } - let otherAnchor: NSLayoutYAxisAnchor - switch bottom.boundary { - case .superview: otherAnchor = bottomAnchor - case .margin: otherAnchor = layoutMarginsGuide.bottomAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = safeAreaLayoutGuide.bottomAnchor - } else { - otherAnchor = layoutMarginsGuide.bottomAnchor - } - } - cachedConstraints.append( - messageInsetsGuide.bottomAnchor.constraint(equalTo: otherAnchor, constant: -length) - .with(priority: .messageInset) - ) - } - - private func update(leading: MessageInsets.Dimension) { - let length: CGFloat - switch leading { - case .absoluteMargin(let dimension, _): - length = dimension - case .relativeMargin(let percentage, _): - length = bounds.width * percentage - } - let otherAnchor: NSLayoutXAxisAnchor - switch leading.boundary { - case .superview: otherAnchor = leadingAnchor - case .margin: otherAnchor = layoutMarginsGuide.leadingAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = safeAreaLayoutGuide.leadingAnchor - } else { - otherAnchor = layoutMarginsGuide.leadingAnchor - } - } - cachedConstraints.append( - messageInsetsGuide.leadingAnchor.constraint(equalTo: otherAnchor, constant: length) - .with(priority: .messageInset) - ) - } - - private func update(trailing: MessageInsets.Dimension) { - let length: CGFloat - switch trailing { - case .absoluteMargin(let dimension, _): - length = dimension - case .relativeMargin(let percentage, _): - length = bounds.width * percentage - } - let otherAnchor: NSLayoutXAxisAnchor - switch trailing.boundary { - case .superview: otherAnchor = trailingAnchor - case .margin: otherAnchor = layoutMarginsGuide.trailingAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = safeAreaLayoutGuide.trailingAnchor - } else { - otherAnchor = layoutMarginsGuide.trailingAnchor - } - } - cachedConstraints.append( - messageInsetsGuide.trailingAnchor.constraint(equalTo: otherAnchor, constant: -length) - .with(priority: .messageInset) - ) - } - - private func update(sizeableView view: MessageSizeable & UIView) { - cachedConstraints += [ - messageInsetsGuide.topAnchor.constraint(equalTo: view.topAnchor), - messageInsetsGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor), - messageInsetsGuide.leadingAnchor.constraint(equalTo: view.leadingAnchor), - messageInsetsGuide.trailingAnchor.constraint(equalTo: view.trailingAnchor), - ] - if let width = view.messageSize.width { - let length = self.length(for: width, extractor: { $0.width }) - cachedConstraints.append( - view.widthAnchor.constraint(equalToConstant: length) - .with(priority: .messageSize) - ) - } - if let height = view.messageSize.height { - let length = self.length(for: height, extractor: { $0.height }) - cachedConstraints.append( - view.heightAnchor.constraint(equalToConstant: length) - .with(priority: .messageSize) - ) - } - } - - private func length( - for dimension: MessageSize.Dimension, - extractor: (CGRect) -> CGFloat - ) -> CGFloat { - switch dimension { - case .absolute(let dimension): - return dimension - case .absoluteMargin(let margin, let boundary): - let insets: UIEdgeInsets - switch boundary { - case .superview: insets = .zero - case .margin: insets = layoutMargins - case .safeArea: - if #available(iOS 11.0, *) { - insets = safeAreaInsets - } else { - insets = layoutMargins - } - } - return extractor(bounds.inset(by: insets)) - margin * 2 - case .relative(let percentage, let boundary): - let insets: UIEdgeInsets - switch boundary { - case .superview: insets = .zero - case .margin: insets = layoutMargins - case .safeArea: - if #available(iOS 11.0, *) { - insets = safeAreaInsets - } else { - insets = layoutMargins - } - } - return extractor(bounds.inset(by: insets)) * percentage - } - } } diff --git a/SwiftMessages/MessageSizeable.swift b/SwiftMessages/MessageSizeable.swift deleted file mode 100644 index 662f1839..00000000 --- a/SwiftMessages/MessageSizeable.swift +++ /dev/null @@ -1,65 +0,0 @@ -// -// BoundaryInsets.swift -// SwiftMessages -// -// Created by Timothy Moose on 2/13/21. -// Copyright © 2021 SwiftKick Mobile. All rights reserved. -// - -import UIKit - -public protocol MessageSizeable { - var messageSize: MessageSize { get } - var messageInsets: MessageInsets { get } -} - -public enum MessageBoundary { - case superview - case safeArea - case margin -} - -/// Insets used for specifying view sizing options in terms of insets from the containing superview or safe area. -public struct MessageInsets { - - public enum Dimension { - - /// Dimension should maintain an absolute margin to the given container boundary. - case absoluteMargin(CGFloat, from: MessageBoundary) - - /// Dimension should maintain a relative margin to the given container boundary. - case relativeMargin(CGFloat, from: MessageBoundary) - } - - public var top: Dimension? - public var bottom: Dimension? - public var leading: Dimension? - public var trailing: Dimension? -} - -public struct MessageSize { - - public enum Dimension { - - /// Dimensions should be an absolute length - case absolute(CGFloat) - - /// Dimension should maintain an absolute length to the given container boundary. - case absoluteMargin(CGFloat, from: MessageBoundary) - - /// Dimension should maintain a relative margin to the given boundary. - case relative(CGFloat, from: MessageBoundary) - } - - public var width: Dimension? - public var height: Dimension? -} - -extension MessageInsets.Dimension { - var boundary: MessageBoundary { - switch self { - case .absoluteMargin(_, let boundary): return boundary - case .relativeMargin(_, let boundary): return boundary - } - } -} diff --git a/SwiftMessages/MessageSizing.swift b/SwiftMessages/MessageSizing.swift deleted file mode 100644 index b4c47dd3..00000000 --- a/SwiftMessages/MessageSizing.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// MessageSizing.swift -// SwiftMessages -// -// Created by Timothy Moose on 2/14/21. -// Copyright © 2021 SwiftKick Mobile. All rights reserved. -// - -import Foundation - -public protocol MessageSizing { - func install(sizeableView: MessageSizeable & UIView) -} diff --git a/SwiftMessages/Resources/CardView.xib b/SwiftMessages/Resources/CardView.xib index f3ad1df4..425a6961 100644 --- a/SwiftMessages/Resources/CardView.xib +++ b/SwiftMessages/Resources/CardView.xib @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> @@ -70,6 +70,7 @@ <constraint firstAttribute="trailing" secondItem="SU0-uJ-4pP" secondAttribute="trailing" constant="20" id="QN2-NH-rWA"/> <constraint firstItem="SU0-uJ-4pP" firstAttribute="top" secondItem="A7b-0a-fJG" secondAttribute="top" constant="20" id="S9l-zM-0wc"/> <constraint firstAttribute="bottom" secondItem="SU0-uJ-4pP" secondAttribute="bottom" constant="20" id="YMg-LN-n7f"/> + <constraint firstAttribute="width" relation="lessThanOrEqual" priority="900" constant="500" id="lOa-jP-2uX"/> <constraint firstItem="SU0-uJ-4pP" firstAttribute="leading" secondItem="A7b-0a-fJG" secondAttribute="leading" constant="20" id="nYJ-Ok-uhC"/> </constraints> <userDefinedRuntimeAttributes> @@ -77,13 +78,25 @@ <real key="value" value="15"/> </userDefinedRuntimeAttribute> </userDefinedRuntimeAttributes> + <variation key="default"> + <mask key="constraints"> + <exclude reference="lOa-jP-2uX"/> + </mask> + </variation> + <variation key="widthClass=regular"> + <mask key="constraints"> + <include reference="lOa-jP-2uX"/> + </mask> + </variation> </view> </subviews> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <constraints> + <constraint firstItem="A7b-0a-fJG" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="uEa-1P-F1Y" secondAttribute="leadingMargin" priority="900" id="LWV-wo-Jec"/> <constraint firstAttribute="trailingMargin" secondItem="A7b-0a-fJG" secondAttribute="trailing" priority="900" id="O6e-Yz-cwK"/> <constraint firstItem="A7b-0a-fJG" firstAttribute="leading" secondItem="uEa-1P-F1Y" secondAttribute="leadingMargin" priority="900" id="RiR-2q-ZY5"/> <constraint firstItem="A7b-0a-fJG" firstAttribute="centerX" secondItem="uEa-1P-F1Y" secondAttribute="centerX" priority="950" id="jLv-ud-1WD"/> + <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="A7b-0a-fJG" secondAttribute="trailing" priority="900" id="lGg-Ey-I5f"/> <constraint firstItem="A7b-0a-fJG" firstAttribute="top" secondItem="uEa-1P-F1Y" secondAttribute="topMargin" id="yAH-C4-oUg"/> <constraint firstAttribute="bottomMargin" secondItem="A7b-0a-fJG" secondAttribute="bottom" id="ygs-aa-zj3"/> </constraints> @@ -106,10 +119,18 @@ </userDefinedRuntimeAttribute> <userDefinedRuntimeAttribute type="boolean" keyPath="collapseLayoutMarginAdditions" value="YES"/> </userDefinedRuntimeAttributes> + <variation key="default"> + <mask key="constraints"> + <exclude reference="LWV-wo-Jec"/> + <exclude reference="lGg-Ey-I5f"/> + </mask> + </variation> <variation key="widthClass=regular"> <mask key="constraints"> + <include reference="LWV-wo-Jec"/> <exclude reference="O6e-Yz-cwK"/> <exclude reference="RiR-2q-ZY5"/> + <include reference="lGg-Ey-I5f"/> </mask> </variation> <connections> diff --git a/SwiftMessages/Resources/CenteredView.xib b/SwiftMessages/Resources/CenteredView.xib index b61242cc..a9fda2be 100644 --- a/SwiftMessages/Resources/CenteredView.xib +++ b/SwiftMessages/Resources/CenteredView.xib @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> @@ -32,7 +32,7 @@ <rect key="frame" x="160.5" y="55.5" width="33" height="0.0"/> </imageView> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="700" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="[Title]" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ggW-gB-SWF"> - <rect key="frame" x="153" y="65.5" width="48" height="20.5"/> + <rect key="frame" x="153" y="65.5" width="48.5" height="20.5"/> <accessibility key="accessibilityConfiguration"> <bool key="isElement" value="NO"/> </accessibility> @@ -69,6 +69,7 @@ <constraint firstAttribute="bottom" secondItem="YST-yc-0HK" secondAttribute="bottom" constant="20" id="Vsy-Y9-qzf"> <variation key="widthClass=regular" constant="30"/> </constraint> + <constraint firstAttribute="width" relation="lessThanOrEqual" priority="900" constant="500" id="Y89-EE-TtG"/> <constraint firstItem="YST-yc-0HK" firstAttribute="top" secondItem="0Mj-jC-BX6" secondAttribute="top" constant="20" id="yRl-kK-cQH"> <variation key="widthClass=regular" constant="30"/> </constraint> @@ -78,6 +79,16 @@ <real key="value" value="15"/> </userDefinedRuntimeAttribute> </userDefinedRuntimeAttributes> + <variation key="default"> + <mask key="constraints"> + <exclude reference="Y89-EE-TtG"/> + </mask> + </variation> + <variation key="widthClass=regular"> + <mask key="constraints"> + <exclude reference="Y89-EE-TtG"/> + </mask> + </variation> </view> </subviews> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> @@ -85,8 +96,10 @@ <constraint firstItem="0Mj-jC-BX6" firstAttribute="top" secondItem="g5x-hF-D0u" secondAttribute="topMargin" id="GWI-aH-o7P"/> <constraint firstItem="0Mj-jC-BX6" firstAttribute="centerX" secondItem="g5x-hF-D0u" secondAttribute="centerX" priority="950" id="XqM-pB-dF4"/> <constraint firstItem="0Mj-jC-BX6" firstAttribute="leading" secondItem="g5x-hF-D0u" secondAttribute="leadingMargin" priority="900" id="bQ3-k8-0v0"/> + <constraint firstItem="0Mj-jC-BX6" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="g5x-hF-D0u" secondAttribute="leadingMargin" priority="900" id="iGY-na-87c"/> <constraint firstAttribute="trailingMargin" secondItem="0Mj-jC-BX6" secondAttribute="trailing" priority="900" id="rSj-h2-U7z"/> <constraint firstAttribute="bottomMargin" secondItem="0Mj-jC-BX6" secondAttribute="bottom" id="wRH-k8-J8S"/> + <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="0Mj-jC-BX6" secondAttribute="trailing" priority="900" id="xAq-z5-Gur"/> </constraints> <nil key="simulatedTopBarMetrics"/> <nil key="simulatedBottomBarMetrics"/> @@ -109,10 +122,18 @@ </userDefinedRuntimeAttribute> <userDefinedRuntimeAttribute type="boolean" keyPath="collapseLayoutMarginAdditions" value="YES"/> </userDefinedRuntimeAttributes> + <variation key="default"> + <mask key="constraints"> + <exclude reference="iGY-na-87c"/> + <exclude reference="xAq-z5-Gur"/> + </mask> + </variation> <variation key="widthClass=regular"> <mask key="constraints"> <exclude reference="bQ3-k8-0v0"/> + <include reference="iGY-na-87c"/> <exclude reference="rSj-h2-U7z"/> + <include reference="xAq-z5-Gur"/> </mask> </variation> <connections> diff --git a/SwiftMessages/Resources/TabView.xib b/SwiftMessages/Resources/TabView.xib index e572aa41..141467c1 100644 --- a/SwiftMessages/Resources/TabView.xib +++ b/SwiftMessages/Resources/TabView.xib @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> @@ -69,6 +69,7 @@ <constraints> <constraint firstItem="bdc-by-rjM" firstAttribute="leading" secondItem="8l1-Wp-omF" secondAttribute="leading" priority="900" constant="20" id="ZeN-Yg-DDA"/> <constraint firstAttribute="trailing" secondItem="bdc-by-rjM" secondAttribute="trailing" priority="900" constant="20" id="Zuf-gb-AgS"/> + <constraint firstAttribute="width" relation="lessThanOrEqual" priority="900" constant="500" id="eE4-1F-BxM"/> </constraints> <edgeInsets key="layoutMargins" top="0.0" left="0.0" bottom="0.0" right="0.0"/> <userDefinedRuntimeAttributes> @@ -77,15 +78,27 @@ </userDefinedRuntimeAttribute> <userDefinedRuntimeAttribute type="boolean" keyPath="roundsLeadingCorners" value="YES"/> </userDefinedRuntimeAttributes> + <variation key="default"> + <mask key="constraints"> + <exclude reference="eE4-1F-BxM"/> + </mask> + </variation> + <variation key="widthClass=regular"> + <mask key="constraints"> + <include reference="eE4-1F-BxM"/> + </mask> + </variation> </view> </subviews> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstItem="8l1-Wp-omF" firstAttribute="centerX" secondItem="Kgd-fq-RpT" secondAttribute="centerX" priority="950" id="7tH-rr-EQZ"/> + <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="8l1-Wp-omF" secondAttribute="trailing" priority="900" id="Auy-Yk-HhC"/> <constraint firstItem="bdc-by-rjM" firstAttribute="top" secondItem="Kgd-fq-RpT" secondAttribute="topMargin" id="ORK-bM-dJT"/> <constraint firstItem="8l1-Wp-omF" firstAttribute="top" secondItem="Kgd-fq-RpT" secondAttribute="top" id="WBW-gJ-lIP"/> <constraint firstAttribute="bottom" secondItem="8l1-Wp-omF" secondAttribute="bottom" id="cYv-6k-QSZ"/> <constraint firstAttribute="bottomMargin" secondItem="bdc-by-rjM" secondAttribute="bottom" id="foq-FY-TKq"/> + <constraint firstItem="8l1-Wp-omF" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Kgd-fq-RpT" secondAttribute="leadingMargin" priority="900" id="pRc-fu-AhN"/> <constraint firstItem="8l1-Wp-omF" firstAttribute="leading" secondItem="Kgd-fq-RpT" secondAttribute="leadingMargin" priority="900" id="tVC-3b-F2x"/> <constraint firstItem="8l1-Wp-omF" firstAttribute="trailing" secondItem="Kgd-fq-RpT" secondAttribute="trailingMargin" priority="900" id="uZe-cg-8cw"/> </constraints> @@ -108,8 +121,16 @@ </userDefinedRuntimeAttribute> <userDefinedRuntimeAttribute type="boolean" keyPath="collapseLayoutMarginAdditions" value="NO"/> </userDefinedRuntimeAttributes> + <variation key="default"> + <mask key="constraints"> + <exclude reference="Auy-Yk-HhC"/> + <exclude reference="pRc-fu-AhN"/> + </mask> + </variation> <variation key="widthClass=regular"> <mask key="constraints"> + <include reference="Auy-Yk-HhC"/> + <include reference="pRc-fu-AhN"/> <exclude reference="tVC-3b-F2x"/> <exclude reference="uZe-cg-8cw"/> </mask> diff --git a/SwiftMessages/SwiftMessagesSegue.swift b/SwiftMessages/SwiftMessagesSegue.swift index f20491bc..8fa696ed 100644 --- a/SwiftMessages/SwiftMessagesSegue.swift +++ b/SwiftMessages/SwiftMessagesSegue.swift @@ -369,15 +369,11 @@ extension SwiftMessagesSegue { if let preferredHeight = toVC?.preferredContentSize.height, preferredHeight - navInset > 0 { - segue.containerView.heightAnchor.constraint(equalToConstant: preferredHeight) - .with(priority: .belowMessageSizeable - 1) - .isActive = true + segue.containerView.heightAnchor.constraint(equalToConstant: preferredHeight).with(priority: UILayoutPriority(rawValue: 951)).isActive = true } if let preferredWidth = toVC?.preferredContentSize.width, preferredWidth > 0 { - segue.containerView.widthAnchor.constraint(equalToConstant: preferredWidth) - .with(priority: .belowMessageSizeable - 1) - .isActive = true + segue.containerView.widthAnchor.constraint(equalToConstant: preferredWidth).with(priority: UILayoutPriority(rawValue: 951)).isActive = true } segue.presenter.config.presentationContext = .view(transitionContainer) segue.messenger.show(presenter: segue.presenter) diff --git a/SwiftMessages/TopBottomAnimation.swift b/SwiftMessages/TopBottomAnimation.swift index 0a91fc3f..78c0d84a 100644 --- a/SwiftMessages/TopBottomAnimation.swift +++ b/SwiftMessages/TopBottomAnimation.swift @@ -88,30 +88,92 @@ public class TopBottomAnimation: NSObject, Animator { if let adjustable = context.messageView as? MarginAdjustable { bounceOffset = adjustable.bounceAnimationOffset } - if let sizeableView = view as? MessageSizeable & UIView { - container.install(sizeableView: sizeableView) - } else { - view.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(view) - } - // Horizontal constraints - do { - view.leadingAnchor.constraint(equalTo: container.leadingAnchor) - .with(priority: .belowMessageSizeable - 1) - .isActive = true - view.centerXAnchor.constraint(equalTo: container.centerXAnchor) - .with(priority: .belowMessageSizeable) - .isActive = true - } + view.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(view) + view.leadingAnchor.constraint(equalTo: container.leadingAnchor).isActive = true + view.trailingAnchor.constraint(equalTo: container.trailingAnchor).isActive = true + let boundaryInsets = (view as? HasBoundaryInsets)?.boundaryInsets ?? BoundaryInsets() switch style { case .top: - view.topAnchor.constraint(equalTo: container.topAnchor, constant: -bounceOffset) - .with(priority: .belowMessageSizeable) - .isActive = true + view.topAnchor.constraint( + equalTo: container.topAnchor, + constant: -bounceOffset + ).with(priority: .defaultHigh).isActive = true + switch boundaryInsets.bottom { + case .automatic: + break + case .absoluteMargin(let dimension, let boundary): + let otherAnchor: NSLayoutYAxisAnchor + switch boundary { + case .superview: otherAnchor = container.bottomAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = container.safeAreaLayoutGuide.bottomAnchor + } else { + otherAnchor = container.layoutMarginsGuide.bottomAnchor + } + case .margin: otherAnchor = container.layoutMarginsGuide.bottomAnchor + } + view.bottomAnchor.constraint(equalTo: otherAnchor, constant: -dimension) + .with(priority: .defaultHigh) + .isActive = true + case .relativeMargin(let dimension, let boundary): + let otherAnchor: NSLayoutDimension! + switch boundary { + case .superview: otherAnchor = container.heightAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = container.safeAreaLayoutGuide.heightAnchor + } else { + otherAnchor = container.layoutMarginsGuide.heightAnchor + } + case .margin: otherAnchor = container.layoutMarginsGuide.heightAnchor + } + view.heightAnchor.constraint( + equalTo: otherAnchor, + multiplier: 1 - dimension + ).with(priority: .defaultHigh).isActive = true + } case .bottom: - view.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: bounceOffset) - .with(priority: .belowMessageSizeable) - .isActive = true + view.bottomAnchor.constraint( + equalTo: container.bottomAnchor, + constant: bounceOffset + ).with(priority: .defaultHigh).isActive = true + switch boundaryInsets.top { + case .automatic: + break + case .absoluteMargin(let dimension, let boundary): + let otherAnchor: NSLayoutYAxisAnchor + switch boundary { + case .superview: otherAnchor = container.topAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = container.safeAreaLayoutGuide.topAnchor + } else { + otherAnchor = container.layoutMarginsGuide.topAnchor + } + case .margin: otherAnchor = container.layoutMarginsGuide.topAnchor + } + view.topAnchor.constraint(equalTo: otherAnchor, constant: dimension) + .with(priority: .defaultHigh) + .isActive = true + case .relativeMargin(let dimension, let boundary): + let otherAnchor: NSLayoutDimension! + switch boundary { + case .superview: otherAnchor = container.heightAnchor + case .safeArea: + if #available(iOS 11.0, *) { + otherAnchor = container.safeAreaLayoutGuide.heightAnchor + } else { + otherAnchor = container.layoutMarginsGuide.heightAnchor + } + case .margin: otherAnchor = container.layoutMarginsGuide.heightAnchor + } + view.heightAnchor.constraint( + equalTo: otherAnchor, + multiplier: 1 - dimension + ).with(priority: .defaultHigh).isActive = true + } } // Important to layout now in order to get the right safe area insets container.layoutIfNeeded() diff --git a/SwiftMessages/UILayoutPriority+Extensions.swift b/SwiftMessages/UILayoutPriority+Extensions.swift deleted file mode 100644 index 1fd3ab88..00000000 --- a/SwiftMessages/UILayoutPriority+Extensions.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// UILayoutPriority+Extensions.swift -// SwiftMessages -// -// Created by Timothy Moose on 2/14/21. -// Copyright © 2021 SwiftKick Mobile. All rights reserved. -// - -import UIKit - -/// The priority used for `MessageSizeable` constraints -public extension UILayoutPriority { - static let aboveMessageSizeable: UILayoutPriority = messageInset + 1 - static let belowMessageSizeable: UILayoutPriority = messageSize - 1 - static let messageSize: UILayoutPriority = UILayoutPriority(900) - static let messageInset: UILayoutPriority = UILayoutPriority(901) -} - From 551e147ee4fab10bd9333e8333fb71f623e3c92f Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 10 Apr 2021 16:33:43 -0500 Subject: [PATCH 35/77] Revert "Consider nav bar behavior in preferred content size" This reverts commit 46ad7377bc1a4191e9967f5f083b8a362510468b. --- SwiftMessages/SwiftMessagesSegue.swift | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/SwiftMessages/SwiftMessagesSegue.swift b/SwiftMessages/SwiftMessagesSegue.swift index 8fa696ed..d4cba417 100644 --- a/SwiftMessages/SwiftMessagesSegue.swift +++ b/SwiftMessages/SwiftMessagesSegue.swift @@ -359,16 +359,8 @@ extension SwiftMessagesSegue { segue.messageView.installBackgroundVerticalView(segue.containerView) } let toVC = transitionContext.viewController(forKey: .to) - - // Nav controller automatically includes height of nav bar in, - // the `preferredContentSize` and our logic needs to consider this. - var navInset: CGFloat = 0 - if let nav = toVC as? UINavigationController { - navInset = nav.navigationBar.frame.height - } - if let preferredHeight = toVC?.preferredContentSize.height, - preferredHeight - navInset > 0 { + preferredHeight > 0 { segue.containerView.heightAnchor.constraint(equalToConstant: preferredHeight).with(priority: UILayoutPriority(rawValue: 951)).isActive = true } if let preferredWidth = toVC?.preferredContentSize.width, From 8900f82cf656f030b6bfa607150d98013191079a Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 10 Apr 2021 16:33:52 -0500 Subject: [PATCH 36/77] Revert "Keep support for iOS 10" This reverts commit 0ee863a30c17b907d2f0290f277a50c949bb48b1. --- SwiftMessages.podspec | 4 ++-- SwiftMessages.xcodeproj/project.pbxproj | 8 +++---- SwiftMessages/TopBottomAnimation.swift | 28 ++++--------------------- 3 files changed, 10 insertions(+), 30 deletions(-) diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index aad0b316..130843c5 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -6,9 +6,9 @@ Pod::Spec.new do |spec| spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } spec.summary = 'A very flexible message bar for iOS written in Swift.' spec.source = {:git => 'https://github.com/SwiftKickMobile/SwiftMessages.git', :tag => spec.version} - spec.platform = :ios, '10.0' + spec.platform = :ios, '11.0' spec.swift_version = '5.0' - spec.ios.deployment_target = '10.0' + spec.ios.deployment_target = '11.0' spec.framework = 'UIKit' spec.requires_arc = true spec.default_subspec = 'App' diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index f5296fde..abec6078 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -630,7 +630,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -682,7 +682,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -704,7 +704,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; INFOPLIST_FILE = SwiftMessages/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -732,7 +732,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; INFOPLIST_FILE = SwiftMessages/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/SwiftMessages/TopBottomAnimation.swift b/SwiftMessages/TopBottomAnimation.swift index 78c0d84a..0a7dc19e 100644 --- a/SwiftMessages/TopBottomAnimation.swift +++ b/SwiftMessages/TopBottomAnimation.swift @@ -106,12 +106,7 @@ public class TopBottomAnimation: NSObject, Animator { let otherAnchor: NSLayoutYAxisAnchor switch boundary { case .superview: otherAnchor = container.bottomAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = container.safeAreaLayoutGuide.bottomAnchor - } else { - otherAnchor = container.layoutMarginsGuide.bottomAnchor - } + case .safeArea: otherAnchor = container.safeAreaLayoutGuide.bottomAnchor case .margin: otherAnchor = container.layoutMarginsGuide.bottomAnchor } view.bottomAnchor.constraint(equalTo: otherAnchor, constant: -dimension) @@ -121,12 +116,7 @@ public class TopBottomAnimation: NSObject, Animator { let otherAnchor: NSLayoutDimension! switch boundary { case .superview: otherAnchor = container.heightAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = container.safeAreaLayoutGuide.heightAnchor - } else { - otherAnchor = container.layoutMarginsGuide.heightAnchor - } + case .safeArea: otherAnchor = container.safeAreaLayoutGuide.heightAnchor case .margin: otherAnchor = container.layoutMarginsGuide.heightAnchor } view.heightAnchor.constraint( @@ -146,12 +136,7 @@ public class TopBottomAnimation: NSObject, Animator { let otherAnchor: NSLayoutYAxisAnchor switch boundary { case .superview: otherAnchor = container.topAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = container.safeAreaLayoutGuide.topAnchor - } else { - otherAnchor = container.layoutMarginsGuide.topAnchor - } + case .safeArea: otherAnchor = container.safeAreaLayoutGuide.topAnchor case .margin: otherAnchor = container.layoutMarginsGuide.topAnchor } view.topAnchor.constraint(equalTo: otherAnchor, constant: dimension) @@ -161,12 +146,7 @@ public class TopBottomAnimation: NSObject, Animator { let otherAnchor: NSLayoutDimension! switch boundary { case .superview: otherAnchor = container.heightAnchor - case .safeArea: - if #available(iOS 11.0, *) { - otherAnchor = container.safeAreaLayoutGuide.heightAnchor - } else { - otherAnchor = container.layoutMarginsGuide.heightAnchor - } + case .safeArea: otherAnchor = container.safeAreaLayoutGuide.heightAnchor case .margin: otherAnchor = container.layoutMarginsGuide.heightAnchor } view.heightAnchor.constraint( From 77d3e953481559a59a3dd22c342c346f20c40e37 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 10 Apr 2021 16:33:59 -0500 Subject: [PATCH 37/77] Revert "BoundaryInsets prototype" This reverts commit fbfbf3c1e6b0d152be878627e7f54904d921a7f6. --- SwiftMessages.podspec | 6 +-- SwiftMessages.xcodeproj/project.pbxproj | 12 ++--- SwiftMessages/Animator.swift | 8 +--- SwiftMessages/BaseView.swift | 9 +--- SwiftMessages/BoundaryInsets.swift | 41 ---------------- SwiftMessages/TopBottomAnimation.swift | 63 +------------------------ 6 files changed, 12 insertions(+), 127 deletions(-) delete mode 100644 SwiftMessages/BoundaryInsets.swift diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 130843c5..22b2d781 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,14 +1,14 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.1.0' + spec.version = '9.0.0' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } spec.summary = 'A very flexible message bar for iOS written in Swift.' spec.source = {:git => 'https://github.com/SwiftKickMobile/SwiftMessages.git', :tag => spec.version} - spec.platform = :ios, '11.0' + spec.platform = :ios, '9.0' spec.swift_version = '5.0' - spec.ios.deployment_target = '11.0' + spec.ios.deployment_target = '9.0' spec.framework = 'UIKit' spec.requires_arc = true spec.default_subspec = 'App' diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index abec6078..95f93353 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -51,7 +51,6 @@ 228DF5681FAD0806004F8A39 /* infoIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */; }; 228DF5691FAD0806004F8A39 /* successIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5481FAD0805004F8A39 /* successIconLight.png */; }; 228DF56A1FAD0806004F8A39 /* infoIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */; }; - 2290944825D88A05002E8111 /* BoundaryInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2290944725D88A05002E8111 /* BoundaryInsets.swift */; }; 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */; }; @@ -138,7 +137,6 @@ 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = infoIconSubtle.png; path = Resources/infoIconSubtle.png; sourceTree = "<group>"; }; 228DF5481FAD0805004F8A39 /* successIconLight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = successIconLight.png; path = Resources/successIconLight.png; sourceTree = "<group>"; }; 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; - 2290944725D88A05002E8111 /* BoundaryInsets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoundaryInsets.swift; sourceTree = "<group>"; }; 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = "<group>"; }; @@ -300,7 +298,6 @@ 22E307FE1E74C5B100E35893 /* AccessibleMessage.swift */, 86AAF82A1D580DD70031EE32 /* Error.swift */, 2298C2061EE480D000E2DDC1 /* Animator.swift */, - 2290944725D88A05002E8111 /* BoundaryInsets.swift */, 2298C2041EE47DC900E2DDC1 /* Weak.swift */, 22F27950210CE25900273E7F /* CornerRoundingView.swift */, 225304652293000C00A03ACF /* KeyboardTrackingView.swift */, @@ -533,7 +530,6 @@ 86BBA8FC1D5E03F100FE8F16 /* MessageView.swift in Sources */, 86BBA9061D5E040C00FE8F16 /* Identifiable.swift in Sources */, 22F27951210CE25900273E7F /* CornerRoundingView.swift in Sources */, - 2290944825D88A05002E8111 /* BoundaryInsets.swift in Sources */, 86BBA9011D5E040600FE8F16 /* PassthroughWindow.swift in Sources */, 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */, 86BBA9031D5E040600FE8F16 /* UIViewController+Extensions.swift in Sources */, @@ -630,7 +626,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.1; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -682,7 +678,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.1; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -704,7 +700,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; INFOPLIST_FILE = SwiftMessages/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -732,7 +728,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; INFOPLIST_FILE = SwiftMessages/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/SwiftMessages/Animator.swift b/SwiftMessages/Animator.swift index b95bcaf9..7d924e2d 100644 --- a/SwiftMessages/Animator.swift +++ b/SwiftMessages/Animator.swift @@ -44,17 +44,13 @@ public struct SafeZoneConflicts: OptionSet { } public class AnimationContext { + public let messageView: UIView public let containerView: UIView public let safeZoneConflicts: SafeZoneConflicts public let interactiveHide: Bool - internal init( - messageView: UIView, - containerView: UIView, - safeZoneConflicts: SafeZoneConflicts, - interactiveHide: Bool - ) { + init(messageView: UIView, containerView: UIView, safeZoneConflicts: SafeZoneConflicts, interactiveHide: Bool) { self.messageView = messageView self.containerView = containerView self.safeZoneConflicts = safeZoneConflicts diff --git a/SwiftMessages/BaseView.swift b/SwiftMessages/BaseView.swift index 93c9df96..9480b87d 100644 --- a/SwiftMessages/BaseView.swift +++ b/SwiftMessages/BaseView.swift @@ -14,7 +14,7 @@ import UIKit of the optional SwiftMessages protocols and provides some convenience functions and a configurable tap handler. Message views do not need to inherit from `BaseVew`. */ -open class BaseView: UIView, BackgroundViewable, MarginAdjustable, HasBoundaryInsets { +open class BaseView: UIView, BackgroundViewable, MarginAdjustable { /* MARK: - IB outlets @@ -229,13 +229,6 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable, HasBoundaryIn @IBInspectable open var bounceAnimationOffset: CGFloat = 5 - /* - MARK: - HasBoundaryInsets - */ - - /// Configure the view's inset from the superview or save area - public var boundaryInsets = BoundaryInsets() - /* MARK: - Setting the height */ diff --git a/SwiftMessages/BoundaryInsets.swift b/SwiftMessages/BoundaryInsets.swift deleted file mode 100644 index f3d1da60..00000000 --- a/SwiftMessages/BoundaryInsets.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// BoundaryInsets.swift -// SwiftMessages -// -// Created by Timothy Moose on 2/13/21. -// Copyright © 2021 SwiftKick Mobile. All rights reserved. -// - -import QuartzCore - -public protocol HasBoundaryInsets { - var boundaryInsets: BoundaryInsets { get } -} - -/// Insets used for specifying view sizing options in terms of insets from the containing superview or safe area. -public struct BoundaryInsets { - - public enum Boundary { - case superview - case safeArea - case margin - } - - /// An abstract dimension used for specifying the message view's size - public enum Dimension { - - /// Dimensions should be determined automatically - case automatic - - /// Dimension should maintain an absolute margin to the given boundary. - case absoluteMargin(CGFloat, with: Boundary) - - /// Dimension should maintain a relative margin to the given boundary. - case relativeMargin(CGFloat, with: Boundary) - } - - public var top: Dimension = .automatic - public var bottom: Dimension = .automatic - public var leading: Dimension = .automatic - public var trailing: Dimension = .automatic -} diff --git a/SwiftMessages/TopBottomAnimation.swift b/SwiftMessages/TopBottomAnimation.swift index 0a7dc19e..d9f1f3a4 100644 --- a/SwiftMessages/TopBottomAnimation.swift +++ b/SwiftMessages/TopBottomAnimation.swift @@ -19,8 +19,6 @@ public class TopBottomAnimation: NSObject, Animator { public let style: Style - open var heightDimension: Dimension? - open var showDuration: TimeInterval = 0.4 open var hideDuration: TimeInterval = 0.2 @@ -92,68 +90,11 @@ public class TopBottomAnimation: NSObject, Animator { container.addSubview(view) view.leadingAnchor.constraint(equalTo: container.leadingAnchor).isActive = true view.trailingAnchor.constraint(equalTo: container.trailingAnchor).isActive = true - let boundaryInsets = (view as? HasBoundaryInsets)?.boundaryInsets ?? BoundaryInsets() switch style { case .top: - view.topAnchor.constraint( - equalTo: container.topAnchor, - constant: -bounceOffset - ).with(priority: .defaultHigh).isActive = true - switch boundaryInsets.bottom { - case .automatic: - break - case .absoluteMargin(let dimension, let boundary): - let otherAnchor: NSLayoutYAxisAnchor - switch boundary { - case .superview: otherAnchor = container.bottomAnchor - case .safeArea: otherAnchor = container.safeAreaLayoutGuide.bottomAnchor - case .margin: otherAnchor = container.layoutMarginsGuide.bottomAnchor - } - view.bottomAnchor.constraint(equalTo: otherAnchor, constant: -dimension) - .with(priority: .defaultHigh) - .isActive = true - case .relativeMargin(let dimension, let boundary): - let otherAnchor: NSLayoutDimension! - switch boundary { - case .superview: otherAnchor = container.heightAnchor - case .safeArea: otherAnchor = container.safeAreaLayoutGuide.heightAnchor - case .margin: otherAnchor = container.layoutMarginsGuide.heightAnchor - } - view.heightAnchor.constraint( - equalTo: otherAnchor, - multiplier: 1 - dimension - ).with(priority: .defaultHigh).isActive = true - } + view.topAnchor.constraint(equalTo: container.topAnchor, constant: -bounceOffset).with(priority: UILayoutPriority(200)).isActive = true case .bottom: - view.bottomAnchor.constraint( - equalTo: container.bottomAnchor, - constant: bounceOffset - ).with(priority: .defaultHigh).isActive = true - switch boundaryInsets.top { - case .automatic: - break - case .absoluteMargin(let dimension, let boundary): - let otherAnchor: NSLayoutYAxisAnchor - switch boundary { - case .superview: otherAnchor = container.topAnchor - case .safeArea: otherAnchor = container.safeAreaLayoutGuide.topAnchor - case .margin: otherAnchor = container.layoutMarginsGuide.topAnchor - } - view.topAnchor.constraint(equalTo: otherAnchor, constant: dimension) - .with(priority: .defaultHigh) - .isActive = true - case .relativeMargin(let dimension, let boundary): - let otherAnchor: NSLayoutDimension! - switch boundary { - case .superview: otherAnchor = container.heightAnchor - case .safeArea: otherAnchor = container.safeAreaLayoutGuide.heightAnchor - case .margin: otherAnchor = container.layoutMarginsGuide.heightAnchor - } - view.heightAnchor.constraint( - equalTo: otherAnchor, - multiplier: 1 - dimension - ).with(priority: .defaultHigh).isActive = true - } + view.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: bounceOffset).with(priority: UILayoutPriority(200)).isActive = true } // Important to layout now in order to get the right safe area insets container.layoutIfNeeded() From 6925ef9f8f19ce7fef2bf3fbe4dcf5fc99d471e0 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Sat, 10 Apr 2021 16:43:36 -0500 Subject: [PATCH 38/77] Fix merge error --- SwiftMessages.xcodeproj/project.pbxproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 95f93353..5103fcdd 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -54,6 +54,7 @@ 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */; }; + 229F778125FAB1E9008C2ACB /* UIWindow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */; }; 22DFC9161EFF30F6001B1CA1 /* CenteredView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */; }; 22DFC9181F00674E001B1CA1 /* PhysicsPanHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */; }; 22E01F641E74EC8B00ACE19A /* MaskingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22E01F631E74EC8B00ACE19A /* MaskingView.swift */; }; @@ -140,6 +141,7 @@ 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = "<group>"; }; + 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+Extensions.swift"; sourceTree = "<group>"; }; 22A2EA6E24EC6CFA00BB2540 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; }; 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = CenteredView.xib; path = Resources/CenteredView.xib; sourceTree = "<group>"; }; 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsPanHandler.swift; sourceTree = "<group>"; }; @@ -209,6 +211,7 @@ children = ( 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */, 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */, + 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */, ); name = Extensions; sourceTree = "<group>"; From b4002f7ec293c426b26b8d1045b5f038cf446f02 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Thu, 3 Jun 2021 10:43:04 -0500 Subject: [PATCH 39/77] Fix Carthage build --- SwiftMessages.podspec | 2 +- iMessageDemo/Podfile | 19 +++++++++++++++++++ iMessageDemo/Podfile.lock | 6 +++--- .../Local Podspecs/SwiftMessages.podspec.json | 4 ++-- iMessageDemo/Pods/Manifest.lock | 6 +++--- .../contents.xcworkspacedata | 7 +++++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++++ .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++++++++ ...ges_SwiftMessages-SwiftMessages-Info.plist | 2 +- .../SwiftMessages/SwiftMessages-Info.plist | 2 +- .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++++++++ 11 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 820b4e9a..a6c018fa 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.0.2' + spec.version = '9.0.3' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } diff --git a/iMessageDemo/Podfile b/iMessageDemo/Podfile index 7c45a63f..7ae17852 100644 --- a/iMessageDemo/Podfile +++ b/iMessageDemo/Podfile @@ -1,6 +1,9 @@ # Uncomment the next line to define a global platform for your project # platform :ios, '9.0' +install! 'cocoapods', + :share_schemes_for_development_pods => false + target 'iMessageDemo' do # Comment the next line if you don't want to use dynamic frameworks use_frameworks! @@ -17,3 +20,19 @@ target 'iMessageExtensionDemo' do pod 'SwiftMessages/AppExtension', :path => "../" end + +post_install do |installer| + # Blow away schemes – the schemes created by CocoaPods break Carthage builds + # because they incluede a SwiftMessages framework that Carthage picks + # over the main SwiftMessages framework. The SwiftMessages framework that gets + # picked is configured for an app extension and doesn't work correctly in an app. + File.directory?(path) + [ + "#{installer.sandbox.root}/Pods.xcodeproj/xcuserdata", + "#{installer.sandbox.root}/Pods.xcodeproj/xcshareddata" + ].each { |path| + if File.directory?(path) + FileUtils.remove_dir(path) + end + } +end diff --git a/iMessageDemo/Podfile.lock b/iMessageDemo/Podfile.lock index 552070e5..b7d82fb3 100644 --- a/iMessageDemo/Podfile.lock +++ b/iMessageDemo/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - SwiftMessages/AppExtension (9.0.1) + - SwiftMessages/AppExtension (9.0.3) DEPENDENCIES: - SwiftMessages/AppExtension (from `../`) @@ -9,8 +9,8 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - SwiftMessages: b71f53eb919887c0273bf43cbc002bd4f0cfb3d6 + SwiftMessages: 077f19126c24033fe24042237ecc20261adb46e4 -PODFILE CHECKSUM: 4cfafdad7d8903d0f4cfadbe05660bcdeff7c9e6 +PODFILE CHECKSUM: dde250cdcd60ccf6ec0a51da5a633d36b9f83a3b COCOAPODS: 1.10.0 diff --git a/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json b/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json index 72a5b097..6d9e93c9 100644 --- a/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json +++ b/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json @@ -1,6 +1,6 @@ { "name": "SwiftMessages", - "version": "9.0.1", + "version": "9.0.3", "license": { "type": "MIT" }, @@ -11,7 +11,7 @@ "summary": "A very flexible message bar for iOS written in Swift.", "source": { "git": "https://github.com/SwiftKickMobile/SwiftMessages.git", - "tag": "9.0.1" + "tag": "9.0.3" }, "platforms": { "ios": "9.0" diff --git a/iMessageDemo/Pods/Manifest.lock b/iMessageDemo/Pods/Manifest.lock index 552070e5..b7d82fb3 100644 --- a/iMessageDemo/Pods/Manifest.lock +++ b/iMessageDemo/Pods/Manifest.lock @@ -1,5 +1,5 @@ PODS: - - SwiftMessages/AppExtension (9.0.1) + - SwiftMessages/AppExtension (9.0.3) DEPENDENCIES: - SwiftMessages/AppExtension (from `../`) @@ -9,8 +9,8 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - SwiftMessages: b71f53eb919887c0273bf43cbc002bd4f0cfb3d6 + SwiftMessages: 077f19126c24033fe24042237ecc20261adb46e4 -PODFILE CHECKSUM: 4cfafdad7d8903d0f4cfadbe05660bcdeff7c9e6 +PODFILE CHECKSUM: dde250cdcd60ccf6ec0a51da5a633d36b9f83a3b COCOAPODS: 1.10.0 diff --git a/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "self:"> + </FileRef> +</Workspace> diff --git a/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEDidComputeMac32BitWarning</key> + <true/> +</dict> +</plist> diff --git a/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..08de0be8 --- /dev/null +++ b/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key> + <false/> +</dict> +</plist> diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist b/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist index 35c2f997..fa5d486a 100644 --- a/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist @@ -13,7 +13,7 @@ <key>CFBundlePackageType</key> <string>BNDL</string> <key>CFBundleShortVersionString</key> - <string>9.0.1</string> + <string>9.0.3</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist index 2687f6bd..364cea2f 100644 --- a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist @@ -15,7 +15,7 @@ <key>CFBundlePackageType</key> <string>FMWK</string> <key>CFBundleShortVersionString</key> - <string>9.0.1</string> + <string>9.0.3</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> diff --git a/iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..08de0be8 --- /dev/null +++ b/iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key> + <false/> +</dict> +</plist> From 3a6fb3f4c2369441f17b340070b7409abe99d021 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Thu, 3 Jun 2021 10:58:48 -0500 Subject: [PATCH 40/77] Update changelog --- CHANGELOG.md | 6 ++++++ iMessageDemo/Podfile.lock | 2 +- iMessageDemo/Pods/Manifest.lock | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08f50bbb..f10c7f2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change Log All notable changes to this project will be documented in this file. +## 9.0.3 + +### Fixes + +* #465 - Fix broken Carthage build. The Carthage build was broken due to the `iMessageDemo` project's use of CocoaPods and the automatically generated `SwiftMessages` framework scheme created by CocoaPods. The podfile was modified to delete this scheme, but Carthage users may need to run `pod install` on the `iMessagesDemo` project, if they have CocoaPods installed, or manually delete the `iMessageDemo/Pods/Pods.xcodeproj/xcuserdata` folder. + ## 9.0.2 ### Fixes diff --git a/iMessageDemo/Podfile.lock b/iMessageDemo/Podfile.lock index b7d82fb3..54bd951e 100644 --- a/iMessageDemo/Podfile.lock +++ b/iMessageDemo/Podfile.lock @@ -11,6 +11,6 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: SwiftMessages: 077f19126c24033fe24042237ecc20261adb46e4 -PODFILE CHECKSUM: dde250cdcd60ccf6ec0a51da5a633d36b9f83a3b +PODFILE CHECKSUM: 2eb9a33592d0c52131c37a9dd169a8c4604ffd7b COCOAPODS: 1.10.0 diff --git a/iMessageDemo/Pods/Manifest.lock b/iMessageDemo/Pods/Manifest.lock index b7d82fb3..54bd951e 100644 --- a/iMessageDemo/Pods/Manifest.lock +++ b/iMessageDemo/Pods/Manifest.lock @@ -11,6 +11,6 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: SwiftMessages: 077f19126c24033fe24042237ecc20261adb46e4 -PODFILE CHECKSUM: dde250cdcd60ccf6ec0a51da5a633d36b9f83a3b +PODFILE CHECKSUM: 2eb9a33592d0c52131c37a9dd169a8c4604ffd7b COCOAPODS: 1.10.0 From af2a69303a8d1f1d9f6fae1bf987ad1d38e7813a Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Thu, 3 Jun 2021 11:33:55 -0500 Subject: [PATCH 41/77] Fix logic that identifies the keyWindow --- CHANGELOG.md | 3 ++- SwiftMessages/UIWindow+Extensions.swift | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f10c7f2c..17f749a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ All notable changes to this project will be documented in this file. ### Fixes -* #465 - Fix broken Carthage build. The Carthage build was broken due to the `iMessageDemo` project's use of CocoaPods and the automatically generated `SwiftMessages` framework scheme created by CocoaPods. The podfile was modified to delete this scheme, but Carthage users may need to run `pod install` on the `iMessagesDemo` project, if they have CocoaPods installed, or manually delete the `iMessageDemo/Pods/Pods.xcodeproj/xcuserdata` folder. +* #466 Alert not shown after Biometry check +* #465 Fix broken Carthage build. The Carthage build was broken due to the `iMessageDemo` project's use of CocoaPods and the automatically generated `SwiftMessages` framework scheme created by CocoaPods. The podfile was modified to delete this scheme, but Carthage users may need to run `pod install` on the `iMessagesDemo` project, if they have CocoaPods installed, or manually delete the `iMessageDemo/Pods/Pods.xcodeproj/xcuserdata` folder. ## 9.0.2 diff --git a/SwiftMessages/UIWindow+Extensions.swift b/SwiftMessages/UIWindow+Extensions.swift index d98c6caf..316fcacd 100644 --- a/SwiftMessages/UIWindow+Extensions.swift +++ b/SwiftMessages/UIWindow+Extensions.swift @@ -13,10 +13,9 @@ extension UIWindow { static var keyWindow: UIWindow? { if #available(iOS 13.0, *) { return UIApplication.shared.connectedScenes - .filter { $0.activationState == .foregroundActive } + .sorted { $0.activationState.sortPriority < $1.activationState.sortPriority } .compactMap { $0 as? UIWindowScene } - .first?.windows - .filter { $0.isKeyWindow } + .compactMap { $0.windows.first { $0.isKeyWindow } } .first } else { return UIApplication.shared.keyWindow @@ -24,3 +23,16 @@ extension UIWindow { } #endif } + +@available(iOS 13.0, *) +private extension UIScene.ActivationState { + var sortPriority: Int { + switch self { + case .foregroundActive: return 1 + case .foregroundInactive: return 2 + case .background: return 3 + case .unattached: return 4 + @unknown default: return 5 + } + } +} From 402984b2171c28038894c73bed4467832041f4c7 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Thu, 3 Jun 2021 12:36:41 -0500 Subject: [PATCH 42/77] =?UTF-8?q?Fix=20467=20-=20don=E2=80=99t=20tell=20th?= =?UTF-8?q?e=20previous=20window=20to=20become=20visible?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SwiftMessages/WindowViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftMessages/WindowViewController.swift b/SwiftMessages/WindowViewController.swift index 96b30095..9c2b721c 100644 --- a/SwiftMessages/WindowViewController.swift +++ b/SwiftMessages/WindowViewController.swift @@ -59,7 +59,7 @@ open class WindowViewController: UIViewController func uninstall() { if window?.isKeyWindow == true { - previousKeyWindow?.makeKeyAndVisible() + previousKeyWindow?.makeKey() } if #available(iOS 13, *) { window?.windowScene = nil From 2187a0c8f8c8a11aa73f05fa915be3cc9c36f240 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Thu, 3 Jun 2021 12:37:54 -0500 Subject: [PATCH 43/77] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17f749a1..d44911cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. ### Fixes +* #467 Lower or equal level window's views disappear upon hide * #466 Alert not shown after Biometry check * #465 Fix broken Carthage build. The Carthage build was broken due to the `iMessageDemo` project's use of CocoaPods and the automatically generated `SwiftMessages` framework scheme created by CocoaPods. The podfile was modified to delete this scheme, but Carthage users may need to run `pod install` on the `iMessagesDemo` project, if they have CocoaPods installed, or manually delete the `iMessageDemo/Pods/Pods.xcodeproj/xcuserdata` folder. From 8cd41df1290aa6f40665eb98aaeb06f59ff3d594 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Tue, 29 Jun 2021 11:29:52 -0500 Subject: [PATCH 44/77] Some minor cleanup --- SwiftMessages/Animator.swift | 4 ++-- SwiftMessages/TopBottomAnimation.swift | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/SwiftMessages/Animator.swift b/SwiftMessages/Animator.swift index 7d924e2d..82074068 100644 --- a/SwiftMessages/Animator.swift +++ b/SwiftMessages/Animator.swift @@ -10,7 +10,7 @@ import UIKit public typealias AnimationCompletion = (_ completed: Bool) -> Void -public protocol AnimationDelegate: class { +public protocol AnimationDelegate: AnyObject { func hide(animator: Animator) func panStarted(animator: Animator) func panEnded(animator: Animator) @@ -58,7 +58,7 @@ public class AnimationContext { } } -public protocol Animator: class { +public protocol Animator: AnyObject { /// Adopting classes should declare as `weak`. var delegate: AnimationDelegate? { get set } diff --git a/SwiftMessages/TopBottomAnimation.swift b/SwiftMessages/TopBottomAnimation.swift index d9f1f3a4..21b0f271 100644 --- a/SwiftMessages/TopBottomAnimation.swift +++ b/SwiftMessages/TopBottomAnimation.swift @@ -19,17 +19,17 @@ public class TopBottomAnimation: NSObject, Animator { public let style: Style - open var showDuration: TimeInterval = 0.4 + public var showDuration: TimeInterval = 0.4 - open var hideDuration: TimeInterval = 0.2 + public var hideDuration: TimeInterval = 0.2 - open var springDamping: CGFloat = 0.8 + public var springDamping: CGFloat = 0.8 - open var closeSpeedThreshold: CGFloat = 750.0; + public var closeSpeedThreshold: CGFloat = 750.0; - open var closePercentThreshold: CGFloat = 0.33; + public var closePercentThreshold: CGFloat = 0.33; - open var closeAbsoluteThreshold: CGFloat = 75.0; + public var closeAbsoluteThreshold: CGFloat = 75.0; public private(set) lazy var panGestureRecognizer: UIPanGestureRecognizer = { let pan = UIPanGestureRecognizer() From 349fec7674f588d7c32b2aa0c55dfe46eb9f071b Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Tue, 29 Jun 2021 13:48:32 -0500 Subject: [PATCH 45/77] Fix warning --- SwiftMessages/KeyboardTrackingView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftMessages/KeyboardTrackingView.swift b/SwiftMessages/KeyboardTrackingView.swift index 69ce6b0b..6af384a6 100644 --- a/SwiftMessages/KeyboardTrackingView.swift +++ b/SwiftMessages/KeyboardTrackingView.swift @@ -8,7 +8,7 @@ import UIKit -public protocol KeyboardTrackingViewDelegate: class { +public protocol KeyboardTrackingViewDelegate: AnyObject { func keyboardTrackingViewWillChange(change: KeyboardTrackingView.Change, userInfo: [AnyHashable : Any]) func keyboardTrackingViewDidChange(change: KeyboardTrackingView.Change, userInfo: [AnyHashable : Any]) } From c5026484ff555db961ec549162e4026b017aa6c5 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Fri, 17 Sep 2021 16:42:06 -0500 Subject: [PATCH 46/77] Work/9.0.4 (#479) * Add dark mode theme * Remove availability check, which is not supported in iOS 15 * Support Xcode 13 (#478) * Remove @available from enum cases * Carthage support * Refactor * Remove unnecessary methods * Code review Co-authored-by: Timothy Moose <tim@swiftkick.it> * Prep for release * Update changelog Co-authored-by: Kohki Miki <giginet.net@gmail.com> --- CHANGELOG.md | 5 + SwiftMessages.podspec | 2 +- SwiftMessages.xcodeproj/project.pbxproj | 10 +- SwiftMessages/MessageView.swift | 72 +- .../SwiftMessages.Config+Extensions.swift | 2 +- SwiftMessages/SwiftMessages.swift | 17 +- SwiftMessages/WindowScene.swift | 9 + iMessageDemo/Podfile.lock | 2 +- iMessageDemo/Pods/Manifest.lock | 2 +- .../Pods/Pods.xcodeproj/project.pbxproj | 900 +++++++++--------- 10 files changed, 550 insertions(+), 471 deletions(-) create mode 100644 SwiftMessages/WindowScene.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index d44911cf..ed087150 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log All notable changes to this project will be documented in this file. +## 9.0.4 + +* #471 Xcode 13 issue - Enum cases with associated values cannot be marked potentially unavailable with '@available' +* Improve colors for dark mode. + ## 9.0.3 ### Fixes diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index a6c018fa..688f100f 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.0.3' + spec.version = '9.0.4' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 5103fcdd..b01d9c2f 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 0797E40E26EE12B400691606 /* WindowScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0797E40D26EE12B400691606 /* WindowScene.swift */; }; 220655121FAF82B600F4E00F /* MarginAdjustable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */; }; 220D386E2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 220D386D2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift */; }; 224FB69921153B440081D4DE /* CALayer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224FB69821153B440081D4DE /* CALayer+Extensions.swift */; }; @@ -54,7 +55,7 @@ 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */; }; - 229F778125FAB1E9008C2ACB /* UIWindow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */; }; + 229F778125FAB1E9008C2ACB /* UIWindow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */; }; 22DFC9161EFF30F6001B1CA1 /* CenteredView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */; }; 22DFC9181F00674E001B1CA1 /* PhysicsPanHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */; }; 22E01F641E74EC8B00ACE19A /* MaskingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22E01F631E74EC8B00ACE19A /* MaskingView.swift */; }; @@ -94,6 +95,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 0797E40D26EE12B400691606 /* WindowScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowScene.swift; sourceTree = "<group>"; }; 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarginAdjustable+Extensions.swift"; sourceTree = "<group>"; }; 220D386D2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftMessages.Config+Extensions.swift"; sourceTree = "<group>"; }; 224FB69821153B440081D4DE /* CALayer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CALayer+Extensions.swift"; sourceTree = "<group>"; }; @@ -141,7 +143,7 @@ 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = "<group>"; }; - 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+Extensions.swift"; sourceTree = "<group>"; }; + 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+Extensions.swift"; sourceTree = "<group>"; }; 22A2EA6E24EC6CFA00BB2540 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; }; 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = CenteredView.xib; path = Resources/CenteredView.xib; sourceTree = "<group>"; }; 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsPanHandler.swift; sourceTree = "<group>"; }; @@ -211,7 +213,7 @@ children = ( 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */, 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */, - 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */, + 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */, ); name = Extensions; sourceTree = "<group>"; @@ -304,6 +306,7 @@ 2298C2041EE47DC900E2DDC1 /* Weak.swift */, 22F27950210CE25900273E7F /* CornerRoundingView.swift */, 225304652293000C00A03ACF /* KeyboardTrackingView.swift */, + 0797E40D26EE12B400691606 /* WindowScene.swift */, ); name = Base; sourceTree = "<group>"; @@ -555,6 +558,7 @@ 86BBA9081D5E040C00FE8F16 /* Error.swift in Sources */, 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */, 86589D471D64B6E40041676C /* BaseView.swift in Sources */, + 0797E40E26EE12B400691606 /* WindowScene.swift in Sources */, 225304622290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift in Sources */, 86BBA9071D5E040C00FE8F16 /* MarginAdjustable.swift in Sources */, 867BED211D622793005212E3 /* BackgroundViewable.swift in Sources */, diff --git a/SwiftMessages/MessageView.swift b/SwiftMessages/MessageView.swift index d9be31d9..c71141a6 100644 --- a/SwiftMessages/MessageView.swift +++ b/SwiftMessages/MessageView.swift @@ -251,24 +251,72 @@ extension MessageView { */ public func configureTheme(_ theme: Theme, iconStyle: IconStyle = .default) { let iconImage = iconStyle.image(theme: theme) + let backgroundColor: UIColor + let foregroundColor: UIColor + let defaultBackgroundColor: UIColor + let defaultForegroundColor: UIColor switch theme { case .info: - let backgroundColor = UIColor(red: 225.0/255.0, green: 225.0/255.0, blue: 225.0/255.0, alpha: 1.0) - let foregroundColor = UIColor.darkText - configureTheme(backgroundColor: backgroundColor, foregroundColor: foregroundColor, iconImage: iconImage) + defaultBackgroundColor = UIColor(red: 225.0/255.0, green: 225.0/255.0, blue: 225.0/255.0, alpha: 1.0) + defaultForegroundColor = UIColor.darkText case .success: - let backgroundColor = UIColor(red: 97.0/255.0, green: 161.0/255.0, blue: 23.0/255.0, alpha: 1.0) - let foregroundColor = UIColor.white - configureTheme(backgroundColor: backgroundColor, foregroundColor: foregroundColor, iconImage: iconImage) + defaultBackgroundColor = UIColor(red: 97.0/255.0, green: 161.0/255.0, blue: 23.0/255.0, alpha: 1.0) + defaultForegroundColor = UIColor.white case .warning: - let backgroundColor = UIColor(red: 238.0/255.0, green: 189.0/255.0, blue: 34.0/255.0, alpha: 1.0) - let foregroundColor = UIColor.white - configureTheme(backgroundColor: backgroundColor, foregroundColor: foregroundColor, iconImage: iconImage) + defaultBackgroundColor = UIColor(red: 246.0/255.0, green: 197.0/255.0, blue: 44.0/255.0, alpha: 1.0) + defaultForegroundColor = UIColor.white case .error: - let backgroundColor = UIColor(red: 249.0/255.0, green: 66.0/255.0, blue: 47.0/255.0, alpha: 1.0) - let foregroundColor = UIColor.white - configureTheme(backgroundColor: backgroundColor, foregroundColor: foregroundColor, iconImage: iconImage) + defaultBackgroundColor = UIColor(red: 249.0/255.0, green: 66.0/255.0, blue: 47.0/255.0, alpha: 1.0) + defaultForegroundColor = UIColor.white } + if #available(iOS 13.0, *) { + switch theme { + case .info: + backgroundColor = UIColor { + switch $0.userInterfaceStyle { + case .dark, .unspecified: return UIColor(red: 125/255.0, green: 125/255.0, blue: 125/255.0, alpha: 1.0) + case .light: fallthrough + @unknown default: + return defaultBackgroundColor + } + } + foregroundColor = .label + case .success: + backgroundColor = UIColor { + switch $0.userInterfaceStyle { + case .dark, .unspecified: return UIColor(red: 55/255.0, green: 122/255.0, blue: 0/255.0, alpha: 1.0) + case .light: fallthrough + @unknown default: + return defaultBackgroundColor + } + } + foregroundColor = .white + case .warning: + backgroundColor = UIColor { + switch $0.userInterfaceStyle { + case .dark, .unspecified: return UIColor(red: 239/255.0, green: 184/255.0, blue: 10/255.0, alpha: 1.0) + case .light: fallthrough + @unknown default: + return defaultBackgroundColor + } + } + foregroundColor = .white + case .error: + backgroundColor = UIColor { + switch $0.userInterfaceStyle { + case .dark, .unspecified: return UIColor(red: 195/255.0, green: 12/255.0, blue: 12/255.0, alpha: 1.0) + case .light: fallthrough + @unknown default: + return defaultBackgroundColor + } + } + foregroundColor = .white + } + } else { + backgroundColor = defaultBackgroundColor + foregroundColor = defaultForegroundColor + } + configureTheme(backgroundColor: backgroundColor, foregroundColor: foregroundColor, iconImage: iconImage) } /** diff --git a/SwiftMessages/SwiftMessages.Config+Extensions.swift b/SwiftMessages/SwiftMessages.Config+Extensions.swift index 9682b5b9..ac0475da 100644 --- a/SwiftMessages/SwiftMessages.Config+Extensions.swift +++ b/SwiftMessages/SwiftMessages.Config+Extensions.swift @@ -20,7 +20,7 @@ extension SwiftMessages.Config { @available (iOS 13.0, *) var windowScene: UIWindowScene? { switch presentationContext { - case .windowScene(let scene, _): return scene + case .windowScene(let scene, _): return scene as? UIWindowScene default: #if SWIFTMESSAGES_APP_EXTENSIONS return nil diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index dfae859c..7c0042f5 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -77,10 +77,10 @@ open class SwiftMessages { of any message view that adopts the `MarginInsetting` protocol (as `MessageView` does) to account for the status bar. As of iOS 13, windows can no longer cover the status bar. The only alternative is to set `Config.prefersStatusBarHidden = true` - to hide it. + to hide it. The `WindowScene` protocol works around the change in Xcode 13 that prevents + using `@availability` attribute with `enum` cases containing associated values. */ - @available(iOS 13.0, *) - case windowScene(_: UIWindowScene, windowLevel: UIWindow.Level) + case windowScene(_: WindowScene, windowLevel: UIWindow.Level) /** Displays the message view under navigation bars and tab bars if an @@ -248,7 +248,16 @@ open class SwiftMessages { Specifies how the container for presenting the message view is selected. The default is `.Automatic`. */ - public var presentationContext = PresentationContext.automatic + public var presentationContext = PresentationContext.automatic { + didSet { + if case .windowScene = presentationContext { + guard #available(iOS 13.0, *) else { + assertionFailure("windowScene is not supported below iOS 13.0.") + return + } + } + } + } /** Specifies the duration of the message view's time on screen before it is diff --git a/SwiftMessages/WindowScene.swift b/SwiftMessages/WindowScene.swift new file mode 100644 index 00000000..a3bbb4ca --- /dev/null +++ b/SwiftMessages/WindowScene.swift @@ -0,0 +1,9 @@ +import Foundation +import UIKit + +/// A workaround for the change in Xcode 13 that prevents using `@availability` attribute +/// with `enum` cases containing associated values. +public protocol WindowScene {} + +@available(iOS 13.0, *) +extension UIWindowScene: WindowScene {} diff --git a/iMessageDemo/Podfile.lock b/iMessageDemo/Podfile.lock index 54bd951e..7162a91f 100644 --- a/iMessageDemo/Podfile.lock +++ b/iMessageDemo/Podfile.lock @@ -13,4 +13,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 2eb9a33592d0c52131c37a9dd169a8c4604ffd7b -COCOAPODS: 1.10.0 +COCOAPODS: 1.10.1 diff --git a/iMessageDemo/Pods/Manifest.lock b/iMessageDemo/Pods/Manifest.lock index 54bd951e..7162a91f 100644 --- a/iMessageDemo/Pods/Manifest.lock +++ b/iMessageDemo/Pods/Manifest.lock @@ -13,4 +13,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 2eb9a33592d0c52131c37a9dd169a8c4604ffd7b -COCOAPODS: 1.10.0 +COCOAPODS: 1.10.1 diff --git a/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj b/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj index 468092a5..0d6bbc21 100644 --- a/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj +++ b/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj @@ -7,106 +7,107 @@ objects = { /* Begin PBXBuildFile section */ - 00468531530F8A70E3D83622BD482026 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E6941E59EF0D89949E3DF3D89488430 /* Weak.swift */; }; - 0303F738260F2C9BAE20B79DE84E82BC /* PhysicsPanHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2337E6D5F621F3CE9A1E3761984EBE87 /* PhysicsPanHandler.swift */; }; - 0B42A04122166EAD384BCE37FD450FAF /* MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8901520225CE89F44E6DE88688F29C10 /* MessageView.swift */; }; - 0CE00BF7FB0F6376D89B0AFF1CFD7510 /* PassthroughView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C557E1DC95AFA417E94ED01301F9F2 /* PassthroughView.swift */; }; - 0E7AE1B3CE2734B39ACCE812B4320B44 /* MarginAdjustable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B91AD9D9E743D17D553D48103BE27C46 /* MarginAdjustable+Extensions.swift */; }; - 138A7742F76993FB9EE3555FD2808562 /* successIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = A80433B71162112A79043CB64261DB51 /* successIconLight.png */; }; - 16047C447B00FAA7F42764EC4167C33B /* NSLayoutConstraint+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0970322A5DD8B4A8373C35ED051DE156 /* NSLayoutConstraint+Extensions.swift */; }; - 1F4159921A25C7B2A0E9C587387D829C /* errorIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1B04615682E8B787C964824435BC6616 /* errorIconLight@2x.png */; }; - 1F6162906845BE72A5BCDAF14D6E14B9 /* warningIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 4512DEEA328AB0AAA95D77C84C89E02C /* warningIconSubtle.png */; }; - 2181E713FC7C00EE871FDA6CB62C7E8C /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5607E285A85AC7163B0B8FD447FD27E /* Theme.swift */; }; - 2558CABB502ED605BC21DCFC55A9C0B7 /* MessageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = AE62AA801971C530345349D18AFCCB82 /* MessageView.xib */; }; - 2B23A9DFDAACFE9C0AD5EB6899E63475 /* infoIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4FE466AC4123CDAE9FDA9FCF4FB9CC60 /* infoIconSubtle@2x.png */; }; - 33785D52B8888C2EA02BD0495408E352 /* successIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A865FFBAE49EF66A35CB9D709E8D7E /* successIconLight@3x.png */; }; - 3505AB28DBFA49FBE5C8250F3E067E60 /* KeyboardTrackingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536660614870EA0E051BF6BDDF495798 /* KeyboardTrackingView.swift */; }; - 365594AAFDD4EE947EB33E6E86A8578E /* errorIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = A850F76D7E3FEDC20FFB877454069171 /* errorIconSubtle.png */; }; - 425F2D4CE95436680D77C263FF15221B /* SwiftMessages_SwiftMessages.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages_SwiftMessages.bundle */; }; - 4267FACE20717FF3F51C2ACAB8C395A4 /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0D0E8B0020635F606875DD02735C502 /* BaseView.swift */; }; - 44150A4B5B2D251FCBB6CA07DC9872B5 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 267E35F9851AAE50DFB8FA0DCA7F2980 /* Animator.swift */; }; - 447E8A096C1ABD2E0AC9674E65A827E3 /* warningIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 0259757860B26C6072E2640B84EC6D45 /* warningIcon.png */; }; - 44C0F194D748EE88027414A5B2094E9B /* successIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8155ED78358FA5CF39089176FBDE501 /* successIcon@3x.png */; }; - 461760E2818D72B948B60B4835E7B1ED /* NSBundle+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FCF161BD9F1C2CAAFBCADE5E59BD3FD /* NSBundle+Extensions.swift */; }; - 462CDC24C5C8DD6905C4112B6B4BD2ED /* successIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = FC73E6C784AF6CA1F956F57F82ED2803 /* successIcon.png */; }; + 00764FFD14D83F4ABEC0D4D53D48080A /* SwiftMessages-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C6E00017F9E79F6D4926E9CB43A66DF /* SwiftMessages-dummy.m */; }; + 02905CCF79B22A773CD0BA32EDB9648A /* AccessibleMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0201BC51C7CA061016B619400691A139 /* AccessibleMessage.swift */; }; + 05D9CBEC9488BAA2962B174703D25218 /* PassthroughWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A331C2E0BE2AE2118D65AA1F12519F2 /* PassthroughWindow.swift */; }; + 0C55441C4B8356AC1244EED7684E1783 /* MaskingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D69BE188B82D84ED23AC4E27BAB61D /* MaskingView.swift */; }; + 11DE7052A0A78D6E27D8D129D413DAF6 /* errorIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 7100245A2722BD53D5B3927ED649069F /* errorIconLight.png */; }; + 13620BA62A66C8C6F9345341BCD111ED /* KeyboardTrackingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90AC342C6F09BF7715D4FB95512DD68A /* KeyboardTrackingView.swift */; }; + 1662CF43016AFC375200E466F130D90E /* warningIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 860D833A7A1B108A89ED34AD74778AC0 /* warningIconSubtle.png */; }; + 28F2E02536C48A4B661D6D8AAFB5D37E /* CornerRoundingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 007ACA6F89C6C856F78352A086F3B8EA /* CornerRoundingView.swift */; }; + 30D023ABC2D1CFC829CF04360768B7F8 /* StatusLine.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1E2FE4DB6869F330F19A3A5459AAFFFB /* StatusLine.xib */; }; + 34CB62900FA4AAC84745C7E958657648 /* errorIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D30B2BF71F9D2C63C2D202C99827CDC1 /* errorIconLight@2x.png */; }; + 3A8B97D9210D1E2BEED5E1159BE7E748 /* warningIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = C56AB83FDAB8D6A1328E7EECCAD99A69 /* warningIconLight.png */; }; + 3BFC9F0FAF0757A2D3574ED4E4100D57 /* CALayer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 467EAD44C7F625F384822180F004E64F /* CALayer+Extensions.swift */; }; + 4256FC87C833154DCDEE84CD98F910D7 /* Identifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFD31968BF9DF7A9E25A136DF254F3A9 /* Identifiable.swift */; }; 46CCA4DDFDBBDD2A9426BB96C08E4255 /* Pods-iMessageExtensionDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F40CA14AD738DD186B4DA8FD14AE5BD /* Pods-iMessageExtensionDemo-dummy.m */; }; - 492F085489FCAB0EEBE74B098F7D3F4D /* StatusLine.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7A6801849037A728E9BC50E06CE8AD2F /* StatusLine.xib */; }; - 4C78ED4E1780F5609E25CE03429C1DE4 /* errorIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 848251807107C20960A3DABAB27F7475 /* errorIconLight@3x.png */; }; - 4DB5D1FB08693DDDC32BCF19CC1B1AA0 /* warningIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 874D31DE863C88B1D699E1EBFBE0641B /* warningIconLight@2x.png */; }; - 4E703B2A80C64CF1142872BE31263940 /* errorIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 0892E032AE12339D1AD84BDCC78A3C07 /* errorIconLight.png */; }; - 4E9CCFC43646B6CDBE3B787AB09A0147 /* CardView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 42F1E753E61B6EDED3908AC66994649C /* CardView.xib */; }; - 5260BD3289BAC54A20457099C4A57EFF /* errorIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 9D1FEAC04417D847EDC10783E054988F /* errorIcon.png */; }; - 52F4ED7F78829270B2AFE5EDBA9EEE2F /* UIEdgeInsets+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9A13E69643D651322647C28E3F9E9C9 /* UIEdgeInsets+Extensions.swift */; }; + 47F1E9964F1112D0E8F0FF8C25204E2F /* SwiftMessages_SwiftMessages.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages_SwiftMessages.bundle */; }; + 4889E21A2024267A944084FB851200B5 /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7EE64CFE0084CF5213A03AF29A668ED /* BaseView.swift */; }; + 4B907B48F27F55DF65CC1553C7C26942 /* infoIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 730840765E737D45772EBE66DB8A6D2E /* infoIconLight.png */; }; + 4B9459A11E2A1D65AE3224CF468AE8CA /* warningIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7C4DF53A4B44C246968618BF25962786 /* warningIconLight@3x.png */; }; + 4E82DE4069FECF20D0E29CB06A0FCFB6 /* SwiftMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC6264350B8D100D5B5C5EEEC316933D /* SwiftMessages.swift */; }; + 531825CE7041C5C1BA684BDA9C8972A3 /* UIEdgeInsets+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36F7B24601DF4C00B14EC8CE2D4A48DC /* UIEdgeInsets+Extensions.swift */; }; 560A2B1056FEFE42AC6524A2A1742CA2 /* Pods-iMessageExtensionDemo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CAB201AD00CAB811B045E2FFB5C03A8 /* Pods-iMessageExtensionDemo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 57072960EA4F0D307171ED90697D3FAF /* TabView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B7FD0618783A3E6B90D3A3323633959F /* TabView.xib */; }; - 5720D965B3CE67653082137053FBEC9C /* infoIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C110C924ED12D2D32ECC27503018A31 /* infoIconLight.png */; }; - 5750C24C3A9CAE11C7E36B37434912D0 /* MaskingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CF61FDEFE095F0486E9914F2262ADB9 /* MaskingView.swift */; }; - 5DF3F4808ED4A6932839C11A5D742B93 /* successIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 54B278C80D821C120FA70ABB6CAF1F46 /* successIconSubtle@3x.png */; }; - 6320AE79D41E8D1F52AF66A670542561 /* CornerRoundingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F8D7902822221456B697BB41111E450 /* CornerRoundingView.swift */; }; - 64595C731B826EB19E9757D524E0BF76 /* warningIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2CFBBC25592C97C925B6F81B53BE57CB /* warningIcon@3x.png */; }; - 683A7897D1E9A73F4717198B1C054D29 /* errorIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 60268FE48AA4DC9FD5060B1E5CE68453 /* errorIcon@2x.png */; }; - 6A539682FDDA0E5DA23E1B5F2BA133C1 /* errorIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6DEAADC09FEB1A8D5B90108103EE478 /* errorIcon@3x.png */; }; - 6C7DAA6A68AFDACD67F2C127CEF4DD6F /* UIWindow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 397C8F928170138667B9326F9655D75D /* UIWindow+Extensions.swift */; }; - 755DA479621A9D2BB8B84540DE648A7A /* warningIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 667DECE93ABCC6869A071FFEB0F83EA5 /* warningIconSubtle@3x.png */; }; - 7ACCA07CCFD868899D61F4B4AE5774DB /* infoIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B7213B7DC5432DA2B272F25E17AA364 /* infoIconSubtle@3x.png */; }; + 56F9865D99C4FADB8FC83CA548F82110 /* successIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 17ADABD24F805C5F7FF62167E7ABEF0A /* successIconSubtle@3x.png */; }; + 5B9F8D117AF7BEDDB511EF475FA25995 /* infoIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 48DC3BADDA3A20F2AEB8585117DAFA0D /* infoIcon@3x.png */; }; + 5CA294C8D3BBC986CF0703D4E2A28687 /* SwiftMessages.Config+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A16E25077F8D76288BE678E6AC1C884 /* SwiftMessages.Config+Extensions.swift */; }; + 61548914728141D77F87E31B3911CE7E /* successIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 91D9224F29E092950BADC27C979E10CC /* successIconSubtle@2x.png */; }; + 62B05E0AC13A614A2F8D8A1BE9B514B3 /* infoIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = F9CDB54E629D60FF881DF27B949F4C2D /* infoIconSubtle.png */; }; + 632538BAE98BBFD6CED58844B7611C24 /* MarginAdjustable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C8214A441D845A4A4DD6570FD5D458F /* MarginAdjustable+Extensions.swift */; }; + 6685298EC64F73060F5DB1A841375069 /* warningIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8AD355ED684A939F2A4E333F95E8AC31 /* warningIconSubtle@2x.png */; }; + 668EDAB86421216BEF7D3F932851A834 /* errorIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 468D9889455DE51BD5BBC2360BDBB877 /* errorIconSubtle@2x.png */; }; + 6A933CC66558A1FB0AB0BC76F9807E71 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF65ECDAFAD03A79B5571C6F66D8F35 /* TopBottomAnimation.swift */; }; + 755898E0E511FC5AE881403BEF2A02FC /* successIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D032FCFAE6607CF878AA2F35EF93146C /* successIcon@3x.png */; }; + 7905F28CF56E06626475EBA3EB73D905 /* MarginAdjustable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68834C60D0C5EA751E9F12E427C5FFE /* MarginAdjustable.swift */; }; + 7B352022AFCAA5C364E1E2F61290628E /* MessageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B8A4CCB4B08D2D3BE586212AB4167DC2 /* MessageView.xib */; }; 7BC52E6F0D9D19B05E62E623E53FCE82 /* Pods-iMessageDemo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D0ECE831FB5E0EE1D68E837671320C7 /* Pods-iMessageDemo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7E5ADF1F3B6849D5A0DF8E2B9C1861C5 /* PhysicsAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE3BED1799B2F867F5C984C2A051E36A /* PhysicsAnimation.swift */; }; - 8148CD8F2B38FB38B7B9CCC12E93ECFB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; - 89ACEF0F9E524BD21D6C2460FEC375F8 /* warningIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = ED86D7B42F55040DCE162653FB3C7EDB /* warningIconSubtle@2x.png */; }; - 966B9C1EE6B73E430F03D51A4FD26D20 /* MarginAdjustable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6C56947CAF8EFCC7858E1E2F1273427 /* MarginAdjustable.swift */; }; - 9CEE0E569456D932AA34329D2038DF98 /* SwiftMessagesSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFFDB7DDC6B6B064B9D12281E2531BFA /* SwiftMessagesSegue.swift */; }; - 9E3D4CA932041E99B6FD56D4E79A726F /* SwiftMessages-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C614EECDDFE644AF0BF7CB16A3D74404 /* SwiftMessages-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9FFE65CB6E825ECAE4838D53E7BA4C06 /* infoIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4412F313361EFEE7A0193533A5AC5999 /* infoIconLight@3x.png */; }; - A11E7A379B288CCA3AE6785B83FA4316 /* AccessibleMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDDAF8A2C45FDDDFD5AFA59203137551 /* AccessibleMessage.swift */; }; - A1734DB0A8A558B2397AF54E63F64416 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8341EF04E2B20C2BF6D4AF2240F80A56 /* Error.swift */; }; + 80DE92140CF5AFB5224643FA952EFDEA /* successIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 52F1CA85E0EED7D94FE0036BC92EB3EC /* successIconLight.png */; }; + 8F1BAB73C85D58C56F55E91573C2E7EF /* infoIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = E41BFEB1BFF85793C0DB85F95184B752 /* infoIcon.png */; }; + 926907C8DCE76101AF5CB470DB7797D7 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88D73E42D996B226222A4EBA46F7DC6D /* Weak.swift */; }; + 934A8FA91D6518CB70273B73F8038ECA /* MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778F6E19CE49B8EDBAC2FCCD8195A55B /* MessageView.swift */; }; + 946185C05E253C9E47ABCD9EDE7E14D1 /* warningIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 29A39558830996C4F54686A1748B74B1 /* warningIcon@2x.png */; }; + 94B459D6CBA2A01D2B8174D138C30920 /* UIWindow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 753B78926D6BB175E96AB6E6F3514E87 /* UIWindow+Extensions.swift */; }; + 95DD12BBA763163407787AB32AAF8E56 /* successIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = A342E145FED9CD8DB4F464D110203E7C /* successIcon.png */; }; + 9B1E91097B4BD539EBCBBCC3C62CB75A /* errorIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = DEC0A6AE07C3285CA508F8FA3F4FE27D /* errorIcon.png */; }; + 9B1F7A4183F57B0AA9DD02624BD8855B /* PhysicsPanHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDEF50CAF615897F7A8540579B445634 /* PhysicsPanHandler.swift */; }; + 9B89868BA12CC4E1D9F116F663E56695 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24021DCE87BE9746D1DFB436C0A3AF7A /* Theme.swift */; }; + 9CFE7FFD7DDE28FCDA72647F2DB82837 /* infoIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 45844D489A130BA91E91E7CDD4969862 /* infoIconSubtle@2x.png */; }; + 9DA2F2EED5C99045AF44FF410A012F9D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; + 9DBD1955C7C621D9DCBE03D2161C91A9 /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D261B7BE0088C26BF6744F27B894492A /* UIViewController+Extensions.swift */; }; + 9F0473806FD530165403E47E834790C2 /* CenteredView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 787EE6DA4FBC3BF85ED2CF0BB6EBF494 /* CenteredView.xib */; }; + 9FA48348FB5F41070356A75237367D6D /* TabView.xib in Resources */ = {isa = PBXBuildFile; fileRef = EABF0CEB87991D02E13306975A8E80BB /* TabView.xib */; }; + A67A9ADFBCB364FCEF1BD92FF20B285C /* CardView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 705B5AF043D00B6538599B4EB1ECD77C /* CardView.xib */; }; A9EB0C8E49AB748B05CF7941ACAF8475 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; - AC4F13F50EB63B484292D67692BC1F9D /* successIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 1DC54BB09EFDFEDE11F484FE73BEDC60 /* successIconSubtle.png */; }; - B2862C6DDAA6543BB2C8F4541F044564 /* SwiftMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3216CF40D770C387D45C3B4AF2CC9E0 /* SwiftMessages.swift */; }; - B2CC8FF0F9FF3FE929180CDB32B69F18 /* infoIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F7004673F1B51EEC365B32F0E060E564 /* infoIcon@2x.png */; }; - B42A7A38C8014DBDE2632B909F71C355 /* successIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 62755A788F910CA88887B6F63BBC545F /* successIcon@2x.png */; }; - B60094A8D1343B7351F0EF9C51F2F0DB /* infoIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 337B3108412E3812254B85BCC4F90EB8 /* infoIcon@3x.png */; }; - BB16D1E73A5D6B27DC4212926986107F /* warningIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BFEF746702215C33B51BEE64C4E48F0A /* warningIcon@2x.png */; }; - BBFE3BAFFCE67F4EACE0C67A7B7FFC3A /* successIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0B3A169D83BDA3613A661845D1607FC0 /* successIconSubtle@2x.png */; }; - BC4618CE535404A9540D4D110B5767A1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 396FCF260E9C2B3F11080A91E3D72334 /* TopBottomAnimation.swift */; }; - BDCF9C5E4F88B2B0AB6D4595E5A281E1 /* successIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F898B2AC5C3404C266BBCA3B6D22B5E4 /* successIconLight@2x.png */; }; + A9FFA668A7F81F50FBDCDCE26E891C8B /* errorIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = E0E4D99C4F78B9BA011D83FE63EE0946 /* errorIcon@3x.png */; }; + AC0A9B473B11FFF4BDEC0A0598795843 /* WindowViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9AA0E820F1C1AA219C066370332845A /* WindowViewController.swift */; }; + AD7F228AE0628DAAE4497493335D2BF7 /* SwiftMessages-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CBEAC9D0EF4113C3FD3B15F511A92D0 /* SwiftMessages-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + ADA044C43E517C5F0603B2A0AFB19860 /* successIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 760BFB41B33B6ED91B3FFD68D39083A0 /* successIconLight@2x.png */; }; + ADA91E8F5FDCD2EEC3D3B18A5B375C2C /* errorIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DF3DE135AB5C5C789CABAECC704CE907 /* errorIcon@2x.png */; }; + ADE48B746D5BB28EC33B403E1E12E0FE /* infoIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E936107A7CF9821DCBFFAF50D916F1E6 /* infoIcon@2x.png */; }; + AF34F903519AF36E07A90EF1BD703777 /* WindowScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8DEFE9675E5359A46A443182F127F06 /* WindowScene.swift */; }; + B02B2EAB7B8662AA27D91403BF9AAF36 /* warningIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = A0EE84E98A10805A2D64B836C465ED11 /* warningIconSubtle@3x.png */; }; + B4D338F85183163DC8CAB8A5864C9015 /* infoIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 676F359BE8561CF7512DB8B42CD7873A /* infoIconLight@3x.png */; }; + B520EDE98BD17CE5676F52A77139A933 /* NSLayoutConstraint+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6924EB5FC7236837637AE8F409000A /* NSLayoutConstraint+Extensions.swift */; }; + B679ED0F79CAF552C081588F3B63B91A /* warningIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0038C9A582787F9882258E8D1080EACF /* warningIcon@3x.png */; }; + C11CE75FD2DFCDF3B72D8D16280A2054 /* successIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 79D34B3C6875DA0279CB934C84CD000B /* successIcon@2x.png */; }; C384FB76A48C06F7581D0F7850F2F4F1 /* Pods-iMessageDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 14BF989232A1D55A0FDAAB70B5A8E1BF /* Pods-iMessageDemo-dummy.m */; }; C3CDAED707B153A58674CB1AC4A33FB2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; - C4598A458697C49C961BFDCD090B3A8F /* infoIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 06F2F626BE8417F1806CC5B17F210C90 /* infoIconSubtle.png */; }; - C5FFE932D5EBE2CC8F2ABFEA893D8E9C /* infoIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 70E7AB099F856140EF93D5B94A967418 /* infoIcon.png */; }; - C6E73F201545CF5ED055C69CD4DB2EFF /* warningIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C17CFEF9B761A322945F74D86CA88036 /* warningIconLight@3x.png */; }; - C8F46E0A5853739D3F632B4828FDE9CC /* PassthroughWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 382E6375390EBB09F829519F8ACCB7D7 /* PassthroughWindow.swift */; }; - CCF5CC8F6022DFD410DDCC99A90D58B0 /* warningIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 79E38069364BC5DF4EA88F352E28B242 /* warningIconLight.png */; }; - D49E06426C51C49E9058371138972A69 /* CALayer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B5EF40CEC1F6DB23F428DC159D4BC2 /* CALayer+Extensions.swift */; }; - D61D59BCDFD2C3C7993CFE883DE60692 /* infoIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6516EE9BFCB9C53C151359F9D0247562 /* infoIconLight@2x.png */; }; - D8BDC20F1566606BF64001B6E96B14B6 /* errorIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 453BC098B6A052020C40DE576F684C7B /* errorIconSubtle@3x.png */; }; - D9077478C2FCD7C3DD1EBE9373281728 /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15C4C88778A19C193D1EC77FA77BAE4C /* UIViewController+Extensions.swift */; }; - E88597F65A00A5AF50EEF2ABA2392B2F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */; }; - E94E8711BDDA31B178AA032D3346C307 /* BackgroundViewable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAB58A9F688DD39112E6CDF20C8969C0 /* BackgroundViewable.swift */; }; - EDA146BF3FF59593677F8B2AA785D8A5 /* errorIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3C313FB1D33EF4B477FD5D3D6179A8BE /* errorIconSubtle@2x.png */; }; - F27E3EEAFDDAA6CB4E7407D6A46DAA5D /* CenteredView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3DF091E68C4659506DB08B0876BD274C /* CenteredView.xib */; }; - F50FE2EE47422AD39AC8F7F115081E7E /* SwiftMessages.Config+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3C32E945AE3E6394EF85CD6BEC714B4 /* SwiftMessages.Config+Extensions.swift */; }; - F5642C087197B9033252FF10FBA92B59 /* WindowViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8566413BFA3FE6827E63E30515C9B3 /* WindowViewController.swift */; }; - FA6CA270F521DF68A75E527954A2DDAD /* SwiftMessages-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A2F9031B7FA82A17F04D4403091DF836 /* SwiftMessages-dummy.m */; }; - FCB6832EB4D32EF085E770E8B4A9BC2C /* Identifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C0DE01AB7D0935933E7AFBDF2945814 /* Identifiable.swift */; }; - FF01BC94FADD5A72282AEE043DF523A7 /* Presenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A965DD26246DCA8CE39FBAB348ABA24 /* Presenter.swift */; }; + C418A50F3C321227B0C6BE1D793680D4 /* successIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = FA199E6F18AB8900B5400EBA0EB32765 /* successIconLight@3x.png */; }; + C739607C022819840C267A0B4A7B2FD9 /* SwiftMessagesSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF27E3EF103BACDEE8CA842B2C90C8CA /* SwiftMessagesSegue.swift */; }; + C826D41BE5AF283B12C122AEF9640C99 /* infoIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C9F5DBB6D77B1E61E9BB1A722A4E1823 /* infoIconSubtle@3x.png */; }; + CC9369D0A5F8715733A4D517E45A3B63 /* infoIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8315EA451FE61625920FEF68174A0D22 /* infoIconLight@2x.png */; }; + CD480EEF400EC9B894F3292506BF0179 /* successIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = B031268635405AA009D05130C0FC253C /* successIconSubtle.png */; }; + D34D8255545B84A38C98D2DBB2F12CC5 /* PassthroughView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E03CBB908F2EC39AA5DA7AF04E1BDDD6 /* PassthroughView.swift */; }; + DE23509CED3A1E62F60E7E4BD6D38A35 /* BackgroundViewable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C706F1F1C6B3CE84445485C8577D5388 /* BackgroundViewable.swift */; }; + DECF1F62709D95EF5B48628A97B3CF98 /* warningIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 3259F99D03B6D738D7F47A625E7BD3BE /* warningIcon.png */; }; + E70A6E572A6DD457A766908E3ADCF49B /* errorIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = C787DA4E67B952C984FF5B065E0A2FF7 /* errorIconSubtle.png */; }; + E8174481BFB4559462F82062D85C0376 /* warningIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FFB0D50D01FFFA3FC2099E395029AE68 /* warningIconLight@2x.png */; }; + ECE268E9A63198F53B3F0337B3EA8AF3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */; }; + F05B5437AFF475FE8811E2A8A734920F /* NSBundle+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E2EB968B30DE56F38B5FCFFEDE9F88F /* NSBundle+Extensions.swift */; }; + F4BE83FBD5001DEDF6736E69ADA6D79B /* Presenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F513F2674553CBC247EE4B24EA25C99C /* Presenter.swift */; }; + F69D9D53A5500A42D4B41097537628E5 /* errorIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = E31D045D9E355D4F7F75564026B2051A /* errorIconSubtle@3x.png */; }; + F75A8D3DA9B4787BEEEBF3F784D5CDEF /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D219D80184B8ED97808EE17507B213A /* Animator.swift */; }; + F9A111F30C3B26D0A35B0829EED70D26 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E610C06F5B006DE57F34D5994532FB /* Error.swift */; }; + FA02B47E32DD9BEAAB8A2D1B66F697D5 /* PhysicsAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D2B448BE319CF56A38E222C0B7DF4CB /* PhysicsAnimation.swift */; }; + FDC2C20416D7EBF959A461E25FAFB16E /* errorIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D34E3F2A49E9024A96334DA4147F27B /* errorIconLight@3x.png */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 141E78A8858DBF8B2695DFEDCBDF5158 /* PBXContainerItemProxy */ = { + 4B785BB517DA1D687C0B772C77660019 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 1FC5E8328653C350899229BDF89FACE5; - remoteInfo = "SwiftMessages-SwiftMessages_SwiftMessages"; + remoteGlobalIDString = DAB613A18652334F6BFC5F27BADF515D; + remoteInfo = SwiftMessages; }; - 4DB1DDB02425E67ED85C70C3B138E205 /* PBXContainerItemProxy */ = { + D19F271ED5B0FED7305E55070B415EDB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = DAB613A18652334F6BFC5F27BADF515D; - remoteInfo = SwiftMessages; + remoteGlobalIDString = 1FC5E8328653C350899229BDF89FACE5; + remoteInfo = "SwiftMessages-SwiftMessages_SwiftMessages"; }; - 900F05D1477FFAB64FF410CBB6B9B74D /* PBXContainerItemProxy */ = { + DA9FA5DB745280F35DD4EFAC9A7A4FD7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; @@ -116,112 +117,113 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 0259757860B26C6072E2640B84EC6D45 /* warningIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIcon.png; path = SwiftMessages/Resources/warningIcon.png; sourceTree = "<group>"; }; - 06F2F626BE8417F1806CC5B17F210C90 /* infoIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconSubtle.png; path = SwiftMessages/Resources/infoIconSubtle.png; sourceTree = "<group>"; }; - 0892E032AE12339D1AD84BDCC78A3C07 /* errorIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconLight.png; path = SwiftMessages/Resources/errorIconLight.png; sourceTree = "<group>"; }; + 0038C9A582787F9882258E8D1080EACF /* warningIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@3x.png"; path = "SwiftMessages/Resources/warningIcon@3x.png"; sourceTree = "<group>"; }; + 007ACA6F89C6C856F78352A086F3B8EA /* CornerRoundingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CornerRoundingView.swift; path = SwiftMessages/CornerRoundingView.swift; sourceTree = "<group>"; }; + 0201BC51C7CA061016B619400691A139 /* AccessibleMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibleMessage.swift; path = SwiftMessages/AccessibleMessage.swift; sourceTree = "<group>"; }; 093D5BBE2A96A1A7AC0432A3AB933576 /* Pods-iMessageDemo-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageDemo-Info.plist"; sourceTree = "<group>"; }; - 0970322A5DD8B4A8373C35ED051DE156 /* NSLayoutConstraint+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSLayoutConstraint+Extensions.swift"; path = "SwiftMessages/NSLayoutConstraint+Extensions.swift"; sourceTree = "<group>"; }; - 0A8566413BFA3FE6827E63E30515C9B3 /* WindowViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WindowViewController.swift; path = SwiftMessages/WindowViewController.swift; sourceTree = "<group>"; }; - 0B3A169D83BDA3613A661845D1607FC0 /* successIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@2x.png"; path = "SwiftMessages/Resources/successIconSubtle@2x.png"; sourceTree = "<group>"; }; + 0AF65ECDAFAD03A79B5571C6F66D8F35 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TopBottomAnimation.swift; path = SwiftMessages/TopBottomAnimation.swift; sourceTree = "<group>"; }; + 0BEC185781E869FB5FDB7F10538230C7 /* SwiftMessages.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SwiftMessages.modulemap; sourceTree = "<group>"; }; + 0D2B448BE319CF56A38E222C0B7DF4CB /* PhysicsAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsAnimation.swift; path = SwiftMessages/PhysicsAnimation.swift; sourceTree = "<group>"; }; 1341BB7116EC50FDF7062C6A91DEDF49 /* Pods-iMessageExtensionDemo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageExtensionDemo-acknowledgements.plist"; sourceTree = "<group>"; }; + 141AADF8046C9D5EC8E194DF662BAC41 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; sourceTree = "<group>"; }; 14BF989232A1D55A0FDAAB70B5A8E1BF /* Pods-iMessageDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-iMessageDemo-dummy.m"; sourceTree = "<group>"; }; - 15C4C88778A19C193D1EC77FA77BAE4C /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Extensions.swift"; path = "SwiftMessages/UIViewController+Extensions.swift"; sourceTree = "<group>"; }; - 19B5EF40CEC1F6DB23F428DC159D4BC2 /* CALayer+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CALayer+Extensions.swift"; path = "SwiftMessages/CALayer+Extensions.swift"; sourceTree = "<group>"; }; - 1B04615682E8B787C964824435BC6616 /* errorIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@2x.png"; path = "SwiftMessages/Resources/errorIconLight@2x.png"; sourceTree = "<group>"; }; - 1DC54BB09EFDFEDE11F484FE73BEDC60 /* successIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconSubtle.png; path = SwiftMessages/Resources/successIconSubtle.png; sourceTree = "<group>"; }; - 2337E6D5F621F3CE9A1E3761984EBE87 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsPanHandler.swift; path = SwiftMessages/PhysicsPanHandler.swift; sourceTree = "<group>"; }; - 267E35F9851AAE50DFB8FA0DCA7F2980 /* Animator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Animator.swift; path = SwiftMessages/Animator.swift; sourceTree = "<group>"; }; - 2B6B36CBE6DC07B2F005E30EA2B121CB /* LICENSE.md */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE.md; sourceTree = "<group>"; }; - 2B7213B7DC5432DA2B272F25E17AA364 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "SwiftMessages/Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; - 2CFBBC25592C97C925B6F81B53BE57CB /* warningIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@3x.png"; path = "SwiftMessages/Resources/warningIcon@3x.png"; sourceTree = "<group>"; }; + 17ADABD24F805C5F7FF62167E7ABEF0A /* successIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@3x.png"; path = "SwiftMessages/Resources/successIconSubtle@3x.png"; sourceTree = "<group>"; }; + 1A331C2E0BE2AE2118D65AA1F12519F2 /* PassthroughWindow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughWindow.swift; path = SwiftMessages/PassthroughWindow.swift; sourceTree = "<group>"; }; + 1E2FE4DB6869F330F19A3A5459AAFFFB /* StatusLine.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = StatusLine.xib; path = SwiftMessages/Resources/StatusLine.xib; sourceTree = "<group>"; }; + 1ED635B9451869879B1A404F00C3CCC7 /* SwiftMessages-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-prefix.pch"; sourceTree = "<group>"; }; + 24021DCE87BE9746D1DFB436C0A3AF7A /* Theme.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Theme.swift; path = SwiftMessages/Theme.swift; sourceTree = "<group>"; }; + 29A39558830996C4F54686A1748B74B1 /* warningIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@2x.png"; path = "SwiftMessages/Resources/warningIcon@2x.png"; sourceTree = "<group>"; }; 2D0ECE831FB5E0EE1D68E837671320C7 /* Pods-iMessageDemo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-iMessageDemo-umbrella.h"; sourceTree = "<group>"; }; - 2E6941E59EF0D89949E3DF3D89488430 /* Weak.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Weak.swift; path = SwiftMessages/Weak.swift; sourceTree = "<group>"; }; - 337B3108412E3812254B85BCC4F90EB8 /* infoIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@3x.png"; path = "SwiftMessages/Resources/infoIcon@3x.png"; sourceTree = "<group>"; }; - 346718C2C7A108C86535F89FEB0EC176 /* SwiftMessages.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SwiftMessages.modulemap; sourceTree = "<group>"; }; - 382E6375390EBB09F829519F8ACCB7D7 /* PassthroughWindow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughWindow.swift; path = SwiftMessages/PassthroughWindow.swift; sourceTree = "<group>"; }; - 396FCF260E9C2B3F11080A91E3D72334 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TopBottomAnimation.swift; path = SwiftMessages/TopBottomAnimation.swift; sourceTree = "<group>"; }; - 397C8F928170138667B9326F9655D75D /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIWindow+Extensions.swift"; path = "SwiftMessages/UIWindow+Extensions.swift"; sourceTree = "<group>"; }; - 3C313FB1D33EF4B477FD5D3D6179A8BE /* errorIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@2x.png"; path = "SwiftMessages/Resources/errorIconSubtle@2x.png"; sourceTree = "<group>"; }; - 3DF091E68C4659506DB08B0876BD274C /* CenteredView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CenteredView.xib; path = SwiftMessages/Resources/CenteredView.xib; sourceTree = "<group>"; }; - 42F1E753E61B6EDED3908AC66994649C /* CardView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CardView.xib; path = SwiftMessages/Resources/CardView.xib; sourceTree = "<group>"; }; - 4412F313361EFEE7A0193533A5AC5999 /* infoIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@3x.png"; path = "SwiftMessages/Resources/infoIconLight@3x.png"; sourceTree = "<group>"; }; - 4512DEEA328AB0AAA95D77C84C89E02C /* warningIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconSubtle.png; path = SwiftMessages/Resources/warningIconSubtle.png; sourceTree = "<group>"; }; - 453BC098B6A052020C40DE576F684C7B /* errorIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@3x.png"; path = "SwiftMessages/Resources/errorIconSubtle@3x.png"; sourceTree = "<group>"; }; + 3259F99D03B6D738D7F47A625E7BD3BE /* warningIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIcon.png; path = SwiftMessages/Resources/warningIcon.png; sourceTree = "<group>"; }; + 36F7B24601DF4C00B14EC8CE2D4A48DC /* UIEdgeInsets+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIEdgeInsets+Extensions.swift"; path = "SwiftMessages/UIEdgeInsets+Extensions.swift"; sourceTree = "<group>"; }; + 3E2EB968B30DE56F38B5FCFFEDE9F88F /* NSBundle+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSBundle+Extensions.swift"; path = "SwiftMessages/NSBundle+Extensions.swift"; sourceTree = "<group>"; }; + 45844D489A130BA91E91E7CDD4969862 /* infoIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@2x.png"; path = "SwiftMessages/Resources/infoIconSubtle@2x.png"; sourceTree = "<group>"; }; + 467EAD44C7F625F384822180F004E64F /* CALayer+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CALayer+Extensions.swift"; path = "SwiftMessages/CALayer+Extensions.swift"; sourceTree = "<group>"; }; + 468D9889455DE51BD5BBC2360BDBB877 /* errorIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@2x.png"; path = "SwiftMessages/Resources/errorIconSubtle@2x.png"; sourceTree = "<group>"; }; 4824F23D80FF9070A5F8A452DB11EB9A /* SwiftMessages.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SwiftMessages.framework; path = SwiftMessages.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4F8D7902822221456B697BB41111E450 /* CornerRoundingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CornerRoundingView.swift; path = SwiftMessages/CornerRoundingView.swift; sourceTree = "<group>"; }; - 4FE466AC4123CDAE9FDA9FCF4FB9CC60 /* infoIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@2x.png"; path = "SwiftMessages/Resources/infoIconSubtle@2x.png"; sourceTree = "<group>"; }; - 536660614870EA0E051BF6BDDF495798 /* KeyboardTrackingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KeyboardTrackingView.swift; path = SwiftMessages/KeyboardTrackingView.swift; sourceTree = "<group>"; }; - 54B278C80D821C120FA70ABB6CAF1F46 /* successIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@3x.png"; path = "SwiftMessages/Resources/successIconSubtle@3x.png"; sourceTree = "<group>"; }; - 5C0DE01AB7D0935933E7AFBDF2945814 /* Identifiable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Identifiable.swift; path = SwiftMessages/Identifiable.swift; sourceTree = "<group>"; }; + 48DC3BADDA3A20F2AEB8585117DAFA0D /* infoIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@3x.png"; path = "SwiftMessages/Resources/infoIcon@3x.png"; sourceTree = "<group>"; }; + 4D34E3F2A49E9024A96334DA4147F27B /* errorIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@3x.png"; path = "SwiftMessages/Resources/errorIconLight@3x.png"; sourceTree = "<group>"; }; + 52F1CA85E0EED7D94FE0036BC92EB3EC /* successIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconLight.png; path = SwiftMessages/Resources/successIconLight.png; sourceTree = "<group>"; }; + 59FEAC25BE3FCB9F8373DE26400CC89D /* SwiftMessages.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = SwiftMessages.podspec; sourceTree = "<group>"; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 5A16E25077F8D76288BE678E6AC1C884 /* SwiftMessages.Config+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "SwiftMessages.Config+Extensions.swift"; path = "SwiftMessages/SwiftMessages.Config+Extensions.swift"; sourceTree = "<group>"; }; 5CAB201AD00CAB811B045E2FFB5C03A8 /* Pods-iMessageExtensionDemo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-iMessageExtensionDemo-umbrella.h"; sourceTree = "<group>"; }; - 60268FE48AA4DC9FD5060B1E5CE68453 /* errorIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@2x.png"; path = "SwiftMessages/Resources/errorIcon@2x.png"; sourceTree = "<group>"; }; - 62755A788F910CA88887B6F63BBC545F /* successIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@2x.png"; path = "SwiftMessages/Resources/successIcon@2x.png"; sourceTree = "<group>"; }; 6489B2A759075E9DC1D1406734F45B5F /* Pods-iMessageExtensionDemo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iMessageExtensionDemo.modulemap"; sourceTree = "<group>"; }; - 6516EE9BFCB9C53C151359F9D0247562 /* infoIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@2x.png"; path = "SwiftMessages/Resources/infoIconLight@2x.png"; sourceTree = "<group>"; }; - 667DECE93ABCC6869A071FFEB0F83EA5 /* warningIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@3x.png"; path = "SwiftMessages/Resources/warningIconSubtle@3x.png"; sourceTree = "<group>"; }; - 6E9D4A0FDDEEDDC5A1A63D89B43C1F18 /* SwiftMessages.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.debug.xcconfig; sourceTree = "<group>"; }; - 70E7AB099F856140EF93D5B94A967418 /* infoIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIcon.png; path = SwiftMessages/Resources/infoIcon.png; sourceTree = "<group>"; }; - 7241B2130D211F0832CCE4928CBB6486 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = "<group>"; }; - 72A865FFBAE49EF66A35CB9D709E8D7E /* successIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@3x.png"; path = "SwiftMessages/Resources/successIconLight@3x.png"; sourceTree = "<group>"; }; - 79E38069364BC5DF4EA88F352E28B242 /* warningIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconLight.png; path = SwiftMessages/Resources/warningIconLight.png; sourceTree = "<group>"; }; - 7A6801849037A728E9BC50E06CE8AD2F /* StatusLine.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = StatusLine.xib; path = SwiftMessages/Resources/StatusLine.xib; sourceTree = "<group>"; }; - 7A965DD26246DCA8CE39FBAB348ABA24 /* Presenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Presenter.swift; path = SwiftMessages/Presenter.swift; sourceTree = "<group>"; }; + 676F359BE8561CF7512DB8B42CD7873A /* infoIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@3x.png"; path = "SwiftMessages/Resources/infoIconLight@3x.png"; sourceTree = "<group>"; }; + 705B5AF043D00B6538599B4EB1ECD77C /* CardView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CardView.xib; path = SwiftMessages/Resources/CardView.xib; sourceTree = "<group>"; }; + 7100245A2722BD53D5B3927ED649069F /* errorIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconLight.png; path = SwiftMessages/Resources/errorIconLight.png; sourceTree = "<group>"; }; + 730840765E737D45772EBE66DB8A6D2E /* infoIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconLight.png; path = SwiftMessages/Resources/infoIconLight.png; sourceTree = "<group>"; }; + 74C53DDA65E08AD7274EA6625408AB99 /* SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SwiftMessages-Info.plist"; sourceTree = "<group>"; }; + 753B78926D6BB175E96AB6E6F3514E87 /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIWindow+Extensions.swift"; path = "SwiftMessages/UIWindow+Extensions.swift"; sourceTree = "<group>"; }; + 760BFB41B33B6ED91B3FFD68D39083A0 /* successIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@2x.png"; path = "SwiftMessages/Resources/successIconLight@2x.png"; sourceTree = "<group>"; }; + 778F6E19CE49B8EDBAC2FCCD8195A55B /* MessageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageView.swift; path = SwiftMessages/MessageView.swift; sourceTree = "<group>"; }; + 787EE6DA4FBC3BF85ED2CF0BB6EBF494 /* CenteredView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CenteredView.xib; path = SwiftMessages/Resources/CenteredView.xib; sourceTree = "<group>"; }; + 79D34B3C6875DA0279CB934C84CD000B /* successIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@2x.png"; path = "SwiftMessages/Resources/successIcon@2x.png"; sourceTree = "<group>"; }; + 7C4DF53A4B44C246968618BF25962786 /* warningIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@3x.png"; path = "SwiftMessages/Resources/warningIconLight@3x.png"; sourceTree = "<group>"; }; + 7C8214A441D845A4A4DD6570FD5D458F /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "MarginAdjustable+Extensions.swift"; path = "SwiftMessages/MarginAdjustable+Extensions.swift"; sourceTree = "<group>"; }; 7CC6A596A9C1659D8E93222DA4144414 /* Pods-iMessageExtensionDemo-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageExtensionDemo-Info.plist"; sourceTree = "<group>"; }; 7F40CA14AD738DD186B4DA8FD14AE5BD /* Pods-iMessageExtensionDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-iMessageExtensionDemo-dummy.m"; sourceTree = "<group>"; }; - 7FCF161BD9F1C2CAAFBCADE5E59BD3FD /* NSBundle+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSBundle+Extensions.swift"; path = "SwiftMessages/NSBundle+Extensions.swift"; sourceTree = "<group>"; }; 820B743874F7AC9F9E3970D68E2E60FA /* Pods-iMessageDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageDemo.release.xcconfig"; sourceTree = "<group>"; }; - 8341EF04E2B20C2BF6D4AF2240F80A56 /* Error.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Error.swift; path = SwiftMessages/Error.swift; sourceTree = "<group>"; }; - 848251807107C20960A3DABAB27F7475 /* errorIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@3x.png"; path = "SwiftMessages/Resources/errorIconLight@3x.png"; sourceTree = "<group>"; }; - 874D31DE863C88B1D699E1EBFBE0641B /* warningIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@2x.png"; path = "SwiftMessages/Resources/warningIconLight@2x.png"; sourceTree = "<group>"; }; - 8901520225CE89F44E6DE88688F29C10 /* MessageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageView.swift; path = SwiftMessages/MessageView.swift; sourceTree = "<group>"; }; + 8315EA451FE61625920FEF68174A0D22 /* infoIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@2x.png"; path = "SwiftMessages/Resources/infoIconLight@2x.png"; sourceTree = "<group>"; }; + 860D833A7A1B108A89ED34AD74778AC0 /* warningIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconSubtle.png; path = SwiftMessages/Resources/warningIconSubtle.png; sourceTree = "<group>"; }; + 87745BF2C7154EF88509BED0D71243F1 /* SwiftMessages.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.debug.xcconfig; sourceTree = "<group>"; }; + 88D73E42D996B226222A4EBA46F7DC6D /* Weak.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Weak.swift; path = SwiftMessages/Weak.swift; sourceTree = "<group>"; }; + 8AD355ED684A939F2A4E333F95E8AC31 /* warningIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@2x.png"; path = "SwiftMessages/Resources/warningIconSubtle@2x.png"; sourceTree = "<group>"; }; + 8D219D80184B8ED97808EE17507B213A /* Animator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Animator.swift; path = SwiftMessages/Animator.swift; sourceTree = "<group>"; }; 8D54691037F1CA4653B76F0558E2AA82 /* Pods-iMessageExtensionDemo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-iMessageExtensionDemo-acknowledgements.markdown"; sourceTree = "<group>"; }; - 90F364E0C9A6EFE24680868D0BD293F1 /* SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SwiftMessages-Info.plist"; sourceTree = "<group>"; }; + 90AC342C6F09BF7715D4FB95512DD68A /* KeyboardTrackingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KeyboardTrackingView.swift; path = SwiftMessages/KeyboardTrackingView.swift; sourceTree = "<group>"; }; 915DE2E4E300BAD440BE13F72E49D731 /* Pods-iMessageDemo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageDemo-acknowledgements.plist"; sourceTree = "<group>"; }; - 9C110C924ED12D2D32ECC27503018A31 /* infoIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconLight.png; path = SwiftMessages/Resources/infoIconLight.png; sourceTree = "<group>"; }; - 9CF61FDEFE095F0486E9914F2262ADB9 /* MaskingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MaskingView.swift; path = SwiftMessages/MaskingView.swift; sourceTree = "<group>"; }; - 9D1FEAC04417D847EDC10783E054988F /* errorIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIcon.png; path = SwiftMessages/Resources/errorIcon.png; sourceTree = "<group>"; }; + 91D9224F29E092950BADC27C979E10CC /* successIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@2x.png"; path = "SwiftMessages/Resources/successIconSubtle@2x.png"; sourceTree = "<group>"; }; + 9C6E00017F9E79F6D4926E9CB43A66DF /* SwiftMessages-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SwiftMessages-dummy.m"; sourceTree = "<group>"; }; + 9CBEAC9D0EF4113C3FD3B15F511A92D0 /* SwiftMessages-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-umbrella.h"; sourceTree = "<group>"; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - A0D0E8B0020635F606875DD02735C502 /* BaseView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BaseView.swift; path = SwiftMessages/BaseView.swift; sourceTree = "<group>"; }; - A2F9031B7FA82A17F04D4403091DF836 /* SwiftMessages-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SwiftMessages-dummy.m"; sourceTree = "<group>"; }; - A3C32E945AE3E6394EF85CD6BEC714B4 /* SwiftMessages.Config+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "SwiftMessages.Config+Extensions.swift"; path = "SwiftMessages/SwiftMessages.Config+Extensions.swift"; sourceTree = "<group>"; }; - A80433B71162112A79043CB64261DB51 /* successIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconLight.png; path = SwiftMessages/Resources/successIconLight.png; sourceTree = "<group>"; }; - A850F76D7E3FEDC20FFB877454069171 /* errorIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconSubtle.png; path = SwiftMessages/Resources/errorIconSubtle.png; sourceTree = "<group>"; }; - A9A13E69643D651322647C28E3F9E9C9 /* UIEdgeInsets+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIEdgeInsets+Extensions.swift"; path = "SwiftMessages/UIEdgeInsets+Extensions.swift"; sourceTree = "<group>"; }; - AE62AA801971C530345349D18AFCCB82 /* MessageView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = MessageView.xib; path = SwiftMessages/Resources/MessageView.xib; sourceTree = "<group>"; }; + A0EE84E98A10805A2D64B836C465ED11 /* warningIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@3x.png"; path = "SwiftMessages/Resources/warningIconSubtle@3x.png"; sourceTree = "<group>"; }; + A342E145FED9CD8DB4F464D110203E7C /* successIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIcon.png; path = SwiftMessages/Resources/successIcon.png; sourceTree = "<group>"; }; AE7AEA9CE6B44DCC96AE4E68FA644DAA /* Pods-iMessageExtensionDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageExtensionDemo.release.xcconfig"; sourceTree = "<group>"; }; AFC41396FB1BD59C9A69EE1DD82E47C2 /* Pods_iMessageDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_iMessageDemo.framework; path = "Pods-iMessageDemo.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; - AFFDB7DDC6B6B064B9D12281E2531BFA /* SwiftMessagesSegue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessagesSegue.swift; path = SwiftMessages/SwiftMessagesSegue.swift; sourceTree = "<group>"; }; - B6DEAADC09FEB1A8D5B90108103EE478 /* errorIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@3x.png"; path = "SwiftMessages/Resources/errorIcon@3x.png"; sourceTree = "<group>"; }; - B7FD0618783A3E6B90D3A3323633959F /* TabView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = TabView.xib; path = SwiftMessages/Resources/TabView.xib; sourceTree = "<group>"; }; - B91AD9D9E743D17D553D48103BE27C46 /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "MarginAdjustable+Extensions.swift"; path = "SwiftMessages/MarginAdjustable+Extensions.swift"; sourceTree = "<group>"; }; + B031268635405AA009D05130C0FC253C /* successIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconSubtle.png; path = SwiftMessages/Resources/successIconSubtle.png; sourceTree = "<group>"; }; + B7BF853CD0CDFA20423D4C813B34B57F /* SwiftMessages.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.release.xcconfig; sourceTree = "<group>"; }; + B8A4CCB4B08D2D3BE586212AB4167DC2 /* MessageView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = MessageView.xib; path = SwiftMessages/Resources/MessageView.xib; sourceTree = "<group>"; }; B99CBDE49D6502CF64EB9059C005BF31 /* Pods-iMessageDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageDemo.debug.xcconfig"; sourceTree = "<group>"; }; + BDEF50CAF615897F7A8540579B445634 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsPanHandler.swift; path = SwiftMessages/PhysicsPanHandler.swift; sourceTree = "<group>"; }; BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages_SwiftMessages.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = SwiftMessages_SwiftMessages.bundle; path = "SwiftMessages-SwiftMessages_SwiftMessages.bundle"; sourceTree = BUILT_PRODUCTS_DIR; }; + BF27E3EF103BACDEE8CA842B2C90C8CA /* SwiftMessagesSegue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessagesSegue.swift; path = SwiftMessages/SwiftMessagesSegue.swift; sourceTree = "<group>"; }; BF61E78F8E8EE539F4A63C5A9D43AC15 /* Pods-iMessageDemo-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-iMessageDemo-frameworks.sh"; sourceTree = "<group>"; }; - BFEF746702215C33B51BEE64C4E48F0A /* warningIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@2x.png"; path = "SwiftMessages/Resources/warningIcon@2x.png"; sourceTree = "<group>"; }; - C17CFEF9B761A322945F74D86CA88036 /* warningIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@3x.png"; path = "SwiftMessages/Resources/warningIconLight@3x.png"; sourceTree = "<group>"; }; C306ACAFEE157959D78E71DBBBD675DC /* Pods-iMessageExtensionDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageExtensionDemo.debug.xcconfig"; sourceTree = "<group>"; }; - C3216CF40D770C387D45C3B4AF2CC9E0 /* SwiftMessages.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessages.swift; path = SwiftMessages/SwiftMessages.swift; sourceTree = "<group>"; }; - C614EECDDFE644AF0BF7CB16A3D74404 /* SwiftMessages-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-umbrella.h"; sourceTree = "<group>"; }; - C6C56947CAF8EFCC7858E1E2F1273427 /* MarginAdjustable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MarginAdjustable.swift; path = SwiftMessages/MarginAdjustable.swift; sourceTree = "<group>"; }; - C7FE39695CB7C6997ACA39C8680B414A /* SwiftMessages.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = SwiftMessages.podspec; sourceTree = "<group>"; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - C8155ED78358FA5CF39089176FBDE501 /* successIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@3x.png"; path = "SwiftMessages/Resources/successIcon@3x.png"; sourceTree = "<group>"; }; - C9D915B60769D3C45A0DA3A5BA9514B8 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; sourceTree = "<group>"; }; - CAB58A9F688DD39112E6CDF20C8969C0 /* BackgroundViewable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BackgroundViewable.swift; path = SwiftMessages/BackgroundViewable.swift; sourceTree = "<group>"; }; + C56AB83FDAB8D6A1328E7EECCAD99A69 /* warningIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconLight.png; path = SwiftMessages/Resources/warningIconLight.png; sourceTree = "<group>"; }; + C5E610C06F5B006DE57F34D5994532FB /* Error.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Error.swift; path = SwiftMessages/Error.swift; sourceTree = "<group>"; }; + C706F1F1C6B3CE84445485C8577D5388 /* BackgroundViewable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BackgroundViewable.swift; path = SwiftMessages/BackgroundViewable.swift; sourceTree = "<group>"; }; + C787DA4E67B952C984FF5B065E0A2FF7 /* errorIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconSubtle.png; path = SwiftMessages/Resources/errorIconSubtle.png; sourceTree = "<group>"; }; + C7EE64CFE0084CF5213A03AF29A668ED /* BaseView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BaseView.swift; path = SwiftMessages/BaseView.swift; sourceTree = "<group>"; }; + C9F5DBB6D77B1E61E9BB1A722A4E1823 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "SwiftMessages/Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; CBC3F501D8BC852716D085B3022E68CA /* Pods_iMessageExtensionDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_iMessageExtensionDemo.framework; path = "Pods-iMessageExtensionDemo.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; CC9152C843976F18EF9AE005786DCC80 /* Pods-iMessageDemo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iMessageDemo.modulemap"; sourceTree = "<group>"; }; + D032FCFAE6607CF878AA2F35EF93146C /* successIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@3x.png"; path = "SwiftMessages/Resources/successIcon@3x.png"; sourceTree = "<group>"; }; + D1D69BE188B82D84ED23AC4E27BAB61D /* MaskingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MaskingView.swift; path = SwiftMessages/MaskingView.swift; sourceTree = "<group>"; }; D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - D5607E285A85AC7163B0B8FD447FD27E /* Theme.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Theme.swift; path = SwiftMessages/Theme.swift; sourceTree = "<group>"; }; - D7C557E1DC95AFA417E94ED01301F9F2 /* PassthroughView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughView.swift; path = SwiftMessages/PassthroughView.swift; sourceTree = "<group>"; }; - E070773539E02C11297794CC4CB839D6 /* SwiftMessages.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.release.xcconfig; sourceTree = "<group>"; }; + D261B7BE0088C26BF6744F27B894492A /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Extensions.swift"; path = "SwiftMessages/UIViewController+Extensions.swift"; sourceTree = "<group>"; }; + D30B2BF71F9D2C63C2D202C99827CDC1 /* errorIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@2x.png"; path = "SwiftMessages/Resources/errorIconLight@2x.png"; sourceTree = "<group>"; }; + D68834C60D0C5EA751E9F12E427C5FFE /* MarginAdjustable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MarginAdjustable.swift; path = SwiftMessages/MarginAdjustable.swift; sourceTree = "<group>"; }; + D8DEFE9675E5359A46A443182F127F06 /* WindowScene.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WindowScene.swift; path = SwiftMessages/WindowScene.swift; sourceTree = "<group>"; }; + D9AA0E820F1C1AA219C066370332845A /* WindowViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WindowViewController.swift; path = SwiftMessages/WindowViewController.swift; sourceTree = "<group>"; }; + DB6924EB5FC7236837637AE8F409000A /* NSLayoutConstraint+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSLayoutConstraint+Extensions.swift"; path = "SwiftMessages/NSLayoutConstraint+Extensions.swift"; sourceTree = "<group>"; }; + DEC0A6AE07C3285CA508F8FA3F4FE27D /* errorIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIcon.png; path = SwiftMessages/Resources/errorIcon.png; sourceTree = "<group>"; }; + DF3DE135AB5C5C789CABAECC704CE907 /* errorIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@2x.png"; path = "SwiftMessages/Resources/errorIcon@2x.png"; sourceTree = "<group>"; }; + E03CBB908F2EC39AA5DA7AF04E1BDDD6 /* PassthroughView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughView.swift; path = SwiftMessages/PassthroughView.swift; sourceTree = "<group>"; }; + E0E4D99C4F78B9BA011D83FE63EE0946 /* errorIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@3x.png"; path = "SwiftMessages/Resources/errorIcon@3x.png"; sourceTree = "<group>"; }; + E31D045D9E355D4F7F75564026B2051A /* errorIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@3x.png"; path = "SwiftMessages/Resources/errorIconSubtle@3x.png"; sourceTree = "<group>"; }; + E41BFEB1BFF85793C0DB85F95184B752 /* infoIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIcon.png; path = SwiftMessages/Resources/infoIcon.png; sourceTree = "<group>"; }; E473E4F019E816262A61B7F5E8B42373 /* Pods-iMessageDemo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-iMessageDemo-acknowledgements.markdown"; sourceTree = "<group>"; }; + E936107A7CF9821DCBFFAF50D916F1E6 /* infoIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@2x.png"; path = "SwiftMessages/Resources/infoIcon@2x.png"; sourceTree = "<group>"; }; + E9E929B0E2A84EA903C9923B926A44E2 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = "<group>"; }; EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - ED86D7B42F55040DCE162653FB3C7EDB /* warningIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@2x.png"; path = "SwiftMessages/Resources/warningIconSubtle@2x.png"; sourceTree = "<group>"; }; - EDDAF8A2C45FDDDFD5AFA59203137551 /* AccessibleMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibleMessage.swift; path = SwiftMessages/AccessibleMessage.swift; sourceTree = "<group>"; }; - F7004673F1B51EEC365B32F0E060E564 /* infoIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@2x.png"; path = "SwiftMessages/Resources/infoIcon@2x.png"; sourceTree = "<group>"; }; - F898B2AC5C3404C266BBCA3B6D22B5E4 /* successIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@2x.png"; path = "SwiftMessages/Resources/successIconLight@2x.png"; sourceTree = "<group>"; }; - FC73E6C784AF6CA1F956F57F82ED2803 /* successIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIcon.png; path = SwiftMessages/Resources/successIcon.png; sourceTree = "<group>"; }; - FCDC8870EA94B5B1E966D34D2B1FA5FE /* SwiftMessages-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-prefix.pch"; sourceTree = "<group>"; }; - FE3BED1799B2F867F5C984C2A051E36A /* PhysicsAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsAnimation.swift; path = SwiftMessages/PhysicsAnimation.swift; sourceTree = "<group>"; }; + EABF0CEB87991D02E13306975A8E80BB /* TabView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = TabView.xib; path = SwiftMessages/Resources/TabView.xib; sourceTree = "<group>"; }; + EC6264350B8D100D5B5C5EEEC316933D /* SwiftMessages.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessages.swift; path = SwiftMessages/SwiftMessages.swift; sourceTree = "<group>"; }; + EFD31968BF9DF7A9E25A136DF254F3A9 /* Identifiable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Identifiable.swift; path = SwiftMessages/Identifiable.swift; sourceTree = "<group>"; }; + F513F2674553CBC247EE4B24EA25C99C /* Presenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Presenter.swift; path = SwiftMessages/Presenter.swift; sourceTree = "<group>"; }; + F9CDB54E629D60FF881DF27B949F4C2D /* infoIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconSubtle.png; path = SwiftMessages/Resources/infoIconSubtle.png; sourceTree = "<group>"; }; + FA199E6F18AB8900B5400EBA0EB32765 /* successIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@3x.png"; path = "SwiftMessages/Resources/successIconLight@3x.png"; sourceTree = "<group>"; }; + FC12F21544AE9FE6D9E1E2F7730EF7EC /* LICENSE.md */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE.md; sourceTree = "<group>"; }; + FFB0D50D01FFFA3FC2099E395029AE68 /* warningIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@2x.png"; path = "SwiftMessages/Resources/warningIconLight@2x.png"; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -233,33 +235,112 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - C3AABE927CAF3C6135B4D37CA433F885 /* Frameworks */ = { + 9DEA36BAD403380FF5C38B4F2B4C3AB9 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - F2C6C6F4FCF31DEB85ADCA0DE9EF6EEC /* Frameworks */ = { + EF08D4F0B96CF6C9AB42DC368EE3849A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A9EB0C8E49AB748B05CF7941ACAF8475 /* Foundation.framework in Frameworks */, + 9DA2F2EED5C99045AF44FF410A012F9D /* Foundation.framework in Frameworks */, + ECE268E9A63198F53B3F0337B3EA8AF3 /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - FA7AA2A57B110DEF3C1F616FA77A05A7 /* Frameworks */ = { + F2C6C6F4FCF31DEB85ADCA0DE9EF6EEC /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 8148CD8F2B38FB38B7B9CCC12E93ECFB /* Foundation.framework in Frameworks */, - E88597F65A00A5AF50EEF2ABA2392B2F /* UIKit.framework in Frameworks */, + A9EB0C8E49AB748B05CF7941ACAF8475 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 089392E699971024974E80EFFB25EE61 /* AppExtension */ = { + isa = PBXGroup; + children = ( + 0201BC51C7CA061016B619400691A139 /* AccessibleMessage.swift */, + 8D219D80184B8ED97808EE17507B213A /* Animator.swift */, + C706F1F1C6B3CE84445485C8577D5388 /* BackgroundViewable.swift */, + C7EE64CFE0084CF5213A03AF29A668ED /* BaseView.swift */, + 467EAD44C7F625F384822180F004E64F /* CALayer+Extensions.swift */, + 705B5AF043D00B6538599B4EB1ECD77C /* CardView.xib */, + 787EE6DA4FBC3BF85ED2CF0BB6EBF494 /* CenteredView.xib */, + 007ACA6F89C6C856F78352A086F3B8EA /* CornerRoundingView.swift */, + C5E610C06F5B006DE57F34D5994532FB /* Error.swift */, + DEC0A6AE07C3285CA508F8FA3F4FE27D /* errorIcon.png */, + DF3DE135AB5C5C789CABAECC704CE907 /* errorIcon@2x.png */, + E0E4D99C4F78B9BA011D83FE63EE0946 /* errorIcon@3x.png */, + 7100245A2722BD53D5B3927ED649069F /* errorIconLight.png */, + D30B2BF71F9D2C63C2D202C99827CDC1 /* errorIconLight@2x.png */, + 4D34E3F2A49E9024A96334DA4147F27B /* errorIconLight@3x.png */, + C787DA4E67B952C984FF5B065E0A2FF7 /* errorIconSubtle.png */, + 468D9889455DE51BD5BBC2360BDBB877 /* errorIconSubtle@2x.png */, + E31D045D9E355D4F7F75564026B2051A /* errorIconSubtle@3x.png */, + EFD31968BF9DF7A9E25A136DF254F3A9 /* Identifiable.swift */, + E41BFEB1BFF85793C0DB85F95184B752 /* infoIcon.png */, + E936107A7CF9821DCBFFAF50D916F1E6 /* infoIcon@2x.png */, + 48DC3BADDA3A20F2AEB8585117DAFA0D /* infoIcon@3x.png */, + 730840765E737D45772EBE66DB8A6D2E /* infoIconLight.png */, + 8315EA451FE61625920FEF68174A0D22 /* infoIconLight@2x.png */, + 676F359BE8561CF7512DB8B42CD7873A /* infoIconLight@3x.png */, + F9CDB54E629D60FF881DF27B949F4C2D /* infoIconSubtle.png */, + 45844D489A130BA91E91E7CDD4969862 /* infoIconSubtle@2x.png */, + C9F5DBB6D77B1E61E9BB1A722A4E1823 /* infoIconSubtle@3x.png */, + 90AC342C6F09BF7715D4FB95512DD68A /* KeyboardTrackingView.swift */, + D68834C60D0C5EA751E9F12E427C5FFE /* MarginAdjustable.swift */, + 7C8214A441D845A4A4DD6570FD5D458F /* MarginAdjustable+Extensions.swift */, + D1D69BE188B82D84ED23AC4E27BAB61D /* MaskingView.swift */, + 778F6E19CE49B8EDBAC2FCCD8195A55B /* MessageView.swift */, + B8A4CCB4B08D2D3BE586212AB4167DC2 /* MessageView.xib */, + 3E2EB968B30DE56F38B5FCFFEDE9F88F /* NSBundle+Extensions.swift */, + DB6924EB5FC7236837637AE8F409000A /* NSLayoutConstraint+Extensions.swift */, + E03CBB908F2EC39AA5DA7AF04E1BDDD6 /* PassthroughView.swift */, + 1A331C2E0BE2AE2118D65AA1F12519F2 /* PassthroughWindow.swift */, + 0D2B448BE319CF56A38E222C0B7DF4CB /* PhysicsAnimation.swift */, + BDEF50CAF615897F7A8540579B445634 /* PhysicsPanHandler.swift */, + F513F2674553CBC247EE4B24EA25C99C /* Presenter.swift */, + 1E2FE4DB6869F330F19A3A5459AAFFFB /* StatusLine.xib */, + A342E145FED9CD8DB4F464D110203E7C /* successIcon.png */, + 79D34B3C6875DA0279CB934C84CD000B /* successIcon@2x.png */, + D032FCFAE6607CF878AA2F35EF93146C /* successIcon@3x.png */, + 52F1CA85E0EED7D94FE0036BC92EB3EC /* successIconLight.png */, + 760BFB41B33B6ED91B3FFD68D39083A0 /* successIconLight@2x.png */, + FA199E6F18AB8900B5400EBA0EB32765 /* successIconLight@3x.png */, + B031268635405AA009D05130C0FC253C /* successIconSubtle.png */, + 91D9224F29E092950BADC27C979E10CC /* successIconSubtle@2x.png */, + 17ADABD24F805C5F7FF62167E7ABEF0A /* successIconSubtle@3x.png */, + EC6264350B8D100D5B5C5EEEC316933D /* SwiftMessages.swift */, + 5A16E25077F8D76288BE678E6AC1C884 /* SwiftMessages.Config+Extensions.swift */, + BF27E3EF103BACDEE8CA842B2C90C8CA /* SwiftMessagesSegue.swift */, + EABF0CEB87991D02E13306975A8E80BB /* TabView.xib */, + 24021DCE87BE9746D1DFB436C0A3AF7A /* Theme.swift */, + 0AF65ECDAFAD03A79B5571C6F66D8F35 /* TopBottomAnimation.swift */, + 36F7B24601DF4C00B14EC8CE2D4A48DC /* UIEdgeInsets+Extensions.swift */, + D261B7BE0088C26BF6744F27B894492A /* UIViewController+Extensions.swift */, + 753B78926D6BB175E96AB6E6F3514E87 /* UIWindow+Extensions.swift */, + 3259F99D03B6D738D7F47A625E7BD3BE /* warningIcon.png */, + 29A39558830996C4F54686A1748B74B1 /* warningIcon@2x.png */, + 0038C9A582787F9882258E8D1080EACF /* warningIcon@3x.png */, + C56AB83FDAB8D6A1328E7EECCAD99A69 /* warningIconLight.png */, + FFB0D50D01FFFA3FC2099E395029AE68 /* warningIconLight@2x.png */, + 7C4DF53A4B44C246968618BF25962786 /* warningIconLight@3x.png */, + 860D833A7A1B108A89ED34AD74778AC0 /* warningIconSubtle.png */, + 8AD355ED684A939F2A4E333F95E8AC31 /* warningIconSubtle@2x.png */, + A0EE84E98A10805A2D64B836C465ED11 /* warningIconSubtle@3x.png */, + 88D73E42D996B226222A4EBA46F7DC6D /* Weak.swift */, + D8DEFE9675E5359A46A443182F127F06 /* WindowScene.swift */, + D9AA0E820F1C1AA219C066370332845A /* WindowViewController.swift */, + ); + name = AppExtension; + sourceTree = "<group>"; + }; 1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -288,24 +369,40 @@ name = iOS; sourceTree = "<group>"; }; - 8F3CF4AFB0CA47B3BFE1C68E51CDF0A9 /* Targets Support Files */ = { + 5EAB54907DABB41DF2E9177067EF69D4 /* SwiftMessages */ = { isa = PBXGroup; children = ( - 9A912CA1E54EADE1787311C1DF7E8F2E /* Pods-iMessageDemo */, - BD13800F87C70DC802DBC0C37E8C5E99 /* Pods-iMessageExtensionDemo */, + 089392E699971024974E80EFFB25EE61 /* AppExtension */, + E7706B1F04CCC75F42C733B60ED5FBDC /* Pod */, + 7C00C98D65B96C8BDE003F39DAFBBBDE /* Support Files */, ); - name = "Targets Support Files"; + name = SwiftMessages; + path = ../..; sourceTree = "<group>"; }; - 9A632FB0C8554E0688B34926AF9C52DB /* SwiftMessages */ = { + 7C00C98D65B96C8BDE003F39DAFBBBDE /* Support Files */ = { isa = PBXGroup; children = ( - AD776BCEA093D43499821A6E4251BF03 /* AppExtension */, - A58DF9B1678B5C3CCA8A840C72186044 /* Pod */, - B3699CF01F28F4B75166BA983453EAF3 /* Support Files */, + 141AADF8046C9D5EC8E194DF662BAC41 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */, + 0BEC185781E869FB5FDB7F10538230C7 /* SwiftMessages.modulemap */, + 9C6E00017F9E79F6D4926E9CB43A66DF /* SwiftMessages-dummy.m */, + 74C53DDA65E08AD7274EA6625408AB99 /* SwiftMessages-Info.plist */, + 1ED635B9451869879B1A404F00C3CCC7 /* SwiftMessages-prefix.pch */, + 9CBEAC9D0EF4113C3FD3B15F511A92D0 /* SwiftMessages-umbrella.h */, + 87745BF2C7154EF88509BED0D71243F1 /* SwiftMessages.debug.xcconfig */, + B7BF853CD0CDFA20423D4C813B34B57F /* SwiftMessages.release.xcconfig */, ); - name = SwiftMessages; - path = ../..; + name = "Support Files"; + path = "iMessageDemo/Pods/Target Support Files/SwiftMessages"; + sourceTree = "<group>"; + }; + 8F3CF4AFB0CA47B3BFE1C68E51CDF0A9 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 9A912CA1E54EADE1787311C1DF7E8F2E /* Pods-iMessageDemo */, + BD13800F87C70DC802DBC0C37E8C5E99 /* Pods-iMessageExtensionDemo */, + ); + name = "Targets Support Files"; sourceTree = "<group>"; }; 9A912CA1E54EADE1787311C1DF7E8F2E /* Pods-iMessageDemo */ = { @@ -325,110 +422,6 @@ path = "Target Support Files/Pods-iMessageDemo"; sourceTree = "<group>"; }; - A58DF9B1678B5C3CCA8A840C72186044 /* Pod */ = { - isa = PBXGroup; - children = ( - 2B6B36CBE6DC07B2F005E30EA2B121CB /* LICENSE.md */, - 7241B2130D211F0832CCE4928CBB6486 /* README.md */, - C7FE39695CB7C6997ACA39C8680B414A /* SwiftMessages.podspec */, - ); - name = Pod; - sourceTree = "<group>"; - }; - AD776BCEA093D43499821A6E4251BF03 /* AppExtension */ = { - isa = PBXGroup; - children = ( - EDDAF8A2C45FDDDFD5AFA59203137551 /* AccessibleMessage.swift */, - 267E35F9851AAE50DFB8FA0DCA7F2980 /* Animator.swift */, - CAB58A9F688DD39112E6CDF20C8969C0 /* BackgroundViewable.swift */, - A0D0E8B0020635F606875DD02735C502 /* BaseView.swift */, - 19B5EF40CEC1F6DB23F428DC159D4BC2 /* CALayer+Extensions.swift */, - 42F1E753E61B6EDED3908AC66994649C /* CardView.xib */, - 3DF091E68C4659506DB08B0876BD274C /* CenteredView.xib */, - 4F8D7902822221456B697BB41111E450 /* CornerRoundingView.swift */, - 8341EF04E2B20C2BF6D4AF2240F80A56 /* Error.swift */, - 9D1FEAC04417D847EDC10783E054988F /* errorIcon.png */, - 60268FE48AA4DC9FD5060B1E5CE68453 /* errorIcon@2x.png */, - B6DEAADC09FEB1A8D5B90108103EE478 /* errorIcon@3x.png */, - 0892E032AE12339D1AD84BDCC78A3C07 /* errorIconLight.png */, - 1B04615682E8B787C964824435BC6616 /* errorIconLight@2x.png */, - 848251807107C20960A3DABAB27F7475 /* errorIconLight@3x.png */, - A850F76D7E3FEDC20FFB877454069171 /* errorIconSubtle.png */, - 3C313FB1D33EF4B477FD5D3D6179A8BE /* errorIconSubtle@2x.png */, - 453BC098B6A052020C40DE576F684C7B /* errorIconSubtle@3x.png */, - 5C0DE01AB7D0935933E7AFBDF2945814 /* Identifiable.swift */, - 70E7AB099F856140EF93D5B94A967418 /* infoIcon.png */, - F7004673F1B51EEC365B32F0E060E564 /* infoIcon@2x.png */, - 337B3108412E3812254B85BCC4F90EB8 /* infoIcon@3x.png */, - 9C110C924ED12D2D32ECC27503018A31 /* infoIconLight.png */, - 6516EE9BFCB9C53C151359F9D0247562 /* infoIconLight@2x.png */, - 4412F313361EFEE7A0193533A5AC5999 /* infoIconLight@3x.png */, - 06F2F626BE8417F1806CC5B17F210C90 /* infoIconSubtle.png */, - 4FE466AC4123CDAE9FDA9FCF4FB9CC60 /* infoIconSubtle@2x.png */, - 2B7213B7DC5432DA2B272F25E17AA364 /* infoIconSubtle@3x.png */, - 536660614870EA0E051BF6BDDF495798 /* KeyboardTrackingView.swift */, - C6C56947CAF8EFCC7858E1E2F1273427 /* MarginAdjustable.swift */, - B91AD9D9E743D17D553D48103BE27C46 /* MarginAdjustable+Extensions.swift */, - 9CF61FDEFE095F0486E9914F2262ADB9 /* MaskingView.swift */, - 8901520225CE89F44E6DE88688F29C10 /* MessageView.swift */, - AE62AA801971C530345349D18AFCCB82 /* MessageView.xib */, - 7FCF161BD9F1C2CAAFBCADE5E59BD3FD /* NSBundle+Extensions.swift */, - 0970322A5DD8B4A8373C35ED051DE156 /* NSLayoutConstraint+Extensions.swift */, - D7C557E1DC95AFA417E94ED01301F9F2 /* PassthroughView.swift */, - 382E6375390EBB09F829519F8ACCB7D7 /* PassthroughWindow.swift */, - FE3BED1799B2F867F5C984C2A051E36A /* PhysicsAnimation.swift */, - 2337E6D5F621F3CE9A1E3761984EBE87 /* PhysicsPanHandler.swift */, - 7A965DD26246DCA8CE39FBAB348ABA24 /* Presenter.swift */, - 7A6801849037A728E9BC50E06CE8AD2F /* StatusLine.xib */, - FC73E6C784AF6CA1F956F57F82ED2803 /* successIcon.png */, - 62755A788F910CA88887B6F63BBC545F /* successIcon@2x.png */, - C8155ED78358FA5CF39089176FBDE501 /* successIcon@3x.png */, - A80433B71162112A79043CB64261DB51 /* successIconLight.png */, - F898B2AC5C3404C266BBCA3B6D22B5E4 /* successIconLight@2x.png */, - 72A865FFBAE49EF66A35CB9D709E8D7E /* successIconLight@3x.png */, - 1DC54BB09EFDFEDE11F484FE73BEDC60 /* successIconSubtle.png */, - 0B3A169D83BDA3613A661845D1607FC0 /* successIconSubtle@2x.png */, - 54B278C80D821C120FA70ABB6CAF1F46 /* successIconSubtle@3x.png */, - C3216CF40D770C387D45C3B4AF2CC9E0 /* SwiftMessages.swift */, - A3C32E945AE3E6394EF85CD6BEC714B4 /* SwiftMessages.Config+Extensions.swift */, - AFFDB7DDC6B6B064B9D12281E2531BFA /* SwiftMessagesSegue.swift */, - B7FD0618783A3E6B90D3A3323633959F /* TabView.xib */, - D5607E285A85AC7163B0B8FD447FD27E /* Theme.swift */, - 396FCF260E9C2B3F11080A91E3D72334 /* TopBottomAnimation.swift */, - A9A13E69643D651322647C28E3F9E9C9 /* UIEdgeInsets+Extensions.swift */, - 15C4C88778A19C193D1EC77FA77BAE4C /* UIViewController+Extensions.swift */, - 397C8F928170138667B9326F9655D75D /* UIWindow+Extensions.swift */, - 0259757860B26C6072E2640B84EC6D45 /* warningIcon.png */, - BFEF746702215C33B51BEE64C4E48F0A /* warningIcon@2x.png */, - 2CFBBC25592C97C925B6F81B53BE57CB /* warningIcon@3x.png */, - 79E38069364BC5DF4EA88F352E28B242 /* warningIconLight.png */, - 874D31DE863C88B1D699E1EBFBE0641B /* warningIconLight@2x.png */, - C17CFEF9B761A322945F74D86CA88036 /* warningIconLight@3x.png */, - 4512DEEA328AB0AAA95D77C84C89E02C /* warningIconSubtle.png */, - ED86D7B42F55040DCE162653FB3C7EDB /* warningIconSubtle@2x.png */, - 667DECE93ABCC6869A071FFEB0F83EA5 /* warningIconSubtle@3x.png */, - 2E6941E59EF0D89949E3DF3D89488430 /* Weak.swift */, - 0A8566413BFA3FE6827E63E30515C9B3 /* WindowViewController.swift */, - ); - name = AppExtension; - sourceTree = "<group>"; - }; - B3699CF01F28F4B75166BA983453EAF3 /* Support Files */ = { - isa = PBXGroup; - children = ( - C9D915B60769D3C45A0DA3A5BA9514B8 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */, - 346718C2C7A108C86535F89FEB0EC176 /* SwiftMessages.modulemap */, - A2F9031B7FA82A17F04D4403091DF836 /* SwiftMessages-dummy.m */, - 90F364E0C9A6EFE24680868D0BD293F1 /* SwiftMessages-Info.plist */, - FCDC8870EA94B5B1E966D34D2B1FA5FE /* SwiftMessages-prefix.pch */, - C614EECDDFE644AF0BF7CB16A3D74404 /* SwiftMessages-umbrella.h */, - 6E9D4A0FDDEEDDC5A1A63D89B43C1F18 /* SwiftMessages.debug.xcconfig */, - E070773539E02C11297794CC4CB839D6 /* SwiftMessages.release.xcconfig */, - ); - name = "Support Files"; - path = "iMessageDemo/Pods/Target Support Files/SwiftMessages"; - sourceTree = "<group>"; - }; BD13800F87C70DC802DBC0C37E8C5E99 /* Pods-iMessageExtensionDemo */ = { isa = PBXGroup; children = ( @@ -448,7 +441,7 @@ C5AAA95D48373FAC474F6EFCC1749444 /* Development Pods */ = { isa = PBXGroup; children = ( - 9A632FB0C8554E0688B34926AF9C52DB /* SwiftMessages */, + 5EAB54907DABB41DF2E9177067EF69D4 /* SwiftMessages */, ); name = "Development Pods"; sourceTree = "<group>"; @@ -464,30 +457,40 @@ ); sourceTree = "<group>"; }; + E7706B1F04CCC75F42C733B60ED5FBDC /* Pod */ = { + isa = PBXGroup; + children = ( + FC12F21544AE9FE6D9E1E2F7730EF7EC /* LICENSE.md */, + E9E929B0E2A84EA903C9923B926A44E2 /* README.md */, + 59FEAC25BE3FCB9F8373DE26400CC89D /* SwiftMessages.podspec */, + ); + name = Pod; + sourceTree = "<group>"; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 96A1C098516CB9F20C4BE19860673FA7 /* Headers */ = { + 21076A86F5547DA5AEE656FE5EC63826 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 560A2B1056FEFE42AC6524A2A1742CA2 /* Pods-iMessageExtensionDemo-umbrella.h in Headers */, + AD7F228AE0628DAAE4497493335D2BF7 /* SwiftMessages-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - AEC231A576EA094C9EF913D75BA2D69C /* Headers */ = { + 96A1C098516CB9F20C4BE19860673FA7 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 7BC52E6F0D9D19B05E62E623E53FCE82 /* Pods-iMessageDemo-umbrella.h in Headers */, + 560A2B1056FEFE42AC6524A2A1742CA2 /* Pods-iMessageExtensionDemo-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - B534C45C1A426DF58D21D75F281F983A /* Headers */ = { + AEC231A576EA094C9EF913D75BA2D69C /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 9E3D4CA932041E99B6FD56D4E79A726F /* SwiftMessages-umbrella.h in Headers */, + 7BC52E6F0D9D19B05E62E623E53FCE82 /* Pods-iMessageDemo-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -496,11 +499,11 @@ /* Begin PBXNativeTarget section */ 1FC5E8328653C350899229BDF89FACE5 /* SwiftMessages-SwiftMessages_SwiftMessages */ = { isa = PBXNativeTarget; - buildConfigurationList = 57E1F5473FEF9FC2401E805CCF8188C3 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages_SwiftMessages" */; + buildConfigurationList = 1B3FEB13A547A2F656C2328E0CE130B5 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages_SwiftMessages" */; buildPhases = ( - 5FA15A9B2968910DC30C1AC895A5397A /* Sources */, - C3AABE927CAF3C6135B4D37CA433F885 /* Frameworks */, - F8808FE568E0B01931D6216DF79110B1 /* Resources */, + FFA9EA2B25A56389D60078D35A7276A6 /* Sources */, + 9DEA36BAD403380FF5C38B4F2B4C3AB9 /* Frameworks */, + BF76892AD99FBDD7554F3F71E205A3B6 /* Resources */, ); buildRules = ( ); @@ -523,7 +526,7 @@ buildRules = ( ); dependencies = ( - BB9BD3F204FD8449B62AD70E23DABC13 /* PBXTargetDependency */, + 4D52C266BAECF408C5DEB677038E1EEA /* PBXTargetDependency */, ); name = "Pods-iMessageExtensionDemo"; productName = "Pods-iMessageExtensionDemo"; @@ -532,17 +535,17 @@ }; DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */ = { isa = PBXNativeTarget; - buildConfigurationList = ABCC3636B5EAEBE6D60D155704F40EBC /* Build configuration list for PBXNativeTarget "SwiftMessages" */; + buildConfigurationList = 7D9EC6095BF15A96EABE2FE5045DA5DE /* Build configuration list for PBXNativeTarget "SwiftMessages" */; buildPhases = ( - B534C45C1A426DF58D21D75F281F983A /* Headers */, - ABE787B29A89D2BB29F92EAE5C8526CF /* Sources */, - FA7AA2A57B110DEF3C1F616FA77A05A7 /* Frameworks */, - C69D4A2DC76A80BD6D45A9BE85B2EEB1 /* Resources */, + 21076A86F5547DA5AEE656FE5EC63826 /* Headers */, + E0A3D02CDE28535DB4F00412E5814A99 /* Sources */, + EF08D4F0B96CF6C9AB42DC368EE3849A /* Frameworks */, + 036D5B81C59A567C797D02AA3A18D7F4 /* Resources */, ); buildRules = ( ); dependencies = ( - 03EC5F5CF0CAA96E132B778FB51EBCE9 /* PBXTargetDependency */, + 35EE405E4B00027013209FA505020C1C /* PBXTargetDependency */, ); name = SwiftMessages; productName = SwiftMessages; @@ -561,7 +564,7 @@ buildRules = ( ); dependencies = ( - 3CF465B66D2B58FC406E66E621CBCB11 /* PBXTargetDependency */, + 50C0F94C8A0A997FF42A574D8367A3C7 /* PBXTargetDependency */, ); name = "Pods-iMessageDemo"; productName = "Pods-iMessageDemo"; @@ -599,73 +602,73 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 61DB2F41473C1B8FEA6385AA240E2586 /* Resources */ = { + 036D5B81C59A567C797D02AA3A18D7F4 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 47F1E9964F1112D0E8F0FF8C25204E2F /* SwiftMessages_SwiftMessages.bundle in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - B1A8F08DE3F2C1EF1D63EF29C9D3D327 /* Resources */ = { + 61DB2F41473C1B8FEA6385AA240E2586 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - C69D4A2DC76A80BD6D45A9BE85B2EEB1 /* Resources */ = { + B1A8F08DE3F2C1EF1D63EF29C9D3D327 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 425F2D4CE95436680D77C263FF15221B /* SwiftMessages_SwiftMessages.bundle in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - F8808FE568E0B01931D6216DF79110B1 /* Resources */ = { + BF76892AD99FBDD7554F3F71E205A3B6 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4E9CCFC43646B6CDBE3B787AB09A0147 /* CardView.xib in Resources */, - F27E3EEAFDDAA6CB4E7407D6A46DAA5D /* CenteredView.xib in Resources */, - 5260BD3289BAC54A20457099C4A57EFF /* errorIcon.png in Resources */, - 683A7897D1E9A73F4717198B1C054D29 /* errorIcon@2x.png in Resources */, - 6A539682FDDA0E5DA23E1B5F2BA133C1 /* errorIcon@3x.png in Resources */, - 4E703B2A80C64CF1142872BE31263940 /* errorIconLight.png in Resources */, - 1F4159921A25C7B2A0E9C587387D829C /* errorIconLight@2x.png in Resources */, - 4C78ED4E1780F5609E25CE03429C1DE4 /* errorIconLight@3x.png in Resources */, - 365594AAFDD4EE947EB33E6E86A8578E /* errorIconSubtle.png in Resources */, - EDA146BF3FF59593677F8B2AA785D8A5 /* errorIconSubtle@2x.png in Resources */, - D8BDC20F1566606BF64001B6E96B14B6 /* errorIconSubtle@3x.png in Resources */, - C5FFE932D5EBE2CC8F2ABFEA893D8E9C /* infoIcon.png in Resources */, - B2CC8FF0F9FF3FE929180CDB32B69F18 /* infoIcon@2x.png in Resources */, - B60094A8D1343B7351F0EF9C51F2F0DB /* infoIcon@3x.png in Resources */, - 5720D965B3CE67653082137053FBEC9C /* infoIconLight.png in Resources */, - D61D59BCDFD2C3C7993CFE883DE60692 /* infoIconLight@2x.png in Resources */, - 9FFE65CB6E825ECAE4838D53E7BA4C06 /* infoIconLight@3x.png in Resources */, - C4598A458697C49C961BFDCD090B3A8F /* infoIconSubtle.png in Resources */, - 2B23A9DFDAACFE9C0AD5EB6899E63475 /* infoIconSubtle@2x.png in Resources */, - 7ACCA07CCFD868899D61F4B4AE5774DB /* infoIconSubtle@3x.png in Resources */, - 2558CABB502ED605BC21DCFC55A9C0B7 /* MessageView.xib in Resources */, - 492F085489FCAB0EEBE74B098F7D3F4D /* StatusLine.xib in Resources */, - 462CDC24C5C8DD6905C4112B6B4BD2ED /* successIcon.png in Resources */, - B42A7A38C8014DBDE2632B909F71C355 /* successIcon@2x.png in Resources */, - 44C0F194D748EE88027414A5B2094E9B /* successIcon@3x.png in Resources */, - 138A7742F76993FB9EE3555FD2808562 /* successIconLight.png in Resources */, - BDCF9C5E4F88B2B0AB6D4595E5A281E1 /* successIconLight@2x.png in Resources */, - 33785D52B8888C2EA02BD0495408E352 /* successIconLight@3x.png in Resources */, - AC4F13F50EB63B484292D67692BC1F9D /* successIconSubtle.png in Resources */, - BBFE3BAFFCE67F4EACE0C67A7B7FFC3A /* successIconSubtle@2x.png in Resources */, - 5DF3F4808ED4A6932839C11A5D742B93 /* successIconSubtle@3x.png in Resources */, - 57072960EA4F0D307171ED90697D3FAF /* TabView.xib in Resources */, - 447E8A096C1ABD2E0AC9674E65A827E3 /* warningIcon.png in Resources */, - BB16D1E73A5D6B27DC4212926986107F /* warningIcon@2x.png in Resources */, - 64595C731B826EB19E9757D524E0BF76 /* warningIcon@3x.png in Resources */, - CCF5CC8F6022DFD410DDCC99A90D58B0 /* warningIconLight.png in Resources */, - 4DB5D1FB08693DDDC32BCF19CC1B1AA0 /* warningIconLight@2x.png in Resources */, - C6E73F201545CF5ED055C69CD4DB2EFF /* warningIconLight@3x.png in Resources */, - 1F6162906845BE72A5BCDAF14D6E14B9 /* warningIconSubtle.png in Resources */, - 89ACEF0F9E524BD21D6C2460FEC375F8 /* warningIconSubtle@2x.png in Resources */, - 755DA479621A9D2BB8B84540DE648A7A /* warningIconSubtle@3x.png in Resources */, + A67A9ADFBCB364FCEF1BD92FF20B285C /* CardView.xib in Resources */, + 9F0473806FD530165403E47E834790C2 /* CenteredView.xib in Resources */, + 9B1E91097B4BD539EBCBBCC3C62CB75A /* errorIcon.png in Resources */, + ADA91E8F5FDCD2EEC3D3B18A5B375C2C /* errorIcon@2x.png in Resources */, + A9FFA668A7F81F50FBDCDCE26E891C8B /* errorIcon@3x.png in Resources */, + 11DE7052A0A78D6E27D8D129D413DAF6 /* errorIconLight.png in Resources */, + 34CB62900FA4AAC84745C7E958657648 /* errorIconLight@2x.png in Resources */, + FDC2C20416D7EBF959A461E25FAFB16E /* errorIconLight@3x.png in Resources */, + E70A6E572A6DD457A766908E3ADCF49B /* errorIconSubtle.png in Resources */, + 668EDAB86421216BEF7D3F932851A834 /* errorIconSubtle@2x.png in Resources */, + F69D9D53A5500A42D4B41097537628E5 /* errorIconSubtle@3x.png in Resources */, + 8F1BAB73C85D58C56F55E91573C2E7EF /* infoIcon.png in Resources */, + ADE48B746D5BB28EC33B403E1E12E0FE /* infoIcon@2x.png in Resources */, + 5B9F8D117AF7BEDDB511EF475FA25995 /* infoIcon@3x.png in Resources */, + 4B907B48F27F55DF65CC1553C7C26942 /* infoIconLight.png in Resources */, + CC9369D0A5F8715733A4D517E45A3B63 /* infoIconLight@2x.png in Resources */, + B4D338F85183163DC8CAB8A5864C9015 /* infoIconLight@3x.png in Resources */, + 62B05E0AC13A614A2F8D8A1BE9B514B3 /* infoIconSubtle.png in Resources */, + 9CFE7FFD7DDE28FCDA72647F2DB82837 /* infoIconSubtle@2x.png in Resources */, + C826D41BE5AF283B12C122AEF9640C99 /* infoIconSubtle@3x.png in Resources */, + 7B352022AFCAA5C364E1E2F61290628E /* MessageView.xib in Resources */, + 30D023ABC2D1CFC829CF04360768B7F8 /* StatusLine.xib in Resources */, + 95DD12BBA763163407787AB32AAF8E56 /* successIcon.png in Resources */, + C11CE75FD2DFCDF3B72D8D16280A2054 /* successIcon@2x.png in Resources */, + 755898E0E511FC5AE881403BEF2A02FC /* successIcon@3x.png in Resources */, + 80DE92140CF5AFB5224643FA952EFDEA /* successIconLight.png in Resources */, + ADA044C43E517C5F0603B2A0AFB19860 /* successIconLight@2x.png in Resources */, + C418A50F3C321227B0C6BE1D793680D4 /* successIconLight@3x.png in Resources */, + CD480EEF400EC9B894F3292506BF0179 /* successIconSubtle.png in Resources */, + 61548914728141D77F87E31B3911CE7E /* successIconSubtle@2x.png in Resources */, + 56F9865D99C4FADB8FC83CA548F82110 /* successIconSubtle@3x.png in Resources */, + 9FA48348FB5F41070356A75237367D6D /* TabView.xib in Resources */, + DECF1F62709D95EF5B48628A97B3CF98 /* warningIcon.png in Resources */, + 946185C05E253C9E47ABCD9EDE7E14D1 /* warningIcon@2x.png in Resources */, + B679ED0F79CAF552C081588F3B63B91A /* warningIcon@3x.png in Resources */, + 3A8B97D9210D1E2BEED5E1159BE7E748 /* warningIconLight.png in Resources */, + E8174481BFB4559462F82062D85C0376 /* warningIconLight@2x.png in Resources */, + 4B9459A11E2A1D65AE3224CF468AE8CA /* warningIconLight@3x.png in Resources */, + 1662CF43016AFC375200E466F130D90E /* warningIconSubtle.png in Resources */, + 6685298EC64F73060F5DB1A841375069 /* warningIconSubtle@2x.png in Resources */, + B02B2EAB7B8662AA27D91403BF9AAF36 /* warningIconSubtle@3x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -688,78 +691,79 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5FA15A9B2968910DC30C1AC895A5397A /* Sources */ = { + E0A3D02CDE28535DB4F00412E5814A99 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 02905CCF79B22A773CD0BA32EDB9648A /* AccessibleMessage.swift in Sources */, + F75A8D3DA9B4787BEEEBF3F784D5CDEF /* Animator.swift in Sources */, + DE23509CED3A1E62F60E7E4BD6D38A35 /* BackgroundViewable.swift in Sources */, + 4889E21A2024267A944084FB851200B5 /* BaseView.swift in Sources */, + 3BFC9F0FAF0757A2D3574ED4E4100D57 /* CALayer+Extensions.swift in Sources */, + 28F2E02536C48A4B661D6D8AAFB5D37E /* CornerRoundingView.swift in Sources */, + F9A111F30C3B26D0A35B0829EED70D26 /* Error.swift in Sources */, + 4256FC87C833154DCDEE84CD98F910D7 /* Identifiable.swift in Sources */, + 13620BA62A66C8C6F9345341BCD111ED /* KeyboardTrackingView.swift in Sources */, + 632538BAE98BBFD6CED58844B7611C24 /* MarginAdjustable+Extensions.swift in Sources */, + 7905F28CF56E06626475EBA3EB73D905 /* MarginAdjustable.swift in Sources */, + 0C55441C4B8356AC1244EED7684E1783 /* MaskingView.swift in Sources */, + 934A8FA91D6518CB70273B73F8038ECA /* MessageView.swift in Sources */, + F05B5437AFF475FE8811E2A8A734920F /* NSBundle+Extensions.swift in Sources */, + B520EDE98BD17CE5676F52A77139A933 /* NSLayoutConstraint+Extensions.swift in Sources */, + D34D8255545B84A38C98D2DBB2F12CC5 /* PassthroughView.swift in Sources */, + 05D9CBEC9488BAA2962B174703D25218 /* PassthroughWindow.swift in Sources */, + FA02B47E32DD9BEAAB8A2D1B66F697D5 /* PhysicsAnimation.swift in Sources */, + 9B1F7A4183F57B0AA9DD02624BD8855B /* PhysicsPanHandler.swift in Sources */, + F4BE83FBD5001DEDF6736E69ADA6D79B /* Presenter.swift in Sources */, + 00764FFD14D83F4ABEC0D4D53D48080A /* SwiftMessages-dummy.m in Sources */, + 5CA294C8D3BBC986CF0703D4E2A28687 /* SwiftMessages.Config+Extensions.swift in Sources */, + 4E82DE4069FECF20D0E29CB06A0FCFB6 /* SwiftMessages.swift in Sources */, + C739607C022819840C267A0B4A7B2FD9 /* SwiftMessagesSegue.swift in Sources */, + 9B89868BA12CC4E1D9F116F663E56695 /* Theme.swift in Sources */, + 6A933CC66558A1FB0AB0BC76F9807E71 /* TopBottomAnimation.swift in Sources */, + 531825CE7041C5C1BA684BDA9C8972A3 /* UIEdgeInsets+Extensions.swift in Sources */, + 9DBD1955C7C621D9DCBE03D2161C91A9 /* UIViewController+Extensions.swift in Sources */, + 94B459D6CBA2A01D2B8174D138C30920 /* UIWindow+Extensions.swift in Sources */, + 926907C8DCE76101AF5CB470DB7797D7 /* Weak.swift in Sources */, + AF34F903519AF36E07A90EF1BD703777 /* WindowScene.swift in Sources */, + AC0A9B473B11FFF4BDEC0A0598795843 /* WindowViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - ABE787B29A89D2BB29F92EAE5C8526CF /* Sources */ = { + FFA9EA2B25A56389D60078D35A7276A6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A11E7A379B288CCA3AE6785B83FA4316 /* AccessibleMessage.swift in Sources */, - 44150A4B5B2D251FCBB6CA07DC9872B5 /* Animator.swift in Sources */, - E94E8711BDDA31B178AA032D3346C307 /* BackgroundViewable.swift in Sources */, - 4267FACE20717FF3F51C2ACAB8C395A4 /* BaseView.swift in Sources */, - D49E06426C51C49E9058371138972A69 /* CALayer+Extensions.swift in Sources */, - 6320AE79D41E8D1F52AF66A670542561 /* CornerRoundingView.swift in Sources */, - A1734DB0A8A558B2397AF54E63F64416 /* Error.swift in Sources */, - FCB6832EB4D32EF085E770E8B4A9BC2C /* Identifiable.swift in Sources */, - 3505AB28DBFA49FBE5C8250F3E067E60 /* KeyboardTrackingView.swift in Sources */, - 0E7AE1B3CE2734B39ACCE812B4320B44 /* MarginAdjustable+Extensions.swift in Sources */, - 966B9C1EE6B73E430F03D51A4FD26D20 /* MarginAdjustable.swift in Sources */, - 5750C24C3A9CAE11C7E36B37434912D0 /* MaskingView.swift in Sources */, - 0B42A04122166EAD384BCE37FD450FAF /* MessageView.swift in Sources */, - 461760E2818D72B948B60B4835E7B1ED /* NSBundle+Extensions.swift in Sources */, - 16047C447B00FAA7F42764EC4167C33B /* NSLayoutConstraint+Extensions.swift in Sources */, - 0CE00BF7FB0F6376D89B0AFF1CFD7510 /* PassthroughView.swift in Sources */, - C8F46E0A5853739D3F632B4828FDE9CC /* PassthroughWindow.swift in Sources */, - 7E5ADF1F3B6849D5A0DF8E2B9C1861C5 /* PhysicsAnimation.swift in Sources */, - 0303F738260F2C9BAE20B79DE84E82BC /* PhysicsPanHandler.swift in Sources */, - FF01BC94FADD5A72282AEE043DF523A7 /* Presenter.swift in Sources */, - FA6CA270F521DF68A75E527954A2DDAD /* SwiftMessages-dummy.m in Sources */, - F50FE2EE47422AD39AC8F7F115081E7E /* SwiftMessages.Config+Extensions.swift in Sources */, - B2862C6DDAA6543BB2C8F4541F044564 /* SwiftMessages.swift in Sources */, - 9CEE0E569456D932AA34329D2038DF98 /* SwiftMessagesSegue.swift in Sources */, - 2181E713FC7C00EE871FDA6CB62C7E8C /* Theme.swift in Sources */, - BC4618CE535404A9540D4D110B5767A1 /* TopBottomAnimation.swift in Sources */, - 52F4ED7F78829270B2AFE5EDBA9EEE2F /* UIEdgeInsets+Extensions.swift in Sources */, - D9077478C2FCD7C3DD1EBE9373281728 /* UIViewController+Extensions.swift in Sources */, - 6C7DAA6A68AFDACD67F2C127CEF4DD6F /* UIWindow+Extensions.swift in Sources */, - 00468531530F8A70E3D83622BD482026 /* Weak.swift in Sources */, - F5642C087197B9033252FF10FBA92B59 /* WindowViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 03EC5F5CF0CAA96E132B778FB51EBCE9 /* PBXTargetDependency */ = { + 35EE405E4B00027013209FA505020C1C /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "SwiftMessages-SwiftMessages_SwiftMessages"; target = 1FC5E8328653C350899229BDF89FACE5 /* SwiftMessages-SwiftMessages_SwiftMessages */; - targetProxy = 141E78A8858DBF8B2695DFEDCBDF5158 /* PBXContainerItemProxy */; + targetProxy = D19F271ED5B0FED7305E55070B415EDB /* PBXContainerItemProxy */; }; - 3CF465B66D2B58FC406E66E621CBCB11 /* PBXTargetDependency */ = { + 4D52C266BAECF408C5DEB677038E1EEA /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SwiftMessages; target = DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */; - targetProxy = 4DB1DDB02425E67ED85C70C3B138E205 /* PBXContainerItemProxy */; + targetProxy = 4B785BB517DA1D687C0B772C77660019 /* PBXContainerItemProxy */; }; - BB9BD3F204FD8449B62AD70E23DABC13 /* PBXTargetDependency */ = { + 50C0F94C8A0A997FF42A574D8367A3C7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SwiftMessages; target = DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */; - targetProxy = 900F05D1477FFAB64FF410CBB6B9B74D /* PBXContainerItemProxy */; + targetProxy = DA9FA5DB745280F35DD4EFAC9A7A4FD7 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 24D1D8F3B822E3083FF435C91CB434FD /* Debug */ = { + 01CE4E62B8DE70DDCEADD46669F1118B /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6E9D4A0FDDEEDDC5A1A63D89B43C1F18 /* SwiftMessages.debug.xcconfig */; + baseConfigurationReference = 87745BF2C7154EF88509BED0D71243F1 /* SwiftMessages.debug.xcconfig */; buildSettings = { CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SwiftMessages"; IBSC_MODULE = SwiftMessages; @@ -773,6 +777,22 @@ }; name = Debug; }; + 27EC13F078A5EF4E57265026E5EA01CB /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B7BF853CD0CDFA20423D4C813B34B57F /* SwiftMessages.release.xcconfig */; + buildSettings = { + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SwiftMessages"; + IBSC_MODULE = SwiftMessages; + INFOPLIST_FILE = "Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = SwiftMessages_SwiftMessages; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; 6427804744C4054555383985007A0B6C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -901,40 +921,6 @@ }; name = Release; }; - 7C5AE2DF0A930DD6AC66390486478632 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = E070773539E02C11297794CC4CB839D6 /* SwiftMessages.release.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/SwiftMessages/SwiftMessages-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SwiftMessages/SwiftMessages-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MODULEMAP_FILE = "Target Support Files/SwiftMessages/SwiftMessages.modulemap"; - PRODUCT_MODULE_NAME = SwiftMessages; - PRODUCT_NAME = SwiftMessages; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; 891563622FB1DE05CD4905BE16203F07 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = C306ACAFEE157959D78E71DBBBD675DC /* Pods-iMessageExtensionDemo.debug.xcconfig */; @@ -1010,21 +996,38 @@ }; name = Release; }; - BCFFE899A2E9C1DF0CA120A3F3CECECC /* Release */ = { + B9F08B726D3DD8C6ACDBB8CC2E05B693 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E070773539E02C11297794CC4CB839D6 /* SwiftMessages.release.xcconfig */; + baseConfigurationReference = 87745BF2C7154EF88509BED0D71243F1 /* SwiftMessages.debug.xcconfig */; buildSettings = { - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SwiftMessages"; - IBSC_MODULE = SwiftMessages; - INFOPLIST_FILE = "Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SwiftMessages/SwiftMessages-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SwiftMessages/SwiftMessages-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; - PRODUCT_NAME = SwiftMessages_SwiftMessages; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/SwiftMessages/SwiftMessages.modulemap"; + PRODUCT_MODULE_NAME = SwiftMessages; + PRODUCT_NAME = SwiftMessages; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; C9423D1E13393A1A8BC54BE4E87A96AD /* Release */ = { isa = XCBuildConfiguration; @@ -1064,9 +1067,9 @@ }; name = Release; }; - F069CD2F5774D5082336F140E5F68B3A /* Debug */ = { + D0E16784196812CD6F00BFEE04C50E82 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6E9D4A0FDDEEDDC5A1A63D89B43C1F18 /* SwiftMessages.debug.xcconfig */; + baseConfigurationReference = B7BF853CD0CDFA20423D4C813B34B57F /* SwiftMessages.release.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -1092,10 +1095,11 @@ SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; FCA0FCAB93E530D2C6BED8D3910FEB4A /* Debug */ = { isa = XCBuildConfiguration; @@ -1137,38 +1141,38 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 20A82A14E31D7EFF5BE9B60529162F4B /* Build configuration list for PBXNativeTarget "Pods-iMessageDemo" */ = { + 1B3FEB13A547A2F656C2328E0CE130B5 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages_SwiftMessages" */ = { isa = XCConfigurationList; buildConfigurations = ( - FCA0FCAB93E530D2C6BED8D3910FEB4A /* Debug */, - C9423D1E13393A1A8BC54BE4E87A96AD /* Release */, + 01CE4E62B8DE70DDCEADD46669F1118B /* Debug */, + 27EC13F078A5EF4E57265026E5EA01CB /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + 20A82A14E31D7EFF5BE9B60529162F4B /* Build configuration list for PBXNativeTarget "Pods-iMessageDemo" */ = { isa = XCConfigurationList; buildConfigurations = ( - 6427804744C4054555383985007A0B6C /* Debug */, - 74556EDEC03158A3009CA84D67369133 /* Release */, + FCA0FCAB93E530D2C6BED8D3910FEB4A /* Debug */, + C9423D1E13393A1A8BC54BE4E87A96AD /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 57E1F5473FEF9FC2401E805CCF8188C3 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages_SwiftMessages" */ = { + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - 24D1D8F3B822E3083FF435C91CB434FD /* Debug */, - BCFFE899A2E9C1DF0CA120A3F3CECECC /* Release */, + 6427804744C4054555383985007A0B6C /* Debug */, + 74556EDEC03158A3009CA84D67369133 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - ABCC3636B5EAEBE6D60D155704F40EBC /* Build configuration list for PBXNativeTarget "SwiftMessages" */ = { + 7D9EC6095BF15A96EABE2FE5045DA5DE /* Build configuration list for PBXNativeTarget "SwiftMessages" */ = { isa = XCConfigurationList; buildConfigurations = ( - F069CD2F5774D5082336F140E5F68B3A /* Debug */, - 7C5AE2DF0A930DD6AC66390486478632 /* Release */, + B9F08B726D3DD8C6ACDBB8CC2E05B693 /* Debug */, + D0E16784196812CD6F00BFEE04C50E82 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; From 1e49de7b3780b69927bc3e61903d8ec0693a3dc5 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Tue, 5 Oct 2021 13:11:30 -0500 Subject: [PATCH 47/77] Work/9.0.5 (#486) * Notifify will change before changes are made * Account for bounceAnimationOffset with keyboard avoidance * Release prep --- CHANGELOG.md | 7 +++++++ SwiftMessages.podspec | 2 +- SwiftMessages/KeyboardTrackingView.swift | 16 +++++++++++++++- SwiftMessages/MaskingView.swift | 11 ++++++++++- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed087150..de1f84a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Change Log All notable changes to this project will be documented in this file. +## 9.0.5 + +### Fixes + +* #482 Fix timing of `KeyboardTrackingView` callbacks. +* #483 KeyboardTrackingView causes a small space under bottom-style view + ## 9.0.4 * #471 Xcode 13 issue - Enum cases with associated values cannot be marked potentially unavailable with '@available' diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 688f100f..c43a5298 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.0.4' + spec.version = '9.0.5' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } diff --git a/SwiftMessages/KeyboardTrackingView.swift b/SwiftMessages/KeyboardTrackingView.swift index 6af384a6..301d969c 100644 --- a/SwiftMessages/KeyboardTrackingView.swift +++ b/SwiftMessages/KeyboardTrackingView.swift @@ -44,6 +44,18 @@ open class KeyboardTrackingView: UIView { /// The margin to maintain between the keyboard and the top of the view. @IBInspectable open var topMargin: CGFloat = 0 + /// Subclasses can override this to do something before the change. + open func willChange( + change: KeyboardTrackingView.Change, + userInfo: [AnyHashable : Any] + ) {} + + /// Subclasses can override this to do something after the change. + open func didChange( + change: KeyboardTrackingView.Change, + userInfo: [AnyHashable : Any] + ) {} + override public init(frame: CGRect) { super.init(frame: frame) postInit() @@ -101,11 +113,12 @@ open class KeyboardTrackingView: UIView { guard !(isPaused || isAutomaticallyPaused), let userInfo = (notification as NSNotification).userInfo, let value = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return } + willChange(change: change, userInfo: userInfo) + delegate?.keyboardTrackingViewWillChange(change: change, userInfo: userInfo) let keyboardRect = value.cgRectValue let thisRect = convert(bounds, to: nil) let newHeight = max(0, thisRect.maxY - keyboardRect.minY) + topMargin guard heightConstraint.constant != newHeight else { return } - delegate?.keyboardTrackingViewWillChange(change: change, userInfo: userInfo) animateKeyboardChange(change: change, height: newHeight, userInfo: userInfo) } @@ -115,6 +128,7 @@ open class KeyboardTrackingView: UIView { let curveNumber = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber { CATransaction.begin() CATransaction.setCompletionBlock { + self.didChange(change: change, userInfo: userInfo) self.delegate?.keyboardTrackingViewDidChange(change: change, userInfo: userInfo) } UIView.beginAnimations(nil, context: nil) diff --git a/SwiftMessages/MaskingView.swift b/SwiftMessages/MaskingView.swift index 0ce4c428..d6313427 100644 --- a/SwiftMessages/MaskingView.swift +++ b/SwiftMessages/MaskingView.swift @@ -65,6 +65,15 @@ class MaskingView: PassthroughView { guard let keyboardTrackingView = keyboardTrackingView, view != keyboardTrackingView, view != backgroundView else { return } - keyboardTrackingView.topAnchor.constraint(greaterThanOrEqualTo: view.bottomAnchor).with(priority: UILayoutPriority(250)).isActive = true + let offset: CGFloat + if let adjustable = view as? MarginAdjustable { + offset = -adjustable.bounceAnimationOffset + } else { + offset = 0 + } + keyboardTrackingView.topAnchor.constraint( + greaterThanOrEqualTo: view.bottomAnchor, + constant: offset + ).with(priority: UILayoutPriority(250)).isActive = true } } From b29dd21090b708aa0ae9ecbaf6e2d0487028dc3f Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkick.it> Date: Fri, 14 Jan 2022 11:33:00 -0600 Subject: [PATCH 48/77] Add view associated type to Event --- CHANGELOG.md | 7 +++++++ README.md | 4 +++- SwiftMessages.podspec | 2 +- SwiftMessages/Presenter.swift | 8 ++++---- SwiftMessages/SwiftMessages.swift | 21 +++++++++++++++++---- 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de1f84a9..8c25038f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Change Log All notable changes to this project will be documented in this file. +## 9.0.6 + +### Features + +* Add `UIView` associated type to `Event`, e.g. `willShow(UIView)` so that event listeners can inspect the view. +* Add `Event.id: String?` property so that event listeners can reason about the view's ID. + ## 9.0.5 ### Fixes diff --git a/README.md b/README.md index c46c84cf..97e83746 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,9 @@ config.preferredStatusBarStyle = .lightContent // Specify one or more event listeners to respond to show and hide events. config.eventListeners.append() { event in - if case .didHide = event { print("yep") } + if case .didHide = event { + print("yep id=\(String(describing: event.id)") + } } SwiftMessages.show(config: config, view: view) diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index c43a5298..4c7b9451 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.0.5' + spec.version = '9.0.6' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index 11243f54..be093beb 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -119,7 +119,7 @@ class Presenter: NSObject { func show(completion: @escaping AnimationCompletion) throws { try presentationContext = getPresentationContext() install() - self.config.eventListeners.forEach { $0(.willShow) } + self.config.eventListeners.forEach { $0(.willShow(self.view)) } showAnimation() { completed in completion(completed) if completed { @@ -128,7 +128,7 @@ class Presenter: NSObject { } else { self.showAccessibilityAnnouncement() } - self.config.eventListeners.forEach { $0(.didShow) } + self.config.eventListeners.forEach { $0(.didShow(self.view)) } } } } @@ -181,7 +181,7 @@ class Presenter: NSObject { func hide(animated: Bool, completion: @escaping AnimationCompletion) { isHiding = true - self.config.eventListeners.forEach { $0(.willHide) } + self.config.eventListeners.forEach { $0(.willHide(self.view)) } let context = animationContext() let action = { if let viewController = self.presentationContext.viewControllerValue() as? WindowViewController { @@ -189,7 +189,7 @@ class Presenter: NSObject { } self.maskingView.removeFromSuperview() completion(true) - self.config.eventListeners.forEach { $0(.didHide) } + self.config.eventListeners.forEach { $0(.didHide(self.view)) } } guard animated else { action() diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index 7c0042f5..5e9f0c3c 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -219,10 +219,23 @@ open class SwiftMessages { Specifies events in the message lifecycle. */ public enum Event { - case willShow - case didShow - case willHide - case didHide + case willShow(UIView) + case didShow(UIView) + case willHide(UIView) + case didHide(UIView) + + public var view: UIView { + switch self { + case .willShow(let view): return view + case .didShow(let view): return view + case .willHide(let view): return view + case .didHide(let view): return view + } + } + + public var id: String? { + return (view as? Identifiable)?.id + } } /** From 4e49214f64f949cc00af225e1f6f4457f6fd62d5 Mon Sep 17 00:00:00 2001 From: mbastos <mathheusb@gmail.com> Date: Sat, 14 May 2022 13:59:22 -0300 Subject: [PATCH 49/77] Add dynamically linked option in products (#495) --- Package.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 5324d1b7..a0f30e8b 100644 --- a/Package.swift +++ b/Package.swift @@ -7,7 +7,8 @@ let package = Package( .iOS("9.0") ], products: [ - .library(name: "SwiftMessages", targets: ["SwiftMessages"]) + .library(name: "SwiftMessages", targets: ["SwiftMessages"]), + .library(name: "SwiftMessages-Dynamic", type: .dynamic, targets: ["SwiftMessages"]) ], targets: [ .target( From 3af7c4d5abf1a023c375b4f7d78f32cf12d02e5b Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Mon, 18 Sep 2023 11:56:20 -0500 Subject: [PATCH 50/77] Prevent orphaned views from blocking (#517) --- SwiftMessages/Presenter.swift | 10 +++++++++- SwiftMessages/SwiftMessages.swift | 8 ++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index be093beb..5a3648b8 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -68,6 +68,13 @@ class Presenter: NSObject { return duration } + /// Detects the scenario where the view was shown, but the containing view heirarchy was removed before the view + /// was hidden. This unusual scenario could result in the message queue being blocked because the presented + /// view was not properly hidden by SwiftMessages. `isOrphaned` allows the queuing logic to unblock the queue. + var isOrphaned: Bool { + return installed && view.window == nil + } + // MARK: - Constants enum PresentationContext { @@ -97,7 +104,7 @@ class Presenter: NSObject { private weak var delegate: PresenterDelegate? private var presentationContext = PresentationContext.viewController(Weak<UIViewController>(value: nil)) - + private var installed = false private var interactivelyHidden = false; // MARK: - Showing and hiding @@ -412,6 +419,7 @@ class Presenter: NSObject { maskingView.accessibleElements = elements } + installed = true guard let containerView = presentationContext.viewValue() else { return } (presentationContext.viewControllerValue() as? WindowViewController)?.install() installMaskingView(containerView: containerView) diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index 5e9f0c3c..395bc0ad 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -586,7 +586,10 @@ open class SwiftMessages { fileprivate func enqueue(presenter: Presenter) { if presenter.config.ignoreDuplicates { counts[presenter.id] = (counts[presenter.id] ?? 0) + 1 - if _current?.id == presenter.id && _current?.isHiding == false { return } + if let _current, + _current.id == presenter.id, + !_current.isHiding, + !_current.isOrphaned { return } if queue.filter({ $0.id == presenter.id }).count > 0 { return } } func doEnqueue() { @@ -606,7 +609,8 @@ open class SwiftMessages { } fileprivate func dequeueNext() { - guard self._current == nil, queue.count > 0 else { return } + guard queue.count > 0 else { return } + if let _current, !_current.isOrphaned { return } let current = queue.removeFirst() self._current = current // Set `autohideToken` before the animation starts in case From 977436eeef05a0a21bee8e7f651cd12f5b7ef191 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Mon, 18 Sep 2023 12:12:49 -0500 Subject: [PATCH 51/77] Remove unowned reference --- SwiftMessages/SwiftMessagesSegue.swift | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/SwiftMessages/SwiftMessagesSegue.swift b/SwiftMessages/SwiftMessagesSegue.swift index d4cba417..80c3939c 100644 --- a/SwiftMessages/SwiftMessagesSegue.swift +++ b/SwiftMessages/SwiftMessagesSegue.swift @@ -208,6 +208,7 @@ open class SwiftMessagesSegue: UIStoryboardSegue { override open func perform() { (source as? WindowViewController)?.install() selfRetainer = self + startReleaseMonitor() if overrideModalPresentationStyle { destination.modalPresentationStyle = .custom } @@ -222,6 +223,19 @@ open class SwiftMessagesSegue: UIStoryboardSegue { } fileprivate let safeAreaWorkaroundViewController = UIViewController() + + /// The self-retainer will not allow the segue, presenting and presented view controllers to be released if the presenting view controller + /// is removed without first dismissing. This monitor handles that scenario by setting `self.selfRetainer = nil` if + /// the presenting view controller is no longer in the heirarchy. + private func startReleaseMonitor() { + DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in + guard let self = self else { return } + switch self.source.view.window { + case .none: self.selfRetainer = nil + case .some: self.startReleaseMonitor() + } + } + } } extension SwiftMessagesSegue { @@ -288,12 +302,13 @@ extension SwiftMessagesSegue { extension SwiftMessagesSegue: UIViewControllerTransitioningDelegate { public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { let shower = TransitioningPresenter(segue: self) - messenger.defaultConfig.eventListeners.append { [unowned self] in + let hider = self.hider + messenger.defaultConfig.eventListeners.append { [weak self] in switch $0 { case .didShow: shower.completeTransition?(true) case .didHide: - if let completeTransition = self.hider.completeTransition { + if let completeTransition = hider.completeTransition { completeTransition(true) } else { // Case where message is internally hidden by SwiftMessages, such as with a @@ -301,7 +316,7 @@ extension SwiftMessagesSegue: UIViewControllerTransitioningDelegate { source.dismiss(animated: false, completion: nil) } (source as? WindowViewController)?.uninstall() - self.selfRetainer = nil + self?.selfRetainer = nil default: break } } From 813938a829bc0599712c9001eb2298cc0ffe6fb6 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Mon, 18 Sep 2023 12:13:02 -0500 Subject: [PATCH 52/77] Update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c25038f..0a4ec930 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # Change Log All notable changes to this project will be documented in this file. +## 9.0.7 + +### Fixes + +* #527 Crash while clicking two times to hide the presenting controller +* #517 Prevent orphaned views from blocking the queue +* Prevent orphaned `SwiftMessagesSeque`s from retaining the presenting view controller + ## 9.0.6 ### Features From 6c16e58ce72f8e7549930e3d2c62e25e224e799b Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Fri, 6 Oct 2023 09:38:19 -0500 Subject: [PATCH 53/77] Add basic support for SwiftUI (#528) --- README.md | 103 ++++- SwiftMessages.podspec | 6 +- SwiftMessages.xcodeproj/project.pbxproj | 72 ++- .../xcschemes/SwiftMessages.xcscheme | 2 +- SwiftMessages/BaseView.swift | 4 +- SwiftMessages/Identifiable.swift | 1 + SwiftMessages/MessageHostingView.swift | 42 ++ SwiftMessages/MessageViewConvertible.swift | 16 + SwiftMessages/SwiftMessageModifier.swift | 62 +++ SwiftMessages/SwiftMessagesSegue.swift | 8 - .../SwiftUIDemo.xcodeproj/project.pbxproj | 436 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 13 + .../SwiftUIDemo/Assets.xcassets/Contents.json | 6 + .../Contents.json | 20 + SwiftUIDemo/SwiftUIDemo/DemoMessage.swift | 22 + SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift | 35 ++ SwiftUIDemo/SwiftUIDemo/DemoView.swift | 48 ++ SwiftUIDemo/SwiftUIDemo/Info.plist | 5 + .../Preview Assets.xcassets/Contents.json | 6 + SwiftUIDemo/SwiftUIDemo/SwiftUIDemoApp.swift | 17 + 23 files changed, 910 insertions(+), 40 deletions(-) create mode 100644 SwiftMessages/MessageHostingView.swift create mode 100644 SwiftMessages/MessageViewConvertible.swift create mode 100644 SwiftMessages/SwiftMessageModifier.swift create mode 100644 SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj create mode 100644 SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Contents.json create mode 100644 SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Demo message background.colorset/Contents.json create mode 100644 SwiftUIDemo/SwiftUIDemo/DemoMessage.swift create mode 100644 SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift create mode 100644 SwiftUIDemo/SwiftUIDemo/DemoView.swift create mode 100644 SwiftUIDemo/SwiftUIDemo/Info.plist create mode 100644 SwiftUIDemo/SwiftUIDemo/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 SwiftUIDemo/SwiftUIDemo/SwiftUIDemoApp.swift diff --git a/README.md b/README.md index 97e83746..0cf8e79d 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ SwiftMessages is a very flexible view and view controller presentation library f Message views and view controllers can be displayed at the top, bottom, or center of the screen, or behind navigation bars and tab bars. There are interactive dismiss gestures including a fun, physics-based one. Multiple background dimming modes. And a lot more! +🔥 Now supports displaying SwiftUI message views 🔥 + In addition to the numerous configuration options, SwiftMessages provides several good-looking layouts and themes. But SwiftMessages is also designer-friendly, which means you can fully and easily customize the view: * Copy one of the included nib files into your project and change it. @@ -32,19 +34,6 @@ Try exploring [the demo app via appetize.io](http://goo.gl/KXw4nD) to get a feel <a href="http://goo.gl/KXw4nD"><img src="./Demo/appetize.png" /></a> </p> -## View Controllers - -SwiftMessages can present view controllers using the `SwiftMessagesSegue` custom modal segue! - -<p align="center"> - <img src="./Design/SwiftMessagesSegue.gif" /> -</p> - -[`SwiftMessagesSegue`](./SwiftMessages/SwiftMessagesSegue.swift) is a subclass of `UIStoryboardSegue` that integrates directly into Interface Builder as a custom modal segue, enabling view controllers to take advantage of SwiftMessages layouts, animations and more. `SwiftMessagesSegue` works with any UIKIt project — storyboards are not required. Refer to the View Controllers readme below for more information. - -#### [View Controllers Readme](./ViewControllers.md) - -And check out our blog post [Elegant Custom UIViewController Transitioning](http://www.swiftkickmobile.com/elegant-custom-uiviewcontroller-transitioning-uiviewcontrollertransitioningdelegate-uiviewcontrolleranimatedtransitioning/) to learn a great technique you can use to build your own custom segues that utilize `UIViewControllerTransitioningDelegate` and `UIViewControllerAnimatedTransitioning`. ## Installation @@ -178,6 +167,94 @@ config.duration = .forever SwiftMessages.show(config: config, view: view) ```` +### View Controllers + +SwiftMessages can present view controllers using the `SwiftMessagesSegue` custom modal segue! + +<p align="center"> + <img src="./Design/SwiftMessagesSegue.gif" /> +</p> + +[`SwiftMessagesSegue`](./SwiftMessages/SwiftMessagesSegue.swift) is a subclass of `UIStoryboardSegue` that integrates directly into Interface Builder as a custom modal segue, enabling view controllers to take advantage of SwiftMessages layouts, animations and more. `SwiftMessagesSegue` works with any UIKIt project — storyboards are not required. Refer to the View Controllers readme below for more information. + +#### [View Controllers Readme](./ViewControllers.md) + +And check out our blog post [Elegant Custom UIViewController Transitioning](http://www.swiftkickmobile.com/elegant-custom-uiviewcontroller-transitioning-uiviewcontrollertransitioningdelegate-uiviewcontrolleranimatedtransitioning/) to learn a great technique you can use to build your own custom segues that utilize `UIViewControllerTransitioningDelegate` and `UIViewControllerAnimatedTransitioning`. + +### SwiftUI + +Any of the built-in SwiftMessages views can be displayed by calling the SwiftMessages APIs from within observable object, a button action closure, etc. However, SwiftMessages can also display your custom SwiftUI views. + +First, define a type that conforms to `MessageViewConvertible`. This will typically be a struct containing the message data: + + +````swift +struct DemoMessage: Identifiable { + let title: String + let body: String + + var id: String { title + body } +} + +extension DemoMessage: MessageViewConvertible { + func asMessageView() -> DemoMessageView { + DemoMessageView(message: self) + } +} + +struct DemoMessageView: View { + + let message: DemoMessage + + var body: some View { + VStack(alignment: .leading) { + Text(message.title).font(.system(size: 20, weight: .bold)) + Text(message.body) + } + .multilineTextAlignment(.leading) + .padding(30) + .frame(maxWidth: .infinity) + .background(.gray) + .cornerRadius(15) + .padding(15) + } +} +```` + +The SwiftUI message view can be displayed just like any other UIKit message by using `MessageHostingView`: + +````swift +struct DemoView: View { + var body: some View { + Button("Show message") { + let message = DemoMessage(title: "Demo", body: "SwiftUI forever!") + let messageView = MessageHostingView(message: message) + SwiftMessages.show(view: messageView) + } + } +} +```` + +But you may also use a state-based approach using the `swiftMessage()` view modifier: + +````swift +struct DemoView: View { + + @State var message: DemoMessage? + + var body: some View { + Button("Show message") { + message = DemoMessage(title: "Demo", body: "SwiftUI forever!") + } + .swiftMessage(message: $message) + } +} +```` + +This technique may be more SwiftUI-like, but it doesn't offer the full capability of SwiftMessages, such as explicitly hiding messages by their ID. It is totally reasonable to use a combination of both approaches. + +Try it out in the SwiftUI demo app! + ### Accessibility SwiftMessages provides excellent VoiceOver support out-of-the-box. diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 4c7b9451..00b6a817 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,14 +1,14 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.0.6' + spec.version = '9.0.7' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } spec.summary = 'A very flexible message bar for iOS written in Swift.' spec.source = {:git => 'https://github.com/SwiftKickMobile/SwiftMessages.git', :tag => spec.version} - spec.platform = :ios, '9.0' + spec.platform = :ios, '12.0' spec.swift_version = '5.0' - spec.ios.deployment_target = '9.0' + spec.ios.deployment_target = '12.0' spec.framework = 'UIKit' spec.requires_arc = true spec.default_subspec = 'App' diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index b01d9c2f..45809f2d 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -52,6 +52,9 @@ 228DF5681FAD0806004F8A39 /* infoIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */; }; 228DF5691FAD0806004F8A39 /* successIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5481FAD0805004F8A39 /* successIconLight.png */; }; 228DF56A1FAD0806004F8A39 /* infoIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */; }; + 228F7DDE2ACF703A006C9644 /* MessageHostingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228F7DDB2ACF7039006C9644 /* MessageHostingView.swift */; }; + 228F7DDF2ACF703A006C9644 /* SwiftMessageModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228F7DDC2ACF703A006C9644 /* SwiftMessageModifier.swift */; }; + 228F7DE02ACF703A006C9644 /* MessageViewConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228F7DDD2ACF703A006C9644 /* MessageViewConvertible.swift */; }; 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */; }; @@ -140,6 +143,9 @@ 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = infoIconSubtle.png; path = Resources/infoIconSubtle.png; sourceTree = "<group>"; }; 228DF5481FAD0805004F8A39 /* successIconLight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = successIconLight.png; path = Resources/successIconLight.png; sourceTree = "<group>"; }; 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; + 228F7DDB2ACF7039006C9644 /* MessageHostingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageHostingView.swift; sourceTree = "<group>"; }; + 228F7DDC2ACF703A006C9644 /* SwiftMessageModifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftMessageModifier.swift; sourceTree = "<group>"; }; + 228F7DDD2ACF703A006C9644 /* MessageViewConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageViewConvertible.swift; sourceTree = "<group>"; }; 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = "<group>"; }; @@ -235,6 +241,15 @@ name = Frameworks; sourceTree = "<group>"; }; + 228F7DDA2ACF7029006C9644 /* SwiftUI */ = { + isa = PBXGroup; + children = ( + 228F7DDC2ACF703A006C9644 /* SwiftMessageModifier.swift */, + 228F7DDD2ACF703A006C9644 /* MessageViewConvertible.swift */, + ); + name = SwiftUI; + sourceTree = "<group>"; + }; 22D4779B20BF1C54005D0D71 /* View Controllers */ = { isa = PBXGroup; children = ( @@ -339,6 +354,7 @@ 86AAF8171D54F0650031EE32 /* PassthroughView.swift */, 22E01F631E74EC8B00ACE19A /* MaskingView.swift */, 86AAF8191D54F0850031EE32 /* PassthroughWindow.swift */, + 228F7DDB2ACF7039006C9644 /* MessageHostingView.swift */, 220D38672597A94C00BB2B88 /* Extensions */, ); name = Internal; @@ -352,6 +368,7 @@ 862C0CD81D5A396900D06168 /* Resources */, 2244656C1EF1D62700C50413 /* Animations */, 22D4779B20BF1C54005D0D71 /* View Controllers */, + 228F7DDA2ACF7029006C9644 /* SwiftUI */, 864495571D4F7C490056EB2A /* Base */, 220D38682597A9FD00BB2B88 /* Extensions */, 867E218E1D4D3DFD00594A41 /* Internal */, @@ -434,8 +451,9 @@ 867E21471D4D01D500594A41 /* Project object */ = { isa = PBXProject; attributes = { + BuildIndependentTargetsInParallel = YES; LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 1200; + LastUpgradeCheck = 1500; ORGANIZATIONNAME = "SwiftKick Mobile"; TargetAttributes = { 86B48AEB1D5A41C900063E2B = { @@ -539,13 +557,16 @@ 86BBA9011D5E040600FE8F16 /* PassthroughWindow.swift in Sources */, 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */, 86BBA9031D5E040600FE8F16 /* UIViewController+Extensions.swift in Sources */, + 228F7DDF2ACF703A006C9644 /* SwiftMessageModifier.swift in Sources */, 224FB69921153B440081D4DE /* CALayer+Extensions.swift in Sources */, 22E01F641E74EC8B00ACE19A /* MaskingView.swift in Sources */, 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */, + 228F7DE02ACF703A006C9644 /* MessageViewConvertible.swift in Sources */, 86BBA9001D5E040600FE8F16 /* PassthroughView.swift in Sources */, 22DFC9181F00674E001B1CA1 /* PhysicsPanHandler.swift in Sources */, 227BA6D920BF224A00E5A843 /* SwiftMessagesSegue.swift in Sources */, 220655121FAF82B600F4E00F /* MarginAdjustable+Extensions.swift in Sources */, + 228F7DDE2ACF703A006C9644 /* MessageHostingView.swift in Sources */, 22E307FF1E74C5B100E35893 /* AccessibleMessage.swift in Sources */, 220D386E2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift in Sources */, 2270044B1FAFA6DD0045DDC3 /* PhysicsAnimation.swift in Sources */, @@ -619,6 +640,7 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -633,7 +655,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.1; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -677,6 +699,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -685,10 +708,11 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.1; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 3.0; VALIDATE_PRODUCT = YES; }; @@ -698,17 +722,24 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + CODE_SIGN_IDENTITY = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; INFOPLIST_FILE = SwiftMessages/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -726,17 +757,24 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + CODE_SIGN_IDENTITY = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; INFOPLIST_FILE = SwiftMessages/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -753,7 +791,11 @@ isa = XCBuildConfiguration; buildSettings = { INFOPLIST_FILE = SwiftMessagesTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessagesTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = On; @@ -765,7 +807,11 @@ isa = XCBuildConfiguration; buildSettings = { INFOPLIST_FILE = SwiftMessagesTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessagesTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = On; diff --git a/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme b/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme index ad3b2531..5c84455f 100644 --- a/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme +++ b/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "1200" + LastUpgradeVersion = "1500" version = "1.3"> <BuildAction parallelizeBuildables = "YES" diff --git a/SwiftMessages/BaseView.swift b/SwiftMessages/BaseView.swift index 9480b87d..e5aa7b9c 100644 --- a/SwiftMessages/BaseView.swift +++ b/SwiftMessages/BaseView.swift @@ -293,7 +293,7 @@ extension BaseView { /// because the background view may be masked. So, when modifying the drop shadow, /// be sure to set the shadow properties of this view's layer. The shadow path is /// updated for you automatically. - open func configureDropShadow() { + public func configureDropShadow() { layer.shadowColor = UIColor.black.cgColor layer.shadowOffset = CGSize(width: 0.0, height: 2.0) layer.shadowRadius = 6.0 @@ -303,7 +303,7 @@ extension BaseView { } /// A convenience function to turn off drop shadow - open func configureNoDropShadow() { + public func configureNoDropShadow() { layer.shadowOpacity = 0 } diff --git a/SwiftMessages/Identifiable.swift b/SwiftMessages/Identifiable.swift index 4594b2d0..2985410f 100644 --- a/SwiftMessages/Identifiable.swift +++ b/SwiftMessages/Identifiable.swift @@ -17,6 +17,7 @@ import Foundation This protocol is optional. Message views that don't adopt `Identifiable` will not have duplicates removed. */ + public protocol Identifiable { var id: String { get } } diff --git a/SwiftMessages/MessageHostingView.swift b/SwiftMessages/MessageHostingView.swift new file mode 100644 index 00000000..d7bb5f1e --- /dev/null +++ b/SwiftMessages/MessageHostingView.swift @@ -0,0 +1,42 @@ +// +// MessageHostingView.swift +// SwiftMessages +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI +import UIKit + +/// A rudimentary hosting view for SwiftUI messages. +@available(iOS 14.0, *) +public class MessageHostingView<Content>: BaseView, Identifiable where Content: View { + + // MARK: - API + + public let id: String + + public init<Message>(message: Message) where Message: MessageViewConvertible, Message.Content == Content { + let messageView: Content = message.asMessageView() + hostVC = UIHostingController(rootView: messageView) + id = message.id + super.init(frame: .zero) + hostVC.loadViewIfNeeded() + installContentView(hostVC.view) + backgroundColor = .clear + hostVC.view.backgroundColor = .clear + } + + // MARK: - Constants + + // MARK: - Variables + + private let hostVC: UIHostingController<Content> + + // MARK: - Lifecycle + + @available(*, unavailable) + required init?(coder _: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/SwiftMessages/MessageViewConvertible.swift b/SwiftMessages/MessageViewConvertible.swift new file mode 100644 index 00000000..6dc168bf --- /dev/null +++ b/SwiftMessages/MessageViewConvertible.swift @@ -0,0 +1,16 @@ +// +// MessageViewConvertible.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI + +@available(iOS 14.0, *) +/// A protocol used to display a SwiftUI message view using the `swiftMessage()` modifier. +public protocol MessageViewConvertible: Equatable, Identifiable { + associatedtype Content: View + func asMessageView() -> Content +} + diff --git a/SwiftMessages/SwiftMessageModifier.swift b/SwiftMessages/SwiftMessageModifier.swift new file mode 100644 index 00000000..479b6d91 --- /dev/null +++ b/SwiftMessages/SwiftMessageModifier.swift @@ -0,0 +1,62 @@ +// +// SwiftMessageModifier.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI + +@available(iOS 14.0, *) +public extension View { + /// A state-based modifier for displaying a message. + func swiftMessage<Message>( + message: Binding<Message?>, + config: SwiftMessages.Config? = nil, + swiftMessages: SwiftMessages? = nil + ) -> some View where Message: MessageViewConvertible { + modifier(SwiftMessageModifier(message: message, config: config, swiftMessages: swiftMessages)) + } +} + +@available(iOS 14.0, *) +private struct SwiftMessageModifier<Message>: ViewModifier where Message: MessageViewConvertible { + // MARK: - API + + fileprivate init( + message: Binding<Message?>, + config: SwiftMessages.Config? = nil, + swiftMessages: SwiftMessages? = nil + ) { + _message = message + self.config = config + self.swiftMessages = swiftMessages + } + + // MARK: - Constants + + // MARK: - Variables + + @Binding private var message: Message? + private let config: SwiftMessages.Config? + private let swiftMessages: SwiftMessages? + + // MARK: - Body + + func body(content: Content) -> some View { + content + .onChange(of: message) { _ in + if let message { + let show: (SwiftMessages.Config, UIView) -> Void = swiftMessages?.show(config:view:) ?? SwiftMessages.show(config:view:) + let view = MessageHostingView(message: message) + var config = config ?? swiftMessages?.defaultConfig ?? SwiftMessages.defaultConfig + config.eventListeners.append { event in + if case .didHide = event, event.id == self.message?.id { + self.message = nil + } + } + show(config, view) + } + } + } +} diff --git a/SwiftMessages/SwiftMessagesSegue.swift b/SwiftMessages/SwiftMessagesSegue.swift index 80c3939c..cd17eec3 100644 --- a/SwiftMessages/SwiftMessagesSegue.swift +++ b/SwiftMessages/SwiftMessagesSegue.swift @@ -348,14 +348,6 @@ extension SwiftMessagesSegue { transitionContext.completeTransition(false) return } - if #available(iOS 12, *) {} - else if #available(iOS 11.0, *) { - // This works around a bug in iOS 11 where the safe area of `messageView` ( - // and all ancestor views) is not set except on iPhone X. By assigning `messageView` - // to a view controller, its safe area is set consistently. This bug has been resolved as - // of Xcode 10 beta 2. - segue.safeAreaWorkaroundViewController.view = segue.presenter.maskingView - } completeTransition = transitionContext.completeTransition let transitionContainer = transitionContext.containerView toView.translatesAutoresizingMaskIntoConstraints = false diff --git a/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj new file mode 100644 index 00000000..8b289e23 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj @@ -0,0 +1,436 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 228F7DAD2ACF17E8006C9644 /* SwiftUIDemoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228F7DAC2ACF17E8006C9644 /* SwiftUIDemoApp.swift */; }; + 228F7DAF2ACF17E8006C9644 /* DemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228F7DAE2ACF17E8006C9644 /* DemoView.swift */; }; + 228F7DB12ACF17E9006C9644 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 228F7DB02ACF17E9006C9644 /* Assets.xcassets */; }; + 228F7DB42ACF17E9006C9644 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 228F7DB32ACF17E9006C9644 /* Preview Assets.xcassets */; }; + 228F7DC82ACF1E63006C9644 /* SwiftMessages.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 228F7DC32ACF1E1E006C9644 /* SwiftMessages.framework */; }; + 228F7DC92ACF1E63006C9644 /* SwiftMessages.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 228F7DC32ACF1E1E006C9644 /* SwiftMessages.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 228F7DD52ACF59E4006C9644 /* DemoMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228F7DD42ACF59E4006C9644 /* DemoMessage.swift */; }; + 228F7DD72ACF5C2E006C9644 /* DemoMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228F7DD62ACF5C2E006C9644 /* DemoMessageView.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 228F7DC22ACF1E1E006C9644 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 228F7DBD2ACF1E1E006C9644 /* SwiftMessages.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 86B48AEC1D5A41C900063E2B; + remoteInfo = SwiftMessages; + }; + 228F7DC42ACF1E1E006C9644 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 228F7DBD2ACF1E1E006C9644 /* SwiftMessages.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 86B48AF51D5A41C900063E2B; + remoteInfo = SwiftMessagesTests; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 228F7DCA2ACF1E63006C9644 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 228F7DC92ACF1E63006C9644 /* SwiftMessages.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 228F7DA92ACF17E8006C9644 /* SwiftUIDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftUIDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 228F7DAC2ACF17E8006C9644 /* SwiftUIDemoApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIDemoApp.swift; sourceTree = "<group>"; }; + 228F7DAE2ACF17E8006C9644 /* DemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoView.swift; sourceTree = "<group>"; }; + 228F7DB02ACF17E9006C9644 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; + 228F7DB32ACF17E9006C9644 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; }; + 228F7DBB2ACF1DB5006C9644 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; + 228F7DBD2ACF1E1E006C9644 /* SwiftMessages.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SwiftMessages.xcodeproj; path = ../SwiftMessages.xcodeproj; sourceTree = "<group>"; }; + 228F7DD42ACF59E4006C9644 /* DemoMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoMessage.swift; sourceTree = "<group>"; }; + 228F7DD62ACF5C2E006C9644 /* DemoMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoMessageView.swift; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 228F7DA62ACF17E8006C9644 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 228F7DC82ACF1E63006C9644 /* SwiftMessages.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 228F7DA02ACF17E8006C9644 = { + isa = PBXGroup; + children = ( + 228F7DAB2ACF17E8006C9644 /* SwiftUIDemo */, + 228F7DAA2ACF17E8006C9644 /* Products */, + 228F7DC72ACF1E63006C9644 /* Frameworks */, + 228F7DBD2ACF1E1E006C9644 /* SwiftMessages.xcodeproj */, + ); + sourceTree = "<group>"; + }; + 228F7DAA2ACF17E8006C9644 /* Products */ = { + isa = PBXGroup; + children = ( + 228F7DA92ACF17E8006C9644 /* SwiftUIDemo.app */, + ); + name = Products; + sourceTree = "<group>"; + }; + 228F7DAB2ACF17E8006C9644 /* SwiftUIDemo */ = { + isa = PBXGroup; + children = ( + 228F7DBB2ACF1DB5006C9644 /* Info.plist */, + 228F7DAC2ACF17E8006C9644 /* SwiftUIDemoApp.swift */, + 228F7DAE2ACF17E8006C9644 /* DemoView.swift */, + 228F7DD42ACF59E4006C9644 /* DemoMessage.swift */, + 228F7DD62ACF5C2E006C9644 /* DemoMessageView.swift */, + 228F7DB02ACF17E9006C9644 /* Assets.xcassets */, + 228F7DB22ACF17E9006C9644 /* Preview Content */, + ); + path = SwiftUIDemo; + sourceTree = "<group>"; + }; + 228F7DB22ACF17E9006C9644 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 228F7DB32ACF17E9006C9644 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = "<group>"; + }; + 228F7DBE2ACF1E1E006C9644 /* Products */ = { + isa = PBXGroup; + children = ( + 228F7DC32ACF1E1E006C9644 /* SwiftMessages.framework */, + 228F7DC52ACF1E1E006C9644 /* SwiftMessagesTests.xctest */, + ); + name = Products; + sourceTree = "<group>"; + }; + 228F7DC72ACF1E63006C9644 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 228F7DA82ACF17E8006C9644 /* SwiftUIDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 228F7DB72ACF17E9006C9644 /* Build configuration list for PBXNativeTarget "SwiftUIDemo" */; + buildPhases = ( + 228F7DA52ACF17E8006C9644 /* Sources */, + 228F7DA62ACF17E8006C9644 /* Frameworks */, + 228F7DA72ACF17E8006C9644 /* Resources */, + 228F7DCA2ACF1E63006C9644 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SwiftUIDemo; + productName = SwiftUIDemo; + productReference = 228F7DA92ACF17E8006C9644 /* SwiftUIDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 228F7DA12ACF17E8006C9644 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; + TargetAttributes = { + 228F7DA82ACF17E8006C9644 = { + CreatedOnToolsVersion = 15.0; + }; + }; + }; + buildConfigurationList = 228F7DA42ACF17E8006C9644 /* Build configuration list for PBXProject "SwiftUIDemo" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 228F7DA02ACF17E8006C9644; + productRefGroup = 228F7DAA2ACF17E8006C9644 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 228F7DBE2ACF1E1E006C9644 /* Products */; + ProjectRef = 228F7DBD2ACF1E1E006C9644 /* SwiftMessages.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 228F7DA82ACF17E8006C9644 /* SwiftUIDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 228F7DC32ACF1E1E006C9644 /* SwiftMessages.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = SwiftMessages.framework; + remoteRef = 228F7DC22ACF1E1E006C9644 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 228F7DC52ACF1E1E006C9644 /* SwiftMessagesTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = SwiftMessagesTests.xctest; + remoteRef = 228F7DC42ACF1E1E006C9644 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 228F7DA72ACF17E8006C9644 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 228F7DB42ACF17E9006C9644 /* Preview Assets.xcassets in Resources */, + 228F7DB12ACF17E9006C9644 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 228F7DA52ACF17E8006C9644 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 228F7DD52ACF59E4006C9644 /* DemoMessage.swift in Sources */, + 228F7DD72ACF5C2E006C9644 /* DemoMessageView.swift in Sources */, + 228F7DAF2ACF17E8006C9644 /* DemoView.swift in Sources */, + 228F7DAD2ACF17E8006C9644 /* SwiftUIDemoApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 228F7DB52ACF17E9006C9644 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 228F7DB62ACF17E9006C9644 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 228F7DB82ACF17E9006C9644 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"SwiftUIDemo/Preview Content\""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = SwiftUIDemo/Info.plist; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.swiftkickmobile.SwiftUIDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 228F7DB92ACF17E9006C9644 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"SwiftUIDemo/Preview Content\""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = SwiftUIDemo/Info.plist; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.swiftkickmobile.SwiftUIDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 228F7DA42ACF17E8006C9644 /* Build configuration list for PBXProject "SwiftUIDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 228F7DB52ACF17E9006C9644 /* Debug */, + 228F7DB62ACF17E9006C9644 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 228F7DB72ACF17E9006C9644 /* Build configuration list for PBXNativeTarget "SwiftUIDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 228F7DB82ACF17E9006C9644 /* Debug */, + 228F7DB92ACF17E9006C9644 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 228F7DA12ACF17E8006C9644 /* Project object */; +} diff --git a/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "self:"> + </FileRef> +</Workspace> diff --git a/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEDidComputeMac32BitWarning</key> + <true/> +</dict> +</plist> diff --git a/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AccentColor.colorset/Contents.json b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..13613e3e --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Contents.json b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Demo message background.colorset/Contents.json b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Demo message background.colorset/Contents.json new file mode 100644 index 00000000..15b79d47 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Demo message background.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xEB", + "green" : "0xE1", + "red" : "0xAC" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/DemoMessage.swift b/SwiftUIDemo/SwiftUIDemo/DemoMessage.swift new file mode 100644 index 00000000..ccc86b66 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/DemoMessage.swift @@ -0,0 +1,22 @@ +// +// DemoMessage.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI +import SwiftMessages + +struct DemoMessage: Identifiable { + let title: String + let body: String + + var id: String { title + body } +} + +extension DemoMessage: MessageViewConvertible { + func asMessageView() -> DemoMessageView { + DemoMessageView(message: self) + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift b/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift new file mode 100644 index 00000000..cce5058c --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift @@ -0,0 +1,35 @@ +// +// DemoMessageView.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI + +struct DemoMessageView: View { + + // MARK: - API + + let message: DemoMessage + + // MARK: - Variables + + // MARK: - Constants + + // MARK: - Body + + var body: some View { + VStack(alignment: .leading) { + Text(message.title).font(.system(size: 20, weight: .bold)) + Text(message.body) + } + .multilineTextAlignment(.leading) + .padding(30) + .frame(maxWidth: .infinity) + .background(.demoMessageBackground) + .cornerRadius(15) + .padding(15) + } +} + diff --git a/SwiftUIDemo/SwiftUIDemo/DemoView.swift b/SwiftUIDemo/SwiftUIDemo/DemoView.swift new file mode 100644 index 00000000..e0bcd6c1 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/DemoView.swift @@ -0,0 +1,48 @@ +// +// DemoView.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI +import SwiftMessages + +struct DemoView: View { + + @State var message: DemoMessage? + + var body: some View { + Button("Show message") { + message = DemoMessage(title: "Demo", body: "This is a sample SwiftUI message! This content should be long enough to wrap.") + } + .buttonBorderShape(.roundedRectangle(radius: 15)) + .swiftMessage(message: $message) + } +} + +#Preview { + DemoView() +} + +struct DemoViewx: View { + var body: some View { + Button("Show message") { + let message = DemoMessage(title: "Demo", body: "SwiftUI forever!") + let messageView = MessageHostingView(message: message) + SwiftMessages.show(view: messageView) + } + } +} + +struct DemoViewy: View { + + @State var message: DemoMessage? + + var body: some View { + Button("Show message") { + message = DemoMessage(title: "Demo", body: "SwiftUI forever!") + } + .swiftMessage(message: $message) + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/Info.plist b/SwiftUIDemo/SwiftUIDemo/Info.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/Info.plist @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict/> +</plist> diff --git a/SwiftUIDemo/SwiftUIDemo/Preview Content/Preview Assets.xcassets/Contents.json b/SwiftUIDemo/SwiftUIDemo/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/SwiftUIDemoApp.swift b/SwiftUIDemo/SwiftUIDemo/SwiftUIDemoApp.swift new file mode 100644 index 00000000..fc444543 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/SwiftUIDemoApp.swift @@ -0,0 +1,17 @@ +// +// SwiftUIDemoApp.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI + +@main +struct SwiftUIDemoApp: App { + var body: some Scene { + WindowGroup { + DemoView() + } + } +} From 947c4e065409de7cae61e5f70a37f366a65f3ec6 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Fri, 6 Oct 2023 09:46:04 -0500 Subject: [PATCH 54/77] Update SwiftUI comments in README.md --- README.md | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 0cf8e79d..8cb208bb 100644 --- a/README.md +++ b/README.md @@ -12,29 +12,22 @@ ## Overview -SwiftMessages is a very flexible view and view controller presentation library for iOS. +🔥🔥🔥 **NEW** SwiftUI support added! -Message views and view controllers can be displayed at the top, bottom, or center of the screen, or behind navigation bars and tab bars. There are interactive dismiss gestures including a fun, physics-based one. Multiple background dimming modes. And a lot more! +SwiftMessages is a very flexible view and view controller presentation library for UIKit and SwiftUI. -🔥 Now supports displaying SwiftUI message views 🔥 +Message views and view controllers can be displayed at the top, bottom, or center of the screen, or behind navigation bars and tab bars. There are interactive dismiss gestures including a fun, physics-based one. Multiple background dimming modes. And a lot more! In addition to the numerous configuration options, SwiftMessages provides several good-looking layouts and themes. But SwiftMessages is also designer-friendly, which means you can fully and easily customize the view: * Copy one of the included nib files into your project and change it. * Subclass `MessageView` and add elements, etc. -* Or just supply an arbitrary instance of `UIView`. - -Try exploring [the demo app via appetize.io](http://goo.gl/KXw4nD) to get a feel for the extensive configurability of SwiftMessages. +* Or just supply an arbitrary instance of `View` or `UIView`. <p align="center"> <img src="./Demo/demo.png" /> </p> -<p align="center"> - <a href="http://goo.gl/KXw4nD"><img src="./Demo/appetize.png" /></a> -</p> - - ## Installation ### Swift Package Manager @@ -185,7 +178,7 @@ And check out our blog post [Elegant Custom UIViewController Transitioning](http Any of the built-in SwiftMessages views can be displayed by calling the SwiftMessages APIs from within observable object, a button action closure, etc. However, SwiftMessages can also display your custom SwiftUI views. -First, define a type that conforms to `MessageViewConvertible`. This will typically be a struct containing the message data: +The first step is to define a type that conforms to `MessageViewConvertible`. This would typically be a struct containing the message data to display: ````swift From 691e9bf4656e5e7b47a66220770b5101b502574d Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Fri, 6 Oct 2023 09:47:53 -0500 Subject: [PATCH 55/77] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a4ec930..fdb8977e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. ## 9.0.7 +### Features + +* Added support for SwiftUI + ### Fixes * #527 Crash while clicking two times to hide the presenting controller From 188705b897cbc38e3f1e993978b5b7e46906e958 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Fri, 6 Oct 2023 09:55:16 -0500 Subject: [PATCH 56/77] Fix email address --- SwiftMessages.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 00b6a817..941a9827 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -3,7 +3,7 @@ Pod::Spec.new do |spec| spec.version = '9.0.7' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' - spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } + spec.authors = { 'Timothy Moose' => 'tim@swiftkickmobile.com' } spec.summary = 'A very flexible message bar for iOS written in Swift.' spec.source = {:git => 'https://github.com/SwiftKickMobile/SwiftMessages.git', :tag => spec.version} spec.platform = :ios, '12.0' From c2bcb351434ae044a486803ad1751b0e10f0d4e1 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Sat, 7 Oct 2023 14:13:34 -0500 Subject: [PATCH 57/77] Address #529 --- CHANGELOG.md | 6 +++++ README.md | 10 +++++++-- SwiftMessages.podspec | 2 +- .../SwiftUIDemo.xcodeproj/project.pbxproj | 4 ++++ SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift | 11 +++++++--- SwiftUIDemo/SwiftUIDemo/DemoView.swift | 22 ------------------- 6 files changed, 27 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdb8977e..d17b7a82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change Log All notable changes to this project will be documented in this file. +## 9.0.8 + +### Changes + +* #529 Update readme and SwiftUI demo to demostrate how to mask edges. + ## 9.0.7 ### Features diff --git a/README.md b/README.md index 8cb208bb..10ec0f22 100644 --- a/README.md +++ b/README.md @@ -208,8 +208,14 @@ struct DemoMessageView: View { .padding(30) .frame(maxWidth: .infinity) .background(.gray) - .cornerRadius(15) - .padding(15) + // This makes a tab-style view where the bottom corners are rounded and the view's background + // extends to the top edge. + .mask( + UnevenRoundedRectangle( + cornerRadii: .init(bottomLeading: 15, bottomTrailing: 15) + ) + .edgesIgnoringSafeArea(.top) + ) } } ```` diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 941a9827..e67d4b08 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.0.7' + spec.version = '9.0.8' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkickmobile.com' } diff --git a/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj index 8b289e23..f6c945bc 100644 --- a/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj +++ b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj @@ -58,6 +58,8 @@ 228F7DBD2ACF1E1E006C9644 /* SwiftMessages.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SwiftMessages.xcodeproj; path = ../SwiftMessages.xcodeproj; sourceTree = "<group>"; }; 228F7DD42ACF59E4006C9644 /* DemoMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoMessage.swift; sourceTree = "<group>"; }; 228F7DD62ACF5C2E006C9644 /* DemoMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoMessageView.swift; sourceTree = "<group>"; }; + 2291AA492AD1E3EC0084868E /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; }; + 2291AA4C2AD1E4520084868E /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = CHANGELOG.md; path = ../CHANGELOG.md; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -75,6 +77,8 @@ 228F7DA02ACF17E8006C9644 = { isa = PBXGroup; children = ( + 2291AA4C2AD1E4520084868E /* CHANGELOG.md */, + 2291AA492AD1E3EC0084868E /* README.md */, 228F7DAB2ACF17E8006C9644 /* SwiftUIDemo */, 228F7DAA2ACF17E8006C9644 /* Products */, 228F7DC72ACF1E63006C9644 /* Frameworks */, diff --git a/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift b/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift index cce5058c..a299c356 100644 --- a/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift +++ b/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift @@ -28,8 +28,13 @@ struct DemoMessageView: View { .padding(30) .frame(maxWidth: .infinity) .background(.demoMessageBackground) - .cornerRadius(15) - .padding(15) + // This makes a tab-style view where the bottom corners are rounded and the view's background + // extends to the top edge. + .mask( + UnevenRoundedRectangle( + cornerRadii: .init(bottomLeading: 15, bottomTrailing: 15) + ) + .edgesIgnoringSafeArea(.top) + ) } } - diff --git a/SwiftUIDemo/SwiftUIDemo/DemoView.swift b/SwiftUIDemo/SwiftUIDemo/DemoView.swift index e0bcd6c1..a6736d89 100644 --- a/SwiftUIDemo/SwiftUIDemo/DemoView.swift +++ b/SwiftUIDemo/SwiftUIDemo/DemoView.swift @@ -24,25 +24,3 @@ struct DemoView: View { #Preview { DemoView() } - -struct DemoViewx: View { - var body: some View { - Button("Show message") { - let message = DemoMessage(title: "Demo", body: "SwiftUI forever!") - let messageView = MessageHostingView(message: message) - SwiftMessages.show(view: messageView) - } - } -} - -struct DemoViewy: View { - - @State var message: DemoMessage? - - var body: some View { - Button("Show message") { - message = DemoMessage(title: "Demo", body: "SwiftUI forever!") - } - .swiftMessage(message: $message) - } -} From 62e12e138fc3eedf88c7553dd5d98712aa119f40 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Wed, 1 Nov 2023 12:59:03 -0500 Subject: [PATCH 58/77] Couple of fixes --- CHANGELOG.md | 7 +++ README.md | 10 ++-- SwiftMessages.podspec | 2 +- SwiftMessages/KeyboardTrackingView.swift | 17 +++++-- SwiftMessages/MessageHostingView.swift | 8 ++++ SwiftUIDemo/SwiftUIDemo/DemoMessage.swift | 3 +- SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift | 46 +++++++++++++++---- SwiftUIDemo/SwiftUIDemo/DemoView.swift | 26 +++++++++-- 8 files changed, 98 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d17b7a82..0f5cc826 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Change Log All notable changes to this project will be documented in this file. +## 9.0.9 + +### Fixes + +* Fix hit testing on SwiftUI views to allow touches around the view's margins to pass through to the underlying view. +* Update `KeyboardTrackingView` to continue tracking the keyboard even when not installed in the view hierarchy. + ## 9.0.8 ### Changes diff --git a/README.md b/README.md index 10ec0f22..5af94cb4 100644 --- a/README.md +++ b/README.md @@ -206,14 +206,14 @@ struct DemoMessageView: View { } .multilineTextAlignment(.leading) .padding(30) + // This makes the message width greedy .frame(maxWidth: .infinity) .background(.gray) - // This makes a tab-style view where the bottom corners are rounded and the view's background - // extends to the top edge. + // This makes a tab-style view where the bottom corners are rounded and + // the view's background extends to the top edge. .mask( - UnevenRoundedRectangle( - cornerRadii: .init(bottomLeading: 15, bottomTrailing: 15) - ) + UnevenRoundedRectangle(bottomLeadingRadius: 15, bottomTrailingRadius: 15) + // This causes the background to extend into the safe area to the screen edge. .edgesIgnoringSafeArea(.top) ) } diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index e67d4b08..0e7b79c0 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.0.8' + spec.version = '9.0.9' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkickmobile.com' } diff --git a/SwiftMessages/KeyboardTrackingView.swift b/SwiftMessages/KeyboardTrackingView.swift index 301d969c..f3c0ad95 100644 --- a/SwiftMessages/KeyboardTrackingView.swift +++ b/SwiftMessages/KeyboardTrackingView.swift @@ -72,6 +72,7 @@ open class KeyboardTrackingView: UIView { private var isAutomaticallyPaused = false private var heightConstraint: NSLayoutConstraint! + private var lastObservedKeyboardRect: CGRect? private func postInit() { translatesAutoresizingMaskIntoConstraints = false @@ -109,15 +110,19 @@ open class KeyboardTrackingView: UIView { isAutomaticallyPaused = false } + open override func layoutSubviews() { + super.layoutSubviews() + heightConstraint.constant = calculateHeightConstant() + } + private func show(change: Change, _ notification: Notification) { guard !(isPaused || isAutomaticallyPaused), let userInfo = (notification as NSNotification).userInfo, let value = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return } willChange(change: change, userInfo: userInfo) delegate?.keyboardTrackingViewWillChange(change: change, userInfo: userInfo) - let keyboardRect = value.cgRectValue - let thisRect = convert(bounds, to: nil) - let newHeight = max(0, thisRect.maxY - keyboardRect.minY) + topMargin + lastObservedKeyboardRect = value.cgRectValue + let newHeight = calculateHeightConstant() guard heightConstraint.constant != newHeight else { return } animateKeyboardChange(change: change, height: newHeight, userInfo: userInfo) } @@ -140,4 +145,10 @@ open class KeyboardTrackingView: UIView { CATransaction.commit() } } + + private func calculateHeightConstant() -> CGFloat { + guard let keyboardRect = lastObservedKeyboardRect else { return 0 } + let thisRect = convert(bounds, to: nil) + return max(0, thisRect.maxY - keyboardRect.minY) + topMargin + } } diff --git a/SwiftMessages/MessageHostingView.swift b/SwiftMessages/MessageHostingView.swift index d7bb5f1e..489ab96a 100644 --- a/SwiftMessages/MessageHostingView.swift +++ b/SwiftMessages/MessageHostingView.swift @@ -39,4 +39,12 @@ public class MessageHostingView<Content>: BaseView, Identifiable where Content: required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } + + public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + let view = super.hitTest(point, with: event) + // The rendered SwiftUI view isn't a direct child of this hosting view. SwiftUI + // inserts another intermediate view that should also ignore touches. + if view == self || view?.superview == self { return nil } + return view + } } diff --git a/SwiftUIDemo/SwiftUIDemo/DemoMessage.swift b/SwiftUIDemo/SwiftUIDemo/DemoMessage.swift index ccc86b66..32624de1 100644 --- a/SwiftUIDemo/SwiftUIDemo/DemoMessage.swift +++ b/SwiftUIDemo/SwiftUIDemo/DemoMessage.swift @@ -11,12 +11,13 @@ import SwiftMessages struct DemoMessage: Identifiable { let title: String let body: String + let style: DemoMessageView.Style var id: String { title + body } } extension DemoMessage: MessageViewConvertible { func asMessageView() -> DemoMessageView { - DemoMessageView(message: self) + DemoMessageView(message: self, style: style) } } diff --git a/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift b/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift index a299c356..53963023 100644 --- a/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift +++ b/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift @@ -7,11 +7,20 @@ import SwiftUI +// A card-style message view struct DemoMessageView: View { // MARK: - API + enum Style { + case standard + case card + case tab + } + let message: DemoMessage + let style: Style + // MARK: - Variables @@ -20,21 +29,42 @@ struct DemoMessageView: View { // MARK: - Body var body: some View { + switch style { + case .standard: + content() + // Mask the content and extend background into the safe area. + .mask { + Rectangle() + .edgesIgnoringSafeArea(.top) + } + case .card: + content() + // Mask the content with a rounded rectangle + .mask { + RoundedRectangle(cornerRadius: 15) + } + // External padding around the card + .padding(10) + case .tab: + content() + // Mask the content with rounded bottom edge and extend background into the safe area. + .mask { + UnevenRoundedRectangle(bottomLeadingRadius: 15, bottomTrailingRadius: 15) + .edgesIgnoringSafeArea(.top) + } + } + } + + @ViewBuilder private func content() -> some View { VStack(alignment: .leading) { Text(message.title).font(.system(size: 20, weight: .bold)) Text(message.body) } .multilineTextAlignment(.leading) + // Internal padding of the card .padding(30) + // Greedy width .frame(maxWidth: .infinity) .background(.demoMessageBackground) - // This makes a tab-style view where the bottom corners are rounded and the view's background - // extends to the top edge. - .mask( - UnevenRoundedRectangle( - cornerRadii: .init(bottomLeading: 15, bottomTrailing: 15) - ) - .edgesIgnoringSafeArea(.top) - ) } } diff --git a/SwiftUIDemo/SwiftUIDemo/DemoView.swift b/SwiftUIDemo/SwiftUIDemo/DemoView.swift index a6736d89..8f47b7df 100644 --- a/SwiftUIDemo/SwiftUIDemo/DemoView.swift +++ b/SwiftUIDemo/SwiftUIDemo/DemoView.swift @@ -13,10 +13,30 @@ struct DemoView: View { @State var message: DemoMessage? var body: some View { - Button("Show message") { - message = DemoMessage(title: "Demo", body: "This is a sample SwiftUI message! This content should be long enough to wrap.") + VStack { + Button("Show standard message") { + message = DemoMessage( + title: "Demo", + body: "This is a sample SwiftUI card-style message! This content should be long enough to wrap.", + style: .standard + ) + } + Button("Show card message") { + message = DemoMessage( + title: "Demo", + body: "This is a sample SwiftUI card-style message! This content should be long enough to wrap.", + style: .card + ) + } + Button("Show tab message") { + message = DemoMessage( + title: "Demo", + body: "This is a sample SwiftUI card-style message! This content should be long enough to wrap.", + style: .tab + ) + } } - .buttonBorderShape(.roundedRectangle(radius: 15)) + .buttonStyle(.bordered) .swiftMessage(message: $message) } } From 95f65d57f018a18ec352c6bf7fde1a6e3c4550c9 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Sun, 3 Dec 2023 10:41:56 -0600 Subject: [PATCH 59/77] #534 Fix warnings? --- SwiftMessages/BaseView.swift | 10 +-- .../MarginAdjustable+Extensions.swift | 21 +----- SwiftMessages/PhysicsAnimation.swift | 4 +- SwiftMessages/Presenter.swift | 65 ++++++++----------- SwiftMessages/TopBottomAnimation.swift | 4 +- 5 files changed, 35 insertions(+), 69 deletions(-) diff --git a/SwiftMessages/BaseView.swift b/SwiftMessages/BaseView.swift index e5aa7b9c..c41d166b 100644 --- a/SwiftMessages/BaseView.swift +++ b/SwiftMessages/BaseView.swift @@ -280,6 +280,11 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable { private var layoutConstraints: [NSLayoutConstraint] = [] private var regularWidthLayoutConstraints: [NSLayoutConstraint] = [] + + open override func layoutSubviews() { + super.layoutSubviews() + updateShadowPath() + } } /* @@ -334,11 +339,6 @@ extension BaseView { // Update the layer's `shadowPath` without animation layer.shadowPath = shadowPath } } - - open override func layoutSubviews() { - super.layoutSubviews() - updateShadowPath() - } } /* diff --git a/SwiftMessages/MarginAdjustable+Extensions.swift b/SwiftMessages/MarginAdjustable+Extensions.swift index b6277885..da8f46d1 100644 --- a/SwiftMessages/MarginAdjustable+Extensions.swift +++ b/SwiftMessages/MarginAdjustable+Extensions.swift @@ -13,25 +13,8 @@ extension MarginAdjustable where Self: UIView { var layoutMargins: UIEdgeInsets = layoutMarginAdditions var safeAreaInsets: UIEdgeInsets = { guard respectSafeArea else { return .zero } - if #available(iOS 11, *) { - insetsLayoutMarginsFromSafeArea = false - return self.safeAreaInsets - } else { - #if SWIFTMESSAGES_APP_EXTENSIONS - let application: UIApplication? = nil - #else - let application: UIApplication? = UIApplication.shared - #endif - if !context.safeZoneConflicts.isDisjoint(with: [.statusBar]), - let app = application, - app.statusBarOrientation == .portrait || app.statusBarOrientation == .portraitUpsideDown { - let frameInWindow = convert(bounds, to: window) - let top = max(0, 20 - frameInWindow.minY) - return UIEdgeInsets(top: top, left: 0, bottom: 0, right: 0) - } else { - return .zero - } - } + insetsLayoutMarginsFromSafeArea = false + return self.safeAreaInsets }() if !context.safeZoneConflicts.isDisjoint(with: .overStatusBar) { safeAreaInsets.top = 0 diff --git a/SwiftMessages/PhysicsAnimation.swift b/SwiftMessages/PhysicsAnimation.swift index 0fb976c5..c073fe4a 100644 --- a/SwiftMessages/PhysicsAnimation.swift +++ b/SwiftMessages/PhysicsAnimation.swift @@ -93,9 +93,7 @@ public class PhysicsAnimation: NSObject, Animator { guard let adjustable = messageView as? MarginAdjustable & UIView, let context = context else { return } adjustable.preservesSuperviewLayoutMargins = false - if #available(iOS 11, *) { - adjustable.insetsLayoutMarginsFromSafeArea = false - } + adjustable.insetsLayoutMarginsFromSafeArea = false adjustable.layoutMargins = adjustable.defaultMarginAdjustment(context: context) } diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index 5a3648b8..44f92015 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -236,7 +236,7 @@ class Presenter: NSObject { } private func safeZoneConflicts() -> SafeZoneConflicts { - guard let window = maskingView.window else { return [] } + guard let _ = maskingView.window else { return [] } let windowLevel: UIWindow.Level = { if let vc = presentationContext.viewControllerValue() as? WindowViewController { return vc.config.windowLevel ?? .normal @@ -253,47 +253,34 @@ class Presenter: NSObject { if let vc = presentationContext.viewControllerValue() as? UITabBarController { return vc.sm_isVisible(view: vc.tabBar) } return false }() - if #available(iOS 11, *) { - if windowLevel > .normal { - // TODO seeing `maskingView.safeAreaInsets.top` value of 20 on - // iPhone 8 with status bar window level. This seems like an iOS bug since - // the message view's window is above the status bar. Applying a special rule - // to allow the animator to revove this amount from the layout margins if needed. - // This may need to be reworked if any future device has a legitimate 20pt top safe area, - // such as with a potentially smaller notch. - if maskingView.safeAreaInsets.top == 20 { - return [.overStatusBar] - } else { - var conflicts: SafeZoneConflicts = [] - if maskingView.safeAreaInsets.top > 0 { - conflicts.formUnion(.sensorNotch) - } - if maskingView.safeAreaInsets.bottom > 0 { - conflicts.formUnion(.homeIndicator) - } - return conflicts + if windowLevel > .normal { + // TODO seeing `maskingView.safeAreaInsets.top` value of 20 on + // iPhone 8 with status bar window level. This seems like an iOS bug since + // the message view's window is above the status bar. Applying a special rule + // to allow the animator to revove this amount from the layout margins if needed. + // This may need to be reworked if any future device has a legitimate 20pt top safe area, + // such as with a potentially smaller notch. + if maskingView.safeAreaInsets.top == 20 { + return [.overStatusBar] + } else { + var conflicts: SafeZoneConflicts = [] + if maskingView.safeAreaInsets.top > 0 { + conflicts.formUnion(.sensorNotch) } + if maskingView.safeAreaInsets.bottom > 0 { + conflicts.formUnion(.homeIndicator) + } + return conflicts } - var conflicts: SafeZoneConflicts = [] - if !underNavigationBar { - conflicts.formUnion(.sensorNotch) - } - if !underTabBar { - conflicts.formUnion(.homeIndicator) - } - return conflicts - } else { - #if SWIFTMESSAGES_APP_EXTENSIONS - return [] - #else - if UIApplication.shared.isStatusBarHidden { return [] } - if (windowLevel > UIWindow.Level.normal) || underNavigationBar { return [] } - let statusBarFrame = UIApplication.shared.statusBarFrame - let statusBarWindowFrame = window.convert(statusBarFrame, from: nil) - let statusBarViewFrame = maskingView.convert(statusBarWindowFrame, from: nil) - return statusBarViewFrame.intersects(maskingView.bounds) ? SafeZoneConflicts.statusBar : [] - #endif } + var conflicts: SafeZoneConflicts = [] + if !underNavigationBar { + conflicts.formUnion(.sensorNotch) + } + if !underTabBar { + conflicts.formUnion(.homeIndicator) + } + return conflicts } private func getPresentationContext() throws -> PresentationContext { diff --git a/SwiftMessages/TopBottomAnimation.swift b/SwiftMessages/TopBottomAnimation.swift index 21b0f271..a0d440c7 100644 --- a/SwiftMessages/TopBottomAnimation.swift +++ b/SwiftMessages/TopBottomAnimation.swift @@ -130,9 +130,7 @@ public class TopBottomAnimation: NSObject, Animator { guard let adjustable = messageView as? MarginAdjustable & UIView, let context = context else { return } adjustable.preservesSuperviewLayoutMargins = false - if #available(iOS 11, *) { - adjustable.insetsLayoutMarginsFromSafeArea = false - } + adjustable.insetsLayoutMarginsFromSafeArea = false var layoutMargins = adjustable.defaultMarginAdjustment(context: context) switch style { case .top: From 633b6e593b5730daf9e682cd21f50764bd1e257c Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Sun, 3 Dec 2023 11:54:25 -0600 Subject: [PATCH 60/77] #535 Remove needless async code --- Package.swift | 2 +- SwiftMessages.podspec | 4 +- SwiftMessages.xcodeproj/project.pbxproj | 16 +- .../xcschemes/SwiftMessages.xcscheme | 2 +- SwiftMessages/KeyboardTrackingView.swift | 13 +- SwiftMessages/Presenter.swift | 2 + SwiftMessages/SwiftMessageModifier.swift | 2 +- SwiftMessages/SwiftMessages.swift | 167 +++++++----------- SwiftMessages/Task+Extensions.swift | 15 ++ 9 files changed, 105 insertions(+), 118 deletions(-) create mode 100644 SwiftMessages/Task+Extensions.swift diff --git a/Package.swift b/Package.swift index a0f30e8b..a906ba1a 100644 --- a/Package.swift +++ b/Package.swift @@ -4,7 +4,7 @@ import PackageDescription let package = Package( name: "SwiftMessages", platforms: [ - .iOS("9.0") + .iOS("13.0") ], products: [ .library(name: "SwiftMessages", targets: ["SwiftMessages"]), diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 0e7b79c0..b2b0e4ff 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -6,9 +6,9 @@ Pod::Spec.new do |spec| spec.authors = { 'Timothy Moose' => 'tim@swiftkickmobile.com' } spec.summary = 'A very flexible message bar for iOS written in Swift.' spec.source = {:git => 'https://github.com/SwiftKickMobile/SwiftMessages.git', :tag => spec.version} - spec.platform = :ios, '12.0' + spec.platform = :ios, '13.0' spec.swift_version = '5.0' - spec.ios.deployment_target = '12.0' + spec.ios.deployment_target = '13.0' spec.framework = 'UIKit' spec.requires_arc = true spec.default_subspec = 'App' diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 45809f2d..19d5bcd0 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -59,6 +59,7 @@ 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */; }; 229F778125FAB1E9008C2ACB /* UIWindow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */; }; + 22D3B4562B1CEF76002D8665 /* Task+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22D3B4552B1CEF76002D8665 /* Task+Extensions.swift */; }; 22DFC9161EFF30F6001B1CA1 /* CenteredView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */; }; 22DFC9181F00674E001B1CA1 /* PhysicsPanHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */; }; 22E01F641E74EC8B00ACE19A /* MaskingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22E01F631E74EC8B00ACE19A /* MaskingView.swift */; }; @@ -151,6 +152,7 @@ 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = "<group>"; }; 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+Extensions.swift"; sourceTree = "<group>"; }; 22A2EA6E24EC6CFA00BB2540 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; }; + 22D3B4552B1CEF76002D8665 /* Task+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Task+Extensions.swift"; sourceTree = "<group>"; }; 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = CenteredView.xib; path = Resources/CenteredView.xib; sourceTree = "<group>"; }; 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsPanHandler.swift; sourceTree = "<group>"; }; 22E01F631E74EC8B00ACE19A /* MaskingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaskingView.swift; sourceTree = "<group>"; }; @@ -220,6 +222,7 @@ 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */, 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */, 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */, + 22D3B4552B1CEF76002D8665 /* Task+Extensions.swift */, ); name = Extensions; sourceTree = "<group>"; @@ -453,7 +456,7 @@ attributes = { BuildIndependentTargetsInParallel = YES; LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 1500; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = "SwiftKick Mobile"; TargetAttributes = { 86B48AEB1D5A41C900063E2B = { @@ -556,6 +559,7 @@ 22F27951210CE25900273E7F /* CornerRoundingView.swift in Sources */, 86BBA9011D5E040600FE8F16 /* PassthroughWindow.swift in Sources */, 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */, + 22D3B4562B1CEF76002D8665 /* Task+Extensions.swift in Sources */, 86BBA9031D5E040600FE8F16 /* UIViewController+Extensions.swift in Sources */, 228F7DDF2ACF703A006C9644 /* SwiftMessageModifier.swift in Sources */, 224FB69921153B440081D4DE /* CALayer+Extensions.swift in Sources */, @@ -609,6 +613,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; @@ -655,7 +660,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -668,6 +673,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; @@ -708,7 +714,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; @@ -732,7 +738,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; INFOPLIST_FILE = SwiftMessages/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -767,7 +773,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; INFOPLIST_FILE = SwiftMessages/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme b/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme index 5c84455f..ba0f414b 100644 --- a/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme +++ b/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "1500" + LastUpgradeVersion = "1510" version = "1.3"> <BuildAction parallelizeBuildables = "YES" diff --git a/SwiftMessages/KeyboardTrackingView.swift b/SwiftMessages/KeyboardTrackingView.swift index f3c0ad95..946426bf 100644 --- a/SwiftMessages/KeyboardTrackingView.swift +++ b/SwiftMessages/KeyboardTrackingView.swift @@ -136,13 +136,12 @@ open class KeyboardTrackingView: UIView { self.didChange(change: change, userInfo: userInfo) self.delegate?.keyboardTrackingViewDidChange(change: change, userInfo: userInfo) } - UIView.beginAnimations(nil, context: nil) - UIView.setAnimationDuration(durationNumber.doubleValue) - UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: curveNumber.intValue)!) - UIView.setAnimationBeginsFromCurrentState(true) - self.superview?.layoutIfNeeded() - UIView.commitAnimations() - CATransaction.commit() + let curve = UIView.AnimationCurve(rawValue: curveNumber.intValue) ?? .easeInOut + let animation = UIViewPropertyAnimator(duration: durationNumber.doubleValue, curve: curve) { + self.updateConstraintsIfNeeded() + self.superview?.layoutIfNeeded() + } + animation.startAnimation() } } diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index 44f92015..7719a57a 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -12,6 +12,7 @@ protocol PresenterDelegate: AnimationDelegate { func hide(presenter: Presenter) } +@MainActor class Presenter: NSObject { // MARK: - API @@ -77,6 +78,7 @@ class Presenter: NSObject { // MARK: - Constants + @MainActor enum PresentationContext { case viewController(_: Weak<UIViewController>) case view(_: Weak<UIView>) diff --git a/SwiftMessages/SwiftMessageModifier.swift b/SwiftMessages/SwiftMessageModifier.swift index 479b6d91..9974e8b6 100644 --- a/SwiftMessages/SwiftMessageModifier.swift +++ b/SwiftMessages/SwiftMessageModifier.swift @@ -47,7 +47,7 @@ private struct SwiftMessageModifier<Message>: ViewModifier where Message: Messag content .onChange(of: message) { _ in if let message { - let show: (SwiftMessages.Config, UIView) -> Void = swiftMessages?.show(config:view:) ?? SwiftMessages.show(config:view:) + let show: @MainActor (SwiftMessages.Config, UIView) -> Void = swiftMessages?.show(config:view:) ?? SwiftMessages.show(config:view:) let view = MessageHostingView(message: message) var config = config ?? swiftMessages?.defaultConfig ?? SwiftMessages.defaultConfig config.eventListeners.append { event in diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index 395bc0ad..52244eff 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -8,6 +8,7 @@ import UIKit +@MainActor private let globalInstance = SwiftMessages() /** @@ -15,6 +16,7 @@ private let globalInstance = SwiftMessages() It behaves like a queue, only showing one message at a time. Message views that adopt the `Identifiable` protocol (as `MessageView` does) will have duplicates removed. */ +@MainActor open class SwiftMessages { /** @@ -396,9 +398,7 @@ open class SwiftMessages { */ open func show(config: Config, view: UIView) { let presenter = Presenter(config: config, view: view, delegate: self) - messageQueue.sync { - enqueue(presenter: presenter) - } + enqueue(presenter: presenter) } /** @@ -425,11 +425,11 @@ open class SwiftMessages { - Parameter config: The configuration options. - Parameter viewProvider: A block that returns the view to be displayed. */ - open func show(config: Config, viewProvider: @escaping ViewProvider) { - DispatchQueue.main.async { [weak self] in - guard let strongSelf = self else { return } + nonisolated open func show(config: Config, viewProvider: @escaping ViewProvider) { + Task { @MainActor [weak self] in + guard let self else { return } let view = viewProvider() - strongSelf.show(config: config, view: view) + self.show(config: config, view: view) } } @@ -451,9 +451,7 @@ open class SwiftMessages { Hide the current message being displayed by animating it away. */ open func hide(animated: Bool = true) { - messageQueue.sync { - hideCurrent(animated: animated) - } + hideCurrent(animated: animated) } /** @@ -461,12 +459,10 @@ open class SwiftMessages { clear the message queue. */ open func hideAll() { - messageQueue.sync { - queue.removeAll() - delays.removeAll() - counts.removeAll() - hideCurrent() - } + queue.removeAll() + delays.removeAll() + counts.removeAll() + hideCurrent() } /** @@ -476,14 +472,12 @@ open class SwiftMessages { - Parameter id: The identifier of the message to remove. */ open func hide(id: String) { - messageQueue.sync { - if id == _current?.id { - hideCurrent() - } - queue = queue.filter { $0.id != id } - delays.remove(id: id) - counts[id] = nil + if id == _current?.id { + hideCurrent() } + queue = queue.filter { $0.id != id } + delays.remove(id: id) + counts[id] = nil } /** @@ -492,21 +486,19 @@ open class SwiftMessages { shown from multiple code paths to ensure that all paths are ready to hide. */ open func hideCounted(id: String) { - messageQueue.sync { - if let count = counts[id] { - if count < 2 { - counts[id] = nil - } else { - counts[id] = count - 1 - return - } - } - if id == _current?.id { - hideCurrent() + if let count = counts[id] { + if count < 2 { + counts[id] = nil + } else { + counts[id] = count - 1 + return } - queue = queue.filter { $0.id != id } - delays.remove(id: id) } + if id == _current?.id { + hideCurrent() + } + queue = queue.filter { $0.id != id } + delays.remove(id: id) } /** @@ -538,6 +530,7 @@ open class SwiftMessages { open var pauseBetweenMessages: TimeInterval = 0.5 /// Type for keeping track of delayed presentations + @MainActor fileprivate class Delays { fileprivate func add(presenter: Presenter) { @@ -563,20 +556,17 @@ open class SwiftMessages { } func show(presenter: Presenter) { - messageQueue.sync { - enqueue(presenter: presenter) - } + enqueue(presenter: presenter) } - fileprivate let messageQueue = DispatchQueue(label: "it.swiftkick.SwiftMessages", attributes: []) fileprivate var queue: [Presenter] = [] fileprivate var delays = Delays() fileprivate var counts: [String : Int] = [:] fileprivate var _current: Presenter? = nil { didSet { if oldValue != nil { - let delayTime = DispatchTime.now() + pauseBetweenMessages - messageQueue.asyncAfter(deadline: delayTime) { [weak self] in + Task { [weak self] in + try? await Task.sleep(seconds: self?.pauseBetweenMessages ?? 0) self?.dequeueNext() } } @@ -598,9 +588,10 @@ open class SwiftMessages { } if let delay = presenter.delayShow { delays.add(presenter: presenter) - messageQueue.asyncAfter(deadline: .now() + delay) { [weak self] in + Task { [weak self] in + try? await Task.sleep(seconds: delay) // Don't enqueue if the view has been hidden during the delay window. - guard let strongSelf = self, strongSelf.delays.remove(presenter: presenter) else { return } + guard let self, self.delays.remove(presenter: presenter) else { return } doEnqueue() } } else { @@ -618,26 +609,19 @@ open class SwiftMessages { // block on animation completion. self.autohideToken = current current.showDate = CACurrentMediaTime() - DispatchQueue.main.async { [weak self] in - guard let strongSelf = self else { return } - do { - try current.show { completed in - guard let strongSelf = self else { return } - guard completed else { - strongSelf.messageQueue.sync { - strongSelf.internalHide(presenter: current) - } - return - } - if current === strongSelf.autohideToken { - strongSelf.queueAutoHide() - } + do { + try current.show { [weak self] completed in + guard let self else { return } + guard completed else { + self.internalHide(presenter: current) + return } - } catch { - strongSelf.messageQueue.sync { - strongSelf._current = nil + if current === self.autohideToken { + self.queueAutoHide() } } + } catch { + _current = nil } } @@ -654,16 +638,15 @@ open class SwiftMessages { guard let current = _current, !current.isHiding else { return } let action = { [weak self] in current.hide(animated: animated) { (completed) in - guard completed, let strongSelf = self else { return } - strongSelf.messageQueue.sync { - guard strongSelf._current === current else { return } - strongSelf.counts[current.id] = nil - strongSelf._current = nil - } + guard completed, let self else { return } + guard self._current === current else { return } + self.counts[current.id] = nil + self._current = nil } } let delay = current.delayHide ?? 0 - DispatchQueue.main.asyncAfter(deadline: .now() + delay) { + Task { + try? await Task.sleep(seconds: delay) action() } } @@ -674,18 +657,20 @@ open class SwiftMessages { guard let current = _current else { return } autohideToken = current if let pauseDuration = current.pauseDuration { - let delayTime = DispatchTime.now() + pauseDuration - messageQueue.asyncAfter(deadline: delayTime, execute: { + Task { [weak self] in + try? await Task.sleep(seconds: pauseDuration) // Make sure we've still got a green light to auto-hide. - if self.autohideToken !== current { return } + guard let self, self.autohideToken !== current else { return } self.internalHide(presenter: current) - }) + } } } deinit { - // Prevent orphaned messages - hideCurrent() + guard let current = _current else { return } + Task { @MainActor [current] in + current.hide(animated: true) { _ in } + } } } @@ -701,11 +686,7 @@ extension SwiftMessages { - Returns: The view of type `T` if it is currently being shown or hidden. */ public func current<T: UIView>() -> T? { - var view: T? - messageQueue.sync { - view = _current?.view as? T - } - return view + _current?.view as? T } /** @@ -715,13 +696,7 @@ extension SwiftMessages { - Returns: The view with matching id if currently being shown or hidden. */ public func current<T: UIView>(id: String) -> T? { - var view: T? - messageQueue.sync { - if let current = _current, current.id == id { - view = current.view as? T - } - } - return view + _current?.id == id ? _current?.view as? T : nil } /** @@ -731,13 +706,7 @@ extension SwiftMessages { - Returns: The view with matching id if currently queued to be shown. */ public func queued<T: UIView>(id: String) -> T? { - var view: T? - messageQueue.sync { - if let queued = queue.first(where: { $0.id == id }) { - view = queued.view as? T - } - } - return view + queue.first { $0.id == id }?.view as? T } /** @@ -759,16 +728,12 @@ extension SwiftMessages { extension SwiftMessages: PresenterDelegate { func hide(presenter: Presenter) { - messageQueue.sync { - self.internalHide(presenter: presenter) - } + self.internalHide(presenter: presenter) } public func hide(animator: Animator) { - messageQueue.sync { - guard let presenter = self.presenter(forAnimator: animator) else { return } - self.internalHide(presenter: presenter) - } + guard let presenter = self.presenter(forAnimator: animator) else { return } + self.internalHide(presenter: presenter) } public func panStarted(animator: Animator) { @@ -898,7 +863,7 @@ extension SwiftMessages { globalInstance.show(viewProvider: viewProvider) } - public static func show(config: Config, viewProvider: @escaping ViewProvider) { + nonisolated public static func show(config: Config, viewProvider: @escaping ViewProvider) { globalInstance.show(config: config, viewProvider: viewProvider) } diff --git a/SwiftMessages/Task+Extensions.swift b/SwiftMessages/Task+Extensions.swift new file mode 100644 index 00000000..9d6f1c3f --- /dev/null +++ b/SwiftMessages/Task+Extensions.swift @@ -0,0 +1,15 @@ +// +// Task+Extensions.swift +// SwiftMessages +// +// Created by Timothy Moose on 12/3/23. +// Copyright © 2023 SwiftKick Mobile. All rights reserved. +// + +import Foundation + +extension Task where Success == Never, Failure == Never { + static func sleep(seconds: TimeInterval) async throws { + try await sleep(nanoseconds: UInt64(seconds * 1_000_000_000)) + } +} From 5ff2cb30766d7b153bb60b29338e095a0cfd3e38 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Sun, 3 Dec 2023 12:03:14 -0600 Subject: [PATCH 61/77] Remove a couple of more usages of dispatch queues --- SwiftMessages/Animator.swift | 1 + SwiftMessages/PhysicsAnimation.swift | 1 + SwiftMessages/PhysicsPanHandler.swift | 5 ++++- SwiftMessages/SwiftMessagesSegue.swift | 3 ++- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/SwiftMessages/Animator.swift b/SwiftMessages/Animator.swift index 82074068..346ce2f8 100644 --- a/SwiftMessages/Animator.swift +++ b/SwiftMessages/Animator.swift @@ -58,6 +58,7 @@ public class AnimationContext { } } +@MainActor public protocol Animator: AnyObject { /// Adopting classes should declare as `weak`. diff --git a/SwiftMessages/PhysicsAnimation.swift b/SwiftMessages/PhysicsAnimation.swift index c073fe4a..5f5ecaf0 100644 --- a/SwiftMessages/PhysicsAnimation.swift +++ b/SwiftMessages/PhysicsAnimation.swift @@ -8,6 +8,7 @@ import UIKit +@MainActor public class PhysicsAnimation: NSObject, Animator { public enum Placement { diff --git a/SwiftMessages/PhysicsPanHandler.swift b/SwiftMessages/PhysicsPanHandler.swift index da82fc18..e381d22d 100644 --- a/SwiftMessages/PhysicsPanHandler.swift +++ b/SwiftMessages/PhysicsPanHandler.swift @@ -8,6 +8,7 @@ import UIKit +@MainActor open class PhysicsPanHandler { public var hideDelay: TimeInterval = 0.2 @@ -17,6 +18,7 @@ open class PhysicsPanHandler { var time: CFAbsoluteTime } + @MainActor public final class State { weak var messageView: UIView? @@ -127,7 +129,8 @@ open class PhysicsPanHandler { let frame = containerView.convert(view.bounds, from: view) if !containerView.bounds.intersects(frame) { self.isOffScreen = true - DispatchQueue.main.asyncAfter(deadline: .now() + self.hideDelay) { + Task { + try? await Task.sleep(seconds: self.hideDelay) animator.delegate?.hide(animator: animator) } } diff --git a/SwiftMessages/SwiftMessagesSegue.swift b/SwiftMessages/SwiftMessagesSegue.swift index cd17eec3..35687e14 100644 --- a/SwiftMessages/SwiftMessagesSegue.swift +++ b/SwiftMessages/SwiftMessagesSegue.swift @@ -228,7 +228,8 @@ open class SwiftMessagesSegue: UIStoryboardSegue { /// is removed without first dismissing. This monitor handles that scenario by setting `self.selfRetainer = nil` if /// the presenting view controller is no longer in the heirarchy. private func startReleaseMonitor() { - DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in + Task { @MainActor [weak self] in + try? await Task.sleep(seconds: 2) guard let self = self else { return } switch self.source.view.window { case .none: self.selfRetainer = nil From f3555f04126e93af1bcc5c64fa351bfb38d6740c Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Sun, 3 Dec 2023 12:17:07 -0600 Subject: [PATCH 62/77] Fix typo --- SwiftMessages/SwiftMessages.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index 52244eff..1245f067 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -651,7 +651,7 @@ open class SwiftMessages { } } - fileprivate weak var autohideToken: AnyObject? + fileprivate weak var autohideToken: Presenter? fileprivate func queueAutoHide() { guard let current = _current else { return } @@ -660,7 +660,7 @@ open class SwiftMessages { Task { [weak self] in try? await Task.sleep(seconds: pauseDuration) // Make sure we've still got a green light to auto-hide. - guard let self, self.autohideToken !== current else { return } + guard let self, self.autohideToken == current else { return } self.internalHide(presenter: current) } } From e70fb07baae07e3dca3da2ce7a8d497bfd472b20 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Mon, 15 Jan 2024 15:20:12 -0600 Subject: [PATCH 63/77] Add sheet like variation on swiftMessage modifier --- CHANGELOG.md | 12 +++ README.md | 47 +++++++---- SwiftMessages.podspec | 2 +- SwiftMessages/MessageHostingView.swift | 11 ++- SwiftMessages/SwiftMessageModifier.swift | 41 ++++++++-- .../SwiftUIDemo.xcodeproj/project.pbxproj | 4 + SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift | 2 +- .../DemoMessageWithButtonView.swift | 77 +++++++++++++++++++ SwiftUIDemo/SwiftUIDemo/DemoView.swift | 19 +++++ 9 files changed, 190 insertions(+), 25 deletions(-) create mode 100644 SwiftUIDemo/SwiftUIDemo/DemoMessageWithButtonView.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f5cc826..6031c135 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,18 @@ # Change Log All notable changes to this project will be documented in this file. +## 9.0.10 + +### Features + +* Add a `.sheet()` like variation to the `.swiftMessage()` modifier that takes a view builder. This provides more flexibility for constructing message views. + +### Fixes + +* #535 window being accessed from background thread when dequeueNext is called +* #534 Xcode warnings in two swift files +* #533 How do I show a message that appears above the keyboard, when the keyboard is already visible? + ## 9.0.9 ### Fixes diff --git a/README.md b/README.md index 5af94cb4..6a6f5afe 100644 --- a/README.md +++ b/README.md @@ -178,8 +178,7 @@ And check out our blog post [Elegant Custom UIViewController Transitioning](http Any of the built-in SwiftMessages views can be displayed by calling the SwiftMessages APIs from within observable object, a button action closure, etc. However, SwiftMessages can also display your custom SwiftUI views. -The first step is to define a type that conforms to `MessageViewConvertible`. This would typically be a struct containing the message data to display: - +Take the following message view and companion data model: ````swift struct DemoMessage: Identifiable { @@ -189,12 +188,6 @@ struct DemoMessage: Identifiable { var id: String { title + body } } -extension DemoMessage: MessageViewConvertible { - func asMessageView() -> DemoMessageView { - DemoMessageView(message: self) - } -} - struct DemoMessageView: View { let message: DemoMessage @@ -212,7 +205,7 @@ struct DemoMessageView: View { // This makes a tab-style view where the bottom corners are rounded and // the view's background extends to the top edge. .mask( - UnevenRoundedRectangle(bottomLeadingRadius: 15, bottomTrailingRadius: 15) + UnevenRoundedRectangle(bottomLeadingRadius: 15, bottomTrailingRadius: 15) // This causes the background to extend into the safe area to the screen edge. .edgesIgnoringSafeArea(.top) ) @@ -220,14 +213,14 @@ struct DemoMessageView: View { } ```` -The SwiftUI message view can be displayed just like any other UIKit message by using `MessageHostingView`: +You can show it from a button action, view model or other similar context like: ````swift struct DemoView: View { var body: some View { Button("Show message") { let message = DemoMessage(title: "Demo", body: "SwiftUI forever!") - let messageView = MessageHostingView(message: message) + let messageView = MessageHostingView(id: message.id, content: DemoMessageView(message: message) SwiftMessages.show(view: messageView) } } @@ -245,12 +238,40 @@ struct DemoView: View { Button("Show message") { message = DemoMessage(title: "Demo", body: "SwiftUI forever!") } - .swiftMessage(message: $message) + .swiftMessage(message: $message) { message in + DemoMessageView(message: message) + } } } ```` -This technique may be more SwiftUI-like, but it doesn't offer the full capability of SwiftMessages, such as explicitly hiding messages by their ID. It is totally reasonable to use a combination of both approaches. +This is very similar to the `.sheet()` modifier. However, it doesn't expose all of the features of SwiftMessages, such as explicitly hiding messages by ID. It is totally reasonable to use a combination of both approaches. + +If your message views are purely data-driven and don't require delegates, callbacks, etc., there is a slightly simplified variation on `swiftMessage()` that doesn't require a view builder. Instead, your data model should conform to `MessageViewConvertible`. + +````swift +extension DemoMessage: MessageViewConvertible { + func asMessageView() -> DemoMessageView { + DemoMessageView(message: self) + } +} +```` + +Then you can drop the view builder when calling `swiftMessage()`: + +````swift +struct DemoView: View { + + @State var message: DemoMessage? + + var body: some View { + Button("Show message") { + message = DemoMessage(title: "Demo", body: "SwiftUI forever!") + } + .swiftMessage(message: $message) + } +} +```` Try it out in the SwiftUI demo app! diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index b2b0e4ff..8042309b 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.0.9' + spec.version = '9.0.10' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkickmobile.com' } diff --git a/SwiftMessages/MessageHostingView.swift b/SwiftMessages/MessageHostingView.swift index 489ab96a..b295669e 100644 --- a/SwiftMessages/MessageHostingView.swift +++ b/SwiftMessages/MessageHostingView.swift @@ -16,10 +16,9 @@ public class MessageHostingView<Content>: BaseView, Identifiable where Content: public let id: String - public init<Message>(message: Message) where Message: MessageViewConvertible, Message.Content == Content { - let messageView: Content = message.asMessageView() - hostVC = UIHostingController(rootView: messageView) - id = message.id + public init(id: String, content: Content) { + hostVC = UIHostingController(rootView: content) + self.id = id super.init(frame: .zero) hostVC.loadViewIfNeeded() installContentView(hostVC.view) @@ -27,6 +26,10 @@ public class MessageHostingView<Content>: BaseView, Identifiable where Content: hostVC.view.backgroundColor = .clear } + convenience public init<Message>(message: Message) where Message: MessageViewConvertible, Message.Content == Content { + self.init(id: message.id, content: message.asMessageView() ) + } + // MARK: - Constants // MARK: - Variables diff --git a/SwiftMessages/SwiftMessageModifier.swift b/SwiftMessages/SwiftMessageModifier.swift index 9974e8b6..56f40f2c 100644 --- a/SwiftMessages/SwiftMessageModifier.swift +++ b/SwiftMessages/SwiftMessageModifier.swift @@ -9,28 +9,56 @@ import SwiftUI @available(iOS 14.0, *) public extension View { - /// A state-based modifier for displaying a message. + /// A state-based modifier for displaying a message when `Message` does not conform to `MessageViewConvertible`. This variant is more flexible and + /// should be used if the message view can't be represented as pure data, such as if it requires a delegate, has callbacks, etc. + func swiftMessage<Message, MessageContent>( + message: Binding<Message?>, + config: SwiftMessages.Config? = nil, + swiftMessages: SwiftMessages? = nil, + @ViewBuilder messageContent: @escaping (Message) -> MessageContent + ) -> some View where Message: Equatable & Identifiable, MessageContent: View { + modifier(SwiftMessageModifier(message: message, config: config, swiftMessages: swiftMessages, messageContent: messageContent)) + } + + /// A state-based modifier for displaying a message when `Message` conforms to `MessageViewConvertible`. This variant should be used if the message + /// view can be represented as pure data. If the message requires a delegate, has callbacks, etc., consider using the variant that takes a message view builder. func swiftMessage<Message>( message: Binding<Message?>, config: SwiftMessages.Config? = nil, swiftMessages: SwiftMessages? = nil ) -> some View where Message: MessageViewConvertible { - modifier(SwiftMessageModifier(message: message, config: config, swiftMessages: swiftMessages)) + swiftMessage(message: message, config: config, swiftMessages: swiftMessages) { content in + content.asMessageView() + } } } @available(iOS 14.0, *) -private struct SwiftMessageModifier<Message>: ViewModifier where Message: MessageViewConvertible { +private struct SwiftMessageModifier<Message, MessageContent>: ViewModifier where Message: Equatable & Identifiable, MessageContent: View { + // MARK: - API fileprivate init( message: Binding<Message?>, config: SwiftMessages.Config? = nil, - swiftMessages: SwiftMessages? = nil + swiftMessages: SwiftMessages? = nil, + @ViewBuilder messageContent: @escaping (Message) -> MessageContent ) { _message = message self.config = config self.swiftMessages = swiftMessages + self.messageContent = messageContent + } + + fileprivate init( + message: Binding<Message?>, + config: SwiftMessages.Config? = nil, + swiftMessages: SwiftMessages? = nil + ) where Message: MessageViewConvertible, Message.Content == MessageContent { + _message = message + self.config = config + self.swiftMessages = swiftMessages + self.messageContent = { $0.asMessageView() } } // MARK: - Constants @@ -40,15 +68,16 @@ private struct SwiftMessageModifier<Message>: ViewModifier where Message: Messag @Binding private var message: Message? private let config: SwiftMessages.Config? private let swiftMessages: SwiftMessages? + @ViewBuilder private let messageContent: (Message) -> MessageContent // MARK: - Body func body(content: Content) -> some View { content - .onChange(of: message) { _ in + .onChange(of: message) { message in if let message { let show: @MainActor (SwiftMessages.Config, UIView) -> Void = swiftMessages?.show(config:view:) ?? SwiftMessages.show(config:view:) - let view = MessageHostingView(message: message) + let view = MessageHostingView(id: message.id, content: messageContent(message)) var config = config ?? swiftMessages?.defaultConfig ?? SwiftMessages.defaultConfig config.eventListeners.append { event in if case .didHide = event, event.id == self.message?.id { diff --git a/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj index f6c945bc..790676b5 100644 --- a/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj +++ b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 22549DC02B55CFE8005E3E21 /* DemoMessageWithButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22549DBF2B55CFE8005E3E21 /* DemoMessageWithButtonView.swift */; }; 228F7DAD2ACF17E8006C9644 /* SwiftUIDemoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228F7DAC2ACF17E8006C9644 /* SwiftUIDemoApp.swift */; }; 228F7DAF2ACF17E8006C9644 /* DemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228F7DAE2ACF17E8006C9644 /* DemoView.swift */; }; 228F7DB12ACF17E9006C9644 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 228F7DB02ACF17E9006C9644 /* Assets.xcassets */; }; @@ -49,6 +50,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 22549DBF2B55CFE8005E3E21 /* DemoMessageWithButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoMessageWithButtonView.swift; sourceTree = "<group>"; }; 228F7DA92ACF17E8006C9644 /* SwiftUIDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftUIDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 228F7DAC2ACF17E8006C9644 /* SwiftUIDemoApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIDemoApp.swift; sourceTree = "<group>"; }; 228F7DAE2ACF17E8006C9644 /* DemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoView.swift; sourceTree = "<group>"; }; @@ -102,6 +104,7 @@ 228F7DAE2ACF17E8006C9644 /* DemoView.swift */, 228F7DD42ACF59E4006C9644 /* DemoMessage.swift */, 228F7DD62ACF5C2E006C9644 /* DemoMessageView.swift */, + 22549DBF2B55CFE8005E3E21 /* DemoMessageWithButtonView.swift */, 228F7DB02ACF17E9006C9644 /* Assets.xcassets */, 228F7DB22ACF17E9006C9644 /* Preview Content */, ); @@ -230,6 +233,7 @@ 228F7DD72ACF5C2E006C9644 /* DemoMessageView.swift in Sources */, 228F7DAF2ACF17E8006C9644 /* DemoView.swift in Sources */, 228F7DAD2ACF17E8006C9644 /* SwiftUIDemoApp.swift in Sources */, + 22549DC02B55CFE8005E3E21 /* DemoMessageWithButtonView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift b/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift index 53963023..11cf9611 100644 --- a/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift +++ b/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift @@ -7,7 +7,7 @@ import SwiftUI -// A card-style message view +// A message view with a title and message. struct DemoMessageView: View { // MARK: - API diff --git a/SwiftUIDemo/SwiftUIDemo/DemoMessageWithButtonView.swift b/SwiftUIDemo/SwiftUIDemo/DemoMessageWithButtonView.swift new file mode 100644 index 00000000..e74172ef --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/DemoMessageWithButtonView.swift @@ -0,0 +1,77 @@ +// +// DemoMessageWithButtonView.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 1/15/24. +// + +import SwiftUI + +// A message view with a title, message and button. +struct DemoMessageWithButtonView<Button>: View where Button: View { + + // MARK: - API + + enum Style { + case standard + case card + case tab + } + + init(message: DemoMessage, style: Style, @ViewBuilder button: @escaping () -> Button) { + self.message = message + self.style = style + self.button = button + } + + // MARK: - Variables + + let message: DemoMessage + let style: Style + @ViewBuilder let button: () -> Button + + // MARK: - Constants + + // MARK: - Body + + var body: some View { + switch style { + case .standard: + content() + // Mask the content and extend background into the safe area. + .mask { + Rectangle() + .edgesIgnoringSafeArea(.top) + } + case .card: + content() + // Mask the content with a rounded rectangle + .mask { + RoundedRectangle(cornerRadius: 15) + } + // External padding around the card + .padding(10) + case .tab: + content() + // Mask the content with rounded bottom edge and extend background into the safe area. + .mask { + UnevenRoundedRectangle(bottomLeadingRadius: 15, bottomTrailingRadius: 15) + .edgesIgnoringSafeArea(.top) + } + } + } + + @ViewBuilder private func content() -> some View { + VStack() { + Text(message.title).font(.system(size: 20, weight: .bold)) + Text(message.body) + button() + } + .multilineTextAlignment(.center) + // Internal padding of the card + .padding(30) + // Greedy width + .frame(maxWidth: .infinity) + .background(.demoMessageBackground) + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/DemoView.swift b/SwiftUIDemo/SwiftUIDemo/DemoView.swift index 8f47b7df..b6562cfe 100644 --- a/SwiftUIDemo/SwiftUIDemo/DemoView.swift +++ b/SwiftUIDemo/SwiftUIDemo/DemoView.swift @@ -10,8 +10,12 @@ import SwiftMessages struct DemoView: View { + /// Demonstrates purely data-driven message presentation. @State var message: DemoMessage? + /// Demonstrates message presentation with a view builder. + @State var messageWithButton: DemoMessage? + var body: some View { VStack { Button("Show standard message") { @@ -35,9 +39,24 @@ struct DemoView: View { style: .tab ) } + Button("Show message with button") { + messageWithButton = DemoMessage( + title: "Demo", + body: "This message view has a button was constructed with a view builder.", + style: .card + ) + } } .buttonStyle(.bordered) .swiftMessage(message: $message) + .swiftMessage(message: $messageWithButton) { message in + DemoMessageWithButtonView(message: message, style: .card) { + Button("Tap Me") { + print("Tap") + } + .buttonStyle(.bordered) + } + } } } From eb9591af8c3ad4964c2cb389e485583e7a632a6f Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Mon, 22 Jan 2024 15:46:30 -0600 Subject: [PATCH 64/77] Fix SwiftUI hang --- SwiftMessages/KeyboardTrackingView.swift | 17 ++++++----------- SwiftMessages/MessageHostingView.swift | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/SwiftMessages/KeyboardTrackingView.swift b/SwiftMessages/KeyboardTrackingView.swift index 946426bf..173af175 100644 --- a/SwiftMessages/KeyboardTrackingView.swift +++ b/SwiftMessages/KeyboardTrackingView.swift @@ -128,20 +128,15 @@ open class KeyboardTrackingView: UIView { } private func animateKeyboardChange(change: Change, height: CGFloat, userInfo: [AnyHashable: Any]) { - self.heightConstraint.constant = height - if let durationNumber = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber, - let curveNumber = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber { - CATransaction.begin() - CATransaction.setCompletionBlock { - self.didChange(change: change, userInfo: userInfo) - self.delegate?.keyboardTrackingViewDidChange(change: change, userInfo: userInfo) - } - let curve = UIView.AnimationCurve(rawValue: curveNumber.intValue) ?? .easeInOut - let animation = UIViewPropertyAnimator(duration: durationNumber.doubleValue, curve: curve) { + if let durationNumber = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber { + UIView.animate(withDuration: durationNumber.doubleValue, delay: 0, options: .curveEaseInOut, animations: { + self.heightConstraint.constant = height self.updateConstraintsIfNeeded() self.superview?.layoutIfNeeded() + }) { completed in + self.didChange(change: change, userInfo: userInfo) + self.delegate?.keyboardTrackingViewDidChange(change: change, userInfo: userInfo) } - animation.startAnimation() } } diff --git a/SwiftMessages/MessageHostingView.swift b/SwiftMessages/MessageHostingView.swift index b295669e..b4634d9b 100644 --- a/SwiftMessages/MessageHostingView.swift +++ b/SwiftMessages/MessageHostingView.swift @@ -10,7 +10,7 @@ import UIKit /// A rudimentary hosting view for SwiftUI messages. @available(iOS 14.0, *) -public class MessageHostingView<Content>: BaseView, Identifiable where Content: View { +public class MessageHostingView<Content>: UIView, Identifiable where Content: View { // MARK: - API @@ -50,4 +50,17 @@ public class MessageHostingView<Content>: BaseView, Identifiable where Content: if view == self || view?.superview == self { return nil } return view } + + // MARK: - Configuration + + private func installContentView(_ contentView: UIView) { + contentView.translatesAutoresizingMaskIntoConstraints = false + addSubview(contentView) + NSLayoutConstraint.activate([ + contentView.topAnchor.constraint(equalTo: topAnchor), + contentView.bottomAnchor.constraint(equalTo: bottomAnchor), + contentView.leftAnchor.constraint(equalTo: leftAnchor), + contentView.rightAnchor.constraint(equalTo: rightAnchor), + ]) + } } From 262e15f870f64e7a71a2b5137b51d7e480282c6c Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Mon, 22 Jan 2024 18:34:08 -0600 Subject: [PATCH 65/77] Update changelog --- CHANGELOG.md | 9 +++++++-- SwiftMessages.podspec | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6031c135..c068572c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,16 @@ # Change Log All notable changes to this project will be documented in this file. -## 9.0.10 +## 10.0.0 ### Features -* Add a `.sheet()` like variation to the `.swiftMessage()` modifier that takes a view builder. This provides more flexibility for constructing message views. +* Add a variation on the `.swiftMessage()` modifier that takes a view builder instead of requiring that the bound value conform to `MessageViewConvertible`. This syntax is more similar to the familiar `sheet()` modifier syntax and provides more flexibility for constructing message views. + +### Changes + +* Use `@MainActor` to ensure that SwiftMessages is not called from a background queue. +* Bump minimum deployment target to iOS 13. ### Fixes diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 8042309b..6d1a842d 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.0.10' + spec.version = '10.0.0' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkickmobile.com' } From e2b1254a973dd954663ff7aa2d8b9abff8dc01da Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Tue, 23 Jan 2024 10:42:23 -0600 Subject: [PATCH 66/77] Fix SwiftUI handling of the message binding --- SwiftMessages/SwiftMessageModifier.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/SwiftMessages/SwiftMessageModifier.swift b/SwiftMessages/SwiftMessageModifier.swift index 56f40f2c..3cab4983 100644 --- a/SwiftMessages/SwiftMessageModifier.swift +++ b/SwiftMessages/SwiftMessageModifier.swift @@ -75,8 +75,10 @@ private struct SwiftMessageModifier<Message, MessageContent>: ViewModifier where func body(content: Content) -> some View { content .onChange(of: message) { message in - if let message { - let show: @MainActor (SwiftMessages.Config, UIView) -> Void = swiftMessages?.show(config:view:) ?? SwiftMessages.show(config:view:) + let show: @MainActor (SwiftMessages.Config, UIView) -> Void = swiftMessages?.show(config:view:) ?? SwiftMessages.show(config:view:) + let hideAll: @MainActor () -> Void = swiftMessages?.hideAll ?? SwiftMessages.hideAll + switch message { + case let message?: let view = MessageHostingView(id: message.id, content: messageContent(message)) var config = config ?? swiftMessages?.defaultConfig ?? SwiftMessages.defaultConfig config.eventListeners.append { event in @@ -84,7 +86,10 @@ private struct SwiftMessageModifier<Message, MessageContent>: ViewModifier where self.message = nil } } + hideAll() show(config, view) + case .none: + hideAll() } } } From fa5f863eaadaee3629bc4fbf6be6448a1d90c4d8 Mon Sep 17 00:00:00 2001 From: AlbertoSamele <51241132+AlbertoSamele@users.noreply.github.com> Date: Tue, 23 Jan 2024 18:15:13 +0000 Subject: [PATCH 67/77] Fixes #207 (#484) --- Demo/Demo.xcodeproj/project.pbxproj | 9 +- .../xcshareddata/xcschemes/Demo.xcscheme | 7 - Demo/Demo/Base.lproj/LaunchScreen.storyboard | 13 +- Demo/Demo/Base.lproj/Main.storyboard | 297 ++++++++++-------- Demo/Demo/ExploreViewController.swift | 15 +- README.md | 5 +- SwiftMessages.xcodeproj/project.pbxproj | 4 + SwiftMessages/AccessibleMessage.swift | 3 +- SwiftMessages/HapticMessage.swift | 16 + SwiftMessages/MessageView.swift | 102 +++--- SwiftMessages/Presenter.swift | 6 + SwiftMessages/SwiftMessages.swift | 32 +- SwiftMessages/UIWindow+Extensions.swift | 14 +- SwiftMessages/WindowViewController.swift | 28 +- .../SwiftUIDemo.xcodeproj/project.pbxproj | 6 +- 15 files changed, 315 insertions(+), 242 deletions(-) create mode 100644 SwiftMessages/HapticMessage.swift diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index e7d3b1e6..57a9b7a5 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -200,7 +200,6 @@ TargetAttributes = { 86AEDCE11D5D1DB70030232E = { CreatedOnToolsVersion = 7.3.1; - DevelopmentTeam = 38R82CD868; LastSwiftMigration = 1020; }; }; @@ -427,11 +426,11 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = 38R82CD868; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Demo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.Demo; + PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages.Demo; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -444,11 +443,11 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = 38R82CD868; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Demo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.Demo; + PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages.Demo; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/Demo/Demo.xcodeproj/xcshareddata/xcschemes/Demo.xcscheme b/Demo/Demo.xcodeproj/xcshareddata/xcschemes/Demo.xcscheme index 847d6292..db82f1fa 100644 --- a/Demo/Demo.xcodeproj/xcshareddata/xcschemes/Demo.xcscheme +++ b/Demo/Demo.xcodeproj/xcshareddata/xcschemes/Demo.xcscheme @@ -50,13 +50,6 @@ ReferencedContainer = "container:Demo.xcodeproj"> </BuildableReference> </BuildableProductRunnable> - <AdditionalOptions> - <AdditionalOption - key = "MallocStackLogging" - value = "" - isEnabled = "YES"> - </AdditionalOption> - </AdditionalOptions> </LaunchAction> <ProfileAction buildConfiguration = "Release" diff --git a/Demo/Demo/Base.lproj/LaunchScreen.storyboard b/Demo/Demo/Base.lproj/LaunchScreen.storyboard index 746bfa0c..4fb64dba 100644 --- a/Demo/Demo/Base.lproj/LaunchScreen.storyboard +++ b/Demo/Demo/Base.lproj/LaunchScreen.storyboard @@ -1,12 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> - <device id="retina4_7" orientation="portrait"> - <adaptation id="fullscreen"/> - </device> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> + <device id="retina4_7" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/> - <capability name="Constraints to layout margins" minToolsVersion="6.0"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> @@ -22,14 +19,14 @@ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="© 2018 SWIFTKICK MOBILE LLC" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sBz-Dk-SSO"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="© 2024 SWIFTKICK MOBILE LLC" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sBz-Dk-SSO"> <rect key="frame" x="46" y="643" width="283" height="16"/> <fontDescription key="fontDescription" type="system" pointSize="13"/> <color key="textColor" red="0.47391887630000001" green="0.47391887630000001" blue="0.47391887630000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="splashBanner" translatesAutoresizingMaskIntoConstraints="NO" id="236-Ta-JzA"> - <rect key="frame" x="16" y="196" width="342" height="274"/> + <rect key="frame" x="16" y="196.5" width="343" height="274"/> </imageView> </subviews> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> diff --git a/Demo/Demo/Base.lproj/Main.storyboard b/Demo/Demo/Base.lproj/Main.storyboard index 08ab75d2..c38d6707 100644 --- a/Demo/Demo/Base.lproj/Main.storyboard +++ b/Demo/Demo/Base.lproj/Main.storyboard @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="JQZ-C5-7mw"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="JQZ-C5-7mw"> <device id="retina4_7" orientation="portrait" appearance="light"/> <dependencies> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15508"/> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/> + <capability name="System colors in document resources" minToolsVersion="11.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> @@ -30,10 +32,10 @@ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="j4a-wU-637"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> <prototypes> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="TitleBody" rowHeight="80" id="2n5-7h-3B5" userLabel="TitleBody Cell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> - <rect key="frame" x="0.0" y="28" width="375" height="80"/> + <rect key="frame" x="0.0" y="50" width="375" height="80"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="2n5-7h-3B5" id="Q5r-8D-38q"> <rect key="frame" x="0.0" y="0.0" width="375" height="80"/> @@ -47,7 +49,7 @@ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Body" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Gpd-DA-5jT"> <rect key="frame" x="26" y="45" width="323" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -67,21 +69,21 @@ </connections> </tableViewCell> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="Explore" rowHeight="80" id="4Pm-kC-YGr" userLabel="Explore Cell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> - <rect key="frame" x="0.0" y="108" width="375" height="80"/> + <rect key="frame" x="0.0" y="130" width="375" height="80"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="4Pm-kC-YGr" id="LmG-UL-Bu8"> - <rect key="frame" x="0.0" y="0.0" width="348" height="80"/> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="80"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="752" text="EXPLORE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TbM-iT-SVg"> - <rect key="frame" x="26" y="21" width="304" height="16"/> + <rect key="frame" x="26" y="21" width="304.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <nil key="highlightedColor"/> </label> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Explore many of the SwiftMessages configuration options." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Siq-Fh-MNa"> - <rect key="frame" x="26" y="45" width="304" height="14"/> + <rect key="frame" x="26" y="45" width="304.5" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -102,21 +104,21 @@ </connections> </tableViewCell> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="ViewController" rowHeight="80" id="edV-Vx-7mh" userLabel="View Controller Cell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> - <rect key="frame" x="0.0" y="188" width="375" height="80"/> + <rect key="frame" x="0.0" y="210" width="375" height="80"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="edV-Vx-7mh" id="6Ng-ZR-L6v"> - <rect key="frame" x="0.0" y="0.0" width="348" height="80"/> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="80"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="752" text="VIEW CONTROLLERS" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qz1-BL-wQN"> - <rect key="frame" x="26" y="21" width="304" height="16"/> + <rect key="frame" x="26" y="21" width="304.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <nil key="highlightedColor"/> </label> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Present modal view controllers with SwiftMessages animations." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sCg-K7-URy"> - <rect key="frame" x="26" y="45" width="304" height="14"/> + <rect key="frame" x="26" y="45" width="304.5" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -137,21 +139,21 @@ </connections> </tableViewCell> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="ViewController2" rowHeight="80" id="5bv-q2-Q3k" userLabel="View Controller Cell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> - <rect key="frame" x="0.0" y="268" width="375" height="80"/> + <rect key="frame" x="0.0" y="290" width="375" height="80"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="5bv-q2-Q3k" id="6q2-Qj-PQE"> - <rect key="frame" x="0.0" y="0.0" width="348" height="80"/> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="80"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="752" text="VIEW CONTROLLERS 2" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="N18-CP-QIt"> - <rect key="frame" x="26" y="21" width="304" height="16"/> + <rect key="frame" x="26" y="21" width="304.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <nil key="highlightedColor"/> </label> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Present modal view controllers with SwiftMessages animations." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="T5Q-9f-KQC"> - <rect key="frame" x="26" y="45" width="304" height="14"/> + <rect key="frame" x="26" y="45" width="304.5" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -171,21 +173,21 @@ </connections> </tableViewCell> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="Counted" rowHeight="80" id="rS6-xs-t4z" userLabel="Counted Cell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> - <rect key="frame" x="0.0" y="348" width="375" height="80"/> + <rect key="frame" x="0.0" y="370" width="375" height="80"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="rS6-xs-t4z" id="oQf-QH-2dc"> - <rect key="frame" x="0.0" y="0.0" width="348" height="80"/> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="80"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="752" text="COUNTED" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rzv-E5-oaM"> - <rect key="frame" x="26" y="21" width="304" height="16"/> + <rect key="frame" x="26" y="21" width="304.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <nil key="highlightedColor"/> </label> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hide a message based on equal number of show() and hideCounted(id:) calls." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ie4-WM-pe4"> - <rect key="frame" x="26" y="45" width="304" height="14"/> + <rect key="frame" x="26" y="45" width="304.5" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -223,25 +225,25 @@ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="none" allowsSelection="NO" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="XwA-eF-0LG"> <rect key="frame" x="0.0" y="0.0" width="375" height="1200"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> <sections> <tableViewSection headerTitle="Presentation" id="ifN-uy-lWX"> <cells> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="nYa-Hy-Lda" userLabel="Presentation style cell"> - <rect key="frame" x="0.0" y="55.5" width="375" height="44"/> + <rect key="frame" x="0.0" y="55.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="nYa-Hy-Lda" id="WC1-5B-Pa4"> - <rect key="frame" x="0.0" y="0.0" width="375" height="44"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="PRESENTATION STYLE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Epw-Yk-L8V"> - <rect key="frame" x="26" y="11" width="146.5" height="0.0"/> + <rect key="frame" x="26" y="11" width="146.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> <segmentedControl opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="751" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="Agu-Vo-ckI"> - <rect key="frame" x="26" y="16" width="194" height="18"/> + <rect key="frame" x="26" y="32" width="194" height="32"/> <segments> <segment title="Top"/> <segment title="Bottom"/> @@ -260,21 +262,21 @@ </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" selectionStyle="default" indentationWidth="10" id="eMM-fw-ePY" userLabel="Presentation context cell"> - <rect key="frame" x="0.0" y="99.5" width="375" height="81"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="eMM-fw-ePY" userLabel="Presentation context cell"> + <rect key="frame" x="0.0" y="129.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="eMM-fw-ePY" id="qjs-CO-J4K"> - <rect key="frame" x="0.0" y="0.0" width="375" height="81"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="PRESENTATION CONTEXT" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="CU0-87-ZCD"> - <rect key="frame" x="26" y="11" width="168.5" height="0.0"/> + <rect key="frame" x="26" y="11" width="168.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> <segmentedControl opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="252" verticalCompressionResistancePriority="751" contentHorizontalAlignment="left" contentVerticalAlignment="top" apportionsSegmentWidthsByContent="YES" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="AYG-qj-yjv"> - <rect key="frame" x="26" y="16" width="302" height="18"/> + <rect key="frame" x="26" y="32" width="302" height="32"/> <segments> <segment title="Automatic"/> <segment title="Normal Level"/> @@ -293,11 +295,11 @@ </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" selectionStyle="default" indentationWidth="10" id="fnL-fA-GeP" userLabel="Duration cell"> - <rect key="frame" x="0.0" y="180.5" width="375" height="108"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="fnL-fA-GeP" userLabel="Duration cell"> + <rect key="frame" x="0.0" y="203.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="fnL-fA-GeP" id="xfk-SM-u8I"> - <rect key="frame" x="0.0" y="0.0" width="375" height="108"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="751" text="DURATION" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cad-I9-jeP"> @@ -306,7 +308,7 @@ <nil key="highlightedColor"/> </label> <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" apportionsSegmentWidthsByContent="YES" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="nng-9a-v3B"> - <rect key="frame" x="26" y="32" width="310" height="2"/> + <rect key="frame" x="26" y="32" width="310" height="32"/> <segments> <segment title="Automatic"/> <segment title="Forever"/> @@ -326,11 +328,11 @@ </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" selectionStyle="default" indentationWidth="10" id="hkB-YI-YQX" userLabel="Dim mode cell"> - <rect key="frame" x="0.0" y="288.5" width="375" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="hkB-YI-YQX" userLabel="Dim mode cell"> + <rect key="frame" x="0.0" y="277.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hkB-YI-YQX" id="6ov-9U-ABh"> - <rect key="frame" x="0.0" y="0.0" width="375" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="DIM MODE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TsP-n5-Vko"> @@ -339,7 +341,7 @@ <nil key="highlightedColor"/> </label> <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="iw9-KB-Nyd"> - <rect key="frame" x="26" y="32" width="211" height="2"/> + <rect key="frame" x="26" y="32" width="211" height="32"/> <segments> <segment title="None"/> <segment title="Gray"/> @@ -360,19 +362,19 @@ </tableViewCellContentView> </tableViewCell> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="zQR-VC-Yl3" userLabel="Interactive hide cell"> - <rect key="frame" x="0.0" y="353.5" width="375" height="44"/> + <rect key="frame" x="0.0" y="351.5" width="375" height="53"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="zQR-VC-Yl3" id="RZq-YF-8fo"> - <rect key="frame" x="0.0" y="0.0" width="375" height="44"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="53"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="INTERACTIVE HIDE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dw8-96-uXk"> - <rect key="frame" x="26" y="14" width="123" height="16"/> + <rect key="frame" x="26" y="18.5" width="123" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <nil key="highlightedColor"/> </label> <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Vdr-7b-DJB"> - <rect key="frame" x="300" y="11" width="51" height="22"/> + <rect key="frame" x="300" y="11" width="51" height="31"/> </switch> </subviews> <constraints> @@ -391,20 +393,52 @@ </variation> </tableViewCellContentView> </tableViewCell> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="BkJ-zT-C7Z" userLabel="Haptic cell"> + <rect key="frame" x="0.0" y="404.5" width="375" height="53"/> + <autoresizingMask key="autoresizingMask"/> + <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="BkJ-zT-C7Z" id="GXF-qW-HHA"> + <rect key="frame" x="0.0" y="0.0" width="375" height="53"/> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Haptic Feedback" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8Vy-cX-rMN"> + <rect key="frame" x="26" y="18.5" width="109" height="16"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> + <nil key="highlightedColor"/> + </label> + <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ah6-5J-Psp"> + <rect key="frame" x="300" y="11" width="51" height="31"/> + </switch> + </subviews> + <constraints> + <constraint firstItem="8Vy-cX-rMN" firstAttribute="centerY" secondItem="GXF-qW-HHA" secondAttribute="centerY" id="605-kz-s84"/> + <constraint firstItem="ah6-5J-Psp" firstAttribute="centerY" secondItem="8Vy-cX-rMN" secondAttribute="centerY" id="CuY-eF-FkL"/> + <constraint firstAttribute="bottomMargin" secondItem="ah6-5J-Psp" secondAttribute="bottom" id="FWM-LN-Om7"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="8Vy-cX-rMN" secondAttribute="trailingMargin" id="P7C-Bc-POB"/> + <constraint firstAttribute="trailingMargin" secondItem="ah6-5J-Psp" secondAttribute="trailing" constant="10" id="QQa-X8-ldo"/> + <constraint firstItem="ah6-5J-Psp" firstAttribute="top" secondItem="GXF-qW-HHA" secondAttribute="topMargin" id="Y7g-Sy-zJR"/> + <constraint firstItem="8Vy-cX-rMN" firstAttribute="leading" secondItem="GXF-qW-HHA" secondAttribute="leadingMargin" constant="10" id="m3b-RD-jOz"/> + </constraints> + <variation key="default"> + <mask key="constraints"> + <exclude reference="605-kz-s84"/> + </mask> + </variation> + </tableViewCellContentView> + </tableViewCell> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="jsU-7Q-nnr" userLabel="Auto rotate cell"> - <rect key="frame" x="0.0" y="397.5" width="375" height="44"/> + <rect key="frame" x="0.0" y="457.5" width="375" height="53"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="jsU-7Q-nnr" id="Lyn-8c-LBy"> - <rect key="frame" x="0.0" y="0.0" width="375" height="44"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="53"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="AUTO ROTATE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VW7-M1-Q0o"> - <rect key="frame" x="26" y="14" width="92" height="16"/> + <rect key="frame" x="26" y="18.5" width="92" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <nil key="highlightedColor"/> </label> <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="WfA-vA-cpG"> - <rect key="frame" x="300" y="11" width="51" height="22"/> + <rect key="frame" x="300" y="11" width="51" height="31"/> </switch> </subviews> <constraints> @@ -427,20 +461,20 @@ </tableViewSection> <tableViewSection headerTitle="Styling" id="Ibz-q6-0d2"> <cells> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" selectionStyle="default" indentationWidth="10" id="u46-FS-ahC" userLabel="Theme cell"> - <rect key="frame" x="0.0" y="497.5" width="375" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="u46-FS-ahC" userLabel="Theme cell"> + <rect key="frame" x="0.0" y="566.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="u46-FS-ahC" id="A01-Bb-OrK"> - <rect key="frame" x="0.0" y="0.0" width="375" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="LAYOUT" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iQk-lG-ZCm"> - <rect key="frame" x="26" y="11" width="53.5" height="0.0"/> + <rect key="frame" x="26" y="11" width="53.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <nil key="highlightedColor"/> </label> <segmentedControl opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="751" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="aBT-5M-2tg"> - <rect key="frame" x="26" y="16" width="323" height="18"/> + <rect key="frame" x="26" y="32" width="323" height="32"/> <segments> <segment title="Default"/> <segment title="Card"/> @@ -460,11 +494,11 @@ </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" selectionStyle="default" indentationWidth="10" id="v73-pR-Iy2" userLabel="Theme cell"> - <rect key="frame" x="0.0" y="562.5" width="375" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="v73-pR-Iy2" userLabel="Theme cell"> + <rect key="frame" x="0.0" y="640.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="v73-pR-Iy2" id="Fdp-gh-OCb"> - <rect key="frame" x="0.0" y="0.0" width="375" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="751" text="THEME" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J7S-wJ-kt0"> @@ -473,7 +507,7 @@ <nil key="highlightedColor"/> </label> <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="NoM-It-vKT"> - <rect key="frame" x="26" y="32" width="323" height="2"/> + <rect key="frame" x="26" y="32" width="323" height="32"/> <segments> <segment title="Info"/> <segment title="Success"/> @@ -494,20 +528,20 @@ </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" selectionStyle="default" indentationWidth="10" id="0mE-sA-4rN" userLabel="Theme cell"> - <rect key="frame" x="0.0" y="627.5" width="375" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="0mE-sA-4rN" userLabel="Theme cell"> + <rect key="frame" x="0.0" y="714.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="0mE-sA-4rN" id="eVs-bm-01A"> - <rect key="frame" x="0.0" y="0.0" width="375" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="ICON STYLE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sXY-rl-8uH"> - <rect key="frame" x="26" y="11" width="79" height="0.0"/> + <rect key="frame" x="26" y="11" width="79" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <nil key="highlightedColor"/> </label> <segmentedControl opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="252" verticalCompressionResistancePriority="751" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="c2K-94-CuB"> - <rect key="frame" x="26" y="16" width="200" height="18"/> + <rect key="frame" x="26" y="32" width="200" height="32"/> <segments> <segment title="Regular"/> <segment title="Light"/> @@ -527,19 +561,19 @@ </tableViewCellContentView> </tableViewCell> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="4RW-U9-BVB" userLabel="Drop shadow cell"> - <rect key="frame" x="0.0" y="692.5" width="375" height="44"/> + <rect key="frame" x="0.0" y="788.5" width="375" height="53"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="4RW-U9-BVB" id="wdb-hX-CIv"> - <rect key="frame" x="0.0" y="0.0" width="375" height="44"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="53"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="DROP SHADOW" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MUL-on-v9R"> - <rect key="frame" x="26" y="14" width="101.5" height="16"/> + <rect key="frame" x="26" y="18.5" width="101.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <nil key="highlightedColor"/> </label> <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="sqb-Fg-YR8"> - <rect key="frame" x="300" y="11" width="51" height="22"/> + <rect key="frame" x="300" y="11" width="51" height="31"/> </switch> </subviews> <constraints> @@ -556,20 +590,20 @@ </tableViewSection> <tableViewSection headerTitle="CONTENT" id="Mih-L6-PeE"> <cells> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" selectionStyle="default" indentationWidth="10" id="ddI-Jn-NgP" userLabel="Title cell"> - <rect key="frame" x="0.0" y="792.5" width="375" height="84"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="ddI-Jn-NgP" userLabel="Title cell"> + <rect key="frame" x="0.0" y="897.5" width="375" height="75"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ddI-Jn-NgP" id="4HG-zA-HtF"> - <rect key="frame" x="0.0" y="0.0" width="375" height="84"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="75"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="TITLE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zs0-Qc-Tls"> - <rect key="frame" x="26" y="11" width="37" height="0.0"/> + <rect key="frame" x="26" y="11" width="37" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <nil key="highlightedColor"/> </label> <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" verticalCompressionResistancePriority="751" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="Heads Up!" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="Z0U-kn-8rs"> - <rect key="frame" x="26" y="14" width="323" height="19"/> + <rect key="frame" x="26" y="30" width="323" height="34"/> <fontDescription key="fontDescription" type="system" pointSize="14"/> <textInputTraits key="textInputTraits" returnKeyType="done" enablesReturnKeyAutomatically="YES"/> </textField> @@ -585,20 +619,20 @@ </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" selectionStyle="default" indentationWidth="10" id="bdE-R5-mtF" userLabel="Subtitle cell"> - <rect key="frame" x="0.0" y="876.5" width="375" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="bdE-R5-mtF" userLabel="Subtitle cell"> + <rect key="frame" x="0.0" y="972.5" width="375" height="75"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="bdE-R5-mtF" id="E8h-YG-8UX"> - <rect key="frame" x="0.0" y="0.0" width="375" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="75"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="BODY" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="KYf-CB-aEU"> - <rect key="frame" x="26" y="11" width="37.5" height="0.0"/> + <rect key="frame" x="26" y="11" width="37.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <nil key="highlightedColor"/> </label> <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" verticalCompressionResistancePriority="751" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="This message is very important." borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="Ev4-j7-wY0"> - <rect key="frame" x="26" y="14" width="323" height="19"/> + <rect key="frame" x="26" y="30" width="323" height="34"/> <fontDescription key="fontDescription" type="system" pointSize="14"/> <textInputTraits key="textInputTraits"/> </textField> @@ -614,48 +648,48 @@ </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" selectionStyle="default" indentationWidth="10" id="i0m-Xn-tMe" userLabel="Hiding cell"> - <rect key="frame" x="0.0" y="941.5" width="375" height="110"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="i0m-Xn-tMe" userLabel="Hiding cell"> + <rect key="frame" x="0.0" y="1047.5" width="375" height="113"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="i0m-Xn-tMe" id="y4L-XO-6WY"> - <rect key="frame" x="0.0" y="0.0" width="375" height="110"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="113"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SHOW" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="07f-nU-dvy"> - <rect key="frame" x="26" y="11" width="42" height="0.0"/> + <rect key="frame" x="26" y="11" width="42" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <nil key="highlightedColor"/> </label> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="UMq-Yn-VYn"> - <rect key="frame" x="26" y="19" width="323" height="14"/> + <rect key="frame" x="26" y="35" width="323" height="67"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="40" translatesAutoresizingMaskIntoConstraints="NO" id="zwT-Yv-eyU"> - <rect key="frame" x="0.0" y="0.0" width="323" height="4.5"/> + <rect key="frame" x="0.0" y="0.0" width="323" height="31"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="sWT-Ug-j6y"> - <rect key="frame" x="0.0" y="0.0" width="141.5" height="4.5"/> + <rect key="frame" x="0.0" y="0.0" width="141.5" height="31"/> <subviews> <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="w9C-j2-COD"> - <rect key="frame" x="0.0" y="0.0" width="51" height="4.5"/> + <rect key="frame" x="0.0" y="0.0" width="51" height="31"/> </switch> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Button" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dRM-c4-ORW"> - <rect key="frame" x="69" y="0.0" width="72.5" height="4.5"/> + <rect key="frame" x="69" y="6" width="72.5" height="19.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> </stackView> <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="WVf-N1-ipR"> - <rect key="frame" x="181.5" y="0.0" width="141.5" height="4.5"/> + <rect key="frame" x="181.5" y="0.0" width="141.5" height="31"/> <subviews> <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CDM-PI-gjl"> - <rect key="frame" x="0.0" y="0.0" width="51" height="4.5"/> + <rect key="frame" x="0.0" y="0.0" width="51" height="31"/> </switch> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PfQ-eZ-O0L"> - <rect key="frame" x="69" y="0.0" width="72.5" height="4.5"/> + <rect key="frame" x="69" y="6" width="72.5" height="19.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -663,32 +697,32 @@ </subviews> </stackView> <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="40" translatesAutoresizingMaskIntoConstraints="NO" id="FqU-2E-xeu"> - <rect key="frame" x="0.0" y="9.5" width="323" height="4.5"/> + <rect key="frame" x="0.0" y="36" width="323" height="31"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="VJa-y8-lxV"> - <rect key="frame" x="0.0" y="0.0" width="141.5" height="4.5"/> + <rect key="frame" x="0.0" y="0.0" width="141.5" height="31"/> <subviews> <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mfB-t8-O1h"> - <rect key="frame" x="0.0" y="0.0" width="51" height="4.5"/> + <rect key="frame" x="0.0" y="0.0" width="51" height="31"/> </switch> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Icon" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XKN-W4-1jq"> - <rect key="frame" x="69" y="0.0" width="72.5" height="4.5"/> + <rect key="frame" x="69" y="6" width="72.5" height="19.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> </stackView> <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="9hh-9r-JQN"> - <rect key="frame" x="181.5" y="0.0" width="141.5" height="4.5"/> + <rect key="frame" x="181.5" y="0.0" width="141.5" height="31"/> <subviews> <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zUi-zd-sZL"> - <rect key="frame" x="0.0" y="0.0" width="51" height="4.5"/> + <rect key="frame" x="0.0" y="0.0" width="51" height="31"/> </switch> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Body" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DGg-y8-Ln9"> - <rect key="frame" x="69" y="0.0" width="72.5" height="4.5"/> + <rect key="frame" x="69" y="6" width="72.5" height="19.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -780,6 +814,7 @@ <outlet property="dimMode" destination="iw9-KB-Nyd" id="OiP-ss-kEO"/> <outlet property="dropShadow" destination="sqb-Fg-YR8" id="zUz-6P-IFz"/> <outlet property="duration" destination="nng-9a-v3B" id="4VC-Yi-AiA"/> + <outlet property="hapticFeedback" destination="ah6-5J-Psp" id="HSQ-XB-1nn"/> <outlet property="iconStyle" destination="c2K-94-CuB" id="Qwt-xY-oZ2"/> <outlet property="interactiveHide" destination="Vdr-7b-DJB" id="pEi-RT-l7U"/> <outlet property="layout" destination="aBT-5M-2tg" id="4GZ-iP-oCa"/> @@ -810,10 +845,10 @@ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="mGe-El-haJ"> - <rect key="frame" x="46" y="84" width="283" height="494"/> + <rect key="frame" x="46" y="104" width="283" height="474"/> <subviews> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DrN-Ei-Pg7"> - <rect key="frame" x="0.0" y="0.0" width="283" height="62"/> + <rect key="frame" x="0.0" y="0.0" width="283" height="59"/> <color key="backgroundColor" red="0.16470588235294117" green="0.6588235294117647" blue="0.98039215686274506" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> <state key="normal" title="Top Message"/> @@ -827,7 +862,7 @@ </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GeC-SP-rSC"> - <rect key="frame" x="0.0" y="72" width="283" height="62"/> + <rect key="frame" x="0.0" y="69" width="283" height="59.5"/> <color key="backgroundColor" red="0.1647058824" green="0.6588235294" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> <state key="normal" title="Bottom Message"/> @@ -841,7 +876,7 @@ </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DGn-eY-EEX"> - <rect key="frame" x="0.0" y="144" width="283" height="62"/> + <rect key="frame" x="0.0" y="138.5" width="283" height="59"/> <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> <state key="normal" title="Top Card"/> @@ -855,7 +890,7 @@ </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZQs-MK-vK3"> - <rect key="frame" x="0.0" y="216" width="283" height="62"/> + <rect key="frame" x="0.0" y="207.5" width="283" height="59"/> <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> <state key="normal" title="Bottom Card"/> @@ -869,7 +904,7 @@ </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kux-aE-Bdv" userLabel="Top Tab"> - <rect key="frame" x="0.0" y="288" width="283" height="62"/> + <rect key="frame" x="0.0" y="276.5" width="283" height="59"/> <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000067" blue="0.62082127703967116" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> <state key="normal" title="Top Tab"/> @@ -883,7 +918,7 @@ </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dMQ-xF-RwV" userLabel="Bottom Tab"> - <rect key="frame" x="0.0" y="360" width="283" height="62"/> + <rect key="frame" x="0.0" y="345.5" width="283" height="59.5"/> <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000001" blue="0.620821277" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> <state key="normal" title="Bottom Tab"/> @@ -897,7 +932,7 @@ </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CDi-Gu-bE2" userLabel="Centered"> - <rect key="frame" x="0.0" y="432" width="283" height="62"/> + <rect key="frame" x="0.0" y="415" width="283" height="59"/> <color key="backgroundColor" red="1" green="0.46653546191345963" blue="0.015686274510000042" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> <state key="normal" title="Centered"/> @@ -913,7 +948,7 @@ </subviews> </stackView> </subviews> - <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> <constraints> <constraint firstItem="mGe-El-haJ" firstAttribute="top" secondItem="WeL-Zn-0tj" secondAttribute="bottom" constant="40" id="6TI-R1-eMQ"/> <constraint firstItem="mGe-El-haJ" firstAttribute="leading" secondItem="YlT-hO-kIK" secondAttribute="leadingMargin" constant="30" id="LqT-Kn-3v7"/> @@ -933,7 +968,7 @@ <tabBarItem key="tabBarItem" title="Item" id="lRD-YW-2WT"/> <value key="contentSizeForViewInPopover" type="size" width="0.0" height="250"/> <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="eD6-og-rzJ"> - <rect key="frame" x="0.0" y="0.0" width="375" height="44"/> + <rect key="frame" x="0.0" y="20" width="375" height="44"/> <autoresizingMask key="autoresizingMask"/> </navigationBar> <connections> @@ -951,19 +986,19 @@ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="veg-5v-Pex"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> <sections> <tableViewSection id="CqX-XV-4eD"> <cells> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="09c-ne-yN9" style="IBUITableViewCellStyleDefault" id="Udi-FH-lzN"> - <rect key="frame" x="0.0" y="28" width="375" height="44"/> + <rect key="frame" x="0.0" y="50" width="375" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Udi-FH-lzN" id="hKw-az-hVR"> - <rect key="frame" x="0.0" y="0.0" width="348" height="44"/> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Item 1" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="09c-ne-yN9"> - <rect key="frame" x="16" y="0.0" width="324" height="44"/> + <rect key="frame" x="16" y="0.0" width="324.5" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <fontDescription key="fontDescription" type="system" pointSize="17"/> <nil key="textColor"/> @@ -976,14 +1011,14 @@ </connections> </tableViewCell> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="idk-C0-F7z" style="IBUITableViewCellStyleDefault" id="hLA-of-n8g"> - <rect key="frame" x="0.0" y="72" width="375" height="44"/> + <rect key="frame" x="0.0" y="93.5" width="375" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="hLA-of-n8g" id="70t-ga-6jT"> - <rect key="frame" x="0.0" y="0.0" width="348" height="44"/> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Item 2" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="idk-C0-F7z"> - <rect key="frame" x="16" y="0.0" width="324" height="44"/> + <rect key="frame" x="16" y="0.0" width="324.5" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <fontDescription key="fontDescription" type="system" pointSize="17"/> <nil key="textColor"/> @@ -996,14 +1031,14 @@ </connections> </tableViewCell> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="fhG-aN-pzJ" style="IBUITableViewCellStyleDefault" id="jc4-aX-Ow9"> - <rect key="frame" x="0.0" y="116" width="375" height="44"/> + <rect key="frame" x="0.0" y="137" width="375" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="jc4-aX-Ow9" id="Jrq-7c-eSM"> - <rect key="frame" x="0.0" y="0.0" width="348" height="44"/> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Item 3" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="fhG-aN-pzJ"> - <rect key="frame" x="16" y="0.0" width="324" height="44"/> + <rect key="frame" x="16" y="0.0" width="324.5" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <fontDescription key="fontDescription" type="system" pointSize="17"/> <nil key="textColor"/> @@ -1049,13 +1084,13 @@ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Nothing to see here." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2bv-DK-h4b"> - <rect key="frame" x="109.5" y="345" width="156" height="21"/> + <rect key="frame" x="110.5" y="355" width="154.5" height="21"/> <fontDescription key="fontDescription" type="system" pointSize="17"/> <nil key="textColor"/> <nil key="highlightedColor"/> </label> </subviews> - <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> <constraints> <constraint firstItem="2bv-DK-h4b" firstAttribute="centerX" secondItem="0Cn-7n-ODp" secondAttribute="centerX" id="1aC-Jw-Zyl"/> <constraint firstItem="2bv-DK-h4b" firstAttribute="centerY" secondItem="0Cn-7n-ODp" secondAttribute="centerYWithinMargins" id="93w-dz-NPV"/> @@ -1072,7 +1107,7 @@ <navigationController id="UrZ-Dq-bGZ" sceneMemberID="viewController"> <tabBarItem key="tabBarItem" title="" image="iconSwiftMessages" id="Ttu-oX-nwD"/> <navigationBar key="navigationBar" contentMode="scaleToFill" id="vE6-lq-HY6"> - <rect key="frame" x="0.0" y="0.0" width="375" height="44"/> + <rect key="frame" x="0.0" y="20" width="375" height="44"/> <autoresizingMask key="autoresizingMask"/> </navigationBar> <connections> @@ -1084,11 +1119,17 @@ <point key="canvasLocation" x="473" y="305"/> </scene> </scenes> - <resources> - <image name="iconSwiftMessages" width="38" height="31"/> - </resources> <inferredMetricsTieBreakers> <segue reference="h5n-Vv-Q3y"/> <segue reference="EaG-Ea-U3j"/> </inferredMetricsTieBreakers> + <resources> + <image name="iconSwiftMessages" width="38" height="31"/> + <systemColor name="secondaryLabelColor"> + <color red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + </systemColor> + <systemColor name="systemBackgroundColor"> + <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + </systemColor> + </resources> </document> diff --git a/Demo/Demo/ExploreViewController.swift b/Demo/Demo/ExploreViewController.swift index d39009a2..5d34762a 100644 --- a/Demo/Demo/ExploreViewController.swift +++ b/Demo/Demo/ExploreViewController.swift @@ -41,16 +41,16 @@ class ExploreViewController: UITableViewController, UITextFieldDelegate { switch theme.selectedSegmentIndex { case 0: - view.configureTheme(.info, iconStyle: iconStyle) + view.configureTheme(.info, iconStyle: iconStyle, includeHaptic: hapticFeedback.isOn) view.accessibilityPrefix = "info" case 1: - view.configureTheme(.success, iconStyle: iconStyle) + view.configureTheme(.success, iconStyle: iconStyle, includeHaptic: hapticFeedback.isOn) view.accessibilityPrefix = "success" case 2: - view.configureTheme(.warning, iconStyle: iconStyle) + view.configureTheme(.warning, iconStyle: iconStyle, includeHaptic: hapticFeedback.isOn) view.accessibilityPrefix = "warning" case 3: - view.configureTheme(.error, iconStyle: iconStyle) + view.configureTheme(.error, iconStyle: iconStyle, includeHaptic: hapticFeedback.isOn) view.accessibilityPrefix = "error" default: let iconText = ["🐸", "🐷", "🐬", "🐠", "🐍", "🐹", "🐼"].randomElement() @@ -140,7 +140,11 @@ class ExploreViewController: UITableViewController, UITextFieldDelegate { break } } - + + if view.defaultHaptic == nil && hapticFeedback.isOn { + config.haptic = .success + } + // Show SwiftMessages.show(config: config, view: view) } @@ -154,6 +158,7 @@ class ExploreViewController: UITableViewController, UITextFieldDelegate { @IBOutlet weak var duration: UISegmentedControl! @IBOutlet weak var dimMode: UISegmentedControl! @IBOutlet weak var interactiveHide: UISwitch! + @IBOutlet weak var hapticFeedback: UISwitch! @IBOutlet weak var layout: UISegmentedControl! @IBOutlet weak var theme: UISegmentedControl! @IBOutlet weak var iconStyle: UISegmentedControl! diff --git a/README.md b/README.md index 6a6f5afe..abec2f0e 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,9 @@ config.dimMode = .gray(interactive: true) // Disable the interactive pan-to-hide gesture. config.interactiveHide = false +// Specify haptic feedback (see also MessageView/configureTheme) +config.haptic = .success + // Specify a status bar style to if the message is displayed directly under the status bar. config.preferredStatusBarStyle = .lightContent @@ -407,7 +410,7 @@ A common mistake is attempting to remove an element by setting the corresponding `MessageView` provides numerous methods that follow the `configure*` naming convention: ````swift -view.configureTheme(.warning) +view.configureTheme(.warning, includeHaptic: true) view.configureContent(title: "Warning", body: "Consider yourself warned.", iconText: "🤔") ```` diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 19d5bcd0..2ea0092a 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -55,6 +55,7 @@ 228F7DDE2ACF703A006C9644 /* MessageHostingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228F7DDB2ACF7039006C9644 /* MessageHostingView.swift */; }; 228F7DDF2ACF703A006C9644 /* SwiftMessageModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228F7DDC2ACF703A006C9644 /* SwiftMessageModifier.swift */; }; 228F7DE02ACF703A006C9644 /* MessageViewConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228F7DDD2ACF703A006C9644 /* MessageViewConvertible.swift */; }; + 22982C172B6030B000852311 /* HapticMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22982C162B6030B000852311 /* HapticMessage.swift */; }; 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */; }; @@ -147,6 +148,7 @@ 228F7DDB2ACF7039006C9644 /* MessageHostingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageHostingView.swift; sourceTree = "<group>"; }; 228F7DDC2ACF703A006C9644 /* SwiftMessageModifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftMessageModifier.swift; sourceTree = "<group>"; }; 228F7DDD2ACF703A006C9644 /* MessageViewConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageViewConvertible.swift; sourceTree = "<group>"; }; + 22982C162B6030B000852311 /* HapticMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HapticMessage.swift; sourceTree = "<group>"; }; 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = "<group>"; }; @@ -319,6 +321,7 @@ 864495551D4F7C390056EB2A /* Identifiable.swift */, 86AAF81D1D5549680031EE32 /* MarginAdjustable.swift */, 22E307FE1E74C5B100E35893 /* AccessibleMessage.swift */, + 22982C162B6030B000852311 /* HapticMessage.swift */, 86AAF82A1D580DD70031EE32 /* Error.swift */, 2298C2061EE480D000E2DDC1 /* Animator.swift */, 2298C2041EE47DC900E2DDC1 /* Weak.swift */, @@ -560,6 +563,7 @@ 86BBA9011D5E040600FE8F16 /* PassthroughWindow.swift in Sources */, 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */, 22D3B4562B1CEF76002D8665 /* Task+Extensions.swift in Sources */, + 22982C172B6030B000852311 /* HapticMessage.swift in Sources */, 86BBA9031D5E040600FE8F16 /* UIViewController+Extensions.swift in Sources */, 228F7DDF2ACF703A006C9644 /* SwiftMessageModifier.swift in Sources */, 224FB69921153B440081D4DE /* CALayer+Extensions.swift in Sources */, diff --git a/SwiftMessages/AccessibleMessage.swift b/SwiftMessages/AccessibleMessage.swift index d540ecea..71590aa0 100644 --- a/SwiftMessages/AccessibleMessage.swift +++ b/SwiftMessages/AccessibleMessage.swift @@ -9,8 +9,7 @@ import Foundation /** - Message views that `AccessibleMessage`, as `MessageView` does will - have proper accessibility behavior when displaying messages. + Message views that conform to `AccessibleMessage` will have proper accessibility behavior when displaying messages. `MessageView` implements this protocol. */ public protocol AccessibleMessage { diff --git a/SwiftMessages/HapticMessage.swift b/SwiftMessages/HapticMessage.swift new file mode 100644 index 00000000..fa86614f --- /dev/null +++ b/SwiftMessages/HapticMessage.swift @@ -0,0 +1,16 @@ +// +// HapticMessage.swift +// SwiftMessages +// +// Created by Timothy Moose on 1/23/24. +// Copyright © 2024 SwiftKick Mobile. All rights reserved. +// + +import Foundation + +/** + Message views that conform to `HapticMessage` can specify a haptic feedback to be used when presented. + */ +protocol HapticMessage { + var defaultHaptic: SwiftMessages.Haptic? { get } +} diff --git a/SwiftMessages/MessageView.swift b/SwiftMessages/MessageView.swift index c71141a6..6384917e 100644 --- a/SwiftMessages/MessageView.swift +++ b/SwiftMessages/MessageView.swift @@ -10,8 +10,15 @@ import UIKit /* */ -open class MessageView: BaseView, Identifiable, AccessibleMessage { +open class MessageView: BaseView, Identifiable, AccessibleMessage, HapticMessage { + + /* + MARK: - Haptic feedback + */ + /// The default haptic feedback to be used when the message is presented. + open var defaultHaptic: SwiftMessages.Haptic? + /* MARK: - Button tap handler */ @@ -248,73 +255,74 @@ extension MessageView { - Parameter theme: The theme type to use. - Parameter iconStyle: The icon style to use. Defaults to `.Default`. + - Parameter useHaptics: If `true`, configures an appropriate haptic based on theme. Defaults to `false`. */ - public func configureTheme(_ theme: Theme, iconStyle: IconStyle = .default) { + public func configureTheme(_ theme: Theme, iconStyle: IconStyle = .default, includeHaptic: Bool = false) { let iconImage = iconStyle.image(theme: theme) let backgroundColor: UIColor let foregroundColor: UIColor let defaultBackgroundColor: UIColor - let defaultForegroundColor: UIColor switch theme { case .info: defaultBackgroundColor = UIColor(red: 225.0/255.0, green: 225.0/255.0, blue: 225.0/255.0, alpha: 1.0) - defaultForegroundColor = UIColor.darkText case .success: defaultBackgroundColor = UIColor(red: 97.0/255.0, green: 161.0/255.0, blue: 23.0/255.0, alpha: 1.0) - defaultForegroundColor = UIColor.white case .warning: defaultBackgroundColor = UIColor(red: 246.0/255.0, green: 197.0/255.0, blue: 44.0/255.0, alpha: 1.0) - defaultForegroundColor = UIColor.white case .error: defaultBackgroundColor = UIColor(red: 249.0/255.0, green: 66.0/255.0, blue: 47.0/255.0, alpha: 1.0) - defaultForegroundColor = UIColor.white } - if #available(iOS 13.0, *) { + if includeHaptic { switch theme { - case .info: - backgroundColor = UIColor { - switch $0.userInterfaceStyle { - case .dark, .unspecified: return UIColor(red: 125/255.0, green: 125/255.0, blue: 125/255.0, alpha: 1.0) - case .light: fallthrough - @unknown default: - return defaultBackgroundColor - } + case .success, .info: + defaultHaptic = SwiftMessages.Haptic.success + case .warning: + defaultHaptic = SwiftMessages.Haptic.warning + case .error: + defaultHaptic = SwiftMessages.Haptic.error + } + } + switch theme { + case .info: + backgroundColor = UIColor { + switch $0.userInterfaceStyle { + case .dark, .unspecified: return UIColor(red: 125/255.0, green: 125/255.0, blue: 125/255.0, alpha: 1.0) + case .light: fallthrough + @unknown default: + return defaultBackgroundColor } - foregroundColor = .label - case .success: - backgroundColor = UIColor { - switch $0.userInterfaceStyle { - case .dark, .unspecified: return UIColor(red: 55/255.0, green: 122/255.0, blue: 0/255.0, alpha: 1.0) - case .light: fallthrough - @unknown default: - return defaultBackgroundColor - } + } + foregroundColor = .label + case .success: + backgroundColor = UIColor { + switch $0.userInterfaceStyle { + case .dark, .unspecified: return UIColor(red: 55/255.0, green: 122/255.0, blue: 0/255.0, alpha: 1.0) + case .light: fallthrough + @unknown default: + return defaultBackgroundColor } - foregroundColor = .white - case .warning: - backgroundColor = UIColor { - switch $0.userInterfaceStyle { - case .dark, .unspecified: return UIColor(red: 239/255.0, green: 184/255.0, blue: 10/255.0, alpha: 1.0) - case .light: fallthrough - @unknown default: - return defaultBackgroundColor - } + } + foregroundColor = .white + case .warning: + backgroundColor = UIColor { + switch $0.userInterfaceStyle { + case .dark, .unspecified: return UIColor(red: 239/255.0, green: 184/255.0, blue: 10/255.0, alpha: 1.0) + case .light: fallthrough + @unknown default: + return defaultBackgroundColor } - foregroundColor = .white - case .error: - backgroundColor = UIColor { - switch $0.userInterfaceStyle { - case .dark, .unspecified: return UIColor(red: 195/255.0, green: 12/255.0, blue: 12/255.0, alpha: 1.0) - case .light: fallthrough - @unknown default: - return defaultBackgroundColor - } + } + foregroundColor = .white + case .error: + backgroundColor = UIColor { + switch $0.userInterfaceStyle { + case .dark, .unspecified: return UIColor(red: 195/255.0, green: 12/255.0, blue: 12/255.0, alpha: 1.0) + case .light: fallthrough + @unknown default: + return defaultBackgroundColor } - foregroundColor = .white } - } else { - backgroundColor = defaultBackgroundColor - foregroundColor = defaultForegroundColor + foregroundColor = .white } configureTheme(backgroundColor: backgroundColor, foregroundColor: foregroundColor, iconImage: iconImage) } diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index 7719a57a..e7f50493 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -129,6 +129,12 @@ class Presenter: NSObject { try presentationContext = getPresentationContext() install() self.config.eventListeners.forEach { $0(.willShow(self.view)) } + switch (self.view as? HapticMessage)?.defaultHaptic ?? config.haptic { + case .error?: UINotificationFeedbackGenerator().notificationOccurred(.error) + case .warning?: UINotificationFeedbackGenerator().notificationOccurred(.warning) + case .success?: UINotificationFeedbackGenerator().notificationOccurred(.success) + default: break + } showAnimation() { completed in completion(completed) if completed { diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index 1245f067..b41a4d01 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -153,6 +153,20 @@ open class SwiftMessages { case indefinite(delay: TimeInterval, minimum: TimeInterval) } + /** + Specifies notification's haptic feedback to be used on `MessageView` display + */ + + /** + Specifies an optional haptic feedback to be used on `MessageView` display + */ + public enum Haptic { + case success + case warning + case error + } + + /** Specifies options for dimming the background behind the message view similar to a popover view controller. @@ -263,16 +277,7 @@ open class SwiftMessages { Specifies how the container for presenting the message view is selected. The default is `.Automatic`. */ - public var presentationContext = PresentationContext.automatic { - didSet { - if case .windowScene = presentationContext { - guard #available(iOS 13.0, *) else { - assertionFailure("windowScene is not supported below iOS 13.0.") - return - } - } - } - } + public var presentationContext = PresentationContext.automatic /** Specifies the duration of the message view's time on screen before it is @@ -286,6 +291,13 @@ open class SwiftMessages { */ public var dimMode = DimMode.none + + /** + Specifies notification's haptic feedback to be played on `MessageView` display. + No default value is provided. + */ + public var haptic: Haptic? = nil + /** Specifies whether or not the interactive pan-to-hide gesture is enabled on the message view. For views that implement the `BackgroundViewable` diff --git a/SwiftMessages/UIWindow+Extensions.swift b/SwiftMessages/UIWindow+Extensions.swift index 316fcacd..6a626f4e 100644 --- a/SwiftMessages/UIWindow+Extensions.swift +++ b/SwiftMessages/UIWindow+Extensions.swift @@ -11,15 +11,11 @@ import UIKit extension UIWindow { #if !SWIFTMESSAGES_APP_EXTENSIONS static var keyWindow: UIWindow? { - if #available(iOS 13.0, *) { - return UIApplication.shared.connectedScenes - .sorted { $0.activationState.sortPriority < $1.activationState.sortPriority } - .compactMap { $0 as? UIWindowScene } - .compactMap { $0.windows.first { $0.isKeyWindow } } - .first - } else { - return UIApplication.shared.keyWindow - } + return UIApplication.shared.connectedScenes + .sorted { $0.activationState.sortPriority < $1.activationState.sortPriority } + .compactMap { $0 as? UIWindowScene } + .compactMap { $0.windows.first { $0.isKeyWindow } } + .first } #endif } diff --git a/SwiftMessages/WindowViewController.swift b/SwiftMessages/WindowViewController.swift index 9c2b721c..30d77f9a 100644 --- a/SwiftMessages/WindowViewController.swift +++ b/SwiftMessages/WindowViewController.swift @@ -27,24 +27,18 @@ open class WindowViewController: UIViewController self.view = view window.rootViewController = self window.windowLevel = config.windowLevel ?? UIWindow.Level.normal - if #available(iOS 13, *) { - window.overrideUserInterfaceStyle = config.overrideUserInterfaceStyle - } + window.overrideUserInterfaceStyle = config.overrideUserInterfaceStyle } func install() { - if #available(iOS 13, *) { - window?.windowScene = config.windowScene - #if !SWIFTMESSAGES_APP_EXTENSIONS - previousKeyWindow = UIWindow.keyWindow - #endif - show( - becomeKey: config.shouldBecomeKeyWindow, - frame: config.windowScene?.coordinateSpace.bounds - ) - } else { - show(becomeKey: config.shouldBecomeKeyWindow) - } + window?.windowScene = config.windowScene + #if !SWIFTMESSAGES_APP_EXTENSIONS + previousKeyWindow = UIWindow.keyWindow + #endif + show( + becomeKey: config.shouldBecomeKeyWindow, + frame: config.windowScene?.coordinateSpace.bounds + ) } private func show(becomeKey: Bool, frame: CGRect? = nil) { @@ -61,9 +55,7 @@ open class WindowViewController: UIViewController if window?.isKeyWindow == true { previousKeyWindow?.makeKey() } - if #available(iOS 13, *) { - window?.windowScene = nil - } + window?.windowScene = nil window?.isHidden = true window = nil } diff --git a/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj index 790676b5..f1519c40 100644 --- a/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj +++ b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj @@ -367,6 +367,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"SwiftUIDemo/Preview Content\""; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = SwiftUIDemo/Info.plist; @@ -380,7 +381,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.swiftkickmobile.SwiftUIDemo; + PRODUCT_BUNDLE_IDENTIFIER = com.swiftkickmobile.SwiftMessages.SwiftUIDemo; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -396,6 +397,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"SwiftUIDemo/Preview Content\""; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = SwiftUIDemo/Info.plist; @@ -409,7 +411,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.swiftkickmobile.SwiftUIDemo; + PRODUCT_BUNDLE_IDENTIFIER = com.swiftkickmobile.SwiftMessages.SwiftUIDemo; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; From b899be48a61ddb209695a8d5e411189b704a7fa3 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Tue, 6 Feb 2024 17:19:57 -0600 Subject: [PATCH 68/77] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c068572c..8316ae28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ### Features * Add a variation on the `.swiftMessage()` modifier that takes a view builder instead of requiring that the bound value conform to `MessageViewConvertible`. This syntax is more similar to the familiar `sheet()` modifier syntax and provides more flexibility for constructing message views. +* #207 Add optional haptic feedback ### Changes From a49306be3a040d14a6196ba435e5cf9c43309cd6 Mon Sep 17 00:00:00 2001 From: Kaleb Cooper <94631017+kalebzen@users.noreply.github.com> Date: Sun, 23 Jun 2024 13:28:37 -0500 Subject: [PATCH 69/77] remove MainActor from class declaration (#543) --- SwiftMessages/SwiftMessages.swift | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index b41a4d01..5d96b3b0 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -16,7 +16,6 @@ private let globalInstance = SwiftMessages() It behaves like a queue, only showing one message at a time. Message views that adopt the `Identifiable` protocol (as `MessageView` does) will have duplicates removed. */ -@MainActor open class SwiftMessages { /** @@ -408,6 +407,7 @@ open class SwiftMessages { - Parameter config: The configuration options. - Parameter view: The view to be displayed. */ + @MainActor open func show(config: Config, view: UIView) { let presenter = Presenter(config: config, view: view, delegate: self) enqueue(presenter: presenter) @@ -420,6 +420,7 @@ open class SwiftMessages { - Parameter config: The configuration options. - Parameter view: The view to be displayed. */ + @MainActor public func show(view: UIView) { show(config: defaultConfig, view: view) } @@ -462,6 +463,7 @@ open class SwiftMessages { /** Hide the current message being displayed by animating it away. */ + @MainActor open func hide(animated: Bool = true) { hideCurrent(animated: animated) } @@ -470,6 +472,7 @@ open class SwiftMessages { Hide the current message, if there is one, by animating it away and clear the message queue. */ + @MainActor open func hideAll() { queue.removeAll() delays.removeAll() @@ -483,6 +486,7 @@ open class SwiftMessages { views, such as `MessageView`, that adopt the `Identifiable` protocol. - Parameter id: The identifier of the message to remove. */ + @MainActor open func hide(id: String) { if id == _current?.id { hideCurrent() @@ -497,6 +501,7 @@ open class SwiftMessages { given message ID are equal. This can be useful for messages that may be shown from multiple code paths to ensure that all paths are ready to hide. */ + @MainActor open func hideCounted(id: String) { if let count = counts[id] { if count < 2 { @@ -567,17 +572,19 @@ open class SwiftMessages { private var presenters = Set<Presenter>() } + @MainActor func show(presenter: Presenter) { enqueue(presenter: presenter) } fileprivate var queue: [Presenter] = [] + @MainActor fileprivate var delays = Delays() fileprivate var counts: [String : Int] = [:] fileprivate var _current: Presenter? = nil { didSet { if oldValue != nil { - Task { [weak self] in + Task { @MainActor [weak self] in try? await Task.sleep(seconds: self?.pauseBetweenMessages ?? 0) self?.dequeueNext() } @@ -585,6 +592,7 @@ open class SwiftMessages { } } + @MainActor fileprivate func enqueue(presenter: Presenter) { if presenter.config.ignoreDuplicates { counts[presenter.id] = (counts[presenter.id] ?? 0) + 1 @@ -611,6 +619,7 @@ open class SwiftMessages { } } + @MainActor fileprivate func dequeueNext() { guard queue.count > 0 else { return } if let _current, !_current.isOrphaned { return } @@ -637,6 +646,7 @@ open class SwiftMessages { } } + @MainActor fileprivate func internalHide(presenter: Presenter) { if presenter == _current { hideCurrent() @@ -646,6 +656,7 @@ open class SwiftMessages { } } + @MainActor fileprivate func hideCurrent(animated: Bool = true) { guard let current = _current, !current.isHiding else { return } let action = { [weak self] in @@ -665,6 +676,7 @@ open class SwiftMessages { fileprivate weak var autohideToken: Presenter? + @MainActor fileprivate func queueAutoHide() { guard let current = _current else { return } autohideToken = current @@ -707,6 +719,7 @@ extension SwiftMessages { - Parameter id: The id of a message that adopts `Identifiable`. - Returns: The view with matching id if currently being shown or hidden. */ + @MainActor public func current<T: UIView>(id: String) -> T? { _current?.id == id ? _current?.view as? T : nil } @@ -717,6 +730,7 @@ extension SwiftMessages { - Parameter id: The id of a message that adopts `Identifiable`. - Returns: The view with matching id if currently queued to be shown. */ + @MainActor public func queued<T: UIView>(id: String) -> T? { queue.first { $0.id == id }?.view as? T } @@ -728,6 +742,7 @@ extension SwiftMessages { - Parameter id: The id of a message that adopts `Identifiable`. - Returns: The view with matching id if currently queued to be shown. */ + @MainActor public func currentOrQueued<T: UIView>(id: String) -> T? { return current(id: id) ?? queued(id: id) } @@ -739,10 +754,12 @@ extension SwiftMessages { extension SwiftMessages: PresenterDelegate { + @MainActor func hide(presenter: Presenter) { self.internalHide(presenter: presenter) } + @MainActor public func hide(animator: Animator) { guard let presenter = self.presenter(forAnimator: animator) else { return } self.internalHide(presenter: presenter) @@ -752,6 +769,7 @@ extension SwiftMessages: PresenterDelegate { autohideToken = nil } + @MainActor public func panEnded(animator: Animator) { queueAutoHide() } @@ -879,26 +897,32 @@ extension SwiftMessages { globalInstance.show(config: config, viewProvider: viewProvider) } + @MainActor public static func show(view: UIView) { globalInstance.show(view: view) } + @MainActor public static func show(config: Config, view: UIView) { globalInstance.show(config: config, view: view) } + @MainActor public static func hide(animated: Bool = true) { globalInstance.hide(animated: animated) } + @MainActor public static func hideAll() { globalInstance.hideAll() } + @MainActor public static func hide(id: String) { globalInstance.hide(id: id) } + @MainActor public static func hideCounted(id: String) { globalInstance.hideCounted(id: id) } @@ -921,14 +945,17 @@ extension SwiftMessages { } } + @MainActor public static func current<T: UIView>(id: String) -> T? { return globalInstance.current(id: id) } + @MainActor public static func queued<T: UIView>(id: String) -> T? { return globalInstance.queued(id: id) } + @MainActor public static func currentOrQueued<T: UIView>(id: String) -> T? { return globalInstance.currentOrQueued(id: id) } From 66841d32bd727ce09d13a3b09ca27e3209f8001f Mon Sep 17 00:00:00 2001 From: Julien Di Marco <juliendimarco@gmail.com> Date: Sun, 23 Jun 2024 22:39:16 +0200 Subject: [PATCH 70/77] feat(TopBottomPresentable): Adds 'TopBottomPresentable' protocol, allow any Animator to be presented correctly by the `Presenter` (#548) --- CHANGELOG.md | 6 +++ SwiftMessages.podspec | 2 +- SwiftMessages.xcodeproj/project.pbxproj | 26 ++++++---- SwiftMessages/Animator.swift | 1 + SwiftMessages/Presenter.swift | 1 + .../SwiftMessages.Config+Extensions.swift | 2 +- SwiftMessages/SwiftMessages.swift | 7 +-- SwiftMessages/TopBottomAnimation.swift | 12 ++--- SwiftMessages/TopBottomAnimationStyle.swift | 12 +++++ SwiftMessages/TopBottomPresentable.swift | 49 +++++++++++++++++++ .../UIViewController+Extensions.swift | 14 ------ 11 files changed, 96 insertions(+), 36 deletions(-) create mode 100644 SwiftMessages/TopBottomAnimationStyle.swift create mode 100644 SwiftMessages/TopBottomPresentable.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 8316ae28..880e47be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change Log All notable changes to this project will be documented in this file. +## 10.0.1 + +## Features + +* Adds 'TopBottomPresentable' protocol to allow animators implementation to reuse 'top/bottom' integration in presentation + ## 10.0.0 ### Features diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 6d1a842d..0500d4ac 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '10.0.0' + spec.version = '10.0.1' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkickmobile.com' } diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 2ea0092a..066f5c75 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -10,6 +10,8 @@ 0797E40E26EE12B400691606 /* WindowScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0797E40D26EE12B400691606 /* WindowScene.swift */; }; 220655121FAF82B600F4E00F /* MarginAdjustable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */; }; 220D386E2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 220D386D2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift */; }; + 224C3C902C28A2F900B50B18 /* TopBottomPresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224C3C8F2C28A2F900B50B18 /* TopBottomPresentable.swift */; }; + 224C3C932C28BC4900B50B18 /* TopBottomAnimationStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224C3C922C28BC4400B50B18 /* TopBottomAnimationStyle.swift */; }; 224FB69921153B440081D4DE /* CALayer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224FB69821153B440081D4DE /* CALayer+Extensions.swift */; }; 225304622290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225304612290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift */; }; 225304662293000C00A03ACF /* KeyboardTrackingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225304652293000C00A03ACF /* KeyboardTrackingView.swift */; }; @@ -103,6 +105,8 @@ 0797E40D26EE12B400691606 /* WindowScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowScene.swift; sourceTree = "<group>"; }; 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarginAdjustable+Extensions.swift"; sourceTree = "<group>"; }; 220D386D2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftMessages.Config+Extensions.swift"; sourceTree = "<group>"; }; + 224C3C8F2C28A2F900B50B18 /* TopBottomPresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopBottomPresentable.swift; sourceTree = "<group>"; }; + 224C3C922C28BC4400B50B18 /* TopBottomAnimationStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopBottomAnimationStyle.swift; sourceTree = "<group>"; }; 224FB69821153B440081D4DE /* CALayer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CALayer+Extensions.swift"; sourceTree = "<group>"; }; 225304612290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraint+Extensions.swift"; sourceTree = "<group>"; }; 225304652293000C00A03ACF /* KeyboardTrackingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardTrackingView.swift; sourceTree = "<group>"; }; @@ -314,20 +318,22 @@ 864495571D4F7C490056EB2A /* Base */ = { isa = PBXGroup; children = ( - 86589D461D64B6E40041676C /* BaseView.swift */, - 86AAF82C1D580F410031EE32 /* Theme.swift */, - 8644955C1D4FAF7C0056EB2A /* WindowViewController.swift */, - 867BED201D622793005212E3 /* BackgroundViewable.swift */, - 864495551D4F7C390056EB2A /* Identifiable.swift */, - 86AAF81D1D5549680031EE32 /* MarginAdjustable.swift */, 22E307FE1E74C5B100E35893 /* AccessibleMessage.swift */, - 22982C162B6030B000852311 /* HapticMessage.swift */, - 86AAF82A1D580DD70031EE32 /* Error.swift */, 2298C2061EE480D000E2DDC1 /* Animator.swift */, - 2298C2041EE47DC900E2DDC1 /* Weak.swift */, + 867BED201D622793005212E3 /* BackgroundViewable.swift */, + 86589D461D64B6E40041676C /* BaseView.swift */, 22F27950210CE25900273E7F /* CornerRoundingView.swift */, + 86AAF82A1D580DD70031EE32 /* Error.swift */, + 22982C162B6030B000852311 /* HapticMessage.swift */, + 864495551D4F7C390056EB2A /* Identifiable.swift */, 225304652293000C00A03ACF /* KeyboardTrackingView.swift */, + 86AAF81D1D5549680031EE32 /* MarginAdjustable.swift */, + 86AAF82C1D580F410031EE32 /* Theme.swift */, + 224C3C922C28BC4400B50B18 /* TopBottomAnimationStyle.swift */, + 224C3C8F2C28A2F900B50B18 /* TopBottomPresentable.swift */, + 2298C2041EE47DC900E2DDC1 /* Weak.swift */, 0797E40D26EE12B400691606 /* WindowScene.swift */, + 8644955C1D4FAF7C0056EB2A /* WindowViewController.swift */, ); name = Base; sourceTree = "<group>"; @@ -568,6 +574,7 @@ 228F7DDF2ACF703A006C9644 /* SwiftMessageModifier.swift in Sources */, 224FB69921153B440081D4DE /* CALayer+Extensions.swift in Sources */, 22E01F641E74EC8B00ACE19A /* MaskingView.swift in Sources */, + 224C3C932C28BC4900B50B18 /* TopBottomAnimationStyle.swift in Sources */, 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */, 228F7DE02ACF703A006C9644 /* MessageViewConvertible.swift in Sources */, 86BBA9001D5E040600FE8F16 /* PassthroughView.swift in Sources */, @@ -578,6 +585,7 @@ 22E307FF1E74C5B100E35893 /* AccessibleMessage.swift in Sources */, 220D386E2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift in Sources */, 2270044B1FAFA6DD0045DDC3 /* PhysicsAnimation.swift in Sources */, + 224C3C902C28A2F900B50B18 /* TopBottomPresentable.swift in Sources */, 86BBA9041D5E040600FE8F16 /* NSBundle+Extensions.swift in Sources */, 86BBA8FD1D5E03F800FE8F16 /* SwiftMessages.swift in Sources */, 86BBA9021D5E040600FE8F16 /* WindowViewController.swift in Sources */, diff --git a/SwiftMessages/Animator.swift b/SwiftMessages/Animator.swift index 346ce2f8..c79d0f0e 100644 --- a/SwiftMessages/Animator.swift +++ b/SwiftMessages/Animator.swift @@ -10,6 +10,7 @@ import UIKit public typealias AnimationCompletion = (_ completed: Bool) -> Void +@MainActor public protocol AnimationDelegate: AnyObject { func hide(animator: Animator) func panStarted(animator: Animator) diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index e7f50493..667d1ebf 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -8,6 +8,7 @@ import UIKit +@MainActor protocol PresenterDelegate: AnimationDelegate { func hide(presenter: Presenter) } diff --git a/SwiftMessages/SwiftMessages.Config+Extensions.swift b/SwiftMessages/SwiftMessages.Config+Extensions.swift index ac0475da..a17a9f22 100644 --- a/SwiftMessages/SwiftMessages.Config+Extensions.swift +++ b/SwiftMessages/SwiftMessages.Config+Extensions.swift @@ -17,7 +17,7 @@ extension SwiftMessages.Config { } } - @available (iOS 13.0, *) + @available(iOS 13.0, *) var windowScene: UIWindowScene? { switch presentationContext { case .windowScene(let scene, _): return scene as? UIWindowScene diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index 5d96b3b0..315ff3ca 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -8,7 +8,6 @@ import UIKit -@MainActor private let globalInstance = SwiftMessages() /** @@ -774,6 +773,7 @@ extension SwiftMessages: PresenterDelegate { queueAutoHide() } + @MainActor private func presenter(forAnimator animator: Animator) -> Presenter? { if let current = _current, animator === current.animator { return current @@ -885,11 +885,12 @@ extension SwiftMessages { a set of static APIs that wrap calls to this instance. For example, `SwiftMessages.show()` is equivalent to `SwiftMessages.sharedInstance.show()`. */ + @MainActor public static var sharedInstance: SwiftMessages { return globalInstance } - - public static func show(viewProvider: @escaping ViewProvider) { + + nonisolated public static func show(viewProvider: @escaping ViewProvider) { globalInstance.show(viewProvider: viewProvider) } diff --git a/SwiftMessages/TopBottomAnimation.swift b/SwiftMessages/TopBottomAnimation.swift index a0d440c7..49a45adc 100644 --- a/SwiftMessages/TopBottomAnimation.swift +++ b/SwiftMessages/TopBottomAnimation.swift @@ -8,16 +8,12 @@ import UIKit +@MainActor public class TopBottomAnimation: NSObject, Animator { - public enum Style { - case top - case bottom - } - public weak var delegate: AnimationDelegate? - public let style: Style + public let style: TopBottomAnimationStyle public var showDuration: TimeInterval = 0.4 @@ -41,11 +37,11 @@ public class TopBottomAnimation: NSObject, Animator { weak var containerView: UIView? var context: AnimationContext? - public init(style: Style) { + public init(style: TopBottomAnimationStyle) { self.style = style } - init(style: Style, delegate: AnimationDelegate) { + init(style: TopBottomAnimationStyle, delegate: AnimationDelegate) { self.style = style self.delegate = delegate } diff --git a/SwiftMessages/TopBottomAnimationStyle.swift b/SwiftMessages/TopBottomAnimationStyle.swift new file mode 100644 index 00000000..626ad09c --- /dev/null +++ b/SwiftMessages/TopBottomAnimationStyle.swift @@ -0,0 +1,12 @@ +// +// TopBottomAnimationStyle.swift +// SwiftMessages +// +// Created by Timothy Moose on 6/23/24. +// Copyright © 2024 SwiftKick Mobile. All rights reserved. +// + +public enum TopBottomAnimationStyle { + case top + case bottom +} diff --git a/SwiftMessages/TopBottomPresentable.swift b/SwiftMessages/TopBottomPresentable.swift new file mode 100644 index 00000000..18804160 --- /dev/null +++ b/SwiftMessages/TopBottomPresentable.swift @@ -0,0 +1,49 @@ +// +// File.swift +// +// +// Created by Julien Di Marco on 23/04/2024. +// + +import Foundation + +// MARK: - TopBottom Presentable Definition + +@MainActor +protocol TopBottomPresentable { + var topBottomStyle: TopBottomAnimationStyle? { get } +} + +// MARK: - TopBottom Presentable Conformances + +extension TopBottomAnimation: TopBottomPresentable { + var topBottomStyle: TopBottomAnimationStyle? { return style } +} + +extension PhysicsAnimation: TopBottomPresentable { + var topBottomStyle: TopBottomAnimationStyle? { + switch placement { + case .top: return .top + case .bottom: return .bottom + default: return nil + } + } +} + +// MARK: - Presentation Style Convenience + +extension SwiftMessages.PresentationStyle { + /// A temporary workaround to allow custom presentation contexts using `TopBottomAnimation` + /// to display properly behind bars. THe long term solution is to refactor all of the + /// presentation context logic to work with safe area insets. + @MainActor + var topBottomStyle: TopBottomAnimationStyle? { + switch self { + case .top: return .top + case .bottom: return .bottom + case .custom(let animator as TopBottomPresentable): return animator.topBottomStyle + case .center: return nil + default: return nil + } + } +} diff --git a/SwiftMessages/UIViewController+Extensions.swift b/SwiftMessages/UIViewController+Extensions.swift index 7fbd4dd1..1400e03c 100644 --- a/SwiftMessages/UIViewController+Extensions.swift +++ b/SwiftMessages/UIViewController+Extensions.swift @@ -85,17 +85,3 @@ extension UIViewController { return true } } - -extension SwiftMessages.PresentationStyle { - /// A temporary workaround to allow custom presentation contexts using `TopBottomAnimation` - /// to display properly behind bars. THe long term solution is to refactor all of the - /// presentation context logic to work with safe area insets. - var topBottomStyle: TopBottomAnimation.Style? { - switch self { - case .top: return .top - case .bottom: return .bottom - case .custom(let animator): return (animator as? TopBottomAnimation)?.style - case .center: return nil - } - } -} From 8b9bc1ce25d11a83e7999aa74c4ebcda47596e63 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Fri, 2 Aug 2024 15:07:52 -0500 Subject: [PATCH 71/77] Make SwiftMessages initializer nonisolated --- SwiftMessages/SwiftMessages.swift | 44 +++++-------------------------- 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index 315ff3ca..0280bbe1 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -15,6 +15,7 @@ private let globalInstance = SwiftMessages() It behaves like a queue, only showing one message at a time. Message views that adopt the `Identifiable` protocol (as `MessageView` does) will have duplicates removed. */ +@MainActor open class SwiftMessages { /** @@ -164,7 +165,6 @@ open class SwiftMessages { case error } - /** Specifies options for dimming the background behind the message view similar to a popover view controller. @@ -398,15 +398,14 @@ open class SwiftMessages { /** Not much to say here. */ - public init() {} - + nonisolated public init() {} + /** Adds the given configuration and view to the message queue to be displayed. - Parameter config: The configuration options. - Parameter view: The view to be displayed. */ - @MainActor open func show(config: Config, view: UIView) { let presenter = Presenter(config: config, view: view, delegate: self) enqueue(presenter: presenter) @@ -419,7 +418,6 @@ open class SwiftMessages { - Parameter config: The configuration options. - Parameter view: The view to be displayed. */ - @MainActor public func show(view: UIView) { show(config: defaultConfig, view: view) } @@ -462,7 +460,6 @@ open class SwiftMessages { /** Hide the current message being displayed by animating it away. */ - @MainActor open func hide(animated: Bool = true) { hideCurrent(animated: animated) } @@ -471,7 +468,6 @@ open class SwiftMessages { Hide the current message, if there is one, by animating it away and clear the message queue. */ - @MainActor open func hideAll() { queue.removeAll() delays.removeAll() @@ -485,7 +481,6 @@ open class SwiftMessages { views, such as `MessageView`, that adopt the `Identifiable` protocol. - Parameter id: The identifier of the message to remove. */ - @MainActor open func hide(id: String) { if id == _current?.id { hideCurrent() @@ -500,7 +495,6 @@ open class SwiftMessages { given message ID are equal. This can be useful for messages that may be shown from multiple code paths to ensure that all paths are ready to hide. */ - @MainActor open func hideCounted(id: String) { if let count = counts[id] { if count < 2 { @@ -571,19 +565,17 @@ open class SwiftMessages { private var presenters = Set<Presenter>() } - @MainActor func show(presenter: Presenter) { enqueue(presenter: presenter) } fileprivate var queue: [Presenter] = [] - @MainActor fileprivate var delays = Delays() fileprivate var counts: [String : Int] = [:] fileprivate var _current: Presenter? = nil { didSet { if oldValue != nil { - Task { @MainActor [weak self] in + Task { [weak self] in try? await Task.sleep(seconds: self?.pauseBetweenMessages ?? 0) self?.dequeueNext() } @@ -591,7 +583,6 @@ open class SwiftMessages { } } - @MainActor fileprivate func enqueue(presenter: Presenter) { if presenter.config.ignoreDuplicates { counts[presenter.id] = (counts[presenter.id] ?? 0) + 1 @@ -618,7 +609,6 @@ open class SwiftMessages { } } - @MainActor fileprivate func dequeueNext() { guard queue.count > 0 else { return } if let _current, !_current.isOrphaned { return } @@ -645,7 +635,6 @@ open class SwiftMessages { } } - @MainActor fileprivate func internalHide(presenter: Presenter) { if presenter == _current { hideCurrent() @@ -655,7 +644,6 @@ open class SwiftMessages { } } - @MainActor fileprivate func hideCurrent(animated: Bool = true) { guard let current = _current, !current.isHiding else { return } let action = { [weak self] in @@ -675,7 +663,6 @@ open class SwiftMessages { fileprivate weak var autohideToken: Presenter? - @MainActor fileprivate func queueAutoHide() { guard let current = _current else { return } autohideToken = current @@ -718,7 +705,6 @@ extension SwiftMessages { - Parameter id: The id of a message that adopts `Identifiable`. - Returns: The view with matching id if currently being shown or hidden. */ - @MainActor public func current<T: UIView>(id: String) -> T? { _current?.id == id ? _current?.view as? T : nil } @@ -729,7 +715,6 @@ extension SwiftMessages { - Parameter id: The id of a message that adopts `Identifiable`. - Returns: The view with matching id if currently queued to be shown. */ - @MainActor public func queued<T: UIView>(id: String) -> T? { queue.first { $0.id == id }?.view as? T } @@ -741,7 +726,6 @@ extension SwiftMessages { - Parameter id: The id of a message that adopts `Identifiable`. - Returns: The view with matching id if currently queued to be shown. */ - @MainActor public func currentOrQueued<T: UIView>(id: String) -> T? { return current(id: id) ?? queued(id: id) } @@ -753,12 +737,10 @@ extension SwiftMessages { extension SwiftMessages: PresenterDelegate { - @MainActor func hide(presenter: Presenter) { self.internalHide(presenter: presenter) } - @MainActor public func hide(animator: Animator) { guard let presenter = self.presenter(forAnimator: animator) else { return } self.internalHide(presenter: presenter) @@ -768,12 +750,10 @@ extension SwiftMessages: PresenterDelegate { autohideToken = nil } - @MainActor public func panEnded(animator: Animator) { queueAutoHide() } - @MainActor private func presenter(forAnimator animator: Animator) -> Presenter? { if let current = _current, animator === current.animator { return current @@ -885,45 +865,38 @@ extension SwiftMessages { a set of static APIs that wrap calls to this instance. For example, `SwiftMessages.show()` is equivalent to `SwiftMessages.sharedInstance.show()`. */ - @MainActor - public static var sharedInstance: SwiftMessages { + nonisolated public static var sharedInstance: SwiftMessages { return globalInstance } - nonisolated public static func show(viewProvider: @escaping ViewProvider) { + public static func show(viewProvider: @escaping ViewProvider) { globalInstance.show(viewProvider: viewProvider) } - nonisolated public static func show(config: Config, viewProvider: @escaping ViewProvider) { + public static func show(config: Config, viewProvider: @escaping ViewProvider) { globalInstance.show(config: config, viewProvider: viewProvider) } - @MainActor public static func show(view: UIView) { globalInstance.show(view: view) } - @MainActor public static func show(config: Config, view: UIView) { globalInstance.show(config: config, view: view) } - @MainActor public static func hide(animated: Bool = true) { globalInstance.hide(animated: animated) } - @MainActor public static func hideAll() { globalInstance.hideAll() } - @MainActor public static func hide(id: String) { globalInstance.hide(id: id) } - @MainActor public static func hideCounted(id: String) { globalInstance.hideCounted(id: id) } @@ -946,17 +919,14 @@ extension SwiftMessages { } } - @MainActor public static func current<T: UIView>(id: String) -> T? { return globalInstance.current(id: id) } - @MainActor public static func queued<T: UIView>(id: String) -> T? { return globalInstance.queued(id: id) } - @MainActor public static func currentOrQueued<T: UIView>(id: String) -> T? { return globalInstance.currentOrQueued(id: id) } From b3bccca835fa3533b6789c0af34d5b46454133dc Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Fri, 2 Aug 2024 18:46:36 -0500 Subject: [PATCH 72/77] Fix broken SwiftUI touch handling in iOS 18 --- SwiftMessages/MessageHostingView.swift | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/SwiftMessages/MessageHostingView.swift b/SwiftMessages/MessageHostingView.swift index b4634d9b..f0aaecd0 100644 --- a/SwiftMessages/MessageHostingView.swift +++ b/SwiftMessages/MessageHostingView.swift @@ -44,10 +44,25 @@ public class MessageHostingView<Content>: UIView, Identifiable where Content: Vi } public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - let view = super.hitTest(point, with: event) - // The rendered SwiftUI view isn't a direct child of this hosting view. SwiftUI - // inserts another intermediate view that should also ignore touches. - if view == self || view?.superview == self { return nil } + guard let view = super.hitTest(point, with: event) else { return nil } + // Touches should pass through unless they land on a view that is rendering a SwiftUI element. + if view == self { return nil } + // In iOS 18 beta, the hit testing behavior changed in a weird way: when a SwiftUI element is tapped, + // the first hit test returns the view that renders the SwiftUI element. However, a second identical hit + // test is performed(!) and on the second test, the `UIHostingController`'s view is returned. We want touches + // to pass through that view. In iOS 17, we would just return `nil` in that case. However, in iOS 18, the + // second hit test is actuall essential to touches being delivered to the SwiftUI elements. The new approach + // is to iterate overall all of the subviews, which are all presumably rendering SwiftUI elements, and + // only return `nil` if the point is not inside any of these subviews. + if view.superview == self { + for subview in view.subviews { + let subviewPoint = self.convert(point, to: subview) + if subview.point(inside: subviewPoint, with: event) { + return view + } + } + return nil + } return view } From 5500236e0942febd2ba865a72c73af9c48633eb3 Mon Sep 17 00:00:00 2001 From: "linpeng.dev" <540933120@qq.com> Date: Mon, 12 Aug 2024 22:03:53 +0800 Subject: [PATCH 73/77] SwiftMessages.Config expands the popupPriority property to support the popup queue to accurately control the display order according to the weight (#555) --- SwiftMessages/Presenter.swift | 2 +- SwiftMessages/SwiftMessages.swift | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index 667d1ebf..2010f22b 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -15,7 +15,7 @@ protocol PresenterDelegate: AnimationDelegate { @MainActor class Presenter: NSObject { - + // MARK: - API init(config: SwiftMessages.Config, view: UIView, delegate: PresenterDelegate) { diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index 0280bbe1..71709659 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -393,6 +393,11 @@ open class SwiftMessages { Supply an instance of `KeyboardTrackingView` to have the message view avoid the keyboard. */ public var keyboardTrackingView: KeyboardTrackingView? + + /** + Specify a positive or negative priority to influence the position of a message in the queue based on it's relative priority. + */ + public var priority: Int = 0 } /** @@ -612,6 +617,17 @@ open class SwiftMessages { fileprivate func dequeueNext() { guard queue.count > 0 else { return } if let _current, !_current.isOrphaned { return } + // Sort by priority + queue = queue.enumerated().sorted { left, right in + // The priority is sorted first + let leftPriority = left.element.config.priority + let rightPriority = right.element.config.priority + if leftPriority != rightPriority { + return leftPriority > rightPriority + } + // The same priority is sorted in queue order + return left.offset < right.offset + }.map { $0.element } let current = queue.removeFirst() self._current = current // Set `autohideToken` before the animation starts in case From 438a2740988e82b55d4a1bf4532a566d7923036e Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Mon, 12 Aug 2024 16:57:37 -0500 Subject: [PATCH 74/77] SwiftUI layout improvement (#560) --- SwiftMessages.xcodeproj/project.pbxproj | 8 +- SwiftMessages/MessageGeometryProxy.swift | 17 + SwiftMessages/MessageHostingView.swift | 43 +- SwiftMessages/PhysicsAnimation.swift | 58 +- SwiftMessages/SwiftMessageModifier.swift | 49 +- iMessageDemo/Podfile.lock | 6 +- .../Local Podspecs/SwiftMessages.podspec.json | 8 +- iMessageDemo/Pods/Manifest.lock | 6 +- .../Pods/Pods.xcodeproj/project.pbxproj | 1242 +++++++++-------- .../Pods-iMessageDemo-Info.plist | 2 +- .../Pods-iMessageDemo-frameworks.sh | 5 +- .../Pods-iMessageDemo.debug.xcconfig | 3 +- .../Pods-iMessageDemo.release.xcconfig | 3 +- .../Pods-iMessageExtensionDemo-Info.plist | 2 +- .../Pods-iMessageExtensionDemo.debug.xcconfig | 3 +- ...ods-iMessageExtensionDemo.release.xcconfig | 3 +- ...ges_SwiftMessages-SwiftMessages-Info.plist | 4 +- .../SwiftMessages/SwiftMessages-Info.plist | 4 +- .../SwiftMessages.debug.xcconfig | 2 + .../SwiftMessages.release.xcconfig | 2 + .../iMessageDemo.xcodeproj/project.pbxproj | 7 +- 21 files changed, 825 insertions(+), 652 deletions(-) create mode 100644 SwiftMessages/MessageGeometryProxy.swift diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index 066f5c75..10384827 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 0797E40E26EE12B400691606 /* WindowScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0797E40D26EE12B400691606 /* WindowScene.swift */; }; 220655121FAF82B600F4E00F /* MarginAdjustable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */; }; 220D386E2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 220D386D2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift */; }; + 223DE69D2C29E50C000161E5 /* MessageGeometryProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 223DE69C2C29E50B000161E5 /* MessageGeometryProxy.swift */; }; 224C3C902C28A2F900B50B18 /* TopBottomPresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224C3C8F2C28A2F900B50B18 /* TopBottomPresentable.swift */; }; 224C3C932C28BC4900B50B18 /* TopBottomAnimationStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224C3C922C28BC4400B50B18 /* TopBottomAnimationStyle.swift */; }; 224FB69921153B440081D4DE /* CALayer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224FB69821153B440081D4DE /* CALayer+Extensions.swift */; }; @@ -105,6 +106,7 @@ 0797E40D26EE12B400691606 /* WindowScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowScene.swift; sourceTree = "<group>"; }; 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarginAdjustable+Extensions.swift"; sourceTree = "<group>"; }; 220D386D2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftMessages.Config+Extensions.swift"; sourceTree = "<group>"; }; + 223DE69C2C29E50B000161E5 /* MessageGeometryProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageGeometryProxy.swift; sourceTree = "<group>"; }; 224C3C8F2C28A2F900B50B18 /* TopBottomPresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopBottomPresentable.swift; sourceTree = "<group>"; }; 224C3C922C28BC4400B50B18 /* TopBottomAnimationStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopBottomAnimationStyle.swift; sourceTree = "<group>"; }; 224FB69821153B440081D4DE /* CALayer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CALayer+Extensions.swift"; sourceTree = "<group>"; }; @@ -253,8 +255,10 @@ 228F7DDA2ACF7029006C9644 /* SwiftUI */ = { isa = PBXGroup; children = ( - 228F7DDC2ACF703A006C9644 /* SwiftMessageModifier.swift */, + 223DE69C2C29E50B000161E5 /* MessageGeometryProxy.swift */, + 228F7DDB2ACF7039006C9644 /* MessageHostingView.swift */, 228F7DDD2ACF703A006C9644 /* MessageViewConvertible.swift */, + 228F7DDC2ACF703A006C9644 /* SwiftMessageModifier.swift */, ); name = SwiftUI; sourceTree = "<group>"; @@ -366,7 +370,6 @@ 86AAF8171D54F0650031EE32 /* PassthroughView.swift */, 22E01F631E74EC8B00ACE19A /* MaskingView.swift */, 86AAF8191D54F0850031EE32 /* PassthroughWindow.swift */, - 228F7DDB2ACF7039006C9644 /* MessageHostingView.swift */, 220D38672597A94C00BB2B88 /* Extensions */, ); name = Internal; @@ -597,6 +600,7 @@ 86589D471D64B6E40041676C /* BaseView.swift in Sources */, 0797E40E26EE12B400691606 /* WindowScene.swift in Sources */, 225304622290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift in Sources */, + 223DE69D2C29E50C000161E5 /* MessageGeometryProxy.swift in Sources */, 86BBA9071D5E040C00FE8F16 /* MarginAdjustable.swift in Sources */, 867BED211D622793005212E3 /* BackgroundViewable.swift in Sources */, ); diff --git a/SwiftMessages/MessageGeometryProxy.swift b/SwiftMessages/MessageGeometryProxy.swift new file mode 100644 index 00000000..73d2d785 --- /dev/null +++ b/SwiftMessages/MessageGeometryProxy.swift @@ -0,0 +1,17 @@ +// +// MessageGeometryProxy.swift +// SwiftMessages +// +// Created by Timothy Moose on 6/24/24. +// Copyright © 2024 SwiftKick Mobile. All rights reserved. +// + +import SwiftUI + +/// A data type that mimicks `GeomtryProxy` and is used with `swiftMessage()` modifier when the geomtry metrics of the container view +/// are needed, particularly because `GeometryReader` doesn't work inside the view builder due to the way the message view is being +/// displayed from UIKit. +public struct MessageGeometryProxy { + public var size: CGSize + public var safeAreaInsets: EdgeInsets +} diff --git a/SwiftMessages/MessageHostingView.swift b/SwiftMessages/MessageHostingView.swift index f0aaecd0..4301090e 100644 --- a/SwiftMessages/MessageHostingView.swift +++ b/SwiftMessages/MessageHostingView.swift @@ -17,13 +17,20 @@ public class MessageHostingView<Content>: UIView, Identifiable where Content: Vi public let id: String public init(id: String, content: Content) { - hostVC = UIHostingController(rootView: content) self.id = id + self.content = { _ in content } + super.init(frame: .zero) + backgroundColor = .clear + } + + public init<Message>( + message: Message, + @ViewBuilder content: @escaping (Message, MessageGeometryProxy) -> Content + ) where Message: Identifiable { + self.id = message.id + self.content = { geom in content(message, geom) } super.init(frame: .zero) - hostVC.loadViewIfNeeded() - installContentView(hostVC.view) backgroundColor = .clear - hostVC.view.backgroundColor = .clear } convenience public init<Message>(message: Message) where Message: MessageViewConvertible, Message.Content == Content { @@ -34,7 +41,8 @@ public class MessageHostingView<Content>: UIView, Identifiable where Content: Vi // MARK: - Variables - private let hostVC: UIHostingController<Content> + private var hostVC: UIHostingController<Content>? + private let content: (MessageGeometryProxy) -> Content // MARK: - Lifecycle @@ -66,6 +74,31 @@ public class MessageHostingView<Content>: UIView, Identifiable where Content: Vi return view } + public override func didMoveToSuperview() { + guard let superview = self.superview else { return } + let size = superview.bounds.size + let insets = superview.safeAreaInsets + let ltr = superview.effectiveUserInterfaceLayoutDirection == .leftToRight + let proxy = MessageGeometryProxy( + size: CGSize( + width: size.width - insets.left - insets.right, + height: size.height - insets.top - insets.bottom + ), + safeAreaInsets: EdgeInsets( + top: insets.top, + leading: ltr ? insets.left : insets.right, + bottom: insets.bottom, + trailing: ltr ? insets.right : insets.left + ) + ) + let hostVC = UIHostingController(rootView: content(proxy)) + self.hostVC = hostVC + hostVC.loadViewIfNeeded() + installContentView(hostVC.view) + hostVC.view.backgroundColor = .clear + + } + // MARK: - Configuration private func installContentView(_ contentView: UIView) { diff --git a/SwiftMessages/PhysicsAnimation.swift b/SwiftMessages/PhysicsAnimation.swift index 5f5ecaf0..ef8476f7 100644 --- a/SwiftMessages/PhysicsAnimation.swift +++ b/SwiftMessages/PhysicsAnimation.swift @@ -37,7 +37,12 @@ public class PhysicsAnimation: NSObject, Animator { } public func show(context: AnimationContext, completion: @escaping AnimationCompletion) { - NotificationCenter.default.addObserver(self, selector: #selector(adjustMargins), name: UIDevice.orientationDidChangeNotification, object: nil) + NotificationCenter.default.addObserver( + self, + selector: #selector(adjustMargins), + name: UIDevice.orientationDidChangeNotification, + object: nil + ) install(context: context) showAnimation(context: context, completion: completion) } @@ -56,12 +61,24 @@ public class PhysicsAnimation: NSObject, Animator { view.transform = CGAffineTransform.identity completion(true) } - UIView.animate(withDuration: hideDuration, delay: 0, options: [.beginFromCurrentState, .curveEaseIn, .allowUserInteraction], animations: { - view.transform = CGAffineTransform(scaleX: 0.8, y: 0.8) - }, completion: nil) - UIView.animate(withDuration: hideDuration, delay: 0, options: [.beginFromCurrentState, .curveEaseIn, .allowUserInteraction], animations: { - view.alpha = 0 - }, completion: nil) + UIView.animate( + withDuration: hideDuration, + delay: 0, + options: [.beginFromCurrentState, .curveEaseIn, .allowUserInteraction], + animations: { + view.transform = CGAffineTransform(scaleX: 0.8, y: 0.8) + }, + completion: nil + ) + UIView.animate( + withDuration: hideDuration, + delay: 0, + options: [.beginFromCurrentState, .curveEaseIn, .allowUserInteraction], + animations: { + view.alpha = 0 + }, + completion: nil + ) CATransaction.commit() } @@ -75,14 +92,31 @@ public class PhysicsAnimation: NSObject, Animator { container.addSubview(view) switch placement { case .center: - view.centerYAnchor.constraint(equalTo: container.centerYAnchor).with(priority: UILayoutPriority(200)).isActive = true + view.centerYAnchor.constraint( + equalTo: container.centerYAnchor + ) + .with(priority: UILayoutPriority(200)) + .isActive = true case .top: - view.topAnchor.constraint(equalTo: container.topAnchor).with(priority: UILayoutPriority(200)).isActive = true + view.topAnchor.constraint( + equalTo: container.topAnchor + ) + .with(priority: UILayoutPriority(200)) + .isActive = true case .bottom: - view.bottomAnchor.constraint(equalTo: container.bottomAnchor).with(priority: UILayoutPriority(200)).isActive = true + view.bottomAnchor.constraint( + equalTo: container.bottomAnchor + ) + .with(priority: UILayoutPriority(200)) + .isActive = true } - NSLayoutConstraint(item: view, attribute: .leading, relatedBy: .equal, toItem: container, attribute: .leading, multiplier: 1, constant: 0).isActive = true - NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: container, attribute: .trailing, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint.activate([ + view.leadingAnchor.constraint(equalTo: container.leadingAnchor), + view.trailingAnchor.constraint(equalTo: container.trailingAnchor), + // Don't allow the message to spill outside of the top or bottom of the container. + view.topAnchor.constraint(greaterThanOrEqualTo: container.topAnchor), + view.bottomAnchor.constraint(lessThanOrEqualTo: container.bottomAnchor), + ]) // Important to layout now in order to get the right safe area insets container.layoutIfNeeded() adjustMargins() diff --git a/SwiftMessages/SwiftMessageModifier.swift b/SwiftMessages/SwiftMessageModifier.swift index 3cab4983..e44d6871 100644 --- a/SwiftMessages/SwiftMessageModifier.swift +++ b/SwiftMessages/SwiftMessageModifier.swift @@ -9,15 +9,36 @@ import SwiftUI @available(iOS 14.0, *) public extension View { - /// A state-based modifier for displaying a message when `Message` does not conform to `MessageViewConvertible`. This variant is more flexible and - /// should be used if the message view can't be represented as pure data, such as if it requires a delegate, has callbacks, etc. + /// A view modifier for displaying a message using similar semantics to the `.sheet()` modifier. func swiftMessage<Message, MessageContent>( message: Binding<Message?>, config: SwiftMessages.Config? = nil, swiftMessages: SwiftMessages? = nil, @ViewBuilder messageContent: @escaping (Message) -> MessageContent ) -> some View where Message: Equatable & Identifiable, MessageContent: View { - modifier(SwiftMessageModifier(message: message, config: config, swiftMessages: swiftMessages, messageContent: messageContent)) + swiftMessage(message: message, config: config, swiftMessages: swiftMessages) { message, _ in + messageContent(message) + } + } + + /// A view modifier for displaying a message using similar semantics to the `.sheet()` modifier. This variant provides a + /// `SwiftMessageGeometryProxy`. The proxy is useful when one needs to know the geometry metrics of the container view, + /// particularly because `GeometryReader` doesn't work inside the view builder due to the way the message view is being + /// displayed from UIKit. + func swiftMessage<Message, MessageContent>( + message: Binding<Message?>, + config: SwiftMessages.Config? = nil, + swiftMessages: SwiftMessages? = nil, + @ViewBuilder messageContent: @escaping (Message, MessageGeometryProxy) -> MessageContent + ) -> some View where Message: Equatable & Identifiable, MessageContent: View { + modifier( + SwiftMessageModifier( + message: message, + config: config, + swiftMessages: swiftMessages, + messageContent: messageContent + ) + ) } /// A state-based modifier for displaying a message when `Message` conforms to `MessageViewConvertible`. This variant should be used if the message @@ -43,6 +64,20 @@ private struct SwiftMessageModifier<Message, MessageContent>: ViewModifier where config: SwiftMessages.Config? = nil, swiftMessages: SwiftMessages? = nil, @ViewBuilder messageContent: @escaping (Message) -> MessageContent + ) { + _message = message + self.config = config + self.swiftMessages = swiftMessages + self.messageContent = { message, _ in + messageContent(message) + } + } + + fileprivate init( + message: Binding<Message?>, + config: SwiftMessages.Config? = nil, + swiftMessages: SwiftMessages? = nil, + @ViewBuilder messageContent: @escaping (Message, MessageGeometryProxy) -> MessageContent ) { _message = message self.config = config @@ -58,7 +93,9 @@ private struct SwiftMessageModifier<Message, MessageContent>: ViewModifier where _message = message self.config = config self.swiftMessages = swiftMessages - self.messageContent = { $0.asMessageView() } + self.messageContent = { message, _ in + message.asMessageView() + } } // MARK: - Constants @@ -68,7 +105,7 @@ private struct SwiftMessageModifier<Message, MessageContent>: ViewModifier where @Binding private var message: Message? private let config: SwiftMessages.Config? private let swiftMessages: SwiftMessages? - @ViewBuilder private let messageContent: (Message) -> MessageContent + @ViewBuilder private let messageContent: (Message, MessageGeometryProxy) -> MessageContent // MARK: - Body @@ -79,7 +116,7 @@ private struct SwiftMessageModifier<Message, MessageContent>: ViewModifier where let hideAll: @MainActor () -> Void = swiftMessages?.hideAll ?? SwiftMessages.hideAll switch message { case let message?: - let view = MessageHostingView(id: message.id, content: messageContent(message)) + let view = MessageHostingView(message: message, content: messageContent) var config = config ?? swiftMessages?.defaultConfig ?? SwiftMessages.defaultConfig config.eventListeners.append { event in if case .didHide = event, event.id == self.message?.id { diff --git a/iMessageDemo/Podfile.lock b/iMessageDemo/Podfile.lock index 7162a91f..400dd99d 100644 --- a/iMessageDemo/Podfile.lock +++ b/iMessageDemo/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - SwiftMessages/AppExtension (9.0.3) + - SwiftMessages/AppExtension (10.0.1) DEPENDENCIES: - SwiftMessages/AppExtension (from `../`) @@ -9,8 +9,8 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - SwiftMessages: 077f19126c24033fe24042237ecc20261adb46e4 + SwiftMessages: 759b4a0bf5c3a116a0d7e8a34b098ba83c458625 PODFILE CHECKSUM: 2eb9a33592d0c52131c37a9dd169a8c4604ffd7b -COCOAPODS: 1.10.1 +COCOAPODS: 1.15.2 diff --git a/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json b/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json index 6d9e93c9..a117b2dd 100644 --- a/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json +++ b/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json @@ -1,20 +1,20 @@ { "name": "SwiftMessages", - "version": "9.0.3", + "version": "10.0.1", "license": { "type": "MIT" }, "homepage": "https://github.com/SwiftKickMobile/SwiftMessages", "authors": { - "Timothy Moose": "tim@swiftkick.it" + "Timothy Moose": "tim@swiftkickmobile.com" }, "summary": "A very flexible message bar for iOS written in Swift.", "source": { "git": "https://github.com/SwiftKickMobile/SwiftMessages.git", - "tag": "9.0.3" + "tag": "10.0.1" }, "platforms": { - "ios": "9.0" + "ios": "13.0" }, "swift_versions": "5.0", "frameworks": "UIKit", diff --git a/iMessageDemo/Pods/Manifest.lock b/iMessageDemo/Pods/Manifest.lock index 7162a91f..400dd99d 100644 --- a/iMessageDemo/Pods/Manifest.lock +++ b/iMessageDemo/Pods/Manifest.lock @@ -1,5 +1,5 @@ PODS: - - SwiftMessages/AppExtension (9.0.3) + - SwiftMessages/AppExtension (10.0.1) DEPENDENCIES: - SwiftMessages/AppExtension (from `../`) @@ -9,8 +9,8 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - SwiftMessages: 077f19126c24033fe24042237ecc20261adb46e4 + SwiftMessages: 759b4a0bf5c3a116a0d7e8a34b098ba83c458625 PODFILE CHECKSUM: 2eb9a33592d0c52131c37a9dd169a8c4604ffd7b -COCOAPODS: 1.10.1 +COCOAPODS: 1.15.2 diff --git a/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj b/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj index 0d6bbc21..cf4122eb 100644 --- a/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj +++ b/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj @@ -3,111 +3,119 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ - 00764FFD14D83F4ABEC0D4D53D48080A /* SwiftMessages-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C6E00017F9E79F6D4926E9CB43A66DF /* SwiftMessages-dummy.m */; }; - 02905CCF79B22A773CD0BA32EDB9648A /* AccessibleMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0201BC51C7CA061016B619400691A139 /* AccessibleMessage.swift */; }; - 05D9CBEC9488BAA2962B174703D25218 /* PassthroughWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A331C2E0BE2AE2118D65AA1F12519F2 /* PassthroughWindow.swift */; }; - 0C55441C4B8356AC1244EED7684E1783 /* MaskingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D69BE188B82D84ED23AC4E27BAB61D /* MaskingView.swift */; }; - 11DE7052A0A78D6E27D8D129D413DAF6 /* errorIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 7100245A2722BD53D5B3927ED649069F /* errorIconLight.png */; }; - 13620BA62A66C8C6F9345341BCD111ED /* KeyboardTrackingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90AC342C6F09BF7715D4FB95512DD68A /* KeyboardTrackingView.swift */; }; - 1662CF43016AFC375200E466F130D90E /* warningIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 860D833A7A1B108A89ED34AD74778AC0 /* warningIconSubtle.png */; }; - 28F2E02536C48A4B661D6D8AAFB5D37E /* CornerRoundingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 007ACA6F89C6C856F78352A086F3B8EA /* CornerRoundingView.swift */; }; - 30D023ABC2D1CFC829CF04360768B7F8 /* StatusLine.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1E2FE4DB6869F330F19A3A5459AAFFFB /* StatusLine.xib */; }; - 34CB62900FA4AAC84745C7E958657648 /* errorIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D30B2BF71F9D2C63C2D202C99827CDC1 /* errorIconLight@2x.png */; }; - 3A8B97D9210D1E2BEED5E1159BE7E748 /* warningIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = C56AB83FDAB8D6A1328E7EECCAD99A69 /* warningIconLight.png */; }; - 3BFC9F0FAF0757A2D3574ED4E4100D57 /* CALayer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 467EAD44C7F625F384822180F004E64F /* CALayer+Extensions.swift */; }; - 4256FC87C833154DCDEE84CD98F910D7 /* Identifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFD31968BF9DF7A9E25A136DF254F3A9 /* Identifiable.swift */; }; - 46CCA4DDFDBBDD2A9426BB96C08E4255 /* Pods-iMessageExtensionDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F40CA14AD738DD186B4DA8FD14AE5BD /* Pods-iMessageExtensionDemo-dummy.m */; }; - 47F1E9964F1112D0E8F0FF8C25204E2F /* SwiftMessages_SwiftMessages.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages_SwiftMessages.bundle */; }; - 4889E21A2024267A944084FB851200B5 /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7EE64CFE0084CF5213A03AF29A668ED /* BaseView.swift */; }; - 4B907B48F27F55DF65CC1553C7C26942 /* infoIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 730840765E737D45772EBE66DB8A6D2E /* infoIconLight.png */; }; - 4B9459A11E2A1D65AE3224CF468AE8CA /* warningIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7C4DF53A4B44C246968618BF25962786 /* warningIconLight@3x.png */; }; - 4E82DE4069FECF20D0E29CB06A0FCFB6 /* SwiftMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC6264350B8D100D5B5C5EEEC316933D /* SwiftMessages.swift */; }; - 531825CE7041C5C1BA684BDA9C8972A3 /* UIEdgeInsets+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36F7B24601DF4C00B14EC8CE2D4A48DC /* UIEdgeInsets+Extensions.swift */; }; - 560A2B1056FEFE42AC6524A2A1742CA2 /* Pods-iMessageExtensionDemo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CAB201AD00CAB811B045E2FFB5C03A8 /* Pods-iMessageExtensionDemo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 56F9865D99C4FADB8FC83CA548F82110 /* successIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 17ADABD24F805C5F7FF62167E7ABEF0A /* successIconSubtle@3x.png */; }; - 5B9F8D117AF7BEDDB511EF475FA25995 /* infoIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 48DC3BADDA3A20F2AEB8585117DAFA0D /* infoIcon@3x.png */; }; - 5CA294C8D3BBC986CF0703D4E2A28687 /* SwiftMessages.Config+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A16E25077F8D76288BE678E6AC1C884 /* SwiftMessages.Config+Extensions.swift */; }; - 61548914728141D77F87E31B3911CE7E /* successIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 91D9224F29E092950BADC27C979E10CC /* successIconSubtle@2x.png */; }; - 62B05E0AC13A614A2F8D8A1BE9B514B3 /* infoIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = F9CDB54E629D60FF881DF27B949F4C2D /* infoIconSubtle.png */; }; - 632538BAE98BBFD6CED58844B7611C24 /* MarginAdjustable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C8214A441D845A4A4DD6570FD5D458F /* MarginAdjustable+Extensions.swift */; }; - 6685298EC64F73060F5DB1A841375069 /* warningIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8AD355ED684A939F2A4E333F95E8AC31 /* warningIconSubtle@2x.png */; }; - 668EDAB86421216BEF7D3F932851A834 /* errorIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 468D9889455DE51BD5BBC2360BDBB877 /* errorIconSubtle@2x.png */; }; - 6A933CC66558A1FB0AB0BC76F9807E71 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF65ECDAFAD03A79B5571C6F66D8F35 /* TopBottomAnimation.swift */; }; - 755898E0E511FC5AE881403BEF2A02FC /* successIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D032FCFAE6607CF878AA2F35EF93146C /* successIcon@3x.png */; }; - 7905F28CF56E06626475EBA3EB73D905 /* MarginAdjustable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68834C60D0C5EA751E9F12E427C5FFE /* MarginAdjustable.swift */; }; - 7B352022AFCAA5C364E1E2F61290628E /* MessageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B8A4CCB4B08D2D3BE586212AB4167DC2 /* MessageView.xib */; }; - 7BC52E6F0D9D19B05E62E623E53FCE82 /* Pods-iMessageDemo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D0ECE831FB5E0EE1D68E837671320C7 /* Pods-iMessageDemo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 80DE92140CF5AFB5224643FA952EFDEA /* successIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 52F1CA85E0EED7D94FE0036BC92EB3EC /* successIconLight.png */; }; - 8F1BAB73C85D58C56F55E91573C2E7EF /* infoIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = E41BFEB1BFF85793C0DB85F95184B752 /* infoIcon.png */; }; - 926907C8DCE76101AF5CB470DB7797D7 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88D73E42D996B226222A4EBA46F7DC6D /* Weak.swift */; }; - 934A8FA91D6518CB70273B73F8038ECA /* MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778F6E19CE49B8EDBAC2FCCD8195A55B /* MessageView.swift */; }; - 946185C05E253C9E47ABCD9EDE7E14D1 /* warningIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 29A39558830996C4F54686A1748B74B1 /* warningIcon@2x.png */; }; - 94B459D6CBA2A01D2B8174D138C30920 /* UIWindow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 753B78926D6BB175E96AB6E6F3514E87 /* UIWindow+Extensions.swift */; }; - 95DD12BBA763163407787AB32AAF8E56 /* successIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = A342E145FED9CD8DB4F464D110203E7C /* successIcon.png */; }; - 9B1E91097B4BD539EBCBBCC3C62CB75A /* errorIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = DEC0A6AE07C3285CA508F8FA3F4FE27D /* errorIcon.png */; }; - 9B1F7A4183F57B0AA9DD02624BD8855B /* PhysicsPanHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDEF50CAF615897F7A8540579B445634 /* PhysicsPanHandler.swift */; }; - 9B89868BA12CC4E1D9F116F663E56695 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24021DCE87BE9746D1DFB436C0A3AF7A /* Theme.swift */; }; - 9CFE7FFD7DDE28FCDA72647F2DB82837 /* infoIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 45844D489A130BA91E91E7CDD4969862 /* infoIconSubtle@2x.png */; }; - 9DA2F2EED5C99045AF44FF410A012F9D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; - 9DBD1955C7C621D9DCBE03D2161C91A9 /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D261B7BE0088C26BF6744F27B894492A /* UIViewController+Extensions.swift */; }; - 9F0473806FD530165403E47E834790C2 /* CenteredView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 787EE6DA4FBC3BF85ED2CF0BB6EBF494 /* CenteredView.xib */; }; - 9FA48348FB5F41070356A75237367D6D /* TabView.xib in Resources */ = {isa = PBXBuildFile; fileRef = EABF0CEB87991D02E13306975A8E80BB /* TabView.xib */; }; - A67A9ADFBCB364FCEF1BD92FF20B285C /* CardView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 705B5AF043D00B6538599B4EB1ECD77C /* CardView.xib */; }; - A9EB0C8E49AB748B05CF7941ACAF8475 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; - A9FFA668A7F81F50FBDCDCE26E891C8B /* errorIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = E0E4D99C4F78B9BA011D83FE63EE0946 /* errorIcon@3x.png */; }; - AC0A9B473B11FFF4BDEC0A0598795843 /* WindowViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9AA0E820F1C1AA219C066370332845A /* WindowViewController.swift */; }; - AD7F228AE0628DAAE4497493335D2BF7 /* SwiftMessages-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CBEAC9D0EF4113C3FD3B15F511A92D0 /* SwiftMessages-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - ADA044C43E517C5F0603B2A0AFB19860 /* successIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 760BFB41B33B6ED91B3FFD68D39083A0 /* successIconLight@2x.png */; }; - ADA91E8F5FDCD2EEC3D3B18A5B375C2C /* errorIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DF3DE135AB5C5C789CABAECC704CE907 /* errorIcon@2x.png */; }; - ADE48B746D5BB28EC33B403E1E12E0FE /* infoIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E936107A7CF9821DCBFFAF50D916F1E6 /* infoIcon@2x.png */; }; - AF34F903519AF36E07A90EF1BD703777 /* WindowScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8DEFE9675E5359A46A443182F127F06 /* WindowScene.swift */; }; - B02B2EAB7B8662AA27D91403BF9AAF36 /* warningIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = A0EE84E98A10805A2D64B836C465ED11 /* warningIconSubtle@3x.png */; }; - B4D338F85183163DC8CAB8A5864C9015 /* infoIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 676F359BE8561CF7512DB8B42CD7873A /* infoIconLight@3x.png */; }; - B520EDE98BD17CE5676F52A77139A933 /* NSLayoutConstraint+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6924EB5FC7236837637AE8F409000A /* NSLayoutConstraint+Extensions.swift */; }; - B679ED0F79CAF552C081588F3B63B91A /* warningIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0038C9A582787F9882258E8D1080EACF /* warningIcon@3x.png */; }; - C11CE75FD2DFCDF3B72D8D16280A2054 /* successIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 79D34B3C6875DA0279CB934C84CD000B /* successIcon@2x.png */; }; - C384FB76A48C06F7581D0F7850F2F4F1 /* Pods-iMessageDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 14BF989232A1D55A0FDAAB70B5A8E1BF /* Pods-iMessageDemo-dummy.m */; }; - C3CDAED707B153A58674CB1AC4A33FB2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; - C418A50F3C321227B0C6BE1D793680D4 /* successIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = FA199E6F18AB8900B5400EBA0EB32765 /* successIconLight@3x.png */; }; - C739607C022819840C267A0B4A7B2FD9 /* SwiftMessagesSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF27E3EF103BACDEE8CA842B2C90C8CA /* SwiftMessagesSegue.swift */; }; - C826D41BE5AF283B12C122AEF9640C99 /* infoIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C9F5DBB6D77B1E61E9BB1A722A4E1823 /* infoIconSubtle@3x.png */; }; - CC9369D0A5F8715733A4D517E45A3B63 /* infoIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8315EA451FE61625920FEF68174A0D22 /* infoIconLight@2x.png */; }; - CD480EEF400EC9B894F3292506BF0179 /* successIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = B031268635405AA009D05130C0FC253C /* successIconSubtle.png */; }; - D34D8255545B84A38C98D2DBB2F12CC5 /* PassthroughView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E03CBB908F2EC39AA5DA7AF04E1BDDD6 /* PassthroughView.swift */; }; - DE23509CED3A1E62F60E7E4BD6D38A35 /* BackgroundViewable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C706F1F1C6B3CE84445485C8577D5388 /* BackgroundViewable.swift */; }; - DECF1F62709D95EF5B48628A97B3CF98 /* warningIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 3259F99D03B6D738D7F47A625E7BD3BE /* warningIcon.png */; }; - E70A6E572A6DD457A766908E3ADCF49B /* errorIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = C787DA4E67B952C984FF5B065E0A2FF7 /* errorIconSubtle.png */; }; - E8174481BFB4559462F82062D85C0376 /* warningIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FFB0D50D01FFFA3FC2099E395029AE68 /* warningIconLight@2x.png */; }; - ECE268E9A63198F53B3F0337B3EA8AF3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */; }; - F05B5437AFF475FE8811E2A8A734920F /* NSBundle+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E2EB968B30DE56F38B5FCFFEDE9F88F /* NSBundle+Extensions.swift */; }; - F4BE83FBD5001DEDF6736E69ADA6D79B /* Presenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F513F2674553CBC247EE4B24EA25C99C /* Presenter.swift */; }; - F69D9D53A5500A42D4B41097537628E5 /* errorIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = E31D045D9E355D4F7F75564026B2051A /* errorIconSubtle@3x.png */; }; - F75A8D3DA9B4787BEEEBF3F784D5CDEF /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D219D80184B8ED97808EE17507B213A /* Animator.swift */; }; - F9A111F30C3B26D0A35B0829EED70D26 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E610C06F5B006DE57F34D5994532FB /* Error.swift */; }; - FA02B47E32DD9BEAAB8A2D1B66F697D5 /* PhysicsAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D2B448BE319CF56A38E222C0B7DF4CB /* PhysicsAnimation.swift */; }; - FDC2C20416D7EBF959A461E25FAFB16E /* errorIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D34E3F2A49E9024A96334DA4147F27B /* errorIconLight@3x.png */; }; + 00A4A53E0D1EFC70DA1EFAEFA82C4BA1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442F9FAEDF369CADB9E6E8FF3668FD95 /* Weak.swift */; }; + 03C7FA1BE62CCD280D63F4C7CDDFB27F /* AccessibleMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9E8A4D41E0A0E52C839F7197C4CE2A0 /* AccessibleMessage.swift */; }; + 04BCE3C12FDE7E91C9EF1FE154E80E2B /* SwiftMessageModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = B19DACBEC8DD85FB850D299DFB7A0374 /* SwiftMessageModifier.swift */; }; + 04C771EB4784B94AC6CA28ED6A919D50 /* WindowScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AB9866F195EB0AED31A33AEC27B67C1 /* WindowScene.swift */; }; + 096A6663757CB52C8A34B3E3146279C8 /* infoIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2CF5DC74916EBE02E70234620CD80150 /* infoIcon@2x.png */; }; + 0ADA608E3B9307694DCF4D0BC426E7FE /* warningIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B241F1B5D295E7806363B802DF03A085 /* warningIcon@2x.png */; }; + 0C093AF5F4D753325F4CE92F2F943CB4 /* MarginAdjustable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14DF8F43552C4F1C4CAEFBAFD9A77004 /* MarginAdjustable.swift */; }; + 0D53997CCCD141D2303E87C29CEFE211 /* MessageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A4D741EF8B40F5472CE2C1C1A34426BD /* MessageView.xib */; }; + 1441D5A06DD6903562EB794FC1AE8822 /* TabView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C33B3DA756F19F5C93D498D557BEB820 /* TabView.xib */; }; + 158EF18377B720081C31C2F2100DDA7A /* Presenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D18688EA04EA2F2BC48ED05D1FE5404 /* Presenter.swift */; }; + 19C0F7897044E72D3A13DE703920FFE1 /* MessageHostingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F989D33CAC3BCDA9B3C4B18F23A4DBE /* MessageHostingView.swift */; }; + 1E507663F3C402CBCA0C50A876F472EF /* errorIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D6A205E933052E98349DC710D78304CB /* errorIconLight@3x.png */; }; + 205A52121D20436063240893A461B29C /* errorIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 38D28C78FCAE6706F1294CEFA6B25F88 /* errorIconSubtle@2x.png */; }; + 24DA4886290040A0EC88B63D82EF412D /* warningIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5E02B1554754BA1F8EF318D567875139 /* warningIconSubtle@3x.png */; }; + 274D5DE28E0446655163A48E2272860A /* CornerRoundingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86872F4639B26435D20BED0CE7E35C7F /* CornerRoundingView.swift */; }; + 28D6446B971F186BACDED83CD8DE4D44 /* SwiftMessages-SwiftMessages_SwiftMessages in Resources */ = {isa = PBXBuildFile; fileRef = BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages-SwiftMessages_SwiftMessages */; }; + 31660027252C457325491844F16AEBDD /* successIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 74793ADC8ADF7674EA6C3041E2B54354 /* successIcon.png */; }; + 330C59E62D17601422EDB29513B9856C /* SwiftMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC10D7DB2D227D4AA8F41CDFDDC24F37 /* SwiftMessages.swift */; }; + 3451B2775584DD75A3BDF9BF28A03F76 /* SwiftMessagesSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = B17EF282E0A0F329DDF17226E83706F8 /* SwiftMessagesSegue.swift */; }; + 3479628DE3B6C9005316A7F591F5E68F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; + 360BEE76BBF40319E6638B3E027E1474 /* errorIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = EDFC2E756AAB98672C4B241097AAF0F6 /* errorIconSubtle.png */; }; + 3613DBA9CBD7E092BD7DC1924E6648D2 /* infoIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = ACCCF5B75EA41D844ED936A92602C5B1 /* infoIconLight@2x.png */; }; + 37A8DD40AF13BCABE7A3CD8EF15A4C53 /* successIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D146564C0660B5F616D6736F6560E17C /* successIconSubtle@2x.png */; }; + 3C566158256E9CC711B73810B2C64E3B /* KeyboardTrackingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A99EE79DBFA3C24A372DDB69162E36C /* KeyboardTrackingView.swift */; }; + 3F53FCE80C716C7DE7A3B1D8D65077BC /* CALayer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35F5FB13175EC0E13D53B445CE31395A /* CALayer+Extensions.swift */; }; + 422B422F962FD298F963F84934A21529 /* infoIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = C3701E97FDB85EFCE90E06D8CBC8ED41 /* infoIconLight.png */; }; + 436D8C63FBE86FF8271ABC32F9A52A9D /* Pods-iMessageDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 14BF989232A1D55A0FDAAB70B5A8E1BF /* Pods-iMessageDemo-dummy.m */; }; + 450919BA3A4D984DC24822CD80483419 /* TopBottomPresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A102DE8896931D80E06F2C74C2B003AC /* TopBottomPresentable.swift */; }; + 45A4B95F1F73413A3001B95E1F91D697 /* UIWindow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBC808D0C98F682E01DC43B544ED093F /* UIWindow+Extensions.swift */; }; + 4609D5EC365EABFE507781BF911B887B /* warningIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 004EE347886E2355CCB352F2AE7A35D6 /* warningIconLight.png */; }; + 469995B0FC2E3748F59D0E3A4445E197 /* CenteredView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 975A42F4C16B65B38769916EC5468D2A /* CenteredView.xib */; }; + 47CC2A912B82A499DB2F5E2ADBE664CF /* HapticMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA8BFA921A44ED7AEAA0E08BCE17EDDA /* HapticMessage.swift */; }; + 47EFB870CC797D2F54396F0AEBC8F576 /* errorIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = EC387534FD34764D4CC28B276A500AD6 /* errorIconLight.png */; }; + 48ADA8D4633776558E7D216434057A2A /* SwiftMessages.Config+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D83D1CC131CDAC7CA2C5BFD8701E8A79 /* SwiftMessages.Config+Extensions.swift */; }; + 4980F404C2B391C621CE2BCF05E08BDF /* errorIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6C12E87D0EA045A56FC0B45F072C74D2 /* errorIconSubtle@3x.png */; }; + 4C9FED5D268E82325C17309FB8904C43 /* warningIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B8B9892D8D5596E09F02DA2D71BF60B4 /* warningIcon@3x.png */; }; + 52A01853AC4F2D0E720579D7F8A531CF /* WindowViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9908774A62A95BF5BA8FE65842868043 /* WindowViewController.swift */; }; + 60F02D519964FFEE8A21221FF5E0B0C5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; + 61F532D30833A9FF1DE00EC98BC018C2 /* successIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5686DFC1E0B24A3051EF376AD8A162C0 /* successIconLight@3x.png */; }; + 634267873AC0F98140DBAFFF9A180BA8 /* MarginAdjustable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B602E4E64DAEF1468DD2F5C2C5DFD00 /* MarginAdjustable+Extensions.swift */; }; + 6583C565BE5BB9E52213854AA85F5A93 /* warningIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 6924A0A48B715EA35080ABB106B96BF7 /* warningIconSubtle.png */; }; + 67DC4D170143131B8AFFB558FDD00465 /* SwiftMessages-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D091A06E439F734980F26F81E9161EF2 /* SwiftMessages-dummy.m */; }; + 67F7D444EAC4475021B3458B21B2A162 /* Identifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88398B7A70E5B00495B670516D964701 /* Identifiable.swift */; }; + 698F203577674AFA4BBCDE93B01B9EEC /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57EB79F63EA99ADBBDA408015A4599BB /* UIViewController+Extensions.swift */; }; + 6A04C3E1C3437ED6BC6F096302B458AB /* errorIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8605740B16E17342A29212D21C380249 /* errorIcon@2x.png */; }; + 6CDE06668BB53C70BF1456F8EEE845D9 /* infoIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C40BBCF3A77C5C7A01708634BB4275C3 /* infoIconSubtle@3x.png */; }; + 6DC0B420F622E197919276CFF2C063CE /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 790409B3FBA491A9262ACCB929F30104 /* BaseView.swift */; }; + 72026C4424B7A1650CBEED98ED9AA288 /* successIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 7B9CEE1B17C98E76723E7404C532515D /* successIconSubtle.png */; }; + 744EA4AF597AFEFEE5B398434F47CA26 /* warningIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 71699C81494BC6585B862CDFC1CDAF54 /* warningIconLight@2x.png */; }; + 7590FF543E2634A83059E509D5B05583 /* Pods-iMessageExtensionDemo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CAB201AD00CAB811B045E2FFB5C03A8 /* Pods-iMessageExtensionDemo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 79BB175F4750822409AB9ED0A9D90D09 /* successIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6EA088414C10E47808EA8490D9BBF64F /* successIcon@3x.png */; }; + 81B1015F29547CAB449757FC5ABCAFAB /* warningIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5FE01208AD70F1B35201AB04E50A23EC /* warningIconLight@3x.png */; }; + 88D024879AEAE247899BFB50C8516515 /* Pods-iMessageDemo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D0ECE831FB5E0EE1D68E837671320C7 /* Pods-iMessageDemo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8CB7CCDF07E1CE6838C7278BC19968B6 /* infoIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 79A086337846180B9A63D8492CCE45B4 /* infoIcon.png */; }; + 8F63F1ABAB21FA99A6CB1A54D5F2B5AA /* infoIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 560722B244EB84DF745199247129C164 /* infoIcon@3x.png */; }; + 942468E4C1AEFCF10D5043243B4007E7 /* NSBundle+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 073CD58B2E8E255484D239A01D707B81 /* NSBundle+Extensions.swift */; }; + 9FBBA6E4D3A2A4CA4BA8535E35D54CA8 /* successIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 44DAC25C8D6D72F70BD1CF9099BDAF10 /* successIconLight@2x.png */; }; + A4724FC3B4F49DCBF50D395257BB6B8E /* CardView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03B5D12D54ACC75F929389CFF15E91FF /* CardView.xib */; }; + A52191D65F4C725EBF61D27F40FEA970 /* infoIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 88237113DAAD8ECF8D5E3FAA27D8A02F /* infoIconLight@3x.png */; }; + A836F848C83565B2A0A06AB23D491946 /* MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9BBC4BF82FBB152E34F2D1EF36A0FB1 /* MessageView.swift */; }; + A865FCE8718103C8E725EC1EC0F9F4F6 /* BackgroundViewable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86C1C9601BF8A5BC563062C310C0E3B5 /* BackgroundViewable.swift */; }; + A8C4AD87F73E9C51F797F34BCFF5AA17 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; + A8EF6BE26B31A8713E37E0629F6466EB /* successIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 252A5DF0FE3237691B8C50B969857389 /* successIconLight.png */; }; + A90C06B459CC64A243DD1184024E5D22 /* infoIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = A6C7FF0D9E13571262231B72D0553E49 /* infoIconSubtle.png */; }; + B04AA81A8A8CE0BCEFD5FAFD841F461F /* Task+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9610DCAAD9A55CDF73BAD54D523E1273 /* Task+Extensions.swift */; }; + B1B4D240B65FFC5A7A981B9504C55270 /* NSLayoutConstraint+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 882EF814D0A1EE2AB28BFEE5C067EE6F /* NSLayoutConstraint+Extensions.swift */; }; + B22AF07D79D1A82DE583AC49E3D472D3 /* Pods-iMessageExtensionDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F40CA14AD738DD186B4DA8FD14AE5BD /* Pods-iMessageExtensionDemo-dummy.m */; }; + B61EBE61C31E78140BF12D32A008A43B /* StatusLine.xib in Resources */ = {isa = PBXBuildFile; fileRef = 62332870F1E2AE3FA16EE5ADC85C104A /* StatusLine.xib */; }; + B646E1CD53F14E0DEE53740799C06AC5 /* SwiftMessages-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 080E269BABA7D072D8C51E29E9AC4A91 /* SwiftMessages-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B6D0E2FA454A946D6C9A7494648F49D9 /* MessageGeometryProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28456F0421422D16D71D14D426309B3F /* MessageGeometryProxy.swift */; }; + B9FDFA90A4FB68CA5357AB70427B4DCD /* TopBottomAnimationStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C61DD3C66AC7ADE1E9CCFE7A4A0BEA59 /* TopBottomAnimationStyle.swift */; }; + BA4779B82B35B85EFE9F595624BA3943 /* UIEdgeInsets+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16B5B2B5429B01345E4DA361DE01904D /* UIEdgeInsets+Extensions.swift */; }; + BAB66573FF29F6337237A8DA0EB9E3E8 /* PassthroughWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0398CE267904AF6C2FD03B3766511ECF /* PassthroughWindow.swift */; }; + BBF31491EF3411DCFA7E649645229E2A /* successIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 47A710678B44C50DA470D1BCF94B87B8 /* successIconSubtle@3x.png */; }; + C2031E7EC3C60B876F2AC04253D3AFC4 /* MessageViewConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06DB4311BFB347093FC18777A503B461 /* MessageViewConvertible.swift */; }; + CCBFBDB03B2444C911BADDE6A6BA08AD /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9414B7316138752779A4B9C7E5C988DB /* Error.swift */; }; + D3B31A631C754CAECABFA4DC672D3D0B /* warningIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 85C6BEF274CDB3807F9BD452A26C68E6 /* warningIconSubtle@2x.png */; }; + D8DFC45149C57377B5C90B3457090564 /* warningIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = D47C1471CCFFBEF214DF9F0ECBDD408B /* warningIcon.png */; }; + D9519DD580DF2E744AB4C4087FA28BCD /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F67BD26788FA0C70E942A7629E41C5E8 /* Animator.swift */; }; + DC6C4E22FA8DD6FA491066A738132EF1 /* infoIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8026A87EEBF1A86A282563F974C4225C /* infoIconSubtle@2x.png */; }; + DD406A0C002AC1D02A6E5794B1729C22 /* PassthroughView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A865E97261799942A6F29092D3D7AE /* PassthroughView.swift */; }; + DE2531A67AEBFED61A060DF13790C3BE /* errorIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 91013DDC05BDB2787740B0C9E5444D23 /* errorIcon@3x.png */; }; + E03C930AD56F078DCD1357E5C83AD67A /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = B32459A84426DD5E88256AD61F3D4E91 /* Theme.swift */; }; + E4906D67B9F27E11EE9F8E8F5C847A14 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */; }; + E54040398A9AD751393A2171DC64D70E /* errorIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 71D489FBDD84B41576199298F717BC08 /* errorIcon.png */; }; + EE9A5A3877D99BFCA5DA70BA4E049CA9 /* successIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DBF06E9B2F93F081139B8A6A922F569 /* successIcon@2x.png */; }; + F2D3ABB0C7B6EB5B531E4E68C40AA89C /* PhysicsPanHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AEEED9FBEA6C5DB7EE3B95E7D8115B3 /* PhysicsPanHandler.swift */; }; + F516490B5276943A352D597431B079B6 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1F1B1264A726D334A72AB1CB001CA9F /* TopBottomAnimation.swift */; }; + F667CC7C7F3285FC39427F2AAA8E7665 /* PhysicsAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D7E08E0434930866B59A3F17A3A577B /* PhysicsAnimation.swift */; }; + F8D0D33FC1C833490057108C322E56CB /* MaskingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC4854845AC1848C056C36719A5D7420 /* MaskingView.swift */; }; + FC0E2BA3CD9C6C3ACF3681841D8EF5BA /* errorIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C49B964EF7710D818E0AF0321724EEF4 /* errorIconLight@2x.png */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 4B785BB517DA1D687C0B772C77660019 /* PBXContainerItemProxy */ = { + 146D3A65FCE17293CC3AD6CBEAE15F9A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = DAB613A18652334F6BFC5F27BADF515D; - remoteInfo = SwiftMessages; + remoteGlobalIDString = 1FC5E8328653C350899229BDF89FACE5; + remoteInfo = "SwiftMessages-SwiftMessages_SwiftMessages"; }; - D19F271ED5B0FED7305E55070B415EDB /* PBXContainerItemProxy */ = { + 70E6358901408AED062E820735630F69 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 1FC5E8328653C350899229BDF89FACE5; - remoteInfo = "SwiftMessages-SwiftMessages_SwiftMessages"; + remoteGlobalIDString = DAB613A18652334F6BFC5F27BADF515D; + remoteInfo = SwiftMessages; }; - DA9FA5DB745280F35DD4EFAC9A7A4FD7 /* PBXContainerItemProxy */ = { + D297C84AE0F13FB6A76F2F391D21D679 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; @@ -117,226 +125,242 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 0038C9A582787F9882258E8D1080EACF /* warningIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@3x.png"; path = "SwiftMessages/Resources/warningIcon@3x.png"; sourceTree = "<group>"; }; - 007ACA6F89C6C856F78352A086F3B8EA /* CornerRoundingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CornerRoundingView.swift; path = SwiftMessages/CornerRoundingView.swift; sourceTree = "<group>"; }; - 0201BC51C7CA061016B619400691A139 /* AccessibleMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibleMessage.swift; path = SwiftMessages/AccessibleMessage.swift; sourceTree = "<group>"; }; + 004EE347886E2355CCB352F2AE7A35D6 /* warningIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconLight.png; path = SwiftMessages/Resources/warningIconLight.png; sourceTree = "<group>"; }; + 0398CE267904AF6C2FD03B3766511ECF /* PassthroughWindow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughWindow.swift; path = SwiftMessages/PassthroughWindow.swift; sourceTree = "<group>"; }; + 03A865E97261799942A6F29092D3D7AE /* PassthroughView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughView.swift; path = SwiftMessages/PassthroughView.swift; sourceTree = "<group>"; }; + 03B5D12D54ACC75F929389CFF15E91FF /* CardView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CardView.xib; path = SwiftMessages/Resources/CardView.xib; sourceTree = "<group>"; }; + 06DB4311BFB347093FC18777A503B461 /* MessageViewConvertible.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageViewConvertible.swift; path = SwiftMessages/MessageViewConvertible.swift; sourceTree = "<group>"; }; + 073CD58B2E8E255484D239A01D707B81 /* NSBundle+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSBundle+Extensions.swift"; path = "SwiftMessages/NSBundle+Extensions.swift"; sourceTree = "<group>"; }; + 080E269BABA7D072D8C51E29E9AC4A91 /* SwiftMessages-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-umbrella.h"; sourceTree = "<group>"; }; 093D5BBE2A96A1A7AC0432A3AB933576 /* Pods-iMessageDemo-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageDemo-Info.plist"; sourceTree = "<group>"; }; - 0AF65ECDAFAD03A79B5571C6F66D8F35 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TopBottomAnimation.swift; path = SwiftMessages/TopBottomAnimation.swift; sourceTree = "<group>"; }; - 0BEC185781E869FB5FDB7F10538230C7 /* SwiftMessages.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SwiftMessages.modulemap; sourceTree = "<group>"; }; - 0D2B448BE319CF56A38E222C0B7DF4CB /* PhysicsAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsAnimation.swift; path = SwiftMessages/PhysicsAnimation.swift; sourceTree = "<group>"; }; + 0FD758C8718F3EEFB5E97E34A29CE1CC /* SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SwiftMessages-Info.plist"; sourceTree = "<group>"; }; 1341BB7116EC50FDF7062C6A91DEDF49 /* Pods-iMessageExtensionDemo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageExtensionDemo-acknowledgements.plist"; sourceTree = "<group>"; }; - 141AADF8046C9D5EC8E194DF662BAC41 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; sourceTree = "<group>"; }; 14BF989232A1D55A0FDAAB70B5A8E1BF /* Pods-iMessageDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-iMessageDemo-dummy.m"; sourceTree = "<group>"; }; - 17ADABD24F805C5F7FF62167E7ABEF0A /* successIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@3x.png"; path = "SwiftMessages/Resources/successIconSubtle@3x.png"; sourceTree = "<group>"; }; - 1A331C2E0BE2AE2118D65AA1F12519F2 /* PassthroughWindow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughWindow.swift; path = SwiftMessages/PassthroughWindow.swift; sourceTree = "<group>"; }; - 1E2FE4DB6869F330F19A3A5459AAFFFB /* StatusLine.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = StatusLine.xib; path = SwiftMessages/Resources/StatusLine.xib; sourceTree = "<group>"; }; - 1ED635B9451869879B1A404F00C3CCC7 /* SwiftMessages-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-prefix.pch"; sourceTree = "<group>"; }; - 24021DCE87BE9746D1DFB436C0A3AF7A /* Theme.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Theme.swift; path = SwiftMessages/Theme.swift; sourceTree = "<group>"; }; - 29A39558830996C4F54686A1748B74B1 /* warningIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@2x.png"; path = "SwiftMessages/Resources/warningIcon@2x.png"; sourceTree = "<group>"; }; + 14DF8F43552C4F1C4CAEFBAFD9A77004 /* MarginAdjustable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MarginAdjustable.swift; path = SwiftMessages/MarginAdjustable.swift; sourceTree = "<group>"; }; + 16B5B2B5429B01345E4DA361DE01904D /* UIEdgeInsets+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIEdgeInsets+Extensions.swift"; path = "SwiftMessages/UIEdgeInsets+Extensions.swift"; sourceTree = "<group>"; }; + 252A5DF0FE3237691B8C50B969857389 /* successIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconLight.png; path = SwiftMessages/Resources/successIconLight.png; sourceTree = "<group>"; }; + 28456F0421422D16D71D14D426309B3F /* MessageGeometryProxy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageGeometryProxy.swift; path = SwiftMessages/MessageGeometryProxy.swift; sourceTree = "<group>"; }; + 2AB9866F195EB0AED31A33AEC27B67C1 /* WindowScene.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WindowScene.swift; path = SwiftMessages/WindowScene.swift; sourceTree = "<group>"; }; + 2CF5DC74916EBE02E70234620CD80150 /* infoIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@2x.png"; path = "SwiftMessages/Resources/infoIcon@2x.png"; sourceTree = "<group>"; }; 2D0ECE831FB5E0EE1D68E837671320C7 /* Pods-iMessageDemo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-iMessageDemo-umbrella.h"; sourceTree = "<group>"; }; - 3259F99D03B6D738D7F47A625E7BD3BE /* warningIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIcon.png; path = SwiftMessages/Resources/warningIcon.png; sourceTree = "<group>"; }; - 36F7B24601DF4C00B14EC8CE2D4A48DC /* UIEdgeInsets+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIEdgeInsets+Extensions.swift"; path = "SwiftMessages/UIEdgeInsets+Extensions.swift"; sourceTree = "<group>"; }; - 3E2EB968B30DE56F38B5FCFFEDE9F88F /* NSBundle+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSBundle+Extensions.swift"; path = "SwiftMessages/NSBundle+Extensions.swift"; sourceTree = "<group>"; }; - 45844D489A130BA91E91E7CDD4969862 /* infoIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@2x.png"; path = "SwiftMessages/Resources/infoIconSubtle@2x.png"; sourceTree = "<group>"; }; - 467EAD44C7F625F384822180F004E64F /* CALayer+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CALayer+Extensions.swift"; path = "SwiftMessages/CALayer+Extensions.swift"; sourceTree = "<group>"; }; - 468D9889455DE51BD5BBC2360BDBB877 /* errorIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@2x.png"; path = "SwiftMessages/Resources/errorIconSubtle@2x.png"; sourceTree = "<group>"; }; - 4824F23D80FF9070A5F8A452DB11EB9A /* SwiftMessages.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SwiftMessages.framework; path = SwiftMessages.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 48DC3BADDA3A20F2AEB8585117DAFA0D /* infoIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@3x.png"; path = "SwiftMessages/Resources/infoIcon@3x.png"; sourceTree = "<group>"; }; - 4D34E3F2A49E9024A96334DA4147F27B /* errorIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@3x.png"; path = "SwiftMessages/Resources/errorIconLight@3x.png"; sourceTree = "<group>"; }; - 52F1CA85E0EED7D94FE0036BC92EB3EC /* successIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconLight.png; path = SwiftMessages/Resources/successIconLight.png; sourceTree = "<group>"; }; - 59FEAC25BE3FCB9F8373DE26400CC89D /* SwiftMessages.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = SwiftMessages.podspec; sourceTree = "<group>"; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 5A16E25077F8D76288BE678E6AC1C884 /* SwiftMessages.Config+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "SwiftMessages.Config+Extensions.swift"; path = "SwiftMessages/SwiftMessages.Config+Extensions.swift"; sourceTree = "<group>"; }; + 35F5FB13175EC0E13D53B445CE31395A /* CALayer+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CALayer+Extensions.swift"; path = "SwiftMessages/CALayer+Extensions.swift"; sourceTree = "<group>"; }; + 38D28C78FCAE6706F1294CEFA6B25F88 /* errorIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@2x.png"; path = "SwiftMessages/Resources/errorIconSubtle@2x.png"; sourceTree = "<group>"; }; + 442F9FAEDF369CADB9E6E8FF3668FD95 /* Weak.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Weak.swift; path = SwiftMessages/Weak.swift; sourceTree = "<group>"; }; + 44DAC25C8D6D72F70BD1CF9099BDAF10 /* successIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@2x.png"; path = "SwiftMessages/Resources/successIconLight@2x.png"; sourceTree = "<group>"; }; + 47A710678B44C50DA470D1BCF94B87B8 /* successIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@3x.png"; path = "SwiftMessages/Resources/successIconSubtle@3x.png"; sourceTree = "<group>"; }; + 4824F23D80FF9070A5F8A452DB11EB9A /* SwiftMessages */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SwiftMessages; path = SwiftMessages.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4DBF06E9B2F93F081139B8A6A922F569 /* successIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@2x.png"; path = "SwiftMessages/Resources/successIcon@2x.png"; sourceTree = "<group>"; }; + 560722B244EB84DF745199247129C164 /* infoIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@3x.png"; path = "SwiftMessages/Resources/infoIcon@3x.png"; sourceTree = "<group>"; }; + 5686DFC1E0B24A3051EF376AD8A162C0 /* successIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@3x.png"; path = "SwiftMessages/Resources/successIconLight@3x.png"; sourceTree = "<group>"; }; + 573965F15F83BD70EEAC9E1E8B0F85C6 /* SwiftMessages.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = SwiftMessages.podspec; sourceTree = "<group>"; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 57EB79F63EA99ADBBDA408015A4599BB /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Extensions.swift"; path = "SwiftMessages/UIViewController+Extensions.swift"; sourceTree = "<group>"; }; 5CAB201AD00CAB811B045E2FFB5C03A8 /* Pods-iMessageExtensionDemo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-iMessageExtensionDemo-umbrella.h"; sourceTree = "<group>"; }; + 5E02B1554754BA1F8EF318D567875139 /* warningIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@3x.png"; path = "SwiftMessages/Resources/warningIconSubtle@3x.png"; sourceTree = "<group>"; }; + 5F989D33CAC3BCDA9B3C4B18F23A4DBE /* MessageHostingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageHostingView.swift; path = SwiftMessages/MessageHostingView.swift; sourceTree = "<group>"; }; + 5FE01208AD70F1B35201AB04E50A23EC /* warningIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@3x.png"; path = "SwiftMessages/Resources/warningIconLight@3x.png"; sourceTree = "<group>"; }; + 6228A8E37F7905D75917DD4CBE65B03C /* SwiftMessages.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SwiftMessages.modulemap; sourceTree = "<group>"; }; + 62332870F1E2AE3FA16EE5ADC85C104A /* StatusLine.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = StatusLine.xib; path = SwiftMessages/Resources/StatusLine.xib; sourceTree = "<group>"; }; 6489B2A759075E9DC1D1406734F45B5F /* Pods-iMessageExtensionDemo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iMessageExtensionDemo.modulemap"; sourceTree = "<group>"; }; - 676F359BE8561CF7512DB8B42CD7873A /* infoIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@3x.png"; path = "SwiftMessages/Resources/infoIconLight@3x.png"; sourceTree = "<group>"; }; - 705B5AF043D00B6538599B4EB1ECD77C /* CardView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CardView.xib; path = SwiftMessages/Resources/CardView.xib; sourceTree = "<group>"; }; - 7100245A2722BD53D5B3927ED649069F /* errorIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconLight.png; path = SwiftMessages/Resources/errorIconLight.png; sourceTree = "<group>"; }; - 730840765E737D45772EBE66DB8A6D2E /* infoIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconLight.png; path = SwiftMessages/Resources/infoIconLight.png; sourceTree = "<group>"; }; - 74C53DDA65E08AD7274EA6625408AB99 /* SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SwiftMessages-Info.plist"; sourceTree = "<group>"; }; - 753B78926D6BB175E96AB6E6F3514E87 /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIWindow+Extensions.swift"; path = "SwiftMessages/UIWindow+Extensions.swift"; sourceTree = "<group>"; }; - 760BFB41B33B6ED91B3FFD68D39083A0 /* successIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@2x.png"; path = "SwiftMessages/Resources/successIconLight@2x.png"; sourceTree = "<group>"; }; - 778F6E19CE49B8EDBAC2FCCD8195A55B /* MessageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageView.swift; path = SwiftMessages/MessageView.swift; sourceTree = "<group>"; }; - 787EE6DA4FBC3BF85ED2CF0BB6EBF494 /* CenteredView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CenteredView.xib; path = SwiftMessages/Resources/CenteredView.xib; sourceTree = "<group>"; }; - 79D34B3C6875DA0279CB934C84CD000B /* successIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@2x.png"; path = "SwiftMessages/Resources/successIcon@2x.png"; sourceTree = "<group>"; }; - 7C4DF53A4B44C246968618BF25962786 /* warningIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@3x.png"; path = "SwiftMessages/Resources/warningIconLight@3x.png"; sourceTree = "<group>"; }; - 7C8214A441D845A4A4DD6570FD5D458F /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "MarginAdjustable+Extensions.swift"; path = "SwiftMessages/MarginAdjustable+Extensions.swift"; sourceTree = "<group>"; }; + 6924A0A48B715EA35080ABB106B96BF7 /* warningIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconSubtle.png; path = SwiftMessages/Resources/warningIconSubtle.png; sourceTree = "<group>"; }; + 6C12E87D0EA045A56FC0B45F072C74D2 /* errorIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@3x.png"; path = "SwiftMessages/Resources/errorIconSubtle@3x.png"; sourceTree = "<group>"; }; + 6EA088414C10E47808EA8490D9BBF64F /* successIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@3x.png"; path = "SwiftMessages/Resources/successIcon@3x.png"; sourceTree = "<group>"; }; + 71699C81494BC6585B862CDFC1CDAF54 /* warningIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@2x.png"; path = "SwiftMessages/Resources/warningIconLight@2x.png"; sourceTree = "<group>"; }; + 71D489FBDD84B41576199298F717BC08 /* errorIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIcon.png; path = SwiftMessages/Resources/errorIcon.png; sourceTree = "<group>"; }; + 74793ADC8ADF7674EA6C3041E2B54354 /* successIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIcon.png; path = SwiftMessages/Resources/successIcon.png; sourceTree = "<group>"; }; + 790409B3FBA491A9262ACCB929F30104 /* BaseView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BaseView.swift; path = SwiftMessages/BaseView.swift; sourceTree = "<group>"; }; + 79A086337846180B9A63D8492CCE45B4 /* infoIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIcon.png; path = SwiftMessages/Resources/infoIcon.png; sourceTree = "<group>"; }; + 7B9CEE1B17C98E76723E7404C532515D /* successIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconSubtle.png; path = SwiftMessages/Resources/successIconSubtle.png; sourceTree = "<group>"; }; 7CC6A596A9C1659D8E93222DA4144414 /* Pods-iMessageExtensionDemo-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageExtensionDemo-Info.plist"; sourceTree = "<group>"; }; 7F40CA14AD738DD186B4DA8FD14AE5BD /* Pods-iMessageExtensionDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-iMessageExtensionDemo-dummy.m"; sourceTree = "<group>"; }; + 8026A87EEBF1A86A282563F974C4225C /* infoIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@2x.png"; path = "SwiftMessages/Resources/infoIconSubtle@2x.png"; sourceTree = "<group>"; }; 820B743874F7AC9F9E3970D68E2E60FA /* Pods-iMessageDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageDemo.release.xcconfig"; sourceTree = "<group>"; }; - 8315EA451FE61625920FEF68174A0D22 /* infoIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@2x.png"; path = "SwiftMessages/Resources/infoIconLight@2x.png"; sourceTree = "<group>"; }; - 860D833A7A1B108A89ED34AD74778AC0 /* warningIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconSubtle.png; path = SwiftMessages/Resources/warningIconSubtle.png; sourceTree = "<group>"; }; - 87745BF2C7154EF88509BED0D71243F1 /* SwiftMessages.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.debug.xcconfig; sourceTree = "<group>"; }; - 88D73E42D996B226222A4EBA46F7DC6D /* Weak.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Weak.swift; path = SwiftMessages/Weak.swift; sourceTree = "<group>"; }; - 8AD355ED684A939F2A4E333F95E8AC31 /* warningIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@2x.png"; path = "SwiftMessages/Resources/warningIconSubtle@2x.png"; sourceTree = "<group>"; }; - 8D219D80184B8ED97808EE17507B213A /* Animator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Animator.swift; path = SwiftMessages/Animator.swift; sourceTree = "<group>"; }; + 85C6BEF274CDB3807F9BD452A26C68E6 /* warningIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@2x.png"; path = "SwiftMessages/Resources/warningIconSubtle@2x.png"; sourceTree = "<group>"; }; + 8605740B16E17342A29212D21C380249 /* errorIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@2x.png"; path = "SwiftMessages/Resources/errorIcon@2x.png"; sourceTree = "<group>"; }; + 86872F4639B26435D20BED0CE7E35C7F /* CornerRoundingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CornerRoundingView.swift; path = SwiftMessages/CornerRoundingView.swift; sourceTree = "<group>"; }; + 86C1C9601BF8A5BC563062C310C0E3B5 /* BackgroundViewable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BackgroundViewable.swift; path = SwiftMessages/BackgroundViewable.swift; sourceTree = "<group>"; }; + 88237113DAAD8ECF8D5E3FAA27D8A02F /* infoIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@3x.png"; path = "SwiftMessages/Resources/infoIconLight@3x.png"; sourceTree = "<group>"; }; + 882EF814D0A1EE2AB28BFEE5C067EE6F /* NSLayoutConstraint+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSLayoutConstraint+Extensions.swift"; path = "SwiftMessages/NSLayoutConstraint+Extensions.swift"; sourceTree = "<group>"; }; + 88398B7A70E5B00495B670516D964701 /* Identifiable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Identifiable.swift; path = SwiftMessages/Identifiable.swift; sourceTree = "<group>"; }; + 8940290DCDAD08810FE0CD944F376444 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; sourceTree = "<group>"; }; + 8AEEED9FBEA6C5DB7EE3B95E7D8115B3 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsPanHandler.swift; path = SwiftMessages/PhysicsPanHandler.swift; sourceTree = "<group>"; }; + 8D18688EA04EA2F2BC48ED05D1FE5404 /* Presenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Presenter.swift; path = SwiftMessages/Presenter.swift; sourceTree = "<group>"; }; 8D54691037F1CA4653B76F0558E2AA82 /* Pods-iMessageExtensionDemo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-iMessageExtensionDemo-acknowledgements.markdown"; sourceTree = "<group>"; }; - 90AC342C6F09BF7715D4FB95512DD68A /* KeyboardTrackingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KeyboardTrackingView.swift; path = SwiftMessages/KeyboardTrackingView.swift; sourceTree = "<group>"; }; + 8D7E08E0434930866B59A3F17A3A577B /* PhysicsAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsAnimation.swift; path = SwiftMessages/PhysicsAnimation.swift; sourceTree = "<group>"; }; + 91013DDC05BDB2787740B0C9E5444D23 /* errorIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@3x.png"; path = "SwiftMessages/Resources/errorIcon@3x.png"; sourceTree = "<group>"; }; 915DE2E4E300BAD440BE13F72E49D731 /* Pods-iMessageDemo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageDemo-acknowledgements.plist"; sourceTree = "<group>"; }; - 91D9224F29E092950BADC27C979E10CC /* successIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@2x.png"; path = "SwiftMessages/Resources/successIconSubtle@2x.png"; sourceTree = "<group>"; }; - 9C6E00017F9E79F6D4926E9CB43A66DF /* SwiftMessages-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SwiftMessages-dummy.m"; sourceTree = "<group>"; }; - 9CBEAC9D0EF4113C3FD3B15F511A92D0 /* SwiftMessages-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-umbrella.h"; sourceTree = "<group>"; }; + 9414B7316138752779A4B9C7E5C988DB /* Error.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Error.swift; path = SwiftMessages/Error.swift; sourceTree = "<group>"; }; + 9610DCAAD9A55CDF73BAD54D523E1273 /* Task+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Task+Extensions.swift"; path = "SwiftMessages/Task+Extensions.swift"; sourceTree = "<group>"; }; + 975A42F4C16B65B38769916EC5468D2A /* CenteredView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CenteredView.xib; path = SwiftMessages/Resources/CenteredView.xib; sourceTree = "<group>"; }; + 9908774A62A95BF5BA8FE65842868043 /* WindowViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WindowViewController.swift; path = SwiftMessages/WindowViewController.swift; sourceTree = "<group>"; }; + 9A99EE79DBFA3C24A372DDB69162E36C /* KeyboardTrackingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KeyboardTrackingView.swift; path = SwiftMessages/KeyboardTrackingView.swift; sourceTree = "<group>"; }; + 9B602E4E64DAEF1468DD2F5C2C5DFD00 /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "MarginAdjustable+Extensions.swift"; path = "SwiftMessages/MarginAdjustable+Extensions.swift"; sourceTree = "<group>"; }; + 9D5A75A919AE6C6D38A627636D7ADC11 /* LICENSE.md */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE.md; sourceTree = "<group>"; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - A0EE84E98A10805A2D64B836C465ED11 /* warningIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@3x.png"; path = "SwiftMessages/Resources/warningIconSubtle@3x.png"; sourceTree = "<group>"; }; - A342E145FED9CD8DB4F464D110203E7C /* successIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIcon.png; path = SwiftMessages/Resources/successIcon.png; sourceTree = "<group>"; }; + A102DE8896931D80E06F2C74C2B003AC /* TopBottomPresentable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TopBottomPresentable.swift; path = SwiftMessages/TopBottomPresentable.swift; sourceTree = "<group>"; }; + A1F1B1264A726D334A72AB1CB001CA9F /* TopBottomAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TopBottomAnimation.swift; path = SwiftMessages/TopBottomAnimation.swift; sourceTree = "<group>"; }; + A399825CF45C4427BF9B80A590BF2BD5 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = "<group>"; }; + A4D741EF8B40F5472CE2C1C1A34426BD /* MessageView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = MessageView.xib; path = SwiftMessages/Resources/MessageView.xib; sourceTree = "<group>"; }; + A6C7FF0D9E13571262231B72D0553E49 /* infoIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconSubtle.png; path = SwiftMessages/Resources/infoIconSubtle.png; sourceTree = "<group>"; }; + ACCCF5B75EA41D844ED936A92602C5B1 /* infoIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@2x.png"; path = "SwiftMessages/Resources/infoIconLight@2x.png"; sourceTree = "<group>"; }; AE7AEA9CE6B44DCC96AE4E68FA644DAA /* Pods-iMessageExtensionDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageExtensionDemo.release.xcconfig"; sourceTree = "<group>"; }; - AFC41396FB1BD59C9A69EE1DD82E47C2 /* Pods_iMessageDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_iMessageDemo.framework; path = "Pods-iMessageDemo.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; - B031268635405AA009D05130C0FC253C /* successIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconSubtle.png; path = SwiftMessages/Resources/successIconSubtle.png; sourceTree = "<group>"; }; - B7BF853CD0CDFA20423D4C813B34B57F /* SwiftMessages.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.release.xcconfig; sourceTree = "<group>"; }; - B8A4CCB4B08D2D3BE586212AB4167DC2 /* MessageView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = MessageView.xib; path = SwiftMessages/Resources/MessageView.xib; sourceTree = "<group>"; }; + AFC41396FB1BD59C9A69EE1DD82E47C2 /* Pods-iMessageDemo */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-iMessageDemo"; path = Pods_iMessageDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B17EF282E0A0F329DDF17226E83706F8 /* SwiftMessagesSegue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessagesSegue.swift; path = SwiftMessages/SwiftMessagesSegue.swift; sourceTree = "<group>"; }; + B19DACBEC8DD85FB850D299DFB7A0374 /* SwiftMessageModifier.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessageModifier.swift; path = SwiftMessages/SwiftMessageModifier.swift; sourceTree = "<group>"; }; + B241F1B5D295E7806363B802DF03A085 /* warningIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@2x.png"; path = "SwiftMessages/Resources/warningIcon@2x.png"; sourceTree = "<group>"; }; + B32459A84426DD5E88256AD61F3D4E91 /* Theme.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Theme.swift; path = SwiftMessages/Theme.swift; sourceTree = "<group>"; }; + B8B9892D8D5596E09F02DA2D71BF60B4 /* warningIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@3x.png"; path = "SwiftMessages/Resources/warningIcon@3x.png"; sourceTree = "<group>"; }; + B941E5186F814BF618D9D0458496379C /* SwiftMessages-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-prefix.pch"; sourceTree = "<group>"; }; B99CBDE49D6502CF64EB9059C005BF31 /* Pods-iMessageDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageDemo.debug.xcconfig"; sourceTree = "<group>"; }; - BDEF50CAF615897F7A8540579B445634 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsPanHandler.swift; path = SwiftMessages/PhysicsPanHandler.swift; sourceTree = "<group>"; }; - BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages_SwiftMessages.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = SwiftMessages_SwiftMessages.bundle; path = "SwiftMessages-SwiftMessages_SwiftMessages.bundle"; sourceTree = BUILT_PRODUCTS_DIR; }; - BF27E3EF103BACDEE8CA842B2C90C8CA /* SwiftMessagesSegue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessagesSegue.swift; path = SwiftMessages/SwiftMessagesSegue.swift; sourceTree = "<group>"; }; + BA61C87AB568667230DCD9DC2E423722 /* SwiftMessages.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.release.xcconfig; sourceTree = "<group>"; }; + BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages-SwiftMessages_SwiftMessages */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = "SwiftMessages-SwiftMessages_SwiftMessages"; path = SwiftMessages_SwiftMessages.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; BF61E78F8E8EE539F4A63C5A9D43AC15 /* Pods-iMessageDemo-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-iMessageDemo-frameworks.sh"; sourceTree = "<group>"; }; C306ACAFEE157959D78E71DBBBD675DC /* Pods-iMessageExtensionDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageExtensionDemo.debug.xcconfig"; sourceTree = "<group>"; }; - C56AB83FDAB8D6A1328E7EECCAD99A69 /* warningIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconLight.png; path = SwiftMessages/Resources/warningIconLight.png; sourceTree = "<group>"; }; - C5E610C06F5B006DE57F34D5994532FB /* Error.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Error.swift; path = SwiftMessages/Error.swift; sourceTree = "<group>"; }; - C706F1F1C6B3CE84445485C8577D5388 /* BackgroundViewable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BackgroundViewable.swift; path = SwiftMessages/BackgroundViewable.swift; sourceTree = "<group>"; }; - C787DA4E67B952C984FF5B065E0A2FF7 /* errorIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconSubtle.png; path = SwiftMessages/Resources/errorIconSubtle.png; sourceTree = "<group>"; }; - C7EE64CFE0084CF5213A03AF29A668ED /* BaseView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BaseView.swift; path = SwiftMessages/BaseView.swift; sourceTree = "<group>"; }; - C9F5DBB6D77B1E61E9BB1A722A4E1823 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "SwiftMessages/Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; - CBC3F501D8BC852716D085B3022E68CA /* Pods_iMessageExtensionDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_iMessageExtensionDemo.framework; path = "Pods-iMessageExtensionDemo.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + C33B3DA756F19F5C93D498D557BEB820 /* TabView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = TabView.xib; path = SwiftMessages/Resources/TabView.xib; sourceTree = "<group>"; }; + C3701E97FDB85EFCE90E06D8CBC8ED41 /* infoIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconLight.png; path = SwiftMessages/Resources/infoIconLight.png; sourceTree = "<group>"; }; + C40BBCF3A77C5C7A01708634BB4275C3 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "SwiftMessages/Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; + C49B964EF7710D818E0AF0321724EEF4 /* errorIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@2x.png"; path = "SwiftMessages/Resources/errorIconLight@2x.png"; sourceTree = "<group>"; }; + C61DD3C66AC7ADE1E9CCFE7A4A0BEA59 /* TopBottomAnimationStyle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TopBottomAnimationStyle.swift; path = SwiftMessages/TopBottomAnimationStyle.swift; sourceTree = "<group>"; }; + C9BBC4BF82FBB152E34F2D1EF36A0FB1 /* MessageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageView.swift; path = SwiftMessages/MessageView.swift; sourceTree = "<group>"; }; + C9E8A4D41E0A0E52C839F7197C4CE2A0 /* AccessibleMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibleMessage.swift; path = SwiftMessages/AccessibleMessage.swift; sourceTree = "<group>"; }; + CBC3F501D8BC852716D085B3022E68CA /* Pods-iMessageExtensionDemo */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-iMessageExtensionDemo"; path = Pods_iMessageExtensionDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CC4854845AC1848C056C36719A5D7420 /* MaskingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MaskingView.swift; path = SwiftMessages/MaskingView.swift; sourceTree = "<group>"; }; CC9152C843976F18EF9AE005786DCC80 /* Pods-iMessageDemo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iMessageDemo.modulemap"; sourceTree = "<group>"; }; - D032FCFAE6607CF878AA2F35EF93146C /* successIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@3x.png"; path = "SwiftMessages/Resources/successIcon@3x.png"; sourceTree = "<group>"; }; - D1D69BE188B82D84ED23AC4E27BAB61D /* MaskingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MaskingView.swift; path = SwiftMessages/MaskingView.swift; sourceTree = "<group>"; }; + D091A06E439F734980F26F81E9161EF2 /* SwiftMessages-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SwiftMessages-dummy.m"; sourceTree = "<group>"; }; + D146564C0660B5F616D6736F6560E17C /* successIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@2x.png"; path = "SwiftMessages/Resources/successIconSubtle@2x.png"; sourceTree = "<group>"; }; D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - D261B7BE0088C26BF6744F27B894492A /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Extensions.swift"; path = "SwiftMessages/UIViewController+Extensions.swift"; sourceTree = "<group>"; }; - D30B2BF71F9D2C63C2D202C99827CDC1 /* errorIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@2x.png"; path = "SwiftMessages/Resources/errorIconLight@2x.png"; sourceTree = "<group>"; }; - D68834C60D0C5EA751E9F12E427C5FFE /* MarginAdjustable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MarginAdjustable.swift; path = SwiftMessages/MarginAdjustable.swift; sourceTree = "<group>"; }; - D8DEFE9675E5359A46A443182F127F06 /* WindowScene.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WindowScene.swift; path = SwiftMessages/WindowScene.swift; sourceTree = "<group>"; }; - D9AA0E820F1C1AA219C066370332845A /* WindowViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WindowViewController.swift; path = SwiftMessages/WindowViewController.swift; sourceTree = "<group>"; }; - DB6924EB5FC7236837637AE8F409000A /* NSLayoutConstraint+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSLayoutConstraint+Extensions.swift"; path = "SwiftMessages/NSLayoutConstraint+Extensions.swift"; sourceTree = "<group>"; }; - DEC0A6AE07C3285CA508F8FA3F4FE27D /* errorIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIcon.png; path = SwiftMessages/Resources/errorIcon.png; sourceTree = "<group>"; }; - DF3DE135AB5C5C789CABAECC704CE907 /* errorIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@2x.png"; path = "SwiftMessages/Resources/errorIcon@2x.png"; sourceTree = "<group>"; }; - E03CBB908F2EC39AA5DA7AF04E1BDDD6 /* PassthroughView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughView.swift; path = SwiftMessages/PassthroughView.swift; sourceTree = "<group>"; }; - E0E4D99C4F78B9BA011D83FE63EE0946 /* errorIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@3x.png"; path = "SwiftMessages/Resources/errorIcon@3x.png"; sourceTree = "<group>"; }; - E31D045D9E355D4F7F75564026B2051A /* errorIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@3x.png"; path = "SwiftMessages/Resources/errorIconSubtle@3x.png"; sourceTree = "<group>"; }; - E41BFEB1BFF85793C0DB85F95184B752 /* infoIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIcon.png; path = SwiftMessages/Resources/infoIcon.png; sourceTree = "<group>"; }; + D47C1471CCFFBEF214DF9F0ECBDD408B /* warningIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIcon.png; path = SwiftMessages/Resources/warningIcon.png; sourceTree = "<group>"; }; + D6A205E933052E98349DC710D78304CB /* errorIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@3x.png"; path = "SwiftMessages/Resources/errorIconLight@3x.png"; sourceTree = "<group>"; }; + D83D1CC131CDAC7CA2C5BFD8701E8A79 /* SwiftMessages.Config+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "SwiftMessages.Config+Extensions.swift"; path = "SwiftMessages/SwiftMessages.Config+Extensions.swift"; sourceTree = "<group>"; }; + DBF30CA29E00D6768396013A24DDE9E9 /* SwiftMessages.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.debug.xcconfig; sourceTree = "<group>"; }; E473E4F019E816262A61B7F5E8B42373 /* Pods-iMessageDemo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-iMessageDemo-acknowledgements.markdown"; sourceTree = "<group>"; }; - E936107A7CF9821DCBFFAF50D916F1E6 /* infoIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@2x.png"; path = "SwiftMessages/Resources/infoIcon@2x.png"; sourceTree = "<group>"; }; - E9E929B0E2A84EA903C9923B926A44E2 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = "<group>"; }; + EA8BFA921A44ED7AEAA0E08BCE17EDDA /* HapticMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HapticMessage.swift; path = SwiftMessages/HapticMessage.swift; sourceTree = "<group>"; }; EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - EABF0CEB87991D02E13306975A8E80BB /* TabView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = TabView.xib; path = SwiftMessages/Resources/TabView.xib; sourceTree = "<group>"; }; - EC6264350B8D100D5B5C5EEEC316933D /* SwiftMessages.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessages.swift; path = SwiftMessages/SwiftMessages.swift; sourceTree = "<group>"; }; - EFD31968BF9DF7A9E25A136DF254F3A9 /* Identifiable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Identifiable.swift; path = SwiftMessages/Identifiable.swift; sourceTree = "<group>"; }; - F513F2674553CBC247EE4B24EA25C99C /* Presenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Presenter.swift; path = SwiftMessages/Presenter.swift; sourceTree = "<group>"; }; - F9CDB54E629D60FF881DF27B949F4C2D /* infoIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconSubtle.png; path = SwiftMessages/Resources/infoIconSubtle.png; sourceTree = "<group>"; }; - FA199E6F18AB8900B5400EBA0EB32765 /* successIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@3x.png"; path = "SwiftMessages/Resources/successIconLight@3x.png"; sourceTree = "<group>"; }; - FC12F21544AE9FE6D9E1E2F7730EF7EC /* LICENSE.md */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE.md; sourceTree = "<group>"; }; - FFB0D50D01FFFA3FC2099E395029AE68 /* warningIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@2x.png"; path = "SwiftMessages/Resources/warningIconLight@2x.png"; sourceTree = "<group>"; }; + EC10D7DB2D227D4AA8F41CDFDDC24F37 /* SwiftMessages.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessages.swift; path = SwiftMessages/SwiftMessages.swift; sourceTree = "<group>"; }; + EC387534FD34764D4CC28B276A500AD6 /* errorIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconLight.png; path = SwiftMessages/Resources/errorIconLight.png; sourceTree = "<group>"; }; + EDFC2E756AAB98672C4B241097AAF0F6 /* errorIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconSubtle.png; path = SwiftMessages/Resources/errorIconSubtle.png; sourceTree = "<group>"; }; + F67BD26788FA0C70E942A7629E41C5E8 /* Animator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Animator.swift; path = SwiftMessages/Animator.swift; sourceTree = "<group>"; }; + FBC808D0C98F682E01DC43B544ED093F /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIWindow+Extensions.swift"; path = "SwiftMessages/UIWindow+Extensions.swift"; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 495E35DFE0854ABB7E2A238D1CFC4550 /* Frameworks */ = { + 534FFF2C8F91B03C61DA3655C52CCCA2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C3CDAED707B153A58674CB1AC4A33FB2 /* Foundation.framework in Frameworks */, + 60F02D519964FFEE8A21221FF5E0B0C5 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 9DEA36BAD403380FF5C38B4F2B4C3AB9 /* Frameworks */ = { + A018844B6146EA7B81717B756ED28077 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + A8C4AD87F73E9C51F797F34BCFF5AA17 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - EF08D4F0B96CF6C9AB42DC368EE3849A /* Frameworks */ = { + C38F39DB95AA37C32F6FD3963E1EC781 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9DA2F2EED5C99045AF44FF410A012F9D /* Foundation.framework in Frameworks */, - ECE268E9A63198F53B3F0337B3EA8AF3 /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - F2C6C6F4FCF31DEB85ADCA0DE9EF6EEC /* Frameworks */ = { + F5DA2E5126F8D945676819F4BFBBFFEB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A9EB0C8E49AB748B05CF7941ACAF8475 /* Foundation.framework in Frameworks */, + 3479628DE3B6C9005316A7F591F5E68F /* Foundation.framework in Frameworks */, + E4906D67B9F27E11EE9F8E8F5C847A14 /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 089392E699971024974E80EFFB25EE61 /* AppExtension */ = { + 0949E0D44EEAC7E812C141F4941C490F /* AppExtension */ = { isa = PBXGroup; children = ( - 0201BC51C7CA061016B619400691A139 /* AccessibleMessage.swift */, - 8D219D80184B8ED97808EE17507B213A /* Animator.swift */, - C706F1F1C6B3CE84445485C8577D5388 /* BackgroundViewable.swift */, - C7EE64CFE0084CF5213A03AF29A668ED /* BaseView.swift */, - 467EAD44C7F625F384822180F004E64F /* CALayer+Extensions.swift */, - 705B5AF043D00B6538599B4EB1ECD77C /* CardView.xib */, - 787EE6DA4FBC3BF85ED2CF0BB6EBF494 /* CenteredView.xib */, - 007ACA6F89C6C856F78352A086F3B8EA /* CornerRoundingView.swift */, - C5E610C06F5B006DE57F34D5994532FB /* Error.swift */, - DEC0A6AE07C3285CA508F8FA3F4FE27D /* errorIcon.png */, - DF3DE135AB5C5C789CABAECC704CE907 /* errorIcon@2x.png */, - E0E4D99C4F78B9BA011D83FE63EE0946 /* errorIcon@3x.png */, - 7100245A2722BD53D5B3927ED649069F /* errorIconLight.png */, - D30B2BF71F9D2C63C2D202C99827CDC1 /* errorIconLight@2x.png */, - 4D34E3F2A49E9024A96334DA4147F27B /* errorIconLight@3x.png */, - C787DA4E67B952C984FF5B065E0A2FF7 /* errorIconSubtle.png */, - 468D9889455DE51BD5BBC2360BDBB877 /* errorIconSubtle@2x.png */, - E31D045D9E355D4F7F75564026B2051A /* errorIconSubtle@3x.png */, - EFD31968BF9DF7A9E25A136DF254F3A9 /* Identifiable.swift */, - E41BFEB1BFF85793C0DB85F95184B752 /* infoIcon.png */, - E936107A7CF9821DCBFFAF50D916F1E6 /* infoIcon@2x.png */, - 48DC3BADDA3A20F2AEB8585117DAFA0D /* infoIcon@3x.png */, - 730840765E737D45772EBE66DB8A6D2E /* infoIconLight.png */, - 8315EA451FE61625920FEF68174A0D22 /* infoIconLight@2x.png */, - 676F359BE8561CF7512DB8B42CD7873A /* infoIconLight@3x.png */, - F9CDB54E629D60FF881DF27B949F4C2D /* infoIconSubtle.png */, - 45844D489A130BA91E91E7CDD4969862 /* infoIconSubtle@2x.png */, - C9F5DBB6D77B1E61E9BB1A722A4E1823 /* infoIconSubtle@3x.png */, - 90AC342C6F09BF7715D4FB95512DD68A /* KeyboardTrackingView.swift */, - D68834C60D0C5EA751E9F12E427C5FFE /* MarginAdjustable.swift */, - 7C8214A441D845A4A4DD6570FD5D458F /* MarginAdjustable+Extensions.swift */, - D1D69BE188B82D84ED23AC4E27BAB61D /* MaskingView.swift */, - 778F6E19CE49B8EDBAC2FCCD8195A55B /* MessageView.swift */, - B8A4CCB4B08D2D3BE586212AB4167DC2 /* MessageView.xib */, - 3E2EB968B30DE56F38B5FCFFEDE9F88F /* NSBundle+Extensions.swift */, - DB6924EB5FC7236837637AE8F409000A /* NSLayoutConstraint+Extensions.swift */, - E03CBB908F2EC39AA5DA7AF04E1BDDD6 /* PassthroughView.swift */, - 1A331C2E0BE2AE2118D65AA1F12519F2 /* PassthroughWindow.swift */, - 0D2B448BE319CF56A38E222C0B7DF4CB /* PhysicsAnimation.swift */, - BDEF50CAF615897F7A8540579B445634 /* PhysicsPanHandler.swift */, - F513F2674553CBC247EE4B24EA25C99C /* Presenter.swift */, - 1E2FE4DB6869F330F19A3A5459AAFFFB /* StatusLine.xib */, - A342E145FED9CD8DB4F464D110203E7C /* successIcon.png */, - 79D34B3C6875DA0279CB934C84CD000B /* successIcon@2x.png */, - D032FCFAE6607CF878AA2F35EF93146C /* successIcon@3x.png */, - 52F1CA85E0EED7D94FE0036BC92EB3EC /* successIconLight.png */, - 760BFB41B33B6ED91B3FFD68D39083A0 /* successIconLight@2x.png */, - FA199E6F18AB8900B5400EBA0EB32765 /* successIconLight@3x.png */, - B031268635405AA009D05130C0FC253C /* successIconSubtle.png */, - 91D9224F29E092950BADC27C979E10CC /* successIconSubtle@2x.png */, - 17ADABD24F805C5F7FF62167E7ABEF0A /* successIconSubtle@3x.png */, - EC6264350B8D100D5B5C5EEEC316933D /* SwiftMessages.swift */, - 5A16E25077F8D76288BE678E6AC1C884 /* SwiftMessages.Config+Extensions.swift */, - BF27E3EF103BACDEE8CA842B2C90C8CA /* SwiftMessagesSegue.swift */, - EABF0CEB87991D02E13306975A8E80BB /* TabView.xib */, - 24021DCE87BE9746D1DFB436C0A3AF7A /* Theme.swift */, - 0AF65ECDAFAD03A79B5571C6F66D8F35 /* TopBottomAnimation.swift */, - 36F7B24601DF4C00B14EC8CE2D4A48DC /* UIEdgeInsets+Extensions.swift */, - D261B7BE0088C26BF6744F27B894492A /* UIViewController+Extensions.swift */, - 753B78926D6BB175E96AB6E6F3514E87 /* UIWindow+Extensions.swift */, - 3259F99D03B6D738D7F47A625E7BD3BE /* warningIcon.png */, - 29A39558830996C4F54686A1748B74B1 /* warningIcon@2x.png */, - 0038C9A582787F9882258E8D1080EACF /* warningIcon@3x.png */, - C56AB83FDAB8D6A1328E7EECCAD99A69 /* warningIconLight.png */, - FFB0D50D01FFFA3FC2099E395029AE68 /* warningIconLight@2x.png */, - 7C4DF53A4B44C246968618BF25962786 /* warningIconLight@3x.png */, - 860D833A7A1B108A89ED34AD74778AC0 /* warningIconSubtle.png */, - 8AD355ED684A939F2A4E333F95E8AC31 /* warningIconSubtle@2x.png */, - A0EE84E98A10805A2D64B836C465ED11 /* warningIconSubtle@3x.png */, - 88D73E42D996B226222A4EBA46F7DC6D /* Weak.swift */, - D8DEFE9675E5359A46A443182F127F06 /* WindowScene.swift */, - D9AA0E820F1C1AA219C066370332845A /* WindowViewController.swift */, + C9E8A4D41E0A0E52C839F7197C4CE2A0 /* AccessibleMessage.swift */, + F67BD26788FA0C70E942A7629E41C5E8 /* Animator.swift */, + 86C1C9601BF8A5BC563062C310C0E3B5 /* BackgroundViewable.swift */, + 790409B3FBA491A9262ACCB929F30104 /* BaseView.swift */, + 35F5FB13175EC0E13D53B445CE31395A /* CALayer+Extensions.swift */, + 03B5D12D54ACC75F929389CFF15E91FF /* CardView.xib */, + 975A42F4C16B65B38769916EC5468D2A /* CenteredView.xib */, + 86872F4639B26435D20BED0CE7E35C7F /* CornerRoundingView.swift */, + 9414B7316138752779A4B9C7E5C988DB /* Error.swift */, + 71D489FBDD84B41576199298F717BC08 /* errorIcon.png */, + 8605740B16E17342A29212D21C380249 /* errorIcon@2x.png */, + 91013DDC05BDB2787740B0C9E5444D23 /* errorIcon@3x.png */, + EC387534FD34764D4CC28B276A500AD6 /* errorIconLight.png */, + C49B964EF7710D818E0AF0321724EEF4 /* errorIconLight@2x.png */, + D6A205E933052E98349DC710D78304CB /* errorIconLight@3x.png */, + EDFC2E756AAB98672C4B241097AAF0F6 /* errorIconSubtle.png */, + 38D28C78FCAE6706F1294CEFA6B25F88 /* errorIconSubtle@2x.png */, + 6C12E87D0EA045A56FC0B45F072C74D2 /* errorIconSubtle@3x.png */, + EA8BFA921A44ED7AEAA0E08BCE17EDDA /* HapticMessage.swift */, + 88398B7A70E5B00495B670516D964701 /* Identifiable.swift */, + 79A086337846180B9A63D8492CCE45B4 /* infoIcon.png */, + 2CF5DC74916EBE02E70234620CD80150 /* infoIcon@2x.png */, + 560722B244EB84DF745199247129C164 /* infoIcon@3x.png */, + C3701E97FDB85EFCE90E06D8CBC8ED41 /* infoIconLight.png */, + ACCCF5B75EA41D844ED936A92602C5B1 /* infoIconLight@2x.png */, + 88237113DAAD8ECF8D5E3FAA27D8A02F /* infoIconLight@3x.png */, + A6C7FF0D9E13571262231B72D0553E49 /* infoIconSubtle.png */, + 8026A87EEBF1A86A282563F974C4225C /* infoIconSubtle@2x.png */, + C40BBCF3A77C5C7A01708634BB4275C3 /* infoIconSubtle@3x.png */, + 9A99EE79DBFA3C24A372DDB69162E36C /* KeyboardTrackingView.swift */, + 14DF8F43552C4F1C4CAEFBAFD9A77004 /* MarginAdjustable.swift */, + 9B602E4E64DAEF1468DD2F5C2C5DFD00 /* MarginAdjustable+Extensions.swift */, + CC4854845AC1848C056C36719A5D7420 /* MaskingView.swift */, + 28456F0421422D16D71D14D426309B3F /* MessageGeometryProxy.swift */, + 5F989D33CAC3BCDA9B3C4B18F23A4DBE /* MessageHostingView.swift */, + C9BBC4BF82FBB152E34F2D1EF36A0FB1 /* MessageView.swift */, + A4D741EF8B40F5472CE2C1C1A34426BD /* MessageView.xib */, + 06DB4311BFB347093FC18777A503B461 /* MessageViewConvertible.swift */, + 073CD58B2E8E255484D239A01D707B81 /* NSBundle+Extensions.swift */, + 882EF814D0A1EE2AB28BFEE5C067EE6F /* NSLayoutConstraint+Extensions.swift */, + 03A865E97261799942A6F29092D3D7AE /* PassthroughView.swift */, + 0398CE267904AF6C2FD03B3766511ECF /* PassthroughWindow.swift */, + 8D7E08E0434930866B59A3F17A3A577B /* PhysicsAnimation.swift */, + 8AEEED9FBEA6C5DB7EE3B95E7D8115B3 /* PhysicsPanHandler.swift */, + 8D18688EA04EA2F2BC48ED05D1FE5404 /* Presenter.swift */, + 62332870F1E2AE3FA16EE5ADC85C104A /* StatusLine.xib */, + 74793ADC8ADF7674EA6C3041E2B54354 /* successIcon.png */, + 4DBF06E9B2F93F081139B8A6A922F569 /* successIcon@2x.png */, + 6EA088414C10E47808EA8490D9BBF64F /* successIcon@3x.png */, + 252A5DF0FE3237691B8C50B969857389 /* successIconLight.png */, + 44DAC25C8D6D72F70BD1CF9099BDAF10 /* successIconLight@2x.png */, + 5686DFC1E0B24A3051EF376AD8A162C0 /* successIconLight@3x.png */, + 7B9CEE1B17C98E76723E7404C532515D /* successIconSubtle.png */, + D146564C0660B5F616D6736F6560E17C /* successIconSubtle@2x.png */, + 47A710678B44C50DA470D1BCF94B87B8 /* successIconSubtle@3x.png */, + B19DACBEC8DD85FB850D299DFB7A0374 /* SwiftMessageModifier.swift */, + EC10D7DB2D227D4AA8F41CDFDDC24F37 /* SwiftMessages.swift */, + D83D1CC131CDAC7CA2C5BFD8701E8A79 /* SwiftMessages.Config+Extensions.swift */, + B17EF282E0A0F329DDF17226E83706F8 /* SwiftMessagesSegue.swift */, + C33B3DA756F19F5C93D498D557BEB820 /* TabView.xib */, + 9610DCAAD9A55CDF73BAD54D523E1273 /* Task+Extensions.swift */, + B32459A84426DD5E88256AD61F3D4E91 /* Theme.swift */, + A1F1B1264A726D334A72AB1CB001CA9F /* TopBottomAnimation.swift */, + C61DD3C66AC7ADE1E9CCFE7A4A0BEA59 /* TopBottomAnimationStyle.swift */, + A102DE8896931D80E06F2C74C2B003AC /* TopBottomPresentable.swift */, + 16B5B2B5429B01345E4DA361DE01904D /* UIEdgeInsets+Extensions.swift */, + 57EB79F63EA99ADBBDA408015A4599BB /* UIViewController+Extensions.swift */, + FBC808D0C98F682E01DC43B544ED093F /* UIWindow+Extensions.swift */, + D47C1471CCFFBEF214DF9F0ECBDD408B /* warningIcon.png */, + B241F1B5D295E7806363B802DF03A085 /* warningIcon@2x.png */, + B8B9892D8D5596E09F02DA2D71BF60B4 /* warningIcon@3x.png */, + 004EE347886E2355CCB352F2AE7A35D6 /* warningIconLight.png */, + 71699C81494BC6585B862CDFC1CDAF54 /* warningIconLight@2x.png */, + 5FE01208AD70F1B35201AB04E50A23EC /* warningIconLight@3x.png */, + 6924A0A48B715EA35080ABB106B96BF7 /* warningIconSubtle.png */, + 85C6BEF274CDB3807F9BD452A26C68E6 /* warningIconSubtle@2x.png */, + 5E02B1554754BA1F8EF318D567875139 /* warningIconSubtle@3x.png */, + 442F9FAEDF369CADB9E6E8FF3668FD95 /* Weak.swift */, + 2AB9866F195EB0AED31A33AEC27B67C1 /* WindowScene.swift */, + 9908774A62A95BF5BA8FE65842868043 /* WindowViewController.swift */, ); name = AppExtension; sourceTree = "<group>"; @@ -349,51 +373,45 @@ name = Frameworks; sourceTree = "<group>"; }; - 423F06E259421657656F08FC805160BA /* Products */ = { + 367D4F82667A10E742DF94EEDD05B67C /* Pod */ = { isa = PBXGroup; children = ( - AFC41396FB1BD59C9A69EE1DD82E47C2 /* Pods_iMessageDemo.framework */, - CBC3F501D8BC852716D085B3022E68CA /* Pods_iMessageExtensionDemo.framework */, - 4824F23D80FF9070A5F8A452DB11EB9A /* SwiftMessages.framework */, - BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages_SwiftMessages.bundle */, + 9D5A75A919AE6C6D38A627636D7ADC11 /* LICENSE.md */, + A399825CF45C4427BF9B80A590BF2BD5 /* README.md */, + 573965F15F83BD70EEAC9E1E8B0F85C6 /* SwiftMessages.podspec */, ); - name = Products; + name = Pod; sourceTree = "<group>"; }; - 59DA5C1F72E1D5BABC43EACBA672C3BA /* iOS */ = { + 3B07A3E7DF9452FD2B994A3383A19C32 /* SwiftMessages */ = { isa = PBXGroup; children = ( - EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */, - D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */, + 0949E0D44EEAC7E812C141F4941C490F /* AppExtension */, + 367D4F82667A10E742DF94EEDD05B67C /* Pod */, + D1F228CBB00BC0EEBE5243BDCD591903 /* Support Files */, ); - name = iOS; + name = SwiftMessages; + path = ../..; sourceTree = "<group>"; }; - 5EAB54907DABB41DF2E9177067EF69D4 /* SwiftMessages */ = { + 46F000C5D88847E6B7EDC4BA40536149 /* Products */ = { isa = PBXGroup; children = ( - 089392E699971024974E80EFFB25EE61 /* AppExtension */, - E7706B1F04CCC75F42C733B60ED5FBDC /* Pod */, - 7C00C98D65B96C8BDE003F39DAFBBBDE /* Support Files */, + AFC41396FB1BD59C9A69EE1DD82E47C2 /* Pods-iMessageDemo */, + CBC3F501D8BC852716D085B3022E68CA /* Pods-iMessageExtensionDemo */, + 4824F23D80FF9070A5F8A452DB11EB9A /* SwiftMessages */, + BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages-SwiftMessages_SwiftMessages */, ); - name = SwiftMessages; - path = ../..; + name = Products; sourceTree = "<group>"; }; - 7C00C98D65B96C8BDE003F39DAFBBBDE /* Support Files */ = { + 59DA5C1F72E1D5BABC43EACBA672C3BA /* iOS */ = { isa = PBXGroup; children = ( - 141AADF8046C9D5EC8E194DF662BAC41 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */, - 0BEC185781E869FB5FDB7F10538230C7 /* SwiftMessages.modulemap */, - 9C6E00017F9E79F6D4926E9CB43A66DF /* SwiftMessages-dummy.m */, - 74C53DDA65E08AD7274EA6625408AB99 /* SwiftMessages-Info.plist */, - 1ED635B9451869879B1A404F00C3CCC7 /* SwiftMessages-prefix.pch */, - 9CBEAC9D0EF4113C3FD3B15F511A92D0 /* SwiftMessages-umbrella.h */, - 87745BF2C7154EF88509BED0D71243F1 /* SwiftMessages.debug.xcconfig */, - B7BF853CD0CDFA20423D4C813B34B57F /* SwiftMessages.release.xcconfig */, + EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */, + D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */, ); - name = "Support Files"; - path = "iMessageDemo/Pods/Target Support Files/SwiftMessages"; + name = iOS; sourceTree = "<group>"; }; 8F3CF4AFB0CA47B3BFE1C68E51CDF0A9 /* Targets Support Files */ = { @@ -441,7 +459,7 @@ C5AAA95D48373FAC474F6EFCC1749444 /* Development Pods */ = { isa = PBXGroup; children = ( - 5EAB54907DABB41DF2E9177067EF69D4 /* SwiftMessages */, + 3B07A3E7DF9452FD2B994A3383A19C32 /* SwiftMessages */, ); name = "Development Pods"; sourceTree = "<group>"; @@ -452,45 +470,51 @@ 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, C5AAA95D48373FAC474F6EFCC1749444 /* Development Pods */, 1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */, - 423F06E259421657656F08FC805160BA /* Products */, + 46F000C5D88847E6B7EDC4BA40536149 /* Products */, 8F3CF4AFB0CA47B3BFE1C68E51CDF0A9 /* Targets Support Files */, ); sourceTree = "<group>"; }; - E7706B1F04CCC75F42C733B60ED5FBDC /* Pod */ = { + D1F228CBB00BC0EEBE5243BDCD591903 /* Support Files */ = { isa = PBXGroup; children = ( - FC12F21544AE9FE6D9E1E2F7730EF7EC /* LICENSE.md */, - E9E929B0E2A84EA903C9923B926A44E2 /* README.md */, - 59FEAC25BE3FCB9F8373DE26400CC89D /* SwiftMessages.podspec */, + 8940290DCDAD08810FE0CD944F376444 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */, + 6228A8E37F7905D75917DD4CBE65B03C /* SwiftMessages.modulemap */, + D091A06E439F734980F26F81E9161EF2 /* SwiftMessages-dummy.m */, + 0FD758C8718F3EEFB5E97E34A29CE1CC /* SwiftMessages-Info.plist */, + B941E5186F814BF618D9D0458496379C /* SwiftMessages-prefix.pch */, + 080E269BABA7D072D8C51E29E9AC4A91 /* SwiftMessages-umbrella.h */, + DBF30CA29E00D6768396013A24DDE9E9 /* SwiftMessages.debug.xcconfig */, + BA61C87AB568667230DCD9DC2E423722 /* SwiftMessages.release.xcconfig */, ); - name = Pod; + name = "Support Files"; + path = "iMessageDemo/Pods/Target Support Files/SwiftMessages"; sourceTree = "<group>"; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 21076A86F5547DA5AEE656FE5EC63826 /* Headers */ = { + 5E0996100D0B6376DB378D36C49FEB72 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - AD7F228AE0628DAAE4497493335D2BF7 /* SwiftMessages-umbrella.h in Headers */, + 88D024879AEAE247899BFB50C8516515 /* Pods-iMessageDemo-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 96A1C098516CB9F20C4BE19860673FA7 /* Headers */ = { + 94D488A57BCCF0DF1CE9E3AA109BAF42 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 560A2B1056FEFE42AC6524A2A1742CA2 /* Pods-iMessageExtensionDemo-umbrella.h in Headers */, + 7590FF543E2634A83059E509D5B05583 /* Pods-iMessageExtensionDemo-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - AEC231A576EA094C9EF913D75BA2D69C /* Headers */ = { + 9F82EEB2B7A573A17661E879E23301CC /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 7BC52E6F0D9D19B05E62E623E53FCE82 /* Pods-iMessageDemo-umbrella.h in Headers */, + B646E1CD53F14E0DEE53740799C06AC5 /* SwiftMessages-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -499,76 +523,76 @@ /* Begin PBXNativeTarget section */ 1FC5E8328653C350899229BDF89FACE5 /* SwiftMessages-SwiftMessages_SwiftMessages */ = { isa = PBXNativeTarget; - buildConfigurationList = 1B3FEB13A547A2F656C2328E0CE130B5 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages_SwiftMessages" */; + buildConfigurationList = B9E25A37EB36EDFCDE7B709EF28887E1 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages_SwiftMessages" */; buildPhases = ( - FFA9EA2B25A56389D60078D35A7276A6 /* Sources */, - 9DEA36BAD403380FF5C38B4F2B4C3AB9 /* Frameworks */, - BF76892AD99FBDD7554F3F71E205A3B6 /* Resources */, + 27425DAD651893A17CC601370E148AA6 /* Sources */, + C38F39DB95AA37C32F6FD3963E1EC781 /* Frameworks */, + B677C83AAEA5EB9CD3E80A8BA2A910E7 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "SwiftMessages-SwiftMessages_SwiftMessages"; - productName = "SwiftMessages-SwiftMessages_SwiftMessages"; - productReference = BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages_SwiftMessages.bundle */; + productName = SwiftMessages_SwiftMessages; + productReference = BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages-SwiftMessages_SwiftMessages */; productType = "com.apple.product-type.bundle"; }; 2757367020CF4EA7726D56118C89F6AE /* Pods-iMessageExtensionDemo */ = { isa = PBXNativeTarget; - buildConfigurationList = ED0C46CBFB7B22526D6F384198E16114 /* Build configuration list for PBXNativeTarget "Pods-iMessageExtensionDemo" */; + buildConfigurationList = D4007834B8D8DEA14D3016E025D2E198 /* Build configuration list for PBXNativeTarget "Pods-iMessageExtensionDemo" */; buildPhases = ( - 96A1C098516CB9F20C4BE19860673FA7 /* Headers */, - 26079E47AEA7D168B2259F29AF1AE73B /* Sources */, - 495E35DFE0854ABB7E2A238D1CFC4550 /* Frameworks */, - B1A8F08DE3F2C1EF1D63EF29C9D3D327 /* Resources */, + 94D488A57BCCF0DF1CE9E3AA109BAF42 /* Headers */, + 7C2BDA53E99CB24205C4C877E7B01D37 /* Sources */, + A018844B6146EA7B81717B756ED28077 /* Frameworks */, + 1A38555F56C7853980EFF926359385D4 /* Resources */, ); buildRules = ( ); dependencies = ( - 4D52C266BAECF408C5DEB677038E1EEA /* PBXTargetDependency */, + 8935DBBDEDCE7F48711B98D9DB279717 /* PBXTargetDependency */, ); name = "Pods-iMessageExtensionDemo"; - productName = "Pods-iMessageExtensionDemo"; - productReference = CBC3F501D8BC852716D085B3022E68CA /* Pods_iMessageExtensionDemo.framework */; + productName = Pods_iMessageExtensionDemo; + productReference = CBC3F501D8BC852716D085B3022E68CA /* Pods-iMessageExtensionDemo */; productType = "com.apple.product-type.framework"; }; DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */ = { isa = PBXNativeTarget; - buildConfigurationList = 7D9EC6095BF15A96EABE2FE5045DA5DE /* Build configuration list for PBXNativeTarget "SwiftMessages" */; + buildConfigurationList = BC0696CE4F28B31FF26CA99798FE7058 /* Build configuration list for PBXNativeTarget "SwiftMessages" */; buildPhases = ( - 21076A86F5547DA5AEE656FE5EC63826 /* Headers */, - E0A3D02CDE28535DB4F00412E5814A99 /* Sources */, - EF08D4F0B96CF6C9AB42DC368EE3849A /* Frameworks */, - 036D5B81C59A567C797D02AA3A18D7F4 /* Resources */, + 9F82EEB2B7A573A17661E879E23301CC /* Headers */, + F72FF659E811A6D8DFB11AE35F7C3B09 /* Sources */, + F5DA2E5126F8D945676819F4BFBBFFEB /* Frameworks */, + 3825F2CC81138FAE9F77136A6C646663 /* Resources */, ); buildRules = ( ); dependencies = ( - 35EE405E4B00027013209FA505020C1C /* PBXTargetDependency */, + E98E5B4F9A2B7044ED32678F81832AEE /* PBXTargetDependency */, ); name = SwiftMessages; productName = SwiftMessages; - productReference = 4824F23D80FF9070A5F8A452DB11EB9A /* SwiftMessages.framework */; + productReference = 4824F23D80FF9070A5F8A452DB11EB9A /* SwiftMessages */; productType = "com.apple.product-type.framework"; }; E2AECC8B9DD9E437C7DD0FD0FFC881F3 /* Pods-iMessageDemo */ = { isa = PBXNativeTarget; - buildConfigurationList = 20A82A14E31D7EFF5BE9B60529162F4B /* Build configuration list for PBXNativeTarget "Pods-iMessageDemo" */; + buildConfigurationList = 1A195C86FC7EF00767CF99ECEBE42625 /* Build configuration list for PBXNativeTarget "Pods-iMessageDemo" */; buildPhases = ( - AEC231A576EA094C9EF913D75BA2D69C /* Headers */, - 41C8F9B8F0E317E193B01E8DC96E6F02 /* Sources */, - F2C6C6F4FCF31DEB85ADCA0DE9EF6EEC /* Frameworks */, - 61DB2F41473C1B8FEA6385AA240E2586 /* Resources */, + 5E0996100D0B6376DB378D36C49FEB72 /* Headers */, + 0642123BC3DE909207A9EC283F481AD9 /* Sources */, + 534FFF2C8F91B03C61DA3655C52CCCA2 /* Frameworks */, + 9859D25D3582DB4C5A3D5ADA90024549 /* Resources */, ); buildRules = ( ); dependencies = ( - 50C0F94C8A0A997FF42A574D8367A3C7 /* PBXTargetDependency */, + 5AEACA50B99030606B5CAF987F9793FD /* PBXTargetDependency */, ); name = "Pods-iMessageDemo"; - productName = "Pods-iMessageDemo"; - productReference = AFC41396FB1BD59C9A69EE1DD82E47C2 /* Pods_iMessageDemo.framework */; + productName = Pods_iMessageDemo; + productReference = AFC41396FB1BD59C9A69EE1DD82E47C2 /* Pods-iMessageDemo */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ @@ -577,19 +601,19 @@ BFDFE7DC352907FC980B868725387E98 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1100; - LastUpgradeCheck = 1100; + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; }; buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; - compatibilityVersion = "Xcode 9.3"; + compatibilityVersion = "Xcode 12.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - en, Base, + en, ); mainGroup = CF1408CF629C7361332E53B88F7BD30C; - productRefGroup = 423F06E259421657656F08FC805160BA /* Products */; + productRefGroup = 46F000C5D88847E6B7EDC4BA40536149 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( @@ -602,173 +626,182 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 036D5B81C59A567C797D02AA3A18D7F4 /* Resources */ = { + 1A38555F56C7853980EFF926359385D4 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 47F1E9964F1112D0E8F0FF8C25204E2F /* SwiftMessages_SwiftMessages.bundle in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 61DB2F41473C1B8FEA6385AA240E2586 /* Resources */ = { + 3825F2CC81138FAE9F77136A6C646663 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 28D6446B971F186BACDED83CD8DE4D44 /* SwiftMessages-SwiftMessages_SwiftMessages in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - B1A8F08DE3F2C1EF1D63EF29C9D3D327 /* Resources */ = { + 9859D25D3582DB4C5A3D5ADA90024549 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - BF76892AD99FBDD7554F3F71E205A3B6 /* Resources */ = { + B677C83AAEA5EB9CD3E80A8BA2A910E7 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - A67A9ADFBCB364FCEF1BD92FF20B285C /* CardView.xib in Resources */, - 9F0473806FD530165403E47E834790C2 /* CenteredView.xib in Resources */, - 9B1E91097B4BD539EBCBBCC3C62CB75A /* errorIcon.png in Resources */, - ADA91E8F5FDCD2EEC3D3B18A5B375C2C /* errorIcon@2x.png in Resources */, - A9FFA668A7F81F50FBDCDCE26E891C8B /* errorIcon@3x.png in Resources */, - 11DE7052A0A78D6E27D8D129D413DAF6 /* errorIconLight.png in Resources */, - 34CB62900FA4AAC84745C7E958657648 /* errorIconLight@2x.png in Resources */, - FDC2C20416D7EBF959A461E25FAFB16E /* errorIconLight@3x.png in Resources */, - E70A6E572A6DD457A766908E3ADCF49B /* errorIconSubtle.png in Resources */, - 668EDAB86421216BEF7D3F932851A834 /* errorIconSubtle@2x.png in Resources */, - F69D9D53A5500A42D4B41097537628E5 /* errorIconSubtle@3x.png in Resources */, - 8F1BAB73C85D58C56F55E91573C2E7EF /* infoIcon.png in Resources */, - ADE48B746D5BB28EC33B403E1E12E0FE /* infoIcon@2x.png in Resources */, - 5B9F8D117AF7BEDDB511EF475FA25995 /* infoIcon@3x.png in Resources */, - 4B907B48F27F55DF65CC1553C7C26942 /* infoIconLight.png in Resources */, - CC9369D0A5F8715733A4D517E45A3B63 /* infoIconLight@2x.png in Resources */, - B4D338F85183163DC8CAB8A5864C9015 /* infoIconLight@3x.png in Resources */, - 62B05E0AC13A614A2F8D8A1BE9B514B3 /* infoIconSubtle.png in Resources */, - 9CFE7FFD7DDE28FCDA72647F2DB82837 /* infoIconSubtle@2x.png in Resources */, - C826D41BE5AF283B12C122AEF9640C99 /* infoIconSubtle@3x.png in Resources */, - 7B352022AFCAA5C364E1E2F61290628E /* MessageView.xib in Resources */, - 30D023ABC2D1CFC829CF04360768B7F8 /* StatusLine.xib in Resources */, - 95DD12BBA763163407787AB32AAF8E56 /* successIcon.png in Resources */, - C11CE75FD2DFCDF3B72D8D16280A2054 /* successIcon@2x.png in Resources */, - 755898E0E511FC5AE881403BEF2A02FC /* successIcon@3x.png in Resources */, - 80DE92140CF5AFB5224643FA952EFDEA /* successIconLight.png in Resources */, - ADA044C43E517C5F0603B2A0AFB19860 /* successIconLight@2x.png in Resources */, - C418A50F3C321227B0C6BE1D793680D4 /* successIconLight@3x.png in Resources */, - CD480EEF400EC9B894F3292506BF0179 /* successIconSubtle.png in Resources */, - 61548914728141D77F87E31B3911CE7E /* successIconSubtle@2x.png in Resources */, - 56F9865D99C4FADB8FC83CA548F82110 /* successIconSubtle@3x.png in Resources */, - 9FA48348FB5F41070356A75237367D6D /* TabView.xib in Resources */, - DECF1F62709D95EF5B48628A97B3CF98 /* warningIcon.png in Resources */, - 946185C05E253C9E47ABCD9EDE7E14D1 /* warningIcon@2x.png in Resources */, - B679ED0F79CAF552C081588F3B63B91A /* warningIcon@3x.png in Resources */, - 3A8B97D9210D1E2BEED5E1159BE7E748 /* warningIconLight.png in Resources */, - E8174481BFB4559462F82062D85C0376 /* warningIconLight@2x.png in Resources */, - 4B9459A11E2A1D65AE3224CF468AE8CA /* warningIconLight@3x.png in Resources */, - 1662CF43016AFC375200E466F130D90E /* warningIconSubtle.png in Resources */, - 6685298EC64F73060F5DB1A841375069 /* warningIconSubtle@2x.png in Resources */, - B02B2EAB7B8662AA27D91403BF9AAF36 /* warningIconSubtle@3x.png in Resources */, + A4724FC3B4F49DCBF50D395257BB6B8E /* CardView.xib in Resources */, + 469995B0FC2E3748F59D0E3A4445E197 /* CenteredView.xib in Resources */, + E54040398A9AD751393A2171DC64D70E /* errorIcon.png in Resources */, + 6A04C3E1C3437ED6BC6F096302B458AB /* errorIcon@2x.png in Resources */, + DE2531A67AEBFED61A060DF13790C3BE /* errorIcon@3x.png in Resources */, + 47EFB870CC797D2F54396F0AEBC8F576 /* errorIconLight.png in Resources */, + FC0E2BA3CD9C6C3ACF3681841D8EF5BA /* errorIconLight@2x.png in Resources */, + 1E507663F3C402CBCA0C50A876F472EF /* errorIconLight@3x.png in Resources */, + 360BEE76BBF40319E6638B3E027E1474 /* errorIconSubtle.png in Resources */, + 205A52121D20436063240893A461B29C /* errorIconSubtle@2x.png in Resources */, + 4980F404C2B391C621CE2BCF05E08BDF /* errorIconSubtle@3x.png in Resources */, + 8CB7CCDF07E1CE6838C7278BC19968B6 /* infoIcon.png in Resources */, + 096A6663757CB52C8A34B3E3146279C8 /* infoIcon@2x.png in Resources */, + 8F63F1ABAB21FA99A6CB1A54D5F2B5AA /* infoIcon@3x.png in Resources */, + 422B422F962FD298F963F84934A21529 /* infoIconLight.png in Resources */, + 3613DBA9CBD7E092BD7DC1924E6648D2 /* infoIconLight@2x.png in Resources */, + A52191D65F4C725EBF61D27F40FEA970 /* infoIconLight@3x.png in Resources */, + A90C06B459CC64A243DD1184024E5D22 /* infoIconSubtle.png in Resources */, + DC6C4E22FA8DD6FA491066A738132EF1 /* infoIconSubtle@2x.png in Resources */, + 6CDE06668BB53C70BF1456F8EEE845D9 /* infoIconSubtle@3x.png in Resources */, + 0D53997CCCD141D2303E87C29CEFE211 /* MessageView.xib in Resources */, + B61EBE61C31E78140BF12D32A008A43B /* StatusLine.xib in Resources */, + 31660027252C457325491844F16AEBDD /* successIcon.png in Resources */, + EE9A5A3877D99BFCA5DA70BA4E049CA9 /* successIcon@2x.png in Resources */, + 79BB175F4750822409AB9ED0A9D90D09 /* successIcon@3x.png in Resources */, + A8EF6BE26B31A8713E37E0629F6466EB /* successIconLight.png in Resources */, + 9FBBA6E4D3A2A4CA4BA8535E35D54CA8 /* successIconLight@2x.png in Resources */, + 61F532D30833A9FF1DE00EC98BC018C2 /* successIconLight@3x.png in Resources */, + 72026C4424B7A1650CBEED98ED9AA288 /* successIconSubtle.png in Resources */, + 37A8DD40AF13BCABE7A3CD8EF15A4C53 /* successIconSubtle@2x.png in Resources */, + BBF31491EF3411DCFA7E649645229E2A /* successIconSubtle@3x.png in Resources */, + 1441D5A06DD6903562EB794FC1AE8822 /* TabView.xib in Resources */, + D8DFC45149C57377B5C90B3457090564 /* warningIcon.png in Resources */, + 0ADA608E3B9307694DCF4D0BC426E7FE /* warningIcon@2x.png in Resources */, + 4C9FED5D268E82325C17309FB8904C43 /* warningIcon@3x.png in Resources */, + 4609D5EC365EABFE507781BF911B887B /* warningIconLight.png in Resources */, + 744EA4AF597AFEFEE5B398434F47CA26 /* warningIconLight@2x.png in Resources */, + 81B1015F29547CAB449757FC5ABCAFAB /* warningIconLight@3x.png in Resources */, + 6583C565BE5BB9E52213854AA85F5A93 /* warningIconSubtle.png in Resources */, + D3B31A631C754CAECABFA4DC672D3D0B /* warningIconSubtle@2x.png in Resources */, + 24DA4886290040A0EC88B63D82EF412D /* warningIconSubtle@3x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 26079E47AEA7D168B2259F29AF1AE73B /* Sources */ = { + 0642123BC3DE909207A9EC283F481AD9 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 46CCA4DDFDBBDD2A9426BB96C08E4255 /* Pods-iMessageExtensionDemo-dummy.m in Sources */, + 436D8C63FBE86FF8271ABC32F9A52A9D /* Pods-iMessageDemo-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 41C8F9B8F0E317E193B01E8DC96E6F02 /* Sources */ = { + 27425DAD651893A17CC601370E148AA6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C384FB76A48C06F7581D0F7850F2F4F1 /* Pods-iMessageDemo-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - E0A3D02CDE28535DB4F00412E5814A99 /* Sources */ = { + 7C2BDA53E99CB24205C4C877E7B01D37 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 02905CCF79B22A773CD0BA32EDB9648A /* AccessibleMessage.swift in Sources */, - F75A8D3DA9B4787BEEEBF3F784D5CDEF /* Animator.swift in Sources */, - DE23509CED3A1E62F60E7E4BD6D38A35 /* BackgroundViewable.swift in Sources */, - 4889E21A2024267A944084FB851200B5 /* BaseView.swift in Sources */, - 3BFC9F0FAF0757A2D3574ED4E4100D57 /* CALayer+Extensions.swift in Sources */, - 28F2E02536C48A4B661D6D8AAFB5D37E /* CornerRoundingView.swift in Sources */, - F9A111F30C3B26D0A35B0829EED70D26 /* Error.swift in Sources */, - 4256FC87C833154DCDEE84CD98F910D7 /* Identifiable.swift in Sources */, - 13620BA62A66C8C6F9345341BCD111ED /* KeyboardTrackingView.swift in Sources */, - 632538BAE98BBFD6CED58844B7611C24 /* MarginAdjustable+Extensions.swift in Sources */, - 7905F28CF56E06626475EBA3EB73D905 /* MarginAdjustable.swift in Sources */, - 0C55441C4B8356AC1244EED7684E1783 /* MaskingView.swift in Sources */, - 934A8FA91D6518CB70273B73F8038ECA /* MessageView.swift in Sources */, - F05B5437AFF475FE8811E2A8A734920F /* NSBundle+Extensions.swift in Sources */, - B520EDE98BD17CE5676F52A77139A933 /* NSLayoutConstraint+Extensions.swift in Sources */, - D34D8255545B84A38C98D2DBB2F12CC5 /* PassthroughView.swift in Sources */, - 05D9CBEC9488BAA2962B174703D25218 /* PassthroughWindow.swift in Sources */, - FA02B47E32DD9BEAAB8A2D1B66F697D5 /* PhysicsAnimation.swift in Sources */, - 9B1F7A4183F57B0AA9DD02624BD8855B /* PhysicsPanHandler.swift in Sources */, - F4BE83FBD5001DEDF6736E69ADA6D79B /* Presenter.swift in Sources */, - 00764FFD14D83F4ABEC0D4D53D48080A /* SwiftMessages-dummy.m in Sources */, - 5CA294C8D3BBC986CF0703D4E2A28687 /* SwiftMessages.Config+Extensions.swift in Sources */, - 4E82DE4069FECF20D0E29CB06A0FCFB6 /* SwiftMessages.swift in Sources */, - C739607C022819840C267A0B4A7B2FD9 /* SwiftMessagesSegue.swift in Sources */, - 9B89868BA12CC4E1D9F116F663E56695 /* Theme.swift in Sources */, - 6A933CC66558A1FB0AB0BC76F9807E71 /* TopBottomAnimation.swift in Sources */, - 531825CE7041C5C1BA684BDA9C8972A3 /* UIEdgeInsets+Extensions.swift in Sources */, - 9DBD1955C7C621D9DCBE03D2161C91A9 /* UIViewController+Extensions.swift in Sources */, - 94B459D6CBA2A01D2B8174D138C30920 /* UIWindow+Extensions.swift in Sources */, - 926907C8DCE76101AF5CB470DB7797D7 /* Weak.swift in Sources */, - AF34F903519AF36E07A90EF1BD703777 /* WindowScene.swift in Sources */, - AC0A9B473B11FFF4BDEC0A0598795843 /* WindowViewController.swift in Sources */, + B22AF07D79D1A82DE583AC49E3D472D3 /* Pods-iMessageExtensionDemo-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - FFA9EA2B25A56389D60078D35A7276A6 /* Sources */ = { + F72FF659E811A6D8DFB11AE35F7C3B09 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 03C7FA1BE62CCD280D63F4C7CDDFB27F /* AccessibleMessage.swift in Sources */, + D9519DD580DF2E744AB4C4087FA28BCD /* Animator.swift in Sources */, + A865FCE8718103C8E725EC1EC0F9F4F6 /* BackgroundViewable.swift in Sources */, + 6DC0B420F622E197919276CFF2C063CE /* BaseView.swift in Sources */, + 3F53FCE80C716C7DE7A3B1D8D65077BC /* CALayer+Extensions.swift in Sources */, + 274D5DE28E0446655163A48E2272860A /* CornerRoundingView.swift in Sources */, + CCBFBDB03B2444C911BADDE6A6BA08AD /* Error.swift in Sources */, + 47CC2A912B82A499DB2F5E2ADBE664CF /* HapticMessage.swift in Sources */, + 67F7D444EAC4475021B3458B21B2A162 /* Identifiable.swift in Sources */, + 3C566158256E9CC711B73810B2C64E3B /* KeyboardTrackingView.swift in Sources */, + 0C093AF5F4D753325F4CE92F2F943CB4 /* MarginAdjustable.swift in Sources */, + 634267873AC0F98140DBAFFF9A180BA8 /* MarginAdjustable+Extensions.swift in Sources */, + F8D0D33FC1C833490057108C322E56CB /* MaskingView.swift in Sources */, + B6D0E2FA454A946D6C9A7494648F49D9 /* MessageGeometryProxy.swift in Sources */, + 19C0F7897044E72D3A13DE703920FFE1 /* MessageHostingView.swift in Sources */, + A836F848C83565B2A0A06AB23D491946 /* MessageView.swift in Sources */, + C2031E7EC3C60B876F2AC04253D3AFC4 /* MessageViewConvertible.swift in Sources */, + 942468E4C1AEFCF10D5043243B4007E7 /* NSBundle+Extensions.swift in Sources */, + B1B4D240B65FFC5A7A981B9504C55270 /* NSLayoutConstraint+Extensions.swift in Sources */, + DD406A0C002AC1D02A6E5794B1729C22 /* PassthroughView.swift in Sources */, + BAB66573FF29F6337237A8DA0EB9E3E8 /* PassthroughWindow.swift in Sources */, + F667CC7C7F3285FC39427F2AAA8E7665 /* PhysicsAnimation.swift in Sources */, + F2D3ABB0C7B6EB5B531E4E68C40AA89C /* PhysicsPanHandler.swift in Sources */, + 158EF18377B720081C31C2F2100DDA7A /* Presenter.swift in Sources */, + 04BCE3C12FDE7E91C9EF1FE154E80E2B /* SwiftMessageModifier.swift in Sources */, + 330C59E62D17601422EDB29513B9856C /* SwiftMessages.swift in Sources */, + 67DC4D170143131B8AFFB558FDD00465 /* SwiftMessages-dummy.m in Sources */, + 48ADA8D4633776558E7D216434057A2A /* SwiftMessages.Config+Extensions.swift in Sources */, + 3451B2775584DD75A3BDF9BF28A03F76 /* SwiftMessagesSegue.swift in Sources */, + B04AA81A8A8CE0BCEFD5FAFD841F461F /* Task+Extensions.swift in Sources */, + E03C930AD56F078DCD1357E5C83AD67A /* Theme.swift in Sources */, + F516490B5276943A352D597431B079B6 /* TopBottomAnimation.swift in Sources */, + B9FDFA90A4FB68CA5357AB70427B4DCD /* TopBottomAnimationStyle.swift in Sources */, + 450919BA3A4D984DC24822CD80483419 /* TopBottomPresentable.swift in Sources */, + BA4779B82B35B85EFE9F595624BA3943 /* UIEdgeInsets+Extensions.swift in Sources */, + 698F203577674AFA4BBCDE93B01B9EEC /* UIViewController+Extensions.swift in Sources */, + 45A4B95F1F73413A3001B95E1F91D697 /* UIWindow+Extensions.swift in Sources */, + 00A4A53E0D1EFC70DA1EFAEFA82C4BA1 /* Weak.swift in Sources */, + 04C771EB4784B94AC6CA28ED6A919D50 /* WindowScene.swift in Sources */, + 52A01853AC4F2D0E720579D7F8A531CF /* WindowViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 35EE405E4B00027013209FA505020C1C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "SwiftMessages-SwiftMessages_SwiftMessages"; - target = 1FC5E8328653C350899229BDF89FACE5 /* SwiftMessages-SwiftMessages_SwiftMessages */; - targetProxy = D19F271ED5B0FED7305E55070B415EDB /* PBXContainerItemProxy */; - }; - 4D52C266BAECF408C5DEB677038E1EEA /* PBXTargetDependency */ = { + 5AEACA50B99030606B5CAF987F9793FD /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SwiftMessages; target = DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */; - targetProxy = 4B785BB517DA1D687C0B772C77660019 /* PBXContainerItemProxy */; + targetProxy = D297C84AE0F13FB6A76F2F391D21D679 /* PBXContainerItemProxy */; }; - 50C0F94C8A0A997FF42A574D8367A3C7 /* PBXTargetDependency */ = { + 8935DBBDEDCE7F48711B98D9DB279717 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SwiftMessages; target = DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */; - targetProxy = DA9FA5DB745280F35DD4EFAC9A7A4FD7 /* PBXContainerItemProxy */; + targetProxy = 70E6358901408AED062E820735630F69 /* PBXContainerItemProxy */; + }; + E98E5B4F9A2B7044ED32678F81832AEE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "SwiftMessages-SwiftMessages_SwiftMessages"; + target = 1FC5E8328653C350899229BDF89FACE5 /* SwiftMessages-SwiftMessages_SwiftMessages */; + targetProxy = 146D3A65FCE17293CC3AD6CBEAE15F9A /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 01CE4E62B8DE70DDCEADD46669F1118B /* Debug */ = { + 3FC2D46D829830CE0E848EA5B410073A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 87745BF2C7154EF88509BED0D71243F1 /* SwiftMessages.debug.xcconfig */; + baseConfigurationReference = DBF30CA29E00D6768396013A24DDE9E9 /* SwiftMessages.debug.xcconfig */; buildSettings = { + CODE_SIGNING_ALLOWED = NO; CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SwiftMessages"; IBSC_MODULE = SwiftMessages; INFOPLIST_FILE = "Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; PRODUCT_NAME = SwiftMessages_SwiftMessages; SDKROOT = iphoneos; SKIP_INSTALL = YES; @@ -777,23 +810,82 @@ }; name = Debug; }; - 27EC13F078A5EF4E57265026E5EA01CB /* Release */ = { + 4503CB76C2B552AADDBE817FB3830956 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B7BF853CD0CDFA20423D4C813B34B57F /* SwiftMessages.release.xcconfig */; + baseConfigurationReference = C306ACAFEE157959D78E71DBBBD675DC /* Pods-iMessageExtensionDemo.debug.xcconfig */; buildSettings = { - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SwiftMessages"; - IBSC_MODULE = SwiftMessages; - INFOPLIST_FILE = "Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - PRODUCT_NAME = SwiftMessages_SwiftMessages; + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 59909018A45193B32A9AC1A497747707 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 820B743874F7AC9F9E3970D68E2E60FA /* Pods-iMessageDemo.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Release; }; - 6427804744C4054555383985007A0B6C /* Debug */ = { + 8C9963745FD01B6B3EF95F9CE58D9F10 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -846,7 +938,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.4; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -859,7 +951,93 @@ }; name = Debug; }; - 74556EDEC03158A3009CA84D67369133 /* Release */ = { + 9AA80409B5B73B4F3944DDDD6463F2F3 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DBF30CA29E00D6768396013A24DDE9E9 /* SwiftMessages.debug.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SwiftMessages/SwiftMessages-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SwiftMessages/SwiftMessages-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/SwiftMessages/SwiftMessages.modulemap"; + PRODUCT_MODULE_NAME = SwiftMessages; + PRODUCT_NAME = SwiftMessages; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 9FEE8F2AB72B17FFBCF0628B7DCBB31F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BA61C87AB568667230DCD9DC2E423722 /* SwiftMessages.release.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SwiftMessages"; + IBSC_MODULE = SwiftMessages; + INFOPLIST_FILE = "Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + PRODUCT_NAME = SwiftMessages_SwiftMessages; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; + A96FA7E94B943E99EB50714920749FAA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BA61C87AB568667230DCD9DC2E423722 /* SwiftMessages.release.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SwiftMessages/SwiftMessages-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SwiftMessages/SwiftMessages-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/SwiftMessages/SwiftMessages.modulemap"; + PRODUCT_MODULE_NAME = SwiftMessages; + PRODUCT_NAME = SwiftMessages; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + B9F3557045385CA606F5AF548D58B58A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -909,7 +1087,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.4; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -921,44 +1099,7 @@ }; name = Release; }; - 891563622FB1DE05CD4905BE16203F07 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C306ACAFEE157959D78E71DBBBD675DC /* Pods-iMessageExtensionDemo.debug.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.4; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - A1CD8FCA9657A138B144BC1F2AABADD3 /* Release */ = { + C071287F0603F63CE0FC42C4A8BB3E9A /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = AE7AEA9CE6B44DCC96AE4E68FA644DAA /* Pods-iMessageExtensionDemo.release.xcconfig */; buildSettings = { @@ -974,7 +1115,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.4; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -996,112 +1137,7 @@ }; name = Release; }; - B9F08B726D3DD8C6ACDBB8CC2E05B693 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 87745BF2C7154EF88509BED0D71243F1 /* SwiftMessages.debug.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/SwiftMessages/SwiftMessages-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SwiftMessages/SwiftMessages-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MODULEMAP_FILE = "Target Support Files/SwiftMessages/SwiftMessages.modulemap"; - PRODUCT_MODULE_NAME = SwiftMessages; - PRODUCT_NAME = SwiftMessages; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - C9423D1E13393A1A8BC54BE4E87A96AD /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 820B743874F7AC9F9E3970D68E2E60FA /* Pods-iMessageDemo.release.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.4; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - D0E16784196812CD6F00BFEE04C50E82 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = B7BF853CD0CDFA20423D4C813B34B57F /* SwiftMessages.release.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/SwiftMessages/SwiftMessages-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SwiftMessages/SwiftMessages-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MODULEMAP_FILE = "Target Support Files/SwiftMessages/SwiftMessages.modulemap"; - PRODUCT_MODULE_NAME = SwiftMessages; - PRODUCT_NAME = SwiftMessages; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - FCA0FCAB93E530D2C6BED8D3910FEB4A /* Debug */ = { + DFD90EB1585D1CB60C100925E96958A9 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = B99CBDE49D6502CF64EB9059C005BF31 /* Pods-iMessageDemo.debug.xcconfig */; buildSettings = { @@ -1117,7 +1153,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.4; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1141,47 +1177,47 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 1B3FEB13A547A2F656C2328E0CE130B5 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages_SwiftMessages" */ = { + 1A195C86FC7EF00767CF99ECEBE42625 /* Build configuration list for PBXNativeTarget "Pods-iMessageDemo" */ = { isa = XCConfigurationList; buildConfigurations = ( - 01CE4E62B8DE70DDCEADD46669F1118B /* Debug */, - 27EC13F078A5EF4E57265026E5EA01CB /* Release */, + DFD90EB1585D1CB60C100925E96958A9 /* Debug */, + 59909018A45193B32A9AC1A497747707 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 20A82A14E31D7EFF5BE9B60529162F4B /* Build configuration list for PBXNativeTarget "Pods-iMessageDemo" */ = { + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - FCA0FCAB93E530D2C6BED8D3910FEB4A /* Debug */, - C9423D1E13393A1A8BC54BE4E87A96AD /* Release */, + 8C9963745FD01B6B3EF95F9CE58D9F10 /* Debug */, + B9F3557045385CA606F5AF548D58B58A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + B9E25A37EB36EDFCDE7B709EF28887E1 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages_SwiftMessages" */ = { isa = XCConfigurationList; buildConfigurations = ( - 6427804744C4054555383985007A0B6C /* Debug */, - 74556EDEC03158A3009CA84D67369133 /* Release */, + 3FC2D46D829830CE0E848EA5B410073A /* Debug */, + 9FEE8F2AB72B17FFBCF0628B7DCBB31F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 7D9EC6095BF15A96EABE2FE5045DA5DE /* Build configuration list for PBXNativeTarget "SwiftMessages" */ = { + BC0696CE4F28B31FF26CA99798FE7058 /* Build configuration list for PBXNativeTarget "SwiftMessages" */ = { isa = XCConfigurationList; buildConfigurations = ( - B9F08B726D3DD8C6ACDBB8CC2E05B693 /* Debug */, - D0E16784196812CD6F00BFEE04C50E82 /* Release */, + 9AA80409B5B73B4F3944DDDD6463F2F3 /* Debug */, + A96FA7E94B943E99EB50714920749FAA /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - ED0C46CBFB7B22526D6F384198E16114 /* Build configuration list for PBXNativeTarget "Pods-iMessageExtensionDemo" */ = { + D4007834B8D8DEA14D3016E025D2E198 /* Build configuration list for PBXNativeTarget "Pods-iMessageExtensionDemo" */ = { isa = XCConfigurationList; buildConfigurations = ( - 891563622FB1DE05CD4905BE16203F07 /* Debug */, - A1CD8FCA9657A138B144BC1F2AABADD3 /* Release */, + 4503CB76C2B552AADDBE817FB3830956 /* Debug */, + C071287F0603F63CE0FC42C4A8BB3E9A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist index 2243fe6e..19cf209d 100644 --- a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist @@ -3,7 +3,7 @@ <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> - <string>en</string> + <string>${PODS_DEVELOPMENT_LANGUAGE}</string> <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleIdentifier</key> diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh index c735166d..70350e1f 100755 --- a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh @@ -18,7 +18,7 @@ echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" -SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" +SWIFT_STDLIB_PATH="${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" BCSYMBOLMAP_DIR="BCSymbolMaps" @@ -41,7 +41,7 @@ install_framework() if [ -L "${source}" ]; then echo "Symlinked..." - source="$(readlink "${source}")" + source="$(readlink -f "${source}")" fi if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then @@ -113,6 +113,7 @@ install_dsym() { rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" else # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + mkdir -p "${DWARF_DSYM_FOLDER_PATH}" touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" fi fi diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.debug.xcconfig b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.debug.xcconfig index 7d10f708..f075bc9b 100644 --- a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.debug.xcconfig +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.debug.xcconfig @@ -3,7 +3,8 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages/SwiftMessages.framework/Headers" -LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -framework "UIKit" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.release.xcconfig b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.release.xcconfig index 7d10f708..f075bc9b 100644 --- a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.release.xcconfig +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.release.xcconfig @@ -3,7 +3,8 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages/SwiftMessages.framework/Headers" -LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -framework "UIKit" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist index 2243fe6e..19cf209d 100644 --- a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist @@ -3,7 +3,7 @@ <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> - <string>en</string> + <string>${PODS_DEVELOPMENT_LANGUAGE}</string> <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleIdentifier</key> diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.debug.xcconfig b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.debug.xcconfig index c23e4e35..2ab61eed 100644 --- a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.debug.xcconfig +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.debug.xcconfig @@ -2,7 +2,8 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages/SwiftMessages.framework/Headers" -LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -framework "UIKit" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.release.xcconfig b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.release.xcconfig index c23e4e35..2ab61eed 100644 --- a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.release.xcconfig +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.release.xcconfig @@ -2,7 +2,8 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages/SwiftMessages.framework/Headers" -LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -framework "UIKit" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist b/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist index fa5d486a..cebedeb8 100644 --- a/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist @@ -3,7 +3,7 @@ <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> - <string>en</string> + <string>${PODS_DEVELOPMENT_LANGUAGE}</string> <key>CFBundleIdentifier</key> <string>${PRODUCT_BUNDLE_IDENTIFIER}</string> <key>CFBundleInfoDictionaryVersion</key> @@ -13,7 +13,7 @@ <key>CFBundlePackageType</key> <string>BNDL</string> <key>CFBundleShortVersionString</key> - <string>9.0.3</string> + <string>10.0.1</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist index 364cea2f..cad5ca66 100644 --- a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist @@ -3,7 +3,7 @@ <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> - <string>en</string> + <string>${PODS_DEVELOPMENT_LANGUAGE}</string> <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleIdentifier</key> @@ -15,7 +15,7 @@ <key>CFBundlePackageType</key> <string>FMWK</string> <key>CFBundleShortVersionString</key> - <string>9.0.3</string> + <string>10.0.1</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.debug.xcconfig b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.debug.xcconfig index 9bbd3c8d..bb609503 100644 --- a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.debug.xcconfig +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.debug.xcconfig @@ -2,10 +2,12 @@ APPLICATION_EXTENSION_API_ONLY = YES CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 SWIFTMESSAGES_APP_EXTENSIONS=1 +LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift OTHER_LDFLAGS = $(inherited) -framework "UIKit" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.release.xcconfig b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.release.xcconfig index 9bbd3c8d..bb609503 100644 --- a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.release.xcconfig +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.release.xcconfig @@ -2,10 +2,12 @@ APPLICATION_EXTENSION_API_ONLY = YES CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 SWIFTMESSAGES_APP_EXTENSIONS=1 +LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift OTHER_LDFLAGS = $(inherited) -framework "UIKit" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates diff --git a/iMessageDemo/iMessageDemo.xcodeproj/project.pbxproj b/iMessageDemo/iMessageDemo.xcodeproj/project.pbxproj index ff0e9049..5ff095c6 100644 --- a/iMessageDemo/iMessageDemo.xcodeproj/project.pbxproj +++ b/iMessageDemo/iMessageDemo.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -149,7 +149,6 @@ EE094075BD5252DAD69071F9 /* Pods-iMessageExtensionDemo.debug.xcconfig */, 212D588BA5EE4E8BF07B02D8 /* Pods-iMessageExtensionDemo.release.xcconfig */, ); - name = Pods; path = Pods; sourceTree = "<group>"; }; @@ -478,6 +477,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 38R82CD868; INFOPLIST_FILE = iMessageDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -497,6 +497,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 38R82CD868; INFOPLIST_FILE = iMessageDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -516,6 +517,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 38R82CD868; INFOPLIST_FILE = iMessageExtensionDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -537,6 +539,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 38R82CD868; INFOPLIST_FILE = iMessageExtensionDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", From 0eba59af7f44603a5d1886590769e6ee7282d9c7 Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Tue, 20 Aug 2024 11:08:30 -0500 Subject: [PATCH 75/77] Remove unecessary sort logic --- SwiftMessages/SwiftMessages.swift | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index 71709659..f05ad494 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -618,16 +618,9 @@ open class SwiftMessages { guard queue.count > 0 else { return } if let _current, !_current.isOrphaned { return } // Sort by priority - queue = queue.enumerated().sorted { left, right in - // The priority is sorted first - let leftPriority = left.element.config.priority - let rightPriority = right.element.config.priority - if leftPriority != rightPriority { - return leftPriority > rightPriority - } - // The same priority is sorted in queue order - return left.offset < right.offset - }.map { $0.element } + queue = queue.sorted { left, right in + left.config.priority > right.config.priority + } let current = queue.removeFirst() self._current = current // Set `autohideToken` before the animation starts in case From c544df6ce316422b9d65a571f932e800213dd09c Mon Sep 17 00:00:00 2001 From: Timothy Moose <tim@swiftkickmobile.com> Date: Mon, 23 Sep 2024 09:52:25 -0500 Subject: [PATCH 76/77] Update changelog --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 880e47be..1fa85286 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,13 @@ All notable changes to this project will be documented in this file. ## Features -* Adds 'TopBottomPresentable' protocol to allow animators implementation to reuse 'top/bottom' integration in presentation +* #523 Add a `priority` configuration option. +* #548 Adds 'TopBottomPresentable' protocol to allow animators implementation to reuse 'top/bottom' integration in presentation +* #543 Make the `SwiftMessages` initializer `nonisolated` to improve interoperability with dependency injection frameworks like Factory. +* #560 Add a new `swiftMessage` modifier variation that provides a ` MessageGeometryProxy` type to the message view builder—this works around an inssue with `GeometryReader` not working in `UIHostingController`. + +Fixes +* Fix broken touch handling in iOS 18. ## 10.0.0 From b929e04ae9bac912b8442716f13ccd99812460ff Mon Sep 17 00:00:00 2001 From: Teameh <1330668+teameh@users.noreply.github.com> Date: Mon, 27 Jan 2025 00:27:25 +0100 Subject: [PATCH 77/77] PhysicsPanHandler.swift make configure public (#571) --- SwiftMessages/PhysicsPanHandler.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftMessages/PhysicsPanHandler.swift b/SwiftMessages/PhysicsPanHandler.swift index e381d22d..86187974 100644 --- a/SwiftMessages/PhysicsPanHandler.swift +++ b/SwiftMessages/PhysicsPanHandler.swift @@ -99,7 +99,7 @@ open class PhysicsPanHandler { return pan }() - func configure(context: AnimationContext, animator: Animator) { + public func configure(context: AnimationContext, animator: Animator) { if let oldView = (messageView as? BackgroundViewable)?.backgroundView ?? messageView { oldView.removeGestureRecognizer(pan) }