From 3a6fb3f4c2369441f17b340070b7409abe99d021 Mon Sep 17 00:00:00 2001 From: Timothy Moose Date: Thu, 3 Jun 2021 10:58:48 -0500 Subject: [PATCH 01/38] 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 08f50bb..f10c7f2 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 b7d82fb..54bd951 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 b7d82fb..54bd951 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 Date: Thu, 3 Jun 2021 11:33:55 -0500 Subject: [PATCH 02/38] 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 f10c7f2..17f749a 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 d98c6ca..316fcac 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 Date: Thu, 3 Jun 2021 12:36:41 -0500 Subject: [PATCH 03/38] =?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 96b3009..9c2b721 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 Date: Thu, 3 Jun 2021 12:37:54 -0500 Subject: [PATCH 04/38] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17f749a..d44911c 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 Date: Tue, 29 Jun 2021 11:29:52 -0500 Subject: [PATCH 05/38] 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 7d924e2..8207406 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 d9f1f3a..21b0f27 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 Date: Tue, 29 Jun 2021 13:48:32 -0500 Subject: [PATCH 06/38] Fix warning --- SwiftMessages/KeyboardTrackingView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftMessages/KeyboardTrackingView.swift b/SwiftMessages/KeyboardTrackingView.swift index 69ce6b0..6af384a 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 Date: Fri, 17 Sep 2021 16:42:06 -0500 Subject: [PATCH 07/38] 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 * Prep for release * Update changelog Co-authored-by: Kohki Miki --- 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 d44911c..ed08715 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 a6c018f..688f100 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 5103fcd..b01d9c2 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 = ""; }; 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarginAdjustable+Extensions.swift"; sourceTree = ""; }; 220D386D2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftMessages.Config+Extensions.swift"; sourceTree = ""; }; 224FB69821153B440081D4DE /* CALayer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CALayer+Extensions.swift"; sourceTree = ""; }; @@ -141,7 +143,7 @@ 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = ""; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = ""; }; 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = ""; }; - 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+Extensions.swift"; sourceTree = ""; }; + 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+Extensions.swift"; sourceTree = ""; }; 22A2EA6E24EC6CFA00BB2540 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = CenteredView.xib; path = Resources/CenteredView.xib; sourceTree = ""; }; 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsPanHandler.swift; sourceTree = ""; }; @@ -211,7 +213,7 @@ children = ( 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */, 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */, - 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */, + 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */, ); name = Extensions; sourceTree = ""; @@ -304,6 +306,7 @@ 2298C2041EE47DC900E2DDC1 /* Weak.swift */, 22F27950210CE25900273E7F /* CornerRoundingView.swift */, 225304652293000C00A03ACF /* KeyboardTrackingView.swift */, + 0797E40D26EE12B400691606 /* WindowScene.swift */, ); name = Base; sourceTree = ""; @@ -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 d9be31d..c71141a 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 9682b5b..ac0475d 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 dfae859..7c0042f 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 0000000..a3bbb4c --- /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 54bd951..7162a91 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 54bd951..7162a91 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 468092a..0d6bbc2 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 = ""; }; - 06F2F626BE8417F1806CC5B17F210C90 /* infoIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconSubtle.png; path = SwiftMessages/Resources/infoIconSubtle.png; sourceTree = ""; }; - 0892E032AE12339D1AD84BDCC78A3C07 /* errorIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconLight.png; path = SwiftMessages/Resources/errorIconLight.png; sourceTree = ""; }; + 0038C9A582787F9882258E8D1080EACF /* warningIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@3x.png"; path = "SwiftMessages/Resources/warningIcon@3x.png"; sourceTree = ""; }; + 007ACA6F89C6C856F78352A086F3B8EA /* CornerRoundingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CornerRoundingView.swift; path = SwiftMessages/CornerRoundingView.swift; sourceTree = ""; }; + 0201BC51C7CA061016B619400691A139 /* AccessibleMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibleMessage.swift; path = SwiftMessages/AccessibleMessage.swift; sourceTree = ""; }; 093D5BBE2A96A1A7AC0432A3AB933576 /* Pods-iMessageDemo-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageDemo-Info.plist"; sourceTree = ""; }; - 0970322A5DD8B4A8373C35ED051DE156 /* NSLayoutConstraint+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSLayoutConstraint+Extensions.swift"; path = "SwiftMessages/NSLayoutConstraint+Extensions.swift"; sourceTree = ""; }; - 0A8566413BFA3FE6827E63E30515C9B3 /* WindowViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WindowViewController.swift; path = SwiftMessages/WindowViewController.swift; sourceTree = ""; }; - 0B3A169D83BDA3613A661845D1607FC0 /* successIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@2x.png"; path = "SwiftMessages/Resources/successIconSubtle@2x.png"; sourceTree = ""; }; + 0AF65ECDAFAD03A79B5571C6F66D8F35 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TopBottomAnimation.swift; path = SwiftMessages/TopBottomAnimation.swift; sourceTree = ""; }; + 0BEC185781E869FB5FDB7F10538230C7 /* SwiftMessages.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SwiftMessages.modulemap; sourceTree = ""; }; + 0D2B448BE319CF56A38E222C0B7DF4CB /* PhysicsAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsAnimation.swift; path = SwiftMessages/PhysicsAnimation.swift; sourceTree = ""; }; 1341BB7116EC50FDF7062C6A91DEDF49 /* Pods-iMessageExtensionDemo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageExtensionDemo-acknowledgements.plist"; sourceTree = ""; }; + 141AADF8046C9D5EC8E194DF662BAC41 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; sourceTree = ""; }; 14BF989232A1D55A0FDAAB70B5A8E1BF /* Pods-iMessageDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-iMessageDemo-dummy.m"; sourceTree = ""; }; - 15C4C88778A19C193D1EC77FA77BAE4C /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Extensions.swift"; path = "SwiftMessages/UIViewController+Extensions.swift"; sourceTree = ""; }; - 19B5EF40CEC1F6DB23F428DC159D4BC2 /* CALayer+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CALayer+Extensions.swift"; path = "SwiftMessages/CALayer+Extensions.swift"; sourceTree = ""; }; - 1B04615682E8B787C964824435BC6616 /* errorIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@2x.png"; path = "SwiftMessages/Resources/errorIconLight@2x.png"; sourceTree = ""; }; - 1DC54BB09EFDFEDE11F484FE73BEDC60 /* successIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconSubtle.png; path = SwiftMessages/Resources/successIconSubtle.png; sourceTree = ""; }; - 2337E6D5F621F3CE9A1E3761984EBE87 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsPanHandler.swift; path = SwiftMessages/PhysicsPanHandler.swift; sourceTree = ""; }; - 267E35F9851AAE50DFB8FA0DCA7F2980 /* Animator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Animator.swift; path = SwiftMessages/Animator.swift; sourceTree = ""; }; - 2B6B36CBE6DC07B2F005E30EA2B121CB /* LICENSE.md */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE.md; sourceTree = ""; }; - 2B7213B7DC5432DA2B272F25E17AA364 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "SwiftMessages/Resources/infoIconSubtle@3x.png"; sourceTree = ""; }; - 2CFBBC25592C97C925B6F81B53BE57CB /* warningIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@3x.png"; path = "SwiftMessages/Resources/warningIcon@3x.png"; sourceTree = ""; }; + 17ADABD24F805C5F7FF62167E7ABEF0A /* successIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@3x.png"; path = "SwiftMessages/Resources/successIconSubtle@3x.png"; sourceTree = ""; }; + 1A331C2E0BE2AE2118D65AA1F12519F2 /* PassthroughWindow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughWindow.swift; path = SwiftMessages/PassthroughWindow.swift; sourceTree = ""; }; + 1E2FE4DB6869F330F19A3A5459AAFFFB /* StatusLine.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = StatusLine.xib; path = SwiftMessages/Resources/StatusLine.xib; sourceTree = ""; }; + 1ED635B9451869879B1A404F00C3CCC7 /* SwiftMessages-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-prefix.pch"; sourceTree = ""; }; + 24021DCE87BE9746D1DFB436C0A3AF7A /* Theme.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Theme.swift; path = SwiftMessages/Theme.swift; sourceTree = ""; }; + 29A39558830996C4F54686A1748B74B1 /* warningIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@2x.png"; path = "SwiftMessages/Resources/warningIcon@2x.png"; sourceTree = ""; }; 2D0ECE831FB5E0EE1D68E837671320C7 /* Pods-iMessageDemo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-iMessageDemo-umbrella.h"; sourceTree = ""; }; - 2E6941E59EF0D89949E3DF3D89488430 /* Weak.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Weak.swift; path = SwiftMessages/Weak.swift; sourceTree = ""; }; - 337B3108412E3812254B85BCC4F90EB8 /* infoIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@3x.png"; path = "SwiftMessages/Resources/infoIcon@3x.png"; sourceTree = ""; }; - 346718C2C7A108C86535F89FEB0EC176 /* SwiftMessages.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SwiftMessages.modulemap; sourceTree = ""; }; - 382E6375390EBB09F829519F8ACCB7D7 /* PassthroughWindow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughWindow.swift; path = SwiftMessages/PassthroughWindow.swift; sourceTree = ""; }; - 396FCF260E9C2B3F11080A91E3D72334 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TopBottomAnimation.swift; path = SwiftMessages/TopBottomAnimation.swift; sourceTree = ""; }; - 397C8F928170138667B9326F9655D75D /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIWindow+Extensions.swift"; path = "SwiftMessages/UIWindow+Extensions.swift"; sourceTree = ""; }; - 3C313FB1D33EF4B477FD5D3D6179A8BE /* errorIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@2x.png"; path = "SwiftMessages/Resources/errorIconSubtle@2x.png"; sourceTree = ""; }; - 3DF091E68C4659506DB08B0876BD274C /* CenteredView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CenteredView.xib; path = SwiftMessages/Resources/CenteredView.xib; sourceTree = ""; }; - 42F1E753E61B6EDED3908AC66994649C /* CardView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CardView.xib; path = SwiftMessages/Resources/CardView.xib; sourceTree = ""; }; - 4412F313361EFEE7A0193533A5AC5999 /* infoIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@3x.png"; path = "SwiftMessages/Resources/infoIconLight@3x.png"; sourceTree = ""; }; - 4512DEEA328AB0AAA95D77C84C89E02C /* warningIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconSubtle.png; path = SwiftMessages/Resources/warningIconSubtle.png; sourceTree = ""; }; - 453BC098B6A052020C40DE576F684C7B /* errorIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@3x.png"; path = "SwiftMessages/Resources/errorIconSubtle@3x.png"; sourceTree = ""; }; + 3259F99D03B6D738D7F47A625E7BD3BE /* warningIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIcon.png; path = SwiftMessages/Resources/warningIcon.png; sourceTree = ""; }; + 36F7B24601DF4C00B14EC8CE2D4A48DC /* UIEdgeInsets+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIEdgeInsets+Extensions.swift"; path = "SwiftMessages/UIEdgeInsets+Extensions.swift"; sourceTree = ""; }; + 3E2EB968B30DE56F38B5FCFFEDE9F88F /* NSBundle+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSBundle+Extensions.swift"; path = "SwiftMessages/NSBundle+Extensions.swift"; sourceTree = ""; }; + 45844D489A130BA91E91E7CDD4969862 /* infoIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@2x.png"; path = "SwiftMessages/Resources/infoIconSubtle@2x.png"; sourceTree = ""; }; + 467EAD44C7F625F384822180F004E64F /* CALayer+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CALayer+Extensions.swift"; path = "SwiftMessages/CALayer+Extensions.swift"; sourceTree = ""; }; + 468D9889455DE51BD5BBC2360BDBB877 /* errorIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@2x.png"; path = "SwiftMessages/Resources/errorIconSubtle@2x.png"; sourceTree = ""; }; 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 = ""; }; - 4FE466AC4123CDAE9FDA9FCF4FB9CC60 /* infoIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@2x.png"; path = "SwiftMessages/Resources/infoIconSubtle@2x.png"; sourceTree = ""; }; - 536660614870EA0E051BF6BDDF495798 /* KeyboardTrackingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KeyboardTrackingView.swift; path = SwiftMessages/KeyboardTrackingView.swift; sourceTree = ""; }; - 54B278C80D821C120FA70ABB6CAF1F46 /* successIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@3x.png"; path = "SwiftMessages/Resources/successIconSubtle@3x.png"; sourceTree = ""; }; - 5C0DE01AB7D0935933E7AFBDF2945814 /* Identifiable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Identifiable.swift; path = SwiftMessages/Identifiable.swift; sourceTree = ""; }; + 48DC3BADDA3A20F2AEB8585117DAFA0D /* infoIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@3x.png"; path = "SwiftMessages/Resources/infoIcon@3x.png"; sourceTree = ""; }; + 4D34E3F2A49E9024A96334DA4147F27B /* errorIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@3x.png"; path = "SwiftMessages/Resources/errorIconLight@3x.png"; sourceTree = ""; }; + 52F1CA85E0EED7D94FE0036BC92EB3EC /* successIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconLight.png; path = SwiftMessages/Resources/successIconLight.png; sourceTree = ""; }; + 59FEAC25BE3FCB9F8373DE26400CC89D /* SwiftMessages.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = SwiftMessages.podspec; sourceTree = ""; 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 = ""; }; 5CAB201AD00CAB811B045E2FFB5C03A8 /* Pods-iMessageExtensionDemo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-iMessageExtensionDemo-umbrella.h"; sourceTree = ""; }; - 60268FE48AA4DC9FD5060B1E5CE68453 /* errorIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@2x.png"; path = "SwiftMessages/Resources/errorIcon@2x.png"; sourceTree = ""; }; - 62755A788F910CA88887B6F63BBC545F /* successIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@2x.png"; path = "SwiftMessages/Resources/successIcon@2x.png"; sourceTree = ""; }; 6489B2A759075E9DC1D1406734F45B5F /* Pods-iMessageExtensionDemo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iMessageExtensionDemo.modulemap"; sourceTree = ""; }; - 6516EE9BFCB9C53C151359F9D0247562 /* infoIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@2x.png"; path = "SwiftMessages/Resources/infoIconLight@2x.png"; sourceTree = ""; }; - 667DECE93ABCC6869A071FFEB0F83EA5 /* warningIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@3x.png"; path = "SwiftMessages/Resources/warningIconSubtle@3x.png"; sourceTree = ""; }; - 6E9D4A0FDDEEDDC5A1A63D89B43C1F18 /* SwiftMessages.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.debug.xcconfig; sourceTree = ""; }; - 70E7AB099F856140EF93D5B94A967418 /* infoIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIcon.png; path = SwiftMessages/Resources/infoIcon.png; sourceTree = ""; }; - 7241B2130D211F0832CCE4928CBB6486 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; - 72A865FFBAE49EF66A35CB9D709E8D7E /* successIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@3x.png"; path = "SwiftMessages/Resources/successIconLight@3x.png"; sourceTree = ""; }; - 79E38069364BC5DF4EA88F352E28B242 /* warningIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconLight.png; path = SwiftMessages/Resources/warningIconLight.png; sourceTree = ""; }; - 7A6801849037A728E9BC50E06CE8AD2F /* StatusLine.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = StatusLine.xib; path = SwiftMessages/Resources/StatusLine.xib; sourceTree = ""; }; - 7A965DD26246DCA8CE39FBAB348ABA24 /* Presenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Presenter.swift; path = SwiftMessages/Presenter.swift; sourceTree = ""; }; + 676F359BE8561CF7512DB8B42CD7873A /* infoIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@3x.png"; path = "SwiftMessages/Resources/infoIconLight@3x.png"; sourceTree = ""; }; + 705B5AF043D00B6538599B4EB1ECD77C /* CardView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CardView.xib; path = SwiftMessages/Resources/CardView.xib; sourceTree = ""; }; + 7100245A2722BD53D5B3927ED649069F /* errorIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconLight.png; path = SwiftMessages/Resources/errorIconLight.png; sourceTree = ""; }; + 730840765E737D45772EBE66DB8A6D2E /* infoIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconLight.png; path = SwiftMessages/Resources/infoIconLight.png; sourceTree = ""; }; + 74C53DDA65E08AD7274EA6625408AB99 /* SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SwiftMessages-Info.plist"; sourceTree = ""; }; + 753B78926D6BB175E96AB6E6F3514E87 /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIWindow+Extensions.swift"; path = "SwiftMessages/UIWindow+Extensions.swift"; sourceTree = ""; }; + 760BFB41B33B6ED91B3FFD68D39083A0 /* successIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@2x.png"; path = "SwiftMessages/Resources/successIconLight@2x.png"; sourceTree = ""; }; + 778F6E19CE49B8EDBAC2FCCD8195A55B /* MessageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageView.swift; path = SwiftMessages/MessageView.swift; sourceTree = ""; }; + 787EE6DA4FBC3BF85ED2CF0BB6EBF494 /* CenteredView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CenteredView.xib; path = SwiftMessages/Resources/CenteredView.xib; sourceTree = ""; }; + 79D34B3C6875DA0279CB934C84CD000B /* successIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@2x.png"; path = "SwiftMessages/Resources/successIcon@2x.png"; sourceTree = ""; }; + 7C4DF53A4B44C246968618BF25962786 /* warningIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@3x.png"; path = "SwiftMessages/Resources/warningIconLight@3x.png"; sourceTree = ""; }; + 7C8214A441D845A4A4DD6570FD5D458F /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "MarginAdjustable+Extensions.swift"; path = "SwiftMessages/MarginAdjustable+Extensions.swift"; sourceTree = ""; }; 7CC6A596A9C1659D8E93222DA4144414 /* Pods-iMessageExtensionDemo-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageExtensionDemo-Info.plist"; sourceTree = ""; }; 7F40CA14AD738DD186B4DA8FD14AE5BD /* Pods-iMessageExtensionDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-iMessageExtensionDemo-dummy.m"; sourceTree = ""; }; - 7FCF161BD9F1C2CAAFBCADE5E59BD3FD /* NSBundle+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSBundle+Extensions.swift"; path = "SwiftMessages/NSBundle+Extensions.swift"; sourceTree = ""; }; 820B743874F7AC9F9E3970D68E2E60FA /* Pods-iMessageDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageDemo.release.xcconfig"; sourceTree = ""; }; - 8341EF04E2B20C2BF6D4AF2240F80A56 /* Error.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Error.swift; path = SwiftMessages/Error.swift; sourceTree = ""; }; - 848251807107C20960A3DABAB27F7475 /* errorIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@3x.png"; path = "SwiftMessages/Resources/errorIconLight@3x.png"; sourceTree = ""; }; - 874D31DE863C88B1D699E1EBFBE0641B /* warningIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@2x.png"; path = "SwiftMessages/Resources/warningIconLight@2x.png"; sourceTree = ""; }; - 8901520225CE89F44E6DE88688F29C10 /* MessageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageView.swift; path = SwiftMessages/MessageView.swift; sourceTree = ""; }; + 8315EA451FE61625920FEF68174A0D22 /* infoIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@2x.png"; path = "SwiftMessages/Resources/infoIconLight@2x.png"; sourceTree = ""; }; + 860D833A7A1B108A89ED34AD74778AC0 /* warningIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconSubtle.png; path = SwiftMessages/Resources/warningIconSubtle.png; sourceTree = ""; }; + 87745BF2C7154EF88509BED0D71243F1 /* SwiftMessages.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.debug.xcconfig; sourceTree = ""; }; + 88D73E42D996B226222A4EBA46F7DC6D /* Weak.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Weak.swift; path = SwiftMessages/Weak.swift; sourceTree = ""; }; + 8AD355ED684A939F2A4E333F95E8AC31 /* warningIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@2x.png"; path = "SwiftMessages/Resources/warningIconSubtle@2x.png"; sourceTree = ""; }; + 8D219D80184B8ED97808EE17507B213A /* Animator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Animator.swift; path = SwiftMessages/Animator.swift; sourceTree = ""; }; 8D54691037F1CA4653B76F0558E2AA82 /* Pods-iMessageExtensionDemo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-iMessageExtensionDemo-acknowledgements.markdown"; sourceTree = ""; }; - 90F364E0C9A6EFE24680868D0BD293F1 /* SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SwiftMessages-Info.plist"; sourceTree = ""; }; + 90AC342C6F09BF7715D4FB95512DD68A /* KeyboardTrackingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KeyboardTrackingView.swift; path = SwiftMessages/KeyboardTrackingView.swift; sourceTree = ""; }; 915DE2E4E300BAD440BE13F72E49D731 /* Pods-iMessageDemo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageDemo-acknowledgements.plist"; sourceTree = ""; }; - 9C110C924ED12D2D32ECC27503018A31 /* infoIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconLight.png; path = SwiftMessages/Resources/infoIconLight.png; sourceTree = ""; }; - 9CF61FDEFE095F0486E9914F2262ADB9 /* MaskingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MaskingView.swift; path = SwiftMessages/MaskingView.swift; sourceTree = ""; }; - 9D1FEAC04417D847EDC10783E054988F /* errorIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIcon.png; path = SwiftMessages/Resources/errorIcon.png; sourceTree = ""; }; + 91D9224F29E092950BADC27C979E10CC /* successIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@2x.png"; path = "SwiftMessages/Resources/successIconSubtle@2x.png"; sourceTree = ""; }; + 9C6E00017F9E79F6D4926E9CB43A66DF /* SwiftMessages-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SwiftMessages-dummy.m"; sourceTree = ""; }; + 9CBEAC9D0EF4113C3FD3B15F511A92D0 /* SwiftMessages-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-umbrella.h"; sourceTree = ""; }; 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 = ""; }; - A2F9031B7FA82A17F04D4403091DF836 /* SwiftMessages-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SwiftMessages-dummy.m"; sourceTree = ""; }; - A3C32E945AE3E6394EF85CD6BEC714B4 /* SwiftMessages.Config+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "SwiftMessages.Config+Extensions.swift"; path = "SwiftMessages/SwiftMessages.Config+Extensions.swift"; sourceTree = ""; }; - A80433B71162112A79043CB64261DB51 /* successIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconLight.png; path = SwiftMessages/Resources/successIconLight.png; sourceTree = ""; }; - A850F76D7E3FEDC20FFB877454069171 /* errorIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconSubtle.png; path = SwiftMessages/Resources/errorIconSubtle.png; sourceTree = ""; }; - A9A13E69643D651322647C28E3F9E9C9 /* UIEdgeInsets+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIEdgeInsets+Extensions.swift"; path = "SwiftMessages/UIEdgeInsets+Extensions.swift"; sourceTree = ""; }; - AE62AA801971C530345349D18AFCCB82 /* MessageView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = MessageView.xib; path = SwiftMessages/Resources/MessageView.xib; sourceTree = ""; }; + A0EE84E98A10805A2D64B836C465ED11 /* warningIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@3x.png"; path = "SwiftMessages/Resources/warningIconSubtle@3x.png"; sourceTree = ""; }; + A342E145FED9CD8DB4F464D110203E7C /* successIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIcon.png; path = SwiftMessages/Resources/successIcon.png; sourceTree = ""; }; AE7AEA9CE6B44DCC96AE4E68FA644DAA /* Pods-iMessageExtensionDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageExtensionDemo.release.xcconfig"; sourceTree = ""; }; 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 = ""; }; - B6DEAADC09FEB1A8D5B90108103EE478 /* errorIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@3x.png"; path = "SwiftMessages/Resources/errorIcon@3x.png"; sourceTree = ""; }; - B7FD0618783A3E6B90D3A3323633959F /* TabView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = TabView.xib; path = SwiftMessages/Resources/TabView.xib; sourceTree = ""; }; - B91AD9D9E743D17D553D48103BE27C46 /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "MarginAdjustable+Extensions.swift"; path = "SwiftMessages/MarginAdjustable+Extensions.swift"; sourceTree = ""; }; + B031268635405AA009D05130C0FC253C /* successIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconSubtle.png; path = SwiftMessages/Resources/successIconSubtle.png; sourceTree = ""; }; + B7BF853CD0CDFA20423D4C813B34B57F /* SwiftMessages.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.release.xcconfig; sourceTree = ""; }; + B8A4CCB4B08D2D3BE586212AB4167DC2 /* MessageView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = MessageView.xib; path = SwiftMessages/Resources/MessageView.xib; sourceTree = ""; }; B99CBDE49D6502CF64EB9059C005BF31 /* Pods-iMessageDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageDemo.debug.xcconfig"; sourceTree = ""; }; + BDEF50CAF615897F7A8540579B445634 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsPanHandler.swift; path = SwiftMessages/PhysicsPanHandler.swift; sourceTree = ""; }; 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 = ""; }; BF61E78F8E8EE539F4A63C5A9D43AC15 /* Pods-iMessageDemo-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-iMessageDemo-frameworks.sh"; sourceTree = ""; }; - BFEF746702215C33B51BEE64C4E48F0A /* warningIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@2x.png"; path = "SwiftMessages/Resources/warningIcon@2x.png"; sourceTree = ""; }; - C17CFEF9B761A322945F74D86CA88036 /* warningIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@3x.png"; path = "SwiftMessages/Resources/warningIconLight@3x.png"; sourceTree = ""; }; C306ACAFEE157959D78E71DBBBD675DC /* Pods-iMessageExtensionDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageExtensionDemo.debug.xcconfig"; sourceTree = ""; }; - C3216CF40D770C387D45C3B4AF2CC9E0 /* SwiftMessages.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessages.swift; path = SwiftMessages/SwiftMessages.swift; sourceTree = ""; }; - C614EECDDFE644AF0BF7CB16A3D74404 /* SwiftMessages-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-umbrella.h"; sourceTree = ""; }; - C6C56947CAF8EFCC7858E1E2F1273427 /* MarginAdjustable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MarginAdjustable.swift; path = SwiftMessages/MarginAdjustable.swift; sourceTree = ""; }; - C7FE39695CB7C6997ACA39C8680B414A /* SwiftMessages.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = SwiftMessages.podspec; sourceTree = ""; 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 = ""; }; - C9D915B60769D3C45A0DA3A5BA9514B8 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; sourceTree = ""; }; - CAB58A9F688DD39112E6CDF20C8969C0 /* BackgroundViewable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BackgroundViewable.swift; path = SwiftMessages/BackgroundViewable.swift; sourceTree = ""; }; + C56AB83FDAB8D6A1328E7EECCAD99A69 /* warningIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconLight.png; path = SwiftMessages/Resources/warningIconLight.png; sourceTree = ""; }; + C5E610C06F5B006DE57F34D5994532FB /* Error.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Error.swift; path = SwiftMessages/Error.swift; sourceTree = ""; }; + C706F1F1C6B3CE84445485C8577D5388 /* BackgroundViewable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BackgroundViewable.swift; path = SwiftMessages/BackgroundViewable.swift; sourceTree = ""; }; + C787DA4E67B952C984FF5B065E0A2FF7 /* errorIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconSubtle.png; path = SwiftMessages/Resources/errorIconSubtle.png; sourceTree = ""; }; + C7EE64CFE0084CF5213A03AF29A668ED /* BaseView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BaseView.swift; path = SwiftMessages/BaseView.swift; sourceTree = ""; }; + C9F5DBB6D77B1E61E9BB1A722A4E1823 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "SwiftMessages/Resources/infoIconSubtle@3x.png"; sourceTree = ""; }; 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 = ""; }; + D032FCFAE6607CF878AA2F35EF93146C /* successIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@3x.png"; path = "SwiftMessages/Resources/successIcon@3x.png"; sourceTree = ""; }; + D1D69BE188B82D84ED23AC4E27BAB61D /* MaskingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MaskingView.swift; path = SwiftMessages/MaskingView.swift; sourceTree = ""; }; 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 = ""; }; - D7C557E1DC95AFA417E94ED01301F9F2 /* PassthroughView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughView.swift; path = SwiftMessages/PassthroughView.swift; sourceTree = ""; }; - E070773539E02C11297794CC4CB839D6 /* SwiftMessages.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.release.xcconfig; sourceTree = ""; }; + D261B7BE0088C26BF6744F27B894492A /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Extensions.swift"; path = "SwiftMessages/UIViewController+Extensions.swift"; sourceTree = ""; }; + D30B2BF71F9D2C63C2D202C99827CDC1 /* errorIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@2x.png"; path = "SwiftMessages/Resources/errorIconLight@2x.png"; sourceTree = ""; }; + D68834C60D0C5EA751E9F12E427C5FFE /* MarginAdjustable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MarginAdjustable.swift; path = SwiftMessages/MarginAdjustable.swift; sourceTree = ""; }; + D8DEFE9675E5359A46A443182F127F06 /* WindowScene.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WindowScene.swift; path = SwiftMessages/WindowScene.swift; sourceTree = ""; }; + D9AA0E820F1C1AA219C066370332845A /* WindowViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WindowViewController.swift; path = SwiftMessages/WindowViewController.swift; sourceTree = ""; }; + DB6924EB5FC7236837637AE8F409000A /* NSLayoutConstraint+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSLayoutConstraint+Extensions.swift"; path = "SwiftMessages/NSLayoutConstraint+Extensions.swift"; sourceTree = ""; }; + DEC0A6AE07C3285CA508F8FA3F4FE27D /* errorIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIcon.png; path = SwiftMessages/Resources/errorIcon.png; sourceTree = ""; }; + DF3DE135AB5C5C789CABAECC704CE907 /* errorIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@2x.png"; path = "SwiftMessages/Resources/errorIcon@2x.png"; sourceTree = ""; }; + E03CBB908F2EC39AA5DA7AF04E1BDDD6 /* PassthroughView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughView.swift; path = SwiftMessages/PassthroughView.swift; sourceTree = ""; }; + E0E4D99C4F78B9BA011D83FE63EE0946 /* errorIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@3x.png"; path = "SwiftMessages/Resources/errorIcon@3x.png"; sourceTree = ""; }; + E31D045D9E355D4F7F75564026B2051A /* errorIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@3x.png"; path = "SwiftMessages/Resources/errorIconSubtle@3x.png"; sourceTree = ""; }; + E41BFEB1BFF85793C0DB85F95184B752 /* infoIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIcon.png; path = SwiftMessages/Resources/infoIcon.png; sourceTree = ""; }; E473E4F019E816262A61B7F5E8B42373 /* Pods-iMessageDemo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-iMessageDemo-acknowledgements.markdown"; sourceTree = ""; }; + E936107A7CF9821DCBFFAF50D916F1E6 /* infoIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@2x.png"; path = "SwiftMessages/Resources/infoIcon@2x.png"; sourceTree = ""; }; + E9E929B0E2A84EA903C9923B926A44E2 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; 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 = ""; }; - EDDAF8A2C45FDDDFD5AFA59203137551 /* AccessibleMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibleMessage.swift; path = SwiftMessages/AccessibleMessage.swift; sourceTree = ""; }; - F7004673F1B51EEC365B32F0E060E564 /* infoIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@2x.png"; path = "SwiftMessages/Resources/infoIcon@2x.png"; sourceTree = ""; }; - F898B2AC5C3404C266BBCA3B6D22B5E4 /* successIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@2x.png"; path = "SwiftMessages/Resources/successIconLight@2x.png"; sourceTree = ""; }; - FC73E6C784AF6CA1F956F57F82ED2803 /* successIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIcon.png; path = SwiftMessages/Resources/successIcon.png; sourceTree = ""; }; - FCDC8870EA94B5B1E966D34D2B1FA5FE /* SwiftMessages-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-prefix.pch"; sourceTree = ""; }; - FE3BED1799B2F867F5C984C2A051E36A /* PhysicsAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsAnimation.swift; path = SwiftMessages/PhysicsAnimation.swift; sourceTree = ""; }; + EABF0CEB87991D02E13306975A8E80BB /* TabView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = TabView.xib; path = SwiftMessages/Resources/TabView.xib; sourceTree = ""; }; + EC6264350B8D100D5B5C5EEEC316933D /* SwiftMessages.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessages.swift; path = SwiftMessages/SwiftMessages.swift; sourceTree = ""; }; + EFD31968BF9DF7A9E25A136DF254F3A9 /* Identifiable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Identifiable.swift; path = SwiftMessages/Identifiable.swift; sourceTree = ""; }; + F513F2674553CBC247EE4B24EA25C99C /* Presenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Presenter.swift; path = SwiftMessages/Presenter.swift; sourceTree = ""; }; + F9CDB54E629D60FF881DF27B949F4C2D /* infoIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconSubtle.png; path = SwiftMessages/Resources/infoIconSubtle.png; sourceTree = ""; }; + FA199E6F18AB8900B5400EBA0EB32765 /* successIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@3x.png"; path = "SwiftMessages/Resources/successIconLight@3x.png"; sourceTree = ""; }; + FC12F21544AE9FE6D9E1E2F7730EF7EC /* LICENSE.md */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE.md; sourceTree = ""; }; + FFB0D50D01FFFA3FC2099E395029AE68 /* warningIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@2x.png"; path = "SwiftMessages/Resources/warningIconLight@2x.png"; sourceTree = ""; }; /* 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 = ""; + }; 1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -288,24 +369,40 @@ name = iOS; sourceTree = ""; }; - 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 = ""; }; - 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 = ""; + }; + 8F3CF4AFB0CA47B3BFE1C68E51CDF0A9 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 9A912CA1E54EADE1787311C1DF7E8F2E /* Pods-iMessageDemo */, + BD13800F87C70DC802DBC0C37E8C5E99 /* Pods-iMessageExtensionDemo */, + ); + name = "Targets Support Files"; sourceTree = ""; }; 9A912CA1E54EADE1787311C1DF7E8F2E /* Pods-iMessageDemo */ = { @@ -325,110 +422,6 @@ path = "Target Support Files/Pods-iMessageDemo"; sourceTree = ""; }; - A58DF9B1678B5C3CCA8A840C72186044 /* Pod */ = { - isa = PBXGroup; - children = ( - 2B6B36CBE6DC07B2F005E30EA2B121CB /* LICENSE.md */, - 7241B2130D211F0832CCE4928CBB6486 /* README.md */, - C7FE39695CB7C6997ACA39C8680B414A /* SwiftMessages.podspec */, - ); - name = Pod; - sourceTree = ""; - }; - 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 = ""; - }; - 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 = ""; - }; BD13800F87C70DC802DBC0C37E8C5E99 /* Pods-iMessageExtensionDemo */ = { isa = PBXGroup; children = ( @@ -448,7 +441,7 @@ C5AAA95D48373FAC474F6EFCC1749444 /* Development Pods */ = { isa = PBXGroup; children = ( - 9A632FB0C8554E0688B34926AF9C52DB /* SwiftMessages */, + 5EAB54907DABB41DF2E9177067EF69D4 /* SwiftMessages */, ); name = "Development Pods"; sourceTree = ""; @@ -464,30 +457,40 @@ ); sourceTree = ""; }; + E7706B1F04CCC75F42C733B60ED5FBDC /* Pod */ = { + isa = PBXGroup; + children = ( + FC12F21544AE9FE6D9E1E2F7730EF7EC /* LICENSE.md */, + E9E929B0E2A84EA903C9923B926A44E2 /* README.md */, + 59FEAC25BE3FCB9F8373DE26400CC89D /* SwiftMessages.podspec */, + ); + name = Pod; + sourceTree = ""; + }; /* 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 Date: Tue, 5 Oct 2021 13:11:30 -0500 Subject: [PATCH 08/38] 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 ed08715..de1f84a 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 688f100..c43a529 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 6af384a..301d969 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 0ce4c42..d631342 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 Date: Fri, 14 Jan 2022 11:33:00 -0600 Subject: [PATCH 09/38] 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 de1f84a..8c25038 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 c46c84c..97e8374 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 c43a529..4c7b945 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 11243f5..be093be 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 7c0042f..5e9f0c3 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 Date: Sat, 14 May 2022 13:59:22 -0300 Subject: [PATCH 10/38] 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 5324d1b..a0f30e8 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 Date: Mon, 18 Sep 2023 11:56:20 -0500 Subject: [PATCH 11/38] 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 be093be..5a3648b 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(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 5e9f0c3..395bc0a 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 Date: Mon, 18 Sep 2023 12:12:49 -0500 Subject: [PATCH 12/38] 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 d4cba41..80c3939 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 Date: Mon, 18 Sep 2023 12:13:02 -0500 Subject: [PATCH 13/38] Update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c25038..0a4ec93 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 Date: Fri, 6 Oct 2023 09:38:19 -0500 Subject: [PATCH 14/38] 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 97e8374..0cf8e79 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

-## View Controllers - -SwiftMessages can present view controllers using the `SwiftMessagesSegue` custom modal segue! - -

- -

- -[`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! + +

+ +

+ +[`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 4c7b945..00b6a81 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 b01d9c2..45809f2 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 = ""; }; 228DF5481FAD0805004F8A39 /* successIconLight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = successIconLight.png; path = Resources/successIconLight.png; sourceTree = ""; }; 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "Resources/infoIconSubtle@3x.png"; sourceTree = ""; }; + 228F7DDB2ACF7039006C9644 /* MessageHostingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageHostingView.swift; sourceTree = ""; }; + 228F7DDC2ACF703A006C9644 /* SwiftMessageModifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftMessageModifier.swift; sourceTree = ""; }; + 228F7DDD2ACF703A006C9644 /* MessageViewConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageViewConvertible.swift; sourceTree = ""; }; 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = ""; }; 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = ""; }; 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = ""; }; @@ -235,6 +241,15 @@ name = Frameworks; sourceTree = ""; }; + 228F7DDA2ACF7029006C9644 /* SwiftUI */ = { + isa = PBXGroup; + children = ( + 228F7DDC2ACF703A006C9644 /* SwiftMessageModifier.swift */, + 228F7DDD2ACF703A006C9644 /* MessageViewConvertible.swift */, + ); + name = SwiftUI; + sourceTree = ""; + }; 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 ad3b253..5c84455 100644 --- a/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme +++ b/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme @@ -1,6 +1,6 @@ : BaseView, Identifiable where Content: View { + + // MARK: - API + + public let id: String + + public init(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 + + // 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 0000000..6dc168b --- /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 0000000..479b6d9 --- /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: Binding, + 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: ViewModifier where Message: MessageViewConvertible { + // MARK: - API + + fileprivate init( + message: Binding, + 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 80c3939..cd17eec 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 0000000..8b289e2 --- /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 = ""; }; + 228F7DAE2ACF17E8006C9644 /* DemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoView.swift; sourceTree = ""; }; + 228F7DB02ACF17E9006C9644 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 228F7DB32ACF17E9006C9644 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 228F7DBB2ACF1DB5006C9644 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 228F7DBD2ACF1E1E006C9644 /* SwiftMessages.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SwiftMessages.xcodeproj; path = ../SwiftMessages.xcodeproj; sourceTree = ""; }; + 228F7DD42ACF59E4006C9644 /* DemoMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoMessage.swift; sourceTree = ""; }; + 228F7DD62ACF5C2E006C9644 /* DemoMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoMessageView.swift; sourceTree = ""; }; +/* 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 = ""; + }; + 228F7DAA2ACF17E8006C9644 /* Products */ = { + isa = PBXGroup; + children = ( + 228F7DA92ACF17E8006C9644 /* SwiftUIDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 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 = ""; + }; + 228F7DB22ACF17E9006C9644 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 228F7DB32ACF17E9006C9644 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 228F7DBE2ACF1E1E006C9644 /* Products */ = { + isa = PBXGroup; + children = ( + 228F7DC32ACF1E1E006C9644 /* SwiftMessages.framework */, + 228F7DC52ACF1E1E006C9644 /* SwiftMessagesTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 228F7DC72ACF1E63006C9644 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* 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 0000000..919434a --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + 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 0000000..18d9810 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + 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 0000000..eb87897 --- /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 0000000..13613e3 --- /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 0000000..73c0059 --- /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 0000000..15b79d4 --- /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 0000000..ccc86b6 --- /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 0000000..cce5058 --- /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 0000000..e0bcd6c --- /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 0000000..0c67376 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/Info.plist @@ -0,0 +1,5 @@ + + + + + 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 0000000..73c0059 --- /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 0000000..fc44454 --- /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 Date: Fri, 6 Oct 2023 09:46:04 -0500 Subject: [PATCH 15/38] 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 0cf8e79..8cb208b 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`.

-

- -

- - ## 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 Date: Fri, 6 Oct 2023 09:47:53 -0500 Subject: [PATCH 16/38] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a4ec93..fdb8977 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 Date: Fri, 6 Oct 2023 09:55:16 -0500 Subject: [PATCH 17/38] Fix email address --- SwiftMessages.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 00b6a81..941a982 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 Date: Sat, 7 Oct 2023 14:13:34 -0500 Subject: [PATCH 18/38] 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 fdb8977..d17b7a8 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 8cb208b..10ec0f2 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 941a982..e67d4b0 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 8b289e2..f6c945b 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 = ""; }; 228F7DD42ACF59E4006C9644 /* DemoMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoMessage.swift; sourceTree = ""; }; 228F7DD62ACF5C2E006C9644 /* DemoMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoMessageView.swift; sourceTree = ""; }; + 2291AA492AD1E3EC0084868E /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; + 2291AA4C2AD1E4520084868E /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = CHANGELOG.md; path = ../CHANGELOG.md; sourceTree = ""; }; /* 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 cce5058..a299c35 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 e0bcd6c..a6736d8 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 Date: Wed, 1 Nov 2023 12:59:03 -0500 Subject: [PATCH 19/38] 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 d17b7a8..0f5cc82 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 10ec0f2..5af94cb 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 e67d4b0..0e7b79c 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 301d969..f3c0ad9 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 d7bb5f1..489ab96 100644 --- a/SwiftMessages/MessageHostingView.swift +++ b/SwiftMessages/MessageHostingView.swift @@ -39,4 +39,12 @@ public class MessageHostingView: 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 ccc86b6..32624de 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 a299c35..5396302 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 a6736d8..8f47b7d 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 Date: Sun, 3 Dec 2023 10:41:56 -0600 Subject: [PATCH 20/38] #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 e5aa7b9..c41d166 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 b627788..da8f46d 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 0fb976c..c073fe4 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 5a3648b..44f9201 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 21b0f27..a0d440c 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 Date: Sun, 3 Dec 2023 11:54:25 -0600 Subject: [PATCH 21/38] #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 a0f30e8..a906ba1 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 0e7b79c..b2b0e4f 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 45809f2..19d5bcd 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 = ""; }; 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+Extensions.swift"; sourceTree = ""; }; 22A2EA6E24EC6CFA00BB2540 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; + 22D3B4552B1CEF76002D8665 /* Task+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Task+Extensions.swift"; sourceTree = ""; }; 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = CenteredView.xib; path = Resources/CenteredView.xib; sourceTree = ""; }; 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsPanHandler.swift; sourceTree = ""; }; 22E01F631E74EC8B00ACE19A /* MaskingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaskingView.swift; sourceTree = ""; }; @@ -220,6 +222,7 @@ 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */, 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */, 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */, + 22D3B4552B1CEF76002D8665 /* Task+Extensions.swift */, ); name = Extensions; sourceTree = ""; @@ -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 5c84455..ba0f414 100644 --- a/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme +++ b/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme @@ -1,6 +1,6 @@ ) case view(_: Weak) diff --git a/SwiftMessages/SwiftMessageModifier.swift b/SwiftMessages/SwiftMessageModifier.swift index 479b6d9..9974e8b 100644 --- a/SwiftMessages/SwiftMessageModifier.swift +++ b/SwiftMessages/SwiftMessageModifier.swift @@ -47,7 +47,7 @@ private struct SwiftMessageModifier: 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 395bc0a..52244ef 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? { - 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(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(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 0000000..9d6f1c3 --- /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 Date: Sun, 3 Dec 2023 12:03:14 -0600 Subject: [PATCH 22/38] 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 8207406..346ce2f 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 c073fe4..5f5ecaf 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 da82fc1..e381d22 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 cd17eec..35687e1 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 Date: Sun, 3 Dec 2023 12:17:07 -0600 Subject: [PATCH 23/38] Fix typo --- SwiftMessages/SwiftMessages.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index 52244ef..1245f06 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 Date: Mon, 15 Jan 2024 15:20:12 -0600 Subject: [PATCH 24/38] 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 0f5cc82..6031c13 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 5af94cb..6a6f5af 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 b2b0e4f..8042309 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 489ab96..b295669 100644 --- a/SwiftMessages/MessageHostingView.swift +++ b/SwiftMessages/MessageHostingView.swift @@ -16,10 +16,9 @@ public class MessageHostingView: BaseView, Identifiable where Content: public let id: String - public init(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: BaseView, Identifiable where Content: hostVC.view.backgroundColor = .clear } + convenience public init(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 9974e8b..56f40f2 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: Binding, + 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: Binding, 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: ViewModifier where Message: MessageViewConvertible { +private struct SwiftMessageModifier: ViewModifier where Message: Equatable & Identifiable, MessageContent: View { + // MARK: - API fileprivate init( message: Binding, 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, + 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: 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 f6c945b..790676b 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 = ""; }; 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 = ""; }; 228F7DAE2ACF17E8006C9644 /* DemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoView.swift; sourceTree = ""; }; @@ -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 5396302..11cf961 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 0000000..e74172e --- /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