From 21ef693113e32d4f7f95076053f099d8ffa12d7d Mon Sep 17 00:00:00 2001 From: Aviel Gross Date: Tue, 29 Apr 2014 14:38:59 +0300 Subject: [PATCH] Initial commit --- AGPushNote/AGPushNoteView.h | 26 +++ AGPushNote/AGPushNoteView.m | 209 ++++++++++++++++++ AGPushNote/AGPushNoteView.xib | 46 ++++ .../WorkspaceSettings.xcsettings | 10 + LICENSE | 21 ++ README.md | 4 + 6 files changed, 316 insertions(+) create mode 100644 AGPushNote/AGPushNoteView.h create mode 100644 AGPushNote/AGPushNoteView.m create mode 100644 AGPushNote/AGPushNoteView.xib create mode 100644 AGPushNote_Example.xcodeproj/project.xcworkspace/xcuserdata/yiftachcohen.xcuserdatad/WorkspaceSettings.xcsettings create mode 100755 LICENSE create mode 100755 README.md diff --git a/AGPushNote/AGPushNoteView.h b/AGPushNote/AGPushNoteView.h new file mode 100644 index 0000000..372c0e4 --- /dev/null +++ b/AGPushNote/AGPushNoteView.h @@ -0,0 +1,26 @@ +// +// IAAPushNoteView.h +// TLV Airport +// +// Created by Aviel Gross on 1/29/14. +// Copyright (c) 2014 NGSoft. All rights reserved. +// + +#import +@protocol AGPushNoteViewDelegate +@optional +- (void)pushNoteDidAppear; // Called after the view has been fully transitioned onto the screen. (equel to completion block). +- (void)pushNoteWillDisappear; // Called before the view is hidden, after the message action block. + +@end +@interface AGPushNoteView : UIToolbar ++ (void)showWithNotificationMessage:(NSString *)message; ++ (void)showWithNotificationMessage:(NSString *)message completion:(void (^)(void))completion; ++ (void)close; ++ (void)closeWitCompletion:(void (^)(void))completion; ++ (void)awake; + ++ (void)setMessageAction:(void (^)(NSString *message))action; + +@property (nonatomic, weak) id pushNoteDelegate; +@end diff --git a/AGPushNote/AGPushNoteView.m b/AGPushNote/AGPushNoteView.m new file mode 100644 index 0000000..67c4f87 --- /dev/null +++ b/AGPushNote/AGPushNoteView.m @@ -0,0 +1,209 @@ +// +// IAAPushNoteView.m +// TLV Airport +// +// Created by Aviel Gross on 1/29/14. +// Copyright (c) 2014 NGSoft. All rights reserved. +// + +#import "AGPushNoteView.h" + +#define APP [UIApplication sharedApplication].delegate +#define isIOS7 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) +#define PUSH_VIEW [AGPushNoteView sharedPushView] + +#define CLOSE_PUSH_SEC 5 +#define SHOW_ANIM_DUR 0.5 +#define HIDE_ANIM_DUR 0.35 + +@interface AGPushNoteView() +@property (weak, nonatomic) IBOutlet UILabel *messageLabel; +@property (weak, nonatomic) IBOutlet UIView *containerView; + +@property (strong, nonatomic) NSTimer *closeTimer; +@property (strong, nonatomic) NSString *currentMessage; +@property (strong, nonatomic) NSMutableArray *pendingPushArr; + +@property (strong, nonatomic) void (^messageTapActionBlock)(NSString *message); +@end + + +@implementation AGPushNoteView + +//Singleton instance +static AGPushNoteView *_sharedPushView; + ++ (instancetype)sharedPushView +{ + @synchronized([self class]) + { + if (!_sharedPushView){ + NSArray *nibArr = [[NSBundle mainBundle] loadNibNamed: @"AGPushNoteView" owner:self options:nil]; + for (id currentObject in nibArr) + { + if ([currentObject isKindOfClass:[AGPushNoteView class]]) + { + _sharedPushView = (AGPushNoteView *)currentObject; + break; + } + } + [_sharedPushView setUpUI]; + } + return _sharedPushView; + } + // to avoid compiler warning + return nil; +} + +#pragma mark - Lifecycle (of sort) +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + // Initialization code + CGRect f = self.frame; + CGFloat width = [UIApplication sharedApplication].keyWindow.bounds.size.width; + self.frame = CGRectMake(f.origin.x, f.origin.y, width, f.size.height); + } + return self; +} + +- (void)setUpUI { + CGRect f = self.frame; + CGFloat width = [UIApplication sharedApplication].keyWindow.bounds.size.width; + CGFloat height = isIOS7? 54: f.size.height; + self.frame = CGRectMake(f.origin.x, -height, width, height); + + CGRect cvF = self.containerView.frame; + self.containerView.frame = CGRectMake(cvF.origin.x, cvF.origin.y, self.frame.size.width, cvF.size.height); + + //OS Specific: + if (isIOS7) { + self.barTintColor = nil; + self.translucent = YES; + self.barStyle = UIBarStyleBlack; + } else { + [self setTintColor:[UIColor colorWithRed:5 green:31 blue:75 alpha:1]]; + [self.messageLabel setTextAlignment:NSTextAlignmentCenter]; + self.messageLabel.shadowColor = [UIColor blackColor]; + } + + self.layer.zPosition = MAXFLOAT; + self.backgroundColor = [UIColor clearColor]; + self.multipleTouchEnabled = NO; + self.exclusiveTouch = YES; + + UITapGestureRecognizer *msgTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(messageTapAction)]; + self.messageLabel.userInteractionEnabled = YES; + [self.messageLabel addGestureRecognizer:msgTap]; + + //:::[For debugging]::: + // self.containerView.backgroundColor = [UIColor yellowColor]; + // self.closeButton.backgroundColor = [UIColor redColor]; + // self.messageLabel.backgroundColor = [UIColor greenColor]; + + [APP.window addSubview:PUSH_VIEW]; +} + ++ (void)awake { + if (PUSH_VIEW.frame.origin.y == 0) { + [APP.window addSubview:PUSH_VIEW]; + } +} + ++ (void)showWithNotificationMessage:(NSString *)message { + [AGPushNoteView showWithNotificationMessage:message completion:^{ + //Nothing. + }]; +} + ++ (void)showWithNotificationMessage:(NSString *)message completion:(void (^)(void))completion { + + PUSH_VIEW.currentMessage = message; + + if (message) { + [PUSH_VIEW.pendingPushArr addObject:message]; + + PUSH_VIEW.messageLabel.text = message; + APP.window.windowLevel = UIWindowLevelStatusBar; + + CGRect f = PUSH_VIEW.frame; + PUSH_VIEW.frame = CGRectMake(f.origin.x, -f.size.height, f.size.width, f.size.height); + [APP.window addSubview:PUSH_VIEW]; + + //Show + [UIView animateWithDuration:SHOW_ANIM_DUR delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ + CGRect f = PUSH_VIEW.frame; + PUSH_VIEW.frame = CGRectMake(f.origin.x, 0, f.size.width, f.size.height); + } completion:^(BOOL finished) { + completion(); + if ([PUSH_VIEW.pushNoteDelegate respondsToSelector:@selector(pushNoteDidAppear)]) { + [PUSH_VIEW.pushNoteDelegate pushNoteDidAppear]; + } + }]; + + //Start timer (Currently not used to make sure user see & read the push...) +// PUSH_VIEW.closeTimer = [NSTimer scheduledTimerWithTimeInterval:CLOSE_PUSH_SEC target:[IAAPushNoteView class] selector:@selector(close) userInfo:nil repeats:NO]; + } +} ++ (void)closeWitCompletion:(void (^)(void))completion { + if ([PUSH_VIEW.pushNoteDelegate respondsToSelector:@selector(pushNoteWillDisappear)]) { + [PUSH_VIEW.pushNoteDelegate pushNoteWillDisappear]; + } + + [PUSH_VIEW.closeTimer invalidate]; + + [UIView animateWithDuration:HIDE_ANIM_DUR delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ + CGRect f = PUSH_VIEW.frame; + PUSH_VIEW.frame = CGRectMake(f.origin.x, -f.size.height, f.size.width, f.size.height); + } completion:^(BOOL finished) { + [PUSH_VIEW handlePendingPushJumpWitCompletion:completion]; + }]; +} + ++ (void)close { + [AGPushNoteView closeWitCompletion:^{ + //Nothing. + }]; +} + +#pragma mark - Pending push managment +- (void)handlePendingPushJumpWitCompletion:(void (^)(void))completion { + id lastObj = [self.pendingPushArr lastObject]; //Get myself + if (lastObj) { + [self.pendingPushArr removeObject:lastObj]; //Remove me from arr + NSString *messagePendingPush = [self.pendingPushArr lastObject]; //Maybe get pending push + if (messagePendingPush) { //If got something - remove from arr, - than show it. + [self.pendingPushArr removeObject:messagePendingPush]; + [AGPushNoteView showWithNotificationMessage:messagePendingPush completion:completion]; + } else { + APP.window.windowLevel = UIWindowLevelNormal; + } + } +} + +- (NSMutableArray *)pendingPushArr { + if (!_pendingPushArr) { + _pendingPushArr = [[NSMutableArray alloc] init]; + } + return _pendingPushArr; +} + +#pragma mark - Actions ++ (void)setMessageAction:(void (^)(NSString *message))action { + PUSH_VIEW.messageTapActionBlock = action; +} + +- (void)messageTapAction { + if (self.messageTapActionBlock) { + self.messageTapActionBlock(self.currentMessage); + [AGPushNoteView close]; + } +} + +- (IBAction)closeActionItem:(UIBarButtonItem *)sender { + [AGPushNoteView close]; +} + + +@end diff --git a/AGPushNote/AGPushNoteView.xib b/AGPushNote/AGPushNoteView.xib new file mode 100644 index 0000000..b8c4409 --- /dev/null +++ b/AGPushNote/AGPushNoteView.xib @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AGPushNote_Example.xcodeproj/project.xcworkspace/xcuserdata/yiftachcohen.xcuserdatad/WorkspaceSettings.xcsettings b/AGPushNote_Example.xcodeproj/project.xcworkspace/xcuserdata/yiftachcohen.xcuserdatad/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..659c876 --- /dev/null +++ b/AGPushNote_Example.xcodeproj/project.xcworkspace/xcuserdata/yiftachcohen.xcuserdatad/WorkspaceSettings.xcsettings @@ -0,0 +1,10 @@ + + + + + HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges + + SnapshotAutomaticallyBeforeSignificantChanges + + + diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..65bdfd9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 avielg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100755 index 0000000..695343c --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +AGPushNote +========== + +Custom view for easily displaying in-app push notification that feels like default iOS banners.