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,15 @@
//
// TLExpressionGroupModel+Download.h
// TLChat
//
// Created by 李伯坤 on 2018/1/2.
// Copyright © 2018年 李伯坤. All rights reserved.
//
#import "TLExpressionGroupModel.h"
@interface TLExpressionGroupModel (Download)
- (void)startDownload;
@end
@@ -0,0 +1,72 @@
//
// TLExpressionGroupModel+Download.m
// TLChat
//
// Created by 李伯坤 on 2018/1/2.
// Copyright © 2018年 李伯坤. All rights reserved.
//
#import "TLExpressionGroupModel+Download.h"
#import "TLExpressionGroupModel+DetailRequest.h"
#import "TLExpressionHelper.h"
#import "NSFileManager+TLChat.h"
@implementation TLExpressionGroupModel (Download)
- (void)startDownload
{
self.status = TLExpressionGroupStatusDownloading;
if (self.data.count == 0) {
self.data = @[].mutableCopy;
[self requestDetailInfoWithPageIndex:1];
}
else {
[self p_startDownload];
}
}
- (void)requestDetailInfoWithPageIndex:(NSInteger)pageIndex
{
[self requestExpressionGroupDetailByPageIndex:pageIndex success:^(NSArray *successData) {
if (successData.count > 0) {
[self.data addObjectsFromArray:successData];
[self p_startDownload];
}
else {
self.status = TLExpressionGroupStatusNet;
if (self.downloadCompleteAction) {
self.downloadCompleteAction(self, NO, @"表情包数据错误");
}
}
} failure:^(id failureData) {
self.status = TLExpressionGroupStatusNet;
if (self.downloadCompleteAction) {
self.downloadCompleteAction(self, NO, @"获取表情包信息失败");
}
}];
}
- (void)p_startDownload
{
[[TLExpressionHelper sharedHelper] downloadExpressionsWithGroupInfo:self progress:^(CGFloat progress) {
self.downloadProgress = progress;
if (self.downloadProgressAction) {
self.downloadProgressAction(self, progress);
}
} success:^(TLExpressionGroupModel *group) {
self.status = TLExpressionGroupStatusLocal;
[[TLExpressionHelper sharedHelper] addExpressionGroup:group];
if (self.downloadCompleteAction) {
self.downloadCompleteAction(group, YES, nil);
}
} failure:^(TLExpressionGroupModel *group, NSString *error) {
self.status = TLExpressionGroupStatusNet;
if (self.downloadCompleteAction) {
self.downloadCompleteAction(group, NO, error);
}
}];
}
@end
@@ -0,0 +1,62 @@
//
// TLDBExpressionSQL.h
// TLChat
//
// Created by 李伯坤 on 16/4/9.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#ifndef TLDBExpressionSQL_h
#define TLDBExpressionSQL_h
#pragma mark - # 表情组
#define EXP_GROUP_TABLE_NAME @"expression_group"
#define SQL_CREATE_EXP_GROUP_TABLE @"CREATE TABLE IF NOT EXISTS %@(\
uid TEXT,\
gid TEXT,\
type INTEGER DEFAULT (0), \
name TEXT,\
desc TEXT,\
detail TEXT,\
count INTEGER DEFAULT (0), \
auth_id TEXT,\
auth_name TEXT,\
date TEXT,\
ext1 TEXT,\
ext2 TEXT,\
ext3 TEXT,\
ext4 TEXT,\
ext5 TEXT,\
PRIMARY KEY(uid, gid))"
#define SQL_ADD_EXP_GROUP @"REPLACE INTO %@ ( uid, gid, type, name, desc, detail, count, auth_id, auth_name, date, ext1, ext2, ext3, ext4, ext5) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )"
#define SQL_SELECT_EXP_GROUP @"SELECT * FROM %@ WHERE uid = '%@' order by date desc"
#define SQL_DELETE_EXP_GROUP @"DELETE FROM %@ WHERE uid = '%@' and gid = '%@'"
#define SQL_SELECT_COUNT_EXP_GROUP_USERS @"SELECT count(uid) FROM %@ WHERE gid = '%@'"
#pragma mark - # 表情
#define EXPS_TABLE_NAME @"expressions"
#define SQL_CREATE_EXPS_TABLE @"CREATE TABLE IF NOT EXISTS %@(\
gid TEXT,\
eid TEXT, \
name TEXT,\
ext1 TEXT,\
ext2 TEXT,\
ext3 TEXT,\
ext4 TEXT,\
ext5 TEXT,\
PRIMARY KEY(gid, eid))"
#define SQL_ADD_EXP @"REPLACE INTO %@ ( gid, eid, name, ext1, ext2, ext3, ext4, ext5) VALUES ( ?, ?, ?, ?, ?, ?, ?, ? )"
#define SQL_SELECT_EXPS @"SELECT * FROM %@ WHERE gid = '%@'"
#endif /* TLDBExpressionSQL_h */
@@ -0,0 +1,35 @@
//
// TLDBExpressionStore.h
// TLChat
//
// Created by 李伯坤 on 16/4/9.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLDBBaseStore.h"
#import "TLExpressionGroupModel.h"
@interface TLDBExpressionStore : TLDBBaseStore
/**
* 添加表情包
*/
- (BOOL)addExpressionGroup:(TLExpressionGroupModel *)group forUid:(NSString *)uid;
/**
* 查询所有表情包
*/
- (NSArray *)expressionGroupsByUid:(NSString *)uid;
/**
* 删除表情包
*/
- (BOOL)deleteExpressionGroupByID:(NSString *)gid forUid:(NSString *)uid;
/**
* 拥有某表情包的用户数
*/
- (NSInteger)countOfUserWhoHasExpressionGroup:(NSString *)gid;
@end
@@ -0,0 +1,151 @@
//
// TLDBExpressionStore.m
// TLChat
//
// Created by 李伯坤 on 16/4/9.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLDBExpressionStore.h"
#import "TLDBExpressionSQL.h"
#import "TLDBManager.h"
#import "TLMacros.h"
@implementation TLDBExpressionStore
- (id)init
{
if (self = [super init]) {
self.dbQueue = [TLDBManager sharedInstance].commonQueue;
BOOL ok = [self createTable];
if (!ok) {
DDLogError(@"DB: 聊天记录表创建失败");
}
}
return self;
}
- (BOOL)createTable
{
NSString *sqlString = [NSString stringWithFormat:SQL_CREATE_EXP_GROUP_TABLE, EXP_GROUP_TABLE_NAME];
BOOL ok = [self createTable:EXP_GROUP_TABLE_NAME withSQL:sqlString];
if (!ok) {
return NO;
}
sqlString = [NSString stringWithFormat:SQL_CREATE_EXPS_TABLE, EXPS_TABLE_NAME];
ok = [self createTable:EXPS_TABLE_NAME withSQL:sqlString];
return ok;
}
#pragma mark - # 表情组
- (BOOL)addExpressionGroup:(TLExpressionGroupModel *)group forUid:(NSString *)uid
{
// 添加表情包
NSString *sqlString = [NSString stringWithFormat:SQL_ADD_EXP_GROUP, EXP_GROUP_TABLE_NAME];
NSArray *arr = [NSArray arrayWithObjects:
uid,
group.gId,
[NSNumber numberWithInteger:group.type],
TLNoNilString(group.name),
TLNoNilString(group.groupInfo),
TLNoNilString(group.detail),
[NSNumber numberWithInteger:group.count],
TLNoNilString(group.authID),
TLNoNilString(group.authName),
TLTimeStamp(group.date),
@"", @"", @"", @"", @"", nil];
BOOL ok = [self excuteSQL:sqlString withArrParameter:arr];
if (!ok) {
return NO;
}
// 添加表情包里的所有表情
ok = [self addExpressions:group.data toGroupID:group.gId];
return ok;
}
- (NSArray *)expressionGroupsByUid:(NSString *)uid
{
__block NSMutableArray *data = [[NSMutableArray alloc] init];
NSString *sqlString = [NSString stringWithFormat: SQL_SELECT_EXP_GROUP, EXP_GROUP_TABLE_NAME, uid];
// 读取表情包信息
[self excuteQuerySQL:sqlString resultBlock:^(FMResultSet *retSet) {
while ([retSet next]) {
TLExpressionGroupModel *group = [[TLExpressionGroupModel alloc] init];
group.gId = [retSet stringForColumn:@"gid"];
group.type = [retSet intForColumn:@"type"];
group.name = [retSet stringForColumn:@"name"];
group.groupInfo = [retSet stringForColumn:@"desc"];
group.detail = [retSet stringForColumn:@"detail"];
group.count = [retSet intForColumn:@"count"];
group.authID = [retSet stringForColumn:@"auth_id"];
group.authName = [retSet stringForColumn:@"auth_name"];
group.status = TLExpressionGroupStatusLocal;
[data addObject:group];
}
[retSet close];
}];
// 读取表情包的所有表情信息
for (TLExpressionGroupModel *group in data) {
group.data = [self expressionsForGroupID:group.gId];
}
return data;
}
- (BOOL)deleteExpressionGroupByID:(NSString *)gid forUid:(NSString *)uid
{
NSString *sqlString = [NSString stringWithFormat:SQL_DELETE_EXP_GROUP, EXP_GROUP_TABLE_NAME, uid, gid];
return [self excuteSQL:sqlString, nil];
}
- (NSInteger)countOfUserWhoHasExpressionGroup:(NSString *)gid
{
NSString *sqlString = [NSString stringWithFormat:SQL_SELECT_COUNT_EXP_GROUP_USERS, EXP_GROUP_TABLE_NAME, gid];
__block NSInteger count = 0;
[self.dbQueue inDatabase:^(FMDatabase *db) {
count = [db intForQuery:sqlString];
}];
return count;
}
#pragma mark - # 表情
- (BOOL)addExpressions:(NSArray *)expressions toGroupID:(NSString *)groupID
{
for (TLExpressionModel *emoji in expressions) {
NSString *sqlString = [NSString stringWithFormat:SQL_ADD_EXP, EXPS_TABLE_NAME];
NSArray *arr = [NSArray arrayWithObjects:
groupID,
emoji.eId,
TLNoNilString(emoji.name),
@"", @"", @"", @"", @"", nil];
BOOL ok = [self excuteSQL:sqlString withArrParameter:arr];
if (!ok) {
return NO;
}
}
return YES;
}
- (NSMutableArray *)expressionsForGroupID:(NSString *)groupID
{
__block NSMutableArray *data = [[NSMutableArray alloc] init];
NSString *sqlString = [NSString stringWithFormat: SQL_SELECT_EXPS, EXPS_TABLE_NAME, groupID];
[self excuteQuerySQL:sqlString resultBlock:^(FMResultSet *retSet) {
while ([retSet next]) {
TLExpressionModel *emoji = [[TLExpressionModel alloc] init];
emoji.gid = [retSet stringForColumn:@"gid"];
emoji.eId = [retSet stringForColumn:@"eid"];
emoji.name = [retSet stringForColumn:@"name"];
[data addObject:emoji];
}
[retSet close];
}];
return data;
}
@end
@@ -0,0 +1,54 @@
//
// TLExpressionHelper.h
// TLChat
//
// Created by 李伯坤 on 16/3/11.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "TLExpressionGroupModel.h"
@interface TLExpressionHelper : NSObject
/// 默认表情(Face
@property (nonatomic, strong, readonly) TLExpressionGroupModel *defaultFaceGroup;
/// 默认系统Emoji
@property (nonatomic, strong, readonly) TLExpressionGroupModel *defaultSystemEmojiGroup;
/// 用户表情组
@property (nonatomic, strong, readonly) NSArray *userEmojiGroups;
/// 用户收藏的表情
@property (nonatomic, strong, readonly) TLExpressionGroupModel *userPreferEmojiGroup;
+ (TLExpressionHelper *)sharedHelper;
/**
* 根据groupID获取表情包
*/
- (TLExpressionGroupModel *)emojiGroupByID:(NSString *)groupID;
/**
* 添加表情包
*/
- (BOOL)addExpressionGroup:(TLExpressionGroupModel *)emojiGroup;
/**
* 删除表情包
*/
- (BOOL)deleteExpressionGroupByID:(NSString *)groupID;
- (void)updateExpressionGroupModelsStatus:(NSArray *)groupModelArray;
#pragma mark - 下载表情包
- (void)downloadExpressionsWithGroupInfo:(TLExpressionGroupModel *)group
progress:(void (^)(CGFloat progress))progress
success:(void (^)(TLExpressionGroupModel *group))success
failure:(void (^)(TLExpressionGroupModel *group, NSString *error))failure;
@end
@@ -0,0 +1,178 @@
//
// TLExpressionHelper.m
// TLChat
//
// Created by 李伯坤 on 16/3/11.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLExpressionHelper.h"
#import "TLDBExpressionStore.h"
#import "TLEmojiKBHelper.h"
#import "TLUserHelper.h"
#import "NSFileManager+TLChat.h"
@interface TLExpressionHelper ()
@property (nonatomic, strong) TLDBExpressionStore *store;
@end
@implementation TLExpressionHelper
@synthesize defaultFaceGroup = _defaultFaceGroup;
@synthesize defaultSystemEmojiGroup = _defaultSystemEmojiGroup;
@synthesize userEmojiGroups = _userEmojiGroups;
+ (TLExpressionHelper *)sharedHelper
{
static TLExpressionHelper *helper;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
helper = [[TLExpressionHelper alloc] init];
});
return helper;
}
- (NSArray *)userEmojiGroups
{
return [self.store expressionGroupsByUid:[TLUserHelper sharedHelper].userID];
}
- (BOOL)addExpressionGroup:(TLExpressionGroupModel *)emojiGroup
{
BOOL ok = [self.store addExpressionGroup:emojiGroup forUid:[TLUserHelper sharedHelper].userID];
if (ok) { // 通知表情键盘
[[TLEmojiKBHelper sharedKBHelper] updateEmojiGroupData];
}
return ok;
}
- (BOOL)deleteExpressionGroupByID:(NSString *)groupID
{
TLExpressionGroupModel *groupModel = [self emojiGroupByID:groupID];
BOOL ok = [self.store deleteExpressionGroupByID:groupID forUid:[TLUserHelper sharedHelper].userID];
if (ok) { // 通知表情键盘
[[TLEmojiKBHelper sharedKBHelper] updateEmojiGroupData];
BOOL canDeleteFile = ![self didExpressionGroupAlwaysInUsed:groupID];
if (canDeleteFile) {
NSError *error;
ok = [[NSFileManager defaultManager] removeItemAtPath:groupModel.path error:&error];
if (!ok) {
DDLogError(@"删除表情文件失败\n路径:%@\n原因:%@", groupModel.path, [error description]);
}
}
}
return ok;
}
- (BOOL)didExpressionGroupAlwaysInUsed:(NSString *)groupID
{
NSInteger count = [self.store countOfUserWhoHasExpressionGroup:groupID];
return count > 0;
}
- (TLExpressionGroupModel *)emojiGroupByID:(NSString *)groupID;
{
for (TLExpressionGroupModel *group in self.userEmojiGroups) {
if ([group.gId isEqualToString:groupID]) {
return group;
}
}
return nil;
}
- (void)downloadExpressionsWithGroupInfo:(TLExpressionGroupModel *)group
progress:(void (^)(CGFloat))progress
success:(void (^)(TLExpressionGroupModel *))success
failure:(void (^)(TLExpressionGroupModel *, NSString *))failure
{
group.type = TLEmojiTypeImageWithTitle;
dispatch_queue_t downloadQueue = dispatch_queue_create([group.gId UTF8String], nil);
dispatch_group_t downloadGroup = dispatch_group_create();
__block CGFloat p = 0;
for (int i = 0; i <= group.data.count; i++) {
dispatch_group_async(downloadGroup, downloadQueue, ^{
NSString *groupPath = [NSFileManager pathExpressionForGroupID:group.gId];
NSString *emojiPath;
NSData *data = nil;
if (i == group.data.count) {
emojiPath = [NSString stringWithFormat:@"%@icon_%@", groupPath, group.gId];
data = [NSData dataWithContentsOfURL:TLURL(group.iconURL)];
}
else {
TLExpressionModel *emoji = group.data[i];
NSString *urlString = [TLExpressionModel expressionDownloadURLWithEid:emoji.eId];
data = [NSData dataWithContentsOfURL:TLURL(urlString)];
if (data == nil) {
urlString = [TLExpressionModel expressionURLWithEid:emoji.eId];
data = [NSData dataWithContentsOfURL:TLURL(urlString)];
}
emojiPath = [NSString stringWithFormat:@"%@%@", groupPath, emoji.eId];
}
[data writeToFile:emojiPath atomically:YES];
p += 1.0;
dispatch_async(dispatch_get_main_queue(), ^{
if (progress) {
progress(p / group.data.count);
}
});
});
}
dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^{
success(group);
});
}
- (void)updateExpressionGroupModelsStatus:(NSArray *)groupModelArray
{
for (TLExpressionGroupModel *group in groupModelArray) {
TLExpressionGroupModel *localEmojiGroup = [[TLExpressionHelper sharedHelper] emojiGroupByID:group.gId];
if (localEmojiGroup) {
group.status = TLExpressionGroupStatusLocal;
}
}
}
#pragma mark - # Getter
- (TLDBExpressionStore *)store
{
if (_store == nil) {
_store = [[TLDBExpressionStore alloc] init];
}
return _store;
}
- (TLExpressionGroupModel *)defaultFaceGroup
{
if (_defaultFaceGroup == nil) {
_defaultFaceGroup = [[TLExpressionGroupModel alloc] init];
_defaultFaceGroup.type = TLEmojiTypeFace;
_defaultFaceGroup.iconPath = @"emojiKB_group_face";
NSString *path = [[NSBundle mainBundle] pathForResource:@"FaceEmoji" ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
_defaultFaceGroup.data = [TLExpressionModel mj_objectArrayWithKeyValuesArray:data];
for (TLExpressionModel *emoji in _defaultFaceGroup.data) {
emoji.type = TLEmojiTypeFace;
}
}
return _defaultFaceGroup;
}
- (TLExpressionGroupModel *)defaultSystemEmojiGroup
{
if (_defaultSystemEmojiGroup == nil) {
_defaultSystemEmojiGroup = [[TLExpressionGroupModel alloc] init];
_defaultSystemEmojiGroup.type = TLEmojiTypeEmoji;
_defaultSystemEmojiGroup.iconPath = @"emojiKB_group_face";
NSString *path = [[NSBundle mainBundle] pathForResource:@"SystemEmoji" ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
_defaultSystemEmojiGroup.data = [TLExpressionModel mj_objectArrayWithKeyValuesArray:data];
}
return _defaultSystemEmojiGroup;
}
@end