T1StatusCell.m 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. //
  2. // T1StatusCell.m
  3. // YYKitExample
  4. //
  5. // Created by ibireme on 15/10/9.
  6. // Copyright (C) 2015 ibireme. All rights reserved.
  7. //
  8. #import "T1StatusCell.h"
  9. #import "T1Helper.h"
  10. #define kCornerRaadius 4
  11. @implementation T1StatusMediaView
  12. - (instancetype)init {
  13. self = [super init];
  14. self.width = kT1ContentWidth;
  15. self.clipsToBounds = YES;
  16. self.layer.cornerRadius = kCornerRaadius;
  17. self.layer.borderColor = [UIColor colorWithWhite:0.865 alpha:1.000].CGColor;
  18. self.layer.borderWidth = CGFloatFromPixel(1);
  19. NSMutableArray *imageViews = [NSMutableArray new];
  20. for (int i = 0; i < 4; i++) {
  21. UIImageView *imageView = [UIImageView new];
  22. imageView.backgroundColor = [UIColor colorWithWhite:0.958 alpha:1.000];
  23. imageView.clipsToBounds = YES;
  24. imageView.contentMode = UIViewContentModeScaleAspectFill;
  25. imageView.layer.borderColor = self.layer.borderColor;
  26. imageView.layer.borderWidth = self.layer.borderWidth;
  27. [self addSubview:imageView];
  28. [imageViews addObject:imageView];
  29. }
  30. _imageViews = imageViews;
  31. @weakify(self);
  32. self.touchBlock = ^(YYControl *view, YYGestureRecognizerState state, NSSet *touches, UIEvent *event) {
  33. @strongify(self);
  34. if (!self) return;
  35. if (state != YYGestureRecognizerStateEnded) return;
  36. UITouch *touch = touches.anyObject;
  37. CGPoint point = [touch locationInView:self];
  38. NSUInteger index = [self imageIndexForPoint:point];
  39. if (index != NSNotFound) {
  40. if ([self.cell.delegate respondsToSelector:@selector(cell:didClickImageAtIndex:withLongPress:)]) {
  41. [self.cell.delegate cell:self.cell didClickImageAtIndex:index withLongPress:NO];
  42. }
  43. }
  44. };
  45. self.longPressBlock = ^(YYControl *view, CGPoint point) {
  46. @strongify(self);
  47. if (!self) return;
  48. NSUInteger index = [self imageIndexForPoint:point];
  49. if (index != NSNotFound) {
  50. if ([self.cell.delegate respondsToSelector:@selector(cell:didClickImageAtIndex:withLongPress:)]) {
  51. [self.cell.delegate cell:self.cell didClickImageAtIndex:index withLongPress:YES];
  52. }
  53. }
  54. };
  55. return self;
  56. }
  57. - (NSUInteger)imageIndexForPoint:(CGPoint)point {
  58. for (int i = 0; i < 4; i++) {
  59. UIImageView *view = self.imageViews[i];
  60. if (!view.hidden && CGRectContainsPoint(view.frame, point)) {
  61. return i;
  62. }
  63. }
  64. return NSNotFound;
  65. }
  66. - (void)setWithMedias:(NSArray<T1Media *> *)medias {
  67. for (int i = 0; i < 4; i++) {
  68. UIImageView *view = _imageViews[i];
  69. if (i >= medias.count) {
  70. view.hidden = YES;
  71. [view cancelCurrentImageRequest];
  72. } else {
  73. view.hidden = NO;
  74. T1Media *media = medias[i];
  75. [view setImageWithURL:media.mediaSmall.url
  76. placeholder:nil
  77. options:YYWebImageOptionSetImageWithFadeAnimation
  78. completion:nil];
  79. }
  80. }
  81. switch (medias.count) {
  82. case 1: {
  83. UIImageView *view = _imageViews.firstObject;
  84. view.frame = self.bounds;
  85. } break;
  86. case 2: {
  87. UIImageView *view0 = _imageViews[0];
  88. view0.origin = CGPointZero;
  89. view0.height = self.height;
  90. view0.width = (self.width - kT1ImagePadding) / 2;
  91. UIImageView *view1 = _imageViews[1];
  92. view1.top = 0;
  93. view1.size = view0.size;
  94. view1.right = self.width;
  95. } break;
  96. case 3: {
  97. UIImageView *view0 = _imageViews[0];
  98. view0.origin = CGPointZero;
  99. view0.height = self.height;
  100. view0.width = (self.width - kT1ImagePadding) / 2;
  101. UIImageView *view1 = _imageViews[1];
  102. view1.top = 0;
  103. view1.width = view0.width;
  104. view1.right = self.width;
  105. view1.height = (self.height - kT1ImagePadding) / 2;
  106. UIImageView *view2 = _imageViews[2];
  107. view2.size = view1.size;
  108. view2.right = self.width;
  109. view2.bottom = self.height;
  110. } break;
  111. case 4: {
  112. UIImageView *view0 = _imageViews[0];
  113. view0.origin = CGPointZero;
  114. view0.width = (self.width - kT1ImagePadding) / 2;
  115. view0.height = (self.height - kT1ImagePadding) / 2;
  116. UIImageView *view1 = _imageViews[1];
  117. view1.size = view0.size;
  118. view1.top = 0;
  119. view1.right = self.width;
  120. UIImageView *view2 = _imageViews[2];
  121. view2.size = view0.size;
  122. view2.left = 0;
  123. view2.bottom = self.height;
  124. UIImageView *view3 = _imageViews[3];
  125. view3.size = view0.size;
  126. view3.right = self.width;
  127. view3.bottom = self.height;
  128. } break;
  129. default: break;
  130. }
  131. }
  132. @end
  133. @implementation T1StatusQuoteView
  134. - (instancetype)init {
  135. self = [super init];
  136. self.width = kT1ContentWidth;
  137. self.clipsToBounds = YES;
  138. self.layer.cornerRadius = kCornerRaadius;
  139. self.layer.borderWidth = CGFloatFromPixel(1);
  140. self.layer.borderColor = [UIColor colorWithWhite:0.000 alpha:0.108].CGColor;
  141. self.exclusiveTouch = YES;
  142. _nameLabel = [YYLabel new];
  143. _nameLabel.textVerticalAlignment = YYTextVerticalAlignmentCenter;
  144. _nameLabel.displaysAsynchronously = YES;
  145. _nameLabel.ignoreCommonProperties = YES;
  146. _nameLabel.fadeOnHighlight = NO;
  147. _nameLabel.fadeOnAsynchronouslyDisplay = NO;
  148. _nameLabel.width = kT1QuoteContentWidth;
  149. _nameLabel.left = kT1CellPadding;
  150. [self addSubview:_nameLabel];
  151. _textLabel = [YYLabel new];
  152. _textLabel.textVerticalAlignment = YYTextVerticalAlignmentCenter;
  153. _textLabel.displaysAsynchronously = YES;
  154. _textLabel.ignoreCommonProperties = YES;
  155. _textLabel.fadeOnHighlight = NO;
  156. _textLabel.fadeOnAsynchronouslyDisplay = NO;
  157. _textLabel.width = kT1QuoteContentWidth;
  158. _textLabel.left = kT1CellPadding;
  159. [self addSubview:_textLabel];
  160. @weakify(self);
  161. self.touchBlock = ^(YYControl *view, YYGestureRecognizerState state, NSSet *touches, UIEvent *event) {
  162. @strongify(self);
  163. if (!self) return;
  164. if (state == YYGestureRecognizerStateBegan) {
  165. self.backgroundColor = kT1CellBGHighlightColor;
  166. } else if (state != YYGestureRecognizerStateMoved) {
  167. self.backgroundColor = [UIColor clearColor];
  168. }
  169. if (state == YYGestureRecognizerStateEnded) {
  170. UITouch *t = touches.anyObject;
  171. CGPoint p = [t locationInView:self];
  172. if (CGRectContainsPoint(self.bounds, p)) {
  173. if ([self.cell.delegate respondsToSelector:@selector(cell:didClickQuoteWithLongPress:)]) {
  174. [self.cell.delegate cell:self.cell didClickQuoteWithLongPress:NO];
  175. }
  176. }
  177. }
  178. };
  179. return self;
  180. }
  181. - (void)setWithLayout:(T1StatusLayout *)layout {
  182. _nameLabel.height = kT1UserNameFontSize * 2;
  183. _nameLabel.centerY = kT1CellPadding + kT1UserNameFontSize / 2;
  184. _nameLabel.textLayout = layout.quotedNameTextLayout;
  185. _textLabel.height = CGRectGetMaxY(layout.quotedTextLayout.textBoundingRect);
  186. _textLabel.top = kT1CellPadding + kT1UserNameFontSize + kT1CellInnerPadding;
  187. _textLabel.textLayout = layout.quotedTextLayout;
  188. }
  189. @end
  190. @implementation T1StatusInlineActionsView
  191. - (instancetype)init {
  192. self = [super init];
  193. self.width = kT1ContentWidth;
  194. self.height = 32;
  195. __weak typeof(self) _self = self;
  196. _replyButton = [UIButton buttonWithType:UIButtonTypeCustom];
  197. _replyButton.size = CGSizeMake(32, 32);
  198. _replyButton.centerY = self.height / 2;
  199. _replyButton.centerX = 6;
  200. _replyButton.adjustsImageWhenHighlighted = NO;
  201. _replyButton.exclusiveTouch = YES;
  202. [_replyButton setImage:[T1Helper imageNamed:@"icn_tweet_action_inline_reply_off"] forState:UIControlStateNormal];
  203. [_replyButton addBlockForControlEvents:UIControlEventTouchDown | UIControlEventTouchDragEnter
  204. block:^(UIButton *sender) {
  205. sender.alpha = 0.6;
  206. }];
  207. [_replyButton addBlockForControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside |
  208. UIControlEventTouchCancel | UIControlEventTouchDragExit
  209. block:^(UIButton *sender) {
  210. sender.alpha = 1;
  211. }];
  212. [_replyButton addBlockForControlEvents:UIControlEventTouchUpInside block:^(id sender) {
  213. if ([_self.cell.delegate respondsToSelector:@selector(cellDidClickReply:)]) {
  214. [_self.cell.delegate cellDidClickReply:_self.cell];
  215. }
  216. }];
  217. [self addSubview:_replyButton];
  218. _retweetButton = [UIButton buttonWithType:UIButtonTypeCustom];
  219. [self addSubview:_retweetButton];
  220. _retweetImageView = [UIImageView new];
  221. [self addSubview:_retweetImageView];
  222. _retweetLabel = [YYLabel new];
  223. [self addSubview:_retweetLabel];
  224. _retweetButton.size = CGSizeMake(32, 32);
  225. _retweetButton.centerY = self.height / 2;
  226. _retweetButton.left = kT1ContentWidth * 0.28 + _replyButton.left;
  227. _retweetImageView.size = CGSizeMake(32, 32);
  228. _retweetImageView.contentMode = UIViewContentModeCenter;
  229. _retweetImageView.center = _retweetButton.center;
  230. _retweetImageView.image = [T1Helper imageNamed:@"icn_tweet_action_inline_retweet_off"];
  231. _retweetLabel.height = _retweetButton.height;
  232. _retweetLabel.left = _retweetImageView.right - 3;
  233. _retweetLabel.userInteractionEnabled = NO;
  234. _replyButton.exclusiveTouch = YES;
  235. [_retweetButton addBlockForControlEvents:UIControlEventTouchDown | UIControlEventTouchDragEnter
  236. block:^(UIButton *sender) {
  237. _self.retweetImageView.alpha = 0.6;
  238. _self.retweetLabel.alpha = 0.6;
  239. }];
  240. [_retweetButton addBlockForControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside |
  241. UIControlEventTouchCancel | UIControlEventTouchDragExit
  242. block:^(UIButton *sender) {
  243. _self.retweetImageView.alpha = 1;
  244. _self.retweetLabel.alpha = 1;
  245. }];
  246. [_retweetButton addBlockForControlEvents:UIControlEventTouchUpInside block:^(id sender) {
  247. if ([_self.cell.delegate respondsToSelector:@selector(cellDidClickRetweet:)]) {
  248. [_self.cell.delegate cellDidClickRetweet:_self.cell];
  249. }
  250. }];
  251. _favoriteButton = [UIButton buttonWithType:UIButtonTypeCustom];
  252. [self addSubview:_favoriteButton];
  253. _favoriteImageView = [YYAnimatedImageView new];
  254. [self addSubview:_favoriteImageView];
  255. _favoriteLabel = [YYLabel new];
  256. [self addSubview:_favoriteLabel];
  257. _favoriteButton.size = CGSizeMake(32, 32);
  258. _favoriteButton.centerY = self.height / 2;
  259. _favoriteButton.left = kT1ContentWidth * 0.28 + _retweetButton.left;
  260. _favoriteImageView.size = CGSizeMake(32, 32);
  261. _favoriteImageView.contentMode = UIViewContentModeCenter;
  262. _favoriteImageView.center = _favoriteButton.center;
  263. _favoriteImageView.image = [T1Helper imageNamed:@"icn_tweet_action_inline_favorite_off"];
  264. _favoriteLabel.height = _favoriteButton.height;
  265. _favoriteLabel.left = _favoriteImageView.right - 4;
  266. _favoriteLabel.userInteractionEnabled = NO;
  267. _favoriteLabel.exclusiveTouch = YES;
  268. [_favoriteButton addBlockForControlEvents:UIControlEventTouchDown | UIControlEventTouchDragEnter
  269. block:^(UIButton *sender) {
  270. _self.favoriteImageView.alpha = 0.6;
  271. _self.favoriteLabel.alpha = 0.6;
  272. }];
  273. [_favoriteButton addBlockForControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside |
  274. UIControlEventTouchCancel | UIControlEventTouchDragExit
  275. block:^(UIButton *sender) {
  276. _self.favoriteImageView.alpha = 1;
  277. _self.favoriteLabel.alpha = 1;
  278. }];
  279. [_favoriteButton addBlockForControlEvents:UIControlEventTouchUpInside block:^(id sender) {
  280. if ([_self.cell.delegate respondsToSelector:@selector(cellDidClickFavorite:)]) {
  281. [_self.cell.delegate cellDidClickFavorite:_self.cell];
  282. }
  283. }];
  284. _followButton = [UIButton buttonWithType:UIButtonTypeCustom];
  285. _followButton.size = CGSizeMake(32, 32);
  286. _followButton.centerY = self.height / 2;
  287. _followButton.right = self.width - 3;
  288. _followButton.adjustsImageWhenHighlighted = NO;
  289. _followButton.exclusiveTouch = YES;
  290. [_followButton setImage:[T1Helper imageNamed:@"icn_tweet_action_inline_follow_off_ipad_experiment"] forState:UIControlStateNormal];
  291. [_followButton addBlockForControlEvents:UIControlEventTouchDown | UIControlEventTouchDragEnter
  292. block:^(UIButton *sender) {
  293. sender.alpha = 0.6;
  294. }];
  295. [_followButton addBlockForControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside |
  296. UIControlEventTouchCancel | UIControlEventTouchDragExit
  297. block:^(UIButton *sender) {
  298. sender.alpha = 1;
  299. }];
  300. [_followButton addBlockForControlEvents:UIControlEventTouchUpInside block:^(id sender) {
  301. if ([_self.cell.delegate respondsToSelector:@selector(cellDidClickFollow:)]) {
  302. [_self.cell.delegate cellDidClickFollow:_self.cell];
  303. }
  304. }];
  305. [self addSubview:_followButton];
  306. return self;
  307. }
  308. - (void)setWithLayout:(T1StatusLayout *)layout {
  309. T1Tweet *tweet = layout.displayedTweet;
  310. if (tweet.retweeted) {
  311. _retweetImageView.image = [T1Helper imageNamed:@"icn_tweet_action_inline_retweet_on_white"];
  312. } else {
  313. _retweetImageView.image = [T1Helper imageNamed:@"icn_tweet_action_inline_retweet_off"];
  314. }
  315. if (tweet.favorited) {
  316. _favoriteImageView.image = [T1Helper imageNamed:@"icn_tweet_action_inline_favorite_on_white"];
  317. } else {
  318. _favoriteImageView.image = [T1Helper imageNamed:@"icn_tweet_action_inline_favorite_off"];
  319. }
  320. if (layout.retweetCountTextLayout) {
  321. _retweetLabel.hidden = NO;
  322. _retweetLabel.width = layout.retweetCountTextLayout.textBoundingSize.width + 5;
  323. _retweetLabel.textLayout = layout.retweetCountTextLayout;
  324. _retweetButton.width = _retweetLabel.right - _retweetButton.left;
  325. } else {
  326. _retweetLabel.hidden = YES;
  327. _retweetButton.width = _retweetButton.height;
  328. }
  329. if (layout.favoriteCountTextLayout) {
  330. _favoriteLabel.hidden = NO;
  331. _favoriteLabel.width = layout.favoriteCountTextLayout.textBoundingSize.width + 5;
  332. _favoriteLabel.textLayout = layout.favoriteCountTextLayout;
  333. _favoriteButton.width = _favoriteLabel.right - _favoriteButton.left;
  334. } else {
  335. _favoriteLabel.hidden = YES;
  336. _favoriteButton.width = _favoriteButton.height;
  337. }
  338. if (tweet.user.following) {
  339. _followButton.hidden = YES;
  340. } else {
  341. _followButton.hidden = NO;
  342. [_followButton setImage:[T1Helper imageNamed:@"icn_tweet_action_inline_follow_off_ipad_experiment"] forState:UIControlStateNormal];
  343. }
  344. }
  345. - (void)updateRetweetWithAnimation {
  346. T1StatusLayout *layout = self.cell.layout;
  347. T1Tweet *tweet = layout.displayedTweet;
  348. if (tweet.retweeted) {
  349. _retweetImageView.image = [T1Helper imageNamed:@"icn_tweet_action_inline_retweet_on_white"];
  350. } else {
  351. _retweetImageView.image = [T1Helper imageNamed:@"icn_tweet_action_inline_retweet_off"];
  352. }
  353. [UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
  354. _retweetImageView.layer.transformScale = 1.5;
  355. } completion:^(BOOL finished) {
  356. [UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
  357. _retweetImageView.layer.transformScale = 1;
  358. } completion:^(BOOL finished) {
  359. }];
  360. }];
  361. if (layout.retweetCountTextLayout) {
  362. _retweetLabel.hidden = NO;
  363. _retweetLabel.width = layout.retweetCountTextLayout.textBoundingSize.width + 5;
  364. _retweetLabel.textLayout = layout.retweetCountTextLayout;
  365. _retweetButton.width = _retweetLabel.right - _retweetButton.left;
  366. } else {
  367. _retweetLabel.hidden = YES;
  368. _retweetButton.width = _retweetButton.height;
  369. }
  370. }
  371. - (void)updateFavouriteWithAnimation {
  372. T1StatusLayout *layout = self.cell.layout;
  373. T1Tweet *tweet = layout.displayedTweet;
  374. if (tweet.favorited) {
  375. UIImage *img = [T1Helper imageNamed:@"fav02c-sheet"];
  376. NSMutableArray *contentRects = [NSMutableArray new];
  377. NSMutableArray *durations = [NSMutableArray new];
  378. for (int j = 0; j < 12; j++) {
  379. for (int i = 0; i < 8; i++) {
  380. CGRect rect;
  381. rect.size = CGSizeMake(img.size.width / 8, img.size.height / 12);
  382. rect.origin.x = img.size.width / 8 * i;
  383. rect.origin.y = img.size.height / 12 * j;
  384. [contentRects addObject:[NSValue valueWithCGRect:rect]];
  385. [durations addObject:@(1 / 60.0)];
  386. }
  387. }
  388. YYSpriteSheetImage *sprite = [[YYSpriteSheetImage alloc] initWithSpriteSheetImage:img contentRects:contentRects frameDurations:durations loopCount:1];
  389. _favoriteImageView.image = sprite;
  390. } else {
  391. _favoriteImageView.image = [T1Helper imageNamed:@"icn_tweet_action_inline_favorite_off"];
  392. [UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
  393. _favoriteImageView.layer.transformScale = 1.5;
  394. } completion:^(BOOL finished) {
  395. [UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
  396. _favoriteImageView.layer.transformScale = 1;
  397. } completion:^(BOOL finished) {
  398. }];
  399. }];
  400. }
  401. if (layout.favoriteCountTextLayout) {
  402. _favoriteLabel.hidden = NO;
  403. _favoriteLabel.width = layout.favoriteCountTextLayout.textBoundingSize.width + 5;
  404. _favoriteLabel.textLayout = layout.favoriteCountTextLayout;
  405. _favoriteButton.width = _favoriteLabel.right - _favoriteButton.left;
  406. } else {
  407. _favoriteLabel.hidden = YES;
  408. _favoriteButton.width = _favoriteButton.height;
  409. }
  410. }
  411. - (void)updateFollowWithAnimation {
  412. T1StatusLayout *layout = self.cell.layout;
  413. T1Tweet *tweet = layout.displayedTweet;
  414. if (tweet.user.following) {
  415. [_followButton setImage:[T1Helper imageNamed:@"icn_tweet_action_inline_follow_on_ipad_experiment"] forState:UIControlStateNormal];
  416. } else {
  417. [_followButton setImage:[T1Helper imageNamed:@"icn_tweet_action_inline_follow_off_ipad_experiment"] forState:UIControlStateNormal];
  418. }
  419. }
  420. @end
  421. @implementation T1StatusView
  422. - (instancetype)init {
  423. self = [super init];
  424. self.width = kScreenWidth;
  425. self.backgroundColor = [UIColor whiteColor];
  426. self.exclusiveTouch = YES;
  427. self.clipsToBounds = YES;
  428. _socialLabel = [YYLabel new];
  429. _socialLabel.textVerticalAlignment = YYTextVerticalAlignmentCenter;
  430. _socialLabel.displaysAsynchronously = YES;
  431. _socialLabel.ignoreCommonProperties = YES;
  432. _socialLabel.fadeOnHighlight = NO;
  433. _socialLabel.fadeOnAsynchronouslyDisplay = NO;
  434. _socialLabel.size = CGSizeMake(kT1ContentWidth, kT1UserNameSubFontSize * 2);
  435. _socialLabel.left = kT1ContentLeft;
  436. _socialLabel.centerY = kT1CellPadding + kT1UserNameSubFontSize / 2;
  437. _socialLabel.userInteractionEnabled = NO;
  438. [self addSubview:_socialLabel];
  439. _socialIconView = [UIImageView new];
  440. _socialIconView.size = CGSizeMake(16, 16);
  441. _socialIconView.centerY = _socialLabel.centerY - 1;
  442. _socialIconView.right = kT1CellPadding + kT1AvatarSize;
  443. _socialIconView.contentMode = UIViewContentModeScaleAspectFit;
  444. _socialIconView.userInteractionEnabled = NO;
  445. [self addSubview:_socialIconView];
  446. _avatarView = [YYControl new];
  447. _avatarView.clipsToBounds = YES;
  448. _avatarView.layer.cornerRadius = 4;
  449. _avatarView.layer.borderWidth = CGFloatFromPixel(1);
  450. _avatarView.layer.borderColor = [UIColor colorWithWhite:0.000 alpha:0.118].CGColor;
  451. _avatarView.backgroundColor = [UIColor colorWithWhite:0.908 alpha:1.000];
  452. _avatarView.contentMode = UIViewContentModeScaleAspectFill;
  453. _avatarView.left = kT1CellPadding;
  454. _avatarView.size = CGSizeMake(kT1AvatarSize, kT1AvatarSize);
  455. _avatarView.exclusiveTouch = YES;
  456. [self addSubview:_avatarView];
  457. _conversationTopJoin = [UIView new];
  458. _conversationTopJoin.userInteractionEnabled = NO;
  459. _conversationTopJoin.hidden = YES;
  460. _conversationTopJoin.width = 3;
  461. _conversationTopJoin.backgroundColor = UIColorHex(e1e8ed);
  462. _conversationTopJoin.clipsToBounds = YES;
  463. _conversationTopJoin.layer.cornerRadius = _conversationTopJoin.width / 2;
  464. _conversationTopJoin.centerX = _avatarView.centerX;
  465. [self addSubview:_conversationTopJoin];
  466. _conversationBottomJoin = [UIView new];
  467. _conversationBottomJoin.userInteractionEnabled = NO;
  468. _conversationBottomJoin.hidden = YES;
  469. _conversationBottomJoin.width = 3;
  470. _conversationBottomJoin.backgroundColor = _conversationTopJoin.backgroundColor;
  471. _conversationBottomJoin.clipsToBounds = YES;
  472. _conversationBottomJoin.layer.cornerRadius = _conversationTopJoin.width / 2;
  473. _conversationBottomJoin.centerX = _avatarView.centerX;
  474. [self addSubview:_conversationBottomJoin];
  475. _nameLabel = [YYLabel new];
  476. _nameLabel.textVerticalAlignment = YYTextVerticalAlignmentCenter;
  477. _nameLabel.displaysAsynchronously = YES;
  478. _nameLabel.ignoreCommonProperties = YES;
  479. _nameLabel.fadeOnHighlight = NO;
  480. _nameLabel.fadeOnAsynchronouslyDisplay = NO;
  481. _nameLabel.left = kT1ContentLeft;
  482. _nameLabel.width = kT1ContentWidth;
  483. _nameLabel.height = kT1UserNameFontSize * 2;
  484. _nameLabel.userInteractionEnabled = NO;
  485. _nameLabel.exclusiveTouch = YES;
  486. [self addSubview:_nameLabel];
  487. _dateLabel = [YYLabel new];
  488. _dateLabel.textVerticalAlignment = YYTextVerticalAlignmentCenter;
  489. _dateLabel.displaysAsynchronously = YES;
  490. _dateLabel.ignoreCommonProperties = YES;
  491. _dateLabel.fadeOnHighlight = NO;
  492. _dateLabel.fadeOnAsynchronouslyDisplay = NO;
  493. _dateLabel.frame = _nameLabel.frame;
  494. _dateLabel.userInteractionEnabled = NO;
  495. [self addSubview:_dateLabel];
  496. _textLabel = [YYLabel new];
  497. _textLabel.textVerticalAlignment = YYTextVerticalAlignmentCenter;
  498. _textLabel.displaysAsynchronously = YES;
  499. _textLabel.ignoreCommonProperties = YES;
  500. _textLabel.fadeOnHighlight = NO;
  501. _textLabel.fadeOnAsynchronouslyDisplay = NO;
  502. _textLabel.left = kT1ContentLeft;
  503. _textLabel.width = kT1ContentWidth;
  504. _textLabel.width += kT1TextContainerInset * 2;
  505. _textLabel.left -= kT1TextContainerInset;
  506. __weak typeof(self) _self = self;
  507. _textLabel.highlightTapAction = ^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect) {
  508. if ([_self.cell.delegate respondsToSelector:@selector(cell:didClickInLabel:textRange:)]) {
  509. [_self.cell.delegate cell:_self.cell didClickInLabel:(YYLabel *)containerView textRange:range];
  510. }
  511. };
  512. [self addSubview:_textLabel];
  513. _mediaView = [T1StatusMediaView new];
  514. _mediaView.left = kT1ContentLeft;
  515. [self addSubview:_mediaView];
  516. _quoteView = [T1StatusQuoteView new];
  517. _quoteView.left = kT1ContentLeft;
  518. [self addSubview:_quoteView];
  519. _inlineActionsView = [T1StatusInlineActionsView new];
  520. _inlineActionsView.left = kT1ContentLeft;
  521. [self addSubview:_inlineActionsView];
  522. _topLine = [UIView new];
  523. _topLine.width = kScreenWidth;
  524. _topLine.height = CGFloatFromPixel(1);
  525. _topLine.backgroundColor = [UIColor colorWithWhite:0.823 alpha:1.000];
  526. [self addSubview:_topLine];
  527. @weakify(self);
  528. self.touchBlock = ^(YYControl *view, YYGestureRecognizerState state, NSSet *touches, UIEvent *event) {
  529. @strongify(self);
  530. if (!self) return;
  531. if (state == YYGestureRecognizerStateBegan) {
  532. self.backgroundColor = kT1CellBGHighlightColor;
  533. } else if (state != YYGestureRecognizerStateMoved) {
  534. self.backgroundColor = [UIColor clearColor];
  535. }
  536. if (state == YYGestureRecognizerStateEnded) {
  537. UITouch *t = touches.anyObject;
  538. CGPoint p = [t locationInView:self];
  539. if (CGRectContainsPoint(self.bounds, p)) {
  540. if ([self.cell.delegate respondsToSelector:@selector(cell:didClickContentWithLongPress:)]) {
  541. [self.cell.delegate cell:self.cell didClickContentWithLongPress:NO];
  542. }
  543. }
  544. }
  545. };
  546. _avatarView.touchBlock = ^(YYControl *view, YYGestureRecognizerState state, NSSet *touches, UIEvent *event) {
  547. @strongify(self);
  548. if (!self) return;
  549. if (state == YYGestureRecognizerStateBegan) {
  550. self.avatarView.alpha = 0.7;
  551. } else if (state != YYGestureRecognizerStateMoved) {
  552. self.avatarView.alpha = 1;
  553. }
  554. if (state == YYGestureRecognizerStateEnded) {
  555. UITouch *t = touches.anyObject;
  556. CGPoint p = [t locationInView:self];
  557. if (CGRectContainsPoint(self.bounds, p)) {
  558. if ([self.cell.delegate respondsToSelector:@selector(cell:didClickAvatarWithLongPress:)]) {
  559. [self.cell.delegate cell:self.cell didClickAvatarWithLongPress:NO];
  560. }
  561. }
  562. }
  563. };
  564. return self;
  565. }
  566. - (void)setWithLayout:(T1StatusLayout *)layout {
  567. self.height = layout.height;
  568. self.topLine.hidden = !layout.showTopLine;
  569. if (layout.isConversationSplit) {
  570. _conversationTopJoin.hidden = NO;
  571. _conversationTopJoin.top = 3;
  572. _conversationTopJoin.height = self.height - 6;
  573. _avatarView.hidden = YES;
  574. _nameLabel.hidden = YES;
  575. _dateLabel.hidden = YES;
  576. _socialLabel.hidden = YES;
  577. _socialIconView.hidden = YES;
  578. _inlineActionsView.hidden = YES;
  579. return;
  580. } else {
  581. if (_avatarView.hidden) {
  582. _avatarView.hidden = NO;
  583. _nameLabel.hidden = NO;
  584. _dateLabel.hidden = NO;
  585. _socialLabel.hidden = NO;
  586. _socialIconView.hidden = NO;
  587. _inlineActionsView.hidden = NO;
  588. }
  589. }
  590. T1Tweet *tweet = layout.displayedTweet;
  591. _avatarView.top = layout.paddingTop;
  592. [_avatarView.layer setImageWithURL:tweet.user.profileImageURLReasonablySmall options:YYWebImageOptionSetImageWithFadeAnimation];
  593. if (layout.socialTextLayout) {
  594. _socialLabel.hidden = NO;
  595. _socialIconView.hidden = NO;
  596. _socialLabel.textLayout = layout.socialTextLayout;
  597. if (layout.tweet.retweetedStatus) {
  598. _socialIconView.hidden = NO;
  599. _socialIconView.image = [T1Helper imageNamed:@"icn_social_proof_conversation_default"];
  600. } else if (layout.tweet.inReplyToScreenName) {
  601. _socialIconView.hidden = NO;
  602. _socialIconView.image = [T1Helper imageNamed:@"icn_activity_rt_tweet"];
  603. } else {
  604. _socialIconView.image = nil;
  605. }
  606. } else {
  607. _socialLabel.hidden = YES;
  608. _socialIconView.hidden = YES;
  609. }
  610. _nameLabel.centerY = layout.paddingTop + kT1TextFontSize / 2;
  611. _nameLabel.textLayout = layout.nameTextLayout;
  612. _dateLabel.centerY = _nameLabel.centerY;
  613. _dateLabel.textLayout = layout.dateTextLayout;
  614. if (layout.textLayout) {
  615. _textLabel.hidden = NO;
  616. _textLabel.top = layout.textTop;
  617. _textLabel.height = layout.textHeight;
  618. _textLabel.textLayout = layout.textLayout;
  619. } else {
  620. _textLabel.hidden = YES;
  621. }
  622. if (layout.images) {
  623. _mediaView.hidden = NO;
  624. _mediaView.top = layout.imagesTop;
  625. _mediaView.height = layout.imagesHeight;
  626. [_mediaView setWithMedias:layout.images];
  627. } else {
  628. _mediaView.hidden = YES;
  629. [_mediaView setWithMedias:nil];
  630. }
  631. if (layout.quoteHeight > 0) {
  632. _quoteView.hidden = NO;
  633. _quoteView.top = layout.quoteTop;
  634. _quoteView.height = layout.quoteHeight;
  635. [_quoteView setWithLayout:layout];
  636. } else {
  637. _quoteView.hidden = YES;
  638. }
  639. _inlineActionsView.centerY = self.height - 19;
  640. [_inlineActionsView setWithLayout:layout];
  641. self.conversationTopJoin.hidden = !layout.showConversationTopJoin;
  642. self.conversationBottomJoin.hidden = !layout.showConversationBottomJoin;
  643. if (layout.showConversationTopJoin) {
  644. _conversationTopJoin.top = - 5;
  645. _conversationTopJoin.height = _avatarView.top - _conversationTopJoin.top - 3;
  646. }
  647. if (layout.showConversationBottomJoin) {
  648. _conversationBottomJoin.top = _avatarView.bottom + 3;
  649. _conversationBottomJoin.height = self.height - _conversationBottomJoin.top + 5;
  650. }
  651. }
  652. - (void)setCell:(T1StatusCell *)cell {
  653. _cell = cell;
  654. _mediaView.cell = cell;
  655. _quoteView.cell = cell;
  656. _inlineActionsView.cell = cell;
  657. }
  658. @end
  659. @implementation T1StatusCell
  660. - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
  661. self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
  662. if (!self) return nil;
  663. _statusView = [T1StatusView new];
  664. _statusView.cell = self;
  665. [self.contentView addSubview:_statusView];
  666. self.contentView.backgroundColor = [UIColor clearColor];
  667. self.backgroundView.backgroundColor = [UIColor clearColor];
  668. return self;
  669. }
  670. - (void)setLayout:(T1StatusLayout *)layout {
  671. _layout = layout;
  672. self.contentView.height = layout.height;
  673. _statusView.height = layout.height;
  674. [_statusView setWithLayout:layout];
  675. }
  676. @end