1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
//
// MessageCell.m
// Juick
//
// Created by Vitaly Takmazov on 03/12/2017.
// Copyright © 2017 com.juick. All rights reserved.
//
#import "MessageCell.h"
#import "Entity.h"
#import "NSDate+TimeAgo.h"
@interface MessageCell()
@property(nonatomic, readonly) NSMutableParagraphStyle *quoteStyle;
@property(nonatomic, readonly) UIFont *boldFont;
@property(nonatomic, readonly) UIFont *italicFont;
- (void) updateAvatarWithUrl:(NSString *)avatarUrl;
@end
@implementation MessageCell
const NSString *unreadMarker = @"●";
- (void)awakeFromNib {
[super awakeFromNib];
self.text.dataDetectorTypes = UIDataDetectorTypeAll;
self.text.tintColor = [UIColor colorNamed:@"Title"];
self.title.textColor = [UIColor colorNamed:@"Title"];
self.timestamp.textColor = [UIColor colorNamed:@"Muted"];
self.summary.textColor = [UIColor colorNamed:@"Muted"];
UIGestureRecognizer *avatarTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(avatarClicked:)];
[avatarTapRecognizer setEnabled:YES];
[self.avatar addGestureRecognizer:avatarTapRecognizer];
[self.avatar setUserInteractionEnabled:YES];
_quoteStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
_quoteStyle.firstLineHeadIndent = 12.0f;
_quoteStyle.headIndent = 12.0f;
_quoteStyle.paragraphSpacing = 6.0f;
UIFontDescriptor* fontDescriptor = [UIFontDescriptor
preferredFontDescriptorWithTextStyle:UIFontTextStyleBody];
UIFontDescriptor* boldFontDescriptor = [fontDescriptor
fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold];
_boldFont = [UIFont fontWithDescriptor:boldFontDescriptor size: 0.0];
UIFontDescriptor* italicFontDescriptor = [fontDescriptor
fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitItalic];
_italicFont = [UIFont fontWithDescriptor:italicFontDescriptor size: 0.0];
}
- (void) updateAvatarWithUrl:(NSString *)avatarUrl {
self.avatar.image = nil;
__weak UIImageView *weakAvatar = self.avatar;
[[AppDelegate shared].api fetchImageWithURL:[NSURL URLWithString:avatarUrl] callback:^(NSData *data) {
[UIView transitionWithView:weakAvatar
duration:0.3
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
weakAvatar.image = [UIImage imageWithData:data];
} completion:nil];
}];
}
- (void) configureWithMessage:(Message *)msg selectable:(BOOL)selectable {
self.selectionStyle = UITableViewCellSelectionStyleNone;
[self updateAvatarWithUrl:msg.user.avatar];
if (!msg.user.uid) {
__weak UILabel *title = self.title;
[[AppDelegate shared].api getUserByUri:msg.user.uri callback:^(User *user) {
title.text = user.uname;
NSString *avatarUrl = user.avatar ? user.avatar : [API defaultAvatarUrl];
[self updateAvatarWithUrl:avatarUrl];
}];
}
if ([msg.attach length] > 0) {
CGFloat imageHeight = [msg.attachment.small.height floatValue] / [[UIScreen mainScreen] scale];
CGFloat imageWidth = [msg.attachment.small.width floatValue] / [[UIScreen mainScreen] scale];
self.attach.image = [UIImage placeholderImageWithColor:[UIColor colorNamed:@"Muted"] size:CGSizeMake(imageWidth, imageHeight)];
self.attachmentHeight.constant = imageHeight;
self.attachmentWidth.constant = imageWidth;
__weak UIImageView *weakAttach = self.attach;
[[AppDelegate shared].api fetchImageWithURL:[NSURL URLWithString:msg.attachment.small.url] callback:^(NSData *data) {
[UIView transitionWithView:weakAttach
duration:0.3
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
weakAttach.image = [UIImage imageWithData:data];
}
completion:nil];
}];
} else {
self.attachmentHeight.constant = 0;
self.attach.image = nil;
}
self.title.text = msg.user.uname;
self.timestamp.text = [[[AppDelegate shared].sharedDateFormatter dateFromString:msg.timestamp] timeAgo];
NSUInteger count = [msg.repliesCount unsignedIntegerValue];
if (count > 0) {
if ([msg.repliesBy length] > 0) {
self.summary.text = [NSString stringWithFormat:@"%@ replies by %@", msg.repliesCount, msg.repliesBy];
} else {
self.summary.text = [NSString stringWithFormat:@"%@ replies", msg.repliesCount];
}
} else {
self.summary.text = nil;
}
if (msg.unread) {
self.summary.text = [NSString stringWithFormat:@"%@ %@", unreadMarker, self.summary.text];
self.summary.textColor = [UIColor colorNamed:@"Funny"];
} else {
self.summary.textColor = [UIColor colorNamed:@"Muted"];
}
self.text.attributedText = nil;
if (msg.text) {
[self.text setHidden:NO];
[self.text setSelectable:selectable];
[self.text setUserInteractionEnabled:selectable];
NSMutableAttributedString *txt = [[NSMutableAttributedString alloc]
initWithString:msg.text
attributes:@{NSFontAttributeName:[UIFont preferredFontForTextStyle:UIFontTextStyleBody],
NSForegroundColorAttributeName:[UIColor colorNamed:@"Text"]
}];
[txt beginEditing];
for (Entity *entity in msg.entities) {
NSUInteger start = entity.start ? [entity.start unsignedIntegerValue] : 0;
NSUInteger end = entity.end ? [entity.end unsignedIntegerValue] : 0;
NSString *text = entity.text ? entity.text : @"";
NSRange currentRange = NSMakeRange(start, end - start);
[txt addAttribute:@"displayText" value:text range:currentRange];
if ([entity.type isEqualToString:@"a"]) {
[txt addAttribute:NSLinkAttributeName value:entity.link range:currentRange];
}
if ([entity.type isEqualToString:@"q"]) {
[txt addAttribute:NSForegroundColorAttributeName value:[UIColor colorNamed:@"Muted"] range:currentRange];
[txt addAttribute:NSParagraphStyleAttributeName value:_quoteStyle range:currentRange];
}
if ([entity.type isEqualToString:@"u"]) {
[txt addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:currentRange];
}
if ([entity.type isEqualToString:@"b"]) {
[txt addAttribute:NSFontAttributeName value:_boldFont range:currentRange];
}
if ([entity.type isEqualToString:@"i"]) {
[txt addAttribute:NSFontAttributeName value:_italicFont range:currentRange];
}
}
[txt enumerateAttribute:@"displayText" inRange:NSMakeRange(0, [txt length]) options:0 usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) {
if (value) {
[txt replaceCharactersInRange:range withString:value];
}
}];
if ([msg.tags count] > 0) {
NSString *tagsList = [NSString stringWithFormat:@"%@\n", [msg.tags componentsJoinedByString:@", "]];
[txt insertAttributedString:[[NSAttributedString alloc]
initWithString:tagsList
attributes:@{
NSFontAttributeName:_italicFont,
NSForegroundColorAttributeName:[UIColor colorNamed:@"Muted"]
}] atIndex:0];
}
[txt endEditing];
self.text.attributedText = txt;
} else {
[self.text setHidden:YES];
}
}
-(void) avatarClicked:(UIGestureRecognizer *)gestureRecognizer {
[self.delegate avatarClicked:self.title.text];
}
@end
|