Merge commit '4195dcf129a898a84a121a05c9b2e354fb19272e'

This commit is contained in:
Ali 2021-07-27 21:47:33 +02:00
commit 188488ffcb
22 changed files with 750 additions and 200 deletions

View File

@ -6567,3 +6567,5 @@ Sorry for the inconvenience.";
"Gallery.SaveToGallery" = "Save to Gallery"; "Gallery.SaveToGallery" = "Save to Gallery";
"Gallery.VideoSaved" = "Video Saved"; "Gallery.VideoSaved" = "Video Saved";
"Gallery.WaitForVideoDownoad" = "Please wait for the video to be fully downloaded."; "Gallery.WaitForVideoDownoad" = "Please wait for the video to be fully downloaded.";
"VoiceChat.VideoParticipantsLimitExceededExtended" = "The voice chat is over %@ members.\nNew participants only have access to audio stream. ";

View File

@ -1,12 +0,0 @@
{
"images" : [
{
"filename" : "ic_cam_flashoff (1).pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -1,12 +0,0 @@
{
"images" : [
{
"filename" : "ic_cam_flashon.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -6,6 +6,12 @@
@end @end
@interface TGCameraSmallFlipButton : TGModernButton
- (void)setHidden:(bool)hidden animated:(bool)animated;
@end
@interface TGCameraCancelButton : TGModernButton @interface TGCameraCancelButton : TGModernButton
- (void)setHidden:(bool)hidden animated:(bool)animated; - (void)setHidden:(bool)hidden animated:(bool)animated;

View File

@ -57,6 +57,7 @@
@property (nonatomic, copy) void(^shutterPressed)(bool fromHardwareButton); @property (nonatomic, copy) void(^shutterPressed)(bool fromHardwareButton);
@property (nonatomic, copy) void(^shutterReleased)(bool fromHardwareButton); @property (nonatomic, copy) void(^shutterReleased)(bool fromHardwareButton);
@property (nonatomic, copy) void(^shutterPanGesture)(UIPanGestureRecognizer *gesture);
@property (nonatomic, copy) void(^cancelPressed)(void); @property (nonatomic, copy) void(^cancelPressed)(void);
@property (nonatomic, copy) void(^donePressed)(void); @property (nonatomic, copy) void(^donePressed)(void);
@property (nonatomic, copy) void(^resultPressed)(NSInteger index); @property (nonatomic, copy) void(^resultPressed)(NSInteger index);
@ -93,6 +94,7 @@
- (void)shutterButtonPressed; - (void)shutterButtonPressed;
- (void)shutterButtonReleased; - (void)shutterButtonReleased;
- (void)shutterButtonPanGesture:(UIPanGestureRecognizer *)gestureRecognizer;
- (void)flipButtonPressed; - (void)flipButtonPressed;
- (void)cancelButtonPressed; - (void)cancelButtonPressed;
- (void)doneButtonPressed; - (void)doneButtonPressed;

View File

@ -2,6 +2,8 @@
@interface TGCameraTimeCodeView : UIView @interface TGCameraTimeCodeView : UIView
@property (nonatomic, assign) UIInterfaceOrientation interfaceOrientation;
@property (nonatomic, copy) NSTimeInterval(^requestedRecordingDuration)(void); @property (nonatomic, copy) NSTimeInterval(^requestedRecordingDuration)(void);
- (void)startRecording; - (void)startRecording;

View File

@ -27,6 +27,8 @@
- (void)setHidden:(bool)hidden animated:(bool)animated; - (void)setHidden:(bool)hidden animated:(bool)animated;
- (void)panGesture:(UIPanGestureRecognizer *)gestureRecognizer;
- (instancetype)initWithFrame:(CGRect)frame hasUltrawideCamera:(bool)hasUltrawideCamera hasTelephotoCamera:(bool)hasTelephotoCamera minZoomLevel:(CGFloat)minZoomLevel maxZoomLevel:(CGFloat)maxZoomLevel; - (instancetype)initWithFrame:(CGRect)frame hasUltrawideCamera:(bool)hasUltrawideCamera hasTelephotoCamera:(bool)hasTelephotoCamera minZoomLevel:(CGFloat)minZoomLevel maxZoomLevel:(CGFloat)maxZoomLevel;
@end @end
@ -34,7 +36,12 @@
@interface TGCameraZoomWheelView : UIView @interface TGCameraZoomWheelView : UIView
@property (nonatomic, assign) UIInterfaceOrientation interfaceOrientation;
@property (copy, nonatomic) void(^panGesture)(UIPanGestureRecognizer *gestureRecognizer);
@property (nonatomic, assign) CGFloat zoomLevel; @property (nonatomic, assign) CGFloat zoomLevel;
- (void)setZoomLevel:(CGFloat)zoomLevel panning:(bool)panning;
- (void)setHidden:(bool)hidden animated:(bool)animated; - (void)setHidden:(bool)hidden animated:(bool)animated;

View File

@ -75,6 +75,10 @@ const NSInteger PGCameraFrameRate = 30;
_preferredCameraPosition = position; _preferredCameraPosition = position;
_currentAudioSession = [[SMetaDisposable alloc] init]; _currentAudioSession = [[SMetaDisposable alloc] init];
self.automaticallyConfiguresApplicationAudioSession = false;
self.usesApplicationAudioSession = true;
} }
return self; return self;
} }
@ -490,11 +494,19 @@ const NSInteger PGCameraFrameRate = 30;
} }
} else if (marks.count == 1) { } else if (marks.count == 1) {
CGFloat mark = [marks.firstObject floatValue]; CGFloat mark = [marks.firstObject floatValue];
if ([self hasTelephotoCamera]) {
if (backingLevel < mark) { if (backingLevel < mark) {
realLevel = 1.0 + 1.0 * (backingLevel - 1.0) / (mark - 1.0); realLevel = 1.0 + 1.0 * (backingLevel - 1.0) / (mark - 1.0);
} else { } else {
realLevel = 2.0 + 6.0 * (backingLevel - mark) / (self.maxZoomLevel - mark); realLevel = 2.0 + 6.0 * (backingLevel - mark) / (self.maxZoomLevel - mark);
} }
} else if ([self hasUltrawideCamera]) {
if (backingLevel < mark) {
realLevel = 0.5 + 0.5 * (backingLevel - 1.0) / (mark - 1.0);
} else {
realLevel = 1.0 + 7.0 * (backingLevel - mark) / (self.maxZoomLevel - mark);
}
}
} }
return realLevel; return realLevel;
@ -504,11 +516,9 @@ const NSInteger PGCameraFrameRate = 30;
} }
- (CGFloat)minZoomLevel { - (CGFloat)minZoomLevel {
if (iosMajorVersion() >= 13.0) { if (self.hasUltrawideCamera) {
if (self.videoDevice.isVirtualDevice && self.videoDevice.constituentDevices.firstObject.deviceType == AVCaptureDeviceTypeBuiltInUltraWideCamera) {
return 0.5; return 0.5;
} }
}
return 1.0; return 1.0;
} }
@ -537,7 +547,7 @@ const NSInteger PGCameraFrameRate = 30;
return; return;
CGFloat level = zoomLevel; CGFloat level = zoomLevel;
CGFloat backingLevel = 1.0; CGFloat backingLevel = zoomLevel;
if (iosMajorVersion() >= 13.0 && device.isVirtualDevice) { if (iosMajorVersion() >= 13.0 && device.isVirtualDevice) {
NSArray *marks = device.virtualDeviceSwitchOverVideoZoomFactors; NSArray *marks = device.virtualDeviceSwitchOverVideoZoomFactors;
if (marks.count == 2) { if (marks.count == 2) {
@ -553,11 +563,20 @@ const NSInteger PGCameraFrameRate = 30;
} }
} else if (marks.count == 1) { } else if (marks.count == 1) {
CGFloat mark = [marks.firstObject floatValue]; CGFloat mark = [marks.firstObject floatValue];
if ([self hasTelephotoCamera]) {
if (zoomLevel < 2.0) { if (zoomLevel < 2.0) {
backingLevel = 1.0 + ((level - 1.0) / 1.0) * (mark - 1.0); backingLevel = 1.0 + ((level - 1.0) / 1.0) * (mark - 1.0);
} else { } else {
backingLevel = mark + ((level - 2.0) / 6.0) * (self.maxZoomLevel - mark); backingLevel = mark + ((level - 2.0) / 6.0) * (self.maxZoomLevel - mark);
} }
} else if ([self hasUltrawideCamera]) {
if (level < 1.0) {
level = MAX(0.5, level);
backingLevel = 1.0 + ((level - 0.5) / 0.5) * (mark - 1.0);
} else {
backingLevel = mark + ((level - 1.0) / 7.0) * (self.maxZoomLevel - mark);
}
}
} }
} }
CGFloat finalLevel = MAX(1.0, MIN([strongSelf maxZoomLevel], backingLevel)); CGFloat finalLevel = MAX(1.0, MIN([strongSelf maxZoomLevel], backingLevel));
@ -830,6 +849,9 @@ const NSInteger PGCameraFrameRate = 30;
if (device == nil) { if (device == nil) {
device = [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInDualCamera mediaType:AVMediaTypeVideo position:position]; device = [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInDualCamera mediaType:AVMediaTypeVideo position:position];
} }
if (device == nil) {
device = [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInDualWideCamera mediaType:AVMediaTypeVideo position:position];
}
if (device != nil) { if (device != nil) {
return device; return device;
} }

View File

