diff --git a/.gitignore b/.gitignore index 4f405ccc..3c698b88 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,50 @@ -xcuserdata \ No newline at end of file +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +.swiftpm/ + +.DS_Store +*.mobileprovision +*.cer +*.certSigningRequest +*.p12 +*.pem +*.pkey +screenshots +rvm.env +.build \ No newline at end of file diff --git a/.swift-version b/.swift-version deleted file mode 100644 index 9f55b2cc..00000000 --- a/.swift-version +++ /dev/null @@ -1 +0,0 @@ -3.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index f5732877..1fa85286 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,469 @@ # Change Log All notable changes to this project will be documented in this file. +## 10.0.1 + +## Features + +* #523 Add a `priority` configuration option. +* #548 Adds 'TopBottomPresentable' protocol to allow animators implementation to reuse 'top/bottom' integration in presentation +* #543 Make the `SwiftMessages` initializer `nonisolated` to improve interoperability with dependency injection frameworks like Factory. +* #560 Add a new `swiftMessage` modifier variation that provides a ` MessageGeometryProxy` type to the message view builder—this works around an inssue with `GeometryReader` not working in `UIHostingController`. + +Fixes +* Fix broken touch handling in iOS 18. + +## 10.0.0 + +### Features + +* Add a variation on the `.swiftMessage()` modifier that takes a view builder instead of requiring that the bound value conform to `MessageViewConvertible`. This syntax is more similar to the familiar `sheet()` modifier syntax and provides more flexibility for constructing message views. +* #207 Add optional haptic feedback + +### Changes + +* Use `@MainActor` to ensure that SwiftMessages is not called from a background queue. +* Bump minimum deployment target to iOS 13. + +### 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 + +* 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 + +* #529 Update readme and SwiftUI demo to demostrate how to mask edges. + +## 9.0.7 + +### Features + +* Added support for SwiftUI + +### 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 + +* 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 + +* #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' +* Improve colors for dark mode. + +## 9.0.3 + +### 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. + +## 9.0.2 + +### Fixes + +* Fix app extension compile error when using CocoaPods. + +## 9.0.1 + +### Fixes + +* #455 #458 Restore key window after message is interacted with. When a message becomes the key window, such as if the user interacts with the message, iOS does not automatically restore the previous key window when the message is dismissed. SwiftMessages has some logic in `WindowViewController` to restore the key window. This change makes that logic more robust. + +## 9.0.0 + +### Features + +* #447 Add the ability to show view controller in a new window with `SwiftMessagesSegue`. +This capability is available when using `SwiftMessagesSegue` programmatically by supplying +an instance of `WindowViewController` as the segue's source view controller. + +### Changes + +* This release has minor breaking changes in the `WindowViewController` initializers. +The `windowLevel` is no longer accepted as an argument because the `config` parameter +should specify the window level in the `presentationContext` property. + +### Fixes + +* #451 Fix app extension crash + +## 8.0.5 + +### Fixes + +* #446 Restore previous key window on dismissal if the message assumed key window status. + +## 8.0.4 + +### Features + +* #442 Add `MarginAdjustable.respectSafeArea` option to exclude safe area from layout margins. +* #430 Support disable `becomeKeyWindow` from SwiftMessages.Config. This is a workaround for potential issues with apps that display additional windows. + +### Fixes + +* #437 Revert to explicitly specifying "SwiftMessages" as the module in nib files. +* #440 Fix crash when using SwiftMessages in app extension + +## 8.0.3 + +### Features + +* Full support for Swift Package Manager + +### Fixes + +* #328 ignoreDuplicates is not working +* #412 Fix deployment target on nib files to match target + +## 8.0.2 + +### Changes + +* [#395](https://github.com/SwiftKickMobile/SwiftMessages/pull/395) Add preliminary support for Swift Package Manager. + +## 8.0.1 + +### Fixes + +* #401 UIAlertController pops up but SwiftMessage layer absorbs all touches. + +## 8.0.0 + +### Changes + +* Add `SwiftMessages.PresentationContext.windowScene` option for targeting a specific window scene. +* Changed the behavior of the default `presentationContext`, `.automatic`. Previously, if the root view controller was presenting, the message would only be displayed over the presented view controller if the `modalPresentationStyle` was `fullScreen` or `overFullScreen`. Now, messages are always displayed over presented view controllers. +* Made `showDuraton` and `hideDuration` on `Animator` non-optional. +* Made `showDuraton` and `hideDuration` writable options on `TopBottomAnimation` and `PhysicsAnimation`. + +### Fixes + +* #365 Fix an issue with customized `TopBottomAnimation` where messages weren't properly displayed under navigation and tab bars. +* #352 Fix accessibility for view controllers presented with `SwiftMessagesSegue`. +* #355 Update card view layout to support centering of pure textual content +* #354 Support `overrideUserInterfaceStyle` when view presented in its own window +* #360 Fix touch handing issue in iOS 13.1.3 +* #382 Fix warnings in Xcode 11.4 + +## 7.0.1 + +### Changes + +* Support iOS 13. + +### Features +* #335 Add option to hide status bar when view is displayed in a window. As of iOS 13, windows can no longer cover the status bar. The only alternative is to set `Config.prefersStatusBarHidden = true` to hide it. + +## 7.0.0 + +### Changes + +* Swift 5 +* Remove deprecated APIs + +### Features + +* #313 Improved sizing on iPad + +>`SwiftMessagesSegue` provides default view controller sizing based on device, with width on iPad being limited to 500pt max. However, it is recommended that you explicitly specify size appropriate for your content using one of the following methods. +> 1. Define sufficient width and height constraints in your view controller such that it sizes itself. +> 1. Set the `preferredContentSize` property (a.k.a "Use Preferred Explicit Size" in Interface Builder's attribute inspector). Zeros are ignored, e.g. `CGSize(width: 0, height: 350)` only affects the height. +> 1. Add explicit width and/or height constraints to `segue.messageView.backgroundView`. +> +>Note that `Layout.topMessage` and `Layout.bottomMessage` are always full screen width. For other layouts, the there is a maximum 500pt width on for regular horizontal size class (iPad) at 950 priority. This limit can be overridden by adding higher-priority constraints. + +* #275 Add ability to avoid the keyboard. + +>The `KeyboardTrackingView` class can be used to cause the message view to avoid the keyboard by sliding up when the keyboard gets too close. +> +>````swift +>// Message view +>var config = SwiftMessages.defaultConfig +>config.keyboardTrackingView = KeyboardTrackingView() +> +>// Or view controller +>segue.keyboardTrackingView = KeyboardTrackingView() +>```` +>You can incorporate `KeyboardTrackingView` into your app even when you're not using SwiftMessages. Install into your view hierarchy by pinning `KeyboardTrackingView` to the bottom, leading, and trailing edges of the screen. Then pin the bottom of your content that should avoid the keyboard to the top `KeyboardTrackingView`. Use an equality constraint to strictly track the keyboard or an inequality constraint to only move when the keyboard gets too close. `KeyboardTrackingView` works by observing keyboard notifications and adjusting its height to maintain its top edge above the keyboard, thereby pushing your content up. See the comments in `KeyboardTrackingView` for configuration options. + + +* #276 Add ability to hide message without animation +* #272 Add duration for `SwiftMessagesSegue` +* #278 Make pan gesture recognizers public + +## 6.0.2 + +### Features + +* #262 Add event listeners to `SwiftMessagesSegue`. + +## 6.0.1 + +### Features +* #257 The `.centered` presentation style, which is a shortcut for a specific configuration of the `PhysicsAnimation` animator, provides a physics-based dismissal gesture where the view can be flung off screen. When the view goes out of the container view's bounds, the animator calls `SwiftMessages.hide()`, which animates the dim view away and concludes the message view's lifecycle. There is currently a small delay of 0.2s before calling `hide()`. + +This change adds the ability to configure the delay by customizing the animator. For example, to set the delay to zero, one would do: + +````swift +let animation = PhysicsAnimation() +animation.panHandler.hideDelay = 0 +config.presentationStyle = .custom(animator: animation) +```` + +## 6.0.0 + +### Changes + +* Migrate to Swift 4.2 + +### Fixes + +* Fix #228 restore shared SwiftMessages scheme + +## 5.0.1 + +### Fixes + +* Remove debug code that broke the view controller's section of the Demo app. + +## 5.0.0 + +### Breaking Changes + +* Removed support for iOS 8. + +### Features +* Add support for modal view controller presentation using [`SwiftMessagesSegue`](./SwiftMessages/SwiftMessagesSegue.swift) custom segue subclass. Try it out in the "View Controllers" section of the Demo app. In addition to the class documentation, more can be found in the [View Controllers](./ViewControllers.md) readme. +* Update nib files to be more visually consistent with iPhone X: + * Introduce [`CornerRoundingView`](./SwiftMessages/CornerRoundingView.swift), which provides configurable corner rounding using squircles (the smoother method of rounding corners that you see on app icons). Nib files that feature rounded corners have their `backgroundView` assigned to a `CornerRoundingView`. `CornerRoundingView` provides a `roundsLeadingCorners` option to dynamically round only the leading corners of the view when presented from top or bottom (a feature used for the tab-style layouts). + * Increased the default corner radius to 20. Corner radius can be changed by either modifying the nib file or +* Reworked the [`MarginAdjustable`](./SwiftMessages/MarginAdjustable.swift) to improve configurability of layout margins. +* Add rubber-banding to the interactive dismissal gesture. Rubber banding is automatically applied for views where `backgroundView` is inset from the message view's edges. +* Added `showDuration` and `hideDuration` properties to the `Animator` protocol (with default implementation that returns `nil`). These values enable animations to work for view controller presentation. + +### Fixes + +* #202 bodyLabel should set textAlignment to .natural +* #200 Automatic Presentation Context Broken +* Fix default value of `TopBottomAnimation.closePercentThreshold` + +## 4.1.4 + +### Bug Fixes +* Fix #191 Prevent usage of UIApplication.shared when building for extensions + +### Improvements +* #192 Add a way to test compilation with app extension + +## 4.1.3 + +### Features +* #183 Added iOS app extension support at compile time. + +### Bug Fixes +* Fix #185 Incorrect margin adjustments in landscape +* Fix #188 Physics animation visual glitch + +## 4.1.2 + +### Features +* Updates for Swift 4.1 +* #164 Added an optional `windowViewController` property to `SwiftMessages.Config` for supplying a custom subclass of `WindowViewController`. + +### Bug Fixes +* Custom presentation styles using `TopBottomAnimation` now display properly under top and bottom bars. + +## 4.1.1 + +### Features +* #152 Get current message being displayed without specifying an `id` + +## 4.1.0 + +### Features + +* Fix #134 add support for `CenterAnimation` displayed on top or bottom instead of center (renamed to `PhysicsAnimation`). + +### Fixes + +* Fix #128 move icons out of asset catalog to prevent mysterious crash +* Fix #129 adjust layout margins on orientation change to preserve layout when iOS hides status bar in landscape. +* Fix #131 by always completing hide/show animations if application isn't active. + + +## 4.0.0 + +### Features +* Swift 4.0 syntax +* Added support for iOS 11 and iPhone X. From the readme: + + SwiftMessages 4 supports iOS 11 out-of-the-box with built-in support for safe areas. To ensur that message view layouts look just right when overlapping safe areas, views that adopt the `MarginAdjustable` protocol (like `MessageView`) will have their layout margins automatically adjusted by SwiftMessages. However, there is no one-size-fits-all adjustment, so the following properties were added to `MarginAdjustable` to allow for additional adjustments to be made to the layout margins: + + ````swift + public protocol MarginAdjustable { + ... + /// Safe area top adjustment in iOS 11+ + var safeAreaTopOffset: CGFloat { get set } + /// Safe area bottom adjustment in iOS 11+ + var safeAreaBottomOffset: CGFloat { get set } + } + ```` + + If you're using using custom nib files or view classes and your layouts don't look quite right, try adjusting the values of these properties. `BaseView` (the super class of `MessageView`) declares these properties to be `@IBDesignable` and you can find sample values in the nib files included with SwiftMessages. + +### Bug Fixes +* Fix #100 memory leak. +* Change `Layout` enum capitalization to current Swift conventions. + +## [3.5.1](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.5.0) + +### Bug Fixes +* Undo change that broke `MessageView` class reference on nib files copied out of the SwiftMessages framework. + +## [3.5.0](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.5.0) + +### Features +* Added `SwiftMessages.hideCounted(id:)` method of hiding. The counted method hides when the number of calls to `show()` and `hideCounted(id:)` for a +given message ID are equal. This can be useful for messages that may be +shown from multiple code paths to ensure that all paths are ready to hide. + + Also added `SwiftMessages.count(id:)` to get the current count and `SwiftMessages.set(id:count:)` to set the current count. + +* Added ways to retrieve message views currently being shown, hidden, or queued to be shown. + + ````swift + // Get a message view with the given ID if it is currently + // being shown or hidden. + if let view = SwiftMessages.current(id: "some id") { ... } + + // Get a message view with the given ID if is it currently + // queued to be shown. + if let view = SwiftMessages.queued(id: "some id") { ... } + + // Get a message view with the given ID if it is currently being + // shown, hidden or in the queue to be shown. + if let view = SwiftMessages.currentOrQueued(id: "some id") { ... } + ```` + +### Bug Fixes +* Fix #116 for message views that don't adopt the `Identifiable` protocol by using the memory address as the ID. +* Fix #113 MessageView not hiding +* Fix #87 Support manual install + +## [3.4.0](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.4.0) + +### Features +* Added `.center` presentation style with a physics-based dismissal gesture. +* Added `.custom(animator:)` presentation style, where you provide an instance of the `Animator` protocol. The `TopBottomAnimation` and `CenterAnimation` animations both implement `Animator` and may be subclassed (configuration options will be added in a future release). `PhysicsPanHandler` class to provide a physics-based dismissal gesture. +* Added `.centered` message view layout with elements centered and arranged vertically. +* Added `configureBackgroundView(width:)` and `configureBackgroundView(sideMargin:)` convenience methods to `MessageView`. + +## [3.3.4](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.3.4) + +### Features +* #89 Add `blur` dim mode option. + +### Bug Fixes +* #98 Fix touch handling in message view's background view. +* #97 Fix main thread checker warning + +## [3.3.3](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.3.3) + +### Bug Fixes +* Fix an issue where rapidly showing and hiding messages could result in messages becoming orphaned on-screen. + +## [3.3.2](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.3.2) + +### Improvements +* `MessageView` is smarter about including additional accessibility views for cases where you've added accessible elements to the view. Previously only the `button` was included. Now all views where `isAccessibilityElement == true`. + + Note that all nib files now have `isAccessibilityElement == false` for `titleLabel`, `bodyLabel` and `iconLabel` (`titleLabel` and `bodyLabel` are read out as part of the overall message view's text). If any of these need to be directly accessible, then copy the nib file into your project and select "Enabled" in the Accessibility section of the Identity Inspector. + +## [3.3.1](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.3.1) + +### Bug Fixes +* Fix regression where the UI was being blocked when using `DimMode.none`. + +## [3.3.0](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.3.0) + +### Features +* Add proper support for VoiceOver. See the [Accessibility section](README.md#accessibility) of the readme. + +## [3.2.1](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.2.1) + +### Bug Fixes +* Fix infinite loop bug introduced in 3.2.0. + +## [3.2.0](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.2.0) + +### Features +* Added the ability to display messages for an indefinite duration while enforcing a minimum duration using `Duration.indefinite(delay:minimum)`. + +This option is useful for displaying a message when a process is taking too long but you don't want to display the message if the process completes in a reasonable amount of time. + +For example, if a URL load is expected to complete in 2 seconds, you may use the value `unknown(delay: 2, minimum 1)` to ensure that the message will not be displayed most of the time, but will be displayed for at least 1 second if the operation takes longer than 2 seconds. By specifying a minimum duration, you can avoid hiding the message too fast if the operation finishes right after the delay interval. + +### Bug Fixes +* Prevent views below the dim view from receiving accessibility focus. +* Prevent taps in the message view from hiding when using interactive dim mode. +* Fix memory leak of single message view + +## [3.1.5](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.1.5) + +### Bug Fixes + +* Fix memory leak of `MessageViews`. + +## [3.1.4](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.1.4) + +### Bug Fixes + +* Fixed an issue where UIKit components were being instantiated off the main queue. + +## [3.1.3](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.1.3) + +### Features + +* Added the ability to set a custom value on `MessageView.id`. This can be useful for dismissing specific messages using a pre-defined `id`. + +## [3.1.2](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.1.2) + +### Features + +* Changed the default behavior when a message is displayed in its own window (such as with `.window` presentation context) to no longer become the key window in order to prevent the keyboard from dismissing. If one needs the message's window to become key, this can be done by setting `SwiftMessages.Config.becomeKeyWindow` to `true`. See + +### Bug Fixes + +* Changed the internal logic of hiding a message view to always succeed to work around the problem of the hide animation failing, such as when started while the app is not active. +* Improved reliability of the automatic adjustments made to avoid message views overlapping the status bar, particularly when using the `.view` presentation context. + ## [3.1.1](https://github.com/SwiftKickMobile/SwiftMessages/releases/tag/3.1.1) ### Features diff --git a/Demo/Podfile b/Demo/.Podfile similarity index 51% rename from Demo/Podfile rename to Demo/.Podfile index e73d6059..e1c67ab0 100644 --- a/Demo/Podfile +++ b/Demo/.Podfile @@ -2,5 +2,7 @@ target 'Demo' do use_frameworks! workspace 'Demo.xcworkspace' xcodeproj 'Demo.xcodeproj' - pod 'SwiftMessages', :path => '../' + pod 'SwiftMessages/App', :path => '../' + pod 'SwiftMessages/SegueExtras', :path => '../' end + diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 7507ff4d..57a9b7a5 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -7,21 +7,84 @@ objects = { /* Begin PBXBuildFile section */ - 49BBBE829403C46C88EE748E /* Pods_Demo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 094A4CD596AFE2FDC36B2833 /* Pods_Demo.framework */; }; + 22652712210F698600310344 /* TacoDialogView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 86C0AB9F1D5E814600F76BD6 /* TacoDialogView.xib */; }; + 226FA5E61F506993004CB2BC /* CountedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 226FA5E51F506993004CB2BC /* CountedViewController.swift */; }; + 226FA5E81F5071D0004CB2BC /* CountedMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 226FA5E71F5071D0004CB2BC /* CountedMessageView.swift */; }; + 226FA5EA1F507586004CB2BC /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 226FA5E91F507586004CB2BC /* Utils.swift */; }; + 22F27953210D0FDE00273E7F /* ViewControllersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22F27952210D0FDE00273E7F /* ViewControllersViewController.swift */; }; + 22FE3FA821193CB90017303D /* SwiftMessages.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22FB324121193A3B005C13D9 /* SwiftMessages.framework */; }; + 22FE3FA921193CB90017303D /* SwiftMessages.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 22FB324121193A3B005C13D9 /* SwiftMessages.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 8642F4361D5F7F540061BDCD /* ExploreViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8642F4351D5F7F540061BDCD /* ExploreViewController.swift */; }; 86AEDCE61D5D1DB70030232E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AEDCE51D5D1DB70030232E /* AppDelegate.swift */; }; 86AEDCE81D5D1DB70030232E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AEDCE71D5D1DB70030232E /* ViewController.swift */; }; 86AEDCEB1D5D1DB70030232E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 86AEDCE91D5D1DB70030232E /* Main.storyboard */; }; 86AEDCED1D5D1DB70030232E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 86AEDCEC1D5D1DB70030232E /* Assets.xcassets */; }; 86AEDCF01D5D1DB70030232E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 86AEDCEE1D5D1DB70030232E /* LaunchScreen.storyboard */; }; - 86C0ABA01D5E814600F76BD6 /* TacoDialogView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 86C0AB9F1D5E814600F76BD6 /* TacoDialogView.xib */; }; 86C0ABA21D5E816600F76BD6 /* TacoDialogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86C0ABA11D5E816600F76BD6 /* TacoDialogView.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 22FB324021193A3B005C13D9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 22FB323A21193A3B005C13D9 /* SwiftMessages.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 86B48AEC1D5A41C900063E2B; + remoteInfo = SwiftMessages; + }; + 22FB324421193A3B005C13D9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 22FB323A21193A3B005C13D9 /* SwiftMessages.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 86B48AF51D5A41C900063E2B; + remoteInfo = SwiftMessagesTests; + }; + 22FB324621193A4D005C13D9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 22FB323A21193A3B005C13D9 /* SwiftMessages.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 86B48AEB1D5A41C900063E2B; + remoteInfo = SwiftMessages; + }; + 22FE3FAA21193CB90017303D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 22FB323A21193A3B005C13D9 /* SwiftMessages.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 86B48AEB1D5A41C900063E2B; + remoteInfo = SwiftMessages; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 22774C2520B8461A00813732 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; + 22FE3FB021193CB90017303D /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 22FE3FA921193CB90017303D /* SwiftMessages.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ - 094A4CD596AFE2FDC36B2833 /* Pods_Demo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Demo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 160AC8A3EE68E1D705664BF8 /* Pods-Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Demo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Demo/Pods-Demo.debug.xcconfig"; sourceTree = "<group>"; }; - 16131DA1E3BA049C9E4C0308 /* Pods-Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Demo.release.xcconfig"; path = "Pods/Target Support Files/Pods-Demo/Pods-Demo.release.xcconfig"; sourceTree = "<group>"; }; + 226FA5E51F506993004CB2BC /* CountedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CountedViewController.swift; sourceTree = "<group>"; }; + 226FA5E71F5071D0004CB2BC /* CountedMessageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CountedMessageView.swift; sourceTree = "<group>"; }; + 226FA5E91F507586004CB2BC /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; }; + 22774C1420B8461900813732 /* Messages.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Messages.framework; path = System/Library/Frameworks/Messages.framework; sourceTree = SDKROOT; }; + 22F27952210D0FDE00273E7F /* ViewControllersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewControllersViewController.swift; sourceTree = "<group>"; }; + 22FB323A21193A3B005C13D9 /* SwiftMessages.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SwiftMessages.xcodeproj; path = ../SwiftMessages.xcodeproj; sourceTree = "<group>"; }; 8642F4351D5F7F540061BDCD /* ExploreViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExploreViewController.swift; sourceTree = "<group>"; }; 86AEDCE21D5D1DB70030232E /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 86AEDCE51D5D1DB70030232E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; @@ -39,28 +102,28 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 49BBBE829403C46C88EE748E /* Pods_Demo.framework in Frameworks */, + 22FE3FA821193CB90017303D /* SwiftMessages.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 6AB98897E817EE976DD72852 /* Frameworks */ = { + 22FB323B21193A3B005C13D9 /* Products */ = { isa = PBXGroup; children = ( - 094A4CD596AFE2FDC36B2833 /* Pods_Demo.framework */, + 22FB324121193A3B005C13D9 /* SwiftMessages.framework */, + 22FB324521193A3B005C13D9 /* SwiftMessagesTests.xctest */, ); - name = Frameworks; + name = Products; sourceTree = "<group>"; }; - 7AEB2A3BA8EF9DC4D87CD5FA /* Pods */ = { + 6AB98897E817EE976DD72852 /* Frameworks */ = { isa = PBXGroup; children = ( - 160AC8A3EE68E1D705664BF8 /* Pods-Demo.debug.xcconfig */, - 16131DA1E3BA049C9E4C0308 /* Pods-Demo.release.xcconfig */, + 22774C1420B8461900813732 /* Messages.framework */, ); - name = Pods; + name = Frameworks; sourceTree = "<group>"; }; 86AEDCD91D5D1DB70030232E = { @@ -68,8 +131,8 @@ children = ( 86AEDCE41D5D1DB70030232E /* Demo */, 86AEDCE31D5D1DB70030232E /* Products */, - 7AEB2A3BA8EF9DC4D87CD5FA /* Pods */, 6AB98897E817EE976DD72852 /* Frameworks */, + 22FB323A21193A3B005C13D9 /* SwiftMessages.xcodeproj */, ); sourceTree = "<group>"; }; @@ -85,14 +148,18 @@ isa = PBXGroup; children = ( 86AEDCE51D5D1DB70030232E /* AppDelegate.swift */, + 86AEDCE91D5D1DB70030232E /* Main.storyboard */, 86AEDCE71D5D1DB70030232E /* ViewController.swift */, 8642F4351D5F7F540061BDCD /* ExploreViewController.swift */, - 86AEDCE91D5D1DB70030232E /* Main.storyboard */, + 226FA5E51F506993004CB2BC /* CountedViewController.swift */, + 22F27952210D0FDE00273E7F /* ViewControllersViewController.swift */, 86AEDCEC1D5D1DB70030232E /* Assets.xcassets */, 86AEDCEE1D5D1DB70030232E /* LaunchScreen.storyboard */, 86AEDCF11D5D1DB70030232E /* Info.plist */, 86C0ABA11D5E816600F76BD6 /* TacoDialogView.swift */, 86C0AB9F1D5E814600F76BD6 /* TacoDialogView.xib */, + 226FA5E71F5071D0004CB2BC /* CountedMessageView.swift */, + 226FA5E91F507586004CB2BC /* Utils.swift */, ); path = Demo; sourceTree = "<group>"; @@ -104,16 +171,17 @@ isa = PBXNativeTarget; buildConfigurationList = 86AEDCF41D5D1DB70030232E /* Build configuration list for PBXNativeTarget "Demo" */; buildPhases = ( - D459C3DF988BEB6ED9625B99 /* [CP] Check Pods Manifest.lock */, 86AEDCDE1D5D1DB70030232E /* Sources */, 86AEDCDF1D5D1DB70030232E /* Frameworks */, 86AEDCE01D5D1DB70030232E /* Resources */, - 1EB2C90557DD78EF0B2FD638 /* [CP] Embed Pods Frameworks */, - 2FFDC4A45AD78DB76BCCD90F /* [CP] Copy Pods Resources */, + 22774C2520B8461A00813732 /* Embed App Extensions */, + 22FE3FB021193CB90017303D /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( + 22FB324721193A4D005C13D9 /* PBXTargetDependency */, + 22FE3FAB21193CB90017303D /* PBXTargetDependency */, ); name = Demo; productName = Demo; @@ -126,19 +194,19 @@ 86AEDCDA1D5D1DB70030232E /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0810; + LastSwiftUpdateCheck = 0940; + LastUpgradeCheck = 1200; ORGANIZATIONNAME = "SwiftKick Mobile"; TargetAttributes = { 86AEDCE11D5D1DB70030232E = { CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 0800; + LastSwiftMigration = 1020; }; }; }; buildConfigurationList = 86AEDCDD1D5D1DB70030232E /* Build configuration list for PBXProject "Demo" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -147,6 +215,12 @@ mainGroup = 86AEDCD91D5D1DB70030232E; productRefGroup = 86AEDCE31D5D1DB70030232E /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 22FB323B21193A3B005C13D9 /* Products */; + ProjectRef = 22FB323A21193A3B005C13D9 /* SwiftMessages.xcodeproj */; + }, + ); projectRoot = ""; targets = ( 86AEDCE11D5D1DB70030232E /* Demo */, @@ -154,82 +228,68 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 22FB324121193A3B005C13D9 /* SwiftMessages.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = SwiftMessages.framework; + remoteRef = 22FB324021193A3B005C13D9 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 22FB324521193A3B005C13D9 /* SwiftMessagesTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = SwiftMessagesTests.xctest; + remoteRef = 22FB324421193A3B005C13D9 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 86AEDCE01D5D1DB70030232E /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 86AEDCF01D5D1DB70030232E /* LaunchScreen.storyboard in Resources */, + 22652712210F698600310344 /* TacoDialogView.xib in Resources */, 86AEDCED1D5D1DB70030232E /* Assets.xcassets in Resources */, - 86C0ABA01D5E814600F76BD6 /* TacoDialogView.xib in Resources */, 86AEDCEB1D5D1DB70030232E /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ -/* Begin PBXShellScriptBuildPhase section */ - 1EB2C90557DD78EF0B2FD638 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Demo/Pods-Demo-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 2FFDC4A45AD78DB76BCCD90F /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Demo/Pods-Demo-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - D459C3DF988BEB6ED9625B99 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Check Pods Manifest.lock"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ 86AEDCDE1D5D1DB70030232E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 8642F4361D5F7F540061BDCD /* ExploreViewController.swift in Sources */, + 226FA5E81F5071D0004CB2BC /* CountedMessageView.swift in Sources */, 86AEDCE81D5D1DB70030232E /* ViewController.swift in Sources */, + 226FA5EA1F507586004CB2BC /* Utils.swift in Sources */, 86AEDCE61D5D1DB70030232E /* AppDelegate.swift in Sources */, + 226FA5E61F506993004CB2BC /* CountedViewController.swift in Sources */, 86C0ABA21D5E816600F76BD6 /* TacoDialogView.swift in Sources */, + 22F27953210D0FDE00273E7F /* ViewControllersViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 22FB324721193A4D005C13D9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftMessages; + targetProxy = 22FB324621193A4D005C13D9 /* PBXContainerItemProxy */; + }; + 22FE3FAB21193CB90017303D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftMessages; + targetProxy = 22FE3FAA21193CB90017303D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ 86AEDCE91D5D1DB70030232E /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -254,19 +314,29 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = 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_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_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -289,7 +359,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -302,19 +372,29 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = 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_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_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -331,7 +411,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -342,29 +422,35 @@ }; 86AEDCF51D5D1DB70030232E /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 160AC8A3EE68E1D705664BF8 /* Pods-Demo.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Demo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.Demo; + PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages.Demo; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 86AEDCF61D5D1DB70030232E /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 16131DA1E3BA049C9E4C0308 /* Pods-Demo.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Demo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.Demo; + PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.SwiftMessages.Demo; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; diff --git a/Demo/Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Demo/Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Demo/Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEDidComputeMac32BitWarning</key> + <true/> +</dict> +</plist> diff --git a/Demo/Demo.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/Demo.xcscheme b/Demo/Demo.xcodeproj/xcshareddata/xcschemes/Demo.xcscheme similarity index 85% rename from Demo/Demo.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/Demo.xcscheme rename to Demo/Demo.xcodeproj/xcshareddata/xcschemes/Demo.xcscheme index 0dcdf7bc..db82f1fa 100644 --- a/Demo/Demo.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/Demo.xcscheme +++ b/Demo/Demo.xcodeproj/xcshareddata/xcschemes/Demo.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0810" + LastUpgradeVersion = "1200" version = "1.3"> <BuildAction parallelizeBuildables = "YES" @@ -29,17 +29,6 @@ shouldUseLaunchSchemeArgsEnv = "YES"> <Testables> </Testables> - <MacroExpansion> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "86AEDCE11D5D1DB70030232E" - BuildableName = "Demo.app" - BlueprintName = "Demo" - ReferencedContainer = "container:Demo.xcodeproj"> - </BuildableReference> - </MacroExpansion> - <AdditionalOptions> - </AdditionalOptions> </TestAction> <LaunchAction buildConfiguration = "Debug" @@ -61,8 +50,6 @@ ReferencedContainer = "container:Demo.xcodeproj"> </BuildableReference> </BuildableProductRunnable> - <AdditionalOptions> - </AdditionalOptions> </LaunchAction> <ProfileAction buildConfiguration = "Release" diff --git a/Demo/Demo.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/xcschememanagement.plist b/Demo/Demo.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index e5aab7bc..00000000 --- a/Demo/Demo.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>SchemeUserState</key> - <dict> - <key>Demo.xcscheme</key> - <dict> - <key>orderHint</key> - <integer>0</integer> - </dict> - </dict> - <key>SuppressBuildableAutocreation</key> - <dict> - <key>86AEDCE11D5D1DB70030232E</key> - <dict> - <key>primary</key> - <true/> - </dict> - </dict> -</dict> -</plist> diff --git a/Demo/Demo.xcworkspace/xcuserdata/wtmoose.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Demo/Demo.xcworkspace/xcuserdata/wtmoose.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist deleted file mode 100644 index 8977aeff..00000000 --- a/Demo/Demo.xcworkspace/xcuserdata/wtmoose.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Bucket - type = "0" - version = "2.0"> - <Breakpoints> - <BreakpointProxy - BreakpointExtensionID = "Xcode.Breakpoint.SymbolicBreakpoint"> - <BreakpointContent - shouldBeEnabled = "Yes" - ignoreCount = "0" - continueAfterRunningActions = "Yes" - symbolName = "UIApplicationMain" - moduleName = ""> - <Actions> - <BreakpointActionProxy - ActionExtensionID = "Xcode.BreakpointAction.DebuggerCommand"> - <ActionContent - consoleCommand = "expr (Class)NSClassFromString(@"IBARevealLoader") == nil ? (void *)dlopen("/Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/libReveal.dylib", 0x2) : ((void*)0)"> - </ActionContent> - </BreakpointActionProxy> - </Actions> - <Locations> - </Locations> - </BreakpointContent> - </BreakpointProxy> - </Breakpoints> -</Bucket> diff --git a/Demo/Demo/AppDelegate.swift b/Demo/Demo/AppDelegate.swift index a3ca313a..ab254933 100644 --- a/Demo/Demo/AppDelegate.swift +++ b/Demo/Demo/AppDelegate.swift @@ -8,37 +8,17 @@ import UIKit +let brandColor = UIColor(red: 42/255.0, green: 168/255.0, blue: 250/255.0, alpha: 1) + @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { + window?.tintColor = brandColor + UISwitch.appearance().onTintColor = brandColor return true } - - func applicationWillResignActive(_ application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(_ application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - } - - func applicationWillEnterForeground(_ application: UIApplication) { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(_ application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(_ application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - } - - } diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json index b8236c65..2eeb86b6 100644 --- a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,44 +1,118 @@ { "images" : [ { - "idiom" : "iphone", "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", "scale" : "2x" }, { - "idiom" : "iphone", "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", "scale" : "3x" }, { + "size" : "29x29", "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", "scale" : "2x" }, { - "idiom" : "iphone", "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", "scale" : "3x" }, { - "idiom" : "iphone", "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", "scale" : "2x" }, { - "idiom" : "iphone", "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", "scale" : "3x" }, { - "idiom" : "iphone", "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", "scale" : "2x" }, { - "idiom" : "iphone", "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x-1.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x-1.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x-1.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x-2.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x-1.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-iTunes.png", + "scale" : "1x" } ], "info" : { diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 00000000..f3637f34 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-1.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-1.png new file mode 100644 index 00000000..7cad51b4 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-1.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-2.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-2.png new file mode 100644 index 00000000..7cad51b4 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-2.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 00000000..7cad51b4 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 00000000..76c56454 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x-1.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x-1.png new file mode 100644 index 00000000..0849f153 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x-1.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 00000000..0849f153 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png new file mode 100644 index 00000000..48315c2e Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 00000000..48315c2e Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 00000000..b26f4bc9 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png new file mode 100644 index 00000000..3ae27f01 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 00000000..3ae27f01 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 00000000..ce7c60fa Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 00000000..ce7c60fa Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 00000000..006d9164 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 00000000..1560730f Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 00000000..a7187cb7 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 00000000..4482fe43 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-iTunes.png b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-iTunes.png new file mode 100644 index 00000000..c6c98fdf Binary files /dev/null and b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Icon-App-iTunes.png differ diff --git a/Demo/Demo/Assets.xcassets/iconSwiftMessages.imageset/iconSwiftMessages.pdf b/Demo/Demo/Assets.xcassets/iconSwiftMessages.imageset/iconSwiftMessages.pdf index 19fbe440..47dca35c 100644 Binary files a/Demo/Demo/Assets.xcassets/iconSwiftMessages.imageset/iconSwiftMessages.pdf and b/Demo/Demo/Assets.xcassets/iconSwiftMessages.imageset/iconSwiftMessages.pdf differ diff --git a/SwiftMessages/Resources/Images.xcassets/infoIcon.imageset/Contents.json b/Demo/Demo/Assets.xcassets/splashBanner.imageset/Contents.json similarity index 63% rename from SwiftMessages/Resources/Images.xcassets/infoIcon.imageset/Contents.json rename to Demo/Demo/Assets.xcassets/splashBanner.imageset/Contents.json index 211a2ee0..7195c55c 100644 --- a/SwiftMessages/Resources/Images.xcassets/infoIcon.imageset/Contents.json +++ b/Demo/Demo/Assets.xcassets/splashBanner.imageset/Contents.json @@ -2,7 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "infoIcon.pdf" + "filename" : "splashBanner.pdf" } ], "info" : { @@ -10,6 +10,6 @@ "author" : "xcode" }, "properties" : { - "template-rendering-intent" : "template" + "template-rendering-intent" : "original" } } \ No newline at end of file diff --git a/Demo/Demo/Assets.xcassets/splashBanner.imageset/splashBanner.pdf b/Demo/Demo/Assets.xcassets/splashBanner.imageset/splashBanner.pdf new file mode 100644 index 00000000..0ee52801 Binary files /dev/null and b/Demo/Demo/Assets.xcassets/splashBanner.imageset/splashBanner.pdf differ diff --git a/Demo/Demo/Base.lproj/LaunchScreen.storyboard b/Demo/Demo/Base.lproj/LaunchScreen.storyboard index 12e77ef2..4fb64dba 100644 --- a/Demo/Demo/Base.lproj/LaunchScreen.storyboard +++ b/Demo/Demo/Base.lproj/LaunchScreen.storyboard @@ -1,9 +1,9 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11201" systemVersion="15G1004" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> + <device id="retina4_7" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/> - <capability name="Constraints to layout margins" minToolsVersion="6.0"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> @@ -19,31 +19,24 @@ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Demo" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hTc-9T-AJk"> - <fontDescription key="fontDescription" type="system" weight="heavy" pointSize="32"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <nil key="highlightedColor"/> - </label> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SwiftMessages" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iEm-gV-LFh"> - <fontDescription key="fontDescription" type="system" pointSize="18"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <nil key="highlightedColor"/> - </label> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="© 2016 SWIFTKICK MOBILE LLC" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sBz-Dk-SSO"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="© 2024 SWIFTKICK MOBILE LLC" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sBz-Dk-SSO"> + <rect key="frame" x="46" y="643" width="283" height="16"/> <fontDescription key="fontDescription" type="system" pointSize="13"/> <color key="textColor" red="0.47391887630000001" green="0.47391887630000001" blue="0.47391887630000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> + <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="splashBanner" translatesAutoresizingMaskIntoConstraints="NO" id="236-Ta-JzA"> + <rect key="frame" x="16" y="196.5" width="343" height="274"/> + </imageView> </subviews> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> + <constraint firstItem="236-Ta-JzA" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="CEe-Gz-yDf"/> <constraint firstItem="sBz-Dk-SSO" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leadingMargin" constant="30" id="Dkq-dl-gDt"/> - <constraint firstItem="hTc-9T-AJk" firstAttribute="top" secondItem="iEm-gV-LFh" secondAttribute="bottom" constant="10" id="FUA-Cy-JNO"/> - <constraint firstItem="iEm-gV-LFh" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="KU7-0z-XwE"/> <constraint firstItem="xb3-aO-Qok" firstAttribute="top" secondItem="sBz-Dk-SSO" secondAttribute="bottom" constant="8" symbolic="YES" id="UrJ-mr-8Jj"/> - <constraint firstItem="hTc-9T-AJk" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="dHc-Lg-8u0"/> <constraint firstAttribute="trailingMargin" secondItem="sBz-Dk-SSO" secondAttribute="trailing" constant="30" id="ezd-98-VGo"/> - <constraint firstItem="hTc-9T-AJk" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="suo-tr-ZDY"/> + <constraint firstItem="236-Ta-JzA" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leadingMargin" id="hFL-YR-MPf"/> + <constraint firstItem="236-Ta-JzA" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="mTQ-eG-DFv"/> </constraints> </view> </viewController> @@ -52,4 +45,7 @@ <point key="canvasLocation" x="53" y="375"/> </scene> </scenes> + <resources> + <image name="splashBanner" width="370" height="274"/> + </resources> </document> diff --git a/Demo/Demo/Base.lproj/Main.storyboard b/Demo/Demo/Base.lproj/Main.storyboard index 2be9921a..c38d6707 100644 --- a/Demo/Demo/Base.lproj/Main.storyboard +++ b/Demo/Demo/Base.lproj/Main.storyboard @@ -1,9 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11201" systemVersion="16A323" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="JQZ-C5-7mw"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="JQZ-C5-7mw"> + <device id="retina4_7" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/> - <capability name="Constraints to layout margins" minToolsVersion="6.0"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/> + <capability name="System colors in document resources" minToolsVersion="11.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> @@ -29,25 +30,26 @@ <objects> <tableViewController id="vur-BZ-g1e" customClass="ViewController" customModule="Demo" customModuleProvider="target" sceneMemberID="viewController"> <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="j4a-wU-637"> - <rect key="frame" x="0.0" y="0.0" width="414" height="736"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> <prototypes> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="TitleBody" rowHeight="80" id="2n5-7h-3B5" userLabel="TitleBodyCell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> - <rect key="frame" x="0.0" y="92" width="414" height="80"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="TitleBody" rowHeight="80" id="2n5-7h-3B5" userLabel="TitleBody Cell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> + <rect key="frame" x="0.0" y="50" width="375" height="80"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="2n5-7h-3B5" id="Q5r-8D-38q"> - <frame key="frameInset" width="414" height="79.666666666666671"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="80"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="752" text="TITLE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Icl-Ci-lfe"> + <rect key="frame" x="26" y="21" width="323" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Body" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Gpd-DA-5jT"> + <rect key="frame" x="26" y="45" width="323" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" red="0.4739188762626263" green="0.4739188762626263" blue="0.4739188762626263" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -66,21 +68,22 @@ <outlet property="titleLabel" destination="Icl-Ci-lfe" id="XnB-LL-hx6"/> </connections> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="Explore" rowHeight="80" id="4Pm-kC-YGr" userLabel="ExploreCell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> - <rect key="frame" x="0.0" y="172" width="414" height="80"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="Explore" rowHeight="80" id="4Pm-kC-YGr" userLabel="Explore Cell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> + <rect key="frame" x="0.0" y="130" width="375" height="80"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="4Pm-kC-YGr" id="LmG-UL-Bu8"> - <frame key="frameInset" width="381" height="79.666666666666671"/> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="80"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="752" text="EXPLORE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TbM-iT-SVg"> + <rect key="frame" x="26" y="21" width="304.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Explore many of the SwiftMessages configuration options." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Siq-Fh-MNa"> + <rect key="frame" x="26" y="45" width="304.5" height="14"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" red="0.47391887630000001" green="0.47391887630000001" blue="0.47391887630000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -100,6 +103,109 @@ <segue destination="NF9-wZ-lbZ" kind="show" id="qqa-aN-MxW"/> </connections> </tableViewCell> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="ViewController" rowHeight="80" id="edV-Vx-7mh" userLabel="View Controller Cell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> + <rect key="frame" x="0.0" y="210" width="375" height="80"/> + <autoresizingMask key="autoresizingMask"/> + <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="edV-Vx-7mh" id="6Ng-ZR-L6v"> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="80"/> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="752" text="VIEW CONTROLLERS" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qz1-BL-wQN"> + <rect key="frame" x="26" y="21" width="304.5" height="16"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> + <nil key="highlightedColor"/> + </label> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Present modal view controllers with SwiftMessages animations." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sCg-K7-URy"> + <rect key="frame" x="26" y="45" width="304.5" height="14"/> + <fontDescription key="fontDescription" type="system" pointSize="16"/> + <color key="textColor" systemColor="secondaryLabelColor"/> + <nil key="highlightedColor"/> + </label> + </subviews> + <constraints> + <constraint firstAttribute="bottomMargin" secondItem="sCg-K7-URy" secondAttribute="bottom" constant="10" id="5CA-Mw-MCB"/> + <constraint firstItem="sCg-K7-URy" firstAttribute="leading" secondItem="6Ng-ZR-L6v" secondAttribute="leadingMargin" constant="10" id="B2Y-Ni-QEB"/> + <constraint firstAttribute="trailingMargin" secondItem="Qz1-BL-wQN" secondAttribute="trailing" constant="10" id="kJt-ef-Icu"/> + <constraint firstItem="sCg-K7-URy" firstAttribute="top" secondItem="Qz1-BL-wQN" secondAttribute="bottom" constant="8" id="rMk-Ai-Ciy"/> + <constraint firstItem="Qz1-BL-wQN" firstAttribute="leading" secondItem="6Ng-ZR-L6v" secondAttribute="leadingMargin" constant="10" id="t99-ux-IyQ"/> + <constraint firstAttribute="trailingMargin" secondItem="sCg-K7-URy" secondAttribute="trailing" constant="10" id="xM7-x5-Q9q"/> + <constraint firstItem="Qz1-BL-wQN" firstAttribute="top" secondItem="6Ng-ZR-L6v" secondAttribute="topMargin" constant="10" id="xjb-IK-xql"/> + </constraints> + </tableViewCellContentView> + <connections> + <outlet property="bodyLabel" destination="sCg-K7-URy" id="RNc-md-GU0"/> + <outlet property="titleLabel" destination="Qz1-BL-wQN" id="U3l-JI-Mxx"/> + <segue destination="bb1-hO-yeb" kind="show" id="1SB-WP-aOw"/> + </connections> + </tableViewCell> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="ViewController2" rowHeight="80" id="5bv-q2-Q3k" userLabel="View Controller Cell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> + <rect key="frame" x="0.0" y="290" width="375" height="80"/> + <autoresizingMask key="autoresizingMask"/> + <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="5bv-q2-Q3k" id="6q2-Qj-PQE"> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="80"/> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="752" text="VIEW CONTROLLERS 2" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="N18-CP-QIt"> + <rect key="frame" x="26" y="21" width="304.5" height="16"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> + <nil key="highlightedColor"/> + </label> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Present modal view controllers with SwiftMessages animations." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="T5Q-9f-KQC"> + <rect key="frame" x="26" y="45" width="304.5" height="14"/> + <fontDescription key="fontDescription" type="system" pointSize="16"/> + <color key="textColor" systemColor="secondaryLabelColor"/> + <nil key="highlightedColor"/> + </label> + </subviews> + <constraints> + <constraint firstAttribute="bottomMargin" secondItem="T5Q-9f-KQC" secondAttribute="bottom" constant="10" id="27V-mS-1Sj"/> + <constraint firstItem="T5Q-9f-KQC" firstAttribute="leading" secondItem="6q2-Qj-PQE" secondAttribute="leadingMargin" constant="10" id="BsF-AT-7xc"/> + <constraint firstItem="N18-CP-QIt" firstAttribute="top" secondItem="6q2-Qj-PQE" secondAttribute="topMargin" constant="10" id="D8T-hb-QkI"/> + <constraint firstItem="N18-CP-QIt" firstAttribute="leading" secondItem="6q2-Qj-PQE" secondAttribute="leadingMargin" constant="10" id="LFW-vb-Grc"/> + <constraint firstAttribute="trailingMargin" secondItem="N18-CP-QIt" secondAttribute="trailing" constant="10" id="Xyo-9E-P0G"/> + <constraint firstItem="T5Q-9f-KQC" firstAttribute="top" secondItem="N18-CP-QIt" secondAttribute="bottom" constant="8" id="frb-lP-XRd"/> + <constraint firstAttribute="trailingMargin" secondItem="T5Q-9f-KQC" secondAttribute="trailing" constant="10" id="jp7-if-3V8"/> + </constraints> + </tableViewCellContentView> + <connections> + <outlet property="bodyLabel" destination="T5Q-9f-KQC" id="IwS-Zu-cgl"/> + <outlet property="titleLabel" destination="N18-CP-QIt" id="Vwg-pB-W5F"/> + </connections> + </tableViewCell> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="Counted" rowHeight="80" id="rS6-xs-t4z" userLabel="Counted Cell" customClass="TitleBodyCell" customModule="Demo" customModuleProvider="target"> + <rect key="frame" x="0.0" y="370" width="375" height="80"/> + <autoresizingMask key="autoresizingMask"/> + <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="rS6-xs-t4z" id="oQf-QH-2dc"> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="80"/> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="752" text="COUNTED" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rzv-E5-oaM"> + <rect key="frame" x="26" y="21" width="304.5" height="16"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> + <nil key="highlightedColor"/> + </label> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hide a message based on equal number of show() and hideCounted(id:) calls." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ie4-WM-pe4"> + <rect key="frame" x="26" y="45" width="304.5" height="14"/> + <fontDescription key="fontDescription" type="system" pointSize="16"/> + <color key="textColor" systemColor="secondaryLabelColor"/> + <nil key="highlightedColor"/> + </label> + </subviews> + <constraints> + <constraint firstItem="rzv-E5-oaM" firstAttribute="leading" secondItem="oQf-QH-2dc" secondAttribute="leadingMargin" constant="10" id="SFU-CL-Wty"/> + <constraint firstItem="ie4-WM-pe4" firstAttribute="top" secondItem="rzv-E5-oaM" secondAttribute="bottom" constant="8" id="U2E-fs-p7F"/> + <constraint firstAttribute="bottomMargin" secondItem="ie4-WM-pe4" secondAttribute="bottom" constant="10" id="cLR-EW-Ts2"/> + <constraint firstItem="rzv-E5-oaM" firstAttribute="top" secondItem="oQf-QH-2dc" secondAttribute="topMargin" constant="10" id="l8I-It-z31"/> + <constraint firstAttribute="trailingMargin" secondItem="rzv-E5-oaM" secondAttribute="trailing" constant="10" id="lLy-zd-IQq"/> + <constraint firstItem="ie4-WM-pe4" firstAttribute="leading" secondItem="oQf-QH-2dc" secondAttribute="leadingMargin" constant="10" id="mRn-xu-Vb7"/> + <constraint firstAttribute="trailingMargin" secondItem="ie4-WM-pe4" secondAttribute="trailing" constant="10" id="roT-wO-OEY"/> + </constraints> + </tableViewCellContentView> + <connections> + <outlet property="bodyLabel" destination="ie4-WM-pe4" id="O4J-r5-8Yi"/> + <outlet property="titleLabel" destination="rzv-E5-oaM" id="R5w-fT-HnU"/> + </connections> + </tableViewCell> </prototypes> <connections> <outlet property="dataSource" destination="vur-BZ-g1e" id="rfz-yY-IL6"/> @@ -116,29 +222,32 @@ <scene sceneID="HFO-dV-gYe"> <objects> <tableViewController id="NF9-wZ-lbZ" customClass="ExploreViewController" customModule="Demo" customModuleProvider="target" sceneMemberID="viewController"> - <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="none" allowsSelection="NO" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="XwA-eF-0LG"> - <rect key="frame" x="0.0" y="0.0" width="600" height="1200"/> + <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="none" allowsSelection="NO" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="XwA-eF-0LG"> + <rect key="frame" x="0.0" y="0.0" width="375" height="1200"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.95686274510000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> <sections> <tableViewSection headerTitle="Presentation" id="ifN-uy-lWX"> <cells> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="65" id="nYa-Hy-Lda" userLabel="Presentation style cell"> - <rect key="frame" x="0.0" y="119.33333333333334" width="600" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="nYa-Hy-Lda" userLabel="Presentation style cell"> + <rect key="frame" x="0.0" y="55.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="nYa-Hy-Lda" id="WC1-5B-Pa4"> - <frame key="frameInset" width="600" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="PRESENTATION STYLE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Epw-Yk-L8V"> + <rect key="frame" x="26" y="11" width="146.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="Agu-Vo-ckI"> + <segmentedControl opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="751" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="Agu-Vo-ckI"> + <rect key="frame" x="26" y="32" width="194" height="32"/> <segments> <segment title="Top"/> <segment title="Bottom"/> + <segment title="Center"/> </segments> </segmentedControl> </subviews> @@ -146,25 +255,28 @@ <constraint firstItem="Agu-Vo-ckI" firstAttribute="leading" secondItem="WC1-5B-Pa4" secondAttribute="leadingMargin" constant="10" id="Cpb-Dt-E6Y"/> <constraint firstItem="Epw-Yk-L8V" firstAttribute="leading" secondItem="WC1-5B-Pa4" secondAttribute="leadingMargin" constant="10" id="J7Q-aQ-QaD"/> <constraint firstItem="Epw-Yk-L8V" firstAttribute="top" secondItem="WC1-5B-Pa4" secondAttribute="topMargin" id="Vit-Z4-Pbb"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="Epw-Yk-L8V" secondAttribute="trailingMargin" id="r47-xj-9xE"/> <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="Agu-Vo-ckI" secondAttribute="trailing" constant="10" id="sjj-OR-At0"/> <constraint firstItem="Agu-Vo-ckI" firstAttribute="top" secondItem="Epw-Yk-L8V" secondAttribute="bottom" constant="5" id="w3y-hH-POd"/> - <constraint firstAttribute="bottomMargin" relation="greaterThanOrEqual" secondItem="Agu-Vo-ckI" secondAttribute="bottom" id="zKd-O2-Bv3"/> + <constraint firstAttribute="bottomMargin" secondItem="Agu-Vo-ckI" secondAttribute="bottom" id="zKd-O2-Bv3"/> </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="65" id="eMM-fw-ePY" userLabel="Presentation context cell"> - <rect key="frame" x="0.0" y="184.33333333333334" width="600" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="eMM-fw-ePY" userLabel="Presentation context cell"> + <rect key="frame" x="0.0" y="129.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="eMM-fw-ePY" id="qjs-CO-J4K"> - <frame key="frameInset" width="600" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="PRESENTATION CONTEXT" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="CU0-87-ZCD"> + <rect key="frame" x="26" y="11" width="168.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" apportionsSegmentWidthsByContent="YES" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="AYG-qj-yjv"> + <segmentedControl opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="252" verticalCompressionResistancePriority="751" contentHorizontalAlignment="left" contentVerticalAlignment="top" apportionsSegmentWidthsByContent="YES" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="AYG-qj-yjv"> + <rect key="frame" x="26" y="32" width="302" height="32"/> <segments> <segment title="Automatic"/> <segment title="Normal Level"/> @@ -175,26 +287,28 @@ <constraints> <constraint firstItem="CU0-87-ZCD" firstAttribute="top" secondItem="qjs-CO-J4K" secondAttribute="topMargin" id="5OO-hZ-eoL"/> <constraint firstItem="AYG-qj-yjv" firstAttribute="top" secondItem="CU0-87-ZCD" secondAttribute="bottom" constant="5" id="crO-zT-nKO"/> - <constraint firstAttribute="bottomMargin" relation="greaterThanOrEqual" secondItem="AYG-qj-yjv" secondAttribute="bottom" id="dEm-3s-rij"/> + <constraint firstAttribute="bottomMargin" secondItem="AYG-qj-yjv" secondAttribute="bottom" id="dEm-3s-rij"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="CU0-87-ZCD" secondAttribute="trailingMargin" id="jqI-ll-YAs"/> <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="AYG-qj-yjv" secondAttribute="trailing" constant="10" id="s4v-Cg-Y2K"/> <constraint firstItem="AYG-qj-yjv" firstAttribute="leading" secondItem="qjs-CO-J4K" secondAttribute="leadingMargin" constant="10" id="xKq-V9-Uib"/> <constraint firstItem="CU0-87-ZCD" firstAttribute="leading" secondItem="qjs-CO-J4K" secondAttribute="leadingMargin" constant="10" id="zZI-MM-YUE"/> </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="65" id="fnL-fA-GeP" userLabel="Duration cell"> - <rect key="frame" x="0.0" y="249.33333333333334" width="600" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="fnL-fA-GeP" userLabel="Duration cell"> + <rect key="frame" x="0.0" y="203.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="fnL-fA-GeP" id="xfk-SM-u8I"> - <frame key="frameInset" width="600" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="DURATION" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cad-I9-jeP"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="751" text="DURATION" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cad-I9-jeP"> + <rect key="frame" x="26" y="11" width="69.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" apportionsSegmentWidthsByContent="YES" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="nng-9a-v3B"> + <rect key="frame" x="26" y="32" width="310" height="32"/> <segments> <segment title="Automatic"/> <segment title="Forever"/> @@ -208,61 +322,69 @@ <constraint firstItem="nng-9a-v3B" firstAttribute="leading" secondItem="xfk-SM-u8I" secondAttribute="leadingMargin" constant="10" id="Atx-vb-rTV"/> <constraint firstItem="cad-I9-jeP" firstAttribute="leading" secondItem="xfk-SM-u8I" secondAttribute="leadingMargin" constant="10" id="CSd-i5-VHE"/> <constraint firstItem="cad-I9-jeP" firstAttribute="top" secondItem="xfk-SM-u8I" secondAttribute="topMargin" id="HF3-KH-Gll"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="cad-I9-jeP" secondAttribute="trailingMargin" id="gtm-dc-eyX"/> <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="nng-9a-v3B" secondAttribute="trailing" constant="10" id="gzc-IX-LKG"/> - <constraint firstAttribute="bottomMargin" relation="greaterThanOrEqual" secondItem="nng-9a-v3B" secondAttribute="bottom" id="izP-fi-ACu"/> + <constraint firstAttribute="bottomMargin" secondItem="nng-9a-v3B" secondAttribute="bottom" id="izP-fi-ACu"/> </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="65" id="hkB-YI-YQX" userLabel="Dim mode cell"> - <rect key="frame" x="0.0" y="314.33333333333337" width="600" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="hkB-YI-YQX" userLabel="Dim mode cell"> + <rect key="frame" x="0.0" y="277.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hkB-YI-YQX" id="6ov-9U-ABh"> - <frame key="frameInset" width="600" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="DIM MODE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TsP-n5-Vko"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="DIM MODE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TsP-n5-Vko"> + <rect key="frame" x="26" y="11" width="68.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="iw9-KB-Nyd"> + <rect key="frame" x="26" y="32" width="211" height="32"/> <segments> <segment title="None"/> - <segment title="Normal"/> - <segment title="Interactive"/> + <segment title="Gray"/> + <segment title="Color"/> + <segment title="Blur"/> </segments> </segmentedControl> </subviews> <constraints> <constraint firstItem="TsP-n5-Vko" firstAttribute="leading" secondItem="6ov-9U-ABh" secondAttribute="leadingMargin" constant="10" id="1lT-9J-nnY"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="TsP-n5-Vko" secondAttribute="trailingMargin" id="AQe-WE-6do"/> <constraint firstItem="iw9-KB-Nyd" firstAttribute="top" secondItem="TsP-n5-Vko" secondAttribute="bottom" constant="5" id="BKH-fV-3Jj"/> <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="iw9-KB-Nyd" secondAttribute="trailing" constant="10" id="JIs-wV-rvK"/> <constraint firstItem="iw9-KB-Nyd" firstAttribute="leading" secondItem="6ov-9U-ABh" secondAttribute="leadingMargin" constant="10" id="Mgi-JB-fHu"/> - <constraint firstAttribute="bottomMargin" relation="greaterThanOrEqual" secondItem="iw9-KB-Nyd" secondAttribute="bottom" id="d3m-BM-mBr"/> + <constraint firstAttribute="bottomMargin" secondItem="iw9-KB-Nyd" secondAttribute="bottom" id="d3m-BM-mBr"/> <constraint firstItem="TsP-n5-Vko" firstAttribute="top" secondItem="6ov-9U-ABh" secondAttribute="topMargin" id="tKc-ds-gCa"/> </constraints> </tableViewCellContentView> </tableViewCell> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="zQR-VC-Yl3" userLabel="Interactive hide cell"> - <rect key="frame" x="0.0" y="379.33333333333337" width="600" height="44"/> + <rect key="frame" x="0.0" y="351.5" width="375" height="53"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="zQR-VC-Yl3" id="RZq-YF-8fo"> - <frame key="frameInset" width="600" height="44"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="53"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="INTERACTIVE HIDE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dw8-96-uXk"> + <rect key="frame" x="26" y="18.5" width="123" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Vdr-7b-DJB"/> + <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Vdr-7b-DJB"> + <rect key="frame" x="300" y="11" width="51" height="31"/> + </switch> </subviews> <constraints> <constraint firstItem="dw8-96-uXk" firstAttribute="leading" secondItem="RZq-YF-8fo" secondAttribute="leadingMargin" constant="10" id="5Yb-Fn-nX6"/> <constraint firstAttribute="trailingMargin" secondItem="Vdr-7b-DJB" secondAttribute="trailing" constant="10" id="5oG-04-THv"/> <constraint firstItem="dw8-96-uXk" firstAttribute="centerY" secondItem="RZq-YF-8fo" secondAttribute="centerY" id="6Td-Pc-Kix"/> <constraint firstItem="Vdr-7b-DJB" firstAttribute="centerY" secondItem="dw8-96-uXk" secondAttribute="centerY" id="7bs-jn-bU1"/> - <constraint firstItem="dw8-96-uXk" firstAttribute="top" secondItem="RZq-YF-8fo" secondAttribute="topMargin" id="rRR-g6-pXq"/> + <constraint firstAttribute="bottomMargin" secondItem="Vdr-7b-DJB" secondAttribute="bottom" id="OsS-B4-XfA"/> + <constraint firstItem="Vdr-7b-DJB" firstAttribute="top" secondItem="RZq-YF-8fo" secondAttribute="topMargin" id="vMT-Nx-zM2"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="dw8-96-uXk" secondAttribute="trailingMargin" id="wyo-o0-Hg8"/> </constraints> <variation key="default"> <mask key="constraints"> @@ -271,26 +393,62 @@ </variation> </tableViewCellContentView> </tableViewCell> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="BkJ-zT-C7Z" userLabel="Haptic cell"> + <rect key="frame" x="0.0" y="404.5" width="375" height="53"/> + <autoresizingMask key="autoresizingMask"/> + <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="BkJ-zT-C7Z" id="GXF-qW-HHA"> + <rect key="frame" x="0.0" y="0.0" width="375" height="53"/> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Haptic Feedback" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8Vy-cX-rMN"> + <rect key="frame" x="26" y="18.5" width="109" height="16"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> + <nil key="highlightedColor"/> + </label> + <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ah6-5J-Psp"> + <rect key="frame" x="300" y="11" width="51" height="31"/> + </switch> + </subviews> + <constraints> + <constraint firstItem="8Vy-cX-rMN" firstAttribute="centerY" secondItem="GXF-qW-HHA" secondAttribute="centerY" id="605-kz-s84"/> + <constraint firstItem="ah6-5J-Psp" firstAttribute="centerY" secondItem="8Vy-cX-rMN" secondAttribute="centerY" id="CuY-eF-FkL"/> + <constraint firstAttribute="bottomMargin" secondItem="ah6-5J-Psp" secondAttribute="bottom" id="FWM-LN-Om7"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="8Vy-cX-rMN" secondAttribute="trailingMargin" id="P7C-Bc-POB"/> + <constraint firstAttribute="trailingMargin" secondItem="ah6-5J-Psp" secondAttribute="trailing" constant="10" id="QQa-X8-ldo"/> + <constraint firstItem="ah6-5J-Psp" firstAttribute="top" secondItem="GXF-qW-HHA" secondAttribute="topMargin" id="Y7g-Sy-zJR"/> + <constraint firstItem="8Vy-cX-rMN" firstAttribute="leading" secondItem="GXF-qW-HHA" secondAttribute="leadingMargin" constant="10" id="m3b-RD-jOz"/> + </constraints> + <variation key="default"> + <mask key="constraints"> + <exclude reference="605-kz-s84"/> + </mask> + </variation> + </tableViewCellContentView> + </tableViewCell> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="jsU-7Q-nnr" userLabel="Auto rotate cell"> - <rect key="frame" x="0.0" y="423.33333333333337" width="600" height="44"/> + <rect key="frame" x="0.0" y="457.5" width="375" height="53"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="jsU-7Q-nnr" id="Lyn-8c-LBy"> - <frame key="frameInset" width="600" height="44"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="53"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="AUTO ROTATE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VW7-M1-Q0o"> + <rect key="frame" x="26" y="18.5" width="92" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="WfA-vA-cpG"/> + <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="WfA-vA-cpG"> + <rect key="frame" x="300" y="11" width="51" height="31"/> + </switch> </subviews> <constraints> <constraint firstAttribute="trailingMargin" secondItem="WfA-vA-cpG" secondAttribute="trailing" constant="10" id="HBd-ud-36Q"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="VW7-M1-Q0o" secondAttribute="trailingMargin" id="O68-K8-nrx"/> + <constraint firstItem="WfA-vA-cpG" firstAttribute="top" secondItem="Lyn-8c-LBy" secondAttribute="topMargin" id="Wjg-VI-0g6"/> <constraint firstItem="VW7-M1-Q0o" firstAttribute="centerY" secondItem="Lyn-8c-LBy" secondAttribute="centerY" id="Yjw-4P-Xec"/> + <constraint firstAttribute="bottomMargin" secondItem="WfA-vA-cpG" secondAttribute="bottom" id="afn-K6-bfX"/> <constraint firstItem="WfA-vA-cpG" firstAttribute="centerY" secondItem="VW7-M1-Q0o" secondAttribute="centerY" id="uuV-KC-8Ti"/> <constraint firstItem="VW7-M1-Q0o" firstAttribute="leading" secondItem="Lyn-8c-LBy" secondAttribute="leadingMargin" constant="10" id="vmK-Hu-mBb"/> - <constraint firstItem="VW7-M1-Q0o" firstAttribute="top" secondItem="Lyn-8c-LBy" secondAttribute="topMargin" id="wyC-LT-Lft"/> </constraints> <variation key="default"> <mask key="constraints"> @@ -303,19 +461,20 @@ </tableViewSection> <tableViewSection headerTitle="Styling" id="Ibz-q6-0d2"> <cells> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="65" id="u46-FS-ahC" userLabel="Theme cell"> - <rect key="frame" x="0.0" y="523.33333333333337" width="600" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="u46-FS-ahC" userLabel="Theme cell"> + <rect key="frame" x="0.0" y="566.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="u46-FS-ahC" id="A01-Bb-OrK"> - <frame key="frameInset" width="600" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="LAYOUT" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iQk-lG-ZCm"> + <rect key="frame" x="26" y="11" width="53.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="aBT-5M-2tg"> + <segmentedControl opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="751" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="aBT-5M-2tg"> + <rect key="frame" x="26" y="32" width="323" height="32"/> <segments> <segment title="Default"/> <segment title="Card"/> @@ -326,27 +485,29 @@ </subviews> <constraints> <constraint firstItem="aBT-5M-2tg" firstAttribute="leading" secondItem="A01-Bb-OrK" secondAttribute="leadingMargin" constant="10" id="8Ot-I8-Po3"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="iQk-lG-ZCm" secondAttribute="trailingMargin" id="8uY-8p-iRR"/> <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="aBT-5M-2tg" secondAttribute="trailing" constant="10" id="9Kt-2l-w5O"/> <constraint firstItem="aBT-5M-2tg" firstAttribute="top" secondItem="iQk-lG-ZCm" secondAttribute="bottom" constant="5" id="K8i-JI-tIa"/> <constraint firstItem="iQk-lG-ZCm" firstAttribute="leading" secondItem="A01-Bb-OrK" secondAttribute="leadingMargin" constant="10" id="TZG-YE-R2B"/> <constraint firstItem="iQk-lG-ZCm" firstAttribute="top" secondItem="A01-Bb-OrK" secondAttribute="topMargin" id="XhZ-Em-VDW"/> - <constraint firstAttribute="bottomMargin" relation="greaterThanOrEqual" secondItem="aBT-5M-2tg" secondAttribute="bottom" id="bWO-4u-AAG"/> + <constraint firstAttribute="bottomMargin" secondItem="aBT-5M-2tg" secondAttribute="bottom" id="bWO-4u-AAG"/> </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="65" id="v73-pR-Iy2" userLabel="Theme cell"> - <rect key="frame" x="0.0" y="588.33333333333337" width="600" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="v73-pR-Iy2" userLabel="Theme cell"> + <rect key="frame" x="0.0" y="640.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="v73-pR-Iy2" id="Fdp-gh-OCb"> - <frame key="frameInset" width="600" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="THEME" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J7S-wJ-kt0"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="751" text="THEME" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J7S-wJ-kt0"> + <rect key="frame" x="26" y="11" width="46.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="NoM-It-vKT"> + <rect key="frame" x="26" y="32" width="323" height="32"/> <segments> <segment title="Info"/> <segment title="Success"/> @@ -359,26 +520,28 @@ <constraints> <constraint firstItem="NoM-It-vKT" firstAttribute="leading" secondItem="Fdp-gh-OCb" secondAttribute="leadingMargin" constant="10" id="3Dm-o8-hOx"/> <constraint firstItem="NoM-It-vKT" firstAttribute="top" secondItem="J7S-wJ-kt0" secondAttribute="bottom" constant="5" id="EGd-0G-8l9"/> - <constraint firstAttribute="bottomMargin" relation="greaterThanOrEqual" secondItem="NoM-It-vKT" secondAttribute="bottom" id="O5S-3g-TaO"/> + <constraint firstAttribute="bottomMargin" secondItem="NoM-It-vKT" secondAttribute="bottom" id="O5S-3g-TaO"/> <constraint firstItem="J7S-wJ-kt0" firstAttribute="leading" secondItem="Fdp-gh-OCb" secondAttribute="leadingMargin" constant="10" id="gAM-iD-DoY"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="J7S-wJ-kt0" secondAttribute="trailingMargin" id="lgp-C7-ccc"/> <constraint firstItem="J7S-wJ-kt0" firstAttribute="top" secondItem="Fdp-gh-OCb" secondAttribute="topMargin" id="mVy-xe-CQk"/> <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="NoM-It-vKT" secondAttribute="trailing" constant="10" id="tQU-NQ-phM"/> </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="65" id="0mE-sA-4rN" userLabel="Theme cell"> - <rect key="frame" x="0.0" y="653.33333333333337" width="600" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="0mE-sA-4rN" userLabel="Theme cell"> + <rect key="frame" x="0.0" y="714.5" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="0mE-sA-4rN" id="eVs-bm-01A"> - <frame key="frameInset" width="600" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="74"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="ICON STYLE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sXY-rl-8uH"> + <rect key="frame" x="26" y="11" width="79" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="c2K-94-CuB"> + <segmentedControl opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="252" verticalCompressionResistancePriority="751" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="c2K-94-CuB"> + <rect key="frame" x="26" y="32" width="200" height="32"/> <segments> <segment title="Regular"/> <segment title="Light"/> @@ -388,86 +551,88 @@ </subviews> <constraints> <constraint firstItem="c2K-94-CuB" firstAttribute="leading" secondItem="eVs-bm-01A" secondAttribute="leadingMargin" constant="10" id="57X-r6-yn8"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="sXY-rl-8uH" secondAttribute="trailingMargin" id="6Hz-mY-AJF"/> <constraint firstItem="sXY-rl-8uH" firstAttribute="top" secondItem="eVs-bm-01A" secondAttribute="topMargin" id="aNb-k2-SZY"/> <constraint firstItem="c2K-94-CuB" firstAttribute="top" secondItem="sXY-rl-8uH" secondAttribute="bottom" constant="5" id="euE-AS-gZT"/> - <constraint firstAttribute="bottomMargin" relation="greaterThanOrEqual" secondItem="c2K-94-CuB" secondAttribute="bottom" id="ifY-M2-nQa"/> + <constraint firstAttribute="bottomMargin" secondItem="c2K-94-CuB" secondAttribute="bottom" id="ifY-M2-nQa"/> <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="c2K-94-CuB" secondAttribute="trailing" constant="10" id="jMs-A0-qxE"/> <constraint firstItem="sXY-rl-8uH" firstAttribute="leading" secondItem="eVs-bm-01A" secondAttribute="leadingMargin" constant="10" id="rCc-O8-QkU"/> </constraints> </tableViewCellContentView> </tableViewCell> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="4RW-U9-BVB" userLabel="Drop shadow cell"> - <rect key="frame" x="0.0" y="718.33333333333337" width="600" height="44"/> + <rect key="frame" x="0.0" y="788.5" width="375" height="53"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="4RW-U9-BVB" id="wdb-hX-CIv"> - <frame key="frameInset" width="600" height="44"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="53"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="DROP SHADOW" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MUL-on-v9R"> + <rect key="frame" x="26" y="18.5" width="101.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="sqb-Fg-YR8"/> + <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="sqb-Fg-YR8"> + <rect key="frame" x="300" y="11" width="51" height="31"/> + </switch> </subviews> <constraints> - <constraint firstItem="MUL-on-v9R" firstAttribute="centerY" secondItem="wdb-hX-CIv" secondAttribute="centerY" id="Hbk-Nh-6hl"/> + <constraint firstAttribute="bottomMargin" secondItem="sqb-Fg-YR8" secondAttribute="bottom" id="8Os-Ki-ivF"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="MUL-on-v9R" secondAttribute="trailingMargin" id="LZS-OO-jq3"/> <constraint firstItem="sqb-Fg-YR8" firstAttribute="centerY" secondItem="MUL-on-v9R" secondAttribute="centerY" id="UHE-lU-Byf"/> - <constraint firstItem="MUL-on-v9R" firstAttribute="top" secondItem="wdb-hX-CIv" secondAttribute="topMargin" id="XSb-es-GvV"/> <constraint firstAttribute="trailingMargin" secondItem="sqb-Fg-YR8" secondAttribute="trailing" constant="10" id="lo9-zU-2YQ"/> <constraint firstItem="MUL-on-v9R" firstAttribute="leading" secondItem="wdb-hX-CIv" secondAttribute="leadingMargin" constant="10" id="uKv-3s-QCh"/> + <constraint firstItem="sqb-Fg-YR8" firstAttribute="top" secondItem="wdb-hX-CIv" secondAttribute="topMargin" id="wQm-n2-N5D"/> </constraints> - <variation key="default"> - <mask key="constraints"> - <exclude reference="Hbk-Nh-6hl"/> - </mask> - </variation> </tableViewCellContentView> </tableViewCell> </cells> </tableViewSection> <tableViewSection headerTitle="CONTENT" id="Mih-L6-PeE"> <cells> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="65" id="ddI-Jn-NgP" userLabel="Title cell"> - <rect key="frame" x="0.0" y="818.33333333333337" width="600" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="ddI-Jn-NgP" userLabel="Title cell"> + <rect key="frame" x="0.0" y="897.5" width="375" height="75"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ddI-Jn-NgP" id="4HG-zA-HtF"> - <frame key="frameInset" width="600" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="75"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="TITLE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zs0-Qc-Tls"> + <rect key="frame" x="26" y="11" width="37" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="Heads Up!" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="Z0U-kn-8rs"> + <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" verticalCompressionResistancePriority="751" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="Heads Up!" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="Z0U-kn-8rs"> + <rect key="frame" x="26" y="30" width="323" height="34"/> <fontDescription key="fontDescription" type="system" pointSize="14"/> <textInputTraits key="textInputTraits" returnKeyType="done" enablesReturnKeyAutomatically="YES"/> </textField> </subviews> <constraints> <constraint firstItem="Z0U-kn-8rs" firstAttribute="top" secondItem="zs0-Qc-Tls" secondAttribute="bottom" constant="3" id="Rzd-5J-cB5"/> - <constraint firstItem="Z0U-kn-8rs" firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="4HG-zA-HtF" secondAttribute="bottomMargin" id="TcB-TW-PDr"/> + <constraint firstItem="Z0U-kn-8rs" firstAttribute="bottom" secondItem="4HG-zA-HtF" secondAttribute="bottomMargin" id="TcB-TW-PDr"/> <constraint firstItem="Z0U-kn-8rs" firstAttribute="leading" secondItem="4HG-zA-HtF" secondAttribute="leadingMargin" constant="10" id="Vdi-x1-PIO"/> <constraint firstAttribute="trailingMargin" secondItem="Z0U-kn-8rs" secondAttribute="trailing" constant="10" id="hIY-BQ-302"/> <constraint firstItem="zs0-Qc-Tls" firstAttribute="top" secondItem="4HG-zA-HtF" secondAttribute="topMargin" id="hjh-hv-09Y"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="zs0-Qc-Tls" secondAttribute="trailingMargin" id="iLg-aD-BQB"/> <constraint firstItem="zs0-Qc-Tls" firstAttribute="leading" secondItem="4HG-zA-HtF" secondAttribute="leadingMargin" constant="10" id="pcw-qp-Boc"/> </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="65" id="bdE-R5-mtF" userLabel="Subtitle cell"> - <rect key="frame" x="0.0" y="883.33333333333337" width="600" height="65"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="bdE-R5-mtF" userLabel="Subtitle cell"> + <rect key="frame" x="0.0" y="972.5" width="375" height="75"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="bdE-R5-mtF" id="E8h-YG-8UX"> - <frame key="frameInset" width="600" height="65"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="75"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="BODY" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="KYf-CB-aEU"> + <rect key="frame" x="26" y="11" width="37.5" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="This message is very important." borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="Ev4-j7-wY0"> + <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" verticalCompressionResistancePriority="751" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="This message is very important." borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="Ev4-j7-wY0"> + <rect key="frame" x="26" y="30" width="323" height="34"/> <fontDescription key="fontDescription" type="system" pointSize="14"/> <textInputTraits key="textInputTraits"/> </textField> @@ -477,43 +642,54 @@ <constraint firstAttribute="trailingMargin" secondItem="Ev4-j7-wY0" secondAttribute="trailing" constant="10" id="4Hf-KW-CsK"/> <constraint firstItem="Ev4-j7-wY0" firstAttribute="top" secondItem="KYf-CB-aEU" secondAttribute="bottom" constant="3" id="dZZ-Cf-rj2"/> <constraint firstItem="KYf-CB-aEU" firstAttribute="top" secondItem="E8h-YG-8UX" secondAttribute="topMargin" id="e5G-Ed-IdX"/> - <constraint firstItem="Ev4-j7-wY0" firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="E8h-YG-8UX" secondAttribute="bottomMargin" id="fb9-ZY-81L"/> + <constraint firstItem="Ev4-j7-wY0" firstAttribute="bottom" secondItem="E8h-YG-8UX" secondAttribute="bottomMargin" id="fb9-ZY-81L"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="KYf-CB-aEU" secondAttribute="trailingMargin" id="qOV-9d-yOF"/> <constraint firstItem="KYf-CB-aEU" firstAttribute="leading" secondItem="E8h-YG-8UX" secondAttribute="leadingMargin" constant="10" id="uL0-uX-tC7"/> </constraints> </tableViewCellContentView> </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="110" id="i0m-Xn-tMe" userLabel="Hiding cell"> - <rect key="frame" x="0.0" y="948.33333333333337" width="600" height="110"/> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="i0m-Xn-tMe" userLabel="Hiding cell"> + <rect key="frame" x="0.0" y="1047.5" width="375" height="113"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="i0m-Xn-tMe" id="y4L-XO-6WY"> - <frame key="frameInset" width="600" height="110"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="113"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SHOW" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="07f-nU-dvy"> + <rect key="frame" x="26" y="11" width="42" height="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="UMq-Yn-VYn"> + <rect key="frame" x="26" y="35" width="323" height="67"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="40" translatesAutoresizingMaskIntoConstraints="NO" id="zwT-Yv-eyU"> + <rect key="frame" x="0.0" y="0.0" width="323" height="31"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="sWT-Ug-j6y"> + <rect key="frame" x="0.0" y="0.0" width="141.5" height="31"/> <subviews> - <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="w9C-j2-COD"/> + <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="w9C-j2-COD"> + <rect key="frame" x="0.0" y="0.0" width="51" height="31"/> + </switch> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Button" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dRM-c4-ORW"> + <rect key="frame" x="69" y="6" width="72.5" height="19.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" red="0.47391887630000001" green="0.47391887630000001" blue="0.47391887630000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> </stackView> <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="WVf-N1-ipR"> + <rect key="frame" x="181.5" y="0.0" width="141.5" height="31"/> <subviews> - <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CDM-PI-gjl"/> + <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CDM-PI-gjl"> + <rect key="frame" x="0.0" y="0.0" width="51" height="31"/> + </switch> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PfQ-eZ-O0L"> + <rect key="frame" x="69" y="6" width="72.5" height="19.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" red="0.47391887630000001" green="0.47391887630000001" blue="0.47391887630000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -521,23 +697,32 @@ </subviews> </stackView> <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="40" translatesAutoresizingMaskIntoConstraints="NO" id="FqU-2E-xeu"> + <rect key="frame" x="0.0" y="36" width="323" height="31"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="VJa-y8-lxV"> + <rect key="frame" x="0.0" y="0.0" width="141.5" height="31"/> <subviews> - <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mfB-t8-O1h"/> + <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mfB-t8-O1h"> + <rect key="frame" x="0.0" y="0.0" width="51" height="31"/> + </switch> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Icon" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XKN-W4-1jq"> + <rect key="frame" x="69" y="6" width="72.5" height="19.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" red="0.47391887630000001" green="0.47391887630000001" blue="0.47391887630000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> </stackView> <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="9hh-9r-JQN"> + <rect key="frame" x="181.5" y="0.0" width="141.5" height="31"/> <subviews> - <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zUi-zd-sZL"/> + <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zUi-zd-sZL"> + <rect key="frame" x="0.0" y="0.0" width="51" height="31"/> + </switch> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Body" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DGg-y8-Ln9"> + <rect key="frame" x="69" y="6" width="72.5" height="19.5"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" red="0.47391887630000001" green="0.47391887630000001" blue="0.47391887630000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <color key="textColor" systemColor="secondaryLabelColor"/> <nil key="highlightedColor"/> </label> </subviews> @@ -550,6 +735,7 @@ <constraints> <constraint firstItem="07f-nU-dvy" firstAttribute="top" secondItem="y4L-XO-6WY" secondAttribute="topMargin" id="9iU-v1-KQS"/> <constraint firstAttribute="trailingMargin" secondItem="UMq-Yn-VYn" secondAttribute="trailing" constant="10" id="FHb-yR-nEi"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="07f-nU-dvy" secondAttribute="trailingMargin" id="R40-d2-woT"/> <constraint firstItem="UMq-Yn-VYn" firstAttribute="leading" secondItem="y4L-XO-6WY" secondAttribute="leadingMargin" constant="10" id="dwS-rh-Hz0"/> <constraint firstItem="07f-nU-dvy" firstAttribute="leading" secondItem="y4L-XO-6WY" secondAttribute="leadingMargin" constant="10" id="gSR-TQ-PsI"/> <constraint firstAttribute="bottomMargin" secondItem="UMq-Yn-VYn" secondAttribute="bottom" id="m0V-Dc-OY5"/> @@ -568,12 +754,17 @@ <navigationItem key="navigationItem" title="Explore" id="rMg-O3-NIm"> <barButtonItem key="rightBarButtonItem" id="dQj-XX-UVC"> <view key="customView" contentMode="scaleToFill" id="put-HD-gTP"> - <rect key="frame" x="455" y="5" width="125" height="33"/> + <rect key="frame" x="234" y="0.0" width="125" height="44"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <subviews> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="PpV-jZ-Yo3"> - <color key="backgroundColor" red="0.26666666666666666" green="0.85490196078431369" blue="0.36862745098039218" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <rect key="frame" x="0.0" y="5" width="62" height="34"/> + <color key="backgroundColor" red="0.1647058824" green="0.6588235294" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <constraints> + <constraint firstAttribute="height" priority="900" constant="33" id="4dH-D2-IES"/> + </constraints> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> + <inset key="contentEdgeInsets" minX="10" minY="0.0" maxX="10" maxY="0.0"/> <state key="normal" title="SHOW"/> <userDefinedRuntimeAttributes> <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> @@ -584,9 +775,14 @@ <action selector="show:" destination="NF9-wZ-lbZ" eventType="touchUpInside" id="M1F-VO-IXP"/> </connections> </button> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vaB-mE-Rve"> - <color key="backgroundColor" red="0.97647058823529409" green="0.25882352941176467" blue="0.18431372549019609" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vaB-mE-Rve"> + <rect key="frame" x="67" y="5" width="58" height="34"/> + <color key="backgroundColor" red="1" green="0.4665354619" blue="0.015686274510000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <constraints> + <constraint firstAttribute="height" priority="900" constant="33" id="rTo-Jm-6qi"/> + </constraints> <fontDescription key="fontDescription" type="boldSystem" pointSize="13"/> + <inset key="contentEdgeInsets" minX="10" minY="0.0" maxX="10" maxY="0.0"/> <state key="normal" title="HIDE"/> <userDefinedRuntimeAttributes> <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> @@ -601,25 +797,24 @@ <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstItem="PpV-jZ-Yo3" firstAttribute="leading" secondItem="put-HD-gTP" secondAttribute="leading" id="NXb-Tj-zUQ"/> - <constraint firstItem="PpV-jZ-Yo3" firstAttribute="top" secondItem="put-HD-gTP" secondAttribute="top" id="aAq-G5-l4S"/> - <constraint firstAttribute="bottom" secondItem="PpV-jZ-Yo3" secondAttribute="bottom" id="aJ1-g1-cqw"/> - <constraint firstAttribute="bottom" secondItem="vaB-mE-Rve" secondAttribute="bottom" id="ej5-L3-QgG"/> + <constraint firstItem="PpV-jZ-Yo3" firstAttribute="top" secondItem="put-HD-gTP" secondAttribute="top" constant="5" id="aAq-G5-l4S"/> + <constraint firstAttribute="bottom" secondItem="PpV-jZ-Yo3" secondAttribute="bottom" constant="5" id="aJ1-g1-cqw"/> + <constraint firstAttribute="bottom" secondItem="vaB-mE-Rve" secondAttribute="bottom" constant="5" id="ej5-L3-QgG"/> <constraint firstAttribute="trailing" secondItem="vaB-mE-Rve" secondAttribute="trailing" id="er4-Vc-rhg"/> - <constraint firstItem="vaB-mE-Rve" firstAttribute="top" secondItem="put-HD-gTP" secondAttribute="top" id="fqH-mE-cIE"/> - <constraint firstItem="PpV-jZ-Yo3" firstAttribute="width" secondItem="vaB-mE-Rve" secondAttribute="width" id="gr5-7B-7fX"/> + <constraint firstItem="vaB-mE-Rve" firstAttribute="top" secondItem="put-HD-gTP" secondAttribute="top" constant="5" id="fqH-mE-cIE"/> <constraint firstItem="vaB-mE-Rve" firstAttribute="leading" secondItem="PpV-jZ-Yo3" secondAttribute="trailing" constant="5" id="ngv-jV-JSb"/> </constraints> </view> </barButtonItem> </navigationItem> - <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> - <size key="freeformSize" width="600" height="1200"/> + <size key="freeformSize" width="375" height="1200"/> <connections> <outlet property="autoRotate" destination="WfA-vA-cpG" id="88o-Le-R5E"/> <outlet property="bodyText" destination="Ev4-j7-wY0" id="mD6-Ge-qJY"/> <outlet property="dimMode" destination="iw9-KB-Nyd" id="OiP-ss-kEO"/> <outlet property="dropShadow" destination="sqb-Fg-YR8" id="zUz-6P-IFz"/> <outlet property="duration" destination="nng-9a-v3B" id="4VC-Yi-AiA"/> + <outlet property="hapticFeedback" destination="ah6-5J-Psp" id="HSQ-XB-1nn"/> <outlet property="iconStyle" destination="c2K-94-CuB" id="Qwt-xY-oZ2"/> <outlet property="interactiveHide" destination="Vdr-7b-DJB" id="pEi-RT-l7U"/> <outlet property="layout" destination="aBT-5M-2tg" id="4GZ-iP-oCa"/> @@ -635,15 +830,284 @@ </tableViewController> <placeholder placeholderIdentifier="IBFirstResponder" id="skR-IF-bf8" userLabel="First Responder" sceneMemberID="firstResponder"/> </objects> - <point key="canvasLocation" x="2342" y="304"/> + <point key="canvasLocation" x="2280.8000000000002" y="-288.75562218890559"/> </scene> - <!--Demo--> + <!--View Controllers--> + <scene sceneID="heM-VN-xQk"> + <objects> + <viewController title="View Controllers" id="bb1-hO-yeb" customClass="ViewControllersViewController" customModule="Demo" customModuleProvider="target" sceneMemberID="viewController"> + <layoutGuides> + <viewControllerLayoutGuide type="top" id="WeL-Zn-0tj"/> + <viewControllerLayoutGuide type="bottom" id="LAn-az-eMU"/> + </layoutGuides> + <view key="view" contentMode="scaleToFill" id="YlT-hO-kIK"> + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="mGe-El-haJ"> + <rect key="frame" x="46" y="104" width="283" height="474"/> + <subviews> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DrN-Ei-Pg7"> + <rect key="frame" x="0.0" y="0.0" width="283" height="59"/> + <color key="backgroundColor" red="0.16470588235294117" green="0.6588235294117647" blue="0.98039215686274506" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Top Message"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopSegue" customModule="Demo" customModuleProvider="target" id="7xS-Ca-mnb"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GeC-SP-rSC"> + <rect key="frame" x="0.0" y="69" width="283" height="59.5"/> + <color key="backgroundColor" red="0.1647058824" green="0.6588235294" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Bottom Message"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomSegue" customModule="Demo" customModuleProvider="target" id="6Yg-dE-eXA"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DGn-eY-EEX"> + <rect key="frame" x="0.0" y="138.5" width="283" height="59"/> + <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Top Card"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopCardSegue" customModule="Demo" customModuleProvider="target" id="qLf-js-3Ls"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZQs-MK-vK3"> + <rect key="frame" x="0.0" y="207.5" width="283" height="59"/> + <color key="backgroundColor" red="0.26627604170000002" green="0.76907009550000005" blue="0.32259114579999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Bottom Card"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomCardSegue" customModule="Demo" customModuleProvider="target" id="TBl-s0-9vL"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kux-aE-Bdv" userLabel="Top Tab"> + <rect key="frame" x="0.0" y="276.5" width="283" height="59"/> + <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000067" blue="0.62082127703967116" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Top Tab"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesTopTabSegue" customModule="Demo" customModuleProvider="target" id="p7Y-6q-gfK"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dMQ-xF-RwV" userLabel="Bottom Tab"> + <rect key="frame" x="0.0" y="345.5" width="283" height="59.5"/> + <color key="backgroundColor" red="0.80000000000000004" green="0.015686274510000001" blue="0.620821277" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Bottom Tab"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesBottomTabSegue" customModule="Demo" customModuleProvider="target" id="EaG-Ea-U3j"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CDi-Gu-bE2" userLabel="Centered"> + <rect key="frame" x="0.0" y="415" width="283" height="59"/> + <color key="backgroundColor" red="1" green="0.46653546191345963" blue="0.015686274510000042" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> + <state key="normal" title="Centered"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> + <integer key="value" value="10"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <segue destination="dHK-y5-h16" kind="custom" customClass="SwiftMessagesCenteredSegue" customModule="Demo" customModuleProvider="target" id="had-cE-9YN"/> + </connections> + </button> + </subviews> + </stackView> + </subviews> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <constraints> + <constraint firstItem="mGe-El-haJ" firstAttribute="top" secondItem="WeL-Zn-0tj" secondAttribute="bottom" constant="40" id="6TI-R1-eMQ"/> + <constraint firstItem="mGe-El-haJ" firstAttribute="leading" secondItem="YlT-hO-kIK" secondAttribute="leadingMargin" constant="30" id="LqT-Kn-3v7"/> + <constraint firstItem="LAn-az-eMU" firstAttribute="top" secondItem="mGe-El-haJ" secondAttribute="bottom" constant="40" id="jWn-cy-X7E"/> + <constraint firstAttribute="trailingMargin" secondItem="mGe-El-haJ" secondAttribute="trailing" constant="30" id="xEo-4G-PBe"/> + </constraints> + </view> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="l01-vw-7yr" userLabel="First Responder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="2281" y="689"/> + </scene> + <!--Item--> + <scene sceneID="Ekq-Hc-xvY"> + <objects> + <navigationController id="dHK-y5-h16" sceneMemberID="viewController"> + <tabBarItem key="tabBarItem" title="Item" id="lRD-YW-2WT"/> + <value key="contentSizeForViewInPopover" type="size" width="0.0" height="250"/> + <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="eD6-og-rzJ"> + <rect key="frame" x="0.0" y="20" width="375" height="44"/> + <autoresizingMask key="autoresizingMask"/> + </navigationBar> + <connections> + <segue destination="CCQ-og-YsG" kind="relationship" relationship="rootViewController" id="Zcn-UD-uH6"/> + </connections> + </navigationController> + <placeholder placeholderIdentifier="IBFirstResponder" id="Ynl-rR-xVc" userLabel="First Responder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="3164" y="689"/> + </scene> + <!--Parent--> + <scene sceneID="k3I-tw-Opi"> + <objects> + <tableViewController id="CCQ-og-YsG" sceneMemberID="viewController"> + <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="veg-5v-Pex"> + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <sections> + <tableViewSection id="CqX-XV-4eD"> + <cells> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="09c-ne-yN9" style="IBUITableViewCellStyleDefault" id="Udi-FH-lzN"> + <rect key="frame" x="0.0" y="50" width="375" height="43.5"/> + <autoresizingMask key="autoresizingMask"/> + <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Udi-FH-lzN" id="hKw-az-hVR"> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="43.5"/> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Item 1" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="09c-ne-yN9"> + <rect key="frame" x="16" y="0.0" width="324.5" height="43.5"/> + <autoresizingMask key="autoresizingMask"/> + <fontDescription key="fontDescription" type="system" pointSize="17"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + </subviews> + </tableViewCellContentView> + <connections> + <segue destination="vdp-aa-LDH" kind="show" id="1PO-Ol-L8M"/> + </connections> + </tableViewCell> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="idk-C0-F7z" style="IBUITableViewCellStyleDefault" id="hLA-of-n8g"> + <rect key="frame" x="0.0" y="93.5" width="375" height="43.5"/> + <autoresizingMask key="autoresizingMask"/> + <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="hLA-of-n8g" id="70t-ga-6jT"> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="43.5"/> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Item 2" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="idk-C0-F7z"> + <rect key="frame" x="16" y="0.0" width="324.5" height="43.5"/> + <autoresizingMask key="autoresizingMask"/> + <fontDescription key="fontDescription" type="system" pointSize="17"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + </subviews> + </tableViewCellContentView> + <connections> + <segue destination="vdp-aa-LDH" kind="show" id="DSE-UC-Xqf"/> + </connections> + </tableViewCell> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="fhG-aN-pzJ" style="IBUITableViewCellStyleDefault" id="jc4-aX-Ow9"> + <rect key="frame" x="0.0" y="137" width="375" height="43.5"/> + <autoresizingMask key="autoresizingMask"/> + <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="jc4-aX-Ow9" id="Jrq-7c-eSM"> + <rect key="frame" x="0.0" y="0.0" width="348.5" height="43.5"/> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Item 3" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="fhG-aN-pzJ"> + <rect key="frame" x="16" y="0.0" width="324.5" height="43.5"/> + <autoresizingMask key="autoresizingMask"/> + <fontDescription key="fontDescription" type="system" pointSize="17"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + </subviews> + </tableViewCellContentView> + <connections> + <segue destination="vdp-aa-LDH" kind="show" id="h5n-Vv-Q3y"/> + </connections> + </tableViewCell> + </cells> + </tableViewSection> + </sections> + <connections> + <outlet property="dataSource" destination="CCQ-og-YsG" id="tjb-6Z-zXO"/> + <outlet property="delegate" destination="CCQ-og-YsG" id="yKW-gj-hGn"/> + </connections> + </tableView> + <navigationItem key="navigationItem" title="Parent" id="jt3-Ix-FaW"> + <barButtonItem key="rightBarButtonItem" title="Done" id="e8e-4N-bax"> + <connections> + <segue destination="Eb3-jR-AqT" kind="unwind" unwindAction="dismissPresentedWithSegue:" id="jd5-2B-4LG"/> + </connections> + </barButtonItem> + </navigationItem> + </tableViewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="sT7-d0-juG" userLabel="First Responder" sceneMemberID="firstResponder"/> + <exit id="Eb3-jR-AqT" userLabel="Exit" sceneMemberID="exit"/> + </objects> + <point key="canvasLocation" x="4060" y="689"/> + </scene> + <!--Child--> + <scene sceneID="HTk-O0-UX2"> + <objects> + <viewController title="Child" id="vdp-aa-LDH" sceneMemberID="viewController"> + <layoutGuides> + <viewControllerLayoutGuide type="top" id="vbE-7C-4e7"/> + <viewControllerLayoutGuide type="bottom" id="SPH-4M-bE7"/> + </layoutGuides> + <view key="view" contentMode="scaleToFill" id="0Cn-7n-ODp"> + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Nothing to see here." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2bv-DK-h4b"> + <rect key="frame" x="110.5" y="355" width="154.5" height="21"/> + <fontDescription key="fontDescription" type="system" pointSize="17"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + </subviews> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <constraints> + <constraint firstItem="2bv-DK-h4b" firstAttribute="centerX" secondItem="0Cn-7n-ODp" secondAttribute="centerX" id="1aC-Jw-Zyl"/> + <constraint firstItem="2bv-DK-h4b" firstAttribute="centerY" secondItem="0Cn-7n-ODp" secondAttribute="centerYWithinMargins" id="93w-dz-NPV"/> + </constraints> + </view> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="mU1-MA-hwk" userLabel="First Responder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="4935" y="689"/> + </scene> + <!--Navigation Controller--> <scene sceneID="TNg-VF-1BI"> <objects> <navigationController id="UrZ-Dq-bGZ" sceneMemberID="viewController"> - <tabBarItem key="tabBarItem" title="Demo" image="iconSwiftMessages" id="Ttu-oX-nwD"/> + <tabBarItem key="tabBarItem" title="" image="iconSwiftMessages" id="Ttu-oX-nwD"/> <navigationBar key="navigationBar" contentMode="scaleToFill" id="vE6-lq-HY6"> - <rect key="frame" x="0.0" y="0.0" width="320" height="44"/> + <rect key="frame" x="0.0" y="20" width="375" height="44"/> <autoresizingMask key="autoresizingMask"/> </navigationBar> <connections> @@ -655,7 +1119,17 @@ <point key="canvasLocation" x="473" y="305"/> </scene> </scenes> + <inferredMetricsTieBreakers> + <segue reference="h5n-Vv-Q3y"/> + <segue reference="EaG-Ea-U3j"/> + </inferredMetricsTieBreakers> <resources> - <image name="iconSwiftMessages" width="35" height="18"/> + <image name="iconSwiftMessages" width="38" height="31"/> + <systemColor name="secondaryLabelColor"> + <color red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> + </systemColor> + <systemColor name="systemBackgroundColor"> + <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + </systemColor> </resources> </document> diff --git a/Demo/Demo/CountedMessageView.swift b/Demo/Demo/CountedMessageView.swift new file mode 100644 index 00000000..e0921bde --- /dev/null +++ b/Demo/Demo/CountedMessageView.swift @@ -0,0 +1,19 @@ +// +// CountedMessageView.swift +// Demo +// +// Created by Timothy Moose on 8/25/17. +// Copyright © 2017 SwiftKick Mobile. All rights reserved. +// + +import UIKit +import SwiftMessages + +class CountedMessageView: UIView, Identifiable { + + @IBOutlet weak var countLabel: UILabel! + + var id: String { + return "counted" + } +} diff --git a/Demo/Demo/CountedViewController.swift b/Demo/Demo/CountedViewController.swift new file mode 100644 index 00000000..6bcc9bf0 --- /dev/null +++ b/Demo/Demo/CountedViewController.swift @@ -0,0 +1,45 @@ +// +// CountedViewController.swift +// Demo +// +// Created by Timothy Moose on 8/25/17. +// Copyright © 2017 SwiftKick Mobile. All rights reserved. +// + +import UIKit +import SwiftMessages + +class CountedViewController: UIViewController { + + @IBOutlet weak var descriptionLabel: UILabel! + @IBOutlet var messageView: CountedMessageView! + @IBOutlet weak var messageContainer: UIView! + + override func viewDidLoad() { + super.viewDidLoad() + descriptionLabel.configureBodyTextStyle() + descriptionLabel.configureCodeStyle(on: "show()") + descriptionLabel.configureCodeStyle(on: "hideCounted(id:)") + } + + @IBAction func show() { + var config = SwiftMessages.defaultConfig + config.presentationStyle = .center + config.duration = .forever + config.presentationContext = .view(messageContainer) + SwiftMessages.show(config: config, view: messageView) + updateCountLabel() + } + + @IBAction func hide() { + SwiftMessages.hideCounted(id: messageView.id) + updateCountLabel() + } + + private func updateCountLabel() { + let count = SwiftMessages.count(id: messageView.id) + let numberFormatter = NumberFormatter() + numberFormatter.numberStyle = .spellOut + messageView.countLabel.text = numberFormatter.string(from: NSNumber(value: count))?.uppercased() + } +} diff --git a/Demo/Demo/ExploreViewController.swift b/Demo/Demo/ExploreViewController.swift index aec24623..5d34762a 100644 --- a/Demo/Demo/ExploreViewController.swift +++ b/Demo/Demo/ExploreViewController.swift @@ -18,11 +18,11 @@ class ExploreViewController: UITableViewController, UITextFieldDelegate { let view: MessageView switch layout.selectedSegmentIndex { case 1: - view = MessageView.viewFromNib(layout: .CardView) + view = MessageView.viewFromNib(layout: .cardView) case 2: - view = MessageView.viewFromNib(layout: .TabView) + view = MessageView.viewFromNib(layout: .tabView) case 3: - view = MessageView.viewFromNib(layout: .StatusLine) + view = MessageView.viewFromNib(layout: .statusLine) default: view = try! SwiftMessages.viewFromNib() } @@ -41,17 +41,21 @@ class ExploreViewController: UITableViewController, UITextFieldDelegate { switch theme.selectedSegmentIndex { case 0: - view.configureTheme(.info, iconStyle: iconStyle) + view.configureTheme(.info, iconStyle: iconStyle, includeHaptic: hapticFeedback.isOn) + view.accessibilityPrefix = "info" case 1: - view.configureTheme(.success, iconStyle: iconStyle) + view.configureTheme(.success, iconStyle: iconStyle, includeHaptic: hapticFeedback.isOn) + view.accessibilityPrefix = "success" case 2: - view.configureTheme(.warning, iconStyle: iconStyle) + view.configureTheme(.warning, iconStyle: iconStyle, includeHaptic: hapticFeedback.isOn) + view.accessibilityPrefix = "warning" case 3: - view.configureTheme(.error, iconStyle: iconStyle) + view.configureTheme(.error, iconStyle: iconStyle, includeHaptic: hapticFeedback.isOn) + view.accessibilityPrefix = "error" default: - let iconText = ["🐸", "🐷", "🐬", "🐠", "🐍", "🐹", "🐼"].sm_random() + let iconText = ["🐸", "🐷", "🐬", "🐠", "🐍", "🐹", "🐼"].randomElement() view.configureTheme(backgroundColor: UIColor.purple, foregroundColor: UIColor.white, iconImage: nil, iconText: iconText) - view.button?.setImage(Icon.ErrorSubtle.image, for: .normal) + view.button?.setImage(Icon.errorSubtle.image, for: .normal) view.button?.setTitle(nil, for: .normal) view.button?.backgroundColor = UIColor.clear view.button?.tintColor = UIColor.green.withAlphaComponent(0.7) @@ -85,15 +89,17 @@ class ExploreViewController: UITableViewController, UITextFieldDelegate { switch presentationStyle.selectedSegmentIndex { case 1: config.presentationStyle = .bottom + case 2: + config.presentationStyle = .center default: break } switch presentationContext.selectedSegmentIndex { case 1: - config.presentationContext = .window(windowLevel: UIWindowLevelNormal) + config.presentationContext = .window(windowLevel: UIWindow.Level.normal) case 2: - config.presentationContext = .window(windowLevel: UIWindowLevelStatusBar) + config.presentationContext = .window(windowLevel: UIWindow.Level.statusBar) default: break } @@ -111,9 +117,11 @@ class ExploreViewController: UITableViewController, UITextFieldDelegate { switch dimMode.selectedSegmentIndex { case 1: - config.dimMode = .gray(interactive: false) - case 2: config.dimMode = .gray(interactive: true) + case 2: + config.dimMode = .color(color: #colorLiteral(red: 0.1019607857, green: 0.2784313858, blue: 0.400000006, alpha: 0.7477525685), interactive: true) + case 3: + config.dimMode = .blur(style: .dark, alpha: 1.0, interactive: true) default: break } @@ -132,7 +140,11 @@ class ExploreViewController: UITableViewController, UITextFieldDelegate { break } } - + + if view.defaultHaptic == nil && hapticFeedback.isOn { + config.haptic = .success + } + // Show SwiftMessages.show(config: config, view: view) } @@ -146,6 +158,7 @@ class ExploreViewController: UITableViewController, UITextFieldDelegate { @IBOutlet weak var duration: UISegmentedControl! @IBOutlet weak var dimMode: UISegmentedControl! @IBOutlet weak var interactiveHide: UISwitch! + @IBOutlet weak var hapticFeedback: UISwitch! @IBOutlet weak var layout: UISegmentedControl! @IBOutlet weak var theme: UISegmentedControl! @IBOutlet weak var iconStyle: UISegmentedControl! diff --git a/Demo/Demo/Info.plist b/Demo/Demo/Info.plist index cf2e887f..1aceb410 100644 --- a/Demo/Demo/Info.plist +++ b/Demo/Demo/Info.plist @@ -35,6 +35,7 @@ <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> + <string>UIInterfaceOrientationPortraitUpsideDown</string> </array> </dict> </plist> diff --git a/Demo/Demo/TacoDialogView.swift b/Demo/Demo/TacoDialogView.swift index a42f6df7..58739c93 100644 --- a/Demo/Demo/TacoDialogView.swift +++ b/Demo/Demo/TacoDialogView.swift @@ -24,7 +24,7 @@ class TacoDialogView: MessageView { fileprivate var count = 1 { didSet { iconLabel?.text = String(repeating: "🌮", count: count)//String(count: count, repeatedValue: ) - titleLabel?.text = TacoDialogView.tacoTitles[count] ?? "\(count)" + String(repeating: "!", count: count) + bodyLabel?.text = TacoDialogView.tacoTitles[count] ?? "\(count)" + String(repeating: "!", count: count) } } diff --git a/Demo/Demo/TacoDialogView.xib b/Demo/Demo/TacoDialogView.xib index 8dcda1a2..af7e8d3b 100644 --- a/Demo/Demo/TacoDialogView.xib +++ b/Demo/Demo/TacoDialogView.xib @@ -1,8 +1,11 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11198.2" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> + <device id="retina4_7" orientation="portrait"> + <adaptation id="fullscreen"/> + </device> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/> <capability name="Constraints to layout margins" minToolsVersion="6.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> @@ -13,17 +16,26 @@ <rect key="frame" x="0.0" y="0.0" width="600" height="309"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dp3-Ae-zep" userLabel="Background view"> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dp3-Ae-zep" userLabel="Background view" customClass="CornerRoundingView" customModule="SwiftMessages"> + <rect key="frame" x="30" y="10" width="540" height="289"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="RJH-Fp-YDa" userLabel="Content view"> + <rect key="frame" x="30" y="30" width="480" height="229"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="Irk-mj-bK8"> + <rect key="frame" x="0.0" y="0.0" width="480" height="60"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" distribution="fillProportionally" alignment="center" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="aav-a1-ogq"> + <rect key="frame" x="0.0" y="0.0" width="480" height="60"/> <subviews> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xLT-bX-GJE"> + <rect key="frame" x="0.0" y="0.0" width="480" height="60"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="748" text="🌮" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="pFx-Py-lZQ" userLabel="Icon label"> + <rect key="frame" x="0.0" y="0.0" width="50" height="60"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> <constraints> <constraint firstAttribute="height" constant="60" id="6yp-AT-q9O"/> </constraints> @@ -32,6 +44,10 @@ <nil key="highlightedColor"/> </label> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="1000" text="Just one, please." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YAk-Zs-x2f"> + <rect key="frame" x="65" y="0.0" width="415" height="60"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> <fontDescription key="fontDescription" name="Futura-CondensedMedium" family="Futura" pointSize="18"/> <color key="textColor" red="0.6705882352941176" green="0.51372549019607838" blue="0.13333333333333333" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> @@ -54,17 +70,23 @@ </subviews> </stackView> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="748" text="How many tocos would you like?" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gMT-Vh-S3z"> + <rect key="frame" x="0.0" y="75.5" width="480" height="23.5"/> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> <fontDescription key="fontDescription" name="Futura-Medium" family="Futura" pointSize="18"/> <color key="textColor" red="0.40392156862745099" green="0.36862745098039218" blue="0.2627450980392157" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Adjust the taco slider and place your order." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="U9w-CI-YK7"> + <rect key="frame" x="0.0" y="115" width="480" height="17"/> <fontDescription key="fontDescription" name="Futura-CondensedMedium" family="Futura" pointSize="14"/> <color key="textColor" red="0.60392156862745094" green="0.44313725490196076" blue="0.10588235294117647" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="1" maxValue="5" translatesAutoresizingMaskIntoConstraints="NO" id="MKs-Kv-aPL"> + <rect key="frame" x="-2" y="147.5" width="484" height="31"/> <color key="minimumTrackTintColor" red="0.94509803921568625" green="0.57647058823529407" blue="0.078431372549019607" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <connections> <action selector="tacoSliderFinished:" destination="JI3-gM-XBO" eventType="touchUpInside" id="ekV-4L-MLR"/> @@ -73,10 +95,13 @@ </connections> </slider> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="bottom" translatesAutoresizingMaskIntoConstraints="NO" id="x8I-RG-nBX"> + <rect key="frame" x="0.0" y="193" width="480" height="36"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="8Qt-TE-nPO"> + <rect key="frame" x="323" y="0.0" width="157" height="36"/> <subviews> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yFi-Ik-klX"> + <rect key="frame" x="0.0" y="0.0" width="58" height="36"/> <fontDescription key="fontDescription" type="system" pointSize="15"/> <state key="normal" title="Forget It"> <color key="titleColor" red="0.94468559679999997" green="0.57750775359999995" blue="0.07530619559" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> @@ -86,6 +111,7 @@ </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rVu-Ei-t6A"> + <rect key="frame" x="73" y="0.0" width="84" height="36"/> <color key="backgroundColor" red="0.94117647058823528" green="0.57647058823529407" blue="0.074509803921568626" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" name="Futura-Medium" family="Futura" pointSize="15"/> <inset key="contentEdgeInsets" minX="8" minY="8" maxX="8" maxY="8"/> @@ -116,17 +142,17 @@ <constraint firstItem="RJH-Fp-YDa" firstAttribute="leading" secondItem="dp3-Ae-zep" secondAttribute="leading" constant="30" id="zmH-aG-8Ij"/> </constraints> <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="5"/> + <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius"> + <real key="value" value="15"/> </userDefinedRuntimeAttribute> </userDefinedRuntimeAttributes> </view> </subviews> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <constraints> - <constraint firstAttribute="trailing" secondItem="dp3-Ae-zep" secondAttribute="trailing" constant="10" id="gGP-zK-6VU"/> + <constraint firstAttribute="trailingMargin" secondItem="dp3-Ae-zep" secondAttribute="trailing" constant="10" id="gGP-zK-6VU"/> <constraint firstItem="dp3-Ae-zep" firstAttribute="leading" secondItem="JI3-gM-XBO" secondAttribute="leadingMargin" constant="10" id="gyP-aD-uO3"/> - <constraint firstAttribute="bottom" secondItem="dp3-Ae-zep" secondAttribute="bottom" constant="10" id="le8-gK-lcY"/> + <constraint firstAttribute="bottomMargin" secondItem="dp3-Ae-zep" secondAttribute="bottom" constant="10" id="le8-gK-lcY"/> <constraint firstItem="dp3-Ae-zep" firstAttribute="top" secondItem="JI3-gM-XBO" secondAttribute="topMargin" constant="10" id="s15-z9-aHc"/> </constraints> <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> @@ -134,16 +160,13 @@ <userDefinedRuntimeAttribute type="number" keyPath="bounceAnimationOffset"> <real key="value" value="0.0"/> </userDefinedRuntimeAttribute> - <userDefinedRuntimeAttribute type="number" keyPath="statusBarOffset"> - <real key="value" value="10"/> - </userDefinedRuntimeAttribute> </userDefinedRuntimeAttributes> <connections> <outlet property="backgroundView" destination="dp3-Ae-zep" id="ZiK-GN-SXH"/> - <outlet property="bodyLabel" destination="gMT-Vh-S3z" id="BkZ-P0-0dh"/> + <outlet property="bodyLabel" destination="YAk-Zs-x2f" id="Koz-Jf-jUo"/> <outlet property="iconLabel" destination="pFx-Py-lZQ" id="xKK-gA-Otu"/> <outlet property="tacoSlider" destination="MKs-Kv-aPL" id="Iky-UQ-58E"/> - <outlet property="titleLabel" destination="YAk-Zs-x2f" id="ufT-ii-FoC"/> + <outlet property="titleLabel" destination="gMT-Vh-S3z" id="FWK-Tl-hc6"/> </connections> <point key="canvasLocation" x="304" y="614.5"/> </view> diff --git a/Demo/Demo/Utils.swift b/Demo/Demo/Utils.swift new file mode 100644 index 00000000..c6057115 --- /dev/null +++ b/Demo/Demo/Utils.swift @@ -0,0 +1,58 @@ +// +// Utils.swift +// Demo +// +// Created by Timothy Moose on 8/25/17. +// Copyright © 2017 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +extension UILabel { + + func configureBodyTextStyle() { + let bodyStyle = NSMutableParagraphStyle() + bodyStyle.lineSpacing = 5.0 + attributedText = NSAttributedString(string: text ?? "", attributes: [NSAttributedString.Key.paragraphStyle : bodyStyle]) + } + + func configureCodeStyle(on substring: String?) { + var attributes: [NSAttributedString.Key : Any] = [:] + let codeFont = UIFont(name: "CourierNewPSMT", size: font.pointSize)! + attributes[NSAttributedString.Key.font] = codeFont + attributes[NSAttributedString.Key.backgroundColor] = UIColor(white: 0.96, alpha: 1) + attributedText = attributedText?.setAttributes(attributes: attributes, onSubstring: substring) + } +} + +extension NSAttributedString { + + public func setAttributes(attributes: [NSAttributedString.Key : Any], onSubstring substring: String?) -> NSAttributedString { + let mutableSelf = NSMutableAttributedString(attributedString: self) + if let substring = substring { + var range = NSRange() + repeat { + let length = mutableSelf.length + let start = range.location + range.length + let remainingLength = length - start + let remainingRange = NSRange(location: start, length: remainingLength) + range = (mutableSelf.string as NSString).range(of: substring, options: .caseInsensitive, range: remainingRange) + NSAttributedString.set(attributes: attributes, in: range, of: mutableSelf) + } while range.length > 0 + } else { + let range = NSRange(location: 0, length: mutableSelf.length) + NSAttributedString.set(attributes: attributes, in: range, of: mutableSelf) + } + return mutableSelf + } + + private static func set(attributes newAttributes: [NSAttributedString.Key : Any], in range: NSRange, of mutableString: NSMutableAttributedString) { + if range.length > 0 { + var attributes = mutableString.attributes(at: range.location, effectiveRange: nil) + for (key, value) in newAttributes { + attributes.updateValue(value, forKey: key) + } + mutableString.setAttributes(attributes, range: range) + } + } +} diff --git a/Demo/Demo/ViewController.swift b/Demo/Demo/ViewController.swift index 0f63170b..aad1e704 100644 --- a/Demo/Demo/ViewController.swift +++ b/Demo/Demo/ViewController.swift @@ -16,6 +16,9 @@ class ViewController: UITableViewController { .titleBody(title: "ANY VIEW", body: "Any view, no matter how cute, can be displayed as a message.", function: ViewController.demoAnyView), .titleBody(title: "CUSTOMIZE", body: "Easily customize by copying one of the SwiftMessages nib files into your project as a starting point. Then order some tacos.", function: ViewController.demoCustomNib), .explore, + .titleBody(title: "CENTERED", body: "Show cenetered messages with a fun, physics-based dismissal gesture.", function: ViewController.demoCentered), + .viewController, + //.counted, ] /* @@ -46,7 +49,7 @@ class ViewController: UITableViewController { } override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return UITableViewAutomaticDimension + return UITableView.automaticDimension } /* @@ -55,31 +58,31 @@ class ViewController: UITableViewController { static func demoBasics() -> Void { - let error = MessageView.viewFromNib(layout: .TabView) + let error = MessageView.viewFromNib(layout: .tabView) error.configureTheme(.error) error.configureContent(title: "Error", body: "Something is horribly wrong!") error.button?.setTitle("Stop", for: .normal) - let warning = MessageView.viewFromNib(layout: .CardView) + let warning = MessageView.viewFromNib(layout: .cardView) warning.configureTheme(.warning) warning.configureDropShadow() - let iconText = ["🤔", "😳", "🙄", "😶"].sm_random()! + let iconText = ["🤔", "😳", "🙄", "😶"].randomElement()! warning.configureContent(title: "Warning", body: "Consider yourself warned.", iconText: iconText) warning.button?.isHidden = true var warningConfig = SwiftMessages.defaultConfig - warningConfig.presentationContext = .window(windowLevel: UIWindowLevelStatusBar) + warningConfig.presentationContext = .window(windowLevel: UIWindow.Level.statusBar) - let success = MessageView.viewFromNib(layout: .CardView) + let success = MessageView.viewFromNib(layout: .cardView) success.configureTheme(.success) success.configureDropShadow() success.configureContent(title: "Success", body: "Something good happened!") success.button?.isHidden = true var successConfig = SwiftMessages.defaultConfig - successConfig.presentationStyle = .bottom - successConfig.presentationContext = .window(windowLevel: UIWindowLevelNormal) + successConfig.presentationStyle = .center + successConfig.presentationContext = .window(windowLevel: UIWindow.Level.normal) - let info = MessageView.viewFromNib(layout: .MessageView) + let info = MessageView.viewFromNib(layout: .messageView) info.configureTheme(.info) info.button?.isHidden = true info.configureContent(title: "Info", body: "This is a very lengthy and informative info message that wraps across multiple lines and grows in height as needed.") @@ -87,19 +90,19 @@ class ViewController: UITableViewController { infoConfig.presentationStyle = .bottom infoConfig.duration = .seconds(seconds: 0.25) - let status = MessageView.viewFromNib(layout: .StatusLine) + let status = MessageView.viewFromNib(layout: .statusLine) status.backgroundView.backgroundColor = UIColor.purple status.bodyLabel?.textColor = UIColor.white status.configureContent(body: "A tiny line of text covering the status bar.") var statusConfig = SwiftMessages.defaultConfig - statusConfig.presentationContext = .window(windowLevel: UIWindowLevelStatusBar) + statusConfig.presentationContext = .window(windowLevel: UIWindow.Level.statusBar) - let status2 = MessageView.viewFromNib(layout: .StatusLine) + let status2 = MessageView.viewFromNib(layout: .statusLine) status2.backgroundView.backgroundColor = UIColor.orange status2.bodyLabel?.textColor = UIColor.white status2.configureContent(body: "Switched to light status bar!") var status2Config = SwiftMessages.defaultConfig - status2Config.presentationContext = .window(windowLevel: UIWindowLevelNormal) + status2Config.presentationContext = .window(windowLevel: UIWindow.Level.normal) status2Config.preferredStatusBarStyle = .lightContent SwiftMessages.show(view: error) @@ -115,13 +118,20 @@ class ViewController: UITableViewController { imageView.image = UIImage(named: "puppies") imageView.contentMode = .scaleAspectFill imageView.clipsToBounds = true - let f = CGRect(x: 100, y: 100, width: 100, height: 100) - let messageView = BaseView(frame: f) - messageView.installContentView(imageView) - messageView.preferredHeight = 120.0 + let messageView = BaseView(frame: .zero) + messageView.layoutMargins = .zero + messageView.backgroundHeight = 120.0 + do { + let backgroundView = CornerRoundingView() + backgroundView.cornerRadius = 15 + backgroundView.layer.masksToBounds = true + messageView.installBackgroundView(backgroundView) + messageView.installContentView(imageView) + messageView.layoutMarginAdditions = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) + } messageView.configureDropShadow() var config = SwiftMessages.defaultConfig - config.presentationContext = .window(windowLevel: UIWindowLevelStatusBar) + config.presentationContext = .window(windowLevel: UIWindow.Level.statusBar) SwiftMessages.show(config: config, view: messageView) } @@ -131,15 +141,27 @@ class ViewController: UITableViewController { view.getTacosAction = { _ in SwiftMessages.hide() } view.cancelAction = { SwiftMessages.hide() } var config = SwiftMessages.defaultConfig - config.presentationContext = .window(windowLevel: UIWindowLevelStatusBar) + config.presentationContext = .window(windowLevel: UIWindow.Level.statusBar) config.duration = .forever config.presentationStyle = .bottom config.dimMode = .gray(interactive: true) SwiftMessages.show(config: config, view: view) } - static func demoExplore() { - + static func demoCentered() { + let messageView: MessageView = MessageView.viewFromNib(layout: .centeredView) + messageView.configureBackgroundView(width: 250) + messageView.configureContent(title: "Hey There!", body: "Please try swiping to dismiss this message.", iconImage: nil, iconText: "🦄", buttonImage: nil, buttonTitle: "No Thanks") { _ in + SwiftMessages.hide() + } + messageView.backgroundView.backgroundColor = UIColor.init(white: 0.97, alpha: 1) + messageView.backgroundView.layer.cornerRadius = 10 + var config = SwiftMessages.defaultConfig + config.presentationStyle = .center + config.duration = .forever + config.dimMode = .blur(style: .dark, alpha: 1, interactive: true) + config.presentationContext = .window(windowLevel: UIWindow.Level.statusBar) + SwiftMessages.show(config: config, view: messageView) } } @@ -149,26 +171,38 @@ enum Item { case titleBody(title: String, body: String, function: Function) case explore - + case counted + case viewController + func dequeueCell(_ tableView: UITableView) -> UITableViewCell { switch self { - case .titleBody(let data): + case .titleBody(let title, let body, _): let cell = tableView.dequeueReusableCell(withIdentifier: "TitleBody") as! TitleBodyCell - cell.titleLabel.text = data.title - cell.bodyLabel.text = data.body + cell.titleLabel.text = title + cell.bodyLabel.text = body cell.configureBodyTextStyle() return cell case .explore: let cell = tableView.dequeueReusableCell(withIdentifier: "Explore") as! TitleBodyCell cell.configureBodyTextStyle() return cell + case .counted: + let cell = tableView.dequeueReusableCell(withIdentifier: "Counted") as! TitleBodyCell + cell.configureBodyTextStyle() + cell.bodyLabel.configureCodeStyle(on: "show()") + cell.bodyLabel.configureCodeStyle(on: "hideCounted(id:)") + return cell + case .viewController: + let cell = tableView.dequeueReusableCell(withIdentifier: "ViewController") as! TitleBodyCell + cell.configureBodyTextStyle() + return cell } } func performDemo() { switch self { - case .titleBody(let data): - data.function() + case .titleBody(_, _, let function): + function() default: break } @@ -182,7 +216,6 @@ class TitleBodyCell: UITableViewCell { func configureBodyTextStyle() { let bodyStyle = NSMutableParagraphStyle() bodyStyle.lineSpacing = 5.0 - bodyLabel.attributedText = NSAttributedString(string: bodyLabel.text ?? "", attributes: [NSParagraphStyleAttributeName : bodyStyle]) + bodyLabel.configureBodyTextStyle() } } - diff --git a/Demo/Demo/ViewControllersViewController.swift b/Demo/Demo/ViewControllersViewController.swift new file mode 100644 index 00000000..6fb14eeb --- /dev/null +++ b/Demo/Demo/ViewControllersViewController.swift @@ -0,0 +1,65 @@ +// +// ViewControllersViewController.swift +// Demo +// +// Created by Timothy Moose on 7/28/18. +// Copyright © 2018 SwiftKick Mobile. All rights reserved. +// + +import UIKit +import SwiftMessages + +class ViewControllersViewController: UIViewController { + @objc @IBAction private func dismissPresented(segue: UIStoryboardSegue) { + dismiss(animated: true, completion: nil) + } +} + +class SwiftMessagesTopSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .topMessage) + } +} + +class SwiftMessagesTopCardSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .topCard) + } +} + +class SwiftMessagesTopTabSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .topTab) + } +} + +class SwiftMessagesBottomSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .bottomMessage) + } +} + +class SwiftMessagesBottomCardSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .bottomCard) + } +} + +class SwiftMessagesBottomTabSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .bottomTab) + } +} + +class SwiftMessagesCenteredSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .centered) + } +} diff --git a/Demo/Podfile.lock b/Demo/Podfile.lock deleted file mode 100644 index 254dff49..00000000 --- a/Demo/Podfile.lock +++ /dev/null @@ -1,16 +0,0 @@ -PODS: - - SwiftMessages (3.0.3) - -DEPENDENCIES: - - SwiftMessages (from `../`) - -EXTERNAL SOURCES: - SwiftMessages: - :path: ../ - -SPEC CHECKSUMS: - SwiftMessages: 06669bc36f8aef5883932db29d36e4292979d915 - -PODFILE CHECKSUM: 6431c980c9207084d738b6ba87b2101dd9eb5097 - -COCOAPODS: 1.1.1 diff --git a/Demo/Pods/Local Podspecs/SwiftMessages.podspec.json b/Demo/Pods/Local Podspecs/SwiftMessages.podspec.json deleted file mode 100644 index 71ac2ce5..00000000 --- a/Demo/Pods/Local Podspecs/SwiftMessages.podspec.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "SwiftMessages", - "version": "3.0.3", - "license": { - "type": "MIT" - }, - "homepage": "https://github.com/SwiftKickMobile/SwiftMessages", - "authors": { - "Timothy Moose": "tim@swiftkick.it" - }, - "summary": "A very flexible message bar for iOS written in Swift.", - "source": { - "git": "https://github.com/SwiftKickMobile/SwiftMessages.git", - "tag": "3.0.3" - }, - "platforms": { - "ios": "8.0" - }, - "source_files": "SwiftMessages/**/*.swift", - "resource_bundles": { - "SwiftMessages": [ - "SwiftMessages/Resources/**/*" - ] - }, - "frameworks": "UIKit", - "requires_arc": true -} diff --git a/Demo/Pods/Manifest.lock b/Demo/Pods/Manifest.lock deleted file mode 100644 index 254dff49..00000000 --- a/Demo/Pods/Manifest.lock +++ /dev/null @@ -1,16 +0,0 @@ -PODS: - - SwiftMessages (3.0.3) - -DEPENDENCIES: - - SwiftMessages (from `../`) - -EXTERNAL SOURCES: - SwiftMessages: - :path: ../ - -SPEC CHECKSUMS: - SwiftMessages: 06669bc36f8aef5883932db29d36e4292979d915 - -PODFILE CHECKSUM: 6431c980c9207084d738b6ba87b2101dd9eb5097 - -COCOAPODS: 1.1.1 diff --git a/Demo/Pods/Pods.xcodeproj/project.pbxproj b/Demo/Pods/Pods.xcodeproj/project.pbxproj deleted file mode 100644 index 10b86081..00000000 --- a/Demo/Pods/Pods.xcodeproj/project.pbxproj +++ /dev/null @@ -1,763 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 033755DFF1EAA8845C3A4400F7CABD73 /* MessageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = CBCBA1D883DEEB0334782E5EDB718DDB /* MessageView.xib */; }; - 0D01BFD56C1BEA74B1DD7F669383C02E /* CardView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 935AF4ECA81CC2678E76B92FF03E4CD1 /* CardView.xib */; }; - 0ECE6B9AA78CD7C4640C3ED1F63C28C0 /* StatusLine.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4CB2A7DC83E6F1CB8B9EA75D6C97CBED /* StatusLine.xib */; }; - 3508BE5270089E984127E6DA9200D6EB /* SwiftMessages-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A863D0F2536D769707B46871EBA897B /* SwiftMessages-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 361B87DFD5711CC17EA526078D6AE7BF /* NSBundle+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 464E0975C3D038A42E7D5B43E27DB23B /* NSBundle+Utils.swift */; }; - 37CE3EEAFCF317B15AF9A9496983E43D /* Array+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FAD0CA526C80FBFB3BA8A5C07559FEF /* Array+Utils.swift */; }; - 4A7E56B569DF6C7681E72ECC1F54CC46 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 616BEB51ECCAD129BDBCB7A956B56CC6 /* Foundation.framework */; }; - 4C93067366FED28F560E04E6D497E3F8 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51AF6A2CED446E4872B522299E5F5D10 /* Error.swift */; }; - 4E9B81CE7D381F180D054D2D1583B6D2 /* TabView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B158478428D475305ADAF5828351240 /* TabView.xib */; }; - 55B1ED48905476533300C59DD70C1204 /* PassthroughWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63D213FF475BB82B12655CE24416B7F4 /* PassthroughWindow.swift */; }; - 623E3DF2F6D0B976C165A00D6EA1D55E /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63A5295EC116F9FD3E06892F71998C9A /* Theme.swift */; }; - 6B58CA72D169E768CA259C48AAED3AD1 /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B22FC3EB8475C3D4FA73110FD742497 /* BaseView.swift */; }; - 7CEBD10BD22E92DCD0B7454A87293DB6 /* Pods-Demo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 03EA1E60232BFA05817BC26ACB8E68BA /* Pods-Demo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9B95A220914D3BC576D1F179029605CF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 616BEB51ECCAD129BDBCB7A956B56CC6 /* Foundation.framework */; }; - 9BD977BD90B8240559AD9D461E66C814 /* Pods-Demo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = C5BC86D40B890A7B0844F888209CA06F /* Pods-Demo-dummy.m */; }; - 9F63C90369D73BF39DDB112F66EBFE9A /* UIViewController+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 749543C80A60DDE16A18B30833E939C8 /* UIViewController+Utils.swift */; }; - A0BB3AFC78CAEB0955389592B2345BEF /* MessageViewIOS8.xib in Resources */ = {isa = PBXBuildFile; fileRef = EE0DA5FBD33716312680D2F857D3BFF1 /* MessageViewIOS8.xib */; }; - B521592325469EC120D284763CE632C8 /* BackgroundViewable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8736DDECB493A056A2AB7B962D5A1C36 /* BackgroundViewable.swift */; }; - B884D515F9A27C2F421B298EC82FACA5 /* WindowViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F631B93A4E963F8E97CD304126E81B8 /* WindowViewController.swift */; }; - BCC3C8587F2CF0A9B533B67CD039FAF6 /* Presenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B591B99259586710CB1B7B262B07E78 /* Presenter.swift */; }; - C375636BF954217E7663BD78163ECC1F /* Identifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E520F85C9F3D333AEF256ADBD7C5981 /* Identifiable.swift */; }; - C3BD696FE64625B4EC84D330BF03FC6E /* SwiftMessages.bundle in Resources */ = {isa = PBXBuildFile; fileRef = EDA8A9CFB00CA35B42F93F216EB7DA9B /* SwiftMessages.bundle */; }; - C4F47992FAA181DCA6EA8FBFD5651A21 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0A4D9DDC91358D2E2437AB30046E9553 /* Images.xcassets */; }; - C7C26AB011E621CC61016EA8BB38CFE3 /* SwiftMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CFB0B18866A37CD24FE04F785992F2B /* SwiftMessages.swift */; }; - D2C2509012B61DEEF0851D49431A8037 /* PassthroughView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3520E8580FD3906F08FFE47E8F0D3EA /* PassthroughView.swift */; }; - D2EC6EE885103DECF483741F6272EC48 /* MarginAdjustable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3CC8CF7417590860536205EF5C33255 /* MarginAdjustable.swift */; }; - D9F06A51095F1AFE92D70FFB0AFB72B5 /* MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BBB29F0DA5F0FF9535944F1F59935CF /* MessageView.swift */; }; - DC0C70D1D189212417E59E066A77B052 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7EC994CDC2D681BA26389F78A7E4B325 /* UIKit.framework */; }; - FA1B968C19EDF9104062DB1FF562AA90 /* SwiftMessages-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFFA5D242D0AAB9518D5D81A208B79D /* SwiftMessages-dummy.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 45EF838C81A9FDB837D9733ABAAA0CA6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6E57A87EDA4AA3721FA3CEB34CC36F3A; - remoteInfo = SwiftMessages; - }; - DC9CAF286ADBC369745000328E9F5779 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 87FAE22F1196DDE6C5E9CF0810E33725; - remoteInfo = "SwiftMessages-SwiftMessages"; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 03EA1E60232BFA05817BC26ACB8E68BA /* Pods-Demo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Demo-umbrella.h"; sourceTree = "<group>"; }; - 0A4D9DDC91358D2E2437AB30046E9553 /* Images.xcassets */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; }; - 2A863D0F2536D769707B46871EBA897B /* SwiftMessages-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-umbrella.h"; sourceTree = "<group>"; }; - 322419E99883B306EE7EC77959FCC8DF /* Pods-Demo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-Demo.modulemap"; sourceTree = "<group>"; }; - 3CD5A30239C90F1B549B4AB9299ECF16 /* Pods-Demo-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Demo-frameworks.sh"; sourceTree = "<group>"; }; - 3D653C9DA16200D75AD14323AA830C6B /* Pods-Demo-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Demo-resources.sh"; sourceTree = "<group>"; }; - 464E0975C3D038A42E7D5B43E27DB23B /* NSBundle+Utils.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "NSBundle+Utils.swift"; sourceTree = "<group>"; }; - 4CB2A7DC83E6F1CB8B9EA75D6C97CBED /* StatusLine.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; path = StatusLine.xib; sourceTree = "<group>"; }; - 4CFB0B18866A37CD24FE04F785992F2B /* SwiftMessages.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SwiftMessages.swift; sourceTree = "<group>"; }; - 51AF6A2CED446E4872B522299E5F5D10 /* Error.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; }; - 5259A068CBCD8780234A0D70629C1271 /* SwiftMessages.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftMessages.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 5A26502335E6CC635672E16466F8C0EE /* SwiftMessages.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = SwiftMessages.modulemap; sourceTree = "<group>"; }; - 5B591B99259586710CB1B7B262B07E78 /* Presenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Presenter.swift; sourceTree = "<group>"; }; - 616BEB51ECCAD129BDBCB7A956B56CC6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - 63A5295EC116F9FD3E06892F71998C9A /* Theme.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; }; - 63D213FF475BB82B12655CE24416B7F4 /* PassthroughWindow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PassthroughWindow.swift; sourceTree = "<group>"; }; - 6BBB29F0DA5F0FF9535944F1F59935CF /* MessageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MessageView.swift; sourceTree = "<group>"; }; - 6E520F85C9F3D333AEF256ADBD7C5981 /* Identifiable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Identifiable.swift; sourceTree = "<group>"; }; - 71940C1CEB7995DC34CFE54CAF1AEF88 /* Pods-Demo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Demo-acknowledgements.markdown"; sourceTree = "<group>"; }; - 749543C80A60DDE16A18B30833E939C8 /* UIViewController+Utils.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "UIViewController+Utils.swift"; sourceTree = "<group>"; }; - 7B158478428D475305ADAF5828351240 /* TabView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; path = TabView.xib; sourceTree = "<group>"; }; - 7EC994CDC2D681BA26389F78A7E4B325 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - 7FAD0CA526C80FBFB3BA8A5C07559FEF /* Array+Utils.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Array+Utils.swift"; sourceTree = "<group>"; }; - 8736DDECB493A056A2AB7B962D5A1C36 /* BackgroundViewable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BackgroundViewable.swift; sourceTree = "<group>"; }; - 8B22FC3EB8475C3D4FA73110FD742497 /* BaseView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BaseView.swift; sourceTree = "<group>"; }; - 935AF4ECA81CC2678E76B92FF03E4CD1 /* CardView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; path = CardView.xib; sourceTree = "<group>"; }; - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9F631B93A4E963F8E97CD304126E81B8 /* WindowViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WindowViewController.swift; sourceTree = "<group>"; }; - BFCD7E7BC43700342D2ECDA704620869 /* Pods_Demo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Demo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - C3520E8580FD3906F08FFE47E8F0D3EA /* PassthroughView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PassthroughView.swift; sourceTree = "<group>"; }; - C5BC86D40B890A7B0844F888209CA06F /* Pods-Demo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Demo-dummy.m"; sourceTree = "<group>"; }; - CA19694C0AC41D598DE4ABFEB300E619 /* Pods-Demo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Demo-acknowledgements.plist"; sourceTree = "<group>"; }; - CBCBA1D883DEEB0334782E5EDB718DDB /* MessageView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; path = MessageView.xib; sourceTree = "<group>"; }; - CC6A59B0ADA6CB2F51DAE6508E437829 /* Pods-Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Demo.debug.xcconfig"; sourceTree = "<group>"; }; - DAB0701F8F25395B1ED46510ED4B9797 /* Pods-Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Demo.release.xcconfig"; sourceTree = "<group>"; }; - DAFFA5D242D0AAB9518D5D81A208B79D /* SwiftMessages-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SwiftMessages-dummy.m"; sourceTree = "<group>"; }; - E56520D015ED5615EF53801D8894ED54 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; - E68F8C86FB3267A3C87983DA9E269889 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; - EADFEC8806C084547A9B8D3999011AD3 /* SwiftMessages-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-prefix.pch"; sourceTree = "<group>"; }; - EDA8A9CFB00CA35B42F93F216EB7DA9B /* SwiftMessages.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftMessages.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - EE0DA5FBD33716312680D2F857D3BFF1 /* MessageViewIOS8.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; path = MessageViewIOS8.xib; sourceTree = "<group>"; }; - F08242889B058791110330C1D95B6032 /* SwiftMessages.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.xcconfig; sourceTree = "<group>"; }; - F3CC8CF7417590860536205EF5C33255 /* MarginAdjustable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MarginAdjustable.swift; sourceTree = "<group>"; }; - FD5810E2F88EF29CCA9B7E188B460508 /* ResourceBundle-SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-SwiftMessages-Info.plist"; sourceTree = "<group>"; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 498DB15259537BA06EFE828A427CD8B4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 9B95A220914D3BC576D1F179029605CF /* Foundation.framework in Frameworks */, - DC0C70D1D189212417E59E066A77B052 /* UIKit.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 8AEDA58AB3CF2CF29D7B8B4CD6725062 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - ED81D8C9CD17F825987E610677CA67B2 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 4A7E56B569DF6C7681E72ECC1F54CC46 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 15EC86D4E42688E0ACF8DFD479D81DEB /* Resources */ = { - isa = PBXGroup; - children = ( - 921FD2BED344FC79AEC78DE48E9CEECD /* SwiftMessages */, - ); - name = Resources; - sourceTree = "<group>"; - }; - 1D74C48A5F5DFA0096A4D3FF179106C1 /* Products */ = { - isa = PBXGroup; - children = ( - BFCD7E7BC43700342D2ECDA704620869 /* Pods_Demo.framework */, - EDA8A9CFB00CA35B42F93F216EB7DA9B /* SwiftMessages.bundle */, - 5259A068CBCD8780234A0D70629C1271 /* SwiftMessages.framework */, - ); - name = Products; - sourceTree = "<group>"; - }; - 3D0EB5CD3C73C142233F68A71727F1B8 /* SwiftMessages */ = { - isa = PBXGroup; - children = ( - 15EC86D4E42688E0ACF8DFD479D81DEB /* Resources */, - ED223EF5C8C46CAC2F4E5A0CA078617B /* Support Files */, - CBF70BC86833603ADADCC2B154F9E906 /* SwiftMessages */, - ); - name = SwiftMessages; - path = ../..; - sourceTree = "<group>"; - }; - 433CD3331B6C3787F473C941B61FC68F /* Frameworks */ = { - isa = PBXGroup; - children = ( - E6EE98446B568159EE277B68FD442AF0 /* iOS */, - ); - name = Frameworks; - sourceTree = "<group>"; - }; - 6F2351C272926D3E0225FEFC2F9C5D1F /* Targets Support Files */ = { - isa = PBXGroup; - children = ( - ECC58720C5754A079F9A150E40E2FCDD /* Pods-Demo */, - ); - name = "Targets Support Files"; - sourceTree = "<group>"; - }; - 7A5DB11FD5464933475796D843C9E397 /* Development Pods */ = { - isa = PBXGroup; - children = ( - 3D0EB5CD3C73C142233F68A71727F1B8 /* SwiftMessages */, - ); - name = "Development Pods"; - sourceTree = "<group>"; - }; - 7DB346D0F39D3F0E887471402A8071AB = { - isa = PBXGroup; - children = ( - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, - 7A5DB11FD5464933475796D843C9E397 /* Development Pods */, - 433CD3331B6C3787F473C941B61FC68F /* Frameworks */, - 1D74C48A5F5DFA0096A4D3FF179106C1 /* Products */, - 6F2351C272926D3E0225FEFC2F9C5D1F /* Targets Support Files */, - ); - sourceTree = "<group>"; - }; - 82971C2C4FC60B9F62E1B400A07548C5 /* Resources */ = { - isa = PBXGroup; - children = ( - 935AF4ECA81CC2678E76B92FF03E4CD1 /* CardView.xib */, - 0A4D9DDC91358D2E2437AB30046E9553 /* Images.xcassets */, - CBCBA1D883DEEB0334782E5EDB718DDB /* MessageView.xib */, - EE0DA5FBD33716312680D2F857D3BFF1 /* MessageViewIOS8.xib */, - 4CB2A7DC83E6F1CB8B9EA75D6C97CBED /* StatusLine.xib */, - 7B158478428D475305ADAF5828351240 /* TabView.xib */, - ); - path = Resources; - sourceTree = "<group>"; - }; - 921FD2BED344FC79AEC78DE48E9CEECD /* SwiftMessages */ = { - isa = PBXGroup; - children = ( - 82971C2C4FC60B9F62E1B400A07548C5 /* Resources */, - ); - path = SwiftMessages; - sourceTree = "<group>"; - }; - CBF70BC86833603ADADCC2B154F9E906 /* SwiftMessages */ = { - isa = PBXGroup; - children = ( - 7FAD0CA526C80FBFB3BA8A5C07559FEF /* Array+Utils.swift */, - 8736DDECB493A056A2AB7B962D5A1C36 /* BackgroundViewable.swift */, - 8B22FC3EB8475C3D4FA73110FD742497 /* BaseView.swift */, - 51AF6A2CED446E4872B522299E5F5D10 /* Error.swift */, - 6E520F85C9F3D333AEF256ADBD7C5981 /* Identifiable.swift */, - F3CC8CF7417590860536205EF5C33255 /* MarginAdjustable.swift */, - 6BBB29F0DA5F0FF9535944F1F59935CF /* MessageView.swift */, - 464E0975C3D038A42E7D5B43E27DB23B /* NSBundle+Utils.swift */, - C3520E8580FD3906F08FFE47E8F0D3EA /* PassthroughView.swift */, - 63D213FF475BB82B12655CE24416B7F4 /* PassthroughWindow.swift */, - 5B591B99259586710CB1B7B262B07E78 /* Presenter.swift */, - 4CFB0B18866A37CD24FE04F785992F2B /* SwiftMessages.swift */, - 63A5295EC116F9FD3E06892F71998C9A /* Theme.swift */, - 749543C80A60DDE16A18B30833E939C8 /* UIViewController+Utils.swift */, - 9F631B93A4E963F8E97CD304126E81B8 /* WindowViewController.swift */, - ); - path = SwiftMessages; - sourceTree = "<group>"; - }; - E6EE98446B568159EE277B68FD442AF0 /* iOS */ = { - isa = PBXGroup; - children = ( - 616BEB51ECCAD129BDBCB7A956B56CC6 /* Foundation.framework */, - 7EC994CDC2D681BA26389F78A7E4B325 /* UIKit.framework */, - ); - name = iOS; - sourceTree = "<group>"; - }; - ECC58720C5754A079F9A150E40E2FCDD /* Pods-Demo */ = { - isa = PBXGroup; - children = ( - E68F8C86FB3267A3C87983DA9E269889 /* Info.plist */, - 322419E99883B306EE7EC77959FCC8DF /* Pods-Demo.modulemap */, - 71940C1CEB7995DC34CFE54CAF1AEF88 /* Pods-Demo-acknowledgements.markdown */, - CA19694C0AC41D598DE4ABFEB300E619 /* Pods-Demo-acknowledgements.plist */, - C5BC86D40B890A7B0844F888209CA06F /* Pods-Demo-dummy.m */, - 3CD5A30239C90F1B549B4AB9299ECF16 /* Pods-Demo-frameworks.sh */, - 3D653C9DA16200D75AD14323AA830C6B /* Pods-Demo-resources.sh */, - 03EA1E60232BFA05817BC26ACB8E68BA /* Pods-Demo-umbrella.h */, - CC6A59B0ADA6CB2F51DAE6508E437829 /* Pods-Demo.debug.xcconfig */, - DAB0701F8F25395B1ED46510ED4B9797 /* Pods-Demo.release.xcconfig */, - ); - name = "Pods-Demo"; - path = "Target Support Files/Pods-Demo"; - sourceTree = "<group>"; - }; - ED223EF5C8C46CAC2F4E5A0CA078617B /* Support Files */ = { - isa = PBXGroup; - children = ( - E56520D015ED5615EF53801D8894ED54 /* Info.plist */, - FD5810E2F88EF29CCA9B7E188B460508 /* ResourceBundle-SwiftMessages-Info.plist */, - 5A26502335E6CC635672E16466F8C0EE /* SwiftMessages.modulemap */, - F08242889B058791110330C1D95B6032 /* SwiftMessages.xcconfig */, - DAFFA5D242D0AAB9518D5D81A208B79D /* SwiftMessages-dummy.m */, - EADFEC8806C084547A9B8D3999011AD3 /* SwiftMessages-prefix.pch */, - 2A863D0F2536D769707B46871EBA897B /* SwiftMessages-umbrella.h */, - ); - name = "Support Files"; - path = "Demo/Pods/Target Support Files/SwiftMessages"; - sourceTree = "<group>"; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 24E60D8DEFBB230A9FC577B40F10F1CD /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 3508BE5270089E984127E6DA9200D6EB /* SwiftMessages-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 8F9C13EDC0FC0492D8DCB1575B22C8DB /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 7CEBD10BD22E92DCD0B7454A87293DB6 /* Pods-Demo-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 18A7B303EA25F60ED7928C09C7D23D7B /* Pods-Demo */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7676FBFFE6A190CE823040D6E856EED7 /* Build configuration list for PBXNativeTarget "Pods-Demo" */; - buildPhases = ( - 9135C864A18AC99ED68484EC7AD73856 /* Sources */, - ED81D8C9CD17F825987E610677CA67B2 /* Frameworks */, - 8F9C13EDC0FC0492D8DCB1575B22C8DB /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - BA59837BC38C56DBDC6CC9F9AE779265 /* PBXTargetDependency */, - ); - name = "Pods-Demo"; - productName = "Pods-Demo"; - productReference = BFCD7E7BC43700342D2ECDA704620869 /* Pods_Demo.framework */; - productType = "com.apple.product-type.framework"; - }; - 6E57A87EDA4AA3721FA3CEB34CC36F3A /* SwiftMessages */ = { - isa = PBXNativeTarget; - buildConfigurationList = 740976A81ABF41C22FD2F45BFD7C0323 /* Build configuration list for PBXNativeTarget "SwiftMessages" */; - buildPhases = ( - B5520873975FDBC72CCC819CD01EB650 /* Sources */, - 498DB15259537BA06EFE828A427CD8B4 /* Frameworks */, - 73CD7ADB06D858AE793E20D67BBEF205 /* Resources */, - 24E60D8DEFBB230A9FC577B40F10F1CD /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - A8FCCB2ACAFB3C4206FD1BC959C58270 /* PBXTargetDependency */, - ); - name = SwiftMessages; - productName = SwiftMessages; - productReference = 5259A068CBCD8780234A0D70629C1271 /* SwiftMessages.framework */; - productType = "com.apple.product-type.framework"; - }; - 87FAE22F1196DDE6C5E9CF0810E33725 /* SwiftMessages-SwiftMessages */ = { - isa = PBXNativeTarget; - buildConfigurationList = B67C03EDE53862551C4B0A06352CA5F2 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages" */; - buildPhases = ( - E9B652E79625C5A2F503FEDEADA5DF33 /* Sources */, - 8AEDA58AB3CF2CF29D7B8B4CD6725062 /* Frameworks */, - 07DFA5BC61D0562368824F8C765DDC90 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "SwiftMessages-SwiftMessages"; - productName = "SwiftMessages-SwiftMessages"; - productReference = EDA8A9CFB00CA35B42F93F216EB7DA9B /* SwiftMessages.bundle */; - productType = "com.apple.product-type.bundle"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0700; - }; - buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 7DB346D0F39D3F0E887471402A8071AB; - productRefGroup = 1D74C48A5F5DFA0096A4D3FF179106C1 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 18A7B303EA25F60ED7928C09C7D23D7B /* Pods-Demo */, - 6E57A87EDA4AA3721FA3CEB34CC36F3A /* SwiftMessages */, - 87FAE22F1196DDE6C5E9CF0810E33725 /* SwiftMessages-SwiftMessages */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 07DFA5BC61D0562368824F8C765DDC90 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0D01BFD56C1BEA74B1DD7F669383C02E /* CardView.xib in Resources */, - C4F47992FAA181DCA6EA8FBFD5651A21 /* Images.xcassets in Resources */, - 033755DFF1EAA8845C3A4400F7CABD73 /* MessageView.xib in Resources */, - A0BB3AFC78CAEB0955389592B2345BEF /* MessageViewIOS8.xib in Resources */, - 0ECE6B9AA78CD7C4640C3ED1F63C28C0 /* StatusLine.xib in Resources */, - 4E9B81CE7D381F180D054D2D1583B6D2 /* TabView.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 73CD7ADB06D858AE793E20D67BBEF205 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C3BD696FE64625B4EC84D330BF03FC6E /* SwiftMessages.bundle in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 9135C864A18AC99ED68484EC7AD73856 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9BD977BD90B8240559AD9D461E66C814 /* Pods-Demo-dummy.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B5520873975FDBC72CCC819CD01EB650 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 37CE3EEAFCF317B15AF9A9496983E43D /* Array+Utils.swift in Sources */, - B521592325469EC120D284763CE632C8 /* BackgroundViewable.swift in Sources */, - 6B58CA72D169E768CA259C48AAED3AD1 /* BaseView.swift in Sources */, - 4C93067366FED28F560E04E6D497E3F8 /* Error.swift in Sources */, - C375636BF954217E7663BD78163ECC1F /* Identifiable.swift in Sources */, - D2EC6EE885103DECF483741F6272EC48 /* MarginAdjustable.swift in Sources */, - D9F06A51095F1AFE92D70FFB0AFB72B5 /* MessageView.swift in Sources */, - 361B87DFD5711CC17EA526078D6AE7BF /* NSBundle+Utils.swift in Sources */, - D2C2509012B61DEEF0851D49431A8037 /* PassthroughView.swift in Sources */, - 55B1ED48905476533300C59DD70C1204 /* PassthroughWindow.swift in Sources */, - BCC3C8587F2CF0A9B533B67CD039FAF6 /* Presenter.swift in Sources */, - FA1B968C19EDF9104062DB1FF562AA90 /* SwiftMessages-dummy.m in Sources */, - C7C26AB011E621CC61016EA8BB38CFE3 /* SwiftMessages.swift in Sources */, - 623E3DF2F6D0B976C165A00D6EA1D55E /* Theme.swift in Sources */, - 9F63C90369D73BF39DDB112F66EBFE9A /* UIViewController+Utils.swift in Sources */, - B884D515F9A27C2F421B298EC82FACA5 /* WindowViewController.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E9B652E79625C5A2F503FEDEADA5DF33 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - A8FCCB2ACAFB3C4206FD1BC959C58270 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "SwiftMessages-SwiftMessages"; - target = 87FAE22F1196DDE6C5E9CF0810E33725 /* SwiftMessages-SwiftMessages */; - targetProxy = DC9CAF286ADBC369745000328E9F5779 /* PBXContainerItemProxy */; - }; - BA59837BC38C56DBDC6CC9F9AE779265 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = SwiftMessages; - target = 6E57A87EDA4AA3721FA3CEB34CC36F3A /* SwiftMessages */; - targetProxy = 45EF838C81A9FDB837D9733ABAAA0CA6 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 038EF418B52D0441E52F8B539396E4A7 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F08242889B058791110330C1D95B6032 /* SwiftMessages.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/SwiftMessages/SwiftMessages-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SwiftMessages/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/SwiftMessages/SwiftMessages.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = SwiftMessages; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 13E96A645A77DAD1FD4F541F18F5DDBF /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGNING_REQUIRED = NO; - COPY_PHASE_STRIP = NO; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_DEBUG=1", - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; - ONLY_ACTIVE_ARCH = YES; - PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; - STRIP_INSTALLED_PRODUCT = NO; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Debug; - }; - 50382DD1C8323F8B7FC65393FE1CEE2C /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F08242889B058791110330C1D95B6032 /* SwiftMessages.xcconfig */; - buildSettings = { - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SwiftMessages"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - PRODUCT_NAME = SwiftMessages; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; - }; - name = Debug; - }; - 862AF3139CD84E18D34FAF2F43CD0DA6 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGNING_REQUIRED = NO; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_RELEASE=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; - PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; - STRIP_INSTALLED_PRODUCT = NO; - SYMROOT = "${SRCROOT}/../build"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 86F0F6ED2042D8FD70956747E3C780FB /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F08242889B058791110330C1D95B6032 /* SwiftMessages.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/SwiftMessages/SwiftMessages-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SwiftMessages/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/SwiftMessages/SwiftMessages.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = SwiftMessages; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 9E47B28B4C9823162CBB3549A0727181 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = CC6A59B0ADA6CB2F51DAE6508E437829 /* Pods-Demo.debug.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Target Support Files/Pods-Demo/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Demo/Pods-Demo.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = Pods_Demo; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - DD72B4EDFEB88BBCDEFEC1C509D991A7 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = DAB0701F8F25395B1ED46510ED4B9797 /* Pods-Demo.release.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Target Support Files/Pods-Demo/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Demo/Pods-Demo.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = Pods_Demo; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - EE91522C8B14CE7AA0F098A883A5AB84 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F08242889B058791110330C1D95B6032 /* SwiftMessages.xcconfig */; - buildSettings = { - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SwiftMessages"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - PRODUCT_NAME = SwiftMessages; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 13E96A645A77DAD1FD4F541F18F5DDBF /* Debug */, - 862AF3139CD84E18D34FAF2F43CD0DA6 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 740976A81ABF41C22FD2F45BFD7C0323 /* Build configuration list for PBXNativeTarget "SwiftMessages" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 86F0F6ED2042D8FD70956747E3C780FB /* Debug */, - 038EF418B52D0441E52F8B539396E4A7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7676FBFFE6A190CE823040D6E856EED7 /* Build configuration list for PBXNativeTarget "Pods-Demo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9E47B28B4C9823162CBB3549A0727181 /* Debug */, - DD72B4EDFEB88BBCDEFEC1C509D991A7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B67C03EDE53862551C4B0A06352CA5F2 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 50382DD1C8323F8B7FC65393FE1CEE2C /* Debug */, - EE91522C8B14CE7AA0F098A883A5AB84 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; -} diff --git a/Demo/Pods/Pods.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/Pods-Demo.xcscheme b/Demo/Pods/Pods.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/Pods-Demo.xcscheme deleted file mode 100644 index accc84e5..00000000 --- a/Demo/Pods/Pods.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/Pods-Demo.xcscheme +++ /dev/null @@ -1,71 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Scheme - LastUpgradeVersion = "0810" - version = "1.3"> - <BuildAction - parallelizeBuildables = "YES" - buildImplicitDependencies = "YES"> - <BuildActionEntries> - <BuildActionEntry - buildForTesting = "YES" - buildForRunning = "YES" - buildForProfiling = "YES" - buildForArchiving = "YES" - buildForAnalyzing = "YES"> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "18A7B303EA25F60ED7928C09C7D23D7B" - BuildableName = "Pods_Demo.framework" - BlueprintName = "Pods-Demo" - ReferencedContainer = "container:Pods.xcodeproj"> - </BuildableReference> - </BuildActionEntry> - </BuildActionEntries> - </BuildAction> - <TestAction - buildConfiguration = "Debug" - selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" - selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES"> - <Testables> - </Testables> - <AdditionalOptions> - </AdditionalOptions> - </TestAction> - <LaunchAction - buildConfiguration = "Debug" - selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" - selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - launchStyle = "0" - useCustomWorkingDirectory = "NO" - ignoresPersistentStateOnLaunch = "NO" - debugDocumentVersioning = "YES" - debugServiceExtension = "internal" - allowLocationSimulation = "YES"> - <MacroExpansion> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "18A7B303EA25F60ED7928C09C7D23D7B" - BuildableName = "Pods_Demo.framework" - BlueprintName = "Pods-Demo" - ReferencedContainer = "container:Pods.xcodeproj"> - </BuildableReference> - </MacroExpansion> - <AdditionalOptions> - </AdditionalOptions> - </LaunchAction> - <ProfileAction - buildConfiguration = "Release" - shouldUseLaunchSchemeArgsEnv = "YES" - savedToolIdentifier = "" - useCustomWorkingDirectory = "NO" - debugDocumentVersioning = "YES"> - </ProfileAction> - <AnalyzeAction - buildConfiguration = "Debug"> - </AnalyzeAction> - <ArchiveAction - buildConfiguration = "Release" - revealArchiveInOrganizer = "YES"> - </ArchiveAction> -</Scheme> diff --git a/Demo/Pods/Pods.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/SwiftMessages-SwiftMessages.xcscheme b/Demo/Pods/Pods.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/SwiftMessages-SwiftMessages.xcscheme deleted file mode 100644 index 7481df59..00000000 --- a/Demo/Pods/Pods.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/SwiftMessages-SwiftMessages.xcscheme +++ /dev/null @@ -1,71 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Scheme - LastUpgradeVersion = "0810" - version = "1.3"> - <BuildAction - parallelizeBuildables = "YES" - buildImplicitDependencies = "YES"> - <BuildActionEntries> - <BuildActionEntry - buildForTesting = "YES" - buildForRunning = "YES" - buildForProfiling = "YES" - buildForArchiving = "YES" - buildForAnalyzing = "YES"> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "87FAE22F1196DDE6C5E9CF0810E33725" - BuildableName = "SwiftMessages.bundle" - BlueprintName = "SwiftMessages-SwiftMessages" - ReferencedContainer = "container:Pods.xcodeproj"> - </BuildableReference> - </BuildActionEntry> - </BuildActionEntries> - </BuildAction> - <TestAction - buildConfiguration = "Debug" - selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" - selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES"> - <Testables> - </Testables> - <AdditionalOptions> - </AdditionalOptions> - </TestAction> - <LaunchAction - buildConfiguration = "Debug" - selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" - selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - launchStyle = "0" - useCustomWorkingDirectory = "NO" - ignoresPersistentStateOnLaunch = "NO" - debugDocumentVersioning = "YES" - debugServiceExtension = "internal" - allowLocationSimulation = "YES"> - <MacroExpansion> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "87FAE22F1196DDE6C5E9CF0810E33725" - BuildableName = "SwiftMessages.bundle" - BlueprintName = "SwiftMessages-SwiftMessages" - ReferencedContainer = "container:Pods.xcodeproj"> - </BuildableReference> - </MacroExpansion> - <AdditionalOptions> - </AdditionalOptions> - </LaunchAction> - <ProfileAction - buildConfiguration = "Release" - shouldUseLaunchSchemeArgsEnv = "YES" - savedToolIdentifier = "" - useCustomWorkingDirectory = "NO" - debugDocumentVersioning = "YES"> - </ProfileAction> - <AnalyzeAction - buildConfiguration = "Debug"> - </AnalyzeAction> - <ArchiveAction - buildConfiguration = "Release" - revealArchiveInOrganizer = "YES"> - </ArchiveAction> -</Scheme> diff --git a/Demo/Pods/Pods.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/SwiftMessages.xcscheme b/Demo/Pods/Pods.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/SwiftMessages.xcscheme deleted file mode 100644 index 85e5e3c5..00000000 --- a/Demo/Pods/Pods.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/SwiftMessages.xcscheme +++ /dev/null @@ -1,71 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Scheme - LastUpgradeVersion = "0810" - version = "1.3"> - <BuildAction - parallelizeBuildables = "YES" - buildImplicitDependencies = "YES"> - <BuildActionEntries> - <BuildActionEntry - buildForTesting = "YES" - buildForRunning = "YES" - buildForProfiling = "YES" - buildForArchiving = "YES" - buildForAnalyzing = "YES"> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "6E57A87EDA4AA3721FA3CEB34CC36F3A" - BuildableName = "SwiftMessages.framework" - BlueprintName = "SwiftMessages" - ReferencedContainer = "container:Pods.xcodeproj"> - </BuildableReference> - </BuildActionEntry> - </BuildActionEntries> - </BuildAction> - <TestAction - buildConfiguration = "Debug" - selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" - selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES"> - <Testables> - </Testables> - <AdditionalOptions> - </AdditionalOptions> - </TestAction> - <LaunchAction - buildConfiguration = "Debug" - selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" - selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - launchStyle = "0" - useCustomWorkingDirectory = "NO" - ignoresPersistentStateOnLaunch = "NO" - debugDocumentVersioning = "YES" - debugServiceExtension = "internal" - allowLocationSimulation = "YES"> - <MacroExpansion> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "6E57A87EDA4AA3721FA3CEB34CC36F3A" - BuildableName = "SwiftMessages.framework" - BlueprintName = "SwiftMessages" - ReferencedContainer = "container:Pods.xcodeproj"> - </BuildableReference> - </MacroExpansion> - <AdditionalOptions> - </AdditionalOptions> - </LaunchAction> - <ProfileAction - buildConfiguration = "Release" - shouldUseLaunchSchemeArgsEnv = "YES" - savedToolIdentifier = "" - useCustomWorkingDirectory = "NO" - debugDocumentVersioning = "YES"> - </ProfileAction> - <AnalyzeAction - buildConfiguration = "Debug"> - </AnalyzeAction> - <ArchiveAction - buildConfiguration = "Release" - revealArchiveInOrganizer = "YES"> - </ArchiveAction> -</Scheme> diff --git a/Demo/Pods/Pods.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/xcschememanagement.plist b/Demo/Pods/Pods.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 1cd26f79..00000000 --- a/Demo/Pods/Pods.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>SchemeUserState</key> - <dict> - <key>Pods-Demo.xcscheme</key> - <dict> - <key>isShown</key> - <false/> - </dict> - <key>SwiftMessages-SwiftMessages.xcscheme</key> - <dict> - <key>isShown</key> - <false/> - </dict> - <key>SwiftMessages.xcscheme</key> - <dict> - <key>isShown</key> - <false/> - </dict> - </dict> - <key>SuppressBuildableAutocreation</key> - <dict> - <key>18A7B303EA25F60ED7928C09C7D23D7B</key> - <dict> - <key>primary</key> - <true/> - </dict> - <key>6E57A87EDA4AA3721FA3CEB34CC36F3A</key> - <dict> - <key>primary</key> - <true/> - </dict> - <key>87FAE22F1196DDE6C5E9CF0810E33725</key> - <dict> - <key>primary</key> - <true/> - </dict> - </dict> -</dict> -</plist> diff --git a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-dummy.m b/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-dummy.m deleted file mode 100644 index 05b3bfe1..00000000 --- a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import <Foundation/Foundation.h> -@interface PodsDummy_Pods_Demo : NSObject -@end -@implementation PodsDummy_Pods_Demo -@end diff --git a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-frameworks.sh b/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-frameworks.sh deleted file mode 100755 index c187ce22..00000000 --- a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-frameworks.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/sh -set -e - -echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" -mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - -SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" - -install_framework() -{ - if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then - local source="${BUILT_PRODUCTS_DIR}/$1" - elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then - local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" - elif [ -r "$1" ]; then - local source="$1" - fi - - local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - - if [ -L "${source}" ]; then - echo "Symlinked..." - source="$(readlink "${source}")" - fi - - # use filter instead of exclude so missing patterns dont' throw errors - echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" - rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" - - local basename - basename="$(basename -s .framework "$1")" - binary="${destination}/${basename}.framework/${basename}" - if ! [ -r "$binary" ]; then - binary="${destination}/${basename}" - fi - - # Strip invalid architectures so "fat" simulator / device frameworks work on device - if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then - strip_invalid_archs "$binary" - fi - - # Resign the code if required by the build settings to avoid unstable apps - code_sign_if_enabled "${destination}/$(basename "$1")" - - # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. - if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then - local swift_runtime_libs - swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) - for lib in $swift_runtime_libs; do - echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" - rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" - code_sign_if_enabled "${destination}/${lib}" - done - fi -} - -# Signs a framework with the provided identity -code_sign_if_enabled() { - if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then - # Use the current code_sign_identitiy - echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" - echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" - /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" - fi -} - -# Strip invalid architectures -strip_invalid_archs() { - binary="$1" - # Get architectures for current file - archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" - stripped="" - for arch in $archs; do - if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then - # Strip non-valid architectures in-place - lipo -remove "$arch" -output "$binary" "$binary" || exit 1 - stripped="$stripped $arch" - fi - done - if [[ "$stripped" ]]; then - echo "Stripped $binary of architectures:$stripped" - fi -} - - -if [[ "$CONFIGURATION" == "Debug" ]]; then - install_framework "$BUILT_PRODUCTS_DIR/SwiftMessages/SwiftMessages.framework" -fi -if [[ "$CONFIGURATION" == "Release" ]]; then - install_framework "$BUILT_PRODUCTS_DIR/SwiftMessages/SwiftMessages.framework" -fi diff --git a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-resources.sh b/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-resources.sh deleted file mode 100755 index 25e9d377..00000000 --- a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-resources.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/sh -set -e - -mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - -RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt -> "$RESOURCES_TO_COPY" - -XCASSET_FILES=() - -case "${TARGETED_DEVICE_FAMILY}" in - 1,2) - TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" - ;; - 1) - TARGET_DEVICE_ARGS="--target-device iphone" - ;; - 2) - TARGET_DEVICE_ARGS="--target-device ipad" - ;; - *) - TARGET_DEVICE_ARGS="--target-device mac" - ;; -esac - -install_resource() -{ - if [[ "$1" = /* ]] ; then - RESOURCE_PATH="$1" - else - RESOURCE_PATH="${PODS_ROOT}/$1" - fi - if [[ ! -e "$RESOURCE_PATH" ]] ; then - cat << EOM -error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. -EOM - exit 1 - fi - case $RESOURCE_PATH in - *.storyboard) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" - ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} - ;; - *.xib) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" - ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} - ;; - *.framework) - echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - ;; - *.xcdatamodel) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" - xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" - ;; - *.xcdatamodeld) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" - xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" - ;; - *.xcmappingmodel) - echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" - xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" - ;; - *.xcassets) - ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" - XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") - ;; - *) - echo "$RESOURCE_PATH" - echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" - ;; - esac -} - -mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then - mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi -rm -f "$RESOURCES_TO_COPY" - -if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] -then - # Find all other xcassets (this unfortunately includes those of path pods and other targets). - OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) - while read line; do - if [[ $line != "${PODS_ROOT}*" ]]; then - XCASSET_FILES+=("$line") - fi - done <<<"$OTHER_XCASSETS" - - printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi diff --git a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-umbrella.h b/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-umbrella.h deleted file mode 100644 index 354852dc..00000000 --- a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-umbrella.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifdef __OBJC__ -#import <UIKit/UIKit.h> -#endif - - -FOUNDATION_EXPORT double Pods_DemoVersionNumber; -FOUNDATION_EXPORT const unsigned char Pods_DemoVersionString[]; - diff --git a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.debug.xcconfig b/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.debug.xcconfig deleted file mode 100644 index 211c3a5b..00000000 --- a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.debug.xcconfig +++ /dev/null @@ -1,11 +0,0 @@ -ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -EMBEDDED_CONTENT_CONTAINS_SWIFT = YES -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/SwiftMessages" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/SwiftMessages/SwiftMessages.framework/Headers" -OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT}/Pods diff --git a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.modulemap b/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.modulemap deleted file mode 100644 index efe379fb..00000000 --- a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module Pods_Demo { - umbrella header "Pods-Demo-umbrella.h" - - export * - module * { export * } -} diff --git a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.release.xcconfig b/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.release.xcconfig deleted file mode 100644 index 211c3a5b..00000000 --- a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.release.xcconfig +++ /dev/null @@ -1,11 +0,0 @@ -ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -EMBEDDED_CONTENT_CONTAINS_SWIFT = YES -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/SwiftMessages" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/SwiftMessages/SwiftMessages.framework/Headers" -OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT}/Pods diff --git a/Demo/Pods/Target Support Files/SwiftMessages/SwiftMessages-prefix.pch b/Demo/Pods/Target Support Files/SwiftMessages/SwiftMessages-prefix.pch deleted file mode 100644 index aa992a4a..00000000 --- a/Demo/Pods/Target Support Files/SwiftMessages/SwiftMessages-prefix.pch +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef __OBJC__ -#import <UIKit/UIKit.h> -#endif - diff --git a/Demo/Pods/Target Support Files/SwiftMessages/SwiftMessages.xcconfig b/Demo/Pods/Target Support Files/SwiftMessages/SwiftMessages.xcconfig deleted file mode 100644 index f822dcc5..00000000 --- a/Demo/Pods/Target Support Files/SwiftMessages/SwiftMessages.xcconfig +++ /dev/null @@ -1,10 +0,0 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/SwiftMessages -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" -OTHER_LDFLAGS = -framework "UIKit" -OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES diff --git a/Demo/demo.png b/Demo/demo.png index c42a5d5f..1a81dd87 100644 Binary files a/Demo/demo.png and b/Demo/demo.png differ diff --git a/Design/SwiftMessages Demo App Icon.sketch b/Design/SwiftMessages Demo App Icon.sketch new file mode 100644 index 00000000..4c2a27bd Binary files /dev/null and b/Design/SwiftMessages Demo App Icon.sketch differ diff --git a/Design/SwiftMessagesDesign.sketch b/Design/SwiftMessagesDesign.sketch index b9d4b398..6b94b695 100644 Binary files a/Design/SwiftMessagesDesign.sketch and b/Design/SwiftMessagesDesign.sketch differ diff --git a/Design/SwiftMessagesSegue.gif b/Design/SwiftMessagesSegue.gif new file mode 100644 index 00000000..473c92cd Binary files /dev/null and b/Design/SwiftMessagesSegue.gif differ diff --git a/Design/SwiftMessagesSegueCreate.png b/Design/SwiftMessagesSegueCreate.png new file mode 100644 index 00000000..bc4d1653 Binary files /dev/null and b/Design/SwiftMessagesSegueCreate.png differ diff --git a/Design/swiftmessages.png b/Design/swiftmessages.png new file mode 100644 index 00000000..e979fa48 Binary files /dev/null and b/Design/swiftmessages.png differ diff --git a/Package.swift b/Package.swift new file mode 100644 index 00000000..a906ba1a --- /dev/null +++ b/Package.swift @@ -0,0 +1,23 @@ +// swift-tools-version:5.3 +import PackageDescription + +let package = Package( + name: "SwiftMessages", + platforms: [ + .iOS("13.0") + ], + products: [ + .library(name: "SwiftMessages", targets: ["SwiftMessages"]), + .library(name: "SwiftMessages-Dynamic", type: .dynamic, targets: ["SwiftMessages"]) + ], + targets: [ + .target( + name: "SwiftMessages", + path: "SwiftMessages", + exclude: [ + "Info.plist", + ], + resources: [.process("Resources")] + ) + ] +) diff --git a/README.md b/README.md index f7bd1c15..abec2f0e 100644 --- a/README.md +++ b/README.md @@ -6,58 +6,59 @@ [](http://cocoadocs.org/docsets/SwiftMessages) [](https://github.com/Carthage/Carthage) -SwiftMessages is a message bar library for iOS. It's very flexible. And written in Swift. +<p align="center"> + <img src="./Design/swiftmessages.png" /> +</p> + +## Overview + +🔥🔥🔥 **NEW** SwiftUI support added! + +SwiftMessages is a very flexible view and view controller presentation library for UIKit and SwiftUI. -Message bars can be displayed across the top or bottom of the screen, over or under the status bar, or behind navigation bars and tab bars. There's an interactive dismiss gesture. You can dim the background if you like. And much more! +Message views and view controllers can be displayed at the top, bottom, or center of the screen, or behind navigation bars and tab bars. There are interactive dismiss gestures including a fun, physics-based one. Multiple background dimming modes. And a lot more! -In addition to numerous configuration options, SwiftMessages provides several attractive layouts and themes. But SwiftMessages was also built to be designer-friendly, which means you can fully and easily customize the view: +In addition to the numerous configuration options, SwiftMessages provides several good-looking layouts and themes. But SwiftMessages is also designer-friendly, which means you can fully and easily customize the view: * Copy one of the included nib files into your project and change it. * Subclass `MessageView` and add elements, etc. -* Or just supply an arbitrary instance of `UIView`. - -Try exploring [the demo app via appetize.io](http://goo.gl/KXw4nD) to get a feel for the extensive configurability of SwiftMessages. +* Or just supply an arbitrary instance of `View` or `UIView`. <p align="center"> <img src="./Demo/demo.png" /> </p> -<p align="center"> - <a href="http://goo.gl/KXw4nD"><img src="./Demo/appetize.png" /></a> -</p> - ## Installation +### Swift Package Manager + +Go to `File | Swift Packages | Add Package Dependency...` in Xcode and search for "SwiftMessages". If multiple results are found, select the one owned by SwiftKick Mobile. + ### CocoaPods -Add one of the following lines to your Podfile depending on your Swift version: +Add the following line to your Podfile: ````ruby -# Swift 3.0 - Xcode 8 pod 'SwiftMessages' - -# Swift 2.3 - Xcode 8 -pod 'SwiftMessages', '~> 2.0.0' - -# Swift 2.2 - Xcode 7.3.1 -pod 'SwiftMessages', '~> 1.1.4' ```` -__Note that Swift 2.3 and Swift 3.0 require minimum CocoaPods version 1.1.0__. ### Carthage -Add one of the following lines to your Cartfile depending on your Swift version: +Add the following line to your Cartfile: ````ruby -# Swift 3.0 - Xcode 8 github "SwiftKickMobile/SwiftMessages" +```` -# Swift 2.3 - Xcode 8 -github "SwiftKickMobile/SwiftMessages" ~> 2.0.0 +If the Carthage build fails, [try using the script](https://github.com/Carthage/Carthage/issues/3019). -# Swift 2.2 - Xcode 7.3.1 -github "SwiftKickMobile/SwiftMessages" ~> 1.1.4 -```` +### Manual + +1. Put SwiftMessages repo somewhere in your project directory. +1. In Xcode, add `SwiftMessages.xcodeproj` to your project. +1. On your app's target, add the SwiftMessages framework: + 1. as an embedded binary on the General tab. + 1. as a target dependency on the Build Phases tab. ## Usage @@ -73,19 +74,26 @@ and assortment of nib-based layouts that should handle most cases: ````swift // Instantiate a message view from the provided card view layout. SwiftMessages searches for nib // files in the main bundle first, so you can easily copy them into your project and make changes. -let view = MessageView.viewFromNib(layout: .CardView) +let view = MessageView.viewFromNib(layout: .cardView) // Theme message elements with the warning style. -view.configureTheme(.Warning) +view.configureTheme(.warning) // Add a drop shadow. view.configureDropShadow() // Set message title, body, and icon. Here, we're overriding the default warning // image with an emoji character. -let iconText = ["🤔", "😳", "🙄", "😶"].sm_random()! +let iconText = ["🤔", "😳", "🙄", "😶"].randomElement()! view.configureContent(title: "Warning", body: "Consider yourself warned.", iconText: iconText) +// Increase the external margin around the card. In general, the effect of this setting +// depends on how the given layout is constrained to the layout margins. +view.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) + +// Reduce the corner radius (applicable to layouts featuring rounded corners). +(view.backgroundView as? CornerRoundingView)?.cornerRadius = 10 + // Show the message. SwiftMessages.show(view: view) ```` @@ -95,7 +103,7 @@ your UIKit code is executed on the main queue: ````swift SwiftMessages.show { - let view = MessageView.viewFromNib(layout: .CardView) + let view = MessageView.viewFromNib(layout: .cardView) // ... configure the view return view } @@ -107,27 +115,35 @@ The `SwiftMessages.Config` struct provides numerous configuration options that c var config = SwiftMessages.Config() // Slide up from the bottom. -config.presentationStyle = .Bottom +config.presentationStyle = .bottom -// Display in a window at the specified window level: UIWindowLevelStatusBar -// displays over the status bar while UIWindowLevelNormal displays under. -config.presentationContext = .Window(windowLevel: UIWindowLevelStatusBar) +// Display in a window at the specified window level. +config.presentationContext = .window(windowLevel: .statusBar) + +Note that, as of iOS 13, it is no longer possible to cover the status bar +regardless of the window level. A workaround is to hide the status bar instead. +config.prefersStatusBarHidden = true // Disable the default auto-hiding behavior. -config.duration = .Forever +config.duration = .forever // Dim the background like a popover view. Hide when the background is tapped. -config.dimMode = .Gray(interactive: true) +config.dimMode = .gray(interactive: true) // Disable the interactive pan-to-hide gesture. config.interactiveHide = false +// Specify haptic feedback (see also MessageView/configureTheme) +config.haptic = .success + // Specify a status bar style to if the message is displayed directly under the status bar. -config.preferredStatusBarStyle = .LightContent +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) @@ -136,63 +152,155 @@ SwiftMessages.show(config: config, view: view) Specify default configuration options: ````swift -SwiftMessages.defaultConfig.presentationStyle = .Bottom +SwiftMessages.defaultConfig.presentationStyle = .bottom // Show message with default config. SwiftMessages.show(view: view) // Customize config using the default as a base. var config = SwiftMessages.defaultConfig -config.duration = .Forever +config.duration = .forever SwiftMessages.show(config: config, view: view) ```` -### Customization +### View Controllers -`MessageView` provides the following UI elements, exposed as public, optional `@IBOutlets`: +SwiftMessages can present view controllers using the `SwiftMessagesSegue` custom modal segue! -* __Title__ (`UILabel`) -* __Message body__ (`UILabel`) -* __Image Icon__ (`UIImageView`) -* __Text Icon__ (`UILabel`) -* __Button__ (`UIButton`) +<p align="center"> + <img src="./Design/SwiftMessagesSegue.gif" /> +</p> -Because they are optional, you can freely omit the ones you don't need. +[`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. -**The easiest way to customize `MessageView` is to drag-and-drop one of the pre-defined nib files into your project and make changes.** SwiftMessages always searches the main bundle for nib files first, so it is not necessary to rename the file or make a different API call. However, there are some OS-specific considerations to be aware of: +#### [View Controllers Readme](./ViewControllers.md) -* **iOS 9+** When using one of the `UIStackView` layouts, MessageView.nib, CardView.nib or TabView.nib, as a starting point, you can simply delete elements from the nib file or hide them — no need to adjust the Auto Layout constraints. -* **iOS 8** When using MessageViewIOS8.nib, you'll delete the unwanted elements and fix up the Auto Layout constraints. Or just create your own nib from scratch, which is much like creating a custom `UITableViewCell` or `UICollectionViewCell` — set the base view's class to `MessageView` or whatever subclass or view class you're using and wire up the outlets. +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`. -To facilitate the use of nib-based layouts, `MessageView` provides some type-safe convenience methods for loading the pre-defined nibs: +### 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. + +Take the following message view and companion data model: ````swift -// Instantiate MessageView from one of the provided nibs in a type-safe way. -// SwiftMessages searches the main bundle first, so you easily copy the nib into -// your project and modify it while still using this type-safe call. -let view = MessageView.viewFromNib(layout: .CardView) +struct DemoMessage: Identifiable { + let title: String + let body: String + + var id: String { title + body } +} + +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) + // 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. + .mask( + UnevenRoundedRectangle(bottomLeadingRadius: 15, bottomTrailingRadius: 15) + // This causes the background to extend into the safe area to the screen edge. + .edgesIgnoringSafeArea(.top) + ) + } +} ```` -In addition, the `SwiftMessages` class provides some generic loading methods: +You can show it from a button action, view model or other similar context like: ````swift -// Instantiate MessageView from a named nib. -let view: MessageView = try! SwiftMessages.viewFromNib(named: "MyCustomNib") +struct DemoView: View { + var body: some View { + Button("Show message") { + let message = DemoMessage(title: "Demo", body: "SwiftUI forever!") + let messageView = MessageHostingView(id: message.id, content: DemoMessageView(message: message) + SwiftMessages.show(view: messageView) + } + } +} +```` -// Instantiate MyCustomView from a nib named MyCustomView.nib. -let view: MyCustomView = try! SwiftMessages.viewFromNib() +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) { message in + DemoMessageView(message: message) + } + } +} ```` -`MessageView` provides an optional block-based tap handler for the button and another for the view itself: +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 -// Hide when button tapped -messageView.buttonTapHandler = { _ in SwiftMessages.hide() } +extension DemoMessage: MessageViewConvertible { + func asMessageView() -> DemoMessageView { + DemoMessageView(message: self) + } +} +```` -// Hide when message view tapped -messageView.tapHandler = { _ in SwiftMessages.hide() } +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! + +### Accessibility + +SwiftMessages provides excellent VoiceOver support out-of-the-box. + +* The title and body of the message are combined into a single announcement when the message is shown. The `MessageView.accessibilityPrefix` property can be set to prepend additional clarifying text to the announcement. + + Sometimes, a message may contain important visual cues that aren't captured in the title or body. For example, a message may rely on a yellow background to convey a warning rather than having the word "warning" in the title or body. In this case, it might be helpful to set `MessageView.accessibilityPrefix = "warning"`. + +* If the message is shown with a dim view using `config.dimMode`, elements below the dim view are not focusable until the message is hidden. If `config.dimMode.interactive == true`, the dim view itself will be focusable and read out "dismiss" followed by "button". The former text can be customized by setting the `config.dimModeAccessibilityLabel` property. + +See the `AccessibleMessage` protocol for implementing proper accessibility support in custom views. + +### Keyboard Avoidance + +The `KeyboardTrackingView` class can be used to cause the message view to avoid the keyboard by sliding up when the keyboard gets too close. + +````swift +var config = SwiftMessages.defaultConfig +config.keyboardTrackingView = KeyboardTrackingView() +```` + +You can incorporate `KeyboardTrackingView` into your app even when you're not using SwiftMessages. Install into your view hierarchy by pinning `KeyboardTrackingView` to the bottom, leading, and trailing edges of the screen. Then pin the bottom of your content that should avoid the keyboard to the top `KeyboardTrackingView`. Use an equality constraint to strictly track the keyboard or an inequality constraint to only move when the keyboard gets too close. `KeyboardTrackingView` works by observing keyboard notifications and adjusting its height to maintain its top edge above the keyboard, thereby pushing your content up. See the comments in `KeyboardTrackingView` for configuration options. + ### Message Queueing You can call `SwiftMessages.show()` as many times as you like. SwiftMessages maintains a queue and shows messages one at a time. If your view implements the `Identifiable` protocol (like `MessageView`), duplicate messages will be removed automatically. The pause between messages can be adjusted: @@ -212,18 +320,167 @@ SwiftMessages.hideAll() // Or for a view that implements `Identifiable`: SwiftMessages.hide(id: someId) + +// Or hide when the number of calls to show() and hideCounted(id:) for a +// given message ID are equal. This can be useful for messages that may be +// shown from multiple code paths to ensure that all paths are ready to hide. +SwiftMessages.hideCounted(id: someId) +```` + +Multiple instances of `SwiftMessages` can be used to show more than one message at a time. Note that the static `SwiftMessages.show()` and other static APIs on `SwiftMessage` are just convenience wrappers around the shared instance `SwiftMessages.sharedInstance`). Instances must be retained, thus it should be a property of something (e.g. your view controller): + +````swift +class SomeViewController: UIViewController { + let otherMessages = SwiftMessages() + + func someMethod() { + SwiftMessages.show(...) + otherMessages.show(...) + } +} +```` + +### Retrieving Messages + +There are several APIs available for retrieving messages that are currently being shown, hidden, or queued to be shown. These APIs are useful for updating messages +when some event happens without needing to keep temporary references around. +See also `eventListeners`. + +````swift +// Get a message view with the given ID if it is currently +// being shown or hidden. +if let view = SwiftMessages.current(id: "some id") { ... } + +// Get a message view with the given ID if is it currently +// queued to be shown. +if let view = SwiftMessages.queued(id: "some id") { ... } + +// Get a message view with the given ID if it is currently being +// shown, hidden or in the queue to be shown. +if let view = SwiftMessages.currentOrQueued(id: "some id") { ... } +```` + +### Customization + +SwiftMessages can display any `UIView`. However, there are varying degrees of customization that can be done to the bundled views. + +#### Nib Files + +All of the message designs bundled with SwiftMessages have associated nib files. You are encouraged to copy any of these nib files into your project and modify them to suit your needs. SwiftMessages will load your copy of the file instead of the original. Nib files may be copied in Xcode using drag-and-drop. + +To facilitate the use of nib-based layouts, `MessageView` provides some type-safe convenience methods for loading the bundled nibs: + +````swift +let view = MessageView.viewFromNib(layout: .cardView) +```` + +In addition, the `SwiftMessages` class provides some generic loading methods: + +````swift +// Instantiate MessageView from a named nib. +let view: MessageView = try! SwiftMessages.viewFromNib(named: "MyCustomNib") + +// Instantiate MyCustomView from a nib named MyCustomView.nib. +let view: MyCustomView = try! SwiftMessages.viewFromNib() +```` + +#### MessageView Class + + +[`MessageView`](./SwiftMessages/MessageView.swift) is a light-weight view that all of the bundled designs use. It primarily consists of the following optional `@IBOutlet` properties: + +Element | Declaration | Description +--------|-----------|----- +Title | `titleLabel: UILabel?` | The message title. +Message body | `bodyLabel: UILabel?` | The body of the message. +Image icon | `iconImageView: UIImageView?` | An image-based icon. +Text icon | `iconLabel: UILabel?` | A text-based (emoji) alternative to the image icon. +Button | `button: UIButton?` | An action button. + +The SwiftMessages nib file use `MessageView` as the top-level view with content connected to these outlets. The layouts are done using stack views, which means that you can remove an element by simply hiding it: + +````swift +view.titleLabel.isHidden = true ```` -Multiple instances of `SwiftMessages` can be used to show more than one message at a time. Note that the static `SwiftMessages.show()` and other static APIs on `SwiftMessage` are just convenience wrappers around the shared instance `SwiftMessages.sharedInstance`): +A common mistake is attempting to remove an element by setting the corresponding outlet to `nil`. This does not work because it does not remove the element from the view hierarchy. + +#### Configuration + +`MessageView` provides numerous methods that follow the `configure*` naming convention: + +````swift +view.configureTheme(.warning, includeHaptic: true) +view.configureContent(title: "Warning", body: "Consider yourself warned.", iconText: "🤔") +```` + +All of these methods are shortcuts for quickly configuring the underlying view properties. SwiftMessages strives to avoid doing any internal magic in these methods, so you do not need to call them. You can configure the view properties directly or combine the two approaches. + +#### Interaction + +`MessageView` provides an optional block-based tap handler for the button and another for the view itself: ````swift -let otherMessages = SwiftMessages() -SwiftMessages.show(...) -otherMessages.show(...) +// Hide when button tapped +messageView.buttonTapHandler = { _ in SwiftMessages.hide() } + +// Hide when message view tapped +messageView.tapHandler = { _ in SwiftMessages.hide() } ```` +#### Extending + +The suggested method for starting with `MessageView` as a base and __adding new elements__, such as additional buttons, is as follows: + + 1. Copy one of the bundled nib files into your project or create a new one from scratch. + 1. Add new elements to the nib file. + 1. Sublcass `MessageView` and create outlets for the new elements. + 1. Assign the top-level view in the nib file to the subclass. + 1. Connect outlets between the nib file and the subclass. + 1. (recommended) override the implementation of `Identifiable` as needed to incorporate new elements into the message's identity. + 1. (recommended) override the implementation of `AccessibleMessage` as needed to incorporate new elements into Voice Over. + 1. Use one of the nib-loading methods above to load the view. + +#### BaseView Class + +[`BaseView`](./SwiftMessages/BaseView.swift) is the superclass of `MessageView` and provides numerous options that aren't specific to the "title + body + icon + button" design of `MessageView`. Custom views that are significantly different from `MessageView`, such as a progress indicator, should subclass `BaseView`. + +#### CornerRoundingView Class + +[`CornerRoundingView`](./SwiftMessages/CornerRoundingView.swift) is a custom view that messages can use for rounding all or a subset of corners with squircles (the smoother method of rounding corners that you see on app icons). The nib files that feature rounded corners have `backgroundView` assigned to a `CornerRoundingView`. It provides a `roundsLeadingCorners` option to dynamically round only the leading corners of the view when presented from top or bottom (a feature used for the tab-style layouts). + +#### Animator Protocol + +[`Animator`](./SwiftMessages/Animator.swift) is the protocol that SwiftMessages uses for presentation and dismissal animations. Custom animations can be done through the `SwiftMessages.PresentationStyle.custom(animator:)`. Some related components: +* [`TopBottomAnimation`](./SwiftMessages/TopBottomAnimation.swift) is a sliding implementation of `Animator` used internally by `.top` and `.bottom` presentation styles. It provides some customization options. +* [`PhysicsAnimation`](./SwiftMessages/PhysicsAnimation.swift) is a scaling + opacity implementation of `Animator` used internally by the `.center` presentation style. It provides a fun physics-based dismissal gesture and provides customization options including `.top` and `.bottom` placement. +* [`PhysicsPanHandler`](./SwiftMessages/PhysicsPanHandler.swift) provides the physics-based dismissal gesture for `PhysicsAnimation` and can be incorporated into other `Animator` implementations. + +High-quality PRs for cool `Animator` implementations are welcome! + +#### MarginAdjustable Protocol + +[`MarginAdjustable`](./SwiftMessages/MarginAdjustable.swift) is a protocol adopted by `BaseView`. If the view being presented adopts `MarginAdjustable`, SwiftMessages takes ownership of the view's layout margins to ensure ideal spacing across the full range of presentation contexts. + +#### BackgroundViewable Protocol + +[`BackgroundViewable`](./SwiftMessages/BackgroundViewable.swift) is a protocol adopted by `BaseView` and requires that a view provide a single `backgroundView` property. `BaseView` initializes `backgroundView = self`, which you can freely re-assign to any subview. + +If the view being presented adopts `BackgroundViewable`, SwiftMessages will ignore touches outside of `backgroundView`. This is important because message views always span the full width of the device. Card and tab-style layouts appear inset from the edges of the device because the message view's background is transparent and `backgroundView` is assigned to a subview constrained to the layout margins. In these layouts, touches in the transparent margins should be ignored. + +#### Identifiable Protocol + +[`Identifiable`](./SwiftMessages/Identifiable.swift) is a protocol adopted by `MessageView` and requires that a view provide a single `id` property, which SwiftMessages uses for message deduplication. + +`MessageView` computes the `id` based on the message content, but `id` can also be set explicitly as needed. + +#### AccessibleMessage Protocol + +[`AccessibleMessage`](./SwiftMessages/AccessibleMessage.swift) is a protocol adopted by `MessageView`. If the view being presented adopts `AccessibleMessage`, SwiftMessages provides improved Voice Over. + + ## About SwiftKick Mobile -We make apps real nice! [Get in touch](mailto:tim@swiftkick.it) if you need one. +We build high quality apps! [Get in touch](http://www.swiftkickmobile.com) if you need help with a project. ## License diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 6073cdaa..0500d4ac 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,15 +1,32 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '3.1.1' + spec.version = '10.0.1' 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 => '3.1.1'} - spec.platform = :ios, '8.0' - spec.ios.deployment_target = '8.0' - spec.source_files = 'SwiftMessages/**/*.swift' - spec.resource_bundles = {'SwiftMessages' => ['SwiftMessages/Resources/**/*']} + spec.source = {:git => 'https://github.com/SwiftKickMobile/SwiftMessages.git', :tag => spec.version} + spec.platform = :ios, '13.0' + spec.swift_version = '5.0' + spec.ios.deployment_target = '13.0' spec.framework = 'UIKit' spec.requires_arc = true + spec.default_subspec = 'App' + + spec.subspec 'App' do |app| + app.source_files = 'SwiftMessages/**/*.swift' + app.resource_bundles = {'SwiftMessages' => ['SwiftMessages/Resources/*.*']} + end + + spec.subspec 'AppExtension' do |ext| + ext.source_files = 'SwiftMessages/**/*.swift' + ext.exclude_files = 'SwiftMessages/**/SegueConvenienceClasses.swift' + ext.resource_bundles = {'SwiftMessages_SwiftMessages' => ['SwiftMessages/Resources/**/*.*']} + + # For app extensions, disabling code paths using unavailable API + ext.pod_target_xcconfig = { + 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => 'SWIFTMESSAGES_APP_EXTENSIONS', + 'GCC_PREPROCESSOR_DEFINITIONS' => 'SWIFTMESSAGES_APP_EXTENSIONS=1' + } + end end diff --git a/SwiftMessages.xcodeproj/project.pbxproj b/SwiftMessages.xcodeproj/project.pbxproj index f9c14afe..10384827 100644 --- a/SwiftMessages.xcodeproj/project.pbxproj +++ b/SwiftMessages.xcodeproj/project.pbxproj @@ -3,10 +3,72 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 54; 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 */; }; + 223DE69D2C29E50C000161E5 /* MessageGeometryProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 223DE69C2C29E50B000161E5 /* MessageGeometryProxy.swift */; }; + 224C3C902C28A2F900B50B18 /* TopBottomPresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224C3C8F2C28A2F900B50B18 /* TopBottomPresentable.swift */; }; + 224C3C932C28BC4900B50B18 /* TopBottomAnimationStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224C3C922C28BC4400B50B18 /* TopBottomAnimationStyle.swift */; }; + 224FB69921153B440081D4DE /* CALayer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224FB69821153B440081D4DE /* CALayer+Extensions.swift */; }; + 225304622290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225304612290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift */; }; + 225304662293000C00A03ACF /* KeyboardTrackingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225304652293000C00A03ACF /* KeyboardTrackingView.swift */; }; + 2270044B1FAFA6DD0045DDC3 /* PhysicsAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2270044A1FAFA6DD0045DDC3 /* PhysicsAnimation.swift */; }; + 22774BA020B5EF2A00813732 /* UIEdgeInsets+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */; }; + 227BA6D920BF224A00E5A843 /* SwiftMessagesSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 227BA6D820BF224A00E5A843 /* SwiftMessagesSegue.swift */; }; + 228DF5261FACAC51004F8A39 /* errorIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5231FACAC51004F8A39 /* errorIcon.png */; }; + 228DF5271FACAC51004F8A39 /* errorIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5241FACAC51004F8A39 /* errorIcon@2x.png */; }; + 228DF5281FACAC51004F8A39 /* errorIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5251FACAC51004F8A39 /* errorIcon@3x.png */; }; + 228DF54A1FAD0806004F8A39 /* successIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5291FAD0802004F8A39 /* successIconLight@3x.png */; }; + 228DF54B1FAD0806004F8A39 /* warningIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF52A1FAD0802004F8A39 /* warningIconLight.png */; }; + 228DF54C1FAD0806004F8A39 /* errorIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF52B1FAD0802004F8A39 /* errorIconLight.png */; }; + 228DF54D1FAD0806004F8A39 /* infoIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF52C1FAD0803004F8A39 /* infoIcon@2x.png */; }; + 228DF54E1FAD0806004F8A39 /* warningIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF52D1FAD0803004F8A39 /* warningIconSubtle.png */; }; + 228DF54F1FAD0806004F8A39 /* successIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF52E1FAD0803004F8A39 /* successIconSubtle@3x.png */; }; + 228DF5501FAD0806004F8A39 /* infoIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF52F1FAD0803004F8A39 /* infoIcon.png */; }; + 228DF5511FAD0806004F8A39 /* infoIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5301FAD0803004F8A39 /* infoIconLight@2x.png */; }; + 228DF5521FAD0806004F8A39 /* successIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5311FAD0803004F8A39 /* successIcon.png */; }; + 228DF5531FAD0806004F8A39 /* successIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5321FAD0803004F8A39 /* successIcon@2x.png */; }; + 228DF5541FAD0806004F8A39 /* successIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5331FAD0803004F8A39 /* successIcon@3x.png */; }; + 228DF5551FAD0806004F8A39 /* warningIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5341FAD0803004F8A39 /* warningIcon@2x.png */; }; + 228DF5561FAD0806004F8A39 /* successIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5351FAD0803004F8A39 /* successIconSubtle.png */; }; + 228DF5571FAD0806004F8A39 /* warningIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5361FAD0803004F8A39 /* warningIconSubtle@2x.png */; }; + 228DF5581FAD0806004F8A39 /* errorIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5371FAD0803004F8A39 /* errorIconSubtle.png */; }; + 228DF5591FAD0806004F8A39 /* successIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5381FAD0803004F8A39 /* successIconSubtle@2x.png */; }; + 228DF55A1FAD0806004F8A39 /* errorIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5391FAD0804004F8A39 /* errorIconLight@3x.png */; }; + 228DF55B1FAD0806004F8A39 /* warningIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF53A1FAD0804004F8A39 /* warningIconLight@3x.png */; }; + 228DF55C1FAD0806004F8A39 /* warningIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF53B1FAD0804004F8A39 /* warningIcon.png */; }; + 228DF55D1FAD0806004F8A39 /* warningIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF53C1FAD0804004F8A39 /* warningIconLight@2x.png */; }; + 228DF55E1FAD0806004F8A39 /* warningIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF53D1FAD0804004F8A39 /* warningIconSubtle@3x.png */; }; + 228DF55F1FAD0806004F8A39 /* errorIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF53E1FAD0804004F8A39 /* errorIconLight@2x.png */; }; + 228DF5601FAD0806004F8A39 /* warningIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF53F1FAD0804004F8A39 /* warningIcon@3x.png */; }; + 228DF5611FAD0806004F8A39 /* infoIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5401FAD0804004F8A39 /* infoIcon@3x.png */; }; + 228DF5621FAD0806004F8A39 /* infoIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5411FAD0804004F8A39 /* infoIconLight.png */; }; + 228DF5631FAD0806004F8A39 /* infoIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5421FAD0804004F8A39 /* infoIconSubtle@2x.png */; }; + 228DF5641FAD0806004F8A39 /* errorIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5431FAD0805004F8A39 /* errorIconSubtle@2x.png */; }; + 228DF5651FAD0806004F8A39 /* successIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5441FAD0805004F8A39 /* successIconLight@2x.png */; }; + 228DF5661FAD0806004F8A39 /* errorIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5451FAD0805004F8A39 /* errorIconSubtle@3x.png */; }; + 228DF5671FAD0806004F8A39 /* infoIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 228DF5461FAD0805004F8A39 /* infoIconLight@3x.png */; }; + 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 */; }; + 22982C172B6030B000852311 /* HapticMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22982C162B6030B000852311 /* HapticMessage.swift */; }; + 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2041EE47DC900E2DDC1 /* Weak.swift */; }; + 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2061EE480D000E2DDC1 /* Animator.swift */; }; + 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */; }; + 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 */; }; + 22E307FF1E74C5B100E35893 /* AccessibleMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22E307FE1E74C5B100E35893 /* AccessibleMessage.swift */; }; + 22F27951210CE25900273E7F /* CornerRoundingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22F27950210CE25900273E7F /* CornerRoundingView.swift */; }; 86589D471D64B6E40041676C /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86589D461D64B6E40041676C /* BaseView.swift */; }; 86589D911D692B1C0041676C /* TabView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 86589D901D692B1B0041676C /* TabView.xib */; }; 867BED211D622793005212E3 /* BackgroundViewable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 867BED201D622793005212E3 /* BackgroundViewable.swift */; }; @@ -20,17 +82,14 @@ 86BBA9001D5E040600FE8F16 /* PassthroughView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AAF8171D54F0650031EE32 /* PassthroughView.swift */; }; 86BBA9011D5E040600FE8F16 /* PassthroughWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AAF8191D54F0850031EE32 /* PassthroughWindow.swift */; }; 86BBA9021D5E040600FE8F16 /* WindowViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8644955C1D4FAF7C0056EB2A /* WindowViewController.swift */; }; - 86BBA9031D5E040600FE8F16 /* UIViewController+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AAF81B1D551FE60031EE32 /* UIViewController+Utils.swift */; }; - 86BBA9041D5E040600FE8F16 /* NSBundle+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 862C0CB01D5911C100D06168 /* NSBundle+Utils.swift */; }; + 86BBA9031D5E040600FE8F16 /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AAF81B1D551FE60031EE32 /* UIViewController+Extensions.swift */; }; + 86BBA9041D5E040600FE8F16 /* NSBundle+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 862C0CB01D5911C100D06168 /* NSBundle+Extensions.swift */; }; 86BBA9051D5E040C00FE8F16 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AAF82C1D580F410031EE32 /* Theme.swift */; }; 86BBA9061D5E040C00FE8F16 /* Identifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 864495551D4F7C390056EB2A /* Identifiable.swift */; }; 86BBA9071D5E040C00FE8F16 /* MarginAdjustable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AAF81D1D5549680031EE32 /* MarginAdjustable.swift */; }; 86BBA9081D5E040C00FE8F16 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86AAF82A1D580DD70031EE32 /* Error.swift */; }; - 86DBE0041D75BE800071E51D /* Array+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86DBE0031D75BE800071E51D /* Array+Utils.swift */; }; E6E49F911D70A344006CB883 /* MessageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 862C0CDA1D5A397F00D06168 /* MessageView.xib */; }; E6E49F921D70A349006CB883 /* StatusLine.xib in Resources */ = {isa = PBXBuildFile; fileRef = 862C0CDB1D5A397F00D06168 /* StatusLine.xib */; }; - E6E49F931D70A34C006CB883 /* MessageViewIOS8.xib in Resources */ = {isa = PBXBuildFile; fileRef = 862C0CE21D5A3A0D00D06168 /* MessageViewIOS8.xib */; }; - E6E49F941D70A395006CB883 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 862C0CD91D5A397F00D06168 /* Images.xcassets */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -44,12 +103,73 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 862C0C6A1D58E93300D06168 /* SwiftMessages.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; path = SwiftMessages.podspec; sourceTree = SOURCE_ROOT; }; - 862C0CB01D5911C100D06168 /* NSBundle+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSBundle+Utils.swift"; sourceTree = "<group>"; }; - 862C0CD91D5A397F00D06168 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Resources/Images.xcassets; sourceTree = "<group>"; }; + 0797E40D26EE12B400691606 /* WindowScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowScene.swift; sourceTree = "<group>"; }; + 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarginAdjustable+Extensions.swift"; sourceTree = "<group>"; }; + 220D386D2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftMessages.Config+Extensions.swift"; sourceTree = "<group>"; }; + 223DE69C2C29E50B000161E5 /* MessageGeometryProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageGeometryProxy.swift; sourceTree = "<group>"; }; + 224C3C8F2C28A2F900B50B18 /* TopBottomPresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopBottomPresentable.swift; sourceTree = "<group>"; }; + 224C3C922C28BC4400B50B18 /* TopBottomAnimationStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopBottomAnimationStyle.swift; sourceTree = "<group>"; }; + 224FB69821153B440081D4DE /* CALayer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CALayer+Extensions.swift"; sourceTree = "<group>"; }; + 225304612290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraint+Extensions.swift"; sourceTree = "<group>"; }; + 225304652293000C00A03ACF /* KeyboardTrackingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardTrackingView.swift; sourceTree = "<group>"; }; + 2270044A1FAFA6DD0045DDC3 /* PhysicsAnimation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhysicsAnimation.swift; sourceTree = "<group>"; }; + 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIEdgeInsets+Extensions.swift"; sourceTree = "<group>"; }; + 227BA6D820BF224A00E5A843 /* SwiftMessagesSegue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftMessagesSegue.swift; sourceTree = "<group>"; }; + 228DF5231FACAC51004F8A39 /* errorIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = errorIcon.png; path = Resources/errorIcon.png; sourceTree = "<group>"; }; + 228DF5241FACAC51004F8A39 /* errorIcon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "errorIcon@2x.png"; path = "Resources/errorIcon@2x.png"; sourceTree = "<group>"; }; + 228DF5251FACAC51004F8A39 /* errorIcon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "errorIcon@3x.png"; path = "Resources/errorIcon@3x.png"; sourceTree = "<group>"; }; + 228DF5291FAD0802004F8A39 /* successIconLight@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "successIconLight@3x.png"; path = "Resources/successIconLight@3x.png"; sourceTree = "<group>"; }; + 228DF52A1FAD0802004F8A39 /* warningIconLight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = warningIconLight.png; path = Resources/warningIconLight.png; sourceTree = "<group>"; }; + 228DF52B1FAD0802004F8A39 /* errorIconLight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = errorIconLight.png; path = Resources/errorIconLight.png; sourceTree = "<group>"; }; + 228DF52C1FAD0803004F8A39 /* infoIcon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIcon@2x.png"; path = "Resources/infoIcon@2x.png"; sourceTree = "<group>"; }; + 228DF52D1FAD0803004F8A39 /* warningIconSubtle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = warningIconSubtle.png; path = Resources/warningIconSubtle.png; sourceTree = "<group>"; }; + 228DF52E1FAD0803004F8A39 /* successIconSubtle@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "successIconSubtle@3x.png"; path = "Resources/successIconSubtle@3x.png"; sourceTree = "<group>"; }; + 228DF52F1FAD0803004F8A39 /* infoIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = infoIcon.png; path = Resources/infoIcon.png; sourceTree = "<group>"; }; + 228DF5301FAD0803004F8A39 /* infoIconLight@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIconLight@2x.png"; path = "Resources/infoIconLight@2x.png"; sourceTree = "<group>"; }; + 228DF5311FAD0803004F8A39 /* successIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = successIcon.png; path = Resources/successIcon.png; sourceTree = "<group>"; }; + 228DF5321FAD0803004F8A39 /* successIcon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "successIcon@2x.png"; path = "Resources/successIcon@2x.png"; sourceTree = "<group>"; }; + 228DF5331FAD0803004F8A39 /* successIcon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "successIcon@3x.png"; path = "Resources/successIcon@3x.png"; sourceTree = "<group>"; }; + 228DF5341FAD0803004F8A39 /* warningIcon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "warningIcon@2x.png"; path = "Resources/warningIcon@2x.png"; sourceTree = "<group>"; }; + 228DF5351FAD0803004F8A39 /* successIconSubtle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = successIconSubtle.png; path = Resources/successIconSubtle.png; sourceTree = "<group>"; }; + 228DF5361FAD0803004F8A39 /* warningIconSubtle@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "warningIconSubtle@2x.png"; path = "Resources/warningIconSubtle@2x.png"; sourceTree = "<group>"; }; + 228DF5371FAD0803004F8A39 /* errorIconSubtle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = errorIconSubtle.png; path = Resources/errorIconSubtle.png; sourceTree = "<group>"; }; + 228DF5381FAD0803004F8A39 /* successIconSubtle@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "successIconSubtle@2x.png"; path = "Resources/successIconSubtle@2x.png"; sourceTree = "<group>"; }; + 228DF5391FAD0804004F8A39 /* errorIconLight@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "errorIconLight@3x.png"; path = "Resources/errorIconLight@3x.png"; sourceTree = "<group>"; }; + 228DF53A1FAD0804004F8A39 /* warningIconLight@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "warningIconLight@3x.png"; path = "Resources/warningIconLight@3x.png"; sourceTree = "<group>"; }; + 228DF53B1FAD0804004F8A39 /* warningIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = warningIcon.png; path = Resources/warningIcon.png; sourceTree = "<group>"; }; + 228DF53C1FAD0804004F8A39 /* warningIconLight@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "warningIconLight@2x.png"; path = "Resources/warningIconLight@2x.png"; sourceTree = "<group>"; }; + 228DF53D1FAD0804004F8A39 /* warningIconSubtle@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "warningIconSubtle@3x.png"; path = "Resources/warningIconSubtle@3x.png"; sourceTree = "<group>"; }; + 228DF53E1FAD0804004F8A39 /* errorIconLight@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "errorIconLight@2x.png"; path = "Resources/errorIconLight@2x.png"; sourceTree = "<group>"; }; + 228DF53F1FAD0804004F8A39 /* warningIcon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "warningIcon@3x.png"; path = "Resources/warningIcon@3x.png"; sourceTree = "<group>"; }; + 228DF5401FAD0804004F8A39 /* infoIcon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIcon@3x.png"; path = "Resources/infoIcon@3x.png"; sourceTree = "<group>"; }; + 228DF5411FAD0804004F8A39 /* infoIconLight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = infoIconLight.png; path = Resources/infoIconLight.png; sourceTree = "<group>"; }; + 228DF5421FAD0804004F8A39 /* infoIconSubtle@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIconSubtle@2x.png"; path = "Resources/infoIconSubtle@2x.png"; sourceTree = "<group>"; }; + 228DF5431FAD0805004F8A39 /* errorIconSubtle@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "errorIconSubtle@2x.png"; path = "Resources/errorIconSubtle@2x.png"; sourceTree = "<group>"; }; + 228DF5441FAD0805004F8A39 /* successIconLight@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "successIconLight@2x.png"; path = "Resources/successIconLight@2x.png"; sourceTree = "<group>"; }; + 228DF5451FAD0805004F8A39 /* errorIconSubtle@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "errorIconSubtle@3x.png"; path = "Resources/errorIconSubtle@3x.png"; sourceTree = "<group>"; }; + 228DF5461FAD0805004F8A39 /* infoIconLight@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIconLight@3x.png"; path = "Resources/infoIconLight@3x.png"; sourceTree = "<group>"; }; + 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = infoIconSubtle.png; path = Resources/infoIconSubtle.png; sourceTree = "<group>"; }; + 228DF5481FAD0805004F8A39 /* successIconLight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = successIconLight.png; path = Resources/successIconLight.png; sourceTree = "<group>"; }; + 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; + 228F7DDB2ACF7039006C9644 /* MessageHostingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageHostingView.swift; sourceTree = "<group>"; }; + 228F7DDC2ACF703A006C9644 /* SwiftMessageModifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftMessageModifier.swift; sourceTree = "<group>"; }; + 228F7DDD2ACF703A006C9644 /* MessageViewConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageViewConvertible.swift; sourceTree = "<group>"; }; + 22982C162B6030B000852311 /* HapticMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HapticMessage.swift; sourceTree = "<group>"; }; + 2298C2041EE47DC900E2DDC1 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; }; + 2298C2061EE480D000E2DDC1 /* Animator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animator.swift; sourceTree = "<group>"; }; + 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBottomAnimation.swift; sourceTree = "<group>"; }; + 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+Extensions.swift"; sourceTree = "<group>"; }; + 22A2EA6E24EC6CFA00BB2540 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; }; + 22D3B4552B1CEF76002D8665 /* Task+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Task+Extensions.swift"; sourceTree = "<group>"; }; + 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = CenteredView.xib; path = Resources/CenteredView.xib; sourceTree = "<group>"; }; + 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsPanHandler.swift; sourceTree = "<group>"; }; + 22E01F631E74EC8B00ACE19A /* MaskingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaskingView.swift; sourceTree = "<group>"; }; + 22E307FE1E74C5B100E35893 /* AccessibleMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessibleMessage.swift; sourceTree = "<group>"; }; + 22F27950210CE25900273E7F /* CornerRoundingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerRoundingView.swift; sourceTree = "<group>"; }; + 862C0C6A1D58E93300D06168 /* SwiftMessages.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; path = SwiftMessages.podspec; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 862C0CB01D5911C100D06168 /* NSBundle+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSBundle+Extensions.swift"; sourceTree = "<group>"; }; 862C0CDA1D5A397F00D06168 /* MessageView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MessageView.xib; path = Resources/MessageView.xib; sourceTree = "<group>"; }; 862C0CDB1D5A397F00D06168 /* StatusLine.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = StatusLine.xib; path = Resources/StatusLine.xib; sourceTree = "<group>"; }; - 862C0CE21D5A3A0D00D06168 /* MessageViewIOS8.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MessageViewIOS8.xib; path = Resources/MessageViewIOS8.xib; sourceTree = "<group>"; }; 864495551D4F7C390056EB2A /* Identifiable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Identifiable.swift; sourceTree = "<group>"; }; 864495581D4FA0AD0056EB2A /* SwiftMessages.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftMessages.swift; sourceTree = "<group>"; }; 8644955C1D4FAF7C0056EB2A /* WindowViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowViewController.swift; sourceTree = "<group>"; }; @@ -60,7 +180,7 @@ 867E21931D4D50BB00594A41 /* Presenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Presenter.swift; sourceTree = "<group>"; }; 86AAF8171D54F0650031EE32 /* PassthroughView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassthroughView.swift; sourceTree = "<group>"; }; 86AAF8191D54F0850031EE32 /* PassthroughWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassthroughWindow.swift; sourceTree = "<group>"; }; - 86AAF81B1D551FE60031EE32 /* UIViewController+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Utils.swift"; sourceTree = "<group>"; }; + 86AAF81B1D551FE60031EE32 /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extensions.swift"; sourceTree = "<group>"; }; 86AAF81D1D5549680031EE32 /* MarginAdjustable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarginAdjustable.swift; sourceTree = "<group>"; }; 86AAF82A1D580DD70031EE32 /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; }; 86AAF82C1D580F410031EE32 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; }; @@ -71,7 +191,6 @@ 86B48AFA1D5A41C900063E2B /* SwiftMessagesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftMessagesTests.swift; sourceTree = "<group>"; }; 86B48AFC1D5A41C900063E2B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 86BBA8F81D5E01FC00FE8F16 /* CardView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = CardView.xib; path = Resources/CardView.xib; sourceTree = "<group>"; }; - 86DBE0031D75BE800071E51D /* Array+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Array+Utils.swift"; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -93,15 +212,109 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 220D38672597A94C00BB2B88 /* Extensions */ = { + isa = PBXGroup; + children = ( + 224FB69821153B440081D4DE /* CALayer+Extensions.swift */, + 862C0CB01D5911C100D06168 /* NSBundle+Extensions.swift */, + 86AAF81B1D551FE60031EE32 /* UIViewController+Extensions.swift */, + 225304612290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift */, + 220D386D2597AA5B00BB2B88 /* SwiftMessages.Config+Extensions.swift */, + ); + name = Extensions; + sourceTree = "<group>"; + }; + 220D38682597A9FD00BB2B88 /* Extensions */ = { + isa = PBXGroup; + children = ( + 220655111FAF82B600F4E00F /* MarginAdjustable+Extensions.swift */, + 22774B9F20B5EF2A00813732 /* UIEdgeInsets+Extensions.swift */, + 229F778025FAB1E9008C2ACB /* UIWindow+Extensions.swift */, + 22D3B4552B1CEF76002D8665 /* Task+Extensions.swift */, + ); + name = Extensions; + sourceTree = "<group>"; + }; + 2244656C1EF1D62700C50413 /* Animations */ = { + isa = PBXGroup; + children = ( + 2298C2081EE486E300E2DDC1 /* TopBottomAnimation.swift */, + 2270044A1FAFA6DD0045DDC3 /* PhysicsAnimation.swift */, + 22DFC9171F00674E001B1CA1 /* PhysicsPanHandler.swift */, + ); + name = Animations; + sourceTree = "<group>"; + }; + 224FB6C8211651D10081D4DE /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = "<group>"; + }; + 228F7DDA2ACF7029006C9644 /* SwiftUI */ = { + isa = PBXGroup; + children = ( + 223DE69C2C29E50B000161E5 /* MessageGeometryProxy.swift */, + 228F7DDB2ACF7039006C9644 /* MessageHostingView.swift */, + 228F7DDD2ACF703A006C9644 /* MessageViewConvertible.swift */, + 228F7DDC2ACF703A006C9644 /* SwiftMessageModifier.swift */, + ); + name = SwiftUI; + sourceTree = "<group>"; + }; + 22D4779B20BF1C54005D0D71 /* View Controllers */ = { + isa = PBXGroup; + children = ( + 227BA6D820BF224A00E5A843 /* SwiftMessagesSegue.swift */, + ); + name = "View Controllers"; + sourceTree = "<group>"; + }; 862C0CD81D5A396900D06168 /* Resources */ = { isa = PBXGroup; children = ( - 862C0CD91D5A397F00D06168 /* Images.xcassets */, 862C0CDA1D5A397F00D06168 /* MessageView.xib */, 86BBA8F81D5E01FC00FE8F16 /* CardView.xib */, 86589D901D692B1B0041676C /* TabView.xib */, 862C0CDB1D5A397F00D06168 /* StatusLine.xib */, - 862C0CE21D5A3A0D00D06168 /* MessageViewIOS8.xib */, + 22DFC9151EFF30F6001B1CA1 /* CenteredView.xib */, + 228DF52B1FAD0802004F8A39 /* errorIconLight.png */, + 228DF53E1FAD0804004F8A39 /* errorIconLight@2x.png */, + 228DF5391FAD0804004F8A39 /* errorIconLight@3x.png */, + 228DF5371FAD0803004F8A39 /* errorIconSubtle.png */, + 228DF5431FAD0805004F8A39 /* errorIconSubtle@2x.png */, + 228DF5451FAD0805004F8A39 /* errorIconSubtle@3x.png */, + 228DF52F1FAD0803004F8A39 /* infoIcon.png */, + 228DF52C1FAD0803004F8A39 /* infoIcon@2x.png */, + 228DF5401FAD0804004F8A39 /* infoIcon@3x.png */, + 228DF5411FAD0804004F8A39 /* infoIconLight.png */, + 228DF5301FAD0803004F8A39 /* infoIconLight@2x.png */, + 228DF5461FAD0805004F8A39 /* infoIconLight@3x.png */, + 228DF5471FAD0805004F8A39 /* infoIconSubtle.png */, + 228DF5421FAD0804004F8A39 /* infoIconSubtle@2x.png */, + 228DF5491FAD0805004F8A39 /* infoIconSubtle@3x.png */, + 228DF5311FAD0803004F8A39 /* successIcon.png */, + 228DF5321FAD0803004F8A39 /* successIcon@2x.png */, + 228DF5331FAD0803004F8A39 /* successIcon@3x.png */, + 228DF5481FAD0805004F8A39 /* successIconLight.png */, + 228DF5441FAD0805004F8A39 /* successIconLight@2x.png */, + 228DF5291FAD0802004F8A39 /* successIconLight@3x.png */, + 228DF5351FAD0803004F8A39 /* successIconSubtle.png */, + 228DF5381FAD0803004F8A39 /* successIconSubtle@2x.png */, + 228DF52E1FAD0803004F8A39 /* successIconSubtle@3x.png */, + 228DF53B1FAD0804004F8A39 /* warningIcon.png */, + 228DF5341FAD0803004F8A39 /* warningIcon@2x.png */, + 228DF53F1FAD0804004F8A39 /* warningIcon@3x.png */, + 228DF52A1FAD0802004F8A39 /* warningIconLight.png */, + 228DF53C1FAD0804004F8A39 /* warningIconLight@2x.png */, + 228DF53A1FAD0804004F8A39 /* warningIconLight@3x.png */, + 228DF52D1FAD0803004F8A39 /* warningIconSubtle.png */, + 228DF5361FAD0803004F8A39 /* warningIconSubtle@2x.png */, + 228DF53D1FAD0804004F8A39 /* warningIconSubtle@3x.png */, + 228DF5231FACAC51004F8A39 /* errorIcon.png */, + 228DF5241FACAC51004F8A39 /* errorIcon@2x.png */, + 228DF5251FACAC51004F8A39 /* errorIcon@3x.png */, ); name = Resources; sourceTree = "<group>"; @@ -109,13 +322,22 @@ 864495571D4F7C490056EB2A /* Base */ = { isa = PBXGroup; children = ( - 86589D461D64B6E40041676C /* BaseView.swift */, - 86AAF82C1D580F410031EE32 /* Theme.swift */, + 22E307FE1E74C5B100E35893 /* AccessibleMessage.swift */, + 2298C2061EE480D000E2DDC1 /* Animator.swift */, 867BED201D622793005212E3 /* BackgroundViewable.swift */, + 86589D461D64B6E40041676C /* BaseView.swift */, + 22F27950210CE25900273E7F /* CornerRoundingView.swift */, + 86AAF82A1D580DD70031EE32 /* Error.swift */, + 22982C162B6030B000852311 /* HapticMessage.swift */, 864495551D4F7C390056EB2A /* Identifiable.swift */, + 225304652293000C00A03ACF /* KeyboardTrackingView.swift */, 86AAF81D1D5549680031EE32 /* MarginAdjustable.swift */, - 86AAF82A1D580DD70031EE32 /* Error.swift */, - 86DBE0031D75BE800071E51D /* Array+Utils.swift */, + 86AAF82C1D580F410031EE32 /* Theme.swift */, + 224C3C922C28BC4400B50B18 /* TopBottomAnimationStyle.swift */, + 224C3C8F2C28A2F900B50B18 /* TopBottomPresentable.swift */, + 2298C2041EE47DC900E2DDC1 /* Weak.swift */, + 0797E40D26EE12B400691606 /* WindowScene.swift */, + 8644955C1D4FAF7C0056EB2A /* WindowViewController.swift */, ); name = Base; sourceTree = "<group>"; @@ -126,6 +348,9 @@ 86B48AED1D5A41C900063E2B /* SwiftMessages */, 86B48AF91D5A41C900063E2B /* SwiftMessagesTests */, 867E21501D4D01D500594A41 /* Products */, + 224FB6C8211651D10081D4DE /* Frameworks */, + 22A2EA6E24EC6CFA00BB2540 /* Package.swift */, + 862C0C6A1D58E93300D06168 /* SwiftMessages.podspec */, ); sourceTree = "<group>"; }; @@ -143,10 +368,9 @@ children = ( 867E21931D4D50BB00594A41 /* Presenter.swift */, 86AAF8171D54F0650031EE32 /* PassthroughView.swift */, + 22E01F631E74EC8B00ACE19A /* MaskingView.swift */, 86AAF8191D54F0850031EE32 /* PassthroughWindow.swift */, - 8644955C1D4FAF7C0056EB2A /* WindowViewController.swift */, - 86AAF81B1D551FE60031EE32 /* UIViewController+Utils.swift */, - 862C0CB01D5911C100D06168 /* NSBundle+Utils.swift */, + 220D38672597A94C00BB2B88 /* Extensions */, ); name = Internal; sourceTree = "<group>"; @@ -157,7 +381,11 @@ 864495581D4FA0AD0056EB2A /* SwiftMessages.swift */, 867E21821D4D025200594A41 /* MessageView.swift */, 862C0CD81D5A396900D06168 /* Resources */, + 2244656C1EF1D62700C50413 /* Animations */, + 22D4779B20BF1C54005D0D71 /* View Controllers */, + 228F7DDA2ACF7029006C9644 /* SwiftUI */, 864495571D4F7C490056EB2A /* Base */, + 220D38682597A9FD00BB2B88 /* Extensions */, 867E218E1D4D3DFD00594A41 /* Internal */, 86B48B031D5A41E500063E2B /* Support */, ); @@ -176,7 +404,6 @@ 86B48B031D5A41E500063E2B /* Support */ = { isa = PBXGroup; children = ( - 862C0C6A1D58E93300D06168 /* SwiftMessages.podspec */, 86B48AEE1D5A41C900063E2B /* SwiftMessages.h */, 86B48AF01D5A41C900063E2B /* Info.plist */, ); @@ -239,24 +466,25 @@ 867E21471D4D01D500594A41 /* Project object */ = { isa = PBXProject; attributes = { + BuildIndependentTargetsInParallel = YES; LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = "SwiftKick Mobile"; TargetAttributes = { 86B48AEB1D5A41C900063E2B = { CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 0800; + LastSwiftMigration = 1020; ProvisioningStyle = Automatic; }; 86B48AF41D5A41C900063E2B = { CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 0800; + LastSwiftMigration = 0900; }; }; }; buildConfigurationList = 867E214A1D4D01D500594A41 /* Build configuration list for PBXProject "SwiftMessages" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -278,12 +506,47 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - E6E49F931D70A34C006CB883 /* MessageViewIOS8.xib in Resources */, + 228DF5581FAD0806004F8A39 /* errorIconSubtle.png in Resources */, + 228DF55C1FAD0806004F8A39 /* warningIcon.png in Resources */, + 228DF5521FAD0806004F8A39 /* successIcon.png in Resources */, + 228DF5531FAD0806004F8A39 /* successIcon@2x.png in Resources */, + 228DF54C1FAD0806004F8A39 /* errorIconLight.png in Resources */, + 228DF55B1FAD0806004F8A39 /* warningIconLight@3x.png in Resources */, + 228DF5571FAD0806004F8A39 /* warningIconSubtle@2x.png in Resources */, + 228DF5651FAD0806004F8A39 /* successIconLight@2x.png in Resources */, + 228DF5671FAD0806004F8A39 /* infoIconLight@3x.png in Resources */, E6E49F911D70A344006CB883 /* MessageView.xib in Resources */, + 228DF5551FAD0806004F8A39 /* warningIcon@2x.png in Resources */, + 228DF5661FAD0806004F8A39 /* errorIconSubtle@3x.png in Resources */, + 228DF5511FAD0806004F8A39 /* infoIconLight@2x.png in Resources */, + 228DF5611FAD0806004F8A39 /* infoIcon@3x.png in Resources */, + 228DF54A1FAD0806004F8A39 /* successIconLight@3x.png in Resources */, + 228DF5271FACAC51004F8A39 /* errorIcon@2x.png in Resources */, + 228DF55D1FAD0806004F8A39 /* warningIconLight@2x.png in Resources */, + 228DF5501FAD0806004F8A39 /* infoIcon.png in Resources */, + 228DF54E1FAD0806004F8A39 /* warningIconSubtle.png in Resources */, + 228DF5601FAD0806004F8A39 /* warningIcon@3x.png in Resources */, + 228DF5641FAD0806004F8A39 /* errorIconSubtle@2x.png in Resources */, + 228DF55F1FAD0806004F8A39 /* errorIconLight@2x.png in Resources */, + 228DF55A1FAD0806004F8A39 /* errorIconLight@3x.png in Resources */, + 228DF5631FAD0806004F8A39 /* infoIconSubtle@2x.png in Resources */, 86BBA8F91D5E01FC00FE8F16 /* CardView.xib in Resources */, - E6E49F941D70A395006CB883 /* Images.xcassets in Resources */, + 228DF5681FAD0806004F8A39 /* infoIconSubtle.png in Resources */, + 228DF54F1FAD0806004F8A39 /* successIconSubtle@3x.png in Resources */, + 228DF56A1FAD0806004F8A39 /* infoIconSubtle@3x.png in Resources */, + 228DF5261FACAC51004F8A39 /* errorIcon.png in Resources */, + 228DF5691FAD0806004F8A39 /* successIconLight.png in Resources */, 86589D911D692B1C0041676C /* TabView.xib in Resources */, + 228DF5621FAD0806004F8A39 /* infoIconLight.png in Resources */, + 228DF55E1FAD0806004F8A39 /* warningIconSubtle@3x.png in Resources */, + 228DF5591FAD0806004F8A39 /* successIconSubtle@2x.png in Resources */, E6E49F921D70A349006CB883 /* StatusLine.xib in Resources */, + 228DF5561FAD0806004F8A39 /* successIconSubtle.png in Resources */, + 228DF5541FAD0806004F8A39 /* successIcon@3x.png in Resources */, + 228DF54B1FAD0806004F8A39 /* warningIconLight.png in Resources */, + 228DF54D1FAD0806004F8A39 /* infoIcon@2x.png in Resources */, + 22DFC9161EFF30F6001B1CA1 /* CenteredView.xib in Resources */, + 228DF5281FACAC51004F8A39 /* errorIcon@3x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -301,21 +564,45 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 225304662293000C00A03ACF /* KeyboardTrackingView.swift in Sources */, + 22774BA020B5EF2A00813732 /* UIEdgeInsets+Extensions.swift in Sources */, 86BBA8FC1D5E03F100FE8F16 /* MessageView.swift in Sources */, 86BBA9061D5E040C00FE8F16 /* Identifiable.swift in Sources */, + 22F27951210CE25900273E7F /* CornerRoundingView.swift in Sources */, 86BBA9011D5E040600FE8F16 /* PassthroughWindow.swift in Sources */, - 86BBA9031D5E040600FE8F16 /* UIViewController+Utils.swift in Sources */, + 2298C2071EE480D000E2DDC1 /* Animator.swift in Sources */, + 22D3B4562B1CEF76002D8665 /* Task+Extensions.swift in Sources */, + 22982C172B6030B000852311 /* HapticMessage.swift in Sources */, + 86BBA9031D5E040600FE8F16 /* UIViewController+Extensions.swift in Sources */, + 228F7DDF2ACF703A006C9644 /* SwiftMessageModifier.swift in Sources */, + 224FB69921153B440081D4DE /* CALayer+Extensions.swift in Sources */, + 22E01F641E74EC8B00ACE19A /* MaskingView.swift in Sources */, + 224C3C932C28BC4900B50B18 /* TopBottomAnimationStyle.swift in Sources */, + 2298C2051EE47DC900E2DDC1 /* Weak.swift in Sources */, + 228F7DE02ACF703A006C9644 /* MessageViewConvertible.swift in Sources */, 86BBA9001D5E040600FE8F16 /* PassthroughView.swift in Sources */, - 86BBA9041D5E040600FE8F16 /* NSBundle+Utils.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 */, + 224C3C902C28A2F900B50B18 /* TopBottomPresentable.swift in Sources */, + 86BBA9041D5E040600FE8F16 /* NSBundle+Extensions.swift in Sources */, 86BBA8FD1D5E03F800FE8F16 /* SwiftMessages.swift in Sources */, 86BBA9021D5E040600FE8F16 /* WindowViewController.swift in Sources */, + 229F778125FAB1E9008C2ACB /* UIWindow+Extensions.swift in Sources */, 86BBA8FF1D5E040600FE8F16 /* Presenter.swift in Sources */, 86BBA9051D5E040C00FE8F16 /* Theme.swift in Sources */, 86BBA9081D5E040C00FE8F16 /* Error.swift in Sources */, + 2298C2091EE486E300E2DDC1 /* TopBottomAnimation.swift in Sources */, 86589D471D64B6E40041676C /* BaseView.swift in Sources */, + 0797E40E26EE12B400691606 /* WindowScene.swift in Sources */, + 225304622290C76E00A03ACF /* NSLayoutConstraint+Extensions.swift in Sources */, + 223DE69D2C29E50C000161E5 /* MessageGeometryProxy.swift in Sources */, 86BBA9071D5E040C00FE8F16 /* MarginAdjustable.swift in Sources */, 867BED211D622793005212E3 /* BackgroundViewable.swift in Sources */, - 86DBE0041D75BE800071E51D /* Array+Utils.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -342,19 +629,30 @@ 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"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = 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_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_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -363,6 +661,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; @@ -377,7 +676,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -390,19 +689,30 @@ 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"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = 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_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_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -411,6 +721,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; @@ -419,10 +730,11 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.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; }; @@ -432,23 +744,34 @@ 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"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.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; + SWIFT_INSTALL_OBJC_HEADER = NO; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WARNING_CFLAGS = ""; }; name = Debug; }; @@ -456,22 +779,33 @@ 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"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.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; - SWIFT_VERSION = 3.0; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WARNING_CFLAGS = ""; }; name = Release; }; @@ -479,10 +813,15 @@ 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_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -490,10 +829,15 @@ 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_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/SwiftMessages.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SwiftMessages.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/SwiftMessages.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEDidComputeMac32BitWarning</key> + <true/> +</dict> +</plist> diff --git a/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme b/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme index f87415e3..ba0f414b 100644 --- a/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme +++ b/SwiftMessages.xcodeproj/xcshareddata/xcschemes/SwiftMessages.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0800" + LastUpgradeVersion = "1510" version = "1.3"> <BuildAction parallelizeBuildables = "YES" @@ -49,17 +49,6 @@ </BuildableReference> </TestableReference> </Testables> - <MacroExpansion> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "86B48AEB1D5A41C900063E2B" - BuildableName = "SwiftMessages.framework" - BlueprintName = "SwiftMessages" - ReferencedContainer = "container:SwiftMessages.xcodeproj"> - </BuildableReference> - </MacroExpansion> - <AdditionalOptions> - </AdditionalOptions> </TestAction> <LaunchAction buildConfiguration = "Debug" @@ -81,8 +70,6 @@ ReferencedContainer = "container:SwiftMessages.xcodeproj"> </BuildableReference> </BuildableProductRunnable> - <AdditionalOptions> - </AdditionalOptions> </LaunchAction> <ProfileAction buildConfiguration = "Release" diff --git a/SwiftMessages.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/SwiftMessages.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist deleted file mode 100644 index fe2b4541..00000000 --- a/SwiftMessages.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Bucket - type = "1" - version = "2.0"> -</Bucket> diff --git a/SwiftMessages.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/xcschememanagement.plist b/SwiftMessages.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index f4d4e831..00000000 --- a/SwiftMessages.xcodeproj/xcuserdata/wtmoose.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>SchemeUserState</key> - <dict> - <key>SwiftMessages.xcscheme_^#shared#^_</key> - <dict> - <key>orderHint</key> - <integer>0</integer> - </dict> - </dict> - <key>SuppressBuildableAutocreation</key> - <dict> - <key>867E214E1D4D01D500594A41</key> - <dict> - <key>primary</key> - <true/> - </dict> - <key>867E21621D4D01D500594A41</key> - <dict> - <key>primary</key> - <true/> - </dict> - <key>867E216D1D4D01D500594A41</key> - <dict> - <key>primary</key> - <true/> - </dict> - <key>86B48AEB1D5A41C900063E2B</key> - <dict> - <key>primary</key> - <true/> - </dict> - <key>86B48AF41D5A41C900063E2B</key> - <dict> - <key>primary</key> - <true/> - </dict> - </dict> -</dict> -</plist> diff --git a/SwiftMessages/AccessibleMessage.swift b/SwiftMessages/AccessibleMessage.swift new file mode 100644 index 00000000..71590aa0 --- /dev/null +++ b/SwiftMessages/AccessibleMessage.swift @@ -0,0 +1,19 @@ +// +// AccessibleMessage.swift +// SwiftMessages +// +// Created by Timothy Moose on 3/11/17. +// Copyright © 2017 SwiftKick Mobile. All rights reserved. +// + +import Foundation + +/** + Message views that conform to `AccessibleMessage` will have proper accessibility behavior when displaying messages. + `MessageView` implements this protocol. + */ +public protocol AccessibleMessage { + var accessibilityMessage: String? { get } + var accessibilityElement: NSObject? { get } + var additionalAccessibilityElements: [NSObject]? { get } +} diff --git a/SwiftMessages/Animator.swift b/SwiftMessages/Animator.swift new file mode 100644 index 00000000..c79d0f0e --- /dev/null +++ b/SwiftMessages/Animator.swift @@ -0,0 +1,80 @@ +// +// Animator.swift +// SwiftMessages +// +// Created by Timothy Moose on 6/4/17. +// Copyright © 2017 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +public typealias AnimationCompletion = (_ completed: Bool) -> Void + +@MainActor +public protocol AnimationDelegate: AnyObject { + func hide(animator: Animator) + func panStarted(animator: Animator) + func panEnded(animator: Animator) +} + +/** + An option set representing the known types of safe area conflicts + that could require margin adjustments on the message view in order to + get the layouts to look right. + */ +public struct SafeZoneConflicts: OptionSet { + public let rawValue: Int + + public init(rawValue: Int) { + self.rawValue = rawValue + } + + /// Message view behind status bar + public static let statusBar = SafeZoneConflicts(rawValue: 1 << 0) + + /// Message view behind the sensor notch on iPhone X + public static let sensorNotch = SafeZoneConflicts(rawValue: 1 << 1) + + /// Message view behind home indicator on iPhone X + public static let homeIndicator = SafeZoneConflicts(rawValue: 1 << 2) + + /// Message view is over the status bar on an iPhone 8 or lower. This is a special + /// case because we logically expect the top safe area to be zero, but it is reported as 20 + /// (which seems like an iOS bug). We use the `overStatusBar` to indicate this special case. + public static let overStatusBar = SafeZoneConflicts(rawValue: 1 << 3) +} + +public class AnimationContext { + + public let messageView: UIView + public let containerView: UIView + public let safeZoneConflicts: SafeZoneConflicts + public let interactiveHide: Bool + + init(messageView: UIView, containerView: UIView, safeZoneConflicts: SafeZoneConflicts, interactiveHide: Bool) { + self.messageView = messageView + self.containerView = containerView + self.safeZoneConflicts = safeZoneConflicts + self.interactiveHide = interactiveHide + } +} + +@MainActor +public protocol Animator: AnyObject { + + /// Adopting classes should declare as `weak`. + var delegate: AnimationDelegate? { get set } + + func show(context: AnimationContext, completion: @escaping AnimationCompletion) + + func hide(context: AnimationContext, completion: @escaping AnimationCompletion) + + /// The show animation duration. If the animation duration is unknown, such as if using `UIDynamicAnimator`, + /// then provide an estimate. This value is used by `SwiftMessagesSegue`. + var showDuration: TimeInterval { get } + + /// The hide animation duration. If the animation duration is unknown, such as if using `UIDynamicAnimator`, + /// then provide an estimate. This value is used by `SwiftMessagesSegue`. + var hideDuration: TimeInterval { get } +} + diff --git a/SwiftMessages/Array+Utils.swift b/SwiftMessages/Array+Utils.swift deleted file mode 100644 index 5e728257..00000000 --- a/SwiftMessages/Array+Utils.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// Array+Utils.swift -// SwiftMessages -// -// Created by Tim Moose on 8/30/16. -// Copyright © 2016 SwiftKick Mobile. All rights reserved. -// - -import Darwin - -public extension Array { - - /** - Returns a random element from the array. Can be used to create a playful - message that cycles randomly through a set of emoji icons, for example. - */ - public func sm_random() -> Iterator.Element? { - guard count > 0 else { return nil } - return self[Int(arc4random_uniform(UInt32(count)))] - } -} diff --git a/SwiftMessages/BaseView.swift b/SwiftMessages/BaseView.swift index 471f3e5a..c41d166b 100644 --- a/SwiftMessages/BaseView.swift +++ b/SwiftMessages/BaseView.swift @@ -9,34 +9,35 @@ import UIKit -/* +/** The `BaseView` class is a reusable message view base class that implements some of the optional SwiftMessages protocols and provides some convenience functions and a configurable tap handler. Message views do not need to inherit from `BaseVew`. */ open class BaseView: UIView, BackgroundViewable, MarginAdjustable { - + /* MARK: - IB outlets */ - + /** Fulfills the `BackgroundViewable` protocol and is the target for the optional `tapHandler` block. Defaults to `self`. */ - @IBOutlet open var backgroundView: UIView! { + @IBOutlet open weak var backgroundView: UIView! { didSet { if let old = oldValue { old.removeGestureRecognizer(tapRecognizer) } installTapRecognizer() + updateBackgroundHeightConstraint() } } - + // The `contentView` property was removed because it no longer had any functionality // in the framework. This is a minor backwards incompatible change. If you've copied // one of the included nib files from a previous release, you may get a key-value - // coding runtime error related to contentView, in which case you can subclass the + // coding runtime error related to contentView, in which case you can subclass the // view and add a `contentView` property or you can remove the outlet connection in // Interface Builder. // @IBOutlet public var contentView: UIView! @@ -44,29 +45,27 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable { /* MARK: - Initialization */ - - public required init?(coder aDecoder: NSCoder) { + + public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) backgroundView = self + layoutMargins = UIEdgeInsets.zero } - + public override init(frame: CGRect) { super.init(frame: frame) backgroundView = self - } - - open override func awakeFromNib() { layoutMargins = UIEdgeInsets.zero } /* - MARK: - Installing content + MARK: - Installing background and content */ - + /** A convenience function for installing a content view as a subview of `backgroundView` and pinning the edges to `backgroundView` with the specified `insets`. - + - Parameter contentView: The view to be installed into the background view and assigned to the `contentView` property. - Parameter insets: The amount to inset the content view from the background view. @@ -75,17 +74,84 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable { open func installContentView(_ contentView: UIView, insets: UIEdgeInsets = UIEdgeInsets.zero) { contentView.translatesAutoresizingMaskIntoConstraints = false backgroundView.addSubview(contentView) - let top = NSLayoutConstraint(item: contentView, attribute: .top, relatedBy: .equal, toItem: backgroundView, attribute: .topMargin, multiplier: 1.0, constant: insets.top) - let left = NSLayoutConstraint(item: contentView, attribute: .left, relatedBy: .equal, toItem: backgroundView, attribute: .leftMargin, multiplier: 1.0, constant: insets.left) - let bottom = NSLayoutConstraint(item: contentView, attribute: .bottom, relatedBy: .equal, toItem: backgroundView, attribute: .bottomMargin, multiplier: 1.0, constant: -insets.bottom) - let right = NSLayoutConstraint(item: contentView, attribute: .right, relatedBy: .equal, toItem: backgroundView, attribute: .rightMargin, multiplier: 1.0, constant: -insets.right) - backgroundView.addConstraints([top, left, bottom, right]) + contentView.topAnchor.constraint(equalTo: backgroundView.topAnchor, constant: insets.top).isActive = true + contentView.bottomAnchor.constraint(equalTo: backgroundView.bottomAnchor, constant: -insets.bottom).isActive = true + contentView.leftAnchor.constraint(equalTo: backgroundView.leftAnchor, constant: insets.left).isActive = true + contentView.rightAnchor.constraint(equalTo: backgroundView.rightAnchor, constant: -insets.right).isActive = true + contentView.heightAnchor.constraint(equalToConstant: 350).with(priority: UILayoutPriority(rawValue: 200)).isActive = true + } + + /** + A convenience function for installing a background view and pinning to the layout margins. + This is useful for creating programatic layouts where the background view needs to be + inset from the message view's edges (like a card-style layout). + + - Parameter backgroundView: The view to be installed as a subview and + assigned to the `backgroundView` property. + - Parameter insets: The amount to inset the content view from the margins. Default is zero inset. + */ + open func installBackgroundView(_ backgroundView: UIView, insets: UIEdgeInsets = UIEdgeInsets.zero) { + backgroundView.translatesAutoresizingMaskIntoConstraints = false + if backgroundView != self { + backgroundView.removeFromSuperview() + } + addSubview(backgroundView) + self.backgroundView = backgroundView + backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor).with(priority: UILayoutPriority(rawValue: 950)).isActive = true + backgroundView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: insets.top).with(priority: UILayoutPriority(rawValue: 900)).isActive = true + backgroundView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor, constant: -insets.bottom).with(priority: UILayoutPriority(rawValue: 900)).isActive = true + backgroundView.heightAnchor.constraint(equalToConstant: 350).with(priority: UILayoutPriority(rawValue: 200)).isActive = true + layoutConstraints = [ + backgroundView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: insets.left).with(priority: UILayoutPriority(rawValue: 900)), + backgroundView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: -insets.right).with(priority: UILayoutPriority(rawValue: 900)), + ] + regularWidthLayoutConstraints = [ + backgroundView.leftAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.leftAnchor, constant: insets.left).with(priority: UILayoutPriority(rawValue: 900)), + backgroundView.rightAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.rightAnchor, constant: -insets.right).with(priority: UILayoutPriority(rawValue: 900)), + backgroundView.widthAnchor.constraint(lessThanOrEqualToConstant: 500).with(priority: UILayoutPriority(rawValue: 950)), + backgroundView.widthAnchor.constraint(equalToConstant: 500).with(priority: UILayoutPriority(rawValue: 200)), + ] + installTapRecognizer() + } + + /** + A convenience function for installing a background view and pinning to the horizontal + layout margins and to the vertical edges. This is useful for creating programatic layouts where + the background view needs to be inset from the message view's horizontal edges (like a tab-style layout). + + - Parameter backgroundView: The view to be installed as a subview and + assigned to the `backgroundView` property. + - Parameter insets: The amount to inset the content view from the horizontal margins and vertical edges. + Default is zero inset. + */ + open func installBackgroundVerticalView(_ backgroundView: UIView, insets: UIEdgeInsets = UIEdgeInsets.zero) { + backgroundView.translatesAutoresizingMaskIntoConstraints = false + if backgroundView != self { + backgroundView.removeFromSuperview() + } + addSubview(backgroundView) + self.backgroundView = backgroundView + backgroundView.centerXAnchor.constraint(equalTo: centerXAnchor).with(priority: UILayoutPriority(rawValue: 950)).isActive = true + backgroundView.topAnchor.constraint(equalTo: topAnchor, constant: insets.top).with(priority: UILayoutPriority(rawValue: 1000)).isActive = true + backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -insets.bottom).with(priority: UILayoutPriority(rawValue: 1000)).isActive = true + backgroundView.heightAnchor.constraint(equalToConstant: 350).with(priority: UILayoutPriority(rawValue: 200)).isActive = true + layoutConstraints = [ + backgroundView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: insets.left).with(priority: UILayoutPriority(rawValue: 900)), + backgroundView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: -insets.right).with(priority: UILayoutPriority(rawValue: 900)), + ] + regularWidthLayoutConstraints = [ + backgroundView.leftAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.leftAnchor, constant: insets.left).with(priority: UILayoutPriority(rawValue: 900)), + backgroundView.rightAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.rightAnchor, constant: -insets.right).with(priority: UILayoutPriority(rawValue: 900)), + backgroundView.widthAnchor.constraint(lessThanOrEqualToConstant: 500).with(priority: UILayoutPriority(rawValue: 950)), + backgroundView.widthAnchor.constraint(equalToConstant: 500).with(priority: UILayoutPriority(rawValue: 200)), + ] + installTapRecognizer() } - + /* MARK: - Tap handler */ - + /** An optional tap handler that will be called when the `backgroundView` is tapped. */ @@ -94,18 +160,19 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable { installTapRecognizer() } } - + fileprivate lazy var tapRecognizer: UITapGestureRecognizer = { let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(MessageView.tapped)) return tapRecognizer }() - - func tapped() { + + @objc func tapped() { tapHandler?(self) } - + fileprivate func installTapRecognizer() { guard let backgroundView = backgroundView else { return } + removeGestureRecognizer(tapRecognizer) backgroundView.removeGestureRecognizer(tapRecognizer) if tapHandler != nil { // Only install the tap recognizer if there is a tap handler, @@ -115,40 +182,108 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable { } } + open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + if backgroundView != self { + let backgroundViewPoint = convert(point, to: backgroundView) + return backgroundView.point(inside: backgroundViewPoint, with: event) + } + return super.point(inside: point, with: event) + } + /* MARK: - MarginAdjustable - + These properties fulfill the `MarginAdjustable` protocol and are exposed as `@IBInspectables` so that they can be adjusted directly in nib files (see MessageView.nib). */ - - @IBInspectable open var bounceAnimationOffset: CGFloat = 5.0 - - @IBInspectable open var statusBarOffset: CGFloat = 20.0 - - + + public var layoutMarginAdditions: UIEdgeInsets { + get { + return UIEdgeInsets(top: topLayoutMarginAddition, left: leftLayoutMarginAddition, bottom: bottomLayoutMarginAddition, right: rightLayoutMarginAddition) + } + set { + topLayoutMarginAddition = newValue.top + leftLayoutMarginAddition = newValue.left + bottomLayoutMarginAddition = newValue.bottom + rightLayoutMarginAddition = newValue.right + } + } + + /// Start margins from the safe area. + open var respectSafeArea: Bool = true + + /// IBInspectable access to layoutMarginAdditions.top + @IBInspectable open var topLayoutMarginAddition: CGFloat = 0 + + /// IBInspectable access to layoutMarginAdditions.left + @IBInspectable open var leftLayoutMarginAddition: CGFloat = 0 + + /// IBInspectable access to layoutMarginAdditions.bottom + @IBInspectable open var bottomLayoutMarginAddition: CGFloat = 0 + + /// IBInspectable access to layoutMarginAdditions.right + @IBInspectable open var rightLayoutMarginAddition: CGFloat = 0 + + @IBInspectable open var collapseLayoutMarginAdditions: Bool = true + + @IBInspectable open var bounceAnimationOffset: CGFloat = 5 + /* - MARK: - Setting preferred height + MARK: - Setting the height */ - + /** - An optional value that sets the message view's intrinsic content height. - This can be used as a way to specify a fixed height for the message view. - Note that this height is not guaranteed depending on anyt Auto Layout - constraints used within the message view. + An optional explicit height for the background view, which can be used if + the message view's intrinsic content size does not produce the desired height. */ - open var preferredHeight: CGFloat? { + open var backgroundHeight: CGFloat? { didSet { - setNeedsLayout() + updateBackgroundHeightConstraint() } } - - open override var intrinsicContentSize: CGSize { - if let preferredHeight = preferredHeight { - return CGSize(width: UIViewNoIntrinsicMetric, height: preferredHeight) + + private func updateBackgroundHeightConstraint() { + if let existing = backgroundHeightConstraint { + let view = existing.firstItem as! UIView + view.removeConstraint(existing) + backgroundHeightConstraint = nil + } + if let height = backgroundHeight, let backgroundView = backgroundView { + let constraint = NSLayoutConstraint(item: backgroundView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: height) + backgroundView.addConstraint(constraint) + backgroundHeightConstraint = constraint } - return super.intrinsicContentSize + } + + private var backgroundHeightConstraint: NSLayoutConstraint? + + /* + Mark: - Layout + */ + + open override func updateConstraints() { + super.updateConstraints() + let on: [NSLayoutConstraint] + let off: [NSLayoutConstraint] + switch traitCollection.horizontalSizeClass { + case .regular: + on = regularWidthLayoutConstraints + off = layoutConstraints + default: + on = layoutConstraints + off = regularWidthLayoutConstraints + } + on.forEach { $0.isActive = true } + off.forEach { $0.isActive = false } + } + + private var layoutConstraints: [NSLayoutConstraint] = [] + private var regularWidthLayoutConstraints: [NSLayoutConstraint] = [] + + open override func layoutSubviews() { + super.layoutSubviews() + updateShadowPath() } } @@ -157,10 +292,13 @@ open class BaseView: UIView, BackgroundViewable, MarginAdjustable { */ extension BaseView { - + /// A convenience function to configure a default drop shadow effect. - open func configureDropShadow() { - let layer = backgroundView.layer + /// The shadow is to this view's layer instead of that of the background view + /// because the background view may be masked. So, when modifying the drop shadow, + /// be sure to set the shadow properties of this view's layer. The shadow path is + /// updated for you automatically. + public func configureDropShadow() { layer.shadowColor = UIColor.black.cgColor layer.shadowOffset = CGSize(width: 0.0, height: 2.0) layer.shadowRadius = 6.0 @@ -168,13 +306,70 @@ extension BaseView { layer.masksToBounds = false updateShadowPath() } - + + /// A convenience function to turn off drop shadow + public func configureNoDropShadow() { + layer.shadowOpacity = 0 + } + private func updateShadowPath() { - layer.shadowPath = UIBezierPath(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath + backgroundView?.layoutIfNeeded() + let shadowLayer = backgroundView?.layer ?? layer + let shadowRect = layer.convert(shadowLayer.bounds, from: shadowLayer) + let shadowPath: CGPath? + if let backgroundMaskLayer = shadowLayer.mask as? CAShapeLayer, + let backgroundMaskPath = backgroundMaskLayer.path { + var transform = CGAffineTransform(translationX: shadowRect.minX, y: shadowRect.minY) + shadowPath = backgroundMaskPath.copy(using: &transform) + } else { + shadowPath = UIBezierPath(roundedRect: shadowRect, cornerRadius: shadowLayer.cornerRadius).cgPath + } + // This is a workaround needed for smooth rotation animations. + if let foundAnimation = layer.findAnimation(forKeyPath: "bounds.size") { + // Update the layer's `shadowPath` with animation, copying the relevant properties + // from the found animation. + let animation = CABasicAnimation(keyPath: "shadowPath") + animation.duration = foundAnimation.duration + animation.timingFunction = foundAnimation.timingFunction + animation.fromValue = layer.shadowPath + animation.toValue = shadowPath + layer.add(animation, forKey: "shadowPath") + layer.shadowPath = shadowPath + } else { + // Update the layer's `shadowPath` without animation + layer.shadowPath = shadowPath } } - - open override func layoutSubviews() { - super.layoutSubviews() - updateShadowPath() +} + +/* + MARK: - Configuring the width + + This extension provides a few convenience functions for configuring the + background view's width. You are encouraged to write your own such functions + if these don't exactly meet your needs. + */ + +extension BaseView { + + /** + A shortcut for configuring the left and right layout margins. For views that + have `backgroundView` as a subview of `MessageView`, the background view should + be pinned to the left and right `layoutMargins` in order for this configuration to work. + */ + public func configureBackgroundView(sideMargin: CGFloat) { + layoutMargins.left = sideMargin + layoutMargins.right = sideMargin + } + + /** + A shortcut for adding a width constraint to the `backgroundView`. When calling this + method, it is important to ensure that the width constraint doesn't conflict with + other constraints. The CardView.nib and TabView.nib layouts are compatible with + this method. + */ + public func configureBackgroundView(width: CGFloat) { + guard let backgroundView = backgroundView else { return } + let constraint = NSLayoutConstraint(item: backgroundView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: width) + backgroundView.addConstraint(constraint) } } diff --git a/SwiftMessages/CALayer+Extensions.swift b/SwiftMessages/CALayer+Extensions.swift new file mode 100644 index 00000000..e0b32f55 --- /dev/null +++ b/SwiftMessages/CALayer+Extensions.swift @@ -0,0 +1,18 @@ +// +// CALayer+Extensions.swift +// SwiftMessages +// +// Created by Timothy Moose on 8/3/18. +// Copyright © 2018 SwiftKick Mobile. All rights reserved. +// + +import QuartzCore + +extension CALayer { + func findAnimation(forKeyPath keyPath: String) -> CABasicAnimation? { + return animationKeys()? + .compactMap({ animation(forKey: $0) as? CABasicAnimation }) + .filter({ $0.keyPath == keyPath }) + .first + } +} diff --git a/SwiftMessages/CornerRoundingView.swift b/SwiftMessages/CornerRoundingView.swift new file mode 100644 index 00000000..398b731c --- /dev/null +++ b/SwiftMessages/CornerRoundingView.swift @@ -0,0 +1,83 @@ +// +// CornerRoundingView.swift +// SwiftMessages +// +// Created by Timothy Moose on 7/28/18. +// Copyright © 2018 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +/// A background view that messages can use for rounding all or a subset of corners with squircles +/// (the smoother method of rounding corners that you see on app icons). +open class CornerRoundingView: UIView { + + /// Specifies the corner radius to use. + @IBInspectable + open var cornerRadius: CGFloat = 0 { + didSet { + updateMaskPath() + } + } + + /// Set to `true` for layouts where only the leading corners should be + /// rounded. For example, the layout in TabView.xib rounds the bottom corners + /// when displayed from the top and the top corners when displayed from the bottom. + /// When this property is `true`, the `roundedCorners` property will be overwritten + /// by relevant animators (e.g. `TopBottomAnimation`). + @IBInspectable + open var roundsLeadingCorners: Bool = false + + /// Specifies which corners should be rounded. When `roundsLeadingCorners = true`, relevant + /// relevant animators (e.g. `TopBottomAnimation`) will overwrite the value of this property. + open var roundedCorners: UIRectCorner = [.allCorners] { + didSet { + updateMaskPath() + } + } + + override public init(frame: CGRect) { + super.init(frame: frame) + sharedInit() + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + sharedInit() + } + + private func sharedInit() { + layer.mask = shapeLayer + } + + private let shapeLayer = CAShapeLayer() + + override open func layoutSubviews() { + super.layoutSubviews() + updateMaskPath() + } + + private func updateMaskPath() { + let newPath = UIBezierPath(roundedRect: layer.bounds, byRoundingCorners: roundedCorners, cornerRadii: cornerRadii).cgPath + // Update the `shapeLayer's` path with animation if we detect our `layer's` size is being animated. + // This is a workaround needed for smooth rotation animations. + if let foundAnimation = layer.findAnimation(forKeyPath: "bounds.size") { + // Update the `shapeLayer's` path with animation, copying the relevant properties + // from the found animation. + let animation = CABasicAnimation(keyPath: "path") + animation.duration = foundAnimation.duration + animation.timingFunction = foundAnimation.timingFunction + animation.fromValue = shapeLayer.path + animation.toValue = newPath + shapeLayer.add(animation, forKey: "path") + shapeLayer.path = newPath + } else { + // Update the `shapeLayer's` path without animation + shapeLayer.path = newPath + } + } + + private var cornerRadii: CGSize { + return CGSize(width: cornerRadius, height: cornerRadius) + } +} diff --git a/SwiftMessages/HapticMessage.swift b/SwiftMessages/HapticMessage.swift new file mode 100644 index 00000000..fa86614f --- /dev/null +++ b/SwiftMessages/HapticMessage.swift @@ -0,0 +1,16 @@ +// +// HapticMessage.swift +// SwiftMessages +// +// Created by Timothy Moose on 1/23/24. +// Copyright © 2024 SwiftKick Mobile. All rights reserved. +// + +import Foundation + +/** + Message views that conform to `HapticMessage` can specify a haptic feedback to be used when presented. + */ +protocol HapticMessage { + var defaultHaptic: SwiftMessages.Haptic? { get } +} diff --git a/SwiftMessages/Identifiable.swift b/SwiftMessages/Identifiable.swift index d7678659..2985410f 100644 --- a/SwiftMessages/Identifiable.swift +++ b/SwiftMessages/Identifiable.swift @@ -9,14 +9,15 @@ import Foundation /** - Message views that implement the `Identifiable` protocol will have duplicate messages + Message views that adopt the `Identifiable` protocol will have duplicate messages removed from the `MessageView` queue. Typically, the `id` would be set to a string representation of the content of the message view. For example, `MessageView`, combines the title and message body text. - This protocol is optional. Messave views that don't implement `Identifiable` will not + This protocol is optional. Message views that don't adopt `Identifiable` will not have duplicates removed. */ + public protocol Identifiable { var id: String { get } -} \ No newline at end of file +} diff --git a/SwiftMessages/KeyboardTrackingView.swift b/SwiftMessages/KeyboardTrackingView.swift new file mode 100644 index 00000000..173af175 --- /dev/null +++ b/SwiftMessages/KeyboardTrackingView.swift @@ -0,0 +1,148 @@ +// +// KeyboardTrackingView.swift +// SwiftMessages +// +// Created by Timothy Moose on 5/20/19. +// Copyright © 2019 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +public protocol KeyboardTrackingViewDelegate: AnyObject { + func keyboardTrackingViewWillChange(change: KeyboardTrackingView.Change, userInfo: [AnyHashable : Any]) + func keyboardTrackingViewDidChange(change: KeyboardTrackingView.Change, userInfo: [AnyHashable : Any]) +} + +/// A view that adjusts it's height based on keyboard hide and show notifications. +/// Pin it to the bottom of the screen using Auto Layout and then pin views that +/// should avoid the keyboard to the top of it. Supply an instance of this class +/// on `SwiftMessages.Config.keyboardTrackingView` or `SwiftMessagesSegue.keyboardTrackingView` +/// for automatic keyboard avoidance for the entire SwiftMessages view or view controller. +open class KeyboardTrackingView: UIView { + + public enum Change { + case show + case hide + case frame + } + + public weak var delegate: KeyboardTrackingViewDelegate? + + /// Typically, when a view controller is not being displayed, keyboard + /// tracking should be paused to avoid responding to keyboard events + /// caused by other view controllers or apps. Setting `isPaused = false` in + /// `viewWillAppear` and `isPaused = true` in `viewWillDisappear` usually works. This class + /// automatically pauses and resumes when the app resigns and becomes active, respectively. + open var isPaused = false { + didSet { + if !isPaused { + isAutomaticallyPaused = false + } + } + } + + /// 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() + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + open override func awakeFromNib() { + super.awakeFromNib() + postInit() + } + + private var isAutomaticallyPaused = false + private var heightConstraint: NSLayoutConstraint! + private var lastObservedKeyboardRect: CGRect? + + private func postInit() { + translatesAutoresizingMaskIntoConstraints = false + heightConstraint = heightAnchor.constraint(equalToConstant: 0) + heightConstraint.isActive = true + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(pause), name: UIApplication.willResignActiveNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(resume), name: UIApplication.didBecomeActiveNotification, object: nil) + backgroundColor = .clear + } + + @objc private func keyboardWillChangeFrame(_ notification: Notification) { + show(change: .frame, notification) + } + + @objc private func keyboardWillShow(_ notification: Notification) { + show(change: .show, notification) + } + + @objc private func keyboardWillHide(_ notification: Notification) { + guard !(isPaused || isAutomaticallyPaused), + let userInfo = (notification as NSNotification).userInfo else { return } + guard heightConstraint.constant != 0 else { return } + delegate?.keyboardTrackingViewWillChange(change: .hide, userInfo: userInfo) + animateKeyboardChange(change: .hide, height: 0, userInfo: userInfo) + } + + @objc private func pause() { + isAutomaticallyPaused = true + } + + @objc private func resume() { + 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) + lastObservedKeyboardRect = value.cgRectValue + let newHeight = calculateHeightConstant() + guard heightConstraint.constant != newHeight else { return } + animateKeyboardChange(change: change, height: newHeight, userInfo: userInfo) + } + + private func animateKeyboardChange(change: Change, height: CGFloat, userInfo: [AnyHashable: Any]) { + if let durationNumber = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber { + UIView.animate(withDuration: durationNumber.doubleValue, delay: 0, options: .curveEaseInOut, animations: { + self.heightConstraint.constant = height + self.updateConstraintsIfNeeded() + self.superview?.layoutIfNeeded() + }) { completed in + self.didChange(change: change, userInfo: userInfo) + self.delegate?.keyboardTrackingViewDidChange(change: change, userInfo: userInfo) + } + } + } + + 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/MarginAdjustable+Extensions.swift b/SwiftMessages/MarginAdjustable+Extensions.swift new file mode 100644 index 00000000..da8f46d1 --- /dev/null +++ b/SwiftMessages/MarginAdjustable+Extensions.swift @@ -0,0 +1,43 @@ +// +// MarginAdjustable+Extensions.swift +// SwiftMessages +// +// Created by Timothy Moose on 11/5/17. +// Copyright © 2017 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +extension MarginAdjustable where Self: UIView { + public func defaultMarginAdjustment(context: AnimationContext) -> UIEdgeInsets { + var layoutMargins: UIEdgeInsets = layoutMarginAdditions + var safeAreaInsets: UIEdgeInsets = { + guard respectSafeArea else { return .zero } + insetsLayoutMarginsFromSafeArea = false + return self.safeAreaInsets + }() + if !context.safeZoneConflicts.isDisjoint(with: .overStatusBar) { + safeAreaInsets.top = 0 + } + layoutMargins = collapseLayoutMarginAdditions + ? layoutMargins.collapse(toInsets: safeAreaInsets) + : layoutMargins + safeAreaInsets + return layoutMargins + } +} + +extension UIEdgeInsets { + func collapse(toInsets insets: UIEdgeInsets) -> UIEdgeInsets { + let top = self.top.collapse(toInset: insets.top) + let left = self.left.collapse(toInset: insets.left) + let bottom = self.bottom.collapse(toInset: insets.bottom) + let right = self.right.collapse(toInset: insets.right) + return UIEdgeInsets(top: top, left: left, bottom: bottom, right: right) + } +} + +extension CGFloat { + func collapse(toInset inset: CGFloat) -> CGFloat { + return Swift.max(self, inset) + } +} diff --git a/SwiftMessages/MarginAdjustable.swift b/SwiftMessages/MarginAdjustable.swift index 559993ec..86fe9017 100644 --- a/SwiftMessages/MarginAdjustable.swift +++ b/SwiftMessages/MarginAdjustable.swift @@ -22,6 +22,21 @@ import UIKit is responsible for setting is own internal margins appropriately. */ public protocol MarginAdjustable { + + /// The amount to add to the safe area insets in calculating + /// the layout margins. + var layoutMarginAdditions: UIEdgeInsets { get } + + /// When `true`, SwiftMessages automatically collapses layout margin additions (topLayoutMarginAddition, etc.) + /// when the default layout margins are greater than zero. This is typically used when a margin addition is only + /// needed when the safe area inset is zero for a given edge. When the safe area inset for a given edge is non-zero, + /// the additional margin is not added. + var collapseLayoutMarginAdditions: Bool { get set } + + + /// Start margins from the safe area. + var respectSafeArea: Bool { get set } + var bounceAnimationOffset: CGFloat { get set } - var statusBarOffset: CGFloat { get set } -} \ No newline at end of file +} + diff --git a/SwiftMessages/MaskingView.swift b/SwiftMessages/MaskingView.swift new file mode 100644 index 00000000..d6313427 --- /dev/null +++ b/SwiftMessages/MaskingView.swift @@ -0,0 +1,79 @@ +// +// MaskingView.swift +// SwiftMessages +// +// Created by Timothy Moose on 3/11/17. +// Copyright © 2017 SwiftKick Mobile. All rights reserved. +// + +import UIKit + + +class MaskingView: PassthroughView { + + func install(keyboardTrackingView: KeyboardTrackingView) { + self.keyboardTrackingView = keyboardTrackingView + keyboardTrackingView.translatesAutoresizingMaskIntoConstraints = false + addSubview(keyboardTrackingView) + keyboardTrackingView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true + keyboardTrackingView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true + keyboardTrackingView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true + } + + var accessibleElements: [NSObject] = [] + + weak var backgroundView: UIView? { + didSet { + oldValue?.removeFromSuperview() + if let view = backgroundView { + view.isUserInteractionEnabled = false + view.frame = bounds + view.autoresizingMask = [.flexibleWidth, .flexibleHeight] + addSubview(view) + sendSubviewToBack(view) + } + } + } + + override func accessibilityElementCount() -> Int { + return accessibleElements.count + } + + override func accessibilityElement(at index: Int) -> Any? { + return accessibleElements[index] + } + + override func index(ofAccessibilityElement element: Any) -> Int { + guard let object = element as? NSObject else { return 0 } + return accessibleElements.firstIndex(of: object) ?? 0 + } + + init() { + super.init(frame: CGRect.zero) + clipsToBounds = true + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + clipsToBounds = true + } + + private var keyboardTrackingView: KeyboardTrackingView? + + override func addSubview(_ view: UIView) { + super.addSubview(view) + guard let keyboardTrackingView = keyboardTrackingView, + view != keyboardTrackingView, + view != backgroundView else { return } + 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 + } +} diff --git a/SwiftMessages/MessageGeometryProxy.swift b/SwiftMessages/MessageGeometryProxy.swift new file mode 100644 index 00000000..73d2d785 --- /dev/null +++ b/SwiftMessages/MessageGeometryProxy.swift @@ -0,0 +1,17 @@ +// +// MessageGeometryProxy.swift +// SwiftMessages +// +// Created by Timothy Moose on 6/24/24. +// Copyright © 2024 SwiftKick Mobile. All rights reserved. +// + +import SwiftUI + +/// A data type that mimicks `GeomtryProxy` and is used with `swiftMessage()` modifier when the geomtry metrics of the container view +/// are needed, particularly because `GeometryReader` doesn't work inside the view builder due to the way the message view is being +/// displayed from UIKit. +public struct MessageGeometryProxy { + public var size: CGSize + public var safeAreaInsets: EdgeInsets +} diff --git a/SwiftMessages/MessageHostingView.swift b/SwiftMessages/MessageHostingView.swift new file mode 100644 index 00000000..4301090e --- /dev/null +++ b/SwiftMessages/MessageHostingView.swift @@ -0,0 +1,114 @@ +// +// MessageHostingView.swift +// SwiftMessages +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI +import UIKit + +/// A rudimentary hosting view for SwiftUI messages. +@available(iOS 14.0, *) +public class MessageHostingView<Content>: UIView, Identifiable where Content: View { + + // MARK: - API + + public let id: String + + public init(id: String, content: Content) { + self.id = id + self.content = { _ in content } + super.init(frame: .zero) + backgroundColor = .clear + } + + public init<Message>( + message: Message, + @ViewBuilder content: @escaping (Message, MessageGeometryProxy) -> Content + ) where Message: Identifiable { + self.id = message.id + self.content = { geom in content(message, geom) } + super.init(frame: .zero) + backgroundColor = .clear + } + + convenience public init<Message>(message: Message) where Message: MessageViewConvertible, Message.Content == Content { + self.init(id: message.id, content: message.asMessageView() ) + } + + // MARK: - Constants + + // MARK: - Variables + + private var hostVC: UIHostingController<Content>? + private let content: (MessageGeometryProxy) -> Content + + // MARK: - Lifecycle + + @available(*, unavailable) + required init?(coder _: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + guard let view = super.hitTest(point, with: event) else { return nil } + // Touches should pass through unless they land on a view that is rendering a SwiftUI element. + if view == self { return nil } + // In iOS 18 beta, the hit testing behavior changed in a weird way: when a SwiftUI element is tapped, + // the first hit test returns the view that renders the SwiftUI element. However, a second identical hit + // test is performed(!) and on the second test, the `UIHostingController`'s view is returned. We want touches + // to pass through that view. In iOS 17, we would just return `nil` in that case. However, in iOS 18, the + // second hit test is actuall essential to touches being delivered to the SwiftUI elements. The new approach + // is to iterate overall all of the subviews, which are all presumably rendering SwiftUI elements, and + // only return `nil` if the point is not inside any of these subviews. + if view.superview == self { + for subview in view.subviews { + let subviewPoint = self.convert(point, to: subview) + if subview.point(inside: subviewPoint, with: event) { + return view + } + } + return nil + } + return view + } + + public override func didMoveToSuperview() { + guard let superview = self.superview else { return } + let size = superview.bounds.size + let insets = superview.safeAreaInsets + let ltr = superview.effectiveUserInterfaceLayoutDirection == .leftToRight + let proxy = MessageGeometryProxy( + size: CGSize( + width: size.width - insets.left - insets.right, + height: size.height - insets.top - insets.bottom + ), + safeAreaInsets: EdgeInsets( + top: insets.top, + leading: ltr ? insets.left : insets.right, + bottom: insets.bottom, + trailing: ltr ? insets.right : insets.left + ) + ) + let hostVC = UIHostingController(rootView: content(proxy)) + self.hostVC = hostVC + hostVC.loadViewIfNeeded() + installContentView(hostVC.view) + hostVC.view.backgroundColor = .clear + + } + + // MARK: - Configuration + + private func installContentView(_ contentView: UIView) { + contentView.translatesAutoresizingMaskIntoConstraints = false + addSubview(contentView) + NSLayoutConstraint.activate([ + contentView.topAnchor.constraint(equalTo: topAnchor), + contentView.bottomAnchor.constraint(equalTo: bottomAnchor), + contentView.leftAnchor.constraint(equalTo: leftAnchor), + contentView.rightAnchor.constraint(equalTo: rightAnchor), + ]) + } +} diff --git a/SwiftMessages/MessageView.swift b/SwiftMessages/MessageView.swift index 8c816e8e..6384917e 100644 --- a/SwiftMessages/MessageView.swift +++ b/SwiftMessages/MessageView.swift @@ -10,8 +10,15 @@ import UIKit /* */ -open class MessageView: BaseView, Identifiable { +open class MessageView: BaseView, Identifiable, AccessibleMessage, HapticMessage { + + /* + MARK: - Haptic feedback + */ + /// The default haptic feedback to be used when the message is presented. + open var defaultHaptic: SwiftMessages.Haptic? + /* MARK: - Button tap handler */ @@ -20,10 +27,23 @@ open class MessageView: BaseView, Identifiable { /// configured to call this tap handler on `.TouchUpInside`. open var buttonTapHandler: ((_ button: UIButton) -> Void)? - func buttonTapped(_ button: UIButton) { + @objc func buttonTapped(_ button: UIButton) { buttonTapHandler?(button) } - + + /* + MARK: - Touch handling + */ + + open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + // Only accept touches within the background view. Anything outside of the + // background view's bounds should be transparent and does not need to receive + // touches. This helps with tap dismissal when using `DimMode.gray` and `DimMode.color`. + return backgroundView == self + ? super.point(inside: point, with: event) + : backgroundView.point(inside: convert(point, to: backgroundView), with: event) + } + /* MARK: - IB outlets */ @@ -59,7 +79,57 @@ open class MessageView: BaseView, Identifiable { */ open var id: String { - return "MessageView:title=\(titleLabel?.text), body=\(bodyLabel?.text)" + get { + return customId ?? "MessageView:title=\(String(describing: titleLabel?.text)), body=\(String(describing: bodyLabel?.text))" + } + set { + customId = newValue + } + } + + private var customId: String? + + /* + MARK: - AccessibleMessage + */ + + /** + An optional prefix for the `accessibilityMessage` that can + be used to further clarify the message for VoiceOver. For example, + the view's background color or icon might convey that a message is + a warning, in which case one may specify the value "warning". + */ + open var accessibilityPrefix: String? + + open var accessibilityMessage: String? { + #if swift(>=4.1) + let components = [accessibilityPrefix, titleLabel?.text, bodyLabel?.text].compactMap { $0 } + #else + let components = [accessibilityPrefix, titleLabel?.text, bodyLabel?.text].flatMap { $0 } + #endif + guard components.count > 0 else { return nil } + return components.joined(separator: ", ") + } + + public var accessibilityElement: NSObject? { + return backgroundView + } + + open var additionalAccessibilityElements: [NSObject]? { + var elements: [NSObject] = [] + func getAccessibleSubviews(view: UIView) { + for subview in view.subviews { + if subview.isAccessibilityElement { + elements.append(subview) + } else { + // Only doing this for non-accessible `subviews`, which avoids + // including button labels, etc. + getAccessibleSubviews(view: subview) + } + } + } + getAccessibleSubviews(view: self.backgroundView) + return elements } } @@ -85,30 +155,30 @@ extension MessageView { The standard message view that stretches across the full width of the container view. */ - case MessageView = "MessageView" + case messageView = "MessageView" /** A floating card-style view with rounded corners. */ - case CardView = "CardView" + case cardView = "CardView" /** Like `CardView` with one end attached to the super view. */ - case TabView = "TabView" + case tabView = "TabView" /** A 20pt tall view that can be used to overlay the status bar. Note that this layout will automatically grow taller if displayed directly under the status bar (see the `ContentInsetting` protocol). */ - case StatusLine = "StatusLine" - + case statusLine = "StatusLine" + /** - A standard message view like `MessageView`, but without - stack views for iOS 8. + A floating card-style view with elements centered and arranged vertically. + This view is typically used with `.center` presentation style. */ - case MessageViewIOS8 = "MessageViewIOS8" + case centeredView = "CenteredView" } /** @@ -140,10 +210,40 @@ extension MessageView { } } +/* + MARK: - Layout adjustments + + This extension provides a few convenience functions for adjusting the layout. + */ + +extension MessageView { + /** + Constrains the image view to a specified size. By default, the size of the + image view is determined by its `intrinsicContentSize`. + + - Parameter size: The size to be translated into Auto Layout constraints. + - Parameter contentMode: The optional content mode to apply. + */ + public func configureIcon(withSize size: CGSize, contentMode: UIView.ContentMode? = nil) { + var views: [UIView] = [] + if let iconImageView = iconImageView { views.append(iconImageView) } + if let iconLabel = iconLabel { views.append(iconLabel) } + views.forEach { + let constraints = [$0.heightAnchor.constraint(equalToConstant: size.height), + $0.widthAnchor.constraint(equalToConstant: size.width)] + constraints.forEach { $0.priority = UILayoutPriority(999.0) } + $0.addConstraints(constraints) + if let contentMode = contentMode { + $0.contentMode = contentMode + } + } + } +} + /* MARK: - Theming - This extention provides a few convenience functions for setting styles, + This extension provides a few convenience functions for setting styles, colors and icons. You are encouraged to write your own such functions if these don't exactly meet your needs. */ @@ -155,27 +255,76 @@ extension MessageView { - Parameter theme: The theme type to use. - Parameter iconStyle: The icon style to use. Defaults to `.Default`. + - Parameter useHaptics: If `true`, configures an appropriate haptic based on theme. Defaults to `false`. */ - public func configureTheme(_ theme: Theme, iconStyle: IconStyle = .default) { + public func configureTheme(_ theme: Theme, iconStyle: IconStyle = .default, includeHaptic: Bool = false) { let iconImage = iconStyle.image(theme: theme) + let backgroundColor: UIColor + let foregroundColor: UIColor + let defaultBackgroundColor: UIColor 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) 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) 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) 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) } + if includeHaptic { + switch theme { + case .success, .info: + defaultHaptic = SwiftMessages.Haptic.success + case .warning: + defaultHaptic = SwiftMessages.Haptic.warning + case .error: + defaultHaptic = SwiftMessages.Haptic.error + } + } + switch theme { + case .info: + backgroundColor = UIColor { + switch $0.userInterfaceStyle { + case .dark, .unspecified: return UIColor(red: 125/255.0, green: 125/255.0, blue: 125/255.0, alpha: 1.0) + case .light: fallthrough + @unknown default: + return defaultBackgroundColor + } + } + foregroundColor = .label + case .success: + backgroundColor = UIColor { + switch $0.userInterfaceStyle { + case .dark, .unspecified: return UIColor(red: 55/255.0, green: 122/255.0, blue: 0/255.0, alpha: 1.0) + case .light: fallthrough + @unknown default: + return defaultBackgroundColor + } + } + foregroundColor = .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 + } + configureTheme(backgroundColor: backgroundColor, foregroundColor: foregroundColor, iconImage: iconImage) } /** @@ -197,7 +346,7 @@ extension MessageView { bodyLabel?.textColor = foregroundColor button?.backgroundColor = foregroundColor button?.tintColor = backgroundColor - button?.contentEdgeInsets = UIEdgeInsetsMake(7.0, 7.0, 7.0, 7.0) + button?.contentEdgeInsets = UIEdgeInsets(top: 7.0, left: 7.0, bottom: 7.0, right: 7.0) button?.layer.cornerRadius = 5.0 iconImageView?.isHidden = iconImageView?.image == nil iconLabel?.isHidden = iconLabel?.text == nil @@ -288,10 +437,12 @@ extension MessageView { bodyLabel?.text = body iconImageView?.image = iconImage iconLabel?.text = iconText - button?.setImage(buttonImage, for: UIControlState()) - button?.setTitle(buttonTitle, for: UIControlState()) + button?.setImage(buttonImage, for: .normal) + button?.setTitle(buttonTitle, for: .normal) self.buttonTapHandler = buttonTapHandler iconImageView?.isHidden = iconImageView?.image == nil iconLabel?.isHidden = iconLabel?.text == nil } } + + diff --git a/SwiftMessages/MessageViewConvertible.swift b/SwiftMessages/MessageViewConvertible.swift new file mode 100644 index 00000000..6dc168bf --- /dev/null +++ b/SwiftMessages/MessageViewConvertible.swift @@ -0,0 +1,16 @@ +// +// MessageViewConvertible.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI + +@available(iOS 14.0, *) +/// A protocol used to display a SwiftUI message view using the `swiftMessage()` modifier. +public protocol MessageViewConvertible: Equatable, Identifiable { + associatedtype Content: View + func asMessageView() -> Content +} + diff --git a/SwiftMessages/NSBundle+Extensions.swift b/SwiftMessages/NSBundle+Extensions.swift new file mode 100644 index 00000000..fdfb08b7 --- /dev/null +++ b/SwiftMessages/NSBundle+Extensions.swift @@ -0,0 +1,48 @@ +// +// NSBundle+Extensions.swift +// SwiftMessages +// +// Created by Timothy Moose on 8/8/16. +// Copyright © 2016 SwiftKick Mobile LLC. All rights reserved. +// + +import Foundation + +private class BundleToken {} + +extension Bundle { + // This is copied method from SPM generated Bundle.module for CocoaPods support + static func sm_frameworkBundle() -> Bundle { + + let candidates = [ + // Bundle should be present here when the package is linked into an App. + Bundle.main.resourceURL, + + // Bundle should be present here when the package is linked into a framework. + Bundle(for: BundleToken.self).resourceURL, + + // For command-line tools. + Bundle.main.bundleURL, + ] + + let bundleNames = [ + // For Swift Package Manager + "SwiftMessages_SwiftMessages", + + // For Carthage + "SwiftMessages", + ] + + for bundleName in bundleNames { + for candidate in candidates { + let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle") + if let bundle = bundlePath.flatMap(Bundle.init(url:)) { + return bundle + } + } + } + + // Return whatever bundle this code is in as a last resort. + return Bundle(for: BundleToken.self) + } +} diff --git a/SwiftMessages/NSBundle+Utils.swift b/SwiftMessages/NSBundle+Utils.swift deleted file mode 100644 index e093ef71..00000000 --- a/SwiftMessages/NSBundle+Utils.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// NSBundle+Utils.swift -// SwiftMessages -// -// Created by Timothy Moose on 8/8/16. -// Copyright © 2016 SwiftKick Mobile LLC. All rights reserved. -// - -import Foundation - -extension Bundle { - static func sm_frameworkBundle() -> Bundle { - let bundle = Bundle(for: MessageView.self) - if let path = bundle.path(forResource: "SwiftMessages", ofType: "bundle") { - return Bundle(path: path)! - } - else { - return bundle - } - } -} diff --git a/SwiftMessages/NSLayoutConstraint+Extensions.swift b/SwiftMessages/NSLayoutConstraint+Extensions.swift new file mode 100644 index 00000000..01f678dc --- /dev/null +++ b/SwiftMessages/NSLayoutConstraint+Extensions.swift @@ -0,0 +1,16 @@ +// +// NSLayoutConstraint+Extensions.swift +// SwiftMessages +// +// Created by Timothy Moose on 5/18/19. +// Copyright © 2019 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +extension NSLayoutConstraint { + func with(priority: UILayoutPriority) -> NSLayoutConstraint { + self.priority = priority + return self + } +} diff --git a/SwiftMessages/PassthroughView.swift b/SwiftMessages/PassthroughView.swift index e6a97863..d76da24b 100644 --- a/SwiftMessages/PassthroughView.swift +++ b/SwiftMessages/PassthroughView.swift @@ -8,21 +8,24 @@ import UIKit -class PassthroughView: UIView { - - var tapRecognizer: UITapGestureRecognizer? - - var tappedHander: (() -> Void)? { - didSet { - if let tap = tapRecognizer { - removeGestureRecognizer(tap) - } - if tappedHander == nil { return } - let tap = UITapGestureRecognizer(target: self, action: #selector(PassthroughView.tapped)) - addGestureRecognizer(tap) - } +class PassthroughView: UIControl { + + var tappedHander: (() -> Void)? + + override init(frame: CGRect) { + super.init(frame: frame) + initCommon() } - + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + initCommon() + } + + private func initCommon() { + addTarget(self, action: #selector(tapped), for: .touchUpInside) + } + @objc func tapped() { tappedHander?() } diff --git a/SwiftMessages/PassthroughWindow.swift b/SwiftMessages/PassthroughWindow.swift index e1336fc0..704e4814 100644 --- a/SwiftMessages/PassthroughWindow.swift +++ b/SwiftMessages/PassthroughWindow.swift @@ -9,8 +9,28 @@ import UIKit class PassthroughWindow: UIWindow { + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + // iOS has started embedding the SwiftMessages view in private views that block + // interaction with views underneath, essentially making the window behave like a modal. + // To work around this, we'll ignore hit test results on these views. let view = super.hitTest(point, with: event) - return view == self ? nil : view + if let view = view, + let hitTestView = hitTestView, + hitTestView.isDescendant(of: view) && hitTestView != view { + return nil + } + return view + } + + init(hitTestView: UIView) { + self.hitTestView = hitTestView + super.init(frame: .zero) } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private weak var hitTestView: UIView? } diff --git a/SwiftMessages/PhysicsAnimation.swift b/SwiftMessages/PhysicsAnimation.swift new file mode 100644 index 00000000..ef8476f7 --- /dev/null +++ b/SwiftMessages/PhysicsAnimation.swift @@ -0,0 +1,158 @@ +// +// PhysicsAnimation.swift +// SwiftMessages +// +// Created by Timothy Moose on 6/14/17. +// Copyright © 2017 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +@MainActor +public class PhysicsAnimation: NSObject, Animator { + + public enum Placement { + case top + case center + case bottom + } + + open var placement: Placement = .center + + open var showDuration: TimeInterval = 0.5 + + open var hideDuration: TimeInterval = 0.15 + + public var panHandler = PhysicsPanHandler() + + public weak var delegate: AnimationDelegate? + weak var messageView: UIView? + weak var containerView: UIView? + var context: AnimationContext? + + public override init() {} + + init(delegate: AnimationDelegate) { + self.delegate = delegate + } + + public func show(context: AnimationContext, completion: @escaping AnimationCompletion) { + NotificationCenter.default.addObserver( + self, + selector: #selector(adjustMargins), + name: UIDevice.orientationDidChangeNotification, + object: nil + ) + install(context: context) + showAnimation(context: context, completion: completion) + } + + public func hide(context: AnimationContext, completion: @escaping AnimationCompletion) { + NotificationCenter.default.removeObserver(self) + if panHandler.isOffScreen { + context.messageView.alpha = 0 + panHandler.state?.stop() + } + let view = context.messageView + self.context = context + CATransaction.begin() + CATransaction.setCompletionBlock { + view.alpha = 1 + view.transform = CGAffineTransform.identity + completion(true) + } + UIView.animate( + withDuration: hideDuration, + delay: 0, + options: [.beginFromCurrentState, .curveEaseIn, .allowUserInteraction], + animations: { + view.transform = CGAffineTransform(scaleX: 0.8, y: 0.8) + }, + completion: nil + ) + UIView.animate( + withDuration: hideDuration, + delay: 0, + options: [.beginFromCurrentState, .curveEaseIn, .allowUserInteraction], + animations: { + view.alpha = 0 + }, + completion: nil + ) + CATransaction.commit() + } + + func install(context: AnimationContext) { + let view = context.messageView + let container = context.containerView + messageView = view + containerView = container + self.context = context + view.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(view) + switch placement { + case .center: + view.centerYAnchor.constraint( + equalTo: container.centerYAnchor + ) + .with(priority: UILayoutPriority(200)) + .isActive = true + case .top: + view.topAnchor.constraint( + equalTo: container.topAnchor + ) + .with(priority: UILayoutPriority(200)) + .isActive = true + case .bottom: + view.bottomAnchor.constraint( + equalTo: container.bottomAnchor + ) + .with(priority: UILayoutPriority(200)) + .isActive = true + } + NSLayoutConstraint.activate([ + view.leadingAnchor.constraint(equalTo: container.leadingAnchor), + view.trailingAnchor.constraint(equalTo: container.trailingAnchor), + // Don't allow the message to spill outside of the top or bottom of the container. + view.topAnchor.constraint(greaterThanOrEqualTo: container.topAnchor), + view.bottomAnchor.constraint(lessThanOrEqualTo: container.bottomAnchor), + ]) + // Important to layout now in order to get the right safe area insets + container.layoutIfNeeded() + adjustMargins() + container.layoutIfNeeded() + installInteractive(context: context) + } + + @objc public func adjustMargins() { + guard let adjustable = messageView as? MarginAdjustable & UIView, + let context = context else { return } + adjustable.preservesSuperviewLayoutMargins = false + adjustable.insetsLayoutMarginsFromSafeArea = false + adjustable.layoutMargins = adjustable.defaultMarginAdjustment(context: context) + } + + func showAnimation(context: AnimationContext, completion: @escaping AnimationCompletion) { + let view = context.messageView + view.alpha = 0.25 + view.transform = CGAffineTransform(scaleX: 0.6, y: 0.6) + CATransaction.begin() + CATransaction.setCompletionBlock { + completion(true) + } + UIView.animate(withDuration: showDuration, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0, options: [.beginFromCurrentState, .curveLinear, .allowUserInteraction], animations: { + view.transform = CGAffineTransform.identity + }, completion: nil) + UIView.animate(withDuration: 0.3 * showDuration, delay: 0, options: [.beginFromCurrentState, .curveLinear, .allowUserInteraction], animations: { + view.alpha = 1 + }, completion: nil) + CATransaction.commit() + } + + func installInteractive(context: AnimationContext) { + guard context.interactiveHide else { return } + panHandler.configure(context: context, animator: self) + } +} + + diff --git a/SwiftMessages/PhysicsPanHandler.swift b/SwiftMessages/PhysicsPanHandler.swift new file mode 100644 index 00000000..86187974 --- /dev/null +++ b/SwiftMessages/PhysicsPanHandler.swift @@ -0,0 +1,178 @@ +// +// PhysicsPanHandler.swift +// SwiftMessages +// +// Created by Timothy Moose on 6/25/17. +// Copyright © 2017 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +@MainActor +open class PhysicsPanHandler { + + public var hideDelay: TimeInterval = 0.2 + + public struct MotionSnapshot { + var angle: CGFloat + var time: CFAbsoluteTime + } + + @MainActor + public final class State { + + weak var messageView: UIView? + weak var containerView: UIView? + var dynamicAnimator: UIDynamicAnimator + var itemBehavior: UIDynamicItemBehavior + var attachmentBehavior: UIAttachmentBehavior? { + didSet { + if let oldValue = oldValue { + dynamicAnimator.removeBehavior(oldValue) + } + if let attachmentBehavior = attachmentBehavior { + dynamicAnimator.addBehavior(attachmentBehavior) + addSnapshot() + } + } + } + var snapshots: [MotionSnapshot] = [] + + public init(messageView: UIView, containerView: UIView) { + self.messageView = messageView + self.containerView = containerView + let dynamicAnimator = UIDynamicAnimator(referenceView: containerView) + let itemBehavior = UIDynamicItemBehavior(items: [messageView]) + itemBehavior.allowsRotation = true + dynamicAnimator.addBehavior(itemBehavior) + self.itemBehavior = itemBehavior + self.dynamicAnimator = dynamicAnimator + } + + func update(attachmentAnchorPoint anchorPoint: CGPoint) { + addSnapshot() + attachmentBehavior?.anchorPoint = anchorPoint + } + + func addSnapshot() { + let angle = messageView?.angle ?? snapshots.last?.angle ?? 0 + let time = CFAbsoluteTimeGetCurrent() + snapshots.append(MotionSnapshot(angle: angle, time: time)) + } + + public func stop() { + guard let messageView = messageView else { + dynamicAnimator.removeAllBehaviors() + return + } + let center = messageView.center + let transform = messageView.transform + dynamicAnimator.removeAllBehaviors() + messageView.center = center + messageView.transform = transform + } + + public var angularVelocity: CGFloat { + guard let last = snapshots.last else { return 0 } + for previous in snapshots.reversed() { + // Ignore snapshots where the angle or time hasn't changed to avoid degenerate cases. + if previous.angle != last.angle && previous.time != last.time { + return (last.angle - previous.angle) / CGFloat(last.time - previous.time) + } + } + return 0 + } + } + + weak var animator: Animator? + weak var messageView: UIView? + weak var containerView: UIView? + private(set) public var state: State? + private(set) public var isOffScreen = false + private var restingCenter: CGPoint? + + public init() {} + + public private(set) lazy var pan: UIPanGestureRecognizer = { + let pan = UIPanGestureRecognizer() + pan.addTarget(self, action: #selector(pan(_:))) + return pan + }() + + public func configure(context: AnimationContext, animator: Animator) { + if let oldView = (messageView as? BackgroundViewable)?.backgroundView ?? messageView { + oldView.removeGestureRecognizer(pan) + } + messageView = context.messageView + let view = (messageView as? BackgroundViewable)?.backgroundView ?? messageView + view?.addGestureRecognizer(pan) + containerView = context.containerView + self.animator = animator + } + + @objc func pan(_ pan: UIPanGestureRecognizer) { + guard let messageView = messageView, let containerView = containerView, let animator = animator else { return } + let anchorPoint = pan.location(in: containerView) + switch pan.state { + case .began: + animator.delegate?.panStarted(animator: animator) + let state = State(messageView: messageView, containerView: containerView) + self.state = state + let center = messageView.center + restingCenter = center + let offset = UIOffset(horizontal: anchorPoint.x - center.x, vertical: anchorPoint.y - center.y) + let attachmentBehavior = UIAttachmentBehavior(item: messageView, offsetFromCenter: offset, attachedToAnchor: anchorPoint) + state.attachmentBehavior = attachmentBehavior + state.itemBehavior.action = { [weak self, weak messageView, weak containerView] in + guard let self = self, !self.isOffScreen, let messageView = messageView, let containerView = containerView, let animator = self.animator else { return } + let view = (messageView as? BackgroundViewable)?.backgroundView ?? messageView + let frame = containerView.convert(view.bounds, from: view) + if !containerView.bounds.intersects(frame) { + self.isOffScreen = true + Task { + try? await Task.sleep(seconds: self.hideDelay) + animator.delegate?.hide(animator: animator) + } + } + } + case .changed: + guard let state = state else { return } + state.update(attachmentAnchorPoint: anchorPoint) + case .ended, .cancelled: + guard let state = state else { return } + state.update(attachmentAnchorPoint: anchorPoint) + let velocity = pan.velocity(in: containerView) + let angularVelocity = state.angularVelocity + let speed = sqrt(pow(velocity.x, 2) + pow(velocity.y, 2)) + // The multiplier on angular velocity was determined by hand-tuning + let energy = sqrt(pow(speed, 2) + pow(angularVelocity * 75, 2)) + if energy > 200 && speed > 600 { + // Limit the speed and angular velocity to reasonable values + let speedScale = speed > 0 ? min(1, 1800 / speed) : 1 + let escapeVelocity = CGPoint(x: velocity.x * speedScale, y: velocity.y * speedScale) + let angularSpeedScale = min(1, 10 / abs(angularVelocity)) + let escapeAngularVelocity = angularVelocity * angularSpeedScale + state.itemBehavior.addLinearVelocity(escapeVelocity, for: messageView) + state.itemBehavior.addAngularVelocity(escapeAngularVelocity, for: messageView) + state.attachmentBehavior = nil + } else { + state.stop() + self.state = nil + animator.delegate?.panEnded(animator: animator) + UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.65, initialSpringVelocity: 0, options: .beginFromCurrentState, animations: { + messageView.center = self.restingCenter ?? CGPoint(x: containerView.bounds.width / 2, y: containerView.bounds.height / 2) + messageView.transform = CGAffineTransform.identity + }, completion: nil) + } + default: + break + } + } +} + +extension UIView { + var angle: CGFloat { + // http://stackoverflow.com/a/2051861/1271826 + return atan2(transform.b, transform.a) + } +} diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index 2d33ef0a..2010f22b 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -8,21 +8,78 @@ import UIKit -class Weak<T: AnyObject> { - weak var value : T? - init(value: T?) { - self.value = value - } -} - -protocol PresenterDelegate: class { +@MainActor +protocol PresenterDelegate: AnimationDelegate { func hide(presenter: Presenter) - func panStarted(presenter: Presenter) - func panEnded(presenter: Presenter) } -class Presenter: NSObject, UIGestureRecognizerDelegate { +@MainActor +class Presenter: NSObject { + + // MARK: - API + + init(config: SwiftMessages.Config, view: UIView, delegate: PresenterDelegate) { + self.config = config + self.view = view + self.delegate = delegate + self.animator = Presenter.animator(forPresentationStyle: config.presentationStyle, delegate: delegate) + if let identifiable = view as? Identifiable { + id = identifiable.id + } else { + var mutableView = view + id = withUnsafePointer(to: &mutableView) { "\($0)" } + } + + super.init() + } + + var id: String + var config: SwiftMessages.Config + let maskingView = MaskingView() + let animator: Animator + var isHiding = false + let view: UIView + + var delayShow: TimeInterval? { + if case .indefinite(let delay, _) = config.duration { return delay } + return nil + } + + var showDate: CFTimeInterval? + + /// Returns the required delay for hiding based on time shown + var delayHide: TimeInterval? { + if interactivelyHidden { return 0 } + if case .indefinite(_, let minimum) = config.duration, let showDate = showDate { + let timeIntervalShown = CACurrentMediaTime() - showDate + return max(0, minimum - timeIntervalShown) + } + return nil + } + var pauseDuration: TimeInterval? { + let duration: TimeInterval? + switch self.config.duration { + case .automatic: + duration = 2 + case .seconds(let seconds): + duration = seconds + case .forever, .indefinite: + duration = nil + } + 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 + + @MainActor enum PresentationContext { case viewController(_: Weak<UIViewController>) case view(_: Weak<UIView>) @@ -45,193 +102,55 @@ class Presenter: NSObject, UIGestureRecognizerDelegate { } } } - - let config: SwiftMessages.Config - let view: UIView - weak var delegate: PresenterDelegate? - let maskingView = PassthroughView() - var presentationContext = PresentationContext.viewController(Weak<UIViewController>(value: nil)) - let panRecognizer: UIPanGestureRecognizer - var translationConstraint: NSLayoutConstraint! = nil - - init(config: SwiftMessages.Config, view: UIView, delegate: PresenterDelegate) { - self.config = config - self.view = view - self.delegate = delegate - panRecognizer = UIPanGestureRecognizer() - super.init() - panRecognizer.addTarget(self, action: #selector(Presenter.pan(_:))) - panRecognizer.delegate = self - maskingView.clipsToBounds = true - } - - var id: String? { - let identifiable = view as? Identifiable - return identifiable?.id - } - - var pauseDuration: TimeInterval? { - let duration: TimeInterval? - switch self.config.duration { - case .automatic: - duration = 2.0 - case .seconds(let seconds): - duration = seconds - case .forever: - duration = nil + + // MARK: - Variables + + private weak var delegate: PresenterDelegate? + private var presentationContext = PresentationContext.viewController(Weak<UIViewController>(value: nil)) + private var installed = false + private var interactivelyHidden = false; + + // MARK: - Showing and hiding + + private static func animator(forPresentationStyle style: SwiftMessages.PresentationStyle, delegate: AnimationDelegate) -> Animator { + switch style { + case .top: + return TopBottomAnimation(style: .top, delegate: delegate) + case .bottom: + return TopBottomAnimation(style: .bottom, delegate: delegate) + case .center: + return PhysicsAnimation(delegate: delegate) + case .custom(let animator): + animator.delegate = delegate + return animator } - return duration } - - func show(completion: @escaping (_ completed: Bool) -> Void) throws { + + func show(completion: @escaping AnimationCompletion) throws { try presentationContext = getPresentationContext() install() - self.config.eventListeners.forEach { $0(.willShow) } + self.config.eventListeners.forEach { $0(.willShow(self.view)) } + switch (self.view as? HapticMessage)?.defaultHaptic ?? config.haptic { + case .error?: UINotificationFeedbackGenerator().notificationOccurred(.error) + case .warning?: UINotificationFeedbackGenerator().notificationOccurred(.warning) + case .success?: UINotificationFeedbackGenerator().notificationOccurred(.success) + default: break + } showAnimation() { completed in completion(completed) if completed { - self.config.eventListeners.forEach { $0(.didShow) } - } - } - } - - func getPresentationContext() throws -> PresentationContext { - - func newWindowViewController(_ windowLevel: UIWindowLevel) -> UIViewController { - let viewController = WindowViewController(windowLevel: windowLevel, config: config) - return viewController - } - - switch config.presentationContext { - case .automatic: - if let rootViewController = UIApplication.shared.keyWindow?.rootViewController { - let viewController = rootViewController.sm_selectPresentationContextTopDown(config) - return .viewController(Weak(value: viewController)) - } else { - throw SwiftMessagesError.noRootViewController - } - case .window(let level): - let viewController = newWindowViewController(level) - return .viewController(Weak(value: viewController)) - case .viewController(let viewController): - let viewController = viewController.sm_selectPresentationContextBottomUp(config) - return .viewController(Weak(value: viewController)) - case .view(let view): - return .view(Weak(value: view)) - } - } - - /* - MARK: - Installation - */ - - func install() { - guard let containerView = presentationContext.viewValue() else { return } - if let windowViewController = presentationContext.viewControllerValue() as? WindowViewController { - windowViewController.install() - } - do { - maskingView.translatesAutoresizingMaskIntoConstraints = false - if let nav = presentationContext.viewControllerValue() as? UINavigationController { - containerView.insertSubview(maskingView, belowSubview: nav.navigationBar) - } else if let tab = presentationContext.viewControllerValue() as? UITabBarController { - containerView.insertSubview(maskingView, belowSubview: tab.tabBar) - } else { - containerView.addSubview(maskingView) - } - let leading = NSLayoutConstraint(item: maskingView, attribute: .leading, relatedBy: .equal, toItem: containerView, attribute: .leading, multiplier: 1.00, constant: 0.0) - let trailing = NSLayoutConstraint(item: maskingView, attribute: .trailing, relatedBy: .equal, toItem: containerView, attribute: .trailing, multiplier: 1.00, constant: 0.0) - let top = topLayoutConstraint(view: maskingView, containerView: containerView, viewController: presentationContext.viewControllerValue()) - let bottom = bottomLayoutConstraint(view: maskingView, containerView: containerView, viewController: presentationContext.viewControllerValue()) - containerView.addConstraints([top, leading, bottom, trailing]) - } - do { - view.translatesAutoresizingMaskIntoConstraints = false - maskingView.addSubview(view) - let leading = NSLayoutConstraint(item: view, attribute: .leading, relatedBy: .equal, toItem: maskingView, attribute: .leading, multiplier: 1.00, constant: 0.0) - let trailing = NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: maskingView, attribute: .trailing, multiplier: 1.00, constant: 0.0) - switch config.presentationStyle { - case .top: - translationConstraint = NSLayoutConstraint(item: view, attribute: .top, relatedBy: .equal, toItem: maskingView, attribute: .top, multiplier: 1.00, constant: 0.0) - case .bottom: - translationConstraint = NSLayoutConstraint(item: maskingView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.00, constant: 0.0) - } - maskingView.addConstraints([leading, trailing, translationConstraint]) - if let adjustable = view as? MarginAdjustable { - var top: CGFloat = 0.0 - var bottom: CGFloat = 0.0 - switch config.presentationStyle { - case .top: - top += adjustable.bounceAnimationOffset - if !UIApplication.shared.isStatusBarHidden { - if let vc = presentationContext.viewControllerValue() as? WindowViewController { - if vc.windowLevel == UIWindowLevelNormal { - top += adjustable.statusBarOffset - } - } else if let vc = presentationContext.viewControllerValue() as? UINavigationController, !vc.sm_isVisible(view: vc.navigationBar) { - top += adjustable.statusBarOffset - } - } - case .bottom: - bottom += adjustable.bounceAnimationOffset - } - view.layoutMargins = UIEdgeInsets(top: top, left: 0.0, bottom: bottom, right: 0.0) - } - let size = view.systemLayoutSizeFitting(UILayoutFittingCompressedSize) - translationConstraint.constant -= size.height - } - containerView.layoutIfNeeded() - if config.interactiveHide { - view.addGestureRecognizer(panRecognizer) - } - do { - - func setupInteractive(_ interactive: Bool) { - if interactive { - maskingView.tappedHander = { [weak self] in - guard let strongSelf = self else { return } - self?.delegate?.hide(presenter: strongSelf) - } + if self.config.dimMode.modal { + self.showAccessibilityFocus() } else { - // There's no action to take, but the presence of - // a tap handler prevents interaction with underlying views. - maskingView.tappedHander = { } + self.showAccessibilityAnnouncement() } + self.config.eventListeners.forEach { $0(.didShow(self.view)) } } - - switch config.dimMode { - case .none: - break - case .gray(let interactive): - setupInteractive(interactive) - case .color(_, let interactive): - setupInteractive(interactive) - } - } - } - - func topLayoutConstraint(view: UIView, containerView: UIView, viewController: UIViewController?) -> NSLayoutConstraint { - if case .top = config.presentationStyle, let nav = viewController as? UINavigationController, nav.sm_isVisible(view: nav.navigationBar) { - return NSLayoutConstraint(item: view, attribute: .top, relatedBy: .equal, toItem: nav.navigationBar, attribute: .bottom, multiplier: 1.00, constant: 0.0) - } - return NSLayoutConstraint(item: view, attribute: .top, relatedBy: .equal, toItem: containerView, attribute: .top, multiplier: 1.00, constant: 0.0) - } - - func bottomLayoutConstraint(view: UIView, containerView: UIView, viewController: UIViewController?) -> NSLayoutConstraint { - if case .bottom = config.presentationStyle, let tab = viewController as? UITabBarController, tab.sm_isVisible(view: tab.tabBar) { - return NSLayoutConstraint(item: view, attribute: .bottom, relatedBy: .equal, toItem: tab.tabBar, attribute: .top, multiplier: 1.00, constant: 0.0) } - return NSLayoutConstraint(item: view, attribute: .bottom, relatedBy: .equal, toItem: containerView, attribute: .bottom, multiplier: 1.00, constant: 0.0) } - - /* - MARK: - Showing and hiding - */ - func showAnimation(completion: @escaping (_ completed: Bool) -> Void) { + private func showAnimation(completion: @escaping AnimationCompletion) { - showViewAnimation(completion: completion) - func dim(_ color: UIColor) { self.maskingView.backgroundColor = UIColor.clear UIView.animate(withDuration: 0.2, animations: { @@ -239,6 +158,19 @@ class Presenter: NSObject, UIGestureRecognizerDelegate { }) } + func blur(style: UIBlurEffect.Style, alpha: CGFloat) { + let blurView = UIVisualEffectView(effect: nil) + blurView.alpha = alpha + maskingView.backgroundView = blurView + UIView.animate(withDuration: 0.3) { + blurView.effect = UIBlurEffect(style: style) + } + } + + let context = animationContext() + animator.show(context: context) { (completed) in + completion(completed) + } switch config.dimMode { case .none: break @@ -246,66 +178,54 @@ class Presenter: NSObject, UIGestureRecognizerDelegate { dim(UIColor(white: 0, alpha: 0.3)) case .color(let color, _): dim(color) + case .blur(let style, let alpha, _): + blur(style: style, alpha: alpha) } } - func showViewAnimation(completion: @escaping (_ completed: Bool) -> Void) { - switch config.presentationStyle { - case .top, .bottom: - let animationDistance = self.translationConstraint.constant + bounceOffset - // Cap the initial velocity at zero because the bounceOffset may not be great - // enough to allow for greater bounce induced by a quick panning motion. - let initialSpringVelocity = animationDistance == 0.0 ? 0.0 : min(0.0, closeSpeed / animationDistance) - UIView.animate(withDuration: 0.4, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: initialSpringVelocity, options: [.beginFromCurrentState, .curveLinear, .allowUserInteraction], animations: { - self.translationConstraint.constant = -self.bounceOffset - self.view.superview?.layoutIfNeeded() - }, completion: { completed in - completion(completed) - }) - } + private func showAccessibilityAnnouncement() { + guard let accessibleMessage = view as? AccessibleMessage, + let message = accessibleMessage.accessibilityMessage else { return } + UIAccessibility.post(notification: UIAccessibility.Notification.announcement, argument: message) } - func hide(completion: @escaping (_ completed: Bool) -> Void) { - self.config.eventListeners.forEach { $0(.willHide) } - switch config.presentationStyle { - case .top, .bottom: - UIView.animate(withDuration: 0.2, delay: 0, options: [.beginFromCurrentState, .curveEaseIn], animations: { - let size = self.view.systemLayoutSizeFitting(UILayoutFittingCompressedSize) - self.translationConstraint.constant -= size.height - self.view.superview?.layoutIfNeeded() - }, completion: { completed in - if let viewController = self.presentationContext.viewControllerValue() as? WindowViewController { - viewController.uninstall() - } - self.maskingView.removeFromSuperview() - completion(completed) - if completed { - self.config.eventListeners.forEach { $0(.didHide) } - } - }) -// TODO the spring animation makes the interactive hide transition smoother, but -// TODO the added delay due to damping makes status bar style transitions look bad. -// TODO need to find an animation technique that accommodates both concerns. -// let size = self.view.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize) -// // Travel a bit further to account for possible drop shadow -// let translationDistance = size.height - panTranslationY -// let initialSpringVelocity = size.height == 0.0 ? 0.0 : closeSpeed / translationDistance -// UIView.animateWithDuration(0.35, delay: 0, usingSpringWithDamping: 1.0, initialSpringVelocity: initialSpringVelocity, options: [.BeginFromCurrentState, .CurveLinear], animations: { -// self.translationConstraint.constant -= translationDistance -// self.view.superview?.layoutIfNeeded() -// }, completion: { (completed) in -// if let viewController = self.presentationContext.value as? WindowViewController { -// viewController.uninstall() -// } -// self.maskingView.removeFromSuperview() -// completion(completed: completed) -// }) + private func showAccessibilityFocus() { + guard let accessibleMessage = view as? AccessibleMessage, + let focus = accessibleMessage.accessibilityElement ?? accessibleMessage.additionalAccessibilityElements?.first else { return } + UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: focus) + } + + func hide(animated: Bool, completion: @escaping AnimationCompletion) { + isHiding = true + self.config.eventListeners.forEach { $0(.willHide(self.view)) } + let context = animationContext() + let action = { + if let viewController = self.presentationContext.viewControllerValue() as? WindowViewController { + viewController.uninstall() + } + self.maskingView.removeFromSuperview() + completion(true) + self.config.eventListeners.forEach { $0(.didHide(self.view)) } } - + guard animated else { + action() + return + } + animator.hide(context: context) { (completed) in + action() + } + func undim() { - UIView.animate(withDuration: 0.2, animations: { + UIView.animate(withDuration: 0.2, delay: 0, options: .beginFromCurrentState, animations: { self.maskingView.backgroundColor = UIColor.clear - }) + }, completion: nil) + } + + func unblur() { + guard let view = maskingView.backgroundView as? UIVisualEffectView else { return } + UIView.animate(withDuration: 0.2, delay: 0, options: .beginFromCurrentState, animations: { + view.effect = nil + }, completion: nil) } switch config.dimMode { @@ -315,92 +235,193 @@ class Presenter: NSObject, UIGestureRecognizerDelegate { undim() case .color: undim() + case .blur: + unblur() } } - - fileprivate var bounceOffset: CGFloat { - var bounceOffset: CGFloat = 5.0 - if let adjustable = view as? MarginAdjustable { - bounceOffset = adjustable.bounceAnimationOffset - } - return bounceOffset + + private func animationContext() -> AnimationContext { + return AnimationContext(messageView: view, containerView: maskingView, safeZoneConflicts: safeZoneConflicts(), interactiveHide: config.interactiveHide) } - - /* - MARK: - Swipe to close - */ - - fileprivate var closing = false - fileprivate var closeSpeed: CGFloat = 0.0 - fileprivate var closePercent: CGFloat = 0.0 - fileprivate var panTranslationY: CGFloat = 0.0 - - @objc func pan(_ pan: UIPanGestureRecognizer) { - switch pan.state { - case .changed: - let backgroundView = panBackgroundView - let backgroundHeight = backgroundView.bounds.height - bounceOffset - if backgroundHeight <= 0 { return } - let point = pan.location(ofTouch: 0, in: backgroundView) - var velocity = pan.velocity(in: backgroundView) - var translation = pan.translation(in: backgroundView) - if case .top = config.presentationStyle { - velocity.y *= -1.0 - translation.y *= -1.0 - } - if !closing { - if backgroundView.bounds.contains(point) && velocity.y > 0.0 && velocity.x / velocity.y < 5.0 { - closing = true - pan.setTranslation(CGPoint.zero, in: backgroundView) - delegate?.panStarted(presenter: self) - } + + private func safeZoneConflicts() -> SafeZoneConflicts { + guard let _ = maskingView.window else { return [] } + let windowLevel: UIWindow.Level = { + if let vc = presentationContext.viewControllerValue() as? WindowViewController { + return vc.config.windowLevel ?? .normal } - if !closing { return } - let translationAmount = -bounceOffset - max(0.0, translation.y) - translationConstraint.constant = translationAmount - closeSpeed = velocity.y - closePercent = translation.y / backgroundHeight - panTranslationY = translation.y - case .ended, .cancelled: - if closeSpeed > 750.0 || closePercent > 0.33 { - delegate?.hide(presenter: self) + return .normal + }() + // TODO `underNavigationBar` and `underTabBar` should look up the presentation context's hierarchy + // TODO for cases where both should be true (probably not an issue for typical height messages, though). + let underNavigationBar: Bool = { + if let vc = presentationContext.viewControllerValue() as? UINavigationController { return vc.sm_isVisible(view: vc.navigationBar) } + return false + }() + let underTabBar: Bool = { + if let vc = presentationContext.viewControllerValue() as? UITabBarController { return vc.sm_isVisible(view: vc.tabBar) } + return false + }() + 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 { - closing = false - closeSpeed = 0.0 - closePercent = 0.0 - panTranslationY = 0.0 - showViewAnimation(completion: { (completed) in - self.delegate?.panEnded(presenter: self) - }) + var conflicts: SafeZoneConflicts = [] + if maskingView.safeAreaInsets.top > 0 { + conflicts.formUnion(.sensorNotch) + } + if maskingView.safeAreaInsets.bottom > 0 { + conflicts.formUnion(.homeIndicator) + } + return conflicts } - default: - break } + var conflicts: SafeZoneConflicts = [] + if !underNavigationBar { + conflicts.formUnion(.sensorNotch) + } + if !underTabBar { + conflicts.formUnion(.homeIndicator) + } + return conflicts } - fileprivate var panBackgroundView: UIView { - if let view = view as? BackgroundViewable { - return view.backgroundView - } else { - return view + private func getPresentationContext() throws -> PresentationContext { + + func newWindowViewController() -> UIViewController { + let viewController = WindowViewController.newInstance(config: config) + return viewController + } + + switch config.presentationContext { + case .automatic: + #if SWIFTMESSAGES_APP_EXTENSIONS + throw SwiftMessagesError.noRootViewController + #else + if let rootViewController = UIWindow.keyWindow?.rootViewController { + let viewController = rootViewController.sm_selectPresentationContextTopDown(config) + return .viewController(Weak(value: viewController)) + } else { + throw SwiftMessagesError.noRootViewController + } + #endif + case .window: + let viewController = newWindowViewController() + return .viewController(Weak(value: viewController)) + case .windowScene: + let viewController = newWindowViewController() + return .viewController(Weak(value: viewController)) + case .viewController(let viewController): + let viewController = viewController.sm_selectPresentationContextBottomUp(config) + return .viewController(Weak(value: viewController)) + case .view(let view): + return .view(Weak(value: view)) } } - - fileprivate func shouldBeginPan(_ pan: UIGestureRecognizer) -> Bool { - let backgroundView = panBackgroundView - let point = pan.location(ofTouch: 0, in: backgroundView) - return backgroundView.bounds.contains(point) - } - + /* - MARK: - UIGestureRecognizerDelegate + MARK: - Installation */ - - func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { - if gestureRecognizer == panRecognizer { - return shouldBeginPan(gestureRecognizer) + + func install() { + + func topLayoutConstraint(view: UIView, containerView: UIView, viewController: UIViewController?) -> NSLayoutConstraint { + if case .top = config.presentationStyle.topBottomStyle, let nav = viewController as? UINavigationController, nav.sm_isVisible(view: nav.navigationBar) { + return NSLayoutConstraint(item: view, attribute: .top, relatedBy: .equal, toItem: nav.navigationBar, attribute: .bottom, multiplier: 1.00, constant: 0.0) + } + return NSLayoutConstraint(item: view, attribute: .top, relatedBy: .equal, toItem: containerView, attribute: .top, multiplier: 1.00, constant: 0.0) + } + + func bottomLayoutConstraint(view: UIView, containerView: UIView, viewController: UIViewController?) -> NSLayoutConstraint { + if case .bottom = config.presentationStyle.topBottomStyle, let tab = viewController as? UITabBarController, tab.sm_isVisible(view: tab.tabBar) { + return NSLayoutConstraint(item: view, attribute: .bottom, relatedBy: .equal, toItem: tab.tabBar, attribute: .top, multiplier: 1.00, constant: 0.0) + } + return NSLayoutConstraint(item: view, attribute: .bottom, relatedBy: .equal, toItem: containerView, attribute: .bottom, multiplier: 1.00, constant: 0.0) + } + + func installMaskingView(containerView: UIView) { + maskingView.translatesAutoresizingMaskIntoConstraints = false + if let nav = presentationContext.viewControllerValue() as? UINavigationController { + containerView.insertSubview(maskingView, belowSubview: nav.navigationBar) + } else if let tab = presentationContext.viewControllerValue() as? UITabBarController { + containerView.insertSubview(maskingView, belowSubview: tab.tabBar) + } else { + containerView.addSubview(maskingView) + } + maskingView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true + maskingView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true + topLayoutConstraint(view: maskingView, containerView: containerView, viewController: presentationContext.viewControllerValue()).isActive = true + bottomLayoutConstraint(view: maskingView, containerView: containerView, viewController: presentationContext.viewControllerValue()).isActive = true + if let keyboardTrackingView = config.keyboardTrackingView { + maskingView.install(keyboardTrackingView: keyboardTrackingView) + } + // Update the container view's layout in order to know the masking view's frame + containerView.layoutIfNeeded() } - return true + + func installInteractive() { + guard config.dimMode.modal else { return } + if config.dimMode.interactive { + maskingView.tappedHander = { [weak self] in + guard let strongSelf = self else { return } + strongSelf.interactivelyHidden = true + strongSelf.delegate?.hide(presenter: strongSelf) + } + } else { + // There's no action to take, but the presence of + // a tap handler prevents interaction with underlying views. + maskingView.tappedHander = { } + } + } + + func installAccessibility() { + var elements: [NSObject] = [] + if let accessibleMessage = view as? AccessibleMessage { + if let message = accessibleMessage.accessibilityMessage { + let element = accessibleMessage.accessibilityElement ?? view + element.isAccessibilityElement = true + if element.accessibilityLabel == nil { + element.accessibilityLabel = message + } + elements.append(element) + } + if let additional = accessibleMessage.additionalAccessibilityElements { + elements += additional + } + } else { + elements += [view] + } + if config.dimMode.interactive { + let dismissView = UIView(frame: maskingView.bounds) + dismissView.translatesAutoresizingMaskIntoConstraints = true + dismissView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + maskingView.addSubview(dismissView) + maskingView.sendSubviewToBack(dismissView) + dismissView.isUserInteractionEnabled = false + dismissView.isAccessibilityElement = true + dismissView.accessibilityLabel = config.dimModeAccessibilityLabel + dismissView.accessibilityTraits = UIAccessibilityTraits.button + elements.append(dismissView) + } + if config.dimMode.modal { + maskingView.accessibilityViewIsModal = true + } + maskingView.accessibleElements = elements + } + + installed = true + guard let containerView = presentationContext.viewValue() else { return } + (presentationContext.viewControllerValue() as? WindowViewController)?.install() + installMaskingView(containerView: containerView) + installInteractive() + installAccessibility() } } + diff --git a/SwiftMessages/Resources/CardView.xib b/SwiftMessages/Resources/CardView.xib index c03297b7..425a6961 100644 --- a/SwiftMessages/Resources/CardView.xib +++ b/SwiftMessages/Resources/CardView.xib @@ -1,37 +1,54 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11198.2" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> + <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> - <deployment version="2304" identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/> - <capability name="Constraints to layout margins" minToolsVersion="6.0"/> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> - <view contentMode="scaleToFill" id="JI3-gM-XBO" userLabel="Card View" customClass="MessageView" customModule="SwiftMessages"> - <rect key="frame" x="0.0" y="0.0" width="600" height="161"/> + <view contentMode="scaleToFill" id="uEa-1P-F1Y" userLabel="Card View" customClass="MessageView" customModule="SwiftMessages"> + <rect key="frame" x="0.0" y="0.0" width="510" height="160"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dp3-Ae-zep" userLabel="Background view"> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="A7b-0a-fJG" userLabel="Corner rounding view" customClass="CornerRoundingView" customModule="SwiftMessages"> + <rect key="frame" x="20" y="44" width="470" height="82"/> <subviews> - <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="RJH-Fp-YDa" userLabel="Content view"> + <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="SU0-uJ-4pP" userLabel="Content view"> + <rect key="frame" x="20" y="20" width="430" height="42"/> <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="😬" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pFx-Py-lZQ" userLabel="Icon label"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="😬" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="T1i-ce-9y8" userLabel="Icon label"> + <rect key="frame" x="0.0" y="0.0" width="43" height="42"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> <fontDescription key="fontDescription" type="system" pointSize="38"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="errorIcon" translatesAutoresizingMaskIntoConstraints="NO" id="eGt-Nj-7Fu" userLabel="Icon image view"/> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="top" translatesAutoresizingMaskIntoConstraints="NO" id="cJi-r8-oeb"> + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="errorIcon" translatesAutoresizingMaskIntoConstraints="NO" id="RxA-tv-YM7" userLabel="Icon image view"> + <rect key="frame" x="53" y="4" width="33" height="34"/> + </imageView> + <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="i9r-ex-CgT"> + <rect key="frame" x="96" y="2" width="267" height="38.5"/> <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="[Title]" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IWB-BS-FgD"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="[Title]" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8HR-oh-U9F"> + <rect key="frame" x="0.0" y="0.0" width="267" height="20.5"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> <fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="[Message Body]" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gMT-Vh-S3z"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="[Message Body]" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9oc-qg-igL"> + <rect key="frame" x="0.0" y="20.5" width="267" height="18"/> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> <fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> @@ -39,52 +56,92 @@ </subviews> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> </stackView> - <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="252" horizontalCompressionResistancePriority="752" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VUM-rq-TVm"> + <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="252" horizontalCompressionResistancePriority="752" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CxK-Y3-nSI"> + <rect key="frame" x="373" y="6" width="57" height="30"/> <fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/> <state key="normal" title="[Button]"/> </button> </subviews> + <variation key="widthClass=regular" spacing="15"/> </stackView> </subviews> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> - <constraint firstAttribute="bottom" secondItem="RJH-Fp-YDa" secondAttribute="bottom" constant="20" id="3t4-62-KuN"/> - <constraint firstItem="RJH-Fp-YDa" firstAttribute="top" secondItem="dp3-Ae-zep" secondAttribute="top" constant="20" id="6rK-Yv-gKZ"/> - <constraint firstAttribute="trailing" secondItem="RJH-Fp-YDa" secondAttribute="trailing" constant="20" id="dJi-po-g6O"/> - <constraint firstItem="RJH-Fp-YDa" firstAttribute="leading" secondItem="dp3-Ae-zep" secondAttribute="leading" constant="20" id="zmH-aG-8Ij"/> + <constraint firstAttribute="trailing" secondItem="SU0-uJ-4pP" secondAttribute="trailing" constant="20" id="QN2-NH-rWA"/> + <constraint firstItem="SU0-uJ-4pP" firstAttribute="top" secondItem="A7b-0a-fJG" secondAttribute="top" constant="20" id="S9l-zM-0wc"/> + <constraint firstAttribute="bottom" secondItem="SU0-uJ-4pP" secondAttribute="bottom" constant="20" id="YMg-LN-n7f"/> + <constraint firstAttribute="width" relation="lessThanOrEqual" priority="900" constant="500" id="lOa-jP-2uX"/> + <constraint firstItem="SU0-uJ-4pP" firstAttribute="leading" secondItem="A7b-0a-fJG" secondAttribute="leading" constant="20" id="nYJ-Ok-uhC"/> </constraints> <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="5"/> + <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius"> + <real key="value" value="15"/> </userDefinedRuntimeAttribute> </userDefinedRuntimeAttributes> + <variation key="default"> + <mask key="constraints"> + <exclude reference="lOa-jP-2uX"/> + </mask> + </variation> + <variation key="widthClass=regular"> + <mask key="constraints"> + <include reference="lOa-jP-2uX"/> + </mask> + </variation> </view> </subviews> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <constraints> - <constraint firstAttribute="trailing" secondItem="dp3-Ae-zep" secondAttribute="trailing" constant="10" id="gGP-zK-6VU"/> - <constraint firstItem="dp3-Ae-zep" firstAttribute="leading" secondItem="JI3-gM-XBO" secondAttribute="leadingMargin" constant="10" id="gyP-aD-uO3"/> - <constraint firstAttribute="bottom" secondItem="dp3-Ae-zep" secondAttribute="bottom" constant="10" id="le8-gK-lcY"/> - <constraint firstItem="dp3-Ae-zep" firstAttribute="top" secondItem="JI3-gM-XBO" secondAttribute="topMargin" constant="10" id="s15-z9-aHc"/> + <constraint firstItem="A7b-0a-fJG" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="uEa-1P-F1Y" secondAttribute="leadingMargin" priority="900" id="LWV-wo-Jec"/> + <constraint firstAttribute="trailingMargin" secondItem="A7b-0a-fJG" secondAttribute="trailing" priority="900" id="O6e-Yz-cwK"/> + <constraint firstItem="A7b-0a-fJG" firstAttribute="leading" secondItem="uEa-1P-F1Y" secondAttribute="leadingMargin" priority="900" id="RiR-2q-ZY5"/> + <constraint firstItem="A7b-0a-fJG" firstAttribute="centerX" secondItem="uEa-1P-F1Y" secondAttribute="centerX" priority="950" id="jLv-ud-1WD"/> + <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="A7b-0a-fJG" secondAttribute="trailing" priority="900" id="lGg-Ey-I5f"/> + <constraint firstItem="A7b-0a-fJG" firstAttribute="top" secondItem="uEa-1P-F1Y" secondAttribute="topMargin" id="yAH-C4-oUg"/> + <constraint firstAttribute="bottomMargin" secondItem="A7b-0a-fJG" secondAttribute="bottom" id="ygs-aa-zj3"/> </constraints> <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> <userDefinedRuntimeAttributes> <userDefinedRuntimeAttribute type="number" keyPath="bounceAnimationOffset"> <real key="value" value="0.0"/> </userDefinedRuntimeAttribute> - <userDefinedRuntimeAttribute type="number" keyPath="statusBarOffset"> + <userDefinedRuntimeAttribute type="number" keyPath="topLayoutMarginAddition"> <real key="value" value="10"/> </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="leftLayoutMarginAddition"> + <real key="value" value="10"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="bottomLayoutMarginAddition"> + <real key="value" value="10"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="rightLayoutMarginAddition"> + <real key="value" value="10"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="boolean" keyPath="collapseLayoutMarginAdditions" value="YES"/> </userDefinedRuntimeAttributes> + <variation key="default"> + <mask key="constraints"> + <exclude reference="LWV-wo-Jec"/> + <exclude reference="lGg-Ey-I5f"/> + </mask> + </variation> + <variation key="widthClass=regular"> + <mask key="constraints"> + <include reference="LWV-wo-Jec"/> + <exclude reference="O6e-Yz-cwK"/> + <exclude reference="RiR-2q-ZY5"/> + <include reference="lGg-Ey-I5f"/> + </mask> + </variation> <connections> - <outlet property="backgroundView" destination="dp3-Ae-zep" id="ZiK-GN-SXH"/> - <outlet property="bodyLabel" destination="gMT-Vh-S3z" id="BkZ-P0-0dh"/> - <outlet property="button" destination="VUM-rq-TVm" id="7RH-Cf-FAH"/> - <outlet property="iconImageView" destination="eGt-Nj-7Fu" id="N4v-CG-mEM"/> - <outlet property="iconLabel" destination="pFx-Py-lZQ" id="xKK-gA-Otu"/> - <outlet property="titleLabel" destination="IWB-BS-FgD" id="ZFQ-sh-fDL"/> + <outlet property="backgroundView" destination="A7b-0a-fJG" id="R1k-6D-zIA"/> + <outlet property="bodyLabel" destination="9oc-qg-igL" id="ebS-73-kbp"/> + <outlet property="button" destination="CxK-Y3-nSI" id="csj-uy-rHl"/> + <outlet property="iconImageView" destination="RxA-tv-YM7" id="w6j-4o-RnC"/> + <outlet property="iconLabel" destination="T1i-ce-9y8" id="XiD-0J-kdm"/> + <outlet property="titleLabel" destination="8HR-oh-U9F" id="Zbb-wl-ubV"/> </connections> - <point key="canvasLocation" x="360" y="358.5"/> + <point key="canvasLocation" x="510.35156249999994" y="386.96925329428984"/> </view> </objects> <resources> diff --git a/SwiftMessages/Resources/CenteredView.xib b/SwiftMessages/Resources/CenteredView.xib new file mode 100644 index 00000000..a9fda2be --- /dev/null +++ b/SwiftMessages/Resources/CenteredView.xib @@ -0,0 +1,153 @@ +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> + <device id="retina6_1" orientation="portrait" appearance="light"/> + <dependencies> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> + </dependencies> + <objects> + <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> + <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> + <view contentMode="scaleToFill" id="g5x-hF-D0u" userLabel="Centered View" customClass="MessageView" customModule="SwiftMessages"> + <rect key="frame" x="0.0" y="0.0" width="434" height="272"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Mj-jC-BX6" userLabel="Background view" customClass="CornerRoundingView" customModule="SwiftMessages"> + <rect key="frame" x="20" y="44" width="394" height="194"/> + <subviews> + <stackView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="700" axis="vertical" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="YST-yc-0HK" userLabel="Content view"> + <rect key="frame" x="20" y="20" width="354" height="154"/> + <subviews> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="700" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" verticalCompressionResistancePriority="753" text="😬" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="elb-HW-olH" userLabel="Icon label"> + <rect key="frame" x="155.5" y="0.0" width="43" height="45.5"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> + <fontDescription key="fontDescription" type="system" pointSize="38"/> + <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <nil key="highlightedColor"/> + </label> + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="700" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="errorIcon" translatesAutoresizingMaskIntoConstraints="NO" id="hUK-sr-A3U" userLabel="Icon image view"> + <rect key="frame" x="160.5" y="55.5" width="33" height="0.0"/> + </imageView> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="700" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="[Title]" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ggW-gB-SWF"> + <rect key="frame" x="153" y="65.5" width="48.5" height="20.5"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> + <fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/> + <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <nil key="highlightedColor"/> + </label> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="700" verticalHuggingPriority="251" verticalCompressionResistancePriority="752" text="[Message Body]" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TGC-Td-alh"> + <rect key="frame" x="121" y="96" width="112" height="18"/> + <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> + <fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/> + <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <nil key="highlightedColor"/> + </label> + <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="700" horizontalCompressionResistancePriority="752" verticalCompressionResistancePriority="754" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VOA-Iy-PCr"> + <rect key="frame" x="148.5" y="124" width="57" height="30"/> + <fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/> + <state key="normal" title="[Button]"/> + </button> + </subviews> + </stackView> + </subviews> + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <constraints> + <constraint firstItem="YST-yc-0HK" firstAttribute="leading" secondItem="0Mj-jC-BX6" secondAttribute="leading" constant="20" id="BRx-pe-2BP"> + <variation key="widthClass=regular" constant="30"/> + </constraint> + <constraint firstAttribute="trailing" secondItem="YST-yc-0HK" secondAttribute="trailing" constant="20" id="JYB-gw-7Ol"> + <variation key="widthClass=regular" constant="30"/> + </constraint> + <constraint firstAttribute="bottom" secondItem="YST-yc-0HK" secondAttribute="bottom" constant="20" id="Vsy-Y9-qzf"> + <variation key="widthClass=regular" constant="30"/> + </constraint> + <constraint firstAttribute="width" relation="lessThanOrEqual" priority="900" constant="500" id="Y89-EE-TtG"/> + <constraint firstItem="YST-yc-0HK" firstAttribute="top" secondItem="0Mj-jC-BX6" secondAttribute="top" constant="20" id="yRl-kK-cQH"> + <variation key="widthClass=regular" constant="30"/> + </constraint> + </constraints> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius"> + <real key="value" value="15"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <variation key="default"> + <mask key="constraints"> + <exclude reference="Y89-EE-TtG"/> + </mask> + </variation> + <variation key="widthClass=regular"> + <mask key="constraints"> + <exclude reference="Y89-EE-TtG"/> + </mask> + </variation> + </view> + </subviews> + <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> + <constraints> + <constraint firstItem="0Mj-jC-BX6" firstAttribute="top" secondItem="g5x-hF-D0u" secondAttribute="topMargin" id="GWI-aH-o7P"/> + <constraint firstItem="0Mj-jC-BX6" firstAttribute="centerX" secondItem="g5x-hF-D0u" secondAttribute="centerX" priority="950" id="XqM-pB-dF4"/> + <constraint firstItem="0Mj-jC-BX6" firstAttribute="leading" secondItem="g5x-hF-D0u" secondAttribute="leadingMargin" priority="900" id="bQ3-k8-0v0"/> + <constraint firstItem="0Mj-jC-BX6" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="g5x-hF-D0u" secondAttribute="leadingMargin" priority="900" id="iGY-na-87c"/> + <constraint firstAttribute="trailingMargin" secondItem="0Mj-jC-BX6" secondAttribute="trailing" priority="900" id="rSj-h2-U7z"/> + <constraint firstAttribute="bottomMargin" secondItem="0Mj-jC-BX6" secondAttribute="bottom" id="wRH-k8-J8S"/> + <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="0Mj-jC-BX6" secondAttribute="trailing" priority="900" id="xAq-z5-Gur"/> + </constraints> + <nil key="simulatedTopBarMetrics"/> + <nil key="simulatedBottomBarMetrics"/> + <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="bounceAnimationOffset"> + <real key="value" value="0.0"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="topLayoutMarginAddition"> + <real key="value" value="10"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="leftLayoutMarginAddition"> + <real key="value" value="10"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="bottomLayoutMarginAddition"> + <real key="value" value="10"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="rightLayoutMarginAddition"> + <real key="value" value="10"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="boolean" keyPath="collapseLayoutMarginAdditions" value="YES"/> + </userDefinedRuntimeAttributes> + <variation key="default"> + <mask key="constraints"> + <exclude reference="iGY-na-87c"/> + <exclude reference="xAq-z5-Gur"/> + </mask> + </variation> + <variation key="widthClass=regular"> + <mask key="constraints"> + <exclude reference="bQ3-k8-0v0"/> + <include reference="iGY-na-87c"/> + <exclude reference="rSj-h2-U7z"/> + <include reference="xAq-z5-Gur"/> + </mask> + </variation> + <connections> + <outlet property="backgroundView" destination="0Mj-jC-BX6" id="idD-fU-aXH"/> + <outlet property="bodyLabel" destination="TGC-Td-alh" id="swz-Qb-Dxw"/> + <outlet property="button" destination="VOA-Iy-PCr" id="LGs-Ax-1Ds"/> + <outlet property="iconImageView" destination="hUK-sr-A3U" id="Htw-4A-Adn"/> + <outlet property="iconLabel" destination="elb-HW-olH" id="JXQ-xt-3t7"/> + <outlet property="titleLabel" destination="ggW-gB-SWF" id="Coi-Gy-uPh"/> + </connections> + <point key="canvasLocation" x="368.5546875" y="347.4377745241581"/> + </view> + </objects> + <resources> + <image name="errorIcon" width="33" height="34"/> + </resources> +</document> diff --git a/SwiftMessages/Resources/Images.xcassets/Contents.json b/SwiftMessages/Resources/Images.xcassets/Contents.json deleted file mode 100644 index da4a164c..00000000 --- a/SwiftMessages/Resources/Images.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/SwiftMessages/Resources/Images.xcassets/errorIcon.imageset/Contents.json b/SwiftMessages/Resources/Images.xcassets/errorIcon.imageset/Contents.json deleted file mode 100644 index fa61713f..00000000 --- a/SwiftMessages/Resources/Images.xcassets/errorIcon.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "errorIcon.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "template-rendering-intent" : "template" - } -} \ No newline at end of file diff --git a/SwiftMessages/Resources/Images.xcassets/errorIcon.imageset/errorIcon.pdf b/SwiftMessages/Resources/Images.xcassets/errorIcon.imageset/errorIcon.pdf deleted file mode 100644 index 186638c2..00000000 Binary files a/SwiftMessages/Resources/Images.xcassets/errorIcon.imageset/errorIcon.pdf and /dev/null differ diff --git a/SwiftMessages/Resources/Images.xcassets/errorIconLight.imageset/Contents.json b/SwiftMessages/Resources/Images.xcassets/errorIconLight.imageset/Contents.json deleted file mode 100644 index 2f501a23..00000000 --- a/SwiftMessages/Resources/Images.xcassets/errorIconLight.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "errorIconLight.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "template-rendering-intent" : "template" - } -} \ No newline at end of file diff --git a/SwiftMessages/Resources/Images.xcassets/errorIconLight.imageset/errorIconLight.pdf b/SwiftMessages/Resources/Images.xcassets/errorIconLight.imageset/errorIconLight.pdf deleted file mode 100644 index 27cb6b8c..00000000 Binary files a/SwiftMessages/Resources/Images.xcassets/errorIconLight.imageset/errorIconLight.pdf and /dev/null differ diff --git a/SwiftMessages/Resources/Images.xcassets/errorIconSubtle.imageset/Contents.json b/SwiftMessages/Resources/Images.xcassets/errorIconSubtle.imageset/Contents.json deleted file mode 100644 index e6b30b25..00000000 --- a/SwiftMessages/Resources/Images.xcassets/errorIconSubtle.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "errorIconSubtle.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "template-rendering-intent" : "template" - } -} \ No newline at end of file diff --git a/SwiftMessages/Resources/Images.xcassets/errorIconSubtle.imageset/errorIconSubtle.pdf b/SwiftMessages/Resources/Images.xcassets/errorIconSubtle.imageset/errorIconSubtle.pdf deleted file mode 100644 index a0ab3628..00000000 Binary files a/SwiftMessages/Resources/Images.xcassets/errorIconSubtle.imageset/errorIconSubtle.pdf and /dev/null differ diff --git a/SwiftMessages/Resources/Images.xcassets/infoIcon.imageset/infoIcon.pdf b/SwiftMessages/Resources/Images.xcassets/infoIcon.imageset/infoIcon.pdf deleted file mode 100644 index 120bd67a..00000000 Binary files a/SwiftMessages/Resources/Images.xcassets/infoIcon.imageset/infoIcon.pdf and /dev/null differ diff --git a/SwiftMessages/Resources/Images.xcassets/infoIconLight.imageset/Contents.json b/SwiftMessages/Resources/Images.xcassets/infoIconLight.imageset/Contents.json deleted file mode 100644 index 1b87f941..00000000 --- a/SwiftMessages/Resources/Images.xcassets/infoIconLight.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "infoIconLight.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "template-rendering-intent" : "template" - } -} \ No newline at end of file diff --git a/SwiftMessages/Resources/Images.xcassets/infoIconLight.imageset/infoIconLight.pdf b/SwiftMessages/Resources/Images.xcassets/infoIconLight.imageset/infoIconLight.pdf deleted file mode 100644 index afab1871..00000000 Binary files a/SwiftMessages/Resources/Images.xcassets/infoIconLight.imageset/infoIconLight.pdf and /dev/null differ diff --git a/SwiftMessages/Resources/Images.xcassets/infoIconSubtle.imageset/Contents.json b/SwiftMessages/Resources/Images.xcassets/infoIconSubtle.imageset/Contents.json deleted file mode 100644 index 6e3f345b..00000000 --- a/SwiftMessages/Resources/Images.xcassets/infoIconSubtle.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "infoIconSubtle.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "template-rendering-intent" : "template" - } -} \ No newline at end of file diff --git a/SwiftMessages/Resources/Images.xcassets/infoIconSubtle.imageset/infoIconSubtle.pdf b/SwiftMessages/Resources/Images.xcassets/infoIconSubtle.imageset/infoIconSubtle.pdf deleted file mode 100644 index 9aa3443d..00000000 Binary files a/SwiftMessages/Resources/Images.xcassets/infoIconSubtle.imageset/infoIconSubtle.pdf and /dev/null differ diff --git a/SwiftMessages/Resources/Images.xcassets/successIcon.imageset/Contents.json b/SwiftMessages/Resources/Images.xcassets/successIcon.imageset/Contents.json deleted file mode 100644 index 6c462cde..00000000 --- a/SwiftMessages/Resources/Images.xcassets/successIcon.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "successIcon.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "template-rendering-intent" : "template" - } -} \ No newline at end of file diff --git a/SwiftMessages/Resources/Images.xcassets/successIcon.imageset/successIcon.pdf b/SwiftMessages/Resources/Images.xcassets/successIcon.imageset/successIcon.pdf deleted file mode 100644 index 2141b427..00000000 Binary files a/SwiftMessages/Resources/Images.xcassets/successIcon.imageset/successIcon.pdf and /dev/null differ diff --git a/SwiftMessages/Resources/Images.xcassets/successIconLight.imageset/Contents.json b/SwiftMessages/Resources/Images.xcassets/successIconLight.imageset/Contents.json deleted file mode 100644 index 2119691e..00000000 --- a/SwiftMessages/Resources/Images.xcassets/successIconLight.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "successIconLight.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "template-rendering-intent" : "template" - } -} \ No newline at end of file diff --git a/SwiftMessages/Resources/Images.xcassets/successIconLight.imageset/successIconLight.pdf b/SwiftMessages/Resources/Images.xcassets/successIconLight.imageset/successIconLight.pdf deleted file mode 100644 index 91293032..00000000 Binary files a/SwiftMessages/Resources/Images.xcassets/successIconLight.imageset/successIconLight.pdf and /dev/null differ diff --git a/SwiftMessages/Resources/Images.xcassets/successIconSubtle.imageset/Contents.json b/SwiftMessages/Resources/Images.xcassets/successIconSubtle.imageset/Contents.json deleted file mode 100644 index 82a84d16..00000000 --- a/SwiftMessages/Resources/Images.xcassets/successIconSubtle.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "successIconSubtle.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "template-rendering-intent" : "template" - } -} \ No newline at end of file diff --git a/SwiftMessages/Resources/Images.xcassets/successIconSubtle.imageset/successIconSubtle.pdf b/SwiftMessages/Resources/Images.xcassets/successIconSubtle.imageset/successIconSubtle.pdf deleted file mode 100644 index 86052549..00000000 Binary files a/SwiftMessages/Resources/Images.xcassets/successIconSubtle.imageset/successIconSubtle.pdf and /dev/null differ diff --git a/SwiftMessages/Resources/Images.xcassets/warningIcon.imageset/Contents.json b/SwiftMessages/Resources/Images.xcassets/warningIcon.imageset/Contents.json deleted file mode 100644 index 602136f4..00000000 --- a/SwiftMessages/Resources/Images.xcassets/warningIcon.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "warningIcon.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "template-rendering-intent" : "template" - } -} \ No newline at end of file diff --git a/SwiftMessages/Resources/Images.xcassets/warningIcon.imageset/warningIcon.pdf b/SwiftMessages/Resources/Images.xcassets/warningIcon.imageset/warningIcon.pdf deleted file mode 100644 index 570e8bf6..00000000 Binary files a/SwiftMessages/Resources/Images.xcassets/warningIcon.imageset/warningIcon.pdf and /dev/null differ diff --git a/SwiftMessages/Resources/Images.xcassets/warningIconLight.imageset/Contents.json b/SwiftMessages/Resources/Images.xcassets/warningIconLight.imageset/Contents.json deleted file mode 100644 index a74cbdf3..00000000 --- a/SwiftMessages/Resources/Images.xcassets/warningIconLight.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "warningIconLight.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "template-rendering-intent" : "template" - } -} \ No newline at end of file diff --git a/SwiftMessages/Resources/Images.xcassets/warningIconLight.imageset/warningIconLight.pdf b/SwiftMessages/Resources/Images.xcassets/warningIconLight.imageset/warningIconLight.pdf deleted file mode 100644 index 32310ae5..00000000 Binary files a/SwiftMessages/Resources/Images.xcassets/warningIconLight.imageset/warningIconLight.pdf and /dev/null differ diff --git a/SwiftMessages/Resources/Images.xcassets/warningIconSubtle.imageset/Contents.json b/SwiftMessages/Resources/Images.xcassets/warningIconSubtle.imageset/Contents.json deleted file mode 100644 index d3f2dc56..00000000 --- a/SwiftMessages/Resources/Images.xcassets/warningIconSubtle.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "warningIconSubtle.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "template-rendering-intent" : "template" - } -} \ No newline at end of file diff --git a/SwiftMessages/Resources/Images.xcassets/warningIconSubtle.imageset/warningIconSubtle.pdf b/SwiftMessages/Resources/Images.xcassets/warningIconSubtle.imageset/warningIconSubtle.pdf deleted file mode 100644 index 0ad367ec..00000000 Binary files a/SwiftMessages/Resources/Images.xcassets/warningIconSubtle.imageset/warningIconSubtle.pdf and /dev/null differ diff --git a/SwiftMessages/Resources/MessageView.xib b/SwiftMessages/Resources/MessageView.xib index c063e18e..52ceaa7d 100644 --- a/SwiftMessages/Resources/MessageView.xib +++ b/SwiftMessages/Resources/MessageView.xib @@ -1,34 +1,50 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11198.2" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> + <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> - <deployment version="2304" identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/> - <capability name="Constraints to layout margins" minToolsVersion="6.0"/> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17126"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="MessageView" customModule="SwiftMessages"> - <rect key="frame" x="0.0" y="0.0" width="600" height="103"/> + <rect key="frame" x="0.0" y="0.0" width="600" height="154"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Nx9-Zd-fca"> + <rect key="frame" x="20" y="44" width="560" height="76"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="😬" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1Bu-DY-qZo" userLabel="Icon label"> + <rect key="frame" x="0.0" y="15.5" width="43" height="45.5"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> <fontDescription key="fontDescription" type="system" pointSize="38"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="errorIcon" translatesAutoresizingMaskIntoConstraints="NO" id="PbA-QP-XpA" userLabel="Icon image view"/> + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="errorIcon" translatesAutoresizingMaskIntoConstraints="NO" id="PbA-QP-XpA" userLabel="Icon image view"> + <rect key="frame" x="53" y="21" width="33" height="34"/> + </imageView> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="MKC-Mf-yZN"> + <rect key="frame" x="96" y="16.5" width="397" height="43.5"/> <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="[Title]" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8T6-4T-ytS"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="[Title]" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8T6-4T-ytS"> + <rect key="frame" x="0.0" y="0.0" width="397" height="20.5"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> <fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="[Message Body]" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dFP-4Z-N2a"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="[Message Body]" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dFP-4Z-N2a"> + <rect key="frame" x="0.0" y="25.5" width="397" height="18"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> <fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> @@ -36,29 +52,41 @@ </subviews> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> </stackView> - <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="252" horizontalCompressionResistancePriority="752" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VCW-IQ-FfQ"> + <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="252" horizontalCompressionResistancePriority="752" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VCW-IQ-FfQ"> + <rect key="frame" x="503" y="23" width="57" height="30"/> <fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/> <state key="normal" title="[Button]"/> </button> </subviews> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> + <variation key="widthClass=regular" spacing="15"/> </stackView> </subviews> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> - <constraint firstAttribute="trailing" secondItem="Nx9-Zd-fca" secondAttribute="trailing" constant="20" id="4sW-g4-sKy"/> - <constraint firstAttribute="bottomMargin" secondItem="Nx9-Zd-fca" secondAttribute="bottom" constant="20" id="SPZ-ev-Lj3"/> - <constraint firstItem="Nx9-Zd-fca" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="topMargin" constant="20" id="UDP-8w-ZKv"/> - <constraint firstItem="Nx9-Zd-fca" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leadingMargin" constant="20" id="jKx-hQ-JzW"/> + <constraint firstAttribute="trailingMargin" secondItem="Nx9-Zd-fca" secondAttribute="trailing" id="4sW-g4-sKy"/> + <constraint firstAttribute="bottomMargin" secondItem="Nx9-Zd-fca" secondAttribute="bottom" id="SPZ-ev-Lj3"/> + <constraint firstItem="Nx9-Zd-fca" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="topMargin" id="UDP-8w-ZKv"/> + <constraint firstItem="Nx9-Zd-fca" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leadingMargin" id="jKx-hQ-JzW"/> </constraints> <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> <userDefinedRuntimeAttributes> <userDefinedRuntimeAttribute type="number" keyPath="bounceAnimationOffset"> <real key="value" value="5"/> </userDefinedRuntimeAttribute> - <userDefinedRuntimeAttribute type="number" keyPath="statusBarOffset"> - <real key="value" value="8"/> + <userDefinedRuntimeAttribute type="number" keyPath="topLayoutMarginAddition"> + <real key="value" value="20"/> </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="leftLayoutMarginAddition"> + <real key="value" value="20"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="bottomLayoutMarginAddition"> + <real key="value" value="20"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="rightLayoutMarginAddition"> + <real key="value" value="20"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="boolean" keyPath="collapseLayoutMarginAdditions" value="NO"/> </userDefinedRuntimeAttributes> <connections> <outlet property="bodyLabel" destination="dFP-4Z-N2a" id="xf2-M7-BfM"/> @@ -67,7 +95,7 @@ <outlet property="iconLabel" destination="1Bu-DY-qZo" id="PWN-yD-bZu"/> <outlet property="titleLabel" destination="8T6-4T-ytS" id="ZfL-Z3-Gk0"/> </connections> - <point key="canvasLocation" x="360" y="352.5"/> + <point key="canvasLocation" x="359.4202898550725" y="334.15178571428572"/> </view> </objects> <resources> diff --git a/SwiftMessages/Resources/MessageViewIOS8.xib b/SwiftMessages/Resources/MessageViewIOS8.xib deleted file mode 100644 index 1a2a9d54..00000000 --- a/SwiftMessages/Resources/MessageViewIOS8.xib +++ /dev/null @@ -1,94 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11198.2" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> - <dependencies> - <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/> - <capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/> - <capability name="Constraints to layout margins" minToolsVersion="6.0"/> - <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> - </dependencies> - <objects> - <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> - <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> - <view contentMode="scaleToFill" id="D36-3K-dlr" customClass="MessageView" customModule="SwiftMessages" customModuleProvider="target"> - <rect key="frame" x="0.0" y="0.0" width="600" height="103"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <subviews> - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4g0-UX-cgn" userLabel="Content view"> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="😬" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hN0-co-Tho" userLabel="Icon label"> - <fontDescription key="fontDescription" type="system" pointSize="32"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <nil key="highlightedColor"/> - </label> - <imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="252" verticalHuggingPriority="251" image="errorIcon" translatesAutoresizingMaskIntoConstraints="NO" id="q3r-OQ-1bR" userLabel="Icon image view"/> - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hRn-ww-fBK" userLabel="Text container"> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="[Title]" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ahp-gB-92W"> - <fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <nil key="highlightedColor"/> - </label> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="[Message Body]" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OV1-yz-3U3"> - <fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <nil key="highlightedColor"/> - </label> - </subviews> - <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> - <constraints> - <constraint firstAttribute="trailing" secondItem="ahp-gB-92W" secondAttribute="trailing" id="2sf-3u-gfN"/> - <constraint firstItem="OV1-yz-3U3" firstAttribute="top" secondItem="ahp-gB-92W" secondAttribute="bottom" constant="5" id="43Q-Ya-7Wv"/> - <constraint firstItem="OV1-yz-3U3" firstAttribute="leading" secondItem="hRn-ww-fBK" secondAttribute="leading" id="4vN-wA-aCm"/> - <constraint firstAttribute="bottom" secondItem="OV1-yz-3U3" secondAttribute="bottom" id="O66-Ve-8T4"/> - <constraint firstItem="ahp-gB-92W" firstAttribute="top" secondItem="hRn-ww-fBK" secondAttribute="top" id="TAI-Py-Rqq"/> - <constraint firstAttribute="trailing" secondItem="OV1-yz-3U3" secondAttribute="trailing" id="h6Q-XY-v9c"/> - <constraint firstItem="ahp-gB-92W" firstAttribute="leading" secondItem="hRn-ww-fBK" secondAttribute="leading" id="rrA-5L-fts"/> - </constraints> - </view> - </subviews> - <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> - <constraints> - <constraint firstItem="hRn-ww-fBK" firstAttribute="leading" secondItem="hN0-co-Tho" secondAttribute="trailing" constant="20" id="9Mf-Iy-3zb"/> - <constraint firstItem="q3r-OQ-1bR" firstAttribute="leading" secondItem="4g0-UX-cgn" secondAttribute="leading" constant="20" id="9oG-Zs-sAS"/> - <constraint firstItem="hRn-ww-fBK" firstAttribute="leading" secondItem="q3r-OQ-1bR" secondAttribute="trailing" constant="20" id="HPD-bV-5gP"/> - <constraint firstItem="hN0-co-Tho" firstAttribute="centerY" secondItem="4g0-UX-cgn" secondAttribute="centerYWithinMargins" id="Ipr-7h-kui"/> - <constraint firstAttribute="trailing" secondItem="hRn-ww-fBK" secondAttribute="trailing" constant="20" id="Lpa-bU-ecR"/> - <constraint firstItem="hN0-co-Tho" firstAttribute="leading" secondItem="4g0-UX-cgn" secondAttribute="leading" constant="20" id="OUk-54-FJE"/> - <constraint firstItem="q3r-OQ-1bR" firstAttribute="top" relation="greaterThanOrEqual" secondItem="4g0-UX-cgn" secondAttribute="top" constant="20" id="PJH-pA-Odz"/> - <constraint firstItem="hRn-ww-fBK" firstAttribute="centerY" secondItem="4g0-UX-cgn" secondAttribute="centerYWithinMargins" id="Ptv-cW-3dz"/> - <constraint firstItem="hRn-ww-fBK" firstAttribute="top" relation="greaterThanOrEqual" secondItem="4g0-UX-cgn" secondAttribute="top" constant="20" id="w4j-vg-8eK"/> - <constraint firstItem="q3r-OQ-1bR" firstAttribute="centerY" secondItem="4g0-UX-cgn" secondAttribute="centerYWithinMargins" id="wIn-X4-eRd"/> - <constraint firstItem="hN0-co-Tho" firstAttribute="top" relation="greaterThanOrEqual" secondItem="4g0-UX-cgn" secondAttribute="top" constant="20" id="yMi-JN-dIx"/> - </constraints> - </view> - </subviews> - <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <constraints> - <constraint firstAttribute="trailingMargin" secondItem="4g0-UX-cgn" secondAttribute="trailing" id="N6z-c2-h8Y"/> - <constraint firstItem="4g0-UX-cgn" firstAttribute="leading" secondItem="D36-3K-dlr" secondAttribute="leadingMargin" id="cLy-WR-pFK"/> - <constraint firstItem="4g0-UX-cgn" firstAttribute="top" secondItem="D36-3K-dlr" secondAttribute="topMargin" id="hqV-tv-Dq3"/> - <constraint firstAttribute="bottomMargin" secondItem="4g0-UX-cgn" secondAttribute="bottom" id="owe-dy-vX4"/> - </constraints> - <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="bounceAnimationOffset"> - <real key="value" value="5"/> - </userDefinedRuntimeAttribute> - <userDefinedRuntimeAttribute type="number" keyPath="statusBarOffset"> - <real key="value" value="8"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <outlet property="bodyLabel" destination="OV1-yz-3U3" id="mc8-61-Icn"/> - <outlet property="iconImageView" destination="q3r-OQ-1bR" id="R3P-Gs-Mqa"/> - <outlet property="iconLabel" destination="hN0-co-Tho" id="Pkn-8u-E8X"/> - <outlet property="titleLabel" destination="ahp-gB-92W" id="nkU-6v-kIf"/> - </connections> - <point key="canvasLocation" x="360" y="352.5"/> - </view> - </objects> - <resources> - <image name="errorIcon" width="33" height="34"/> - </resources> -</document> diff --git a/SwiftMessages/Resources/StatusLine.xib b/SwiftMessages/Resources/StatusLine.xib index 8485fbd0..3dbef99f 100644 --- a/SwiftMessages/Resources/StatusLine.xib +++ b/SwiftMessages/Resources/StatusLine.xib @@ -1,19 +1,23 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11198.2" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> + <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/> - <capability name="Constraints to layout margins" minToolsVersion="6.0"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17126"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> <view contentMode="scaleToFill" id="mGT-Jp-zjF" userLabel="Status Line" customClass="MessageView" customModule="SwiftMessages"> - <rect key="frame" x="0.0" y="0.0" width="600" height="32"/> + <rect key="frame" x="0.0" y="0.0" width="600" height="96"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="[Message Body]" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Jtv-Px-mvN" userLabel="Body Label"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="[Message Body]" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Jtv-Px-mvN" userLabel="Body Label"> + <rect key="frame" x="20" y="44" width="560" height="18"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> <constraints> <constraint firstAttribute="height" priority="999" constant="20" id="iWH-Cw-QQQ"/> </constraints> @@ -24,20 +28,31 @@ </subviews> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> + <constraint firstItem="Jtv-Px-mvN" firstAttribute="leading" secondItem="mGT-Jp-zjF" secondAttribute="leadingMargin" id="CHS-zo-loe"/> <constraint firstItem="Jtv-Px-mvN" firstAttribute="top" secondItem="mGT-Jp-zjF" secondAttribute="topMargin" id="dki-gE-LYc"/> <constraint firstAttribute="bottomMargin" secondItem="Jtv-Px-mvN" secondAttribute="bottom" id="gJ8-94-HgY"/> - <constraint firstItem="Jtv-Px-mvN" firstAttribute="centerX" secondItem="mGT-Jp-zjF" secondAttribute="centerX" id="hSb-Hs-Drr"/> + <constraint firstAttribute="trailingMargin" secondItem="Jtv-Px-mvN" secondAttribute="trailing" id="hII-4c-bJX"/> </constraints> <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="statusBarOffset"> - <real key="value" value="14"/> + <userDefinedRuntimeAttribute type="number" keyPath="leftLayoutMarginAddition"> + <real key="value" value="30"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="rightLayoutMarginAddition"> + <real key="value" value="30"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="boolean" keyPath="collapseLayoutMarginAdditions" value="NO"/> + <userDefinedRuntimeAttribute type="number" keyPath="topLayoutMarginAddition"> + <real key="value" value="0.0"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="bottomLayoutMarginAddition"> + <real key="value" value="0.0"/> </userDefinedRuntimeAttribute> </userDefinedRuntimeAttributes> <connections> <outlet property="bodyLabel" destination="Jtv-Px-mvN" id="bcr-eT-Nhm"/> </connections> - <point key="canvasLocation" x="497" y="368"/> + <point key="canvasLocation" x="495.6521739130435" y="346.20535714285711"/> </view> </objects> </document> diff --git a/SwiftMessages/Resources/TabView.xib b/SwiftMessages/Resources/TabView.xib index 253e5ff9..141467c1 100644 --- a/SwiftMessages/Resources/TabView.xib +++ b/SwiftMessages/Resources/TabView.xib @@ -1,9 +1,9 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11198.2" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> + <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> - <deployment version="2304" identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/> - <capability name="Constraints to layout margins" minToolsVersion="6.0"/> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> @@ -13,25 +13,42 @@ <rect key="frame" x="0.0" y="0.0" width="600" height="123"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> - <view contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8l1-Wp-omF" userLabel="Background view"> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8l1-Wp-omF" userLabel="Corner rounding view" customClass="CornerRoundingView" customModule="SwiftMessages"> + <rect key="frame" x="20" y="0.0" width="560" height="123"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="bdc-by-rjM" userLabel="Content view"> + <rect key="frame" x="20" y="44" width="520" height="45"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="😬" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="09t-tr-Q8T" userLabel="Icon label"> + <rect key="frame" x="0.0" y="0.0" width="43" height="45"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> <fontDescription key="fontDescription" type="system" pointSize="38"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="errorIcon" translatesAutoresizingMaskIntoConstraints="NO" id="iJe-yo-EnG" userLabel="Icon image view"/> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="top" translatesAutoresizingMaskIntoConstraints="NO" id="h4V-Az-Wau"> + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="errorIcon" translatesAutoresizingMaskIntoConstraints="NO" id="iJe-yo-EnG" userLabel="Icon image view"> + <rect key="frame" x="53" y="5.5" width="33" height="34"/> + </imageView> + <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="h4V-Az-Wau"> + <rect key="frame" x="96" y="3.5" width="357" height="38.5"/> <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="[Title]" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="RxN-E1-uzx"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="[Title]" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="RxN-E1-uzx"> + <rect key="frame" x="0.0" y="0.0" width="357" height="20.5"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> <fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="[Message Body]" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JoS-PU-kVw"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="[Message Body]" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JoS-PU-kVw"> + <rect key="frame" x="0.0" y="20.5" width="357" height="18"/> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> + <accessibility key="accessibilityConfiguration"> + <bool key="isElement" value="NO"/> + </accessibility> <fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> @@ -39,44 +56,85 @@ </subviews> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> </stackView> - <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="252" horizontalCompressionResistancePriority="752" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vBc-Qb-BBh"> + <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="252" horizontalCompressionResistancePriority="752" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vBc-Qb-BBh"> + <rect key="frame" x="463" y="7.5" width="57" height="30"/> <fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/> <state key="normal" title="[Button]"/> </button> </subviews> + <variation key="widthClass=regular" spacing="15"/> </stackView> </subviews> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> - <constraint firstItem="bdc-by-rjM" firstAttribute="top" secondItem="8l1-Wp-omF" secondAttribute="topMargin" constant="20" id="3Q1-Vl-OFg"/> - <constraint firstItem="bdc-by-rjM" firstAttribute="leading" secondItem="8l1-Wp-omF" secondAttribute="leading" constant="20" id="ZeN-Yg-DDA"/> - <constraint firstAttribute="trailing" secondItem="bdc-by-rjM" secondAttribute="trailing" constant="20" id="Zuf-gb-AgS"/> - <constraint firstAttribute="bottomMargin" secondItem="bdc-by-rjM" secondAttribute="bottom" constant="20" id="jri-TS-nOa"/> + <constraint firstItem="bdc-by-rjM" firstAttribute="leading" secondItem="8l1-Wp-omF" secondAttribute="leading" priority="900" constant="20" id="ZeN-Yg-DDA"/> + <constraint firstAttribute="trailing" secondItem="bdc-by-rjM" secondAttribute="trailing" priority="900" constant="20" id="Zuf-gb-AgS"/> + <constraint firstAttribute="width" relation="lessThanOrEqual" priority="900" constant="500" id="eE4-1F-BxM"/> </constraints> <edgeInsets key="layoutMargins" top="0.0" left="0.0" bottom="0.0" right="0.0"/> <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> - <integer key="value" value="5"/> + <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius"> + <real key="value" value="15"/> </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="boolean" keyPath="roundsLeadingCorners" value="YES"/> </userDefinedRuntimeAttributes> + <variation key="default"> + <mask key="constraints"> + <exclude reference="eE4-1F-BxM"/> + </mask> + </variation> + <variation key="widthClass=regular"> + <mask key="constraints"> + <include reference="eE4-1F-BxM"/> + </mask> + </variation> </view> </subviews> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <constraints> - <constraint firstAttribute="trailing" secondItem="8l1-Wp-omF" secondAttribute="trailing" constant="10" id="9zp-kw-f7h"/> + <constraint firstItem="8l1-Wp-omF" firstAttribute="centerX" secondItem="Kgd-fq-RpT" secondAttribute="centerX" priority="950" id="7tH-rr-EQZ"/> + <constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="8l1-Wp-omF" secondAttribute="trailing" priority="900" id="Auy-Yk-HhC"/> + <constraint firstItem="bdc-by-rjM" firstAttribute="top" secondItem="Kgd-fq-RpT" secondAttribute="topMargin" id="ORK-bM-dJT"/> <constraint firstItem="8l1-Wp-omF" firstAttribute="top" secondItem="Kgd-fq-RpT" secondAttribute="top" id="WBW-gJ-lIP"/> <constraint firstAttribute="bottom" secondItem="8l1-Wp-omF" secondAttribute="bottom" id="cYv-6k-QSZ"/> - <constraint firstItem="8l1-Wp-omF" firstAttribute="leading" secondItem="Kgd-fq-RpT" secondAttribute="leadingMargin" constant="10" id="tVC-3b-F2x"/> + <constraint firstAttribute="bottomMargin" secondItem="bdc-by-rjM" secondAttribute="bottom" id="foq-FY-TKq"/> + <constraint firstItem="8l1-Wp-omF" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Kgd-fq-RpT" secondAttribute="leadingMargin" priority="900" id="pRc-fu-AhN"/> + <constraint firstItem="8l1-Wp-omF" firstAttribute="leading" secondItem="Kgd-fq-RpT" secondAttribute="leadingMargin" priority="900" id="tVC-3b-F2x"/> + <constraint firstItem="8l1-Wp-omF" firstAttribute="trailing" secondItem="Kgd-fq-RpT" secondAttribute="trailingMargin" priority="900" id="uZe-cg-8cw"/> </constraints> <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> <userDefinedRuntimeAttributes> <userDefinedRuntimeAttribute type="number" keyPath="bounceAnimationOffset"> - <real key="value" value="55"/> + <real key="value" value="5"/> </userDefinedRuntimeAttribute> - <userDefinedRuntimeAttribute type="number" keyPath="statusBarOffset"> + <userDefinedRuntimeAttribute type="number" keyPath="topLayoutMarginAddition"> + <real key="value" value="20"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="leftLayoutMarginAddition"> + <real key="value" value="10"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="bottomLayoutMarginAddition"> + <real key="value" value="20"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="rightLayoutMarginAddition"> <real key="value" value="10"/> </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="boolean" keyPath="collapseLayoutMarginAdditions" value="NO"/> </userDefinedRuntimeAttributes> + <variation key="default"> + <mask key="constraints"> + <exclude reference="Auy-Yk-HhC"/> + <exclude reference="pRc-fu-AhN"/> + </mask> + </variation> + <variation key="widthClass=regular"> + <mask key="constraints"> + <include reference="Auy-Yk-HhC"/> + <include reference="pRc-fu-AhN"/> + <exclude reference="tVC-3b-F2x"/> + <exclude reference="uZe-cg-8cw"/> + </mask> + </variation> <connections> <outlet property="backgroundView" destination="8l1-Wp-omF" id="3L7-KM-Nup"/> <outlet property="bodyLabel" destination="JoS-PU-kVw" id="BPZ-4f-hLF"/> diff --git a/SwiftMessages/Resources/errorIcon.png b/SwiftMessages/Resources/errorIcon.png new file mode 100644 index 00000000..92f59e79 Binary files /dev/null and b/SwiftMessages/Resources/errorIcon.png differ diff --git a/SwiftMessages/Resources/errorIcon@2x.png b/SwiftMessages/Resources/errorIcon@2x.png new file mode 100644 index 00000000..2a0be86e Binary files /dev/null and b/SwiftMessages/Resources/errorIcon@2x.png differ diff --git a/SwiftMessages/Resources/errorIcon@3x.png b/SwiftMessages/Resources/errorIcon@3x.png new file mode 100644 index 00000000..07a9e775 Binary files /dev/null and b/SwiftMessages/Resources/errorIcon@3x.png differ diff --git a/SwiftMessages/Resources/errorIconLight.png b/SwiftMessages/Resources/errorIconLight.png new file mode 100644 index 00000000..bd00a52f Binary files /dev/null and b/SwiftMessages/Resources/errorIconLight.png differ diff --git a/SwiftMessages/Resources/errorIconLight@2x.png b/SwiftMessages/Resources/errorIconLight@2x.png new file mode 100644 index 00000000..f4a5c669 Binary files /dev/null and b/SwiftMessages/Resources/errorIconLight@2x.png differ diff --git a/SwiftMessages/Resources/errorIconLight@3x.png b/SwiftMessages/Resources/errorIconLight@3x.png new file mode 100644 index 00000000..6360adbd Binary files /dev/null and b/SwiftMessages/Resources/errorIconLight@3x.png differ diff --git a/SwiftMessages/Resources/errorIconSubtle.png b/SwiftMessages/Resources/errorIconSubtle.png new file mode 100644 index 00000000..833f7c71 Binary files /dev/null and b/SwiftMessages/Resources/errorIconSubtle.png differ diff --git a/SwiftMessages/Resources/errorIconSubtle@2x.png b/SwiftMessages/Resources/errorIconSubtle@2x.png new file mode 100644 index 00000000..0a6d0d9d Binary files /dev/null and b/SwiftMessages/Resources/errorIconSubtle@2x.png differ diff --git a/SwiftMessages/Resources/errorIconSubtle@3x.png b/SwiftMessages/Resources/errorIconSubtle@3x.png new file mode 100644 index 00000000..d15795bb Binary files /dev/null and b/SwiftMessages/Resources/errorIconSubtle@3x.png differ diff --git a/SwiftMessages/Resources/infoIcon.png b/SwiftMessages/Resources/infoIcon.png new file mode 100644 index 00000000..16a0cc7f Binary files /dev/null and b/SwiftMessages/Resources/infoIcon.png differ diff --git a/SwiftMessages/Resources/infoIcon@2x.png b/SwiftMessages/Resources/infoIcon@2x.png new file mode 100644 index 00000000..a1ab6761 Binary files /dev/null and b/SwiftMessages/Resources/infoIcon@2x.png differ diff --git a/SwiftMessages/Resources/infoIcon@3x.png b/SwiftMessages/Resources/infoIcon@3x.png new file mode 100644 index 00000000..fb98813f Binary files /dev/null and b/SwiftMessages/Resources/infoIcon@3x.png differ diff --git a/SwiftMessages/Resources/infoIconLight.png b/SwiftMessages/Resources/infoIconLight.png new file mode 100644 index 00000000..9195a166 Binary files /dev/null and b/SwiftMessages/Resources/infoIconLight.png differ diff --git a/SwiftMessages/Resources/infoIconLight@2x.png b/SwiftMessages/Resources/infoIconLight@2x.png new file mode 100644 index 00000000..4662af3d Binary files /dev/null and b/SwiftMessages/Resources/infoIconLight@2x.png differ diff --git a/SwiftMessages/Resources/infoIconLight@3x.png b/SwiftMessages/Resources/infoIconLight@3x.png new file mode 100644 index 00000000..999376e2 Binary files /dev/null and b/SwiftMessages/Resources/infoIconLight@3x.png differ diff --git a/SwiftMessages/Resources/infoIconSubtle.png b/SwiftMessages/Resources/infoIconSubtle.png new file mode 100644 index 00000000..aa1a119e Binary files /dev/null and b/SwiftMessages/Resources/infoIconSubtle.png differ diff --git a/SwiftMessages/Resources/infoIconSubtle@2x.png b/SwiftMessages/Resources/infoIconSubtle@2x.png new file mode 100644 index 00000000..901635d4 Binary files /dev/null and b/SwiftMessages/Resources/infoIconSubtle@2x.png differ diff --git a/SwiftMessages/Resources/infoIconSubtle@3x.png b/SwiftMessages/Resources/infoIconSubtle@3x.png new file mode 100644 index 00000000..769fd02e Binary files /dev/null and b/SwiftMessages/Resources/infoIconSubtle@3x.png differ diff --git a/SwiftMessages/Resources/successIcon.png b/SwiftMessages/Resources/successIcon.png new file mode 100644 index 00000000..1d371c7f Binary files /dev/null and b/SwiftMessages/Resources/successIcon.png differ diff --git a/SwiftMessages/Resources/successIcon@2x.png b/SwiftMessages/Resources/successIcon@2x.png new file mode 100644 index 00000000..719218cf Binary files /dev/null and b/SwiftMessages/Resources/successIcon@2x.png differ diff --git a/SwiftMessages/Resources/successIcon@3x.png b/SwiftMessages/Resources/successIcon@3x.png new file mode 100644 index 00000000..74893cab Binary files /dev/null and b/SwiftMessages/Resources/successIcon@3x.png differ diff --git a/SwiftMessages/Resources/successIconLight.png b/SwiftMessages/Resources/successIconLight.png new file mode 100644 index 00000000..0e5314c6 Binary files /dev/null and b/SwiftMessages/Resources/successIconLight.png differ diff --git a/SwiftMessages/Resources/successIconLight@2x.png b/SwiftMessages/Resources/successIconLight@2x.png new file mode 100644 index 00000000..149ab077 Binary files /dev/null and b/SwiftMessages/Resources/successIconLight@2x.png differ diff --git a/SwiftMessages/Resources/successIconLight@3x.png b/SwiftMessages/Resources/successIconLight@3x.png new file mode 100644 index 00000000..5e152999 Binary files /dev/null and b/SwiftMessages/Resources/successIconLight@3x.png differ diff --git a/SwiftMessages/Resources/successIconSubtle.png b/SwiftMessages/Resources/successIconSubtle.png new file mode 100644 index 00000000..61334838 Binary files /dev/null and b/SwiftMessages/Resources/successIconSubtle.png differ diff --git a/SwiftMessages/Resources/successIconSubtle@2x.png b/SwiftMessages/Resources/successIconSubtle@2x.png new file mode 100644 index 00000000..fbe6053f Binary files /dev/null and b/SwiftMessages/Resources/successIconSubtle@2x.png differ diff --git a/SwiftMessages/Resources/successIconSubtle@3x.png b/SwiftMessages/Resources/successIconSubtle@3x.png new file mode 100644 index 00000000..6ce53797 Binary files /dev/null and b/SwiftMessages/Resources/successIconSubtle@3x.png differ diff --git a/SwiftMessages/Resources/warningIcon.png b/SwiftMessages/Resources/warningIcon.png new file mode 100644 index 00000000..77357618 Binary files /dev/null and b/SwiftMessages/Resources/warningIcon.png differ diff --git a/SwiftMessages/Resources/warningIcon@2x.png b/SwiftMessages/Resources/warningIcon@2x.png new file mode 100644 index 00000000..448d6865 Binary files /dev/null and b/SwiftMessages/Resources/warningIcon@2x.png differ diff --git a/SwiftMessages/Resources/warningIcon@3x.png b/SwiftMessages/Resources/warningIcon@3x.png new file mode 100644 index 00000000..e2c8d46f Binary files /dev/null and b/SwiftMessages/Resources/warningIcon@3x.png differ diff --git a/SwiftMessages/Resources/warningIconLight.png b/SwiftMessages/Resources/warningIconLight.png new file mode 100644 index 00000000..fce1a0e5 Binary files /dev/null and b/SwiftMessages/Resources/warningIconLight.png differ diff --git a/SwiftMessages/Resources/warningIconLight@2x.png b/SwiftMessages/Resources/warningIconLight@2x.png new file mode 100644 index 00000000..91de0d9b Binary files /dev/null and b/SwiftMessages/Resources/warningIconLight@2x.png differ diff --git a/SwiftMessages/Resources/warningIconLight@3x.png b/SwiftMessages/Resources/warningIconLight@3x.png new file mode 100644 index 00000000..11d68596 Binary files /dev/null and b/SwiftMessages/Resources/warningIconLight@3x.png differ diff --git a/SwiftMessages/Resources/warningIconSubtle.png b/SwiftMessages/Resources/warningIconSubtle.png new file mode 100644 index 00000000..e54dcd35 Binary files /dev/null and b/SwiftMessages/Resources/warningIconSubtle.png differ diff --git a/SwiftMessages/Resources/warningIconSubtle@2x.png b/SwiftMessages/Resources/warningIconSubtle@2x.png new file mode 100644 index 00000000..cfd2ebd4 Binary files /dev/null and b/SwiftMessages/Resources/warningIconSubtle@2x.png differ diff --git a/SwiftMessages/Resources/warningIconSubtle@3x.png b/SwiftMessages/Resources/warningIconSubtle@3x.png new file mode 100644 index 00000000..95715670 Binary files /dev/null and b/SwiftMessages/Resources/warningIconSubtle@3x.png differ diff --git a/SwiftMessages/SwiftMessageModifier.swift b/SwiftMessages/SwiftMessageModifier.swift new file mode 100644 index 00000000..e44d6871 --- /dev/null +++ b/SwiftMessages/SwiftMessageModifier.swift @@ -0,0 +1,133 @@ +// +// SwiftMessageModifier.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI + +@available(iOS 14.0, *) +public extension View { + /// A view modifier for displaying a message using similar semantics to the `.sheet()` modifier. + func swiftMessage<Message, MessageContent>( + message: Binding<Message?>, + config: SwiftMessages.Config? = nil, + swiftMessages: SwiftMessages? = nil, + @ViewBuilder messageContent: @escaping (Message) -> MessageContent + ) -> some View where Message: Equatable & Identifiable, MessageContent: View { + swiftMessage(message: message, config: config, swiftMessages: swiftMessages) { message, _ in + messageContent(message) + } + } + + /// A view modifier for displaying a message using similar semantics to the `.sheet()` modifier. This variant provides a + /// `SwiftMessageGeometryProxy`. The proxy is useful when one needs to know the geometry metrics of the container view, + /// particularly because `GeometryReader` doesn't work inside the view builder due to the way the message view is being + /// displayed from UIKit. + func swiftMessage<Message, MessageContent>( + message: Binding<Message?>, + config: SwiftMessages.Config? = nil, + swiftMessages: SwiftMessages? = nil, + @ViewBuilder messageContent: @escaping (Message, MessageGeometryProxy) -> MessageContent + ) -> some View where Message: Equatable & Identifiable, MessageContent: View { + modifier( + SwiftMessageModifier( + message: message, + config: config, + swiftMessages: swiftMessages, + messageContent: messageContent + ) + ) + } + + /// A state-based modifier for displaying a message when `Message` conforms to `MessageViewConvertible`. This variant should be used if the message + /// view can be represented as pure data. If the message requires a delegate, has callbacks, etc., consider using the variant that takes a message view builder. + func swiftMessage<Message>( + message: Binding<Message?>, + config: SwiftMessages.Config? = nil, + swiftMessages: SwiftMessages? = nil + ) -> some View where Message: MessageViewConvertible { + swiftMessage(message: message, config: config, swiftMessages: swiftMessages) { content in + content.asMessageView() + } + } +} + +@available(iOS 14.0, *) +private struct SwiftMessageModifier<Message, MessageContent>: ViewModifier where Message: Equatable & Identifiable, MessageContent: View { + + // MARK: - API + + fileprivate init( + message: Binding<Message?>, + config: SwiftMessages.Config? = nil, + swiftMessages: SwiftMessages? = nil, + @ViewBuilder messageContent: @escaping (Message) -> MessageContent + ) { + _message = message + self.config = config + self.swiftMessages = swiftMessages + self.messageContent = { message, _ in + messageContent(message) + } + } + + fileprivate init( + message: Binding<Message?>, + config: SwiftMessages.Config? = nil, + swiftMessages: SwiftMessages? = nil, + @ViewBuilder messageContent: @escaping (Message, MessageGeometryProxy) -> MessageContent + ) { + _message = message + self.config = config + self.swiftMessages = swiftMessages + self.messageContent = messageContent + } + + fileprivate init( + message: Binding<Message?>, + config: SwiftMessages.Config? = nil, + swiftMessages: SwiftMessages? = nil + ) where Message: MessageViewConvertible, Message.Content == MessageContent { + _message = message + self.config = config + self.swiftMessages = swiftMessages + self.messageContent = { message, _ in + message.asMessageView() + } + } + + // MARK: - Constants + + // MARK: - Variables + + @Binding private var message: Message? + private let config: SwiftMessages.Config? + private let swiftMessages: SwiftMessages? + @ViewBuilder private let messageContent: (Message, MessageGeometryProxy) -> MessageContent + + // MARK: - Body + + func body(content: Content) -> some View { + content + .onChange(of: message) { message in + let show: @MainActor (SwiftMessages.Config, UIView) -> Void = swiftMessages?.show(config:view:) ?? SwiftMessages.show(config:view:) + let hideAll: @MainActor () -> Void = swiftMessages?.hideAll ?? SwiftMessages.hideAll + switch message { + case let message?: + let view = MessageHostingView(message: message, content: messageContent) + var config = config ?? swiftMessages?.defaultConfig ?? SwiftMessages.defaultConfig + config.eventListeners.append { event in + if case .didHide = event, event.id == self.message?.id { + self.message = nil + } + } + hideAll() + show(config, view) + case .none: + hideAll() + } + } + } +} diff --git a/SwiftMessages/SwiftMessages.Config+Extensions.swift b/SwiftMessages/SwiftMessages.Config+Extensions.swift new file mode 100644 index 00000000..a17a9f22 --- /dev/null +++ b/SwiftMessages/SwiftMessages.Config+Extensions.swift @@ -0,0 +1,44 @@ +// +// SwiftMessages.Config+Extensions.swift +// SwiftMessages +// +// Created by Timothy Moose on 12/26/20. +// Copyright © 2020 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +extension SwiftMessages.Config { + var windowLevel: UIWindow.Level? { + switch presentationContext { + case .window(let level): return level + case .windowScene(_, let level): return level + default: return nil + } + } + + @available(iOS 13.0, *) + var windowScene: UIWindowScene? { + switch presentationContext { + case .windowScene(let scene, _): return scene as? UIWindowScene + default: + #if SWIFTMESSAGES_APP_EXTENSIONS + return nil + #else + return UIWindow.keyWindow?.windowScene + #endif + } + } + + var shouldBecomeKeyWindow: Bool { + if let becomeKeyWindow = becomeKeyWindow { return becomeKeyWindow } + switch dimMode { + case .gray, .color, .blur: + // Should become key window in modal presentation style + // for proper VoiceOver handling. + return true + case .none: + return false + } + } +} diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index d469cf58..f05ad494 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -13,9 +13,10 @@ private let globalInstance = SwiftMessages() /** The `SwiftMessages` class provides the interface for showing and hiding messages. It behaves like a queue, only showing one message at a time. Message views that - implement the `Identifiable` protocol (as `MessageView` does) will have duplicates removed. + adopt the `Identifiable` protocol (as `MessageView` does) will have duplicates removed. */ -open class SwiftMessages: PresenterDelegate { +@MainActor +open class SwiftMessages { /** Specifies whether the message view is displayed at the top or bottom @@ -32,6 +33,16 @@ open class SwiftMessages: PresenterDelegate { Message view slides up from the bottom. */ case bottom + + /** + Message view fades into the center. + */ + case center + + /** + User-defined animation + */ + case custom(animator: Animator) } /** @@ -43,32 +54,44 @@ open class SwiftMessages: PresenterDelegate { /** Displays the message view under navigation bars and tab bars if an appropriate one is found. Otherwise, it is displayed in a new window - at level `UIWindowLevelNormal`. Use this option to automatically display + at level `UIWindow.Level.normal`. Use this option to automatically display under bars, where applicable. Because this option involves a top-down - search, an approrpiate context might not be found when the view controller - heirarchy incorporates custom containers. If this is the case, the + search, an appropriate context might not be found when the view controller + hierarchy incorporates custom containers. If this is the case, the .ViewController option can provide a more targeted context. */ case automatic /** - Displays the message in a new window at the specified window level. Use - `UIWindowLevelNormal` to display under the status bar and `UIWindowLevelStatusBar` - to display over. When displaying under the status bar, SwiftMessages automatically - increases the top margins of any message view that adopts the `MarginInsetting` - protocol (as `MessageView` does) to account for the status bar. + Displays the message in a new window at the specified window level. + SwiftMessages automatically increases the top margins 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. */ - case window(windowLevel: UIWindowLevel) - + case window(windowLevel: UIWindow.Level) + + /** + Displays the message in a new window, at the specified window level, + in the specified window scene. SwiftMessages automatically increases the top margins + 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. The `WindowScene` protocol works around the change in Xcode 13 that prevents + using `@availability` attribute with `enum` cases containing associated values. + */ + case windowScene(_: WindowScene, windowLevel: UIWindow.Level) + /** Displays the message view under navigation bars and tab bars if an appropriate one is found using the given view controller as a starting point and searching up the parent view controller chain. Otherwise, it is displayed in the given view controller's view. This option can be used - for targeted placement in a view controller heirarchy. + for targeted placement in a view controller hierarchy. */ case viewController(_: UIViewController) - + /** Displays the message view in the given container view. */ @@ -97,6 +120,49 @@ open class SwiftMessages: PresenterDelegate { - Parameter seconds: The number of seconds. */ case seconds(seconds: TimeInterval) + + /** + The `indefinite` option is similar to `forever` in the sense that + the message view will not be automatically hidden. However, it + provides two options that can be useful in some scenarios: + + - `delay`: wait the specified time interval before displaying + the message. If you hide the message during the delay + interval by calling either `hideAll()` or `hide(id:)`, + the message will not be displayed. This is not the case for + `hide()` because it only acts on a visible message. Messages + shown during another message's delay window are displayed first. + - `minimum`: if the message is displayed, ensure that it is displayed + for a minimum time interval. If you explicitly hide the + during this interval, the message will be hidden at the + end of the interval. + + This option is useful for displaying a message when a process is taking + too long but you don't want to display the message if the process completes + in a reasonable amount of time. The value `indefinite(delay: 0, minimum: 0)` + is equivalent to `forever`. + + For example, if a URL load is expected to complete in 2 seconds, you may use + the value `indefinite(delay: 2, minimum 1)` to ensure that the message will not + be displayed in most cases, but will be displayed for at least 1 second if + the operation takes longer than 2 seconds. By specifying a minimum duration, + you can avoid hiding the message too fast if the operation finishes right + after the delay interval. + */ + case indefinite(delay: TimeInterval, minimum: TimeInterval) + } + + /** + Specifies notification's haptic feedback to be used on `MessageView` display + */ + + /** + Specifies an optional haptic feedback to be used on `MessageView` display + */ + public enum Haptic { + case success + case warning + case error } /** @@ -113,8 +179,8 @@ open class SwiftMessages: PresenterDelegate { /** Dim the background behind the message view a gray color. - - Parameter interactive: Specifies whether or not tapping the - dimmed area dismisses the message view. + - `interactive`: Specifies whether or not tapping the + dimmed area dismisses the message view. */ case gray(interactive: Bool) @@ -123,21 +189,67 @@ open class SwiftMessages: PresenterDelegate { SwiftMessages does not apply alpha transparency to the color, so any alpha must be baked into the `UIColor` instance. - - Parameter color: The color of the dim view. - - Parameter interactive: Specifies whether or not tapping the - dimmed area dismisses the message view. + - `color`: The color of the dim view. + - `interactive`: Specifies whether or not tapping the + dimmed area dismisses the message view. */ case color(color: UIColor, interactive: Bool) + + /** + Dim the background behind the message view using a blur effect with + the given style + + - `style`: The blur effect style to use + - `alpha`: The alpha level of the blur + - `interactive`: Specifies whether or not tapping the + dimmed area dismisses the message view. + */ + case blur(style: UIBlurEffect.Style, alpha: CGFloat, interactive: Bool) + + public var interactive: Bool { + switch self { + case .gray(let interactive): + return interactive + case .color(_, let interactive): + return interactive + case .blur (_, _, let interactive): + return interactive + case .none: + return false + } + } + + public var modal: Bool { + switch self { + case .gray, .color, .blur: + return true + case .none: + return false + } + } } /** 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 + } } /** @@ -177,6 +289,13 @@ open class SwiftMessages: PresenterDelegate { */ public var dimMode = DimMode.none + + /** + Specifies notification's haptic feedback to be played on `MessageView` display. + No default value is provided. + */ + public var haptic: Haptic? = nil + /** Specifies whether or not the interactive pan-to-hide gesture is enabled on the message view. For views that implement the `BackgroundViewable` @@ -188,15 +307,22 @@ open class SwiftMessages: PresenterDelegate { public var interactiveHide = true /** - Specifies the preferred status bar style when the view is displayed - directly behind the status bar, such as when using `.Window` - presentation context with a `UIWindowLevelNormal` window level - and `.Top` presentation style. This option is useful if the message - view has a background color that needs a different status bar style than - the current one. The default is `.Default`. + Specifies the preferred status bar style when the view is being + displayed in a window. This can be useful when the view is being + displayed behind the status bar and the message view has a background + color that needs a different status bar style than the current one. + The default is `nil`. */ public var preferredStatusBarStyle: UIStatusBarStyle? - + + /** + Specifies the preferred status bar visibility when the view is being + displayed in a window. As of iOS 13, windows can no longer cover the + status bar. The only alternative is to hide the status bar by setting + this options to `true`. Default is `nil`. + */ + public var prefersStatusBarHidden: Bool? + /** If a view controller is created to host the message view, should the view controller auto rotate? The default is 'true', meaning it should auto @@ -214,13 +340,71 @@ open class SwiftMessages: PresenterDelegate { Specifies an optional array of event listeners. */ public var eventListeners: [EventListener] = [] + + /** + Specifies that in cases where the message is displayed in its own window, + such as with `.window` presentation context, the window should become + the key window. This option should only be used if the message view + needs to receive non-touch events, such as keyboard input. From Apple's + documentation https://developer.apple.com/reference/uikit/uiwindow: + + > Whereas touch events are delivered to the window where they occurred, + > events that do not have a relevant coordinate value are delivered to + > the key window. Only one window at a time can be the key window, and + > you can use a window’s keyWindow property to determine its status. + > Most of the time, your app’s main window is the key window, but UIKit + > may designate a different window as needed. + */ + public var becomeKeyWindow: Bool? + + /** + The `dimMode` background will use this accessibility + label, e.g. "dismiss" when the `interactive` option is used. + */ + public var dimModeAccessibilityLabel: String = "dismiss" + + /** + The user interface style to use when SwiftMessages displays a message its own window. + Use with apps that don't support dark mode to prevent messages from adopting the + system's interface style. + */ + @available(iOS 13, *) + public var overrideUserInterfaceStyle: UIUserInterfaceStyle { + // Note that this is modelled as a computed property because + // Swift doesn't allow `@available` with stored properties. + get { + guard let rawValue = overrideUserInterfaceStyleRawValue else { return .unspecified } + return UIUserInterfaceStyle(rawValue: rawValue) ?? .unspecified + } + set { + overrideUserInterfaceStyleRawValue = newValue.rawValue + } + } + private var overrideUserInterfaceStyleRawValue: Int? + + /** + If specified, SwiftMessages calls this closure when an instance of + `WindowViewController` is needed. Use this if you need to supply a custom subclass + of `WindowViewController`. + */ + public var windowViewController: ((_ config: SwiftMessages.Config) -> WindowViewController)? + + /** + Supply an instance of `KeyboardTrackingView` to have the message view avoid the keyboard. + */ + public var keyboardTrackingView: KeyboardTrackingView? + + /** + Specify a positive or negative priority to influence the position of a message in the queue based on it's relative priority. + */ + public var priority: Int = 0 } /** Not much to say here. */ - public init() {} - + nonisolated public init() {} + /** Adds the given configuration and view to the message queue to be displayed. @@ -228,11 +412,8 @@ open class SwiftMessages: PresenterDelegate { - Parameter view: The view to be displayed. */ open func show(config: Config, view: UIView) { - syncQueue.async { [weak self] in - guard let strongSelf = self else { return } - let presenter = Presenter(config: config, view: view, delegate: strongSelf) - strongSelf.enqueue(presenter: presenter) - } + let presenter = Presenter(config: config, view: view, delegate: self) + enqueue(presenter: presenter) } /** @@ -259,11 +440,11 @@ open class SwiftMessages: PresenterDelegate { - 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) } } @@ -284,11 +465,8 @@ open class SwiftMessages: PresenterDelegate { /** Hide the current message being displayed by animating it away. */ - open func hide() { - syncQueue.async { [weak self] in - guard let strongSelf = self else { return } - strongSelf.hideCurrent() - } + open func hide(animated: Bool = true) { + hideCurrent(animated: animated) } /** @@ -296,29 +474,64 @@ open class SwiftMessages: PresenterDelegate { clear the message queue. */ open func hideAll() { - syncQueue.async { [weak self] in - guard let strongSelf = self else { return } - strongSelf.queue.removeAll() - strongSelf.hideCurrent() - } + queue.removeAll() + delays.removeAll() + counts.removeAll() + hideCurrent() } /** Hide a message with the given `id`. If the specified message is currently being displayed, it will be animated away. Works with message - views, such as `MessageView`, that implement the `Identifiable` protocol. + views, such as `MessageView`, that adopt the `Identifiable` protocol. - Parameter id: The identifier of the message to remove. */ open func hide(id: String) { - syncQueue.async { [weak self] in - guard let strongSelf = self else { return } - if id == strongSelf.current?.id { - strongSelf.hideCurrent() + if id == _current?.id { + hideCurrent() + } + queue = queue.filter { $0.id != id } + delays.remove(id: id) + counts[id] = nil + } + + /** + Hide the message when the number of calls to show() and hideCounted(id:) for a + given message ID are equal. This can be useful for messages that may be + shown from multiple code paths to ensure that all paths are ready to hide. + */ + open func hideCounted(id: String) { + if let count = counts[id] { + if count < 2 { + counts[id] = nil + } else { + counts[id] = count - 1 + return } - strongSelf.queue = strongSelf.queue.filter { $0.id != id } } + if id == _current?.id { + hideCurrent() + } + queue = queue.filter { $0.id != id } + delays.remove(id: id) } - + + /** + Get the count of a message with the given ID (see `hideCounted(id:)`) + */ + public func count(id: String) -> Int { + return counts[id] ?? 0 + } + + /** + Explicitly set the count of a message with the given ID (see `hideCounted(id:)`). + Not sure if there's a use case for this, but why not?! + */ + public func set(count: Int, for id: String) { + guard counts[id] != nil else { return } + return counts[id] = count + } + /** Specifies the default configuration to use when calling the variants of `show()` that don't take a `config` argument or as a base for custom configs. @@ -330,111 +543,238 @@ open class SwiftMessages: PresenterDelegate { and showing the next. Default is 0.5 seconds. */ open var pauseBetweenMessages: TimeInterval = 0.5 - - let syncQueue = DispatchQueue(label: "it.swiftkick.SwiftMessages", attributes: []) - var queue: [Presenter] = [] - var current: Presenter? = nil { + + /// Type for keeping track of delayed presentations + @MainActor + fileprivate class Delays { + + fileprivate func add(presenter: Presenter) { + presenters.insert(presenter) + } + + @discardableResult + fileprivate func remove(presenter: Presenter) -> Bool { + guard presenters.contains(presenter) else { return false } + presenters.remove(presenter) + return true + } + + fileprivate func remove(id: String) { + presenters = presenters.filter { $0.id != id } + } + + fileprivate func removeAll() { + presenters.removeAll() + } + + private var presenters = Set<Presenter>() + } + + func show(presenter: Presenter) { + enqueue(presenter: presenter) + } + + 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 - syncQueue.asyncAfter(deadline: delayTime, execute: { [weak self] in - guard let strongSelf = self else { return } - strongSelf.dequeueNext() - }) + Task { [weak self] in + try? await Task.sleep(seconds: self?.pauseBetweenMessages ?? 0) + self?.dequeueNext() + } } } } - - func enqueue(presenter: Presenter) { - if presenter.config.ignoreDuplicates, let id = presenter.id { - if current?.id == id { return } - if queue.filter({ $0.id == id }).count > 0 { return } + + fileprivate func enqueue(presenter: Presenter) { + if presenter.config.ignoreDuplicates { + counts[presenter.id] = (counts[presenter.id] ?? 0) + 1 + if let _current, + _current.id == presenter.id, + !_current.isHiding, + !_current.isOrphaned { return } + if queue.filter({ $0.id == presenter.id }).count > 0 { return } + } + func doEnqueue() { + queue.append(presenter) + dequeueNext() + } + if let delay = presenter.delayShow { + delays.add(presenter: presenter) + 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 self, self.delays.remove(presenter: presenter) else { return } + doEnqueue() + } + } else { + doEnqueue() } - queue.append(presenter) - dequeueNext() } - func dequeueNext() { - guard self.current == nil else { return } + fileprivate func dequeueNext() { guard queue.count > 0 else { return } + if let _current, !_current.isOrphaned { return } + // Sort by priority + queue = queue.sorted { left, right in + left.config.priority > right.config.priority + } let current = queue.removeFirst() - self.current = current - 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.syncQueue.async(execute: { - guard let strongSelf = self else { return } - strongSelf.hide(presenter: current) - }) - return - } - strongSelf.queueAutoHide() + self._current = current + // Set `autohideToken` before the animation starts in case + // the dismiss gesture begins before we've queued the autohide + // block on animation completion. + self.autohideToken = current + current.showDate = CACurrentMediaTime() + do { + try current.show { [weak self] completed in + guard let self else { return } + guard completed else { + self.internalHide(presenter: current) + return + } + if current === self.autohideToken { + self.queueAutoHide() } - } catch { - strongSelf.current = nil } + } catch { + _current = nil } } - - func hideCurrent() { - guard let current = current else { return } - DispatchQueue.main.async { [weak self] in - current.hide { (completed) in - guard completed else { return } - guard let strongSelf = self else { return } - strongSelf.syncQueue.async(execute: { - guard let strongSelf = self else { return } - strongSelf.current = nil - }) + + fileprivate func internalHide(presenter: Presenter) { + if presenter == _current { + hideCurrent() + } else { + queue = queue.filter { $0 != presenter } + delays.remove(presenter: presenter) + } + } + + fileprivate func hideCurrent(animated: Bool = true) { + guard let current = _current, !current.isHiding else { return } + let action = { [weak self] in + current.hide(animated: animated) { (completed) in + 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 + Task { + try? await Task.sleep(seconds: delay) + action() + } } - - fileprivate var autohideToken: AnyObject? - + + fileprivate weak var autohideToken: Presenter? + fileprivate func queueAutoHide() { - guard let current = current else { return } + guard let current = _current else { return } autohideToken = current if let pauseDuration = current.pauseDuration { - let delayTime = DispatchTime.now() + pauseDuration - syncQueue.asyncAfter(deadline: delayTime, execute: { [weak self] in - guard let strongSelf = self else { return } + Task { [weak self] in + try? await Task.sleep(seconds: pauseDuration) // Make sure we've still got a green light to auto-hide. - if strongSelf.autohideToken !== current { return } - strongSelf.hide(presenter: current) - }) + guard let self, self.autohideToken == current else { return } + self.internalHide(presenter: current) + } } } - - /* - MARK: - PresenterDelegate + + deinit { + guard let current = _current else { return } + Task { @MainActor [current] in + current.hide(animated: true) { _ in } + } + } +} + +/* + MARK: - Accessing messages + */ + +extension SwiftMessages { + + /** + Returns the message view of type `T` if it is currently being shown or hidden. + + - Returns: The view of type `T` if it is currently being shown or hidden. */ - + public func current<T: UIView>() -> T? { + _current?.view as? T + } + + /** + Returns a message view with the given `id` if it is currently being shown or hidden. + + - Parameter id: The id of a message that adopts `Identifiable`. + - Returns: The view with matching id if currently being shown or hidden. + */ + public func current<T: UIView>(id: String) -> T? { + _current?.id == id ? _current?.view as? T : nil + } + + /** + Returns a message view with the given `id` if it is currently in the queue to be shown. + + - Parameter id: The id of a message that adopts `Identifiable`. + - Returns: The view with matching id if currently queued to be shown. + */ + public func queued<T: UIView>(id: String) -> T? { + queue.first { $0.id == id }?.view as? T + } + + /** + Returns a message view with the given `id` if it is currently being + shown, hidden or in the queue to be shown. + + - Parameter id: The id of a message that adopts `Identifiable`. + - Returns: The view with matching id if currently queued to be shown. + */ + public func currentOrQueued<T: UIView>(id: String) -> T? { + return current(id: id) ?? queued(id: id) + } +} + +/* + MARK: - PresenterDelegate + */ + +extension SwiftMessages: PresenterDelegate { + func hide(presenter: Presenter) { - syncQueue.async { [weak self] in - guard let strongSelf = self else { return } - if let current = strongSelf.current, presenter === current { - strongSelf.hideCurrent() - } - strongSelf.queue = strongSelf.queue.filter { $0 !== presenter } - } + self.internalHide(presenter: presenter) } - - func panStarted(presenter: Presenter) { + + public func hide(animator: Animator) { + guard let presenter = self.presenter(forAnimator: animator) else { return } + self.internalHide(presenter: presenter) + } + + public func panStarted(animator: Animator) { autohideToken = nil } - - func panEnded(presenter: Presenter) { + + public func panEnded(animator: Animator) { queueAutoHide() } + + private func presenter(forAnimator animator: Animator) -> Presenter? { + if let current = _current, animator === current.animator { + return current + } + let queued = queue.filter { $0.animator === animator } + return queued.first + } } /** MARK: - Creating views from nibs - + This extension provides several convenience functions for instantiating views from nib files. SwiftMessages provides several default nib files in the Resources folder that can be drag-and-dropped into a project as a starting point and modified. @@ -510,7 +850,11 @@ extension SwiftMessages { } } let arrayOfViews = resolvedBundle.loadNibNamed(name, owner: filesOwner, options: nil) ?? [] + #if swift(>=4.1) + guard let view = arrayOfViews.compactMap( { $0 as? T} ).first else { throw SwiftMessagesError.cannotLoadViewFromNib(nibName: name) } + #else guard let view = arrayOfViews.flatMap( { $0 as? T} ).first else { throw SwiftMessagesError.cannotLoadViewFromNib(nibName: name) } + #endif return view } } @@ -530,10 +874,10 @@ extension SwiftMessages { a set of static APIs that wrap calls to this instance. For example, `SwiftMessages.show()` is equivalent to `SwiftMessages.sharedInstance.show()`. */ - public static var sharedInstance: SwiftMessages { + nonisolated public static var sharedInstance: SwiftMessages { return globalInstance } - + public static func show(viewProvider: @escaping ViewProvider) { globalInstance.show(viewProvider: viewProvider) } @@ -550,8 +894,8 @@ extension SwiftMessages { globalInstance.show(config: config, view: view) } - public static func hide() { - globalInstance.hide() + public static func hide(animated: Bool = true) { + globalInstance.hide(animated: animated) } public static func hideAll() { @@ -561,7 +905,11 @@ extension SwiftMessages { public static func hide(id: String) { globalInstance.hide(id: id) } - + + public static func hideCounted(id: String) { + globalInstance.hideCounted(id: id) + } + public static var defaultConfig: Config { get { return globalInstance.defaultConfig @@ -579,4 +927,24 @@ extension SwiftMessages { globalInstance.pauseBetweenMessages = newValue } } + + public static func current<T: UIView>(id: String) -> T? { + return globalInstance.current(id: id) + } + + public static func queued<T: UIView>(id: String) -> T? { + return globalInstance.queued(id: id) + } + + public static func currentOrQueued<T: UIView>(id: String) -> T? { + return globalInstance.currentOrQueued(id: id) + } + + public static func count(id: String) -> Int { + return globalInstance.count(id: id) + } + + public static func set(count: Int, for id: String) { + globalInstance.set(count: count, for: id) + } } diff --git a/SwiftMessages/SwiftMessagesSegue.swift b/SwiftMessages/SwiftMessagesSegue.swift new file mode 100644 index 00000000..35687e14 --- /dev/null +++ b/SwiftMessages/SwiftMessagesSegue.swift @@ -0,0 +1,407 @@ +// +// SwiftMessagesSegue.swift +// SwiftMessages +// +// Created by Timothy Moose on 5/30/18. +// Copyright © 2018 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +/** + `SwiftMessagesSegue` is a configurable subclass of `UIStoryboardSegue` that utilizes + SwiftMessages to present and dismiss modal view controllers. It performs these transitions by + becoming your view controller's `transitioningDelegate` and calling SwiftMessage's `show()` + and `hide()` under the hood. + + To use `SwiftMessagesSegue` with Interface Builder, control-drag a segue, then select + "swift messages" from the Segue Type dialog. This configures a default transition. There are + two suggested ways to further configure the transition by setting options on `SwiftMessagesSegue`. + First, and recommended, you may subclass `SwiftMessagesSegue` and override `init(identifier:source:destination:)`. + Subclasses will automatically appear in the segue type dialog using an auto-generated name (for example, the + name for "VeryNiceSegue" would be "very nice"). Second, you may override `prepare(for:sender:)` in the + presenting view controller and downcast the segue to `SwiftMessagesSegue`. + + `SwiftMessagesSegue` can be used without an associated storyboard or segue by doing the following in + the presenting view controller. + + let destinationVC = ... // make a reference to a destination view controller + let segue = SwiftMessagesSegue(identifier: nil, source: self, destination: destinationVC) + ... // do any configuration here + segue.perform() + + To dismiss, call the UIKit API on the presenting view controller: + + dismiss(animated: true, completion: nil) + + It is not necessary to retain `segue` because it retains itself until dismissal. However, you can + retain it if you plan to `perform()` more than once. + + #### Present the controller on top of all controllers + + If you don't know the presenter or you don't want to pass it as a source, like when you + have a completely separated message controller, you can pass a `WindowViewController` + as the `source` argument of the segue's initializer. + + By default, the window will be shown in the current window scene at `.normal` window level. + However, these parameters can be customized by initializing the view controller with a `SwiftMessages.Config` that has the `SwiftMessages.Config.presentationContext` set to either `.window` or `.windowScene`: + + + note: Some additional details: + 1. Your view controller's view will be embedded in a `SwiftMessages.BaseView` in order to + utilize some SwiftMessages features. This view can be accessed and configured via the + `SwiftMessagesSegue.messageView` property. For example, you may configure a default drop + shadow by calling `segue.messageView.configureDropShadow()`. + 2. SwiftMessagesSegue provides static default view controller sizing based on device. + However, it is recommended that you specify sizing appropriate for your content using + one of the following methods. + 1. Define sufficient width and height constraints in your view controller. + 2. Set `preferredContentSize` (a.k.a "Use Preferred Explicit Size" in Interface Builder's + attribute inspector). Zeros are ignored, e.g. `CGSize(width: 0, height: 350)` only + affects the height. + 3. Add explicit width and/or height constraints to `segue.messageView.backgroundView`. + Note that `Layout.topMessage` and `Layout.bottomMessage` are always full screen width. + For other layouts, the there is a maximum 500pt width on iPad (regular horizontal size class) + at 950 priority, which can be overridden by adding higher-priority constraints. + + See the "View Controllers" selection in the Demo app for examples. + */ + +open class SwiftMessagesSegue: UIStoryboardSegue { + + /** + Specifies one of the pre-defined layouts, mirroring a subset of `MessageView.Layout`. + */ + public enum Layout { + + /// The standard message view layout on top. + case topMessage + + /// The standard message view layout on bottom. + case bottomMessage + + /// A floating card-style view with rounded corners on top + case topCard + + /// A floating tab-style view with rounded corners on bottom + case topTab + + /// A floating card-style view with rounded corners on bottom + case bottomCard + + /// A floating tab-style view with rounded corners on top + case bottomTab + + /// A floating card-style view typically used with `.center` presentation style. + case centered + } + + /** + Specifies how the view controller's view is installed into the + containing message view. + */ + public enum Containment { + + /** + The view controller's view is installed for edge-to-edge display, extending into the safe areas + to the device edges. This is done by calling `messageView.installContentView(:insets:)` + See that method's documentation for additional details. + */ + case content + + /** + The view controller's view is installed for card-style layouts, inset from the margins + and avoiding safe areas. This is done by calling `messageView.installBackgroundView(:insets:)`. + See that method's documentation for details. + */ + case background + + /** + The view controller's view is installed for tab-style layouts, inset from the side margins, but extending + to the device edge on the top or bottom. This is done by calling `messageView.installBackgroundVerticalView(:insets:)`. + See that method's documentation for details. + */ + case backgroundVertical + } + + /// The presentation style to use. See the SwiftMessages.PresentationStyle for details. + public var presentationStyle: SwiftMessages.PresentationStyle { + get { return messenger.defaultConfig.presentationStyle } + set { messenger.defaultConfig.presentationStyle = newValue } + } + + /// The dim mode to use. See the SwiftMessages.DimMode for details. + public var dimMode: SwiftMessages.DimMode { + get { return messenger.defaultConfig.dimMode} + set { messenger.defaultConfig.dimMode = newValue } + } + + // duration + public var duration: SwiftMessages.Duration { + get { return messenger.defaultConfig.duration} + set { messenger.defaultConfig.duration = newValue } + } + + /// Specifies whether or not the interactive pan-to-hide gesture is enabled + /// on the message view. The default value is `true`, but may not be appropriate + /// for view controllers that use swipe or pan gestures. + public var interactiveHide: Bool { + get { return messenger.defaultConfig.interactiveHide } + set { messenger.defaultConfig.interactiveHide = newValue } + } + + /// Specifies an optional array of event listeners. + public var eventListeners: [SwiftMessages.EventListener] { + get { return messenger.defaultConfig.eventListeners } + set { messenger.defaultConfig.eventListeners = newValue } + } + + /** + Normally, the destination view controller's `modalPresentationStyle` is changed + to `.custom` in the `perform()` function. Set this property to `false` to prevent it from + being overridden. + */ + public var overrideModalPresentationStyle: Bool = true + + /** + The view that is passed to `SwiftMessages.show(config:view:)` during presentation. + The view controller's view is installed into `containerView`, which is itself installed + into `messageView`. `SwiftMessagesSegue` does this installation automatically based on the + value of the `containment` property. `BaseView` is the parent of `MessageView` and provides a + number of configuration options that you may use. For example, you may configure a default drop + shadow by calling `messageView.configureDropShadow()`. + */ + public var messageView = BaseView() + + /** + The view controller's view is embedded in `containerView` before being installed into + `messageView`. This view provides configurable squircle (round) corners (see the parent + class `CornerRoundingView`). + */ + public var containerView: CornerRoundingView = CornerRoundingView() + + /** + Specifies how the view controller's view is installed into the + containing message view. See `Containment` for details. + */ + public var containment: Containment = .content + + /** + Supply an instance of `KeyboardTrackingView` to have the message view avoid the keyboard. + */ + public var keyboardTrackingView: KeyboardTrackingView? { + get { + return messenger.defaultConfig.keyboardTrackingView + } + set { + messenger.defaultConfig.keyboardTrackingView = newValue + } + } + + private var messenger = SwiftMessages() + private var selfRetainer: SwiftMessagesSegue? = nil + private lazy var hider = { return TransitioningDismisser(segue: self) }() + + private lazy var presenter = { + return Presenter(config: messenger.defaultConfig, view: messageView, delegate: messenger) + }() + + override open func perform() { + (source as? WindowViewController)?.install() + selfRetainer = self + startReleaseMonitor() + if overrideModalPresentationStyle { + destination.modalPresentationStyle = .custom + } + destination.transitioningDelegate = self + source.present(destination, animated: true, completion: nil) + } + + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + dimMode = .gray(interactive: true) + messenger.defaultConfig.duration = .forever + } + + 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() { + 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 + case .some: self.startReleaseMonitor() + } + } + } +} + +extension SwiftMessagesSegue { + /// A convenience method for configuring some pre-defined layouts that mirror a subset of `MessageView.Layout`. + public func configure(layout: Layout) { + messageView.bounceAnimationOffset = 0 + containment = .content + containerView.cornerRadius = 0 + containerView.roundsLeadingCorners = false + messageView.configureDropShadow() + switch layout { + case .topMessage: + messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) + messageView.collapseLayoutMarginAdditions = false + let animation = TopBottomAnimation(style: .top) + animation.springDamping = 1 + presentationStyle = .custom(animator: animation) + case .bottomMessage: + messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) + messageView.collapseLayoutMarginAdditions = false + let animation = TopBottomAnimation(style: .bottom) + animation.springDamping = 1 + presentationStyle = .custom(animator: animation) + case .topCard: + containment = .background + messageView.layoutMarginAdditions = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) + messageView.collapseLayoutMarginAdditions = true + containerView.cornerRadius = 15 + presentationStyle = .top + case .bottomCard: + containment = .background + messageView.layoutMarginAdditions = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) + messageView.collapseLayoutMarginAdditions = true + containerView.cornerRadius = 15 + presentationStyle = .bottom + case .topTab: + containment = .backgroundVertical + messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 10, bottom: 20, right: 10) + messageView.collapseLayoutMarginAdditions = true + containerView.cornerRadius = 15 + containerView.roundsLeadingCorners = true + let animation = TopBottomAnimation(style: .top) + animation.springDamping = 1 + presentationStyle = .custom(animator: animation) + case .bottomTab: + containment = .backgroundVertical + messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 10, bottom: 20, right: 10) + messageView.collapseLayoutMarginAdditions = true + containerView.cornerRadius = 15 + containerView.roundsLeadingCorners = true + let animation = TopBottomAnimation(style: .bottom) + animation.springDamping = 1 + presentationStyle = .custom(animator: animation) + case .centered: + containment = .background + messageView.layoutMarginAdditions = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) + messageView.collapseLayoutMarginAdditions = true + containerView.cornerRadius = 15 + presentationStyle = .center + } + } +} + +extension SwiftMessagesSegue: UIViewControllerTransitioningDelegate { + public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { + let shower = TransitioningPresenter(segue: self) + let hider = self.hider + messenger.defaultConfig.eventListeners.append { [weak self] in + switch $0 { + case .didShow: + shower.completeTransition?(true) + case .didHide: + if let completeTransition = hider.completeTransition { + completeTransition(true) + } else { + // Case where message is internally hidden by SwiftMessages, such as with a + // dismiss gesture, rather than by view controller dismissal. + source.dismiss(animated: false, completion: nil) + } + (source as? WindowViewController)?.uninstall() + self?.selfRetainer = nil + default: break + } + } + return shower + } + + public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { + return hider + } +} + +extension SwiftMessagesSegue { + private class TransitioningPresenter: NSObject, UIViewControllerAnimatedTransitioning { + + fileprivate private(set) var completeTransition: ((Bool) -> Void)? + private weak var segue: SwiftMessagesSegue? + + fileprivate init(segue: SwiftMessagesSegue) { + self.segue = segue + } + + func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { + return segue?.presenter.animator.showDuration ?? 0.5 + } + + func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { + guard let segue = segue, + let toView = transitionContext.view(forKey: .to) else { + transitionContext.completeTransition(false) + return + } + completeTransition = transitionContext.completeTransition + let transitionContainer = transitionContext.containerView + toView.translatesAutoresizingMaskIntoConstraints = false + segue.containerView.addSubview(toView) + segue.containerView.topAnchor.constraint(equalTo: toView.topAnchor).isActive = true + segue.containerView.bottomAnchor.constraint(equalTo: toView.bottomAnchor).isActive = true + segue.containerView.leadingAnchor.constraint(equalTo: toView.leadingAnchor).isActive = true + segue.containerView.trailingAnchor.constraint(equalTo: toView.trailingAnchor).isActive = true + // Install the `toView` into the message view. + switch segue.containment { + case .content: + segue.messageView.installContentView(segue.containerView) + case .background: + segue.messageView.installBackgroundView(segue.containerView) + case .backgroundVertical: + segue.messageView.installBackgroundVerticalView(segue.containerView) + } + let toVC = transitionContext.viewController(forKey: .to) + if let preferredHeight = toVC?.preferredContentSize.height, + preferredHeight > 0 { + segue.containerView.heightAnchor.constraint(equalToConstant: preferredHeight).with(priority: UILayoutPriority(rawValue: 951)).isActive = true + } + if let preferredWidth = toVC?.preferredContentSize.width, + preferredWidth > 0 { + segue.containerView.widthAnchor.constraint(equalToConstant: preferredWidth).with(priority: UILayoutPriority(rawValue: 951)).isActive = true + } + segue.presenter.config.presentationContext = .view(transitionContainer) + segue.messenger.show(presenter: segue.presenter) + } + } +} + +extension SwiftMessagesSegue { + private class TransitioningDismisser: NSObject, UIViewControllerAnimatedTransitioning { + + fileprivate private(set) var completeTransition: ((Bool) -> Void)? + private weak var segue: SwiftMessagesSegue? + + fileprivate init(segue: SwiftMessagesSegue) { + self.segue = segue + } + + func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { + return segue?.presenter.animator.hideDuration ?? 0.5 + } + + func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { + guard let messenger = segue?.messenger else { + transitionContext.completeTransition(false) + return + } + completeTransition = transitionContext.completeTransition + messenger.hide() + } + } +} diff --git a/SwiftMessages/Task+Extensions.swift b/SwiftMessages/Task+Extensions.swift new file mode 100644 index 00000000..9d6f1c3f --- /dev/null +++ b/SwiftMessages/Task+Extensions.swift @@ -0,0 +1,15 @@ +// +// Task+Extensions.swift +// SwiftMessages +// +// Created by Timothy Moose on 12/3/23. +// Copyright © 2023 SwiftKick Mobile. All rights reserved. +// + +import Foundation + +extension Task where Success == Never, Failure == Never { + static func sleep(seconds: TimeInterval) async throws { + try await sleep(nanoseconds: UInt64(seconds * 1_000_000_000)) + } +} diff --git a/SwiftMessages/Theme.swift b/SwiftMessages/Theme.swift index a31bc579..5bf10a4e 100644 --- a/SwiftMessages/Theme.swift +++ b/SwiftMessages/Theme.swift @@ -19,22 +19,22 @@ public enum Theme { /// The Icon enum provides type-safe access to the included icons. public enum Icon: String { - case Error = "errorIcon" - case Warning = "warningIcon" - case Success = "successIcon" - case Info = "infoIcon" - case ErrorLight = "errorIconLight" - case WarningLight = "warningIconLight" - case SuccessLight = "successIconLight" - case InfoLight = "infoIconLight" - case ErrorSubtle = "errorIconSubtle" - case WarningSubtle = "warningIconSubtle" - case SuccessSubtle = "successIconSubtle" - case InfoSubtle = "infoIconSubtle" + case error = "errorIcon" + case warning = "warningIcon" + case success = "successIcon" + case info = "infoIcon" + case errorLight = "errorIconLight" + case warningLight = "warningIconLight" + case successLight = "successIconLight" + case infoLight = "infoIconLight" + case errorSubtle = "errorIconSubtle" + case warningSubtle = "warningIconSubtle" + case successSubtle = "successIconSubtle" + case infoSubtle = "infoIconSubtle" /// Returns the associated image. - public var image: UIImage { - return UIImage(named: rawValue, in: Bundle.sm_frameworkBundle(), compatibleWith: nil)! + public var image: UIImage { + return UIImage(named: rawValue, in: Bundle.sm_frameworkBundle(), compatibleWith: nil)!.withRenderingMode(.alwaysTemplate) } } @@ -44,22 +44,24 @@ public enum IconStyle { case `default` case light case subtle + case none /// Returns the image for the given theme - public func image(theme: Theme) -> UIImage { + public func image(theme: Theme) -> UIImage? { switch (theme, self) { - case (.info, .default): return Icon.Info.image - case (.info, .light): return Icon.InfoLight.image - case (.info, .subtle): return Icon.InfoSubtle.image - case (.success, .default): return Icon.Success.image - case (.success, .light): return Icon.SuccessLight.image - case (.success, .subtle): return Icon.SuccessSubtle.image - case (.warning, .default): return Icon.Warning.image - case (.warning, .light): return Icon.WarningLight.image - case (.warning, .subtle): return Icon.WarningSubtle.image - case (.error, .default): return Icon.Error.image - case (.error, .light): return Icon.ErrorLight.image - case (.error, .subtle): return Icon.ErrorSubtle.image + case (.info, .default): return Icon.info.image + case (.info, .light): return Icon.infoLight.image + case (.info, .subtle): return Icon.infoSubtle.image + case (.success, .default): return Icon.success.image + case (.success, .light): return Icon.successLight.image + case (.success, .subtle): return Icon.successSubtle.image + case (.warning, .default): return Icon.warning.image + case (.warning, .light): return Icon.warningLight.image + case (.warning, .subtle): return Icon.warningSubtle.image + case (.error, .default): return Icon.error.image + case (.error, .light): return Icon.errorLight.image + case (.error, .subtle): return Icon.errorSubtle.image + default: return nil } } } diff --git a/SwiftMessages/TopBottomAnimation.swift b/SwiftMessages/TopBottomAnimation.swift new file mode 100644 index 00000000..49a45adc --- /dev/null +++ b/SwiftMessages/TopBottomAnimation.swift @@ -0,0 +1,227 @@ +// +// TopBottomAnimation.swift +// SwiftMessages +// +// Created by Timothy Moose on 6/4/17. +// Copyright © 2017 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +@MainActor +public class TopBottomAnimation: NSObject, Animator { + + public weak var delegate: AnimationDelegate? + + public let style: TopBottomAnimationStyle + + public var showDuration: TimeInterval = 0.4 + + public var hideDuration: TimeInterval = 0.2 + + public var springDamping: CGFloat = 0.8 + + public var closeSpeedThreshold: CGFloat = 750.0; + + public var closePercentThreshold: CGFloat = 0.33; + + public var closeAbsoluteThreshold: CGFloat = 75.0; + + public private(set) lazy var panGestureRecognizer: UIPanGestureRecognizer = { + let pan = UIPanGestureRecognizer() + pan.addTarget(self, action: #selector(pan(_:))) + return pan + }() + + weak var messageView: UIView? + weak var containerView: UIView? + var context: AnimationContext? + + public init(style: TopBottomAnimationStyle) { + self.style = style + } + + init(style: TopBottomAnimationStyle, delegate: AnimationDelegate) { + self.style = style + self.delegate = delegate + } + + public func show(context: AnimationContext, completion: @escaping AnimationCompletion) { + NotificationCenter.default.addObserver(self, selector: #selector(adjustMargins), name: UIDevice.orientationDidChangeNotification, object: nil) + install(context: context) + showAnimation(completion: completion) + } + + public func hide(context: AnimationContext, completion: @escaping AnimationCompletion) { + NotificationCenter.default.removeObserver(self) + let view = context.messageView + self.context = context + UIView.animate(withDuration: hideDuration, delay: 0, options: [.beginFromCurrentState, .curveEaseIn], animations: { + switch self.style { + case .top: + view.transform = CGAffineTransform(translationX: 0, y: -view.frame.height) + case .bottom: + view.transform = CGAffineTransform(translationX: 0, y: view.frame.maxY + view.frame.height) + } + }, completion: { completed in + #if SWIFTMESSAGES_APP_EXTENSIONS + completion(completed) + #else + // Fix #131 by always completing if application isn't active. + completion(completed || UIApplication.shared.applicationState != .active) + #endif + }) + } + + func install(context: AnimationContext) { + let view = context.messageView + let container = context.containerView + messageView = view + containerView = container + self.context = context + if let adjustable = context.messageView as? MarginAdjustable { + bounceOffset = adjustable.bounceAnimationOffset + } + view.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(view) + view.leadingAnchor.constraint(equalTo: container.leadingAnchor).isActive = true + view.trailingAnchor.constraint(equalTo: container.trailingAnchor).isActive = true + switch style { + case .top: + view.topAnchor.constraint(equalTo: container.topAnchor, constant: -bounceOffset).with(priority: UILayoutPriority(200)).isActive = true + case .bottom: + view.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: bounceOffset).with(priority: UILayoutPriority(200)).isActive = true + } + // Important to layout now in order to get the right safe area insets + container.layoutIfNeeded() + adjustMargins() + container.layoutIfNeeded() + let animationDistance = view.frame.height + switch style { + case .top: + view.transform = CGAffineTransform(translationX: 0, y: -animationDistance) + case .bottom: + view.transform = CGAffineTransform(translationX: 0, y: animationDistance) + } + if context.interactiveHide { + if let view = view as? BackgroundViewable { + view.backgroundView.addGestureRecognizer(panGestureRecognizer) + } else { + view.addGestureRecognizer(panGestureRecognizer) + } + } + if let view = view as? BackgroundViewable, + let cornerRoundingView = view.backgroundView as? CornerRoundingView, + cornerRoundingView.roundsLeadingCorners { + switch style { + case .top: + cornerRoundingView.roundedCorners = [.bottomLeft, .bottomRight] + case .bottom: + cornerRoundingView.roundedCorners = [.topLeft, .topRight] + } + } + } + + @objc public func adjustMargins() { + guard let adjustable = messageView as? MarginAdjustable & UIView, + let context = context else { return } + adjustable.preservesSuperviewLayoutMargins = false + adjustable.insetsLayoutMarginsFromSafeArea = false + var layoutMargins = adjustable.defaultMarginAdjustment(context: context) + switch style { + case .top: + layoutMargins.top += bounceOffset + case .bottom: + layoutMargins.bottom += bounceOffset + } + adjustable.layoutMargins = layoutMargins + } + + func showAnimation(completion: @escaping AnimationCompletion) { + guard let view = messageView else { + completion(false) + return + } + let animationDistance = abs(view.transform.ty) + // Cap the initial velocity at zero because the bounceOffset may not be great + // enough to allow for greater bounce induced by a quick panning motion. + let initialSpringVelocity = animationDistance == 0.0 ? 0.0 : min(0.0, closeSpeed / animationDistance) + UIView.animate(withDuration: showDuration, delay: 0.0, usingSpringWithDamping: springDamping, initialSpringVelocity: initialSpringVelocity, options: [.beginFromCurrentState, .curveLinear, .allowUserInteraction], animations: { + view.transform = .identity + }, completion: { completed in + // Fix #131 by always completing if application isn't active. + #if SWIFTMESSAGES_APP_EXTENSIONS + completion(completed) + #else + completion(completed || UIApplication.shared.applicationState != .active) + #endif + }) + } + + fileprivate var bounceOffset: CGFloat = 5 + + /* + MARK: - Pan to close + */ + + fileprivate var closing = false + fileprivate var rubberBanding = false + fileprivate var closeSpeed: CGFloat = 0.0 + fileprivate var closePercent: CGFloat = 0.0 + fileprivate var panTranslationY: CGFloat = 0.0 + + @objc func pan(_ pan: UIPanGestureRecognizer) { + switch pan.state { + case .changed: + guard let view = messageView else { return } + let height = view.bounds.height - bounceOffset + if height <= 0 { return } + var velocity = pan.velocity(in: view) + var translation = pan.translation(in: view) + if case .top = style { + velocity.y *= -1.0 + translation.y *= -1.0 + } + var translationAmount = translation.y >= 0 ? translation.y : -pow(abs(translation.y), 0.7) + if !closing { + // Turn on rubber banding if background view is inset from message view. + if let background = (messageView as? BackgroundViewable)?.backgroundView, background != view { + switch style { + case .top: + rubberBanding = background.frame.minY > 0 + case .bottom: + rubberBanding = background.frame.maxY < view.bounds.height + } + } + if !rubberBanding && translationAmount < 0 { return } + closing = true + delegate?.panStarted(animator: self) + } + if !rubberBanding && translationAmount < 0 { translationAmount = 0 } + switch style { + case .top: + view.transform = CGAffineTransform(translationX: 0, y: -translationAmount) + case .bottom: + view.transform = CGAffineTransform(translationX: 0, y: translationAmount) + } + closeSpeed = velocity.y + closePercent = translation.y / height + panTranslationY = translation.y + case .ended, .cancelled: + if closeSpeed > closeSpeedThreshold || closePercent > closePercentThreshold || panTranslationY > closeAbsoluteThreshold { + delegate?.hide(animator: self) + } else { + closing = false + rubberBanding = false + closeSpeed = 0.0 + closePercent = 0.0 + panTranslationY = 0.0 + showAnimation(completion: { (completed) in + self.delegate?.panEnded(animator: self) + }) + } + default: + break + } + } +} diff --git a/SwiftMessages/TopBottomAnimationStyle.swift b/SwiftMessages/TopBottomAnimationStyle.swift new file mode 100644 index 00000000..626ad09c --- /dev/null +++ b/SwiftMessages/TopBottomAnimationStyle.swift @@ -0,0 +1,12 @@ +// +// TopBottomAnimationStyle.swift +// SwiftMessages +// +// Created by Timothy Moose on 6/23/24. +// Copyright © 2024 SwiftKick Mobile. All rights reserved. +// + +public enum TopBottomAnimationStyle { + case top + case bottom +} diff --git a/SwiftMessages/TopBottomPresentable.swift b/SwiftMessages/TopBottomPresentable.swift new file mode 100644 index 00000000..18804160 --- /dev/null +++ b/SwiftMessages/TopBottomPresentable.swift @@ -0,0 +1,49 @@ +// +// File.swift +// +// +// Created by Julien Di Marco on 23/04/2024. +// + +import Foundation + +// MARK: - TopBottom Presentable Definition + +@MainActor +protocol TopBottomPresentable { + var topBottomStyle: TopBottomAnimationStyle? { get } +} + +// MARK: - TopBottom Presentable Conformances + +extension TopBottomAnimation: TopBottomPresentable { + var topBottomStyle: TopBottomAnimationStyle? { return style } +} + +extension PhysicsAnimation: TopBottomPresentable { + var topBottomStyle: TopBottomAnimationStyle? { + switch placement { + case .top: return .top + case .bottom: return .bottom + default: return nil + } + } +} + +// MARK: - Presentation Style Convenience + +extension SwiftMessages.PresentationStyle { + /// A temporary workaround to allow custom presentation contexts using `TopBottomAnimation` + /// to display properly behind bars. THe long term solution is to refactor all of the + /// presentation context logic to work with safe area insets. + @MainActor + var topBottomStyle: TopBottomAnimationStyle? { + switch self { + case .top: return .top + case .bottom: return .bottom + case .custom(let animator as TopBottomPresentable): return animator.topBottomStyle + case .center: return nil + default: return nil + } + } +} diff --git a/SwiftMessages/UIEdgeInsets+Extensions.swift b/SwiftMessages/UIEdgeInsets+Extensions.swift new file mode 100644 index 00000000..19bbe4e3 --- /dev/null +++ b/SwiftMessages/UIEdgeInsets+Extensions.swift @@ -0,0 +1,27 @@ +// +// UIEdgeInsets+Extensions.swift +// SwiftMessages +// +// Created by Timothy Moose on 5/23/18. +// Copyright © 2018 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +extension UIEdgeInsets { + public static func +(left: UIEdgeInsets, right: UIEdgeInsets) -> UIEdgeInsets { + let topSum = left.top + right.top + let leftSum = left.left + right.left + let bottomSum = left.bottom + right.bottom + let rightSum = left.right + right.right + return UIEdgeInsets(top: topSum, left: leftSum, bottom: bottomSum, right: rightSum) + } + + public static func -(left: UIEdgeInsets, right: UIEdgeInsets) -> UIEdgeInsets { + let topSum = left.top - right.top + let leftSum = left.left - right.left + let bottomSum = left.bottom - right.bottom + let rightSum = left.right - right.right + return UIEdgeInsets(top: topSum, left: leftSum, bottom: bottomSum, right: rightSum) + } +} diff --git a/SwiftMessages/UIViewController+Utils.swift b/SwiftMessages/UIViewController+Extensions.swift similarity index 67% rename from SwiftMessages/UIViewController+Utils.swift rename to SwiftMessages/UIViewController+Extensions.swift index eaa38cb6..1400e03c 100644 --- a/SwiftMessages/UIViewController+Utils.swift +++ b/SwiftMessages/UIViewController+Extensions.swift @@ -1,5 +1,5 @@ // -// UIViewController+Utils.swift +// UIViewController+Extensions.swift // SwiftMessages // // Created by Timothy Moose on 8/5/16. @@ -8,24 +8,22 @@ import UIKit -private let fullScreenStyles: [UIModalPresentationStyle] = [.fullScreen, .overFullScreen] - extension UIViewController { func sm_selectPresentationContextTopDown(_ config: SwiftMessages.Config) -> UIViewController { - let presentationStyle = config.presentationStyle - if let presented = sm_presentedFullScreenViewController() { + let topBottomStyle = config.presentationStyle.topBottomStyle + if let presented = presentedViewController { return presented.sm_selectPresentationContextTopDown(config) - } else if case .top = presentationStyle, let navigationController = sm_selectNavigationControllerTopDown() { + } else if case .top? = topBottomStyle, let navigationController = sm_selectNavigationControllerTopDown() { return navigationController - } else if case .bottom = presentationStyle, let tabBarController = sm_selectTabBarControllerTopDown() { + } else if case .bottom? = topBottomStyle, let tabBarController = sm_selectTabBarControllerTopDown() { return tabBarController } - return WindowViewController(windowLevel: self.view.window?.windowLevel ?? UIWindowLevelNormal, config: config) + return WindowViewController.newInstance(config: config) } fileprivate func sm_selectNavigationControllerTopDown() -> UINavigationController? { - if let presented = sm_presentedFullScreenViewController() { + if let presented = presentedViewController { return presented.sm_selectNavigationControllerTopDown() } else if let navigationController = self as? UINavigationController { if navigationController.sm_isVisible(view: navigationController.navigationBar) { @@ -39,7 +37,7 @@ extension UIViewController { } fileprivate func sm_selectTabBarControllerTopDown() -> UITabBarController? { - if let presented = sm_presentedFullScreenViewController() { + if let presented = presentedViewController { return presented.sm_selectTabBarControllerTopDown() } else if let navigationController = self as? UINavigationController { return navigationController.topViewController?.sm_selectTabBarControllerTopDown() @@ -51,24 +49,17 @@ extension UIViewController { } return nil } - - fileprivate func sm_presentedFullScreenViewController() -> UIViewController? { - if let presented = self.presentedViewController, fullScreenStyles.contains(presented.modalPresentationStyle) { - return presented - } - return nil - } func sm_selectPresentationContextBottomUp(_ config: SwiftMessages.Config) -> UIViewController { - let presentationStyle = config.presentationStyle + let topBottomStyle = config.presentationStyle.topBottomStyle if let parent = parent { if let navigationController = parent as? UINavigationController { - if case .top = presentationStyle, navigationController.sm_isVisible(view: navigationController.navigationBar) { + if case .top? = topBottomStyle, navigationController.sm_isVisible(view: navigationController.navigationBar) { return navigationController } return navigationController.sm_selectPresentationContextBottomUp(config) } else if let tabBarController = parent as? UITabBarController { - if case .bottom = presentationStyle, tabBarController.sm_isVisible(view: tabBarController.tabBar) { + if case .bottom? = topBottomStyle, tabBarController.sm_isVisible(view: tabBarController.tabBar) { return tabBarController } return tabBarController.sm_selectPresentationContextBottomUp(config) @@ -80,7 +71,7 @@ extension UIViewController { if let parent = self.parent { return parent.sm_selectPresentationContextBottomUp(config) } else { - return WindowViewController(windowLevel: self.view.window?.windowLevel ?? UIWindowLevelNormal, config: config) + return WindowViewController.newInstance(config: config) } } return self diff --git a/SwiftMessages/UIWindow+Extensions.swift b/SwiftMessages/UIWindow+Extensions.swift new file mode 100644 index 00000000..6a626f4e --- /dev/null +++ b/SwiftMessages/UIWindow+Extensions.swift @@ -0,0 +1,34 @@ +// +// UIWindow+Extensions.swift +// SwiftMessages +// +// Created by Timothy Moose on 3/11/21. +// Copyright © 2021 SwiftKick Mobile. All rights reserved. +// + +import UIKit + +extension UIWindow { + #if !SWIFTMESSAGES_APP_EXTENSIONS + static var keyWindow: UIWindow? { + return UIApplication.shared.connectedScenes + .sorted { $0.activationState.sortPriority < $1.activationState.sortPriority } + .compactMap { $0 as? UIWindowScene } + .compactMap { $0.windows.first { $0.isKeyWindow } } + .first + } + #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 + } + } +} diff --git a/SwiftMessages/Weak.swift b/SwiftMessages/Weak.swift new file mode 100644 index 00000000..a9bc4700 --- /dev/null +++ b/SwiftMessages/Weak.swift @@ -0,0 +1,16 @@ +// +// Weak.swift +// SwiftMessages +// +// Created by Timothy Moose on 6/4/17. +// Copyright © 2017 SwiftKick Mobile. All rights reserved. +// + +import Foundation + +public class Weak<T: AnyObject> { + public weak var value : T? + public init(value: T?) { + self.value = value + } +} diff --git a/SwiftMessages/WindowScene.swift b/SwiftMessages/WindowScene.swift new file mode 100644 index 00000000..a3bbb4ca --- /dev/null +++ b/SwiftMessages/WindowScene.swift @@ -0,0 +1,9 @@ +import Foundation +import UIKit + +/// A workaround for the change in Xcode 13 that prevents using `@availability` attribute +/// with `enum` cases containing associated values. +public protocol WindowScene {} + +@available(iOS 13.0, *) +extension UIWindowScene: WindowScene {} diff --git a/SwiftMessages/WindowViewController.swift b/SwiftMessages/WindowViewController.swift index 6440526c..30d77f9a 100644 --- a/SwiftMessages/WindowViewController.swift +++ b/SwiftMessages/WindowViewController.swift @@ -8,48 +8,80 @@ import UIKit -class WindowViewController: UIViewController +open class WindowViewController: UIViewController { - fileprivate var window: UIWindow? - - let windowLevel: UIWindowLevel - let config: SwiftMessages.Config - - override var shouldAutorotate: Bool { + override open var shouldAutorotate: Bool { return config.shouldAutorotate } - - init(windowLevel: UIWindowLevel = UIWindowLevelNormal, config: SwiftMessages.Config) - { - self.windowLevel = windowLevel + + convenience public init() { + self.init(config: SwiftMessages.Config()) + } + + public init(config: SwiftMessages.Config) { self.config = config - let window = PassthroughWindow(frame: UIScreen.main.bounds) + let view = PassthroughView() + let window = PassthroughWindow(hitTestView: view) self.window = window super.init(nibName: nil, bundle: nil) - self.view = PassthroughView() + self.view = view window.rootViewController = self - window.windowLevel = windowLevel + window.windowLevel = config.windowLevel ?? UIWindow.Level.normal + window.overrideUserInterfaceStyle = config.overrideUserInterfaceStyle } - + func install() { + window?.windowScene = config.windowScene + #if !SWIFTMESSAGES_APP_EXTENSIONS + previousKeyWindow = UIWindow.keyWindow + #endif + show( + becomeKey: config.shouldBecomeKeyWindow, + frame: config.windowScene?.coordinateSpace.bounds + ) + } + + private func show(becomeKey: Bool, frame: CGRect? = nil) { guard let window = window else { return } - window.makeKeyAndVisible() + window.frame = frame ?? UIScreen.main.bounds + if becomeKey { + window.makeKeyAndVisible() + } else { + window.isHidden = false + } } func uninstall() { + if window?.isKeyWindow == true { + previousKeyWindow?.makeKey() + } + window?.windowScene = nil window?.isHidden = true window = nil } - required init?(coder aDecoder: NSCoder) { + required public init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - override public var preferredStatusBarStyle: UIStatusBarStyle { - return config.preferredStatusBarStyle ?? UIApplication.shared.statusBarStyle + override open var preferredStatusBarStyle: UIStatusBarStyle { + return config.preferredStatusBarStyle ?? super.preferredStatusBarStyle } - - override var prefersStatusBarHidden: Bool { - return UIApplication.shared.isStatusBarHidden + + open override var prefersStatusBarHidden: Bool { + return config.prefersStatusBarHidden ?? super.prefersStatusBarHidden + } + + // MARK: - Variables + + private var window: UIWindow? + private weak var previousKeyWindow: UIWindow? + + let config: SwiftMessages.Config +} + +extension WindowViewController { + static func newInstance(config: SwiftMessages.Config) -> WindowViewController { + return config.windowViewController?(config) ?? WindowViewController(config: config) } } diff --git a/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj new file mode 100644 index 00000000..f1519c40 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.pbxproj @@ -0,0 +1,446 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + 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 */; }; + 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 */ + 22549DBF2B55CFE8005E3E21 /* DemoMessageWithButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoMessageWithButtonView.swift; sourceTree = "<group>"; }; + 228F7DA92ACF17E8006C9644 /* SwiftUIDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftUIDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 228F7DAC2ACF17E8006C9644 /* SwiftUIDemoApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIDemoApp.swift; sourceTree = "<group>"; }; + 228F7DAE2ACF17E8006C9644 /* DemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoView.swift; sourceTree = "<group>"; }; + 228F7DB02ACF17E9006C9644 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; + 228F7DB32ACF17E9006C9644 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; }; + 228F7DBB2ACF1DB5006C9644 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; + 228F7DBD2ACF1E1E006C9644 /* SwiftMessages.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SwiftMessages.xcodeproj; path = ../SwiftMessages.xcodeproj; sourceTree = "<group>"; }; + 228F7DD42ACF59E4006C9644 /* DemoMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoMessage.swift; sourceTree = "<group>"; }; + 228F7DD62ACF5C2E006C9644 /* DemoMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoMessageView.swift; sourceTree = "<group>"; }; + 2291AA492AD1E3EC0084868E /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; }; + 2291AA4C2AD1E4520084868E /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = CHANGELOG.md; path = ../CHANGELOG.md; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 228F7DA62ACF17E8006C9644 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 228F7DC82ACF1E63006C9644 /* SwiftMessages.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 228F7DA02ACF17E8006C9644 = { + isa = PBXGroup; + children = ( + 2291AA4C2AD1E4520084868E /* CHANGELOG.md */, + 2291AA492AD1E3EC0084868E /* README.md */, + 228F7DAB2ACF17E8006C9644 /* SwiftUIDemo */, + 228F7DAA2ACF17E8006C9644 /* Products */, + 228F7DC72ACF1E63006C9644 /* Frameworks */, + 228F7DBD2ACF1E1E006C9644 /* SwiftMessages.xcodeproj */, + ); + sourceTree = "<group>"; + }; + 228F7DAA2ACF17E8006C9644 /* Products */ = { + isa = PBXGroup; + children = ( + 228F7DA92ACF17E8006C9644 /* SwiftUIDemo.app */, + ); + name = Products; + sourceTree = "<group>"; + }; + 228F7DAB2ACF17E8006C9644 /* SwiftUIDemo */ = { + isa = PBXGroup; + children = ( + 228F7DBB2ACF1DB5006C9644 /* Info.plist */, + 228F7DAC2ACF17E8006C9644 /* SwiftUIDemoApp.swift */, + 228F7DAE2ACF17E8006C9644 /* DemoView.swift */, + 228F7DD42ACF59E4006C9644 /* DemoMessage.swift */, + 228F7DD62ACF5C2E006C9644 /* DemoMessageView.swift */, + 22549DBF2B55CFE8005E3E21 /* DemoMessageWithButtonView.swift */, + 228F7DB02ACF17E9006C9644 /* Assets.xcassets */, + 228F7DB22ACF17E9006C9644 /* Preview Content */, + ); + path = SwiftUIDemo; + sourceTree = "<group>"; + }; + 228F7DB22ACF17E9006C9644 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 228F7DB32ACF17E9006C9644 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = "<group>"; + }; + 228F7DBE2ACF1E1E006C9644 /* Products */ = { + isa = PBXGroup; + children = ( + 228F7DC32ACF1E1E006C9644 /* SwiftMessages.framework */, + 228F7DC52ACF1E1E006C9644 /* SwiftMessagesTests.xctest */, + ); + name = Products; + sourceTree = "<group>"; + }; + 228F7DC72ACF1E63006C9644 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 228F7DA82ACF17E8006C9644 /* SwiftUIDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 228F7DB72ACF17E9006C9644 /* Build configuration list for PBXNativeTarget "SwiftUIDemo" */; + buildPhases = ( + 228F7DA52ACF17E8006C9644 /* Sources */, + 228F7DA62ACF17E8006C9644 /* Frameworks */, + 228F7DA72ACF17E8006C9644 /* Resources */, + 228F7DCA2ACF1E63006C9644 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SwiftUIDemo; + productName = SwiftUIDemo; + productReference = 228F7DA92ACF17E8006C9644 /* SwiftUIDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 228F7DA12ACF17E8006C9644 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; + TargetAttributes = { + 228F7DA82ACF17E8006C9644 = { + CreatedOnToolsVersion = 15.0; + }; + }; + }; + buildConfigurationList = 228F7DA42ACF17E8006C9644 /* Build configuration list for PBXProject "SwiftUIDemo" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 228F7DA02ACF17E8006C9644; + productRefGroup = 228F7DAA2ACF17E8006C9644 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 228F7DBE2ACF1E1E006C9644 /* Products */; + ProjectRef = 228F7DBD2ACF1E1E006C9644 /* SwiftMessages.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 228F7DA82ACF17E8006C9644 /* SwiftUIDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 228F7DC32ACF1E1E006C9644 /* SwiftMessages.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = SwiftMessages.framework; + remoteRef = 228F7DC22ACF1E1E006C9644 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 228F7DC52ACF1E1E006C9644 /* SwiftMessagesTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = SwiftMessagesTests.xctest; + remoteRef = 228F7DC42ACF1E1E006C9644 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 228F7DA72ACF17E8006C9644 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 228F7DB42ACF17E9006C9644 /* Preview Assets.xcassets in Resources */, + 228F7DB12ACF17E9006C9644 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 228F7DA52ACF17E8006C9644 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 228F7DD52ACF59E4006C9644 /* DemoMessage.swift in Sources */, + 228F7DD72ACF5C2E006C9644 /* DemoMessageView.swift in Sources */, + 228F7DAF2ACF17E8006C9644 /* DemoView.swift in Sources */, + 228F7DAD2ACF17E8006C9644 /* SwiftUIDemoApp.swift in Sources */, + 22549DC02B55CFE8005E3E21 /* DemoMessageWithButtonView.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\""; + DEVELOPMENT_TEAM = ""; + 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.SwiftMessages.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\""; + DEVELOPMENT_TEAM = ""; + 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.SwiftMessages.SwiftUIDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 228F7DA42ACF17E8006C9644 /* Build configuration list for PBXProject "SwiftUIDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 228F7DB52ACF17E9006C9644 /* Debug */, + 228F7DB62ACF17E9006C9644 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 228F7DB72ACF17E9006C9644 /* Build configuration list for PBXNativeTarget "SwiftUIDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 228F7DB82ACF17E9006C9644 /* Debug */, + 228F7DB92ACF17E9006C9644 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 228F7DA12ACF17E8006C9644 /* Project object */; +} diff --git a/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "self:"> + </FileRef> +</Workspace> diff --git a/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEDidComputeMac32BitWarning</key> + <true/> +</dict> +</plist> diff --git a/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AccentColor.colorset/Contents.json b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..13613e3e --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Contents.json b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Demo message background.colorset/Contents.json b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Demo message background.colorset/Contents.json new file mode 100644 index 00000000..15b79d47 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Demo message background.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xEB", + "green" : "0xE1", + "red" : "0xAC" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/DemoMessage.swift b/SwiftUIDemo/SwiftUIDemo/DemoMessage.swift new file mode 100644 index 00000000..32624de1 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/DemoMessage.swift @@ -0,0 +1,23 @@ +// +// DemoMessage.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI +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, style: style) + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift b/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift new file mode 100644 index 00000000..11cf9611 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/DemoMessageView.swift @@ -0,0 +1,70 @@ +// +// DemoMessageView.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI + +// A message view with a title and message. +struct DemoMessageView: View { + + // MARK: - API + + enum Style { + case standard + case card + case tab + } + + let message: DemoMessage + let style: Style + + + // MARK: - Variables + + // MARK: - Constants + + // MARK: - Body + + var body: some View { + switch style { + case .standard: + content() + // Mask the content and extend background into the safe area. + .mask { + Rectangle() + .edgesIgnoringSafeArea(.top) + } + case .card: + content() + // Mask the content with a rounded rectangle + .mask { + RoundedRectangle(cornerRadius: 15) + } + // External padding around the card + .padding(10) + case .tab: + content() + // Mask the content with rounded bottom edge and extend background into the safe area. + .mask { + UnevenRoundedRectangle(bottomLeadingRadius: 15, bottomTrailingRadius: 15) + .edgesIgnoringSafeArea(.top) + } + } + } + + @ViewBuilder private func content() -> some View { + VStack(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) + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/DemoMessageWithButtonView.swift b/SwiftUIDemo/SwiftUIDemo/DemoMessageWithButtonView.swift new file mode 100644 index 00000000..e74172ef --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/DemoMessageWithButtonView.swift @@ -0,0 +1,77 @@ +// +// DemoMessageWithButtonView.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 1/15/24. +// + +import SwiftUI + +// A message view with a title, message and button. +struct DemoMessageWithButtonView<Button>: View where Button: View { + + // MARK: - API + + enum Style { + case standard + case card + case tab + } + + init(message: DemoMessage, style: Style, @ViewBuilder button: @escaping () -> Button) { + self.message = message + self.style = style + self.button = button + } + + // MARK: - Variables + + let message: DemoMessage + let style: Style + @ViewBuilder let button: () -> Button + + // MARK: - Constants + + // MARK: - Body + + var body: some View { + switch style { + case .standard: + content() + // Mask the content and extend background into the safe area. + .mask { + Rectangle() + .edgesIgnoringSafeArea(.top) + } + case .card: + content() + // Mask the content with a rounded rectangle + .mask { + RoundedRectangle(cornerRadius: 15) + } + // External padding around the card + .padding(10) + case .tab: + content() + // Mask the content with rounded bottom edge and extend background into the safe area. + .mask { + UnevenRoundedRectangle(bottomLeadingRadius: 15, bottomTrailingRadius: 15) + .edgesIgnoringSafeArea(.top) + } + } + } + + @ViewBuilder private func content() -> some View { + VStack() { + Text(message.title).font(.system(size: 20, weight: .bold)) + Text(message.body) + button() + } + .multilineTextAlignment(.center) + // Internal padding of the card + .padding(30) + // Greedy width + .frame(maxWidth: .infinity) + .background(.demoMessageBackground) + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/DemoView.swift b/SwiftUIDemo/SwiftUIDemo/DemoView.swift new file mode 100644 index 00000000..b6562cfe --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/DemoView.swift @@ -0,0 +1,65 @@ +// +// DemoView.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI +import SwiftMessages + +struct DemoView: View { + + /// Demonstrates purely data-driven message presentation. + @State var message: DemoMessage? + + /// Demonstrates message presentation with a view builder. + @State var messageWithButton: DemoMessage? + + var body: some View { + VStack { + Button("Show standard message") { + 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 + ) + } + Button("Show message with button") { + messageWithButton = DemoMessage( + title: "Demo", + body: "This message view has a button was constructed with a view builder.", + style: .card + ) + } + } + .buttonStyle(.bordered) + .swiftMessage(message: $message) + .swiftMessage(message: $messageWithButton) { message in + DemoMessageWithButtonView(message: message, style: .card) { + Button("Tap Me") { + print("Tap") + } + .buttonStyle(.bordered) + } + } + } +} + +#Preview { + DemoView() +} diff --git a/SwiftUIDemo/SwiftUIDemo/Info.plist b/SwiftUIDemo/SwiftUIDemo/Info.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/Info.plist @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict/> +</plist> diff --git a/SwiftUIDemo/SwiftUIDemo/Preview Content/Preview Assets.xcassets/Contents.json b/SwiftUIDemo/SwiftUIDemo/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwiftUIDemo/SwiftUIDemo/SwiftUIDemoApp.swift b/SwiftUIDemo/SwiftUIDemo/SwiftUIDemoApp.swift new file mode 100644 index 00000000..fc444543 --- /dev/null +++ b/SwiftUIDemo/SwiftUIDemo/SwiftUIDemoApp.swift @@ -0,0 +1,17 @@ +// +// SwiftUIDemoApp.swift +// SwiftUIDemo +// +// Created by Timothy Moose on 10/5/23. +// + +import SwiftUI + +@main +struct SwiftUIDemoApp: App { + var body: some Scene { + WindowGroup { + DemoView() + } + } +} diff --git a/ViewControllers.md b/ViewControllers.md new file mode 100644 index 00000000..85b63106 --- /dev/null +++ b/ViewControllers.md @@ -0,0 +1,147 @@ +# View Controllers + +[`SwiftMessagesSegue`](./SwiftMessages/SwiftMessagesSegue.swift) is a configurable subclass of `UIStoryboardSegue` that presents and dismisses modal view controllers by acting as the presenting view controller's `transitioningDelegate` and utilizing SwiftMessages' `show()` and `hide()` function on the destination view controller's view. + +## Usage + +### Interface Builder + +First, create a segue by control-dragging from the sender element to the destination view controller. Then select "swift messages" (or the name of a `SwiftMessagesSegue` subclass) in the segue type prompt. In the image below, we've created a segue using the `VeryNiceSegue` subclass by selecting "very nice" from the prompt. + +<p align="center"> + <img src="./Design/SwiftMessagesSegueCreate.png" /> +</p> + +### Programatic + +`SwiftMessagesSegue` can be used without an associated storyboard or segue by doing the following in the presenting view controller. + +````swift +let destinationVC = ... // make a reference to a destination view controller +let segue = SwiftMessagesSegue(identifier: nil, source: self, destination: destinationVC) +... // do any configuration here +segue.perform() +```` + +To dismiss, call the UIKit API on the presenting view controller: + +````swift +dismiss(animated: true, completion: nil) +```` + +It is not necessary to retain `segue` because it retains itself until dismissal. However, you can retain it if you plan to `perform()` more than once. + +#### Present the controller on top of all controllers + +If you don't know the presenter or you don't want to pass it as a source, like when you +have a completely separated message controller, you can pass a `WindowViewController` +as the `source` argument of the segue's initializer. + +By default, the window will be shown in the current window scene at `.normal` window level. +However, these parameters can be customized by initializing the view controller with a `SwiftMessages.Config` that has the `SwiftMessages.Config.presentationContext` set to either `.window` or `.windowScene`: + +```swift +let destinationVC = ... // make a reference to a destination view controller +var config = SwiftMessages.defaultConfig +config.presentationContext = .windowScene(...) // specify the window properties +let sourceVC = WindowViewController(config: config) +let segue = SwiftMessagesSegue(identifier: nil, source: self, destination: destinationVC) +segue.perform() +``` + +### Configuration + +`SwiftMessagesSegue` generally requires configuration to achieve specific layouts and optional behaviors. There are a few good ways to do this: + +1. __(Recommended)__ Subclass `SwiftMessagesSegue` and apply configurations in `init(identifier:source:destination:)`. Subclasses will automatically appear in the segue type dialog using an auto-generated name. For example, the name for "VeryNiceSegue" would be "very nice". + + + ```swift + class VeryNiceSegue: SwiftMessagesSegue { + override public init(identifier: String?, source: UIViewController, destination: UIViewController) { + super.init(identifier: identifier, source: source, destination: destination) + configure(layout: .bottomCard) + dimMode = .blur(style: .dark, alpha: 0.9, interactive: true) + messageView.configureNoDropShadow() + } + } + ``` + + +1. Apply configurations in `prepare(for:sender:)` of the presenting view controller after down-casting the segue to `SwiftMessagesSegue`. + + ````swift + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + if let segue = segue as? SwiftMessagesSegue { + segue.configure(layout: .bottomCard) + segue.dimMode = .blur(style: .dark, alpha: 0.9, interactive: true) + segue.messageView.configureNoDropShadow() + } + } + ```` + +The `configure(layout:)` method is a shortcut for configuring some basic layout and animation options that roughly mirror the options in `SwiftMessages.Layout`. + +````swift +// Configure a bottom card-style presentation +segue.configure(layout: .bottomCard) +```` + +Many more styles can be achieved by customizing the underlying options. Some of the `SwiftMessages.Config` options are useful for view controller presentation and are mirrored on `SwiftMessagesSegue`. + +````swift +// Turn off interactive dismiss +segue.interactiveHide = false + +// Enable dimmed background with tap-to-dismiss +segue.dimMode = .gray(interactive: true) + +// Specify the animation and positioning +segue.presentationStyle = .bottom +```` + +The `messageView` property provides access to an instance of [`BaseView`](./SwiftMessages/BaseView.swift), the superclass of [`MessageView`](./SwiftMessages/MessageView.swift), that serves as the view presented by SwiftMessages. The view controller's view is contained as a descendant of this view. There are some useful options available on `messageView`: + +````swift +// Increase the internal layout margins. With the `.background` containment option, +// the margin additions specify the outer margins around `messageView.backgroundView`. +segue.messageView.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) + +// Collapse layout margin edges that encroach on non-zero safe area insets. +messageView.collapseLayoutMarginAdditions = true + +// Add a default drop shadow. +segue.messageView.configureDropShadow() + +// Indicate that the view controller's view should be installed +// as the `backgroundView` of `messageView`. +segue.containment = .background +```` + +The view controller's view is a direct subview of `containerView`, an instance of [`ViewControllerContainerView`](./SwiftMessages/ViewControllerContainerView.swift), which provides corner rounding options. + +````swift +// Change the corner radius +segue.containerView.cornerRadius = 20 +```` + +### Sizing + +`SwiftMessagesSegue` provides default view controller sizing based on device, with width on iPad being limited to 500pt max. However, it is recommended that you explicitly specify size appropriate for your content using one of the following methods. + 1. Define sufficient width and height constraints in your view controller such that it sizes itself. + 1. Set the `preferredContentSize` property (a.k.a "Use Preferred Explicit Size" in Interface Builder's attribute inspector). Zeros are ignored, e.g. `CGSize(width: 0, height: 350)` only affects the height. + 1. Add explicit width and/or height constraints to `segue.messageView.backgroundView`. + +Note that `Layout.topMessage` and `Layout.bottomMessage` are always full screen width. For other layouts, the there is a maximum 500pt width on for regular horizontal size class (iPad) at 950 priority. This limit can be overridden by adding higher-priority constraints. + +### Keyboard Avoidance + +The `KeyboardTrackingView` class can be used to cause the message view to avoid the keyboard by sliding up when the keyboard gets too close. + +````swift +segue.keyboardTrackingView = KeyboardTrackingView() +```` + +You can incorporate `KeyboardTrackingView` into your app even when you're not using SwiftMessages. Install into your view hierarchy by pinning `KeyboardTrackingView` to the bottom, leading, and trailing edges of the screen. Then pin the bottom of your content that should avoid the keyboard to the top `KeyboardTrackingView`. Use an equality constraint to strictly track the keyboard or an inequality constraint to only move when the keyboard gets too close. `KeyboardTrackingView` works by observing keyboard notifications and adjusting its height to maintain its top edge above the keyboard, thereby pushing your content up. See the comments in `KeyboardTrackingView` for configuration options. + +See [`SwiftMessagesSegue`](./SwiftMessages/SwiftMessagesSegue.swift) for additional documentation and technical details. diff --git a/iMessageDemo/.Podfile b/iMessageDemo/.Podfile new file mode 100644 index 00000000..1cc162cb --- /dev/null +++ b/iMessageDemo/.Podfile @@ -0,0 +1,12 @@ +target 'iMessageDemo' do + use_frameworks! + workspace 'iMessageDemo.xcworkspace' + xcodeproj 'iMessageDemo.xcodeproj' +end + +target 'iMessageExtensionDemo' do + use_frameworks! + workspace 'iMessageDemo.xcworkspace' + xcodeproj 'iMessageDemo.xcodeproj' + pod 'SwiftMessages/AppExtension', :path => '../' +end diff --git a/iMessageDemo/Podfile b/iMessageDemo/Podfile new file mode 100644 index 00000000..7ae17852 --- /dev/null +++ b/iMessageDemo/Podfile @@ -0,0 +1,38 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +install! 'cocoapods', + :share_schemes_for_development_pods => false + +target 'iMessageDemo' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + # Pods for iMessageDemo + +end + +target 'iMessageExtensionDemo' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + # Pods for iMessageExtensionDemo + pod 'SwiftMessages/AppExtension', :path => "../" + +end + +post_install do |installer| + # Blow away schemes – the schemes created by CocoaPods break Carthage builds + # because they incluede a SwiftMessages framework that Carthage picks + # over the main SwiftMessages framework. The SwiftMessages framework that gets + # picked is configured for an app extension and doesn't work correctly in an app. + File.directory?(path) + [ + "#{installer.sandbox.root}/Pods.xcodeproj/xcuserdata", + "#{installer.sandbox.root}/Pods.xcodeproj/xcshareddata" + ].each { |path| + if File.directory?(path) + FileUtils.remove_dir(path) + end + } +end diff --git a/iMessageDemo/Podfile.lock b/iMessageDemo/Podfile.lock new file mode 100644 index 00000000..400dd99d --- /dev/null +++ b/iMessageDemo/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - SwiftMessages/AppExtension (10.0.1) + +DEPENDENCIES: + - SwiftMessages/AppExtension (from `../`) + +EXTERNAL SOURCES: + SwiftMessages: + :path: "../" + +SPEC CHECKSUMS: + SwiftMessages: 759b4a0bf5c3a116a0d7e8a34b098ba83c458625 + +PODFILE CHECKSUM: 2eb9a33592d0c52131c37a9dd169a8c4604ffd7b + +COCOAPODS: 1.15.2 diff --git a/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json b/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json new file mode 100644 index 00000000..a117b2dd --- /dev/null +++ b/iMessageDemo/Pods/Local Podspecs/SwiftMessages.podspec.json @@ -0,0 +1,49 @@ +{ + "name": "SwiftMessages", + "version": "10.0.1", + "license": { + "type": "MIT" + }, + "homepage": "https://github.com/SwiftKickMobile/SwiftMessages", + "authors": { + "Timothy Moose": "tim@swiftkickmobile.com" + }, + "summary": "A very flexible message bar for iOS written in Swift.", + "source": { + "git": "https://github.com/SwiftKickMobile/SwiftMessages.git", + "tag": "10.0.1" + }, + "platforms": { + "ios": "13.0" + }, + "swift_versions": "5.0", + "frameworks": "UIKit", + "requires_arc": true, + "default_subspecs": "App", + "subspecs": [ + { + "name": "App", + "source_files": "SwiftMessages/**/*.swift", + "resource_bundles": { + "SwiftMessages": [ + "SwiftMessages/Resources/*.*" + ] + } + }, + { + "name": "AppExtension", + "source_files": "SwiftMessages/**/*.swift", + "exclude_files": "SwiftMessages/**/SegueConvenienceClasses.swift", + "resource_bundles": { + "SwiftMessages_SwiftMessages": [ + "SwiftMessages/Resources/**/*.*" + ] + }, + "pod_target_xcconfig": { + "SWIFT_ACTIVE_COMPILATION_CONDITIONS": "SWIFTMESSAGES_APP_EXTENSIONS", + "GCC_PREPROCESSOR_DEFINITIONS": "SWIFTMESSAGES_APP_EXTENSIONS=1" + } + } + ], + "swift_version": "5.0" +} diff --git a/iMessageDemo/Pods/Manifest.lock b/iMessageDemo/Pods/Manifest.lock new file mode 100644 index 00000000..400dd99d --- /dev/null +++ b/iMessageDemo/Pods/Manifest.lock @@ -0,0 +1,16 @@ +PODS: + - SwiftMessages/AppExtension (10.0.1) + +DEPENDENCIES: + - SwiftMessages/AppExtension (from `../`) + +EXTERNAL SOURCES: + SwiftMessages: + :path: "../" + +SPEC CHECKSUMS: + SwiftMessages: 759b4a0bf5c3a116a0d7e8a34b098ba83c458625 + +PODFILE CHECKSUM: 2eb9a33592d0c52131c37a9dd169a8c4604ffd7b + +COCOAPODS: 1.15.2 diff --git a/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj b/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 00000000..cf4122eb --- /dev/null +++ b/iMessageDemo/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,1228 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 00A4A53E0D1EFC70DA1EFAEFA82C4BA1 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442F9FAEDF369CADB9E6E8FF3668FD95 /* Weak.swift */; }; + 03C7FA1BE62CCD280D63F4C7CDDFB27F /* AccessibleMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9E8A4D41E0A0E52C839F7197C4CE2A0 /* AccessibleMessage.swift */; }; + 04BCE3C12FDE7E91C9EF1FE154E80E2B /* SwiftMessageModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = B19DACBEC8DD85FB850D299DFB7A0374 /* SwiftMessageModifier.swift */; }; + 04C771EB4784B94AC6CA28ED6A919D50 /* WindowScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AB9866F195EB0AED31A33AEC27B67C1 /* WindowScene.swift */; }; + 096A6663757CB52C8A34B3E3146279C8 /* infoIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2CF5DC74916EBE02E70234620CD80150 /* infoIcon@2x.png */; }; + 0ADA608E3B9307694DCF4D0BC426E7FE /* warningIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B241F1B5D295E7806363B802DF03A085 /* warningIcon@2x.png */; }; + 0C093AF5F4D753325F4CE92F2F943CB4 /* MarginAdjustable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14DF8F43552C4F1C4CAEFBAFD9A77004 /* MarginAdjustable.swift */; }; + 0D53997CCCD141D2303E87C29CEFE211 /* MessageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A4D741EF8B40F5472CE2C1C1A34426BD /* MessageView.xib */; }; + 1441D5A06DD6903562EB794FC1AE8822 /* TabView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C33B3DA756F19F5C93D498D557BEB820 /* TabView.xib */; }; + 158EF18377B720081C31C2F2100DDA7A /* Presenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D18688EA04EA2F2BC48ED05D1FE5404 /* Presenter.swift */; }; + 19C0F7897044E72D3A13DE703920FFE1 /* MessageHostingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F989D33CAC3BCDA9B3C4B18F23A4DBE /* MessageHostingView.swift */; }; + 1E507663F3C402CBCA0C50A876F472EF /* errorIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D6A205E933052E98349DC710D78304CB /* errorIconLight@3x.png */; }; + 205A52121D20436063240893A461B29C /* errorIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 38D28C78FCAE6706F1294CEFA6B25F88 /* errorIconSubtle@2x.png */; }; + 24DA4886290040A0EC88B63D82EF412D /* warningIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5E02B1554754BA1F8EF318D567875139 /* warningIconSubtle@3x.png */; }; + 274D5DE28E0446655163A48E2272860A /* CornerRoundingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86872F4639B26435D20BED0CE7E35C7F /* CornerRoundingView.swift */; }; + 28D6446B971F186BACDED83CD8DE4D44 /* SwiftMessages-SwiftMessages_SwiftMessages in Resources */ = {isa = PBXBuildFile; fileRef = BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages-SwiftMessages_SwiftMessages */; }; + 31660027252C457325491844F16AEBDD /* successIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 74793ADC8ADF7674EA6C3041E2B54354 /* successIcon.png */; }; + 330C59E62D17601422EDB29513B9856C /* SwiftMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC10D7DB2D227D4AA8F41CDFDDC24F37 /* SwiftMessages.swift */; }; + 3451B2775584DD75A3BDF9BF28A03F76 /* SwiftMessagesSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = B17EF282E0A0F329DDF17226E83706F8 /* SwiftMessagesSegue.swift */; }; + 3479628DE3B6C9005316A7F591F5E68F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; + 360BEE76BBF40319E6638B3E027E1474 /* errorIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = EDFC2E756AAB98672C4B241097AAF0F6 /* errorIconSubtle.png */; }; + 3613DBA9CBD7E092BD7DC1924E6648D2 /* infoIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = ACCCF5B75EA41D844ED936A92602C5B1 /* infoIconLight@2x.png */; }; + 37A8DD40AF13BCABE7A3CD8EF15A4C53 /* successIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D146564C0660B5F616D6736F6560E17C /* successIconSubtle@2x.png */; }; + 3C566158256E9CC711B73810B2C64E3B /* KeyboardTrackingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A99EE79DBFA3C24A372DDB69162E36C /* KeyboardTrackingView.swift */; }; + 3F53FCE80C716C7DE7A3B1D8D65077BC /* CALayer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35F5FB13175EC0E13D53B445CE31395A /* CALayer+Extensions.swift */; }; + 422B422F962FD298F963F84934A21529 /* infoIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = C3701E97FDB85EFCE90E06D8CBC8ED41 /* infoIconLight.png */; }; + 436D8C63FBE86FF8271ABC32F9A52A9D /* Pods-iMessageDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 14BF989232A1D55A0FDAAB70B5A8E1BF /* Pods-iMessageDemo-dummy.m */; }; + 450919BA3A4D984DC24822CD80483419 /* TopBottomPresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A102DE8896931D80E06F2C74C2B003AC /* TopBottomPresentable.swift */; }; + 45A4B95F1F73413A3001B95E1F91D697 /* UIWindow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBC808D0C98F682E01DC43B544ED093F /* UIWindow+Extensions.swift */; }; + 4609D5EC365EABFE507781BF911B887B /* warningIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 004EE347886E2355CCB352F2AE7A35D6 /* warningIconLight.png */; }; + 469995B0FC2E3748F59D0E3A4445E197 /* CenteredView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 975A42F4C16B65B38769916EC5468D2A /* CenteredView.xib */; }; + 47CC2A912B82A499DB2F5E2ADBE664CF /* HapticMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA8BFA921A44ED7AEAA0E08BCE17EDDA /* HapticMessage.swift */; }; + 47EFB870CC797D2F54396F0AEBC8F576 /* errorIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = EC387534FD34764D4CC28B276A500AD6 /* errorIconLight.png */; }; + 48ADA8D4633776558E7D216434057A2A /* SwiftMessages.Config+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D83D1CC131CDAC7CA2C5BFD8701E8A79 /* SwiftMessages.Config+Extensions.swift */; }; + 4980F404C2B391C621CE2BCF05E08BDF /* errorIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6C12E87D0EA045A56FC0B45F072C74D2 /* errorIconSubtle@3x.png */; }; + 4C9FED5D268E82325C17309FB8904C43 /* warningIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B8B9892D8D5596E09F02DA2D71BF60B4 /* warningIcon@3x.png */; }; + 52A01853AC4F2D0E720579D7F8A531CF /* WindowViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9908774A62A95BF5BA8FE65842868043 /* WindowViewController.swift */; }; + 60F02D519964FFEE8A21221FF5E0B0C5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; + 61F532D30833A9FF1DE00EC98BC018C2 /* successIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5686DFC1E0B24A3051EF376AD8A162C0 /* successIconLight@3x.png */; }; + 634267873AC0F98140DBAFFF9A180BA8 /* MarginAdjustable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B602E4E64DAEF1468DD2F5C2C5DFD00 /* MarginAdjustable+Extensions.swift */; }; + 6583C565BE5BB9E52213854AA85F5A93 /* warningIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 6924A0A48B715EA35080ABB106B96BF7 /* warningIconSubtle.png */; }; + 67DC4D170143131B8AFFB558FDD00465 /* SwiftMessages-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D091A06E439F734980F26F81E9161EF2 /* SwiftMessages-dummy.m */; }; + 67F7D444EAC4475021B3458B21B2A162 /* Identifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88398B7A70E5B00495B670516D964701 /* Identifiable.swift */; }; + 698F203577674AFA4BBCDE93B01B9EEC /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57EB79F63EA99ADBBDA408015A4599BB /* UIViewController+Extensions.swift */; }; + 6A04C3E1C3437ED6BC6F096302B458AB /* errorIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8605740B16E17342A29212D21C380249 /* errorIcon@2x.png */; }; + 6CDE06668BB53C70BF1456F8EEE845D9 /* infoIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C40BBCF3A77C5C7A01708634BB4275C3 /* infoIconSubtle@3x.png */; }; + 6DC0B420F622E197919276CFF2C063CE /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 790409B3FBA491A9262ACCB929F30104 /* BaseView.swift */; }; + 72026C4424B7A1650CBEED98ED9AA288 /* successIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = 7B9CEE1B17C98E76723E7404C532515D /* successIconSubtle.png */; }; + 744EA4AF597AFEFEE5B398434F47CA26 /* warningIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 71699C81494BC6585B862CDFC1CDAF54 /* warningIconLight@2x.png */; }; + 7590FF543E2634A83059E509D5B05583 /* Pods-iMessageExtensionDemo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CAB201AD00CAB811B045E2FFB5C03A8 /* Pods-iMessageExtensionDemo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 79BB175F4750822409AB9ED0A9D90D09 /* successIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6EA088414C10E47808EA8490D9BBF64F /* successIcon@3x.png */; }; + 81B1015F29547CAB449757FC5ABCAFAB /* warningIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5FE01208AD70F1B35201AB04E50A23EC /* warningIconLight@3x.png */; }; + 88D024879AEAE247899BFB50C8516515 /* Pods-iMessageDemo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D0ECE831FB5E0EE1D68E837671320C7 /* Pods-iMessageDemo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8CB7CCDF07E1CE6838C7278BC19968B6 /* infoIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 79A086337846180B9A63D8492CCE45B4 /* infoIcon.png */; }; + 8F63F1ABAB21FA99A6CB1A54D5F2B5AA /* infoIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 560722B244EB84DF745199247129C164 /* infoIcon@3x.png */; }; + 942468E4C1AEFCF10D5043243B4007E7 /* NSBundle+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 073CD58B2E8E255484D239A01D707B81 /* NSBundle+Extensions.swift */; }; + 9FBBA6E4D3A2A4CA4BA8535E35D54CA8 /* successIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 44DAC25C8D6D72F70BD1CF9099BDAF10 /* successIconLight@2x.png */; }; + A4724FC3B4F49DCBF50D395257BB6B8E /* CardView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03B5D12D54ACC75F929389CFF15E91FF /* CardView.xib */; }; + A52191D65F4C725EBF61D27F40FEA970 /* infoIconLight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 88237113DAAD8ECF8D5E3FAA27D8A02F /* infoIconLight@3x.png */; }; + A836F848C83565B2A0A06AB23D491946 /* MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9BBC4BF82FBB152E34F2D1EF36A0FB1 /* MessageView.swift */; }; + A865FCE8718103C8E725EC1EC0F9F4F6 /* BackgroundViewable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86C1C9601BF8A5BC563062C310C0E3B5 /* BackgroundViewable.swift */; }; + A8C4AD87F73E9C51F797F34BCFF5AA17 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; + A8EF6BE26B31A8713E37E0629F6466EB /* successIconLight.png in Resources */ = {isa = PBXBuildFile; fileRef = 252A5DF0FE3237691B8C50B969857389 /* successIconLight.png */; }; + A90C06B459CC64A243DD1184024E5D22 /* infoIconSubtle.png in Resources */ = {isa = PBXBuildFile; fileRef = A6C7FF0D9E13571262231B72D0553E49 /* infoIconSubtle.png */; }; + B04AA81A8A8CE0BCEFD5FAFD841F461F /* Task+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9610DCAAD9A55CDF73BAD54D523E1273 /* Task+Extensions.swift */; }; + B1B4D240B65FFC5A7A981B9504C55270 /* NSLayoutConstraint+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 882EF814D0A1EE2AB28BFEE5C067EE6F /* NSLayoutConstraint+Extensions.swift */; }; + B22AF07D79D1A82DE583AC49E3D472D3 /* Pods-iMessageExtensionDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F40CA14AD738DD186B4DA8FD14AE5BD /* Pods-iMessageExtensionDemo-dummy.m */; }; + B61EBE61C31E78140BF12D32A008A43B /* StatusLine.xib in Resources */ = {isa = PBXBuildFile; fileRef = 62332870F1E2AE3FA16EE5ADC85C104A /* StatusLine.xib */; }; + B646E1CD53F14E0DEE53740799C06AC5 /* SwiftMessages-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 080E269BABA7D072D8C51E29E9AC4A91 /* SwiftMessages-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B6D0E2FA454A946D6C9A7494648F49D9 /* MessageGeometryProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28456F0421422D16D71D14D426309B3F /* MessageGeometryProxy.swift */; }; + B9FDFA90A4FB68CA5357AB70427B4DCD /* TopBottomAnimationStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C61DD3C66AC7ADE1E9CCFE7A4A0BEA59 /* TopBottomAnimationStyle.swift */; }; + BA4779B82B35B85EFE9F595624BA3943 /* UIEdgeInsets+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16B5B2B5429B01345E4DA361DE01904D /* UIEdgeInsets+Extensions.swift */; }; + BAB66573FF29F6337237A8DA0EB9E3E8 /* PassthroughWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0398CE267904AF6C2FD03B3766511ECF /* PassthroughWindow.swift */; }; + BBF31491EF3411DCFA7E649645229E2A /* successIconSubtle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 47A710678B44C50DA470D1BCF94B87B8 /* successIconSubtle@3x.png */; }; + C2031E7EC3C60B876F2AC04253D3AFC4 /* MessageViewConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06DB4311BFB347093FC18777A503B461 /* MessageViewConvertible.swift */; }; + CCBFBDB03B2444C911BADDE6A6BA08AD /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9414B7316138752779A4B9C7E5C988DB /* Error.swift */; }; + D3B31A631C754CAECABFA4DC672D3D0B /* warningIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 85C6BEF274CDB3807F9BD452A26C68E6 /* warningIconSubtle@2x.png */; }; + D8DFC45149C57377B5C90B3457090564 /* warningIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = D47C1471CCFFBEF214DF9F0ECBDD408B /* warningIcon.png */; }; + D9519DD580DF2E744AB4C4087FA28BCD /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F67BD26788FA0C70E942A7629E41C5E8 /* Animator.swift */; }; + DC6C4E22FA8DD6FA491066A738132EF1 /* infoIconSubtle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8026A87EEBF1A86A282563F974C4225C /* infoIconSubtle@2x.png */; }; + DD406A0C002AC1D02A6E5794B1729C22 /* PassthroughView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A865E97261799942A6F29092D3D7AE /* PassthroughView.swift */; }; + DE2531A67AEBFED61A060DF13790C3BE /* errorIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 91013DDC05BDB2787740B0C9E5444D23 /* errorIcon@3x.png */; }; + E03C930AD56F078DCD1357E5C83AD67A /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = B32459A84426DD5E88256AD61F3D4E91 /* Theme.swift */; }; + E4906D67B9F27E11EE9F8E8F5C847A14 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */; }; + E54040398A9AD751393A2171DC64D70E /* errorIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 71D489FBDD84B41576199298F717BC08 /* errorIcon.png */; }; + EE9A5A3877D99BFCA5DA70BA4E049CA9 /* successIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DBF06E9B2F93F081139B8A6A922F569 /* successIcon@2x.png */; }; + F2D3ABB0C7B6EB5B531E4E68C40AA89C /* PhysicsPanHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AEEED9FBEA6C5DB7EE3B95E7D8115B3 /* PhysicsPanHandler.swift */; }; + F516490B5276943A352D597431B079B6 /* TopBottomAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1F1B1264A726D334A72AB1CB001CA9F /* TopBottomAnimation.swift */; }; + F667CC7C7F3285FC39427F2AAA8E7665 /* PhysicsAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D7E08E0434930866B59A3F17A3A577B /* PhysicsAnimation.swift */; }; + F8D0D33FC1C833490057108C322E56CB /* MaskingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC4854845AC1848C056C36719A5D7420 /* MaskingView.swift */; }; + FC0E2BA3CD9C6C3ACF3681841D8EF5BA /* errorIconLight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C49B964EF7710D818E0AF0321724EEF4 /* errorIconLight@2x.png */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 146D3A65FCE17293CC3AD6CBEAE15F9A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1FC5E8328653C350899229BDF89FACE5; + remoteInfo = "SwiftMessages-SwiftMessages_SwiftMessages"; + }; + 70E6358901408AED062E820735630F69 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAB613A18652334F6BFC5F27BADF515D; + remoteInfo = SwiftMessages; + }; + D297C84AE0F13FB6A76F2F391D21D679 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAB613A18652334F6BFC5F27BADF515D; + remoteInfo = SwiftMessages; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 004EE347886E2355CCB352F2AE7A35D6 /* warningIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconLight.png; path = SwiftMessages/Resources/warningIconLight.png; sourceTree = "<group>"; }; + 0398CE267904AF6C2FD03B3766511ECF /* PassthroughWindow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughWindow.swift; path = SwiftMessages/PassthroughWindow.swift; sourceTree = "<group>"; }; + 03A865E97261799942A6F29092D3D7AE /* PassthroughView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PassthroughView.swift; path = SwiftMessages/PassthroughView.swift; sourceTree = "<group>"; }; + 03B5D12D54ACC75F929389CFF15E91FF /* CardView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CardView.xib; path = SwiftMessages/Resources/CardView.xib; sourceTree = "<group>"; }; + 06DB4311BFB347093FC18777A503B461 /* MessageViewConvertible.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageViewConvertible.swift; path = SwiftMessages/MessageViewConvertible.swift; sourceTree = "<group>"; }; + 073CD58B2E8E255484D239A01D707B81 /* NSBundle+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSBundle+Extensions.swift"; path = "SwiftMessages/NSBundle+Extensions.swift"; sourceTree = "<group>"; }; + 080E269BABA7D072D8C51E29E9AC4A91 /* SwiftMessages-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-umbrella.h"; sourceTree = "<group>"; }; + 093D5BBE2A96A1A7AC0432A3AB933576 /* Pods-iMessageDemo-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageDemo-Info.plist"; sourceTree = "<group>"; }; + 0FD758C8718F3EEFB5E97E34A29CE1CC /* SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SwiftMessages-Info.plist"; sourceTree = "<group>"; }; + 1341BB7116EC50FDF7062C6A91DEDF49 /* Pods-iMessageExtensionDemo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageExtensionDemo-acknowledgements.plist"; sourceTree = "<group>"; }; + 14BF989232A1D55A0FDAAB70B5A8E1BF /* Pods-iMessageDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-iMessageDemo-dummy.m"; sourceTree = "<group>"; }; + 14DF8F43552C4F1C4CAEFBAFD9A77004 /* MarginAdjustable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MarginAdjustable.swift; path = SwiftMessages/MarginAdjustable.swift; sourceTree = "<group>"; }; + 16B5B2B5429B01345E4DA361DE01904D /* UIEdgeInsets+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIEdgeInsets+Extensions.swift"; path = "SwiftMessages/UIEdgeInsets+Extensions.swift"; sourceTree = "<group>"; }; + 252A5DF0FE3237691B8C50B969857389 /* successIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconLight.png; path = SwiftMessages/Resources/successIconLight.png; sourceTree = "<group>"; }; + 28456F0421422D16D71D14D426309B3F /* MessageGeometryProxy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageGeometryProxy.swift; path = SwiftMessages/MessageGeometryProxy.swift; sourceTree = "<group>"; }; + 2AB9866F195EB0AED31A33AEC27B67C1 /* WindowScene.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WindowScene.swift; path = SwiftMessages/WindowScene.swift; sourceTree = "<group>"; }; + 2CF5DC74916EBE02E70234620CD80150 /* infoIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@2x.png"; path = "SwiftMessages/Resources/infoIcon@2x.png"; sourceTree = "<group>"; }; + 2D0ECE831FB5E0EE1D68E837671320C7 /* Pods-iMessageDemo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-iMessageDemo-umbrella.h"; sourceTree = "<group>"; }; + 35F5FB13175EC0E13D53B445CE31395A /* CALayer+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CALayer+Extensions.swift"; path = "SwiftMessages/CALayer+Extensions.swift"; sourceTree = "<group>"; }; + 38D28C78FCAE6706F1294CEFA6B25F88 /* errorIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@2x.png"; path = "SwiftMessages/Resources/errorIconSubtle@2x.png"; sourceTree = "<group>"; }; + 442F9FAEDF369CADB9E6E8FF3668FD95 /* Weak.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Weak.swift; path = SwiftMessages/Weak.swift; sourceTree = "<group>"; }; + 44DAC25C8D6D72F70BD1CF9099BDAF10 /* successIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@2x.png"; path = "SwiftMessages/Resources/successIconLight@2x.png"; sourceTree = "<group>"; }; + 47A710678B44C50DA470D1BCF94B87B8 /* successIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@3x.png"; path = "SwiftMessages/Resources/successIconSubtle@3x.png"; sourceTree = "<group>"; }; + 4824F23D80FF9070A5F8A452DB11EB9A /* SwiftMessages */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SwiftMessages; path = SwiftMessages.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4DBF06E9B2F93F081139B8A6A922F569 /* successIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@2x.png"; path = "SwiftMessages/Resources/successIcon@2x.png"; sourceTree = "<group>"; }; + 560722B244EB84DF745199247129C164 /* infoIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIcon@3x.png"; path = "SwiftMessages/Resources/infoIcon@3x.png"; sourceTree = "<group>"; }; + 5686DFC1E0B24A3051EF376AD8A162C0 /* successIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconLight@3x.png"; path = "SwiftMessages/Resources/successIconLight@3x.png"; sourceTree = "<group>"; }; + 573965F15F83BD70EEAC9E1E8B0F85C6 /* SwiftMessages.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = SwiftMessages.podspec; sourceTree = "<group>"; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 57EB79F63EA99ADBBDA408015A4599BB /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIViewController+Extensions.swift"; path = "SwiftMessages/UIViewController+Extensions.swift"; sourceTree = "<group>"; }; + 5CAB201AD00CAB811B045E2FFB5C03A8 /* Pods-iMessageExtensionDemo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-iMessageExtensionDemo-umbrella.h"; sourceTree = "<group>"; }; + 5E02B1554754BA1F8EF318D567875139 /* warningIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@3x.png"; path = "SwiftMessages/Resources/warningIconSubtle@3x.png"; sourceTree = "<group>"; }; + 5F989D33CAC3BCDA9B3C4B18F23A4DBE /* MessageHostingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageHostingView.swift; path = SwiftMessages/MessageHostingView.swift; sourceTree = "<group>"; }; + 5FE01208AD70F1B35201AB04E50A23EC /* warningIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@3x.png"; path = "SwiftMessages/Resources/warningIconLight@3x.png"; sourceTree = "<group>"; }; + 6228A8E37F7905D75917DD4CBE65B03C /* SwiftMessages.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SwiftMessages.modulemap; sourceTree = "<group>"; }; + 62332870F1E2AE3FA16EE5ADC85C104A /* StatusLine.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = StatusLine.xib; path = SwiftMessages/Resources/StatusLine.xib; sourceTree = "<group>"; }; + 6489B2A759075E9DC1D1406734F45B5F /* Pods-iMessageExtensionDemo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iMessageExtensionDemo.modulemap"; sourceTree = "<group>"; }; + 6924A0A48B715EA35080ABB106B96BF7 /* warningIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIconSubtle.png; path = SwiftMessages/Resources/warningIconSubtle.png; sourceTree = "<group>"; }; + 6C12E87D0EA045A56FC0B45F072C74D2 /* errorIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconSubtle@3x.png"; path = "SwiftMessages/Resources/errorIconSubtle@3x.png"; sourceTree = "<group>"; }; + 6EA088414C10E47808EA8490D9BBF64F /* successIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIcon@3x.png"; path = "SwiftMessages/Resources/successIcon@3x.png"; sourceTree = "<group>"; }; + 71699C81494BC6585B862CDFC1CDAF54 /* warningIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconLight@2x.png"; path = "SwiftMessages/Resources/warningIconLight@2x.png"; sourceTree = "<group>"; }; + 71D489FBDD84B41576199298F717BC08 /* errorIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIcon.png; path = SwiftMessages/Resources/errorIcon.png; sourceTree = "<group>"; }; + 74793ADC8ADF7674EA6C3041E2B54354 /* successIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIcon.png; path = SwiftMessages/Resources/successIcon.png; sourceTree = "<group>"; }; + 790409B3FBA491A9262ACCB929F30104 /* BaseView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BaseView.swift; path = SwiftMessages/BaseView.swift; sourceTree = "<group>"; }; + 79A086337846180B9A63D8492CCE45B4 /* infoIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIcon.png; path = SwiftMessages/Resources/infoIcon.png; sourceTree = "<group>"; }; + 7B9CEE1B17C98E76723E7404C532515D /* successIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = successIconSubtle.png; path = SwiftMessages/Resources/successIconSubtle.png; sourceTree = "<group>"; }; + 7CC6A596A9C1659D8E93222DA4144414 /* Pods-iMessageExtensionDemo-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageExtensionDemo-Info.plist"; sourceTree = "<group>"; }; + 7F40CA14AD738DD186B4DA8FD14AE5BD /* Pods-iMessageExtensionDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-iMessageExtensionDemo-dummy.m"; sourceTree = "<group>"; }; + 8026A87EEBF1A86A282563F974C4225C /* infoIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@2x.png"; path = "SwiftMessages/Resources/infoIconSubtle@2x.png"; sourceTree = "<group>"; }; + 820B743874F7AC9F9E3970D68E2E60FA /* Pods-iMessageDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageDemo.release.xcconfig"; sourceTree = "<group>"; }; + 85C6BEF274CDB3807F9BD452A26C68E6 /* warningIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIconSubtle@2x.png"; path = "SwiftMessages/Resources/warningIconSubtle@2x.png"; sourceTree = "<group>"; }; + 8605740B16E17342A29212D21C380249 /* errorIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@2x.png"; path = "SwiftMessages/Resources/errorIcon@2x.png"; sourceTree = "<group>"; }; + 86872F4639B26435D20BED0CE7E35C7F /* CornerRoundingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CornerRoundingView.swift; path = SwiftMessages/CornerRoundingView.swift; sourceTree = "<group>"; }; + 86C1C9601BF8A5BC563062C310C0E3B5 /* BackgroundViewable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BackgroundViewable.swift; path = SwiftMessages/BackgroundViewable.swift; sourceTree = "<group>"; }; + 88237113DAAD8ECF8D5E3FAA27D8A02F /* infoIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@3x.png"; path = "SwiftMessages/Resources/infoIconLight@3x.png"; sourceTree = "<group>"; }; + 882EF814D0A1EE2AB28BFEE5C067EE6F /* NSLayoutConstraint+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSLayoutConstraint+Extensions.swift"; path = "SwiftMessages/NSLayoutConstraint+Extensions.swift"; sourceTree = "<group>"; }; + 88398B7A70E5B00495B670516D964701 /* Identifiable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Identifiable.swift; path = SwiftMessages/Identifiable.swift; sourceTree = "<group>"; }; + 8940290DCDAD08810FE0CD944F376444 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; sourceTree = "<group>"; }; + 8AEEED9FBEA6C5DB7EE3B95E7D8115B3 /* PhysicsPanHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsPanHandler.swift; path = SwiftMessages/PhysicsPanHandler.swift; sourceTree = "<group>"; }; + 8D18688EA04EA2F2BC48ED05D1FE5404 /* Presenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Presenter.swift; path = SwiftMessages/Presenter.swift; sourceTree = "<group>"; }; + 8D54691037F1CA4653B76F0558E2AA82 /* Pods-iMessageExtensionDemo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-iMessageExtensionDemo-acknowledgements.markdown"; sourceTree = "<group>"; }; + 8D7E08E0434930866B59A3F17A3A577B /* PhysicsAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhysicsAnimation.swift; path = SwiftMessages/PhysicsAnimation.swift; sourceTree = "<group>"; }; + 91013DDC05BDB2787740B0C9E5444D23 /* errorIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIcon@3x.png"; path = "SwiftMessages/Resources/errorIcon@3x.png"; sourceTree = "<group>"; }; + 915DE2E4E300BAD440BE13F72E49D731 /* Pods-iMessageDemo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iMessageDemo-acknowledgements.plist"; sourceTree = "<group>"; }; + 9414B7316138752779A4B9C7E5C988DB /* Error.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Error.swift; path = SwiftMessages/Error.swift; sourceTree = "<group>"; }; + 9610DCAAD9A55CDF73BAD54D523E1273 /* Task+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Task+Extensions.swift"; path = "SwiftMessages/Task+Extensions.swift"; sourceTree = "<group>"; }; + 975A42F4C16B65B38769916EC5468D2A /* CenteredView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = CenteredView.xib; path = SwiftMessages/Resources/CenteredView.xib; sourceTree = "<group>"; }; + 9908774A62A95BF5BA8FE65842868043 /* WindowViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WindowViewController.swift; path = SwiftMessages/WindowViewController.swift; sourceTree = "<group>"; }; + 9A99EE79DBFA3C24A372DDB69162E36C /* KeyboardTrackingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KeyboardTrackingView.swift; path = SwiftMessages/KeyboardTrackingView.swift; sourceTree = "<group>"; }; + 9B602E4E64DAEF1468DD2F5C2C5DFD00 /* MarginAdjustable+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "MarginAdjustable+Extensions.swift"; path = "SwiftMessages/MarginAdjustable+Extensions.swift"; sourceTree = "<group>"; }; + 9D5A75A919AE6C6D38A627636D7ADC11 /* LICENSE.md */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE.md; sourceTree = "<group>"; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + A102DE8896931D80E06F2C74C2B003AC /* TopBottomPresentable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TopBottomPresentable.swift; path = SwiftMessages/TopBottomPresentable.swift; sourceTree = "<group>"; }; + A1F1B1264A726D334A72AB1CB001CA9F /* TopBottomAnimation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TopBottomAnimation.swift; path = SwiftMessages/TopBottomAnimation.swift; sourceTree = "<group>"; }; + A399825CF45C4427BF9B80A590BF2BD5 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = "<group>"; }; + A4D741EF8B40F5472CE2C1C1A34426BD /* MessageView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = MessageView.xib; path = SwiftMessages/Resources/MessageView.xib; sourceTree = "<group>"; }; + A6C7FF0D9E13571262231B72D0553E49 /* infoIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconSubtle.png; path = SwiftMessages/Resources/infoIconSubtle.png; sourceTree = "<group>"; }; + ACCCF5B75EA41D844ED936A92602C5B1 /* infoIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconLight@2x.png"; path = "SwiftMessages/Resources/infoIconLight@2x.png"; sourceTree = "<group>"; }; + AE7AEA9CE6B44DCC96AE4E68FA644DAA /* Pods-iMessageExtensionDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageExtensionDemo.release.xcconfig"; sourceTree = "<group>"; }; + AFC41396FB1BD59C9A69EE1DD82E47C2 /* Pods-iMessageDemo */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-iMessageDemo"; path = Pods_iMessageDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B17EF282E0A0F329DDF17226E83706F8 /* SwiftMessagesSegue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessagesSegue.swift; path = SwiftMessages/SwiftMessagesSegue.swift; sourceTree = "<group>"; }; + B19DACBEC8DD85FB850D299DFB7A0374 /* SwiftMessageModifier.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessageModifier.swift; path = SwiftMessages/SwiftMessageModifier.swift; sourceTree = "<group>"; }; + B241F1B5D295E7806363B802DF03A085 /* warningIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@2x.png"; path = "SwiftMessages/Resources/warningIcon@2x.png"; sourceTree = "<group>"; }; + B32459A84426DD5E88256AD61F3D4E91 /* Theme.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Theme.swift; path = SwiftMessages/Theme.swift; sourceTree = "<group>"; }; + B8B9892D8D5596E09F02DA2D71BF60B4 /* warningIcon@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "warningIcon@3x.png"; path = "SwiftMessages/Resources/warningIcon@3x.png"; sourceTree = "<group>"; }; + B941E5186F814BF618D9D0458496379C /* SwiftMessages-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftMessages-prefix.pch"; sourceTree = "<group>"; }; + B99CBDE49D6502CF64EB9059C005BF31 /* Pods-iMessageDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageDemo.debug.xcconfig"; sourceTree = "<group>"; }; + BA61C87AB568667230DCD9DC2E423722 /* SwiftMessages.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.release.xcconfig; sourceTree = "<group>"; }; + BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages-SwiftMessages_SwiftMessages */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = "SwiftMessages-SwiftMessages_SwiftMessages"; path = SwiftMessages_SwiftMessages.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + BF61E78F8E8EE539F4A63C5A9D43AC15 /* Pods-iMessageDemo-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-iMessageDemo-frameworks.sh"; sourceTree = "<group>"; }; + C306ACAFEE157959D78E71DBBBD675DC /* Pods-iMessageExtensionDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iMessageExtensionDemo.debug.xcconfig"; sourceTree = "<group>"; }; + C33B3DA756F19F5C93D498D557BEB820 /* TabView.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = TabView.xib; path = SwiftMessages/Resources/TabView.xib; sourceTree = "<group>"; }; + C3701E97FDB85EFCE90E06D8CBC8ED41 /* infoIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = infoIconLight.png; path = SwiftMessages/Resources/infoIconLight.png; sourceTree = "<group>"; }; + C40BBCF3A77C5C7A01708634BB4275C3 /* infoIconSubtle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "infoIconSubtle@3x.png"; path = "SwiftMessages/Resources/infoIconSubtle@3x.png"; sourceTree = "<group>"; }; + C49B964EF7710D818E0AF0321724EEF4 /* errorIconLight@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@2x.png"; path = "SwiftMessages/Resources/errorIconLight@2x.png"; sourceTree = "<group>"; }; + C61DD3C66AC7ADE1E9CCFE7A4A0BEA59 /* TopBottomAnimationStyle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TopBottomAnimationStyle.swift; path = SwiftMessages/TopBottomAnimationStyle.swift; sourceTree = "<group>"; }; + C9BBC4BF82FBB152E34F2D1EF36A0FB1 /* MessageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MessageView.swift; path = SwiftMessages/MessageView.swift; sourceTree = "<group>"; }; + C9E8A4D41E0A0E52C839F7197C4CE2A0 /* AccessibleMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibleMessage.swift; path = SwiftMessages/AccessibleMessage.swift; sourceTree = "<group>"; }; + CBC3F501D8BC852716D085B3022E68CA /* Pods-iMessageExtensionDemo */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-iMessageExtensionDemo"; path = Pods_iMessageExtensionDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CC4854845AC1848C056C36719A5D7420 /* MaskingView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MaskingView.swift; path = SwiftMessages/MaskingView.swift; sourceTree = "<group>"; }; + CC9152C843976F18EF9AE005786DCC80 /* Pods-iMessageDemo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iMessageDemo.modulemap"; sourceTree = "<group>"; }; + D091A06E439F734980F26F81E9161EF2 /* SwiftMessages-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SwiftMessages-dummy.m"; sourceTree = "<group>"; }; + D146564C0660B5F616D6736F6560E17C /* successIconSubtle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "successIconSubtle@2x.png"; path = "SwiftMessages/Resources/successIconSubtle@2x.png"; sourceTree = "<group>"; }; + D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + D47C1471CCFFBEF214DF9F0ECBDD408B /* warningIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = warningIcon.png; path = SwiftMessages/Resources/warningIcon.png; sourceTree = "<group>"; }; + D6A205E933052E98349DC710D78304CB /* errorIconLight@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "errorIconLight@3x.png"; path = "SwiftMessages/Resources/errorIconLight@3x.png"; sourceTree = "<group>"; }; + D83D1CC131CDAC7CA2C5BFD8701E8A79 /* SwiftMessages.Config+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "SwiftMessages.Config+Extensions.swift"; path = "SwiftMessages/SwiftMessages.Config+Extensions.swift"; sourceTree = "<group>"; }; + DBF30CA29E00D6768396013A24DDE9E9 /* SwiftMessages.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftMessages.debug.xcconfig; sourceTree = "<group>"; }; + E473E4F019E816262A61B7F5E8B42373 /* Pods-iMessageDemo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-iMessageDemo-acknowledgements.markdown"; sourceTree = "<group>"; }; + EA8BFA921A44ED7AEAA0E08BCE17EDDA /* HapticMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HapticMessage.swift; path = SwiftMessages/HapticMessage.swift; sourceTree = "<group>"; }; + EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + EC10D7DB2D227D4AA8F41CDFDDC24F37 /* SwiftMessages.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftMessages.swift; path = SwiftMessages/SwiftMessages.swift; sourceTree = "<group>"; }; + EC387534FD34764D4CC28B276A500AD6 /* errorIconLight.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconLight.png; path = SwiftMessages/Resources/errorIconLight.png; sourceTree = "<group>"; }; + EDFC2E756AAB98672C4B241097AAF0F6 /* errorIconSubtle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = errorIconSubtle.png; path = SwiftMessages/Resources/errorIconSubtle.png; sourceTree = "<group>"; }; + F67BD26788FA0C70E942A7629E41C5E8 /* Animator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Animator.swift; path = SwiftMessages/Animator.swift; sourceTree = "<group>"; }; + FBC808D0C98F682E01DC43B544ED093F /* UIWindow+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIWindow+Extensions.swift"; path = "SwiftMessages/UIWindow+Extensions.swift"; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 534FFF2C8F91B03C61DA3655C52CCCA2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 60F02D519964FFEE8A21221FF5E0B0C5 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A018844B6146EA7B81717B756ED28077 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A8C4AD87F73E9C51F797F34BCFF5AA17 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C38F39DB95AA37C32F6FD3963E1EC781 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F5DA2E5126F8D945676819F4BFBBFFEB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3479628DE3B6C9005316A7F591F5E68F /* Foundation.framework in Frameworks */, + E4906D67B9F27E11EE9F8E8F5C847A14 /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0949E0D44EEAC7E812C141F4941C490F /* AppExtension */ = { + isa = PBXGroup; + children = ( + C9E8A4D41E0A0E52C839F7197C4CE2A0 /* AccessibleMessage.swift */, + F67BD26788FA0C70E942A7629E41C5E8 /* Animator.swift */, + 86C1C9601BF8A5BC563062C310C0E3B5 /* BackgroundViewable.swift */, + 790409B3FBA491A9262ACCB929F30104 /* BaseView.swift */, + 35F5FB13175EC0E13D53B445CE31395A /* CALayer+Extensions.swift */, + 03B5D12D54ACC75F929389CFF15E91FF /* CardView.xib */, + 975A42F4C16B65B38769916EC5468D2A /* CenteredView.xib */, + 86872F4639B26435D20BED0CE7E35C7F /* CornerRoundingView.swift */, + 9414B7316138752779A4B9C7E5C988DB /* Error.swift */, + 71D489FBDD84B41576199298F717BC08 /* errorIcon.png */, + 8605740B16E17342A29212D21C380249 /* errorIcon@2x.png */, + 91013DDC05BDB2787740B0C9E5444D23 /* errorIcon@3x.png */, + EC387534FD34764D4CC28B276A500AD6 /* errorIconLight.png */, + C49B964EF7710D818E0AF0321724EEF4 /* errorIconLight@2x.png */, + D6A205E933052E98349DC710D78304CB /* errorIconLight@3x.png */, + EDFC2E756AAB98672C4B241097AAF0F6 /* errorIconSubtle.png */, + 38D28C78FCAE6706F1294CEFA6B25F88 /* errorIconSubtle@2x.png */, + 6C12E87D0EA045A56FC0B45F072C74D2 /* errorIconSubtle@3x.png */, + EA8BFA921A44ED7AEAA0E08BCE17EDDA /* HapticMessage.swift */, + 88398B7A70E5B00495B670516D964701 /* Identifiable.swift */, + 79A086337846180B9A63D8492CCE45B4 /* infoIcon.png */, + 2CF5DC74916EBE02E70234620CD80150 /* infoIcon@2x.png */, + 560722B244EB84DF745199247129C164 /* infoIcon@3x.png */, + C3701E97FDB85EFCE90E06D8CBC8ED41 /* infoIconLight.png */, + ACCCF5B75EA41D844ED936A92602C5B1 /* infoIconLight@2x.png */, + 88237113DAAD8ECF8D5E3FAA27D8A02F /* infoIconLight@3x.png */, + A6C7FF0D9E13571262231B72D0553E49 /* infoIconSubtle.png */, + 8026A87EEBF1A86A282563F974C4225C /* infoIconSubtle@2x.png */, + C40BBCF3A77C5C7A01708634BB4275C3 /* infoIconSubtle@3x.png */, + 9A99EE79DBFA3C24A372DDB69162E36C /* KeyboardTrackingView.swift */, + 14DF8F43552C4F1C4CAEFBAFD9A77004 /* MarginAdjustable.swift */, + 9B602E4E64DAEF1468DD2F5C2C5DFD00 /* MarginAdjustable+Extensions.swift */, + CC4854845AC1848C056C36719A5D7420 /* MaskingView.swift */, + 28456F0421422D16D71D14D426309B3F /* MessageGeometryProxy.swift */, + 5F989D33CAC3BCDA9B3C4B18F23A4DBE /* MessageHostingView.swift */, + C9BBC4BF82FBB152E34F2D1EF36A0FB1 /* MessageView.swift */, + A4D741EF8B40F5472CE2C1C1A34426BD /* MessageView.xib */, + 06DB4311BFB347093FC18777A503B461 /* MessageViewConvertible.swift */, + 073CD58B2E8E255484D239A01D707B81 /* NSBundle+Extensions.swift */, + 882EF814D0A1EE2AB28BFEE5C067EE6F /* NSLayoutConstraint+Extensions.swift */, + 03A865E97261799942A6F29092D3D7AE /* PassthroughView.swift */, + 0398CE267904AF6C2FD03B3766511ECF /* PassthroughWindow.swift */, + 8D7E08E0434930866B59A3F17A3A577B /* PhysicsAnimation.swift */, + 8AEEED9FBEA6C5DB7EE3B95E7D8115B3 /* PhysicsPanHandler.swift */, + 8D18688EA04EA2F2BC48ED05D1FE5404 /* Presenter.swift */, + 62332870F1E2AE3FA16EE5ADC85C104A /* StatusLine.xib */, + 74793ADC8ADF7674EA6C3041E2B54354 /* successIcon.png */, + 4DBF06E9B2F93F081139B8A6A922F569 /* successIcon@2x.png */, + 6EA088414C10E47808EA8490D9BBF64F /* successIcon@3x.png */, + 252A5DF0FE3237691B8C50B969857389 /* successIconLight.png */, + 44DAC25C8D6D72F70BD1CF9099BDAF10 /* successIconLight@2x.png */, + 5686DFC1E0B24A3051EF376AD8A162C0 /* successIconLight@3x.png */, + 7B9CEE1B17C98E76723E7404C532515D /* successIconSubtle.png */, + D146564C0660B5F616D6736F6560E17C /* successIconSubtle@2x.png */, + 47A710678B44C50DA470D1BCF94B87B8 /* successIconSubtle@3x.png */, + B19DACBEC8DD85FB850D299DFB7A0374 /* SwiftMessageModifier.swift */, + EC10D7DB2D227D4AA8F41CDFDDC24F37 /* SwiftMessages.swift */, + D83D1CC131CDAC7CA2C5BFD8701E8A79 /* SwiftMessages.Config+Extensions.swift */, + B17EF282E0A0F329DDF17226E83706F8 /* SwiftMessagesSegue.swift */, + C33B3DA756F19F5C93D498D557BEB820 /* TabView.xib */, + 9610DCAAD9A55CDF73BAD54D523E1273 /* Task+Extensions.swift */, + B32459A84426DD5E88256AD61F3D4E91 /* Theme.swift */, + A1F1B1264A726D334A72AB1CB001CA9F /* TopBottomAnimation.swift */, + C61DD3C66AC7ADE1E9CCFE7A4A0BEA59 /* TopBottomAnimationStyle.swift */, + A102DE8896931D80E06F2C74C2B003AC /* TopBottomPresentable.swift */, + 16B5B2B5429B01345E4DA361DE01904D /* UIEdgeInsets+Extensions.swift */, + 57EB79F63EA99ADBBDA408015A4599BB /* UIViewController+Extensions.swift */, + FBC808D0C98F682E01DC43B544ED093F /* UIWindow+Extensions.swift */, + D47C1471CCFFBEF214DF9F0ECBDD408B /* warningIcon.png */, + B241F1B5D295E7806363B802DF03A085 /* warningIcon@2x.png */, + B8B9892D8D5596E09F02DA2D71BF60B4 /* warningIcon@3x.png */, + 004EE347886E2355CCB352F2AE7A35D6 /* warningIconLight.png */, + 71699C81494BC6585B862CDFC1CDAF54 /* warningIconLight@2x.png */, + 5FE01208AD70F1B35201AB04E50A23EC /* warningIconLight@3x.png */, + 6924A0A48B715EA35080ABB106B96BF7 /* warningIconSubtle.png */, + 85C6BEF274CDB3807F9BD452A26C68E6 /* warningIconSubtle@2x.png */, + 5E02B1554754BA1F8EF318D567875139 /* warningIconSubtle@3x.png */, + 442F9FAEDF369CADB9E6E8FF3668FD95 /* Weak.swift */, + 2AB9866F195EB0AED31A33AEC27B67C1 /* WindowScene.swift */, + 9908774A62A95BF5BA8FE65842868043 /* WindowViewController.swift */, + ); + name = AppExtension; + sourceTree = "<group>"; + }; + 1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 59DA5C1F72E1D5BABC43EACBA672C3BA /* iOS */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + 367D4F82667A10E742DF94EEDD05B67C /* Pod */ = { + isa = PBXGroup; + children = ( + 9D5A75A919AE6C6D38A627636D7ADC11 /* LICENSE.md */, + A399825CF45C4427BF9B80A590BF2BD5 /* README.md */, + 573965F15F83BD70EEAC9E1E8B0F85C6 /* SwiftMessages.podspec */, + ); + name = Pod; + sourceTree = "<group>"; + }; + 3B07A3E7DF9452FD2B994A3383A19C32 /* SwiftMessages */ = { + isa = PBXGroup; + children = ( + 0949E0D44EEAC7E812C141F4941C490F /* AppExtension */, + 367D4F82667A10E742DF94EEDD05B67C /* Pod */, + D1F228CBB00BC0EEBE5243BDCD591903 /* Support Files */, + ); + name = SwiftMessages; + path = ../..; + sourceTree = "<group>"; + }; + 46F000C5D88847E6B7EDC4BA40536149 /* Products */ = { + isa = PBXGroup; + children = ( + AFC41396FB1BD59C9A69EE1DD82E47C2 /* Pods-iMessageDemo */, + CBC3F501D8BC852716D085B3022E68CA /* Pods-iMessageExtensionDemo */, + 4824F23D80FF9070A5F8A452DB11EB9A /* SwiftMessages */, + BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages-SwiftMessages_SwiftMessages */, + ); + name = Products; + sourceTree = "<group>"; + }; + 59DA5C1F72E1D5BABC43EACBA672C3BA /* iOS */ = { + isa = PBXGroup; + children = ( + EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */, + D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */, + ); + name = iOS; + sourceTree = "<group>"; + }; + 8F3CF4AFB0CA47B3BFE1C68E51CDF0A9 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 9A912CA1E54EADE1787311C1DF7E8F2E /* Pods-iMessageDemo */, + BD13800F87C70DC802DBC0C37E8C5E99 /* Pods-iMessageExtensionDemo */, + ); + name = "Targets Support Files"; + sourceTree = "<group>"; + }; + 9A912CA1E54EADE1787311C1DF7E8F2E /* Pods-iMessageDemo */ = { + isa = PBXGroup; + children = ( + CC9152C843976F18EF9AE005786DCC80 /* Pods-iMessageDemo.modulemap */, + E473E4F019E816262A61B7F5E8B42373 /* Pods-iMessageDemo-acknowledgements.markdown */, + 915DE2E4E300BAD440BE13F72E49D731 /* Pods-iMessageDemo-acknowledgements.plist */, + 14BF989232A1D55A0FDAAB70B5A8E1BF /* Pods-iMessageDemo-dummy.m */, + BF61E78F8E8EE539F4A63C5A9D43AC15 /* Pods-iMessageDemo-frameworks.sh */, + 093D5BBE2A96A1A7AC0432A3AB933576 /* Pods-iMessageDemo-Info.plist */, + 2D0ECE831FB5E0EE1D68E837671320C7 /* Pods-iMessageDemo-umbrella.h */, + B99CBDE49D6502CF64EB9059C005BF31 /* Pods-iMessageDemo.debug.xcconfig */, + 820B743874F7AC9F9E3970D68E2E60FA /* Pods-iMessageDemo.release.xcconfig */, + ); + name = "Pods-iMessageDemo"; + path = "Target Support Files/Pods-iMessageDemo"; + sourceTree = "<group>"; + }; + BD13800F87C70DC802DBC0C37E8C5E99 /* Pods-iMessageExtensionDemo */ = { + isa = PBXGroup; + children = ( + 6489B2A759075E9DC1D1406734F45B5F /* Pods-iMessageExtensionDemo.modulemap */, + 8D54691037F1CA4653B76F0558E2AA82 /* Pods-iMessageExtensionDemo-acknowledgements.markdown */, + 1341BB7116EC50FDF7062C6A91DEDF49 /* Pods-iMessageExtensionDemo-acknowledgements.plist */, + 7F40CA14AD738DD186B4DA8FD14AE5BD /* Pods-iMessageExtensionDemo-dummy.m */, + 7CC6A596A9C1659D8E93222DA4144414 /* Pods-iMessageExtensionDemo-Info.plist */, + 5CAB201AD00CAB811B045E2FFB5C03A8 /* Pods-iMessageExtensionDemo-umbrella.h */, + C306ACAFEE157959D78E71DBBBD675DC /* Pods-iMessageExtensionDemo.debug.xcconfig */, + AE7AEA9CE6B44DCC96AE4E68FA644DAA /* Pods-iMessageExtensionDemo.release.xcconfig */, + ); + name = "Pods-iMessageExtensionDemo"; + path = "Target Support Files/Pods-iMessageExtensionDemo"; + sourceTree = "<group>"; + }; + C5AAA95D48373FAC474F6EFCC1749444 /* Development Pods */ = { + isa = PBXGroup; + children = ( + 3B07A3E7DF9452FD2B994A3383A19C32 /* SwiftMessages */, + ); + name = "Development Pods"; + sourceTree = "<group>"; + }; + CF1408CF629C7361332E53B88F7BD30C = { + isa = PBXGroup; + children = ( + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + C5AAA95D48373FAC474F6EFCC1749444 /* Development Pods */, + 1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */, + 46F000C5D88847E6B7EDC4BA40536149 /* Products */, + 8F3CF4AFB0CA47B3BFE1C68E51CDF0A9 /* Targets Support Files */, + ); + sourceTree = "<group>"; + }; + D1F228CBB00BC0EEBE5243BDCD591903 /* Support Files */ = { + isa = PBXGroup; + children = ( + 8940290DCDAD08810FE0CD944F376444 /* ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist */, + 6228A8E37F7905D75917DD4CBE65B03C /* SwiftMessages.modulemap */, + D091A06E439F734980F26F81E9161EF2 /* SwiftMessages-dummy.m */, + 0FD758C8718F3EEFB5E97E34A29CE1CC /* SwiftMessages-Info.plist */, + B941E5186F814BF618D9D0458496379C /* SwiftMessages-prefix.pch */, + 080E269BABA7D072D8C51E29E9AC4A91 /* SwiftMessages-umbrella.h */, + DBF30CA29E00D6768396013A24DDE9E9 /* SwiftMessages.debug.xcconfig */, + BA61C87AB568667230DCD9DC2E423722 /* SwiftMessages.release.xcconfig */, + ); + name = "Support Files"; + path = "iMessageDemo/Pods/Target Support Files/SwiftMessages"; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 5E0996100D0B6376DB378D36C49FEB72 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 88D024879AEAE247899BFB50C8516515 /* Pods-iMessageDemo-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 94D488A57BCCF0DF1CE9E3AA109BAF42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 7590FF543E2634A83059E509D5B05583 /* Pods-iMessageExtensionDemo-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9F82EEB2B7A573A17661E879E23301CC /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + B646E1CD53F14E0DEE53740799C06AC5 /* SwiftMessages-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1FC5E8328653C350899229BDF89FACE5 /* SwiftMessages-SwiftMessages_SwiftMessages */ = { + isa = PBXNativeTarget; + buildConfigurationList = B9E25A37EB36EDFCDE7B709EF28887E1 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages_SwiftMessages" */; + buildPhases = ( + 27425DAD651893A17CC601370E148AA6 /* Sources */, + C38F39DB95AA37C32F6FD3963E1EC781 /* Frameworks */, + B677C83AAEA5EB9CD3E80A8BA2A910E7 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "SwiftMessages-SwiftMessages_SwiftMessages"; + productName = SwiftMessages_SwiftMessages; + productReference = BEBF018059B0DFCAC8494ABD1C578AD9 /* SwiftMessages-SwiftMessages_SwiftMessages */; + productType = "com.apple.product-type.bundle"; + }; + 2757367020CF4EA7726D56118C89F6AE /* Pods-iMessageExtensionDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = D4007834B8D8DEA14D3016E025D2E198 /* Build configuration list for PBXNativeTarget "Pods-iMessageExtensionDemo" */; + buildPhases = ( + 94D488A57BCCF0DF1CE9E3AA109BAF42 /* Headers */, + 7C2BDA53E99CB24205C4C877E7B01D37 /* Sources */, + A018844B6146EA7B81717B756ED28077 /* Frameworks */, + 1A38555F56C7853980EFF926359385D4 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 8935DBBDEDCE7F48711B98D9DB279717 /* PBXTargetDependency */, + ); + name = "Pods-iMessageExtensionDemo"; + productName = Pods_iMessageExtensionDemo; + productReference = CBC3F501D8BC852716D085B3022E68CA /* Pods-iMessageExtensionDemo */; + productType = "com.apple.product-type.framework"; + }; + DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */ = { + isa = PBXNativeTarget; + buildConfigurationList = BC0696CE4F28B31FF26CA99798FE7058 /* Build configuration list for PBXNativeTarget "SwiftMessages" */; + buildPhases = ( + 9F82EEB2B7A573A17661E879E23301CC /* Headers */, + F72FF659E811A6D8DFB11AE35F7C3B09 /* Sources */, + F5DA2E5126F8D945676819F4BFBBFFEB /* Frameworks */, + 3825F2CC81138FAE9F77136A6C646663 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + E98E5B4F9A2B7044ED32678F81832AEE /* PBXTargetDependency */, + ); + name = SwiftMessages; + productName = SwiftMessages; + productReference = 4824F23D80FF9070A5F8A452DB11EB9A /* SwiftMessages */; + productType = "com.apple.product-type.framework"; + }; + E2AECC8B9DD9E437C7DD0FD0FFC881F3 /* Pods-iMessageDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A195C86FC7EF00767CF99ECEBE42625 /* Build configuration list for PBXNativeTarget "Pods-iMessageDemo" */; + buildPhases = ( + 5E0996100D0B6376DB378D36C49FEB72 /* Headers */, + 0642123BC3DE909207A9EC283F481AD9 /* Sources */, + 534FFF2C8F91B03C61DA3655C52CCCA2 /* Frameworks */, + 9859D25D3582DB4C5A3D5ADA90024549 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 5AEACA50B99030606B5CAF987F9793FD /* PBXTargetDependency */, + ); + name = "Pods-iMessageDemo"; + productName = Pods_iMessageDemo; + productReference = AFC41396FB1BD59C9A69EE1DD82E47C2 /* Pods-iMessageDemo */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BFDFE7DC352907FC980B868725387E98 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; + }; + buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = CF1408CF629C7361332E53B88F7BD30C; + productRefGroup = 46F000C5D88847E6B7EDC4BA40536149 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + E2AECC8B9DD9E437C7DD0FD0FFC881F3 /* Pods-iMessageDemo */, + 2757367020CF4EA7726D56118C89F6AE /* Pods-iMessageExtensionDemo */, + DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */, + 1FC5E8328653C350899229BDF89FACE5 /* SwiftMessages-SwiftMessages_SwiftMessages */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A38555F56C7853980EFF926359385D4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3825F2CC81138FAE9F77136A6C646663 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 28D6446B971F186BACDED83CD8DE4D44 /* SwiftMessages-SwiftMessages_SwiftMessages in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9859D25D3582DB4C5A3D5ADA90024549 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B677C83AAEA5EB9CD3E80A8BA2A910E7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A4724FC3B4F49DCBF50D395257BB6B8E /* CardView.xib in Resources */, + 469995B0FC2E3748F59D0E3A4445E197 /* CenteredView.xib in Resources */, + E54040398A9AD751393A2171DC64D70E /* errorIcon.png in Resources */, + 6A04C3E1C3437ED6BC6F096302B458AB /* errorIcon@2x.png in Resources */, + DE2531A67AEBFED61A060DF13790C3BE /* errorIcon@3x.png in Resources */, + 47EFB870CC797D2F54396F0AEBC8F576 /* errorIconLight.png in Resources */, + FC0E2BA3CD9C6C3ACF3681841D8EF5BA /* errorIconLight@2x.png in Resources */, + 1E507663F3C402CBCA0C50A876F472EF /* errorIconLight@3x.png in Resources */, + 360BEE76BBF40319E6638B3E027E1474 /* errorIconSubtle.png in Resources */, + 205A52121D20436063240893A461B29C /* errorIconSubtle@2x.png in Resources */, + 4980F404C2B391C621CE2BCF05E08BDF /* errorIconSubtle@3x.png in Resources */, + 8CB7CCDF07E1CE6838C7278BC19968B6 /* infoIcon.png in Resources */, + 096A6663757CB52C8A34B3E3146279C8 /* infoIcon@2x.png in Resources */, + 8F63F1ABAB21FA99A6CB1A54D5F2B5AA /* infoIcon@3x.png in Resources */, + 422B422F962FD298F963F84934A21529 /* infoIconLight.png in Resources */, + 3613DBA9CBD7E092BD7DC1924E6648D2 /* infoIconLight@2x.png in Resources */, + A52191D65F4C725EBF61D27F40FEA970 /* infoIconLight@3x.png in Resources */, + A90C06B459CC64A243DD1184024E5D22 /* infoIconSubtle.png in Resources */, + DC6C4E22FA8DD6FA491066A738132EF1 /* infoIconSubtle@2x.png in Resources */, + 6CDE06668BB53C70BF1456F8EEE845D9 /* infoIconSubtle@3x.png in Resources */, + 0D53997CCCD141D2303E87C29CEFE211 /* MessageView.xib in Resources */, + B61EBE61C31E78140BF12D32A008A43B /* StatusLine.xib in Resources */, + 31660027252C457325491844F16AEBDD /* successIcon.png in Resources */, + EE9A5A3877D99BFCA5DA70BA4E049CA9 /* successIcon@2x.png in Resources */, + 79BB175F4750822409AB9ED0A9D90D09 /* successIcon@3x.png in Resources */, + A8EF6BE26B31A8713E37E0629F6466EB /* successIconLight.png in Resources */, + 9FBBA6E4D3A2A4CA4BA8535E35D54CA8 /* successIconLight@2x.png in Resources */, + 61F532D30833A9FF1DE00EC98BC018C2 /* successIconLight@3x.png in Resources */, + 72026C4424B7A1650CBEED98ED9AA288 /* successIconSubtle.png in Resources */, + 37A8DD40AF13BCABE7A3CD8EF15A4C53 /* successIconSubtle@2x.png in Resources */, + BBF31491EF3411DCFA7E649645229E2A /* successIconSubtle@3x.png in Resources */, + 1441D5A06DD6903562EB794FC1AE8822 /* TabView.xib in Resources */, + D8DFC45149C57377B5C90B3457090564 /* warningIcon.png in Resources */, + 0ADA608E3B9307694DCF4D0BC426E7FE /* warningIcon@2x.png in Resources */, + 4C9FED5D268E82325C17309FB8904C43 /* warningIcon@3x.png in Resources */, + 4609D5EC365EABFE507781BF911B887B /* warningIconLight.png in Resources */, + 744EA4AF597AFEFEE5B398434F47CA26 /* warningIconLight@2x.png in Resources */, + 81B1015F29547CAB449757FC5ABCAFAB /* warningIconLight@3x.png in Resources */, + 6583C565BE5BB9E52213854AA85F5A93 /* warningIconSubtle.png in Resources */, + D3B31A631C754CAECABFA4DC672D3D0B /* warningIconSubtle@2x.png in Resources */, + 24DA4886290040A0EC88B63D82EF412D /* warningIconSubtle@3x.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 0642123BC3DE909207A9EC283F481AD9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 436D8C63FBE86FF8271ABC32F9A52A9D /* Pods-iMessageDemo-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 27425DAD651893A17CC601370E148AA6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7C2BDA53E99CB24205C4C877E7B01D37 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B22AF07D79D1A82DE583AC49E3D472D3 /* Pods-iMessageExtensionDemo-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F72FF659E811A6D8DFB11AE35F7C3B09 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 03C7FA1BE62CCD280D63F4C7CDDFB27F /* AccessibleMessage.swift in Sources */, + D9519DD580DF2E744AB4C4087FA28BCD /* Animator.swift in Sources */, + A865FCE8718103C8E725EC1EC0F9F4F6 /* BackgroundViewable.swift in Sources */, + 6DC0B420F622E197919276CFF2C063CE /* BaseView.swift in Sources */, + 3F53FCE80C716C7DE7A3B1D8D65077BC /* CALayer+Extensions.swift in Sources */, + 274D5DE28E0446655163A48E2272860A /* CornerRoundingView.swift in Sources */, + CCBFBDB03B2444C911BADDE6A6BA08AD /* Error.swift in Sources */, + 47CC2A912B82A499DB2F5E2ADBE664CF /* HapticMessage.swift in Sources */, + 67F7D444EAC4475021B3458B21B2A162 /* Identifiable.swift in Sources */, + 3C566158256E9CC711B73810B2C64E3B /* KeyboardTrackingView.swift in Sources */, + 0C093AF5F4D753325F4CE92F2F943CB4 /* MarginAdjustable.swift in Sources */, + 634267873AC0F98140DBAFFF9A180BA8 /* MarginAdjustable+Extensions.swift in Sources */, + F8D0D33FC1C833490057108C322E56CB /* MaskingView.swift in Sources */, + B6D0E2FA454A946D6C9A7494648F49D9 /* MessageGeometryProxy.swift in Sources */, + 19C0F7897044E72D3A13DE703920FFE1 /* MessageHostingView.swift in Sources */, + A836F848C83565B2A0A06AB23D491946 /* MessageView.swift in Sources */, + C2031E7EC3C60B876F2AC04253D3AFC4 /* MessageViewConvertible.swift in Sources */, + 942468E4C1AEFCF10D5043243B4007E7 /* NSBundle+Extensions.swift in Sources */, + B1B4D240B65FFC5A7A981B9504C55270 /* NSLayoutConstraint+Extensions.swift in Sources */, + DD406A0C002AC1D02A6E5794B1729C22 /* PassthroughView.swift in Sources */, + BAB66573FF29F6337237A8DA0EB9E3E8 /* PassthroughWindow.swift in Sources */, + F667CC7C7F3285FC39427F2AAA8E7665 /* PhysicsAnimation.swift in Sources */, + F2D3ABB0C7B6EB5B531E4E68C40AA89C /* PhysicsPanHandler.swift in Sources */, + 158EF18377B720081C31C2F2100DDA7A /* Presenter.swift in Sources */, + 04BCE3C12FDE7E91C9EF1FE154E80E2B /* SwiftMessageModifier.swift in Sources */, + 330C59E62D17601422EDB29513B9856C /* SwiftMessages.swift in Sources */, + 67DC4D170143131B8AFFB558FDD00465 /* SwiftMessages-dummy.m in Sources */, + 48ADA8D4633776558E7D216434057A2A /* SwiftMessages.Config+Extensions.swift in Sources */, + 3451B2775584DD75A3BDF9BF28A03F76 /* SwiftMessagesSegue.swift in Sources */, + B04AA81A8A8CE0BCEFD5FAFD841F461F /* Task+Extensions.swift in Sources */, + E03C930AD56F078DCD1357E5C83AD67A /* Theme.swift in Sources */, + F516490B5276943A352D597431B079B6 /* TopBottomAnimation.swift in Sources */, + B9FDFA90A4FB68CA5357AB70427B4DCD /* TopBottomAnimationStyle.swift in Sources */, + 450919BA3A4D984DC24822CD80483419 /* TopBottomPresentable.swift in Sources */, + BA4779B82B35B85EFE9F595624BA3943 /* UIEdgeInsets+Extensions.swift in Sources */, + 698F203577674AFA4BBCDE93B01B9EEC /* UIViewController+Extensions.swift in Sources */, + 45A4B95F1F73413A3001B95E1F91D697 /* UIWindow+Extensions.swift in Sources */, + 00A4A53E0D1EFC70DA1EFAEFA82C4BA1 /* Weak.swift in Sources */, + 04C771EB4784B94AC6CA28ED6A919D50 /* WindowScene.swift in Sources */, + 52A01853AC4F2D0E720579D7F8A531CF /* WindowViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 5AEACA50B99030606B5CAF987F9793FD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftMessages; + target = DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */; + targetProxy = D297C84AE0F13FB6A76F2F391D21D679 /* PBXContainerItemProxy */; + }; + 8935DBBDEDCE7F48711B98D9DB279717 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftMessages; + target = DAB613A18652334F6BFC5F27BADF515D /* SwiftMessages */; + targetProxy = 70E6358901408AED062E820735630F69 /* PBXContainerItemProxy */; + }; + E98E5B4F9A2B7044ED32678F81832AEE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "SwiftMessages-SwiftMessages_SwiftMessages"; + target = 1FC5E8328653C350899229BDF89FACE5 /* SwiftMessages-SwiftMessages_SwiftMessages */; + targetProxy = 146D3A65FCE17293CC3AD6CBEAE15F9A /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 3FC2D46D829830CE0E848EA5B410073A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DBF30CA29E00D6768396013A24DDE9E9 /* SwiftMessages.debug.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SwiftMessages"; + IBSC_MODULE = SwiftMessages; + INFOPLIST_FILE = "Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + PRODUCT_NAME = SwiftMessages_SwiftMessages; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + 4503CB76C2B552AADDBE817FB3830956 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C306ACAFEE157959D78E71DBBBD675DC /* Pods-iMessageExtensionDemo.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 59909018A45193B32A9AC1A497747707 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 820B743874F7AC9F9E3970D68E2E60FA /* Pods-iMessageDemo.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 8C9963745FD01B6B3EF95F9CE58D9F10 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + 9AA80409B5B73B4F3944DDDD6463F2F3 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DBF30CA29E00D6768396013A24DDE9E9 /* SwiftMessages.debug.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SwiftMessages/SwiftMessages-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SwiftMessages/SwiftMessages-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/SwiftMessages/SwiftMessages.modulemap"; + PRODUCT_MODULE_NAME = SwiftMessages; + PRODUCT_NAME = SwiftMessages; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 9FEE8F2AB72B17FFBCF0628B7DCBB31F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BA61C87AB568667230DCD9DC2E423722 /* SwiftMessages.release.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SwiftMessages"; + IBSC_MODULE = SwiftMessages; + INFOPLIST_FILE = "Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + PRODUCT_NAME = SwiftMessages_SwiftMessages; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; + A96FA7E94B943E99EB50714920749FAA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BA61C87AB568667230DCD9DC2E423722 /* SwiftMessages.release.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SwiftMessages/SwiftMessages-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SwiftMessages/SwiftMessages-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/SwiftMessages/SwiftMessages.modulemap"; + PRODUCT_MODULE_NAME = SwiftMessages; + PRODUCT_NAME = SwiftMessages; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + B9F3557045385CA606F5AF548D58B58A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + C071287F0603F63CE0FC42C4A8BB3E9A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AE7AEA9CE6B44DCC96AE4E68FA644DAA /* Pods-iMessageExtensionDemo.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DFD90EB1585D1CB60C100925E96958A9 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B99CBDE49D6502CF64EB9059C005BF31 /* Pods-iMessageDemo.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A195C86FC7EF00767CF99ECEBE42625 /* Build configuration list for PBXNativeTarget "Pods-iMessageDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DFD90EB1585D1CB60C100925E96958A9 /* Debug */, + 59909018A45193B32A9AC1A497747707 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8C9963745FD01B6B3EF95F9CE58D9F10 /* Debug */, + B9F3557045385CA606F5AF548D58B58A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B9E25A37EB36EDFCDE7B709EF28887E1 /* Build configuration list for PBXNativeTarget "SwiftMessages-SwiftMessages_SwiftMessages" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3FC2D46D829830CE0E848EA5B410073A /* Debug */, + 9FEE8F2AB72B17FFBCF0628B7DCBB31F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + BC0696CE4F28B31FF26CA99798FE7058 /* Build configuration list for PBXNativeTarget "SwiftMessages" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9AA80409B5B73B4F3944DDDD6463F2F3 /* Debug */, + A96FA7E94B943E99EB50714920749FAA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D4007834B8D8DEA14D3016E025D2E198 /* Build configuration list for PBXNativeTarget "Pods-iMessageExtensionDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4503CB76C2B552AADDBE817FB3830956 /* Debug */, + C071287F0603F63CE0FC42C4A8BB3E9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; +} diff --git a/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "self:"> + </FileRef> +</Workspace> diff --git a/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEDidComputeMac32BitWarning</key> + <true/> +</dict> +</plist> diff --git a/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..08de0be8 --- /dev/null +++ b/iMessageDemo/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key> + <false/> +</dict> +</plist> diff --git a/Demo/Pods/Target Support Files/Pods-Demo/Info.plist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist similarity index 94% rename from Demo/Pods/Target Support Files/Pods-Demo/Info.plist rename to iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist index 2243fe6e..19cf209d 100644 --- a/Demo/Pods/Target Support Files/Pods-Demo/Info.plist +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-Info.plist @@ -3,7 +3,7 @@ <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> - <string>en</string> + <string>${PODS_DEVELOPMENT_LANGUAGE}</string> <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleIdentifier</key> diff --git a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-acknowledgements.markdown b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-acknowledgements.markdown similarity index 100% rename from Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-acknowledgements.markdown rename to iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-acknowledgements.markdown diff --git a/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-acknowledgements.plist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-acknowledgements.plist similarity index 100% rename from Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-acknowledgements.plist rename to iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-acknowledgements.plist diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-dummy.m b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-dummy.m new file mode 100644 index 00000000..2d3a72b7 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-dummy.m @@ -0,0 +1,5 @@ +#import <Foundation/Foundation.h> +@interface PodsDummy_Pods_iMessageDemo : NSObject +@end +@implementation PodsDummy_Pods_iMessageDemo +@end diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-input-files.xcfilelist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-input-files.xcfilelist new file mode 100644 index 00000000..c2649f16 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-input-files.xcfilelist @@ -0,0 +1,2 @@ +${PODS_ROOT}/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh +${BUILT_PRODUCTS_DIR}/SwiftMessages/SwiftMessages.framework \ No newline at end of file diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-output-files.xcfilelist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-output-files.xcfilelist new file mode 100644 index 00000000..7e50d50f --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Debug-output-files.xcfilelist @@ -0,0 +1 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftMessages.framework \ No newline at end of file diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-input-files.xcfilelist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-input-files.xcfilelist new file mode 100644 index 00000000..c2649f16 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-input-files.xcfilelist @@ -0,0 +1,2 @@ +${PODS_ROOT}/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh +${BUILT_PRODUCTS_DIR}/SwiftMessages/SwiftMessages.framework \ No newline at end of file diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-output-files.xcfilelist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-output-files.xcfilelist new file mode 100644 index 00000000..7e50d50f --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-Release-output-files.xcfilelist @@ -0,0 +1 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftMessages.framework \ No newline at end of file diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh new file mode 100755 index 00000000..70350e1f --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh @@ -0,0 +1,186 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" +BCSYMBOLMAP_DIR="BCSymbolMaps" + + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink -f "${source}")" + fi + + if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then + # Locate and install any .bcsymbolmaps if present, and remove them from the .framework before the framework is copied + find "${source}/${BCSYMBOLMAP_DIR}" -name "*.bcsymbolmap"|while read f; do + echo "Installing $f" + install_bcsymbolmap "$f" "$destination" + rm "$f" + done + rmdir "${source}/${BCSYMBOLMAP_DIR}" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + warn_missing_arch=${2:-true} + if [ -r "$source" ]; then + # Copy the dSYM into the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .dSYM "$source")" + binary_name="$(ls "$source/Contents/Resources/DWARF")" + binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" + + # Strip invalid architectures from the dSYM. + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then + strip_invalid_archs "$binary" "$warn_missing_arch" + fi + if [[ $STRIP_BINARY_RETVAL == 0 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + mkdir -p "${DWARF_DSYM_FOLDER_PATH}" + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" + fi + fi +} + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + warn_missing_arch=${2:-true} + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + if [[ "$warn_missing_arch" == "true" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + fi + STRIP_BINARY_RETVAL=1 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=0 +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identity + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/SwiftMessages/SwiftMessages.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/SwiftMessages/SwiftMessages.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-umbrella.h b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-umbrella.h new file mode 100644 index 00000000..2e129a27 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import <UIKit/UIKit.h> +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_iMessageDemoVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_iMessageDemoVersionString[]; + diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.debug.xcconfig b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.debug.xcconfig new file mode 100644 index 00000000..f075bc9b --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.debug.xcconfig @@ -0,0 +1,15 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages/SwiftMessages.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -framework "UIKit" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.modulemap b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.modulemap new file mode 100644 index 00000000..980c725a --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.modulemap @@ -0,0 +1,6 @@ +framework module Pods_iMessageDemo { + umbrella header "Pods-iMessageDemo-umbrella.h" + + export * + module * { export * } +} diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.release.xcconfig b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.release.xcconfig new file mode 100644 index 00000000..f075bc9b --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.release.xcconfig @@ -0,0 +1,15 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages/SwiftMessages.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -framework "UIKit" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Demo/Pods/Target Support Files/SwiftMessages/Info.plist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist similarity index 91% rename from Demo/Pods/Target Support Files/SwiftMessages/Info.plist rename to iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist index b3ee339e..19cf209d 100644 --- a/Demo/Pods/Target Support Files/SwiftMessages/Info.plist +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-Info.plist @@ -3,7 +3,7 @@ <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> - <string>en</string> + <string>${PODS_DEVELOPMENT_LANGUAGE}</string> <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleIdentifier</key> @@ -15,7 +15,7 @@ <key>CFBundlePackageType</key> <string>FMWK</string> <key>CFBundleShortVersionString</key> - <string>3.0.3</string> + <string>1.0.0</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.markdown b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.markdown new file mode 100644 index 00000000..cfe94293 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.markdown @@ -0,0 +1,14 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## SwiftMessages + +Copyright (c) 2016 SwiftKick Mobile LLC + + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Generated by CocoaPods - https://cocoapods.org diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.plist b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.plist new file mode 100644 index 00000000..25aea9b0 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-acknowledgements.plist @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>PreferenceSpecifiers</key> + <array> + <dict> + <key>FooterText</key> + <string>This application makes use of the following third party libraries:</string> + <key>Title</key> + <string>Acknowledgements</string> + <key>Type</key> + <string>PSGroupSpecifier</string> + </dict> + <dict> + <key>FooterText</key> + <string>Copyright (c) 2016 SwiftKick Mobile LLC + + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</string> + <key>License</key> + <string>MIT</string> + <key>Title</key> + <string>SwiftMessages</string> + <key>Type</key> + <string>PSGroupSpecifier</string> + </dict> + <dict> + <key>FooterText</key> + <string>Generated by CocoaPods - https://cocoapods.org</string> + <key>Title</key> + <string></string> + <key>Type</key> + <string>PSGroupSpecifier</string> + </dict> + </array> + <key>StringsTable</key> + <string>Acknowledgements</string> + <key>Title</key> + <string>Acknowledgements</string> +</dict> +</plist> diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-dummy.m b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-dummy.m new file mode 100644 index 00000000..a9fef241 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-dummy.m @@ -0,0 +1,5 @@ +#import <Foundation/Foundation.h> +@interface PodsDummy_Pods_iMessageExtensionDemo : NSObject +@end +@implementation PodsDummy_Pods_iMessageExtensionDemo +@end diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-umbrella.h b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-umbrella.h new file mode 100644 index 00000000..b45e1cf3 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import <UIKit/UIKit.h> +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_iMessageExtensionDemoVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_iMessageExtensionDemoVersionString[]; + diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.debug.xcconfig b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.debug.xcconfig new file mode 100644 index 00000000..2ab61eed --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.debug.xcconfig @@ -0,0 +1,14 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages/SwiftMessages.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -framework "UIKit" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.modulemap b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.modulemap new file mode 100644 index 00000000..ab391867 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.modulemap @@ -0,0 +1,6 @@ +framework module Pods_iMessageExtensionDemo { + umbrella header "Pods-iMessageExtensionDemo-umbrella.h" + + export * + module * { export * } +} diff --git a/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.release.xcconfig b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.release.xcconfig new file mode 100644 index 00000000..2ab61eed --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.release.xcconfig @@ -0,0 +1,14 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages/SwiftMessages.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_LDFLAGS = $(inherited) -framework "SwiftMessages" -framework "UIKit" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Demo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages-Info.plist b/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages-SwiftMessages-Info.plist similarity index 96% rename from Demo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages-Info.plist rename to iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages-SwiftMessages-Info.plist index 87f1d46d..35c2f997 100644 --- a/Demo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages-Info.plist +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages-SwiftMessages-Info.plist @@ -13,7 +13,7 @@ <key>CFBundlePackageType</key> <string>BNDL</string> <key>CFBundleShortVersionString</key> - <string>3.0.3</string> + <string>9.0.1</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist b/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist new file mode 100644 index 00000000..cebedeb8 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/ResourceBundle-SwiftMessages_SwiftMessages-SwiftMessages-Info.plist @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>${PODS_DEVELOPMENT_LANGUAGE}</string> + <key>CFBundleIdentifier</key> + <string>${PRODUCT_BUNDLE_IDENTIFIER}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>10.0.1</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>NSPrincipalClass</key> + <string></string> +</dict> +</plist> diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist new file mode 100644 index 00000000..cad5ca66 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-Info.plist @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>${PODS_DEVELOPMENT_LANGUAGE}</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>${PRODUCT_BUNDLE_IDENTIFIER}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>FMWK</string> + <key>CFBundleShortVersionString</key> + <string>10.0.1</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>${CURRENT_PROJECT_VERSION}</string> + <key>NSPrincipalClass</key> + <string></string> +</dict> +</plist> diff --git a/Demo/Pods/Target Support Files/SwiftMessages/SwiftMessages-dummy.m b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-dummy.m similarity index 100% rename from Demo/Pods/Target Support Files/SwiftMessages/SwiftMessages-dummy.m rename to iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-dummy.m diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-prefix.pch b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import <UIKit/UIKit.h> +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Demo/Pods/Target Support Files/SwiftMessages/SwiftMessages-umbrella.h b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-umbrella.h similarity index 53% rename from Demo/Pods/Target Support Files/SwiftMessages/SwiftMessages-umbrella.h rename to iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-umbrella.h index 7b316e52..9aa634f0 100644 --- a/Demo/Pods/Target Support Files/SwiftMessages/SwiftMessages-umbrella.h +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages-umbrella.h @@ -1,5 +1,13 @@ #ifdef __OBJC__ #import <UIKit/UIKit.h> +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif #endif diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.debug.xcconfig b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.debug.xcconfig new file mode 100644 index 00000000..bb609503 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.debug.xcconfig @@ -0,0 +1,17 @@ +APPLICATION_EXTENSION_API_ONLY = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 SWIFTMESSAGES_APP_EXTENSIONS=1 +LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_LDFLAGS = $(inherited) -framework "UIKit" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFTMESSAGES_APP_EXTENSIONS +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Demo/Pods/Target Support Files/SwiftMessages/SwiftMessages.modulemap b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.modulemap similarity index 100% rename from Demo/Pods/Target Support Files/SwiftMessages/SwiftMessages.modulemap rename to iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.modulemap diff --git a/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.release.xcconfig b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.release.xcconfig new file mode 100644 index 00000000..bb609503 --- /dev/null +++ b/iMessageDemo/Pods/Target Support Files/SwiftMessages/SwiftMessages.release.xcconfig @@ -0,0 +1,17 @@ +APPLICATION_EXTENSION_API_ONLY = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SwiftMessages +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 SWIFTMESSAGES_APP_EXTENSIONS=1 +LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_LDFLAGS = $(inherited) -framework "UIKit" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFTMESSAGES_APP_EXTENSIONS +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iMessageDemo/iMessageDemo.xcodeproj/project.pbxproj b/iMessageDemo/iMessageDemo.xcodeproj/project.pbxproj new file mode 100644 index 00000000..5ff095c6 --- /dev/null +++ b/iMessageDemo/iMessageDemo.xcodeproj/project.pbxproj @@ -0,0 +1,589 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 2272F1F521080DAE00AD190C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2272F1F421080DAE00AD190C /* AppDelegate.swift */; }; + 2272F21021080DD500AD190C /* MessagesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2272F20F21080DD500AD190C /* MessagesViewController.swift */; }; + 2272F21321080DD500AD190C /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2272F21121080DD500AD190C /* MainInterface.storyboard */; }; + 2272F21921080DD600AD190C /* iMessageExtensionDemo.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 2272F20A21080DD500AD190C /* iMessageExtensionDemo.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 2272F21F2108113F00AD190C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2272F21E2108113F00AD190C /* Main.storyboard */; }; + 2272F221210811BE00AD190C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2272F220210811BE00AD190C /* LaunchScreen.storyboard */; }; + 76D3135B88AA54ECC98CBD36 /* Pods_iMessageDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73DC8D5C3B1552230D960BF7 /* Pods_iMessageDemo.framework */; }; + F49106CE51DB9708982AF779 /* Pods_iMessageExtensionDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E1E18BC615CEA5704F4B5FB /* Pods_iMessageExtensionDemo.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 2272F21721080DD600AD190C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2272F1E921080DAE00AD190C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2272F20921080DD500AD190C; + remoteInfo = iMessageExtensionDemo; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 2272F21D21080DD600AD190C /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 2272F21921080DD600AD190C /* iMessageExtensionDemo.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; + 22FE4001211944040017303D /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 212D588BA5EE4E8BF07B02D8 /* Pods-iMessageExtensionDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iMessageExtensionDemo.release.xcconfig"; path = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.release.xcconfig"; sourceTree = "<group>"; }; + 21DDEA06F4193D7F35B70A53 /* Pods-iMessageDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iMessageDemo.release.xcconfig"; path = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.release.xcconfig"; sourceTree = "<group>"; }; + 2272F1F121080DAE00AD190C /* iMessageDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iMessageDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 2272F1F421080DAE00AD190C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; + 2272F20021080DB200AD190C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; + 2272F20A21080DD500AD190C /* iMessageExtensionDemo.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = iMessageExtensionDemo.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 2272F20C21080DD500AD190C /* Messages.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Messages.framework; path = System/Library/Frameworks/Messages.framework; sourceTree = SDKROOT; }; + 2272F20F21080DD500AD190C /* MessagesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagesViewController.swift; sourceTree = "<group>"; }; + 2272F21221080DD500AD190C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; }; + 2272F21621080DD600AD190C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; + 2272F21E2108113F00AD190C /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; }; + 2272F220210811BE00AD190C /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; }; + 4E1E18BC615CEA5704F4B5FB /* Pods_iMessageExtensionDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_iMessageExtensionDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 73DC8D5C3B1552230D960BF7 /* Pods_iMessageDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_iMessageDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 76B6E320915B554B5D628DFC /* Pods-iMessageDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iMessageDemo.debug.xcconfig"; path = "Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo.debug.xcconfig"; sourceTree = "<group>"; }; + EE094075BD5252DAD69071F9 /* Pods-iMessageExtensionDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iMessageExtensionDemo.debug.xcconfig"; path = "Target Support Files/Pods-iMessageExtensionDemo/Pods-iMessageExtensionDemo.debug.xcconfig"; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2272F1EE21080DAE00AD190C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 76D3135B88AA54ECC98CBD36 /* Pods_iMessageDemo.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2272F20721080DD500AD190C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F49106CE51DB9708982AF779 /* Pods_iMessageExtensionDemo.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2272F1E821080DAE00AD190C = { + isa = PBXGroup; + children = ( + 2272F1F321080DAE00AD190C /* iMessageDemo */, + 2272F20E21080DD500AD190C /* iMessageExtensionDemo */, + 2272F20B21080DD500AD190C /* Frameworks */, + 2272F1F221080DAE00AD190C /* Products */, + C99B3449FCA583CA3ECDC53C /* Pods */, + ); + sourceTree = "<group>"; + }; + 2272F1F221080DAE00AD190C /* Products */ = { + isa = PBXGroup; + children = ( + 2272F1F121080DAE00AD190C /* iMessageDemo.app */, + 2272F20A21080DD500AD190C /* iMessageExtensionDemo.appex */, + ); + name = Products; + sourceTree = "<group>"; + }; + 2272F1F321080DAE00AD190C /* iMessageDemo */ = { + isa = PBXGroup; + children = ( + 2272F1F421080DAE00AD190C /* AppDelegate.swift */, + 2272F20021080DB200AD190C /* Info.plist */, + 2272F21E2108113F00AD190C /* Main.storyboard */, + 2272F220210811BE00AD190C /* LaunchScreen.storyboard */, + ); + path = iMessageDemo; + sourceTree = "<group>"; + }; + 2272F20B21080DD500AD190C /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2272F20C21080DD500AD190C /* Messages.framework */, + 73DC8D5C3B1552230D960BF7 /* Pods_iMessageDemo.framework */, + 4E1E18BC615CEA5704F4B5FB /* Pods_iMessageExtensionDemo.framework */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + 2272F20E21080DD500AD190C /* iMessageExtensionDemo */ = { + isa = PBXGroup; + children = ( + 2272F21121080DD500AD190C /* MainInterface.storyboard */, + 2272F20F21080DD500AD190C /* MessagesViewController.swift */, + 2272F21621080DD600AD190C /* Info.plist */, + ); + path = iMessageExtensionDemo; + sourceTree = "<group>"; + }; + C99B3449FCA583CA3ECDC53C /* Pods */ = { + isa = PBXGroup; + children = ( + 76B6E320915B554B5D628DFC /* Pods-iMessageDemo.debug.xcconfig */, + 21DDEA06F4193D7F35B70A53 /* Pods-iMessageDemo.release.xcconfig */, + EE094075BD5252DAD69071F9 /* Pods-iMessageExtensionDemo.debug.xcconfig */, + 212D588BA5EE4E8BF07B02D8 /* Pods-iMessageExtensionDemo.release.xcconfig */, + ); + path = Pods; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2272F1F021080DAE00AD190C /* iMessageDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2272F20321080DB200AD190C /* Build configuration list for PBXNativeTarget "iMessageDemo" */; + buildPhases = ( + C9C10288A07806AC55B5E4B3 /* [CP] Check Pods Manifest.lock */, + 2272F1ED21080DAE00AD190C /* Sources */, + 2272F1EE21080DAE00AD190C /* Frameworks */, + 2272F1EF21080DAE00AD190C /* Resources */, + 2272F21D21080DD600AD190C /* Embed App Extensions */, + 22FE4001211944040017303D /* Embed Frameworks */, + 77C3B4728FB9FC385B4279B6 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 2272F21821080DD600AD190C /* PBXTargetDependency */, + ); + name = iMessageDemo; + productName = iMessageDemo; + productReference = 2272F1F121080DAE00AD190C /* iMessageDemo.app */; + productType = "com.apple.product-type.application"; + }; + 2272F20921080DD500AD190C /* iMessageExtensionDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2272F21A21080DD600AD190C /* Build configuration list for PBXNativeTarget "iMessageExtensionDemo" */; + buildPhases = ( + 7FD245EE0E3D4F436FEB306E /* [CP] Check Pods Manifest.lock */, + 2272F20621080DD500AD190C /* Sources */, + 2272F20721080DD500AD190C /* Frameworks */, + 2272F20821080DD500AD190C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = iMessageExtensionDemo; + productName = iMessageExtensionDemo; + productReference = 2272F20A21080DD500AD190C /* iMessageExtensionDemo.appex */; + productType = "com.apple.product-type.app-extension.messages"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2272F1E921080DAE00AD190C /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0940; + LastUpgradeCheck = 0940; + ORGANIZATIONNAME = it.swiftkick; + TargetAttributes = { + 2272F1F021080DAE00AD190C = { + CreatedOnToolsVersion = 9.4.1; + }; + 2272F20921080DD500AD190C = { + CreatedOnToolsVersion = 9.4.1; + }; + }; + }; + buildConfigurationList = 2272F1EC21080DAE00AD190C /* Build configuration list for PBXProject "iMessageDemo" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 2272F1E821080DAE00AD190C; + productRefGroup = 2272F1F221080DAE00AD190C /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2272F1F021080DAE00AD190C /* iMessageDemo */, + 2272F20921080DD500AD190C /* iMessageExtensionDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2272F1EF21080DAE00AD190C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2272F21F2108113F00AD190C /* Main.storyboard in Resources */, + 2272F221210811BE00AD190C /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2272F20821080DD500AD190C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2272F21321080DD500AD190C /* MainInterface.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 77C3B4728FB9FC385B4279B6 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-iMessageDemo/Pods-iMessageDemo-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 7FD245EE0E3D4F436FEB306E /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-iMessageExtensionDemo-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + C9C10288A07806AC55B5E4B3 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-iMessageDemo-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2272F1ED21080DAE00AD190C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2272F1F521080DAE00AD190C /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2272F20621080DD500AD190C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2272F21021080DD500AD190C /* MessagesViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 2272F21821080DD600AD190C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 2272F20921080DD500AD190C /* iMessageExtensionDemo */; + targetProxy = 2272F21721080DD600AD190C /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 2272F21121080DD500AD190C /* MainInterface.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 2272F21221080DD500AD190C /* Base */, + ); + name = MainInterface.storyboard; + sourceTree = "<group>"; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 2272F20121080DB200AD190C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_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; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 2272F20221080DB200AD190C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_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; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 2272F20421080DB200AD190C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 76B6E320915B554B5D628DFC /* Pods-iMessageDemo.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 38R82CD868; + INFOPLIST_FILE = iMessageDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.Demo.iMessageDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 2272F20521080DB200AD190C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 21DDEA06F4193D7F35B70A53 /* Pods-iMessageDemo.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 38R82CD868; + INFOPLIST_FILE = iMessageDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.Demo.iMessageDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 2272F21B21080DD600AD190C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EE094075BD5252DAD69071F9 /* Pods-iMessageExtensionDemo.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 38R82CD868; + INFOPLIST_FILE = iMessageExtensionDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.Demo.iMessageDemo.iMessageExtensionDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 2272F21C21080DD600AD190C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 212D588BA5EE4E8BF07B02D8 /* Pods-iMessageExtensionDemo.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 38R82CD868; + INFOPLIST_FILE = iMessageExtensionDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = it.swiftkick.Demo.iMessageDemo.iMessageExtensionDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2272F1EC21080DAE00AD190C /* Build configuration list for PBXProject "iMessageDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2272F20121080DB200AD190C /* Debug */, + 2272F20221080DB200AD190C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2272F20321080DB200AD190C /* Build configuration list for PBXNativeTarget "iMessageDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2272F20421080DB200AD190C /* Debug */, + 2272F20521080DB200AD190C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2272F21A21080DD600AD190C /* Build configuration list for PBXNativeTarget "iMessageExtensionDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2272F21B21080DD600AD190C /* Debug */, + 2272F21C21080DD600AD190C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 2272F1E921080DAE00AD190C /* Project object */; +} diff --git a/iMessageDemo/iMessageDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/iMessageDemo/iMessageDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..acd14a7a --- /dev/null +++ b/iMessageDemo/iMessageDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "group:../../SwiftMessages.xcodeproj"> + </FileRef> + <FileRef + location = "self:"> + </FileRef> +</Workspace> diff --git a/iMessageDemo/iMessageDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/iMessageDemo/iMessageDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/iMessageDemo/iMessageDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEDidComputeMac32BitWarning</key> + <true/> +</dict> +</plist> diff --git a/iMessageDemo/iMessageDemo.xcodeproj/xcshareddata/xcschemes/iMessageExtensionDemo.xcscheme b/iMessageDemo/iMessageDemo.xcodeproj/xcshareddata/xcschemes/iMessageExtensionDemo.xcscheme new file mode 100644 index 00000000..9a5cdf8c --- /dev/null +++ b/iMessageDemo/iMessageDemo.xcodeproj/xcshareddata/xcschemes/iMessageExtensionDemo.xcscheme @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "0940" + wasCreatedForAppExtension = "YES" + version = "2.0"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + <BuildActionEntries> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "2272F20921080DD500AD190C" + BuildableName = "iMessageExtensionDemo.appex" + BlueprintName = "iMessageExtensionDemo" + ReferencedContainer = "container:iMessageDemo.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "2272F1F021080DAE00AD190C" + BuildableName = "iMessageDemo.app" + BlueprintName = "iMessageDemo" + ReferencedContainer = "container:iMessageDemo.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + </BuildActionEntries> + </BuildAction> + <TestAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + shouldUseLaunchSchemeArgsEnv = "YES"> + <Testables> + </Testables> + <MacroExpansion> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "2272F20921080DD500AD190C" + BuildableName = "iMessageExtensionDemo.appex" + BlueprintName = "iMessageExtensionDemo" + ReferencedContainer = "container:iMessageDemo.xcodeproj"> + </BuildableReference> + </MacroExpansion> + <AdditionalOptions> + </AdditionalOptions> + </TestAction> + <LaunchAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "" + selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + debugServiceExtension = "internal" + allowLocationSimulation = "YES" + launchAutomaticallySubstyle = "2"> + <BuildableProductRunnable + runnableDebuggingMode = "0"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "2272F1F021080DAE00AD190C" + BuildableName = "iMessageDemo.app" + BlueprintName = "iMessageDemo" + ReferencedContainer = "container:iMessageDemo.xcodeproj"> + </BuildableReference> + </BuildableProductRunnable> + <AdditionalOptions> + </AdditionalOptions> + </LaunchAction> + <ProfileAction + buildConfiguration = "Release" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES" + launchAutomaticallySubstyle = "2"> + <BuildableProductRunnable + runnableDebuggingMode = "0"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "2272F1F021080DAE00AD190C" + BuildableName = "iMessageDemo.app" + BlueprintName = "iMessageDemo" + ReferencedContainer = "container:iMessageDemo.xcodeproj"> + </BuildableReference> + </BuildableProductRunnable> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Release" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/Demo/Demo.xcworkspace/contents.xcworkspacedata b/iMessageDemo/iMessageDemo.xcworkspace/contents.xcworkspacedata similarity index 78% rename from Demo/Demo.xcworkspace/contents.xcworkspacedata rename to iMessageDemo/iMessageDemo.xcworkspace/contents.xcworkspacedata index 1f140198..d69114e3 100644 --- a/Demo/Demo.xcworkspace/contents.xcworkspacedata +++ b/iMessageDemo/iMessageDemo.xcworkspace/contents.xcworkspacedata @@ -2,7 +2,7 @@ <Workspace version = "1.0"> <FileRef - location = "group:Demo.xcodeproj"> + location = "group:iMessageDemo.xcodeproj"> </FileRef> <FileRef location = "group:Pods/Pods.xcodeproj"> diff --git a/iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEDidComputeMac32BitWarning</key> + <true/> +</dict> +</plist> diff --git a/iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..08de0be8 --- /dev/null +++ b/iMessageDemo/iMessageDemo.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key> + <false/> +</dict> +</plist> diff --git a/iMessageDemo/iMessageDemo/AppDelegate.swift b/iMessageDemo/iMessageDemo/AppDelegate.swift new file mode 100644 index 00000000..dbf09531 --- /dev/null +++ b/iMessageDemo/iMessageDemo/AppDelegate.swift @@ -0,0 +1,15 @@ +// +// AppDelegate.swift +// iMessageDemo +// +// Created by Timothy Moose on 7/24/18. +// Copyright © 2018 it.swiftkick. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? +} + diff --git a/iMessageDemo/iMessageDemo/Info.plist b/iMessageDemo/iMessageDemo/Info.plist new file mode 100644 index 00000000..16be3b68 --- /dev/null +++ b/iMessageDemo/iMessageDemo/Info.plist @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>$(DEVELOPMENT_LANGUAGE)</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>LSRequiresIPhoneOS</key> + <true/> + <key>UILaunchStoryboardName</key> + <string>LaunchScreen</string> + <key>UIMainStoryboardFile</key> + <string>Main</string> + <key>UIRequiredDeviceCapabilities</key> + <array> + <string>armv7</string> + </array> + <key>UISupportedInterfaceOrientations</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> + <key>UISupportedInterfaceOrientations~ipad</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationPortraitUpsideDown</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> +</dict> +</plist> diff --git a/iMessageDemo/iMessageDemo/LaunchScreen.storyboard b/iMessageDemo/iMessageDemo/LaunchScreen.storyboard new file mode 100644 index 00000000..3c38c376 --- /dev/null +++ b/iMessageDemo/iMessageDemo/LaunchScreen.storyboard @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> + <device id="retina4_7" orientation="portrait"> + <adaptation id="fullscreen"/> + </device> + <dependencies> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/> + <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/> + <capability name="Safe area layout guides" minToolsVersion="9.0"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> + </dependencies> + <scenes> + <!--View Controller--> + <scene sceneID="EHf-IW-A2E"> + <objects> + <viewController id="01J-lp-oVM" sceneMemberID="viewController"> + <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="obG-Y5-kRd"> + <rect key="frame" x="30" y="606" width="315" height="41"/> + <string key="text">Copyright © 2018 it.swiftkick +All rights reserved.</string> + <fontDescription key="fontDescription" type="system" pointSize="17"/> + <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <nil key="highlightedColor"/> + </label> + <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="iMessageDemo" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb"> + <rect key="frame" x="0.0" y="202" width="375" height="43"/> + <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/> + <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <nil key="highlightedColor"/> + </label> + </subviews> + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <constraints> + <constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="obG-Y5-kRd" secondAttribute="centerX" id="5cz-MP-9tL"/> + <constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="GJd-Yh-RWb" secondAttribute="centerX" id="Q3B-4B-g5h"/> + <constraint firstItem="obG-Y5-kRd" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" constant="30" id="SfN-ll-jLj"/> + <constraint firstAttribute="bottom" secondItem="obG-Y5-kRd" secondAttribute="bottom" constant="20" id="Y44-ml-fuU"/> + <constraint firstItem="GJd-Yh-RWb" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="1/3" constant="1" id="moa-c2-u7t"/> + <constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" constant="20" symbolic="YES" id="x7j-FC-K8j"/> + </constraints> + <viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/> + </view> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="53" y="375"/> + </scene> + </scenes> +</document> diff --git a/iMessageDemo/iMessageDemo/Main.storyboard b/iMessageDemo/iMessageDemo/Main.storyboard new file mode 100644 index 00000000..36731d41 --- /dev/null +++ b/iMessageDemo/iMessageDemo/Main.storyboard @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="zZj-3H-hcB"> + <device id="retina4_7" orientation="portrait"> + <adaptation id="fullscreen"/> + </device> + <dependencies> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/> + <capability name="Safe area layout guides" minToolsVersion="9.0"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> + </dependencies> + <scenes> + <!--View Controller--> + <scene sceneID="3Nc-P1-eQ3"> + <objects> + <viewController id="zZj-3H-hcB" sceneMemberID="viewController"> + <view key="view" contentMode="scaleToFill" id="PbU-Gb-nkc"> + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="This app is for testing SwiftMessages built for iMessage extensions. Run the iMessageExtensionDemo target." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="KJc-2q-VVl"> + <rect key="frame" x="30" y="303" width="315" height="61"/> + <fontDescription key="fontDescription" type="system" pointSize="17"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + </subviews> + <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + <constraints> + <constraint firstItem="KJc-2q-VVl" firstAttribute="centerY" secondItem="PbU-Gb-nkc" secondAttribute="centerY" id="HZG-sD-ICp"/> + <constraint firstItem="KJc-2q-VVl" firstAttribute="leading" secondItem="xhg-mc-eEY" secondAttribute="leading" constant="30" id="PCq-J0-T1A"/> + <constraint firstItem="xhg-mc-eEY" firstAttribute="trailing" secondItem="KJc-2q-VVl" secondAttribute="trailing" constant="30" id="lEm-Vd-IE8"/> + </constraints> + <viewLayoutGuide key="safeArea" id="xhg-mc-eEY"/> + </view> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="x0r-iX-g1P" userLabel="First Responder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="154" y="162"/> + </scene> + </scenes> +</document> diff --git a/iMessageDemo/iMessageExtensionDemo/Base.lproj/MainInterface.storyboard b/iMessageDemo/iMessageExtensionDemo/Base.lproj/MainInterface.storyboard new file mode 100644 index 00000000..b3ce9d7c --- /dev/null +++ b/iMessageDemo/iMessageExtensionDemo/Base.lproj/MainInterface.storyboard @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ObA-dk-sSI"> + <device id="retina4_7" orientation="portrait"> + <adaptation id="fullscreen"/> + </device> + <dependencies> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/> + <capability name="Safe area layout guides" minToolsVersion="9.0"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> + </dependencies> + <scenes> + <!--Messages View Controller--> + <scene sceneID="7MM-of-jgj"> + <objects> + <viewController id="ObA-dk-sSI" customClass="MessagesViewController" customModule="iMessageDemo" customModuleProvider="target" sceneMemberID="viewController"> + <view key="view" contentMode="scaleToFill" id="zMn-AG-sqS"> + <rect key="frame" x="0.0" y="0.0" width="320" height="528"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="pjb-TD-WZf"> + <rect key="frame" x="132.5" y="242" width="55" height="44"/> + <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + <constraints> + <constraint firstAttribute="height" constant="44" id="zlU-jj-d5D"/> + </constraints> + <inset key="contentEdgeInsets" minX="10" minY="0.0" maxX="10" maxY="0.0"/> + <state key="normal" title="Test"/> + <connections> + <action selector="buttonTapped" destination="ObA-dk-sSI" eventType="touchUpInside" id="W8K-oF-WAU"/> + </connections> + </button> + </subviews> + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <constraints> + <constraint firstItem="pjb-TD-WZf" firstAttribute="centerY" secondItem="zMn-AG-sqS" secondAttribute="centerY" id="VJC-Go-emt"/> + <constraint firstItem="pjb-TD-WZf" firstAttribute="centerX" secondItem="zMn-AG-sqS" secondAttribute="centerX" id="pa5-MH-D6S"/> + </constraints> + <viewLayoutGuide key="safeArea" id="LDy-ih-0nr"/> + </view> + <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> + <size key="freeformSize" width="320" height="528"/> + <connections> + <outlet property="button" destination="pjb-TD-WZf" id="6xJ-Ph-fBt"/> + </connections> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="X47-rx-isc" userLabel="First Responder" sceneMemberID="firstResponder"/> + </objects> + </scene> + </scenes> +</document> diff --git a/iMessageDemo/iMessageExtensionDemo/Info.plist b/iMessageDemo/iMessageExtensionDemo/Info.plist new file mode 100644 index 00000000..2c1114de --- /dev/null +++ b/iMessageDemo/iMessageExtensionDemo/Info.plist @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>$(DEVELOPMENT_LANGUAGE)</string> + <key>CFBundleDisplayName</key> + <string>iMessageExtensionDemo</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>XPC!</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>NSExtension</key> + <dict> + <key>NSExtensionMainStoryboard</key> + <string>MainInterface</string> + <key>NSExtensionPointIdentifier</key> + <string>com.apple.message-payload-provider</string> + </dict> +</dict> +</plist> diff --git a/iMessageDemo/iMessageExtensionDemo/MessagesViewController.swift b/iMessageDemo/iMessageExtensionDemo/MessagesViewController.swift new file mode 100644 index 00000000..c71afe17 --- /dev/null +++ b/iMessageDemo/iMessageExtensionDemo/MessagesViewController.swift @@ -0,0 +1,35 @@ +// +// MessagesViewController.swift +// iMessageDemo +// +// Created by Timothy Moose on 5/25/18. +// Copyright © 2018 SwiftKick Mobile. All rights reserved. +// + +import UIKit +import Messages +import SwiftMessages + +class MessagesViewController: MSMessagesAppViewController { + + @IBOutlet weak var button: UIButton! { + didSet { + button.layer.cornerRadius = 5 + } + } + + @IBAction func buttonTapped() { + let messageView: MessageView = MessageView.viewFromNib(layout: .centeredView) + messageView.configureContent(title: "Test", body: "Yep, it works!") + messageView.button?.isHidden = true + messageView.iconLabel?.isHidden = true + messageView.iconImageView?.isHidden = true + messageView.configureTheme(backgroundColor: .black, foregroundColor: .white) + messageView.configureDropShadow() + messageView.configureBackgroundView(width: 200) + var config = SwiftMessages.defaultConfig + config.presentationStyle = .center + config.presentationContext = .viewController(self) + SwiftMessages.show(config: config, view: messageView) + } +}