chore: import upstream snapshot with attribution
This commit is contained in:
+14
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// TLExpressionMessageCell.h
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/3/19.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TLMessageBaseCell.h"
|
||||
#import "TLExpressionMessage.h"
|
||||
|
||||
@interface TLExpressionMessageCell : TLMessageBaseCell
|
||||
|
||||
@end
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// TLExpressionMessageCell.m
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/3/19.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TLExpressionMessageCell.h"
|
||||
#import <SDWebImage/UIImage+GIF.h>
|
||||
#import "NSFileManager+TLChat.h"
|
||||
|
||||
@interface TLExpressionMessageCell ()
|
||||
|
||||
@property (nonatomic, strong) UIImageView *msgImageView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TLExpressionMessageCell
|
||||
|
||||
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
|
||||
{
|
||||
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
|
||||
[self.contentView addSubview:self.msgImageView];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setMessage:(TLExpressionMessage *)message
|
||||
{
|
||||
[self.msgImageView setAlpha:1.0]; // 取消长按效果
|
||||
// if (self.message && [self.message.messageID isEqualToString:message.messageID]) {
|
||||
// return;
|
||||
// }
|
||||
TLMessageOwnerType lastOwnType = self.message ? self.message.ownerTyper : -1;
|
||||
[super setMessage:message];
|
||||
|
||||
NSData *data = [NSData dataWithContentsOfFile:message.path];
|
||||
if (data) {
|
||||
[self.msgImageView setImage:[UIImage imageNamed:message.path]];
|
||||
[self.msgImageView setImage:[UIImage sd_animatedGIFWithData:data]];
|
||||
}
|
||||
else { // 表情组被删掉,先从缓存目录中查找,没有的话在下载并存入缓存目录
|
||||
NSString *cachePath = [NSFileManager cacheForFile:[NSString stringWithFormat:@"%@_%@.gif", message.emoji.gid, message.emoji.eId]];
|
||||
NSData *data = [NSData dataWithContentsOfFile:cachePath];
|
||||
if (data) {
|
||||
[self.msgImageView setImage:[UIImage imageNamed:cachePath]];
|
||||
[self.msgImageView setImage:[UIImage sd_animatedGIFWithData:data]];
|
||||
}
|
||||
else {
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[self.msgImageView tt_setImageWithURL:TLURL(message.url) completed:^(UIImage *image, NSError *error, TLImageCacheType cacheType, NSURL *imageURL) {
|
||||
if ([[imageURL description] isEqualToString:[(TLExpressionMessage *)weakSelf.message url]]) {
|
||||
dispatch_async(dispatch_get_global_queue(0, 0), ^{
|
||||
NSData *data = [NSData dataWithContentsOfURL:imageURL];
|
||||
[data writeToFile:cachePath atomically:NO]; // 再写入到缓存中
|
||||
if ([[imageURL description] isEqualToString:[(TLExpressionMessage *)weakSelf.message url]]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[weakSelf.msgImageView setImage:[UIImage sd_animatedGIFWithData:data]];
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
if (lastOwnType != message.ownerTyper) {
|
||||
if (message.ownerTyper == TLMessageOwnerTypeSelf) {
|
||||
[self.msgImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.mas_equalTo(self.usernameLabel.mas_bottom).mas_offset(5);
|
||||
make.right.mas_equalTo(self.messageBackgroundView).mas_offset(-10);
|
||||
}];
|
||||
}
|
||||
else if (message.ownerTyper == TLMessageOwnerTypeFriend){
|
||||
[self.msgImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.mas_equalTo(self.usernameLabel.mas_bottom).mas_offset(5);
|
||||
make.left.mas_equalTo(self.messageBackgroundView).mas_offset(10);
|
||||
}];
|
||||
}
|
||||
}
|
||||
[self.msgImageView mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||
make.size.mas_equalTo(message.messageFrame.contentSize);
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Event Response -
|
||||
- (void)longPressMsgBGView:(UIGestureRecognizer *)gestureRecognizer
|
||||
{
|
||||
if (gestureRecognizer.state != UIGestureRecognizerStateBegan) {
|
||||
return;
|
||||
}
|
||||
[self.msgImageView setAlpha:0.7]; // 比较low的选中效果
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(messageCellLongPress:rect:)]) {
|
||||
CGRect rect = self.msgImageView.frame;
|
||||
[self.delegate messageCellLongPress:self.message rect:rect];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)doubleTabpMsgBGView
|
||||
{
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(messageCellDoubleClick:)]) {
|
||||
[self.delegate messageCellDoubleClick:self.message];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Getter -
|
||||
- (UIImageView *)msgImageView
|
||||
{
|
||||
if (_msgImageView == nil) {
|
||||
_msgImageView = [[UIImageView alloc] init];
|
||||
[_msgImageView setUserInteractionEnabled:YES];
|
||||
|
||||
UILongPressGestureRecognizer *longPressGR = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressMsgBGView:)];
|
||||
[_msgImageView addGestureRecognizer:longPressGR];
|
||||
|
||||
UITapGestureRecognizer *doubleTapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTabpMsgBGView)];
|
||||
[doubleTapGR setNumberOfTapsRequired:2];
|
||||
[_msgImageView addGestureRecognizer:doubleTapGR];
|
||||
}
|
||||
return _msgImageView;
|
||||
}
|
||||
|
||||
@end
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// TLImageMessageCell.h
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/3/14.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TLMessageBaseCell.h"
|
||||
#import "TLImageMessage.h"
|
||||
|
||||
@interface TLImageMessageCell : TLMessageBaseCell
|
||||
|
||||
@end
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// TLImageMessageCell.m
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/3/14.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TLImageMessageCell.h"
|
||||
#import "TLMessageImageView.h"
|
||||
#import "NSFileManager+TLChat.h"
|
||||
|
||||
#define MSG_SPACE_TOP 2
|
||||
|
||||
@interface TLImageMessageCell ()
|
||||
|
||||
@property (nonatomic, strong) TLMessageImageView *msgImageView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TLImageMessageCell
|
||||
|
||||
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
|
||||
{
|
||||
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
|
||||
[self.contentView addSubview:self.msgImageView];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setMessage:(TLImageMessage *)message
|
||||
{
|
||||
[self.msgImageView setAlpha:1.0]; // 取消长按效果
|
||||
if (self.message && [self.message.messageID isEqualToString:message.messageID]) {
|
||||
return;
|
||||
}
|
||||
TLMessageOwnerType lastOwnType = self.message ? self.message.ownerTyper : -1;
|
||||
[super setMessage:message];
|
||||
|
||||
if ([message imagePath]) {
|
||||
NSString *imagePath = [NSFileManager pathUserChatImage:[message imagePath]];
|
||||
[self.msgImageView setThumbnailPath:imagePath highDefinitionImageURL:[message imagePath]];
|
||||
}
|
||||
else {
|
||||
[self.msgImageView setThumbnailPath:nil highDefinitionImageURL:[message imagePath]];
|
||||
[self.msgImageView tt_setImageWithURL:[NSURL URLWithString:[message imageURL]]];
|
||||
}
|
||||
|
||||
if (lastOwnType != message.ownerTyper) {
|
||||
if (message.ownerTyper == TLMessageOwnerTypeSelf) {
|
||||
[self.msgImageView setBackgroundImage:[UIImage imageNamed:@"message_sender_bg"]];
|
||||
[self.msgImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.mas_equalTo(self.messageBackgroundView);
|
||||
make.right.mas_equalTo(self.messageBackgroundView);
|
||||
}];
|
||||
}
|
||||
else if (message.ownerTyper == TLMessageOwnerTypeFriend){
|
||||
[self.msgImageView setBackgroundImage:[UIImage imageNamed:@"message_receiver_bg"]];
|
||||
[self.msgImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.mas_equalTo(self.messageBackgroundView);
|
||||
make.left.mas_equalTo(self.messageBackgroundView);
|
||||
}];
|
||||
}
|
||||
}
|
||||
[self.msgImageView mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||
make.size.mas_equalTo(message.messageFrame.contentSize);
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Event Response -
|
||||
- (void)tapMessageView
|
||||
{
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(messageCellTap:)]) {
|
||||
[self.delegate messageCellTap:self.message];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)longPressMsgBGView:(UIGestureRecognizer *)gestureRecognizer
|
||||
{
|
||||
if (gestureRecognizer.state != UIGestureRecognizerStateBegan) {
|
||||
return;
|
||||
}
|
||||
[self.msgImageView setAlpha:0.7]; // 比较low的选中效果
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(messageCellLongPress:rect:)]) {
|
||||
CGRect rect = self.msgImageView.frame;
|
||||
rect.size.height -= 10; // 北京图片底部空白区域
|
||||
[self.delegate messageCellLongPress:self.message rect:rect];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)doubleTabpMsgBGView
|
||||
{
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(messageCellDoubleClick:)]) {
|
||||
[self.delegate messageCellDoubleClick:self.message];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Getter -
|
||||
- (TLMessageImageView *)msgImageView
|
||||
{
|
||||
if (_msgImageView == nil) {
|
||||
_msgImageView = [[TLMessageImageView alloc] init];
|
||||
[_msgImageView setUserInteractionEnabled:YES];
|
||||
|
||||
UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapMessageView)];
|
||||
[_msgImageView addGestureRecognizer:tapGR];
|
||||
|
||||
UILongPressGestureRecognizer *longPressGR = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressMsgBGView:)];
|
||||
[_msgImageView addGestureRecognizer:longPressGR];
|
||||
|
||||
UITapGestureRecognizer *doubleTapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTabpMsgBGView)];
|
||||
[doubleTapGR setNumberOfTapsRequired:2];
|
||||
[_msgImageView addGestureRecognizer:doubleTapGR];
|
||||
}
|
||||
return _msgImageView;
|
||||
}
|
||||
|
||||
@end
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// TLMessageBaseCell.h
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/3/1.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "TLMessageCellDelegate.h"
|
||||
#import "TLMessage.h"
|
||||
|
||||
@interface TLMessageBaseCell : UITableViewCell
|
||||
|
||||
@property (nonatomic, assign) id<TLMessageCellDelegate>delegate;
|
||||
|
||||
@property (nonatomic, strong) UILabel *timeLabel;
|
||||
|
||||
@property (nonatomic, strong) UIButton *avatarButton;
|
||||
|
||||
@property (nonatomic, strong) UILabel *usernameLabel;
|
||||
|
||||
@property (nonatomic, strong) UIImageView *messageBackgroundView;
|
||||
|
||||
@property (nonatomic, strong) TLMessage *message;
|
||||
|
||||
/**
|
||||
* 更新消息,如果子类不重写,默认调用setMessage方法
|
||||
*/
|
||||
- (void)updateMessage:(TLMessage *)message;
|
||||
|
||||
@end
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
//
|
||||
// TLMessageBaseCell.m
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/3/1.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TLMessageBaseCell.h"
|
||||
#import "NSDate+TLChat.h"
|
||||
#import "NSFileManager+TLChat.h"
|
||||
|
||||
#define TIMELABEL_HEIGHT 20.0f
|
||||
#define TIMELABEL_SPACE_Y 10.0f
|
||||
|
||||
#define NAMELABEL_HEIGHT 14.0f
|
||||
#define NAMELABEL_SPACE_X 12.0f
|
||||
#define NAMELABEL_SPACE_Y 1.0f
|
||||
|
||||
#define AVATAR_WIDTH 40.0f
|
||||
#define AVATAR_SPACE_X 8.0f
|
||||
#define AVATAR_SPACE_Y 12.0f
|
||||
|
||||
#define MSGBG_SPACE_X 5.0f
|
||||
#define MSGBG_SPACE_Y 1.0f
|
||||
|
||||
@interface TLMessageBaseCell ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation TLMessageBaseCell
|
||||
|
||||
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
|
||||
{
|
||||
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
|
||||
[self setBackgroundColor:[UIColor clearColor]];
|
||||
[self setSelectionStyle:UITableViewCellSelectionStyleNone];
|
||||
[self.contentView addSubview:self.timeLabel];
|
||||
[self.contentView addSubview:self.avatarButton];
|
||||
[self.contentView addSubview:self.usernameLabel];
|
||||
[self.contentView addSubview:self.messageBackgroundView];
|
||||
[self p_addMasonry];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setMessage:(TLMessage *)message
|
||||
{
|
||||
if (_message && [_message.messageID isEqualToString:message.messageID]) {
|
||||
return;
|
||||
}
|
||||
[self.timeLabel setText:[NSString stringWithFormat:@" %@ ", message.date.chatTimeInfo]];
|
||||
[self.usernameLabel setText:[message.fromUser chat_username]];
|
||||
if ([message.fromUser chat_avatarPath].length > 0) {
|
||||
NSString *path = [NSFileManager pathUserAvatar:[message.fromUser chat_avatarPath]];
|
||||
[self.avatarButton setImage:[UIImage imageNamed:path] forState:UIControlStateNormal];
|
||||
}
|
||||
else {
|
||||
[self.avatarButton tt_setImageWithURL:TLURL([message.fromUser chat_avatarURL]) forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
// 时间
|
||||
if (!_message || _message.showTime != message.showTime) {
|
||||
[self.timeLabel mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||
make.height.mas_equalTo(message.showTime ? TIMELABEL_HEIGHT : 0);
|
||||
make.top.mas_equalTo(self.contentView).mas_offset(message.showTime ? TIMELABEL_SPACE_Y : 0);
|
||||
}];
|
||||
}
|
||||
|
||||
if (!message || _message.ownerTyper != message.ownerTyper) {
|
||||
// 头像
|
||||
[self.avatarButton mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.width.and.height.mas_equalTo(AVATAR_WIDTH);
|
||||
make.top.mas_equalTo(self.timeLabel.mas_bottom).mas_offset(AVATAR_SPACE_Y);
|
||||
if(message.ownerTyper == TLMessageOwnerTypeSelf) {
|
||||
make.right.mas_equalTo(self.contentView).mas_offset(-AVATAR_SPACE_X);
|
||||
}
|
||||
else {
|
||||
make.left.mas_equalTo(self.contentView).mas_offset(AVATAR_SPACE_X);
|
||||
}
|
||||
}];
|
||||
|
||||
// 用户名
|
||||
[self.usernameLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.mas_equalTo(self.avatarButton).mas_equalTo(-NAMELABEL_SPACE_Y);
|
||||
if (message.ownerTyper == TLMessageOwnerTypeSelf) {
|
||||
make.right.mas_equalTo(self.avatarButton.mas_left).mas_offset(- NAMELABEL_SPACE_X);
|
||||
}
|
||||
else {
|
||||
make.left.mas_equalTo(self.avatarButton.mas_right).mas_equalTo(NAMELABEL_SPACE_X);
|
||||
}
|
||||
}];
|
||||
|
||||
// 背景
|
||||
[self.messageBackgroundView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
message.ownerTyper == TLMessageOwnerTypeSelf ? make.right.mas_equalTo(self.avatarButton.mas_left).mas_offset(-MSGBG_SPACE_X) : make.left.mas_equalTo(self.avatarButton.mas_right).mas_offset(MSGBG_SPACE_X);
|
||||
make.top.mas_equalTo(self.usernameLabel.mas_bottom).mas_offset(message.showName ? 0 : -MSGBG_SPACE_Y);
|
||||
}];
|
||||
}
|
||||
|
||||
[self.usernameLabel setHidden:!message.showName];
|
||||
[self.usernameLabel mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||
make.height.mas_equalTo(message.showName ? NAMELABEL_HEIGHT : 0);
|
||||
}];
|
||||
|
||||
_message = message;
|
||||
}
|
||||
|
||||
- (void)updateMessage:(TLMessage *)message
|
||||
{
|
||||
[self setMessage:message];
|
||||
}
|
||||
|
||||
#pragma mark - Private Methods -
|
||||
- (void)p_addMasonry
|
||||
{
|
||||
[self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.mas_equalTo(self.contentView).mas_offset(TIMELABEL_SPACE_Y);
|
||||
make.centerX.mas_equalTo(self.contentView);
|
||||
}];
|
||||
|
||||
[self.usernameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.mas_equalTo(self.avatarButton).mas_equalTo(-NAMELABEL_SPACE_Y);
|
||||
make.right.mas_equalTo(self.avatarButton.mas_left).mas_offset(- NAMELABEL_SPACE_X);
|
||||
}];
|
||||
|
||||
// Default - self
|
||||
[self.avatarButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.right.mas_equalTo(self.contentView).mas_offset(-AVATAR_SPACE_X);
|
||||
make.width.and.height.mas_equalTo(AVATAR_WIDTH);
|
||||
make.top.mas_equalTo(self.timeLabel.mas_bottom).mas_offset(AVATAR_SPACE_Y);
|
||||
}];
|
||||
|
||||
[self.messageBackgroundView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.right.mas_equalTo(self.avatarButton.mas_left).mas_offset(-MSGBG_SPACE_X);
|
||||
make.top.mas_equalTo(self.usernameLabel.mas_bottom).mas_offset(-MSGBG_SPACE_Y);
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Event Response -
|
||||
- (void)avatarButtonDown:(UIButton *)sender
|
||||
{
|
||||
if (_delegate && [_delegate respondsToSelector:@selector(messageCellDidClickAvatarForUser:)]) {
|
||||
[_delegate messageCellDidClickAvatarForUser:self.message.fromUser];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)longPressMsgBGView:(UIGestureRecognizer *)gestureRecognizer
|
||||
{
|
||||
if (gestureRecognizer.state != UIGestureRecognizerStateBegan) {
|
||||
return;
|
||||
}
|
||||
[self.messageBackgroundView setHighlighted:YES];
|
||||
if (_delegate && [_delegate respondsToSelector:@selector(messageCellLongPress:rect:)]) {
|
||||
CGRect rect = self.messageBackgroundView.frame;
|
||||
rect.size.height -= 10; // 北京图片底部空白区域
|
||||
[_delegate messageCellLongPress:self.message rect:rect];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)doubleTabpMsgBGView
|
||||
{
|
||||
if (_delegate && [_delegate respondsToSelector:@selector(messageCellDoubleClick:)]) {
|
||||
[_delegate messageCellDoubleClick:self.message];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Getter -
|
||||
- (UILabel *)timeLabel
|
||||
{
|
||||
if (_timeLabel == nil) {
|
||||
_timeLabel = [[UILabel alloc] init];
|
||||
[_timeLabel setFont:[UIFont systemFontOfSize:12.0f]];
|
||||
[_timeLabel setTextColor:[UIColor whiteColor]];
|
||||
[_timeLabel setBackgroundColor:[UIColor grayColor]];
|
||||
[_timeLabel setAlpha:0.7f];
|
||||
[_timeLabel.layer setMasksToBounds:YES];
|
||||
[_timeLabel.layer setCornerRadius:5.0f];
|
||||
}
|
||||
return _timeLabel;
|
||||
}
|
||||
|
||||
- (UIButton *)avatarButton
|
||||
{
|
||||
if (_avatarButton == nil) {
|
||||
_avatarButton = [[UIButton alloc] init];
|
||||
[_avatarButton.layer setMasksToBounds:YES];
|
||||
[_avatarButton.layer setBorderWidth:BORDER_WIDTH_1PX];
|
||||
[_avatarButton.layer setBorderColor:[UIColor colorWithWhite:0.7 alpha:1.0].CGColor];
|
||||
[_avatarButton addTarget:self action:@selector(avatarButtonDown:) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return _avatarButton;
|
||||
}
|
||||
|
||||
- (UILabel *)usernameLabel
|
||||
{
|
||||
if (_usernameLabel == nil) {
|
||||
_usernameLabel = [[UILabel alloc] init];
|
||||
[_usernameLabel setTextColor:[UIColor grayColor]];
|
||||
[_usernameLabel setFont:[UIFont systemFontOfSize:12.0f]];
|
||||
}
|
||||
return _usernameLabel;
|
||||
}
|
||||
|
||||
- (UIImageView *)messageBackgroundView
|
||||
{
|
||||
if (_messageBackgroundView == nil) {
|
||||
_messageBackgroundView = [[UIImageView alloc] init];
|
||||
[_messageBackgroundView setUserInteractionEnabled:YES];
|
||||
|
||||
UILongPressGestureRecognizer *longPressGR = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressMsgBGView:)];
|
||||
[_messageBackgroundView addGestureRecognizer:longPressGR];
|
||||
|
||||
UITapGestureRecognizer *doubleTapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTabpMsgBGView)];
|
||||
[doubleTapGR setNumberOfTapsRequired:2];
|
||||
[_messageBackgroundView addGestureRecognizer:doubleTapGR];
|
||||
}
|
||||
return _messageBackgroundView;
|
||||
}
|
||||
|
||||
@end
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
|
||||
//
|
||||
// TLMessageCellDelegate.h
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/3/2.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol TLChatUserProtocol;
|
||||
@class TLMessage;
|
||||
@protocol TLMessageCellDelegate <NSObject>
|
||||
|
||||
- (void)messageCellDidClickAvatarForUser:(id<TLChatUserProtocol>)user;
|
||||
|
||||
- (void)messageCellTap:(TLMessage *)message;
|
||||
|
||||
- (void)messageCellLongPress:(TLMessage *)message rect:(CGRect)rect;
|
||||
|
||||
- (void)messageCellDoubleClick:(TLMessage *)message;
|
||||
|
||||
@end
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// TLMessageImageView.h
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/3/15.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface TLMessageImageView : UIImageView
|
||||
|
||||
@property (nonatomic, strong) UIImage *backgroundImage;
|
||||
|
||||
/**
|
||||
* 设置消息图片(规则:收到消息时,先下载缩略图到本地,再添加到列表显示,并自动下载大图)
|
||||
*
|
||||
* @param imagePath 缩略图Path
|
||||
* @param imageURL 高清图URL
|
||||
*/
|
||||
- (void)setThumbnailPath:(NSString *)imagePath highDefinitionImageURL:(NSString *)imageURL;
|
||||
|
||||
@end
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// TLMessageImageView.m
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/3/15.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TLMessageImageView.h"
|
||||
|
||||
@interface TLMessageImageView ()
|
||||
|
||||
@property (nonatomic, weak) CAShapeLayer *maskLayer;
|
||||
|
||||
@property (nonatomic, weak) CALayer *contentLayer;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TLMessageImageView
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
CAShapeLayer *maskLayer = [CAShapeLayer layer];
|
||||
maskLayer.contentsCenter = CGRectMake(0.5, 0.6, 0.1, 0.1);
|
||||
maskLayer.contentsScale = [UIScreen mainScreen].scale; //非常关键设置自动拉伸的效果且不变形
|
||||
CALayer *contentLayer = [[CALayer alloc] init];
|
||||
[contentLayer setMask:maskLayer];
|
||||
[self.layer addSublayer:contentLayer];
|
||||
|
||||
self.maskLayer = maskLayer;
|
||||
self.contentLayer = contentLayer;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
NSLog(@"delloc TLMessageImageView");
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
[self.maskLayer setFrame:CGRectMake(0, 0, self.width, self.height)];
|
||||
[self.contentLayer setFrame:CGRectMake(0, 0, self.width, self.height)];
|
||||
}
|
||||
|
||||
- (void)setThumbnailPath:(NSString *)imagePath highDefinitionImageURL:(NSString *)imageURL
|
||||
{
|
||||
if (imagePath == nil) {
|
||||
[self.contentLayer setContents:nil];
|
||||
}
|
||||
else {
|
||||
UIImage *image = [[UIImage imageNamed:imagePath] copy];
|
||||
[self.contentLayer setContents:(id)(image.CGImage)];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setBackgroundImage:(UIImage *)backgroundImage
|
||||
{
|
||||
UIImage *image = [backgroundImage copy];
|
||||
[self.maskLayer setContents:(id)image.CGImage];
|
||||
}
|
||||
|
||||
@end
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// TLTextMessageCell.h
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/3/1.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TLMessageBaseCell.h"
|
||||
#import "TLTextMessage.h"
|
||||
|
||||
@interface TLTextMessageCell : TLMessageBaseCell
|
||||
|
||||
|
||||
@end
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// TLTextMessageCell.m
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/3/1.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TLTextMessageCell.h"
|
||||
|
||||
#define MSG_SPACE_TOP 14
|
||||
#define MSG_SPACE_BTM 20
|
||||
#define MSG_SPACE_LEFT 19
|
||||
#define MSG_SPACE_RIGHT 22
|
||||
|
||||
@interface TLTextMessageCell ()
|
||||
|
||||
@property (nonatomic, strong) UILabel *messageLabel;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TLTextMessageCell
|
||||
|
||||
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
|
||||
{
|
||||
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
|
||||
[self.contentView addSubview:self.messageLabel];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setMessage:(TLTextMessage *)message
|
||||
{
|
||||
if (self.message && [self.message.messageID isEqualToString:message.messageID]) {
|
||||
return;
|
||||
}
|
||||
TLMessageOwnerType lastOwnType = self.message ? self.message.ownerTyper : -1;
|
||||
[super setMessage:message];
|
||||
[self.messageLabel setAttributedText:[message attrText]];
|
||||
|
||||
[self.messageLabel setContentCompressionResistancePriority:500 forAxis:UILayoutConstraintAxisHorizontal];
|
||||
[self.messageBackgroundView setContentCompressionResistancePriority:100 forAxis:UILayoutConstraintAxisHorizontal];
|
||||
if (lastOwnType != message.ownerTyper) {
|
||||
if (message.ownerTyper == TLMessageOwnerTypeSelf) {
|
||||
[self.messageBackgroundView setImage:[UIImage imageNamed:@"message_sender_bg"]];
|
||||
[self.messageBackgroundView setHighlightedImage:[UIImage imageNamed:@"message_sender_bgHL"]];
|
||||
|
||||
[self.messageLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.right.mas_equalTo(self.messageBackgroundView).mas_offset(-MSG_SPACE_RIGHT);
|
||||
make.top.mas_equalTo(self.messageBackgroundView).mas_offset(MSG_SPACE_TOP);
|
||||
}];
|
||||
[self.messageBackgroundView mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.mas_equalTo(self.messageLabel).mas_offset(-MSG_SPACE_LEFT);
|
||||
make.bottom.mas_equalTo(self.messageLabel).mas_offset(MSG_SPACE_BTM);
|
||||
}];
|
||||
}
|
||||
else if (message.ownerTyper == TLMessageOwnerTypeFriend){
|
||||
[self.messageBackgroundView setImage:[UIImage imageNamed:@"message_receiver_bg"]];
|
||||
[self.messageBackgroundView setHighlightedImage:[UIImage imageNamed:@"message_receiver_bgHL"]];
|
||||
|
||||
[self.messageLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.mas_equalTo(self.messageBackgroundView).mas_offset(MSG_SPACE_LEFT);
|
||||
make.top.mas_equalTo(self.messageBackgroundView).mas_offset(MSG_SPACE_TOP);
|
||||
}];
|
||||
[self.messageBackgroundView mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||
make.right.mas_equalTo(self.messageLabel).mas_offset(MSG_SPACE_RIGHT);
|
||||
make.bottom.mas_equalTo(self.messageLabel).mas_offset(MSG_SPACE_BTM);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
[self.messageLabel mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||
make.size.mas_equalTo(message.messageFrame.contentSize);
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Getter -
|
||||
- (UILabel *)messageLabel
|
||||
{
|
||||
if (_messageLabel == nil) {
|
||||
_messageLabel = [[UILabel alloc] init];
|
||||
[_messageLabel setFont:[UIFont fontTextMessageText]];
|
||||
[_messageLabel setNumberOfLines:0];
|
||||
}
|
||||
return _messageLabel;
|
||||
}
|
||||
|
||||
@end
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// TLVoiceImageView.h
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/7/11.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface TLVoiceImageView : UIImageView
|
||||
|
||||
@property (nonatomic, assign) BOOL isFromMe;
|
||||
|
||||
- (void)startPlayingAnimation;
|
||||
|
||||
- (void)stopPlayingAnimation;
|
||||
|
||||
@end
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// TLVoiceImageView.m
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/7/11.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TLVoiceImageView.h"
|
||||
|
||||
@interface TLVoiceImageView ()
|
||||
|
||||
@property (nonatomic, strong) NSArray *imagesArray;
|
||||
|
||||
@property (nonatomic, strong) UIImage *normalImage;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TLVoiceImageView
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
[self setIsFromMe:YES];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setIsFromMe:(BOOL)isFromMe
|
||||
{
|
||||
_isFromMe = isFromMe;
|
||||
if (isFromMe) {
|
||||
self.imagesArray = @[[UIImage imageNamed:@"message_voice_sender_playing_1"],
|
||||
[UIImage imageNamed:@"message_voice_sender_playing_2"],
|
||||
[UIImage imageNamed:@"message_voice_sender_playing_3"]];
|
||||
self.normalImage = [UIImage imageNamed:@"message_voice_sender_normal"];
|
||||
}
|
||||
else {
|
||||
self.imagesArray = @[[UIImage imageNamed:@"message_voice_receiver_playing_1"],
|
||||
[UIImage imageNamed:@"message_voice_receiver_playing_2"],
|
||||
[UIImage imageNamed:@"message_voice_receiver_playing_3"]];
|
||||
self.normalImage = [UIImage imageNamed:@"message_voice_receiver_normal"];
|
||||
}
|
||||
[self setImage:self.normalImage];
|
||||
}
|
||||
|
||||
- (void)startPlayingAnimation
|
||||
{
|
||||
self.animationImages = self.imagesArray;
|
||||
self.animationRepeatCount = 0;
|
||||
self.animationDuration = 1.0;
|
||||
[self startAnimating];
|
||||
}
|
||||
|
||||
- (void)stopPlayingAnimation
|
||||
{
|
||||
[self stopAnimating];
|
||||
}
|
||||
|
||||
@end
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// TLVoiceMessageCell.h
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/5/6.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TLMessageBaseCell.h"
|
||||
#import "TLVoiceMessage.h"
|
||||
|
||||
@interface TLVoiceMessageCell : TLMessageBaseCell
|
||||
|
||||
@end
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
//
|
||||
// TLVoiceMessageCell.m
|
||||
// TLChat
|
||||
//
|
||||
// Created by 李伯坤 on 16/5/6.
|
||||
// Copyright © 2016年 李伯坤. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TLVoiceMessageCell.h"
|
||||
#import "TLVoiceImageView.h"
|
||||
|
||||
@interface TLVoiceMessageCell ()
|
||||
|
||||
@property (nonatomic, strong) UILabel *voiceTimeLabel;
|
||||
|
||||
@property (nonatomic, strong) TLVoiceImageView *voiceImageView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TLVoiceMessageCell
|
||||
|
||||
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
|
||||
{
|
||||
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
|
||||
[self.contentView addSubview:self.voiceTimeLabel];
|
||||
[self.messageBackgroundView addSubview:self.voiceImageView];
|
||||
|
||||
UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapMsgBGView)];
|
||||
[self.messageBackgroundView addGestureRecognizer:tapGR];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setMessage:(TLVoiceMessage *)message
|
||||
{
|
||||
TLMessageOwnerType lastOwnType = self.message ? self.message.ownerTyper : -1;
|
||||
[super setMessage:message];
|
||||
|
||||
[self.voiceTimeLabel setText:[NSString stringWithFormat:@"%.0lf\"\n", message.time]];
|
||||
|
||||
if (lastOwnType != message.ownerTyper) {
|
||||
if (message.ownerTyper == TLMessageOwnerTypeSelf) {
|
||||
[self.voiceImageView setIsFromMe:YES];
|
||||
[self.messageBackgroundView setImage:[UIImage imageNamed:@"message_sender_bg"]];
|
||||
[self.messageBackgroundView setHighlightedImage:[UIImage imageNamed:@"message_sender_bgHL"]];
|
||||
|
||||
[self.voiceTimeLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.right.mas_equalTo(self.messageBackgroundView.mas_left);
|
||||
make.top.mas_equalTo(self.messageBackgroundView.mas_centerY).mas_offset(-5);
|
||||
}];
|
||||
[self.voiceImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.right.mas_equalTo(-13);
|
||||
make.centerY.mas_equalTo(self.avatarButton);
|
||||
}];
|
||||
}
|
||||
else if (message.ownerTyper == TLMessageOwnerTypeFriend){
|
||||
[self.voiceImageView setIsFromMe:NO];
|
||||
[self.messageBackgroundView setImage:[UIImage imageNamed:@"message_receiver_bg"]];
|
||||
[self.messageBackgroundView setHighlightedImage:[UIImage imageNamed:@"message_receiver_bgHL"]];
|
||||
[self.voiceTimeLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.mas_equalTo(self.messageBackgroundView.mas_right);
|
||||
make.top.mas_equalTo(self.messageBackgroundView.mas_centerY).mas_offset(-5);
|
||||
}];
|
||||
[self.voiceImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.mas_equalTo(13);
|
||||
make.centerY.mas_equalTo(self.avatarButton);
|
||||
}];
|
||||
}
|
||||
}
|
||||
[self.messageBackgroundView mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||
make.size.mas_equalTo(message.messageFrame.contentSize);
|
||||
}];
|
||||
|
||||
if (message.msgStatus == TLVoiceMessageStatusRecording) {
|
||||
[self.voiceTimeLabel setHidden:YES];
|
||||
[self.voiceImageView setHidden:YES];
|
||||
[self p_startRecordingAnimation];
|
||||
}
|
||||
else {
|
||||
[self.voiceTimeLabel setHidden:NO];
|
||||
[self.voiceImageView setHidden:NO];
|
||||
[self p_stopRecordingAnimation];
|
||||
[self.messageBackgroundView setAlpha:1.0];
|
||||
}
|
||||
message.msgStatus == TLVoiceMessageStatusPlaying ? [self.voiceImageView startPlayingAnimation] : [self.voiceImageView stopPlayingAnimation];
|
||||
}
|
||||
|
||||
- (void)updateMessage:(TLVoiceMessage *)message
|
||||
{
|
||||
[super setMessage:message];
|
||||
|
||||
[self.voiceTimeLabel setText:[NSString stringWithFormat:@"%.0lf\"\n", message.time]];
|
||||
if (message.msgStatus == TLVoiceMessageStatusRecording) {
|
||||
[self.voiceTimeLabel setHidden:YES];
|
||||
[self.voiceImageView setHidden:YES];
|
||||
[self p_startRecordingAnimation];
|
||||
}
|
||||
else {
|
||||
[self.voiceTimeLabel setHidden:NO];
|
||||
[self.voiceImageView setHidden:NO];
|
||||
[self p_stopRecordingAnimation];
|
||||
}
|
||||
message.msgStatus == TLVoiceMessageStatusPlaying ? [self.voiceImageView startPlayingAnimation] : [self.voiceImageView stopPlayingAnimation];
|
||||
|
||||
[UIView animateWithDuration:0.5 animations:^{
|
||||
[self.messageBackgroundView mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||
make.size.mas_equalTo(message.messageFrame.contentSize);
|
||||
}];
|
||||
[self layoutIfNeeded];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - # Event Response
|
||||
- (void)didTapMsgBGView
|
||||
{
|
||||
[self.voiceImageView startPlayingAnimation];
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(messageCellTap:)]) {
|
||||
[self.delegate messageCellTap:self.message];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - # Private Methods
|
||||
static bool isStartAnimation = NO;
|
||||
static float bgAlpha = 1.0;
|
||||
- (void)p_startRecordingAnimation
|
||||
{
|
||||
isStartAnimation = YES;
|
||||
bgAlpha = 0.4;
|
||||
[self p_repeatAnimation];
|
||||
}
|
||||
|
||||
- (void)p_repeatAnimation
|
||||
{
|
||||
[UIView animateWithDuration:1.0 animations:^{
|
||||
[self.messageBackgroundView setAlpha:bgAlpha];
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished) {
|
||||
bgAlpha = bgAlpha > 0.9 ? 0.4 : 1.0;
|
||||
if (isStartAnimation) {
|
||||
[self p_repeatAnimation];
|
||||
}
|
||||
else {
|
||||
[self.messageBackgroundView setAlpha:1.0];
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)p_stopRecordingAnimation
|
||||
{
|
||||
isStartAnimation = NO;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - # Getter
|
||||
- (UILabel *)voiceTimeLabel
|
||||
{
|
||||
if (_voiceTimeLabel == nil) {
|
||||
_voiceTimeLabel = [[UILabel alloc] init];
|
||||
[_voiceTimeLabel setTextColor:[UIColor grayColor]];
|
||||
[_voiceTimeLabel setFont:[UIFont systemFontOfSize:14.0f]];
|
||||
}
|
||||
return _voiceTimeLabel;
|
||||
}
|
||||
|
||||
- (TLVoiceImageView *)voiceImageView
|
||||
{
|
||||
if (_voiceImageView == nil) {
|
||||
_voiceImageView = [[TLVoiceImageView alloc] init];
|
||||
}
|
||||
return _voiceImageView;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user