@ -128,7 +128,6 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
NSTimer *_switchToVideoTimer; NSTimer *_switchToVideoTimer;
NSTimer *_startRecordingTimer; NSTimer *_startRecordingTimer;
bool _recordingByShutterHold;
bool _stopRecordingOnRelease; bool _stopRecordingOnRelease;
bool _shownMicrophoneAlert; bool _shownMicrophoneAlert;
@ -419,6 +418,14 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
[strongSelf shutterReleased]; [strongSelf shutterReleased];
}; };
_interfaceView.shutterPanGesture = ^(UIPanGestureRecognizer *gesture) {
__strong TGCameraController *strongSelf = weakSelf;
if (strongSelf == nil)
return;
[strongSelf handleRamp:gesture];
};
_interfaceView.cancelPressed = ^ _interfaceView.cancelPressed = ^
{ {
__strong TGCameraController *strongSelf = weakSelf; __strong TGCameraController *strongSelf = weakSelf;
@ -455,7 +462,9 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
} }
[_autorotationCorrectionView addSubview:_interfaceView]; [_autorotationCorrectionView addSubview:_interfaceView];
if ((int)self.view.frame.size.width > 320 || [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
[_autorotationCorrectionView addSubview:_cornersView]; [_autorotationCorrectionView addSubview:_cornersView];
}
_photoSwipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)]; _photoSwipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)];
_photoSwipeGestureRecognizer.delegate = self; _photoSwipeGestureRecognizer.delegate = self;
@ -594,6 +603,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
TGDispatchOnMainThread(^ TGDispatchOnMainThread(^
{ {
[strongSelf->_previewView endTransitionAnimated:true]; [strongSelf->_previewView endTransitionAnimated:true];
[strongSelf->_interfaceView setZoomLevel:1.0f displayNeeded:false];
if (!strongSelf->_dismissing) if (!strongSelf->_dismissing)
{ {
@ -803,7 +813,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
{ {
[strongSelf->_previewView beginTransitionWithSnapshotImage:image animated:false]; [strongSelf->_previewView beginTransitionWithSnapshotImage:image animated:false];
TGDispatchAfter(0.05, dispatch_get_main_queue(), ^{ TGDispatchAfter(0.15, dispatch_get_main_queue(), ^{
[strongSelf->_previewView endTransitionAnimated:true]; [strongSelf->_previewView endTransitionAnimated:true];
strongSelf->_crossfadingForZoom = false; strongSelf->_crossfadingForZoom = false;
}); });
@ -1150,8 +1160,12 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
{ {
_stopRecordingOnRelease = false; _stopRecordingOnRelease = false;
_camera.disabled = true;
[_camera stopVideoRecording]; [_camera stopVideoRecording];
TGDispatchAfter(0.3, dispatch_get_main_queue(), ^{
[_camera setZoomLevel:1.0];
[_interfaceView setZoomLevel:1.0 displayNeeded:false];
_camera.disabled = true;
});
[_buttonHandler ignoreEventsFor:1.0f andDisable:[self willPresentResultController]]; [_buttonHandler ignoreEventsFor:1.0f andDisable:[self willPresentResultController]];
} }
@ -2612,6 +2626,37 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
} }
} }
- (void)handleRamp:(UIPanGestureRecognizer *)gestureRecognizer
{
if (!_stopRecordingOnRelease) {
[gestureRecognizer setTranslation:CGPointZero inView:self.view];
return;
}
switch (gestureRecognizer.state)
{
case UIGestureRecognizerStateChanged:
{
CGPoint translation = [gestureRecognizer translationInView:self.view];
CGFloat value = 1.0;
if (translation.y < 0.0) {
value = MIN(8.0, value + ABS(translation.y) / 60.0);
}
[_camera setZoomLevel:value];
[_interfaceView setZoomLevel:value displayNeeded:true];
}
break;
case UIGestureRecognizerStateEnded:
{
[self shutterReleased];
}
break;
default:
break;
}
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{ {
if (gestureRecognizer == _panGestureRecognizer) if (gestureRecognizer == _panGestureRecognizer)
@ -2659,6 +2704,8 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
default: default:
{ {
if (widescreenWidth == 926.0f)
return CGRectMake(0, 154, screenSize.width, screenSize.height - 154 - 249);
if (widescreenWidth == 896.0f) if (widescreenWidth == 896.0f)
return CGRectMake(0, 121, screenSize.width, screenSize.height - 121 - 223); return CGRectMake(0, 121, screenSize.width, screenSize.height - 121 - 223);
else if (widescreenWidth == 844.0f) else if (widescreenWidth == 844.0f)

View File

@ -27,6 +27,8 @@ const CGFloat TGCameraFlashControlHeight = 44.0f;
self = [super initWithFrame:frame]; self = [super initWithFrame:frame];
if (self != nil) { if (self != nil) {
self.contentMode = UIViewContentModeRedraw; self.contentMode = UIViewContentModeRedraw;
self.opaque = false;
self.backgroundColor = [UIColor clearColor];
} }
return self; return self;
} }
@ -102,7 +104,8 @@ const CGFloat TGCameraFlashControlHeight = 44.0f;
CGPathRelease(strokedPath); CGPathRelease(strokedPath);
CGPathRelease(path); CGPathRelease(path);
CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor); CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextSetStrokeColorWithColor(context, [UIColor clearColor].CGColor);
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextDrawPath(context, kCGPathFillStroke); CGContextDrawPath(context, kCGPathFillStroke);
} }

View File

@ -64,6 +64,53 @@
@end @end
@implementation TGCameraSmallFlipButton
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self != nil)
{
self.exclusiveTouch = true;
UIImage *image = TGTintedImage(TGComponentsImageNamed(@"CameraFlipButton"), [UIColor whiteColor]);
[self setImage:image forState:UIControlStateNormal];
}
return self;
}
- (void)setHidden:(BOOL)hidden
{
self.alpha = hidden ? 0.0f : 1.0f;
super.hidden = hidden;
}
- (void)setHidden:(bool)hidden animated:(bool)animated
{
if (animated)
{
super.hidden = false;
self.userInteractionEnabled = false;
[UIView animateWithDuration:0.25f animations:^
{
self.alpha = hidden ? 0.0f : 1.0f;
} completion:^(BOOL finished)
{
self.userInteractionEnabled = true;
if (finished)
self.hidden = hidden;
}];
}
else
{
self.alpha = hidden ? 0.0f : 1.0f;
super.hidden = hidden;
}
}
@end
@implementation TGCameraCancelButton @implementation TGCameraCancelButton

View File

@ -26,7 +26,7 @@ static NSString *TGCameraEncodeText(NSString *string, int key)
+ (UIColor *)accentColor + (UIColor *)accentColor
{ {
return UIColorRGB(0xffd60a); return UIColorRGB(0xf8d74a);
} }
+ (UIColor *)redColor + (UIColor *)redColor

View File

@ -64,7 +64,8 @@
UIView *_videoLandscapePanelView; UIView *_videoLandscapePanelView;
TGCameraFlashControl *_flashControl; TGCameraFlashControl *_flashControl;
TGCameraFlashActiveView *_flashActiveView;
TGCameraSmallFlipButton *_topFlipButton;
bool _hasResults; bool _hasResults;
@ -137,7 +138,7 @@
_topPanelOffset = 33.0f; _topPanelOffset = 33.0f;
_topPanelHeight = 44.0f; _topPanelHeight = 44.0f;
_bottomPanelOffset = 63.0f; _bottomPanelOffset = 63.0f;
_bottomPanelHeight = 123.0f; _bottomPanelHeight = 128.0f;
_modeControlOffset = 3.0f; _modeControlOffset = 3.0f;
_modeControlHeight = 40.0f; _modeControlHeight = 40.0f;
_counterOffset = 7.0f; _counterOffset = 7.0f;
@ -198,6 +199,62 @@
_topPanelBackgroundView.backgroundColor = [TGCameraInterfaceAssets transparentPanelBackgroundColor]; _topPanelBackgroundView.backgroundColor = [TGCameraInterfaceAssets transparentPanelBackgroundColor];
[_topPanelView addSubview:_topPanelBackgroundView]; [_topPanelView addSubview:_topPanelBackgroundView];
_zoomModeView = [[TGCameraZoomModeView alloc] initWithFrame:CGRectMake(floor((frame.size.width - 129.0) / 2.0), frame.size.height - _bottomPanelHeight - _bottomPanelOffset - 18 - 43, 129, 43) hasUltrawideCamera:hasUltrawideCamera hasTelephotoCamera:hasTelephotoCamera minZoomLevel:hasUltrawideCamera ? 0.5 : 1.0 maxZoomLevel:8.0];
_zoomModeView.zoomChanged = ^(CGFloat zoomLevel, bool done, bool animated) {
__strong TGCameraMainPhoneView *strongSelf = weakSelf;
if (strongSelf == nil)
return;
if (done) {
[strongSelf->_zoomWheelView setZoomLevel:zoomLevel];
[strongSelf->_zoomModeView setZoomLevel:zoomLevel animated:false];
if (!strongSelf->_zoomWheelView.isHidden) {
strongSelf->_dismissingWheel = true;
TGDispatchAfter(0.6, dispatch_get_main_queue(), ^{
if (strongSelf->_dismissingWheel) {
[strongSelf->_zoomModeView setHidden:false animated:true];
[strongSelf->_zoomWheelView setHidden:true animated:true];
}
});
}
} else {
strongSelf->_dismissingWheel = false;
[strongSelf->_zoomWheelView setZoomLevel:zoomLevel panning:true];
[strongSelf->_zoomModeView setHidden:true animated:true];
[strongSelf->_zoomWheelView setHidden:false animated:true];
}
if (strongSelf.zoomChanged != nil)
strongSelf.zoomChanged(zoomLevel, animated);
};
[_zoomModeView setZoomLevel:1.0];
if (hasTelephotoCamera || hasUltrawideCamera) {
[self addSubview:_zoomModeView];
}
_zoomWheelView = [[TGCameraZoomWheelView alloc] initWithFrame:CGRectMake(0.0, frame.size.height - _bottomPanelHeight - _bottomPanelOffset - 132, frame.size.width, 132) hasUltrawideCamera:hasUltrawideCamera hasTelephotoCamera:hasTelephotoCamera];
[_zoomWheelView setHidden:true animated:false];
[_zoomWheelView setZoomLevel:1.0];
_zoomWheelView.panGesture = ^(UIPanGestureRecognizer *gestureRecognizer) {
__strong TGCameraMainPhoneView *strongSelf = weakSelf;
if (strongSelf == nil)
return;
[strongSelf->_zoomModeView panGesture:gestureRecognizer];
};
if (hasTelephotoCamera || hasUltrawideCamera) {
[self addSubview:_zoomWheelView];
}
_zoomView = [[TGCameraZoomView alloc] initWithFrame:CGRectMake(10, frame.size.height - _bottomPanelHeight - _bottomPanelOffset - 18, frame.size.width - 20, 1.5f)];
_zoomView.activityChanged = ^(bool active)
{
};
if (!hasTelephotoCamera && !hasUltrawideCamera) {
[self addSubview:_zoomView];
}
_bottomPanelView = [[UIView alloc] init]; _bottomPanelView = [[UIView alloc] init];
[self addSubview:_bottomPanelView]; [self addSubview:_bottomPanelView];
@ -224,9 +281,11 @@
[_doneButton addTarget:self action:@selector(doneButtonPressed) forControlEvents:UIControlEventTouchUpInside]; [_doneButton addTarget:self action:@selector(doneButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[_bottomPanelView addSubview:_doneButton]; [_bottomPanelView addSubview:_doneButton];
UIPanGestureRecognizer *shutterPanGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(shutterButtonPanGesture:)];
_shutterButton = [[TGCameraShutterButton alloc] initWithFrame:CGRectMake((frame.size.width - shutterButtonWidth) / 2, 10, shutterButtonWidth, shutterButtonWidth)]; _shutterButton = [[TGCameraShutterButton alloc] initWithFrame:CGRectMake((frame.size.width - shutterButtonWidth) / 2, 10, shutterButtonWidth, shutterButtonWidth)];
[_shutterButton addTarget:self action:@selector(shutterButtonReleased) forControlEvents:UIControlEventTouchUpInside]; [_shutterButton addTarget:self action:@selector(shutterButtonReleased) forControlEvents:UIControlEventTouchUpInside];
[_shutterButton addTarget:self action:@selector(shutterButtonPressed) forControlEvents:UIControlEventTouchDown]; [_shutterButton addTarget:self action:@selector(shutterButtonPressed) forControlEvents:UIControlEventTouchDown];
[_shutterButton addGestureRecognizer:shutterPanGestureRecognizer];
[_bottomPanelView addSubview:_shutterButton]; [_bottomPanelView addSubview:_shutterButton];
_modeControl = [[TGCameraModeControl alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, _modeControlHeight) avatar:avatar]; _modeControl = [[TGCameraModeControl alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, _modeControlHeight) avatar:avatar];
@ -239,6 +298,11 @@
_flashControl = [[TGCameraFlashControl alloc] initWithFrame:CGRectMake(3.0, 0, TGCameraFlashControlHeight, TGCameraFlashControlHeight)]; _flashControl = [[TGCameraFlashControl alloc] initWithFrame:CGRectMake(3.0, 0, TGCameraFlashControlHeight, TGCameraFlashControlHeight)];
[_topPanelView addSubview:_flashControl]; [_topPanelView addSubview:_flashControl];
_topFlipButton = [[TGCameraSmallFlipButton alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
_topFlipButton.hidden = true;
[_topFlipButton addTarget:self action:@selector(flipButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[_topPanelView addSubview:_topFlipButton];
_timecodeView = [[TGCameraTimeCodeView alloc] initWithFrame:CGRectMake((frame.size.width - 120) / 2, 12, 120, 28)]; _timecodeView = [[TGCameraTimeCodeView alloc] initWithFrame:CGRectMake((frame.size.width - 120) / 2, 12, 120, 28)];
_timecodeView.alpha = 0.0; _timecodeView.alpha = 0.0;
_timecodeView.requestedRecordingDuration = ^NSTimeInterval _timecodeView.requestedRecordingDuration = ^NSTimeInterval
@ -254,54 +318,13 @@
_videoLandscapePanelView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 274, 44)]; _videoLandscapePanelView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 274, 44)];
_videoLandscapePanelView.alpha = 0.0f; _videoLandscapePanelView.alpha = 0.0f;
_videoLandscapePanelView.backgroundColor = [TGCameraInterfaceAssets transparentPanelBackgroundColor];
_videoLandscapePanelView.hidden = true; _videoLandscapePanelView.hidden = true;
_videoLandscapePanelView.layer.cornerRadius = 3.5f;
[self addSubview:_videoLandscapePanelView]; [self addSubview:_videoLandscapePanelView];
_toastView = [[TGCameraToastView alloc] initWithFrame:CGRectMake(0, frame.size.height - _bottomPanelHeight - 42, frame.size.width, 32)]; _toastView = [[TGCameraToastView alloc] initWithFrame:CGRectMake(0, frame.size.height - _bottomPanelHeight - 42, frame.size.width, 32)];
_toastView.userInteractionEnabled = false; _toastView.userInteractionEnabled = false;
[self addSubview:_toastView]; [self addSubview:_toastView];
_zoomModeView = [[TGCameraZoomModeView alloc] initWithFrame:CGRectMake(floor((frame.size.width - 129.0) / 2.0), frame.size.height - _bottomPanelHeight - _bottomPanelOffset - 18 - 43, 129, 43) hasUltrawideCamera:hasUltrawideCamera hasTelephotoCamera:hasTelephotoCamera minZoomLevel:hasUltrawideCamera ? 0.5 : 1.0 maxZoomLevel:8.0];
_zoomModeView.zoomChanged = ^(CGFloat zoomLevel, bool done, bool animated) {
__strong TGCameraMainPhoneView *strongSelf = weakSelf;
if (strongSelf == nil)
return;
if (done) {
[strongSelf->_zoomWheelView setZoomLevel:zoomLevel];
[strongSelf->_zoomModeView setZoomLevel:zoomLevel animated:false];
if (!strongSelf->_zoomWheelView.isHidden) {
strongSelf->_dismissingWheel = true;
TGDispatchAfter(0.6, dispatch_get_main_queue(), ^{
if (strongSelf->_dismissingWheel) {
[strongSelf->_zoomModeView setHidden:false animated:true];
// [strongSelf->_zoomWheelView setHidden:true animated:true];
}
});
}
} else {
strongSelf->_dismissingWheel = false;
[strongSelf->_zoomWheelView setZoomLevel:zoomLevel];
[strongSelf->_zoomModeView setHidden:true animated:true];
// [strongSelf->_zoomWheelView setHidden:false animated:true];
}
if (strongSelf.zoomChanged != nil)
strongSelf.zoomChanged(zoomLevel, animated);
};
[_zoomModeView setZoomLevel:1.0];
[self addSubview:_zoomModeView];
_zoomWheelView = [[TGCameraZoomWheelView alloc] initWithFrame:CGRectMake(0.0, frame.size.height - _bottomPanelHeight - _bottomPanelOffset - 132, frame.size.width, 132) hasUltrawideCamera:hasUltrawideCamera hasTelephotoCamera:hasTelephotoCamera];
[_zoomWheelView setHidden:true animated:false];
[_zoomWheelView setZoomLevel:1.0];
_zoomWheelView.userInteractionEnabled = false;
[self addSubview:_zoomWheelView];
_flashControl.modeChanged = ^(PGCameraFlashMode mode) _flashControl.modeChanged = ^(PGCameraFlashMode mode)
{ {
__strong TGCameraMainPhoneView *strongSelf = weakSelf; __strong TGCameraMainPhoneView *strongSelf = weakSelf;
@ -379,13 +402,15 @@
if (results.count == 0) if (results.count == 0)
{ {
_hasResults = false; _hasResults = false;
_topFlipButton.hidden = true;
_flipButton.hidden = false; _flipButton.hidden = false;
_doneButton.hidden = true; _doneButton.hidden = true;
} }
else else
{ {
_hasResults = true; _hasResults = true;
_flipButton.hidden = false; _topFlipButton.hidden = _modeControl.cameraMode == PGCameraModePhotoScan;
_flipButton.hidden = true;
_doneButton.hidden = false; _doneButton.hidden = false;
if (_modeControl.cameraMode == PGCameraModePhotoScan) { if (_modeControl.cameraMode == PGCameraModePhotoScan) {
_modeControl.hidden = true; _modeControl.hidden = true;
@ -444,7 +469,12 @@
{ {
UIView *view = [super hitTest:point withEvent:event]; UIView *view = [super hitTest:point withEvent:event];
if ([view isDescendantOfView:_topPanelView] || [view isDescendantOfView:_bottomPanelView] || [view isDescendantOfView:_videoLandscapePanelView] || [view isDescendantOfView:_tooltipContainerView] || [view isDescendantOfView:_selectedPhotosView] || [view isDescendantOfView:_zoomModeView] || view == _zoomModeView) if (!_zoomModeView.isHidden && CGRectContainsPoint(_zoomModeView.frame, point)) {
CGPoint zoomPoint = [self convertPoint:point toView:_zoomModeView];
return [_zoomModeView hitTest:zoomPoint withEvent:event];
}
if ([view isDescendantOfView:_topPanelView] || [view isDescendantOfView:_bottomPanelView] || [view isDescendantOfView:_videoLandscapePanelView] || [view isDescendantOfView:_tooltipContainerView] || [view isDescendantOfView:_selectedPhotosView] || [view isDescendantOfView:_zoomModeView] || view == _zoomModeView || (view == _zoomWheelView && !_zoomWheelView.isHidden))
return view; return view;
return nil; return nil;
@ -561,6 +591,8 @@
{ {
bool hasDoneButton = _hasResults; bool hasDoneButton = _hasResults;
_zoomWheelView.clipsToBounds = !hidden;
if (animated) if (animated)
{ {
if (!hidden) if (!hidden)
@ -568,10 +600,16 @@
_modeControl.hidden = false; _modeControl.hidden = false;
_cancelButton.hidden = false; _cancelButton.hidden = false;
_flashControl.hidden = false; _flashControl.hidden = false;
_flipButton.hidden = false; _flipButton.hidden = hasDoneButton;
_topFlipButton.hidden = !hasDoneButton;
_bottomPanelBackgroundView.hidden = false; _bottomPanelBackgroundView.hidden = false;
} }
[UIView animateWithDuration:0.2 delay:0.0 options:7 << 16 animations:^{
CGFloat offset = hidden ? 19 : 18 + 43;
_zoomModeView.frame = CGRectMake(floor((self.bounds.size.width - 129.0) / 2.0), self.bounds.size.height - _bottomPanelHeight - _bottomPanelOffset - offset, 129, 43);
} completion:nil];
[UIView animateWithDuration:0.25 animations:^ [UIView animateWithDuration:0.25 animations:^
{ {
CGFloat alpha = hidden ? 0.0f : 1.0f; CGFloat alpha = hidden ? 0.0f : 1.0f;
@ -579,6 +617,7 @@
_cancelButton.alpha = alpha; _cancelButton.alpha = alpha;
_flashControl.alpha = alpha; _flashControl.alpha = alpha;
_flipButton.alpha = alpha; _flipButton.alpha = alpha;
_topFlipButton.alpha = alpha;
_bottomPanelBackgroundView.alpha = alpha; _bottomPanelBackgroundView.alpha = alpha;
if (hasDoneButton) if (hasDoneButton)
@ -590,7 +629,8 @@
_modeControl.hidden = hidden; _modeControl.hidden = hidden;
_cancelButton.hidden = hidden; _cancelButton.hidden = hidden;
_flashControl.hidden = hidden; _flashControl.hidden = hidden;
_flipButton.hidden = hidden; _flipButton.hidden = hidden || hasDoneButton;
_topFlipButton.hidden = hidden || !hasDoneButton;
_bottomPanelBackgroundView.hidden = hidden; _bottomPanelBackgroundView.hidden = hidden;
if (hasDoneButton) if (hasDoneButton)
@ -609,11 +649,16 @@
_cancelButton.alpha = alpha; _cancelButton.alpha = alpha;
_flashControl.hidden = hidden; _flashControl.hidden = hidden;
_flashControl.alpha = alpha; _flashControl.alpha = alpha;
_flipButton.hidden = hidden; _flipButton.hidden = hidden || hasDoneButton;
_flipButton.alpha = alpha; _flipButton.alpha = alpha;
_topFlipButton.hidden = hidden || !hasDoneButton;
_topFlipButton.alpha = alpha;
_bottomPanelBackgroundView.hidden = hidden; _bottomPanelBackgroundView.hidden = hidden;
_bottomPanelBackgroundView.alpha = alpha; _bottomPanelBackgroundView.alpha = alpha;
CGFloat offset = hidden ? 19 : 18 + 43;
_zoomModeView.frame = CGRectMake(floor((self.bounds.size.width - 129.0) / 2.0), self.bounds.size.height - _bottomPanelHeight - _bottomPanelOffset - offset, 129, 43);
if (hasDoneButton) if (hasDoneButton)
{ {
_doneButton.hidden = hidden; _doneButton.hidden = hidden;
@ -642,13 +687,15 @@
{ {
if (_modeControl.cameraMode == PGCameraModeVideo) if (_modeControl.cameraMode == PGCameraModeVideo)
{ {
_topPanelView.alpha = 0.0f;
_videoLandscapePanelView.alpha = 0.0f; _videoLandscapePanelView.alpha = 0.0f;
} }
_flipButton.transform = CGAffineTransformMakeRotation(TGRotationForInterfaceOrientation(orientation)); _flipButton.transform = CGAffineTransformMakeRotation(TGRotationForInterfaceOrientation(orientation));
_flashControl.transform = CGAffineTransformMakeRotation(TGRotationForInterfaceOrientation(orientation)); _flashControl.transform = CGAffineTransformMakeRotation(TGRotationForInterfaceOrientation(orientation));
_zoomModeView.interfaceOrientation = orientation; _zoomModeView.interfaceOrientation = orientation;
_timecodeView.interfaceOrientation = orientation;
_zoomWheelView.interfaceOrientation = orientation;
_topFlipButton.transform = CGAffineTransformMakeRotation(TGRotationForInterfaceOrientation(orientation));
} completion:^(__unused BOOL finished) } completion:^(__unused BOOL finished)
{ {
if (_modeControl.cameraMode == PGCameraModeVideo) if (_modeControl.cameraMode == PGCameraModeVideo)
@ -669,8 +716,6 @@
{ {
if (UIInterfaceOrientationIsLandscape(orientation)) if (UIInterfaceOrientationIsLandscape(orientation))
_videoLandscapePanelView.alpha = 1.0f; _videoLandscapePanelView.alpha = 1.0f;
else
_topPanelView.alpha = 1.0f;
} }
} completion:nil]; } completion:nil];
}]; }];
@ -680,6 +725,9 @@
_flipButton.transform = CGAffineTransformMakeRotation(TGRotationForInterfaceOrientation(orientation)); _flipButton.transform = CGAffineTransformMakeRotation(TGRotationForInterfaceOrientation(orientation));
_flashControl.transform = CGAffineTransformMakeRotation(TGRotationForInterfaceOrientation(orientation)); _flashControl.transform = CGAffineTransformMakeRotation(TGRotationForInterfaceOrientation(orientation));
_zoomModeView.interfaceOrientation = orientation; _zoomModeView.interfaceOrientation = orientation;
_timecodeView.interfaceOrientation = orientation;
_zoomWheelView.interfaceOrientation = orientation;
_topFlipButton.transform = CGAffineTransformMakeRotation(TGRotationForInterfaceOrientation(orientation));
[self _layoutTopPanelSubviewsForInterfaceOrientation:orientation]; [self _layoutTopPanelSubviewsForInterfaceOrientation:orientation];
} }
@ -694,7 +742,6 @@
case UIInterfaceOrientationLandscapeLeft: case UIInterfaceOrientationLandscapeLeft:
{ {
_videoLandscapePanelView.hidden = false; _videoLandscapePanelView.hidden = false;
_topPanelView.hidden = true;
_videoLandscapePanelView.transform = transform; _videoLandscapePanelView.transform = transform;
_videoLandscapePanelView.frame = CGRectMake(3, (self.frame.size.height - _videoLandscapePanelView.frame.size.height) / 2, _videoLandscapePanelView.frame.size.width, _videoLandscapePanelView.frame.size.height); _videoLandscapePanelView.frame = CGRectMake(3, (self.frame.size.height - _videoLandscapePanelView.frame.size.height) / 2, _videoLandscapePanelView.frame.size.width, _videoLandscapePanelView.frame.size.height);
@ -703,7 +750,6 @@
case UIInterfaceOrientationLandscapeRight: case UIInterfaceOrientationLandscapeRight:
{ {
_videoLandscapePanelView.hidden = false; _videoLandscapePanelView.hidden = false;
_topPanelView.hidden = true;
_videoLandscapePanelView.transform = transform; _videoLandscapePanelView.transform = transform;
_videoLandscapePanelView.frame = CGRectMake(self.frame.size.width - _videoLandscapePanelView.frame.size.width - 3, (self.frame.size.height - _videoLandscapePanelView.frame.size.height) / 2, _videoLandscapePanelView.frame.size.width, _videoLandscapePanelView.frame.size.height); _videoLandscapePanelView.frame = CGRectMake(self.frame.size.width - _videoLandscapePanelView.frame.size.width - 3, (self.frame.size.height - _videoLandscapePanelView.frame.size.height) / 2, _videoLandscapePanelView.frame.size.width, _videoLandscapePanelView.frame.size.height);
@ -713,20 +759,18 @@
case UIInterfaceOrientationPortraitUpsideDown: case UIInterfaceOrientationPortraitUpsideDown:
{ {
_videoLandscapePanelView.hidden = true; _videoLandscapePanelView.hidden = true;
_topPanelView.hidden = false;
_topPanelView.transform = transform; _topPanelView.transform = transform;
_topPanelView.frame = CGRectMake(0, 0, _topPanelView.frame.size.width, _topPanelView.frame.size.height); _topPanelView.frame = CGRectMake(0, _topPanelOffset, _topPanelView.frame.size.width, _topPanelView.frame.size.height);
} }
break; break;
default: default:
{ {
_videoLandscapePanelView.hidden = true; _videoLandscapePanelView.hidden = true;
_topPanelView.hidden = false;
_topPanelView.transform = transform; _topPanelView.transform = transform;
_topPanelView.frame = CGRectMake(0, 0, _topPanelView.frame.size.width, _topPanelView.frame.size.height); _topPanelView.frame = CGRectMake(0, _topPanelOffset, _topPanelView.frame.size.width, _topPanelView.frame.size.height);
} }
break; break;
} }
@ -744,7 +788,7 @@
- (void)_layoutTopPanelSubviewsForInterfaceOrientation:(UIInterfaceOrientation)orientation - (void)_layoutTopPanelSubviewsForInterfaceOrientation:(UIInterfaceOrientation)orientation
{ {
UIView *superview = _flashControl.superview; UIView *superview = _timecodeView.superview;
CGSize superviewSize = superview.frame.size; CGSize superviewSize = superview.frame.size;
if (superview == _videoLandscapePanelView && superviewSize.width < superviewSize.height) if (superview == _videoLandscapePanelView && superviewSize.width < superviewSize.height)
@ -777,6 +821,8 @@
_flipButton.frame = CGRectMake(self.frame.size.width - _flipButton.frame.size.width - 20.0f, round(_shutterButton.center.y - _flipButton.frame.size.height / 2.0f), _flipButton.frame.size.width, _flipButton.frame.size.height); _flipButton.frame = CGRectMake(self.frame.size.width - _flipButton.frame.size.width - 20.0f, round(_shutterButton.center.y - _flipButton.frame.size.height / 2.0f), _flipButton.frame.size.width, _flipButton.frame.size.height);
_topFlipButton.frame = CGRectMake(self.frame.size.width - _topFlipButton.frame.size.width - 4.0f, 0.0f, _topFlipButton.frame.size.width, _topFlipButton.frame.size.height);
_toastView.frame = CGRectMake(0, self.frame.size.height - _bottomPanelHeight - _bottomPanelOffset - 32 - 16, self.frame.size.width, 32); _toastView.frame = CGRectMake(0, self.frame.size.height - _bottomPanelHeight - _bottomPanelOffset - 32 - 16, self.frame.size.width, 32);
CGFloat photosViewSize = TGPhotoThumbnailSizeForCurrentScreen().height + 4 * 2; CGFloat photosViewSize = TGPhotoThumbnailSizeForCurrentScreen().height + 4 * 2;

View File

@ -100,7 +100,7 @@ const CGFloat TGCameraTabletPanelViewWidth = 102.0f;
}; };
[_panelView addSubview:_timecodeView]; [_panelView addSubview:_timecodeView];
_flipButton = [[TGCameraFlipButton alloc] initWithFrame:CGRectMake(0, 0, 44, 44)]; _flipButton = [[TGCameraFlipButton alloc] initWithFrame:CGRectMake(0, 20, 44, 44)];
[_flipButton addTarget:self action:@selector(flipButtonPressed) forControlEvents:UIControlEventTouchUpInside]; [_flipButton addTarget:self action:@selector(flipButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[_panelView addSubview:_flipButton]; [_panelView addSubview:_flipButton];
@ -277,6 +277,10 @@ const CGFloat TGCameraTabletPanelViewWidth = 102.0f;
(_panelView.frame.size.height - _shutterButton.frame.size.height) / 2, (_panelView.frame.size.height - _shutterButton.frame.size.height) / 2,
_shutterButton.frame.size.width, _shutterButton.frame.size.height); _shutterButton.frame.size.width, _shutterButton.frame.size.height);
_flipButton.frame = CGRectMake((_panelView.frame.size.width - _shutterButton.frame.size.width) / 2,
_shutterButton.frame.origin.y + _shutterButton.frame.size.height + 20.0,
_flipButton.frame.size.width, _flipButton.frame.size.height);
CGFloat flipButtonPosition = 0.0f; CGFloat flipButtonPosition = 0.0f;
CGFloat cancelButtonPosition = _panelView.frame.size.height - _cancelButton.frame.size.height - 7; CGFloat cancelButtonPosition = _panelView.frame.size.height - _cancelButton.frame.size.height - 7;
if (!_doneButton.hidden) if (!_doneButton.hidden)
@ -284,7 +288,6 @@ const CGFloat TGCameraTabletPanelViewWidth = 102.0f;
flipButtonPosition = _panelView.frame.size.height / 8.0f - _flipButton.frame.size.height / 2.0f; flipButtonPosition = _panelView.frame.size.height / 8.0f - _flipButton.frame.size.height / 2.0f;
cancelButtonPosition = 7.0f; cancelButtonPosition = 7.0f;
} }
_flipButton.frame = CGRectMake((_panelView.frame.size.width - _flipButton.frame.size.width) / 2, flipButtonPosition, _flipButton.frame.size.width, _flipButton.frame.size.height);
_doneButton.frame = CGRectMake((_panelView.frame.size.width - _doneButton.frame.size.width) / 2, _panelView.frame.size.height - _doneButton.frame.size.height - 7, _doneButton.frame.size.width, _doneButton.frame.size.height); _doneButton.frame = CGRectMake((_panelView.frame.size.width - _doneButton.frame.size.width) / 2, _panelView.frame.size.height - _doneButton.frame.size.height - 7, _doneButton.frame.size.width, _doneButton.frame.size.height);

View File

@ -201,6 +201,11 @@
self.shutterReleased(false); self.shutterReleased(false);
} }
- (void)shutterButtonPanGesture:(UIPanGestureRecognizer *)gestureRecognizer {
if (self.shutterPanGesture != nil)
self.shutterPanGesture(gestureRecognizer);
}
- (void)cancelButtonPressed - (void)cancelButtonPressed
{ {
if (self.cancelPressed != nil) if (self.cancelPressed != nil)
@ -228,6 +233,7 @@
{ {
[_zoomView setZoomLevel:zoomLevel displayNeeded:displayNeeded]; [_zoomView setZoomLevel:zoomLevel displayNeeded:displayNeeded];
[_zoomModeView setZoomLevel:zoomLevel animated:true]; [_zoomModeView setZoomLevel:zoomLevel animated:true];
[_zoomWheelView setZoomLevel:zoomLevel];
} }
- (void)zoomChangingEnded - (void)zoomChangingEnded

View File

@ -8,6 +8,7 @@
@interface TGCameraTimeCodeView () @interface TGCameraTimeCodeView ()
{ {
UIView *_backgroundView; UIView *_backgroundView;
UIView *_recordingBackgroundView;
UILabel *_timeLabel; UILabel *_timeLabel;
NSUInteger _recordingDurationSeconds; NSUInteger _recordingDurationSeconds;
@ -25,10 +26,17 @@
_backgroundView = [[UIView alloc] init]; _backgroundView = [[UIView alloc] init];
_backgroundView.clipsToBounds = true; _backgroundView.clipsToBounds = true;
_backgroundView.layer.cornerRadius = 4.0; _backgroundView.layer.cornerRadius = 4.0;
_backgroundView.backgroundColor = [TGCameraInterfaceAssets redColor]; _backgroundView.backgroundColor = [TGCameraInterfaceAssets transparentPanelBackgroundColor];
_backgroundView.alpha = 0.0; _backgroundView.alpha = 0.0;
[self addSubview:_backgroundView]; [self addSubview:_backgroundView];
_recordingBackgroundView = [[UIView alloc] init];
_recordingBackgroundView.clipsToBounds = true;
_recordingBackgroundView.layer.cornerRadius = 4.0;
_recordingBackgroundView.backgroundColor = [TGCameraInterfaceAssets redColor];
_recordingBackgroundView.alpha = 0.0;
[self addSubview:_recordingBackgroundView];
_timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; _timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
_timeLabel.backgroundColor = [UIColor clearColor]; _timeLabel.backgroundColor = [UIColor clearColor];
_timeLabel.font = [TGCameraInterfaceAssets regularFontOfSize:21]; _timeLabel.font = [TGCameraInterfaceAssets regularFontOfSize:21];
@ -45,6 +53,12 @@
[self stopRecording]; [self stopRecording];
} }
- (void)setInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
_interfaceOrientation = interfaceOrientation;
_backgroundView.alpha = UIInterfaceOrientationIsLandscape(interfaceOrientation) ? 1.0 : 0.0;
}
- (void)_updateRecordingTime - (void)_updateRecordingTime
{ {
if (_recordingDurationSeconds > 60 * 60) { if (_recordingDurationSeconds > 60 * 60) {
@ -57,6 +71,7 @@
CGFloat inset = 8.0f; CGFloat inset = 8.0f;
CGFloat backgroundWidth = _timeLabel.frame.size.width + inset * 2.0; CGFloat backgroundWidth = _timeLabel.frame.size.width + inset * 2.0;
_backgroundView.frame = CGRectMake(floor((self.frame.size.width - backgroundWidth) / 2.0), 0.0, backgroundWidth, 28.0); _backgroundView.frame = CGRectMake(floor((self.frame.size.width - backgroundWidth) / 2.0), 0.0, backgroundWidth, 28.0);
_recordingBackgroundView.frame = _backgroundView.frame;
_timeLabel.frame = CGRectMake(floor((self.frame.size.width - _timeLabel.frame.size.width) / 2.0), floor((28 - _timeLabel.frame.size.height) / 2.0), _timeLabel.frame.size.width, _timeLabel.frame.size.height); _timeLabel.frame = CGRectMake(floor((self.frame.size.width - _timeLabel.frame.size.width) / 2.0), floor((28 - _timeLabel.frame.size.height) / 2.0), _timeLabel.frame.size.width, _timeLabel.frame.size.height);
} }
@ -68,7 +83,7 @@
_recordingTimer = [TGTimerTarget scheduledMainThreadTimerWithTarget:self action:@selector(recordingTimerEvent) interval:1.0 repeat:false]; _recordingTimer = [TGTimerTarget scheduledMainThreadTimerWithTarget:self action:@selector(recordingTimerEvent) interval:1.0 repeat:false];
[UIView animateWithDuration:0.2 animations:^{ [UIView animateWithDuration:0.2 animations:^{
_backgroundView.alpha = 1.0; _recordingBackgroundView.alpha = 1.0;
}]; }];
} }
@ -78,7 +93,7 @@
_recordingTimer = nil; _recordingTimer = nil;
[UIView animateWithDuration:0.2 animations:^{ [UIView animateWithDuration:0.2 animations:^{
_backgroundView.alpha = 0.0; _recordingBackgroundView.alpha = 0.0;
}]; }];
} }

View File

@ -54,7 +54,7 @@
CGContextRef context = UIGraphicsGetCurrentContext(); CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [TGCameraInterfaceAssets accentColor].CGColor); CGContextSetStrokeColorWithColor(context, [TGCameraInterfaceAssets accentColor].CGColor);
CGContextSetLineWidth(context, 1.5f); CGContextSetLineWidth(context, 1.0f);
CGContextStrokeEllipseInRect(context, CGRectMake(0.75f, 0.75f, 12.5f - 1.5f, 12.5f - 1.5f)); CGContextStrokeEllipseInRect(context, CGRectMake(0.75f, 0.75f, 12.5f - 1.5f, 12.5f - 1.5f));
knobImage = UIGraphicsGetImageFromCurrentImageContext(); knobImage = UIGraphicsGetImageFromCurrentImageContext();
@ -170,7 +170,11 @@
{ {
_clipView.frame = CGRectMake(22, (self.frame.size.height - 12.5f) / 2, self.frame.size.width - 44, 12.5f); _clipView.frame = CGRectMake(22, (self.frame.size.height - 12.5f) / 2, self.frame.size.width - 44, 12.5f);
CGFloat position = (_clipView.frame.size.width - _knobView.frame.size.width) * self.zoomLevel; CGFloat zoomLevel = self.zoomLevel;
zoomLevel = MAX(1.0, zoomLevel);
CGFloat factor = zoomLevel / 8.0;
CGFloat position = (_clipView.frame.size.width - _knobView.frame.size.width) * factor;
if (self.zoomLevel < 1.0f - FLT_EPSILON) if (self.zoomLevel < 1.0f - FLT_EPSILON)
position = CGFloor(position); position = CGFloor(position);
@ -196,6 +200,7 @@
_label = [[UILabel alloc] initWithFrame:self.bounds]; _label = [[UILabel alloc] initWithFrame:self.bounds];
_label.textAlignment = NSTextAlignmentCenter; _label.textAlignment = NSTextAlignmentCenter;
_label.font = [TGCameraInterfaceAssets boldFontOfSize:13.0];
[self addSubview:_backgroundView]; [self addSubview:_backgroundView];
[self addSubview:_label]; [self addSubview:_label];
@ -209,7 +214,6 @@
_label.text = value; _label.text = value;
_label.textColor = selected ? [TGCameraInterfaceAssets accentColor] : [UIColor whiteColor]; _label.textColor = selected ? [TGCameraInterfaceAssets accentColor] : [UIColor whiteColor];
_label.font = [TGCameraInterfaceAssets boldFontOfSize:13.0];
if (animated) { if (animated) {
[UIView animateWithDuration:0.3f animations:^ [UIView animateWithDuration:0.3f animations:^
@ -225,7 +229,7 @@
@end @end
@interface TGCameraZoomModeView () @interface TGCameraZoomModeView () <UIGestureRecognizerDelegate>
{ {
CGFloat _minZoomLevel; CGFloat _minZoomLevel;
CGFloat _maxZoomLevel; CGFloat _maxZoomLevel;
@ -267,23 +271,31 @@
[_rightItem addTarget:self action:@selector(rightPressed) forControlEvents:UIControlEventTouchUpInside]; [_rightItem addTarget:self action:@selector(rightPressed) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_backgroundView]; [self addSubview:_backgroundView];
if (hasUltrawideCamera) {
[self addSubview:_leftItem];
}
[self addSubview:_centerItem]; [self addSubview:_centerItem];
if (hasTelephotoCamera) { if (hasTelephotoCamera && hasUltrawideCamera) {
[self addSubview:_leftItem];
[self addSubview:_rightItem]; [self addSubview:_rightItem];
} }
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)]; UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)];
panGestureRecognizer.delegate = self;
[self addGestureRecognizer:panGestureRecognizer]; [self addGestureRecognizer:panGestureRecognizer];
UILongPressGestureRecognizer *pressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(pressGesture:)]; UILongPressGestureRecognizer *pressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(pressGesture:)];
pressGestureRecognizer.delegate = self;
[self addGestureRecognizer:pressGestureRecognizer]; [self addGestureRecognizer:pressGestureRecognizer];
} }
return self; return self;
} }
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if (gestureRecognizer.view == self && otherGestureRecognizer.view == self) {
return true;
} else {
return false;
}
}
- (void)pressGesture:(UILongPressGestureRecognizer *)gestureRecognizer { - (void)pressGesture:(UILongPressGestureRecognizer *)gestureRecognizer {
switch (gestureRecognizer.state) { switch (gestureRecognizer.state) {
case UIGestureRecognizerStateBegan: case UIGestureRecognizerStateBegan:
@ -305,8 +317,23 @@
switch (gestureRecognizer.state) { switch (gestureRecognizer.state) {
case UIGestureRecognizerStateChanged: case UIGestureRecognizerStateChanged:
_zoomLevel = MAX(0.5, MIN(10.0, _zoomLevel - translation.x / 100.0)); {
CGFloat delta = -translation.x / 60.0;
if (_zoomLevel > 2.0) {
delta *= 3.5;
}
_zoomLevel = MAX(_minZoomLevel, MIN(_maxZoomLevel, _zoomLevel + delta));
self.zoomChanged(_zoomLevel, false, false); self.zoomChanged(_zoomLevel, false, false);
}
break;
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled:
{
if (gestureRecognizer.view != self) {
self.zoomChanged(_zoomLevel, true, false);
}
}
break; break;
default: default:
break; break;
@ -321,8 +348,23 @@
} }
- (void)centerPressed { - (void)centerPressed {
if (!(_hasTelephotoCamera && _hasUltrawideCamera)) {
if (_zoomLevel == 1.0) {
if (_hasUltrawideCamera) {
[self setZoomLevel:0.5 animated:true];
self.zoomChanged(0.5, true, true);
} else if (_hasTelephotoCamera) {
[self setZoomLevel:2.0 animated:true];
self.zoomChanged(2.0, true, true);
}
} else {
[self setZoomLevel:1.0 animated:true]; [self setZoomLevel:1.0 animated:true];
self.zoomChanged(1.0, true, true); self.zoomChanged(1.0, true, true);
}
} else {
[self setZoomLevel:1.0 animated:true];
self.zoomChanged(1.0, true, true);
}
} }
- (void)rightPressed { - (void)rightPressed {
@ -338,40 +380,44 @@
{ {
_zoomLevel = zoomLevel; _zoomLevel = zoomLevel;
if (zoomLevel < 1.0) { if (zoomLevel < 1.0) {
NSString *value = [NSString stringWithFormat:@"%.1fx", zoomLevel]; NSString *value = [NSString stringWithFormat:@"%.1f×", zoomLevel];
if ([value isEqual:@"1,0x"]) {
value = @"0,9x";
}
value = [value stringByReplacingOccurrencesOfString:@"." withString:@","]; value = [value stringByReplacingOccurrencesOfString:@"." withString:@","];
if ([value isEqual:@"1,0×"] || [value isEqual:@"1×"]) {
value = @"0,9×";
}
if (_leftItem.superview != nil) {
[_leftItem setValue:value selected:true animated:animated]; [_leftItem setValue:value selected:true animated:animated];
[_centerItem setValue:@"1" selected:false animated:animated]; [_centerItem setValue:@"1" selected:false animated:animated];
} else {
[_centerItem setValue:value selected:false animated:animated];
}
[_rightItem setValue:@"2" selected:false animated:animated]; [_rightItem setValue:@"2" selected:false animated:animated];
} else if (zoomLevel < 2.0) { } else if (zoomLevel < 2.0) {
[_leftItem setValue:@"0,5" selected:false animated:animated]; [_leftItem setValue:@"0,5" selected:false animated:animated];
if ((zoomLevel - 1.0) < 0.1) { bool selected = _hasTelephotoCamera && _hasUltrawideCamera;
[_centerItem setValue:@"1x" selected:true animated:animated]; if ((zoomLevel - 1.0) < 0.025) {
[_centerItem setValue:@"1×" selected:true animated:animated];
} else { } else {
NSString *value = [NSString stringWithFormat:@"%.1fx", zoomLevel]; NSString *value = [NSString stringWithFormat:@"%.1f×", zoomLevel];
value = [value stringByReplacingOccurrencesOfString:@"." withString:@","]; value = [value stringByReplacingOccurrencesOfString:@"." withString:@","];
if ([value isEqual:@"1,0x"]) { value = [value stringByReplacingOccurrencesOfString:@",0×" withString:@"×"];
value = @"1x"; if ([value isEqual:@"2×"]) {
} else if ([value isEqual:@"2,0x"]) { value = @"1,9×";
value = @"1,9x";
} }
[_centerItem setValue:value selected:true animated:animated]; [_centerItem setValue:value selected:selected animated:animated];
} }
[_rightItem setValue:@"2" selected:false animated:animated]; [_rightItem setValue:@"2" selected:false animated:animated];
} else { } else {
[_leftItem setValue:@"0,5" selected:false animated:animated]; [_leftItem setValue:@"0,5" selected:false animated:animated];
[_centerItem setValue:@"1" selected:false animated:animated];
CGFloat near = round(zoomLevel); NSString *value = [[NSString stringWithFormat:@"%.1f×", zoomLevel] stringByReplacingOccurrencesOfString:@"." withString:@","];
if (ABS(zoomLevel - near) < 0.1) { value = [value stringByReplacingOccurrencesOfString:@",0×" withString:@"×"];
[_rightItem setValue:[NSString stringWithFormat:@"%dx", (int)zoomLevel] selected:true animated:animated];
} else { if (_rightItem.superview != nil) {
NSString *value = [NSString stringWithFormat:@"%.1fx", zoomLevel]; [_centerItem setValue:@"1" selected:false animated:animated];
value = [value stringByReplacingOccurrencesOfString:@"." withString:@","];
[_rightItem setValue:value selected:true animated:animated]; [_rightItem setValue:value selected:true animated:animated];
} else {
[_centerItem setValue:value selected:true animated:animated];
} }
} }
} }
@ -409,9 +455,13 @@
- (void)layoutSubviews - (void)layoutSubviews
{ {
if (_rightItem.superview == nil) { if (_leftItem.superview == nil && _rightItem.superview == nil) {
_backgroundView.frame = CGRectMake(43, 0, 43, 43); _backgroundView.frame = CGRectMake(43, 0, 43, 43);
} else if (_leftItem.superview == nil) { } else if (_leftItem.superview != nil && _rightItem.superview == nil) {
_backgroundView.frame = CGRectMake(21 + TGScreenPixel, 0, 86, 43);
_leftItem.frame = CGRectMake(21 + TGScreenPixel, 0, 43, 43);
_centerItem.frame = CGRectMake(21 + TGScreenPixel + 43, 0, 43, 43);
} else if (_leftItem.superview == nil && _rightItem.superview != nil) {
_backgroundView.frame = CGRectMake(21 + TGScreenPixel, 0, 86, 43); _backgroundView.frame = CGRectMake(21 + TGScreenPixel, 0, 86, 43);
_centerItem.frame = CGRectMake(21 + TGScreenPixel, 0, 43, 43); _centerItem.frame = CGRectMake(21 + TGScreenPixel, 0, 43, 43);
_rightItem.frame = CGRectMake(21 + TGScreenPixel + 43, 0, 43, 43); _rightItem.frame = CGRectMake(21 + TGScreenPixel + 43, 0, 43, 43);
@ -437,7 +487,21 @@
{ {
bool _hasUltrawideCamera; bool _hasUltrawideCamera;
bool _hasTelephotoCamera; bool _hasTelephotoCamera;
UIView *_containerView;
UIImageView *_backgroundView; UIImageView *_backgroundView;
UIImageView *_scaleView;
UIImageView *_maskView;
UIImageView *_arrowView;
UILabel *_valueLabel;
UILabel *_05Label;
UILabel *_1Label;
UILabel *_2Label;
UILabel *_8Label;
UIPanGestureRecognizer *_gestureRecognizer;
UISelectionFeedbackGenerator *_feedbackGenerator;
} }
@end @end
@ -459,84 +523,355 @@
CGContextRestoreGState(context); CGContextRestoreGState(context);
} }
- (NSArray *)ultraLines {
return @[
@[@0.5, @-19.6, @3],
@[@0.6, @-14.4, @1],
@[@0.7, @-10.0, @1],
@[@0.8, @-6.3, @1],
@[@0.9, @-3.0, @1]
];
}
- (NSArray *)lines {
return @[
@[@1.0, @0.0, @3],
@[@1.1, @2.7, @1],
@[@1.2, @5.2, @1],
@[@1.3, @7.4, @1],
@[@1.4, @9.6, @1],
@[@1.5, @11.5, @1],
@[@1.6, @13.3, @1],
@[@1.7, @15.0, @1],
@[@1.8, @16.7, @1],
@[@1.9, @18.2, @1],
@[@2.0, @19.6, _hasTelephotoCamera ? @3 : @2],
@[@2.1, @21.0, @1],
@[@2.2, @22.4, @1],
@[@2.3, @23.7, @1],
@[@2.4, @24.8, @1],
@[@2.5, @26.0, @1],
@[@2.6, @27.1, @1],
@[@2.7, @28.2, @1],
@[@2.8, @29.2, @1],
@[@2.9, @30.2, @1],
@[@3.0, @31.1, @2],
@[@3.1, @32.0, @1],
@[@3.2, @32.9, @1],
@[@3.3, @33.8, @1],
@[@3.4, @34.7, @1],
@[@3.5, @35.5, @1],
@[@3.6, @36.34, @1],
@[@3.7, @37.1, @1],
@[@3.8, @37.85, @1],
@[@3.9, @38.55, @1],
@[@4.0, @39.3, @2],
@[@4.1, @40.0, @1],
@[@4.2, @40.77, @1],
@[@4.3, @41.4, @1],
@[@4.4, @42.05, @1],
@[@4.5, @42.63, @1],
@[@4.6, @43.3, @1],
@[@4.7, @43.89, @1],
@[@4.8, @44.42, @1],
@[@4.9, @45.05, @1],
@[@5.0, @45.6, @2],
@[@5.1, @46.17, @1],
@[@5.2, @46.77, @1],
@[@5.3, @47.31, @1],
@[@5.4, @47.78, @1],
@[@5.5, @48.34, @1],
@[@5.6, @48.8, @1],
@[@5.7, @49.31, @1],
@[@5.8, @49.85, @1],
@[@5.9, @50.3, @1],
@[@6.0, @50.8, @2],
@[@6.1, @51.25, @1],
@[@6.2, @51.7, @1],
@[@6.3, @52.18, @1],
@[@6.4, @52.63, @1],
@[@6.5, @53.12, @1],
@[@6.6, @53.49, @1],
@[@6.7, @53.88, @1],
@[@6.8, @54.28, @1],
@[@6.9, @54.71, @1],
@[@7.0, @55.15, @2],
@[@7.1, @55.53, @1],
@[@7.2, @55.91, @1],
@[@7.3, @56.36, @1],
@[@7.4, @56.74, @1],
@[@7.5, @57.09, @1],
@[@7.6, @57.52, @1],
@[@7.7, @57.89, @1],
@[@7.8, @58.19, @1],
@[@7.9, @58.56, @1],
@[@8.0, @58.93, @3],
];
}
- (instancetype)initWithFrame:(CGRect)frame hasUltrawideCamera:(bool)hasUltrawideCamera hasTelephotoCamera:(bool)hasTelephotoCamera - (instancetype)initWithFrame:(CGRect)frame hasUltrawideCamera:(bool)hasUltrawideCamera hasTelephotoCamera:(bool)hasTelephotoCamera
{ {
self = [super initWithFrame:frame]; self = [super initWithFrame:frame];
if (self != nil) if (self != nil)
{ {
_hasUltrawideCamera = true;// hasUltrawideCamera; TGIsRetina();
_hasTelephotoCamera = true;//hasTelephotoCamera;
self.clipsToBounds = true; if (iosMajorVersion() >= 10) {
_feedbackGenerator = [[UISelectionFeedbackGenerator alloc] init];
}
_hasUltrawideCamera = hasUltrawideCamera;
_hasTelephotoCamera = hasTelephotoCamera;
CGFloat side = floor(frame.size.width * 1.1435); CGFloat side = floor(frame.size.width * 1.1435);
CGFloat length = 17.0; CGFloat length = 17.0;
CGFloat smallWidth = MAX(0.5, 1.0 - TGScreenPixel); CGFloat smallWidth = MAX(0.5, 1.0 - TGScreenPixel);
CGFloat mediumWidth = 1.0; CGFloat mediumWidth = smallWidth;
CGFloat bigWidth = 1.0 + TGScreenPixel; CGFloat bigWidth = 1.0;
CGFloat smallAngle = M_PI * 0.12; _backgroundView = [[UIImageView alloc] initWithImage:TGCircleImage(side, [UIColor colorWithWhite:0.0 alpha:0.5])];
CGFloat finalAngle = 1.08; _backgroundView.frame = CGRectMake(TGScreenPixelFloor((frame.size.width - side) / 2.0), 0.0, side, side);
[self addSubview:_backgroundView];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(side, side), false, 0.0f); UIGraphicsBeginImageContextWithOptions(CGSizeMake(side, side), false, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext(); CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor colorWithWhite:0.0 alpha:0.75].CGColor); NSArray *ultraLines = [self ultraLines];
CGContextFillEllipseInRect(context, CGRectMake(0, 0, side, side)); NSArray *lines = [self lines];
[self _drawLineInContext:context side:side atAngle:0.0 lineLength:length lineWidth:bigWidth opaque:true];
if (_hasUltrawideCamera) { if (_hasUltrawideCamera) {
for (NSInteger i = 0; i < 4; i++) { for (NSArray *values in ultraLines) {
CGFloat angle = (smallAngle / 5.0) * (i + 1) + (0.007 * (i - 1)); CGFloat angle = [values[1] floatValue];
[self _drawLineInContext:context side:side atAngle:-angle lineLength:length lineWidth:smallWidth opaque:false]; CGFloat width = [values[2] intValue];
}
[self _drawLineInContext:context side:side atAngle:-smallAngle lineLength:length lineWidth:bigWidth opaque:true];
}
if (_hasTelephotoCamera) {
[self _drawLineInContext:context side:side atAngle:smallAngle lineLength:length lineWidth:bigWidth opaque:true];
for (NSInteger i = 0; i < 4; i++) { CGFloat lineWidth = smallWidth;
CGFloat angle = (smallAngle / 5.0) * (i + 1) + (0.01 * (i - 1)); if (width == 2) {
[self _drawLineInContext:context side:side atAngle:angle lineLength:length lineWidth:smallWidth opaque:false]; lineWidth = mediumWidth;
} else if (width == 3) {
lineWidth = bigWidth;
}
[self _drawLineInContext:context side:side atAngle:TGDegreesToRadians(angle) lineLength:length lineWidth:lineWidth opaque:width > 1];
}
}
for (NSArray *values in lines) {
CGFloat angle = [values[1] floatValue];
CGFloat width = [values[2] intValue];
CGFloat lineWidth = smallWidth;
if (width == 2) {
lineWidth = mediumWidth;
} else if (width == 3) {
lineWidth = bigWidth;
} }
[self _drawLineInContext:context side:side atAngle:finalAngle lineLength:length lineWidth:bigWidth opaque:true]; [self _drawLineInContext:context side:side atAngle:TGDegreesToRadians(angle) lineLength:length lineWidth:lineWidth opaque:width > 1];
} else {
[self _drawLineInContext:context side:side atAngle:smallAngle lineLength:length lineWidth:mediumWidth opaque:true];
[self _drawLineInContext:context side:side atAngle:finalAngle lineLength:length lineWidth:bigWidth opaque:true];
} }
UIImage *scaleImage = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:25 topCapHeight:25];
UIImage *image = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:25 topCapHeight:25];
UIGraphicsEndImageContext(); UIGraphicsEndImageContext();
_backgroundView = [[UIImageView alloc] initWithFrame:CGRectMake(TGScreenPixelFloor((frame.size.width - side) / 2.0), 0.0, side, side)]; _containerView = [[UIView alloc] initWithFrame:CGRectMake(TGScreenPixelFloor((frame.size.width - side) / 2.0), 0.0, side, frame.size.height)];
_backgroundView.image = image; _containerView.userInteractionEnabled = false;
[self addSubview:_containerView];
[self addSubview:_backgroundView]; UIGraphicsBeginImageContextWithOptions(CGSizeMake(side, frame.size.height), false, 0.0f);
context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextFillEllipseInRect(context, CGRectMake(0, 0, side, side));
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextMoveToPoint(context, side / 2.0 - 7.0, 0);
CGContextAddLineToPoint(context, side / 2.0 + 7.0, 0);
CGContextAddLineToPoint(context, side / 2.0 + 2.0, 22);
CGContextAddLineToPoint(context, side / 2.0 - 2.0, 22);
CGContextClosePath(context);
CGContextFillPath(context);
CGContextFillRect(context, CGRectMake(side / 2.0 - 1.0, 20, 2.0, 7.0));
CGContextFillEllipseInRect(context, CGRectMake(side / 2.0 - 17.0, 21.0, 34.0, 34.0));
UIImage *maskImage = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:25 topCapHeight:25];
UIGraphicsEndImageContext();
_maskView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, side, frame.size.height)];
_maskView.image = maskImage;
_containerView.maskView = _maskView;
_scaleView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, side, side)];
_scaleView.image = scaleImage;
[_containerView addSubview:_scaleView];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(4, 10), false, 0.0f);
context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [TGCameraInterfaceAssets accentColor].CGColor);
CGContextMoveToPoint(context, 0, 0);
CGContextAddLineToPoint(context, 4, 0);
CGContextAddLineToPoint(context, 2 + TGScreenPixel, 10);
CGContextAddLineToPoint(context, 2 - TGScreenPixel, 10);
CGContextClosePath(context);
CGContextFillPath(context);
UIImage *arrowImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
_arrowView = [[UIImageView alloc] initWithFrame:CGRectMake(floor((frame.size.width - 4) / 2.0), 4, 4, 10)];
_arrowView.image = arrowImage;
_arrowView.userInteractionEnabled = false;
[self addSubview:_arrowView];
_valueLabel = [[UILabel alloc] init];
_valueLabel.font = [TGCameraInterfaceAssets boldFontOfSize:13.0];
_valueLabel.textColor = [TGCameraInterfaceAssets accentColor];
_valueLabel.userInteractionEnabled = false;
[self addSubview:_valueLabel];
CGFloat radius = side / 2.0;
if (_hasUltrawideCamera) {
_05Label = [[UILabel alloc] init];
_05Label.text = @"0,5";
_05Label.font = [TGCameraInterfaceAssets boldFontOfSize:13.0];
_05Label.textColor = [UIColor whiteColor];
[_05Label sizeToFit];
[_scaleView addSubview:_05Label];
_05Label.center = CGPointMake(radius - sin(TGDegreesToRadians(19.6)) * (radius - 38.0), radius - cos(TGDegreesToRadians(19.6)) * (radius - 38.0));
_05Label.transform = CGAffineTransformMakeRotation(TGDegreesToRadians(-19.6));
}
_1Label = [[UILabel alloc] init];
_1Label.text = @"1";
_1Label.font = [TGCameraInterfaceAssets boldFontOfSize:13.0];
_1Label.textColor = [UIColor whiteColor];
[_1Label sizeToFit];
_1Label.frame = CGRectMake(TGScreenPixelFloor((_scaleView.bounds.size.width - _1Label.frame.size.width) / 2.0), 30.0, _1Label.frame.size.width, _1Label.frame.size.height);
[_scaleView addSubview:_1Label];
if (_hasTelephotoCamera) {
_2Label = [[UILabel alloc] init];
_2Label.text = @"2";
_2Label.font = [TGCameraInterfaceAssets boldFontOfSize:13.0];
_2Label.textColor = [UIColor whiteColor];
[_2Label sizeToFit];
[_scaleView addSubview:_2Label];
_2Label.center = CGPointMake(radius - sin(TGDegreesToRadians(-19.6)) * (radius - 38.0), radius - cos(TGDegreesToRadians(-19.6)) * (radius - 38.0));
_2Label.transform = CGAffineTransformMakeRotation(TGDegreesToRadians(19.6));
}
_8Label = [[UILabel alloc] init];
_8Label.text = @"8";
_8Label.font = [TGCameraInterfaceAssets boldFontOfSize:13.0];
_8Label.textColor = [UIColor whiteColor];
[_8Label sizeToFit];
[_scaleView addSubview:_8Label];
_8Label.center = CGPointMake(radius - sin(TGDegreesToRadians(-58.93)) * (radius - 38.0), radius - cos(TGDegreesToRadians(-58.93)) * (radius - 38.0));
_8Label.transform = CGAffineTransformMakeRotation(TGDegreesToRadians(58.93));
_gestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)];
[self addGestureRecognizer:_gestureRecognizer];
} }
return self; return self;
} }
- (void)panGesture:(UIPanGestureRecognizer *)gestureRecognizer {
if (self.panGesture != nil) {
self.panGesture(gestureRecognizer);
}
}
- (void)setZoomLevel:(CGFloat)zoomLevel { - (void)setZoomLevel:(CGFloat)zoomLevel {
[self setZoomLevel:zoomLevel panning:false];
}
- (void)setZoomLevel:(CGFloat)zoomLevel panning:(bool)panning {
zoomLevel = MAX(0.5, zoomLevel); zoomLevel = MAX(0.5, zoomLevel);
_zoomLevel = zoomLevel; _zoomLevel = zoomLevel;
CGFloat angle = 0.0; NSArray *ultraLines = [self ultraLines];
if (zoomLevel < 1.0) { NSArray *lines = [self lines];
CGFloat delta = (zoomLevel - 0.5) / 0.5;
angle = TGDegreesToRadians(20.8) * (1.0 - delta); CGFloat finalAngle = 0.0;
} else if (zoomLevel < 2.0) { NSArray *allLines = [ultraLines arrayByAddingObjectsFromArray:lines];
CGFloat delta = zoomLevel - 1.0; NSArray *previous = nil;
angle = TGDegreesToRadians(-22.0) * delta; for (NSArray *values in allLines) {
} else if (zoomLevel < 10.0) { CGFloat value = [values[0] floatValue];
CGFloat delta = (zoomLevel - 2.0) / 8.0; CGFloat angle = [values[1] floatValue];
angle = TGDegreesToRadians(-22.0) + TGDegreesToRadians(-68.0) * delta;
if (previous == nil && zoomLevel <= value) {
finalAngle = angle;
break;
} }
_backgroundView.transform = CGAffineTransformMakeRotation(angle); if (previous != nil && zoomLevel <= value) {
if (zoomLevel == value) {
finalAngle = angle;
break;
} else {
CGFloat previousValue = [previous[0] floatValue];
CGFloat previousAngle = [previous[1] floatValue];
if (zoomLevel > previousValue) {
CGFloat factor = (zoomLevel - previousValue) / (value - previousValue);
finalAngle = previousAngle + (angle - previousAngle) * factor;
break;
}
}
}
previous = values;
}
finalAngle = -TGDegreesToRadians(finalAngle);
_scaleView.transform = CGAffineTransformMakeRotation(finalAngle);
NSString *value = [NSString stringWithFormat:@"%.1f×", zoomLevel];
value = [value stringByReplacingOccurrencesOfString:@"." withString:@","];
value = [value stringByReplacingOccurrencesOfString:@",0×" withString:@"×"];
NSString *previousValue = _valueLabel.text;
_valueLabel.text = value;
[_valueLabel sizeToFit];
if (panning && ![previousValue isEqualToString:value] && ([value isEqualToString:@"0,5×"] || ![value containsString:@","])) {
[_feedbackGenerator selectionChanged];
}
CGRect valueLabelFrame = CGRectMake(TGScreenPixelFloor((self.frame.size.width - _valueLabel.bounds.size.width) / 2.0), 30.0, _valueLabel.bounds.size.width, _valueLabel.bounds.size.height);
_valueLabel.bounds = CGRectMake(0, 0, valueLabelFrame.size.width, valueLabelFrame.size.height);
_valueLabel.center = CGPointMake(valueLabelFrame.origin.x + valueLabelFrame.size.width / 2.0, valueLabelFrame.origin.y + valueLabelFrame.size.height / 2.0);
}
- (void)setInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
_interfaceOrientation = interfaceOrientation;
CGFloat delta = 0.0f;
switch (interfaceOrientation) {
case UIInterfaceOrientationLandscapeLeft:
delta = -90.0f;
break;
case UIInterfaceOrientationLandscapeRight:
delta = 90.0f;
break;
case UIInterfaceOrientationPortraitUpsideDown:
delta = 180.0f;
default:
break;
}
_valueLabel.transform = CGAffineTransformMakeRotation(TGDegreesToRadians(delta));
_05Label.transform = CGAffineTransformMakeRotation(TGDegreesToRadians(-19.6 + delta));
_1Label.transform = CGAffineTransformMakeRotation(TGDegreesToRadians(delta));
_2Label.transform = CGAffineTransformMakeRotation(TGDegreesToRadians(19.6 + delta));
_8Label.transform = CGAffineTransformMakeRotation(TGDegreesToRadians(58.93 + delta));
} }
- (void)setHidden:(BOOL)hidden - (void)setHidden:(BOOL)hidden

