1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-04 10:27:46 +01:00
Telegram/Telegraph/TGNotificationWindow.m

376 lines
12 KiB
Mathematica
Raw Normal View History

2014-07-10 16:11:09 +02:00
#import "TGNotificationWindow.h"
#import "TGViewController.h"
#import "ActionStage.h"
#import "TGObserverProxy.h"
#import "TGAppDelegate.h"
#import <QuartzCore/QuartzCore.h>
@implementation TGOverlayWindowViewController
- (UIStatusBarStyle)preferredStatusBarStyle
{
UIViewController *topViewController = ((UINavigationController *)TGAppDelegateInstance.mainNavigationController).topViewController;
if ([topViewController isKindOfClass:[UITabBarController class]])
topViewController = [(UITabBarController *)topViewController selectedViewController];
UIStatusBarStyle style = [topViewController preferredStatusBarStyle];
return style;
}
- (BOOL)shouldAutorotate
{
static NSArray *nonRotateableWindowClasses = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
NSMutableArray *array = [[NSMutableArray alloc] init];
Class alertClass = NSClassFromString(TGEncodeText(@"`VJBmfsuPwfsmbzXjoepx", -1));
if (alertClass != nil)
[array addObject:alertClass];
nonRotateableWindowClasses = array;
});
for (UIWindow *window in [UIApplication sharedApplication].windows.reverseObjectEnumerator)
{
for (Class classInfo in nonRotateableWindowClasses)
{
if ([window isKindOfClass:classInfo])
return false;
}
}
if (TGAppDelegateInstance.mainNavigationController.presentedViewController != nil)
return [TGAppDelegateInstance.mainNavigationController.presentedViewController shouldAutorotate];
return [TGAppDelegateInstance.mainNavigationController shouldAutorotate];
}
- (void)loadView
{
[super loadView];
self.view.userInteractionEnabled = false;
self.view.opaque = false;
self.view.backgroundColor = [UIColor clearColor];
}
@end
@interface TGNotificationWindow ()
{
bool _isSwipeDismissing;
}
@property (nonatomic, strong) UIView *containerView;
@property (nonatomic, strong) UIView *contentView;
@property (nonatomic, strong) TGObserverProxy *statusBarOrientationChangeProxy;
@end
@implementation TGNotificationWindow
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.rootViewController = [[TGOverlayWindowViewController alloc] init];
self.clipsToBounds = false;
_containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, 20 + 44)];
_containerView.layer.anchorPoint = CGPointMake(0.5f, 0.0f);
_containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
_containerView.opaque = false;
[self addSubview:_containerView];
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureRecognized:)];
[self addGestureRecognizer:panRecognizer];
self.exclusiveTouch = true;
_statusBarOrientationChangeProxy = [[TGObserverProxy alloc] initWithTarget:self targetSelector:@selector(orientationWillBeChanged:) name:UIApplicationWillChangeStatusBarOrientationNotification];
}
return self;
}
- (void)orientationWillBeChanged:(NSNotification *)notification
{
UIInterfaceOrientation fromOrientation = [[UIApplication sharedApplication] statusBarOrientation];
NSNumber *nNewOrientation = [notification.userInfo objectForKey:UIApplicationStatusBarOrientationUserInfoKey];
UIInterfaceOrientation orientation = (UIInterfaceOrientation)[nNewOrientation intValue];
dispatch_async(dispatch_get_main_queue(), ^
{
[self willRotateToInterfaceOrientation:orientation fromOrientation:fromOrientation duration:UIInterfaceOrientationIsLandscape(orientation) == UIInterfaceOrientationIsLandscape( fromOrientation) ? 0.6 : 0.3];
});
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation fromOrientation:(UIInterfaceOrientation)__unused fromOrientation duration:(NSTimeInterval)duration
{
for (UIView *view in self.subviews)
{
if (view != _containerView)
view.hidden = true;
}
CGSize screenSize = [TGViewController screenSizeForInterfaceOrientation:UIInterfaceOrientationPortrait];
[UIView animateWithDuration:duration animations:^
{
if (orientation == UIDeviceOrientationPortrait)
{
self.layer.anchorPoint = CGPointMake(0.5f, (screenSize.height / 2) / _windowHeight);
CGAffineTransform transform = CGAffineTransformIdentity;
self.transform = transform;
self.frame = CGRectMake(0, 0, screenSize.width, _windowHeight);
}
else if (orientation == UIDeviceOrientationLandscapeLeft)
{
self.layer.anchorPoint = CGPointMake(0.5f, (screenSize.width / 2) / _windowHeight);
CGAffineTransform transform = CGAffineTransformMakeRotation((float)M_PI_2);
self.transform = transform;
CGRect bounds = self.bounds;
bounds.size.width = screenSize.height;
self.bounds = bounds;
}
else if (orientation == UIDeviceOrientationLandscapeRight)
{
self.layer.anchorPoint = CGPointMake(0.5f, (screenSize.width / 2) / _windowHeight);
CGAffineTransform transform = CGAffineTransformMakeRotation((float)-M_PI_2);
self.transform = transform;
CGRect bounds = self.bounds;
bounds.size.width = screenSize.height;
self.bounds = bounds;
}
}];
}
- (void)adjustToInterfaceOrientation:(UIInterfaceOrientation)orientation
{
CGSize screenSize = [TGViewController screenSizeForInterfaceOrientation:UIInterfaceOrientationPortrait];
if (orientation == UIInterfaceOrientationPortrait)
{
self.layer.anchorPoint = CGPointMake(0.5f, (screenSize.height / 2) / _windowHeight);
CGAffineTransform transform = CGAffineTransformIdentity;
self.transform = transform;
self.frame = CGRectMake(0, 0, screenSize.width, _windowHeight);
}
else if (orientation == UIDeviceOrientationLandscapeLeft)
{
if (CGRectIsEmpty(self.frame))
[self adjustToInterfaceOrientation:UIInterfaceOrientationPortrait];
self.layer.anchorPoint = CGPointMake(0.5f, (screenSize.width / 2) / _windowHeight);
CGAffineTransform transform = CGAffineTransformMakeRotation((float)M_PI_2);
self.transform = transform;
CGRect bounds = self.bounds;
bounds.size.width = screenSize.height;
self.bounds = bounds;
}
else if (orientation == UIInterfaceOrientationLandscapeRight)
{
if (CGRectIsEmpty(self.frame))
[self adjustToInterfaceOrientation:UIInterfaceOrientationPortrait];
self.layer.anchorPoint = CGPointMake(0.5f, (screenSize.width / 2) / _windowHeight);
CGAffineTransform transform = CGAffineTransformMakeRotation((float)-M_PI_2);
self.transform = transform;
CGRect bounds = self.bounds;
bounds.size.width = screenSize.height;
self.bounds = bounds;
}
}
- (void)setContentView:(UIView *)view
{
[_contentView removeFromSuperview];
_contentView = view;
view.frame = _containerView.bounds;
[_containerView addSubview:view];
}
- (void)animateIn
{
_isDismissed = false;
CGRect frame = _containerView.layer.frame;
frame.origin.x = 0;
_containerView.layer.frame = frame;
frame.origin = CGPointZero;
if (self.hidden || !CGRectEqualToRect(_containerView.layer.frame, frame))
{
/*CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0f / -1000.0f;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 89.0f * (float)M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
rotationAndPerspectiveTransform = CATransform3DTranslate(rotationAndPerspectiveTransform, 0, -frame.size.height, 0);
_containerView.layer.transform = rotationAndPerspectiveTransform;*/
self.hidden = false;
CGRect startFrame = frame;
startFrame.origin.y = -frame.size.height;
_containerView.layer.frame = startFrame;
[UIView animateWithDuration:0.3 animations:^
{
//_containerView.layer.transform = CATransform3DIdentity;
_containerView.layer.frame = frame;
}];
}
}
- (void)animateOut
{
_isDismissed = true;
if (self.hidden)
return;
CGRect frame = _containerView.layer.frame;
frame.origin.y = -frame.size.height;
[UIView animateWithDuration:0.3 animations:^
{
_containerView.layer.frame = frame;
} completion:^(__unused BOOL finished)
{
self.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)
{
float 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;
self.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];
}
- (void)performTapAction
{
if (_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
{
frame.origin.y = 0;
frame.size.height = 20 + 44;
[super setFrame:frame];
self.rootViewController.view.frame = self.bounds;
}
- (BOOL)_canBecomeKeyWindow
{
return false;
}
@end