1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-02 17:38:07 +01:00
Telegram/Telegraph/TGBotConversationHeaderView.m
2015-10-01 19:19:52 +03:00

385 lines
16 KiB
Objective-C

#import "TGBotConversationHeaderView.h"
#import "TGTextMessageBackgroundViewModel.h"
#import "TGModernTextViewModel.h"
#import "TGReusableLabel.h"
#import "TGModernFlatteningViewModel.h"
#import "TGFont.h"
#import "TGImageUtils.h"
#import "TGViewController.h"
#import "TGMessage.h"
#import "TGTelegraphConversationMessageAssetsSource.h"
#import "TGDoubleTapGestureRecognizer.h"
@interface TGBotConversationHeaderView () <UIGestureRecognizerDelegate, TGDoubleTapGestureRecognizerDelegate>
{
TGModernViewContext *_context;
TGModernViewStorage *_viewStorage;
TGTextMessageBackgroundViewModel *_backgroundModel;
UILabel *_titleLabel;
TGModernFlatteningViewModel *_contentModel;
TGModernTextViewModel *_textModel;
NSMutableArray *_currentLinkSelectionViews;
UIButton *_startButton;
TGDoubleTapGestureRecognizer *_boundDoubleTapRecognizer;
}
@end
@implementation TGBotConversationHeaderView
- (instancetype)initWithContext:(TGModernViewContext *)context botInfo:(TGBotInfo *)botInfo
{
self = [super init];
if (self != nil)
{
_context = context;
_viewStorage = [[TGModernViewStorage alloc] init];
_backgroundModel = [[TGTextMessageBackgroundViewModel alloc] initWithType:TGTextMessageBackgroundIncoming];
[_backgroundModel setPartialMode:true];
[_backgroundModel bindViewToContainer:self viewStorage:_viewStorage];
_titleLabel = [[UILabel alloc] init];
_titleLabel.textAlignment = NSTextAlignmentLeft;
_titleLabel.backgroundColor = [UIColor clearColor];
_titleLabel.textColor = [UIColor blackColor];
_titleLabel.text = botInfo.botDescription;
_titleLabel.text = TGLocalized(@"Bot.DescriptionTitle");
_titleLabel.numberOfLines = 1;
_titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
_titleLabel.font = [UIFont boldSystemFontOfSize:16.0f];
[self addSubview:_titleLabel];
NSString *text = botInfo.botDescription;
_contentModel = [[TGModernFlatteningViewModel alloc] initWithContext:nil];
_textModel = [[TGModernTextViewModel alloc] initWithText:text font:TGCoreTextSystemFontOfSize(16.0f)];
_textModel.textCheckingResults = [TGMessage textCheckingResultsForText:text highlightMentionsAndTags:true highlightCommands:true];
_textModel.layoutFlags = TGReusableLabelLayoutMultiline | TGReusableLabelLayoutHighlightCommands | TGReusableLabelLayoutHighlightLinks;
[_textModel layoutForContainerSize:CGSizeMake([self maximumContentWidth], CGFLOAT_MAX)];
[_contentModel addSubmodel:_textModel];
[_contentModel bindViewToContainer:self viewStorage:_viewStorage];
[_contentModel setNeedsSubmodelContentsUpdate];
_currentLinkSelectionViews = [[NSMutableArray alloc] init];
_boundDoubleTapRecognizer = [[TGDoubleTapGestureRecognizer alloc] initWithTarget:self action:@selector(messageDoubleTapGesture:)];
_boundDoubleTapRecognizer.delegate = self;
[_contentModel.boundView addGestureRecognizer:_boundDoubleTapRecognizer];
}
return self;
}
- (bool)gestureRecognizerShouldHandleLongTap:(TGDoubleTapGestureRecognizer *)__unused recognizer
{
return true;
}
- (int)gestureRecognizer:(TGDoubleTapGestureRecognizer *)__unused recognizer shouldFailTap:(CGPoint)point
{
if ([_textModel linkAtPoint:CGPointMake(point.x - _textModel.frame.origin.x, point.y - _textModel.frame.origin.y) regionData:NULL] != nil)
{
return 3;
}
return false;
}
- (void)gestureRecognizer:(TGDoubleTapGestureRecognizer *)__unused recognizer didBeginAtPoint:(CGPoint)point
{
[self updateLinkSelection:point];
}
- (void)messageDoubleTapGesture:(TGDoubleTapGestureRecognizer *)recognizer
{
if (recognizer.state != UIGestureRecognizerStateBegan)
{
[self clearLinkSelection];
if (recognizer.state == UIGestureRecognizerStateRecognized)
{
CGPoint point = [recognizer locationInView:[_contentModel boundView]];
NSString *linkCandidate = [_textModel linkAtPoint:CGPointMake(point.x - _textModel.frame.origin.x, point.y - _textModel.frame.origin.y) regionData:NULL];
if (linkCandidate != nil)
{
if (recognizer.longTapped)
{
[_context.companionHandle requestAction:@"openLinkWithOptionsRequested" options:@{@"url": linkCandidate}];
}
else
{
[_context.companionHandle requestAction:@"openLinkRequested" options:@{@"url": linkCandidate}];
}
}
}
}
}
- (void)clearLinkSelection
{
for (UIView *linkView in _currentLinkSelectionViews)
{
[linkView removeFromSuperview];
}
_currentLinkSelectionViews = nil;
}
- (void)updateLinkSelection:(CGPoint)point
{
if ([_contentModel boundView] != nil)
{
[self clearLinkSelection];
CGPoint offset = CGPointZero;// CGPointMake(_contentModel.frame.origin.x - _backgroundModel.frame.origin.x, _contentModel.frame.origin.y - _backgroundModel.frame.origin.y);
NSArray *regionData = nil;
NSString *link = [_textModel linkAtPoint:CGPointMake(point.x - _textModel.frame.origin.x - offset.x, point.y - _textModel.frame.origin.y - offset.y) regionData:&regionData];
CGPoint regionOffset = CGPointZero;
if (link != nil)
{
CGRect topRegion = regionData.count > 0 ? [regionData[0] CGRectValue] : CGRectZero;
CGRect middleRegion = regionData.count > 1 ? [regionData[1] CGRectValue] : CGRectZero;
CGRect bottomRegion = regionData.count > 2 ? [regionData[2] CGRectValue] : CGRectZero;
topRegion.origin = CGPointMake(topRegion.origin.x + regionOffset.x, topRegion.origin.y + regionOffset.y);
middleRegion.origin = CGPointMake(middleRegion.origin.x + regionOffset.x, middleRegion.origin.y + regionOffset.y);
bottomRegion.origin = CGPointMake(bottomRegion.origin.x + regionOffset.x, bottomRegion.origin.y + regionOffset.y);
UIImageView *topView = nil;
UIImageView *middleView = nil;
UIImageView *bottomView = nil;
UIImageView *topCornerLeft = nil;
UIImageView *topCornerRight = nil;
UIImageView *bottomCornerLeft = nil;
UIImageView *bottomCornerRight = nil;
NSMutableArray *linkHighlightedViews = [[NSMutableArray alloc] init];
topView = [[UIImageView alloc] init];
middleView = [[UIImageView alloc] init];
bottomView = [[UIImageView alloc] init];
topCornerLeft = [[UIImageView alloc] init];
topCornerRight = [[UIImageView alloc] init];
bottomCornerLeft = [[UIImageView alloc] init];
bottomCornerRight = [[UIImageView alloc] init];
if (topRegion.size.height != 0)
{
topView.hidden = false;
topView.frame = topRegion;
if (middleRegion.size.height == 0 && bottomRegion.size.height == 0)
topView.image = [[TGTelegraphConversationMessageAssetsSource instance] messageLinkFull];
else
topView.image = [[TGTelegraphConversationMessageAssetsSource instance] messageLinkFull];
}
else
{
topView.hidden = true;
topView.frame = CGRectZero;
}
if (middleRegion.size.height != 0)
{
middleView.hidden = false;
middleView.frame = middleRegion;
if (bottomRegion.size.height == 0)
middleView.image = [[TGTelegraphConversationMessageAssetsSource instance] messageLinkFull];
else
middleView.image = [[TGTelegraphConversationMessageAssetsSource instance] messageLinkFull];
}
else
{
middleView.hidden = true;
middleView.frame = CGRectZero;
}
if (bottomRegion.size.height != 0)
{
bottomView.hidden = false;
bottomView.frame = bottomRegion;
bottomView.image = [[TGTelegraphConversationMessageAssetsSource instance] messageLinkFull];
}
else
{
bottomView.hidden = true;
bottomView.frame = CGRectZero;
}
topCornerLeft.hidden = true;
topCornerRight.hidden = true;
bottomCornerLeft.hidden = true;
bottomCornerRight.hidden = true;
if (topRegion.size.height != 0 && middleRegion.size.height != 0)
{
if (topRegion.origin.x == middleRegion.origin.x)
{
topCornerLeft.hidden = false;
topCornerLeft.image = [[TGTelegraphConversationMessageAssetsSource instance] messageLinkCornerLR];
topCornerLeft.frame = CGRectMake(topRegion.origin.x, topRegion.origin.y + topRegion.size.height - 3.5f, 4, 7);
}
else if (topRegion.origin.x < middleRegion.origin.x + middleRegion.size.width - 3.5f)
{
topCornerLeft.hidden = false;
topCornerLeft.image = [[TGTelegraphConversationMessageAssetsSource instance] messageLinkCornerBT];
topCornerLeft.frame = CGRectMake(topRegion.origin.x - 3.5f, topRegion.origin.y + topRegion.size.height - 4, 7, 4);
}
if (topRegion.origin.x + topRegion.size.width == middleRegion.origin.x + middleRegion.size.width)
{
topCornerRight.hidden = false;
topCornerRight.image = [[TGTelegraphConversationMessageAssetsSource instance] messageLinkCornerRL];
topCornerRight.frame = CGRectMake(topRegion.origin.x + topRegion.size.width - 4, topRegion.origin.y + topRegion.size.height - 3.5f, 4, 7);
}
else if (topRegion.origin.x + topRegion.size.width < middleRegion.origin.x + middleRegion.size.width - 3.5f)
{
topCornerRight.hidden = false;
topCornerRight.image = [[TGTelegraphConversationMessageAssetsSource instance] messageLinkCornerBT];
topCornerRight.frame = CGRectMake(topRegion.origin.x + topRegion.size.width - 3.5f, topRegion.origin.y + topRegion.size.height - 4, 7, 4);
}
else if (bottomRegion.size.height == 0 && topRegion.origin.x < middleRegion.origin.x + middleRegion.size.width - 3.5f && topRegion.origin.x + topRegion.size.width > middleRegion.origin.x + middleRegion.size.width + 3.5f)
{
topCornerRight.hidden = false;
topCornerRight.image = [[TGTelegraphConversationMessageAssetsSource instance] messageLinkCornerTB];
topCornerRight.frame = CGRectMake(middleRegion.origin.x + middleRegion.size.width - 3.5f, middleRegion.origin.y, 7, 4);
}
}
if (middleRegion.size.height != 0 && bottomRegion.size.height != 0)
{
if (middleRegion.origin.x == bottomRegion.origin.x)
{
bottomCornerLeft.hidden = false;
bottomCornerLeft.image = [[TGTelegraphConversationMessageAssetsSource instance] messageLinkCornerLR];
bottomCornerLeft.frame = CGRectMake(middleRegion.origin.x, middleRegion.origin.y + middleRegion.size.height - 3.5f, 4, 7);
}
if (bottomRegion.origin.x + bottomRegion.size.width < middleRegion.origin.x + middleRegion.size.width - 3.5f)
{
bottomCornerRight.hidden = false;
bottomCornerRight.image = [[TGTelegraphConversationMessageAssetsSource instance] messageLinkCornerTB];
bottomCornerRight.frame = CGRectMake(bottomRegion.origin.x + bottomRegion.size.width - 3.5f, bottomRegion.origin.y, 7, 4);
}
}
if (!topView.hidden)
[linkHighlightedViews addObject:topView];
if (!middleView.hidden)
[linkHighlightedViews addObject:middleView];
if (!bottomView.hidden)
[linkHighlightedViews addObject:bottomView];
if (!topCornerLeft.hidden)
[linkHighlightedViews addObject:topCornerLeft];
if (!topCornerRight.hidden)
[linkHighlightedViews addObject:topCornerRight];
if (!bottomCornerLeft.hidden)
[linkHighlightedViews addObject:bottomCornerLeft];
if (!bottomCornerRight.hidden)
[linkHighlightedViews addObject:bottomCornerRight];
for (UIView *partView in linkHighlightedViews)
{
partView.frame = CGRectOffset(partView.frame, _textModel.frame.origin.x, _textModel.frame.origin.y + 1);
[[_contentModel boundView] addSubview:partView];
}
_currentLinkSelectionViews = linkHighlightedViews;
}
}
}
- (void)setFrame:(CGRect)frame
{
[super setFrame:frame];
}
- (CGFloat)titleSpacing
{
return 7.0f;
}
- (CGFloat)maximumContentWidth
{
UIEdgeInsets backgroundInsets = [self backgroundInsets];
UIEdgeInsets contentInsets = [self contentInsets];
CGFloat minSide = MIN([TGViewController screenSizeForInterfaceOrientation:UIInterfaceOrientationPortrait].width, [TGViewController screenSizeForInterfaceOrientation:UIInterfaceOrientationPortrait].height);
if (TGIsPad())
minSide = 448.0f;
return CGFloor(minSide * 0.85f - backgroundInsets.left - backgroundInsets.right - contentInsets.left - contentInsets.right);
}
- (void)sizeToFit
{
UIEdgeInsets backgroundInsets = [self backgroundInsets];
UIEdgeInsets contentInsets = [self contentInsets];
CGFloat maxWidth = [self maximumContentWidth];
CGSize titleSize = [_titleLabel sizeThatFits:CGSizeMake(maxWidth, FLT_MAX)];
titleSize.width = CGCeil(titleSize.width);
titleSize.height = CGCeil(titleSize.height);
CGSize labelSize = _textModel.frame.size;
CGFloat contentWidth = MAX(labelSize.width, titleSize.width);
_titleLabel.frame = CGRectMake(backgroundInsets.left + contentInsets.left + CGFloor((contentWidth - titleSize.width) / 2.0f), backgroundInsets.top + contentInsets.top, titleSize.width, titleSize.height);
_contentModel.frame = CGRectMake(backgroundInsets.left + contentInsets.left - 2, backgroundInsets.top + contentInsets.top + titleSize.height + [self titleSpacing] - 2, contentWidth + 4, labelSize.height + 4);
[_contentModel updateSubmodelContentsIfNeeded];
_textModel.frame = CGRectMake(2.0f, 2.0f, _textModel.frame.size.width, _textModel.frame.size.height);
CGRect frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, MAX(labelSize.width, titleSize.width) + backgroundInsets.left + backgroundInsets.right + contentInsets.left + contentInsets.right, labelSize.height + backgroundInsets.top + backgroundInsets.bottom + contentInsets.top + contentInsets.bottom + titleSize.height + [self titleSpacing]);
if (false && [TGViewController hasLargeScreen])
{
frame.size.width = CGEven(frame.size.width);
frame.size.height = CGEven(frame.size.height);
}
else
{
frame.size.width = CGOdd(frame.size.width);
frame.size.height = CGOdd(frame.size.height);
}
self.frame = frame;
}
- (UIEdgeInsets)backgroundInsets
{
return UIEdgeInsetsMake(5.0f, 0.0f, 5.0f, 0.0f);
}
- (UIEdgeInsets)contentInsets
{
return UIEdgeInsetsMake(12.0f, 20.0f, 12.0f, 20.0f);
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect bounds = self.bounds;
UIEdgeInsets backgroundInsets = [self backgroundInsets];
_backgroundModel.frame = CGRectMake(backgroundInsets.left - 3.0f, backgroundInsets.top, bounds.size.width - backgroundInsets.left + backgroundInsets.right, bounds.size.height - backgroundInsets.top - backgroundInsets.bottom);
}
@end