View File

@ -300,7 +300,7 @@ typedef enum
} }
CGFloat minSide = MIN(_wrapperView.frame.size.width, _wrapperView.frame.size.height); CGFloat minSide = MIN(_wrapperView.frame.size.width, _wrapperView.frame.size.height);
CGFloat diameter = MIN(404.0, minSide - 24.0f); CGFloat diameter = minSide == 320.0 ? 216.0 : MIN(404.0, minSide - 24.0f);
CGFloat shadowSize = 21.0f; CGFloat shadowSize = 21.0f;
CGFloat circleWrapperViewLength = diameter + shadowSize * 2.0; CGFloat circleWrapperViewLength = diameter + shadowSize * 2.0;

View File

@ -379,7 +379,7 @@ public final class VoiceChatController: ViewController {
} }
private enum ListEntry: Comparable, Identifiable { private enum ListEntry: Comparable, Identifiable {
case tiles([VoiceChatTileItem], VoiceChatTileLayoutMode) case tiles([VoiceChatTileItem], VoiceChatTileLayoutMode, Int32, Bool)
case invite(PresentationTheme, PresentationStrings, String, Bool) case invite(PresentationTheme, PresentationStrings, String, Bool)
case peer(VoiceChatPeerEntry, Int32) case peer(VoiceChatPeerEntry, Int32)
@ -396,8 +396,8 @@ public final class VoiceChatController: ViewController {
static func ==(lhs: ListEntry, rhs: ListEntry) -> Bool { static func ==(lhs: ListEntry, rhs: ListEntry) -> Bool {
switch lhs { switch lhs {
case let .tiles(lhsTiles, lhsLayoutMode): case let .tiles(lhsTiles, lhsLayoutMode, lhsVideoLimit, lhsReachedLimit):
if case let .tiles(rhsTiles, rhsLayoutMode) = rhs, lhsTiles == rhsTiles, lhsLayoutMode == rhsLayoutMode { if case let .tiles(rhsTiles, rhsLayoutMode, rhsVideoLimit, rhsReachedLimit) = rhs, lhsTiles == rhsTiles, lhsLayoutMode == rhsLayoutMode, lhsVideoLimit == rhsVideoLimit, lhsReachedLimit == rhsReachedLimit {
return true return true
} else { } else {
return false return false
@ -644,8 +644,8 @@ public final class VoiceChatController: ViewController {
func item(context: AccountContext, presentationData: PresentationData, interaction: Interaction) -> ListViewItem { func item(context: AccountContext, presentationData: PresentationData, interaction: Interaction) -> ListViewItem {
switch self { switch self {
case let .tiles(tiles, layoutMode): case let .tiles(tiles, layoutMode, videoLimit, reachedLimit):
return VoiceChatTilesGridItem(context: context, tiles: tiles, layoutMode: layoutMode, getIsExpanded: { return VoiceChatTilesGridItem(context: context, tiles: tiles, layoutMode: layoutMode, videoLimit: videoLimit, reachedLimit: reachedLimit, getIsExpanded: {
return interaction.isExpanded return interaction.isExpanded
}) })
case let .invite(_, _, text, isLink): case let .invite(_, _, text, isLink):
@ -5021,12 +5021,16 @@ public final class VoiceChatController: ViewController {
self.joinedVideo = joinedVideo self.joinedVideo = joinedVideo
let configuration = self.configuration ?? VoiceChatConfiguration.defaultValue
var reachedLimit = false
if !joinedVideo && (!tileItems.isEmpty || !gridTileItems.isEmpty), let peer = self.peer { if !joinedVideo && (!tileItems.isEmpty || !gridTileItems.isEmpty), let peer = self.peer {
tileItems.removeAll() tileItems.removeAll()
gridTileItems.removeAll() gridTileItems.removeAll()
let configuration = self.configuration ?? VoiceChatConfiguration.defaultValue
tileItems.append(VoiceChatTileItem(account: self.context.account, peer: peer, videoEndpointId: "", videoReady: false, videoTimeouted: true, isVideoLimit: true, videoLimit: configuration.videoParticipantsMaxCount, isPaused: false, isOwnScreencast: false, strings: self.presentationData.strings, nameDisplayOrder: self.presentationData.nameDisplayOrder, speaking: false, secondary: false, isTablet: false, icon: .none, text: .none, additionalText: nil, action: {}, contextAction: nil, getVideo: { _ in return nil }, getAudioLevel: nil)) tileItems.append(VoiceChatTileItem(account: self.context.account, peer: peer, videoEndpointId: "", videoReady: false, videoTimeouted: true, isVideoLimit: true, videoLimit: configuration.videoParticipantsMaxCount, isPaused: false, isOwnScreencast: false, strings: self.presentationData.strings, nameDisplayOrder: self.presentationData.nameDisplayOrder, speaking: false, secondary: false, isTablet: false, icon: .none, text: .none, additionalText: nil, action: {}, contextAction: nil, getVideo: { _ in return nil }, getAudioLevel: nil))
} else if !tileItems.isEmpty && !(self.callState?.isVideoEnabled ?? false) {
reachedLimit = true
} }
for member in callMembers.0 { for member in callMembers.0 {
@ -5110,11 +5114,11 @@ public final class VoiceChatController: ViewController {
updateLayout = true updateLayout = true
self.currentTileItems = gridTileItems self.currentTileItems = gridTileItems
if displayPanelVideos && !tileItems.isEmpty { if displayPanelVideos && !tileItems.isEmpty {
entries.insert(.tiles(tileItems, .pairs), at: 0) entries.insert(.tiles(tileItems, .pairs, configuration.videoParticipantsMaxCount, reachedLimit), at: 0)
} }
} else { } else {
if !tileItems.isEmpty { if !tileItems.isEmpty {
entries.insert(.tiles(tileItems, .pairs), at: 0) entries.insert(.tiles(tileItems, .pairs, configuration.videoParticipantsMaxCount, reachedLimit), at: 0)
} }
} }

View File

@ -181,12 +181,16 @@ final class VoiceChatTilesGridItem: ListViewItem {
let context: AccountContext let context: AccountContext
let tiles: [VoiceChatTileItem] let tiles: [VoiceChatTileItem]
let layoutMode: VoiceChatTileLayoutMode let layoutMode: VoiceChatTileLayoutMode
let videoLimit: Int32
let reachedLimit: Bool
let getIsExpanded: () -> Bool let getIsExpanded: () -> Bool
init(context: AccountContext, tiles: [VoiceChatTileItem], layoutMode: VoiceChatTileLayoutMode, getIsExpanded: @escaping () -> Bool) { init(context: AccountContext, tiles: [VoiceChatTileItem], layoutMode: VoiceChatTileLayoutMode, videoLimit: Int32, reachedLimit: Bool, getIsExpanded: @escaping () -> Bool) {
self.context = context self.context = context
self.tiles = tiles self.tiles = tiles
self.layoutMode = layoutMode self.layoutMode = layoutMode
self.videoLimit = videoLimit
self.reachedLimit = reachedLimit
self.getIsExpanded = getIsExpanded self.getIsExpanded = getIsExpanded
} }
@ -231,6 +235,8 @@ final class VoiceChatTilesGridItemNode: ListViewItemNode {
let backgroundNode: ASDisplayNode let backgroundNode: ASDisplayNode
let cornersNode: ASImageNode let cornersNode: ASImageNode
let limitLabel: TextNode
private var absoluteLocation: (CGRect, CGSize)? private var absoluteLocation: (CGRect, CGSize)?
var tileNodes: [VoiceChatTileItemNode] { var tileNodes: [VoiceChatTileItemNode] {
@ -248,10 +254,14 @@ final class VoiceChatTilesGridItemNode: ListViewItemNode {
self.cornersNode.displaysAsynchronously = false self.cornersNode.displaysAsynchronously = false
self.cornersNode.image = decorationCornersImage(top: true, bottom: false, dark: false) self.cornersNode.image = decorationCornersImage(top: true, bottom: false, dark: false)
self.limitLabel = TextNode()
self.limitLabel.alpha = 0.0
super.init(layerBacked: false, dynamicBounce: false) super.init(layerBacked: false, dynamicBounce: false)
self.addSubnode(self.backgroundNode) self.addSubnode(self.backgroundNode)
self.addSubnode(self.cornersNode) self.addSubnode(self.cornersNode)
self.addSubnode(self.limitLabel)
} }
override func animateFrameTransition(_ progress: CGFloat, _ currentValue: CGFloat) { override func animateFrameTransition(_ progress: CGFloat, _ currentValue: CGFloat) {
@ -274,10 +284,20 @@ final class VoiceChatTilesGridItemNode: ListViewItemNode {
func asyncLayout() -> (_ item: VoiceChatTilesGridItem, _ params: ListViewItemLayoutParams) -> (ListViewItemNodeLayout, () -> Void) { func asyncLayout() -> (_ item: VoiceChatTilesGridItem, _ params: ListViewItemLayoutParams) -> (ListViewItemNodeLayout, () -> Void) {
let currentItem = self.item let currentItem = self.item
let makeLabelLayout = TextNode.asyncLayout(self.limitLabel)
return { item, params in return { item, params in
let presentationData = item.context.sharedContext.currentPresentationData.with { $0 }
let (textLayout, textApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: presentationData.strings.VoiceChat_VideoParticipantsLimitExceededExtended(String(item.videoLimit)).string, font: Font.regular(13.0), textColor: UIColor(rgb: 0x8e8e93), paragraphAlignment: .center), maximumNumberOfLines: 3, truncationType: .end, constrainedSize: CGSize(width: params.width - 32.0, height: CGFloat.greatestFiniteMagnitude), lineSpacing: 0.25))
let rowCount = ceil(CGFloat(item.tiles.count) / 2.0) let rowCount = ceil(CGFloat(item.tiles.count) / 2.0)
let contentSize = CGSize(width: params.width, height: rowCount * (tileHeight + tileSpacing)) let gridSize = CGSize(width: params.width, height: rowCount * (tileHeight + tileSpacing))
var contentSize = gridSize
if item.reachedLimit {
contentSize.height += 10.0 + textLayout.size.height + 10.0
}
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: UIEdgeInsets()) let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: UIEdgeInsets())
return (layout, { [weak self] in return (layout, { [weak self] in
if let strongSelf = self { if let strongSelf = self {
strongSelf.item = item strongSelf.item = item
@ -295,22 +315,29 @@ final class VoiceChatTilesGridItemNode: ListViewItemNode {
strongSelf.tileGridNode = tileGridNode strongSelf.tileGridNode = tileGridNode
} }
if let (rect, size) = strongSelf.absoluteLocation { if let (rect, size) = strongSelf.absoluteLocation {
tileGridNode.updateAbsoluteRect(rect, within: size) tileGridNode.updateAbsoluteRect(rect, within: size)
} }
let transition: ContainedViewLayoutTransition = currentItem == nil ? .immediate : .animated(duration: 0.3, curve: .easeInOut) let transition: ContainedViewLayoutTransition = currentItem == nil ? .immediate : .animated(duration: 0.3, curve: .easeInOut)
let tileGridSize = tileGridNode.update(size: CGSize(width: params.width - params.leftInset - params.rightInset, height: params.availableHeight), layoutMode: item.layoutMode, items: item.tiles, transition: transition) let tileGridSize = tileGridNode.update(size: CGSize(width: params.width - params.leftInset - params.rightInset, height: params.availableHeight), layoutMode: item.layoutMode, items: item.tiles, transition: transition)
var backgroundSize = tileGridSize
if item.reachedLimit {
backgroundSize.height += 10.0 + textLayout.size.height + 10.0
}
if currentItem == nil { if currentItem == nil {
tileGridNode.frame = CGRect(x: params.leftInset, y: 0.0, width: tileGridSize.width, height: tileGridSize.height) tileGridNode.frame = CGRect(x: params.leftInset, y: 0.0, width: tileGridSize.width, height: tileGridSize.height)
strongSelf.backgroundNode.frame = tileGridNode.frame strongSelf.backgroundNode.frame = CGRect(origin: tileGridNode.frame.origin, size: backgroundSize)
strongSelf.cornersNode.frame = CGRect(x: params.leftInset, y: layout.size.height, width: tileGridSize.width, height: 50.0) strongSelf.cornersNode.frame = CGRect(x: params.leftInset, y: layout.size.height, width: tileGridSize.width, height: 50.0)
} else { } else {
transition.updateFrame(node: tileGridNode, frame: CGRect(origin: CGPoint(x: params.leftInset, y: 0.0), size: tileGridSize)) transition.updateFrame(node: tileGridNode, frame: CGRect(origin: CGPoint(x: params.leftInset, y: 0.0), size: tileGridSize))
transition.updateFrame(node: strongSelf.backgroundNode, frame: CGRect(origin: CGPoint(x: params.leftInset, y: 0.0), size: tileGridSize)) transition.updateFrame(node: strongSelf.backgroundNode, frame: CGRect(origin: tileGridNode.frame.origin, size: backgroundSize))
strongSelf.cornersNode.frame = CGRect(x: params.leftInset, y: layout.size.height, width: tileGridSize.width, height: 50.0) strongSelf.cornersNode.frame = CGRect(x: params.leftInset, y: layout.size.height, width: tileGridSize.width, height: 50.0)
} }
let _ = textApply()
transition.updateFrame(node: strongSelf.limitLabel, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((params.width - textLayout.size.width) / 2.0), y: gridSize.height + 10.0), size: textLayout.size))
transition.updateAlpha(node: strongSelf.limitLabel, alpha: item.reachedLimit ? 1.0 : 0.0)
} }
}) })
} }