mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
1091 lines
40 KiB
Objective-C
1091 lines
40 KiB
Objective-C
#import "TGModernConversationInputMicButton.h"
|
|
|
|
#import "LegacyComponentsInternal.h"
|
|
|
|
#import <LegacyComponents/TGModernButton.h>
|
|
#import "TGOverlayController.h"
|
|
#import "TGColor.h"
|
|
#import "TGImageUtils.h"
|
|
#import "TGPhotoEditorSparseView.h"
|
|
|
|
static const CGFloat innerCircleRadius = 110.0f;
|
|
static const CGFloat outerCircleRadius = innerCircleRadius + 50.0f;
|
|
static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius;
|
|
|
|
@interface TGModernConversationInputMicWindow : UIWindow
|
|
{
|
|
bool _ignoreNextTouch;
|
|
}
|
|
|
|
@property (nonatomic, copy) void (^requestedLockedAction)(void);
|
|
|
|
@end
|
|
|
|
@interface TGModernConversationInputLockView : UIView
|
|
{
|
|
CALayer *_baseLayer;
|
|
CALayer *_arcLayer;
|
|
}
|
|
|
|
@property (nonatomic, assign) CGFloat lockness;
|
|
@property (nonatomic, strong) UIColor *color;
|
|
|
|
@end
|
|
|
|
|
|
@interface TGModernConversationInputMicButtonOverlayController : TGOverlayController
|
|
|
|
@end
|
|
|
|
@implementation TGModernConversationInputMicButtonOverlayController
|
|
|
|
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
|
|
{
|
|
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
|
|
|
|
[self.view.window.layer removeAnimationForKey:@"backgroundColor"];
|
|
[CATransaction begin];
|
|
[CATransaction setDisableActions:true];
|
|
self.view.window.layer.backgroundColor = [UIColor clearColor].CGColor;
|
|
[CATransaction commit];
|
|
|
|
for (UIView *view in self.view.window.subviews)
|
|
{
|
|
if (view != self.view)
|
|
{
|
|
[view removeFromSuperview];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
@interface TGModernConversationInputMicButtonWindowPresentation : NSObject <TGModernConversationInputMicButtonPresentation> {
|
|
@public
|
|
TGModernConversationInputMicWindow *_overlayWindow;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation TGModernConversationInputMicButtonWindowPresentation
|
|
|
|
- (instancetype)init {
|
|
self = [super init];
|
|
if (self != nil) {
|
|
_overlayWindow = [[TGModernConversationInputMicWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
|
_overlayWindow.windowLevel = 1000000000.0f;
|
|
_overlayWindow.rootViewController = [[TGModernConversationInputMicButtonOverlayController alloc] init];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (UIView *)view {
|
|
return _overlayWindow.rootViewController.view;
|
|
}
|
|
|
|
- (void)setUserInteractionEnabled:(bool)enabled {
|
|
_overlayWindow.userInteractionEnabled = enabled;
|
|
}
|
|
|
|
- (void)present {
|
|
_overlayWindow.hidden = false;
|
|
}
|
|
|
|
- (void)dismiss {
|
|
_overlayWindow.hidden = true;
|
|
}
|
|
|
|
@end
|
|
|
|
@interface TGModernConversationInputMicButton () <UIGestureRecognizerDelegate>
|
|
{
|
|
CGPoint _touchLocation;
|
|
UIPanGestureRecognizer *_panRecognizer;
|
|
|
|
CGPoint _lastVelocity;
|
|
|
|
bool _processCurrentTouch;
|
|
CFAbsoluteTime _lastTouchTime;
|
|
bool _acceptTouchDownAsTouchUp;
|
|
|
|
UIImageView *_innerCircleView;
|
|
UIImageView *_outerCircleView;
|
|
|
|
UIView *_innerIconWrapperView;
|
|
UIImageView *_innerIconView;
|
|
|
|
UIView *_lockPanelWrapperView;
|
|
UIView *_lockPanelView;
|
|
UIImageView *_lockArrowView;
|
|
TGModernConversationInputLockView *_lockView;
|
|
UIImage *_previousIcon;
|
|
TGModernButton *_stopButton;
|
|
|
|
CGFloat _currentScale;
|
|
CGFloat _currentTranslation;
|
|
CGFloat _targetTranslation;
|
|
|
|
CGFloat _cancelTranslation;
|
|
CGFloat _cancelTargetTranslation;
|
|
|
|
CFAbsoluteTime _animationStartTime;
|
|
|
|
CADisplayLink *_displayLink;
|
|
CGFloat _currentLevel;
|
|
CGFloat _inputLevel;
|
|
bool _animatedIn;
|
|
|
|
bool _hidesPanelOnLock;
|
|
|
|
UIImage *_icon;
|
|
|
|
id<TGModernConversationInputMicButtonPresentation> _presentation;
|
|
UIView<TGModernConversationInputMicButtonDecoration> *_decoration;
|
|
UIView<TGModernConversationInputMicButtonLock> *_lock;
|
|
|
|
BOOL _xFeedbackOccured;
|
|
BOOL _yFeedbackOccured;
|
|
|
|
bool _skipCancelUpdate;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation TGModernConversationInputMicButton
|
|
|
|
- (void)setFadeDisabled:(bool)fadeDisabled {
|
|
_fadeDisabled = fadeDisabled;
|
|
_iconView.alpha = fadeDisabled ? 0.5f : 1.0f;
|
|
}
|
|
|
|
- (UIImage *)innerCircleImage:(UIColor *)color
|
|
{
|
|
UIGraphicsBeginImageContextWithOptions(CGSizeMake(innerCircleRadius, innerCircleRadius), false, 0.0f);
|
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
CGContextSetFillColorWithColor(context, color.CGColor);
|
|
CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, innerCircleRadius, innerCircleRadius));
|
|
|
|
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
|
UIGraphicsEndImageContext();
|
|
return image;
|
|
}
|
|
|
|
- (UIImage *)outerCircleImage:(UIColor *)color
|
|
{
|
|
UIGraphicsBeginImageContextWithOptions(CGSizeMake(outerCircleRadius, outerCircleRadius), false, 0.0f);
|
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
CGContextSetFillColorWithColor(context, [color colorWithAlphaComponent:0.2f].CGColor);
|
|
CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, outerCircleRadius, outerCircleRadius));
|
|
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
|
UIGraphicsEndImageContext();
|
|
|
|
return image;
|
|
}
|
|
|
|
- (instancetype)initWithFrame:(CGRect)frame
|
|
{
|
|
self = [super initWithFrame:frame];
|
|
if (self != nil)
|
|
{
|
|
self.exclusiveTouch = true;
|
|
self.multipleTouchEnabled = false;
|
|
|
|
_panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)];
|
|
_panRecognizer.cancelsTouchesInView = false;
|
|
_panRecognizer.delegate = self;
|
|
[self addGestureRecognizer:_panRecognizer];
|
|
|
|
_icon = TGComponentsImageNamed(@"InputMicRecordingOverlay.png");
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)panGesture:(UIPanGestureRecognizer *)__unused gestureRecognizer
|
|
{
|
|
}
|
|
|
|
- (void)dealloc {
|
|
_displayLink.paused = true;
|
|
[_displayLink removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
|
}
|
|
|
|
- (CADisplayLink *)displayLink {
|
|
if (_displayLink == nil) {
|
|
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkUpdate)];
|
|
_displayLink.paused = true;
|
|
[_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
|
}
|
|
return _displayLink;
|
|
}
|
|
|
|
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)__unused event
|
|
{
|
|
return CGRectContainsPoint(CGRectInset(self.bounds, -10.0f, 0.0f), point);
|
|
}
|
|
|
|
- (UIImage *)icon
|
|
{
|
|
return _icon;
|
|
}
|
|
|
|
- (void)setIcon:(UIImage *)icon
|
|
{
|
|
_icon = icon;
|
|
_innerIconView.image = icon;
|
|
CGPoint center = _innerIconView.center;
|
|
_innerIconView.frame = CGRectMake(0.0f, 0.0f, icon.size.width, icon.size.height);
|
|
_innerIconView.center = center;
|
|
}
|
|
|
|
- (void)updateOverlay
|
|
{
|
|
if (_presentation == nil) {
|
|
return;
|
|
}
|
|
UIView *parentView = [_presentation view];
|
|
|
|
CGPoint centerPointInSelfWindow = [self.window convertPoint:self.center fromView:self.superview];
|
|
CGPoint centerPointInParentViewWindow = [self.window convertPoint:centerPointInSelfWindow toWindow:parentView.window];
|
|
CGPoint centerPoint = [parentView.window convertPoint:centerPointInParentViewWindow toView:parentView];
|
|
|
|
centerPoint.x += _centerOffset.x;
|
|
centerPoint.y += _centerOffset.y;
|
|
_innerCircleView.center = centerPoint;
|
|
_outerCircleView.center = centerPoint;
|
|
_decoration.center = centerPoint;
|
|
_innerIconWrapperView.center = CGPointMake(_decoration.frame.size.width / 2.0f, _decoration.frame.size.height / 2.0f);
|
|
|
|
_lockPanelWrapperView.frame = CGRectMake(floor(centerPoint.x - _lockPanelWrapperView.frame.size.width / 2.0f), floor(centerPoint.y - 122.0f - _lockPanelWrapperView.frame.size.height / 2.0f), _lockPanelWrapperView.frame.size.width, _lockPanelWrapperView.frame.size.height);
|
|
|
|
_stopButton.frame = CGRectMake(floor(centerPoint.x - _stopButton.frame.size.width / 2.0f), floor(centerPoint.y - 102.0f - _stopButton.frame.size.height / 2.0f), _stopButton.frame.size.width, _stopButton.frame.size.height);
|
|
}
|
|
|
|
- (void)setPallete:(TGModernConversationInputMicPallete *)pallete {
|
|
bool update = _pallete != nil;
|
|
_pallete = pallete;
|
|
|
|
if (!update)
|
|
return;
|
|
|
|
if ([_lockPanelView isKindOfClass:[UIImageView class]]) {
|
|
((UIImageView *)_lockPanelView).image = [self panelBackgroundImage];
|
|
}
|
|
_lockArrowView.image = TGTintedImage(TGComponentsImageNamed(@"VideoRecordArrow"), self.pallete != nil ? self.pallete.lockColor : UIColorRGB(0x9597a0));
|
|
_lockView.color = self.pallete.lockColor;
|
|
|
|
_innerCircleView.image = [self innerCircleImage:self.pallete != nil ? self.pallete.buttonColor : TGAccentColor()];
|
|
_outerCircleView.image = [self outerCircleImage:self.pallete != nil ? self.pallete.buttonColor : TGAccentColor()];
|
|
[_stopButton setImage:[self stopButtonImage] forState:UIControlStateNormal];
|
|
}
|
|
|
|
- (UIImage *)panelBackgroundImage
|
|
{
|
|
UIGraphicsBeginImageContextWithOptions(CGSizeMake(40.0f, 40.0f), false, 0.0f);
|
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
|
|
CGRect rect = CGRectMake(TGScreenPixel / 2.0f, TGScreenPixel / 2.0f, 40.0f - TGScreenPixel, 40.0 - TGScreenPixel);
|
|
CGFloat radius = 40.0f / 2.0f;
|
|
|
|
CGFloat minx = CGRectGetMinX(rect), midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect);
|
|
CGFloat miny = CGRectGetMinY(rect), midy = CGRectGetMidY(rect), maxy = CGRectGetMaxY(rect);
|
|
|
|
CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
|
|
CGContextSetStrokeColorWithColor(context, TGAccentColor().CGColor);
|
|
CGContextSetLineWidth(context, TGScreenPixel);
|
|
|
|
CGContextMoveToPoint(context, minx, midy);
|
|
CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
|
|
CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
|
|
CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
|
|
CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
|
|
CGContextClosePath(context);
|
|
|
|
CGContextSetFillColorWithColor(context, (self.pallete != nil ? self.pallete.backgroundColor : UIColorRGB(0xf7f7f7)).CGColor);
|
|
CGContextSetStrokeColorWithColor(context, (self.pallete != nil ? self.pallete.borderColor : UIColorRGB(0xb2b2b2)).CGColor);
|
|
CGContextDrawPath(context, kCGPathFillStroke);
|
|
|
|
UIImage *panelBackgroundView = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:19 topCapHeight:19];
|
|
UIGraphicsEndImageContext();
|
|
return panelBackgroundView;
|
|
}
|
|
|
|
- (UIImage *)stopButtonImage
|
|
{
|
|
UIGraphicsBeginImageContextWithOptions(CGSizeMake(40.0f, 40.0f), false, 0.0f);
|
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
|
|
CGContextSetFillColorWithColor(context, (self.pallete != nil ? self.pallete.backgroundColor : UIColorRGB(0xf7f7f7)).CGColor);
|
|
CGContextSetStrokeColorWithColor(context, (self.pallete != nil ? self.pallete.borderColor : UIColorRGB(0xb2b2b2)).CGColor);
|
|
CGContextSetLineWidth(context, TGScreenPixel);
|
|
|
|
|
|
CGContextAddPath(context, [UIBezierPath bezierPathWithRoundedRect:CGRectMake(12.0, 12.0, 5.0, 14.0) cornerRadius:1.0].CGPath);
|
|
CGContextFillPath(context);
|
|
|
|
CGContextAddPath(context, [UIBezierPath bezierPathWithRoundedRect:CGRectMake(40.0 - 12.0 - 5.0, 12.0, 5.0, 14.0) cornerRadius:1.0].CGPath);
|
|
CGContextFillPath(context);
|
|
|
|
// CGRect rect1 = CGRectMake(TGScreenPixel / 2.0f, TGScreenPixel / 2.0f, 40.0f - TGScreenPixel, 40.0 - TGScreenPixel);
|
|
// CGContextFillEllipseInRect(context, rect1);
|
|
// CGContextStrokeEllipseInRect(context, rect1);
|
|
//
|
|
// CGRect iconRect = CGRectInset(rect1, 12.0f, 12.0f);
|
|
// CGFloat radius = 1.0f;
|
|
//
|
|
// CGFloat minx = CGRectGetMinX(iconRect), midx = CGRectGetMidX(iconRect), maxx = CGRectGetMaxX(iconRect);
|
|
// CGFloat miny = CGRectGetMinY(iconRect), midy = CGRectGetMidY(iconRect), maxy = CGRectGetMaxY(iconRect);
|
|
//
|
|
// CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
|
|
//
|
|
// CGContextMoveToPoint(context, minx, midy);
|
|
// CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
|
|
// CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
|
|
// CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
|
|
// CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
|
|
// CGContextClosePath(context);
|
|
|
|
CGContextSetFillColorWithColor(context, (self.pallete != nil ? self.pallete.buttonColor : TGAccentColor()).CGColor);
|
|
CGContextDrawPath(context, kCGPathFill);
|
|
|
|
UIImage *stopButtonImage = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:19 topCapHeight:19];
|
|
UIGraphicsEndImageContext();
|
|
return stopButtonImage;
|
|
}
|
|
|
|
- (UIView *)createLockPanelView {
|
|
UIImageView *view = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 40.0f, 72.0f)];
|
|
view.userInteractionEnabled = true;
|
|
view.image = [self panelBackgroundImage];
|
|
return view;
|
|
}
|
|
|
|
- (void)animateIn {
|
|
if (!_locked) {
|
|
_lockView.lockness = 0.0f;
|
|
[_lock updateLockness:0.0];
|
|
}
|
|
|
|
_currentScale = 1.0;
|
|
_animatedIn = true;
|
|
_animationStartTime = CACurrentMediaTime();
|
|
|
|
if (_presentation == nil) {
|
|
if ([_delegate respondsToSelector:@selector(micButtonPresenter)]) {
|
|
_presentation = [_delegate micButtonPresenter];
|
|
} else {
|
|
_presentation = [[TGModernConversationInputMicButtonWindowPresentation alloc] init];
|
|
__weak TGModernConversationInputMicButton *weakSelf = self;
|
|
|
|
(((TGModernConversationInputMicButtonWindowPresentation *)_presentation)->_overlayWindow).requestedLockedAction = ^
|
|
{
|
|
__strong TGModernConversationInputMicButton *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
id<TGModernConversationInputMicButtonDelegate> delegate = strongSelf.delegate;
|
|
if ([delegate respondsToSelector:@selector(micButtonInteractionRequestedLockedAction)])
|
|
[delegate micButtonInteractionRequestedLockedAction];
|
|
};
|
|
}
|
|
|
|
_lockPanelWrapperView = [[TGPhotoEditorSparseView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 40.0f, 72.0f)];
|
|
[[_presentation view] addSubview:_lockPanelWrapperView];
|
|
|
|
_lockPanelView = [self createLockPanelView];
|
|
|
|
[_lockPanelWrapperView addSubview:_lockPanelView];
|
|
|
|
if ([_delegate respondsToSelector:@selector(micButtonLock)]) {
|
|
_lock = [_delegate micButtonLock];
|
|
_lock.center = CGPointMake(CGRectGetMidX(_lockPanelView.bounds), CGRectGetMidY(_lockPanelView.bounds));
|
|
[_lockPanelView addSubview:_lock];
|
|
} else {
|
|
_lockArrowView = [[UIImageView alloc] initWithImage:TGTintedImage(TGComponentsImageNamed(@"VideoRecordArrow"), self.pallete != nil ? self.pallete.lockColor : UIColorRGB(0x9597a0))];
|
|
_lockArrowView.frame = CGRectMake(floor((_lockPanelView.frame.size.width - _lockArrowView.frame.size.width) / 2.0f), 54.0f, _lockArrowView.frame.size.width, _lockArrowView.frame.size.height);
|
|
[_lockPanelView addSubview:_lockArrowView];
|
|
|
|
_lockView = [[TGModernConversationInputLockView alloc] init];
|
|
_lockView.color = self.pallete.lockColor;
|
|
_lockView.frame = CGRectMake(floor((_lockPanelView.frame.size.width - _lockView.frame.size.width) / 2.0f), 6.0f, _lockView.frame.size.width, _lockView.frame.size.height);
|
|
[_lockPanelView addSubview:_lockView];
|
|
}
|
|
|
|
_innerCircleView = [[UIImageView alloc] initWithImage:[self innerCircleImage:self.pallete != nil ? self.pallete.buttonColor : TGAccentColor()]];
|
|
_innerCircleView.alpha = 0.0f;
|
|
[[_presentation view] addSubview:_innerCircleView];
|
|
|
|
if ([_delegate respondsToSelector:@selector(micButtonDecoration)]) {
|
|
UIView<TGModernConversationInputMicButtonDecoration> *decoration = [_delegate micButtonDecoration];
|
|
_decoration = decoration;
|
|
[[_presentation view] addSubview:_decoration];
|
|
}
|
|
|
|
if (_decoration == nil) {
|
|
_outerCircleView = [[UIImageView alloc] initWithImage:[self outerCircleImage:self.pallete != nil ? self.pallete.buttonColor : TGAccentColor()]];
|
|
_outerCircleView.alpha = 0.0f;
|
|
_outerCircleView.tag = 0x01f2bca;
|
|
[[_presentation view] addSubview:_outerCircleView];
|
|
|
|
[_outerCircleView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(outerCircleTapGesture:)]];
|
|
} else {
|
|
_decoration.userInteractionEnabled = true;
|
|
[_decoration addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(outerCircleTapGesture:)]];
|
|
}
|
|
|
|
_innerIconView = [[UIImageView alloc] initWithImage:_icon];
|
|
|
|
_innerIconWrapperView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 30.0f, 30.0f)];
|
|
_innerIconWrapperView.alpha = 0.0f;
|
|
_innerIconWrapperView.userInteractionEnabled = false;
|
|
[_innerIconWrapperView addSubview:_innerIconView];
|
|
|
|
[_decoration addSubview:_innerIconWrapperView];
|
|
|
|
if (_lock == nil) {
|
|
_stopButton = [[TGModernButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 40.0f, 40.0f)];
|
|
_stopButton.accessibilityLabel = TGLocalized(@"VoiceOver.Recording.StopAndPreview");
|
|
_stopButton.adjustsImageWhenHighlighted = false;
|
|
_stopButton.exclusiveTouch = true;
|
|
[_stopButton setImage:[self stopButtonImage] forState:UIControlStateNormal];
|
|
_stopButton.userInteractionEnabled = false;
|
|
_stopButton.alpha = 0.0f;
|
|
[_stopButton addTarget:self action:@selector(stopPressed) forControlEvents:UIControlEventTouchUpInside];
|
|
[[_presentation view] addSubview:_stopButton];
|
|
}
|
|
}
|
|
|
|
[_presentation setUserInteractionEnabled:_blocking];
|
|
[_presentation present];
|
|
|
|
_stopButton.userInteractionEnabled = false;
|
|
|
|
dispatch_block_t block = ^{
|
|
[self updateOverlay];
|
|
};
|
|
|
|
block();
|
|
dispatch_async(dispatch_get_main_queue(), block);
|
|
|
|
//_innerIconWrapperView.transform = CGAffineTransformIdentity;
|
|
_innerCircleView.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
|
_outerCircleView.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
|
_decoration.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
|
_innerCircleView.alpha = 0.2f;
|
|
_outerCircleView.alpha = 0.2f;
|
|
_decoration.alpha = 0.2;
|
|
|
|
_lockPanelWrapperView.transform = CGAffineTransformMakeTranslation(0.0f, _locked ? 36.0 : 100.0f);
|
|
_lockPanelWrapperView.alpha = 0.0f;
|
|
|
|
_lock.transform = CGAffineTransformIdentity;
|
|
|
|
if (iosMajorVersion() >= 8) {
|
|
[UIView animateWithDuration:0.50 delay:0.0 usingSpringWithDamping:0.55f initialSpringVelocity:0.0f options:UIViewAnimationOptionBeginFromCurrentState animations:^{
|
|
_innerCircleView.transform = CGAffineTransformIdentity;
|
|
_outerCircleView.transform = CGAffineTransformMakeScale(outerCircleMinScale, outerCircleMinScale);
|
|
_decoration.transform = CGAffineTransformIdentity;
|
|
|
|
_lockPanelWrapperView.transform = CGAffineTransformIdentity;
|
|
} completion:nil];
|
|
|
|
[UIView animateWithDuration:0.1 animations:^{
|
|
_innerCircleView.alpha = 1.0f;
|
|
self.iconView.alpha = 0.0f;
|
|
_innerIconWrapperView.alpha = 1.0f;
|
|
_outerCircleView.alpha = 1.0f;
|
|
_decoration.alpha = 1.0;
|
|
|
|
_lockPanelWrapperView.alpha = 1.0f;
|
|
}];
|
|
}
|
|
else {
|
|
[UIView animateWithDuration:0.2 animations:^
|
|
{
|
|
_lockPanelWrapperView.transform = CGAffineTransformIdentity;
|
|
_lockPanelWrapperView.alpha = 1.0f;
|
|
}];
|
|
}
|
|
[self displayLink].paused = false;
|
|
|
|
if (_locked) {
|
|
_skipCancelUpdate = true;
|
|
[self animateLock];
|
|
_skipCancelUpdate = false;
|
|
}
|
|
}
|
|
|
|
- (void)outerCircleTapGesture:(UITapGestureRecognizer *)recognizer {
|
|
if (recognizer.state == UIGestureRecognizerStateEnded) {
|
|
[self _commitCompleted];
|
|
}
|
|
}
|
|
|
|
- (void)animateOut:(BOOL)toSmallSize {
|
|
_locked = false;
|
|
_animatedIn = false;
|
|
_displayLink.paused = true;
|
|
_currentLevel = 0.0f;
|
|
_currentTranslation = 0.0f;
|
|
_targetTranslation = 0.0f;
|
|
_cancelTranslation = 0;
|
|
_cancelTargetTranslation = 0;
|
|
_currentScale = 1.0f;
|
|
[UIView animateWithDuration:0.18 animations:^{
|
|
_innerCircleView.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
|
_outerCircleView.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
|
if (toSmallSize) {
|
|
_decoration.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(0.33f, 0.33f), CGAffineTransformMakeTranslation(0, 2 - TGScreenPixel));
|
|
//_innerIconWrapperView.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(0.492f, 0.492f), CGAffineTransformMakeTranslation(-TGScreenPixel, 1));
|
|
} else {
|
|
_decoration.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
|
_decoration.alpha = 0.0;
|
|
//_innerIconWrapperView.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
|
_innerIconWrapperView.alpha = 0.0f;
|
|
}
|
|
_innerCircleView.alpha = 0.0f;
|
|
_outerCircleView.alpha = 0.0f;
|
|
self.iconView.alpha = 1.0f;
|
|
|
|
CGAffineTransform transform = CGAffineTransformMakeTranslation(0.0f, 100.0f);
|
|
transform = CGAffineTransformScale(transform, 0.2f, 0.2f);
|
|
|
|
if (![_lockPanelWrapperView.layer.animationKeys containsObject:@"transform"])
|
|
_lockPanelWrapperView.transform = transform;
|
|
|
|
_lockPanelWrapperView.alpha = 0.0f;
|
|
|
|
_stopButton.alpha = 0.0f;
|
|
} completion:^(BOOL finished) {
|
|
if (finished || [[[LegacyComponentsGlobals provider] applicationInstance] applicationState] == UIApplicationStateBackground) {
|
|
[_presentation dismiss];
|
|
_presentation = nil;
|
|
|
|
id<TGModernConversationInputMicButtonDelegate> delegate = _delegate;
|
|
if ([delegate respondsToSelector:@selector(micButtonInteractionUpdateCancelTranslation:)])
|
|
[delegate micButtonInteractionUpdateCancelTranslation:-_cancelTargetTranslation];
|
|
}
|
|
|
|
if (_previousIcon != nil)
|
|
[self setIcon:_previousIcon];
|
|
_previousIcon = nil;
|
|
}];
|
|
}
|
|
|
|
- (void)dismiss
|
|
{
|
|
[_presentation dismiss];
|
|
_presentation = nil;
|
|
}
|
|
|
|
- (void)setHidesPanelOnLock {
|
|
_hidesPanelOnLock = true;
|
|
}
|
|
|
|
+ (UIImage *)stopIconImage
|
|
{
|
|
static dispatch_once_t onceToken;
|
|
static UIImage *iconImage;
|
|
dispatch_once(&onceToken, ^
|
|
{
|
|
CGRect rect = CGRectMake(0, 0, 22.0f, 22.0f);
|
|
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0);
|
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
|
|
CGContextAddPath(context, [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 22, 22) cornerRadius:7].CGPath);
|
|
CGContextSetFillColorWithColor(context, UIColorRGBA(0x0ffffff, 1.3f).CGColor);
|
|
CGContextFillPath(context);
|
|
|
|
iconImage = UIGraphicsGetImageFromCurrentImageContext();
|
|
UIGraphicsEndImageContext();
|
|
});
|
|
return iconImage;
|
|
}
|
|
|
|
- (void)animateLock {
|
|
if (!_animatedIn) {
|
|
return;
|
|
}
|
|
|
|
_lockView.lockness = 1.0f;
|
|
[_lock updateLockness:1.0];
|
|
|
|
UIView *snapshotView = [_innerIconView snapshotViewAfterScreenUpdates:false];
|
|
snapshotView.frame = _innerIconView.frame;
|
|
[_innerIconWrapperView insertSubview:snapshotView atIndex:0];
|
|
|
|
UIImage *icon = _hidesPanelOnLock ? [TGModernConversationInputMicButton stopIconImage] : TGComponentsImageNamed(@"RecordSendIcon");
|
|
_previousIcon = _innerIconView.image;
|
|
[self setIcon:TGTintedImage(icon, _pallete != nil && !_hidesPanelOnLock ? _pallete.iconColor : [UIColor whiteColor])];
|
|
|
|
_currentScale = 1;
|
|
_cancelTargetTranslation = 0;
|
|
id<TGModernConversationInputMicButtonDelegate> delegate = _delegate;
|
|
if ([delegate respondsToSelector:@selector(micButtonInteractionUpdateCancelTranslation:)] && !_skipCancelUpdate)
|
|
[delegate micButtonInteractionUpdateCancelTranslation:-_cancelTargetTranslation];
|
|
|
|
_innerIconView.transform = CGAffineTransformMakeScale(0.3f, 0.3f);
|
|
_innerIconView.alpha = 0.0f;
|
|
[UIView animateWithDuration:0.3 delay:0.0 options:7 << 16 animations:^
|
|
{
|
|
_innerIconView.transform = CGAffineTransformIdentity;
|
|
snapshotView.transform = CGAffineTransformMakeScale(0.001f, 0.001f);
|
|
} completion:^(__unused BOOL finished) {
|
|
[snapshotView removeFromSuperview];
|
|
}];
|
|
|
|
[UIView animateWithDuration:0.2 animations:^
|
|
{
|
|
snapshotView.alpha = 0.0f;
|
|
_innerIconView.alpha = 1.0f;
|
|
|
|
_lockPanelView.frame = CGRectMake(_lockPanelView.frame.origin.x, 40.0f, _lockPanelView.frame.size.width, 72.0f - 32.0f);
|
|
_lockView.transform = CGAffineTransformMakeTranslation(0.0f, -11.0f);
|
|
_lock.transform = CGAffineTransformMakeTranslation(0.0f, -16.0f);
|
|
_lockArrowView.transform = CGAffineTransformMakeTranslation(0.0f, -39.0f);
|
|
_lockArrowView.alpha = 0.0f;
|
|
|
|
if (_hidesPanelOnLock) {
|
|
_lockPanelView.transform = CGAffineTransformScale(_lockPanelView.transform, 0.01, 0.01);
|
|
_lockPanelView.alpha = 0.0;
|
|
}
|
|
} completion:^(BOOL finished) {
|
|
if (_hidesPanelOnLock) {
|
|
[_lockPanelWrapperView removeFromSuperview];
|
|
}
|
|
}];
|
|
|
|
if (_lock == nil) {
|
|
TGDispatchAfter(0.45, dispatch_get_main_queue(), ^
|
|
{
|
|
[UIView animateWithDuration:0.2 delay:0.0 options:7 << 16 animations:^
|
|
{
|
|
_lockPanelWrapperView.transform = CGAffineTransformMakeTranslation(0.0f, 120.0f);
|
|
} completion:^(__unused BOOL finished)
|
|
{
|
|
_lockPanelWrapperView.alpha = 0.0f;
|
|
_lockPanelView.frame = CGRectMake(_lockPanelView.frame.origin.x, 0.0f, _lockPanelView.frame.size.width, 72.0f);
|
|
_lockView.transform = CGAffineTransformIdentity;
|
|
_lockArrowView.transform = CGAffineTransformIdentity;
|
|
_lockArrowView.alpha = 1.0f;
|
|
}];
|
|
});
|
|
}
|
|
|
|
_stopButton.userInteractionEnabled = true;
|
|
[UIView animateWithDuration:0.25 delay:0.56 options:kNilOptions animations:^
|
|
{
|
|
_stopButton.alpha = 1.0f;
|
|
} completion:nil];
|
|
}
|
|
|
|
- (void)stopPressed
|
|
{
|
|
_stopButton.userInteractionEnabled = false;
|
|
|
|
id<TGModernConversationInputMicButtonDelegate> delegate = _delegate;
|
|
if ([delegate respondsToSelector:@selector(micButtonInteractionStopped)])
|
|
[delegate micButtonInteractionStopped];
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
[UIView animateWithDuration:0.2 animations:^
|
|
{
|
|
_stopButton.alpha = 0.0f;
|
|
}];
|
|
});
|
|
}
|
|
|
|
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
|
|
{
|
|
if ([super beginTrackingWithTouch:touch withEvent:event])
|
|
{
|
|
if (_acceptTouchDownAsTouchUp || _locked)
|
|
{
|
|
_locked = false;
|
|
_acceptTouchDownAsTouchUp = false;
|
|
_processCurrentTouch = false;
|
|
|
|
[self _commitCompleted];
|
|
}
|
|
else
|
|
{
|
|
_lastVelocity = CGPointZero;
|
|
|
|
if (ABS(CFAbsoluteTimeGetCurrent() - _lastTouchTime) < 0.4)
|
|
{
|
|
_processCurrentTouch = false;
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
_processCurrentTouch = true;
|
|
_lastTouchTime = CFAbsoluteTimeGetCurrent();
|
|
|
|
id<TGModernConversationInputMicButtonDelegate> delegate = _delegate;
|
|
if ([delegate respondsToSelector:@selector(micButtonInteractionBegan)])
|
|
[delegate micButtonInteractionBegan];
|
|
|
|
_touchLocation = [touch locationInView:self];
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
|
|
{
|
|
if ([super continueTrackingWithTouch:touch withEvent:event])
|
|
{
|
|
_lastVelocity = [_panRecognizer velocityInView:self];
|
|
|
|
if (_processCurrentTouch)
|
|
{
|
|
CGFloat distanceX = MIN(0.0f, [touch locationInView:self].x - _touchLocation.x);
|
|
CGFloat distanceY = MIN(0.0f, [touch locationInView:self].y - _touchLocation.y);
|
|
|
|
CGPoint value = CGPointMake(MAX(0.0f, MIN(1.0f, (-distanceX) / 300.0f)), MAX(0.0f, MIN(1.0f, (-distanceY) / 300.0f)));
|
|
|
|
CGPoint velocity = [_panRecognizer velocityInView:self];
|
|
|
|
if (CACurrentMediaTime() > _animationStartTime) {
|
|
CGFloat scale = MAX(0.4f, MIN(1.0f, 1.0f - value.x));
|
|
|
|
_currentScale = scale;
|
|
|
|
_targetTranslation = distanceY;
|
|
_cancelTargetTranslation = distanceX;
|
|
CGFloat targetLockness = _locked ? 1.0f : MIN(1.0f, fabs(_targetTranslation) / 105.0f);
|
|
[_lock updateLockness:targetLockness];
|
|
_lockView.lockness = targetLockness;
|
|
_lockView.transform = CGAffineTransformMakeTranslation(0.0f, -11.0f * targetLockness);
|
|
_lock.transform = CGAffineTransformMakeTranslation(0.0f, -16.0f * targetLockness);
|
|
|
|
_lockPanelView.frame = CGRectMake(_lockPanelView.frame.origin.x,
|
|
40.0f * targetLockness,
|
|
_lockPanelView.frame.size.width,
|
|
72.0f - 32.0f * targetLockness);
|
|
|
|
_lockArrowView.alpha = MAX(0.0f, 1.0f - targetLockness * 1.6f);
|
|
_lockArrowView.transform = CGAffineTransformMakeTranslation(0.0f, -39.0f * targetLockness);
|
|
}
|
|
|
|
id<TGModernConversationInputMicButtonDelegate> delegate = _delegate;
|
|
if ([delegate respondsToSelector:@selector(micButtonInteractionUpdateCancelTranslation:)])
|
|
[delegate micButtonInteractionUpdateCancelTranslation:-_cancelTargetTranslation];
|
|
|
|
if (distanceX < -150.0f) {
|
|
id<TGModernConversationInputMicButtonDelegate> delegate = _delegate;
|
|
if ([delegate respondsToSelector:@selector(micButtonInteractionCancelled:)])
|
|
[delegate micButtonInteractionCancelled:velocity];
|
|
|
|
_targetTranslation = 0.0f;
|
|
|
|
return false;
|
|
} else if (distanceX < -100.0 && !_xFeedbackOccured) {
|
|
_xFeedbackOccured = true;
|
|
} else if (distanceX > -100.0) {
|
|
_xFeedbackOccured = false;
|
|
}
|
|
|
|
if (distanceY < -110.0f) {
|
|
[self _commitLocked];
|
|
|
|
return false;
|
|
} else if (distanceY < -60.0 && !_yFeedbackOccured) {
|
|
_yFeedbackOccured = true;
|
|
} else if (distanceY > -60.0) {
|
|
_yFeedbackOccured = false;
|
|
}
|
|
|
|
if ([delegate respondsToSelector:@selector(micButtonInteractionUpdate:)])
|
|
[delegate micButtonInteractionUpdate:value];
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
- (void)cancelTrackingWithEvent:(UIEvent *)event
|
|
{
|
|
if (_processCurrentTouch)
|
|
{
|
|
_currentTranslation = 0.0f;
|
|
|
|
TGDispatchAfter(1.0, dispatch_get_main_queue(), ^
|
|
{
|
|
[self _commitLocked];
|
|
});
|
|
}
|
|
|
|
[super cancelTrackingWithEvent:event];
|
|
|
|
_yFeedbackOccured = false;
|
|
_xFeedbackOccured = false;
|
|
}
|
|
|
|
- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
|
|
{
|
|
if (_processCurrentTouch)
|
|
{
|
|
_targetTranslation = 0.0f;
|
|
|
|
CGFloat distanceX = MIN(0.0f, [touch locationInView:self].x - _touchLocation.x);
|
|
CGFloat distanceY = MIN(0.0f, [touch locationInView:self].y - _touchLocation.y);
|
|
|
|
if (fabs(distanceX) > fabs(distanceY))
|
|
distanceY = 0.0f;
|
|
else
|
|
distanceX = 0.0f;
|
|
|
|
CGPoint velocity = _lastVelocity;
|
|
id<TGModernConversationInputMicButtonDelegate> delegate = _delegate;
|
|
if (velocity.x < -400.0f || distanceX < -100.0)
|
|
{
|
|
if ([delegate respondsToSelector:@selector(micButtonInteractionCancelled:)])
|
|
[delegate micButtonInteractionCancelled:_lastVelocity];
|
|
}
|
|
else if (velocity.y < -400.0f || distanceY < -60)
|
|
{
|
|
[self _commitLocked];
|
|
}
|
|
else
|
|
{
|
|
[self _commitCompleted];
|
|
}
|
|
}
|
|
|
|
[super endTrackingWithTouch:touch withEvent:event];
|
|
|
|
_yFeedbackOccured = false;
|
|
_yFeedbackOccured = false;
|
|
}
|
|
|
|
- (void)_commitLocked
|
|
{
|
|
id<TGModernConversationInputMicButtonDelegate> delegate = _delegate;
|
|
|
|
bool shouldLock = true;
|
|
if ([delegate respondsToSelector:@selector(micButtonShouldLock)])
|
|
shouldLock = [delegate micButtonShouldLock];
|
|
|
|
if (!shouldLock)
|
|
return;
|
|
|
|
if ([delegate respondsToSelector:@selector(micButtonInteractionLocked)])
|
|
[delegate micButtonInteractionLocked];
|
|
|
|
_locked = true;
|
|
_targetTranslation = 0.0f;
|
|
|
|
[self animateLock];
|
|
}
|
|
|
|
- (void)_commitCompleted
|
|
{
|
|
id<TGModernConversationInputMicButtonDelegate> delegate = _delegate;
|
|
if ([delegate respondsToSelector:@selector(micButtonInteractionCompleted:)])
|
|
[delegate micButtonInteractionCompleted:_lastVelocity];
|
|
}
|
|
|
|
- (void)displayLinkUpdate {
|
|
if (_decoration != NULL) {
|
|
_outerCircleView.image = nil;
|
|
_innerCircleView.image = nil;
|
|
}
|
|
NSTimeInterval t = CACurrentMediaTime();
|
|
|
|
_currentLevel = _currentLevel * 0.9f + _inputLevel * 0.1f;
|
|
|
|
_currentTranslation = MIN(0.0, _currentTranslation * 0.7f + _targetTranslation * 0.3f);
|
|
_cancelTranslation = MIN(0.0, _cancelTranslation * 0.7f + _cancelTargetTranslation * 0.3f);
|
|
|
|
if (t > _animationStartTime) {
|
|
CGFloat outerScale = outerCircleMinScale + _currentLevel * (1.0f - outerCircleMinScale);
|
|
CGAffineTransform translation = CGAffineTransformMakeTranslation(0, _currentTranslation);
|
|
CGAffineTransform transform = CGAffineTransformScale(translation, outerScale, outerScale);
|
|
|
|
_outerCircleView.transform = transform;
|
|
|
|
if (_lockPanelWrapperView.layer.animationKeys.count == 0)
|
|
_lockPanelWrapperView.transform = translation;
|
|
|
|
transform = CGAffineTransformScale(translation, _currentScale, _currentScale);
|
|
transform = CGAffineTransformTranslate(transform, _cancelTranslation, 0);
|
|
|
|
_innerCircleView.transform = transform;
|
|
//_innerIconWrapperView.transform = transform;
|
|
_decoration.transform = transform;
|
|
}
|
|
}
|
|
|
|
- (void)reset {
|
|
_targetTranslation = 0.0;
|
|
[self updateOverlay];
|
|
}
|
|
|
|
- (void)addMicLevel:(CGFloat)level {
|
|
_inputLevel = level;
|
|
[_decoration updateLevel:level];
|
|
}
|
|
|
|
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)__unused gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)__unused otherGestureRecognizer {
|
|
return true;
|
|
}
|
|
|
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
|
|
return [super hitTest:point withEvent:event];
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
@implementation TGModernConversationInputLockView
|
|
|
|
- (instancetype)initWithFrame:(CGRect)frame
|
|
{
|
|
self = [super initWithFrame:CGRectMake(frame.origin.x, frame.origin.y, 40.0f, 40.0f)];
|
|
if (self != nil)
|
|
{
|
|
self.backgroundColor = [UIColor clearColor];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)setLockness:(CGFloat)lockness
|
|
{
|
|
_lockness = lockness;
|
|
[self setNeedsDisplay];
|
|
}
|
|
|
|
- (void)setColor:(UIColor *)color
|
|
{
|
|
_color = color;
|
|
[self setNeedsDisplay];
|
|
}
|
|
|
|
- (void)drawRect:(CGRect)rect
|
|
{
|
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
|
|
CGRect rrect = CGRectMake(rect.size.width / 2.0f - 6.0f, 6.0, 12.0f, 33.0);
|
|
CGFloat radius = 6.0;
|
|
|
|
CGFloat minx = CGRectGetMinX(rrect);
|
|
CGFloat midx = CGRectGetMidX(rrect);
|
|
CGFloat maxx = CGRectGetMaxX(rrect);
|
|
|
|
CGFloat miny = CGRectGetMinY(rrect) + _lockness * 6.0f;
|
|
CGFloat midy = CGRectGetMidY(rrect);
|
|
|
|
UIColor *color = _color ?: UIColorRGB(0x9597a0);
|
|
CGContextSetStrokeColorWithColor(context, color.CGColor);
|
|
|
|
CGFloat lineWidth = 1.5f;
|
|
CGFloat scale = (int)TGScreenScaling();
|
|
if (scale >= 3.0)
|
|
lineWidth = 5.0f / 3.0f;
|
|
|
|
CGContextSetLineWidth(context, lineWidth);
|
|
|
|
CGContextMoveToPoint(context, minx, midy);
|
|
CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
|
|
CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
|
|
CGContextAddLineToPoint(context, maxx, midy + (-6.0f * (1.0f - _lockness)));
|
|
CGContextDrawPath(context, kCGPathStroke);
|
|
|
|
CGContextSetBlendMode(context, kCGBlendModeClear);
|
|
|
|
CGContextSetBlendMode(context, kCGBlendModeNormal);
|
|
|
|
CGContextStrokeEllipseInRect(context, CGRectMake(rect.size.width / 2.0f - 8.0f, rect.size.height - 18.0f, 16.0f, 16.0f));
|
|
|
|
CGContextSetFillColorWithColor(context, color.CGColor);
|
|
CGContextFillEllipseInRect(context, CGRectMake(rect.size.width / 2.0f - 2.0f, rect.size.height - 12.0f, 4.0f, 4.0f));
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
@implementation TGModernConversationInputMicWindow
|
|
|
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
|
{
|
|
UIView *firstResult = [self.subviews.firstObject hitTest:point withEvent:event];
|
|
if ([firstResult isKindOfClass:[UIControl class]])
|
|
return firstResult;
|
|
|
|
if (!self.userInteractionEnabled)
|
|
return nil;
|
|
|
|
UIView *blockingResult = [super hitTest:point withEvent:event];
|
|
|
|
__block bool block = false;
|
|
if (_ignoreNextTouch)
|
|
{
|
|
_ignoreNextTouch = false;
|
|
return blockingResult;
|
|
}
|
|
|
|
NSArray *windows = [[LegacyComponentsGlobals provider] applicationWindows];
|
|
[windows enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(UIWindow *window, __unused NSUInteger index, BOOL *stop)
|
|
{
|
|
if ([window isKindOfClass:[TGModernConversationInputMicWindow class]])
|
|
return;
|
|
|
|
UIView *result = [window hitTest:point withEvent:event];
|
|
if (result.tag == 0xbeef || result.superview.tag == 0xbeef)
|
|
{
|
|
*stop = true;
|
|
return;
|
|
}
|
|
|
|
NSString *stringClass = NSStringFromClass(result.superview.class);
|
|
bool navBarDescendant = stringClass.length > 0 && ([stringClass rangeOfString:@"UINav"].location != NSNotFound || [stringClass rangeOfString:@"AdaptorView"].location != NSNotFound);
|
|
bool shouldBlock = [result isKindOfClass:[UINavigationBar class]] || navBarDescendant || result.tag == -1;
|
|
if (shouldBlock)
|
|
{
|
|
block = true;
|
|
*stop = true;
|
|
}
|
|
}];
|
|
|
|
if (block)
|
|
{
|
|
_ignoreNextTouch = true;
|
|
if (self.requestedLockedAction != nil)
|
|
self.requestedLockedAction();
|
|
|
|
return blockingResult;
|
|
}
|
|
|
|
return nil;
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
@implementation TGModernConversationInputMicPallete
|
|
|
|
+ (instancetype)palleteWithDark:(bool)dark buttonColor:(UIColor *)buttonColor iconColor:(UIColor *)iconColor backgroundColor:(UIColor *)backgroundColor borderColor:(UIColor *)borderColor lockColor:(UIColor *)lockColor textColor:(UIColor *)textColor secondaryTextColor:(UIColor *)secondaryTextColor recordingColor:(UIColor *)recordingColor
|
|
{
|
|
TGModernConversationInputMicPallete *pallete = [[TGModernConversationInputMicPallete alloc] init];
|
|
pallete->_isDark = dark;
|
|
pallete->_buttonColor = buttonColor;
|
|
pallete->_iconColor = iconColor;
|
|
pallete->_backgroundColor = backgroundColor;
|
|
pallete->_borderColor = borderColor;
|
|
pallete->_lockColor = lockColor;
|
|
pallete->_textColor = textColor;
|
|
pallete->_secondaryTextColor = secondaryTextColor;
|
|
pallete->_recordingColor = recordingColor;
|
|
return pallete;
|
|
}
|
|
|
|
@end
|