diff --git a/LegacyComponents.xcodeproj/project.pbxproj b/LegacyComponents.xcodeproj/project.pbxproj index cf434889bd..d55c187ef6 100644 --- a/LegacyComponents.xcodeproj/project.pbxproj +++ b/LegacyComponents.xcodeproj/project.pbxproj @@ -1179,6 +1179,10 @@ D07BCC061F2B82D100ED97AA /* TGModernConversationTitleActivityIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = D07BCC041F2B82D100ED97AA /* TGModernConversationTitleActivityIndicator.m */; }; D0B6D3E01F5986DD003BBB35 /* TGModernConversationInputMicButton.h in Headers */ = {isa = PBXBuildFile; fileRef = D0B6D3DE1F5986DD003BBB35 /* TGModernConversationInputMicButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; D0B6D3E11F5986DD003BBB35 /* TGModernConversationInputMicButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B6D3DF1F5986DD003BBB35 /* TGModernConversationInputMicButton.m */; }; + D0BFAE5320AB33F900793CF2 /* TGIconSwitchView.m in Sources */ = {isa = PBXBuildFile; fileRef = D0BFAE5120AB33F700793CF2 /* TGIconSwitchView.m */; }; + D0BFAE5420AB33F900793CF2 /* TGIconSwitchView.h in Headers */ = {isa = PBXBuildFile; fileRef = D0BFAE5220AB33F800793CF2 /* TGIconSwitchView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D0BFAE5720AB34AB00793CF2 /* TGAnimationUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = D0BFAE5520AB34AA00793CF2 /* TGAnimationUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D0BFAE5820AB34AB00793CF2 /* TGAnimationUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = D0BFAE5620AB34AA00793CF2 /* TGAnimationUtils.m */; }; D0F7C9C41F55DA49005B255A /* TGVideoCameraMovieRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = D0F7C9C21F55DA49005B255A /* TGVideoCameraMovieRecorder.h */; settings = {ATTRIBUTES = (Public, ); }; }; D0F7C9C51F55DA49005B255A /* TGVideoCameraMovieRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = D0F7C9C31F55DA49005B255A /* TGVideoCameraMovieRecorder.m */; }; D0F7C9C81F55DA83005B255A /* TGVideoCameraGLRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = D0F7C9C61F55DA83005B255A /* TGVideoCameraGLRenderer.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -2367,6 +2371,10 @@ D07BCC041F2B82D100ED97AA /* TGModernConversationTitleActivityIndicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGModernConversationTitleActivityIndicator.m; sourceTree = ""; }; D0B6D3DE1F5986DD003BBB35 /* TGModernConversationInputMicButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGModernConversationInputMicButton.h; sourceTree = ""; }; D0B6D3DF1F5986DD003BBB35 /* TGModernConversationInputMicButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGModernConversationInputMicButton.m; sourceTree = ""; }; + D0BFAE5120AB33F700793CF2 /* TGIconSwitchView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGIconSwitchView.m; sourceTree = ""; }; + D0BFAE5220AB33F800793CF2 /* TGIconSwitchView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGIconSwitchView.h; sourceTree = ""; }; + D0BFAE5520AB34AA00793CF2 /* TGAnimationUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGAnimationUtils.h; sourceTree = ""; }; + D0BFAE5620AB34AA00793CF2 /* TGAnimationUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGAnimationUtils.m; sourceTree = ""; }; D0EB42021F3142F400838FE6 /* LegacyComponentsResources.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = LegacyComponentsResources.bundle; path = Resources/LegacyComponentsResources.bundle; sourceTree = ""; }; D0F7C9C21F55DA49005B255A /* TGVideoCameraMovieRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGVideoCameraMovieRecorder.h; sourceTree = ""; }; D0F7C9C31F55DA49005B255A /* TGVideoCameraMovieRecorder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGVideoCameraMovieRecorder.m; sourceTree = ""; }; @@ -2589,6 +2597,8 @@ D07BC9671F2A3F5C00ED97AA /* TGCache.m */, D07BCAAC1F2B45DA00ED97AA /* TGFileUtils.h */, D0F7C9D41F55DB2D005B255A /* TGLiveUploadInterface.h */, + D0BFAE5520AB34AA00793CF2 /* TGAnimationUtils.h */, + D0BFAE5620AB34AA00793CF2 /* TGAnimationUtils.m */, ); name = Utils; sourceTree = ""; @@ -2787,6 +2797,8 @@ D02660851F34B9B1000E2DC5 /* TGSearchBar.m */, D02660881F34B9F9000E2DC5 /* TGSearchDisplayMixin.h */, D02660891F34B9F9000E2DC5 /* TGSearchDisplayMixin.m */, + D0BFAE5220AB33F800793CF2 /* TGIconSwitchView.h */, + D0BFAE5120AB33F700793CF2 /* TGIconSwitchView.m */, ); name = "Basic UI Components"; sourceTree = ""; @@ -4090,6 +4102,7 @@ D01779491F20FFF60044446D /* TGMediaAssetMoment.h in Headers */, D07BCAED1F2B507600ED97AA /* TGAttachmentVideoCell.h in Headers */, 09E97B571F97C11700526020 /* TGTooltipView.h in Headers */, + D0BFAE5720AB34AB00793CF2 /* TGAnimationUtils.h in Headers */, D07BC9251F2A380D00ED97AA /* TGPaintSwatch.h in Headers */, D07BC91D1F2A380D00ED97AA /* TGPaintShader.h in Headers */, 09F916B11F5D9A4E00E0AEFA /* TGModernConversationAlphacodeAssociatedPanel.h in Headers */, @@ -4214,6 +4227,7 @@ D01778271F1F961D0044446D /* TGMessageEntitiesAttachment.h in Headers */, D07BC9791F2A471000ED97AA /* TGStickerKeyboardTabPanel.h in Headers */, D017775B1F1F8FE60044446D /* PSKeyValueReader.h in Headers */, + D0BFAE5420AB33F900793CF2 /* TGIconSwitchView.h in Headers */, D0177B201F2641B10044446D /* PGCameraShotMetadata.h in Headers */, D0177A111F213B440044446D /* JNWSpringAnimation.h in Headers */, D07BC8C31F2A37EC00ED97AA /* TGPhotoPaintController.h in Headers */, @@ -4640,6 +4654,7 @@ D04269161F586EC80037ECE8 /* TGVideoMessageCaptureController.m in Sources */, D07BCBF81F2B72DC00ED97AA /* STKQueueEntry.m in Sources */, D07BC81F1F2A2C0B00ED97AA /* PGPhotoSharpenPass.m in Sources */, + D0BFAE5320AB33F900793CF2 /* TGIconSwitchView.m in Sources */, D02660871F34B9B1000E2DC5 /* TGSearchBar.m in Sources */, D07BC9591F2A3EBF00ED97AA /* TGModernConversationAssociatedInputPanel.m in Sources */, D01778561F1F961D0044446D /* TGLocalMessageMetaMediaAttachment.m in Sources */, @@ -4745,6 +4760,7 @@ D07BCA081F2A9A2B00ED97AA /* TGMediaPickerGalleryVideoItemView.m in Sources */, D07BC9221F2A380D00ED97AA /* TGPaintSlice.m in Sources */, D07BC9BB1F2A705D00ED97AA /* TGPhotoFilterCell.m in Sources */, + D0BFAE5820AB34AB00793CF2 /* TGAnimationUtils.m in Sources */, D0177A571F21F7F40044446D /* TGDoubleTapGestureRecognizer.m in Sources */, D07BC7FF1F2A2C0B00ED97AA /* PGFadeTool.m in Sources */, 0916FEAB20A1EBFA0084A755 /* TGPassportMRZ.m in Sources */, diff --git a/LegacyComponents/LegacyComponents.h b/LegacyComponents/LegacyComponents.h index 3221de0911..fbbbf1fa46 100644 --- a/LegacyComponents/LegacyComponents.h +++ b/LegacyComponents/LegacyComponents.h @@ -322,3 +322,5 @@ FOUNDATION_EXPORT const unsigned char LegacyComponentsVersionString[]; #import #import #import + +#import diff --git a/LegacyComponents/LegacyComponentsInternal.m b/LegacyComponents/LegacyComponentsInternal.m index cd4cfe2b73..5ef77d899a 100644 --- a/LegacyComponents/LegacyComponentsInternal.m +++ b/LegacyComponents/LegacyComponentsInternal.m @@ -72,6 +72,9 @@ int iosMajorVersion() case 11: version = 11; break; + case 12: + version = 12; + break; default: version = 9; break; diff --git a/LegacyComponents/Resources/LegacyComponentsResources.bundle/PermissionSwitchOff@2x.png b/LegacyComponents/Resources/LegacyComponentsResources.bundle/PermissionSwitchOff@2x.png new file mode 100644 index 0000000000..3d440aca23 Binary files /dev/null and b/LegacyComponents/Resources/LegacyComponentsResources.bundle/PermissionSwitchOff@2x.png differ diff --git a/LegacyComponents/Resources/LegacyComponentsResources.bundle/PermissionSwitchOff@3x.png b/LegacyComponents/Resources/LegacyComponentsResources.bundle/PermissionSwitchOff@3x.png new file mode 100644 index 0000000000..721dd962d4 Binary files /dev/null and b/LegacyComponents/Resources/LegacyComponentsResources.bundle/PermissionSwitchOff@3x.png differ diff --git a/LegacyComponents/Resources/LegacyComponentsResources.bundle/PermissionSwitchOn@2x.png b/LegacyComponents/Resources/LegacyComponentsResources.bundle/PermissionSwitchOn@2x.png new file mode 100644 index 0000000000..0731b92a71 Binary files /dev/null and b/LegacyComponents/Resources/LegacyComponentsResources.bundle/PermissionSwitchOn@2x.png differ diff --git a/LegacyComponents/Resources/LegacyComponentsResources.bundle/PermissionSwitchOn@3x.png b/LegacyComponents/Resources/LegacyComponentsResources.bundle/PermissionSwitchOn@3x.png new file mode 100644 index 0000000000..b3855cbcfe Binary files /dev/null and b/LegacyComponents/Resources/LegacyComponentsResources.bundle/PermissionSwitchOn@3x.png differ diff --git a/LegacyComponents/TGAnimationUtils.h b/LegacyComponents/TGAnimationUtils.h new file mode 100644 index 0000000000..c220a6f334 --- /dev/null +++ b/LegacyComponents/TGAnimationUtils.h @@ -0,0 +1,22 @@ +#import + +#ifdef __cplusplus +extern "C" { +#endif + +extern NSString *kCAMediaTimingFunctionSpring; + +#ifdef __cplusplus +} +#endif + +@interface CALayer (AnimationUtils) + +- (void)animateAlphaFrom:(CGFloat)from to:(CGFloat)to duration:(NSTimeInterval)duration timingFunction:(NSString *)timingFunction removeOnCompletion:(bool)removeOnCompletion completion:(void (^)(bool))completion; + +- (void)animateScaleFrom:(CGFloat)from to:(CGFloat)to duration:(NSTimeInterval)duration timingFunction:(NSString *)timingFunction removeOnCompletion:(bool)removeOnCompletion completion:(void (^)(bool))completion; +- (void)animateSpringScaleFrom:(CGFloat)from to:(CGFloat)to duration:(NSTimeInterval)duration removeOnCompletion:(bool)removeOnCompletion completion:(void (^)(bool))completion; + +- (void)animatePositionFrom:(CGPoint)from to:(CGPoint)to duration:(NSTimeInterval)duration timingFunction:(NSString *)timingFunction removeOnCompletion:(bool)removeOnCompletion completion:(void (^)(bool))completion; + +@end diff --git a/LegacyComponents/TGAnimationUtils.m b/LegacyComponents/TGAnimationUtils.m new file mode 100644 index 0000000000..ddae4ce14c --- /dev/null +++ b/LegacyComponents/TGAnimationUtils.m @@ -0,0 +1,146 @@ +#import "TGAnimationUtils.h" + +#import + +NSString *kCAMediaTimingFunctionSpring = @"kCAMediaTimingFunctionSpring"; + +@interface TGLayerAnimationDelegate : NSObject { + void (^_completion)(bool); +} + +@end + +@implementation TGLayerAnimationDelegate + +- (instancetype)initWithCompletion:(void (^)(bool))completion { + self = [super init]; + if (self != nil) { + _completion = [completion copy]; + } + return self; +} + +- (void)animationDidStop:(__unused CAAnimation *)anim finished:(BOOL)flag { + if (_completion) { + _completion(flag); + } +} + +@end + +@interface CAAnimation (AnimationUtils) + +@end + +@implementation CAAnimation (AnimationUtils) + +- (void)setCompletionBlock:(void (^)(bool))block { + self.delegate = [[TGLayerAnimationDelegate alloc] initWithCompletion:block]; +} + +@end + + +static CABasicAnimation * _Nonnull makeSpringAnimation(NSString * _Nonnull keyPath) { + CASpringAnimation *springAnimation = [CASpringAnimation animationWithKeyPath:keyPath]; + springAnimation.mass = 3.0f; + springAnimation.stiffness = 1000.0f; + springAnimation.damping = 500.0f; + springAnimation.duration = 0.5;//springAnimation.settlingDuration; + springAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; + return springAnimation; +} + +static CABasicAnimation * _Nonnull makeExtendedSpringAnimation(NSString * _Nonnull keyPath, CGFloat damping) { + CASpringAnimation *springAnimation = [CASpringAnimation animationWithKeyPath:keyPath]; + springAnimation.mass = 3.0f; + springAnimation.stiffness = 1000.0f; + springAnimation.damping = damping; + springAnimation.duration = 0.5;//springAnimation.settlingDuration; + springAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; + return springAnimation; +} + +@implementation CALayer (AnimationUtils) + +- (void)animateFrom:(id)from to:(id)to keyPath:(NSString *)keyPath timingFunction:(NSString *)timingFunction duration:(NSTimeInterval)duration removeOnCompletion:(bool)removeOnCompletion completion:(void (^)(bool))completion { + if ([timingFunction isEqualToString:kCAMediaTimingFunctionSpring]) { + CABasicAnimation *animation = makeSpringAnimation(keyPath); + animation.fromValue = from; + animation.toValue = to; + animation.removedOnCompletion = removeOnCompletion; + animation.fillMode = kCAFillModeForwards; + if (completion != nil) { + [animation setCompletionBlock:completion]; + } + + float k = (float)TGAnimationSpeedFactor(); + float speed = 1.0f; + if (k != 0 && k != 1) { + speed = 1.0f / k; + } + + animation.speed = speed * (float)(animation.duration / duration); + + [self addAnimation:animation forKey:keyPath]; + } else { + float k = (float)TGAnimationSpeedFactor(); + float speed = 1.0f; + if (k != 0 && k != 1) { + speed = 1.0f / k; + } + + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:keyPath]; + animation.fromValue = from; + animation.toValue = to; + animation.duration = duration; + animation.timingFunction = [CAMediaTimingFunction functionWithName: timingFunction]; + animation.removedOnCompletion = removeOnCompletion; + animation.fillMode = kCAFillModeForwards; + animation.speed = speed; + if (completion != nil) { + [animation setCompletionBlock:completion]; + } + + [self addAnimation:animation forKey:keyPath]; + } +} + +- (void)animateSpringFrom:(id)from to:(id)to keyPath:(NSString *)keyPath duration:(NSTimeInterval)duration removeOnCompletion:(bool)removeOnCompletion completion:(void (^)(bool))completion { + CABasicAnimation *animation = makeExtendedSpringAnimation(keyPath, 75.0f); + animation.fromValue = from; + animation.toValue = to; + animation.removedOnCompletion = removeOnCompletion; + animation.fillMode = kCAFillModeForwards; + if (completion != nil) { + [animation setCompletionBlock:completion]; + } + + float k = (float)TGAnimationSpeedFactor(); + float speed = 1.0f; + if (k != 0 && k != 1) { + speed = 1.0f / k; + } + + animation.speed = speed * (float)(animation.duration / duration); + + [self addAnimation:animation forKey:keyPath]; +} + +- (void)animateAlphaFrom:(CGFloat)from to:(CGFloat)to duration:(NSTimeInterval)duration timingFunction:(NSString *)timingFunction removeOnCompletion:(bool)removeOnCompletion completion:(void (^)(bool))completion { + [self animateFrom:@(from) to:@(to) keyPath:@"opacity" timingFunction:timingFunction duration:duration removeOnCompletion:removeOnCompletion completion:completion]; +} + +- (void)animateScaleFrom:(CGFloat)from to:(CGFloat)to duration:(NSTimeInterval)duration timingFunction:(NSString *)timingFunction removeOnCompletion:(bool)removeOnCompletion completion:(void (^)(bool))completion { + [self animateFrom:@(from) to:@(to) keyPath:@"transform.scale" timingFunction:timingFunction duration:duration removeOnCompletion:removeOnCompletion completion:completion]; +} + +- (void)animateSpringScaleFrom:(CGFloat)from to:(CGFloat)to duration:(NSTimeInterval)duration removeOnCompletion:(bool)removeOnCompletion completion:(void (^)(bool))completion { + [self animateSpringFrom:@(from) to:@(to) keyPath:@"transform.scale" duration:duration removeOnCompletion:removeOnCompletion completion:completion]; +} + +- (void)animatePositionFrom:(CGPoint)from to:(CGPoint)to duration:(NSTimeInterval)duration timingFunction:(NSString *)timingFunction removeOnCompletion:(bool)removeOnCompletion completion:(void (^)(bool))completion { + [self animateFrom:[NSValue valueWithCGPoint:from] to:[NSValue valueWithCGPoint:to] keyPath:@"position" timingFunction:timingFunction duration:duration removeOnCompletion:removeOnCompletion completion:completion]; +} + +@end diff --git a/LegacyComponents/TGIconSwitchView.h b/LegacyComponents/TGIconSwitchView.h new file mode 100644 index 0000000000..0e935bf857 --- /dev/null +++ b/LegacyComponents/TGIconSwitchView.h @@ -0,0 +1,6 @@ +#import +#import + +@interface TGIconSwitchView : UISwitch + +@end diff --git a/LegacyComponents/TGIconSwitchView.m b/LegacyComponents/TGIconSwitchView.m new file mode 100644 index 0000000000..15e031df03 --- /dev/null +++ b/LegacyComponents/TGIconSwitchView.m @@ -0,0 +1,123 @@ +#import "TGIconSwitchView.h" + +#import + +#import "LegacyComponentsInternal.h" + +#import "TGAnimationUtils.h" + +#import + +static const void *positionChangedKey = &positionChangedKey; + +@interface TGBaseIconSwitch : CALayer + +@end + +@implementation TGBaseIconSwitch + +- (void)setPosition:(CGPoint)center { + [super setPosition:center]; + + void (^block)(CGPoint) = objc_getAssociatedObject(self, positionChangedKey); + if (block) { + block(center); + } +} + +@end + +@interface TGIconSwitchView () { + UIImageView *_offIconView; + UIImageView *_onIconView; + + bool _stateIsOn; +} + +@end + +@implementation TGIconSwitchView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self != nil) { + if (iosMajorVersion() >= 8) { + _offIconView = [[UIImageView alloc] initWithImage:TGComponentsImageNamed(@"PermissionSwitchOff.png")]; + _onIconView = [[UIImageView alloc] initWithImage:TGComponentsImageNamed(@"PermissionSwitchOn.png")]; + self.layer.cornerRadius = 17.0f; + self.backgroundColor = [UIColor redColor]; + self.tintColor = [UIColor redColor]; + UIView *handleView = self.subviews[0].subviews.lastObject; + + static Class subclass; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + subclass = freedomMakeClass([handleView.layer class], [TGBaseIconSwitch class]); + object_setClass(handleView.layer, subclass); + }); + + _offIconView.frame = CGRectOffset(_offIconView.bounds, TGScreenPixelFloor(21.5f), TGScreenPixelFloor(14.5f)); + _onIconView.frame = CGRectOffset(_onIconView.bounds, 20.0f, 15.0f); + [handleView addSubview:_onIconView]; + [handleView addSubview:_offIconView]; + + _onIconView.alpha = 0.0f; + + [self addTarget:self action:@selector(currentValueChanged) forControlEvents:UIControlEventValueChanged]; + + __weak TGIconSwitchView *weakSelf = self; + void (^block)(CGPoint) = ^(CGPoint point) { + __strong TGIconSwitchView *strongSelf = weakSelf; + if (strongSelf != nil) { + [strongSelf updateState:point.x > 30.0 animated:true force:false]; + } + }; + objc_setAssociatedObject(handleView.layer, positionChangedKey, [block copy], OBJC_ASSOCIATION_RETAIN); + } + } + return self; +} + +- (void)setOn:(BOOL)on animated:(BOOL)animated { + [super setOn:on animated:animated]; + + [self updateState:on animated:animated force:true]; +} + +- (void)updateState:(bool)on animated:(bool)animated force:(bool)force { + if (_stateIsOn != on || force) { + _stateIsOn = on; + + if (on) { + _onIconView.alpha = 1.0f; + _offIconView.alpha = 0.0f; + } else { + _onIconView.alpha = 0.0f; + _offIconView.alpha = 1.0f; + } + + if (animated) { + if (on) { + [_offIconView.layer animateAlphaFrom:1.0f to:0.0f duration:0.25 timingFunction:kCAMediaTimingFunctionEaseInEaseOut removeOnCompletion:true completion:nil]; + [_offIconView.layer animateScaleFrom:1.0f to:0.2f duration:0.251 timingFunction:kCAMediaTimingFunctionEaseInEaseOut removeOnCompletion:true completion:nil]; + [_onIconView.layer animateAlphaFrom:0.0f to:1.0f duration:0.25 timingFunction:kCAMediaTimingFunctionEaseInEaseOut removeOnCompletion:true completion:nil]; + [_onIconView.layer animateSpringScaleFrom:0.2f to:1.0f duration:0.5 removeOnCompletion:true completion:nil]; + } else { + [_onIconView.layer animateAlphaFrom:1.0f to:0.0f duration:0.25 timingFunction:kCAMediaTimingFunctionEaseInEaseOut removeOnCompletion:true completion:nil]; + [_onIconView.layer animateScaleFrom:1.0f to:0.2f duration:0.251 timingFunction:kCAMediaTimingFunctionEaseInEaseOut removeOnCompletion:true completion:nil]; + [_offIconView.layer animateAlphaFrom:0.0f to:1.0f duration:0.25 timingFunction:kCAMediaTimingFunctionEaseInEaseOut removeOnCompletion:true completion:nil]; + [_offIconView.layer animateSpringScaleFrom:0.2f to:1.0f duration:0.5 removeOnCompletion:true completion:nil]; + } + } + } +} + +- (void)currentValueChanged { + [self updateState:self.isOn animated:true force:false]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; +} + +@end diff --git a/LegacyComponents/TGMediaAssetsController.m b/LegacyComponents/TGMediaAssetsController.m index 9c6a9c7ada..f2b75570e8 100644 --- a/LegacyComponents/TGMediaAssetsController.m +++ b/LegacyComponents/TGMediaAssetsController.m @@ -105,7 +105,7 @@ if ([group isKindOfClass:[TGMediaAssetGroup class]]) { pickerController = [[TGMediaAssetsPickerController alloc] initWithContext:strongController->_context assetsLibrary:strongController.assetsLibrary assetGroup:group intent:intent selectionContext:strongController->_selectionContext editingContext:strongController->_editingContext saveEditedPhotos:strongController->_saveEditedPhotos]; - pickerController.pallete = assetsController.pallete; + pickerController.pallete = strongController.pallete; } else if ([group isKindOfClass:[TGMediaAssetMomentList class]]) { diff --git a/LegacyComponents/TGMenuSheetController.h b/LegacyComponents/TGMenuSheetController.h index d9a600adde..38ea38aeb8 100644 --- a/LegacyComponents/TGMenuSheetController.h +++ b/LegacyComponents/TGMenuSheetController.h @@ -40,6 +40,7 @@ @property (nonatomic, assign) bool narrowInLandscape; @property (nonatomic, assign) bool inhibitPopoverPresentation; @property (nonatomic, assign) bool stickWithSpecifiedParentController; +@property (nonatomic, assign) bool forceFullScreen; @property (nonatomic, readonly) NSArray *itemViews; diff --git a/LegacyComponents/TGMenuSheetController.m b/LegacyComponents/TGMenuSheetController.m index 722e2a6fee..f192f38c83 100644 --- a/LegacyComponents/TGMenuSheetController.m +++ b/LegacyComponents/TGMenuSheetController.m @@ -124,7 +124,7 @@ typedef enum [super loadView]; self.view = [[TGMenuSheetContainerView alloc] initWithFrame:self.view.frame]; - if ([_context currentSizeClass] == UIUserInterfaceSizeClassCompact) + if ([_context currentSizeClass] == UIUserInterfaceSizeClassCompact || _forceFullScreen) { self.view.frame = [_context fullscreenBounds]; self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; @@ -229,7 +229,7 @@ typedef enum [strongSelf repositionMenuWithReferenceSize:[strongSelf->_context fullscreenBounds].size]; }; - if (animated && compact) + if (animated && (compact || _forceFullScreen)) { TGMenuSheetView *sheetView = _sheetView; @@ -443,10 +443,11 @@ typedef enum UIUserInterfaceSizeClass sizeClass = [self sizeClass]; bool compact = (sizeClass == UIUserInterfaceSizeClassCompact); - if (compact) + if (compact || _forceFullScreen) self.modalPresentationStyle = UIModalPresentationFullScreen; - else + else { self.modalPresentationStyle = UIModalPresentationPopover; + } if (!self.stickWithSpecifiedParentController && viewController.navigationController != nil) viewController = viewController.navigationController.parentViewController ?: viewController.navigationController; @@ -477,7 +478,7 @@ typedef enum _sheetView.menuWidth = referenceSize.width; } - if (compact) + if (compact || _forceFullScreen) { [viewController addChildViewController:self]; [viewController.view addSubview:self.view]; @@ -561,7 +562,7 @@ typedef enum if (self.willDismiss != nil) self.willDismiss(manual); - if (compact) + if (compact || _forceFullScreen) { if (iosMajorVersion() >= 7 && [self.parentViewController isKindOfClass:[TGNavigationController class]]) ((TGNavigationController *)self.parentViewController).interactivePopGestureRecognizer.enabled = true; @@ -697,7 +698,7 @@ typedef enum if (_sheetView == nil) return; - if (_hasSwipeGesture && [self sizeClass] != UIUserInterfaceSizeClassRegular) + if (_hasSwipeGesture && ([self sizeClass] != UIUserInterfaceSizeClassRegular || _forceFullScreen)) { if (_gestureRecognizer != nil) { @@ -858,45 +859,36 @@ typedef enum UIUserInterfaceSizeClass previousClass = [self sizeClass]; _sizeClass = sizeClass; - [_sheetView updateTraitsWithSizeClass:[self sizeClass]]; + [_sheetView updateTraitsWithSizeClass:_forceFullScreen ? UIUserInterfaceSizeClassCompact : [self sizeClass]]; if (_presented && previousClass != [self sizeClass]) { - switch (sizeClass) - { - case UIUserInterfaceSizeClassRegular: + if (sizeClass == UIUserInterfaceSizeClassRegular && !_forceFullScreen) { + _dimView.hidden = true; + + self.modalPresentationStyle = UIModalPresentationPopover; + + [self.view removeFromSuperview]; + [self removeFromParentViewController]; + + [self _presentPopoverInController:_parentController]; + + if (iosMajorVersion() >= 7 && [_parentController isKindOfClass:[TGNavigationController class]]) + ((TGNavigationController *)_parentController).interactivePopGestureRecognizer.enabled = true; + } else { + _dimView.hidden = false; + + [self.presentingViewController dismissViewControllerAnimated:false completion:^ { - _dimView.hidden = true; + self.modalPresentationStyle = UIModalPresentationFullScreen; - self.modalPresentationStyle = UIModalPresentationPopover; - - [self.view removeFromSuperview]; - [self removeFromParentViewController]; - - [self _presentPopoverInController:_parentController]; + [_parentController addChildViewController:self]; + [_parentController.view addSubview:self.view]; + [self.view setNeedsLayout]; if (iosMajorVersion() >= 7 && [_parentController isKindOfClass:[TGNavigationController class]]) - ((TGNavigationController *)_parentController).interactivePopGestureRecognizer.enabled = true; - } - break; - - default: - { - _dimView.hidden = false; - - [self.presentingViewController dismissViewControllerAnimated:false completion:^ - { - self.modalPresentationStyle = UIModalPresentationFullScreen; - - [_parentController addChildViewController:self]; - [_parentController.view addSubview:self.view]; - [self.view setNeedsLayout]; - - if (iosMajorVersion() >= 7 && [_parentController isKindOfClass:[TGNavigationController class]]) - ((TGNavigationController *)_parentController).interactivePopGestureRecognizer.enabled = false; - }]; - } - break; + ((TGNavigationController *)_parentController).interactivePopGestureRecognizer.enabled = false; + }]; } } @@ -907,7 +899,7 @@ typedef enum - (void)viewWillLayoutSubviews { - if ([self sizeClass] == UIUserInterfaceSizeClassRegular || [self isInPopover]) + if (([self sizeClass] == UIUserInterfaceSizeClassRegular || [self isInPopover]) && !_forceFullScreen) { _sheetView.menuWidth = TGMenuSheetPadMenuWidth; @@ -921,8 +913,13 @@ typedef enum else { CGSize referenceSize = TGIsPad() ? _parentController.view.bounds.size : [_context fullscreenBounds].size; + CGFloat viewWidth = self.view.frame.size.width; + + if ([self sizeClass] == UIUserInterfaceSizeClassRegular) { + referenceSize.width = TGMenuSheetPadMenuWidth; + } - _containerView.frame = CGRectMake(_containerView.frame.origin.x, _containerView.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height); + _containerView.frame = CGRectMake(_containerView.frame.origin.x, _containerView.frame.origin.y, viewWidth, self.view.frame.size.height); _dimView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); _sheetView.safeAreaInset = [self safeAreaInsetForOrientation:self.interfaceOrientation]; @@ -958,7 +955,7 @@ typedef enum - (void)repositionMenuWithReferenceSize:(CGSize)referenceSize { - if ([self sizeClass] == UIUserInterfaceSizeClassRegular) + if ([self sizeClass] == UIUserInterfaceSizeClassRegular && !_forceFullScreen) return; UIEdgeInsets safeAreaInset = [self safeAreaInsetForOrientation:self.interfaceOrientation]; diff --git a/LegacyComponents/TGNavigationController.m b/LegacyComponents/TGNavigationController.m index 911c56bb0d..f3c907db29 100644 --- a/LegacyComponents/TGNavigationController.m +++ b/LegacyComponents/TGNavigationController.m @@ -183,18 +183,24 @@ if ([TGViewController hasTallScreen] && _becomeActiveObserver == nil && _enterBackgroundObserver == nil) { + __weak TGNavigationController *weakSelf = self; _enterBackgroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil queue:nil usingBlock:^(__unused NSNotification * _Nonnull note) { - [[NSNotificationCenter defaultCenter] removeObserver:_enterBackgroundObserver]; - _enterBackgroundObserver = nil; - - if (_becomeActiveObserver == nil) - { - _becomeActiveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) + __strong TGNavigationController *strongSelf = weakSelf; + if (strongSelf != nil) { + [[NSNotificationCenter defaultCenter] removeObserver:strongSelf->_enterBackgroundObserver]; + strongSelf->_enterBackgroundObserver = nil; + + if (strongSelf->_becomeActiveObserver == nil) { - if ([TGViewController hasTallScreen]) - _fixNextInteractiveTransition = true; - }]; + strongSelf->_becomeActiveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { + __strong TGNavigationController *strongSelf = weakSelf; + if (strongSelf != nil) { + if ([TGViewController hasTallScreen]) + strongSelf->_fixNextInteractiveTransition = true; + } + }]; + } } }]; }