Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Aviel Gross authored and Aviel Gross committed Apr 29, 2014
1 parent da96143 commit 881e45c
Show file tree
Hide file tree
Showing 8 changed files with 354 additions and 9 deletions.
26 changes: 23 additions & 3 deletions AGPushNote_Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
299C5686190F867300C8AECF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 299C5668190F867300C8AECF /* UIKit.framework */; };
299C568E190F867300C8AECF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 299C568C190F867300C8AECF /* InfoPlist.strings */; };
299C5690190F867300C8AECF /* AGPushNote_ExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 299C568F190F867300C8AECF /* AGPushNote_ExampleTests.m */; };
299C569D190F872600C8AECF /* AGPushNoteView.m in Sources */ = {isa = PBXBuildFile; fileRef = 299C569B190F872600C8AECF /* AGPushNoteView.m */; };
299C569E190F872600C8AECF /* AGPushNoteView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 299C569C190F872600C8AECF /* AGPushNoteView.xib */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -53,6 +55,9 @@
299C568B190F867300C8AECF /* AGPushNote_ExampleTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AGPushNote_ExampleTests-Info.plist"; sourceTree = "<group>"; };
299C568D190F867300C8AECF /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
299C568F190F867300C8AECF /* AGPushNote_ExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AGPushNote_ExampleTests.m; sourceTree = "<group>"; };
299C569A190F872600C8AECF /* AGPushNoteView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AGPushNoteView.h; sourceTree = "<group>"; };
299C569B190F872600C8AECF /* AGPushNoteView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AGPushNoteView.m; sourceTree = "<group>"; };
299C569C190F872600C8AECF /* AGPushNoteView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AGPushNoteView.xib; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -112,12 +117,10 @@
299C566A190F867300C8AECF /* AGPushNote_Example */ = {
isa = PBXGroup;
children = (
299C5673190F867300C8AECF /* AGAppDelegate.h */,
299C5674190F867300C8AECF /* AGAppDelegate.m */,
299C5699190F870700C8AECF /* PushNote View */,
299C5676190F867300C8AECF /* Main.storyboard */,
299C5679190F867300C8AECF /* AGViewController.h */,
299C567A190F867300C8AECF /* AGViewController.m */,
299C567C190F867300C8AECF /* Images.xcassets */,
299C566B190F867300C8AECF /* Supporting Files */,
);
path = AGPushNote_Example;
Expand All @@ -126,6 +129,9 @@
299C566B190F867300C8AECF /* Supporting Files */ = {
isa = PBXGroup;
children = (
299C5673190F867300C8AECF /* AGAppDelegate.h */,
299C5674190F867300C8AECF /* AGAppDelegate.m */,
299C567C190F867300C8AECF /* Images.xcassets */,
299C566C190F867300C8AECF /* AGPushNote_Example-Info.plist */,
299C566D190F867300C8AECF /* InfoPlist.strings */,
299C5670190F867300C8AECF /* main.m */,
Expand All @@ -152,6 +158,16 @@
name = "Supporting Files";
sourceTree = "<group>";
};
299C5699190F870700C8AECF /* PushNote View */ = {
isa = PBXGroup;
children = (
299C569A190F872600C8AECF /* AGPushNoteView.h */,
299C569B190F872600C8AECF /* AGPushNoteView.m */,
299C569C190F872600C8AECF /* AGPushNoteView.xib */,
);
name = "PushNote View";
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -229,6 +245,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
299C569E190F872600C8AECF /* AGPushNoteView.xib in Resources */,
299C567D190F867300C8AECF /* Images.xcassets in Resources */,
299C566F190F867300C8AECF /* InfoPlist.strings in Resources */,
299C5678190F867300C8AECF /* Main.storyboard in Resources */,
Expand All @@ -250,6 +267,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
299C569D190F872600C8AECF /* AGPushNoteView.m in Sources */,
299C5675190F867300C8AECF /* AGAppDelegate.m in Sources */,
299C567B190F867300C8AECF /* AGViewController.m in Sources */,
299C5671190F867300C8AECF /* main.m in Sources */,
Expand Down Expand Up @@ -380,6 +398,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "AGPushNote_Example/AGPushNote_Example-Prefix.pch";
INFOPLIST_FILE = "AGPushNote_Example/AGPushNote_Example-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
Expand All @@ -393,6 +412,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "AGPushNote_Example/AGPushNote_Example-Prefix.pch";
INFOPLIST_FILE = "AGPushNote_Example/AGPushNote_Example-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
Expand Down
26 changes: 26 additions & 0 deletions AGPushNote_Example/AGPushNoteView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// IAAPushNoteView.h
// TLV Airport
//
// Created by Aviel Gross on 1/29/14.
// Copyright (c) 2014 NGSoft. All rights reserved.
//

#import <UIKit/UIKit.h>
@protocol AGPushNoteViewDelegate <NSObject>
@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<AGPushNoteViewDelegate> pushNoteDelegate;
@end
209 changes: 209 additions & 0 deletions AGPushNote_Example/AGPushNoteView.m
Original file line number Diff line number Diff line change
@@ -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
46 changes: 46 additions & 0 deletions AGPushNote_Example/AGPushNoteView.xib
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="5056" systemVersion="13C1021" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment defaultVersion="1536" identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3733"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" barStyle="black" id="dXp-SS-CuN" customClass="AGPushNoteView">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<items>
<barButtonItem style="done" systemItem="stop" id="pRY-8K-Lxt">
<connections>
<action selector="closeActionItem:" destination="dXp-SS-CuN" id="ToV-av-Emk"/>
</connections>
</barButtonItem>
<barButtonItem style="plain" id="hSw-lx-Uca">
<view key="customView" alpha="0.5" contentMode="scaleToFill" id="E4g-eI-zJ9">
<rect key="frame" x="40" y="0.0" width="270" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="message" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="270" translatesAutoresizingMaskIntoConstraints="NO" id="SuY-fE-zer">
<rect key="frame" x="0.0" y="0.0" width="270" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</barButtonItem>
</items>
<color key="barTintColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<connections>
<outlet property="containerView" destination="E4g-eI-zJ9" id="UYa-0B-O43"/>
<outlet property="messageLabel" destination="SuY-fE-zer" id="R8k-sE-qWe"/>
</connections>
</toolbar>
</objects>
</document>
Loading

0 comments on commit 881e45c

Please sign in to comment.