mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00

git-subtree-dir: submodules/AsyncDisplayKit git-subtree-mainline: d06f423e0ed3df1fed9bd10d79ee312a9179b632 git-subtree-split: 02bedc12816e251ad71777f9d2578329b6d2bef6
426 lines
21 KiB
Objective-C
426 lines
21 KiB
Objective-C
//
|
|
// PhotoTableViewCell.m
|
|
// Texture
|
|
//
|
|
// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved.
|
|
// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved.
|
|
// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
|
|
#import "PhotoTableViewCell.h"
|
|
#import "Utilities.h"
|
|
#import "PINImageView+PINRemoteImage.h"
|
|
#import "PINButton+PINRemoteImage.h"
|
|
|
|
#define DEBUG_PHOTOCELL_LAYOUT 0
|
|
#define USE_UIKIT_AUTOLAYOUT 1
|
|
#define USE_UIKIT_MANUAL_LAYOUT !USE_UIKIT_AUTOLAYOUT
|
|
|
|
#define HEADER_HEIGHT 50
|
|
#define USER_IMAGE_HEIGHT 30
|
|
#define HORIZONTAL_BUFFER 10
|
|
#define VERTICAL_BUFFER 5
|
|
#define FONT_SIZE 14
|
|
|
|
@implementation PhotoTableViewCell
|
|
{
|
|
PhotoModel *_photoModel;
|
|
|
|
UIImageView *_userAvatarImageView;
|
|
UIImageView *_photoImageView;
|
|
UILabel *_userNameLabel;
|
|
UILabel *_photoLocationLabel;
|
|
UILabel *_photoTimeIntervalSincePostLabel;
|
|
UILabel *_photoLikesLabel;
|
|
UILabel *_photoDescriptionLabel;
|
|
|
|
NSLayoutConstraint *_userNameYPositionWithPhotoLocation;
|
|
NSLayoutConstraint *_userNameYPositionWithoutPhotoLocation;
|
|
NSLayoutConstraint *_photoLocationYPosition;
|
|
}
|
|
|
|
#pragma mark - Class Methods
|
|
|
|
+ (CGFloat)heightForPhotoModel:(PhotoModel *)photo withWidth:(CGFloat)width;
|
|
{
|
|
CGFloat photoHeight = width;
|
|
|
|
UIFont *font = [UIFont systemFontOfSize:FONT_SIZE];
|
|
CGFloat likesHeight = roundf([font lineHeight]);
|
|
|
|
NSAttributedString *descriptionAttrString = [photo descriptionAttributedStringWithFontSize:FONT_SIZE];
|
|
CGFloat availableWidth = (width - HORIZONTAL_BUFFER * 2);
|
|
CGFloat descriptionHeight = [descriptionAttrString boundingRectWithSize:CGSizeMake(availableWidth, CGFLOAT_MAX)
|
|
options:NSStringDrawingUsesLineFragmentOrigin
|
|
context:nil].size.height;
|
|
|
|
return HEADER_HEIGHT + photoHeight + likesHeight + descriptionHeight + (4 * VERTICAL_BUFFER);
|
|
}
|
|
|
|
#pragma mark - Lifecycle
|
|
|
|
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
|
|
{
|
|
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
|
|
|
|
if (self) {
|
|
_userAvatarImageView = [[UIImageView alloc] init];
|
|
_photoImageView = [[UIImageView alloc] init];
|
|
_photoImageView.contentMode = UIViewContentModeScaleAspectFill;
|
|
_userNameLabel = [[UILabel alloc] init];
|
|
_photoLocationLabel = [[UILabel alloc] init];
|
|
_photoTimeIntervalSincePostLabel = [[UILabel alloc] init];
|
|
_photoLikesLabel = [[UILabel alloc] init];
|
|
_photoDescriptionLabel = [[UILabel alloc] init];
|
|
_photoDescriptionLabel.numberOfLines = 3;
|
|
|
|
[self addSubview:_userAvatarImageView];
|
|
[self addSubview:_photoImageView];
|
|
[self addSubview:_userNameLabel];
|
|
[self addSubview:_photoLocationLabel];
|
|
[self addSubview:_photoTimeIntervalSincePostLabel];
|
|
[self addSubview:_photoLikesLabel];
|
|
[self addSubview:_photoDescriptionLabel];
|
|
|
|
#if USE_UIKIT_AUTOLAYOUT
|
|
[_userAvatarImageView setTranslatesAutoresizingMaskIntoConstraints:NO];
|
|
[_photoImageView setTranslatesAutoresizingMaskIntoConstraints:NO];
|
|
[_userNameLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
|
|
[_photoLocationLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
|
|
[_photoTimeIntervalSincePostLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
|
|
[_photoLikesLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
|
|
[_photoDescriptionLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
|
|
|
|
[self setupConstraints];
|
|
[self updateConstraints];
|
|
#endif
|
|
|
|
#if DEBUG_PHOTOCELL_LAYOUT
|
|
_userAvatarImageView.backgroundColor = [UIColor greenColor];
|
|
_userNameLabel.backgroundColor = [UIColor greenColor];
|
|
_photoLocationLabel.backgroundColor = [UIColor greenColor];
|
|
_photoTimeIntervalSincePostLabel.backgroundColor = [UIColor greenColor];
|
|
_photoDescriptionLabel.backgroundColor = [UIColor greenColor];
|
|
_photoLikesLabel.backgroundColor = [UIColor greenColor];
|
|
#endif
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
-(void)setFrame:(CGRect)frame
|
|
{
|
|
[super setFrame:frame];
|
|
}
|
|
|
|
- (void)setupConstraints
|
|
{
|
|
// _userAvatarImageView
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_userAvatarImageView
|
|
attribute:NSLayoutAttributeLeft
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_userAvatarImageView.superview
|
|
attribute:NSLayoutAttributeLeft
|
|
multiplier:1.0
|
|
constant:HORIZONTAL_BUFFER]];
|
|
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_userAvatarImageView
|
|
attribute:NSLayoutAttributeTop
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_userAvatarImageView.superview
|
|
attribute:NSLayoutAttributeTop
|
|
multiplier:1.0
|
|
constant:HORIZONTAL_BUFFER]];
|
|
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_userAvatarImageView
|
|
attribute:NSLayoutAttributeWidth
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:nil
|
|
attribute:NSLayoutAttributeNotAnAttribute
|
|
multiplier:0.0
|
|
constant:USER_IMAGE_HEIGHT]];
|
|
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_userAvatarImageView
|
|
attribute:NSLayoutAttributeHeight
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_userAvatarImageView
|
|
attribute:NSLayoutAttributeWidth
|
|
multiplier:1.0
|
|
constant:0.0]];
|
|
|
|
// _userNameLabel
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_userNameLabel
|
|
attribute:NSLayoutAttributeLeft
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_userAvatarImageView
|
|
attribute:NSLayoutAttributeRight
|
|
multiplier:1.0
|
|
constant:HORIZONTAL_BUFFER]];
|
|
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_userNameLabel
|
|
attribute:NSLayoutAttributeRight
|
|
relatedBy:NSLayoutRelationLessThanOrEqual
|
|
toItem:_photoTimeIntervalSincePostLabel
|
|
attribute:NSLayoutAttributeLeft
|
|
multiplier:1.0
|
|
constant:-HORIZONTAL_BUFFER]];
|
|
|
|
_userNameYPositionWithoutPhotoLocation = [NSLayoutConstraint constraintWithItem:_userNameLabel
|
|
attribute:NSLayoutAttributeCenterY
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_userAvatarImageView
|
|
attribute:NSLayoutAttributeCenterY
|
|
multiplier:1.0
|
|
constant:0.0];
|
|
[self addConstraint:_userNameYPositionWithoutPhotoLocation];
|
|
|
|
_userNameYPositionWithPhotoLocation = [NSLayoutConstraint constraintWithItem:_userNameLabel
|
|
attribute:NSLayoutAttributeTop
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_userAvatarImageView
|
|
attribute:NSLayoutAttributeTop
|
|
multiplier:1.0
|
|
constant:-2];
|
|
_userNameYPositionWithPhotoLocation.active = NO;
|
|
[self addConstraint:_userNameYPositionWithPhotoLocation];
|
|
|
|
// _photoLocationLabel
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_photoLocationLabel
|
|
attribute:NSLayoutAttributeLeft
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_userAvatarImageView
|
|
attribute:NSLayoutAttributeRight
|
|
multiplier:1.0
|
|
constant:HORIZONTAL_BUFFER]];
|
|
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_photoLocationLabel
|
|
attribute:NSLayoutAttributeRight
|
|
relatedBy:NSLayoutRelationLessThanOrEqual
|
|
toItem:_photoTimeIntervalSincePostLabel
|
|
attribute:NSLayoutAttributeLeft
|
|
multiplier:1.0
|
|
constant:-HORIZONTAL_BUFFER]];
|
|
|
|
_photoLocationYPosition = [NSLayoutConstraint constraintWithItem:_photoLocationLabel
|
|
attribute:NSLayoutAttributeBottom
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_userAvatarImageView
|
|
attribute:NSLayoutAttributeBottom
|
|
multiplier:1.0
|
|
constant:2];
|
|
_photoLocationYPosition.active = NO;
|
|
[self addConstraint:_photoLocationYPosition];
|
|
|
|
// _photoTimeIntervalSincePostLabel
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_photoTimeIntervalSincePostLabel
|
|
attribute:NSLayoutAttributeRight
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_photoTimeIntervalSincePostLabel.superview
|
|
attribute:NSLayoutAttributeRight
|
|
multiplier:1.0
|
|
constant:-HORIZONTAL_BUFFER]];
|
|
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_photoTimeIntervalSincePostLabel
|
|
attribute:NSLayoutAttributeCenterY
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_userAvatarImageView
|
|
attribute:NSLayoutAttributeCenterY
|
|
multiplier:1.0
|
|
constant:0.0]];
|
|
|
|
// _photoImageView
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_photoImageView
|
|
attribute:NSLayoutAttributeTop
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_photoImageView.superview
|
|
attribute:NSLayoutAttributeTop
|
|
multiplier:1.0
|
|
constant:HEADER_HEIGHT]];
|
|
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_photoImageView
|
|
attribute:NSLayoutAttributeWidth
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeWidth
|
|
multiplier:1.0
|
|
constant:0.0]];
|
|
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_photoImageView
|
|
attribute:NSLayoutAttributeHeight
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_photoImageView
|
|
attribute:NSLayoutAttributeWidth
|
|
multiplier:1.0
|
|
constant:0.0]];
|
|
|
|
// _photoLikesLabel
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_photoLikesLabel
|
|
attribute:NSLayoutAttributeTop
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_photoImageView
|
|
attribute:NSLayoutAttributeBottom
|
|
multiplier:1.0
|
|
constant:VERTICAL_BUFFER]];
|
|
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_photoLikesLabel
|
|
attribute:NSLayoutAttributeLeft
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_photoLikesLabel.superview
|
|
attribute:NSLayoutAttributeLeft
|
|
multiplier:1.0
|
|
constant:HORIZONTAL_BUFFER]];
|
|
|
|
// _photoDescriptionLabel
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_photoDescriptionLabel
|
|
attribute:NSLayoutAttributeTop
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_photoLikesLabel
|
|
attribute:NSLayoutAttributeBottom
|
|
multiplier:1.0
|
|
constant:VERTICAL_BUFFER]];
|
|
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_photoDescriptionLabel
|
|
attribute:NSLayoutAttributeLeft
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_photoDescriptionLabel.superview
|
|
attribute:NSLayoutAttributeLeft
|
|
multiplier:1.0
|
|
constant:HORIZONTAL_BUFFER]];
|
|
|
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:_photoDescriptionLabel
|
|
attribute:NSLayoutAttributeWidth
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_photoDescriptionLabel.superview
|
|
attribute:NSLayoutAttributeWidth
|
|
multiplier:1.0
|
|
constant:-HORIZONTAL_BUFFER]];
|
|
}
|
|
|
|
- (void)updateConstraints
|
|
{
|
|
[super updateConstraints];
|
|
|
|
if (_photoLocationLabel.attributedText) {
|
|
_userNameYPositionWithoutPhotoLocation.active = NO;
|
|
_userNameYPositionWithPhotoLocation.active = YES;
|
|
_photoLocationYPosition.active = YES;
|
|
} else {
|
|
_userNameYPositionWithoutPhotoLocation.active = YES;
|
|
_userNameYPositionWithPhotoLocation.active = NO;
|
|
_photoLocationYPosition.active = NO;
|
|
}
|
|
}
|
|
|
|
- (void)layoutSubviews
|
|
{
|
|
[super layoutSubviews];
|
|
|
|
#if USE_UIKIT_PROGRAMMATIC_LAYOUT
|
|
CGSize boundsSize = self.bounds.size;
|
|
|
|
CGRect rect = CGRectMake(HORIZONTAL_BUFFER, (HEADER_HEIGHT - USER_IMAGE_HEIGHT) / 2.0,
|
|
USER_IMAGE_HEIGHT, USER_IMAGE_HEIGHT);
|
|
_userAvatarImageView.frame = rect;
|
|
|
|
rect.size = _photoTimeIntervalSincePostLabel.bounds.size;
|
|
rect.origin.x = boundsSize.width - HORIZONTAL_BUFFER - rect.size.width;
|
|
rect.origin.y = (HEADER_HEIGHT - rect.size.height) / 2.0;
|
|
_photoTimeIntervalSincePostLabel.frame = rect;
|
|
|
|
CGFloat availableWidth = CGRectGetMinX(_photoTimeIntervalSincePostLabel.frame) - HORIZONTAL_BUFFER;
|
|
rect.size = _userNameLabel.bounds.size;
|
|
rect.size.width = MIN(availableWidth, rect.size.width);
|
|
|
|
rect.origin.x = HORIZONTAL_BUFFER + USER_IMAGE_HEIGHT + HORIZONTAL_BUFFER;
|
|
|
|
if (_photoLocationLabel.attributedText) {
|
|
CGSize locationSize = _photoLocationLabel.bounds.size;
|
|
locationSize.width = MIN(availableWidth, locationSize.width);
|
|
|
|
rect.origin.y = (HEADER_HEIGHT - rect.size.height - locationSize.height) / 2.0;
|
|
_userNameLabel.frame = rect;
|
|
|
|
// FIXME: Name rects at least for this sub-condition
|
|
rect.origin.y += rect.size.height;
|
|
rect.size = locationSize;
|
|
_photoLocationLabel.frame = rect;
|
|
} else {
|
|
rect.origin.y = (HEADER_HEIGHT - rect.size.height) / 2.0;
|
|
_userNameLabel.frame = rect;
|
|
}
|
|
|
|
_photoImageView.frame = CGRectMake(0, HEADER_HEIGHT, boundsSize.width, boundsSize.width);
|
|
|
|
// FIXME: Make PhotoCellFooterView
|
|
rect.size = _photoLikesLabel.bounds.size;
|
|
rect.origin = CGPointMake(HORIZONTAL_BUFFER, CGRectGetMaxY(_photoImageView.frame) + VERTICAL_BUFFER);
|
|
_photoLikesLabel.frame = rect;
|
|
|
|
rect.size = _photoDescriptionLabel.bounds.size;
|
|
rect.size.width = MIN(boundsSize.width - HORIZONTAL_BUFFER * 2, rect.size.width);
|
|
rect.origin.y = CGRectGetMaxY(_photoLikesLabel.frame) + VERTICAL_BUFFER;
|
|
_photoDescriptionLabel.frame = rect;
|
|
#endif
|
|
}
|
|
|
|
- (void)prepareForReuse
|
|
{
|
|
[super prepareForReuse];
|
|
|
|
_userAvatarImageView.image = nil;
|
|
_photoImageView.image = nil;
|
|
_userNameLabel.attributedText = nil;
|
|
_photoLocationLabel.attributedText = nil;
|
|
_photoLocationLabel.frame = CGRectZero; // next cell might not have a _photoLocationLabel
|
|
_photoTimeIntervalSincePostLabel.attributedText = nil;
|
|
_photoLikesLabel.attributedText = nil;
|
|
_photoDescriptionLabel.attributedText = nil;
|
|
}
|
|
|
|
#pragma mark - Instance Methods
|
|
|
|
- (void)updateCellWithPhotoObject:(PhotoModel *)photo
|
|
{
|
|
_photoModel = photo;
|
|
_userNameLabel.attributedText = [photo.ownerUserProfile usernameAttributedStringWithFontSize:FONT_SIZE];
|
|
_photoTimeIntervalSincePostLabel.attributedText = [photo uploadDateAttributedStringWithFontSize:FONT_SIZE];
|
|
_photoLikesLabel.attributedText = [photo likesAttributedStringWithFontSize:FONT_SIZE];
|
|
_photoDescriptionLabel.attributedText = [photo descriptionAttributedStringWithFontSize:FONT_SIZE];
|
|
|
|
[_userNameLabel sizeToFit];
|
|
[_photoTimeIntervalSincePostLabel sizeToFit];
|
|
[_photoLikesLabel sizeToFit];
|
|
[_photoDescriptionLabel sizeToFit];
|
|
CGRect rect = _photoDescriptionLabel.frame;
|
|
CGFloat availableWidth = (self.bounds.size.width - HORIZONTAL_BUFFER * 2);
|
|
rect.size = [_photoDescriptionLabel sizeThatFits:CGSizeMake(availableWidth, CGFLOAT_MAX)];
|
|
_photoDescriptionLabel.frame = rect;
|
|
|
|
[UIImage downloadImageForURL:photo.URL completion:^(UIImage *image) {
|
|
_photoImageView.image = image;
|
|
}];
|
|
|
|
[self downloadAndProcessUserAvatarForPhoto:photo];
|
|
|
|
//update location
|
|
_photoLocationLabel.attributedText = [photo locationAttributedStringWithFontSize:FONT_SIZE];
|
|
[_photoLocationLabel sizeToFit];
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[self updateConstraints];
|
|
[self setNeedsLayout];
|
|
});
|
|
}
|
|
|
|
#pragma mark - Helper Methods
|
|
|
|
- (void)downloadAndProcessUserAvatarForPhoto:(PhotoModel *)photo
|
|
{
|
|
[UIImage downloadImageForURL:photo.URL completion:^(UIImage *image) {
|
|
CGSize profileImageSize = CGSizeMake(USER_IMAGE_HEIGHT, USER_IMAGE_HEIGHT);
|
|
_userAvatarImageView.image = [image makeCircularImageWithSize:profileImageSize];
|
|
}];
|
|
}
|
|
|
|
@end
|