chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:35:01 +08:00
commit a2e318a963
2974 changed files with 158180 additions and 0 deletions
@@ -0,0 +1,22 @@
//
// TLExpressionMessage.h
// TLChat
//
// Created by libokun on 16/3/28.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLMessage.h"
#import "TLExpressionModel.h"
@interface TLExpressionMessage : TLMessage
@property (nonatomic, strong) TLExpressionModel *emoji;
@property (nonatomic, strong, readonly) NSString *path;
@property (nonatomic, strong, readonly) NSString *url;
@property (nonatomic, assign, readonly) CGSize emojiSize;
@end
@@ -0,0 +1,97 @@
//
// TLExpressionMessage.m
// TLChat
//
// Created by libokun on 16/3/28.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLExpressionMessage.h"
@implementation TLExpressionMessage
@synthesize emoji = _emoji;
- (id)init
{
if (self = [super init]) {
[self setMessageType:TLMessageTypeExpression];
}
return self;
}
- (void)setEmoji:(TLExpressionModel *)emoji
{
_emoji = emoji;
[self.content setObject:emoji.gid forKey:@"groupID"];
[self.content setObject:emoji.eId forKey:@"emojiID"];
CGSize imageSize = [UIImage imageNamed:self.path].size;
[self.content setObject:[NSNumber numberWithDouble:imageSize.width] forKey:@"w"];
[self.content setObject:[NSNumber numberWithDouble:imageSize.height] forKey:@"h"];
}
- (TLExpressionModel *)emoji
{
if (_emoji == nil) {
_emoji = [[TLExpressionModel alloc] init];
_emoji.gid = self.content[@"groupID"];
_emoji.eId = self.content[@"emojiID"];
}
return _emoji;
}
- (NSString *)path
{
return self.emoji.path;
}
- (NSString *)url
{
return [TLExpressionModel expressionDownloadURLWithEid:self.emoji.eId];
}
- (CGSize)emojiSize
{
CGFloat width = [self.content[@"w"] doubleValue];
CGFloat height = [self.content[@"h"] doubleValue];
return CGSizeMake(width, height);
}
#pragma mark -
- (TLMessageFrame *)messageFrame
{
if (kMessageFrame == nil) {
kMessageFrame = [[TLMessageFrame alloc] init];
kMessageFrame.height = 20 + (self.showTime ? 30 : 0) + (self.showName ? 15 : 0);
kMessageFrame.height += 5;
CGSize emojiSize = self.emojiSize;
if (CGSizeEqualToSize(emojiSize, CGSizeZero)) {
kMessageFrame.contentSize = CGSizeMake(80, 80);
}
else if (emojiSize.width > emojiSize.height) {
CGFloat height = MAX_MESSAGE_EXPRESSION_WIDTH * emojiSize.height / emojiSize.width;
height = height < MIN_MESSAGE_EXPRESSION_WIDTH ? MIN_MESSAGE_EXPRESSION_WIDTH : height;
kMessageFrame.contentSize = CGSizeMake(MAX_MESSAGE_EXPRESSION_WIDTH, height);
}
else {
CGFloat width = MAX_MESSAGE_EXPRESSION_WIDTH * emojiSize.width / emojiSize.height;
width = width < MIN_MESSAGE_EXPRESSION_WIDTH ? MIN_MESSAGE_EXPRESSION_WIDTH : width;
kMessageFrame.contentSize = CGSizeMake(width, MAX_MESSAGE_EXPRESSION_WIDTH);
}
kMessageFrame.height += kMessageFrame.contentSize.height;
}
return kMessageFrame;
}
- (NSString *)conversationContent
{
return @"[表情]";
}
- (NSString *)messageCopy
{
return [self.content mj_JSONString];
}
@end
@@ -0,0 +1,17 @@
//
// TLImageMessage.h
// TLChat
//
// Created by libokun on 16/3/28.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLMessage.h"
@interface TLImageMessage : TLMessage
@property (nonatomic, strong) NSString *imagePath; // 本地图片Path
@property (nonatomic, strong) NSString *imageURL; // 网络图片URL
@property (nonatomic, assign) CGSize imageSize;
@end
@@ -0,0 +1,99 @@
//
// TLImageMessage.m
// TLChat
//
// Created by libokun on 16/3/28.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLImageMessage.h"
@implementation TLImageMessage
@synthesize imagePath = _imagePath;
@synthesize imageURL = _imageURL;
- (id)init
{
if (self = [super init]) {
[self setMessageType:TLMessageTypeImage];
}
return self;
}
#pragma mark -
- (NSString *)imagePath
{
if (_imagePath == nil) {
_imagePath = [self.content objectForKey:@"path"];
}
return _imagePath;
}
- (void)setImagePath:(NSString *)imagePath
{
_imagePath = imagePath;
[self.content setObject:imagePath forKey:@"path"];
}
- (NSString *)imageURL
{
if (_imageURL == nil) {
_imageURL = [self.content objectForKey:@"url"];
}
return _imageURL;
}
- (void)setImageURL:(NSString *)imageURL
{
_imageURL = imageURL;
[self.content setObject:imageURL forKey:@"url"];
}
- (CGSize)imageSize
{
CGFloat width = [[self.content objectForKey:@"w"] doubleValue];
CGFloat height = [[self.content objectForKey:@"h"] doubleValue];
return CGSizeMake(width, height);
}
- (void)setImageSize:(CGSize)imageSize
{
[self.content setObject:[NSNumber numberWithDouble:imageSize.width] forKey:@"w"];
[self.content setObject:[NSNumber numberWithDouble:imageSize.height] forKey:@"h"];
}
#pragma mark -
- (TLMessageFrame *)messageFrame
{
if (kMessageFrame == nil) {
kMessageFrame = [[TLMessageFrame alloc] init];
kMessageFrame.height = 20 + (self.showTime ? 30 : 0) + (self.showName ? 15 : 0);
CGSize imageSize = self.imageSize;
if (CGSizeEqualToSize(imageSize, CGSizeZero)) {
kMessageFrame.contentSize = CGSizeMake(100, 100);
}
else if (imageSize.width > imageSize.height) {
CGFloat height = MAX_MESSAGE_IMAGE_WIDTH * imageSize.height / imageSize.width;
height = height < MIN_MESSAGE_IMAGE_WIDTH ? MIN_MESSAGE_IMAGE_WIDTH : height;
kMessageFrame.contentSize = CGSizeMake(MAX_MESSAGE_IMAGE_WIDTH, height);
}
else {
CGFloat width = MAX_MESSAGE_IMAGE_WIDTH * imageSize.width / imageSize.height;
width = width < MIN_MESSAGE_IMAGE_WIDTH ? MIN_MESSAGE_IMAGE_WIDTH : width;
kMessageFrame.contentSize = CGSizeMake(width, MAX_MESSAGE_IMAGE_WIDTH);
}
kMessageFrame.height += kMessageFrame.contentSize.height;
}
return kMessageFrame;
}
- (NSString *)conversationContent
{
return @"[图片]";
}
- (NSString *)messageCopy
{
return [self.content mj_JSONString];
}
@end
@@ -0,0 +1,80 @@
//
// TLMessage.h
// TLChat
//
// Created by 李伯坤 on 16/2/15.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "TLChatUserProtocol.h"
#import "TLMessageProtocol.h"
#import <MapKit/MapKit.h>
#import "TLMessageConstants.h"
/**
* 消息所有者类型
*/
typedef NS_ENUM(NSInteger, TLPartnerType){
TLPartnerTypeUser, // 用户
TLPartnerTypeGroup, // 群聊
};
/**
* 消息拥有者
*/
typedef NS_ENUM(NSInteger, TLMessageOwnerType){
TLMessageOwnerTypeUnknown, // 未知的消息拥有者
TLMessageOwnerTypeSystem, // 系统消息
TLMessageOwnerTypeSelf, // 自己发送的消息
TLMessageOwnerTypeFriend, // 接收到的他人消息
};
/**
* 消息发送状态
*/
typedef NS_ENUM(NSInteger, TLMessageSendState){
TLMessageSendSuccess, // 消息发送成功
TLMessageSendFail, // 消息发送失败
};
/**
* 消息读取状态
*/
typedef NS_ENUM(NSInteger, TLMessageReadState) {
TLMessageUnRead, // 消息未读
TLMessageReaded, // 消息已读
};
@interface TLMessage : NSObject <TLMessageProtocol>
{
TLMessageFrame *kMessageFrame;
}
@property (nonatomic, strong) NSString *messageID; // 消息ID
@property (nonatomic, strong) NSString *userID; // 发送者ID
@property (nonatomic, strong) NSString *friendID; // 接收者ID
@property (nonatomic, strong) NSString *groupID; // 讨论组ID(无则为nil
@property (nonatomic, strong) NSDate *date; // 发送时间
@property (nonatomic, strong) id<TLChatUserProtocol> fromUser; // 发送者
@property (nonatomic, assign) BOOL showTime;
@property (nonatomic, assign) BOOL showName;
@property (nonatomic, assign) TLPartnerType partnerType; // 对方类型
@property (nonatomic, assign) TLMessageType messageType; // 消息类型
@property (nonatomic, assign) TLMessageOwnerType ownerTyper; // 发送者类型
@property (nonatomic, assign) TLMessageReadState readState; // 读取状态
@property (nonatomic, assign) TLMessageSendState sendState; // 发送状态
@property (nonatomic, strong) NSMutableDictionary *content;
@property (nonatomic, strong, readonly) TLMessageFrame *messageFrame; // 消息frame
+ (TLMessage *)createMessageByType:(TLMessageType)type;
- (void)resetMessageFrame;
@end
@@ -0,0 +1,69 @@
//
// TLMessage.m
// TLChat
//
// Created by 李伯坤 on 16/2/15.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLMessage.h"
@implementation TLMessage
+ (TLMessage *)createMessageByType:(TLMessageType)type
{
NSString *className;
if (type == TLMessageTypeText) {
className = @"TLTextMessage";
}
else if (type == TLMessageTypeImage) {
className = @"TLImageMessage";
}
else if (type == TLMessageTypeExpression) {
className = @"TLExpressionMessage";
}
else if (type == TLMessageTypeVoice) {
className = @"TLVoiceMessage";
}
if (className) {
return [[NSClassFromString(className) alloc] init];
}
return nil;
}
- (id)init
{
if (self = [super init]) {
self.messageID = [NSString stringWithFormat:@"%lld", (long long)([[NSDate date] timeIntervalSince1970] * 10000)];
}
return self;
}
- (void)resetMessageFrame
{
kMessageFrame = nil;
}
#pragma mark - # Protocol
- (NSString *)conversationContent
{
return @"子类未定义";
}
- (NSString *)messageCopy
{
return @"子类未定义";
}
#pragma mark - # Getter
- (NSMutableDictionary *)content
{
if (_content == nil) {
_content = [[NSMutableDictionary alloc] init];
}
return _content;
}
@end
@@ -0,0 +1,36 @@
//
// TLMessageConstants.h
// TLChat
//
// Created by 李伯坤 on 2017/9/20.
// Copyright © 2017年 李伯坤. All rights reserved.
//
#ifndef TLMessageConstants_h
#define TLMessageConstants_h
/**
* 消息类型
*/
typedef NS_ENUM(NSInteger, TLMessageType) {
TLMessageTypeUnknown,
TLMessageTypeText, // 文字
TLMessageTypeImage, // 图片
TLMessageTypeExpression, // 表情
TLMessageTypeVoice, // 语音
TLMessageTypeVideo, // 视频
TLMessageTypeURL, // 链接
TLMessageTypePosition, // 位置
TLMessageTypeBusinessCard, // 名片
TLMessageTypeSystem, // 系统
TLMessageTypeOther,
};
#define MAX_MESSAGE_WIDTH SCREEN_WIDTH * 0.58
#define MAX_MESSAGE_IMAGE_WIDTH SCREEN_WIDTH * 0.45
#define MIN_MESSAGE_IMAGE_WIDTH SCREEN_WIDTH * 0.25
#define MAX_MESSAGE_EXPRESSION_WIDTH SCREEN_WIDTH * 0.35
#define MIN_MESSAGE_EXPRESSION_WIDTH SCREEN_WIDTH * 0.2
#endif /* TLMessageConstants_h */
@@ -0,0 +1,17 @@
//
// TLMessageFrame.h
// TLChat
//
// Created by 李伯坤 on 16/3/14.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface TLMessageFrame : NSObject
@property (nonatomic, assign) CGFloat height;
@property (nonatomic, assign) CGSize contentSize;
@end
@@ -0,0 +1,13 @@
//
// TLMessageFrame.m
// TLChat
//
// Created by 李伯坤 on 16/3/14.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLMessageFrame.h"
@implementation TLMessageFrame
@end
@@ -0,0 +1,18 @@
//
// TLMessageProtocol.h
// TLChat
//
// Created by libokun on 16/3/28.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "TLMessageFrame.h"
@protocol TLMessageProtocol <NSObject>
- (NSString *)messageCopy;
- (NSString *)conversationContent;
@end
@@ -0,0 +1,17 @@
//
// TLTextMessage.h
// TLChat
//
// Created by libokun on 16/3/28.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLMessage.h"
@interface TLTextMessage : TLMessage
@property (nonatomic, strong) NSString *text; // 文字信息
@property (nonatomic, strong) NSAttributedString *attrText; // 格式化的文字信息(仅展示用)
@end
@@ -0,0 +1,73 @@
//
// TLTextMessage.m
// TLChat
//
// Created by libokun on 16/3/28.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLTextMessage.h"
#import "NSString+Message.h"
static UILabel *textLabel = nil;
@implementation TLTextMessage
@synthesize text = _text;
- (id)init
{
if (self = [super init]) {
[self setMessageType:TLMessageTypeText];
if (textLabel == nil) {
textLabel = [[UILabel alloc] init];
[textLabel setFont:[UIFont fontTextMessageText]];
[textLabel setNumberOfLines:0];
}
}
return self;
}
- (NSString *)text
{
if (_text == nil) {
_text = [self.content objectForKey:@"text"];
}
return _text;
}
- (void)setText:(NSString *)text
{
_text = text;
[self.content setObject:text forKey:@"text"];
}
- (NSAttributedString *)attrText
{
if (_attrText == nil) {
_attrText = [self.text toMessageString];
}
return _attrText;
}
- (TLMessageFrame *)messageFrame
{
if (kMessageFrame == nil) {
kMessageFrame = [[TLMessageFrame alloc] init];
kMessageFrame.height = 20 + (self.showTime ? 30 : 0) + (self.showName ? 15 : 0) + 20;
[textLabel setAttributedText:self.attrText];
kMessageFrame.contentSize = [textLabel sizeThatFits:CGSizeMake(MAX_MESSAGE_WIDTH, MAXFLOAT)];
kMessageFrame.height += kMessageFrame.contentSize.height;
}
return kMessageFrame;
}
- (NSString *)conversationContent
{
return self.text;
}
- (NSString *)messageCopy
{
return self.text;
}
@end
@@ -0,0 +1,20 @@
//
// TLVideoMessage.h
// TLChat
//
// Created by 李伯坤 on 16/10/1.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLMessage.h"
@interface TLVideoMessage : TLMessage
@property (nonatomic, strong, readonly) NSString *videoPath;
@property (nonatomic, strong) NSString *videoURL;
@property (nonatomic, strong, readonly) NSString *imagePath; // 本地图片Path
@property (nonatomic, strong) NSString *imageURL; // 网络图片URL
@property (nonatomic, assign) CGSize imageSize;
@end
@@ -0,0 +1,13 @@
//
// TLVideoMessage.m
// TLChat
//
// Created by 李伯坤 on 16/10/1.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLVideoMessage.h"
@implementation TLVideoMessage
@end
@@ -0,0 +1,27 @@
//
// TLVoiceMessage.h
// TLChat
//
// Created by 李伯坤 on 16/7/11.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLMessage.h"
typedef NS_ENUM(NSInteger, TLVoiceMessageStatus) {
TLVoiceMessageStatusNormal,
TLVoiceMessageStatusRecording,
TLVoiceMessageStatusPlaying,
};
@interface TLVoiceMessage : TLMessage
@property (nonatomic, strong) NSString *recFileName;
@property (nonatomic, strong, readonly) NSString *path;
@property (nonatomic, strong) NSString *url;
@property (nonatomic, assign) CGFloat time;
@property (nonatomic, assign) TLVoiceMessageStatus msgStatus;
@end
@@ -0,0 +1,93 @@
//
// TLVoiceMessage.m
// TLChat
//
// Created by 李伯坤 on 16/7/11.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLVoiceMessage.h"
#import "NSFileManager+TLChat.h"
@implementation TLVoiceMessage
@synthesize recFileName = _recFileName;
@synthesize path = _path;
@synthesize url = _url;
@synthesize time = _time;
- (id)init
{
if (self = [super init]) {
[self setMessageType:TLMessageTypeVoice];
}
return self;
}
- (NSString *)recFileName
{
if (_recFileName == nil) {
_recFileName = [self.content objectForKey:@"path"];
}
return _recFileName;
}
- (void)setRecFileName:(NSString *)recFileName
{
_recFileName = recFileName;
[self.content setObject:recFileName forKey:@"path"];
}
- (NSString *)path
{
if (_path == nil) {
_path = [NSFileManager pathUserChatVoice:self.recFileName];;
}
return _path;
}
- (NSString *)url
{
if (_url == nil) {
_url = [self.content objectForKey:@"url"];
}
return _url;
}
- (void)setUrl:(NSString *)url
{
_url = url;
[self.content setObject:url forKey:@"url"];
}
- (CGFloat)time
{
return [[self.content objectForKey:@"time"] doubleValue];
}
- (void)setTime:(CGFloat)time
{
[self.content setObject:[NSNumber numberWithDouble:time] forKey:@"time"];
}
#pragma mark -
- (TLMessageFrame *)messageFrame
{
if (kMessageFrame == nil) {
kMessageFrame = [[TLMessageFrame alloc] init];
CGFloat width = 60 + (self.time > 20 ? 1.0 : self.time / 20.0) * (MAX_MESSAGE_WIDTH - 60);
CGFloat height = 54;
kMessageFrame.contentSize = CGSizeMake(width, height);
kMessageFrame.height = kMessageFrame.contentSize.height + (self.showTime ? 30 : 0) + (self.showName ? 15 : 0) + 3;
}
return kMessageFrame;
}
- (NSString *)conversationContent
{
return @"[语音消息]";
}
- (NSString *)messageCopy
{
return [self.content mj_JSONString];
}
@end