| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- // Created by Tencent on 2023/07/20.
- // Copyright © 2023 Tencent. All rights reserved.
- #import "TUIMessageCellConfig.h"
- #import <TUICore/TUIThemeManager.h>
- #import <TIMCommon/TUIMessageCell.h>
- #import <TIMCommon/TUIMessageCellData.h>
- #import <TIMCommon/TUISystemMessageCell.h>
- #import <TIMCommon/TUISystemMessageCellData.h>
- #import "TUIMessageDataProvider.h"
- #import "TUIFaceMessageCell.h"
- #import "TUIFaceMessageCellData.h"
- #import "TUIFileMessageCell.h"
- #import "TUIFileMessageCellData.h"
- #import "TUIImageMessageCell.h"
- #import "TUIImageMessageCellData.h"
- #import "TUIJoinGroupMessageCell.h"
- #import "TUIJoinGroupMessageCellData.h"
- #import "TUIMergeMessageCell.h"
- #import "TUIMergeMessageCellData.h"
- #import "TUIReferenceMessageCell.h"
- #import "TUIReplyMessageCell.h"
- #import "TUIReplyMessageCellData.h"
- #import "TUITextMessageCell.h"
- #import "TUITextMessageCellData.h"
- #import "TUIVideoMessageCell.h"
- #import "TUIVideoMessageCellData.h"
- #import "TUIVoiceMessageCell.h"
- #import "TUIVoiceMessageCellData.h"
- #define kIsCustomMessageFromPlugin @"kIsCustomMessageFromPlugin"
- typedef Class<TUIMessageCellProtocol> CellClass;
- typedef NSString * MessageID;
- typedef NSNumber * HeightNumber;
- static NSMutableDictionary *gCustomMessageInfoMap = nil;
- @interface TUIMessageCellConfig ()
- @property(nonatomic, weak) UITableView *tableView;
- @property(nonatomic, strong) NSMutableDictionary<TUICellDataClassName, CellClass> *cellClassMaps;
- @property(nonatomic, strong) NSMutableDictionary<MessageID, HeightNumber> *heightCacheMaps;
- @end
- @implementation TUIMessageCellConfig (MessageCellWidth)
- + (void)setMaxTextSize:(CGSize)maxTextSz {
- [TUITextMessageCell setMaxTextSize:maxTextSz];
- }
- @end
- #pragma mark - Custom Message Register
- @implementation TUIMessageCellConfig (CustomMessageRegister)
- + (NSMutableDictionary *)getCustomMessageInfoMap {
- if (gCustomMessageInfoMap == nil) {
- gCustomMessageInfoMap = [NSMutableDictionary dictionary];
- }
- return gCustomMessageInfoMap;
- }
- + (void)registerBuiltInCustomMessageInfo {
- [self registerCustomMessageCell:@"TUILinkCell" messageCellData:@"TUILinkCellData" forBusinessID:BussinessID_TextLink];
- [self registerCustomMessageCell:@"TUIGroupCreatedCell" messageCellData:@"TUIGroupCreatedCellData" forBusinessID:BussinessID_GroupCreate];
- [self registerCustomMessageCell:@"TUIEvaluationCell" messageCellData:@"TUIEvaluationCellData" forBusinessID:BussinessID_Evaluation];
- [self registerCustomMessageCell:@"TUIOrderCell" messageCellData:@"TUIOrderCellData" forBusinessID:BussinessID_Order];
- [self registerCustomMessageCell:@"TUIMessageCell" messageCellData:@"TUITypingStatusCellData" forBusinessID:BussinessID_Typing];
- [self registerCustomMessageCell:@"TUISystemMessageCell" messageCellData:@"TUILocalTipsCellData" forBusinessID:@"local_tips"];
- }
- + (void)registerExternalCustomMessageInfo {
- // Insert your own custom message UI here, your businessID can not be same with built-in
- //
- // Example:
- // [self registerCustomMessageCell:#your message cell# messageCellData:#your message cell data# forBusinessID:#your id#];
- //
- // ...
-
- [self registerCustomMessageCell:@"MOSystemNormalCell" messageCellData:@"MOSystemNormalCellData" forBusinessID:@"MOSystemNormalCell"];
- [self registerCustomMessageCell:@"MOUserLinkCell" messageCellData:@"MOUserLinkCellData" forBusinessID:@"MOUserLinkCell"];
- [self registerCustomMessageCell:@"MOUserNotificationCell" messageCellData:@"MOUserNotificationCellData" forBusinessID:@"MOUserNotificationCell"];
- }
- + (void)registerCustomMessageCell:(TUICellClassName)messageCellName
- messageCellData:(TUICellDataClassName)messageCellDataName
- forBusinessID:(TUIBusinessID)businessID {
- [self registerCustomMessageCell:messageCellName messageCellData:messageCellDataName forBusinessID:businessID isPlugin:NO];
- }
- + (void)registerCustomMessageCell:(TUICellClassName)messageCellName
- messageCellData:(TUICellDataClassName)messageCellDataName
- forBusinessID:(TUIBusinessID)businessID
- isPlugin:(BOOL)isPlugin {
- NSAssert(messageCellName.length > 0, @"message cell name can not be nil");
- NSAssert(messageCellDataName.length > 0, @"message cell data name can not be nil");
- NSAssert(businessID.length > 0, @"businessID can not be nil");
- NSAssert([[self getCustomMessageInfoMap] objectForKey:businessID] == nil, @"businessID can not be same with the exists");
-
- NSMutableDictionary *info = [NSMutableDictionary dictionary];
- info[BussinessID] = businessID;
- info[TMessageCell_Name] = messageCellName;
- info[TMessageCell_Data_Name] = messageCellDataName;
- info[kIsCustomMessageFromPlugin] = @(isPlugin);
- [[self getCustomMessageInfoMap] setObject:info forKey:businessID];
- }
- + (void)enumerateCustomMessageInfo:(void(^)(NSString *messageCellName,
- NSString *messageCellDataName,
- NSString *businessID,
- BOOL isPlugin))callback {
- if (callback == nil) {
- return;
- }
- [[self getCustomMessageInfoMap] enumerateKeysAndObjectsUsingBlock:^(TUIBusinessID key, NSDictionary *info, BOOL * _Nonnull stop) {
- NSString *businessID = info[BussinessID];
- NSString *messageCellName = info[TMessageCell_Name];
- NSString *messageCellDataName = info[TMessageCell_Data_Name];
- NSNumber *isPlugin = info[kIsCustomMessageFromPlugin];
- if (businessID && messageCellName && messageCellDataName && isPlugin) {
- callback(messageCellName, messageCellDataName, businessID, isPlugin);
- }
- }];
- }
- + (nullable Class)getCustomMessageCellDataClass:(NSString *)businessID {
- NSDictionary *info = [[self getCustomMessageInfoMap] objectForKey:businessID];
- if (info == nil) {
- return nil;
- }
- NSString *messageCellDataName = info[TMessageCell_Data_Name];
- Class messageCellDataClass = NSClassFromString(messageCellDataName);
- return messageCellDataClass;
- }
- + (BOOL)isPluginCustomMessageCellData:(TUIMessageCellData *)data {
- __block BOOL flag = NO;
- [[self getCustomMessageInfoMap] enumerateKeysAndObjectsUsingBlock:^(TUIBusinessID key, NSDictionary *info, BOOL * _Nonnull stop) {
- NSString *businessID = info[BussinessID];
- NSNumber *isPlugin = info[kIsCustomMessageFromPlugin];
- if (businessID && isPlugin && isPlugin.boolValue && [data.reuseId isEqualToString:businessID]) {
- flag = YES;
- *stop = YES;
- }
- }];
- return flag;
- }
- @end
- #pragma mark - Cell Message cell height
- @implementation TUIMessageCellConfig (MessageCellHeight)
- - (NSString *)getHeightCacheKey:(TUIMessageCellData *)msg {
- return msg.msgID.length == 0 ? [NSString stringWithFormat:@"%p", msg] : msg.msgID;
- }
- - (CGFloat)getHeightFromMessageCellData:(TUIMessageCellData *)cellData {
- static CGFloat screenWidth = 0;
- if (screenWidth == 0) {
- screenWidth = Screen_Width;
- }
- NSString *key = [self getHeightCacheKey:cellData];
- CGFloat height = [[self.heightCacheMaps objectForKey:key] floatValue];
- if (height == 0) {
- CellClass cellClass = [self.cellClassMaps objectForKey:NSStringFromClass(cellData.class)];
- if ([cellClass respondsToSelector:@selector(getHeight:withWidth:)]) {
- height = [cellClass getHeight:cellData withWidth:screenWidth];
- [self.heightCacheMaps setObject:@(height) forKey:key];
- }
- }
- return height;
- }
- - (CGFloat)getEstimatedHeightFromMessageCellData:(TUIMessageCellData *)cellData {
- NSString *key = [self getHeightCacheKey:cellData];
- CGFloat height = [[self.heightCacheMaps objectForKey:key] floatValue];
- return height > 0 ? height : UITableViewAutomaticDimension;;
- }
- - (void)removeHeightCacheOfMessageCellData:(TUIMessageCellData *)cellData {
- NSString *key = [self getHeightCacheKey:cellData];
- [self.heightCacheMaps removeObjectForKey:key];
- }
- @end
- #pragma mark - TUIMessageTable
- @implementation TUIMessageCellConfig
- #pragma mark - Life Cycle
- + (void)load {
- [self registerBuiltInCustomMessageInfo];
- [self registerExternalCustomMessageInfo];
- }
- #pragma mark - UI
- - (void)bindTableView:(UITableView *)tableView {
- self.tableView = tableView;
-
- [self bindMessageCellClass:TUITextMessageCell.class cellDataClass:TUITextMessageCellData.class reuseID:TTextMessageCell_ReuseId];
- [self bindMessageCellClass:TUIVoiceMessageCell.class cellDataClass:TUIVoiceMessageCellData.class reuseID:TVoiceMessageCell_ReuseId];
- [self bindMessageCellClass:TUIImageMessageCell.class cellDataClass:TUIImageMessageCellData.class reuseID:TImageMessageCell_ReuseId];
- [self bindMessageCellClass:TUISystemMessageCell.class cellDataClass:TUISystemMessageCellData.class reuseID:TSystemMessageCell_ReuseId];
- [self bindMessageCellClass:TUIFaceMessageCell.class cellDataClass:TUIFaceMessageCellData.class reuseID:TFaceMessageCell_ReuseId];
- [self bindMessageCellClass:TUIVideoMessageCell.class cellDataClass:TUIVideoMessageCellData.class reuseID:TVideoMessageCell_ReuseId];
- [self bindMessageCellClass:TUIFileMessageCell.class cellDataClass:TUIFileMessageCellData.class reuseID:TFileMessageCell_ReuseId];
- [self bindMessageCellClass:TUIJoinGroupMessageCell.class cellDataClass:TUIJoinGroupMessageCellData.class reuseID:TJoinGroupMessageCell_ReuseId];
- [self bindMessageCellClass:TUIMergeMessageCell.class cellDataClass:TUIMergeMessageCellData.class reuseID:TMergeMessageCell_ReuserId];
- [self bindMessageCellClass:TUIReplyMessageCell.class cellDataClass:TUIReplyMessageCellData.class reuseID:TReplyMessageCell_ReuseId];
- [self bindMessageCellClass:TUIReferenceMessageCell.class cellDataClass:TUIReferenceMessageCellData.class reuseID:TUIReferenceMessageCell_ReuseId];
- __weak typeof(self) weakSelf = self;
- [self.class enumerateCustomMessageInfo:^(NSString * _Nonnull messageCellName,
- NSString * _Nonnull messageCellDataName,
- NSString * _Nonnull businessID,
- BOOL isPlugin) {
- Class cellClass = NSClassFromString(messageCellName);
- Class cellDataClass = NSClassFromString(messageCellDataName);
- [weakSelf bindMessageCellClass:cellClass cellDataClass:cellDataClass reuseID:businessID];
- }];
- }
- - (void)bindMessageCellClass:(Class)cellClass cellDataClass:(Class)cellDataClass reuseID:(NSString *)reuseID {
- NSAssert(cellClass != nil, @"The UITableViewCell can not be nil");
- NSAssert(cellDataClass != nil, @"The cell data class can not be nil");
- NSAssert(reuseID.length > 0, @"The reuse identifier can not be nil");
-
- [self.tableView registerClass:cellClass forCellReuseIdentifier:reuseID];
- [self.cellClassMaps setObject:cellClass forKey:NSStringFromClass(cellDataClass)];
- }
- #pragma mark - Lazy && Read-write operate
- - (NSMutableDictionary<TUICellDataClassName,CellClass> *)cellClassMaps {
- if (_cellClassMaps == nil) {
- _cellClassMaps = [NSMutableDictionary dictionary];
- }
- return _cellClassMaps;
- }
- - (NSMutableDictionary<MessageID,HeightNumber> *)heightCacheMaps {
- if (_heightCacheMaps == nil) {
- _heightCacheMaps = [NSMutableDictionary dictionary];
- }
- return _heightCacheMaps;
- }
- @end
|