From bfdb53d6cd49d07b28fb5560d6aae36580229ebc Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Fri, 14 Feb 2014 22:29:20 +0100 Subject: [PATCH 01/27] Improve callbacks by passing the view as a parameter This way one can directly call the `fadeMeOut` method on the actual view instead of having to call `[TSMessage dismissActiveNotification]` (which would be necessary if you want to dismiss the view programmatically in the callback, because you have disabled manual dismiss via `canBeDismissedByUser:NO`). I find it better to deal with the actual instance of the view rather than relying on it being the currently active notification. Right now it is only possible for it being the currently active notification, but these changes will make sense in conjunction with the next changes I'd like to propose in the next commits. ;) --- ExampleProject/Example/TSDemoViewController.m | 2 +- TSMessages/Classes/TSMessage.h | 5 +++-- TSMessages/Classes/TSMessage.m | 4 ++-- TSMessages/Views/TSMessageView.h | 4 ++-- TSMessages/Views/TSMessageView.m | 12 ++++++------ 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/ExampleProject/Example/TSDemoViewController.m b/ExampleProject/Example/TSDemoViewController.m index 3f30ef05..928232d5 100644 --- a/ExampleProject/Example/TSDemoViewController.m +++ b/ExampleProject/Example/TSDemoViewController.m @@ -60,7 +60,7 @@ - (IBAction)didTapButton:(id)sender duration:TSMessageNotificationDurationAutomatic callback:nil buttonTitle:NSLocalizedString(@"Update", nil) - buttonCallback:^{ + buttonCallback:^(TSMessageView *messageView){ [TSMessage showNotificationWithTitle:NSLocalizedString(@"Thanks for updating", nil) type:TSMessageNotificationTypeSuccess]; } diff --git a/TSMessages/Classes/TSMessage.h b/TSMessages/Classes/TSMessage.h index 4156f5d0..bf194ea6 100755 --- a/TSMessages/Classes/TSMessage.h +++ b/TSMessages/Classes/TSMessage.h @@ -48,6 +48,7 @@ typedef NS_ENUM(NSInteger,TSMessageNotificationDuration) { TSMessageNotificationDurationEndless = -1 // The notification is displayed until the user dismissed it or it is dismissed by calling dismissActiveNotification }; +typedef void (^TSMessageCallback)(TSMessageView *messageView); @interface TSMessage : NSObject @@ -102,9 +103,9 @@ typedef NS_ENUM(NSInteger,TSMessageNotificationDuration) { image:(UIImage *)image type:(TSMessageNotificationType)type duration:(NSTimeInterval)duration - callback:(void (^)())callback + callback:(TSMessageCallback)callback buttonTitle:(NSString *)buttonTitle - buttonCallback:(void (^)())buttonCallback + buttonCallback:(TSMessageCallback)buttonCallback atPosition:(TSMessageNotificationPosition)messagePosition canBeDismissedByUser:(BOOL)dismissingEnabled; diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index 5fbb149e..b5319730 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -90,9 +90,9 @@ + (void)showNotificationInViewController:(UIViewController *)viewController image:(UIImage *)image type:(TSMessageNotificationType)type duration:(NSTimeInterval)duration - callback:(void (^)())callback + callback:(TSMessageCallback)callback buttonTitle:(NSString *)buttonTitle - buttonCallback:(void (^)())buttonCallback + buttonCallback:(TSMessageCallback)buttonCallback atPosition:(TSMessageNotificationPosition)messagePosition canBeDismissedByUser:(BOOL)dismissingEnabled { diff --git a/TSMessages/Views/TSMessageView.h b/TSMessages/Views/TSMessageView.h index b52cf221..10132bd8 100755 --- a/TSMessages/Views/TSMessageView.h +++ b/TSMessages/Views/TSMessageView.h @@ -64,9 +64,9 @@ type:(TSMessageNotificationType)notificationType duration:(CGFloat)duration inViewController:(UIViewController *)viewController - callback:(void (^)())callback + callback:(TSMessageCallback)callback buttonTitle:(NSString *)buttonTitle - buttonCallback:(void (^)())buttonCallback + buttonCallback:(TSMessageCallback)buttonCallback atPosition:(TSMessageNotificationPosition)position canBeDismissedByUser:(BOOL)dismissingEnabled; diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index 00177ed0..acc1ff06 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -50,8 +50,8 @@ @interface TSMessageView () @property (nonatomic, assign) CGFloat textSpaceLeft; @property (nonatomic, assign) CGFloat textSpaceRight; -@property (copy) void (^callback)(); -@property (copy) void (^buttonCallback)(); +@property (copy) TSMessageCallback callback; +@property (copy) TSMessageCallback buttonCallback; - (CGFloat)updateHeightOfMessageView; - (void)layoutSubviews; @@ -91,9 +91,9 @@ - (id)initWithTitle:(NSString *)title type:(TSMessageNotificationType)notificationType duration:(CGFloat)duration inViewController:(UIViewController *)viewController - callback:(void (^)())callback + callback:(TSMessageCallback)callback buttonTitle:(NSString *)buttonTitle - buttonCallback:(void (^)())buttonCallback + buttonCallback:(TSMessageCallback)buttonCallback atPosition:(TSMessageNotificationPosition)position canBeDismissedByUser:(BOOL)dismissingEnabled { @@ -466,7 +466,7 @@ - (void)buttonTapped:(id) sender { if (self.buttonCallback) { - self.buttonCallback(); + self.buttonCallback(self); } [self fadeMeOut]; @@ -478,7 +478,7 @@ - (void)handleTap:(UITapGestureRecognizer *)tapGesture { if (self.callback) { - self.callback(); + self.callback(self); } } } From c7b036307f458e195123166c1f95e9a62c29a475 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Fri, 14 Feb 2014 23:52:15 +0100 Subject: [PATCH 02/27] Add permanent messages Permanent notifications differ from normal ones in that permanent messages are not contained in the messages queue and can be displayed in addition to the other messages. Permanent notifications do not get dismissed automatically, hence they do not have a duration but have to be dismissed by the user or programmatically in one of the callbacks. The constructor for a permanent message also returns the instance of the message view, so that one can also capture it and dismiss it with other custom events. --- .../Pods/Pods.xcodeproj/project.pbxproj | 2362 +++++------------ TSMessages/Classes/TSMessage+Private.h | 18 + TSMessages/Classes/TSMessage.h | 38 +- TSMessages/Classes/TSMessage.m | 211 +- TSMessages/Views/TSMessageView.m | 11 +- 5 files changed, 879 insertions(+), 1761 deletions(-) create mode 100644 TSMessages/Classes/TSMessage+Private.h diff --git a/ExampleProject/Pods/Pods.xcodeproj/project.pbxproj b/ExampleProject/Pods/Pods.xcodeproj/project.pbxproj index 79638ebf..804cee70 100644 --- a/ExampleProject/Pods/Pods.xcodeproj/project.pbxproj +++ b/ExampleProject/Pods/Pods.xcodeproj/project.pbxproj @@ -1,1675 +1,687 @@ - - - - - archiveVersion - 1 - classes - - objectVersion - 46 - objects - - 008FCB1214A547FABF2ACE78 - - baseConfigurationReference - 08ED9A1527024644ADCBA9CD - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - GCC_VERSION - com.apple.compilers.llvm.clang.1_0 - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 5.1 - OTHER_LDFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - 0664DAB085284272A58FA5C1 - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundMessage.png - path - TSMessages/Resources/Images/NotificationBackgroundMessage.png - sourceTree - <group> - - 07359EA6F65641E7B1FA9119 - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundWarningIcon@2x.png - path - TSMessages/Resources/Images/NotificationBackgroundWarningIcon@2x.png - sourceTree - <group> - - 08DC72AB9F3D4F8A8B67ECB5 - - isa - PBXTargetDependency - target - E7AEDF3C45F849A8B4358B09 - targetProxy - E7F054B132B240E3BCC9A26E - - 08ED9A1527024644ADCBA9CD - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods.xcconfig - sourceTree - <group> - - 09E89CC7D8724A98B872DF42 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - TSMessage.m - path - TSMessages/Classes/TSMessage.m - sourceTree - <group> - - 0AF065F777E848F29746E2F6 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - HexColor.h - path - Classes/HexColor.h - sourceTree - <group> - - 0C3AF44C9B9D401A981B09FD - - children - - 219C6D4DAB0E422DBFD10D53 - D52EEB5E95A5449CB60B0762 - 616DE37D6F1B45CC935B46AC - - isa - PBXGroup - name - HexColors - path - HexColors - sourceTree - <group> - - 12C3F91EE0224C298A362BF0 - - baseConfigurationReference - EB62E0597B194FE5A930E405 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Pods-HexColors-prefix.pch - GCC_VERSION - com.apple.compilers.llvm.clang.1_0 - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 5.1 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 135D534C82F94C44AF0289B6 - - buildActionMask - 2147483647 - files - - 430D5356AE65432AAF3A6519 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 13D06846069C48AA81FDBCA0 - - buildActionMask - 2147483647 - files - - 850DFF742B9443539B374637 - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 1879866D15D84BC5B4A108BA - - containerPortal - C35E0B354E5646DEAFE4B4FA - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 68B61584912B40AD8DB67427 - remoteInfo - Pods-TSMessages - - 1B314248BB734734ADC43083 - - fileRef - 5ED86E633260493EA1A2F499 - isa - PBXBuildFile - - 219C6D4DAB0E422DBFD10D53 - - children - - 75B471412A9147839B6A56D1 - - isa - PBXGroup - name - Products - sourceTree - <group> - - 231C8250C74C4AFB9E3469E5 - - buildConfigurationList - C153462D0780424C997F2D88 - buildPhases - - 4A33B9F733C04F85AC86FD5B - EB2450E8D1A647E290A31F05 - - buildRules - - dependencies - - 08DC72AB9F3D4F8A8B67ECB5 - CC58D3CE77FE488681CFF19F - - isa - PBXNativeTarget - name - Pods - productName - Pods - productReference - 87EB580E368F4E6CB33840A8 - productType - com.apple.product-type.library.static - - 24F689F22A5A42809DBA68A7 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - TSBlurView.m - path - TSMessages/Views/TSBlurView.m - sourceTree - <group> - - 26254BFC82E04500BF05E57B - - buildSettings - - IPHONEOS_DEPLOYMENT_TARGET - 5.1 - ONLY_ACTIVE_ARCH - YES - STRIP_INSTALLED_PRODUCT - NO - - isa - XCBuildConfiguration - name - Debug - - 2686CD3D628D49B8AD706E91 - - fileRef - 24F689F22A5A42809DBA68A7 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 29BDFA547266427AA426611F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.script.sh - path - Pods-resources.sh - sourceTree - <group> - - 3A68D0F35A2448709D775945 - - children - - 3B17E30CA6F248738B1CCE1F - E6F8608730F84A098DEB8A05 - 53202C8D4E6B4B018F7C74D6 - 24F689F22A5A42809DBA68A7 - 09E89CC7D8724A98B872DF42 - BEBBB8EDFAD74B189406A0B0 - - isa - PBXGroup - name - Source Files - sourceTree - <group> - - 3B17E30CA6F248738B1CCE1F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - TSBlurView.h - path - TSMessages/Views/TSBlurView.h - sourceTree - <group> - - 3D0DACDDAAB94F4DA8202A8F - - baseConfigurationReference - EB62E0597B194FE5A930E405 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Pods-HexColors-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - GCC_VERSION - com.apple.compilers.llvm.clang.1_0 - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 5.1 - OTHER_LDFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - 3DED0B6E248A4FBEB11DFB7D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-HexColors-prefix.pch - sourceTree - <group> - - 3EEBBA57508D41E99C45BA64 - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationButtonBackground@2x.png - path - TSMessages/Resources/Images/NotificationButtonBackground@2x.png - sourceTree - <group> - - 3FFBF8A4E845423A93DE50A6 - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundWarningIcon.png - path - TSMessages/Resources/Images/NotificationBackgroundWarningIcon.png - sourceTree - <group> - - 41F15AC86CD44FEEA58FC25A - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundError.png - path - TSMessages/Resources/Images/NotificationBackgroundError.png - sourceTree - <group> - - 430D5356AE65432AAF3A6519 - - fileRef - 7150BC66A9C84380B009DD48 - isa - PBXBuildFile - - 45CF47DADDF14BDBAA87ED67 - - fileRef - 899217DAF97C4C3F9BAE6861 - isa - PBXBuildFile - - 48F158896D204969B78EF9EE - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-HexColors.xcconfig - sourceTree - <group> - - 492C1D29D48B4EB38856AC3E - - children - - C49A102233D542D7BC33EA02 - CE97B018E4C2414A9A5C3FAB - A68C68D28A4A4CE5A2765112 - CCA854EFD62D4F43B92AB2F6 - - isa - PBXGroup - name - Support Files - sourceTree - SOURCE_ROOT - - 4A33B9F733C04F85AC86FD5B - - buildActionMask - 2147483647 - files - - 45CF47DADDF14BDBAA87ED67 - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 4EC9FB627F934E5B8D11BC28 - - fileRef - 7150BC66A9C84380B009DD48 - isa - PBXBuildFile - - 513393A64B2C4D5F98177A07 - - buildActionMask - 2147483647 - files - - 97F0EDB908074C5F96389171 - 7FC0316E0D3A474DAE207938 - B860D15F4D8947D18C6CA21F - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 5223B9E5408A4BB7AB5AC3FA - - buildConfigurations - - 3D0DACDDAAB94F4DA8202A8F - 12C3F91EE0224C298A362BF0 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 53202C8D4E6B4B018F7C74D6 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - TSMessageView.h - path - TSMessages/Views/TSMessageView.h - sourceTree - <group> - - 544743058F5540DA887032D5 - - fileRef - 09E89CC7D8724A98B872DF42 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 560E3253C75441BFAC032222 - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundSuccessIcon.png - path - TSMessages/Resources/Images/NotificationBackgroundSuccessIcon.png - sourceTree - <group> - - 5867460F45EE48B7BCBF246E - - baseConfigurationReference - CCA854EFD62D4F43B92AB2F6 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Pods-TSMessages-prefix.pch - GCC_VERSION - com.apple.compilers.llvm.clang.1_0 - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 5.1 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 5ED86E633260493EA1A2F499 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - HexColor.m - path - Classes/HexColor.m - sourceTree - <group> - - 616DE37D6F1B45CC935B46AC - - children - - 618EA4400E7548A38F36A30A - 3DED0B6E248A4FBEB11DFB7D - 48F158896D204969B78EF9EE - EB62E0597B194FE5A930E405 - - isa - PBXGroup - name - Support Files - sourceTree - SOURCE_ROOT - - 618EA4400E7548A38F36A30A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-HexColors-dummy.m - sourceTree - <group> - - 63CAD95C55E041EEAD195B89 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-TSMessages.a - sourceTree - BUILT_PRODUCTS_DIR - - 64FAFE92EB6D4225BEC33044 - - buildConfigurations - - 7B220166450A440C843BD8DF - 5867460F45EE48B7BCBF246E - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 684D99C3E370489080DFAD7C - - children - - 63CAD95C55E041EEAD195B89 - - isa - PBXGroup - name - Products - sourceTree - <group> - - 68B61584912B40AD8DB67427 - - buildConfigurationList - 64FAFE92EB6D4225BEC33044 - buildPhases - - 6D1EB0FB25E44FBAB7DBE383 - 135D534C82F94C44AF0289B6 - 513393A64B2C4D5F98177A07 - - buildRules - - dependencies - - E5B62395E5324C6A91FA3B02 - - isa - PBXNativeTarget - name - Pods-TSMessages - productName - Pods-TSMessages - productReference - 63CAD95C55E041EEAD195B89 - productType - com.apple.product-type.library.static - - 69503BF241F446369D378606 - - children - - 7150BC66A9C84380B009DD48 - - isa - PBXGroup - name - Frameworks - sourceTree - <group> - - 6B01F6793B184344B82979BC - - fileRef - BEBBB8EDFAD74B189406A0B0 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 6B0361DEF3DD4CEDB3E81214 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-environment.h - sourceTree - <group> - - 6D1EB0FB25E44FBAB7DBE383 - - buildActionMask - 2147483647 - files - - C2E8986407F543A9B622B1D2 - 2686CD3D628D49B8AD706E91 - 544743058F5540DA887032D5 - 6B01F6793B184344B82979BC - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 7048A9DCF66E435485B109D8 - - containerPortal - C35E0B354E5646DEAFE4B4FA - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - E7AEDF3C45F849A8B4358B09 - remoteInfo - Pods-HexColors - - 7150BC66A9C84380B009DD48 - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - Foundation.framework - path - System/Library/Frameworks/Foundation.framework - sourceTree - SDKROOT - - 75B471412A9147839B6A56D1 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-HexColors.a - sourceTree - BUILT_PRODUCTS_DIR - - 7B220166450A440C843BD8DF - - baseConfigurationReference - CCA854EFD62D4F43B92AB2F6 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Pods-TSMessages-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - GCC_VERSION - com.apple.compilers.llvm.clang.1_0 - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 5.1 - OTHER_LDFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - 7C69054C69EB4A928CD7B5E5 - - fileRef - 618EA4400E7548A38F36A30A - isa - PBXBuildFile - - 7FC0316E0D3A474DAE207938 - - fileRef - E6F8608730F84A098DEB8A05 - isa - PBXBuildFile - - 850DFF742B9443539B374637 - - fileRef - 0AF065F777E848F29746E2F6 - isa - PBXBuildFile - - 87EB580E368F4E6CB33840A8 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods.a - sourceTree - BUILT_PRODUCTS_DIR - - 899217DAF97C4C3F9BAE6861 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-dummy.m - sourceTree - <group> - - 8A93E30DB3AC40E99B0E1A12 - - children - - 6B0361DEF3DD4CEDB3E81214 - 899217DAF97C4C3F9BAE6861 - CC5BD63FA0E64476B6D096E2 - D00A0431231A400AA0A4F3B2 - 29BDFA547266427AA426611F - 08ED9A1527024644ADCBA9CD - - isa - PBXGroup - name - Pods - sourceTree - <group> - - 8D9C3A3F98A44F99B303AB91 - - children - - E97E54CD959C4B56927F6158 - - isa - PBXGroup - name - Development Pods - sourceTree - <group> - - 95AC99116638428092659625 - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationButtonBackground.png - path - TSMessages/Resources/Images/NotificationButtonBackground.png - sourceTree - <group> - - 9633151B14DB45819E79B2B4 - - fileRef - 75B471412A9147839B6A56D1 - isa - PBXBuildFile - - 97F0EDB908074C5F96389171 - - fileRef - 3B17E30CA6F248738B1CCE1F - isa - PBXBuildFile - - 99E8DD8063B34CB9927C685C - - baseConfigurationReference - 08ED9A1527024644ADCBA9CD - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_VERSION - com.apple.compilers.llvm.clang.1_0 - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 5.1 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - A08DC63CAC864D67BB5EF8D0 - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundWarning.png - path - TSMessages/Resources/Images/NotificationBackgroundWarning.png - sourceTree - <group> - - A1A1D99C3C214E88A19D1243 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text - name - Podfile - path - ../Podfile - sourceTree - SOURCE_ROOT - xcLanguageSpecificationIdentifier - xcode.lang.ruby - - A3336BB570604D1B91C8DF90 - - children - - AF317538018444A5BCCE7E50 - 41F15AC86CD44FEEA58FC25A - B430868717094FA5818548C7 - CD662529CAB847FD9E04D618 - BAEF50BEB4FB427C888F0C83 - 0664DAB085284272A58FA5C1 - C7F2DD42A80247B39C9E8B0A - D83066B9EE164853BDDADFC1 - EF26C31740F34C1DA03DE6F0 - 560E3253C75441BFAC032222 - F062BB1E748A4BA18E2EE45B - A08DC63CAC864D67BB5EF8D0 - E9D4E4D4993E44ECA6E4D666 - 3FFBF8A4E845423A93DE50A6 - 07359EA6F65641E7B1FA9119 - 95AC99116638428092659625 - 3EEBBA57508D41E99C45BA64 - - isa - PBXGroup - name - Resources - sourceTree - <group> - - A5C45F2F48AB4C5880D46F26 - - children - - 87EB580E368F4E6CB33840A8 - - isa - PBXGroup - name - Products - sourceTree - <group> - - A68C68D28A4A4CE5A2765112 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-TSMessages.xcconfig - sourceTree - <group> - - A819D4D0AFD046CBBA030B26 - - buildActionMask - 2147483647 - files - - AD7AEBFA715C431B9F5FB89A - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - ACA8E41999534F83A6B1699C - - children - - 8A93E30DB3AC40E99B0E1A12 - - isa - PBXGroup - name - Targets Support Files - sourceTree - <group> - - AD7AEBFA715C431B9F5FB89A - - fileRef - 7150BC66A9C84380B009DD48 - isa - PBXBuildFile - - ADE06B4A58814760A98532FC - - buildSettings - - IPHONEOS_DEPLOYMENT_TARGET - 5.1 - STRIP_INSTALLED_PRODUCT - NO - - isa - XCBuildConfiguration - name - Release - - AF317538018444A5BCCE7E50 - - includeInIndex - 1 - isa - PBXFileReference - name - TSMessagesDefaultDesign.json - path - TSMessages/Resources/TSMessagesDefaultDesign.json - sourceTree - <group> - - B430868717094FA5818548C7 - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundError@2x.png - path - TSMessages/Resources/Images/NotificationBackgroundError@2x.png - sourceTree - <group> - - B860D15F4D8947D18C6CA21F - - fileRef - 53202C8D4E6B4B018F7C74D6 - isa - PBXBuildFile - - BAEF50BEB4FB427C888F0C83 - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundErrorIcon@2x.png - path - TSMessages/Resources/Images/NotificationBackgroundErrorIcon@2x.png - sourceTree - <group> - - BE1F7843899B486681962C59 - - fileRef - 63CAD95C55E041EEAD195B89 - isa - PBXBuildFile - - BEBBB8EDFAD74B189406A0B0 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - TSMessageView.m - path - TSMessages/Views/TSMessageView.m - sourceTree - <group> - - C153462D0780424C997F2D88 - - buildConfigurations - - 008FCB1214A547FABF2ACE78 - 99E8DD8063B34CB9927C685C - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - C2E8986407F543A9B622B1D2 - - fileRef - C49A102233D542D7BC33EA02 - isa - PBXBuildFile - - C35E0B354E5646DEAFE4B4FA - - attributes - - LastUpgradeCheck - 0500 - - buildConfigurationList - E649BF1EB5B14728861CDEE1 - compatibilityVersion - Xcode 3.2 - developmentRegion - English - hasScannedForEncodings - 0 - isa - PBXProject - knownRegions - - en - - mainGroup - D7D3F2C08A5C43D4A9998514 - productRefGroup - A5C45F2F48AB4C5880D46F26 - projectDirPath - - projectReferences - - projectRoot - - targets - - 231C8250C74C4AFB9E3469E5 - E7AEDF3C45F849A8B4358B09 - 68B61584912B40AD8DB67427 - - - C49A102233D542D7BC33EA02 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-TSMessages-dummy.m - sourceTree - <group> - - C7F2DD42A80247B39C9E8B0A - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundMessage@2x.png - path - TSMessages/Resources/Images/NotificationBackgroundMessage@2x.png - sourceTree - <group> - - CC58D3CE77FE488681CFF19F - - isa - PBXTargetDependency - target - 68B61584912B40AD8DB67427 - targetProxy - 1879866D15D84BC5B4A108BA - - CC5BD63FA0E64476B6D096E2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text - path - Pods-acknowledgements.markdown - sourceTree - <group> - - CCA854EFD62D4F43B92AB2F6 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-TSMessages-Private.xcconfig - sourceTree - <group> - - CD662529CAB847FD9E04D618 - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundErrorIcon.png - path - TSMessages/Resources/Images/NotificationBackgroundErrorIcon.png - sourceTree - <group> - - CE97B018E4C2414A9A5C3FAB - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-TSMessages-prefix.pch - sourceTree - <group> - - D00A0431231A400AA0A4F3B2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.plist.xml - path - Pods-acknowledgements.plist - sourceTree - <group> - - D52EEB5E95A5449CB60B0762 - - children - - 0AF065F777E848F29746E2F6 - 5ED86E633260493EA1A2F499 - - isa - PBXGroup - name - Source Files - sourceTree - <group> - - D6101DA0AC8A4BA5AC30167C - - children - - 0C3AF44C9B9D401A981B09FD - - isa - PBXGroup - name - Pods - sourceTree - <group> - - D7D3F2C08A5C43D4A9998514 - - children - - 8D9C3A3F98A44F99B303AB91 - 69503BF241F446369D378606 - D6101DA0AC8A4BA5AC30167C - A5C45F2F48AB4C5880D46F26 - ACA8E41999534F83A6B1699C - A1A1D99C3C214E88A19D1243 - - isa - PBXGroup - sourceTree - <group> - - D83066B9EE164853BDDADFC1 - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundSuccess.png - path - TSMessages/Resources/Images/NotificationBackgroundSuccess.png - sourceTree - <group> - - E5B62395E5324C6A91FA3B02 - - isa - PBXTargetDependency - target - E7AEDF3C45F849A8B4358B09 - targetProxy - 7048A9DCF66E435485B109D8 - - E649BF1EB5B14728861CDEE1 - - buildConfigurations - - 26254BFC82E04500BF05E57B - ADE06B4A58814760A98532FC - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - E6F8608730F84A098DEB8A05 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - TSMessage.h - path - TSMessages/Classes/TSMessage.h - sourceTree - <group> - - E7AEDF3C45F849A8B4358B09 - - buildConfigurationList - 5223B9E5408A4BB7AB5AC3FA - buildPhases - - FF6F3D5673F44B39A7D6E9E6 - A819D4D0AFD046CBBA030B26 - 13D06846069C48AA81FDBCA0 - - buildRules - - dependencies - - isa - PBXNativeTarget - name - Pods-HexColors - productName - Pods-HexColors - productReference - 75B471412A9147839B6A56D1 - productType - com.apple.product-type.library.static - - E7F054B132B240E3BCC9A26E - - containerPortal - C35E0B354E5646DEAFE4B4FA - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - E7AEDF3C45F849A8B4358B09 - remoteInfo - Pods-HexColors - - E97E54CD959C4B56927F6158 - - children - - 684D99C3E370489080DFAD7C - A3336BB570604D1B91C8DF90 - 3A68D0F35A2448709D775945 - 492C1D29D48B4EB38856AC3E - - isa - PBXGroup - name - TSMessages - path - ../.. - sourceTree - <group> - - E9D4E4D4993E44ECA6E4D666 - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundWarning@2x.png - path - TSMessages/Resources/Images/NotificationBackgroundWarning@2x.png - sourceTree - <group> - - EB2450E8D1A647E290A31F05 - - buildActionMask - 2147483647 - files - - 4EC9FB627F934E5B8D11BC28 - 9633151B14DB45819E79B2B4 - BE1F7843899B486681962C59 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - EB62E0597B194FE5A930E405 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-HexColors-Private.xcconfig - sourceTree - <group> - - EF26C31740F34C1DA03DE6F0 - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundSuccess@2x.png - path - TSMessages/Resources/Images/NotificationBackgroundSuccess@2x.png - sourceTree - <group> - - F062BB1E748A4BA18E2EE45B - - includeInIndex - 1 - isa - PBXFileReference - name - NotificationBackgroundSuccessIcon@2x.png - path - TSMessages/Resources/Images/NotificationBackgroundSuccessIcon@2x.png - sourceTree - <group> - - FF6F3D5673F44B39A7D6E9E6 - - buildActionMask - 2147483647 - files - - 1B314248BB734734ADC43083 - 7C69054C69EB4A928CD7B5E5 - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - - rootObject - C35E0B354E5646DEAFE4B4FA - - +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1B314248BB734734ADC43083 /* HexColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 5ED86E633260493EA1A2F499 /* HexColor.m */; }; + 2686CD3D628D49B8AD706E91 /* TSBlurView.m in Sources */ = {isa = PBXBuildFile; fileRef = 24F689F22A5A42809DBA68A7 /* TSBlurView.m */; settings = {COMPILER_FLAGS = "-fobjc-arc -DOS_OBJECT_USE_OBJC=0"; }; }; + 430D5356AE65432AAF3A6519 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7150BC66A9C84380B009DD48 /* Foundation.framework */; }; + 45CF47DADDF14BDBAA87ED67 /* Pods-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 899217DAF97C4C3F9BAE6861 /* Pods-dummy.m */; }; + 4EC9FB627F934E5B8D11BC28 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7150BC66A9C84380B009DD48 /* Foundation.framework */; }; + 544743058F5540DA887032D5 /* TSMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 09E89CC7D8724A98B872DF42 /* TSMessage.m */; settings = {COMPILER_FLAGS = "-fobjc-arc -DOS_OBJECT_USE_OBJC=0"; }; }; + 6B01F6793B184344B82979BC /* TSMessageView.m in Sources */ = {isa = PBXBuildFile; fileRef = BEBBB8EDFAD74B189406A0B0 /* TSMessageView.m */; settings = {COMPILER_FLAGS = "-fobjc-arc -DOS_OBJECT_USE_OBJC=0"; }; }; + 7C69054C69EB4A928CD7B5E5 /* Pods-HexColors-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 618EA4400E7548A38F36A30A /* Pods-HexColors-dummy.m */; }; + 7FC0316E0D3A474DAE207938 /* TSMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = E6F8608730F84A098DEB8A05 /* TSMessage.h */; }; + 850DFF742B9443539B374637 /* HexColor.h in Headers */ = {isa = PBXBuildFile; fileRef = 0AF065F777E848F29746E2F6 /* HexColor.h */; }; + 9633151B14DB45819E79B2B4 /* libPods-HexColors.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 75B471412A9147839B6A56D1 /* libPods-HexColors.a */; }; + 97F0EDB908074C5F96389171 /* TSBlurView.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B17E30CA6F248738B1CCE1F /* TSBlurView.h */; }; + AD7AEBFA715C431B9F5FB89A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7150BC66A9C84380B009DD48 /* Foundation.framework */; }; + B860D15F4D8947D18C6CA21F /* TSMessageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 53202C8D4E6B4B018F7C74D6 /* TSMessageView.h */; }; + BE1F7843899B486681962C59 /* libPods-TSMessages.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 63CAD95C55E041EEAD195B89 /* libPods-TSMessages.a */; }; + C2E8986407F543A9B622B1D2 /* Pods-TSMessages-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = C49A102233D542D7BC33EA02 /* Pods-TSMessages-dummy.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 1879866D15D84BC5B4A108BA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C35E0B354E5646DEAFE4B4FA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 68B61584912B40AD8DB67427; + remoteInfo = "Pods-TSMessages"; + }; + 7048A9DCF66E435485B109D8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C35E0B354E5646DEAFE4B4FA /* Project object */; + proxyType = 1; + remoteGlobalIDString = E7AEDF3C45F849A8B4358B09; + remoteInfo = "Pods-HexColors"; + }; + E7F054B132B240E3BCC9A26E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C35E0B354E5646DEAFE4B4FA /* Project object */; + proxyType = 1; + remoteGlobalIDString = E7AEDF3C45F849A8B4358B09; + remoteInfo = "Pods-HexColors"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0664DAB085284272A58FA5C1 /* NotificationBackgroundMessage.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundMessage.png; path = TSMessages/Resources/Images/NotificationBackgroundMessage.png; sourceTree = ""; }; + 07359EA6F65641E7B1FA9119 /* NotificationBackgroundWarningIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundWarningIcon@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundWarningIcon@2x.png"; sourceTree = ""; }; + 08ED9A1527024644ADCBA9CD /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Pods.xcconfig; sourceTree = ""; }; + 09E89CC7D8724A98B872DF42 /* TSMessage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = TSMessage.m; path = TSMessages/Classes/TSMessage.m; sourceTree = ""; }; + 0AF065F777E848F29746E2F6 /* HexColor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HexColor.h; path = Classes/HexColor.h; sourceTree = ""; }; + 24F689F22A5A42809DBA68A7 /* TSBlurView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = TSBlurView.m; path = TSMessages/Views/TSBlurView.m; sourceTree = ""; }; + 29BDFA547266427AA426611F /* Pods-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-resources.sh"; sourceTree = ""; }; + 2E35B5F218AED63C0000C422 /* TSMessage+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "TSMessage+Private.h"; path = "TSMessages/Classes/TSMessage+Private.h"; sourceTree = ""; }; + 3B17E30CA6F248738B1CCE1F /* TSBlurView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = TSBlurView.h; path = TSMessages/Views/TSBlurView.h; sourceTree = ""; }; + 3DED0B6E248A4FBEB11DFB7D /* Pods-HexColors-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-HexColors-prefix.pch"; sourceTree = ""; }; + 3EEBBA57508D41E99C45BA64 /* NotificationButtonBackground@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationButtonBackground@2x.png"; path = "TSMessages/Resources/Images/NotificationButtonBackground@2x.png"; sourceTree = ""; }; + 3FFBF8A4E845423A93DE50A6 /* NotificationBackgroundWarningIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundWarningIcon.png; path = TSMessages/Resources/Images/NotificationBackgroundWarningIcon.png; sourceTree = ""; }; + 41F15AC86CD44FEEA58FC25A /* NotificationBackgroundError.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundError.png; path = TSMessages/Resources/Images/NotificationBackgroundError.png; sourceTree = ""; }; + 48F158896D204969B78EF9EE /* Pods-HexColors.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-HexColors.xcconfig"; sourceTree = ""; }; + 53202C8D4E6B4B018F7C74D6 /* TSMessageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = TSMessageView.h; path = TSMessages/Views/TSMessageView.h; sourceTree = ""; }; + 560E3253C75441BFAC032222 /* NotificationBackgroundSuccessIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundSuccessIcon.png; path = TSMessages/Resources/Images/NotificationBackgroundSuccessIcon.png; sourceTree = ""; }; + 5ED86E633260493EA1A2F499 /* HexColor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HexColor.m; path = Classes/HexColor.m; sourceTree = ""; }; + 618EA4400E7548A38F36A30A /* Pods-HexColors-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-HexColors-dummy.m"; sourceTree = ""; }; + 63CAD95C55E041EEAD195B89 /* libPods-TSMessages.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-TSMessages.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6B0361DEF3DD4CEDB3E81214 /* Pods-environment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-environment.h"; sourceTree = ""; }; + 7150BC66A9C84380B009DD48 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 75B471412A9147839B6A56D1 /* libPods-HexColors.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HexColors.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 87EB580E368F4E6CB33840A8 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 899217DAF97C4C3F9BAE6861 /* Pods-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-dummy.m"; sourceTree = ""; }; + 95AC99116638428092659625 /* NotificationButtonBackground.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationButtonBackground.png; path = TSMessages/Resources/Images/NotificationButtonBackground.png; sourceTree = ""; }; + A08DC63CAC864D67BB5EF8D0 /* NotificationBackgroundWarning.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundWarning.png; path = TSMessages/Resources/Images/NotificationBackgroundWarning.png; sourceTree = ""; }; + A1A1D99C3C214E88A19D1243 /* Podfile */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + A68C68D28A4A4CE5A2765112 /* Pods-TSMessages.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TSMessages.xcconfig"; sourceTree = ""; }; + AF317538018444A5BCCE7E50 /* TSMessagesDefaultDesign.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = TSMessagesDefaultDesign.json; path = TSMessages/Resources/TSMessagesDefaultDesign.json; sourceTree = ""; }; + B430868717094FA5818548C7 /* NotificationBackgroundError@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundError@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundError@2x.png"; sourceTree = ""; }; + BAEF50BEB4FB427C888F0C83 /* NotificationBackgroundErrorIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundErrorIcon@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundErrorIcon@2x.png"; sourceTree = ""; }; + BEBBB8EDFAD74B189406A0B0 /* TSMessageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = TSMessageView.m; path = TSMessages/Views/TSMessageView.m; sourceTree = ""; }; + C49A102233D542D7BC33EA02 /* Pods-TSMessages-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-TSMessages-dummy.m"; sourceTree = ""; }; + C7F2DD42A80247B39C9E8B0A /* NotificationBackgroundMessage@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundMessage@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundMessage@2x.png"; sourceTree = ""; }; + CC5BD63FA0E64476B6D096E2 /* Pods-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-acknowledgements.markdown"; sourceTree = ""; }; + CCA854EFD62D4F43B92AB2F6 /* Pods-TSMessages-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TSMessages-Private.xcconfig"; sourceTree = ""; }; + CD662529CAB847FD9E04D618 /* NotificationBackgroundErrorIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundErrorIcon.png; path = TSMessages/Resources/Images/NotificationBackgroundErrorIcon.png; sourceTree = ""; }; + CE97B018E4C2414A9A5C3FAB /* Pods-TSMessages-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-TSMessages-prefix.pch"; sourceTree = ""; }; + D00A0431231A400AA0A4F3B2 /* Pods-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-acknowledgements.plist"; sourceTree = ""; }; + D83066B9EE164853BDDADFC1 /* NotificationBackgroundSuccess.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundSuccess.png; path = TSMessages/Resources/Images/NotificationBackgroundSuccess.png; sourceTree = ""; }; + E6F8608730F84A098DEB8A05 /* TSMessage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = TSMessage.h; path = TSMessages/Classes/TSMessage.h; sourceTree = ""; }; + E9D4E4D4993E44ECA6E4D666 /* NotificationBackgroundWarning@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundWarning@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundWarning@2x.png"; sourceTree = ""; }; + EB62E0597B194FE5A930E405 /* Pods-HexColors-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-HexColors-Private.xcconfig"; sourceTree = ""; }; + EF26C31740F34C1DA03DE6F0 /* NotificationBackgroundSuccess@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundSuccess@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundSuccess@2x.png"; sourceTree = ""; }; + F062BB1E748A4BA18E2EE45B /* NotificationBackgroundSuccessIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundSuccessIcon@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundSuccessIcon@2x.png"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 135D534C82F94C44AF0289B6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 430D5356AE65432AAF3A6519 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A819D4D0AFD046CBBA030B26 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AD7AEBFA715C431B9F5FB89A /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EB2450E8D1A647E290A31F05 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4EC9FB627F934E5B8D11BC28 /* Foundation.framework in Frameworks */, + 9633151B14DB45819E79B2B4 /* libPods-HexColors.a in Frameworks */, + BE1F7843899B486681962C59 /* libPods-TSMessages.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0C3AF44C9B9D401A981B09FD /* HexColors */ = { + isa = PBXGroup; + children = ( + 219C6D4DAB0E422DBFD10D53 /* Products */, + D52EEB5E95A5449CB60B0762 /* Source Files */, + 616DE37D6F1B45CC935B46AC /* Support Files */, + ); + path = HexColors; + sourceTree = ""; + }; + 219C6D4DAB0E422DBFD10D53 /* Products */ = { + isa = PBXGroup; + children = ( + 75B471412A9147839B6A56D1 /* libPods-HexColors.a */, + ); + name = Products; + sourceTree = ""; + }; + 3A68D0F35A2448709D775945 /* Source Files */ = { + isa = PBXGroup; + children = ( + 3B17E30CA6F248738B1CCE1F /* TSBlurView.h */, + E6F8608730F84A098DEB8A05 /* TSMessage.h */, + 2E35B5F218AED63C0000C422 /* TSMessage+Private.h */, + 53202C8D4E6B4B018F7C74D6 /* TSMessageView.h */, + 24F689F22A5A42809DBA68A7 /* TSBlurView.m */, + 09E89CC7D8724A98B872DF42 /* TSMessage.m */, + BEBBB8EDFAD74B189406A0B0 /* TSMessageView.m */, + ); + name = "Source Files"; + sourceTree = ""; + }; + 492C1D29D48B4EB38856AC3E /* Support Files */ = { + isa = PBXGroup; + children = ( + C49A102233D542D7BC33EA02 /* Pods-TSMessages-dummy.m */, + CE97B018E4C2414A9A5C3FAB /* Pods-TSMessages-prefix.pch */, + A68C68D28A4A4CE5A2765112 /* Pods-TSMessages.xcconfig */, + CCA854EFD62D4F43B92AB2F6 /* Pods-TSMessages-Private.xcconfig */, + ); + name = "Support Files"; + sourceTree = SOURCE_ROOT; + }; + 616DE37D6F1B45CC935B46AC /* Support Files */ = { + isa = PBXGroup; + children = ( + 618EA4400E7548A38F36A30A /* Pods-HexColors-dummy.m */, + 3DED0B6E248A4FBEB11DFB7D /* Pods-HexColors-prefix.pch */, + 48F158896D204969B78EF9EE /* Pods-HexColors.xcconfig */, + EB62E0597B194FE5A930E405 /* Pods-HexColors-Private.xcconfig */, + ); + name = "Support Files"; + sourceTree = SOURCE_ROOT; + }; + 684D99C3E370489080DFAD7C /* Products */ = { + isa = PBXGroup; + children = ( + 63CAD95C55E041EEAD195B89 /* libPods-TSMessages.a */, + ); + name = Products; + sourceTree = ""; + }; + 69503BF241F446369D378606 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 7150BC66A9C84380B009DD48 /* Foundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 8A93E30DB3AC40E99B0E1A12 /* Pods */ = { + isa = PBXGroup; + children = ( + 6B0361DEF3DD4CEDB3E81214 /* Pods-environment.h */, + 899217DAF97C4C3F9BAE6861 /* Pods-dummy.m */, + CC5BD63FA0E64476B6D096E2 /* Pods-acknowledgements.markdown */, + D00A0431231A400AA0A4F3B2 /* Pods-acknowledgements.plist */, + 29BDFA547266427AA426611F /* Pods-resources.sh */, + 08ED9A1527024644ADCBA9CD /* Pods.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 8D9C3A3F98A44F99B303AB91 /* Development Pods */ = { + isa = PBXGroup; + children = ( + E97E54CD959C4B56927F6158 /* TSMessages */, + ); + name = "Development Pods"; + sourceTree = ""; + }; + A3336BB570604D1B91C8DF90 /* Resources */ = { + isa = PBXGroup; + children = ( + AF317538018444A5BCCE7E50 /* TSMessagesDefaultDesign.json */, + 41F15AC86CD44FEEA58FC25A /* NotificationBackgroundError.png */, + B430868717094FA5818548C7 /* NotificationBackgroundError@2x.png */, + CD662529CAB847FD9E04D618 /* NotificationBackgroundErrorIcon.png */, + BAEF50BEB4FB427C888F0C83 /* NotificationBackgroundErrorIcon@2x.png */, + 0664DAB085284272A58FA5C1 /* NotificationBackgroundMessage.png */, + C7F2DD42A80247B39C9E8B0A /* NotificationBackgroundMessage@2x.png */, + D83066B9EE164853BDDADFC1 /* NotificationBackgroundSuccess.png */, + EF26C31740F34C1DA03DE6F0 /* NotificationBackgroundSuccess@2x.png */, + 560E3253C75441BFAC032222 /* NotificationBackgroundSuccessIcon.png */, + F062BB1E748A4BA18E2EE45B /* NotificationBackgroundSuccessIcon@2x.png */, + A08DC63CAC864D67BB5EF8D0 /* NotificationBackgroundWarning.png */, + E9D4E4D4993E44ECA6E4D666 /* NotificationBackgroundWarning@2x.png */, + 3FFBF8A4E845423A93DE50A6 /* NotificationBackgroundWarningIcon.png */, + 07359EA6F65641E7B1FA9119 /* NotificationBackgroundWarningIcon@2x.png */, + 95AC99116638428092659625 /* NotificationButtonBackground.png */, + 3EEBBA57508D41E99C45BA64 /* NotificationButtonBackground@2x.png */, + ); + name = Resources; + sourceTree = ""; + }; + A5C45F2F48AB4C5880D46F26 /* Products */ = { + isa = PBXGroup; + children = ( + 87EB580E368F4E6CB33840A8 /* libPods.a */, + ); + name = Products; + sourceTree = ""; + }; + ACA8E41999534F83A6B1699C /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 8A93E30DB3AC40E99B0E1A12 /* Pods */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + D52EEB5E95A5449CB60B0762 /* Source Files */ = { + isa = PBXGroup; + children = ( + 0AF065F777E848F29746E2F6 /* HexColor.h */, + 5ED86E633260493EA1A2F499 /* HexColor.m */, + ); + name = "Source Files"; + sourceTree = ""; + }; + D6101DA0AC8A4BA5AC30167C /* Pods */ = { + isa = PBXGroup; + children = ( + 0C3AF44C9B9D401A981B09FD /* HexColors */, + ); + name = Pods; + sourceTree = ""; + }; + D7D3F2C08A5C43D4A9998514 = { + isa = PBXGroup; + children = ( + 8D9C3A3F98A44F99B303AB91 /* Development Pods */, + 69503BF241F446369D378606 /* Frameworks */, + D6101DA0AC8A4BA5AC30167C /* Pods */, + A5C45F2F48AB4C5880D46F26 /* Products */, + ACA8E41999534F83A6B1699C /* Targets Support Files */, + A1A1D99C3C214E88A19D1243 /* Podfile */, + ); + sourceTree = ""; + }; + E97E54CD959C4B56927F6158 /* TSMessages */ = { + isa = PBXGroup; + children = ( + 684D99C3E370489080DFAD7C /* Products */, + A3336BB570604D1B91C8DF90 /* Resources */, + 3A68D0F35A2448709D775945 /* Source Files */, + 492C1D29D48B4EB38856AC3E /* Support Files */, + ); + name = TSMessages; + path = ../..; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 13D06846069C48AA81FDBCA0 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 850DFF742B9443539B374637 /* HexColor.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 513393A64B2C4D5F98177A07 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 97F0EDB908074C5F96389171 /* TSBlurView.h in Headers */, + 7FC0316E0D3A474DAE207938 /* TSMessage.h in Headers */, + B860D15F4D8947D18C6CA21F /* TSMessageView.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 231C8250C74C4AFB9E3469E5 /* Pods */ = { + isa = PBXNativeTarget; + buildConfigurationList = C153462D0780424C997F2D88 /* Build configuration list for PBXNativeTarget "Pods" */; + buildPhases = ( + 4A33B9F733C04F85AC86FD5B /* Sources */, + EB2450E8D1A647E290A31F05 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 08DC72AB9F3D4F8A8B67ECB5 /* PBXTargetDependency */, + CC58D3CE77FE488681CFF19F /* PBXTargetDependency */, + ); + name = Pods; + productName = Pods; + productReference = 87EB580E368F4E6CB33840A8 /* libPods.a */; + productType = "com.apple.product-type.library.static"; + }; + 68B61584912B40AD8DB67427 /* Pods-TSMessages */ = { + isa = PBXNativeTarget; + buildConfigurationList = 64FAFE92EB6D4225BEC33044 /* Build configuration list for PBXNativeTarget "Pods-TSMessages" */; + buildPhases = ( + 6D1EB0FB25E44FBAB7DBE383 /* Sources */, + 135D534C82F94C44AF0289B6 /* Frameworks */, + 513393A64B2C4D5F98177A07 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + E5B62395E5324C6A91FA3B02 /* PBXTargetDependency */, + ); + name = "Pods-TSMessages"; + productName = "Pods-TSMessages"; + productReference = 63CAD95C55E041EEAD195B89 /* libPods-TSMessages.a */; + productType = "com.apple.product-type.library.static"; + }; + E7AEDF3C45F849A8B4358B09 /* Pods-HexColors */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5223B9E5408A4BB7AB5AC3FA /* Build configuration list for PBXNativeTarget "Pods-HexColors" */; + buildPhases = ( + FF6F3D5673F44B39A7D6E9E6 /* Sources */, + A819D4D0AFD046CBBA030B26 /* Frameworks */, + 13D06846069C48AA81FDBCA0 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Pods-HexColors"; + productName = "Pods-HexColors"; + productReference = 75B471412A9147839B6A56D1 /* libPods-HexColors.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + C35E0B354E5646DEAFE4B4FA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + }; + buildConfigurationList = E649BF1EB5B14728861CDEE1 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = D7D3F2C08A5C43D4A9998514; + productRefGroup = A5C45F2F48AB4C5880D46F26 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 231C8250C74C4AFB9E3469E5 /* Pods */, + E7AEDF3C45F849A8B4358B09 /* Pods-HexColors */, + 68B61584912B40AD8DB67427 /* Pods-TSMessages */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 4A33B9F733C04F85AC86FD5B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 45CF47DADDF14BDBAA87ED67 /* Pods-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D1EB0FB25E44FBAB7DBE383 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C2E8986407F543A9B622B1D2 /* Pods-TSMessages-dummy.m in Sources */, + 2686CD3D628D49B8AD706E91 /* TSBlurView.m in Sources */, + 544743058F5540DA887032D5 /* TSMessage.m in Sources */, + 6B01F6793B184344B82979BC /* TSMessageView.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FF6F3D5673F44B39A7D6E9E6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1B314248BB734734ADC43083 /* HexColor.m in Sources */, + 7C69054C69EB4A928CD7B5E5 /* Pods-HexColors-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 08DC72AB9F3D4F8A8B67ECB5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = E7AEDF3C45F849A8B4358B09 /* Pods-HexColors */; + targetProxy = E7F054B132B240E3BCC9A26E /* PBXContainerItemProxy */; + }; + CC58D3CE77FE488681CFF19F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 68B61584912B40AD8DB67427 /* Pods-TSMessages */; + targetProxy = 1879866D15D84BC5B4A108BA /* PBXContainerItemProxy */; + }; + E5B62395E5324C6A91FA3B02 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = E7AEDF3C45F849A8B4358B09 /* Pods-HexColors */; + targetProxy = 7048A9DCF66E435485B109D8 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 008FCB1214A547FABF2ACE78 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 08ED9A1527024644ADCBA9CD /* Pods.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + DSTROOT = /tmp/xcodeproj.dst; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; + IPHONEOS_DEPLOYMENT_TARGET = 5.1; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 12C3F91EE0224C298A362BF0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EB62E0597B194FE5A930E405 /* Pods-HexColors-Private.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DSTROOT = /tmp/xcodeproj.dst; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Pods-HexColors-prefix.pch"; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; + IPHONEOS_DEPLOYMENT_TARGET = 5.1; + OTHER_CFLAGS = ( + "-DNS_BLOCK_ASSERTIONS=1", + "$(inherited)", + ); + OTHER_CPLUSPLUSFLAGS = ( + "-DNS_BLOCK_ASSERTIONS=1", + "$(inherited)", + ); + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 26254BFC82E04500BF05E57B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + IPHONEOS_DEPLOYMENT_TARGET = 5.1; + ONLY_ACTIVE_ARCH = YES; + STRIP_INSTALLED_PRODUCT = NO; + }; + name = Debug; + }; + 3D0DACDDAAB94F4DA8202A8F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EB62E0597B194FE5A930E405 /* Pods-HexColors-Private.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + DSTROOT = /tmp/xcodeproj.dst; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Pods-HexColors-prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; + IPHONEOS_DEPLOYMENT_TARGET = 5.1; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 5867460F45EE48B7BCBF246E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CCA854EFD62D4F43B92AB2F6 /* Pods-TSMessages-Private.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DSTROOT = /tmp/xcodeproj.dst; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Pods-TSMessages-prefix.pch"; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; + IPHONEOS_DEPLOYMENT_TARGET = 5.1; + OTHER_CFLAGS = ( + "-DNS_BLOCK_ASSERTIONS=1", + "$(inherited)", + ); + OTHER_CPLUSPLUSFLAGS = ( + "-DNS_BLOCK_ASSERTIONS=1", + "$(inherited)", + ); + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 7B220166450A440C843BD8DF /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CCA854EFD62D4F43B92AB2F6 /* Pods-TSMessages-Private.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + DSTROOT = /tmp/xcodeproj.dst; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Pods-TSMessages-prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; + IPHONEOS_DEPLOYMENT_TARGET = 5.1; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 99E8DD8063B34CB9927C685C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 08ED9A1527024644ADCBA9CD /* Pods.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DSTROOT = /tmp/xcodeproj.dst; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; + IPHONEOS_DEPLOYMENT_TARGET = 5.1; + OTHER_CFLAGS = ( + "-DNS_BLOCK_ASSERTIONS=1", + "$(inherited)", + ); + OTHER_CPLUSPLUSFLAGS = ( + "-DNS_BLOCK_ASSERTIONS=1", + "$(inherited)", + ); + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + ADE06B4A58814760A98532FC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + IPHONEOS_DEPLOYMENT_TARGET = 5.1; + STRIP_INSTALLED_PRODUCT = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 5223B9E5408A4BB7AB5AC3FA /* Build configuration list for PBXNativeTarget "Pods-HexColors" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3D0DACDDAAB94F4DA8202A8F /* Debug */, + 12C3F91EE0224C298A362BF0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 64FAFE92EB6D4225BEC33044 /* Build configuration list for PBXNativeTarget "Pods-TSMessages" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B220166450A440C843BD8DF /* Debug */, + 5867460F45EE48B7BCBF246E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C153462D0780424C997F2D88 /* Build configuration list for PBXNativeTarget "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 008FCB1214A547FABF2ACE78 /* Debug */, + 99E8DD8063B34CB9927C685C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E649BF1EB5B14728861CDEE1 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 26254BFC82E04500BF05E57B /* Debug */, + ADE06B4A58814760A98532FC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = C35E0B354E5646DEAFE4B4FA /* Project object */; +} diff --git a/TSMessages/Classes/TSMessage+Private.h b/TSMessages/Classes/TSMessage+Private.h new file mode 100644 index 00000000..6afd8eb1 --- /dev/null +++ b/TSMessages/Classes/TSMessage+Private.h @@ -0,0 +1,18 @@ +// +// TSMessage+Private.h +// Felix Krause +// +// Created by Felix Krause on 24.08.12. +// Copyright (c) 2012 Felix Krause. All rights reserved. +// + +#import "TSMessage.h" + +@class TSMessageView; + +@interface TSMessage (Private) +- (void)fadeOutCurrentNotification; +- (void)fadeOutNotification:(TSMessageView *)messageView; +- (void)fadeOutNotification:(TSMessageView *)messageView completion:(void (^)())completion; +- (TSMessageView *)currentNotification; +@end \ No newline at end of file diff --git a/TSMessages/Classes/TSMessage.h b/TSMessages/Classes/TSMessage.h index bf194ea6..1254ff74 100755 --- a/TSMessages/Classes/TSMessage.h +++ b/TSMessages/Classes/TSMessage.h @@ -45,7 +45,8 @@ typedef NS_ENUM(NSInteger, TSMessageNotificationPosition) { /** This enum can be passed to the duration parameter */ typedef NS_ENUM(NSInteger,TSMessageNotificationDuration) { TSMessageNotificationDurationAutomatic = 0, - TSMessageNotificationDurationEndless = -1 // The notification is displayed until the user dismissed it or it is dismissed by calling dismissActiveNotification + TSMessageNotificationDurationEndless = -1, // The notification is displayed until the user dismissed it or it is dismissed by calling dismissActiveNotification + TSMessageNotificationDurationPermanent = -2 // Just like endless, but does not prevent }; typedef void (^TSMessageCallback)(TSMessageView *messageView); @@ -109,6 +110,41 @@ typedef void (^TSMessageCallback)(TSMessageView *messageView); atPosition:(TSMessageNotificationPosition)messagePosition canBeDismissedByUser:(BOOL)dismissingEnabled; +/** Shows a permanent notification message in a specific view controller + This differs from normal notifications in that permanent messages are not + contained in the messages queue and can be displayed in addition to the + other messages. + + Permanent notifications do not get dismissed automatically, hence they do + not have a duration but have to be dismissed by the user or programmatically + in one of the callbacks. + This constructor for a permanent message also returns the instance of the + message view, so that one can also capture it and dismiss it with other + custom events. + + @param viewController The view controller to show the notification in. + @param title The title of the notification view + @param subtitle The message that is displayed underneath the title (optional) + @param image A custom icon image (optional) + @param type The notification type (Message, Warning, Error, Success) + @param duration The duration of the notification being displayed + @param callback The block that should be executed, when the user tapped on the message + @param buttonTitle The title for button (optional) + @param buttonCallback The block that should be executed, when the user tapped on the button + @param messagePosition The position of the message on the screen + @param dismissingEnabled Should the message be dismissed when the user taps/swipes it + */ ++ (TSMessageView *)showPermanentNotificationInViewController:(UIViewController *)viewController + title:(NSString *)title + subtitle:(NSString *)subtitle + image:(UIImage *)image + type:(TSMessageNotificationType)type + callback:(TSMessageCallback)callback + buttonTitle:(NSString *)buttonTitle + buttonCallback:(TSMessageCallback)buttonCallback + atPosition:(TSMessageNotificationPosition)messagePosition + canBeDismissedByUser:(BOOL)dismissingEnabled; + /** Fades out the currently displayed notification. If another notification is in the queue, the next one will be displayed automatically @return YES if the currently displayed notification was successfully dismissed. NO if no notification diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index b5319730..da2eccfa 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -21,7 +21,7 @@ @interface TSMessage () @property (nonatomic, strong) NSMutableArray *messages; - (void)fadeInCurrentNotification; -- (void)fadeOutNotification:(TSMessageView *)currentView; +- (void)fadeOutCurrentNotification; @end @@ -111,12 +111,39 @@ + (void)showNotificationInViewController:(UIViewController *)viewController [self prepareNotificationToBeShown:v]; } ++ (TSMessageView *)showPermanentNotificationInViewController:(UIViewController *)viewController + title:(NSString *)title + subtitle:(NSString *)subtitle + image:(UIImage *)image + type:(TSMessageNotificationType)type + callback:(TSMessageCallback)callback + buttonTitle:(NSString *)buttonTitle + buttonCallback:(TSMessageCallback)buttonCallback + atPosition:(TSMessageNotificationPosition)messagePosition + canBeDismissedByUser:(BOOL)dismissingEnabled { + TSMessageView *v = [[TSMessageView alloc] initWithTitle:title + subtitle:subtitle + image:image + type:type + duration:TSMessageNotificationDurationEndless + inViewController:viewController + callback:callback + buttonTitle:buttonTitle + buttonCallback:buttonCallback + atPosition:messagePosition + canBeDismissedByUser:dismissingEnabled]; + + [[TSMessage sharedMessage] fadeInNotification:v]; + + return v; +} + + (void)prepareNotificationToBeShown:(TSMessageView *)messageView { NSString *title = messageView.title; NSString *subtitle = messageView.subtitle; - + for (TSMessageView *n in [TSMessage sharedMessage].messages) { if (([n.title isEqualToString:title] || (!n.title && !title)) && ([n.subtitle isEqualToString:subtitle] || (!n.subtitle && !subtitle))) @@ -124,9 +151,9 @@ + (void)prepareNotificationToBeShown:(TSMessageView *)messageView return; // avoid showing the same messages twice in a row } } - + [[TSMessage sharedMessage].messages addObject:messageView]; - + if (!notificationActive) { [[TSMessage sharedMessage] fadeInCurrentNotification]; @@ -145,39 +172,51 @@ - (id)init return self; } +- (TSMessageView *)currentNotification { + if ([self.messages count] > 0) + { + return [self.messages objectAtIndex:0]; + } + + return nil; +} + - (void)fadeInCurrentNotification { - if ([self.messages count] == 0) return; - + if (!self.currentNotification) return; + notificationActive = YES; - - TSMessageView *currentView = [self.messages objectAtIndex:0]; - + + [self fadeInNotification:self.currentNotification]; +} + +- (void)fadeInNotification:(TSMessageView *)messageView +{ __block CGFloat verticalOffset = 0.0f; - + void (^addStatusBarHeightToVerticalOffset)() = ^void() { BOOL isPortrait = UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]); CGSize statusBarSize = [UIApplication sharedApplication].statusBarFrame.size; CGFloat offset = isPortrait ? statusBarSize.height : statusBarSize.width; verticalOffset += offset; }; - - if ([currentView.viewController isKindOfClass:[UINavigationController class]] || [currentView.viewController.parentViewController isKindOfClass:[UINavigationController class]]) + + if ([messageView.viewController isKindOfClass:[UINavigationController class]] || [messageView.viewController.parentViewController isKindOfClass:[UINavigationController class]]) { UINavigationController *currentNavigationController; - - if([currentView.viewController isKindOfClass:[UINavigationController class]]) - currentNavigationController = (UINavigationController *)currentView.viewController; + + if([messageView.viewController isKindOfClass:[UINavigationController class]]) + currentNavigationController = (UINavigationController *)messageView.viewController; else - currentNavigationController = (UINavigationController *)currentView.viewController.parentViewController; - + currentNavigationController = (UINavigationController *)messageView.viewController.parentViewController; + BOOL isViewIsUnderStatusBar = [[[currentNavigationController childViewControllers] firstObject] wantsFullScreenLayout]; if (!isViewIsUnderStatusBar && currentNavigationController.parentViewController == nil) { isViewIsUnderStatusBar = ![currentNavigationController isNavigationBarHidden]; // strange but true } if (![currentNavigationController isNavigationBarHidden]) { - [currentNavigationController.view insertSubview:currentView + [currentNavigationController.view insertSubview:messageView belowSubview:[currentNavigationController navigationBar]]; verticalOffset = [currentNavigationController navigationBar].bounds.size.height; if ([TSMessage iOS7StyleEnabled] || isViewIsUnderStatusBar) { @@ -186,7 +225,7 @@ - (void)fadeInCurrentNotification } else { - [currentView.viewController.view addSubview:currentView]; + [messageView.viewController.view addSubview:messageView]; if ([TSMessage iOS7StyleEnabled] || isViewIsUnderStatusBar) { addStatusBarHeightToVerticalOffset(); } @@ -194,42 +233,42 @@ - (void)fadeInCurrentNotification } else { - [currentView.viewController.view addSubview:currentView]; + [messageView.viewController.view addSubview:messageView]; if ([TSMessage iOS7StyleEnabled]) { addStatusBarHeightToVerticalOffset(); } } - + CGPoint toPoint; - if (currentView.messagePosition == TSMessageNotificationPositionTop) + if (messageView.messagePosition == TSMessageNotificationPositionTop) { CGFloat navigationbarBottomOfViewController = 0; - - if (currentView.delegate && [currentView.delegate respondsToSelector:@selector(navigationbarBottomOfViewController:)]) - navigationbarBottomOfViewController = [currentView.delegate navigationbarBottomOfViewController:currentView.viewController]; - - toPoint = CGPointMake(currentView.center.x, - navigationbarBottomOfViewController + verticalOffset + CGRectGetHeight(currentView.frame) / 2.0); + + if (messageView.delegate && [messageView.delegate respondsToSelector:@selector(navigationbarBottomOfViewController:)]) + navigationbarBottomOfViewController = [messageView.delegate navigationbarBottomOfViewController:messageView.viewController]; + + toPoint = CGPointMake(messageView.center.x, + navigationbarBottomOfViewController + verticalOffset + CGRectGetHeight(messageView.frame) / 2.0); } else { - CGFloat y = currentView.viewController.view.bounds.size.height - CGRectGetHeight(currentView.frame) / 2.0; - if (!currentView.viewController.navigationController.isToolbarHidden) { - y -= CGRectGetHeight(currentView.viewController.navigationController.toolbar.bounds); + CGFloat y = messageView.viewController.view.bounds.size.height - CGRectGetHeight(messageView.frame) / 2.0; + if (!messageView.viewController.navigationController.isToolbarHidden) { + y -= CGRectGetHeight(messageView.viewController.navigationController.toolbar.bounds); } - toPoint = CGPointMake(currentView.center.x, y); + toPoint = CGPointMake(messageView.center.x, y); } - + dispatch_block_t animationBlock = ^{ - currentView.center = toPoint; + messageView.center = toPoint; if (![TSMessage iOS7StyleEnabled]) { - currentView.alpha = TSMessageViewAlpha; + messageView.alpha = TSMessageViewAlpha; } }; void(^completionBlock)(BOOL) = ^(BOOL finished) { - currentView.messageIsFullyDisplayed = YES; + messageView.messageIsFullyDisplayed = YES; }; - + if (![TSMessage iOS7StyleEnabled]) { [UIView animateWithDuration:kTSMessageAnimationDuration delay:0.0 @@ -247,77 +286,89 @@ - (void)fadeInCurrentNotification completion:completionBlock]; #endif } - - if (currentView.duration == TSMessageNotificationDurationAutomatic) + + if (messageView.duration == TSMessageNotificationDurationAutomatic) { - currentView.duration = kTSMessageAnimationDuration + kTSMessageDisplayTime + currentView.frame.size.height * kTSMessageExtraDisplayTimePerPixel; + messageView.duration = kTSMessageAnimationDuration + kTSMessageDisplayTime + messageView.frame.size.height * kTSMessageExtraDisplayTimePerPixel; } - - if (currentView.duration != TSMessageNotificationDurationEndless) + + if (messageView.duration != TSMessageNotificationDurationEndless) { dispatch_async(dispatch_get_main_queue(), ^ { - [self performSelector:@selector(fadeOutNotification:) - withObject:currentView - afterDelay:currentView.duration]; + [self performSelector:@selector(fadeOutCurrentNotification) + withObject:nil + afterDelay:messageView.duration]; }); } } -- (void)fadeOutNotification:(TSMessageView *)currentView +- (void)fadeOutNotification:(TSMessageView *)messageView { - currentView.messageIsFullyDisplayed = NO; - [NSObject cancelPreviousPerformRequestsWithTarget:self - selector:@selector(fadeOutNotification:) - object:currentView]; - + [self fadeOutNotification:messageView completion:NULL]; +} + +- (void)fadeOutNotification:(TSMessageView *)messageView completion:(void (^)())completion +{ + messageView.messageIsFullyDisplayed = NO; + CGPoint fadeOutToPoint; - if (currentView.messagePosition == TSMessageNotificationPositionTop) + if (messageView.messagePosition == TSMessageNotificationPositionTop) { - fadeOutToPoint = CGPointMake(currentView.center.x, -CGRectGetHeight(currentView.frame)/2.f); + fadeOutToPoint = CGPointMake(messageView.center.x, -CGRectGetHeight(messageView.frame)/2.f); } else { - fadeOutToPoint = CGPointMake(currentView.center.x, - currentView.viewController.view.bounds.size.height + CGRectGetHeight(currentView.frame)/2.f); + fadeOutToPoint = CGPointMake(messageView.center.x, + messageView.viewController.view.bounds.size.height + CGRectGetHeight(messageView.frame)/2.f); } - + [UIView animateWithDuration:kTSMessageAnimationDuration animations:^ { - currentView.center = fadeOutToPoint; + messageView.center = fadeOutToPoint; if (![TSMessage iOS7StyleEnabled]) { - currentView.alpha = 0.f; + messageView.alpha = 0.f; } } completion:^(BOOL finished) { - [currentView removeFromSuperview]; - - if ([self.messages count] > 0) - { - [self.messages removeObjectAtIndex:0]; - } - - notificationActive = NO; - - if ([self.messages count] > 0) - { - [self fadeInCurrentNotification]; + [messageView removeFromSuperview]; + + if (completion) { + completion(); } }]; } +- (void)fadeOutCurrentNotification +{ + if (!self.currentNotification) return; + + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(fadeOutCurrentNotification) + object:nil]; + + [self fadeOutNotification:self.currentNotification completion:^{ + if ([self.messages count] > 0) + { + [self.messages removeObjectAtIndex:0]; + } + + notificationActive = NO; + + if ([self.messages count] > 0) + { + [self fadeInCurrentNotification]; + } + }]; +} + + (BOOL)dismissActiveNotification { - if ([[TSMessage sharedMessage].messages count] == 0) return NO; - + if (![TSMessage sharedMessage].currentNotification) return NO; + dispatch_async(dispatch_get_main_queue(), ^ { - if ([[TSMessage sharedMessage].messages count] == 0) return; - TSMessageView *currentMessage = [[TSMessage sharedMessage].messages objectAtIndex:0]; - if (currentMessage.messageIsFullyDisplayed) - { - [[TSMessage sharedMessage] fadeOutNotification:currentMessage]; - } + [[TSMessage sharedMessage] fadeOutCurrentNotification]; }); return YES; } @@ -346,7 +397,7 @@ + (BOOL)isNotificationActive + (UIViewController *)defaultViewController { __strong UIViewController *defaultViewController = _defaultViewController; - + if (!defaultViewController) { NSLog(@"TSMessages: It is recommended to set a custom defaultViewController that is used to display the notifications"); defaultViewController = [UIApplication sharedApplication].keyWindow.rootViewController; @@ -363,7 +414,7 @@ + (BOOL)iOS7StyleEnabled #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 iOS7SDK = YES; #endif - + _useiOS7Style = ! (TS_SYSTEM_VERSION_LESS_THAN(@"7.0") || !iOS7SDK); }); return _useiOS7Style; diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index acc1ff06..88817364 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -10,6 +10,7 @@ #import "HexColor.h" #import "TSBlurView.h" #import "TSMessage.h" +#import "TSMessage+Private.h" #define TSMessageViewPadding 15.0 @@ -19,10 +20,6 @@ static NSMutableDictionary *_notificationDesign; -@interface TSMessage (TSMessageView) -- (void)fadeOutNotification:(TSMessageView *)currentView; // private method of TSMessage, but called by TSMessageView in -[fadeMeOut] -@end - @interface TSMessageView () /** The displayed title of this message */ @@ -450,7 +447,11 @@ - (void)layoutSubviews - (void)fadeMeOut { - [[TSMessage sharedMessage] performSelectorOnMainThread:@selector(fadeOutNotification:) withObject:self waitUntilDone:NO]; + if (self == [TSMessage sharedMessage].currentNotification) { + [[TSMessage sharedMessage] performSelectorOnMainThread:@selector(fadeOutCurrentNotification) withObject:nil waitUntilDone:NO]; + } else { + [[TSMessage sharedMessage] performSelectorOnMainThread:@selector(fadeOutNotification:) withObject:self waitUntilDone:NO]; + } } - (void)didMoveToWindow { From 5f0f1938c5772e724e5f17c76b4a2b8b45fb453e Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Sat, 15 Feb 2014 00:11:36 +0100 Subject: [PATCH 03/27] Add permanent messages to demo --- ExampleProject/Example/TSDemoViewController.h | 1 + ExampleProject/Example/TSDemoViewController.m | 16 ++++++++++++++++ .../en.lproj/MainStoryboard.storyboard | 19 +++++++++++++++---- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/ExampleProject/Example/TSDemoViewController.h b/ExampleProject/Example/TSDemoViewController.h index dd353171..f4bf1e47 100644 --- a/ExampleProject/Example/TSDemoViewController.h +++ b/ExampleProject/Example/TSDemoViewController.h @@ -23,5 +23,6 @@ - (IBAction)didTapBottom:(id)sender; - (IBAction)didTapText:(id)sender; - (IBAction)didTapCustomDesign:(id)sender; +- (IBAction)didTapPermanent:(id)sender; @end diff --git a/ExampleProject/Example/TSDemoViewController.m b/ExampleProject/Example/TSDemoViewController.m index 928232d5..407bb7e7 100644 --- a/ExampleProject/Example/TSDemoViewController.m +++ b/ExampleProject/Example/TSDemoViewController.m @@ -68,6 +68,22 @@ - (IBAction)didTapButton:(id)sender canBeDismissedByUser:YES]; } +- (IBAction)didTapPermanent:(id)sender { + [TSMessage showPermanentNotificationInViewController:self + title:NSLocalizedString(@"Permanent notification", nil) + subtitle:NSLocalizedString(@"Stays here until it gets dismissed", nil) + image:nil + type:TSMessageNotificationTypeMessage + callback:^(TSMessageView *messageView) { + [TSMessage showNotificationWithTitle:NSLocalizedString(@"Action triggered", nil) + type:TSMessageNotificationTypeSuccess]; + } buttonTitle:NSLocalizedString(@"Dismiss", nil) + buttonCallback:^(TSMessageView *messageView) { + [messageView fadeMeOut]; + } atPosition:TSMessageNotificationPositionBottom + canBeDismissedByUser:NO]; +} + - (IBAction)didTapToggleNavigationBar:(id)sender { [self.navigationController setNavigationBarHidden:!self.navigationController.navigationBarHidden animated:YES]; } diff --git a/ExampleProject/Example/en.lproj/MainStoryboard.storyboard b/ExampleProject/Example/en.lproj/MainStoryboard.storyboard index 4744e022..1fea5e6e 100644 --- a/ExampleProject/Example/en.lproj/MainStoryboard.storyboard +++ b/ExampleProject/Example/en.lproj/MainStoryboard.storyboard @@ -1,8 +1,8 @@ - + - + @@ -81,7 +81,7 @@ + - - + @@ -197,7 +198,7 @@ - + diff --git a/TSMessages/Classes/TSMessage.h b/TSMessages/Classes/TSMessage.h index 1254ff74..1e94ac90 100755 --- a/TSMessages/Classes/TSMessage.h +++ b/TSMessages/Classes/TSMessage.h @@ -166,8 +166,4 @@ typedef void (^TSMessageCallback)(TSMessageView *messageView); You don't have to use this method. */ + (void)prepareNotificationToBeShown:(TSMessageView *)messageView; -/** Indicates whether currently the iOS 7 style of TSMessages is used - This depends on the Base SDK and the currently used device */ -+ (BOOL)iOS7StyleEnabled; - @end diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index da2eccfa..28e2c9a0 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -203,30 +203,33 @@ - (void)fadeInNotification:(TSMessageView *)messageView if ([messageView.viewController isKindOfClass:[UINavigationController class]] || [messageView.viewController.parentViewController isKindOfClass:[UINavigationController class]]) { - UINavigationController *currentNavigationController; + UINavigationController *navigationController; + UIViewController *viewController = messageView.viewController; - if([messageView.viewController isKindOfClass:[UINavigationController class]]) - currentNavigationController = (UINavigationController *)messageView.viewController; + if ([viewController isKindOfClass:[UINavigationController class]]) + navigationController = (UINavigationController *)viewController; else - currentNavigationController = (UINavigationController *)messageView.viewController.parentViewController; - - BOOL isViewIsUnderStatusBar = [[[currentNavigationController childViewControllers] firstObject] wantsFullScreenLayout]; - if (!isViewIsUnderStatusBar && currentNavigationController.parentViewController == nil) { - isViewIsUnderStatusBar = ![currentNavigationController isNavigationBarHidden]; // strange but true + navigationController = (UINavigationController *)viewController.parentViewController; + + viewController = [[navigationController childViewControllers] firstObject]; + + BOOL isViewIsUnderStatusBar = ![viewController prefersStatusBarHidden]; + + if (!isViewIsUnderStatusBar && navigationController.parentViewController == nil) { + isViewIsUnderStatusBar = ![navigationController isNavigationBarHidden]; // strange but true } - if (![currentNavigationController isNavigationBarHidden]) + + if (![navigationController isNavigationBarHidden]) { - [currentNavigationController.view insertSubview:messageView - belowSubview:[currentNavigationController navigationBar]]; - verticalOffset = [currentNavigationController navigationBar].bounds.size.height; - if ([TSMessage iOS7StyleEnabled] || isViewIsUnderStatusBar) { - addStatusBarHeightToVerticalOffset(); - } + [navigationController.view insertSubview:messageView + belowSubview:[navigationController navigationBar]]; + verticalOffset = [navigationController navigationBar].bounds.size.height; + addStatusBarHeightToVerticalOffset(); } else { [messageView.viewController.view addSubview:messageView]; - if ([TSMessage iOS7StyleEnabled] || isViewIsUnderStatusBar) { + if (isViewIsUnderStatusBar) { addStatusBarHeightToVerticalOffset(); } } @@ -234,9 +237,7 @@ - (void)fadeInNotification:(TSMessageView *)messageView else { [messageView.viewController.view addSubview:messageView]; - if ([TSMessage iOS7StyleEnabled]) { - addStatusBarHeightToVerticalOffset(); - } + addStatusBarHeightToVerticalOffset(); } CGPoint toPoint; @@ -261,31 +262,19 @@ - (void)fadeInNotification:(TSMessageView *)messageView dispatch_block_t animationBlock = ^{ messageView.center = toPoint; - if (![TSMessage iOS7StyleEnabled]) { - messageView.alpha = TSMessageViewAlpha; - } }; + void(^completionBlock)(BOOL) = ^(BOOL finished) { messageView.messageIsFullyDisplayed = YES; }; - if (![TSMessage iOS7StyleEnabled]) { - [UIView animateWithDuration:kTSMessageAnimationDuration - delay:0.0 - options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction - animations:animationBlock - completion:completionBlock]; - } else { -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 - [UIView animateWithDuration:kTSMessageAnimationDuration + 0.1 - delay:0 - usingSpringWithDamping:0.8 - initialSpringVelocity:0.f - options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction - animations:animationBlock - completion:completionBlock]; -#endif - } + [UIView animateWithDuration:kTSMessageAnimationDuration + 0.1 + delay:0 + usingSpringWithDamping:0.8 + initialSpringVelocity:0.f + options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction + animations:animationBlock + completion:completionBlock]; if (messageView.duration == TSMessageNotificationDurationAutomatic) { @@ -326,9 +315,6 @@ - (void)fadeOutNotification:(TSMessageView *)messageView completion:(void (^)()) [UIView animateWithDuration:kTSMessageAnimationDuration animations:^ { messageView.center = fadeOutToPoint; - if (![TSMessage iOS7StyleEnabled]) { - messageView.alpha = 0.f; - } } completion:^(BOOL finished) { [messageView removeFromSuperview]; @@ -385,10 +371,8 @@ + (void)addCustomDesignFromFileWithName:(NSString *)fileName [TSMessageView addNotificationDesignFromFile:fileName]; } - #pragma mark Other methods - + (BOOL)isNotificationActive { return notificationActive; @@ -405,19 +389,4 @@ + (UIViewController *)defaultViewController return defaultViewController; } -+ (BOOL)iOS7StyleEnabled -{ - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - // Decide wheter to use iOS 7 style or not based on the running device and the base sdk - BOOL iOS7SDK = NO; -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 - iOS7SDK = YES; -#endif - - _useiOS7Style = ! (TS_SYSTEM_VERSION_LESS_THAN(@"7.0") || !iOS7SDK); - }); - return _useiOS7Style; -} - @end diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index c4472275..b3a8c81d 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -145,24 +145,10 @@ - (id)initWithTitle:(NSString *)title image = [UIImage imageNamed:[current valueForKey:@"imageName"]]; } - if (![TSMessage iOS7StyleEnabled]) - { - self.alpha = 0.0; - - // add background image here - UIImage *backgroundImage = [[UIImage imageNamed:[current valueForKey:@"backgroundImageName"]] stretchableImageWithLeftCapWidth:0.0 topCapHeight:0.0]; - _backgroundImageView = [[UIImageView alloc] initWithImage:backgroundImage]; - self.backgroundImageView.autoresizingMask = (UIViewAutoresizingFlexibleWidth); - [self addSubview:self.backgroundImageView]; - } - else - { - // On iOS 7 and above use a blur layer instead (not yet finished) - _backgroundBlurView = [[TSBlurView alloc] init]; - self.backgroundBlurView.autoresizingMask = (UIViewAutoresizingFlexibleWidth); - self.backgroundBlurView.blurTintColor = [UIColor colorWithHexString:current[@"backgroundColor"]]; - [self addSubview:self.backgroundBlurView]; - } + _backgroundBlurView = [[TSBlurView alloc] init]; + self.backgroundBlurView.autoresizingMask = (UIViewAutoresizingFlexibleWidth); + self.backgroundBlurView.blurTintColor = [UIColor colorWithHexString:current[@"backgroundColor"]]; + [self addSubview:self.backgroundBlurView]; UIColor *fontColor = [UIColor colorWithHexString:[current valueForKey:@"textColor"] alpha:1.0]; @@ -277,20 +263,6 @@ - (id)initWithTitle:(NSString *)title self.textSpaceRight = self.button.frame.size.width + TSMessageViewPadding; } - // Add a border on the bottom (or on the top, depending on the view's postion) - if (![TSMessage iOS7StyleEnabled]) - { - _borderView = [[UIView alloc] initWithFrame:CGRectMake(0.0, - 0.0, // will be set later - screenWidth, - [[current valueForKey:@"borderHeight"] floatValue])]; - self.borderView.backgroundColor = [UIColor colorWithHexString:[current valueForKey:@"borderColor"] - alpha:1.0]; - self.borderView.autoresizingMask = (UIViewAutoresizingFlexibleWidth); - [self addSubview:self.borderView]; - } - - CGFloat actualHeight = [self updateHeightOfMessageView]; // this call also takes care of positioning the labels CGFloat topPosition = -actualHeight; @@ -409,28 +381,25 @@ - (CGFloat)updateHeightOfMessageView currentHeight); // increase frame of background view because of the spring animation - if ([TSMessage iOS7StyleEnabled]) + if (self.messagePosition == TSMessageNotificationPositionTop) { - if (self.messagePosition == TSMessageNotificationPositionTop) - { - float topOffset = 0.f; - - UINavigationController *navigationController = self.viewController.navigationController; - if (!navigationController && [self.viewController isKindOfClass:[UINavigationController class]]) { - navigationController = (UINavigationController *)self.viewController; - } - BOOL isNavBarIsHidden = !navigationController || self.viewController.navigationController.navigationBarHidden; - BOOL isNavBarIsOpaque = !self.viewController.navigationController.navigationBar.isTranslucent && self.viewController.navigationController.navigationBar.alpha == 1; - - if (isNavBarIsHidden || isNavBarIsOpaque) { - topOffset = -30.f; - } - backgroundFrame = UIEdgeInsetsInsetRect(backgroundFrame, UIEdgeInsetsMake(topOffset, 0.f, 0.f, 0.f)); + float topOffset = 0.f; + + UINavigationController *navigationController = self.viewController.navigationController; + if (!navigationController && [self.viewController isKindOfClass:[UINavigationController class]]) { + navigationController = (UINavigationController *)self.viewController; } - else if (self.messagePosition == TSMessageNotificationPositionBottom) - { - backgroundFrame = UIEdgeInsetsInsetRect(backgroundFrame, UIEdgeInsetsMake(0.f, 0.f, -30.f, 0.f)); + BOOL isNavBarIsHidden = !navigationController || self.viewController.navigationController.navigationBarHidden; + BOOL isNavBarIsOpaque = !self.viewController.navigationController.navigationBar.isTranslucent && self.viewController.navigationController.navigationBar.alpha == 1; + + if (isNavBarIsHidden || isNavBarIsOpaque) { + topOffset = -30.f; } + backgroundFrame = UIEdgeInsetsInsetRect(backgroundFrame, UIEdgeInsetsMake(topOffset, 0.f, 0.f, 0.f)); + } + else if (self.messagePosition == TSMessageNotificationPositionBottom) + { + backgroundFrame = UIEdgeInsetsInsetRect(backgroundFrame, UIEdgeInsetsMake(0.f, 0.f, -30.f, 0.f)); } self.backgroundImageView.frame = backgroundFrame; From e1341cd26b35a13213dd61c65bc2e653d8ae73b7 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Sun, 16 Feb 2014 22:19:31 +0100 Subject: [PATCH 06/27] Remove iOS 7 style remainder --- TSMessages/Classes/TSMessage.m | 3 --- 1 file changed, 3 deletions(-) diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index 28e2c9a0..2af2c619 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -30,9 +30,6 @@ @implementation TSMessage static TSMessage *sharedMessage; static BOOL notificationActive; -static BOOL _useiOS7Style; - - __weak static UIViewController *_defaultViewController; + (TSMessage *)sharedMessage From 4e5377f3d88a2668f33bce51c58ab7a93a3c0e53 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Sun, 16 Feb 2014 22:20:15 +0100 Subject: [PATCH 07/27] Fix check for image from custom design file --- TSMessages/Views/TSMessageView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index b3a8c81d..1a8845f5 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -140,7 +140,7 @@ - (id)initWithTitle:(NSString *)title current = [notificationDesign valueForKey:currentString]; - if (!image && [current valueForKey:@"imageName"]) + if (!image && [current valueForKey:@"imageName"] != [NSNull null] && [[current valueForKey:@"imageName"] length]) { image = [UIImage imageNamed:[current valueForKey:@"imageName"]]; } From 0ae292741b479efb54af7b61161a7bb6c3854590 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Mon, 17 Feb 2014 22:37:30 +0100 Subject: [PATCH 08/27] Refactor initializers --- .../xcshareddata/Example.xccheckout | 14 +- ExampleProject/Example/TSDemoViewController.h | 2 - ExampleProject/Example/TSDemoViewController.m | 204 +++--- .../Pods/Pods.xcodeproj/project.pbxproj | 2 + TSMessages/Classes/TSMessage.h | 149 ++--- TSMessages/Classes/TSMessage.m | 324 ++++------ TSMessages/Views/TSBlurView.h | 2 - TSMessages/Views/TSBlurView.m | 3 - TSMessages/Views/TSMessageView+Private.h | 18 + TSMessages/Views/TSMessageView.h | 65 +- TSMessages/Views/TSMessageView.m | 579 ++++++++---------- 11 files changed, 612 insertions(+), 750 deletions(-) create mode 100644 TSMessages/Views/TSMessageView+Private.h diff --git a/ExampleProject/Example.xcworkspace/xcshareddata/Example.xccheckout b/ExampleProject/Example.xcworkspace/xcshareddata/Example.xccheckout index 053192aa..b196e01a 100644 --- a/ExampleProject/Example.xcworkspace/xcshareddata/Example.xccheckout +++ b/ExampleProject/Example.xcworkspace/xcshareddata/Example.xccheckout @@ -5,34 +5,34 @@ IDESourceControlProjectFavoriteDictionaryKey IDESourceControlProjectIdentifier - 82A6ACD6-46DE-447A-A964-E17104032B30 + AE4EFDAC-4D12-4D15-A6B2-1AAEAC767CAB IDESourceControlProjectName Example IDESourceControlProjectOriginsDictionary - D20D76B5-659E-40F1-BC19-299E96EF607D - https://github.com/onato/TSMessages.git + CBF9685F-3E4F-4E6C-92E3-4DF0D18A1180 + ssh://github.com/dennisreimann/TSMessages.git IDESourceControlProjectPath ExampleProject/Example.xcworkspace IDESourceControlProjectRelativeInstallPathDictionary - D20D76B5-659E-40F1-BC19-299E96EF607D + CBF9685F-3E4F-4E6C-92E3-4DF0D18A1180 ../.. IDESourceControlProjectURL - https://github.com/onato/TSMessages.git + ssh://github.com/dennisreimann/TSMessages.git IDESourceControlProjectVersion 110 IDESourceControlProjectWCCIdentifier - D20D76B5-659E-40F1-BC19-299E96EF607D + CBF9685F-3E4F-4E6C-92E3-4DF0D18A1180 IDESourceControlProjectWCConfigurations IDESourceControlRepositoryExtensionIdentifierKey public.vcs.git IDESourceControlWCCIdentifierKey - D20D76B5-659E-40F1-BC19-299E96EF607D + CBF9685F-3E4F-4E6C-92E3-4DF0D18A1180 IDESourceControlWCCName TSMessages diff --git a/ExampleProject/Example/TSDemoViewController.h b/ExampleProject/Example/TSDemoViewController.h index 00e581c3..c5850d4b 100644 --- a/ExampleProject/Example/TSDemoViewController.h +++ b/ExampleProject/Example/TSDemoViewController.h @@ -10,7 +10,6 @@ #import "TSMessageView.h" @interface TSDemoViewController : UIViewController - - (IBAction)didTapError:(id)sender; - (IBAction)didTapWarning:(id)sender; - (IBAction)didTapMessage:(id)sender; @@ -23,5 +22,4 @@ - (IBAction)didTapText:(id)sender; - (IBAction)didTapCustomDesign:(id)sender; - (IBAction)didTapPermanent:(id)sender; - @end diff --git a/ExampleProject/Example/TSDemoViewController.m b/ExampleProject/Example/TSDemoViewController.m index 11c85348..6bc7b55d 100644 --- a/ExampleProject/Example/TSDemoViewController.m +++ b/ExampleProject/Example/TSDemoViewController.m @@ -33,13 +33,15 @@ - (void)viewDidLoad [self.navigationController.navigationBar setTranslucent:YES]; } -- (void)setHideStatusbar:(BOOL)hideStatusbar { +- (void)setHideStatusbar:(BOOL)hideStatusbar +{ _hideStatusbar = hideStatusbar; [self setNeedsStatusBarAppearanceUpdate]; } -- (BOOL)prefersStatusBarHidden { +- (BOOL)prefersStatusBarHidden +{ return self.hideStatusbar; } @@ -52,93 +54,104 @@ - (CGFloat)navigationbarBottomOfViewController:(UIViewController *)viewControlle - (IBAction)didTapError:(id)sender { - [TSMessage showNotificationWithTitle:NSLocalizedString(@"Something failed", nil) - subtitle:NSLocalizedString(@"The internet connection seems to be down. Please check that!", nil) - type:TSMessageNotificationTypeError]; + TSMessageView *messageView = [TSMessage showNotificationWithTitle:NSLocalizedString(@"Something failed", nil) + subtitle:NSLocalizedString(@"The internet connection seems to be down. Please check that!", nil) + type:TSMessageNotificationTypeError]; + [messageView setUserDismissEnabled]; } - (IBAction)didTapWarning:(id)sender { - [TSMessage showNotificationWithTitle:NSLocalizedString(@"Some random warning", nil) - subtitle:NSLocalizedString(@"Look out! Something is happening there!", nil) - type:TSMessageNotificationTypeWarning]; + TSMessageView *messageView = [TSMessage showNotificationWithTitle:NSLocalizedString(@"Some random warning", nil) + subtitle:NSLocalizedString(@"Look out! Something is happening there!", nil) + type:TSMessageNotificationTypeWarning]; + [messageView setUserDismissEnabled]; } - (IBAction)didTapMessage:(id)sender { - [TSMessage showNotificationWithTitle:NSLocalizedString(@"Tell the user something", nil) - subtitle:NSLocalizedString(@"This is some neutral notification!", nil) - type:TSMessageNotificationTypeMessage]; + TSMessageView *messageView = [TSMessage showNotificationWithTitle:NSLocalizedString(@"Tell the user something", nil) + subtitle:NSLocalizedString(@"This is some neutral notification!", nil) + type:TSMessageNotificationTypeMessage]; + [messageView setUserDismissEnabled]; } - (IBAction)didTapSuccess:(id)sender { - [TSMessage showNotificationWithTitle:NSLocalizedString(@"Success", nil) - subtitle:NSLocalizedString(@"Some task was successfully completed!", nil) - type:TSMessageNotificationTypeSuccess]; + TSMessageView *messageView = [TSMessage showNotificationWithTitle:NSLocalizedString(@"Success", nil) + subtitle:NSLocalizedString(@"Some task was successfully completed!", nil) + type:TSMessageNotificationTypeSuccess]; + [messageView setUserDismissEnabled]; } - (IBAction)didTapButton:(id)sender { - [TSMessage showNotificationInViewController:self - title:NSLocalizedString(@"New version available", nil) - subtitle:NSLocalizedString(@"Please update our app. We would be very thankful", nil) - image:nil - type:TSMessageNotificationTypeMessage - duration:TSMessageNotificationDurationAutomatic - callback:nil - buttonTitle:NSLocalizedString(@"Update", nil) - buttonCallback:^(TSMessageView *messageView){ - [TSMessage showNotificationWithTitle:NSLocalizedString(@"Thanks for updating", nil) - type:TSMessageNotificationTypeSuccess]; - } - atPosition:TSMessageNotificationPositionTop - canBeDismissedByUser:YES]; -} - -- (IBAction)didTapPermanent:(id)sender { - [TSMessage showPermanentNotificationInViewController:self - title:NSLocalizedString(@"Permanent notification", nil) - subtitle:NSLocalizedString(@"Stays here until it gets dismissed", nil) - image:nil - type:TSMessageNotificationTypeMessage - callback:^(TSMessageView *messageView) { - [TSMessage showNotificationWithTitle:NSLocalizedString(@"Action triggered", nil) - type:TSMessageNotificationTypeSuccess]; - } buttonTitle:NSLocalizedString(@"Dismiss", nil) - buttonCallback:^(TSMessageView *messageView) { - [messageView fadeMeOut]; - } atPosition:TSMessageNotificationPositionBottom - canBeDismissedByUser:NO]; -} - -- (IBAction)didTapToggleNavigationBar:(id)sender { + TSMessageView *view = [TSMessage notificationWithTitle:NSLocalizedString(@"New version available", nil) + subtitle:NSLocalizedString(@"Please update our app. We would be very thankful", nil) + type:TSMessageNotificationTypeMessage]; + + [view setButtonWithTitle:NSLocalizedString(@"Update", nil) callback:^(TSMessageView *messageView) { + [messageView dismiss]; + + [TSMessage showNotificationWithTitle:NSLocalizedString(@"Thanks for updating", nil) subtitle:nil type:TSMessageNotificationTypeSuccess]; + }]; + + [view setUserDismissEnabled]; + + [TSMessage prepareNotificationToBeShown:view]; +} + +- (IBAction)didTapPermanent:(id)sender +{ + TSMessageView *view = [TSMessage notificationWithTitle:NSLocalizedString(@"Permanent notification", nil) + subtitle:NSLocalizedString(@"Stays here until it gets dismissed", nil) + type:TSMessageNotificationTypeMessage]; + + view.position = TSMessageNotificationPositionBottom; + + [view setButtonWithTitle:NSLocalizedString(@"Dismiss", nil) callback:^(TSMessageView *messageView) { + [messageView dismiss]; + }]; + + view.tapCallback = ^(TSMessageView *messageView) { + [TSMessage showNotificationWithTitle:NSLocalizedString(@"Action triggered", nil) subtitle:nil type:TSMessageNotificationTypeSuccess]; + }; + + [view setUserDismissEnabled]; + + [TSMessage showPermanentNotification:view]; +} + +- (IBAction)didTapToggleNavigationBar:(id)sender +{ [self.navigationController setNavigationBarHidden:!self.navigationController.navigationBarHidden animated:YES]; } -- (IBAction)didTapToggleNavigationBarAlpha:(id)sender { +- (IBAction)didTapToggleNavigationBarAlpha:(id)sender +{ CGFloat alpha = self.navigationController.navigationBar.alpha; self.navigationController.navigationBar.alpha = (alpha == 1.f) ? 0.5 : 1; } -- (IBAction)didTapToggleStatusbar:(id)sender { +- (IBAction)didTapToggleStatusbar:(id)sender +{ self.hideStatusbar = !self.hideStatusbar; } - (IBAction)didTapCustomImage:(id)sender { - [TSMessage showNotificationInViewController:self - title:NSLocalizedString(@"Custom image", nil) - subtitle:NSLocalizedString(@"This uses an image you can define", nil) - image:[UIImage imageNamed:@"NotificationButtonBackground.png"] - type:TSMessageNotificationTypeMessage - duration:TSMessageNotificationDurationAutomatic - callback:nil - buttonTitle:nil - buttonCallback:nil - atPosition:TSMessageNotificationPositionTop - canBeDismissedByUser:YES]; + UIImage *image = [UIImage imageNamed:@"NotificationButtonBackground.png"]; + + TSMessageView *messageView = [TSMessage notificationWithTitle:NSLocalizedString(@"Custom image", nil) + subtitle:NSLocalizedString(@"This uses an image you can define", nil) + image:image + type:TSMessageNotificationTypeMessage + inViewController:self]; + + [messageView setUserDismissEnabled]; + + [TSMessage prepareNotificationToBeShown:messageView]; } - (IBAction)didTapDismissCurrentMessage:(id)sender @@ -148,63 +161,60 @@ - (IBAction)didTapDismissCurrentMessage:(id)sender - (IBAction)didTapEndless:(id)sender { - [TSMessage showNotificationInViewController:self - title:NSLocalizedString(@"Endless", nil) - subtitle:NSLocalizedString(@"This message can not be dismissed and will not be hidden automatically. Tap the 'Dismiss' button to dismiss the currently shown message", nil) - image:nil - type:TSMessageNotificationTypeSuccess - duration:TSMessageNotificationDurationEndless - callback:nil - buttonTitle:nil - buttonCallback:nil - atPosition:TSMessageNotificationPositionTop - canBeDismissedByUser:NO]; + TSMessageView *messageView = [TSMessage notificationWithTitle:NSLocalizedString(@"Endless", nil) + subtitle:NSLocalizedString(@"This message can not be dismissed and will not be hidden automatically. Tap the 'Dismiss' button to dismiss the currently shown message", nil) + type:TSMessageNotificationTypeSuccess]; + + messageView.duration = TSMessageNotificationDurationEndless; + + [TSMessage prepareNotificationToBeShown:messageView]; } - (IBAction)didTapLong:(id)sender { - [TSMessage showNotificationInViewController:self - title:NSLocalizedString(@"Long", nil) - subtitle:NSLocalizedString(@"This message is displayed 10 seconds instead of the calculated value", nil) - image:nil - type:TSMessageNotificationTypeWarning - duration:10.0 - callback:nil - buttonTitle:nil - buttonCallback:nil - atPosition:TSMessageNotificationPositionTop - canBeDismissedByUser:YES]; + TSMessageView *messageView = [TSMessage notificationWithTitle:NSLocalizedString(@"Long", nil) + subtitle:NSLocalizedString(@"This message is displayed 10 seconds instead of the calculated value", nil) + type:TSMessageNotificationTypeWarning]; + messageView.duration = 10.0; + + [messageView setUserDismissEnabled]; + + [TSMessage prepareNotificationToBeShown:messageView]; } - (IBAction)didTapBottom:(id)sender { - [TSMessage showNotificationInViewController:self - title:NSLocalizedString(@"Hu!", nil) - subtitle:NSLocalizedString(@"I'm down here :)", nil) - image:nil - type:TSMessageNotificationTypeSuccess - duration:TSMessageNotificationDurationAutomatic - callback:nil - buttonTitle:nil - buttonCallback:nil - atPosition:TSMessageNotificationPositionBottom - canBeDismissedByUser:YES]; + TSMessageView *messageView = [TSMessage notificationWithTitle:NSLocalizedString(@"Hu!", nil) + subtitle:NSLocalizedString(@"I'm down here :)", nil) + type:TSMessageNotificationTypeSuccess]; + + messageView.duration = TSMessageNotificationDurationAutomatic; + messageView.position = TSMessageNotificationPositionBottom; + + [messageView setUserDismissEnabled]; + + [TSMessage prepareNotificationToBeShown:messageView]; } - (IBAction)didTapText:(id)sender { - [TSMessage showNotificationWithTitle:NSLocalizedString(@"With 'Text' I meant a long text, so here it is", nil) - subtitle:NSLocalizedString(@"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus", nil) - type:TSMessageNotificationTypeWarning]; + TSMessageView *messageView = [TSMessage showNotificationWithTitle:NSLocalizedString(@"With 'Text' I meant a long text, so here it is", nil) + subtitle:NSLocalizedString(@"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus", nil) + type:TSMessageNotificationTypeWarning]; + + [messageView setUserDismissEnabled]; } - (IBAction)didTapCustomDesign:(id)sender { // this is an example on how to apply a custom design [TSMessage addCustomDesignFromFileWithName:@"AlternativeDesign.json"]; - [TSMessage showNotificationWithTitle:NSLocalizedString(@"Updated to custom design file", nil) + + TSMessageView *messageView = [TSMessage showNotificationWithTitle:NSLocalizedString(@"Updated to custom design file", nil) subtitle:NSLocalizedString(@"From now on, all the titles of success messages are larger", nil) type:TSMessageNotificationTypeSuccess]; + + [messageView setUserDismissEnabled]; } @end diff --git a/ExampleProject/Pods/Pods.xcodeproj/project.pbxproj b/ExampleProject/Pods/Pods.xcodeproj/project.pbxproj index 804cee70..90d676b2 100644 --- a/ExampleProject/Pods/Pods.xcodeproj/project.pbxproj +++ b/ExampleProject/Pods/Pods.xcodeproj/project.pbxproj @@ -58,6 +58,7 @@ 24F689F22A5A42809DBA68A7 /* TSBlurView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = TSBlurView.m; path = TSMessages/Views/TSBlurView.m; sourceTree = ""; }; 29BDFA547266427AA426611F /* Pods-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-resources.sh"; sourceTree = ""; }; 2E35B5F218AED63C0000C422 /* TSMessage+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "TSMessage+Private.h"; path = "TSMessages/Classes/TSMessage+Private.h"; sourceTree = ""; }; + 2EA90CF918B2AB60008B71EF /* TSMessageView+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "TSMessageView+Private.h"; path = "TSMessages/Views/TSMessageView+Private.h"; sourceTree = ""; }; 3B17E30CA6F248738B1CCE1F /* TSBlurView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = TSBlurView.h; path = TSMessages/Views/TSBlurView.h; sourceTree = ""; }; 3DED0B6E248A4FBEB11DFB7D /* Pods-HexColors-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-HexColors-prefix.pch"; sourceTree = ""; }; 3EEBBA57508D41E99C45BA64 /* NotificationButtonBackground@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationButtonBackground@2x.png"; path = "TSMessages/Resources/Images/NotificationButtonBackground@2x.png"; sourceTree = ""; }; @@ -152,6 +153,7 @@ E6F8608730F84A098DEB8A05 /* TSMessage.h */, 2E35B5F218AED63C0000C422 /* TSMessage+Private.h */, 53202C8D4E6B4B018F7C74D6 /* TSMessageView.h */, + 2EA90CF918B2AB60008B71EF /* TSMessageView+Private.h */, 24F689F22A5A42809DBA68A7 /* TSBlurView.m */, 09E89CC7D8724A98B872DF42 /* TSMessage.m */, BEBBB8EDFAD74B189406A0B0 /* TSMessageView.m */, diff --git a/TSMessages/Classes/TSMessage.h b/TSMessages/Classes/TSMessage.h index 1e94ac90..f86075c5 100755 --- a/TSMessages/Classes/TSMessage.h +++ b/TSMessages/Classes/TSMessage.h @@ -25,28 +25,25 @@ #endif #endif - -#define TS_SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) - +#define TS_SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) @class TSMessageView; typedef NS_ENUM(NSInteger, TSMessageNotificationType) { TSMessageNotificationTypeMessage = 0, + TSMessageNotificationTypeSuccess, TSMessageNotificationTypeWarning, - TSMessageNotificationTypeError, - TSMessageNotificationTypeSuccess + TSMessageNotificationTypeError }; + typedef NS_ENUM(NSInteger, TSMessageNotificationPosition) { TSMessageNotificationPositionTop = 0, TSMessageNotificationPositionBottom }; -/** This enum can be passed to the duration parameter */ -typedef NS_ENUM(NSInteger,TSMessageNotificationDuration) { +typedef NS_ENUM(NSInteger, TSMessageNotificationDuration) { TSMessageNotificationDurationAutomatic = 0, TSMessageNotificationDurationEndless = -1, // The notification is displayed until the user dismissed it or it is dismissed by calling dismissActiveNotification - TSMessageNotificationDurationPermanent = -2 // Just like endless, but does not prevent }; typedef void (^TSMessageCallback)(TSMessageView *messageView); @@ -57,113 +54,99 @@ typedef void (^TSMessageCallback)(TSMessageView *messageView); + (UIViewController *)defaultViewController; -/** Shows a notification message - @param message The title of the notification view - @param type The notification type (Message, Warning, Error, Success) - */ -+ (void)showNotificationWithTitle:(NSString *)message - type:(TSMessageNotificationType)type; +/** Returns a message view for further customization -/** Shows a notification message @param title The title of the notification view @param subtitle The text that is displayed underneath the title @param type The notification type (Message, Warning, Error, Success) + + @return The message view */ -+ (void)showNotificationWithTitle:(NSString *)title - subtitle:(NSString *)subtitle - type:(TSMessageNotificationType)type; ++ (TSMessageView *)notificationWithTitle:(NSString *)title + subtitle:(NSString *)subtitle + type:(TSMessageNotificationType)type; + +/** Shows a notification right away and returns the message view -/** Shows a notification message in a specific view controller - @param viewController The view controller to show the notification in. - You can use +setDefaultViewController: to set the the default one instead @param title The title of the notification view @param subtitle The text that is displayed underneath the title @param type The notification type (Message, Warning, Error, Success) + + @return The message view */ -+ (void)showNotificationInViewController:(UIViewController *)viewController - title:(NSString *)title - subtitle:(NSString *)subtitle - type:(TSMessageNotificationType)type; ++ (TSMessageView *)showNotificationWithTitle:(NSString *)title + subtitle:(NSString *)subtitle + type:(TSMessageNotificationType)type; -/** Shows a notification message in a specific view controller - @param viewController The view controller to show the notification in. +/** Returns a message view in a specific view controller for further customization + @param title The title of the notification view @param subtitle The message that is displayed underneath the title (optional) @param image A custom icon image (optional) @param type The notification type (Message, Warning, Error, Success) - @param duration The duration of the notification being displayed - @param callback The block that should be executed, when the user tapped on the message - @param buttonTitle The title for button (optional) - @param buttonCallback The block that should be executed, when the user tapped on the button - @param messagePosition The position of the message on the screen - @param dismissingEnabled Should the message be dismissed when the user taps/swipes it + @param viewController The view controller to show the notification in + + @return The message view */ -+ (void)showNotificationInViewController:(UIViewController *)viewController - title:(NSString *)title ++ (TSMessageView *)notificationWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageNotificationType)type - duration:(NSTimeInterval)duration - callback:(TSMessageCallback)callback - buttonTitle:(NSString *)buttonTitle - buttonCallback:(TSMessageCallback)buttonCallback - atPosition:(TSMessageNotificationPosition)messagePosition - canBeDismissedByUser:(BOOL)dismissingEnabled; - -/** Shows a permanent notification message in a specific view controller - This differs from normal notifications in that permanent messages are not - contained in the messages queue and can be displayed in addition to the - other messages. - - Permanent notifications do not get dismissed automatically, hence they do - not have a duration but have to be dismissed by the user or programmatically - in one of the callbacks. - This constructor for a permanent message also returns the instance of the - message view, so that one can also capture it and dismiss it with other - custom events. + inViewController:(UIViewController *)viewController; - @param viewController The view controller to show the notification in. +/** Shows a notification right away in a specific view controller and returns + the message view + @param title The title of the notification view - @param subtitle The message that is displayed underneath the title (optional) + @param subtitle The text that is displayed underneath the title @param image A custom icon image (optional) @param type The notification type (Message, Warning, Error, Success) - @param duration The duration of the notification being displayed - @param callback The block that should be executed, when the user tapped on the message - @param buttonTitle The title for button (optional) - @param buttonCallback The block that should be executed, when the user tapped on the button - @param messagePosition The position of the message on the screen - @param dismissingEnabled Should the message be dismissed when the user taps/swipes it + @param viewController The view controller to show the notification in + + @return The message view */ -+ (TSMessageView *)showPermanentNotificationInViewController:(UIViewController *)viewController - title:(NSString *)title - subtitle:(NSString *)subtitle - image:(UIImage *)image - type:(TSMessageNotificationType)type - callback:(TSMessageCallback)callback - buttonTitle:(NSString *)buttonTitle - buttonCallback:(TSMessageCallback)buttonCallback - atPosition:(TSMessageNotificationPosition)messagePosition - canBeDismissedByUser:(BOOL)dismissingEnabled; - -/** Fades out the currently displayed notification. If another notification is in the queue, - the next one will be displayed automatically - @return YES if the currently displayed notification was successfully dismissed. NO if no notification - was currently displayed. - */ -+ (BOOL)dismissActiveNotification; ++ (TSMessageView *)showNotificationWithTitle:(NSString *)title + subtitle:(NSString *)subtitle + image:(UIImage *)image + type:(TSMessageNotificationType)type + inViewController:(UIViewController *)viewController; /** Use this method to set a default view controller to display the messages in */ + (void)setDefaultViewController:(UIViewController *)defaultViewController; -/** Use this method to use custom designs in your messages. */ +/** Use this method to use custom designs for your messages. */ + (void)addCustomDesignFromFileWithName:(NSString *)fileName; -/** Indicates whether a notification is currently active. */ +/** Fades out the currently displayed notification. If another notification is in the queue, + the next one will be displayed automatically + + @return YES if the currently displayed notification was successfully dismissed. + NO if no notification was currently displayed. + */ ++ (BOOL)dismissActiveNotification; + +/** Indicates whether a notification is currently active. + + @return YES if a notification is currently being displayed. + NO if no notification is currently being displayed. + */ + (BOOL)isNotificationActive; -/** Prepares the notification view to be displayed in the future. It is queued and then - displayed in fadeInCurrentNotification. - You don't have to use this method. */ +/** Prepares the notification view to be displayed in the future. + It is queued and then displayed in fadeInCurrentNotification. + */ + (void)prepareNotificationToBeShown:(TSMessageView *)messageView; +/** Shows a permanent notification message. + + This differs from normal notifications in that permanent messages are not + contained in the messages queue and can be displayed in addition to the + other messages. + + Permanent notifications do not get dismissed automatically, hence they do + not have a duration but have to be dismissed by the user or programmatically + in one of the callbacks. + */ ++ (void)showPermanentNotification:(TSMessageView *)messageView; + @end diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index 2af2c619..efe69f55 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -8,133 +8,81 @@ #import "TSMessage.h" #import "TSMessageView.h" +#import "TSMessageView+Private.h" #define kTSMessageDisplayTime 1.5 -#define kTSMessageExtraDisplayTimePerPixel 0.04 #define kTSMessageAnimationDuration 0.3 - - +#define kTSMessageExtraDisplayTimePerPixel 0.04 @interface TSMessage () - -/** The queued messages (TSMessageView objects) */ @property (nonatomic, strong) NSMutableArray *messages; - -- (void)fadeInCurrentNotification; -- (void)fadeOutCurrentNotification; - @end @implementation TSMessage -static TSMessage *sharedMessage; -static BOOL notificationActive; +static TSMessage *_sharedMessage; +static BOOL _notificationActive; __weak static UIViewController *_defaultViewController; + (TSMessage *)sharedMessage { - if (!sharedMessage) + if (!_sharedMessage) { - sharedMessage = [[[self class] alloc] init]; + _sharedMessage = [[[self class] alloc] init]; } - return sharedMessage; + + return _sharedMessage; } - -#pragma mark Public methods for setting up the notification - -+ (void)showNotificationWithTitle:(NSString *)title - type:(TSMessageNotificationType)type +- (id)init { - [self showNotificationWithTitle:title - subtitle:nil - type:type]; + if ((self = [super init])) + { + _messages = [[NSMutableArray alloc] init]; + } + + return self; } -+ (void)showNotificationWithTitle:(NSString *)title - subtitle:(NSString *)subtitle - type:(TSMessageNotificationType)type +#pragma mark - Setup notifications + ++ (TSMessageView *)notificationWithTitle:(NSString *)title subtitle:(NSString *)subtitle type:(TSMessageNotificationType)type { - [self showNotificationInViewController:[self defaultViewController] - title:title - subtitle:subtitle - type:type]; + return [self notificationWithTitle:title subtitle:subtitle image:nil type:type inViewController:self.defaultViewController]; } -+ (void)showNotificationInViewController:(UIViewController *)viewController - title:(NSString *)title - subtitle:(NSString *)subtitle - type:(TSMessageNotificationType)type ++ (TSMessageView *)notificationWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageNotificationType)type inViewController:(UIViewController *)viewController { - [self showNotificationInViewController:viewController - title:title - subtitle:subtitle - image:nil - type:type - duration:TSMessageNotificationDurationAutomatic - callback:nil - buttonTitle:nil - buttonCallback:nil - atPosition:TSMessageNotificationPositionTop - canBeDismissedByUser:YES]; + TSMessageView *view = [[TSMessageView alloc] initWithTitle:title subtitle:subtitle image:image type:type]; + + view.viewController = viewController; + + return view; } +#pragma mark - Setup notifications and display them right away -+ (void)showNotificationInViewController:(UIViewController *)viewController - title:(NSString *)title - subtitle:(NSString *)subtitle - image:(UIImage *)image - type:(TSMessageNotificationType)type - duration:(NSTimeInterval)duration - callback:(TSMessageCallback)callback - buttonTitle:(NSString *)buttonTitle - buttonCallback:(TSMessageCallback)buttonCallback - atPosition:(TSMessageNotificationPosition)messagePosition - canBeDismissedByUser:(BOOL)dismissingEnabled ++ (TSMessageView *)showNotificationWithTitle:(NSString *)title subtitle:(NSString *)subtitle type:(TSMessageNotificationType)type { - // Create the TSMessageView - TSMessageView *v = [[TSMessageView alloc] initWithTitle:title - subtitle:subtitle - image:image - type:type - duration:duration - inViewController:viewController - callback:callback - buttonTitle:buttonTitle - buttonCallback:buttonCallback - atPosition:messagePosition - canBeDismissedByUser:dismissingEnabled]; - [self prepareNotificationToBeShown:v]; + return [self showNotificationWithTitle:title subtitle:subtitle image:nil type:type inViewController:self.defaultViewController]; } -+ (TSMessageView *)showPermanentNotificationInViewController:(UIViewController *)viewController - title:(NSString *)title - subtitle:(NSString *)subtitle - image:(UIImage *)image - type:(TSMessageNotificationType)type - callback:(TSMessageCallback)callback - buttonTitle:(NSString *)buttonTitle - buttonCallback:(TSMessageCallback)buttonCallback - atPosition:(TSMessageNotificationPosition)messagePosition - canBeDismissedByUser:(BOOL)dismissingEnabled { - TSMessageView *v = [[TSMessageView alloc] initWithTitle:title - subtitle:subtitle - image:image - type:type - duration:TSMessageNotificationDurationEndless - inViewController:viewController - callback:callback - buttonTitle:buttonTitle - buttonCallback:buttonCallback - atPosition:messagePosition - canBeDismissedByUser:dismissingEnabled]; - - [[TSMessage sharedMessage] fadeInNotification:v]; - - return v; ++ (TSMessageView *)showNotificationWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageNotificationType)type inViewController:(UIViewController *)viewController +{ + TSMessageView *view = [self notificationWithTitle:title subtitle:subtitle image:image type:type inViewController:viewController]; + + [self prepareNotificationToBeShown:view]; + + return view; } +#pragma mark - Displaying notifications + ++ (void)showPermanentNotification:(TSMessageView *)messageView +{ + [[TSMessage sharedMessage] fadeInNotification:messageView]; +} + (void)prepareNotificationToBeShown:(TSMessageView *)messageView { @@ -143,52 +91,86 @@ + (void)prepareNotificationToBeShown:(TSMessageView *)messageView for (TSMessageView *n in [TSMessage sharedMessage].messages) { - if (([n.title isEqualToString:title] || (!n.title && !title)) && ([n.subtitle isEqualToString:subtitle] || (!n.subtitle && !subtitle))) - { - return; // avoid showing the same messages twice in a row - } + // avoid showing the same messages twice in a row + BOOL equalTitle = ([n.title isEqualToString:title] || (!n.title && !title)); + BOOL equalSubtitle = ([n.subtitle isEqualToString:subtitle] || (!n.subtitle && !subtitle)); + + if (equalTitle && equalSubtitle) return; } [[TSMessage sharedMessage].messages addObject:messageView]; - if (!notificationActive) + if (!_notificationActive) { [[TSMessage sharedMessage] fadeInCurrentNotification]; } } ++ (BOOL)dismissActiveNotification +{ + if (![TSMessage sharedMessage].currentNotification) return NO; + + dispatch_async(dispatch_get_main_queue(), ^{ + [[TSMessage sharedMessage] fadeOutCurrentNotification]; + }); + + return YES; +} -#pragma mark Fading in/out the message view ++ (BOOL)isNotificationActive +{ + return _notificationActive; +} -- (id)init +#pragma mark - Customizing notifications + ++ (void)addCustomDesignFromFileWithName:(NSString *)fileName { - if ((self = [super init])) - { - _messages = [[NSMutableArray alloc] init]; - } - return self; + [TSMessageView addNotificationDesignFromFile:fileName]; } -- (TSMessageView *)currentNotification { - if ([self.messages count] > 0) +#pragma mark - Default view controller + ++ (UIViewController *)defaultViewController +{ + __strong UIViewController *defaultViewController = _defaultViewController; + + if (!defaultViewController) { - return [self.messages objectAtIndex:0]; + NSLog(@"TSMessages: It is recommended to set a custom defaultViewController that is used to display the notifications"); + defaultViewController = [UIApplication sharedApplication].keyWindow.rootViewController; } + + return defaultViewController; +} - return nil; ++ (void)setDefaultViewController:(UIViewController *)defaultViewController +{ + _defaultViewController = defaultViewController; +} + +#pragma mark - Internals + +- (TSMessageView *)currentNotification +{ + if (!self.messages.count) return nil; + + return [self.messages firstObject]; } - (void)fadeInCurrentNotification { if (!self.currentNotification) return; - notificationActive = YES; + _notificationActive = YES; [self fadeInNotification:self.currentNotification]; } - (void)fadeInNotification:(TSMessageView *)messageView { + [messageView prepareForDisplay]; + __block CGFloat verticalOffset = 0.0f; void (^addStatusBarHeightToVerticalOffset)() = ^void() { @@ -204,16 +186,22 @@ - (void)fadeInNotification:(TSMessageView *)messageView UIViewController *viewController = messageView.viewController; if ([viewController isKindOfClass:[UINavigationController class]]) + { navigationController = (UINavigationController *)viewController; + } else + { navigationController = (UINavigationController *)viewController.parentViewController; + } viewController = [[navigationController childViewControllers] firstObject]; BOOL isViewIsUnderStatusBar = ![viewController prefersStatusBarHidden]; - if (!isViewIsUnderStatusBar && navigationController.parentViewController == nil) { - isViewIsUnderStatusBar = ![navigationController isNavigationBarHidden]; // strange but true + if (!isViewIsUnderStatusBar && navigationController.parentViewController == nil) + { + // strange but true + isViewIsUnderStatusBar = ![navigationController isNavigationBarHidden]; } if (![navigationController isNavigationBarHidden]) @@ -226,7 +214,9 @@ - (void)fadeInNotification:(TSMessageView *)messageView else { [messageView.viewController.view addSubview:messageView]; - if (isViewIsUnderStatusBar) { + + if (isViewIsUnderStatusBar) + { addStatusBarHeightToVerticalOffset(); } } @@ -238,40 +228,40 @@ - (void)fadeInNotification:(TSMessageView *)messageView } CGPoint toPoint; - if (messageView.messagePosition == TSMessageNotificationPositionTop) + if (messageView.position == TSMessageNotificationPositionTop) { CGFloat navigationbarBottomOfViewController = 0; if (messageView.delegate && [messageView.delegate respondsToSelector:@selector(navigationbarBottomOfViewController:)]) + { navigationbarBottomOfViewController = [messageView.delegate navigationbarBottomOfViewController:messageView.viewController]; - - toPoint = CGPointMake(messageView.center.x, - navigationbarBottomOfViewController + verticalOffset + CGRectGetHeight(messageView.frame) / 2.0); + } + + toPoint = CGPointMake(messageView.center.x, navigationbarBottomOfViewController + verticalOffset + CGRectGetHeight(messageView.frame) / 2.0); } else { CGFloat y = messageView.viewController.view.bounds.size.height - CGRectGetHeight(messageView.frame) / 2.0; - if (!messageView.viewController.navigationController.isToolbarHidden) { + + if (!messageView.viewController.navigationController.isToolbarHidden) + { y -= CGRectGetHeight(messageView.viewController.navigationController.toolbar.bounds); } + toPoint = CGPointMake(messageView.center.x, y); } - dispatch_block_t animationBlock = ^{ - messageView.center = toPoint; - }; - - void(^completionBlock)(BOOL) = ^(BOOL finished) { - messageView.messageIsFullyDisplayed = YES; - }; - [UIView animateWithDuration:kTSMessageAnimationDuration + 0.1 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0.f options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction - animations:animationBlock - completion:completionBlock]; + animations:^{ + messageView.center = toPoint; + } + completion:^(BOOL finished) { + messageView.messageFullyDisplayed = YES; + }]; if (messageView.duration == TSMessageNotificationDurationAutomatic) { @@ -280,12 +270,9 @@ - (void)fadeInNotification:(TSMessageView *)messageView if (messageView.duration != TSMessageNotificationDurationEndless) { - dispatch_async(dispatch_get_main_queue(), ^ - { - [self performSelector:@selector(fadeOutCurrentNotification) - withObject:nil - afterDelay:messageView.duration]; - }); + dispatch_async(dispatch_get_main_queue(), ^{ + [self performSelector:@selector(fadeOutCurrentNotification) withObject:nil afterDelay:messageView.duration]; + }); } } @@ -296,29 +283,25 @@ - (void)fadeOutNotification:(TSMessageView *)messageView - (void)fadeOutNotification:(TSMessageView *)messageView completion:(void (^)())completion { - messageView.messageIsFullyDisplayed = NO; + messageView.messageFullyDisplayed = NO; CGPoint fadeOutToPoint; - if (messageView.messagePosition == TSMessageNotificationPositionTop) + + if (messageView.position == TSMessageNotificationPositionTop) { fadeOutToPoint = CGPointMake(messageView.center.x, -CGRectGetHeight(messageView.frame)/2.f); } else { - fadeOutToPoint = CGPointMake(messageView.center.x, - messageView.viewController.view.bounds.size.height + CGRectGetHeight(messageView.frame)/2.f); + fadeOutToPoint = CGPointMake(messageView.center.x, messageView.viewController.view.bounds.size.height + CGRectGetHeight(messageView.frame)/2.f); } - [UIView animateWithDuration:kTSMessageAnimationDuration animations:^ - { + [UIView animateWithDuration:kTSMessageAnimationDuration animations:^{ messageView.center = fadeOutToPoint; - } completion:^(BOOL finished) - { + } completion:^(BOOL finished) { [messageView removeFromSuperview]; - if (completion) { - completion(); - } + if (completion) completion(); }]; } @@ -326,64 +309,21 @@ - (void)fadeOutCurrentNotification { if (!self.currentNotification) return; - [NSObject cancelPreviousPerformRequestsWithTarget:self - selector:@selector(fadeOutCurrentNotification) - object:nil]; + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(fadeOutCurrentNotification) object:nil]; [self fadeOutNotification:self.currentNotification completion:^{ - if ([self.messages count] > 0) + if (self.messages.count) { [self.messages removeObjectAtIndex:0]; } - notificationActive = NO; + _notificationActive = NO; - if ([self.messages count] > 0) + if (self.messages.count) { [self fadeInCurrentNotification]; } }]; } -+ (BOOL)dismissActiveNotification -{ - if (![TSMessage sharedMessage].currentNotification) return NO; - - dispatch_async(dispatch_get_main_queue(), ^ - { - [[TSMessage sharedMessage] fadeOutCurrentNotification]; - }); - return YES; -} - -#pragma mark Customizing TSMessages - -+ (void)setDefaultViewController:(UIViewController *)defaultViewController -{ - _defaultViewController = defaultViewController; -} - -+ (void)addCustomDesignFromFileWithName:(NSString *)fileName -{ - [TSMessageView addNotificationDesignFromFile:fileName]; -} - -#pragma mark Other methods - -+ (BOOL)isNotificationActive -{ - return notificationActive; -} - -+ (UIViewController *)defaultViewController -{ - __strong UIViewController *defaultViewController = _defaultViewController; - - if (!defaultViewController) { - NSLog(@"TSMessages: It is recommended to set a custom defaultViewController that is used to display the notifications"); - defaultViewController = [UIApplication sharedApplication].keyWindow.rootViewController; - } - return defaultViewController; -} - @end diff --git a/TSMessages/Views/TSBlurView.h b/TSMessages/Views/TSBlurView.h index 98509196..5581c732 100644 --- a/TSMessages/Views/TSBlurView.h +++ b/TSMessages/Views/TSBlurView.h @@ -9,7 +9,5 @@ #import @interface TSBlurView : UIView - @property (nonatomic, strong) UIColor *blurTintColor; - @end diff --git a/TSMessages/Views/TSBlurView.m b/TSMessages/Views/TSBlurView.m index 47714ce2..83bd1112 100644 --- a/TSMessages/Views/TSBlurView.m +++ b/TSMessages/Views/TSBlurView.m @@ -10,14 +10,11 @@ #import @interface TSBlurView () - @property (nonatomic, strong) UIToolbar *toolbar; - @end @implementation TSBlurView - - (UIToolbar *)toolbar { if (_toolbar == nil) { diff --git a/TSMessages/Views/TSMessageView+Private.h b/TSMessages/Views/TSMessageView+Private.h new file mode 100644 index 00000000..8ec40fea --- /dev/null +++ b/TSMessages/Views/TSMessageView+Private.h @@ -0,0 +1,18 @@ +// +// TSMessageView+Private.h +// Felix Krause +// +// Created by Felix Krause on 24.08.12. +// Copyright (c) 2012 Felix Krause. All rights reserved. +// + +#import +#import "TSMessageView.h" + +@interface TSMessageView (Private) +@property (nonatomic, readonly) NSString *title; +@property (nonatomic, readonly) NSString *subtitle; +@property (nonatomic, assign, getter = isMessageFullyDisplayed) BOOL messageFullyDisplayed; + +- (void)prepareForDisplay; +@end diff --git a/TSMessages/Views/TSMessageView.h b/TSMessages/Views/TSMessageView.h index 10132bd8..8403887d 100755 --- a/TSMessages/Views/TSMessageView.h +++ b/TSMessages/Views/TSMessageView.h @@ -11,70 +11,43 @@ #define TSMessageViewAlpha 0.95 - - @protocol TSMessageViewProtocol @optional /** Implement this method to pass a custom value for positioning the message view */ - (CGFloat)navigationbarBottomOfViewController:(UIViewController *)viewController; @end - - - @interface TSMessageView : UIView - -/** The displayed title of this message */ -@property (nonatomic, readonly) NSString *title; - -/** The displayed subtitle of this message */ -@property (nonatomic, readonly) NSString *subtitle; - /** The view controller this message is displayed in */ -@property (nonatomic, readonly) UIViewController *viewController; +@property (nonatomic, weak) UIViewController *viewController; + +/** Is the message currenlty fully displayed? Is set as soon as the message is really fully visible */ +@property (nonatomic, readonly) BOOL isMessageFullyDisplayed; /** The duration of the displayed message. If it is 0.0, it will automatically be calculated */ @property (nonatomic, assign) CGFloat duration; /** The position of the message (top or bottom) */ -@property (nonatomic, assign) TSMessageNotificationPosition messagePosition; - -/** Is the message currenlty fully displayed? Is set as soon as the message is really fully visible */ -@property (nonatomic, assign) BOOL messageIsFullyDisplayed; +@property (nonatomic, assign) TSMessageNotificationPosition position; /** By setting this delegate it's possible to set a custom offset for the notification view */ -@property(nonatomic, assign) id delegate; +@property(nonatomic, assign) id delegate; -/** Inits the notification view. Do not call this from outside this library. - @param title The title of the notification view - @param subtitle The subtitle of the notification view (optional) - @param image A custom icon image (optional) - @param notificationType The type (color) of the notification view - @param duration The duration this notification should be displayed (optional) - @param viewController The view controller this message should be displayed in - @param callback The block that should be executed, when the user tapped on the message - @param buttonTitle The title for button (optional) - @param buttonCallback The block that should be executed, when the user tapped on the button - @param position The position of the message on the screen - @param dismissingEnabled Should this message be dismissed when the user taps/swipes it? - */ -- (id)initWithTitle:(NSString *)title - subtitle:(NSString *)subtitle - image:(UIImage *)image - type:(TSMessageNotificationType)notificationType - duration:(CGFloat)duration - inViewController:(UIViewController *)viewController - callback:(TSMessageCallback)callback - buttonTitle:(NSString *)buttonTitle - buttonCallback:(TSMessageCallback)buttonCallback - atPosition:(TSMessageNotificationPosition)position -canBeDismissedByUser:(BOOL)dismissingEnabled; +/** The callback that should be invoked, when the user taps the message */ +@property (nonatomic, copy) TSMessageCallback tapCallback; -/** Fades out this notification view */ -- (void)fadeMeOut; +- (id)initWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageNotificationType)notificationType; -/** Use this method to load a custom design file */ -+ (void)addNotificationDesignFromFile:(NSString *)file; +/** Dismisses this notification view */ +- (void)dismiss; + +/** Adds a button with a callback that gets invoked when the button is tapped */ +- (void)setButtonWithTitle:(NSString *)title callback:(TSMessageCallback)callback; +/** Enables dismissing the message by swiping */ +- (void)setUserDismissEnabled; +- (void)setUserDismissEnabledWithCallback:(TSMessageCallback)callback; +/** Use this method to load a custom design file */ ++ (void)addNotificationDesignFromFile:(NSString *)file; @end diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index 1a8845f5..463e72d0 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -11,316 +11,229 @@ #import "TSBlurView.h" #import "TSMessage.h" #import "TSMessage+Private.h" - +#import "TSMessageView+Private.h" #define TSMessageViewPadding 15.0 - #define TSDesignFileName @"TSMessagesDefaultDesign.json" - static NSMutableDictionary *_notificationDesign; @interface TSMessageView () +@property (nonatomic) NSDictionary *config; +@property (nonatomic) UILabel *titleLabel; +@property (nonatomic) UILabel *contentLabel; +@property (nonatomic) UIImageView *iconImageView; +@property (nonatomic) UIButton *button; +@property (nonatomic) TSBlurView *backgroundBlurView; +@property (nonatomic, copy) TSMessageCallback buttonCallback; +@property (nonatomic, copy) TSMessageCallback dismissCallback; +@property (nonatomic, assign, getter = isMessageFullyDisplayed) BOOL messageFullyDisplayed; +@end -/** The displayed title of this message */ -@property (nonatomic, strong) NSString *title; - -/** The displayed subtitle of this message view */ -@property (nonatomic, strong) NSString *subtitle; +@implementation TSMessageView -/** The title of the added button */ -@property (nonatomic, strong) NSString *buttonTitle; +- (id)initWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageNotificationType)notificationType +{ + if ((self = [self init])) + { + self.duration = TSMessageNotificationDurationAutomatic; + self.position = TSMessageNotificationPositionTop; + + [self setupConfigForType:notificationType]; + [self setupBackgroundView]; + [self setupTitle:title]; + [self setupSubtitle:subtitle]; + [self setupImage:image]; + [self setupAutoresizing]; + [self setupTapHandler]; + } + + return self; +} -/** The view controller this message is displayed in */ -@property (nonatomic, strong) UIViewController *viewController; +#pragma mark - Setup helpers +- (void)setupConfigForType:(TSMessageNotificationType)notificationType +{ + NSString *config; + + switch (notificationType) + { + case TSMessageNotificationTypeError: config = @"error"; break; + case TSMessageNotificationTypeSuccess: config = @"success"; break; + case TSMessageNotificationTypeWarning: config = @"warning"; break; + + default: config = @"message"; break; + } + + self.config = [TSMessageView notificationDesign][config]; +} -/** Internal properties needed to resize the view on device rotation properly */ -@property (nonatomic, strong) UILabel *titleLabel; -@property (nonatomic, strong) UILabel *contentLabel; -@property (nonatomic, strong) UIImageView *iconImageView; -@property (nonatomic, strong) UIButton *button; -@property (nonatomic, strong) UIView *borderView; -@property (nonatomic, strong) UIImageView *backgroundImageView; -@property (nonatomic, strong) TSBlurView *backgroundBlurView; // Only used in iOS 7 +- (void)setupBackgroundView +{ + self.backgroundBlurView = [[TSBlurView alloc] init]; + self.backgroundBlurView.autoresizingMask = UIViewAutoresizingFlexibleWidth; + self.backgroundBlurView.blurTintColor = [UIColor colorWithHexString:self.config[@"backgroundColor"]]; + + [self addSubview:self.backgroundBlurView]; +} -@property (nonatomic, assign) CGFloat textSpaceLeft; -@property (nonatomic, assign) CGFloat textSpaceRight; +- (void)setupAutoresizing +{ + self.autoresizingMask = (self.position == TSMessageNotificationPositionTop) ? + (UIViewAutoresizingFlexibleWidth) : + (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); +} -@property (copy) TSMessageCallback callback; -@property (copy) TSMessageCallback buttonCallback; +- (void)setupTitle:(NSString *)title +{ + UIColor *fontColor = [UIColor colorWithHexString:self.config[@"textColor"] alpha:1]; + CGFloat fontSize = [self.config[@"titleFontSize"] floatValue]; + NSString *fontName = self.config[@"titleFontName"]; + + self.titleLabel = [[UILabel alloc] init]; + self.titleLabel.numberOfLines = 0; + self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; + self.titleLabel.shadowOffset = CGSizeMake([self.config[@"shadowOffsetX"] floatValue], [self.config[@"shadowOffsetY"] floatValue]); + self.titleLabel.shadowColor = [UIColor colorWithHexString:self.config[@"shadowColor"] alpha:1]; + self.titleLabel.backgroundColor = [UIColor clearColor]; + self.titleLabel.textColor = fontColor; + self.titleLabel.text = title; + self.titleLabel.font = fontName ? + [UIFont fontWithName:fontName size:fontSize] : + [UIFont boldSystemFontOfSize:fontSize]; + + [self addSubview:self.titleLabel]; +} -- (CGFloat)updateHeightOfMessageView; -- (void)layoutSubviews; +- (void)setupSubtitle:(NSString *)subtitle +{ + if (!subtitle.length) return; + + UIColor *contentTextColor = [UIColor colorWithHexString:self.config[@"contentTextColor"] alpha:1]; + UIColor *fontColor = [UIColor colorWithHexString:self.config[@"textColor"] alpha:1]; + CGFloat fontSize = [self.config[@"contentFontSize"] floatValue]; + NSString *fontName = self.config[@"contentFontName"]; + + if (!contentTextColor) contentTextColor = fontColor; + + self.contentLabel = [[UILabel alloc] init]; + self.contentLabel.numberOfLines = 0; + self.contentLabel.lineBreakMode = NSLineBreakByWordWrapping; + self.contentLabel.shadowOffset = CGSizeMake([self.config[@"shadowOffsetX"] floatValue], [self.config[@"shadowOffsetY"] floatValue]); + self.contentLabel.shadowColor = [UIColor colorWithHexString:self.config[@"shadowColor"] alpha:1]; + self.contentLabel.backgroundColor = [UIColor clearColor]; + self.contentLabel.textColor = contentTextColor; + self.contentLabel.text = subtitle; + self.contentLabel.font = fontName ? + [UIFont fontWithName:fontName size:fontSize] : + [UIFont systemFontOfSize:fontSize]; + + [self addSubview:self.contentLabel]; +} -@end +- (void)setupImage:(UIImage *)image +{ + if (!image && self.config[@"imageName"] != [NSNull null] && [self.config[@"imageName"] length]) image = [UIImage imageNamed:self.config[@"imageName"]]; + + self.iconImageView = [[UIImageView alloc] initWithImage:image]; + self.iconImageView.frame = CGRectMake(TSMessageViewPadding * 2, TSMessageViewPadding, image.size.width, image.size.height); + + [self addSubview:self.iconImageView]; +} +- (void)setupTapHandler +{ + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; + tapGesture.delegate = self; + [self addGestureRecognizer:tapGesture]; +} -@implementation TSMessageView +#pragma mark - Message view attributes and actions -+ (NSMutableDictionary *)notificationDesign +- (void)setButtonWithTitle:(NSString *)title callback:(TSMessageCallback)callback { - if (!_notificationDesign) - { - NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:TSDesignFileName]; - _notificationDesign = [NSMutableDictionary dictionaryWithDictionary:[NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] - options:kNilOptions - error:nil]]; - } + self.buttonCallback = callback; - return _notificationDesign; + UIImage *buttonBackgroundImage = [[UIImage imageNamed:self.config[@"buttonBackgroundImageName"]] resizableImageWithCapInsets:UIEdgeInsetsMake(15.0, 12.0, 15.0, 11.0)]; + UIColor *buttonTitleShadowColor = [UIColor colorWithHexString:self.config[@"buttonTitleShadowColor"] alpha:1]; + UIColor *buttonTitleTextColor = [UIColor colorWithHexString:self.config[@"buttonTitleTextColor"] alpha:1]; + UIColor *fontColor = [UIColor colorWithHexString:self.config[@"textColor"] alpha:1]; + + if (!buttonBackgroundImage) buttonBackgroundImage = [[UIImage imageNamed:self.config[@"NotificationButtonBackground"]] resizableImageWithCapInsets:UIEdgeInsetsMake(15.0, 12.0, 15.0, 11.0)]; + if (!buttonTitleShadowColor) buttonTitleShadowColor = [UIColor colorWithHexString:self.config[@"shadowColor"] alpha:1]; + if (!buttonTitleTextColor) buttonTitleTextColor = fontColor; + + self.button = [UIButton buttonWithType:UIButtonTypeCustom]; + self.button.contentEdgeInsets = UIEdgeInsetsMake(0, 5, 0, 5); + self.button.titleLabel.font = [UIFont boldSystemFontOfSize:14]; + self.button.titleLabel.shadowOffset = CGSizeMake([self.config[@"buttonTitleShadowOffsetX"] floatValue], [self.config[@"buttonTitleShadowOffsetY"] floatValue]); + + [self.button setTitle:title forState:UIControlStateNormal]; + [self.button setBackgroundImage:buttonBackgroundImage forState:UIControlStateNormal]; + [self.button setTitleShadowColor:buttonTitleShadowColor forState:UIControlStateNormal]; + [self.button setTitleColor:buttonTitleTextColor forState:UIControlStateNormal]; + [self.button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside]; + [self.button sizeToFit]; + + self.button.frame = CGRectMake(self.viewController.view.bounds.size.width - TSMessageViewPadding - self.button.frame.size.width, 0, self.button.frame.size.width, 31); + + [self addSubview:self.button]; } +- (void)setUserDismissEnabled +{ + [self setUserDismissEnabledWithCallback:^(TSMessageView *messageView) { + [messageView dismiss]; + }]; +} -+ (void)addNotificationDesignFromFile:(NSString *)filename +- (void)setUserDismissEnabledWithCallback:(TSMessageCallback)callback { - NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:filename]; - NSDictionary *design = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] - options:kNilOptions - error:nil]; + self.dismissCallback = callback; - [[TSMessageView notificationDesign] addEntriesFromDictionary:design]; + UISwipeGestureRecognizer *gestureRec = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss)]; + gestureRec.direction = (self.position == TSMessageNotificationPositionTop ? UISwipeGestureRecognizerDirectionUp : UISwipeGestureRecognizerDirectionDown); + [self addGestureRecognizer:gestureRec]; } -- (id)initWithTitle:(NSString *)title - subtitle:(NSString *)subtitle - image:(UIImage *)image - type:(TSMessageNotificationType)notificationType - duration:(CGFloat)duration - inViewController:(UIViewController *)viewController - callback:(TSMessageCallback)callback - buttonTitle:(NSString *)buttonTitle - buttonCallback:(TSMessageCallback)buttonCallback - atPosition:(TSMessageNotificationPosition)position -canBeDismissedByUser:(BOOL)dismissingEnabled +#pragma mark - View handling + +- (void)didMoveToWindow { - NSDictionary *notificationDesign = [TSMessageView notificationDesign]; + [super didMoveToWindow]; - if ((self = [self init])) + if (self.duration == TSMessageNotificationDurationEndless && self.superview && !self.window) { - _title = title; - _subtitle = subtitle; - _buttonTitle = buttonTitle; - _duration = duration; - _viewController = viewController; - _messagePosition = position; - self.callback = callback; - self.buttonCallback = buttonCallback; - - CGFloat screenWidth = self.viewController.view.bounds.size.width; - NSDictionary *current; - NSString *currentString; - switch (notificationType) - { - case TSMessageNotificationTypeMessage: - { - currentString = @"message"; - break; - } - case TSMessageNotificationTypeError: - { - currentString = @"error"; - break; - } - case TSMessageNotificationTypeSuccess: - { - currentString = @"success"; - break; - } - case TSMessageNotificationTypeWarning: - { - currentString = @"warning"; - break; - } - - default: - break; - } - - current = [notificationDesign valueForKey:currentString]; - - - if (!image && [current valueForKey:@"imageName"] != [NSNull null] && [[current valueForKey:@"imageName"] length]) - { - image = [UIImage imageNamed:[current valueForKey:@"imageName"]]; - } - - _backgroundBlurView = [[TSBlurView alloc] init]; - self.backgroundBlurView.autoresizingMask = (UIViewAutoresizingFlexibleWidth); - self.backgroundBlurView.blurTintColor = [UIColor colorWithHexString:current[@"backgroundColor"]]; - [self addSubview:self.backgroundBlurView]; - - UIColor *fontColor = [UIColor colorWithHexString:[current valueForKey:@"textColor"] - alpha:1.0]; - - - self.textSpaceLeft = 2 * TSMessageViewPadding; - if (image) self.textSpaceLeft += image.size.width + 2 * TSMessageViewPadding; - - // Set up title label - _titleLabel = [[UILabel alloc] init]; - [self.titleLabel setText:title]; - [self.titleLabel setTextColor:fontColor]; - [self.titleLabel setBackgroundColor:[UIColor clearColor]]; - CGFloat fontSize = [[current valueForKey:@"titleFontSize"] floatValue]; - NSString *fontName = [current valueForKey:@"titleFontName"]; - if (fontName != nil) { - [self.titleLabel setFont:[UIFont fontWithName:fontName size:fontSize]]; - } else { - [self.titleLabel setFont:[UIFont boldSystemFontOfSize:fontSize]]; - } - [self.titleLabel setShadowColor:[UIColor colorWithHexString:[current valueForKey:@"shadowColor"] alpha:1.0]]; - [self.titleLabel setShadowOffset:CGSizeMake([[current valueForKey:@"shadowOffsetX"] floatValue], - [[current valueForKey:@"shadowOffsetY"] floatValue])]; - self.titleLabel.numberOfLines = 0; - self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; - [self addSubview:self.titleLabel]; - - // Set up content label (if set) - if ([subtitle length]) - { - _contentLabel = [[UILabel alloc] init]; - [self.contentLabel setText:subtitle]; - - UIColor *contentTextColor = [UIColor colorWithHexString:[current valueForKey:@"contentTextColor"] alpha:1.0]; - if (!contentTextColor) - { - contentTextColor = fontColor; - } - [self.contentLabel setTextColor:contentTextColor]; - [self.contentLabel setBackgroundColor:[UIColor clearColor]]; - CGFloat fontSize = [[current valueForKey:@"contentFontSize"] floatValue]; - NSString *fontName = [current valueForKey:@"contentFontName"]; - if (fontName != nil) { - [self.contentLabel setFont:[UIFont fontWithName:fontName size:fontSize]]; - } else { - [self.contentLabel setFont:[UIFont systemFontOfSize:fontSize]]; - } - [self.contentLabel setShadowColor:self.titleLabel.shadowColor]; - [self.contentLabel setShadowOffset:self.titleLabel.shadowOffset]; - self.contentLabel.lineBreakMode = self.titleLabel.lineBreakMode; - self.contentLabel.numberOfLines = 0; - - [self addSubview:self.contentLabel]; - } - - if (image) - { - _iconImageView = [[UIImageView alloc] initWithImage:image]; - self.iconImageView.frame = CGRectMake(TSMessageViewPadding * 2, - TSMessageViewPadding, - image.size.width, - image.size.height); - [self addSubview:self.iconImageView]; - } - - // Set up button (if set) - if ([buttonTitle length]) - { - _button = [UIButton buttonWithType:UIButtonTypeCustom]; - - UIImage *buttonBackgroundImage = [[UIImage imageNamed:[current valueForKey:@"buttonBackgroundImageName"]] resizableImageWithCapInsets:UIEdgeInsetsMake(15.0, 12.0, 15.0, 11.0)]; - - if (!buttonBackgroundImage) - { - buttonBackgroundImage = [[UIImage imageNamed:[current valueForKey:@"NotificationButtonBackground"]] resizableImageWithCapInsets:UIEdgeInsetsMake(15.0, 12.0, 15.0, 11.0)]; - } - - [self.button setBackgroundImage:buttonBackgroundImage forState:UIControlStateNormal]; - [self.button setTitle:self.buttonTitle forState:UIControlStateNormal]; - - UIColor *buttonTitleShadowColor = [UIColor colorWithHexString:[current valueForKey:@"buttonTitleShadowColor"] alpha:1.0]; - if (!buttonTitleShadowColor) - { - buttonTitleShadowColor = self.titleLabel.shadowColor; - } - - [self.button setTitleShadowColor:buttonTitleShadowColor forState:UIControlStateNormal]; - - UIColor *buttonTitleTextColor = [UIColor colorWithHexString:[current valueForKey:@"buttonTitleTextColor"] alpha:1.0]; - if (!buttonTitleTextColor) - { - buttonTitleTextColor = fontColor; - } - - [self.button setTitleColor:buttonTitleTextColor forState:UIControlStateNormal]; - self.button.titleLabel.font = [UIFont boldSystemFontOfSize:14.0]; - self.button.titleLabel.shadowOffset = CGSizeMake([[current valueForKey:@"buttonTitleShadowOffsetX"] floatValue], - [[current valueForKey:@"buttonTitleShadowOffsetY"] floatValue]); - [self.button addTarget:self - action:@selector(buttonTapped:) - forControlEvents:UIControlEventTouchUpInside]; - - self.button.contentEdgeInsets = UIEdgeInsetsMake(0.0, 5.0, 0.0, 5.0); - [self.button sizeToFit]; - self.button.frame = CGRectMake(screenWidth - TSMessageViewPadding - self.button.frame.size.width, - 0.0, - self.button.frame.size.width, - 31.0); - - [self addSubview:self.button]; - - self.textSpaceRight = self.button.frame.size.width + TSMessageViewPadding; - } - - CGFloat actualHeight = [self updateHeightOfMessageView]; // this call also takes care of positioning the labels - CGFloat topPosition = -actualHeight; - - if (self.messagePosition == TSMessageNotificationPositionBottom) - { - topPosition = self.viewController.view.bounds.size.height; - } - - self.frame = CGRectMake(0.0, topPosition, screenWidth, actualHeight); - - if (self.messagePosition == TSMessageNotificationPositionTop) - { - self.autoresizingMask = UIViewAutoresizingFlexibleWidth; - } - else - { - self.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); - } - - if (dismissingEnabled) - { - UISwipeGestureRecognizer *gestureRec = [[UISwipeGestureRecognizer alloc] initWithTarget:self - action:@selector(fadeMeOut)]; - [gestureRec setDirection:(self.messagePosition == TSMessageNotificationPositionTop ? - UISwipeGestureRecognizerDirectionUp : - UISwipeGestureRecognizerDirectionDown)]; - [self addGestureRecognizer:gestureRec]; - - UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc] initWithTarget:self - action:@selector(fadeMeOut)]; - [self addGestureRecognizer:tapRec]; - } - - UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; - tapGesture.delegate = self; - [self addGestureRecognizer:tapGesture]; + [self dismiss]; } - return self; } - -- (CGFloat)updateHeightOfMessageView +- (void)layoutSubviews { + [super layoutSubviews]; + CGFloat currentHeight; CGFloat screenWidth = self.viewController.view.bounds.size.width; + CGFloat textSpaceRight = self.button.frame.size.width + TSMessageViewPadding; + CGFloat textSpaceLeft = 2 * TSMessageViewPadding; + UIImage *image = self.iconImageView.image; + if (image) textSpaceLeft += image.size.width + 2 * TSMessageViewPadding; - self.titleLabel.frame = CGRectMake(self.textSpaceLeft, + // title + self.titleLabel.frame = CGRectMake(textSpaceLeft, TSMessageViewPadding, - screenWidth - TSMessageViewPadding - self.textSpaceLeft - self.textSpaceRight, + screenWidth - TSMessageViewPadding - textSpaceLeft - textSpaceRight, 0.0); [self.titleLabel sizeToFit]; - if ([self.subtitle length]) + // subtitle + if (self.contentLabel) { - self.contentLabel.frame = CGRectMake(self.textSpaceLeft, + self.contentLabel.frame = CGRectMake(textSpaceLeft, self.titleLabel.frame.origin.y + self.titleLabel.frame.size.height + 5.0, - screenWidth - TSMessageViewPadding - self.textSpaceLeft - self.textSpaceRight, + screenWidth - TSMessageViewPadding - textSpaceLeft - textSpaceRight, 0.0); [self.contentLabel sizeToFit]; @@ -328,134 +241,164 @@ - (CGFloat)updateHeightOfMessageView } else { - // only the title was set currentHeight = self.titleLabel.frame.origin.y + self.titleLabel.frame.size.height; } currentHeight += TSMessageViewPadding; + // image if (self.iconImageView) { - // Check if that makes the popup larger (height) + // check if that makes the popup larger (height) if (self.iconImageView.frame.origin.y + self.iconImageView.frame.size.height + TSMessageViewPadding > currentHeight) { currentHeight = self.iconImageView.frame.origin.y + self.iconImageView.frame.size.height; } else { - // z-align - self.iconImageView.center = CGPointMake([self.iconImageView center].x, - round(currentHeight / 2.0)); + self.iconImageView.center = CGPointMake([self.iconImageView center].x, round(currentHeight / 2.0)); } } - // z-align button - self.button.center = CGPointMake([self.button center].x, - round(currentHeight / 2.0)); - - if (self.messagePosition == TSMessageNotificationPositionTop) - { - // Correct the border position - CGRect borderFrame = self.borderView.frame; - borderFrame.origin.y = currentHeight; - self.borderView.frame = borderFrame; - } - - currentHeight += self.borderView.frame.size.height; - self.frame = CGRectMake(0.0, self.frame.origin.y, self.frame.size.width, currentHeight); - + // button if (self.button) { - self.button.frame = CGRectMake(self.frame.size.width - self.textSpaceRight, + self.button.center = CGPointMake([self.button center].x, round(currentHeight / 2.0)); + + self.button.frame = CGRectMake(self.frame.size.width - textSpaceRight, round((self.frame.size.height / 2.0) - self.button.frame.size.height / 2.0), self.button.frame.size.width, self.button.frame.size.height); } - CGRect backgroundFrame = CGRectMake(self.backgroundImageView.frame.origin.x, - self.backgroundImageView.frame.origin.y, + CGRect backgroundFrame = CGRectMake(self.backgroundBlurView.frame.origin.x, + self.backgroundBlurView.frame.origin.y, screenWidth, currentHeight); // increase frame of background view because of the spring animation - if (self.messagePosition == TSMessageNotificationPositionTop) + if (self.position == TSMessageNotificationPositionTop) { float topOffset = 0.f; UINavigationController *navigationController = self.viewController.navigationController; + if (!navigationController && [self.viewController isKindOfClass:[UINavigationController class]]) { navigationController = (UINavigationController *)self.viewController; } + BOOL isNavBarIsHidden = !navigationController || self.viewController.navigationController.navigationBarHidden; BOOL isNavBarIsOpaque = !self.viewController.navigationController.navigationBar.isTranslucent && self.viewController.navigationController.navigationBar.alpha == 1; if (isNavBarIsHidden || isNavBarIsOpaque) { topOffset = -30.f; } - backgroundFrame = UIEdgeInsetsInsetRect(backgroundFrame, UIEdgeInsetsMake(topOffset, 0.f, 0.f, 0.f)); + + backgroundFrame = UIEdgeInsetsInsetRect(backgroundFrame, UIEdgeInsetsMake(topOffset, 0.f, topOffset, 0.f)); } - else if (self.messagePosition == TSMessageNotificationPositionBottom) + else if (self.position == TSMessageNotificationPositionBottom) { backgroundFrame = UIEdgeInsetsInsetRect(backgroundFrame, UIEdgeInsetsMake(0.f, 0.f, -30.f, 0.f)); } - self.backgroundImageView.frame = backgroundFrame; self.backgroundBlurView.frame = backgroundFrame; - - return currentHeight; } -- (void)layoutSubviews +- (void)prepareForDisplay { - [super layoutSubviews]; - [self updateHeightOfMessageView]; + [self setNeedsLayout]; + [self layoutIfNeeded]; + + CGFloat actualHeight = self.frame.size.height; + CGFloat topPosition = -actualHeight; + + if (self.position == TSMessageNotificationPositionBottom) + { + topPosition = self.viewController.view.bounds.size.height; + } + + self.frame = CGRectMake(0.0, topPosition, self.viewController.view.bounds.size.width, actualHeight); } -- (void)fadeMeOut +#pragma mark - Actions + +- (void)buttonTapped:(id) sender { - if (self == [TSMessage sharedMessage].currentNotification) { - [[TSMessage sharedMessage] performSelectorOnMainThread:@selector(fadeOutCurrentNotification) withObject:nil waitUntilDone:NO]; - } else { - [[TSMessage sharedMessage] performSelectorOnMainThread:@selector(fadeOutNotification:) withObject:self waitUntilDone:NO]; + if (self.buttonCallback) + { + self.buttonCallback(self); } } -- (void)didMoveToWindow { - [super didMoveToWindow]; - if (self.duration == TSMessageNotificationDurationEndless && self.superview && !self.window ) { - // view controller was dismissed, let's fade out - [self fadeMeOut]; +- (void)handleTap:(UITapGestureRecognizer *)tapGesture +{ + if (tapGesture.state != UIGestureRecognizerStateRecognized) return; + + if (self.tapCallback) + { + self.tapCallback(self); } } -#pragma mark - Target/Action -- (void)buttonTapped:(id) sender +- (void)dismiss { - if (self.buttonCallback) + if (self == [TSMessage sharedMessage].currentNotification) { - self.buttonCallback(self); + [[TSMessage sharedMessage] performSelectorOnMainThread:@selector(fadeOutCurrentNotification) withObject:nil waitUntilDone:NO]; + } + else + { + [[TSMessage sharedMessage] performSelectorOnMainThread:@selector(fadeOutNotification:) withObject:self waitUntilDone:NO]; } } -- (void)handleTap:(UITapGestureRecognizer *)tapGesture +#pragma mark - Custom design + ++ (NSMutableDictionary *)notificationDesign { - if (tapGesture.state == UIGestureRecognizerStateRecognized) + if (!_notificationDesign) { - if (self.callback) - { - self.callback(self); - } + NSError *error = nil; + NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:TSDesignFileName]; + NSData *data = [NSData dataWithContentsOfFile:path]; + NSDictionary *config = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; + _notificationDesign = [NSMutableDictionary dictionaryWithDictionary:config]; } + + return _notificationDesign; +} + + ++ (void)addNotificationDesignFromFile:(NSString *)filename +{ + NSError *error = nil; + NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:filename]; + NSData *data = [NSData dataWithContentsOfFile:path]; + NSDictionary *design = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; + + [[TSMessageView notificationDesign] addEntriesFromDictionary:design]; } #pragma mark - UIGestureRecognizerDelegate - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { - return ! ([touch.view isKindOfClass:[UIControl class]]); + return !([touch.view isKindOfClass:[UIControl class]]); +} + +#pragma mark - Private + +- (NSString *)title +{ + return self.titleLabel.text; +} + +- (NSString *)subtitle +{ + return self.contentLabel.text; } @end From 21f3551a5f62db542f650f0035967370a4169cfb Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Thu, 20 Feb 2014 22:25:32 +0100 Subject: [PATCH 09/27] Rename showOrEnqueueNotification method --- ExampleProject/Example/TSDemoViewController.m | 10 +++++----- TSMessages/Classes/TSMessage.h | 8 +++++--- TSMessages/Classes/TSMessage.m | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/ExampleProject/Example/TSDemoViewController.m b/ExampleProject/Example/TSDemoViewController.m index 6bc7b55d..122a981a 100644 --- a/ExampleProject/Example/TSDemoViewController.m +++ b/ExampleProject/Example/TSDemoViewController.m @@ -98,7 +98,7 @@ - (IBAction)didTapButton:(id)sender [view setUserDismissEnabled]; - [TSMessage prepareNotificationToBeShown:view]; + [TSMessage showOrEnqueueNotification:view]; } - (IBAction)didTapPermanent:(id)sender @@ -151,7 +151,7 @@ - (IBAction)didTapCustomImage:(id)sender [messageView setUserDismissEnabled]; - [TSMessage prepareNotificationToBeShown:messageView]; + [TSMessage showOrEnqueueNotification:messageView]; } - (IBAction)didTapDismissCurrentMessage:(id)sender @@ -167,7 +167,7 @@ - (IBAction)didTapEndless:(id)sender messageView.duration = TSMessageNotificationDurationEndless; - [TSMessage prepareNotificationToBeShown:messageView]; + [TSMessage showOrEnqueueNotification:messageView]; } - (IBAction)didTapLong:(id)sender @@ -179,7 +179,7 @@ - (IBAction)didTapLong:(id)sender [messageView setUserDismissEnabled]; - [TSMessage prepareNotificationToBeShown:messageView]; + [TSMessage showOrEnqueueNotification:messageView]; } - (IBAction)didTapBottom:(id)sender @@ -193,7 +193,7 @@ - (IBAction)didTapBottom:(id)sender [messageView setUserDismissEnabled]; - [TSMessage prepareNotificationToBeShown:messageView]; + [TSMessage showOrEnqueueNotification:messageView]; } - (IBAction)didTapText:(id)sender diff --git a/TSMessages/Classes/TSMessage.h b/TSMessages/Classes/TSMessage.h index f86075c5..3ab73d43 100755 --- a/TSMessages/Classes/TSMessage.h +++ b/TSMessages/Classes/TSMessage.h @@ -132,10 +132,12 @@ typedef void (^TSMessageCallback)(TSMessageView *messageView); */ + (BOOL)isNotificationActive; -/** Prepares the notification view to be displayed in the future. - It is queued and then displayed in fadeInCurrentNotification. +/** Shows or enqueues the notification view. If there is a notification + displayed currently, the notification view gets added to the end of the + queue and displayed after its prior notifications are shown. If it is + the only notification it gets shown right away. */ -+ (void)prepareNotificationToBeShown:(TSMessageView *)messageView; ++ (void)showOrEnqueueNotification:(TSMessageView *)messageView; /** Shows a permanent notification message. diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index efe69f55..20855cf3 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -72,7 +72,7 @@ + (TSMessageView *)showNotificationWithTitle:(NSString *)title subtitle:(NSStrin { TSMessageView *view = [self notificationWithTitle:title subtitle:subtitle image:image type:type inViewController:viewController]; - [self prepareNotificationToBeShown:view]; + [self showOrEnqueueNotification:view]; return view; } @@ -84,7 +84,7 @@ + (void)showPermanentNotification:(TSMessageView *)messageView [[TSMessage sharedMessage] fadeInNotification:messageView]; } -+ (void)prepareNotificationToBeShown:(TSMessageView *)messageView ++ (void)showOrEnqueueNotification:(TSMessageView *)messageView { NSString *title = messageView.title; NSString *subtitle = messageView.subtitle; From ef9ba728c485735b3777cfc7b961853c07377347 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Thu, 20 Feb 2014 22:30:41 +0100 Subject: [PATCH 10/27] Move custom design handling to TSMessage class --- TSMessages/Classes/TSMessage+Private.h | 1 + TSMessages/Classes/TSMessage.m | 28 +++++++++++++++++++--- TSMessages/Views/TSMessageView.h | 3 --- TSMessages/Views/TSMessageView.m | 32 +------------------------- 4 files changed, 27 insertions(+), 37 deletions(-) diff --git a/TSMessages/Classes/TSMessage+Private.h b/TSMessages/Classes/TSMessage+Private.h index 6afd8eb1..5caf98c8 100644 --- a/TSMessages/Classes/TSMessage+Private.h +++ b/TSMessages/Classes/TSMessage+Private.h @@ -11,6 +11,7 @@ @class TSMessageView; @interface TSMessage (Private) ++ (NSMutableDictionary *)notificationDesign; - (void)fadeOutCurrentNotification; - (void)fadeOutNotification:(TSMessageView *)messageView; - (void)fadeOutNotification:(TSMessageView *)messageView completion:(void (^)())completion; diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index 20855cf3..74645647 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -13,6 +13,7 @@ #define kTSMessageDisplayTime 1.5 #define kTSMessageAnimationDuration 0.3 #define kTSMessageExtraDisplayTimePerPixel 0.04 +#define kTSDesignFileName @"TSMessagesDefaultDesign.json" @interface TSMessage () @property (nonatomic, strong) NSMutableArray *messages; @@ -20,8 +21,9 @@ @interface TSMessage () @implementation TSMessage -static TSMessage *_sharedMessage; static BOOL _notificationActive; +static TSMessage *_sharedMessage; +static NSMutableDictionary *_notificationDesign; __weak static UIViewController *_defaultViewController; @@ -122,11 +124,31 @@ + (BOOL)isNotificationActive return _notificationActive; } -#pragma mark - Customizing notifications +#pragma mark - Customizing notifications design + (void)addCustomDesignFromFileWithName:(NSString *)fileName { - [TSMessageView addNotificationDesignFromFile:fileName]; + NSError *error = nil; + NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName]; + NSData *data = [NSData dataWithContentsOfFile:path]; + NSDictionary *design = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; + + [self.notificationDesign addEntriesFromDictionary:design]; +} + ++ (NSMutableDictionary *)notificationDesign +{ + if (!_notificationDesign) + { + NSError *error = nil; + NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:kTSDesignFileName]; + NSData *data = [NSData dataWithContentsOfFile:path]; + NSDictionary *config = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; + + _notificationDesign = [NSMutableDictionary dictionaryWithDictionary:config]; + } + + return _notificationDesign; } #pragma mark - Default view controller diff --git a/TSMessages/Views/TSMessageView.h b/TSMessages/Views/TSMessageView.h index 8403887d..1c95cbc6 100755 --- a/TSMessages/Views/TSMessageView.h +++ b/TSMessages/Views/TSMessageView.h @@ -47,7 +47,4 @@ /** Enables dismissing the message by swiping */ - (void)setUserDismissEnabled; - (void)setUserDismissEnabledWithCallback:(TSMessageCallback)callback; - -/** Use this method to load a custom design file */ -+ (void)addNotificationDesignFromFile:(NSString *)file; @end diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index 463e72d0..f69c419e 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -14,9 +14,6 @@ #import "TSMessageView+Private.h" #define TSMessageViewPadding 15.0 -#define TSDesignFileName @"TSMessagesDefaultDesign.json" - -static NSMutableDictionary *_notificationDesign; @interface TSMessageView () @property (nonatomic) NSDictionary *config; @@ -66,7 +63,7 @@ - (void)setupConfigForType:(TSMessageNotificationType)notificationType default: config = @"message"; break; } - self.config = [TSMessageView notificationDesign][config]; + self.config = [TSMessage notificationDesign][config]; } - (void)setupBackgroundView @@ -355,33 +352,6 @@ - (void)dismiss } } -#pragma mark - Custom design - -+ (NSMutableDictionary *)notificationDesign -{ - if (!_notificationDesign) - { - NSError *error = nil; - NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:TSDesignFileName]; - NSData *data = [NSData dataWithContentsOfFile:path]; - NSDictionary *config = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; - _notificationDesign = [NSMutableDictionary dictionaryWithDictionary:config]; - } - - return _notificationDesign; -} - - -+ (void)addNotificationDesignFromFile:(NSString *)filename -{ - NSError *error = nil; - NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:filename]; - NSData *data = [NSData dataWithContentsOfFile:path]; - NSDictionary *design = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; - - [[TSMessageView notificationDesign] addEntriesFromDictionary:design]; -} - #pragma mark - UIGestureRecognizerDelegate - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch From 72e1039fbca49c2e3293ea8b8af0666c4fd795e8 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Thu, 20 Feb 2014 22:47:14 +0100 Subject: [PATCH 11/27] Remove xccheckout file from repository --- .gitignore | 1 + .../xcshareddata/Example.xccheckout | 41 ------------------- 2 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 ExampleProject/Example.xcworkspace/xcshareddata/Example.xccheckout diff --git a/.gitignore b/.gitignore index 88719254..0bc019e7 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ *.perspectivev3 !default.perspectivev3 xcuserdata +*.xccheckout profile *.moved-aside DerivedData diff --git a/ExampleProject/Example.xcworkspace/xcshareddata/Example.xccheckout b/ExampleProject/Example.xcworkspace/xcshareddata/Example.xccheckout deleted file mode 100644 index b196e01a..00000000 --- a/ExampleProject/Example.xcworkspace/xcshareddata/Example.xccheckout +++ /dev/null @@ -1,41 +0,0 @@ - - - - - IDESourceControlProjectFavoriteDictionaryKey - - IDESourceControlProjectIdentifier - AE4EFDAC-4D12-4D15-A6B2-1AAEAC767CAB - IDESourceControlProjectName - Example - IDESourceControlProjectOriginsDictionary - - CBF9685F-3E4F-4E6C-92E3-4DF0D18A1180 - ssh://github.com/dennisreimann/TSMessages.git - - IDESourceControlProjectPath - ExampleProject/Example.xcworkspace - IDESourceControlProjectRelativeInstallPathDictionary - - CBF9685F-3E4F-4E6C-92E3-4DF0D18A1180 - ../.. - - IDESourceControlProjectURL - ssh://github.com/dennisreimann/TSMessages.git - IDESourceControlProjectVersion - 110 - IDESourceControlProjectWCCIdentifier - CBF9685F-3E4F-4E6C-92E3-4DF0D18A1180 - IDESourceControlProjectWCConfigurations - - - IDESourceControlRepositoryExtensionIdentifierKey - public.vcs.git - IDESourceControlWCCIdentifierKey - CBF9685F-3E4F-4E6C-92E3-4DF0D18A1180 - IDESourceControlWCCName - TSMessages - - - - From ae243672c1666965434acdcdb40a7e055b739dbb Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Fri, 21 Feb 2014 20:40:27 +0100 Subject: [PATCH 12/27] Remove state variable --- TSMessages/Classes/TSMessage.m | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index 74645647..7eb6af61 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -21,7 +21,6 @@ @interface TSMessage () @implementation TSMessage -static BOOL _notificationActive; static TSMessage *_sharedMessage; static NSMutableDictionary *_notificationDesign; @@ -99,10 +98,12 @@ + (void)showOrEnqueueNotification:(TSMessageView *)messageView if (equalTitle && equalSubtitle) return; } + + BOOL isDisplayable = !self.isNotificationActive; [[TSMessage sharedMessage].messages addObject:messageView]; - if (!_notificationActive) + if (isDisplayable) { [[TSMessage sharedMessage] fadeInCurrentNotification]; } @@ -121,7 +122,7 @@ + (BOOL)dismissActiveNotification + (BOOL)isNotificationActive { - return _notificationActive; + return !![TSMessage sharedMessage].currentNotification; } #pragma mark - Customizing notifications design @@ -184,8 +185,6 @@ - (void)fadeInCurrentNotification { if (!self.currentNotification) return; - _notificationActive = YES; - [self fadeInNotification:self.currentNotification]; } @@ -339,8 +338,6 @@ - (void)fadeOutCurrentNotification [self.messages removeObjectAtIndex:0]; } - _notificationActive = NO; - if (self.messages.count) { [self fadeInCurrentNotification]; From 3e70131064d7e95dcc776c1faf2840b3445b718e Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Fri, 21 Feb 2014 20:45:58 +0100 Subject: [PATCH 13/27] Use dispatch_once for singleton initialization --- TSMessages/Classes/TSMessage.m | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index 7eb6af61..a94bddd6 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -21,19 +21,18 @@ @interface TSMessage () @implementation TSMessage -static TSMessage *_sharedMessage; -static NSMutableDictionary *_notificationDesign; - __weak static UIViewController *_defaultViewController; + (TSMessage *)sharedMessage { - if (!_sharedMessage) - { - _sharedMessage = [[[self class] alloc] init]; - } + static TSMessage *sharedMessage = nil; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + sharedMessage = [[[self class] alloc] init]; + }); - return _sharedMessage; + return sharedMessage; } - (id)init @@ -139,17 +138,19 @@ + (void)addCustomDesignFromFileWithName:(NSString *)fileName + (NSMutableDictionary *)notificationDesign { - if (!_notificationDesign) - { + static NSMutableDictionary *notificationDesign = nil; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ NSError *error = nil; NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:kTSDesignFileName]; NSData *data = [NSData dataWithContentsOfFile:path]; NSDictionary *config = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; - _notificationDesign = [NSMutableDictionary dictionaryWithDictionary:config]; - } + notificationDesign = [NSMutableDictionary dictionaryWithDictionary:config]; + }); - return _notificationDesign; + return notificationDesign; } #pragma mark - Default view controller From 0e4ac78a5ff2d129269467455d6c40acb229ad82 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Fri, 21 Feb 2014 21:00:57 +0100 Subject: [PATCH 14/27] Remove unused defines --- TSMessages/Classes/TSMessage.h | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/TSMessages/Classes/TSMessage.h b/TSMessages/Classes/TSMessage.h index 3ab73d43..df780580 100755 --- a/TSMessages/Classes/TSMessage.h +++ b/TSMessages/Classes/TSMessage.h @@ -8,25 +8,6 @@ #import -// NS_ENUM is now the preferred way to do typedefs. It gives the compiler and debugger more information, which helps everyone. -// When using SDK 6 or later, NS_ENUM is defined by Apple, so this block does nothing. -// For SDK 5 or earlier, this is the same definition block Apple uses. -#ifndef NS_ENUM -#if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum)) -#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type -#if (__cplusplus) -#define NS_OPTIONS(_type, _name) _type _name; enum : _type -#else -#define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type -#endif -#else -#define NS_ENUM(_type, _name) _type _name; enum -#define NS_OPTIONS(_type, _name) _type _name; enum -#endif -#endif - -#define TS_SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) - @class TSMessageView; typedef NS_ENUM(NSInteger, TSMessageNotificationType) { From a614835b15363f69c2cf6523a6d341a13278e69d Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Fri, 21 Feb 2014 21:31:28 +0100 Subject: [PATCH 15/27] Consolidate naming notification -> message show -> display fadeOut -> dismiss --- ExampleProject/Example/AlternativeDesign.json | 22 +-- ExampleProject/Example/TSDemoViewController.m | 111 ++++++++------- .../Pods/Local Podspecs/TSMessages.podspec | 12 +- ExampleProject/Pods/Pods-resources.sh | 32 ++--- .../Pods/Pods.xcodeproj/project.pbxproj | 70 ++++----- TSMessages.podspec | 12 +- TSMessages/Classes/TSMessage+Private.h | 10 +- TSMessages/Classes/TSMessage.h | 134 +++++++++--------- TSMessages/Classes/TSMessage.m | 102 ++++++------- ...ssage.png => MessageBackgroundDefault.png} | Bin ...2x.png => MessageBackgroundDefault@2x.png} | Bin ...ndError.png => MessageBackgroundError.png} | Bin ...r@2x.png => MessageBackgroundError@2x.png} | Bin ...con.png => MessageBackgroundErrorIcon.png} | Bin ....png => MessageBackgroundErrorIcon@2x.png} | Bin ...ccess.png => MessageBackgroundSuccess.png} | Bin ...2x.png => MessageBackgroundSuccess@2x.png} | Bin ...n.png => MessageBackgroundSuccessIcon.png} | Bin ...ng => MessageBackgroundSuccessIcon@2x.png} | Bin ...rning.png => MessageBackgroundWarning.png} | Bin ...2x.png => MessageBackgroundWarning@2x.png} | Bin ...n.png => MessageBackgroundWarningIcon.png} | Bin ...ng => MessageBackgroundWarningIcon@2x.png} | Bin ...ground.png => MessageButtonBackground.png} | Bin ...@2x.png => MessageButtonBackground@2x.png} | Bin .../Resources/TSMessagesDefaultDesign.json | 22 +-- TSMessages/Views/TSMessageView.h | 10 +- TSMessages/Views/TSMessageView.m | 40 +++--- 28 files changed, 290 insertions(+), 287 deletions(-) rename TSMessages/Resources/Images/{NotificationBackgroundMessage.png => MessageBackgroundDefault.png} (100%) rename TSMessages/Resources/Images/{NotificationBackgroundMessage@2x.png => MessageBackgroundDefault@2x.png} (100%) rename TSMessages/Resources/Images/{NotificationBackgroundError.png => MessageBackgroundError.png} (100%) rename TSMessages/Resources/Images/{NotificationBackgroundError@2x.png => MessageBackgroundError@2x.png} (100%) rename TSMessages/Resources/Images/{NotificationBackgroundErrorIcon.png => MessageBackgroundErrorIcon.png} (100%) rename TSMessages/Resources/Images/{NotificationBackgroundErrorIcon@2x.png => MessageBackgroundErrorIcon@2x.png} (100%) rename TSMessages/Resources/Images/{NotificationBackgroundSuccess.png => MessageBackgroundSuccess.png} (100%) rename TSMessages/Resources/Images/{NotificationBackgroundSuccess@2x.png => MessageBackgroundSuccess@2x.png} (100%) rename TSMessages/Resources/Images/{NotificationBackgroundSuccessIcon.png => MessageBackgroundSuccessIcon.png} (100%) rename TSMessages/Resources/Images/{NotificationBackgroundSuccessIcon@2x.png => MessageBackgroundSuccessIcon@2x.png} (100%) rename TSMessages/Resources/Images/{NotificationBackgroundWarning.png => MessageBackgroundWarning.png} (100%) rename TSMessages/Resources/Images/{NotificationBackgroundWarning@2x.png => MessageBackgroundWarning@2x.png} (100%) rename TSMessages/Resources/Images/{NotificationBackgroundWarningIcon.png => MessageBackgroundWarningIcon.png} (100%) rename TSMessages/Resources/Images/{NotificationBackgroundWarningIcon@2x.png => MessageBackgroundWarningIcon@2x.png} (100%) rename TSMessages/Resources/Images/{NotificationButtonBackground.png => MessageButtonBackground.png} (100%) rename TSMessages/Resources/Images/{NotificationButtonBackground@2x.png => MessageButtonBackground@2x.png} (100%) diff --git a/ExampleProject/Example/AlternativeDesign.json b/ExampleProject/Example/AlternativeDesign.json index cf627ba5..5b30713a 100644 --- a/ExampleProject/Example/AlternativeDesign.json +++ b/ExampleProject/Example/AlternativeDesign.json @@ -1,16 +1,16 @@ { "success": { - "backgroundImageName": "NotificationBackgroundSuccess.png", + "backgroundImageName": "MessageBackgroundSuccess.png", "borderColor": "#005700", "borderHeight": 1, - "buttonBackgroundImageName": "NotificationButtonBackground.png", + "buttonBackgroundImageName": "MessageButtonBackground.png", "buttonTitleTextColor": "#FFFFFF", "buttonTitleShadowColor": "#67B759", "buttonTitleShadowOffsetX": 0, "buttonTitleShadowOffsetY": -1, "contentFontSize": 12, "contentTextColor": "#FFFFFF", - "imageName": "NotificationBackgroundSuccessIcon.png", + "imageName": "MessageBackgroundSuccessIcon.png", "shadowColor": "#67B759", "shadowOffsetX": 0, "shadowOffsetY": -1, @@ -18,10 +18,10 @@ "titleFontSize": 25 }, "message": { - "backgroundImageName": "NotificationBackgroundMessage.png", + "backgroundImageName": "MessageBackgroundDefault.png", "borderColor": "#727C83", "borderHeight": 1, - "buttonBackgroundImageName": "NotificationButtonBackground.png", + "buttonBackgroundImageName": "MessageButtonBackground.png", "buttonTitleTextColor": "#727C83", "buttonTitleShadowColor": "#EBEEF1", "buttonTitleShadowOffsetX": 0, @@ -36,17 +36,17 @@ "titleFontSize": 14 }, "warning": { - "backgroundImageName": "NotificationBackgroundWarning.png", + "backgroundImageName": "MessageBackgroundWarning.png", "borderColor": "#A28918", "borderHeight": 1, - "buttonBackgroundImageName": "NotificationButtonBackground.png", + "buttonBackgroundImageName": "MessageButtonBackground.png", "buttonTitleTextColor": "#484638", "buttonTitleShadowColor": "#E5D87C", "buttonTitleShadowOffsetX": 0, "buttonTitleShadowOffsetY": 1, "contentFontSize": 12, "contentTextColor": "#484638", - "imageName": "NotificationBackgroundWarningIcon.png", + "imageName": "MessageBackgroundWarningIcon.png", "shadowColor": "#E5D87C", "shadowOffsetX": 0, "shadowOffsetY": 1, @@ -54,17 +54,17 @@ "titleFontSize": 14 }, "error": { - "backgroundImageName": "NotificationBackgroundError.png", + "backgroundImageName": "MessageBackgroundError.png", "borderColor": "#700000", "borderHeight": 1, - "buttonBackgroundImageName": "NotificationButtonBackground.png", + "buttonBackgroundImageName": "MessageButtonBackground.png", "buttonTitleTextColor": "#FFFFFF", "buttonTitleShadowColor": "#812929", "buttonTitleShadowOffsetX": 0, "buttonTitleShadowOffsetY": -1, "contentFontSize": 12, "contentTextColor": "#FFFFFF", - "imageName": "NotificationBackgroundErrorIcon.png", + "imageName": "MessageBackgroundErrorIcon.png", "shadowColor": "#812929", "shadowOffsetX": 0, "shadowOffsetY": -1, diff --git a/ExampleProject/Example/TSDemoViewController.m b/ExampleProject/Example/TSDemoViewController.m index 122a981a..a8f44bb3 100644 --- a/ExampleProject/Example/TSDemoViewController.m +++ b/ExampleProject/Example/TSDemoViewController.m @@ -54,72 +54,76 @@ - (CGFloat)navigationbarBottomOfViewController:(UIViewController *)viewControlle - (IBAction)didTapError:(id)sender { - TSMessageView *messageView = [TSMessage showNotificationWithTitle:NSLocalizedString(@"Something failed", nil) - subtitle:NSLocalizedString(@"The internet connection seems to be down. Please check that!", nil) - type:TSMessageNotificationTypeError]; + TSMessageView *messageView = [TSMessage displayMessageWithTitle:NSLocalizedString(@"Something failed", nil) + subtitle:NSLocalizedString(@"The internet connection seems to be down. Please check that!", nil) + type:TSMessageTypeError]; [messageView setUserDismissEnabled]; } - (IBAction)didTapWarning:(id)sender { - TSMessageView *messageView = [TSMessage showNotificationWithTitle:NSLocalizedString(@"Some random warning", nil) - subtitle:NSLocalizedString(@"Look out! Something is happening there!", nil) - type:TSMessageNotificationTypeWarning]; + TSMessageView *messageView = [TSMessage displayMessageWithTitle:NSLocalizedString(@"Some random warning", nil) + subtitle:NSLocalizedString(@"Look out! Something is happening there!", nil) + type:TSMessageTypeWarning]; [messageView setUserDismissEnabled]; } - (IBAction)didTapMessage:(id)sender { - TSMessageView *messageView = [TSMessage showNotificationWithTitle:NSLocalizedString(@"Tell the user something", nil) - subtitle:NSLocalizedString(@"This is some neutral notification!", nil) - type:TSMessageNotificationTypeMessage]; + TSMessageView *messageView = [TSMessage displayMessageWithTitle:NSLocalizedString(@"Tell the user something", nil) + subtitle:NSLocalizedString(@"This is some neutral message!", nil) + type:TSMessageTypeDefault]; [messageView setUserDismissEnabled]; } - (IBAction)didTapSuccess:(id)sender { - TSMessageView *messageView = [TSMessage showNotificationWithTitle:NSLocalizedString(@"Success", nil) - subtitle:NSLocalizedString(@"Some task was successfully completed!", nil) - type:TSMessageNotificationTypeSuccess]; + TSMessageView *messageView = [TSMessage displayMessageWithTitle:NSLocalizedString(@"Success", nil) + subtitle:NSLocalizedString(@"Some task was successfully completed!", nil) + type:TSMessageTypeSuccess]; [messageView setUserDismissEnabled]; } - (IBAction)didTapButton:(id)sender { - TSMessageView *view = [TSMessage notificationWithTitle:NSLocalizedString(@"New version available", nil) - subtitle:NSLocalizedString(@"Please update our app. We would be very thankful", nil) - type:TSMessageNotificationTypeMessage]; + TSMessageView *view = [TSMessage messageWithTitle:NSLocalizedString(@"New version available", nil) + subtitle:NSLocalizedString(@"Please update our app. We would be very thankful", nil) + type:TSMessageTypeDefault]; [view setButtonWithTitle:NSLocalizedString(@"Update", nil) callback:^(TSMessageView *messageView) { [messageView dismiss]; - - [TSMessage showNotificationWithTitle:NSLocalizedString(@"Thanks for updating", nil) subtitle:nil type:TSMessageNotificationTypeSuccess]; + + [TSMessage displayMessageWithTitle:NSLocalizedString(@"Thanks for updating", nil) + subtitle:nil + type:TSMessageTypeSuccess]; }]; [view setUserDismissEnabled]; - [TSMessage showOrEnqueueNotification:view]; + [TSMessage displayOrEnqueueMessage:view]; } - (IBAction)didTapPermanent:(id)sender { - TSMessageView *view = [TSMessage notificationWithTitle:NSLocalizedString(@"Permanent notification", nil) - subtitle:NSLocalizedString(@"Stays here until it gets dismissed", nil) - type:TSMessageNotificationTypeMessage]; + TSMessageView *view = [TSMessage messageWithTitle:NSLocalizedString(@"Permanent message", nil) + subtitle:NSLocalizedString(@"Stays here until it gets dismissed", nil) + type:TSMessageTypeDefault]; - view.position = TSMessageNotificationPositionBottom; + view.position = TSMessagePositionBottom; [view setButtonWithTitle:NSLocalizedString(@"Dismiss", nil) callback:^(TSMessageView *messageView) { [messageView dismiss]; }]; view.tapCallback = ^(TSMessageView *messageView) { - [TSMessage showNotificationWithTitle:NSLocalizedString(@"Action triggered", nil) subtitle:nil type:TSMessageNotificationTypeSuccess]; + [TSMessage displayMessageWithTitle:NSLocalizedString(@"Action triggered", nil) + subtitle:nil + type:TSMessageTypeSuccess]; }; [view setUserDismissEnabled]; - [TSMessage showPermanentNotification:view]; + [TSMessage displayPermanentMessage:view]; } - (IBAction)didTapToggleNavigationBar:(id)sender @@ -141,78 +145,77 @@ - (IBAction)didTapToggleStatusbar:(id)sender - (IBAction)didTapCustomImage:(id)sender { - UIImage *image = [UIImage imageNamed:@"NotificationButtonBackground.png"]; + UIImage *image = [UIImage imageNamed:@"MessageButtonBackground.png"]; - TSMessageView *messageView = [TSMessage notificationWithTitle:NSLocalizedString(@"Custom image", nil) - subtitle:NSLocalizedString(@"This uses an image you can define", nil) - image:image - type:TSMessageNotificationTypeMessage - inViewController:self]; + TSMessageView *messageView = [TSMessage messageWithTitle:NSLocalizedString(@"Custom image", nil) + subtitle:NSLocalizedString(@"This uses an image you can define", nil) + image:image + type:TSMessageTypeDefault + inViewController:self]; [messageView setUserDismissEnabled]; - [TSMessage showOrEnqueueNotification:messageView]; + [TSMessage displayOrEnqueueMessage:messageView]; } - (IBAction)didTapDismissCurrentMessage:(id)sender { - [TSMessage dismissActiveNotification]; + [TSMessage dismissCurrentMessage]; } - (IBAction)didTapEndless:(id)sender { - TSMessageView *messageView = [TSMessage notificationWithTitle:NSLocalizedString(@"Endless", nil) - subtitle:NSLocalizedString(@"This message can not be dismissed and will not be hidden automatically. Tap the 'Dismiss' button to dismiss the currently shown message", nil) - type:TSMessageNotificationTypeSuccess]; + TSMessageView *messageView = [TSMessage messageWithTitle:NSLocalizedString(@"Endless", nil) + subtitle:NSLocalizedString(@"This message can not be dismissed and will not be hidden automatically. Tap the 'Dismiss' button to dismiss the current message.", nil) + type:TSMessageTypeSuccess]; - messageView.duration = TSMessageNotificationDurationEndless; + messageView.duration = TSMessageDurationEndless; - [TSMessage showOrEnqueueNotification:messageView]; + [TSMessage displayOrEnqueueMessage:messageView]; } - (IBAction)didTapLong:(id)sender { - TSMessageView *messageView = [TSMessage notificationWithTitle:NSLocalizedString(@"Long", nil) - subtitle:NSLocalizedString(@"This message is displayed 10 seconds instead of the calculated value", nil) - type:TSMessageNotificationTypeWarning]; + TSMessageView *messageView = [TSMessage messageWithTitle:NSLocalizedString(@"Long", nil) + subtitle:NSLocalizedString(@"This message is displayed 10 seconds instead of the calculated value", nil) + type:TSMessageTypeWarning]; messageView.duration = 10.0; [messageView setUserDismissEnabled]; - [TSMessage showOrEnqueueNotification:messageView]; + [TSMessage displayOrEnqueueMessage:messageView]; } - (IBAction)didTapBottom:(id)sender { - TSMessageView *messageView = [TSMessage notificationWithTitle:NSLocalizedString(@"Hu!", nil) - subtitle:NSLocalizedString(@"I'm down here :)", nil) - type:TSMessageNotificationTypeSuccess]; + TSMessageView *messageView = [TSMessage messageWithTitle:NSLocalizedString(@"Hu!", nil) + subtitle:NSLocalizedString(@"I'm down here :)", nil) + type:TSMessageTypeSuccess]; - messageView.duration = TSMessageNotificationDurationAutomatic; - messageView.position = TSMessageNotificationPositionBottom; + messageView.duration = TSMessageDurationAutomatic; + messageView.position = TSMessagePositionBottom; [messageView setUserDismissEnabled]; - [TSMessage showOrEnqueueNotification:messageView]; + [TSMessage displayOrEnqueueMessage:messageView]; } - (IBAction)didTapText:(id)sender { - TSMessageView *messageView = [TSMessage showNotificationWithTitle:NSLocalizedString(@"With 'Text' I meant a long text, so here it is", nil) - subtitle:NSLocalizedString(@"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus", nil) - type:TSMessageNotificationTypeWarning]; + TSMessageView *messageView = [TSMessage displayMessageWithTitle:NSLocalizedString(@"With 'Text' I meant a long text, so here it is", nil) + subtitle:NSLocalizedString(@"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus", nil) + type:TSMessageTypeWarning]; [messageView setUserDismissEnabled]; } - (IBAction)didTapCustomDesign:(id)sender { - // this is an example on how to apply a custom design [TSMessage addCustomDesignFromFileWithName:@"AlternativeDesign.json"]; - TSMessageView *messageView = [TSMessage showNotificationWithTitle:NSLocalizedString(@"Updated to custom design file", nil) - subtitle:NSLocalizedString(@"From now on, all the titles of success messages are larger", nil) - type:TSMessageNotificationTypeSuccess]; + TSMessageView *messageView = [TSMessage displayMessageWithTitle:NSLocalizedString(@"Updated to custom design file", nil) + subtitle:NSLocalizedString(@"From now on, all the titles of success messages are larger", nil) + type:TSMessageTypeSuccess]; [messageView setUserDismissEnabled]; } diff --git a/ExampleProject/Pods/Local Podspecs/TSMessages.podspec b/ExampleProject/Pods/Local Podspecs/TSMessages.podspec index 2a41f31b..d0c68047 100644 --- a/ExampleProject/Pods/Local Podspecs/TSMessages.podspec +++ b/ExampleProject/Pods/Local Podspecs/TSMessages.podspec @@ -1,13 +1,13 @@ Pod::Spec.new do |s| s.name = "TSMessages" s.version = "0.9.4" - s.summary = "Easy to use and customizable messages/notifications for iOS à la Tweetbot." + s.summary = "Easy to use and customizable messages for iOS à la Tweetbot." s.description = <<-DESC - This framework provides an easy to use class to show little notification views on the top of the screen. (à la Tweetbot). -The notification moves from the top of the screen underneath the navigation bar and stays there for a few seconds, depending on the length of the displayed text. To dismiss a notification before the time runs out, the user can swipe it to the top or just tap it. + This framework provides an easy to use class to show little message views on the top of the screen. (à la Tweetbot). +The message moves from the top of the screen underneath the navigation bar and stays there for a few seconds, depending on the length of the displayed text. To dismiss a message before the time runs out, the user can swipe it to the top or just tap it. There are 4 different types already set up for you: Success, Error, Warning, Message. DESC - + s.homepage = "https://github.com/toursprung/TSMessages/" s.license = 'MIT' @@ -16,14 +16,14 @@ There are 4 different types already set up for you: Success, Error, Warning, Mes s.author = { "Felix Krause" => "krausefx@gmail.com" } s.source = { :git => "https://github.com/toursprung/TSMessages.git", :tag => "0.9.4"} - + s.platform = :ios, '5.0' s.source_files = 'TSMessages/Classes/**/*.{h,m}', 'TSMessages/Views/**/*.{h,m}' s.resources = "TSMessages/Resources/**/*.{png,json}" - + s.requires_arc = true s.dependency 'HexColors' end diff --git a/ExampleProject/Pods/Pods-resources.sh b/ExampleProject/Pods/Pods-resources.sh index 54f63589..16a51736 100755 --- a/ExampleProject/Pods/Pods-resources.sh +++ b/ExampleProject/Pods/Pods-resources.sh @@ -39,22 +39,22 @@ install_resource() ;; esac } -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundError.png" -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundError@2x.png" -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundErrorIcon.png" -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundErrorIcon@2x.png" -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundMessage.png" -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundMessage@2x.png" -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundSuccess.png" -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundSuccess@2x.png" -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundSuccessIcon.png" -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundSuccessIcon@2x.png" -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundWarning.png" -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundWarning@2x.png" -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundWarningIcon.png" -install_resource "../../TSMessages/Resources/Images/NotificationBackgroundWarningIcon@2x.png" -install_resource "../../TSMessages/Resources/Images/NotificationButtonBackground.png" -install_resource "../../TSMessages/Resources/Images/NotificationButtonBackground@2x.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundError.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundError@2x.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundErrorIcon.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundErrorIcon@2x.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundDefault.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundDefault@2x.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundSuccess.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundSuccess@2x.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundSuccessIcon.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundSuccessIcon@2x.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundWarning.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundWarning@2x.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundWarningIcon.png" +install_resource "../../TSMessages/Resources/Images/MessageBackgroundWarningIcon@2x.png" +install_resource "../../TSMessages/Resources/Images/MessageButtonBackground.png" +install_resource "../../TSMessages/Resources/Images/MessageButtonBackground@2x.png" install_resource "../../TSMessages/Resources/TSMessagesDefaultDesign.json" rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" diff --git a/ExampleProject/Pods/Pods.xcodeproj/project.pbxproj b/ExampleProject/Pods/Pods.xcodeproj/project.pbxproj index 90d676b2..7f550c82 100644 --- a/ExampleProject/Pods/Pods.xcodeproj/project.pbxproj +++ b/ExampleProject/Pods/Pods.xcodeproj/project.pbxproj @@ -50,8 +50,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 0664DAB085284272A58FA5C1 /* NotificationBackgroundMessage.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundMessage.png; path = TSMessages/Resources/Images/NotificationBackgroundMessage.png; sourceTree = ""; }; - 07359EA6F65641E7B1FA9119 /* NotificationBackgroundWarningIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundWarningIcon@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundWarningIcon@2x.png"; sourceTree = ""; }; + 0664DAB085284272A58FA5C1 /* MessageBackgroundDefault.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = MessageBackgroundDefault.png; path = TSMessages/Resources/Images/MessageBackgroundDefault.png; sourceTree = ""; }; + 07359EA6F65641E7B1FA9119 /* MessageBackgroundWarningIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "MessageBackgroundWarningIcon@2x.png"; path = "TSMessages/Resources/Images/MessageBackgroundWarningIcon@2x.png"; sourceTree = ""; }; 08ED9A1527024644ADCBA9CD /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Pods.xcconfig; sourceTree = ""; }; 09E89CC7D8724A98B872DF42 /* TSMessage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = TSMessage.m; path = TSMessages/Classes/TSMessage.m; sourceTree = ""; }; 0AF065F777E848F29746E2F6 /* HexColor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HexColor.h; path = Classes/HexColor.h; sourceTree = ""; }; @@ -61,12 +61,12 @@ 2EA90CF918B2AB60008B71EF /* TSMessageView+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "TSMessageView+Private.h"; path = "TSMessages/Views/TSMessageView+Private.h"; sourceTree = ""; }; 3B17E30CA6F248738B1CCE1F /* TSBlurView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = TSBlurView.h; path = TSMessages/Views/TSBlurView.h; sourceTree = ""; }; 3DED0B6E248A4FBEB11DFB7D /* Pods-HexColors-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-HexColors-prefix.pch"; sourceTree = ""; }; - 3EEBBA57508D41E99C45BA64 /* NotificationButtonBackground@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationButtonBackground@2x.png"; path = "TSMessages/Resources/Images/NotificationButtonBackground@2x.png"; sourceTree = ""; }; - 3FFBF8A4E845423A93DE50A6 /* NotificationBackgroundWarningIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundWarningIcon.png; path = TSMessages/Resources/Images/NotificationBackgroundWarningIcon.png; sourceTree = ""; }; - 41F15AC86CD44FEEA58FC25A /* NotificationBackgroundError.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundError.png; path = TSMessages/Resources/Images/NotificationBackgroundError.png; sourceTree = ""; }; + 3EEBBA57508D41E99C45BA64 /* MessageButtonBackground@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "MessageButtonBackground@2x.png"; path = "TSMessages/Resources/Images/MessageButtonBackground@2x.png"; sourceTree = ""; }; + 3FFBF8A4E845423A93DE50A6 /* MessageBackgroundWarningIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = MessageBackgroundWarningIcon.png; path = TSMessages/Resources/Images/MessageBackgroundWarningIcon.png; sourceTree = ""; }; + 41F15AC86CD44FEEA58FC25A /* MessageBackgroundError.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = MessageBackgroundError.png; path = TSMessages/Resources/Images/MessageBackgroundError.png; sourceTree = ""; }; 48F158896D204969B78EF9EE /* Pods-HexColors.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-HexColors.xcconfig"; sourceTree = ""; }; 53202C8D4E6B4B018F7C74D6 /* TSMessageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = TSMessageView.h; path = TSMessages/Views/TSMessageView.h; sourceTree = ""; }; - 560E3253C75441BFAC032222 /* NotificationBackgroundSuccessIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundSuccessIcon.png; path = TSMessages/Resources/Images/NotificationBackgroundSuccessIcon.png; sourceTree = ""; }; + 560E3253C75441BFAC032222 /* MessageBackgroundSuccessIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = MessageBackgroundSuccessIcon.png; path = TSMessages/Resources/Images/MessageBackgroundSuccessIcon.png; sourceTree = ""; }; 5ED86E633260493EA1A2F499 /* HexColor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HexColor.m; path = Classes/HexColor.m; sourceTree = ""; }; 618EA4400E7548A38F36A30A /* Pods-HexColors-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-HexColors-dummy.m"; sourceTree = ""; }; 63CAD95C55E041EEAD195B89 /* libPods-TSMessages.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-TSMessages.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -75,27 +75,27 @@ 75B471412A9147839B6A56D1 /* libPods-HexColors.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HexColors.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 87EB580E368F4E6CB33840A8 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 899217DAF97C4C3F9BAE6861 /* Pods-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-dummy.m"; sourceTree = ""; }; - 95AC99116638428092659625 /* NotificationButtonBackground.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationButtonBackground.png; path = TSMessages/Resources/Images/NotificationButtonBackground.png; sourceTree = ""; }; - A08DC63CAC864D67BB5EF8D0 /* NotificationBackgroundWarning.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundWarning.png; path = TSMessages/Resources/Images/NotificationBackgroundWarning.png; sourceTree = ""; }; + 95AC99116638428092659625 /* MessageButtonBackground.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = MessageButtonBackground.png; path = TSMessages/Resources/Images/MessageButtonBackground.png; sourceTree = ""; }; + A08DC63CAC864D67BB5EF8D0 /* MessageBackgroundWarning.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = MessageBackgroundWarning.png; path = TSMessages/Resources/Images/MessageBackgroundWarning.png; sourceTree = ""; }; A1A1D99C3C214E88A19D1243 /* Podfile */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; A68C68D28A4A4CE5A2765112 /* Pods-TSMessages.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TSMessages.xcconfig"; sourceTree = ""; }; AF317538018444A5BCCE7E50 /* TSMessagesDefaultDesign.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = TSMessagesDefaultDesign.json; path = TSMessages/Resources/TSMessagesDefaultDesign.json; sourceTree = ""; }; - B430868717094FA5818548C7 /* NotificationBackgroundError@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundError@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundError@2x.png"; sourceTree = ""; }; - BAEF50BEB4FB427C888F0C83 /* NotificationBackgroundErrorIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundErrorIcon@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundErrorIcon@2x.png"; sourceTree = ""; }; + B430868717094FA5818548C7 /* MessageBackgroundError@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "MessageBackgroundError@2x.png"; path = "TSMessages/Resources/Images/MessageBackgroundError@2x.png"; sourceTree = ""; }; + BAEF50BEB4FB427C888F0C83 /* MessageBackgroundErrorIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "MessageBackgroundErrorIcon@2x.png"; path = "TSMessages/Resources/Images/MessageBackgroundErrorIcon@2x.png"; sourceTree = ""; }; BEBBB8EDFAD74B189406A0B0 /* TSMessageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = TSMessageView.m; path = TSMessages/Views/TSMessageView.m; sourceTree = ""; }; C49A102233D542D7BC33EA02 /* Pods-TSMessages-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-TSMessages-dummy.m"; sourceTree = ""; }; - C7F2DD42A80247B39C9E8B0A /* NotificationBackgroundMessage@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundMessage@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundMessage@2x.png"; sourceTree = ""; }; + C7F2DD42A80247B39C9E8B0A /* MessageBackgroundDefault@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "MessageBackgroundDefault@2x.png"; path = "TSMessages/Resources/Images/MessageBackgroundDefault@2x.png"; sourceTree = ""; }; CC5BD63FA0E64476B6D096E2 /* Pods-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-acknowledgements.markdown"; sourceTree = ""; }; CCA854EFD62D4F43B92AB2F6 /* Pods-TSMessages-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TSMessages-Private.xcconfig"; sourceTree = ""; }; - CD662529CAB847FD9E04D618 /* NotificationBackgroundErrorIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundErrorIcon.png; path = TSMessages/Resources/Images/NotificationBackgroundErrorIcon.png; sourceTree = ""; }; + CD662529CAB847FD9E04D618 /* MessageBackgroundErrorIcon.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = MessageBackgroundErrorIcon.png; path = TSMessages/Resources/Images/MessageBackgroundErrorIcon.png; sourceTree = ""; }; CE97B018E4C2414A9A5C3FAB /* Pods-TSMessages-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-TSMessages-prefix.pch"; sourceTree = ""; }; D00A0431231A400AA0A4F3B2 /* Pods-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-acknowledgements.plist"; sourceTree = ""; }; - D83066B9EE164853BDDADFC1 /* NotificationBackgroundSuccess.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = NotificationBackgroundSuccess.png; path = TSMessages/Resources/Images/NotificationBackgroundSuccess.png; sourceTree = ""; }; + D83066B9EE164853BDDADFC1 /* MessageBackgroundSuccess.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = MessageBackgroundSuccess.png; path = TSMessages/Resources/Images/MessageBackgroundSuccess.png; sourceTree = ""; }; E6F8608730F84A098DEB8A05 /* TSMessage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = TSMessage.h; path = TSMessages/Classes/TSMessage.h; sourceTree = ""; }; - E9D4E4D4993E44ECA6E4D666 /* NotificationBackgroundWarning@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundWarning@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundWarning@2x.png"; sourceTree = ""; }; + E9D4E4D4993E44ECA6E4D666 /* MessageBackgroundWarning@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "MessageBackgroundWarning@2x.png"; path = "TSMessages/Resources/Images/MessageBackgroundWarning@2x.png"; sourceTree = ""; }; EB62E0597B194FE5A930E405 /* Pods-HexColors-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-HexColors-Private.xcconfig"; sourceTree = ""; }; - EF26C31740F34C1DA03DE6F0 /* NotificationBackgroundSuccess@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundSuccess@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundSuccess@2x.png"; sourceTree = ""; }; - F062BB1E748A4BA18E2EE45B /* NotificationBackgroundSuccessIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "NotificationBackgroundSuccessIcon@2x.png"; path = "TSMessages/Resources/Images/NotificationBackgroundSuccessIcon@2x.png"; sourceTree = ""; }; + EF26C31740F34C1DA03DE6F0 /* MessageBackgroundSuccess@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "MessageBackgroundSuccess@2x.png"; path = "TSMessages/Resources/Images/MessageBackgroundSuccess@2x.png"; sourceTree = ""; }; + F062BB1E748A4BA18E2EE45B /* MessageBackgroundSuccessIcon@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "MessageBackgroundSuccessIcon@2x.png"; path = "TSMessages/Resources/Images/MessageBackgroundSuccessIcon@2x.png"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -149,14 +149,14 @@ 3A68D0F35A2448709D775945 /* Source Files */ = { isa = PBXGroup; children = ( - 3B17E30CA6F248738B1CCE1F /* TSBlurView.h */, E6F8608730F84A098DEB8A05 /* TSMessage.h */, 2E35B5F218AED63C0000C422 /* TSMessage+Private.h */, + 09E89CC7D8724A98B872DF42 /* TSMessage.m */, 53202C8D4E6B4B018F7C74D6 /* TSMessageView.h */, 2EA90CF918B2AB60008B71EF /* TSMessageView+Private.h */, - 24F689F22A5A42809DBA68A7 /* TSBlurView.m */, - 09E89CC7D8724A98B872DF42 /* TSMessage.m */, BEBBB8EDFAD74B189406A0B0 /* TSMessageView.m */, + 3B17E30CA6F248738B1CCE1F /* TSBlurView.h */, + 24F689F22A5A42809DBA68A7 /* TSBlurView.m */, ); name = "Source Files"; sourceTree = ""; @@ -224,22 +224,22 @@ isa = PBXGroup; children = ( AF317538018444A5BCCE7E50 /* TSMessagesDefaultDesign.json */, - 41F15AC86CD44FEEA58FC25A /* NotificationBackgroundError.png */, - B430868717094FA5818548C7 /* NotificationBackgroundError@2x.png */, - CD662529CAB847FD9E04D618 /* NotificationBackgroundErrorIcon.png */, - BAEF50BEB4FB427C888F0C83 /* NotificationBackgroundErrorIcon@2x.png */, - 0664DAB085284272A58FA5C1 /* NotificationBackgroundMessage.png */, - C7F2DD42A80247B39C9E8B0A /* NotificationBackgroundMessage@2x.png */, - D83066B9EE164853BDDADFC1 /* NotificationBackgroundSuccess.png */, - EF26C31740F34C1DA03DE6F0 /* NotificationBackgroundSuccess@2x.png */, - 560E3253C75441BFAC032222 /* NotificationBackgroundSuccessIcon.png */, - F062BB1E748A4BA18E2EE45B /* NotificationBackgroundSuccessIcon@2x.png */, - A08DC63CAC864D67BB5EF8D0 /* NotificationBackgroundWarning.png */, - E9D4E4D4993E44ECA6E4D666 /* NotificationBackgroundWarning@2x.png */, - 3FFBF8A4E845423A93DE50A6 /* NotificationBackgroundWarningIcon.png */, - 07359EA6F65641E7B1FA9119 /* NotificationBackgroundWarningIcon@2x.png */, - 95AC99116638428092659625 /* NotificationButtonBackground.png */, - 3EEBBA57508D41E99C45BA64 /* NotificationButtonBackground@2x.png */, + 41F15AC86CD44FEEA58FC25A /* MessageBackgroundError.png */, + B430868717094FA5818548C7 /* MessageBackgroundError@2x.png */, + CD662529CAB847FD9E04D618 /* MessageBackgroundErrorIcon.png */, + BAEF50BEB4FB427C888F0C83 /* MessageBackgroundErrorIcon@2x.png */, + 0664DAB085284272A58FA5C1 /* MessageBackgroundDefault.png */, + C7F2DD42A80247B39C9E8B0A /* MessageBackgroundDefault@2x.png */, + D83066B9EE164853BDDADFC1 /* MessageBackgroundSuccess.png */, + EF26C31740F34C1DA03DE6F0 /* MessageBackgroundSuccess@2x.png */, + 560E3253C75441BFAC032222 /* MessageBackgroundSuccessIcon.png */, + F062BB1E748A4BA18E2EE45B /* MessageBackgroundSuccessIcon@2x.png */, + A08DC63CAC864D67BB5EF8D0 /* MessageBackgroundWarning.png */, + E9D4E4D4993E44ECA6E4D666 /* MessageBackgroundWarning@2x.png */, + 3FFBF8A4E845423A93DE50A6 /* MessageBackgroundWarningIcon.png */, + 07359EA6F65641E7B1FA9119 /* MessageBackgroundWarningIcon@2x.png */, + 95AC99116638428092659625 /* MessageButtonBackground.png */, + 3EEBBA57508D41E99C45BA64 /* MessageButtonBackground@2x.png */, ); name = Resources; sourceTree = ""; diff --git a/TSMessages.podspec b/TSMessages.podspec index c9f9cdef..43f0c36f 100644 --- a/TSMessages.podspec +++ b/TSMessages.podspec @@ -1,13 +1,13 @@ Pod::Spec.new do |s| s.name = "TSMessages" s.version = "0.9.4" - s.summary = "Easy to use and customizable messages/notifications for iOS à la Tweetbot." + s.summary = "Easy to use and customizable messages for iOS à la Tweetbot." s.description = <<-DESC - This framework provides an easy to use class to show little notification views on the top of the screen. (à la Tweetbot). -The notification moves from the top of the screen underneath the navigation bar and stays there for a few seconds, depending on the length of the displayed text. To dismiss a notification before the time runs out, the user can swipe it to the top or just tap it. + This framework provides an easy to use class to show little message views on the top of the screen. (à la Tweetbot). +The message moves from the top of the screen underneath the navigation bar and stays there for a few seconds, depending on the length of the displayed text. To dismiss a message before the time runs out, the user can swipe it to the top or just tap it. There are 4 different types already set up for you: Success, Error, Warning, Message. DESC - + s.homepage = "https://github.com/toursprung/TSMessages/" s.license = 'MIT' @@ -15,14 +15,14 @@ There are 4 different types already set up for you: Success, Error, Warning, Mes s.author = { "Felix Krause" => "krausefx@gmail.com" } s.source = { :git => "https://github.com/toursprung/TSMessages.git", :tag => "#{s.version}"} - + s.platform = :ios, '5.0' s.source_files = 'TSMessages/Classes/**/*.{h,m}', 'TSMessages/Views/**/*.{h,m}' s.resources = "TSMessages/Resources/**/*.{png,json}" - + s.requires_arc = true s.dependency 'HexColors' end diff --git a/TSMessages/Classes/TSMessage+Private.h b/TSMessages/Classes/TSMessage+Private.h index 5caf98c8..acb5130d 100644 --- a/TSMessages/Classes/TSMessage+Private.h +++ b/TSMessages/Classes/TSMessage+Private.h @@ -11,9 +11,9 @@ @class TSMessageView; @interface TSMessage (Private) -+ (NSMutableDictionary *)notificationDesign; -- (void)fadeOutCurrentNotification; -- (void)fadeOutNotification:(TSMessageView *)messageView; -- (void)fadeOutNotification:(TSMessageView *)messageView completion:(void (^)())completion; -- (TSMessageView *)currentNotification; ++ (NSMutableDictionary *)design; +- (void)dismissCurrentMessage; +- (void)dismissMessage:(TSMessageView *)messageView; +- (void)dismissMessage:(TSMessageView *)messageView completion:(void (^)())completion; +- (TSMessageView *)currentMessage; @end \ No newline at end of file diff --git a/TSMessages/Classes/TSMessage.h b/TSMessages/Classes/TSMessage.h index df780580..af8961b4 100755 --- a/TSMessages/Classes/TSMessage.h +++ b/TSMessages/Classes/TSMessage.h @@ -10,21 +10,21 @@ @class TSMessageView; -typedef NS_ENUM(NSInteger, TSMessageNotificationType) { - TSMessageNotificationTypeMessage = 0, - TSMessageNotificationTypeSuccess, - TSMessageNotificationTypeWarning, - TSMessageNotificationTypeError +typedef NS_ENUM(NSInteger, TSMessageType) { + TSMessageTypeDefault = 0, + TSMessageTypeSuccess, + TSMessageTypeWarning, + TSMessageTypeError }; -typedef NS_ENUM(NSInteger, TSMessageNotificationPosition) { - TSMessageNotificationPositionTop = 0, - TSMessageNotificationPositionBottom +typedef NS_ENUM(NSInteger, TSMessagePosition) { + TSMessagePositionTop = 0, + TSMessagePositionBottom }; -typedef NS_ENUM(NSInteger, TSMessageNotificationDuration) { - TSMessageNotificationDurationAutomatic = 0, - TSMessageNotificationDurationEndless = -1, // The notification is displayed until the user dismissed it or it is dismissed by calling dismissActiveNotification +typedef NS_ENUM(NSInteger, TSMessageDuration) { + TSMessageDurationAutomatic = 0, + TSMessageDurationEndless = -1, // The message is displayed until the user dismissed it or it is dismissed by calling dismissCurrentMessage }; typedef void (^TSMessageCallback)(TSMessageView *messageView); @@ -37,60 +37,60 @@ typedef void (^TSMessageCallback)(TSMessageView *messageView); /** Returns a message view for further customization - @param title The title of the notification view + @param title The title of the message view @param subtitle The text that is displayed underneath the title - @param type The notification type (Message, Warning, Error, Success) - + @param type The message type (Default, Warning, Error, Success) + @return The message view */ -+ (TSMessageView *)notificationWithTitle:(NSString *)title - subtitle:(NSString *)subtitle - type:(TSMessageNotificationType)type; ++ (TSMessageView *)messageWithTitle:(NSString *)title + subtitle:(NSString *)subtitle + type:(TSMessageType)type; -/** Shows a notification right away and returns the message view +/** Displays a message right away and returns the message view - @param title The title of the notification view + @param title The title of the message view @param subtitle The text that is displayed underneath the title - @param type The notification type (Message, Warning, Error, Success) - + @param type The message type (Default, Warning, Error, Success) + @return The message view */ -+ (TSMessageView *)showNotificationWithTitle:(NSString *)title - subtitle:(NSString *)subtitle - type:(TSMessageNotificationType)type; ++ (TSMessageView *)displayMessageWithTitle:(NSString *)title + subtitle:(NSString *)subtitle + type:(TSMessageType)type; /** Returns a message view in a specific view controller for further customization - - @param title The title of the notification view + + @param title The title of the message view @param subtitle The message that is displayed underneath the title (optional) @param image A custom icon image (optional) - @param type The notification type (Message, Warning, Error, Success) - @param viewController The view controller to show the notification in - + @param type The message type (Default, Warning, Error, Success) + @param viewController The view controller to display the message in + @return The message view */ -+ (TSMessageView *)notificationWithTitle:(NSString *)title - subtitle:(NSString *)subtitle - image:(UIImage *)image - type:(TSMessageNotificationType)type - inViewController:(UIViewController *)viewController; ++ (TSMessageView *)messageWithTitle:(NSString *)title + subtitle:(NSString *)subtitle + image:(UIImage *)image + type:(TSMessageType)type + inViewController:(UIViewController *)viewController; -/** Shows a notification right away in a specific view controller and returns +/** Displays a message right away in a specific view controller and returns the message view - - @param title The title of the notification view + + @param title The title of the message view @param subtitle The text that is displayed underneath the title @param image A custom icon image (optional) - @param type The notification type (Message, Warning, Error, Success) - @param viewController The view controller to show the notification in - + @param type The message type (Default, Warning, Error, Success) + @param viewController The view controller to display the message in + @return The message view */ -+ (TSMessageView *)showNotificationWithTitle:(NSString *)title - subtitle:(NSString *)subtitle - image:(UIImage *)image - type:(TSMessageNotificationType)type - inViewController:(UIViewController *)viewController; ++ (TSMessageView *)displayMessageWithTitle:(NSString *)title + subtitle:(NSString *)subtitle + image:(UIImage *)image + type:(TSMessageType)type + inViewController:(UIViewController *)viewController; /** Use this method to set a default view controller to display the messages in */ + (void)setDefaultViewController:(UIViewController *)defaultViewController; @@ -98,38 +98,38 @@ typedef void (^TSMessageCallback)(TSMessageView *messageView); /** Use this method to use custom designs for your messages. */ + (void)addCustomDesignFromFileWithName:(NSString *)fileName; -/** Fades out the currently displayed notification. If another notification is in the queue, - the next one will be displayed automatically - - @return YES if the currently displayed notification was successfully dismissed. - NO if no notification was currently displayed. +/** Dismisses the current message. If another message is in the queue, + it will be displayed automatically. + + @return YES if the current message was successfully dismissed. + NO if there is no current message to be dismissed. */ -+ (BOOL)dismissActiveNotification; ++ (BOOL)dismissCurrentMessage; + +/** Indicates whether a message is currently being displayed. -/** Indicates whether a notification is currently active. - - @return YES if a notification is currently being displayed. - NO if no notification is currently being displayed. + @return YES if a message is currently being displayed. + NO if no message is currently being displayed. */ -+ (BOOL)isNotificationActive; ++ (BOOL)isDisplayingMessage; -/** Shows or enqueues the notification view. If there is a notification - displayed currently, the notification view gets added to the end of the - queue and displayed after its prior notifications are shown. If it is - the only notification it gets shown right away. +/** Displays or enqueues the message view. If there is a message + displayed currently, the message view gets added to the end of the + queue and displayed after its prior messages are displayed. + If it is the only message it gets displayed right away. */ -+ (void)showOrEnqueueNotification:(TSMessageView *)messageView; ++ (void)displayOrEnqueueMessage:(TSMessageView *)messageView; -/** Shows a permanent notification message. - - This differs from normal notifications in that permanent messages are not +/** Displays a permanent message. + + This differs from normal message in that permanent messages are not contained in the messages queue and can be displayed in addition to the other messages. - - Permanent notifications do not get dismissed automatically, hence they do + + Permanent messages do not get dismissed automatically, hence they do not have a duration but have to be dismissed by the user or programmatically in one of the callbacks. */ -+ (void)showPermanentNotification:(TSMessageView *)messageView; ++ (void)displayPermanentMessage:(TSMessageView *)messageView; @end diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index a94bddd6..ff5ae9c3 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -45,14 +45,14 @@ - (id)init return self; } -#pragma mark - Setup notifications +#pragma mark - Setup messages -+ (TSMessageView *)notificationWithTitle:(NSString *)title subtitle:(NSString *)subtitle type:(TSMessageNotificationType)type ++ (TSMessageView *)messageWithTitle:(NSString *)title subtitle:(NSString *)subtitle type:(TSMessageType)type { - return [self notificationWithTitle:title subtitle:subtitle image:nil type:type inViewController:self.defaultViewController]; + return [self messageWithTitle:title subtitle:subtitle image:nil type:type inViewController:self.defaultViewController]; } -+ (TSMessageView *)notificationWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageNotificationType)type inViewController:(UIViewController *)viewController ++ (TSMessageView *)messageWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageType)type inViewController:(UIViewController *)viewController { TSMessageView *view = [[TSMessageView alloc] initWithTitle:title subtitle:subtitle image:image type:type]; @@ -61,70 +61,70 @@ + (TSMessageView *)notificationWithTitle:(NSString *)title subtitle:(NSString *) return view; } -#pragma mark - Setup notifications and display them right away +#pragma mark - Setup messages and display them right away -+ (TSMessageView *)showNotificationWithTitle:(NSString *)title subtitle:(NSString *)subtitle type:(TSMessageNotificationType)type ++ (TSMessageView *)displayMessageWithTitle:(NSString *)title subtitle:(NSString *)subtitle type:(TSMessageType)type { - return [self showNotificationWithTitle:title subtitle:subtitle image:nil type:type inViewController:self.defaultViewController]; + return [self displayMessageWithTitle:title subtitle:subtitle image:nil type:type inViewController:self.defaultViewController]; } -+ (TSMessageView *)showNotificationWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageNotificationType)type inViewController:(UIViewController *)viewController ++ (TSMessageView *)displayMessageWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageType)type inViewController:(UIViewController *)viewController { - TSMessageView *view = [self notificationWithTitle:title subtitle:subtitle image:image type:type inViewController:viewController]; + TSMessageView *view = [self messageWithTitle:title subtitle:subtitle image:image type:type inViewController:viewController]; - [self showOrEnqueueNotification:view]; + [self displayOrEnqueueMessage:view]; return view; } -#pragma mark - Displaying notifications +#pragma mark - Displaying messages -+ (void)showPermanentNotification:(TSMessageView *)messageView ++ (void)displayPermanentMessage:(TSMessageView *)messageView { - [[TSMessage sharedMessage] fadeInNotification:messageView]; + [[TSMessage sharedMessage] fadeInMessage:messageView]; } -+ (void)showOrEnqueueNotification:(TSMessageView *)messageView ++ (void)displayOrEnqueueMessage:(TSMessageView *)messageView { NSString *title = messageView.title; NSString *subtitle = messageView.subtitle; for (TSMessageView *n in [TSMessage sharedMessage].messages) { - // avoid showing the same messages twice in a row + // avoid displaying the same messages twice in a row BOOL equalTitle = ([n.title isEqualToString:title] || (!n.title && !title)); BOOL equalSubtitle = ([n.subtitle isEqualToString:subtitle] || (!n.subtitle && !subtitle)); if (equalTitle && equalSubtitle) return; } - BOOL isDisplayable = !self.isNotificationActive; + BOOL isDisplayable = !self.isDisplayingMessage; [[TSMessage sharedMessage].messages addObject:messageView]; if (isDisplayable) { - [[TSMessage sharedMessage] fadeInCurrentNotification]; + [[TSMessage sharedMessage] fadeInCurrentMessage]; } } -+ (BOOL)dismissActiveNotification ++ (BOOL)dismissCurrentMessage { - if (![TSMessage sharedMessage].currentNotification) return NO; + if (![TSMessage sharedMessage].currentMessage) return NO; dispatch_async(dispatch_get_main_queue(), ^{ - [[TSMessage sharedMessage] fadeOutCurrentNotification]; + [[TSMessage sharedMessage] dismissCurrentMessage]; }); return YES; } -+ (BOOL)isNotificationActive ++ (BOOL)isDisplayingMessage { - return !![TSMessage sharedMessage].currentNotification; + return !![TSMessage sharedMessage].currentMessage; } -#pragma mark - Customizing notifications design +#pragma mark - Customizing design + (void)addCustomDesignFromFileWithName:(NSString *)fileName { @@ -133,12 +133,12 @@ + (void)addCustomDesignFromFileWithName:(NSString *)fileName NSData *data = [NSData dataWithContentsOfFile:path]; NSDictionary *design = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; - [self.notificationDesign addEntriesFromDictionary:design]; + [self.design addEntriesFromDictionary:design]; } -+ (NSMutableDictionary *)notificationDesign ++ (NSMutableDictionary *)design { - static NSMutableDictionary *notificationDesign = nil; + static NSMutableDictionary *design = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -147,10 +147,10 @@ + (NSMutableDictionary *)notificationDesign NSData *data = [NSData dataWithContentsOfFile:path]; NSDictionary *config = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; - notificationDesign = [NSMutableDictionary dictionaryWithDictionary:config]; + design = [NSMutableDictionary dictionaryWithDictionary:config]; }); - return notificationDesign; + return design; } #pragma mark - Default view controller @@ -161,7 +161,7 @@ + (UIViewController *)defaultViewController if (!defaultViewController) { - NSLog(@"TSMessages: It is recommended to set a custom defaultViewController that is used to display the notifications"); + NSLog(@"TSMessages: It is recommended to set a custom defaultViewController that is used to display the messages"); defaultViewController = [UIApplication sharedApplication].keyWindow.rootViewController; } @@ -175,21 +175,21 @@ + (void)setDefaultViewController:(UIViewController *)defaultViewController #pragma mark - Internals -- (TSMessageView *)currentNotification +- (TSMessageView *)currentMessage { if (!self.messages.count) return nil; return [self.messages firstObject]; } -- (void)fadeInCurrentNotification +- (void)fadeInCurrentMessage { - if (!self.currentNotification) return; + if (!self.currentMessage) return; - [self fadeInNotification:self.currentNotification]; + [self fadeInMessage:self.currentMessage]; } -- (void)fadeInNotification:(TSMessageView *)messageView +- (void)fadeInMessage:(TSMessageView *)messageView { [messageView prepareForDisplay]; @@ -250,7 +250,7 @@ - (void)fadeInNotification:(TSMessageView *)messageView } CGPoint toPoint; - if (messageView.position == TSMessageNotificationPositionTop) + if (messageView.position == TSMessagePositionTop) { CGFloat navigationbarBottomOfViewController = 0; @@ -285,41 +285,41 @@ - (void)fadeInNotification:(TSMessageView *)messageView messageView.messageFullyDisplayed = YES; }]; - if (messageView.duration == TSMessageNotificationDurationAutomatic) + if (messageView.duration == TSMessageDurationAutomatic) { messageView.duration = kTSMessageAnimationDuration + kTSMessageDisplayTime + messageView.frame.size.height * kTSMessageExtraDisplayTimePerPixel; } - if (messageView.duration != TSMessageNotificationDurationEndless) + if (messageView.duration != TSMessageDurationEndless) { dispatch_async(dispatch_get_main_queue(), ^{ - [self performSelector:@selector(fadeOutCurrentNotification) withObject:nil afterDelay:messageView.duration]; + [self performSelector:@selector(dismissCurrentMessage) withObject:nil afterDelay:messageView.duration]; }); } } -- (void)fadeOutNotification:(TSMessageView *)messageView +- (void)dismissMessage:(TSMessageView *)messageView { - [self fadeOutNotification:messageView completion:NULL]; + [self dismissMessage:messageView completion:NULL]; } -- (void)fadeOutNotification:(TSMessageView *)messageView completion:(void (^)())completion +- (void)dismissMessage:(TSMessageView *)messageView completion:(void (^)())completion { messageView.messageFullyDisplayed = NO; - CGPoint fadeOutToPoint; + CGPoint dismissToPoint; - if (messageView.position == TSMessageNotificationPositionTop) + if (messageView.position == TSMessagePositionTop) { - fadeOutToPoint = CGPointMake(messageView.center.x, -CGRectGetHeight(messageView.frame)/2.f); + dismissToPoint = CGPointMake(messageView.center.x, -CGRectGetHeight(messageView.frame)/2.f); } else { - fadeOutToPoint = CGPointMake(messageView.center.x, messageView.viewController.view.bounds.size.height + CGRectGetHeight(messageView.frame)/2.f); + dismissToPoint = CGPointMake(messageView.center.x, messageView.viewController.view.bounds.size.height + CGRectGetHeight(messageView.frame)/2.f); } [UIView animateWithDuration:kTSMessageAnimationDuration animations:^{ - messageView.center = fadeOutToPoint; + messageView.center = dismissToPoint; } completion:^(BOOL finished) { [messageView removeFromSuperview]; @@ -327,13 +327,13 @@ - (void)fadeOutNotification:(TSMessageView *)messageView completion:(void (^)()) }]; } -- (void)fadeOutCurrentNotification +- (void)dismissCurrentMessage { - if (!self.currentNotification) return; + if (!self.currentMessage) return; - [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(fadeOutCurrentNotification) object:nil]; + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(dismissCurrentMessage) object:nil]; - [self fadeOutNotification:self.currentNotification completion:^{ + [self dismissMessage:self.currentMessage completion:^{ if (self.messages.count) { [self.messages removeObjectAtIndex:0]; @@ -341,7 +341,7 @@ - (void)fadeOutCurrentNotification if (self.messages.count) { - [self fadeInCurrentNotification]; + [self fadeInCurrentMessage]; } }]; } diff --git a/TSMessages/Resources/Images/NotificationBackgroundMessage.png b/TSMessages/Resources/Images/MessageBackgroundDefault.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundMessage.png rename to TSMessages/Resources/Images/MessageBackgroundDefault.png diff --git a/TSMessages/Resources/Images/NotificationBackgroundMessage@2x.png b/TSMessages/Resources/Images/MessageBackgroundDefault@2x.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundMessage@2x.png rename to TSMessages/Resources/Images/MessageBackgroundDefault@2x.png diff --git a/TSMessages/Resources/Images/NotificationBackgroundError.png b/TSMessages/Resources/Images/MessageBackgroundError.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundError.png rename to TSMessages/Resources/Images/MessageBackgroundError.png diff --git a/TSMessages/Resources/Images/NotificationBackgroundError@2x.png b/TSMessages/Resources/Images/MessageBackgroundError@2x.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundError@2x.png rename to TSMessages/Resources/Images/MessageBackgroundError@2x.png diff --git a/TSMessages/Resources/Images/NotificationBackgroundErrorIcon.png b/TSMessages/Resources/Images/MessageBackgroundErrorIcon.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundErrorIcon.png rename to TSMessages/Resources/Images/MessageBackgroundErrorIcon.png diff --git a/TSMessages/Resources/Images/NotificationBackgroundErrorIcon@2x.png b/TSMessages/Resources/Images/MessageBackgroundErrorIcon@2x.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundErrorIcon@2x.png rename to TSMessages/Resources/Images/MessageBackgroundErrorIcon@2x.png diff --git a/TSMessages/Resources/Images/NotificationBackgroundSuccess.png b/TSMessages/Resources/Images/MessageBackgroundSuccess.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundSuccess.png rename to TSMessages/Resources/Images/MessageBackgroundSuccess.png diff --git a/TSMessages/Resources/Images/NotificationBackgroundSuccess@2x.png b/TSMessages/Resources/Images/MessageBackgroundSuccess@2x.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundSuccess@2x.png rename to TSMessages/Resources/Images/MessageBackgroundSuccess@2x.png diff --git a/TSMessages/Resources/Images/NotificationBackgroundSuccessIcon.png b/TSMessages/Resources/Images/MessageBackgroundSuccessIcon.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundSuccessIcon.png rename to TSMessages/Resources/Images/MessageBackgroundSuccessIcon.png diff --git a/TSMessages/Resources/Images/NotificationBackgroundSuccessIcon@2x.png b/TSMessages/Resources/Images/MessageBackgroundSuccessIcon@2x.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundSuccessIcon@2x.png rename to TSMessages/Resources/Images/MessageBackgroundSuccessIcon@2x.png diff --git a/TSMessages/Resources/Images/NotificationBackgroundWarning.png b/TSMessages/Resources/Images/MessageBackgroundWarning.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundWarning.png rename to TSMessages/Resources/Images/MessageBackgroundWarning.png diff --git a/TSMessages/Resources/Images/NotificationBackgroundWarning@2x.png b/TSMessages/Resources/Images/MessageBackgroundWarning@2x.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundWarning@2x.png rename to TSMessages/Resources/Images/MessageBackgroundWarning@2x.png diff --git a/TSMessages/Resources/Images/NotificationBackgroundWarningIcon.png b/TSMessages/Resources/Images/MessageBackgroundWarningIcon.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundWarningIcon.png rename to TSMessages/Resources/Images/MessageBackgroundWarningIcon.png diff --git a/TSMessages/Resources/Images/NotificationBackgroundWarningIcon@2x.png b/TSMessages/Resources/Images/MessageBackgroundWarningIcon@2x.png similarity index 100% rename from TSMessages/Resources/Images/NotificationBackgroundWarningIcon@2x.png rename to TSMessages/Resources/Images/MessageBackgroundWarningIcon@2x.png diff --git a/TSMessages/Resources/Images/NotificationButtonBackground.png b/TSMessages/Resources/Images/MessageButtonBackground.png similarity index 100% rename from TSMessages/Resources/Images/NotificationButtonBackground.png rename to TSMessages/Resources/Images/MessageButtonBackground.png diff --git a/TSMessages/Resources/Images/NotificationButtonBackground@2x.png b/TSMessages/Resources/Images/MessageButtonBackground@2x.png similarity index 100% rename from TSMessages/Resources/Images/NotificationButtonBackground@2x.png rename to TSMessages/Resources/Images/MessageButtonBackground@2x.png diff --git a/TSMessages/Resources/TSMessagesDefaultDesign.json b/TSMessages/Resources/TSMessagesDefaultDesign.json index abf139a2..4b3dfa54 100644 --- a/TSMessages/Resources/TSMessagesDefaultDesign.json +++ b/TSMessages/Resources/TSMessagesDefaultDesign.json @@ -1,16 +1,16 @@ { "success": { - "backgroundImageName": "NotificationBackgroundSuccess.png", + "backgroundImageName": "MessageBackgroundSuccess.png", "borderColor": "#005700", "borderHeight": 1, - "buttonBackgroundImageName": "NotificationButtonBackground.png", + "buttonBackgroundImageName": "MessageButtonBackground.png", "buttonTitleTextColor": "#FFFFFF", "buttonTitleShadowColor": "#67B759", "buttonTitleShadowOffsetX": 0, "buttonTitleShadowOffsetY": -1, "contentFontSize": 12, "contentTextColor": "#FFFFFF", - "imageName": "NotificationBackgroundSuccessIcon.png", + "imageName": "MessageBackgroundSuccessIcon.png", "shadowColor": "#67B759", "shadowOffsetX": 0, "shadowOffsetY": -1, @@ -20,10 +20,10 @@ "backgroundAlpha": 0.8 }, "message": { - "backgroundImageName": "NotificationBackgroundMessage.png", + "backgroundImageName": "MessageBackgroundDefault.png", "borderColor": "#727C83", "borderHeight": 1, - "buttonBackgroundImageName": "NotificationButtonBackground.png", + "buttonBackgroundImageName": "MessageButtonBackground.png", "buttonTitleTextColor": "#727C83", "buttonTitleShadowColor": "#EBEEF1", "buttonTitleShadowOffsetX": 0, @@ -39,17 +39,17 @@ "backgroundColor": "#D4DDDF" }, "warning": { - "backgroundImageName": "NotificationBackgroundWarning.png", + "backgroundImageName": "MessageBackgroundWarning.png", "borderColor": "#A28918", "borderHeight": 1, - "buttonBackgroundImageName": "NotificationButtonBackground.png", + "buttonBackgroundImageName": "MessageButtonBackground.png", "buttonTitleTextColor": "#484638", "buttonTitleShadowColor": "#E5D87C", "buttonTitleShadowOffsetX": 0, "buttonTitleShadowOffsetY": 1, "contentFontSize": 12, "contentTextColor": "#484638", - "imageName": "NotificationBackgroundWarningIcon.png", + "imageName": "MessageBackgroundWarningIcon.png", "shadowColor": "#E5D87C", "shadowOffsetX": 0, "shadowOffsetY": 1, @@ -58,17 +58,17 @@ "backgroundColor": "#DAC43C" }, "error": { - "backgroundImageName": "NotificationBackgroundError.png", + "backgroundImageName": "MessageBackgroundError.png", "borderColor": "#700000", "borderHeight": 1, - "buttonBackgroundImageName": "NotificationButtonBackground.png", + "buttonBackgroundImageName": "MessageButtonBackground.png", "buttonTitleTextColor": "#FFFFFF", "buttonTitleShadowColor": "#812929", "buttonTitleShadowOffsetX": 0, "buttonTitleShadowOffsetY": -1, "contentFontSize": 12, "contentTextColor": "#FFFFFF", - "imageName": "NotificationBackgroundErrorIcon.png", + "imageName": "MessageBackgroundErrorIcon.png", "shadowColor": "#812929", "shadowOffsetX": 0, "shadowOffsetY": -1, diff --git a/TSMessages/Views/TSMessageView.h b/TSMessages/Views/TSMessageView.h index 1c95cbc6..901a79e7 100755 --- a/TSMessages/Views/TSMessageView.h +++ b/TSMessages/Views/TSMessageView.h @@ -28,17 +28,17 @@ @property (nonatomic, assign) CGFloat duration; /** The position of the message (top or bottom) */ -@property (nonatomic, assign) TSMessageNotificationPosition position; +@property (nonatomic, assign) TSMessagePosition position; -/** By setting this delegate it's possible to set a custom offset for the notification view */ -@property(nonatomic, assign) id delegate; +/** By setting this delegate it's possible to set a custom offset for the message view */ +@property (nonatomic, assign) id delegate; /** The callback that should be invoked, when the user taps the message */ @property (nonatomic, copy) TSMessageCallback tapCallback; -- (id)initWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageNotificationType)notificationType; +- (id)initWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageType)type; -/** Dismisses this notification view */ +/** Dismisses this message view */ - (void)dismiss; /** Adds a button with a callback that gets invoked when the button is tapped */ diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index f69c419e..a3c97053 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -29,14 +29,14 @@ @interface TSMessageView () @implementation TSMessageView -- (id)initWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageNotificationType)notificationType +- (id)initWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageType)type { if ((self = [self init])) { - self.duration = TSMessageNotificationDurationAutomatic; - self.position = TSMessageNotificationPositionTop; + self.duration = TSMessageDurationAutomatic; + self.position = TSMessagePositionTop; - [self setupConfigForType:notificationType]; + [self setupConfigForType:type]; [self setupBackgroundView]; [self setupTitle:title]; [self setupSubtitle:subtitle]; @@ -50,20 +50,20 @@ - (id)initWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIIma #pragma mark - Setup helpers -- (void)setupConfigForType:(TSMessageNotificationType)notificationType +- (void)setupConfigForType:(TSMessageType)type { NSString *config; - switch (notificationType) + switch (type) { - case TSMessageNotificationTypeError: config = @"error"; break; - case TSMessageNotificationTypeSuccess: config = @"success"; break; - case TSMessageNotificationTypeWarning: config = @"warning"; break; + case TSMessageTypeError: config = @"error"; break; + case TSMessageTypeSuccess: config = @"success"; break; + case TSMessageTypeWarning: config = @"warning"; break; default: config = @"message"; break; } - self.config = [TSMessage notificationDesign][config]; + self.config = [TSMessage design][config]; } - (void)setupBackgroundView @@ -77,7 +77,7 @@ - (void)setupBackgroundView - (void)setupAutoresizing { - self.autoresizingMask = (self.position == TSMessageNotificationPositionTop) ? + self.autoresizingMask = (self.position == TSMessagePositionTop) ? (UIViewAutoresizingFlexibleWidth) : (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); } @@ -157,7 +157,7 @@ - (void)setButtonWithTitle:(NSString *)title callback:(TSMessageCallback)callbac UIColor *buttonTitleTextColor = [UIColor colorWithHexString:self.config[@"buttonTitleTextColor"] alpha:1]; UIColor *fontColor = [UIColor colorWithHexString:self.config[@"textColor"] alpha:1]; - if (!buttonBackgroundImage) buttonBackgroundImage = [[UIImage imageNamed:self.config[@"NotificationButtonBackground"]] resizableImageWithCapInsets:UIEdgeInsetsMake(15.0, 12.0, 15.0, 11.0)]; + if (!buttonBackgroundImage) buttonBackgroundImage = [[UIImage imageNamed:self.config[@"MessageButtonBackground"]] resizableImageWithCapInsets:UIEdgeInsetsMake(15.0, 12.0, 15.0, 11.0)]; if (!buttonTitleShadowColor) buttonTitleShadowColor = [UIColor colorWithHexString:self.config[@"shadowColor"] alpha:1]; if (!buttonTitleTextColor) buttonTitleTextColor = fontColor; @@ -190,7 +190,7 @@ - (void)setUserDismissEnabledWithCallback:(TSMessageCallback)callback self.dismissCallback = callback; UISwipeGestureRecognizer *gestureRec = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss)]; - gestureRec.direction = (self.position == TSMessageNotificationPositionTop ? UISwipeGestureRecognizerDirectionUp : UISwipeGestureRecognizerDirectionDown); + gestureRec.direction = (self.position == TSMessagePositionTop ? UISwipeGestureRecognizerDirectionUp : UISwipeGestureRecognizerDirectionDown); [self addGestureRecognizer:gestureRec]; } @@ -200,7 +200,7 @@ - (void)didMoveToWindow { [super didMoveToWindow]; - if (self.duration == TSMessageNotificationDurationEndless && self.superview && !self.window) + if (self.duration == TSMessageDurationEndless && self.superview && !self.window) { [self dismiss]; } @@ -277,7 +277,7 @@ - (void)layoutSubviews currentHeight); // increase frame of background view because of the spring animation - if (self.position == TSMessageNotificationPositionTop) + if (self.position == TSMessagePositionTop) { float topOffset = 0.f; @@ -296,7 +296,7 @@ - (void)layoutSubviews backgroundFrame = UIEdgeInsetsInsetRect(backgroundFrame, UIEdgeInsetsMake(topOffset, 0.f, topOffset, 0.f)); } - else if (self.position == TSMessageNotificationPositionBottom) + else if (self.position == TSMessagePositionBottom) { backgroundFrame = UIEdgeInsetsInsetRect(backgroundFrame, UIEdgeInsetsMake(0.f, 0.f, -30.f, 0.f)); } @@ -312,7 +312,7 @@ - (void)prepareForDisplay CGFloat actualHeight = self.frame.size.height; CGFloat topPosition = -actualHeight; - if (self.position == TSMessageNotificationPositionBottom) + if (self.position == TSMessagePositionBottom) { topPosition = self.viewController.view.bounds.size.height; } @@ -342,13 +342,13 @@ - (void)handleTap:(UITapGestureRecognizer *)tapGesture - (void)dismiss { - if (self == [TSMessage sharedMessage].currentNotification) + if (self == [TSMessage sharedMessage].currentMessage) { - [[TSMessage sharedMessage] performSelectorOnMainThread:@selector(fadeOutCurrentNotification) withObject:nil waitUntilDone:NO]; + [[TSMessage sharedMessage] performSelectorOnMainThread:@selector(dismissCurrentMessage) withObject:nil waitUntilDone:NO]; } else { - [[TSMessage sharedMessage] performSelectorOnMainThread:@selector(fadeOutNotification:) withObject:self waitUntilDone:NO]; + [[TSMessage sharedMessage] performSelectorOnMainThread:@selector(dismissMessage:) withObject:self waitUntilDone:NO]; } } From 51e6b096f5dc928dab1898fe703467a90ba29549 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Fri, 21 Feb 2014 21:46:39 +0100 Subject: [PATCH 16/27] Update README --- README.md | 81 +++++++++++++++++++++++++------------------------------ 1 file changed, 36 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index befd2dd7..2e0f725e 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ TSMessages ========== -This framework provides an easy to use class to show little notification views on the top of the screen. (à la Tweetbot). +This framework provides an easy to use class to display message views (à la Tweetbot). -The notification moves from the top of the screen underneath the navigation bar and stays there for a few seconds, depending on the length of the displayed text. To dismiss a notification before the time runs out, the user can swipe it to the top or just tap it. +The message moves from the top of the screen underneath the navigation bar and stays there for a few seconds, depending on the length of the displayed text. To dismiss a message before the time runs out, the user can swipe it to the top or just tap it. -There are 4 different types already set up for you: Success, Error, Warning, Message (take a look at the screenshots) +There are 4 different types already set up for you: Success, Error, Warning, Message (take a look at the screenshots). -It is very easy to add new notification types with a different design. Add the new type to the notificationType enum, add the needed design properties to the configuration file and set the name of the theme (used in the config file and images) in TSMessagesView.m inside the switch case. +It is very easy to add new message types with a different design. Add the new type to the message type enum, add the needed design properties to the configuration file and set the name of the theme (used in the config file and images) in TSMessagesView.m inside the switch case. **Take a look at the Example project to see how to use this library.** You have to open the workspace, not the project file, since the Example project uses cocoapods. @@ -25,30 +25,28 @@ Drag the whole folder into your project and remove the example project. This lib Drag HexColors{.h/.m} from Submodules/HexColors/Classes into your project. -To show notifications use the following code: +To display messages use the following code: -------- ```objective-c - [TSMessage showNotificationWithTitle:title - subtitle:subtitle - type:TSMessageNotificationTypeError]; - - - // Add a button inside the message - [TSMessage showNotificationInViewController:self - title:NSLocalizedString(@"New version available", nil) - subtitle:NSLocalizedString(@"Please update our app. We would be very thankful", nil) - image:nil - type:TSMessageNotificationTypeMessage - duration:TSMessageNotificationDurationAutomatic - callback:nil - buttonTitle:NSLocalizedString(@"Update", nil) - buttonCallback:^{ - [TSMessage showNotificationWithTitle:NSLocalizedString(@"Thanks for updating", nil) - type:TSMessageNotificationTypeSuccess]; - } - atPosition:TSMessageNotificationPositionTop - canBeDismisedByUser:YES]; + [TSMessage displayMessageWithTitle:title + subtitle:subtitle + type:TSMessageTypeError]; + + // Add a button to the message + TSMessageView *view = [TSMessage messageWithTitle:@"New version available" + subtitle:@"Please update our app" + type:TSMessageTypeDefault]; + + [view setButtonWithTitle:NSLocalizedString(@"Update", nil) callback:^(TSMessageView *messageView) { + [messageView dismiss]; + + [TSMessage displayMessageWithTitle:NSLocalizedString(@"Thanks for updating", nil) + subtitle:nil + type:TSMessageTypeSuccess]; + }]; + + [TSMessage displayOrEnqueueMessage:view]; // Use a custom design file [TSMessage addCustomDesignFromFileWithName:@"AlternativeDesign.json"]; @@ -56,26 +54,20 @@ To show notifications use the following code: The following properties can be set: -* **viewController**: The view controller to show the notification in. This might be the navigation controller. -* **title**: The title of the notification view +* **viewController**: The view controller to show the message in. This might be the navigation controller. +* **title**: The title of the message view * **subtitle**: The text that is displayed underneath the title (optional) * **image**: A custom icon image that is used instead of the default one (optional) -* **type**: The notification type (Message, Warning, Error, Success) -* **duration**: The duration the notification should be displayed -* **callback**: The block that should be executed, when the user dismissed the message by tapping on it or swiping it to the top. +* **type**: The message type (Message, Warning, Error, Success) +* **duration**: The duration the message should be displayed (optional) +* **callback**: The block that should be executed, when the user dismissed the message by swiping it away (optional) -Except the title and the notification type, all of the listed values are optional +Except the title and the message type, all of the listed values are optional -You don't need to do anything with TSMessageView, except you want to modify the behavior or the types of the notification itself. +You don't need to do anything with TSMessageView, except you want to modify the behavior or the types of the message itself. -If you don't want a detailed description (the text underneath the title) you don't need to set one. The notification will automatically resize itself properly. There are different initializer available. +If you don't want a detailed description (the text underneath the title) you don't need to set one. The message will automatically resize itself properly. -![Warning](http://www.toursprung.com/wp-content/uploads/2013/04/iNotificationWarning.png) -![Success](http://www.toursprung.com/wp-content/uploads/2013/04/iNotificationSuccess.png) -![Error](http://www.toursprung.com/wp-content/uploads/2013/04/iNotificationError.png) -![Message](http://www.toursprung.com/wp-content/uploads/2013/04/iNotificationMessage.png) - -**iOS 7 Support** ![iOS 7 Error](http://www.toursprung.com/wp-content/uploads/2013/09/error_ios7.png) ![iOS 7 Message](http://www.toursprung.com/wp-content/uploads/2013/09/warning_ios7.png) @@ -96,9 +88,9 @@ Changes * Added new customization options for buttons (font size, custom background image, separate font and shadow color) * Added method to dismiss the currently active message * Added option to show a message until it is dismissed by the user -* Added option to disable dismissing notification by the user -* Added method to check whether a notification is currently being displayed -* Fixed auto rotation when notification is displayed on the bottom +* Added option to disable dismissing message by the user +* Added method to check whether a message is currently being displayed +* Fixed auto rotation when message is displayed on the bottom **0.9.2** @@ -106,8 +98,7 @@ Changes * Added option to show a button inside the message - - TODOs ----- -Currently empty \ No newline at end of file +* Fix/improve blur effect +* Potentially support UIKit Dynamics From 8613d476b5381d53e0f5a1c0d0dbc47bc1fbe12f Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Fri, 21 Feb 2014 22:14:01 +0100 Subject: [PATCH 17/27] Improve interface with convenience methods --- ExampleProject/Example/TSDemoViewController.m | 12 ++++++------ README.md | 2 +- TSMessages/Views/TSMessageView.h | 6 ++++++ TSMessages/Views/TSMessageView.m | 8 ++++++++ 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/ExampleProject/Example/TSDemoViewController.m b/ExampleProject/Example/TSDemoViewController.m index a8f44bb3..95a1af53 100644 --- a/ExampleProject/Example/TSDemoViewController.m +++ b/ExampleProject/Example/TSDemoViewController.m @@ -100,7 +100,7 @@ - (IBAction)didTapButton:(id)sender [view setUserDismissEnabled]; - [TSMessage displayOrEnqueueMessage:view]; + [view displayOrEnqueue]; } - (IBAction)didTapPermanent:(id)sender @@ -123,7 +123,7 @@ - (IBAction)didTapPermanent:(id)sender [view setUserDismissEnabled]; - [TSMessage displayPermanentMessage:view]; + [view displayPermanently]; } - (IBAction)didTapToggleNavigationBar:(id)sender @@ -155,7 +155,7 @@ - (IBAction)didTapCustomImage:(id)sender [messageView setUserDismissEnabled]; - [TSMessage displayOrEnqueueMessage:messageView]; + [messageView displayOrEnqueue]; } - (IBAction)didTapDismissCurrentMessage:(id)sender @@ -171,7 +171,7 @@ - (IBAction)didTapEndless:(id)sender messageView.duration = TSMessageDurationEndless; - [TSMessage displayOrEnqueueMessage:messageView]; + [messageView displayOrEnqueue]; } - (IBAction)didTapLong:(id)sender @@ -183,7 +183,7 @@ - (IBAction)didTapLong:(id)sender [messageView setUserDismissEnabled]; - [TSMessage displayOrEnqueueMessage:messageView]; + [messageView displayOrEnqueue]; } - (IBAction)didTapBottom:(id)sender @@ -197,7 +197,7 @@ - (IBAction)didTapBottom:(id)sender [messageView setUserDismissEnabled]; - [TSMessage displayOrEnqueueMessage:messageView]; + [messageView displayOrEnqueue]; } - (IBAction)didTapText:(id)sender diff --git a/README.md b/README.md index 2e0f725e..bb97b55c 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ To display messages use the following code: type:TSMessageTypeSuccess]; }]; - [TSMessage displayOrEnqueueMessage:view]; + [view displayOrEnqueue]; // Use a custom design file [TSMessage addCustomDesignFromFileWithName:@"AlternativeDesign.json"]; diff --git a/TSMessages/Views/TSMessageView.h b/TSMessages/Views/TSMessageView.h index 901a79e7..5a70b322 100755 --- a/TSMessages/Views/TSMessageView.h +++ b/TSMessages/Views/TSMessageView.h @@ -47,4 +47,10 @@ /** Enables dismissing the message by swiping */ - (void)setUserDismissEnabled; - (void)setUserDismissEnabledWithCallback:(TSMessageCallback)callback; + +/** Displays or enqueues the message view. */ +- (void)displayOrEnqueue; + +/** Displays the message permanently. */ +- (void)displayPermanently; @end diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index a3c97053..c2171555 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -194,6 +194,14 @@ - (void)setUserDismissEnabledWithCallback:(TSMessageCallback)callback [self addGestureRecognizer:gestureRec]; } +- (void)displayOrEnqueue { + [TSMessage displayOrEnqueueMessage:self]; +} + +- (void)displayPermanently { + [TSMessage displayPermanentMessage:self]; +} + #pragma mark - View handling - (void)didMoveToWindow From 5de4704f5d71841d7c10051612adbc9cff578e2e Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Fri, 21 Feb 2014 22:17:01 +0100 Subject: [PATCH 18/27] Fix naming I oversaw --- TSMessages/Classes/TSMessage.m | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index ff5ae9c3..c53a2c10 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -81,7 +81,7 @@ + (TSMessageView *)displayMessageWithTitle:(NSString *)title subtitle:(NSString + (void)displayPermanentMessage:(TSMessageView *)messageView { - [[TSMessage sharedMessage] fadeInMessage:messageView]; + [[TSMessage sharedMessage] displayMessage:messageView]; } + (void)displayOrEnqueueMessage:(TSMessageView *)messageView @@ -104,7 +104,7 @@ + (void)displayOrEnqueueMessage:(TSMessageView *)messageView if (isDisplayable) { - [[TSMessage sharedMessage] fadeInCurrentMessage]; + [[TSMessage sharedMessage] displayCurrentMessage]; } } @@ -182,14 +182,14 @@ - (TSMessageView *)currentMessage return [self.messages firstObject]; } -- (void)fadeInCurrentMessage +- (void)displayCurrentMessage { if (!self.currentMessage) return; - [self fadeInMessage:self.currentMessage]; + [self displayMessage:self.currentMessage]; } -- (void)fadeInMessage:(TSMessageView *)messageView +- (void)displayMessage:(TSMessageView *)messageView { [messageView prepareForDisplay]; @@ -341,7 +341,7 @@ - (void)dismissCurrentMessage if (self.messages.count) { - [self fadeInCurrentMessage]; + [self displayCurrentMessage]; } }]; } From 464fd8143b9a8cba78eec8854a1e26b2294097a5 Mon Sep 17 00:00:00 2001 From: Felix Krause Date: Sat, 22 Feb 2014 10:55:05 +0100 Subject: [PATCH 19/27] Improved shadow color of text in alternativeDesign.json --- ExampleProject/Example/AlternativeDesign.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ExampleProject/Example/AlternativeDesign.json b/ExampleProject/Example/AlternativeDesign.json index 5b30713a..57a9c630 100644 --- a/ExampleProject/Example/AlternativeDesign.json +++ b/ExampleProject/Example/AlternativeDesign.json @@ -11,7 +11,7 @@ "contentFontSize": 12, "contentTextColor": "#FFFFFF", "imageName": "MessageBackgroundSuccessIcon.png", - "shadowColor": "#67B759", + "shadowColor": "#000000", "shadowOffsetX": 0, "shadowOffsetY": -1, "textColor": "#FFFFFF", @@ -29,7 +29,7 @@ "contentFontSize": 12, "contentTextColor": "#727C83", "imageName": "", - "shadowColor": "#EBEEF1", + "shadowColor": "#000000", "shadowOffsetX": 0, "shadowOffsetY": 1, "textColor": "#727C83", @@ -47,7 +47,7 @@ "contentFontSize": 12, "contentTextColor": "#484638", "imageName": "MessageBackgroundWarningIcon.png", - "shadowColor": "#E5D87C", + "shadowColor": "#000000", "shadowOffsetX": 0, "shadowOffsetY": 1, "textColor": "#484638", @@ -65,7 +65,7 @@ "contentFontSize": 12, "contentTextColor": "#FFFFFF", "imageName": "MessageBackgroundErrorIcon.png", - "shadowColor": "#812929", + "shadowColor": "#000000", "shadowOffsetX": 0, "shadowOffsetY": -1, "textColor": "#FFFFFF", From 8d446be0a1bbdb584c78eb11997e71f4f2bbcef0 Mon Sep 17 00:00:00 2001 From: Felix Krause Date: Sat, 22 Feb 2014 11:08:26 +0100 Subject: [PATCH 20/27] * Updated alternative design file to fit iOS 7 style --- ExampleProject/Example/AlternativeDesign.json | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/ExampleProject/Example/AlternativeDesign.json b/ExampleProject/Example/AlternativeDesign.json index 57a9c630..243bfe99 100644 --- a/ExampleProject/Example/AlternativeDesign.json +++ b/ExampleProject/Example/AlternativeDesign.json @@ -11,11 +11,13 @@ "contentFontSize": 12, "contentTextColor": "#FFFFFF", "imageName": "MessageBackgroundSuccessIcon.png", - "shadowColor": "#000000", + "shadowColor": "#67B759", "shadowOffsetX": 0, "shadowOffsetY": -1, "textColor": "#FFFFFF", - "titleFontSize": 25 + "titleFontSize": 25, + "backgroundColor": "#76CF67", + "backgroundAlpha": 0.8 }, "message": { "backgroundImageName": "MessageBackgroundDefault.png", @@ -29,11 +31,12 @@ "contentFontSize": 12, "contentTextColor": "#727C83", "imageName": "", - "shadowColor": "#000000", + "shadowColor": "#EBEEF1", "shadowOffsetX": 0, "shadowOffsetY": 1, "textColor": "#727C83", - "titleFontSize": 14 + "titleFontSize": 14, + "backgroundColor": "#D4DDDF" }, "warning": { "backgroundImageName": "MessageBackgroundWarning.png", @@ -47,11 +50,12 @@ "contentFontSize": 12, "contentTextColor": "#484638", "imageName": "MessageBackgroundWarningIcon.png", - "shadowColor": "#000000", + "shadowColor": "#E5D87C", "shadowOffsetX": 0, "shadowOffsetY": 1, "textColor": "#484638", - "titleFontSize": 14 + "titleFontSize": 14, + "backgroundColor": "#DAC43C" }, "error": { "backgroundImageName": "MessageBackgroundError.png", @@ -65,10 +69,11 @@ "contentFontSize": 12, "contentTextColor": "#FFFFFF", "imageName": "MessageBackgroundErrorIcon.png", - "shadowColor": "#000000", + "shadowColor": "#812929", "shadowOffsetX": 0, "shadowOffsetY": -1, "textColor": "#FFFFFF", - "titleFontSize": 14 + "titleFontSize": 14, + "backgroundColor": "#DD3B41" } } \ No newline at end of file From c750d80b4e1e8f63a8d3c7ba4dca236dd03d5988 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Sun, 23 Feb 2014 11:35:34 +0100 Subject: [PATCH 21/27] Change userDismissEnabled and make it default --- ExampleProject/Example/TSDemoViewController.m | 58 ++++++---------- README.md | 1 + TSMessages/Views/TSMessageView.h | 7 +- TSMessages/Views/TSMessageView.m | 67 ++++++++++--------- 4 files changed, 59 insertions(+), 74 deletions(-) diff --git a/ExampleProject/Example/TSDemoViewController.m b/ExampleProject/Example/TSDemoViewController.m index 95a1af53..4038c926 100644 --- a/ExampleProject/Example/TSDemoViewController.m +++ b/ExampleProject/Example/TSDemoViewController.m @@ -54,34 +54,30 @@ - (CGFloat)navigationbarBottomOfViewController:(UIViewController *)viewControlle - (IBAction)didTapError:(id)sender { - TSMessageView *messageView = [TSMessage displayMessageWithTitle:NSLocalizedString(@"Something failed", nil) - subtitle:NSLocalizedString(@"The internet connection seems to be down. Please check that!", nil) - type:TSMessageTypeError]; - [messageView setUserDismissEnabled]; + [TSMessage displayMessageWithTitle:NSLocalizedString(@"Something failed", nil) + subtitle:NSLocalizedString(@"The internet connection seems to be down. Please check that!", nil) + type:TSMessageTypeError]; } - (IBAction)didTapWarning:(id)sender { - TSMessageView *messageView = [TSMessage displayMessageWithTitle:NSLocalizedString(@"Some random warning", nil) - subtitle:NSLocalizedString(@"Look out! Something is happening there!", nil) - type:TSMessageTypeWarning]; - [messageView setUserDismissEnabled]; + [TSMessage displayMessageWithTitle:NSLocalizedString(@"Some random warning", nil) + subtitle:NSLocalizedString(@"Look out! Something is happening there!", nil) + type:TSMessageTypeWarning]; } - (IBAction)didTapMessage:(id)sender { - TSMessageView *messageView = [TSMessage displayMessageWithTitle:NSLocalizedString(@"Tell the user something", nil) - subtitle:NSLocalizedString(@"This is some neutral message!", nil) - type:TSMessageTypeDefault]; - [messageView setUserDismissEnabled]; + [TSMessage displayMessageWithTitle:NSLocalizedString(@"Tell the user something", nil) + subtitle:NSLocalizedString(@"This is some neutral message!", nil) + type:TSMessageTypeDefault]; } - (IBAction)didTapSuccess:(id)sender { - TSMessageView *messageView = [TSMessage displayMessageWithTitle:NSLocalizedString(@"Success", nil) - subtitle:NSLocalizedString(@"Some task was successfully completed!", nil) - type:TSMessageTypeSuccess]; - [messageView setUserDismissEnabled]; + [TSMessage displayMessageWithTitle:NSLocalizedString(@"Success", nil) + subtitle:NSLocalizedString(@"Some task was successfully completed!", nil) + type:TSMessageTypeSuccess]; } - (IBAction)didTapButton:(id)sender @@ -98,8 +94,6 @@ - (IBAction)didTapButton:(id)sender type:TSMessageTypeSuccess]; }]; - [view setUserDismissEnabled]; - [view displayOrEnqueue]; } @@ -108,7 +102,8 @@ - (IBAction)didTapPermanent:(id)sender TSMessageView *view = [TSMessage messageWithTitle:NSLocalizedString(@"Permanent message", nil) subtitle:NSLocalizedString(@"Stays here until it gets dismissed", nil) type:TSMessageTypeDefault]; - + + view.userDismissEnabled = NO; view.position = TSMessagePositionBottom; [view setButtonWithTitle:NSLocalizedString(@"Dismiss", nil) callback:^(TSMessageView *messageView) { @@ -121,8 +116,6 @@ - (IBAction)didTapPermanent:(id)sender type:TSMessageTypeSuccess]; }; - [view setUserDismissEnabled]; - [view displayPermanently]; } @@ -153,8 +146,6 @@ - (IBAction)didTapCustomImage:(id)sender type:TSMessageTypeDefault inViewController:self]; - [messageView setUserDismissEnabled]; - [messageView displayOrEnqueue]; } @@ -170,6 +161,7 @@ - (IBAction)didTapEndless:(id)sender type:TSMessageTypeSuccess]; messageView.duration = TSMessageDurationEndless; + messageView.userDismissEnabled = NO; [messageView displayOrEnqueue]; } @@ -181,8 +173,6 @@ - (IBAction)didTapLong:(id)sender type:TSMessageTypeWarning]; messageView.duration = 10.0; - [messageView setUserDismissEnabled]; - [messageView displayOrEnqueue]; } @@ -195,29 +185,23 @@ - (IBAction)didTapBottom:(id)sender messageView.duration = TSMessageDurationAutomatic; messageView.position = TSMessagePositionBottom; - [messageView setUserDismissEnabled]; - [messageView displayOrEnqueue]; } - (IBAction)didTapText:(id)sender { - TSMessageView *messageView = [TSMessage displayMessageWithTitle:NSLocalizedString(@"With 'Text' I meant a long text, so here it is", nil) - subtitle:NSLocalizedString(@"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus", nil) - type:TSMessageTypeWarning]; - - [messageView setUserDismissEnabled]; + [TSMessage displayMessageWithTitle:NSLocalizedString(@"With 'Text' I meant a long text, so here it is", nil) + subtitle:NSLocalizedString(@"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus", nil) + type:TSMessageTypeWarning]; } - (IBAction)didTapCustomDesign:(id)sender { [TSMessage addCustomDesignFromFileWithName:@"AlternativeDesign.json"]; - TSMessageView *messageView = [TSMessage displayMessageWithTitle:NSLocalizedString(@"Updated to custom design file", nil) - subtitle:NSLocalizedString(@"From now on, all the titles of success messages are larger", nil) - type:TSMessageTypeSuccess]; - - [messageView setUserDismissEnabled]; + [TSMessage displayMessageWithTitle:NSLocalizedString(@"Updated to custom design file", nil) + subtitle:NSLocalizedString(@"From now on, all the titles of success messages are larger", nil) + type:TSMessageTypeSuccess]; } @end diff --git a/README.md b/README.md index bb97b55c..1d8949b6 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ The following properties can be set: * **type**: The message type (Message, Warning, Error, Success) * **duration**: The duration the message should be displayed (optional) * **callback**: The block that should be executed, when the user dismissed the message by swiping it away (optional) +* **userDismissEnabled**: Define whether or not the message can be dismissed by the user by tapping and swipping (on by default) Except the title and the message type, all of the listed values are optional diff --git a/TSMessages/Views/TSMessageView.h b/TSMessages/Views/TSMessageView.h index 5a70b322..b8d4e4e1 100755 --- a/TSMessages/Views/TSMessageView.h +++ b/TSMessages/Views/TSMessageView.h @@ -36,6 +36,9 @@ /** The callback that should be invoked, when the user taps the message */ @property (nonatomic, copy) TSMessageCallback tapCallback; +/** Define whether or not the message can be dismissed by the user by tapping and swipping */ +@property (nonatomic, assign, getter=isUserDismissEnabled) BOOL userDismissEnabled; + - (id)initWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image type:(TSMessageType)type; /** Dismisses this message view */ @@ -44,10 +47,6 @@ /** Adds a button with a callback that gets invoked when the button is tapped */ - (void)setButtonWithTitle:(NSString *)title callback:(TSMessageCallback)callback; -/** Enables dismissing the message by swiping */ -- (void)setUserDismissEnabled; -- (void)setUserDismissEnabledWithCallback:(TSMessageCallback)callback; - /** Displays or enqueues the message view. */ - (void)displayOrEnqueue; diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index c2171555..d300436e 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -21,9 +21,10 @@ @interface TSMessageView () @property (nonatomic) UILabel *contentLabel; @property (nonatomic) UIImageView *iconImageView; @property (nonatomic) UIButton *button; +@property (nonatomic) UITapGestureRecognizer *tapRecognizer; +@property (nonatomic) UISwipeGestureRecognizer *swipeRecognizer; @property (nonatomic) TSBlurView *backgroundBlurView; @property (nonatomic, copy) TSMessageCallback buttonCallback; -@property (nonatomic, copy) TSMessageCallback dismissCallback; @property (nonatomic, assign, getter = isMessageFullyDisplayed) BOOL messageFullyDisplayed; @end @@ -33,6 +34,7 @@ - (id)initWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIIma { if ((self = [self init])) { + self.userDismissEnabled = YES; self.duration = TSMessageDurationAutomatic; self.position = TSMessagePositionTop; @@ -42,7 +44,7 @@ - (id)initWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIIma [self setupSubtitle:subtitle]; [self setupImage:image]; [self setupAutoresizing]; - [self setupTapHandler]; + [self setupGestureRecognizers]; } return self; @@ -139,11 +141,15 @@ - (void)setupImage:(UIImage *)image [self addSubview:self.iconImageView]; } -- (void)setupTapHandler +- (void)setupGestureRecognizers { - UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; - tapGesture.delegate = self; - [self addGestureRecognizer:tapGesture]; + self.tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleViewTap:)]; + self.tapRecognizer.delegate = self; + [self addGestureRecognizer:self.tapRecognizer]; + + self.swipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleViewSwipe:)]; + self.swipeRecognizer.direction = (self.position == TSMessagePositionTop ? UISwipeGestureRecognizerDirectionUp : UISwipeGestureRecognizerDirectionDown); + [self addGestureRecognizer:self.swipeRecognizer]; } #pragma mark - Message view attributes and actions @@ -170,7 +176,7 @@ - (void)setButtonWithTitle:(NSString *)title callback:(TSMessageCallback)callbac [self.button setBackgroundImage:buttonBackgroundImage forState:UIControlStateNormal]; [self.button setTitleShadowColor:buttonTitleShadowColor forState:UIControlStateNormal]; [self.button setTitleColor:buttonTitleTextColor forState:UIControlStateNormal]; - [self.button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside]; + [self.button addTarget:self action:@selector(handleButtonTap:) forControlEvents:UIControlEventTouchUpInside]; [self.button sizeToFit]; self.button.frame = CGRectMake(self.viewController.view.bounds.size.width - TSMessageViewPadding - self.button.frame.size.width, 0, self.button.frame.size.width, 31); @@ -178,22 +184,6 @@ - (void)setButtonWithTitle:(NSString *)title callback:(TSMessageCallback)callbac [self addSubview:self.button]; } -- (void)setUserDismissEnabled -{ - [self setUserDismissEnabledWithCallback:^(TSMessageView *messageView) { - [messageView dismiss]; - }]; -} - -- (void)setUserDismissEnabledWithCallback:(TSMessageCallback)callback -{ - self.dismissCallback = callback; - - UISwipeGestureRecognizer *gestureRec = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss)]; - gestureRec.direction = (self.position == TSMessagePositionTop ? UISwipeGestureRecognizerDirectionUp : UISwipeGestureRecognizerDirectionDown); - [self addGestureRecognizer:gestureRec]; -} - - (void)displayOrEnqueue { [TSMessage displayOrEnqueueMessage:self]; } @@ -330,7 +320,7 @@ - (void)prepareForDisplay #pragma mark - Actions -- (void)buttonTapped:(id) sender +- (void)handleButtonTap:(id) sender { if (self.buttonCallback) { @@ -338,9 +328,14 @@ - (void)buttonTapped:(id) sender } } -- (void)handleTap:(UITapGestureRecognizer *)tapGesture +- (void)handleViewTap:(UITapGestureRecognizer *)tapRecognizer { - if (tapGesture.state != UIGestureRecognizerStateRecognized) return; + if (tapRecognizer.state != UIGestureRecognizerStateRecognized) return; + + if (self.isUserDismissEnabled) + { + [self dismiss]; + } if (self.tapCallback) { @@ -348,6 +343,19 @@ - (void)handleTap:(UITapGestureRecognizer *)tapGesture } } +- (void)handleViewSwipe:(UISwipeGestureRecognizer *)swipeRecognizer +{ + if (swipeRecognizer.state == UIGestureRecognizerStateRecognized && self.isUserDismissEnabled) + { + [self dismiss]; + } +} + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch +{ + return !([touch.view isKindOfClass:[UIControl class]]); +} + - (void)dismiss { if (self == [TSMessage sharedMessage].currentMessage) @@ -360,13 +368,6 @@ - (void)dismiss } } -#pragma mark - UIGestureRecognizerDelegate - -- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch -{ - return !([touch.view isKindOfClass:[UIControl class]]); -} - #pragma mark - Private - (NSString *)title From 898c82b2b2700f5462f2f3d23830173a6b4901dd Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Sun, 23 Feb 2014 13:07:35 +0100 Subject: [PATCH 22/27] Change delegation method to define custom offset --- ExampleProject/Example/TSDemoViewController.h | 12 --- ExampleProject/Example/TSDemoViewController.m | 45 ++++++--- .../en.lproj/MainStoryboard.storyboard | 19 +++- TSMessages/Classes/TSMessage.m | 83 ++--------------- TSMessages/Views/TSMessageView+Private.h | 1 + TSMessages/Views/TSMessageView.h | 2 +- TSMessages/Views/TSMessageView.m | 91 +++++++++++++++++-- 7 files changed, 143 insertions(+), 110 deletions(-) diff --git a/ExampleProject/Example/TSDemoViewController.h b/ExampleProject/Example/TSDemoViewController.h index c5850d4b..ac9828b4 100644 --- a/ExampleProject/Example/TSDemoViewController.h +++ b/ExampleProject/Example/TSDemoViewController.h @@ -10,16 +10,4 @@ #import "TSMessageView.h" @interface TSDemoViewController : UIViewController -- (IBAction)didTapError:(id)sender; -- (IBAction)didTapWarning:(id)sender; -- (IBAction)didTapMessage:(id)sender; -- (IBAction)didTapSuccess:(id)sender; -- (IBAction)didTapButton:(id)sender; -- (IBAction)didTapDismissCurrentMessage:(id)sender; -- (IBAction)didTapEndless:(id)sender; -- (IBAction)didTapLong:(id)sender; -- (IBAction)didTapBottom:(id)sender; -- (IBAction)didTapText:(id)sender; -- (IBAction)didTapCustomDesign:(id)sender; -- (IBAction)didTapPermanent:(id)sender; @end diff --git a/ExampleProject/Example/TSDemoViewController.m b/ExampleProject/Example/TSDemoViewController.m index 4038c926..6a3b7a2a 100644 --- a/ExampleProject/Example/TSDemoViewController.m +++ b/ExampleProject/Example/TSDemoViewController.m @@ -45,13 +45,30 @@ - (BOOL)prefersStatusBarHidden return self.hideStatusbar; } -- (CGFloat)navigationbarBottomOfViewController:(UIViewController *)viewController +- (CGFloat)customMessageOffsetForPosition:(TSMessagePosition)position inViewController:(UIViewController *)viewController { - return 55; + return position == TSMessagePositionTop ? 75 : 25; } #pragma mark Actions +- (IBAction)didTapToggleNavigationBar:(id)sender +{ + [self.navigationController setNavigationBarHidden:!self.navigationController.navigationBarHidden animated:YES]; +} + +- (IBAction)didTapToggleNavigationBarAlpha:(id)sender +{ + CGFloat alpha = self.navigationController.navigationBar.alpha; + + self.navigationController.navigationBar.alpha = (alpha == 1.f) ? 0.5 : 1; +} + +- (IBAction)didTapToggleStatusbar:(id)sender +{ + self.hideStatusbar = !self.hideStatusbar; +} + - (IBAction)didTapError:(id)sender { [TSMessage displayMessageWithTitle:NSLocalizedString(@"Something failed", nil) @@ -86,6 +103,8 @@ - (IBAction)didTapButton:(id)sender subtitle:NSLocalizedString(@"Please update our app. We would be very thankful", nil) type:TSMessageTypeDefault]; + view.delegate = self; + [view setButtonWithTitle:NSLocalizedString(@"Update", nil) callback:^(TSMessageView *messageView) { [messageView dismiss]; @@ -103,6 +122,7 @@ - (IBAction)didTapPermanent:(id)sender subtitle:NSLocalizedString(@"Stays here until it gets dismissed", nil) type:TSMessageTypeDefault]; + view.delegate = self; view.userDismissEnabled = NO; view.position = TSMessagePositionBottom; @@ -119,21 +139,16 @@ - (IBAction)didTapPermanent:(id)sender [view displayPermanently]; } -- (IBAction)didTapToggleNavigationBar:(id)sender +- (IBAction)didTapCustomPosition:(id)sender { - [self.navigationController setNavigationBarHidden:!self.navigationController.navigationBarHidden animated:YES]; -} - -- (IBAction)didTapToggleNavigationBarAlpha:(id)sender -{ - CGFloat alpha = self.navigationController.navigationBar.alpha; + TSMessageView *messageView = [TSMessage messageWithTitle:NSLocalizedString(@"Custom position", nil) + subtitle:NSLocalizedString(@"Define this via a delegation method", nil) + type:TSMessageTypeDefault]; - self.navigationController.navigationBar.alpha = (alpha == 1.f) ? 0.5 : 1; -} - -- (IBAction)didTapToggleStatusbar:(id)sender -{ - self.hideStatusbar = !self.hideStatusbar; + messageView.delegate = self; + messageView.position = TSMessagePositionBottom; + + [messageView displayOrEnqueue]; } - (IBAction)didTapCustomImage:(id)sender diff --git a/ExampleProject/Example/en.lproj/MainStoryboard.storyboard b/ExampleProject/Example/en.lproj/MainStoryboard.storyboard index a75319c1..afac9283 100644 --- a/ExampleProject/Example/en.lproj/MainStoryboard.storyboard +++ b/ExampleProject/Example/en.lproj/MainStoryboard.storyboard @@ -146,6 +146,18 @@ + @@ -193,12 +205,15 @@ + + + @@ -207,7 +222,7 @@ - + @@ -216,7 +231,9 @@ + + diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index c53a2c10..e19aab02 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -193,98 +193,33 @@ - (void)displayMessage:(TSMessageView *)messageView { [messageView prepareForDisplay]; - __block CGFloat verticalOffset = 0.0f; - - void (^addStatusBarHeightToVerticalOffset)() = ^void() { - BOOL isPortrait = UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]); - CGSize statusBarSize = [UIApplication sharedApplication].statusBarFrame.size; - CGFloat offset = isPortrait ? statusBarSize.height : statusBarSize.width; - verticalOffset += offset; - }; - - if ([messageView.viewController isKindOfClass:[UINavigationController class]] || [messageView.viewController.parentViewController isKindOfClass:[UINavigationController class]]) - { - UINavigationController *navigationController; - UIViewController *viewController = messageView.viewController; - - if ([viewController isKindOfClass:[UINavigationController class]]) - { - navigationController = (UINavigationController *)viewController; - } - else - { - navigationController = (UINavigationController *)viewController.parentViewController; - } - - viewController = [[navigationController childViewControllers] firstObject]; - - BOOL isViewIsUnderStatusBar = ![viewController prefersStatusBarHidden]; - - if (!isViewIsUnderStatusBar && navigationController.parentViewController == nil) - { - // strange but true - isViewIsUnderStatusBar = ![navigationController isNavigationBarHidden]; - } - - if (![navigationController isNavigationBarHidden]) - { - [navigationController.view insertSubview:messageView - belowSubview:[navigationController navigationBar]]; - verticalOffset = [navigationController navigationBar].bounds.size.height; - addStatusBarHeightToVerticalOffset(); - } - else - { - [messageView.viewController.view addSubview:messageView]; - - if (isViewIsUnderStatusBar) - { - addStatusBarHeightToVerticalOffset(); - } - } - } - else + // add view + UIViewController *viewController = messageView.viewController; + UINavigationController *navigationController = (UINavigationController *)([viewController isKindOfClass:[UINavigationController class]] ? viewController : viewController.parentViewController); + + if (navigationController.isNavigationBarHidden) { [messageView.viewController.view addSubview:messageView]; - addStatusBarHeightToVerticalOffset(); - } - - CGPoint toPoint; - if (messageView.position == TSMessagePositionTop) - { - CGFloat navigationbarBottomOfViewController = 0; - - if (messageView.delegate && [messageView.delegate respondsToSelector:@selector(navigationbarBottomOfViewController:)]) - { - navigationbarBottomOfViewController = [messageView.delegate navigationbarBottomOfViewController:messageView.viewController]; - } - - toPoint = CGPointMake(messageView.center.x, navigationbarBottomOfViewController + verticalOffset + CGRectGetHeight(messageView.frame) / 2.0); } else { - CGFloat y = messageView.viewController.view.bounds.size.height - CGRectGetHeight(messageView.frame) / 2.0; - - if (!messageView.viewController.navigationController.isToolbarHidden) - { - y -= CGRectGetHeight(messageView.viewController.navigationController.toolbar.bounds); - } - - toPoint = CGPointMake(messageView.center.x, y); + [navigationController.view insertSubview:messageView belowSubview:navigationController.navigationBar]; } + // animate [UIView animateWithDuration:kTSMessageAnimationDuration + 0.1 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0.f options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction animations:^{ - messageView.center = toPoint; + messageView.center = messageView.centerForDisplay; } completion:^(BOOL finished) { messageView.messageFullyDisplayed = YES; }]; + // duration if (messageView.duration == TSMessageDurationAutomatic) { messageView.duration = kTSMessageAnimationDuration + kTSMessageDisplayTime + messageView.frame.size.height * kTSMessageExtraDisplayTimePerPixel; diff --git a/TSMessages/Views/TSMessageView+Private.h b/TSMessages/Views/TSMessageView+Private.h index 8ec40fea..91751664 100644 --- a/TSMessages/Views/TSMessageView+Private.h +++ b/TSMessages/Views/TSMessageView+Private.h @@ -12,6 +12,7 @@ @interface TSMessageView (Private) @property (nonatomic, readonly) NSString *title; @property (nonatomic, readonly) NSString *subtitle; +@property (nonatomic, readonly) CGPoint centerForDisplay; @property (nonatomic, assign, getter = isMessageFullyDisplayed) BOOL messageFullyDisplayed; - (void)prepareForDisplay; diff --git a/TSMessages/Views/TSMessageView.h b/TSMessages/Views/TSMessageView.h index b8d4e4e1..4caff087 100755 --- a/TSMessages/Views/TSMessageView.h +++ b/TSMessages/Views/TSMessageView.h @@ -14,7 +14,7 @@ @protocol TSMessageViewProtocol @optional /** Implement this method to pass a custom value for positioning the message view */ -- (CGFloat)navigationbarBottomOfViewController:(UIViewController *)viewController; +- (CGFloat)customMessageOffsetForPosition:(TSMessagePosition)position inViewController:(UIViewController *)viewController; @end @interface TSMessageView : UIView diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index d300436e..e484354f 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -281,23 +281,21 @@ - (void)layoutSubviews UINavigationController *navigationController = self.viewController.navigationController; - if (!navigationController && [self.viewController isKindOfClass:[UINavigationController class]]) { + if (!navigationController && [self.viewController isKindOfClass:[UINavigationController class]]) + { navigationController = (UINavigationController *)self.viewController; } BOOL isNavBarIsHidden = !navigationController || self.viewController.navigationController.navigationBarHidden; BOOL isNavBarIsOpaque = !self.viewController.navigationController.navigationBar.isTranslucent && self.viewController.navigationController.navigationBar.alpha == 1; - if (isNavBarIsHidden || isNavBarIsOpaque) { + if (isNavBarIsHidden || isNavBarIsOpaque) + { topOffset = -30.f; } backgroundFrame = UIEdgeInsetsInsetRect(backgroundFrame, UIEdgeInsetsMake(topOffset, 0.f, topOffset, 0.f)); } - else if (self.position == TSMessagePositionBottom) - { - backgroundFrame = UIEdgeInsetsInsetRect(backgroundFrame, UIEdgeInsetsMake(0.f, 0.f, -30.f, 0.f)); - } self.backgroundBlurView.frame = backgroundFrame; } @@ -315,7 +313,86 @@ - (void)prepareForDisplay topPosition = self.viewController.view.bounds.size.height; } - self.frame = CGRectMake(0.0, topPosition, self.viewController.view.bounds.size.width, actualHeight); + self.frame = CGRectMake(0, topPosition, self.viewController.view.bounds.size.width, actualHeight); +} + +- (CGPoint)centerForDisplay +{ + CGFloat y; + CGFloat heightOffset = CGRectGetHeight(self.frame) / 2; + + if ([self.delegate respondsToSelector:@selector(customMessageOffsetForPosition:inViewController:)]) + { + CGFloat offset = [self.delegate customMessageOffsetForPosition:self.position inViewController:self.viewController]; + + if (self.position == TSMessagePositionTop) + { + y = offset + heightOffset; + } + else + { + y = self.viewController.view.bounds.size.height - (offset + heightOffset); + } + } + else + { + __block CGFloat offset = 0; + + void (^addStatusBarHeightToVerticalOffset)() = ^void() { + BOOL isPortrait = UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]); + CGSize statusBarSize = [UIApplication sharedApplication].statusBarFrame.size; + + offset += isPortrait ? statusBarSize.height : statusBarSize.width; + }; + + if ([self.viewController isKindOfClass:[UINavigationController class]] || [self.viewController.parentViewController isKindOfClass:[UINavigationController class]]) + { + UIViewController *viewController = self.viewController; + UINavigationController *navigationController = (UINavigationController *)([viewController isKindOfClass:[UINavigationController class]] ? viewController : viewController.parentViewController); + + viewController = [[navigationController childViewControllers] firstObject]; + + BOOL isViewIsUnderStatusBar = !viewController.prefersStatusBarHidden; + + if (!isViewIsUnderStatusBar && navigationController.parentViewController == nil) + { + // strange but true + isViewIsUnderStatusBar = !navigationController.isNavigationBarHidden; + } + + if (!navigationController.isNavigationBarHidden) + { + offset = [navigationController navigationBar].bounds.size.height; + addStatusBarHeightToVerticalOffset(); + } + else if (isViewIsUnderStatusBar) + { + addStatusBarHeightToVerticalOffset(); + } + } + else + { + addStatusBarHeightToVerticalOffset(); + } + + if (self.position == TSMessagePositionTop) + { + y = offset + heightOffset; + } + else + { + y = self.viewController.view.bounds.size.height - heightOffset; + + if (!self.viewController.navigationController.isToolbarHidden) + { + y -= CGRectGetHeight(self.viewController.navigationController.toolbar.bounds); + } + } + } + + CGPoint center = CGPointMake(self.center.x, y); + + return center; } #pragma mark - Actions From 4220b1e22a9182971a8fabb07fda31b0c153d81c Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Sun, 23 Feb 2014 22:08:05 +0100 Subject: [PATCH 23/27] Reimplement forcing message dismissal as in #113 Thanks for the contribution @azrle. I had to reimplement the functionality because of the extensive changes we made meanwhile when working on 1.0 --- TSMessages/Classes/TSMessage+Private.h | 1 - TSMessages/Classes/TSMessage.h | 11 ++++++++++- TSMessages/Classes/TSMessage.m | 16 +++++++++++----- TSMessages/Views/TSMessageView+Private.h | 2 +- TSMessages/Views/TSMessageView.h | 6 +++--- TSMessages/Views/TSMessageView.m | 2 +- 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/TSMessages/Classes/TSMessage+Private.h b/TSMessages/Classes/TSMessage+Private.h index acb5130d..d18f5319 100644 --- a/TSMessages/Classes/TSMessage+Private.h +++ b/TSMessages/Classes/TSMessage+Private.h @@ -12,7 +12,6 @@ @interface TSMessage (Private) + (NSMutableDictionary *)design; -- (void)dismissCurrentMessage; - (void)dismissMessage:(TSMessageView *)messageView; - (void)dismissMessage:(TSMessageView *)messageView completion:(void (^)())completion; - (TSMessageView *)currentMessage; diff --git a/TSMessages/Classes/TSMessage.h b/TSMessages/Classes/TSMessage.h index af8961b4..e2b781a1 100755 --- a/TSMessages/Classes/TSMessage.h +++ b/TSMessages/Classes/TSMessage.h @@ -99,13 +99,22 @@ typedef void (^TSMessageCallback)(TSMessageView *messageView); + (void)addCustomDesignFromFileWithName:(NSString *)fileName; /** Dismisses the current message. If another message is in the queue, - it will be displayed automatically. + it will be displayed automatically after the current one is dismissed. @return YES if the current message was successfully dismissed. NO if there is no current message to be dismissed. */ + (BOOL)dismissCurrentMessage; +/** Dismisses the current message even if it is not fully displayed, yet. + If another message is in the queue, it will be displayed automatically + after the current one is dismissed. + + @return YES if the current message was successfully dismissed. + NO if there is no current message to be dismissed. + */ ++ (BOOL)dismissCurrentMessageForce:(BOOL)force; + /** Indicates whether a message is currently being displayed. @return YES if a message is currently being displayed. diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index e19aab02..99e81634 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -108,17 +108,23 @@ + (void)displayOrEnqueueMessage:(TSMessageView *)messageView } } -+ (BOOL)dismissCurrentMessage ++ (BOOL)dismissCurrentMessageForce:(BOOL)force { - if (![TSMessage sharedMessage].currentMessage) return NO; + TSMessageView *currentMessage = [TSMessage sharedMessage].currentMessage; - dispatch_async(dispatch_get_main_queue(), ^{ - [[TSMessage sharedMessage] dismissCurrentMessage]; - }); + if (!currentMessage) return NO; + if (!currentMessage.isMessageFullyDisplayed && !force) return NO; + + [[TSMessage sharedMessage] dismissCurrentMessage]; return YES; } ++ (BOOL)dismissCurrentMessage +{ + return [self dismissCurrentMessageForce:NO]; +} + + (BOOL)isDisplayingMessage { return !![TSMessage sharedMessage].currentMessage; diff --git a/TSMessages/Views/TSMessageView+Private.h b/TSMessages/Views/TSMessageView+Private.h index 91751664..d92fa672 100644 --- a/TSMessages/Views/TSMessageView+Private.h +++ b/TSMessages/Views/TSMessageView+Private.h @@ -13,7 +13,7 @@ @property (nonatomic, readonly) NSString *title; @property (nonatomic, readonly) NSString *subtitle; @property (nonatomic, readonly) CGPoint centerForDisplay; -@property (nonatomic, assign, getter = isMessageFullyDisplayed) BOOL messageFullyDisplayed; +@property (nonatomic, assign, getter=isMessageFullyDisplayed) BOOL messageFullyDisplayed; - (void)prepareForDisplay; @end diff --git a/TSMessages/Views/TSMessageView.h b/TSMessages/Views/TSMessageView.h index 4caff087..fe37bf68 100755 --- a/TSMessages/Views/TSMessageView.h +++ b/TSMessages/Views/TSMessageView.h @@ -21,9 +21,6 @@ /** The view controller this message is displayed in */ @property (nonatomic, weak) UIViewController *viewController; -/** Is the message currenlty fully displayed? Is set as soon as the message is really fully visible */ -@property (nonatomic, readonly) BOOL isMessageFullyDisplayed; - /** The duration of the displayed message. If it is 0.0, it will automatically be calculated */ @property (nonatomic, assign) CGFloat duration; @@ -52,4 +49,7 @@ /** Displays the message permanently. */ - (void)displayPermanently; + +/** Is the message currently fully displayed? Is set as soon as the message is really fully visible */ +- (BOOL)isMessageFullyDisplayed; @end diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index e484354f..a1442fc6 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -25,7 +25,7 @@ @interface TSMessageView () @property (nonatomic) UISwipeGestureRecognizer *swipeRecognizer; @property (nonatomic) TSBlurView *backgroundBlurView; @property (nonatomic, copy) TSMessageCallback buttonCallback; -@property (nonatomic, assign, getter = isMessageFullyDisplayed) BOOL messageFullyDisplayed; +@property (nonatomic, getter=isMessageFullyDisplayed) BOOL messageFullyDisplayed; @end @implementation TSMessageView From a04e55a8897d5fa1243af38025bb77f1c91b88cb Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Sat, 1 Mar 2014 14:56:02 +0100 Subject: [PATCH 24/27] Fix case where there is no navigation controller --- TSMessages/Classes/TSMessage.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TSMessages/Classes/TSMessage.m b/TSMessages/Classes/TSMessage.m index 99e81634..dab05642 100755 --- a/TSMessages/Classes/TSMessage.m +++ b/TSMessages/Classes/TSMessage.m @@ -203,7 +203,7 @@ - (void)displayMessage:(TSMessageView *)messageView UIViewController *viewController = messageView.viewController; UINavigationController *navigationController = (UINavigationController *)([viewController isKindOfClass:[UINavigationController class]] ? viewController : viewController.parentViewController); - if (navigationController.isNavigationBarHidden) + if (!navigationController || navigationController.isNavigationBarHidden) { [messageView.viewController.view addSubview:messageView]; } From 366b308c010266bc96f756b689cf4abce23f5f61 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Tue, 4 Mar 2014 20:15:35 +0100 Subject: [PATCH 25/27] Improve check for hidden navigationbar Thanks @mRs- for the implementation in #119 :beers: --- TSMessages/Views/TSMessageView.m | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index a1442fc6..f8b400ce 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -357,10 +357,10 @@ - (CGPoint)centerForDisplay if (!isViewIsUnderStatusBar && navigationController.parentViewController == nil) { // strange but true - isViewIsUnderStatusBar = !navigationController.isNavigationBarHidden; + isViewIsUnderStatusBar = ![self isNavigationBarInNavigationControllerHidden:navigationController]; } - if (!navigationController.isNavigationBarHidden) + if (![self isNavigationBarInNavigationControllerHidden:navigationController]) { offset = [navigationController navigationBar].bounds.size.height; addStatusBarHeightToVerticalOffset(); @@ -457,4 +457,17 @@ - (NSString *)subtitle return self.contentLabel.text; } +/** Indicates whether the current navigationBar is hidden by isNavigationBarHidden on the + UINavigationController or isHidden on the navigationBar of the UINavigationController */ +- (BOOL)isNavigationBarInNavigationControllerHidden:(UINavigationController *)navController +{ + if (navController.isNavigationBarHidden) { + return YES; + } else if (navController.navigationBar.isHidden) { + return YES; + } else { + return NO; + } +} + @end From 6784cc6fc82ecd2ba26a24d07e9d0b81b007a862 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Mon, 10 Mar 2014 22:02:22 +0100 Subject: [PATCH 26/27] Also set swipe direction when setting position --- TSMessages/Views/TSMessageView.m | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index f8b400ce..eec7b1fe 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -445,6 +445,12 @@ - (void)dismiss } } +- (void)setPosition:(TSMessagePosition)position { + _position = position; + + self.swipeRecognizer.direction = (self.position == TSMessagePositionTop ? UISwipeGestureRecognizerDirectionUp : UISwipeGestureRecognizerDirectionDown); +} + #pragma mark - Private - (NSString *)title From 592e7d521108272b75d84582edec51957aaf410c Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Fri, 9 May 2014 12:59:54 +0200 Subject: [PATCH 27/27] Add swipe callback --- TSMessages/Views/TSMessageView.h | 3 +++ TSMessages/Views/TSMessageView.m | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/TSMessages/Views/TSMessageView.h b/TSMessages/Views/TSMessageView.h index fe37bf68..334f6840 100755 --- a/TSMessages/Views/TSMessageView.h +++ b/TSMessages/Views/TSMessageView.h @@ -33,6 +33,9 @@ /** The callback that should be invoked, when the user taps the message */ @property (nonatomic, copy) TSMessageCallback tapCallback; +/** The callback that should be invoked, when the user swipes the message */ +@property (nonatomic, copy) TSMessageCallback swipeCallback; + /** Define whether or not the message can be dismissed by the user by tapping and swipping */ @property (nonatomic, assign, getter=isUserDismissEnabled) BOOL userDismissEnabled; diff --git a/TSMessages/Views/TSMessageView.m b/TSMessages/Views/TSMessageView.m index eec7b1fe..194ab33c 100755 --- a/TSMessages/Views/TSMessageView.m +++ b/TSMessages/Views/TSMessageView.m @@ -422,10 +422,17 @@ - (void)handleViewTap:(UITapGestureRecognizer *)tapRecognizer - (void)handleViewSwipe:(UISwipeGestureRecognizer *)swipeRecognizer { - if (swipeRecognizer.state == UIGestureRecognizerStateRecognized && self.isUserDismissEnabled) + if (swipeRecognizer.state != UIGestureRecognizerStateRecognized) return; + + if (self.isUserDismissEnabled) { [self dismiss]; } + + if (self.swipeCallback) + { + self.swipeCallback(self); + } } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch