mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			133 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Objective-C
		
	
			
		
		
	
	
			133 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Objective-C
		
	
| //
 | |
| //  Copyright (c) 2018 Open Whisper Systems. All rights reserved.
 | |
| //
 | |
| 
 | |
| #import "OWSAnyTouchGestureRecognizer.h"
 | |
| #import <UIKit/UIGestureRecognizerSubclass.h>
 | |
| 
 | |
| NS_ASSUME_NONNULL_BEGIN
 | |
| 
 | |
| NSString *NSStringForUIGestureRecognizerState(UIGestureRecognizerState state)
 | |
| {
 | |
|     switch (state) {
 | |
|         case UIGestureRecognizerStatePossible:
 | |
|             return @"UIGestureRecognizerStatePossible";
 | |
|         case UIGestureRecognizerStateBegan:
 | |
|             return @"UIGestureRecognizerStateBegan";
 | |
|         case UIGestureRecognizerStateChanged:
 | |
|             return @"UIGestureRecognizerStateChanged";
 | |
|         case UIGestureRecognizerStateEnded:
 | |
|             return @"UIGestureRecognizerStateEnded";
 | |
|         case UIGestureRecognizerStateCancelled:
 | |
|             return @"UIGestureRecognizerStateCancelled";
 | |
|         case UIGestureRecognizerStateFailed:
 | |
|             return @"UIGestureRecognizerStateFailed";
 | |
|     }
 | |
| }
 | |
| 
 | |
| @implementation OWSAnyTouchGestureRecognizer
 | |
| 
 | |
| - (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer
 | |
| {
 | |
|     return NO;
 | |
| }
 | |
| 
 | |
| - (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer
 | |
| {
 | |
|     return NO;
 | |
| }
 | |
| 
 | |
| - (BOOL)shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
 | |
| {
 | |
|     return NO;
 | |
| }
 | |
| 
 | |
| - (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
 | |
| {
 | |
|     return YES;
 | |
| }
 | |
| 
 | |
| - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
 | |
| {
 | |
|     [super touchesBegan:touches withEvent:event];
 | |
| 
 | |
|     if (self.state == UIGestureRecognizerStatePossible && [self isValidTouch:touches event:event]) {
 | |
|         self.state = UIGestureRecognizerStateRecognized;
 | |
|     } else {
 | |
|         self.state = UIGestureRecognizerStateFailed;
 | |
|     }
 | |
| }
 | |
| 
 | |
| - (UIView *)rootViewInViewHierarchy:(UIView *)view
 | |
| {
 | |
|     OWSAssertDebug(view);
 | |
|     UIResponder *responder = view;
 | |
|     UIView *lastView = nil;
 | |
|     while (responder) {
 | |
|         if ([responder isKindOfClass:[UIView class]]) {
 | |
|             lastView = (UIView *)responder;
 | |
|         }
 | |
|         responder = [responder nextResponder];
 | |
|     }
 | |
|     return lastView;
 | |
| }
 | |
| 
 | |
| - (BOOL)isValidTouch:(NSSet<UITouch *> *)touches event:(UIEvent *)event
 | |
| {
 | |
|     if (event.allTouches.count > 1) {
 | |
|         return NO;
 | |
|     }
 | |
|     if (touches.count != 1) {
 | |
|         return NO;
 | |
|     }
 | |
| 
 | |
|     UITouch *touch = touches.anyObject;
 | |
|     CGPoint location = [touch locationInView:self.view];
 | |
|     if (!CGRectContainsPoint(self.view.bounds, location)) {
 | |
|         return NO;
 | |
|     }
 | |
| 
 | |
|     if ([self subviewControlOfView:self.view containsTouch:touch]) {
 | |
|         return NO;
 | |
|     }
 | |
| 
 | |
|     // Ignore touches that start near the top or bottom edge of the screen;
 | |
|     // they may be a system edge swipe gesture.
 | |
|     UIView *rootView = [self rootViewInViewHierarchy:self.view];
 | |
|     CGPoint rootLocation = [touch locationInView:rootView];
 | |
|     CGFloat distanceToTopEdge = MAX(0, rootLocation.y);
 | |
|     CGFloat distanceToBottomEdge = MAX(0, rootView.bounds.size.height - rootLocation.y);
 | |
|     CGFloat distanceToNearestEdge = MIN(distanceToTopEdge, distanceToBottomEdge);
 | |
|     CGFloat kSystemEdgeSwipeTolerance = 50.f;
 | |
|     if (distanceToNearestEdge < kSystemEdgeSwipeTolerance) {
 | |
|         return NO;
 | |
|     }
 | |
| 
 | |
|     return YES;
 | |
| }
 | |
| 
 | |
| - (BOOL)subviewControlOfView:(UIView *)superview containsTouch:(UITouch *)touch
 | |
| {
 | |
|     for (UIView *subview in superview.subviews) {
 | |
|         if (subview.hidden || !subview.userInteractionEnabled) {
 | |
|             continue;
 | |
|         }
 | |
|         CGPoint location = [touch locationInView:subview];
 | |
|         if (!CGRectContainsPoint(subview.bounds, location)) {
 | |
|             continue;
 | |
|         }
 | |
|         if ([subview isKindOfClass:[UIControl class]]) {
 | |
|             return YES;
 | |
|         }
 | |
|         if ([self subviewControlOfView:subview containsTouch:touch]) {
 | |
|             return YES;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return NO;
 | |
| }
 | |
| 
 | |
| @end
 | |
| 
 | |
| NS_ASSUME_NONNULL_END
 |