1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-03 09:57:46 +01:00
Telegram/Telegraph/TGNotificationWindow.m
2016-02-25 01:03:51 +01:00

298 lines
7.6 KiB
Objective-C

#import "TGNotificationWindow.h"
#import "TGViewController.h"
#import "ActionStage.h"
#import "TGObserverProxy.h"
#import "TGAppDelegate.h"
#import <QuartzCore/QuartzCore.h>
@interface TGNotificationWindowView : UIView
{
bool _isSwipeDismissing;
}
@property (nonatomic, weak) UIWindow *weakWindow;
@property (nonatomic) bool isDismissed;
@property (nonatomic, strong) UIView *containerView;
@property (nonatomic, strong) UIView *contentView;
@end
@implementation TGNotificationWindowView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self != nil)
{
_containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, 20 + 44)];
_containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
_containerView.opaque = false;
[self addSubview:_containerView];
_containerView.exclusiveTouch = true;
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureRecognized:)];
[_containerView addGestureRecognizer:panRecognizer];
}
return self;
}
- (void)setContentView:(UIView *)view
{
[_contentView removeFromSuperview];
_contentView = view;
view.frame = _containerView.bounds;
[_containerView addSubview:view];
}
- (void)animateIn
{
_isDismissed = false;
UIWindow *window = _weakWindow;
CGRect frame = _containerView.frame;
frame.origin.x = 0;
_containerView.frame = frame;
frame.origin = CGPointZero;
if (window.hidden || !CGRectEqualToRect(_containerView.frame, frame))
{
window.hidden = false;
CGRect startFrame = frame;
startFrame.origin.y = -frame.size.height;
_containerView.frame = startFrame;
[UIView animateWithDuration:0.3 animations:^
{
_containerView.frame = frame;
}];
}
}
- (void)animateOut
{
_isDismissed = true;
UIWindow *window = _weakWindow;
if (window.hidden)
return;
CGRect frame = _containerView.frame;
frame.origin.y = -frame.size.height;
[UIView animateWithDuration:0.3 animations:^
{
_containerView.frame = frame;
} completion:^(__unused BOOL finished)
{
window.hidden = true;
}];
}
- (void)panGestureRecognized:(UIPanGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateChanged)
{
if (!_isDismissed)
{
CGRect frame = _containerView.frame;
frame.origin.x = [recognizer translationInView:self].x;
_containerView.frame = frame;
}
}
else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled)
{
CGFloat velocity = [recognizer velocityInView:self].x;
//TGLog(@"Velocity: %f", velocity);
if (ABS(velocity) < 120.0f)
{
CGRect frame = _containerView.frame;
frame.origin.x = 0;
[UIView animateWithDuration:0.3 animations:^
{
_containerView.frame = frame;
}];
}
else
{
if (ABS(velocity) < 300)
velocity = velocity < 0 ? -300 : 300;
CGRect frame = _containerView.frame;
if (velocity < 0)
frame.origin.x = -frame.size.width;
else
frame.origin.x = frame.size.width;
NSTimeInterval duration = ABS(frame.origin.x - _containerView.frame.origin.x) / ABS(velocity);
_isSwipeDismissing = true;
[UIView animateWithDuration:duration animations:^
{
_containerView.frame = frame;
} completion:^(BOOL finished)
{
if (finished)
{
_isSwipeDismissing = false;
UIWindow *window = _weakWindow;
window.hidden = true;
}
}];
}
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!_isSwipeDismissing)
{
CGRect frame = _containerView.frame;
frame.origin.x = 0;
[UIView animateWithDuration:0.3 animations:^
{
_containerView.frame = frame;
}];
}
[super touchesEnded:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!_isSwipeDismissing)
{
CGRect frame = _containerView.frame;
frame.origin.x = 0;
[UIView animateWithDuration:0.3 animations:^
{
_containerView.frame = frame;
}];
}
[super touchesCancelled:touches withEvent:event];
}
@end
@interface TGNotificationWindowController : TGOverlayWindowViewController
@property (nonatomic, strong) TGNotificationWindowView *notificationView;
@property (nonatomic, weak) UIWindow *weakWindow;
@end
@implementation TGNotificationWindowController
- (void)loadView
{
[super loadView];
_notificationView = [[TGNotificationWindowView alloc] initWithFrame:self.view.bounds];
_notificationView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_notificationView.weakWindow = _weakWindow;
[self.view addSubview:_notificationView];
}
- (TGNotificationWindowView *)notificationView
{
if (![self isViewLoaded])
[self loadView];
return _notificationView;
}
@end
@interface TGNotificationWindow ()
@end
@implementation TGNotificationWindow
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
TGNotificationWindowController *controller = [[TGNotificationWindowController alloc] init];
controller.weakWindow = self;
self.rootViewController = controller;
}
return self;
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
CGPoint localPoint = [((TGNotificationWindowController *)self.rootViewController).notificationView convertPoint:point fromView:self];
UIView *result = [((TGNotificationWindowController *)self.rootViewController).notificationView hitTest:localPoint withEvent:event];
if (result == ((TGNotificationWindowController *)self.rootViewController).notificationView || result == self.rootViewController.view)
return nil;
return result;
}
- (void)setContentView:(UIView *)view
{
[((TGNotificationWindowController *)self.rootViewController).notificationView setContentView:view];
}
- (UIView *)contentView
{
return [((TGNotificationWindowController *)self.rootViewController).notificationView contentView];
}
- (void)animateIn
{
[((TGNotificationWindowController *)self.rootViewController).notificationView animateIn];
}
- (void)animateOut
{
[((TGNotificationWindowController *)self.rootViewController).notificationView animateOut];
}
- (BOOL)_canBecomeKeyWindow
{
return false;
}
- (bool)isDismissed
{
return [((TGNotificationWindowController *)self.rootViewController).notificationView isDismissed];
}
- (void)performTapAction
{
if ([self isDismissed])
return;
[self animateOut];
id<ASWatcher> watcher = _watcher.delegate;
if (watcher != nil && [watcher respondsToSelector:@selector(actionStageActionRequested:options:)])
{
[watcher actionStageActionRequested:_watcherAction options:_watcherOptions];
_watcher = nil;
_watcherAction = nil;
_watcherOptions = nil;
}
}
- (void)setFrame:(CGRect)frame
{
[super setFrame:frame];
}
@end