From ff0d334f190e6bc88e5029564cfd2014e1474a48 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 12 Sep 2017 10:41:47 +0300 Subject: [PATCH] no message --- LegacyComponents.xcodeproj/project.pbxproj | 24 + LegacyComponents/LegacyComponents.h | 2 + .../TwitchPlayerInject.js | 5 + LegacyComponents/TGAlphacode.h | 12 + LegacyComponents/TGAlphacode.m | 14 + LegacyComponents/TGAlphacodePanelCell.h | 10 + LegacyComponents/TGAlphacodePanelCell.m | 93 ++++ LegacyComponents/TGCheckButtonView.h | 2 + LegacyComponents/TGCheckButtonView.m | 74 ++- .../TGMediaPickerCaptionInputPanel.h | 3 + .../TGMediaPickerCaptionInputPanel.m | 43 +- .../TGMediaPickerGalleryVideoScrubber.m | 54 +- .../TGMediaPickerGalleryVideoTrimView.m | 98 ++-- ...dernConversationAlphacodeAssociatedPanel.h | 13 + ...dernConversationAlphacodeAssociatedPanel.m | 469 ++++++++++++++++++ LegacyComponents/TGNavigationBar.m | 26 +- LegacyComponents/TGPhotoCaptionInputMixin.m | 70 +++ LegacyComponents/TGSuggestionContext.h | 1 + 18 files changed, 901 insertions(+), 112 deletions(-) create mode 100644 LegacyComponents/TGAlphacode.h create mode 100644 LegacyComponents/TGAlphacode.m create mode 100644 LegacyComponents/TGAlphacodePanelCell.h create mode 100644 LegacyComponents/TGAlphacodePanelCell.m create mode 100644 LegacyComponents/TGModernConversationAlphacodeAssociatedPanel.h create mode 100644 LegacyComponents/TGModernConversationAlphacodeAssociatedPanel.m diff --git a/LegacyComponents.xcodeproj/project.pbxproj b/LegacyComponents.xcodeproj/project.pbxproj index 102108dc7a..d103069a12 100644 --- a/LegacyComponents.xcodeproj/project.pbxproj +++ b/LegacyComponents.xcodeproj/project.pbxproj @@ -16,6 +16,12 @@ 09750FC61F30DD52001B9886 /* TGClipboardGalleryPhotoItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 09750FC41F30DD52001B9886 /* TGClipboardGalleryPhotoItem.m */; }; 09750FCD1F30E53A001B9886 /* TGClipboardGalleryMixin.h in Headers */ = {isa = PBXBuildFile; fileRef = 09750FCB1F30E53A001B9886 /* TGClipboardGalleryMixin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 09750FCE1F30E53A001B9886 /* TGClipboardGalleryMixin.m in Sources */ = {isa = PBXBuildFile; fileRef = 09750FCC1F30E53A001B9886 /* TGClipboardGalleryMixin.m */; }; + 09F916AD1F5D9A4E00E0AEFA /* TGAlphacode.h in Headers */ = {isa = PBXBuildFile; fileRef = 09F916A71F5D9A4E00E0AEFA /* TGAlphacode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 09F916AE1F5D9A4E00E0AEFA /* TGAlphacode.m in Sources */ = {isa = PBXBuildFile; fileRef = 09F916A81F5D9A4E00E0AEFA /* TGAlphacode.m */; }; + 09F916AF1F5D9A4E00E0AEFA /* TGAlphacodePanelCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 09F916A91F5D9A4E00E0AEFA /* TGAlphacodePanelCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 09F916B01F5D9A4E00E0AEFA /* TGAlphacodePanelCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 09F916AA1F5D9A4E00E0AEFA /* TGAlphacodePanelCell.m */; }; + 09F916B11F5D9A4E00E0AEFA /* TGModernConversationAlphacodeAssociatedPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = 09F916AB1F5D9A4E00E0AEFA /* TGModernConversationAlphacodeAssociatedPanel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 09F916B21F5D9A4E00E0AEFA /* TGModernConversationAlphacodeAssociatedPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = 09F916AC1F5D9A4E00E0AEFA /* TGModernConversationAlphacodeAssociatedPanel.m */; }; 09FAA0B31F42F0E90099E8E7 /* TGEmbedTwitchPlayerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 09FAA0B11F42F0E90099E8E7 /* TGEmbedTwitchPlayerView.h */; }; 09FAA0B41F42F0E90099E8E7 /* TGEmbedTwitchPlayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 09FAA0B21F42F0E90099E8E7 /* TGEmbedTwitchPlayerView.m */; }; D017772C1F1F8F100044446D /* LegacyComponents.h in Headers */ = {isa = PBXBuildFile; fileRef = D017772A1F1F8F100044446D /* LegacyComponents.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1127,6 +1133,12 @@ 09750FC41F30DD52001B9886 /* TGClipboardGalleryPhotoItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGClipboardGalleryPhotoItem.m; sourceTree = ""; }; 09750FCB1F30E53A001B9886 /* TGClipboardGalleryMixin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGClipboardGalleryMixin.h; sourceTree = ""; }; 09750FCC1F30E53A001B9886 /* TGClipboardGalleryMixin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGClipboardGalleryMixin.m; sourceTree = ""; }; + 09F916A71F5D9A4E00E0AEFA /* TGAlphacode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGAlphacode.h; sourceTree = ""; }; + 09F916A81F5D9A4E00E0AEFA /* TGAlphacode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGAlphacode.m; sourceTree = ""; }; + 09F916A91F5D9A4E00E0AEFA /* TGAlphacodePanelCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGAlphacodePanelCell.h; sourceTree = ""; }; + 09F916AA1F5D9A4E00E0AEFA /* TGAlphacodePanelCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGAlphacodePanelCell.m; sourceTree = ""; }; + 09F916AB1F5D9A4E00E0AEFA /* TGModernConversationAlphacodeAssociatedPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGModernConversationAlphacodeAssociatedPanel.h; sourceTree = ""; }; + 09F916AC1F5D9A4E00E0AEFA /* TGModernConversationAlphacodeAssociatedPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGModernConversationAlphacodeAssociatedPanel.m; sourceTree = ""; }; 09FAA0B11F42F0E90099E8E7 /* TGEmbedTwitchPlayerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGEmbedTwitchPlayerView.h; sourceTree = ""; }; 09FAA0B21F42F0E90099E8E7 /* TGEmbedTwitchPlayerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGEmbedTwitchPlayerView.m; sourceTree = ""; }; D01777271F1F8F100044446D /* LegacyComponents.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LegacyComponents.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -3378,6 +3390,12 @@ D07BC9451F2A3E9900ED97AA /* Suggestions */ = { isa = PBXGroup; children = ( + 09F916A71F5D9A4E00E0AEFA /* TGAlphacode.h */, + 09F916A81F5D9A4E00E0AEFA /* TGAlphacode.m */, + 09F916A91F5D9A4E00E0AEFA /* TGAlphacodePanelCell.h */, + 09F916AA1F5D9A4E00E0AEFA /* TGAlphacodePanelCell.m */, + 09F916AB1F5D9A4E00E0AEFA /* TGModernConversationAlphacodeAssociatedPanel.h */, + 09F916AC1F5D9A4E00E0AEFA /* TGModernConversationAlphacodeAssociatedPanel.m */, D07BC9561F2A3EBF00ED97AA /* TGModernConversationAssociatedInputPanel.h */, D07BC9571F2A3EBF00ED97AA /* TGModernConversationAssociatedInputPanel.m */, D07BC9461F2A3EA900ED97AA /* TGHashtagPanelCell.h */, @@ -3791,6 +3809,7 @@ D07BCAEB1F2B507600ED97AA /* TGAttachmentGifCell.h in Headers */, D01778481F1F961D0044446D /* TGDocumentAttributeFilename.h in Headers */, D0177A751F2202260044446D /* TGModernBackToolbarButton.h in Headers */, + 09F916AD1F5D9A4E00E0AEFA /* TGAlphacode.h in Headers */, D07BCA0D1F2A9A2B00ED97AA /* TGMediaPickerGalleryVideoTrimView.h in Headers */, D07BC9911F2A480800ED97AA /* TGStickerKeyboardTabCell.h in Headers */, D07BC9F91F2A9A2B00ED97AA /* TGMediaPickerGalleryInterfaceView.h in Headers */, @@ -3833,8 +3852,10 @@ D07BCAED1F2B507600ED97AA /* TGAttachmentVideoCell.h in Headers */, D07BC9251F2A380D00ED97AA /* TGPaintSwatch.h in Headers */, D07BC91D1F2A380D00ED97AA /* TGPaintShader.h in Headers */, + 09F916B11F5D9A4E00E0AEFA /* TGModernConversationAlphacodeAssociatedPanel.h in Headers */, D07BC9641F2A3F4000ED97AA /* TGRemoteImageView.h in Headers */, D07BCB661F2B6A5600ED97AA /* TGEmbedPlayerState.h in Headers */, + 09F916AF1F5D9A4E00E0AEFA /* TGAlphacodePanelCell.h in Headers */, D07BCBC51F2B6F6300ED97AA /* CBLibrary.h in Headers */, D01779841F2107D70044446D /* lmdb.h in Headers */, D0177AF71F23DFC70044446D /* TGDataResource.h in Headers */, @@ -4398,6 +4419,7 @@ D01778061F1F961D0044446D /* TGWebDocument.m in Sources */, D0177A351F21F1980044446D /* UIImage+TGMediaEditableItem.m in Sources */, D01778001F1F961D0044446D /* TGMessageHole.m in Sources */, + 09F916B21F5D9A4E00E0AEFA /* TGModernConversationAlphacodeAssociatedPanel.m in Sources */, D07BC73C1F2A2A7D00ED97AA /* PGPhotoEditorRawDataOutput.m in Sources */, D07BCBC21F2B6F6300ED97AA /* CBGenericDownloadOperation.m in Sources */, D07BC8CE1F2A37EC00ED97AA /* TGPhotoPaintSettingsView.m in Sources */, @@ -4443,6 +4465,7 @@ D07BC8CC1F2A37EC00ED97AA /* TGPhotoPaintSelectionContainerView.m in Sources */, D07BC80F1F2A2C0B00ED97AA /* PGPhotoEnhancePass.m in Sources */, D026606F1F34A7F8000E2DC5 /* TGLocationTrackingButton.m in Sources */, + 09F916AE1F5D9A4E00E0AEFA /* TGAlphacode.m in Sources */, D0177A031F2139980044446D /* POPMath.mm in Sources */, D0177A681F21FB9B0044446D /* TGModernGalleryItemView.m in Sources */, D07BC6F01F2A19A700ED97AA /* TGCameraFlipButton.m in Sources */, @@ -4740,6 +4763,7 @@ D07BC8491F2A2DA200ED97AA /* TGMenuSheetController.m in Sources */, D01778E81F20CAE60044446D /* TGNavigationBar.m in Sources */, D0177A861F2218AB0044446D /* TGModernGalleryZoomableItemView.m in Sources */, + 09F916B01F5D9A4E00E0AEFA /* TGAlphacodePanelCell.m in Sources */, D01779321F20FFAC0044446D /* TGMediaAssetsLibrary.m in Sources */, D07BC7711F2A2B3700ED97AA /* TGPhotoEditorCollectionView.m in Sources */, D01779E51F2139980044446D /* POPAnimationEvent.mm in Sources */, diff --git a/LegacyComponents/LegacyComponents.h b/LegacyComponents/LegacyComponents.h index c0f88b42f5..990b2d86f8 100644 --- a/LegacyComponents/LegacyComponents.h +++ b/LegacyComponents/LegacyComponents.h @@ -68,7 +68,9 @@ FOUNDATION_EXPORT const unsigned char LegacyComponentsVersionString[]; #import #import #import +#import #import +#import #import #import diff --git a/LegacyComponents/Resources/LegacyComponentsResources.bundle/TwitchPlayerInject.js b/LegacyComponents/Resources/LegacyComponentsResources.bundle/TwitchPlayerInject.js index fc3957b338..1325020db9 100644 --- a/LegacyComponents/Resources/LegacyComponentsResources.bundle/TwitchPlayerInject.js +++ b/LegacyComponents/Resources/LegacyComponentsResources.bundle/TwitchPlayerInject.js @@ -72,6 +72,11 @@ function fixPlayer() { video.play(); hidePlayButton(); + + var ageButton = document.getElementById('mature-link'); + if (ageButton != null) { + eventFire(ageButton, 'click'); + } } function onPlaybackStart() { diff --git a/LegacyComponents/TGAlphacode.h b/LegacyComponents/TGAlphacode.h new file mode 100644 index 0000000000..2b02e50306 --- /dev/null +++ b/LegacyComponents/TGAlphacode.h @@ -0,0 +1,12 @@ +#import + +@class SSignal; + +@interface TGAlphacodeEntry : NSObject + +@property (nonatomic, strong, readonly) NSString *emoji; +@property (nonatomic, strong, readonly) NSString *code; + +- (instancetype)initWithEmoji:(NSString *)emoji code:(NSString *)code; + +@end diff --git a/LegacyComponents/TGAlphacode.m b/LegacyComponents/TGAlphacode.m new file mode 100644 index 0000000000..18e4db65dc --- /dev/null +++ b/LegacyComponents/TGAlphacode.m @@ -0,0 +1,14 @@ +#import "TGAlphacode.h" + +@implementation TGAlphacodeEntry + +- (instancetype)initWithEmoji:(NSString *)emoji code:(NSString *)code { + self = [super init]; + if (self != nil) { + _emoji = emoji; + _code = code; + } + return self; +} + +@end diff --git a/LegacyComponents/TGAlphacodePanelCell.h b/LegacyComponents/TGAlphacodePanelCell.h new file mode 100644 index 0000000000..fdd1c67bbd --- /dev/null +++ b/LegacyComponents/TGAlphacodePanelCell.h @@ -0,0 +1,10 @@ +#import + +extern NSString *const TGAlphacodePanelCellKind; + +@interface TGAlphacodePanelCell : UITableViewCell + +- (instancetype)initWithStyle:(TGModernConversationAssociatedInputPanelStyle)style; +- (void)setEmoji:(NSString *)emoji label:(NSString *)label; + +@end diff --git a/LegacyComponents/TGAlphacodePanelCell.m b/LegacyComponents/TGAlphacodePanelCell.m new file mode 100644 index 0000000000..2c6e0bf117 --- /dev/null +++ b/LegacyComponents/TGAlphacodePanelCell.m @@ -0,0 +1,93 @@ +#import "TGAlphacodePanelCell.h" + +#import "LegacyComponentsInternal.h" +#import "TGColor.h" +#import "TGFont.h" + +NSString *const TGAlphacodePanelCellKind = @"TGAlphacodePanelCell"; + +@interface TGAlphacodePanelCell () { + UILabel *_emojiLabel; + UILabel *_descriptionLabel; +} + +@end + +@implementation TGAlphacodePanelCell + +- (instancetype)initWithStyle:(UITableViewCellStyle)style { + self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TGAlphacodePanelCellKind]; + if (self != nil) { + UIColor *backgroundColor = [UIColor whiteColor]; + UIColor *nameColor = [UIColor blackColor]; + UIColor *usernameColor = [UIColor blackColor]; + UIColor *selectionColor = TGSelectionColor(); + + if (style == TGModernConversationAssociatedInputPanelDarkStyle) + { + backgroundColor = UIColorRGB(0x171717); + nameColor = [UIColor whiteColor]; + usernameColor = UIColorRGB(0x828282); + selectionColor = UIColorRGB(0x292929); + } + else if (style == TGModernConversationAssociatedInputPanelDarkBlurredStyle) + { + backgroundColor = [UIColor clearColor]; + nameColor = [UIColor whiteColor]; + usernameColor = UIColorRGB(0x828282); + selectionColor = UIColorRGB(0x3d3d3d); + } + + self.backgroundColor = backgroundColor; + self.backgroundView = [[UIView alloc] init]; + self.backgroundView.backgroundColor = backgroundColor; + self.backgroundView.opaque = false; + + self.selectedBackgroundView = [[UIView alloc] init]; + self.selectedBackgroundView.backgroundColor = selectionColor; + + _emojiLabel = [[UILabel alloc] init]; + _emojiLabel.backgroundColor = [UIColor clearColor]; + _emojiLabel.textColor = nameColor; + _emojiLabel.font = TGSystemFontOfSize(14.0f); + _emojiLabel.lineBreakMode = NSLineBreakByTruncatingTail; + [self.contentView addSubview:_emojiLabel]; + + _descriptionLabel = [[UILabel alloc] init]; + _descriptionLabel.backgroundColor = [UIColor clearColor]; + _descriptionLabel.textColor = usernameColor; + _descriptionLabel.font = TGSystemFontOfSize(14.0f); + _descriptionLabel.lineBreakMode = NSLineBreakByTruncatingTail; + [self.contentView addSubview:_descriptionLabel]; + } + return self; +} + +- (void)setEmoji:(NSString *)emoji label:(NSString *)label { + _emojiLabel.text = emoji; + _descriptionLabel.text = label; + + [self setNeedsLayout]; +} + +- (void)layoutSubviews +{ + [super layoutSubviews]; + + CGSize boundsSize = self.bounds.size; + + CGFloat leftInset = 11.0f; + CGFloat rightInset = 6.0f; + + CGSize titleSize = [_emojiLabel.text sizeWithFont:_emojiLabel.font]; + titleSize.width = CGCeil(MIN((boundsSize.width - leftInset - rightInset) * 3.0f / 4.0f, titleSize.width)); + titleSize.height = CGCeil(titleSize.height); + + CGSize descriptionSize = [_descriptionLabel.text sizeWithFont:_descriptionLabel.font]; + descriptionSize.width = CGCeil(MIN(boundsSize.width - leftInset - 40.0f, descriptionSize.width)); + + _emojiLabel.frame = CGRectMake(leftInset, CGFloor((boundsSize.height - titleSize.height) / 2.0f), titleSize.width, titleSize.height); + _descriptionLabel.frame = CGRectMake(40.0f, CGFloor((boundsSize.height - descriptionSize.height) / 2.0f), descriptionSize.width, descriptionSize.height); +} + +@end diff --git a/LegacyComponents/TGCheckButtonView.h b/LegacyComponents/TGCheckButtonView.h index 9c02ffa07c..2220589cc6 100644 --- a/LegacyComponents/TGCheckButtonView.h +++ b/LegacyComponents/TGCheckButtonView.h @@ -17,4 +17,6 @@ typedef enum - (void)setSelected:(bool)selected animated:(bool)animated; - (void)setSelected:(bool)selected animated:(bool)animated bump:(bool)bump; +- (void)setNumber:(NSInteger)number; + @end diff --git a/LegacyComponents/TGCheckButtonView.m b/LegacyComponents/TGCheckButtonView.m index 76e3da631f..d3ed0c64c0 100644 --- a/LegacyComponents/TGCheckButtonView.m +++ b/LegacyComponents/TGCheckButtonView.m @@ -15,6 +15,9 @@ UIImageView *_checkFillView; UIView *_checkShortFragment; UIView *_checkLongFragment; + + UILabel *_numberLabel; + NSInteger _number; } @end @@ -346,26 +349,33 @@ static CGAffineTransform TGCheckButtonDefaultTransform; } [UIView animateWithDuration:duration delay:0.0f usingSpringWithDamping:damping initialSpringVelocity:initialVelocity options:UIViewAnimationOptionBeginFromCurrentState animations:^ - { - _wrapperView.transform = CGAffineTransformIdentity; - } completion:nil]; + { + _wrapperView.transform = CGAffineTransformIdentity; + } completion:nil]; - _checkView.alpha = 1.0f; - _checkShortFragment.transform = CGAffineTransformMakeScale(1.0f, 0.0f); - _checkLongFragment.transform = CGAffineTransformMakeScale(0.0f, 1.0f); - - [UIView animateKeyframesWithDuration:0.21f delay:0.0f options:kNilOptions animations:^ + if (_number > 0) { - [UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:0.333f animations:^ - { - _checkShortFragment.transform = CGAffineTransformIdentity; - }]; - [UIView addKeyframeWithRelativeStartTime:0.333f relativeDuration:0.666f animations:^ + } + else + { + _checkView.alpha = 1.0f; + _checkShortFragment.transform = CGAffineTransformMakeScale(1.0f, 0.0f); + _checkLongFragment.transform = CGAffineTransformMakeScale(0.0f, 1.0f); + + [UIView animateKeyframesWithDuration:0.21f delay:0.0f options:kNilOptions animations:^ { - _checkLongFragment.transform = CGAffineTransformIdentity; - }]; - } completion:nil]; + [UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:0.333f animations:^ + { + _checkShortFragment.transform = CGAffineTransformIdentity; + }]; + + [UIView addKeyframeWithRelativeStartTime:0.333f relativeDuration:0.666f animations:^ + { + _checkLongFragment.transform = CGAffineTransformIdentity; + }]; + } completion:nil]; + } } else { @@ -375,8 +385,15 @@ static CGAffineTransform TGCheckButtonDefaultTransform; [UIView animateWithDuration:duration animations:^ { - _checkView.transform = CGAffineTransformScale(_checkView.transform, 0.01f, 0.01f); - _checkView.alpha = 0.0f; + if (_number > 0) + { + + } + else + { + _checkView.transform = CGAffineTransformScale(_checkView.transform, 0.01f, 0.01f); + _checkView.alpha = 0.0f; + } if (bump) _wrapperView.transform = CGAffineTransformIdentity; @@ -391,15 +408,28 @@ static CGAffineTransform TGCheckButtonDefaultTransform; _checkFillView.alpha = selected ? 1.0f : 0.0f; _checkFillView.transform = selected ? CGAffineTransformIdentity : CGAffineTransformMakeScale(0.1f, 0.1f); - _checkView.alpha = selected ? 1.0f : 0.0f; - _checkView.transform = TGCheckButtonDefaultTransform; - _checkShortFragment.transform = CGAffineTransformIdentity; - _checkLongFragment.transform = CGAffineTransformIdentity; + if (_number > 0) + { + _checkView.alpha = 0.0f; + } + else + { + _checkView.alpha = selected ? 1.0f : 0.0f; + _checkView.transform = TGCheckButtonDefaultTransform; + _checkShortFragment.transform = CGAffineTransformIdentity; + _checkLongFragment.transform = CGAffineTransformIdentity; + } } super.selected = selected; } +- (void)setNumber:(NSInteger)number +{ + _number = number; + _numberLabel.text = number > 0 ? [NSString stringWithFormat:@"%ld", number] : @""; +} + #pragma mark - - (void)setWrapperScale:(CGFloat)scale animated:(bool)animated diff --git a/LegacyComponents/TGMediaPickerCaptionInputPanel.h b/LegacyComponents/TGMediaPickerCaptionInputPanel.h index a8f4a1c7c7..9dfc5ba59d 100644 --- a/LegacyComponents/TGMediaPickerCaptionInputPanel.h +++ b/LegacyComponents/TGMediaPickerCaptionInputPanel.h @@ -36,6 +36,8 @@ - (void)setContentAreaHeight:(CGFloat)contentAreaHeight; +- (NSInteger)textCaretPosition; + @end @protocol TGMediaPickerCaptionInputPanelDelegate @@ -45,6 +47,7 @@ - (void)inputPanelRequestedSetCaption:(TGMediaPickerCaptionInputPanel *)inputPanel text:(NSString *)text; - (void)inputPanelMentionEntered:(TGMediaPickerCaptionInputPanel *)inputTextPanel mention:(NSString *)mention startOfLine:(bool)startOfLine; - (void)inputPanelHashtagEntered:(TGMediaPickerCaptionInputPanel *)inputTextPanel hashtag:(NSString *)hashtag; +- (void)inputPanelAlphacodeEntered:(TGMediaPickerCaptionInputPanel *)inputTextPanel alphacode:(NSString *)alphacode; - (void)inputPanelWillChangeHeight:(TGMediaPickerCaptionInputPanel *)inputPanel height:(CGFloat)height duration:(NSTimeInterval)duration animationCurve:(int)animationCurve; @optional diff --git a/LegacyComponents/TGMediaPickerCaptionInputPanel.m b/LegacyComponents/TGMediaPickerCaptionInputPanel.m index 41bb2f9b73..2897d2ce66 100644 --- a/LegacyComponents/TGMediaPickerCaptionInputPanel.m +++ b/LegacyComponents/TGMediaPickerCaptionInputPanel.m @@ -582,6 +582,7 @@ static void setViewFrame(UIView *view, CGRect frame) NSString *candidateMention = nil; bool candidateMentionStartOfLine = false; NSString *candidateHashtag = nil; + NSString *candidateAlphacode = nil; if (idx >= 0 && idx < textLength) { @@ -641,7 +642,37 @@ static void setViewFrame(UIView *view, CGRect frame) break; } } - } + + if (candidateHashtag == nil) + { + if (idx >= 0 && idx < textLength) + { + for (NSInteger i = idx; i >= 0; i--) + { + unichar c = [text characterAtIndex:i]; + unichar previousC = 0; + if (i > 0) + previousC = [text characterAtIndex:i - 1]; + if (c == ':' && (previousC == 0 || ![characterSet characterIsMember:previousC])) + { + if (i == idx) { + candidateAlphacode = nil; + } + else + { + @try { + candidateAlphacode = [text substringWithRange:NSMakeRange(i + 1, idx - i)]; + } @catch(NSException *e) { } + } + break; + } + + if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')) + break; + } + } + } +} if ([delegate respondsToSelector:@selector(inputPanelMentionEntered:mention:startOfLine:)]) [delegate inputPanelMentionEntered:self mention:candidateMention startOfLine:candidateMentionStartOfLine]; @@ -649,6 +680,9 @@ static void setViewFrame(UIView *view, CGRect frame) if ([delegate respondsToSelector:@selector(inputPanelHashtagEntered:hashtag:)]) [delegate inputPanelHashtagEntered:self hashtag:candidateHashtag]; + if ([delegate respondsToSelector:@selector(inputPanelAlphacodeEntered:alphacode:)]) + [delegate inputPanelAlphacodeEntered:self alphacode:candidateAlphacode]; + if ([delegate respondsToSelector:@selector(inputPanelTextChanged:text:)]) [delegate inputPanelTextChanged:self text:text]; @@ -698,6 +732,13 @@ static void setViewFrame(UIView *view, CGRect frame) return string; } +- (NSInteger)textCaretPosition { + UITextRange *selRange = _inputField.internalTextView.selectedTextRange; + UITextPosition *selStartPos = selRange.start; + NSInteger idx = [_inputField.internalTextView offsetFromPosition:_inputField.internalTextView.beginningOfDocument toPosition:selStartPos]; + return idx; +} + #pragma mark - - (void)replaceMention:(NSString *)mention diff --git a/LegacyComponents/TGMediaPickerGalleryVideoScrubber.m b/LegacyComponents/TGMediaPickerGalleryVideoScrubber.m index 7c9ab9be07..e3f2bb1db2 100644 --- a/LegacyComponents/TGMediaPickerGalleryVideoScrubber.m +++ b/LegacyComponents/TGMediaPickerGalleryVideoScrubber.m @@ -16,6 +16,7 @@ const CGFloat TGVideoScrubberMinimumTrimDuration = 1.0f; const CGFloat TGVideoScrubberZoomActivationInterval = 0.25f; const CGFloat TGVideoScrubberTrimRectEpsilon = 3.0f; +const CGFloat TGVideoScrubberPadding = 8.0f; typedef enum { @@ -100,7 +101,7 @@ typedef enum _inverseTimeLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; _inverseTimeLabel.font = TGSystemFontOfSize(12.0f); _inverseTimeLabel.backgroundColor = [UIColor clearColor]; - _inverseTimeLabel.text = @"-0:00"; + _inverseTimeLabel.text = @"0:00"; _inverseTimeLabel.textAlignment = NSTextAlignmentRight; _inverseTimeLabel.textColor = [UIColor whiteColor]; [self addSubview:_inverseTimeLabel]; @@ -162,7 +163,7 @@ typedef enum id delegate = strongSelf.delegate; if ([delegate respondsToSelector:@selector(videoScrubberDidEndEditing:)]) [delegate videoScrubberDidEndEditing:strongSelf]; - + CGRect newTrimRect = strongSelf->_trimView.frame; CGRect trimRect = [strongSelf _scrubbingRect]; CGRect normalScrubbingRect = [strongSelf _scrubbingRectZoomedIn:false]; @@ -239,9 +240,9 @@ typedef enum if (strongSelf.maximumLength > DBL_EPSILON && duration > strongSelf.maximumLength) { trimViewRect = CGRectMake(trimView.frame.origin.x + delta, - trimView.frame.origin.y, - trimView.frame.size.width, - trimView.frame.size.height); + trimView.frame.origin.y, + trimView.frame.size.width, + trimView.frame.size.height); [strongSelf _trimStartPosition:&trimStartPosition trimEndPosition:&trimEndPosition forTrimFrame:trimViewRect duration:strongSelf.duration]; } @@ -334,8 +335,8 @@ typedef enum }; [_wrapperView addSubview:_trimView]; - _scrubberHandle = [[UIControl alloc] initWithFrame:CGRectMake(0, -1, 8, 38.5f)]; - _scrubberHandle.hitTestEdgeInsets = UIEdgeInsetsMake(-5, -10, -5, -10); + _scrubberHandle = [[UIControl alloc] initWithFrame:CGRectMake(0, -4.0f, 5.0f, 44.0f)]; + _scrubberHandle.hitTestEdgeInsets = UIEdgeInsetsMake(-5, -12, -5, -12); [_wrapperView addSubview:_scrubberHandle]; static UIImage *handleViewImage = nil; @@ -344,11 +345,10 @@ typedef enum { UIGraphicsBeginImageContextWithOptions(CGSizeMake(_scrubberHandle.frame.size.width, _scrubberHandle.frame.size.height), false, 0.0f); CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetShadowWithColor(context, CGSizeMake(0, 1.5f), 0.5f, [UIColor colorWithWhite:0.0f alpha:0.35f].CGColor); + CGContextSetShadowWithColor(context, CGSizeMake(0, 0), 0.5f, [UIColor colorWithWhite:0.0f alpha:0.65f].CGColor); CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); - UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.5f, 0.5f, _scrubberHandle.frame.size.width - 1, _scrubberHandle.frame.size.height - 2.5f) - cornerRadius:3]; + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.5f, 0.5f, _scrubberHandle.frame.size.width - 1, _scrubberHandle.frame.size.height - 1.0f) cornerRadius:2.0f]; [path fill]; handleViewImage = UIGraphicsGetImageFromCurrentImageContext(); @@ -742,7 +742,7 @@ typedef enum { if (orientation == UIImageOrientationLeft || orientation == UIImageOrientationRight) aspectRatio = 1.0f / aspectRatio; - return CGSizeMake(CGCeil(32 * aspectRatio), 32); + return CGSizeMake(CGCeil(36.0f * aspectRatio), 36.0f); } - (void)_layoutSummaryThumbnailViewsForZoom:(bool)forZoom @@ -945,8 +945,11 @@ typedef enum - (void)_updateTimeLabels { - _currentTimeLabel.text = [TGMediaPickerGalleryVideoScrubber _stringFromTotalSeconds:(NSInteger)self.value]; - _inverseTimeLabel.text = [NSString stringWithFormat:@"-%@", [TGMediaPickerGalleryVideoScrubber _stringFromTotalSeconds:(NSInteger)self.duration - (NSInteger)self.value]]; + _currentTimeLabel.text = @""; + + NSString *text = [NSString stringWithFormat:@"%@ / %@", [TGMediaPickerGalleryVideoScrubber _stringFromTotalSeconds:(NSInteger)self.value], [TGMediaPickerGalleryVideoScrubber _stringFromTotalSeconds:(NSInteger)self.duration]]; + + _inverseTimeLabel.text = text; } #pragma mark - Scrubber Handle @@ -1164,16 +1167,11 @@ typedef enum { CGFloat width = self.frame.size.width; CGFloat origin = 0; - if (self.allowsTrimming) - { - width = width - 12 * 2 - 16; - origin = 12; - } - else - { - width = width - 2 * 2 - 16; - origin = 2; - } + CGFloat handleWidth = self.allowsTrimming ? 12.0f : 0.0f; + + width = width - handleWidth * 2.0f - TGVideoScrubberPadding * 2.0f; + origin = handleWidth; + if (zoomedIn) { @@ -1282,8 +1280,8 @@ typedef enum CGRect scrubbingRect = [self _scrubbingRect]; CGRect normalScrubbingRect = [self _scrubbingRectZoomedIn:false]; - _leftCurtainView.frame = CGRectMake(scrubbingRect.origin.x, 2, _trimView.frame.origin.x - scrubbingRect.origin.x + normalScrubbingRect.origin.x, 32); - _rightCurtainView.frame = CGRectMake(CGRectGetMaxX(_trimView.frame), 2, scrubbingRect.origin.x + scrubbingRect.size.width - CGRectGetMaxX(_trimView.frame) - scrubbingRect.origin.x + normalScrubbingRect.origin.x, 32); + _leftCurtainView.frame = CGRectMake(scrubbingRect.origin.x - 12.0f, 0.0f, _trimView.frame.origin.x - scrubbingRect.origin.x + normalScrubbingRect.origin.x + 12.0f, 36.0f); + _rightCurtainView.frame = CGRectMake(CGRectGetMaxX(_trimView.frame) - 4.0f, 0.0, scrubbingRect.origin.x + scrubbingRect.size.width - CGRectGetMaxX(_trimView.frame) - scrubbingRect.origin.x + normalScrubbingRect.origin.x + 4.0f + 12.0f, 36.0f); } } @@ -1295,7 +1293,7 @@ typedef enum CGFloat screenWidth = MAX(self.frame.size.width, self.frame.size.height); CGFloat recipientWidth = MIN(_recipientLabel.frame.size.width, screenWidth - 100.0f); - _arrowView.frame = CGRectMake(48.0f, 6.0f, _arrowView.frame.size.width, _arrowView.frame.size.height); + _arrowView.frame = CGRectMake(14.0f, 6.0f, _arrowView.frame.size.width, _arrowView.frame.size.height); _recipientLabel.frame = CGRectMake(CGRectGetMaxX(_arrowView.frame) + 6.0f, _arrowView.frame.origin.y - 2.0f, recipientWidth, _recipientLabel.frame.size.height); } @@ -1303,11 +1301,11 @@ typedef enum - (void)layoutSubviews { - _wrapperView.frame = CGRectMake(8, 24, self.frame.size.width - 16, 36); + _wrapperView.frame = CGRectMake(TGVideoScrubberPadding, 24, self.frame.size.width - TGVideoScrubberPadding * 2.0f, 36); [self _layoutTrimViewZoomedIn:_zoomedIn]; CGRect scrubbingRect = [self _scrubbingRect]; - _summaryThumbnailWrapperView.frame = CGRectMake(scrubbingRect.origin.x, 2, scrubbingRect.size.width, 32); + _summaryThumbnailWrapperView.frame = CGRectMake(MIN(0.0, scrubbingRect.origin.x), 0.0f, MAX(_wrapperView.frame.size.width, scrubbingRect.size.width), 36.0f); _zoomedThumbnailWrapperView.frame = _summaryThumbnailWrapperView.frame; [self _updateScrubberAnimationsAndResetCurrentPosition:true]; diff --git a/LegacyComponents/TGMediaPickerGalleryVideoTrimView.m b/LegacyComponents/TGMediaPickerGalleryVideoTrimView.m index 3b62754051..e95c5402bd 100644 --- a/LegacyComponents/TGMediaPickerGalleryVideoTrimView.m +++ b/LegacyComponents/TGMediaPickerGalleryVideoTrimView.m @@ -2,19 +2,13 @@ #import "LegacyComponentsInternal.h" +#import #import @interface TGMediaPickerGalleryVideoTrimView () { - UIControl *_leftSegmentView; - UIView *_topSegmentView; - UIControl *_rightSegmentView; - UIView *_bottomSegmentView; - - UIView *_topShadowView; - - UIImageView *_leftHandleView; - UIImageView *_rightHandleView; + UIButton *_leftSegmentView; + UIButton *_rightSegmentView; UILongPressGestureRecognizer *_startHandlePressGestureRecognizer; UILongPressGestureRecognizer *_endHandlePressGestureRecognizer; @@ -38,40 +32,43 @@ { self.hitTestEdgeInsets = UIEdgeInsetsMake(-5, -25, -5, -25); - UIColor *trimBackgroundColor = UIColorRGB(0x4d4d4d); + UIColor *normalColor = UIColorRGB(0x4d4d4d); + UIColor *accentColor = UIColorRGB(0x5ecdff); - _topShadowView = [[UIView alloc] initWithFrame:CGRectMake(12, 2, 0, 1)]; - _topShadowView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.3f]; - [self addSubview:_topShadowView]; + static dispatch_once_t onceToken; + static UIImage *handle; + dispatch_once(&onceToken, ^ + { + UIGraphicsBeginImageContextWithOptions(CGSizeMake(12.0f, 36.0f), false, 0.0f); + + [normalColor setFill]; + [[UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.0f, 0.0f, 12.0f, 36.0f) byRoundingCorners:UIRectCornerTopLeft | UIRectCornerBottomLeft cornerRadii:CGSizeMake(4.0f, 4.0f)] fill]; + + handle = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + }); - _leftSegmentView = [[UIControl alloc] initWithFrame:CGRectMake(0, 0, 12, 36)]; - _leftSegmentView.backgroundColor = trimBackgroundColor; + UIImage *leftImage = handle; + UIImage *leftHighlightedImage = TGTintedImage(handle, accentColor); + UIImage *rightImage = [UIImage imageWithCGImage:handle.CGImage scale:handle.scale orientation:UIImageOrientationUpMirrored]; + UIImage *rightHighlightedImage = [UIImage imageWithCGImage:leftHighlightedImage.CGImage scale:handle.scale orientation:UIImageOrientationUpMirrored]; + + _leftSegmentView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 12, 36)]; + _leftSegmentView.adjustsImageWhenHighlighted = false; + [_leftSegmentView setBackgroundImage:leftImage forState:UIControlStateNormal]; + [_leftSegmentView setBackgroundImage:leftHighlightedImage forState:UIControlStateSelected]; + [_leftSegmentView setBackgroundImage:leftHighlightedImage forState:UIControlStateSelected | UIControlStateHighlighted]; _leftSegmentView.hitTestEdgeInsets = UIEdgeInsetsMake(-5, -25, -5, -10); [self addSubview:_leftSegmentView]; - _topSegmentView = [[UIView alloc] initWithFrame:CGRectMake(12, 0, 0, 2)]; - _topSegmentView.backgroundColor = trimBackgroundColor; - [self addSubview:_topSegmentView]; - - _rightSegmentView = [[UIControl alloc] initWithFrame:CGRectMake(0, 0, 12, 36)]; - _rightSegmentView.backgroundColor = trimBackgroundColor; + _rightSegmentView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 12, 36)]; + _rightSegmentView.adjustsImageWhenHighlighted = false; + [_rightSegmentView setBackgroundImage:rightImage forState:UIControlStateNormal]; + [_rightSegmentView setBackgroundImage:rightHighlightedImage forState:UIControlStateSelected]; + [_rightSegmentView setBackgroundImage:rightHighlightedImage forState:UIControlStateSelected | UIControlStateHighlighted]; _rightSegmentView.hitTestEdgeInsets = UIEdgeInsetsMake(-5, -10, -5, -25); [self addSubview:_rightSegmentView]; - _bottomSegmentView = [[UIView alloc] initWithFrame:CGRectMake(12, 0, 0, 2)]; - _bottomSegmentView.backgroundColor = trimBackgroundColor; - [self addSubview:_bottomSegmentView]; - - _leftHandleView = [[UIImageView alloc] initWithFrame:_leftSegmentView.bounds]; - _leftHandleView.contentMode = UIViewContentModeCenter; - _leftHandleView.image = TGComponentsImageNamed(@"VideoScrubberLeftArrow"); - [_leftSegmentView addSubview:_leftHandleView]; - - _rightHandleView = [[UIImageView alloc] initWithFrame:_rightSegmentView.bounds]; - _rightHandleView.contentMode = UIViewContentModeCenter; - _rightHandleView.image = TGComponentsImageNamed(@"VideoScrubberRightArrow"); - [_rightSegmentView addSubview:_rightHandleView]; - _startHandlePressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleHandlePress:)]; _startHandlePressGestureRecognizer.delegate = self; _startHandlePressGestureRecognizer.minimumPressDuration = 0.1f; @@ -97,35 +94,26 @@ { _trimmingEnabled = trimmingEnabled; - _leftSegmentView.userInteractionEnabled = trimmingEnabled; - _rightSegmentView.userInteractionEnabled = trimmingEnabled; - - _leftHandleView.hidden = !trimmingEnabled; - _rightHandleView.hidden = !trimmingEnabled; + _leftSegmentView.hidden = !trimmingEnabled; + _rightSegmentView.hidden = !trimmingEnabled; [self setNeedsLayout]; } - (void)setTrimming:(bool)trimming animated:(bool)animated { - UIColor *backgroundColor = trimming ? UIColorRGB(0x5cc0ff) : UIColorRGB(0x4d4d4d); - if (animated) { [UIView animateWithDuration:0.15f animations:^ - { - _leftSegmentView.backgroundColor = backgroundColor; - _topSegmentView.backgroundColor = backgroundColor; - _rightSegmentView.backgroundColor = backgroundColor; - _bottomSegmentView.backgroundColor = backgroundColor; - }]; + { + [_leftSegmentView setSelected:trimming]; + [_rightSegmentView setSelected:trimming]; + }]; } else { - _leftSegmentView.backgroundColor = backgroundColor; - _topSegmentView.backgroundColor = backgroundColor; - _rightSegmentView.backgroundColor = backgroundColor; - _bottomSegmentView.backgroundColor = backgroundColor; + [_leftSegmentView setSelected:trimming]; + [_rightSegmentView setSelected:trimming]; } } @@ -233,14 +221,10 @@ - (void)layoutSubviews { - CGFloat handleWidth = self.trimmingEnabled ? 12.0f : 2.0f; + CGFloat handleWidth = 12.0f; _leftSegmentView.frame = CGRectMake(0, 0, handleWidth, self.frame.size.height); _rightSegmentView.frame = CGRectMake(self.frame.size.width - handleWidth, 0, handleWidth, self.frame.size.height); - - _topSegmentView.frame = CGRectMake(_leftSegmentView.frame.size.width, 0, self.frame.size.width - _leftSegmentView.frame.size.width - _rightSegmentView.frame.size.width, 2); - _bottomSegmentView.frame = CGRectMake(_leftSegmentView.frame.size.width, self.frame.size.height - _bottomSegmentView.frame.size.height, self.frame.size.width - _leftSegmentView.frame.size.width - _rightSegmentView.frame.size.width, 2); - _topShadowView.frame = CGRectMake(_topSegmentView.frame.origin.x, _topSegmentView.frame.size.height, _topSegmentView.frame.size.width, _topShadowView.frame.size.height); } @end diff --git a/LegacyComponents/TGModernConversationAlphacodeAssociatedPanel.h b/LegacyComponents/TGModernConversationAlphacodeAssociatedPanel.h new file mode 100644 index 0000000000..31b15fa9d9 --- /dev/null +++ b/LegacyComponents/TGModernConversationAlphacodeAssociatedPanel.h @@ -0,0 +1,13 @@ +#import "TGModernConversationAssociatedInputPanel.h" + +#import + +@class TGAlphacodeEntry; + +@interface TGModernConversationAlphacodeAssociatedPanel : TGModernConversationAssociatedInputPanel + +@property (nonatomic, copy) void (^alphacodeSelected)(TGAlphacodeEntry *); + +- (void)setAlphacodeListSignal:(SSignal *)alphacodeListSignal; + +@end diff --git a/LegacyComponents/TGModernConversationAlphacodeAssociatedPanel.m b/LegacyComponents/TGModernConversationAlphacodeAssociatedPanel.m new file mode 100644 index 0000000000..8d1ad2b0e0 --- /dev/null +++ b/LegacyComponents/TGModernConversationAlphacodeAssociatedPanel.m @@ -0,0 +1,469 @@ +#import "TGModernConversationAlphacodeAssociatedPanel.h" + +#import "LegacyComponentsInternal.h" +#import "TGColor.h" +#import "TGImageUtils.h" +#import "TGFont.h" +#import "TGViewController.h" + +#import "TGAlphacodePanelCell.h" + +#import "TGAlphacode.h" + +@interface TGModernConversationAlphacodeAssociatedPanel () +{ + SMetaDisposable *_disposable; + NSArray *_codeList; + + UIView *_backgroundView; + UIView *_effectView; + + UITableView *_tableView; + UIView *_stripeView; + UIView *_separatorView; + + UIView *_bottomView; + UIView *_tableViewBackground; + UIView *_tableViewSeparator; + + bool _resetOffsetOnLayout; + bool _animatingOut; +} + +@end + +@implementation TGModernConversationAlphacodeAssociatedPanel + +- (instancetype)initWithStyle:(TGModernConversationAssociatedInputPanelStyle)style +{ + self = [super initWithStyle:style]; + if (self != nil) + { + _disposable = [[SMetaDisposable alloc] init]; + + UIColor *backgroundColor = [UIColor whiteColor]; + UIColor *bottomColor = UIColorRGBA(0xfafafa, 0.98f); + UIColor *separatorColor = UIColorRGB(0xc5c7d0); + UIColor *cellSeparatorColor = UIColorRGB(0xdbdbdb); + + self.clipsToBounds = true; + + if (self.style == TGModernConversationAssociatedInputPanelDarkStyle) + { + backgroundColor = UIColorRGB(0x171717); + bottomColor = backgroundColor; + separatorColor = UIColorRGB(0x292929); + cellSeparatorColor = separatorColor; + } + else if (self.style == TGModernConversationAssociatedInputPanelDarkBlurredStyle) + { + backgroundColor = [UIColor clearColor]; + separatorColor = UIColorRGBA(0xb2b2b2, 0.7f); + cellSeparatorColor = UIColorRGBA(0xb2b2b2, 0.4f); + bottomColor = [UIColor clearColor]; + + CGFloat backgroundAlpha = 0.8f; + if (iosMajorVersion() >= 8) + { + UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]]; + blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + blurEffectView.frame = self.bounds; + [self addSubview:blurEffectView]; + _effectView = blurEffectView; + + backgroundAlpha = 0.4f; + } + + _backgroundView = [[UIView alloc] initWithFrame:self.bounds]; + _backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _backgroundView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:backgroundAlpha]; + [self addSubview:_backgroundView]; + } + + _bottomView = [[UIView alloc] init]; + _bottomView.backgroundColor = bottomColor; + [self addSubview:_bottomView]; + + _tableViewBackground = [[UIView alloc] init]; + _tableViewBackground.backgroundColor = backgroundColor; + [self addSubview:_tableViewBackground]; + + _tableView = [[UITableView alloc] init]; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine; + _tableView.tableFooterView = [[UIView alloc] init]; + if (iosMajorVersion() >= 7) + { + _tableView.separatorColor = cellSeparatorColor; + _tableView.separatorInset = UIEdgeInsetsMake(0.0f, 40.0f, 0.0f, 0.0f); + } + _tableView.backgroundColor = nil; + _tableView.opaque = false; + _tableView.showsVerticalScrollIndicator = false; + _tableView.showsHorizontalScrollIndicator = false; + + [self addSubview:_tableView]; + + _tableViewSeparator = [[UIView alloc] init]; + _tableViewSeparator.backgroundColor = separatorColor; + [self addSubview:_tableViewSeparator]; + + _stripeView = [[UIView alloc] init]; + _stripeView.backgroundColor = separatorColor; + [self addSubview:_stripeView]; + + if (self.style != TGModernConversationAssociatedInputPanelDarkBlurredStyle) + { + _separatorView = [[UIView alloc] init]; + _separatorView.backgroundColor = separatorColor; + [self addSubview:_separatorView]; + } + } + return self; +} + +- (void)dealloc +{ + [_disposable dispose]; +} + +- (void)setFrame:(CGRect)frame +{ + [super setFrame:frame]; + + self.alpha = frame.size.height >= FLT_EPSILON; +} + +- (bool)fillsAvailableSpace { + return true;//iosMajorVersion() >= 9; +} + +- (CGFloat)preferredHeight { + return [self preferredHeightAndOverlayHeight:NULL]; +} + +- (CGFloat)preferredHeightAndOverlayHeight:(CGFloat *)overlayHeight +{ + CGFloat height = 0.0f; + CGFloat lastHeight = 0.0f; + NSInteger lastIndex = MIN([TGViewController isWidescreen] ? 4 : 3, (NSInteger)_codeList.count - 1); + for (NSInteger i = 0; i <= lastIndex; i++) { + CGFloat rowHeight = [self tableView:_tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]]; + if (i == lastIndex) { + lastHeight = rowHeight; + } else { + height += rowHeight; + } + } + + CGFloat completeHeight = 0.0f; + for (NSInteger i = 0; i < (NSInteger)_codeList.count; i++) { + CGFloat rowHeight = [self tableView:_tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]]; + completeHeight += rowHeight; + } + + CGFloat maxHeight = CGFloor(self.frame.size.height * 2.0f / 3.0f); + + height = completeHeight; + + CGFloat overlayHeightValue = 0.0f; + if (height + self.barInset < self.frame.size.height) { + overlayHeightValue = self.barInset; + } + + if (overlayHeight) { + *overlayHeight = overlayHeightValue; + } + + height += overlayHeightValue; + + if (lastIndex > 0) { + return MIN(maxHeight, CGFloor(height)); + } else { + return MIN(maxHeight, height); + } +} + +- (void)setAlphacodeListSignal:(SSignal *)alphacodeListSignal +{ + if (alphacodeListSignal == nil) + { + [_disposable setDisposable:nil]; + [self setCodeList:@[]]; + } + else + { + __weak TGModernConversationAlphacodeAssociatedPanel *weakSelf = self; + [_disposable setDisposable:[[alphacodeListSignal deliverOn:[SQueue mainQueue]] startWithNext:^(NSArray *userList) + { + __strong TGModernConversationAlphacodeAssociatedPanel *strongSelf = weakSelf; + if (strongSelf != nil) + [strongSelf setCodeList:userList]; + }]]; + } +} + +- (void)setCodeList:(NSArray *)codeList +{ + bool wasEmpty = _codeList.count == 0; + _codeList = codeList; + + if (iosMajorVersion() >= 7) { + _tableView.separatorStyle = _codeList.count <= 1 ? UITableViewCellSeparatorStyleNone : UITableViewCellSeparatorStyleSingleLine; + } + + [_tableView reloadData]; + + [self setNeedsPreferredHeightUpdate]; + + _stripeView.hidden = _codeList.count == 0; + _separatorView.hidden = _codeList.count == 0; + _bottomView.hidden = _codeList.count == 0; + + [self scrollViewDidScroll:_tableView]; + + if (_codeList.count != 0 && wasEmpty) { + [self animateIn]; + } else { + [self layoutSubviews]; + } +} + +- (NSInteger)tableView:(UITableView *)__unused tableView numberOfRowsInSection:(NSInteger)__unused section +{ + return _codeList.count; +} + +- (CGFloat)tableView:(UITableView *)__unused tableView heightForRowAtIndexPath:(NSIndexPath *)__unused indexPath { + return 41.0f; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + TGAlphacodePanelCell *cell = (TGAlphacodePanelCell *)[tableView dequeueReusableCellWithIdentifier:TGAlphacodePanelCellKind]; + if (cell == nil) { + cell = [[TGAlphacodePanelCell alloc] initWithStyle:self.style]; + } + + TGAlphacodeEntry *entry = _codeList[indexPath.row]; + [cell setEmoji:entry.emoji label:entry.code]; + + return cell; +} + +- (void)tableView:(UITableView *)__unused tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + TGAlphacodeEntry *entry = _codeList[indexPath.row]; + if (_alphacodeSelected) { + _alphacodeSelected(entry); + } +} + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + if (scrollView == _tableView) { + [self updateTableBackground]; + } +} + +- (void)layoutSubviews +{ + [super layoutSubviews]; + + if (_animatingOut) { + return; + } + + _backgroundView.frame = CGRectMake(-1000, 0, self.frame.size.width + 2000, self.frame.size.height); + _effectView.frame = CGRectMake(-1000, 0, self.frame.size.width + 2000, self.frame.size.height); + + CGFloat separatorHeight = TGScreenPixel; + _separatorView.frame = CGRectMake(0.0f, self.frame.size.height - separatorHeight, self.frame.size.width, separatorHeight); + + UIEdgeInsets previousInset = _tableView.contentInset; + + _tableView.frame = CGRectMake(0.0f, 0.0f, self.frame.size.width, self.frame.size.height); + + if ([self fillsAvailableSpace]) { + CGFloat overlayHeight = 0.0; + CGFloat preferredHeight = [self preferredHeightAndOverlayHeight:&overlayHeight]; + + CGFloat topInset = MAX(0.0f, self.frame.size.height - preferredHeight); + CGFloat insetDifference = topInset - _tableView.contentInset.top; + UIEdgeInsets finalInset = UIEdgeInsetsMake(topInset, 0.0f, MAX(0.0f, overlayHeight - 1.0f / TGScreenScaling()), 0.0f); + + if (_resetOffsetOnLayout) { + _resetOffsetOnLayout = false; + _tableView.contentInset = finalInset; + [_tableView setContentOffset:CGPointMake(0.0f, -_tableView.contentInset.top) animated:false]; + } else if (ABS(insetDifference) > FLT_EPSILON) { + //if (ABS(insetDifference) <= 36.0f + 0.1) { + { + [self _autoAdjustInsetsForScrollView:_tableView finalInset:finalInset previousInset:previousInset]; + + //contentOffset.y -= insetDifference; + //_tableView.contentOffset = contentOffset; + } + } + } else { + _tableView.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f); + } + + _bottomView.frame = CGRectMake(0.0f, self.frame.size.height, self.frame.size.width, 4.0f); + + [self updateTableBackground]; +} + +- (void)_autoAdjustInsetsForScrollView:(UIScrollView *)scrollView finalInset:(UIEdgeInsets)finalInset previousInset:(UIEdgeInsets)previousInset +{ + CGPoint contentOffset = scrollView.contentOffset; + + scrollView.contentInset = finalInset; + if (iosMajorVersion() <= 8 && scrollView.subviews.count != 0) { + if ([NSStringFromClass([scrollView.subviews.firstObject class]) hasPrefix:@"UITableViewWra"]) { + CGRect frame = scrollView.subviews.firstObject.frame; + frame.origin = CGPointZero; + scrollView.subviews.firstObject.frame = frame; + } + } + + if (!UIEdgeInsetsEqualToEdgeInsets(previousInset, UIEdgeInsetsZero)) + { + CGFloat maxOffset = scrollView.contentSize.height - (scrollView.frame.size.height - finalInset.bottom); + + contentOffset.y += previousInset.top - finalInset.top; + contentOffset.y = MAX(-finalInset.top, MIN(contentOffset.y, maxOffset)); + [scrollView setContentOffset:contentOffset animated:false]; + } + else if (contentOffset.y < finalInset.top) + { + contentOffset.y = -finalInset.top; + [scrollView setContentOffset:contentOffset animated:false]; + } +} + +- (void)updateTableBackground { + if (_animatingOut) { + return; + } + + CGFloat backgroundOriginY = MAX(0.0f, -_tableView.contentOffset.y); + _tableViewBackground.frame = CGRectMake(0.0f, backgroundOriginY, self.frame.size.width, self.frame.size.height - backgroundOriginY); + _tableViewSeparator.frame = CGRectMake(0.0f, backgroundOriginY - 0.5f, self.frame.size.width, 0.5f); + + _tableView.scrollIndicatorInsets = UIEdgeInsetsMake(backgroundOriginY, 0.0f, 0.0f, 0.0f); + + self.overlayBarOffset = _tableView.contentOffset.y + _tableView.contentInset.top; + if (self.updateOverlayBarOffset) { + self.updateOverlayBarOffset(self.overlayBarOffset); + } +} + +- (CGRect)tableBackgroundFrame { + return _tableViewBackground.frame; +} + +- (void)selectPreviousItem +{ + if ([self tableView:_tableView numberOfRowsInSection:0] == 0) + return; + + NSIndexPath *newIndexPath = _tableView.indexPathForSelectedRow; + + if (newIndexPath == nil) + newIndexPath = [NSIndexPath indexPathForRow:0 inSection:0]; + else if (newIndexPath.row > 0) + newIndexPath = [NSIndexPath indexPathForRow:newIndexPath.row - 1 inSection:0]; + + if (_tableView.indexPathForSelectedRow != nil) + [_tableView deselectRowAtIndexPath:_tableView.indexPathForSelectedRow animated:false]; + + if (newIndexPath != nil) + [_tableView selectRowAtIndexPath:newIndexPath animated:false scrollPosition:UITableViewScrollPositionBottom]; +} + +- (void)selectNextItem +{ + if ([self tableView:_tableView numberOfRowsInSection:0] == 0) + return; + + NSIndexPath *newIndexPath = _tableView.indexPathForSelectedRow; + + if (newIndexPath == nil) + newIndexPath = [NSIndexPath indexPathForRow:0 inSection:0]; + else if (newIndexPath.row < [self tableView:_tableView numberOfRowsInSection:newIndexPath.section] - 1) + newIndexPath = [NSIndexPath indexPathForRow:newIndexPath.row + 1 inSection:0]; + + if (_tableView.indexPathForSelectedRow != nil) + [_tableView deselectRowAtIndexPath:_tableView.indexPathForSelectedRow animated:false]; + + if (newIndexPath != nil) + [_tableView selectRowAtIndexPath:newIndexPath animated:false scrollPosition:UITableViewScrollPositionBottom]; +} + +- (void)commitSelectedItem +{ + if ([self tableView:_tableView numberOfRowsInSection:0] == 0) + return; + + NSIndexPath *selectedIndexPath = _tableView.indexPathForSelectedRow; + if (selectedIndexPath == nil) + selectedIndexPath = [NSIndexPath indexPathForRow:0 inSection:0]; + + [self tableView:_tableView didSelectRowAtIndexPath:selectedIndexPath]; +} + +- (void)animateIn { + [self layoutSubviews]; + CGFloat offset = [self preferredHeight]; + CGRect normalFrame = _tableView.frame; + _tableView.frame = CGRectMake(normalFrame.origin.x, normalFrame.origin.y + offset, normalFrame.size.width, normalFrame.size.height); + CGRect normalBackgroundFrame = _tableViewBackground.frame; + _tableViewBackground.frame = CGRectMake(normalBackgroundFrame.origin.x, normalBackgroundFrame.origin.y + offset, normalBackgroundFrame.size.width, normalBackgroundFrame.size.height); + CGRect normalSeparatorFrame = _tableViewSeparator.frame; + _tableViewSeparator.frame = CGRectMake(normalSeparatorFrame.origin.x, normalSeparatorFrame.origin.y + offset, normalSeparatorFrame.size.width, normalSeparatorFrame.size.height); + [UIView animateWithDuration:0.3 delay:0.0 options:7 << 16 animations:^{ + _tableView.frame = normalFrame; + _tableViewBackground.frame = normalBackgroundFrame; + _tableViewSeparator.frame = normalSeparatorFrame; + } completion:nil]; +} + +- (void)animateOut:(void (^)())completion { + CGFloat offset = self.frame.size.height - _tableViewBackground.frame.origin.y; + CGRect normalFrame = _tableView.frame; + CGRect normalBackgroundFrame = _tableViewBackground.frame; + CGRect normalSeparatorFrame = _tableViewSeparator.frame; + _animatingOut = true; + + [UIView animateWithDuration:0.15 delay:0.0 options:0 animations:^{ + _tableView.frame = CGRectMake(normalFrame.origin.x, normalFrame.origin.y + offset, normalFrame.size.width, normalFrame.size.height); + _tableViewBackground.frame = CGRectMake(normalBackgroundFrame.origin.x, normalBackgroundFrame.origin.y + offset, normalBackgroundFrame.size.width, normalBackgroundFrame.size.height); + _tableViewSeparator.frame = CGRectMake(normalSeparatorFrame.origin.x, normalSeparatorFrame.origin.y + offset, normalSeparatorFrame.size.width, normalSeparatorFrame.size.height); + } completion:^(__unused BOOL finished) { + completion(); + }]; +} + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + if (CGRectContainsPoint(_tableViewBackground.frame, point)) { + return [super hitTest:point withEvent:event]; + } + return nil; +} + +- (void)setBarInset:(CGFloat)barInset animated:(bool)animated { + if (ABS(barInset - self.barInset) > FLT_EPSILON) { + [super setBarInset:barInset animated:animated]; + + if (animated) { + [self layoutSubviews]; + } else { + [UIView animateWithDuration:0.3 animations:^{ + [self layoutSubviews]; + }]; + } + } +} + +@end diff --git a/LegacyComponents/TGNavigationBar.m b/LegacyComponents/TGNavigationBar.m index c798ed7ee1..ace96b97a6 100644 --- a/LegacyComponents/TGNavigationBar.m +++ b/LegacyComponents/TGNavigationBar.m @@ -50,6 +50,10 @@ @end +@interface TGMusicPlayerContainerView : UIView + +@end + static id _musicPlayerProvider; @interface TGNavigationBar () @@ -57,7 +61,7 @@ static id _musicPlayerProvider; bool _shouldAddBackgdropBackgroundInitialized; bool _shouldAddBackgdropBackground; - UIView *_musicPlayerContainer; + TGMusicPlayerContainerView *_musicPlayerContainer; bool _showMusicPlayerView; } @@ -444,9 +448,8 @@ static id _musicPlayerProvider; { if (_musicPlayerContainer == nil) { - _musicPlayerContainer = [[UIView alloc] init]; + _musicPlayerContainer = [[TGMusicPlayerContainerView alloc] init]; _musicPlayerContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth; - _musicPlayerContainer.clipsToBounds = true; _musicPlayerContainer.frame = CGRectMake(0.0f, self.frame.size.height + self.musicPlayerOffset, self.frame.size.width, 37.0f); _musicPlayerView = [_musicPlayerProvider makeMusicPlayerView:_navigationController]; @@ -457,6 +460,7 @@ static id _musicPlayerProvider; [self addSubview:_musicPlayerContainer]; } } + _musicPlayerContainer.clipsToBounds = true; _musicPlayerContainer.userInteractionEnabled = true; [UIView animateWithDuration:0.3 delay:0.0 options:7 << 16 animations:^ { @@ -464,10 +468,14 @@ static id _musicPlayerProvider; if (animation) animation(); - } completion:nil]; + } completion:^(BOOL finished){ + if (finished) + _musicPlayerContainer.clipsToBounds = false; + }]; } else if (_musicPlayerView != nil) { + _musicPlayerContainer.clipsToBounds = true; _musicPlayerContainer.userInteractionEnabled = false; [UIView animateWithDuration:0.3 delay:0.0 options:7 << 16 animations:^ { @@ -522,3 +530,13 @@ static id _musicPlayerProvider; } @end + + +@implementation TGMusicPlayerContainerView + +- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event +{ + return [self.subviews.firstObject pointInside:[self convertPoint:point toView:self.subviews.firstObject] withEvent:event]; +} + +@end diff --git a/LegacyComponents/TGPhotoCaptionInputMixin.m b/LegacyComponents/TGPhotoCaptionInputMixin.m index c55a733fc1..971a3051ba 100644 --- a/LegacyComponents/TGPhotoCaptionInputMixin.m +++ b/LegacyComponents/TGPhotoCaptionInputMixin.m @@ -8,6 +8,7 @@ #import "TGModernConversationMentionsAssociatedPanel.h" #import "TGModernConversationHashtagsAssociatedPanel.h" +#import "TGModernConversationAlphacodeAssociatedPanel.h" @interface TGPhotoCaptionInputMixin () { @@ -232,6 +233,75 @@ } } +- (void)inputPanelAlphacodeEntered:(TGMediaPickerCaptionInputPanel *)inputTextPanel alphacode:(NSString *)alphacode +{ + if (alphacode == nil) + { + if ([[inputTextPanel associatedPanel] isKindOfClass:[TGModernConversationAlphacodeAssociatedPanel class]]) + [inputTextPanel setAssociatedPanel:nil animated:true]; + } + else + { + TGModernConversationAlphacodeAssociatedPanel *panel = nil; + if ([[inputTextPanel associatedPanel] isKindOfClass:[TGModernConversationAlphacodeAssociatedPanel class]]) + panel = ((TGModernConversationAlphacodeAssociatedPanel *)[inputTextPanel associatedPanel]); + else + { + panel = [[TGModernConversationAlphacodeAssociatedPanel alloc] initWithStyle:TGModernConversationAssociatedInputPanelDarkStyle]; + __weak TGPhotoCaptionInputMixin *weakSelf = self; + panel.alphacodeSelected = ^(TGAlphacodeEntry *entry) + { + __strong TGPhotoCaptionInputMixin *strongSelf = weakSelf; + if (strongSelf != nil) + { + if ([[strongSelf->_inputPanel associatedPanel] isKindOfClass:[TGModernConversationAlphacodeAssociatedPanel class]]) + { + [strongSelf->_inputPanel setAssociatedPanel:nil animated:false]; + } + + NSString *codeText = entry.emoji; + + [strongSelf appendAlphacode:[codeText stringByAppendingString:@" "]]; + } + }; + [inputTextPanel setAssociatedPanel:panel animated:true]; + } + + SSignal *alphacodeListSignal = nil; + if (self.suggestionContext.alphacodeSignal != nil) + alphacodeListSignal = self.suggestionContext.alphacodeSignal(alphacode); + + [panel setAlphacodeListSignal:alphacodeListSignal]; + } +} + +- (void)appendAlphacode:(NSString *)alphacode +{ + NSString *currentText = [_inputPanel inputField].text; + NSRange selectRange = NSMakeRange(0, 0); + + if (currentText.length == 0) + currentText = alphacode; + else + { + NSInteger caretIndex = [_inputPanel textCaretPosition]; + + for (NSInteger i = caretIndex - 1; i >= 0; i--) + { + if ([currentText characterAtIndex:i] == ':') { + currentText = [currentText stringByReplacingCharactersInRange:NSMakeRange(i, caretIndex - i) withString:alphacode]; + selectRange = NSMakeRange(i + alphacode.length, 0); + break; + } + } + } + + [[_inputPanel inputField] setAttributedText:[[NSAttributedString alloc] initWithString:currentText] animated:false]; + [[_inputPanel inputField] selectRange:selectRange force:true]; + + [_inputPanel inputField].internalTextView.enableFirstResponder = true; +} + - (void)inputPanelWillChangeHeight:(TGMediaPickerCaptionInputPanel *)inputPanel height:(CGFloat)__unused height duration:(NSTimeInterval)duration animationCurve:(int)animationCurve { [inputPanel adjustForOrientation:UIInterfaceOrientationPortrait keyboardHeight:_keyboardHeight duration:duration animationCurve:animationCurve]; diff --git a/LegacyComponents/TGSuggestionContext.h b/LegacyComponents/TGSuggestionContext.h index e118a21ef6..a6d4bec6c8 100644 --- a/LegacyComponents/TGSuggestionContext.h +++ b/LegacyComponents/TGSuggestionContext.h @@ -6,5 +6,6 @@ @property (nonatomic, copy) SSignal *(^userListSignal)(NSString *mention); @property (nonatomic, copy) SSignal *(^hashtagListSignal)(NSString *hashtag); +@property (nonatomic, copy) SSignal *(^alphacodeSignal)(NSString *alphacode); @end