mirror of
https://github.com/danog/Telegram.git
synced 2025-01-22 05:52:06 +01:00
584 lines
24 KiB
Objective-C
584 lines
24 KiB
Objective-C
#import "TGStickerMessageViewModel.h"
|
|
|
|
#import "TGMessageImageViewModel.h"
|
|
|
|
#import "TGMessage.h"
|
|
#import "TGUser.h"
|
|
#import "TGConversation.h"
|
|
|
|
#import "TGImageUtils.h"
|
|
#import "TGStringUtils.h"
|
|
#import "TGDateUtils.h"
|
|
|
|
#import "TGModernConversationItem.h"
|
|
|
|
#import "TGTelegraphConversationMessageAssetsSource.h"
|
|
#import "TGDoubleTapGestureRecognizer.h"
|
|
|
|
#import "TGModernViewContext.h"
|
|
|
|
#import "TGMessageImageView.h"
|
|
|
|
#import "TGModernImageViewModel.h"
|
|
|
|
#import "TGContentBubbleViewModel.h"
|
|
|
|
#import "TGReplyHeaderModel.h"
|
|
#import "TGModernFlatteningViewModel.h"
|
|
#import "TGModernImageViewModel.h"
|
|
|
|
#import "TGViewController.h"
|
|
|
|
@interface TGStickerMessageViewModel () <TGDoubleTapGestureRecognizerDelegate, UIGestureRecognizerDelegate>
|
|
{
|
|
bool _incoming;
|
|
bool _incomingAppearance;
|
|
bool _read;
|
|
TGMessageDeliveryState _deliveryState;
|
|
bool _hasAvatar;
|
|
CGSize _size;
|
|
|
|
float _progress;
|
|
bool _progressVisible;
|
|
|
|
TGDocumentMediaAttachment *_document;
|
|
TGMessageImageViewModel *_imageModel;
|
|
|
|
TGDoubleTapGestureRecognizer *_boundDoubleTapRecognizer;
|
|
UITapGestureRecognizer *_replyTapRecognizer;
|
|
|
|
TGModernImageViewModel *_unsentButtonModel;
|
|
UITapGestureRecognizer *_unsentButtonTapRecognizer;
|
|
|
|
UIImageView *_temporaryHighlightView;
|
|
|
|
TGModernFlatteningViewModel *_contentModel;
|
|
TGModernImageViewModel *_replyBackgroundModel;
|
|
TGReplyHeaderModel *_replyHeaderModel;
|
|
|
|
int32_t _replyMessageId;
|
|
TGMessageViewCountContentProperty *_messageViews;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation TGStickerMessageViewModel
|
|
|
|
- (CGSize)displaySizeForSize:(CGSize)size
|
|
{
|
|
CGSize maxSize = CGSizeMake(160, 170);
|
|
return TGFitSize(CGSizeMake(size.width / 2.0f, size.height / 2.0f), maxSize);
|
|
}
|
|
|
|
- (instancetype)initWithMessage:(TGMessage *)message document:(TGDocumentMediaAttachment *)document size:(CGSize)size authorPeer:(id)authorPeer context:(TGModernViewContext *)context replyHeader:(TGMessage *)replyHeader replyPeer:(id)replyPeer
|
|
{
|
|
self = [super initWithAuthorPeer:authorPeer context:context];
|
|
if (self != nil)
|
|
{
|
|
_mid = message.mid;
|
|
_incoming = !message.outgoing;
|
|
_read = !message.unread;
|
|
_deliveryState = message.deliveryState;
|
|
_hasAvatar = authorPeer != nil && [authorPeer isKindOfClass:[TGUser class]];
|
|
_messageViews = message.viewCount;
|
|
|
|
_needsEditingCheckButton = true;
|
|
|
|
_document = document;
|
|
|
|
_size = size;
|
|
|
|
_incomingAppearance = _incoming || [authorPeer isKindOfClass:[TGConversation class]];
|
|
|
|
_imageModel = [[TGMessageImageViewModel alloc] init];
|
|
_imageModel.expectExtendedEdges = true;
|
|
|
|
_imageModel.overlayBackgroundColorHint = UIColorRGBA(0x000000, 0.4f);
|
|
|
|
CGSize displaySize = [self displaySizeForSize:_size];
|
|
|
|
NSMutableString *imageUri = [[NSMutableString alloc] init];
|
|
[imageUri appendString:@"sticker://?"];
|
|
if (_document.documentId != 0)
|
|
[imageUri appendFormat:@"&documentId=%" PRId64, _document.documentId];
|
|
else
|
|
[imageUri appendFormat:@"&localDocumentId=%" PRId64, _document.localDocumentId];
|
|
[imageUri appendFormat:@"&accessHash=%" PRId64, _document.accessHash];
|
|
[imageUri appendFormat:@"&datacenterId=%d", (int)_document.datacenterId];
|
|
[imageUri appendFormat:@"&fileName=%@", [TGStringUtils stringByEscapingForURL:_document.fileName]];
|
|
[imageUri appendFormat:@"&size=%d", (int)_document.size];
|
|
[imageUri appendFormat:@"&width=%d&height=%d", (int)displaySize.width, (int)displaySize.height];
|
|
[imageUri appendFormat:@"&mime-type=%@", [TGStringUtils stringByEscapingForURL:_document.mimeType]];
|
|
|
|
[_imageModel setUri:imageUri];
|
|
|
|
_imageModel.frame = CGRectMake(0.0f, 0.0f, displaySize.width, displaySize.height);
|
|
_imageModel.skipDrawInContext = true;
|
|
[self addSubmodel:_imageModel];
|
|
|
|
[_imageModel setTimestampColor:[[TGTelegraphConversationMessageAssetsSource instance] systemMessageBackgroundColor]];
|
|
[_imageModel setTimestampString:[TGDateUtils stringForShortTime:(int)message.date] displayCheckmarks:!_incoming && _deliveryState != TGMessageDeliveryStateFailed checkmarkValue:(_incoming ? 0 : ((_deliveryState == TGMessageDeliveryStateDelivered ? 1 : 0) + (_read ? 1 : 0))) displayViews:_messageViews != nil viewsValue:_messageViews.viewCount animated:false];
|
|
[_imageModel setDisplayTimestampProgress:_deliveryState == TGMessageDeliveryStatePending];
|
|
[_imageModel setIsBroadcast:message.isBroadcast];
|
|
|
|
__weak TGStickerMessageViewModel *weakSelf = self;
|
|
_imageModel.completionBlock = ^(__unused TGImageView *imageView)
|
|
{
|
|
__strong TGStickerMessageViewModel *strongSelf = weakSelf;
|
|
if (strongSelf != nil)
|
|
{
|
|
if (strongSelf->_progressVisible)
|
|
[strongSelf updateProgressInternal:false progress:1.0f animated:true];
|
|
}
|
|
};
|
|
|
|
if (!_incoming)
|
|
{
|
|
if (_deliveryState == TGMessageDeliveryStatePending)
|
|
{
|
|
}
|
|
else if (_deliveryState == TGMessageDeliveryStateFailed)
|
|
{
|
|
[self addSubmodel:[self unsentButtonModel]];
|
|
}
|
|
else if (_deliveryState == TGMessageDeliveryStateDelivered)
|
|
{
|
|
}
|
|
}
|
|
|
|
if (replyHeader != nil)
|
|
{
|
|
_replyMessageId = replyHeader.mid;
|
|
|
|
_replyBackgroundModel = [[TGModernImageViewModel alloc] initWithImage:[[TGTelegraphConversationMessageAssetsSource instance] systemReplyBackground]];
|
|
_replyBackgroundModel.skipDrawInContext = true;
|
|
[self addSubmodel:_replyBackgroundModel];
|
|
|
|
_contentModel = [[TGModernFlatteningViewModel alloc] init];
|
|
[self addSubmodel:_contentModel];
|
|
|
|
_replyHeaderModel = [TGContentBubbleViewModel replyHeaderModelFromMessage:replyHeader peer:replyPeer incoming:_incomingAppearance system:true];
|
|
[_contentModel addSubmodel:_replyHeaderModel];
|
|
}
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)updateAssets
|
|
{
|
|
[super updateAssets];
|
|
|
|
[_imageModel setTimestampColor:[[TGTelegraphConversationMessageAssetsSource instance] systemMessageBackgroundColor]];
|
|
}
|
|
|
|
- (TGModernImageViewModel *)unsentButtonModel
|
|
{
|
|
if (_unsentButtonModel == nil)
|
|
{
|
|
static UIImage *image = nil;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^
|
|
{
|
|
image = [UIImage imageNamed:@"ModernMessageUnsentButton.png"];
|
|
});
|
|
|
|
_unsentButtonModel = [[TGModernImageViewModel alloc] initWithImage:image];
|
|
_unsentButtonModel.frame = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height);
|
|
_unsentButtonModel.extendedEdges = UIEdgeInsetsMake(6, 6, 6, 6);
|
|
}
|
|
|
|
return _unsentButtonModel;
|
|
}
|
|
|
|
- (void)updateProgressInternal:(bool)progressVisible progress:(float)progress animated:(bool)animated
|
|
{
|
|
bool progressWasVisible = _progressVisible;
|
|
float previousProgress = _progress;
|
|
|
|
_progress = progress;
|
|
_progressVisible = progressVisible;
|
|
|
|
[self updateImageOverlay:((progressWasVisible && !_progressVisible) || (_progressVisible && ABS(_progress - previousProgress) > FLT_EPSILON)) && animated];
|
|
}
|
|
|
|
- (void)updateImageOverlay:(bool)animated
|
|
{
|
|
if (_progressVisible)
|
|
{
|
|
[_imageModel setOverlayType:TGMessageImageViewOverlayProgressNoCancel animated:false];
|
|
[_imageModel setProgress:_progress animated:animated];
|
|
}
|
|
else
|
|
{
|
|
[_imageModel setOverlayType:TGMessageImageViewOverlayNone animated:animated];
|
|
}
|
|
}
|
|
|
|
- (void)updateMessage:(TGMessage *)message viewStorage:(TGModernViewStorage *)viewStorage sizeUpdated:(bool *)sizeUpdated
|
|
{
|
|
[super updateMessage:message viewStorage:viewStorage sizeUpdated:sizeUpdated];
|
|
|
|
_mid = message.mid;
|
|
|
|
if (_deliveryState != message.deliveryState || (!_incoming && _read != !message.unread) || (_messageViews != nil && _messageViews.viewCount != message.viewCount.viewCount))
|
|
{
|
|
_messageViews = message.viewCount;
|
|
_deliveryState = message.deliveryState;
|
|
_read = !message.unread;
|
|
|
|
[_imageModel setTimestampString:[TGDateUtils stringForShortTime:(int)message.date] displayCheckmarks:!_incoming && _deliveryState != TGMessageDeliveryStateFailed checkmarkValue:(_incoming ? 0 : ((_deliveryState == TGMessageDeliveryStateDelivered ? 1 : 0) + (_read ? 1 : 0))) displayViews:_messageViews != nil viewsValue:_messageViews.viewCount animated:true];
|
|
[_imageModel setDisplayTimestampProgress:_deliveryState == TGMessageDeliveryStatePending];
|
|
|
|
if (_deliveryState == TGMessageDeliveryStateDelivered)
|
|
{
|
|
if (_unsentButtonModel != nil)
|
|
{
|
|
[self removeSubmodel:_unsentButtonModel viewStorage:viewStorage];
|
|
_unsentButtonModel = nil;
|
|
}
|
|
}
|
|
else if (_deliveryState == TGMessageDeliveryStateFailed)
|
|
{
|
|
if (_unsentButtonModel == nil)
|
|
{
|
|
[self addSubmodel:[self unsentButtonModel]];
|
|
if ([_imageModel boundView] != nil)
|
|
[_unsentButtonModel bindViewToContainer:[_imageModel boundView].superview viewStorage:viewStorage];
|
|
_unsentButtonModel.frame = CGRectOffset(_unsentButtonModel.frame, self.frame.size.width + _unsentButtonModel.frame.size.width, self.frame.size.height - _unsentButtonModel.frame.size.height - ((_collapseFlags & TGModernConversationItemCollapseBottom) ? 5 : 6));
|
|
|
|
_unsentButtonTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(unsentButtonTapGesture:)];
|
|
[[_unsentButtonModel boundView] addGestureRecognizer:_unsentButtonTapRecognizer];
|
|
}
|
|
|
|
if (self.frame.size.width > FLT_EPSILON)
|
|
{
|
|
if ([_imageModel boundView] != nil)
|
|
{
|
|
[UIView animateWithDuration:0.2 animations:^
|
|
{
|
|
[self layoutForContainerSize:CGSizeMake(self.frame.size.width, 0.0f)];
|
|
}];
|
|
}
|
|
else
|
|
[self layoutForContainerSize:CGSizeMake(self.frame.size.width, 0.0f)];
|
|
}
|
|
}
|
|
else if (_deliveryState == TGMessageDeliveryStatePending)
|
|
{
|
|
if (_unsentButtonModel != nil)
|
|
{
|
|
UIView<TGModernView> *unsentView = [_unsentButtonModel boundView];
|
|
if (unsentView != nil)
|
|
{
|
|
[unsentView removeGestureRecognizer:_unsentButtonTapRecognizer];
|
|
_unsentButtonTapRecognizer = nil;
|
|
}
|
|
|
|
if (unsentView != nil)
|
|
{
|
|
[viewStorage allowResurrectionForOperations:^
|
|
{
|
|
[self removeSubmodel:_unsentButtonModel viewStorage:viewStorage];
|
|
|
|
UIView *restoredView = [viewStorage dequeueViewWithIdentifier:[unsentView viewIdentifier] viewStateIdentifier:[unsentView viewStateIdentifier]];
|
|
|
|
if (restoredView != nil)
|
|
{
|
|
[[_imageModel boundView].superview addSubview:restoredView];
|
|
|
|
[UIView animateWithDuration:0.2 animations:^
|
|
{
|
|
restoredView.frame = CGRectOffset(restoredView.frame, restoredView.frame.size.width + 9, 0.0f);
|
|
restoredView.alpha = 0.0f;
|
|
} completion:^(__unused BOOL finished)
|
|
{
|
|
[viewStorage enqueueView:restoredView];
|
|
}];
|
|
}
|
|
}];
|
|
}
|
|
else
|
|
[self removeSubmodel:_unsentButtonModel viewStorage:viewStorage];
|
|
|
|
_unsentButtonModel = nil;
|
|
}
|
|
|
|
if (self.frame.size.width > FLT_EPSILON)
|
|
{
|
|
if ([_imageModel boundView] != nil)
|
|
{
|
|
[UIView animateWithDuration:0.2 animations:^
|
|
{
|
|
[self layoutForContainerSize:CGSizeMake(self.frame.size.width, 0.0f)];
|
|
}];
|
|
}
|
|
else
|
|
[self layoutForContainerSize:CGSizeMake(self.frame.size.width, 0.0f)];
|
|
}
|
|
}
|
|
}
|
|
|
|
for (id attachment in message.mediaAttachments)
|
|
{
|
|
if ([attachment isKindOfClass:[TGDocumentMediaAttachment class]])
|
|
{
|
|
_document = attachment;
|
|
}
|
|
}
|
|
|
|
CGSize displaySize = [self displaySizeForSize:_size];
|
|
|
|
NSMutableString *imageUri = [[NSMutableString alloc] init];
|
|
[imageUri appendString:@"sticker://?"];
|
|
if (_document.documentId != 0)
|
|
[imageUri appendFormat:@"&documentId=%" PRId64, _document.documentId];
|
|
else
|
|
[imageUri appendFormat:@"&localDocumentId=%" PRId64, _document.localDocumentId];
|
|
[imageUri appendFormat:@"&accessHash=%" PRId64, _document.accessHash];
|
|
[imageUri appendFormat:@"&datacenterId=%d", (int)_document.datacenterId];
|
|
[imageUri appendFormat:@"&fileName=%@", [TGStringUtils stringByEscapingForURL:_document.fileName]];
|
|
[imageUri appendFormat:@"&size=%d", (int)_document.size];
|
|
[imageUri appendFormat:@"&width=%d&height=%d", (int)displaySize.width, (int)displaySize.height];
|
|
[imageUri appendFormat:@"&mime-type=%@", [TGStringUtils stringByEscapingForURL:_document.mimeType]];
|
|
|
|
[_imageModel setUri:imageUri];
|
|
}
|
|
|
|
- (CGRect)effectiveContentFrame
|
|
{
|
|
return _imageModel.frame;
|
|
}
|
|
|
|
- (void)bindSpecialViewsToContainer:(UIView *)container viewStorage:(TGModernViewStorage *)viewStorage atItemPosition:(CGPoint)itemPosition
|
|
{
|
|
[super bindSpecialViewsToContainer:container viewStorage:viewStorage atItemPosition:itemPosition];
|
|
|
|
[_imageModel bindViewToContainer:container viewStorage:viewStorage];
|
|
[_imageModel boundView].frame = CGRectOffset([_imageModel boundView].frame, itemPosition.x, itemPosition.y);
|
|
|
|
_replyBackgroundModel.parentOffset = itemPosition;
|
|
[_replyBackgroundModel bindViewToContainer:container viewStorage:viewStorage];
|
|
|
|
_contentModel.parentOffset = itemPosition;
|
|
[_contentModel bindViewToContainer:container viewStorage:viewStorage];
|
|
|
|
[_replyHeaderModel bindSpecialViewsToContainer:container viewStorage:viewStorage atItemPosition:CGPointMake(itemPosition.x + _contentModel.frame.origin.x + _replyHeaderModel.frame.origin.x, itemPosition.y + _contentModel.frame.origin.y + _replyHeaderModel.frame.origin.y)];
|
|
}
|
|
|
|
- (void)bindViewToContainer:(UIView *)container viewStorage:(TGModernViewStorage *)viewStorage
|
|
{
|
|
[self updateEditingState:nil viewStorage:nil animationDelay:-1.0];
|
|
|
|
_replyBackgroundModel.parentOffset = CGPointZero;
|
|
_contentModel.parentOffset = CGPointZero;
|
|
|
|
[super bindViewToContainer:container viewStorage:viewStorage];
|
|
|
|
[_replyHeaderModel bindSpecialViewsToContainer:_contentModel.boundView viewStorage:viewStorage atItemPosition:CGPointMake(_replyHeaderModel.frame.origin.x, _replyHeaderModel.frame.origin.y)];
|
|
|
|
_boundDoubleTapRecognizer = [[TGDoubleTapGestureRecognizer alloc] initWithTarget:self action:@selector(messageDoubleTapGesture:)];
|
|
_boundDoubleTapRecognizer.delegate = self;
|
|
|
|
if (_replyHeaderModel != nil)
|
|
{
|
|
_replyTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(replyHeaderTapGesture:)];
|
|
[[_contentModel boundView] addGestureRecognizer:_replyTapRecognizer];
|
|
}
|
|
|
|
if (_unsentButtonModel != nil)
|
|
{
|
|
_unsentButtonTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(unsentButtonTapGesture:)];
|
|
[[_unsentButtonModel boundView] addGestureRecognizer:_unsentButtonTapRecognizer];
|
|
}
|
|
|
|
UIView *backgroundView = [_imageModel boundView];
|
|
[backgroundView addGestureRecognizer:_boundDoubleTapRecognizer];
|
|
}
|
|
|
|
- (void)unbindView:(TGModernViewStorage *)viewStorage
|
|
{
|
|
UIView *imageView = [_imageModel boundView];
|
|
[imageView removeGestureRecognizer:_boundDoubleTapRecognizer];
|
|
_boundDoubleTapRecognizer.delegate = nil;
|
|
_boundDoubleTapRecognizer = nil;
|
|
|
|
[[_contentModel boundView] removeGestureRecognizer:_replyTapRecognizer];
|
|
_replyTapRecognizer = nil;
|
|
|
|
if (_temporaryHighlightView != nil)
|
|
{
|
|
[_temporaryHighlightView removeFromSuperview];
|
|
_temporaryHighlightView = nil;
|
|
}
|
|
|
|
if (_unsentButtonModel != nil)
|
|
{
|
|
[[_unsentButtonModel boundView] removeGestureRecognizer:_unsentButtonTapRecognizer];
|
|
_unsentButtonTapRecognizer = nil;
|
|
}
|
|
|
|
[super unbindView:viewStorage];
|
|
}
|
|
|
|
- (void)unsentButtonTapGesture:(UITapGestureRecognizer *)recognizer
|
|
{
|
|
if (recognizer.state == UIGestureRecognizerStateRecognized)
|
|
{
|
|
[_context.companionHandle requestAction:@"showUnsentMessageMenu" options:@{@"mid": @(_mid)}];
|
|
}
|
|
}
|
|
|
|
- (void)replyHeaderTapGesture:(UITapGestureRecognizer *)recognizer
|
|
{
|
|
if (recognizer.state == UIGestureRecognizerStateEnded)
|
|
{
|
|
[_context.companionHandle requestAction:@"navigateToMessage" options:@{@"mid": @(_replyMessageId), @"sourceMid": @(_mid)}];
|
|
}
|
|
}
|
|
|
|
- (void)messageDoubleTapGesture:(TGDoubleTapGestureRecognizer *)recognizer
|
|
{
|
|
if (recognizer.state == UIGestureRecognizerStateRecognized)
|
|
{
|
|
if (recognizer.longTapped || recognizer.doubleTapped)
|
|
[_context.companionHandle requestAction:@"messageSelectionRequested" options:@{@"mid": @(_mid)}];
|
|
}
|
|
}
|
|
|
|
- (bool)gestureRecognizerShouldHandleLongTap:(TGDoubleTapGestureRecognizer *)__unused recognizer
|
|
{
|
|
return true;
|
|
}
|
|
|
|
- (void)gestureRecognizer:(TGDoubleTapGestureRecognizer *)__unused recognizer didBeginAtPoint:(CGPoint)__unused point
|
|
{
|
|
}
|
|
|
|
- (int)gestureRecognizer:(TGDoubleTapGestureRecognizer *)__unused recognizer shouldFailTap:(CGPoint)__unused point
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
- (void)doubleTapGestureRecognizerSingleTapped:(TGDoubleTapGestureRecognizer *)__unused recognizer
|
|
{
|
|
}
|
|
|
|
- (bool)gestureRecognizerShouldLetScrollViewStealTouches:(TGDoubleTapGestureRecognizer *)__unused recognizer
|
|
{
|
|
return true;
|
|
}
|
|
|
|
- (bool)gestureRecognizerShouldFailOnMove:(TGDoubleTapGestureRecognizer *)__unused recognizer
|
|
{
|
|
return true;
|
|
}
|
|
|
|
- (void)setTemporaryHighlighted:(bool)temporaryHighlighted viewStorage:(TGModernViewStorage *)__unused viewStorage
|
|
{
|
|
if (iosMajorVersion() >= 7)
|
|
{
|
|
TGImageView *imageView = ((TGMessageImageViewContainer *)_imageModel.boundView).imageView;
|
|
if (imageView.currentImage != nil)
|
|
{
|
|
if (temporaryHighlighted)
|
|
{
|
|
if (_temporaryHighlightView == nil)
|
|
{
|
|
UIImage *highlightImage = [imageView.currentImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
|
_temporaryHighlightView = [[UIImageView alloc] initWithImage:highlightImage];
|
|
_temporaryHighlightView.frame = [_imageModel boundView].frame;
|
|
_temporaryHighlightView.tintColor = UIColorRGBA(0x000000, 0.2f);
|
|
[[_imageModel boundView].superview addSubview:_temporaryHighlightView];
|
|
}
|
|
}
|
|
else if (_temporaryHighlightView != nil)
|
|
{
|
|
UIImageView *temporaryView = _temporaryHighlightView;
|
|
[UIView animateWithDuration:0.4 animations:^
|
|
{
|
|
temporaryView.alpha = 0.0f;
|
|
} completion:^(__unused BOOL finished)
|
|
{
|
|
[temporaryView removeFromSuperview];
|
|
}];
|
|
_temporaryHighlightView = nil;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)layoutForContainerSize:(CGSize)containerSize
|
|
{
|
|
bool isPost = _authorPeer != nil && [_authorPeer isKindOfClass:[TGConversation class]];
|
|
TGMessageViewModelLayoutConstants const *layoutConstants = TGGetMessageViewModelLayoutConstants();
|
|
|
|
CGFloat topSpacing = (_collapseFlags & TGModernConversationItemCollapseTop) ? layoutConstants->topInsetCollapsed : layoutConstants->topInset;
|
|
CGFloat bottomSpacing = (_collapseFlags & TGModernConversationItemCollapseBottom) ? layoutConstants->bottomInsetCollapsed : layoutConstants->bottomInset;
|
|
|
|
if (isPost) {
|
|
topSpacing = layoutConstants->topPostInset;
|
|
bottomSpacing = layoutConstants->bottomPostInset;
|
|
}
|
|
|
|
CGFloat avatarOffset = 0.0f;
|
|
if (_hasAvatar)
|
|
avatarOffset = 38.0f;
|
|
|
|
CGFloat unsentOffset = 0.0f;
|
|
if (!_incomingAppearance && _deliveryState == TGMessageDeliveryStateFailed)
|
|
unsentOffset = 29.0f;
|
|
|
|
CGRect imageFrame = CGRectMake(_incomingAppearance ? (avatarOffset + layoutConstants->leftImageInset) : (containerSize.width - _imageModel.frame.size.width - layoutConstants->rightImageInset - unsentOffset), topSpacing, _imageModel.frame.size.width, _imageModel.frame.size.height);
|
|
if (_incomingAppearance && _editing)
|
|
imageFrame.origin.x += 42.0f;
|
|
|
|
_imageModel.frame = imageFrame;
|
|
|
|
if (_contentModel != nil)
|
|
{
|
|
CGFloat availableWidth = containerSize.width - imageFrame.size.width - 40.0f - avatarOffset;
|
|
|
|
bool updateContent = false;
|
|
[_replyHeaderModel layoutForContainerSize:CGSizeMake(availableWidth, 0.0f) updateContent:&updateContent];
|
|
CGRect contentFrame = CGRectMake(0.0f, CGRectGetMaxY(imageFrame) - _replyHeaderModel.frame.size.height - 8.0f, _replyHeaderModel.frame.size.width + 14.0f, _replyHeaderModel.frame.size.height + 4.0f);
|
|
if (_incomingAppearance)
|
|
contentFrame.origin.x = containerSize.width - contentFrame.size.width - 7.0f;
|
|
else
|
|
contentFrame.origin.x = 9.0f + (_editing ? 42.0f : 0.0f);
|
|
|
|
_contentModel.frame = contentFrame;
|
|
_replyHeaderModel.frame = CGRectMake(5.0f, 0.0f, _replyHeaderModel.frame.size.width, _replyHeaderModel.frame.size.height);
|
|
_replyBackgroundModel.frame = CGRectMake(contentFrame.origin.x, contentFrame.origin.y + 3.0f, _replyHeaderModel.frame.size.width + 12.0f, _replyHeaderModel.frame.size.height - 1.0f);
|
|
|
|
if ((_incomingAppearance && _replyBackgroundModel.frame.origin.x < CGRectGetMaxX(imageFrame)) || (!_incomingAppearance && CGRectGetMaxX(_replyBackgroundModel.frame) > imageFrame.origin.x))
|
|
{
|
|
_contentModel.alpha = 0.0f;
|
|
_replyBackgroundModel.alpha = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
_contentModel.alpha = 1.0f;
|
|
_replyBackgroundModel.alpha = 1.0f;
|
|
}
|
|
|
|
if (updateContent)
|
|
{
|
|
[_contentModel setNeedsSubmodelContentsUpdate];
|
|
[_contentModel updateSubmodelContentsIfNeeded];
|
|
}
|
|
}
|
|
|
|
if (_unsentButtonModel != nil)
|
|
{
|
|
_unsentButtonModel.frame = CGRectMake(containerSize.width - _unsentButtonModel.frame.size.width - 9, _imageModel.frame.size.height + topSpacing + bottomSpacing - _unsentButtonModel.frame.size.height - ((_collapseFlags & TGModernConversationItemCollapseBottom) ? 5 : 6), _unsentButtonModel.frame.size.width, _unsentButtonModel.frame.size.height);
|
|
}
|
|
|
|
CGRect frame = self.frame;
|
|
frame.size = CGSizeMake(containerSize.width, _imageModel.frame.size.height + topSpacing + bottomSpacing);
|
|
self.frame = frame;
|
|
|
|
[super layoutForContainerSize:containerSize];
|
|
}
|
|
|
|
@end
|