Skip to content

Commit

Permalink
Allow customizing the order of views and the image size (#52)
Browse files Browse the repository at this point in the history
* Allow customizing the order of views and the image size

* Fix tests
  • Loading branch information
AvdLee authored Feb 19, 2021
1 parent 4dae6cf commit 7a20be9
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 33 deletions.
3 changes: 3 additions & 0 deletions Sources/UINotification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public protocol UINotificationStyle {

/// The chevron image which is shown when a notification has an action attached.
var chevronImage: UIImage? { get }

/// The size to use for the thumbnail view.
var thumbnailSize: CGSize { get }
}

/// Handles changes in UINotification
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public struct UINotificationSystemStyle: UINotificationStyle {
public var maxWidth: CGFloat?
public var interactive: Bool = true
public var chevronImage: UIImage?
public var thumbnailSize: CGSize = .init(width: 31, height: 31)

public init() { }
}
21 changes: 17 additions & 4 deletions Sources/UINotificationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ open class UINotificationView: UIView {
/// Will be set by the presenter. Is used to animate the notification view with a pan gesture.
var topConstraint: NSLayoutConstraint?

var imageViewWidthConstraint: NSLayoutConstraint?
var imageViewHeightConstraint: NSLayoutConstraint?

/// The limit of translation before we will dismiss the notification.
internal let translationDismissLimit: CGFloat = -15

Expand All @@ -36,8 +39,13 @@ open class UINotificationView: UIView {
return stackView
}()

/// Override this to change the order of subviews. For example, to show the subtitle above the title.
open var arrangedSubviews: [UIView] {
return [self.titleLabel, self.subtitleLabel]
}

open private(set) lazy var titlesStackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [self.titleLabel, self.subtitleLabel])
let stackView = UIStackView(arrangedSubviews: arrangedSubviews)
stackView.axis = .vertical
stackView.spacing = 0
stackView.translatesAutoresizingMaskIntoConstraints = false
Expand Down Expand Up @@ -110,7 +118,7 @@ open class UINotificationView: UIView {
translatesAutoresizingMaskIntoConstraints = false
isUserInteractionEnabled = true

layoutMargins = UIEdgeInsets(top: 4, left: 0, bottom: 4, right: 0)
layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)

addArrangedSubviewsForContainerStackView()
addSubview(containerStackView)
Expand All @@ -132,6 +140,8 @@ open class UINotificationView: UIView {

imageView.image = notification.content.image
imageView.isHidden = notification.content.image == nil
imageViewWidthConstraint?.constant = notification.style.thumbnailSize.width
imageViewHeightConstraint?.constant = notification.style.thumbnailSize.height

backgroundColor = notification.style.backgroundColor

Expand All @@ -154,6 +164,9 @@ open class UINotificationView: UIView {
/// Called when all constraints should be setup for the notification. Can be overwritten to set your own constraints.
/// When setting your own constraints, you should not be calling super.
open func setupConstraints() {
imageViewWidthConstraint = imageView.widthAnchor.constraint(equalToConstant: 31)
imageViewHeightConstraint = imageView.heightAnchor.constraint(equalToConstant: 31)

let constraints = [
containerStackView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 18),
containerStackView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: -18),
Expand All @@ -162,8 +175,8 @@ open class UINotificationView: UIView {

chevronImageView.widthAnchor.constraint(equalToConstant: chevronImageView.image?.size.width ?? 0),

imageView.widthAnchor.constraint(equalToConstant: 31),
imageView.heightAnchor.constraint(equalToConstant: 31)
imageViewWidthConstraint!,
imageViewHeightConstraint!
]

button?.setContentHuggingPriority(.defaultHigh, for: .horizontal)
Expand Down
17 changes: 10 additions & 7 deletions UINotifications.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1010;
LastUpgradeCheck = 1230;
ORGANIZATIONNAME = WeTransfer;
TargetAttributes = {
502C139F206E5F230082CE37 = {
Expand Down Expand Up @@ -400,6 +400,7 @@
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;
Expand All @@ -426,7 +427,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
Expand Down Expand Up @@ -462,6 +463,7 @@
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;
Expand All @@ -482,7 +484,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
Expand All @@ -504,7 +506,7 @@
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = UINotifications/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.wetransfer.UINotifications;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
Expand All @@ -526,7 +528,7 @@
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = UINotifications/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.wetransfer.UINotifications;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
Expand Down Expand Up @@ -594,6 +596,7 @@
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;
Expand All @@ -620,7 +623,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
Expand All @@ -643,7 +646,7 @@
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = UINotifications/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.wetransfer.UINotifications;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
Expand Down
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1230"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand All @@ -26,8 +26,17 @@
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
codeCoverageEnabled = "YES"
shouldUseLaunchSchemeArgsEnv = "YES">
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "502C139F206E5F230082CE37"
BuildableName = "UINotifications.framework"
BlueprintName = "UINotifications"
ReferencedContainer = "container:UINotifications.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
Expand All @@ -41,17 +50,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "502C139F206E5F230082CE37"
BuildableName = "UINotifications.framework"
BlueprintName = "UINotifications"
ReferencedContainer = "container:UINotifications.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand All @@ -72,8 +70,6 @@
ReferencedContainer = "container:UINotifications.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1230"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand All @@ -23,8 +23,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand All @@ -36,8 +34,6 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
17 changes: 16 additions & 1 deletion UINotificationsTests/UINotificationDefaultElementsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import XCTest
final class UINotificationDefaultElementsTests: UINotificationTestCase {

struct CustomStyle: UINotificationStyle {
var thumbnailSize: CGSize
var titleFont: UIFont = UIFont.systemFont(ofSize: 13, weight: .semibold)
var subtitleFont: UIFont = UIFont.systemFont(ofSize: 13, weight: .semibold)
var titleTextColor: UIColor = UIColor.black
Expand All @@ -27,9 +28,10 @@ final class UINotificationDefaultElementsTests: UINotificationTestCase {
let customHeight: CGFloat?
let maxWidth: CGFloat?

init(customHeight: CGFloat? = nil, maxWidth: CGFloat? = nil) {
init(customHeight: CGFloat? = nil, maxWidth: CGFloat? = nil, thumbnailSize: CGSize = CGSize(width: 20, height: 20)) {
self.customHeight = customHeight
self.maxWidth = maxWidth
self.thumbnailSize = thumbnailSize
}
}

Expand Down Expand Up @@ -76,6 +78,19 @@ final class UINotificationDefaultElementsTests: UINotificationTestCase {

waitFor(notificationCenter.currentPresenter?.presentationContext.notificationView.frame.size.height == customHeight, timeout: 5.0, description: "Custom height should be applied to the view")
}

/// When passing a notification style with a custom thumbnail size, this should be applied to the presented view.
func testCustomNotificationThumbnailSize() {
let notificationCenter = UINotificationCenter()
notificationCenter.isDuplicateQueueingAllowed = true
notificationCenter.presenterType = MockPresenter.self
let customSize = CGSize(width: 25, height: 25)
let notification = UINotification(content: UINotificationContent(title: "test"), style: CustomStyle(thumbnailSize: customSize))

notificationCenter.show(notification: notification)

waitFor(notificationCenter.currentPresenter?.presentationContext.notificationView.imageView.frame.size == customSize, timeout: 5.0, description: "Custom height should be applied to the view")
}

/// When passing a notification style with a max width, this should be applied to the presented view.
func testNotificationViewMaxWidth() {
Expand Down
1 change: 1 addition & 0 deletions UINotificationsTests/UINotificationDefaultViewTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ final class UINotificationViewTests: UINotificationTestCase {
}

private struct LargeChevronStyle: UINotificationStyle {
var thumbnailSize: CGSize = CGSize(width: 20, height: 20)
var titleFont: UIFont = UIFont.systemFont(ofSize: 13, weight: .semibold)
var subtitleFont: UIFont = UIFont.systemFont(ofSize: 13, weight: .semibold)
var titleTextColor: UIColor = UIColor.black
Expand Down

0 comments on commit 7a20be9

Please sign in to comment.