| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- //
- // T1StatusLayout.m
- // YYKitExample
- //
- // Created by guoyaoyuan on 15/10/10.
- // Copyright (C) 2015 ibireme. All rights reserved.
- //
- #import "T1StatusLayout.h"
- #import "T1Helper.h"
- @implementation T1StatusLayout
- - (void)setTweet:(T1Tweet *)tweet {
- if (_tweet != tweet) {
- _tweet = tweet;
- [self layout];
- }
- }
- - (void)layout {
- [self reset];
- if (!_tweet) {
- if (_conversation) {
- _isConversationSplit = YES;
- _height = kT1ConversationSplitHeight;
- return;
- } else {
- return;
- }
- }
-
- if (_conversation) {
- BOOL isTop = NO, isBottom = NO;
- if (_tweet.tidStr) {
- NSUInteger index = [_conversation.contextIDs indexOfObject:_tweet.tidStr];
- if (index == 0) {
- isTop = YES;
- } else if (index + 1 == _conversation.contextIDs.count) {
- isBottom = YES;
- }
- }
-
- if (isTop) {
- _showTopLine = YES;
- _showConversationBottomJoin = YES;
- } else if (isBottom) {
- _showConversationTopJoin = YES;
- } else {
- _showConversationTopJoin = YES;
- _showConversationBottomJoin = YES;
- }
- } else {
- _showTopLine = YES;
- }
-
- T1Tweet *tweet = self.displayedTweet;
-
- UIFont *nameSubFont = [UIFont systemFontOfSize:kT1UserNameSubFontSize];
- NSMutableAttributedString *dateText = [[NSMutableAttributedString alloc] initWithString:[T1Helper stringWithTimelineDate:tweet.createdAt]];
-
- if (tweet.card) {
- UIImage *iconImage = [T1Helper imageNamed:@"ic_tweet_attr_summary_default"];
- NSAttributedString *icon = [NSAttributedString attachmentStringWithContent:iconImage contentMode:UIViewContentModeCenter attachmentSize:iconImage.size alignToFont:nameSubFont alignment:YYTextVerticalAlignmentCenter];
- [dateText insertString:@" " atIndex:0];
- [dateText insertAttributedString:icon atIndex:0];
- }
- dateText.font = nameSubFont;
- dateText.color = kT1UserNameSubColor;
- dateText.alignment = NSTextAlignmentRight;
-
- _dateTextLayout = [YYTextLayout layoutWithContainerSize:CGSizeMake(kT1ContentWidth, kT1UserNameSubFontSize * 2) text:dateText];
-
-
- UIFont *nameFont = [UIFont systemFontOfSize:kT1UserNameFontSize];
- NSMutableAttributedString *nameText = [[NSMutableAttributedString alloc] initWithString:(tweet.user.name ? tweet.user.name : @"")];
- nameText.font = nameFont;
- nameText.color = kT1UserNameColor;
- if (tweet.user.screenName) {
- NSMutableAttributedString *screenNameText = [[NSMutableAttributedString alloc] initWithString:tweet.user.screenName];
- [screenNameText insertString:@" @" atIndex:0];
- screenNameText.font = nameSubFont;
- screenNameText.color = kT1UserNameSubColor;
- [nameText appendAttributedString:screenNameText];
- }
- nameText.lineBreakMode = NSLineBreakByCharWrapping;
-
- YYTextContainer *nameContainer = [YYTextContainer containerWithSize:CGSizeMake(kT1ContentWidth - _dateTextLayout.textBoundingRect.size.width - 5, kT1UserNameFontSize * 2)];
- nameContainer.maximumNumberOfRows = 1;
- _nameTextLayout = [YYTextLayout layoutWithContainer:nameContainer text:nameText];
-
-
- NSString *socialString = nil;
- if (_tweet.retweetedStatus) {
- if (_tweet.user.name) {
- socialString = [NSString stringWithFormat:@"%@ Retweeted",_tweet.user.name];
- }
- } else if (tweet.inReplyToScreenName) {
- socialString = [NSString stringWithFormat:@"in reply to @%@",tweet.inReplyToScreenName];
- }
-
- if (socialString) {
- NSMutableAttributedString *socialText = [[NSMutableAttributedString alloc] initWithString:socialString];
- socialText.font = nameSubFont;
- socialText.color = kT1UserNameSubColor;
- socialText.lineBreakMode = NSLineBreakByCharWrapping;
- YYTextContainer *socialContainer = [YYTextContainer containerWithSize:CGSizeMake(kT1ContentWidth, kT1UserNameFontSize * 2)];
- socialContainer.maximumNumberOfRows = 1;
- _socialTextLayout = [YYTextLayout layoutWithContainer:socialContainer text:socialText];
- }
-
- YYTextContainer *textContainer = [YYTextContainer containerWithSize:CGSizeMake(kT1ContentWidth + 2 * kT1TextContainerInset, CGFLOAT_MAX)];
- textContainer.insets = UIEdgeInsetsMake(0, kT1TextContainerInset, 0, kT1TextContainerInset);
- _textLayout = [YYTextLayout layoutWithContainer:textContainer text:[self textForTweet:tweet]];
-
- if (tweet.medias.count || tweet.extendedMedias.count) {
- NSMutableArray *images = [NSMutableArray new];
- NSMutableSet *imageIDs = [NSMutableSet new];
-
- for (T1Media *media in tweet.medias) {
- if ([media.type isEqualToString:@"photo"]) {
- if (media.mediaSmall && media.mediaLarge) {
- if (media.midStr && ![imageIDs containsObject:media.midStr]) {
- [images addObject:media];
- [imageIDs addObject:media.midStr];
- }
- }
- }
- }
-
- for (T1Media *media in tweet.extendedMedias) {
- if ([media.type isEqualToString:@"photo"]) {
- if (media.mediaSmall && media.mediaLarge) {
- if (media.midStr && ![imageIDs containsObject:media.midStr]) {
- [images addObject:media];
- [imageIDs addObject:media.midStr];
- }
- }
- }
- }
-
- while (images.count > 4) {
- [images removeLastObject];
- }
- if (images.count > 0) {
- _images = images;
- }
- }
-
-
- if (!_images && !_tweet.retweetedStatus && _tweet.quotedStatus) {
- T1Tweet *quote = _tweet.quotedStatus;
- NSMutableAttributedString *nameText = [[NSMutableAttributedString alloc] initWithString:(quote.user.name ? quote.user.name : @"")];
- nameText.font = nameFont;
- nameText.color = kT1UserNameColor;
- if (quote.user.screenName) {
- NSMutableAttributedString *screenNameText = [[NSMutableAttributedString alloc] initWithString:quote.user.screenName];
- [screenNameText insertString:@" @" atIndex:0];
- screenNameText.font = nameSubFont;
- screenNameText.color = kT1UserNameSubColor;
- [nameText appendAttributedString:screenNameText];
- }
- nameText.lineBreakMode = NSLineBreakByCharWrapping;
-
- YYTextContainer *nameContainer = [YYTextContainer containerWithSize:CGSizeMake(kT1QuoteContentWidth, kT1UserNameFontSize * 2)];
- nameContainer.maximumNumberOfRows = 1;
- _quotedNameTextLayout = [YYTextLayout layoutWithContainer:nameContainer text:nameText];
-
- NSAttributedString *quoteText = [self textForTweet:quote];
- _quotedTextLayout = [YYTextLayout layoutWithContainerSize:CGSizeMake(kT1QuoteContentWidth, CGFLOAT_MAX) text:quoteText];
- }
-
- _retweetCountTextLayout = [self retweetCountTextLayoutForTweet:tweet];
- _favoriteCountTextLayout = [self favoriteCountTextLayoutForTweet:tweet];
-
- if (_socialTextLayout) {
- _paddingTop = kT1CellExtendedPadding;
- } else {
- _paddingTop = kT1CellPadding;
- }
-
- _textTop = _paddingTop + kT1UserNameFontSize + kT1CellInnerPadding;
- _textHeight = _textLayout ? (CGRectGetMaxY(_textLayout.textBoundingRect)) : 0;
- _imagesTop = _quoteTop = _textTop + _textHeight + kT1CellInnerPadding;
- if (_images) {
- _imagesHeight = kT1ContentWidth * (9.0 / 16.0);
- } else if (_quotedTextLayout) {
- _quoteHeight = 2 * kT1CellPadding + kT1UserNameFontSize + CGRectGetMaxY(_quotedTextLayout.textBoundingRect);
- }
-
- CGFloat height = 0;
- if (_imagesHeight > 0) {
- height = _imagesTop + _imagesHeight;
- } else if (_quoteHeight > 0) {
- height = _quoteTop + _quoteHeight;
- } else {
- height = _textTop + _textHeight;
- }
- height += kT1ActionsHeight;
- if (height < _paddingTop + kT1AvatarSize) {
- height = _paddingTop + kT1AvatarSize;
- }
- height += kT1CellExtendedPadding;
- _height = height;
- }
- - (void)reset {
- _height = 0;
- _paddingTop = 0;
- _textTop = 0;
- _textHeight = 0;
- _imagesTop = 0;
- _imagesHeight = 0;
- _quoteTop = 0;
- _quoteHeight = 0;
-
- _showTopLine = NO;
- _isConversationSplit = NO;
- _showConversationTopJoin = NO;
- _showConversationBottomJoin = NO;
- _socialTextLayout = nil;
- _nameTextLayout = nil;
- _dateTextLayout = nil;
- _textLayout = nil;
- _quotedNameTextLayout = nil;
- _quotedTextLayout = nil;
- _retweetCountTextLayout = nil;
- _favoriteCountTextLayout = nil;
- _images = nil;
- }
- - (NSAttributedString *)textForTweet:(T1Tweet *)tweet{
- if (tweet.text.length == 0) return nil;
- NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:tweet.text];
- text.font = [UIFont systemFontOfSize:kT1TextFontSize];
- text.color = kT1TextColor;
-
- for (T1URL *url in tweet.urls) {
- if (url.ranges) {
- for (NSValue *value in url.ranges) {
- [self setHighlightInfo:@{@"T1URL" : url} withRange:value.rangeValue toText:text];
- }
- } else {
- [self setHighlightInfo:@{@"T1URL" : url} withRange:url.range toText:text];
- }
- }
-
- for (T1Media *media in tweet.medias) {
- if (media.ranges) {
- for (NSValue *value in media.ranges) {
- [self setHighlightInfo:@{@"T1Media" : media} withRange:value.rangeValue toText:text];
- }
- } else {
- [self setHighlightInfo:@{@"T1Media" : media} withRange:media.range toText:text];
- }
- }
-
- for (T1Media *media in tweet.extendedMedias) {
- if (media.ranges) {
- for (NSValue *value in media.ranges) {
- [self setHighlightInfo:@{@"T1Media" : media} withRange:value.rangeValue toText:text];
- }
- } else {
- [self setHighlightInfo:@{@"T1Media" : media} withRange:media.range toText:text];
- }
- }
-
- return text;
- }
- - (void)setHighlightInfo:(NSDictionary*)info withRange:(NSRange)range toText:(NSMutableAttributedString *)text {
- if (range.length == 0 || text.length == 0) return;
- {
- NSString *str = text.string;
- unichar *chars = malloc(str.length * sizeof(unichar));
- if (!chars) return;
- [str getCharacters:chars range:NSMakeRange(0, str.length)];
-
- NSUInteger start = range.location, end = range.location + range.length;
- for (int i = 0; i < str.length; i++) {
- unichar c = chars[i];
- if (0xD800 <= c && c <= 0xDBFF) { // UTF16 lead surrogates
- if (start > i) start++;
- if (end > i) end++;
- }
- }
- free(chars);
- if (end <= start) return;
- range = NSMakeRange(start, end - start);
- }
-
- if (range.location >= text.length) return;
- if (range.location + range.length > text.length) return;
-
- YYTextBorder *border = [YYTextBorder new];
- border.cornerRadius = 3;
- border.insets = UIEdgeInsetsMake(-2, -2, -2, -2);
- border.fillColor = kT1TextHighlightedBackgroundColor;
-
- YYTextHighlight *highlight = [YYTextHighlight new];
- [highlight setBackgroundBorder:border];
- highlight.userInfo = info;
-
- [text setTextHighlight:highlight range:range];
- [text setColor:kT1TextHighlightedColor range:range];
- }
- - (T1Tweet *)displayedTweet {
- return _tweet.retweetedStatus ? _tweet.retweetedStatus : _tweet;
- }
- - (YYTextLayout *)retweetCountTextLayoutForTweet:(T1Tweet *)tweet {
- if (tweet.retweetCount > 0) {
- NSMutableAttributedString *retweet = [[NSMutableAttributedString alloc] initWithString:[T1Helper shortedNumberDesc:tweet.retweetCount]];
- retweet.font = [UIFont systemFontOfSize:kT1ActionFontSize];
- retweet.color = tweet.retweeted ? kT1TextActionRetweetColor : kT1TextActionsColor;
- return [YYTextLayout layoutWithContainerSize:CGSizeMake(100, kT1ActionFontSize * 2) text:retweet];
- }
- return nil;
- }
- - (YYTextLayout *)favoriteCountTextLayoutForTweet:(T1Tweet *)tweet {
- if (tweet.favoriteCount > 0) {
- NSMutableAttributedString *favourite = [[NSMutableAttributedString alloc] initWithString:[T1Helper shortedNumberDesc:tweet.favoriteCount]];
- favourite.font = [UIFont systemFontOfSize:kT1ActionFontSize];
- favourite.color = tweet.favorited ? kT1TextActionFavoriteColor : kT1TextActionsColor;
- return [YYTextLayout layoutWithContainerSize:CGSizeMake(100, kT1ActionFontSize * 2) text:favourite];
- }
- return nil;
- }
- @end
|