This commit is contained in:
启星
2025-08-12 14:27:12 +08:00
parent 9d18b353b1
commit 1bd5e77c45
8785 changed files with 978163 additions and 2 deletions

View File

@@ -0,0 +1,35 @@
//
// TCommonFriendCellData.h
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/7.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <TIMCommon/TIMCommonModel.h>
NS_ASSUME_NONNULL_BEGIN
@class V2TIMFriendInfo;
@class V2TIMGroupInfo;
typedef NS_ENUM(NSInteger, TUIContactOnlineStatus) { TUIContactOnlineStatusUnknown = 0, TUIContactOnlineStatusOnline = 1, TUIContactOnlineStatusOffline = 2 };
@interface TUICommonContactCellData : TUICommonCellData
- (instancetype)initWithFriend:(V2TIMFriendInfo *)args;
- (instancetype)initWithGroupInfo:(V2TIMGroupInfo *)args;
@property V2TIMFriendInfo *friendProfile;
@property NSString *identifier;
@property NSURL *avatarUrl;
@property NSString *title;
@property UIImage *avatarImage;
// The flag of indicating the user's online status
@property(nonatomic, assign) TUIContactOnlineStatus onlineStatus;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,51 @@
//
// TCommonFriendCellData.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/7.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUICommonContactCellData.h"
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
@implementation TUICommonContactCellData {
V2TIMFriendInfo *_friendProfile;
}
- (instancetype)initWithFriend:(V2TIMFriendInfo *)args {
self = [super init];
if (args.friendRemark.length) {
_title = args.friendRemark;
} else {
_title = [args.userFullInfo showName];
}
_identifier = args.userID;
_avatarUrl = [NSURL URLWithString:args.userFullInfo.faceURL];
_friendProfile = args;
return self;
}
- (instancetype)initWithGroupInfo:(V2TIMGroupInfo *)args {
self = [super init];
_title = args.groupName;
_avatarImage = DefaultGroupAvatarImageByGroupType(args.groupType);
_avatarUrl = [NSURL URLWithString:args.faceURL];
_identifier = args.groupID;
return self;
}
- (NSComparisonResult)compare:(TUICommonContactCellData *)data {
return [self.title localizedCompare:data.title];
}
- (CGFloat)heightOfWidth:(CGFloat)width {
return 56;
}
@end

View File

@@ -0,0 +1,45 @@
//
// TCommonPendencyCellData.h
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/7.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <TIMCommon/TIMCommonModel.h>
@class V2TIMFriendApplication;
NS_ASSUME_NONNULL_BEGIN
@interface TUICommonPendencyCellData : TUICommonCellData
@property V2TIMFriendApplication *application;
@property NSString *identifier;
@property NSURL *avatarUrl;
@property NSString *title;
@property NSString *addSource;
@property NSString *addWording;
@property BOOL isAccepted;
@property BOOL isRejected;
@property SEL cbuttonSelector;
@property SEL cRejectButtonSelector;
@property BOOL hideSource;
- (instancetype)initWithPendency:(V2TIMFriendApplication *)application;
typedef void (^TUICommonPendencyCellDataSuccessCallback)(void);
typedef void (^TUICommonPendencyCellDataFailureCallback)(int code, NSString *msg);
- (void)agreeWithSuccess:(TUICommonPendencyCellDataSuccessCallback)success
failure:(TUICommonPendencyCellDataFailureCallback)failure;
- (void)rejectWithSuccess:(TUICommonPendencyCellDataSuccessCallback)success
failure:(TUICommonPendencyCellDataFailureCallback)failure;
- (void)agree;
- (void)reject;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,91 @@
//
// TCommonPendencyCellData.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/7.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUICommonPendencyCellData.h"
#import <TIMCommon/TIMCommonModel.h>
#import <TUICore/TUIGlobalization.h>
#import <TUICore/TUITool.h>
#import <TUICore/UIView+TUIToast.h>
@implementation TUICommonPendencyCellData
- (instancetype)initWithPendency:(V2TIMFriendApplication *)application {
self = [super init];
_identifier = application.userID;
if (application.nickName.length > 0) {
_title = application.nickName;
} else {
_title = _identifier;
}
if (application.addSource) {
_addSource = [NSString
stringWithFormat:TIMCommonLocalizableString(TUIKitAddFriendSourceFormat), [application.addSource substringFromIndex:@"AddSource_Type_".length]];
}
_addWording = application.addWording;
_avatarUrl = [NSURL URLWithString:application.faceUrl];
_isAccepted = NO;
_application = application;
_hideSource = NO;
return self;
}
- (BOOL)isEqual:(TUICommonPendencyCellData *)object {
return [self.identifier isEqual:object.identifier];
}
- (void)agree {
[self agreeWithSuccess:^{
//Success
} failure:^(int code, NSString * _Nonnull msg) {
//failure
}];
}
- (void)reject {
[self rejectWithSuccess:^{
//Success
} failure:^(int code, NSString * _Nonnull msg) {
//failure
}];
}
- (void)agreeWithSuccess:(TUICommonPendencyCellDataSuccessCallback)success failure:(TUICommonPendencyCellDataFailureCallback)failure {
[[V2TIMManager sharedInstance] acceptFriendApplication:_application
type:V2TIM_FRIEND_ACCEPT_AGREE_AND_ADD
succ:^(V2TIMFriendOperationResult *result) {
if (success) {
success();
}
[TUITool makeToast:TIMCommonLocalizableString(TUIKitFriendApplicationApproved)];
}
fail:^(int code, NSString *msg) {
[TUITool makeToastError:code msg:msg];
if (failure) {
failure(code,msg);
}
}];
}
- (void)rejectWithSuccess:(TUICommonPendencyCellDataSuccessCallback)success failure:(TUICommonPendencyCellDataFailureCallback)failure {
[[V2TIMManager sharedInstance] refuseFriendApplication:_application
succ:^(V2TIMFriendOperationResult *result) {
if (success) {
success();
}
[TUITool makeToast:TIMCommonLocalizableString(TUIKitFirendRequestRejected)];
}
fail:^(int code, NSString *msg) {
if (failure) {
failure(code,msg);
}
[TUITool makeToastError:code msg:msg];
}];
}
@end

View File

@@ -0,0 +1,22 @@
//
// TUIContactActionCellData.h
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/6/21.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <TIMCommon/TIMCommonModel.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUIContactActionCellData : TUICommonCellData
@property NSString *title;
@property UIImage *icon;
@property NSInteger readNum;
@property (nonatomic, copy, nullable) void (^onClicked)(NSDictionary * _Nullable param);
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,13 @@
//
// TUIContactActionCellData.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/6/21.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIContactActionCellData.h"
@implementation TUIContactActionCellData
@end

View File

@@ -0,0 +1,87 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
/**
* This document declares the modules used to implement the conversation unit data source
* The conversation unit data source (hereinafter referred to as the "data source") contains a series of information and data required for the display of the
* conversation unit, which will be described further below. The data source also contains some business logic, such as getting and generating message overview
* (subTitle), updating conversation information (group message or user message update) and other logic.
*/
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUIContactConversationCellData : TUICommonCellData
@property(nonatomic, strong) NSString *conversationID;
@property(nonatomic, strong) NSString *groupID;
@property(nonatomic, strong) NSString *groupType;
@property(nonatomic, strong) NSString *userID;
@property(nonatomic, strong) NSString *title;
@property(nonatomic, strong) NSString *faceUrl;
@property(nonatomic, strong) UIImage *avatarImage;
@property(nonatomic, strong) NSString *draftText;
@property(nonatomic, assign) int unreadCount;
/**
* Conversation Messages Overview (subtitle)
* The overview is responsible for displaying the content/type of the latest message for the corresponding conversation.
* When the latest message is a text message/system message, the content of the overview is the text content of the message.
* When the latest message is a multimedia message, the content of the overview is the name of the corresponding multimedia form, such as: "Animation
* Expression" / "[File]" / "[Voice]" / "[Picture]" / "[Video]", etc. . If there is a draft in the current conversation, the overview content is:
* "[Draft]XXXXX", where XXXXX is the draft content.
*/
@property(nonatomic, strong) NSMutableAttributedString *subTitle;
/**
* seq list of group@ messages
*/
@property(nonatomic, strong) NSMutableArray<NSNumber *> *atMsgSeqs;
/**
* Latest message time
* Save the receive/send time of the latest message in the conversation.
*/
@property(nonatomic, strong) NSDate *time;
/**
* The flag that whether the conversation is pinned to the top
*/
@property(nonatomic, assign) BOOL isOnTop;
/**
* Indicates whether to display the message checkbox
* In the conversation list, the message checkbox is not displayed by default.
* In the message forwarding scenario, the list cell is multiplexed to the select conversation page. When the "Multiple Choice" button is clicked, the
* conversation list becomes multi-selectable. YES: Multiple selection is enable, multiple selection views are displayed; NO: Multiple selection is disable, the
* default view is displayed
*/
@property(nonatomic, assign) BOOL showCheckBox;
/**
* Indicates whether the current message is selected, the default is NO
*/
@property(nonatomic, assign) BOOL selected;
/**
* Whether the current conversation is marked as do-not-disturb for new messages
*/
@property(nonatomic, assign) BOOL isNotDisturb;
/**
* key by which to sort the conversation list
*/
@property(nonatomic, assign) NSUInteger orderKey;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,30 @@
//
// TUIContactConversationCellData.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/16.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIContactConversationCellData.h"
@implementation TUIContactConversationCellData
@synthesize title;
@synthesize userID;
@synthesize groupID;
@synthesize groupType;
@synthesize avatarImage;
@synthesize conversationID;
@synthesize draftText;
@synthesize faceUrl;
- (CGFloat)heightOfWidth:(CGFloat)width {
return TConversationCell_Height;
}
- (BOOL)isEqual:(TUIContactConversationCellData *)object {
return [self.conversationID isEqual:object.conversationID];
}
@end

View File

@@ -0,0 +1,44 @@
//
// TUIFindContactCellModel.h
// TUIContact
//
// Created by harvy on 2021/12/13.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
@class V2TIMUserFullInfo;
@class V2TIMGroupInfo;
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, TUIFindContactType) {
TUIFindContactTypeC2C = 1,
TUIFindContactTypeGroup = 2,
};
@class TUIFindContactCellModel;
typedef void (^TUIFindContactOnCallback)(TUIFindContactCellModel *);
@interface TUIFindContactCellModel : NSObject
@property(nonatomic, assign) TUIFindContactType type;
@property(nonatomic, strong) UIImage *avatar;
@property(nonatomic, strong) NSURL *avatarUrl;
@property(nonatomic, copy) NSString *mainTitle;
@property(nonatomic, copy) NSString *subTitle;
@property(nonatomic, copy) NSString *desc;
/**
* c2c-> userID, group -> groupID
* If the conversation type is c2c, contactID represents userid; if the conversation type is group, contactID represents groupID
*/
@property(nonatomic, copy) NSString *contactID;
@property(nonatomic, strong) V2TIMUserFullInfo *userInfo;
@property(nonatomic, strong) V2TIMGroupInfo *groupInfo;
@property(nonatomic, copy) TUIFindContactOnCallback onClick;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,13 @@
//
// TUIFindContactCellModel.m
// TUIContact
//
// Created by harvy on 2021/12/13.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIFindContactCellModel.h"
@implementation TUIFindContactCellModel
@end

View File

@@ -0,0 +1,27 @@
//
// TUIMemberInfoCellData.h
// TUIGroup
//
// Created by harvy on 2021/12/27.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, TUIMemberInfoCellStyle) { TUIMemberInfoCellStyleNormal = 0, TUIMemberInfoCellStyleAdd = 1 };
@interface TUIMemberInfoCellData : NSObject
@property(nonatomic, copy) NSString *identifier;
@property(nonatomic, strong) UIImage *avatar;
@property(nonatomic, copy) NSString *avatarUrl;
@property(nonatomic, copy) NSString *name;
@property(nonatomic, assign) TUIMemberInfoCellStyle style;
@property(nonatomic, assign) NSInteger role;
@property(nonatomic, assign) BOOL showAccessory;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,13 @@
//
// TUIMemberInfoCellData.m
// TUIGroup
//
// Created by harvy on 2021/12/27.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIMemberInfoCellData.h"
@implementation TUIMemberInfoCellData
@end

View File

@@ -0,0 +1,29 @@
//
// TUICommonContactCell.h
//
//
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
#import <UIKit/UIKit.h>
#import "TUICommonContactCellData.h"
NS_ASSUME_NONNULL_BEGIN
@interface TUICommonContactCell : TUICommonTableViewCell
@property UIImageView *avatarView;
@property UILabel *titleLabel;
// The icon of indicating the user's online status
@property(nonatomic, strong) UIImageView *onlineStatusIcon;
@property(readonly) TUICommonContactCellData *contactData;
- (void)fillWithData:(TUICommonContactCellData *)contactData;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,114 @@
//
// TCommonContactCell.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/5.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUICommonContactCell.h"
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIThemeManager.h>
#import "TUICommonContactCellData.h"
#define kScale UIScreen.mainScreen.bounds.size.width / 375.0
@interface TUICommonContactCell ()
@property TUICommonContactCellData *contactData;
@end
@implementation TUICommonContactCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.contentView.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF");
self.avatarView = [[UIImageView alloc] initWithImage:DefaultAvatarImage];
[self.contentView addSubview:self.avatarView];
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[self.contentView addSubview:self.titleLabel];
self.titleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000");
self.onlineStatusIcon = [[UIImageView alloc] init];
[self.contentView addSubview:self.onlineStatusIcon];
[self setSelectionStyle:UITableViewCellSelectionStyleNone];
self.changeColorWhenTouched = YES;
}
return self;
}
- (void)fillWithData:(TUICommonContactCellData *)contactData {
[super fillWithData:contactData];
self.contactData = contactData;
self.titleLabel.text = contactData.title;
[self.avatarView sd_setImageWithURL:contactData.avatarUrl placeholderImage:contactData.avatarImage ?: DefaultAvatarImage];
@weakify(self);
[[RACObserve(TUIConfig.defaultConfig, displayOnlineStatusIcon) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(id _Nullable x) {
@strongify(self);
if (contactData.onlineStatus == TUIContactOnlineStatusOnline && TUIConfig.defaultConfig.displayOnlineStatusIcon) {
self.onlineStatusIcon.hidden = NO;
self.onlineStatusIcon.image = TIMCommonDynamicImage(@"icon_online_status", [UIImage imageNamed:TIMCommonImagePath(@"icon_online_status")]);
} else if (contactData.onlineStatus == TUIContactOnlineStatusOffline && TUIConfig.defaultConfig.displayOnlineStatusIcon) {
self.onlineStatusIcon.hidden = NO;
self.onlineStatusIcon.image = TIMCommonDynamicImage(@"icon_offline_status", [UIImage imageNamed:TIMCommonImagePath(@"icon_offline_status")]);
} else {
self.onlineStatusIcon.hidden = YES;
self.onlineStatusIcon.image = nil;
}
}];
// tell constraints they need updating
[self setNeedsUpdateConstraints];
// update constraints now so we can animate the change
[self updateConstraintsIfNeeded];
[self layoutIfNeeded];
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
[super updateConstraints];
CGFloat imgWidth = kScale390(34);
[self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(imgWidth);
make.centerY.mas_equalTo(self.contentView.mas_centerY);
make.leading.mas_equalTo(kScale390(12));
}];
if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) {
self.avatarView.layer.masksToBounds = YES;
self.avatarView.layer.cornerRadius = imgWidth / 2;
} else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) {
self.avatarView.layer.masksToBounds = YES;
self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius;
}
[self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.avatarView.mas_centerY);
make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12);
make.height.mas_equalTo(20);
make.trailing.mas_greaterThanOrEqualTo(self.contentView.mas_trailing);
}];
[self.onlineStatusIcon mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(kScale375(15));
make.trailing.mas_equalTo(self.avatarView.mas_trailing).mas_offset(kScale375(5));
make.bottom.mas_equalTo(self.avatarView.mas_bottom);
}];
self.onlineStatusIcon.layer.cornerRadius = 0.5 * kScale375(15);
}
@end

View File

@@ -0,0 +1,46 @@
//
// TUICommonContactProfileCardCell.m
//
//
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
#import <UIKit/UIKit.h>
@class TUICommonContactProfileCardCell;
@protocol TUIContactProfileCardDelegate <NSObject>
- (void)didTapOnAvatar:(TUICommonContactProfileCardCell *)cell;
@end
@interface TUICommonContactProfileCardCellData : TUICommonCellData
@property(nonatomic, strong) UIImage *avatarImage;
@property(nonatomic, strong) NSURL *avatarUrl;
@property(nonatomic, strong) NSString *name;
@property(nonatomic, strong) NSString *identifier;
@property(nonatomic, strong) NSString *signature;
@property(nonatomic, strong) UIImage *genderIconImage;
@property(nonatomic, strong) NSString *genderString;
@property BOOL showAccessory;
@property BOOL showSignature;
@end
@interface TUICommonContactProfileCardCell : TUICommonTableViewCell
@property(nonatomic, strong) UIImageView *avatar;
@property(nonatomic, strong) UILabel *name;
@property(nonatomic, strong) UILabel *identifier;
@property(nonatomic, strong) UILabel *signature;
@property(nonatomic, strong) UIImageView *genderIcon;
@property(nonatomic, strong) TUICommonContactProfileCardCellData *cardData;
@property(nonatomic, weak) id<TUIContactProfileCardDelegate> delegate;
- (void)fillWithData:(TUICommonContactProfileCardCellData *)data;
@end

View File

@@ -0,0 +1,213 @@
//
// TUIContactProfileCardCell.m
// UIKit
//
// Created by annidy on 2019/5/27.
// Copyright © 2019 Tencent. All rights reserved.
//
#import "TUICommonContactProfileCardCell.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIThemeManager.h>
@implementation TUICommonContactProfileCardCellData
- (instancetype)init {
self = [super init];
if (self) {
_avatarImage = DefaultAvatarImage;
if ([_genderString isEqualToString:TIMCommonLocalizableString(Male)]) {
_genderIconImage = TUIContactCommonBundleImage(@"male");
} else if ([_genderString isEqualToString:TIMCommonLocalizableString(Female)]) {
_genderIconImage = TUIContactCommonBundleImage(@"female");
} else {
_genderIconImage = nil;
}
}
return self;
}
- (CGFloat)heightOfWidth:(CGFloat)width {
return TPersonalCommonCell_Image_Size.height + 2 * TPersonalCommonCell_Margin + (self.showSignature ? 24 : 0);
}
@end
@implementation TUICommonContactProfileCardCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self setupViews];
}
return self;
}
- (void)setupViews {
CGSize headSize = TPersonalCommonCell_Image_Size;
_avatar = [[UIImageView alloc] initWithFrame:CGRectMake(TPersonalCommonCell_Margin, TPersonalCommonCell_Margin, headSize.width, headSize.height)];
_avatar.contentMode = UIViewContentModeScaleAspectFit;
_avatar.layer.cornerRadius = 4;
_avatar.layer.masksToBounds = YES;
UITapGestureRecognizer *tapAvatar = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapAvatar)];
[_avatar addGestureRecognizer:tapAvatar];
_avatar.userInteractionEnabled = YES;
[self.contentView addSubview:_avatar];
// CGSize genderIconSize = CGSizeMake(20, 20);
_genderIcon = [[UIImageView alloc] init];
_genderIcon.contentMode = UIViewContentModeScaleAspectFit;
_genderIcon.image = self.cardData.genderIconImage;
[self.contentView addSubview:_genderIcon];
_name = [[UILabel alloc] init];
[_name setFont:[UIFont boldSystemFontOfSize:18]];
[_name setTextColor:TIMCommonDynamicColor(@"form_title_color", @"#000000")];
[self.contentView addSubview:_name];
_identifier = [[UILabel alloc] init];
[_identifier setFont:[UIFont systemFontOfSize:13]];
[_identifier setTextColor:TIMCommonDynamicColor(@"form_subtitle_color", @"#888888")];
[self.contentView addSubview:_identifier];
_signature = [[UILabel alloc] init];
[_signature setFont:[UIFont systemFontOfSize:14]];
[_signature setTextColor:TIMCommonDynamicColor(@"form_subtitle_color", @"#888888")];
[self.contentView addSubview:_signature];
self.selectionStyle = UITableViewCellSelectionStyleNone;
}
- (void)fillWithData:(TUICommonContactProfileCardCellData *)data {
[super fillWithData:data];
self.cardData = data;
_signature.hidden = !data.showSignature;
// set data
@weakify(self);
RAC(_signature, text) = [RACObserve(data, signature) takeUntil:self.rac_prepareForReuseSignal];
[[[RACObserve(data, identifier) takeUntil:self.rac_prepareForReuseSignal] distinctUntilChanged] subscribeNext:^(NSString *x) {
@strongify(self);
self.identifier.text = [@"ID: " stringByAppendingString:data.identifier];
}];
[[[RACObserve(data, name) takeUntil:self.rac_prepareForReuseSignal] distinctUntilChanged] subscribeNext:^(NSString *x) {
@strongify(self);
self.name.text = x;
}];
[[RACObserve(data, avatarUrl) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(NSURL *x) {
@strongify(self);
[self.avatar sd_setImageWithURL:x placeholderImage:self.cardData.avatarImage];
}];
[[RACObserve(data, genderString) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(NSString *x) {
@strongify(self);
if ([x isEqualToString:TIMCommonLocalizableString(Male)]) {
self.genderIcon.image = TUIContactCommonBundleImage(@"male");
} else if ([x isEqualToString:TIMCommonLocalizableString(Female)]) {
self.genderIcon.image = TUIContactCommonBundleImage(@"female");
} else {
self.genderIcon.image = nil;
}
}];
if (data.showAccessory) {
self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else {
self.accessoryType = UITableViewCellAccessoryNone;
}
// tell constraints they need updating
[self setNeedsUpdateConstraints];
// update constraints now so we can animate the change
[self updateConstraintsIfNeeded];
[self layoutIfNeeded];
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
[super updateConstraints];
CGSize headSize = TPersonalCommonCell_Image_Size;
[self.avatar mas_remakeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(headSize);
make.top.mas_equalTo(TPersonalCommonCell_Margin);
make.leading.mas_equalTo(TPersonalCommonCell_Margin);
}];
if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) {
self.avatar.layer.masksToBounds = YES;
self.avatar.layer.cornerRadius = headSize.height / 2;
} else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) {
self.avatar.layer.masksToBounds = YES;
self.avatar.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius;
}
[self.name sizeToFit];
[self.name mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(TPersonalCommonCell_Margin);
make.leading.mas_equalTo(self.avatar.mas_trailing).mas_offset(15);
make.width.mas_lessThanOrEqualTo(self.name.frame.size.width);
make.height.mas_greaterThanOrEqualTo(self.name.frame.size.height);
make.trailing.mas_lessThanOrEqualTo(self.genderIcon.mas_leading).mas_offset(- 1);
}];
[self.genderIcon mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(self.name.font.pointSize *0.9);
make.centerY.mas_equalTo(self.name);
make.leading.mas_equalTo(self.name.mas_trailing).mas_offset(1);
make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- 10);
}];
[self.identifier sizeToFit];
[self.identifier mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.name);
make.top.mas_equalTo(self.name.mas_bottom).mas_offset(5);
if(self.identifier.frame.size.width > 80) {
make.width.mas_greaterThanOrEqualTo(self.identifier.frame.size.width);
}
else {
make.width.mas_greaterThanOrEqualTo(@80);
}
make.height.mas_greaterThanOrEqualTo(self.identifier.frame.size.height);
make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(-1);
}];
if (self.cardData.showSignature) {
[self.signature sizeToFit];
[self.signature mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.name);
make.top.mas_equalTo(self.identifier.mas_bottom).mas_offset(5);
if(self.signature.frame.size.width > 80) {
make.width.mas_greaterThanOrEqualTo(self.signature.frame.size.width);
}
else {
make.width.mas_greaterThanOrEqualTo(@80);
}
make.height.mas_greaterThanOrEqualTo(self.signature.frame.size.height);
make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(-1);
}];
} else {
self.signature.frame = CGRectZero;
}
}
- (void)layoutSubviews {
[super layoutSubviews];
}
- (void)onTapAvatar {
if (_delegate && [_delegate respondsToSelector:@selector(didTapOnAvatar:)]) [_delegate didTapOnAvatar:self];
}
@end

View File

@@ -0,0 +1,25 @@
//
// TUICommonContactSelectCell.h
//
//
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUICommonContactSelectCell : TUICommonTableViewCell
@property UIButton *selectButton;
@property UIImageView *avatarView;
@property UILabel *titleLabel;
@property(readonly) TUICommonContactSelectCellData *selectData;
- (void)fillWithData:(TUICommonContactSelectCellData *)selectData;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,120 @@
//
// TUICommonContactSelectCell.m
//
//
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import "TUICommonContactSelectCell.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIThemeManager.h>
@interface TUICommonContactSelectCell ()
@property TUICommonContactSelectCellData *selectData;
@end
@implementation TUICommonContactSelectCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.selectButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.contentView addSubview:self.selectButton];
[self.selectButton setImage:[UIImage imageNamed:TIMCommonImagePath(@"icon_select_normal")] forState:UIControlStateNormal];
[self.selectButton setImage:[UIImage imageNamed:TIMCommonImagePath(@"icon_select_pressed")] forState:UIControlStateHighlighted];
[self.selectButton setImage:[UIImage imageNamed:TIMCommonImagePath(@"icon_select_selected")] forState:UIControlStateSelected];
[self.selectButton setImage:[UIImage imageNamed:TIMCommonImagePath(@"icon_select_selected_disable")] forState:UIControlStateDisabled];
self.selectButton.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
self.avatarView = [[UIImageView alloc] initWithImage:DefaultAvatarImage];
[self.contentView addSubview:self.avatarView];
self.avatarView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[self.contentView addSubview:self.titleLabel];
self.titleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000");
self.titleLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
self.selectionStyle = UITableViewCellSelectionStyleNone;
}
return self;
}
- (void)fillWithData:(TUICommonContactSelectCellData *)selectData {
[super fillWithData:selectData];
self.selectData = selectData;
self.titleLabel.text = selectData.title;
if (selectData.avatarUrl) {
[self.avatarView sd_setImageWithURL:selectData.avatarUrl placeholderImage:DefaultAvatarImage];
} else if (selectData.avatarImage) {
[self.avatarView setImage:selectData.avatarImage];
} else {
[self.avatarView setImage:DefaultAvatarImage];
}
if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) {
self.avatarView.layer.masksToBounds = YES;
self.avatarView.layer.cornerRadius = self.avatarView.frame.size.height / 2;
} else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) {
self.avatarView.layer.masksToBounds = YES;
self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius;
}
[self.selectButton setSelected:selectData.isSelected];
self.selectButton.enabled = selectData.enabled;
// tell constraints they need updating
[self setNeedsUpdateConstraints];
// update constraints now so we can animate the change
[self updateConstraintsIfNeeded];
[self layoutIfNeeded];
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
[super updateConstraints];
CGFloat imgWidth = kScale390(34);
[self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(imgWidth);
make.centerY.mas_equalTo(self.contentView.mas_centerY);
make.leading.mas_equalTo(kScale390(12));
}];
if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) {
self.avatarView.layer.masksToBounds = YES;
self.avatarView.layer.cornerRadius = imgWidth / 2;
} else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) {
self.avatarView.layer.masksToBounds = YES;
self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius;
}
[self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.avatarView.mas_centerY);
make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12);
make.height.mas_equalTo(20);
make.trailing.mas_greaterThanOrEqualTo(self.contentView.mas_trailing);
}];
[self.selectButton mas_remakeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.contentView.mas_centerY);
make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-kScale390(20));
make.width.height.mas_equalTo(20);
}];
}
@end

View File

@@ -0,0 +1,37 @@
//
// TUIContactCommonSwitchCell.h
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/10.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUICommonContactSwitchCellData : TUICommonCellData
@property NSString *title;
@property NSString *desc;
@property(getter=isOn) BOOL on;
@property CGFloat margin;
@property SEL cswitchSelector;
@end
@interface TUICommonContactSwitchCell : TUICommonTableViewCell
@property UILabel *titleLabel; // main title label
@property UILabel *descLabel; // detail title label below the main title label, used for explaining details
@property UISwitch *switcher;
@property(readonly) TUICommonContactSwitchCellData *switchData;
- (void)fillWithData:(TUICommonContactSwitchCellData *)data;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,141 @@
//
// TUIContactCommonSwitchCell.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/10.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUICommonContactSwitchCell.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIThemeManager.h>
@implementation TUICommonContactSwitchCellData
- (instancetype)init {
self = [super init];
_margin = 20;
return self;
}
- (CGFloat)heightOfWidth:(CGFloat)width {
CGFloat height = [super heightOfWidth:width];
if (self.desc.length > 0) {
NSString *str = self.desc;
NSDictionary *attribute = @{NSFontAttributeName : [UIFont systemFontOfSize:12]};
CGSize size = [str boundingRectWithSize:CGSizeMake(264, 999)
options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:attribute
context:nil]
.size;
height += size.height + 10;
}
return height;
}
@end
@interface TUICommonContactSwitchCell ()
@property TUICommonContactSwitchCellData *switchData;
@end
@implementation TUICommonContactSwitchCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
_titleLabel = [[UILabel alloc] init];
_titleLabel.textColor = TIMCommonDynamicColor(@"form_key_text_color", @"#444444");
_titleLabel.font = [UIFont systemFontOfSize:16];
_titleLabel.rtlAlignment = TUITextRTLAlignmentLeading;
[self.contentView addSubview:_titleLabel];
_descLabel = [[UILabel alloc] init];
_descLabel.textColor = TIMCommonDynamicColor(@"group_modify_desc_color", @"#888888");
_descLabel.font = [UIFont systemFontOfSize:12];
_descLabel.numberOfLines = 0;
_descLabel.rtlAlignment = TUITextRTLAlignmentLeading;
_descLabel.hidden = YES;
[self.contentView addSubview:_descLabel];
_switcher = [[UISwitch alloc] init];
// Change the color when the switch is on to blue
_switcher.onTintColor = TIMCommonDynamicColor(@"common_switch_on_color", @"#147AFF");
self.accessoryView = _switcher;
[self.contentView addSubview:_switcher];
[_switcher addTarget:self action:@selector(switchClick) forControlEvents:UIControlEventValueChanged];
self.selectionStyle = UITableViewCellSelectionStyleNone;
}
return self;
}
- (void)fillWithData:(TUICommonContactSwitchCellData *)switchData {
[super fillWithData:switchData];
self.switchData = switchData;
_titleLabel.text = switchData.title;
[_switcher setOn:switchData.isOn];
// tell constraints they need updating
[self setNeedsUpdateConstraints];
// update constraints now so we can animate the change
[self updateConstraintsIfNeeded];
[self layoutIfNeeded];
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
[super updateConstraints];
if (self.switchData.desc.length > 0) {
_descLabel.text = self.switchData.desc;
_descLabel.hidden = NO;
NSString *str = self.switchData.desc;
NSDictionary *attribute = @{NSFontAttributeName : [UIFont systemFontOfSize:12]};
CGSize size = [str boundingRectWithSize:CGSizeMake(264, 999)
options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:attribute
context:nil]
.size;
[self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(size.width);
make.height.mas_equalTo(24);
make.leading.mas_equalTo(self.switchData.margin);
make.top.mas_equalTo(12);
}];
[self.descLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(size.width);
make.height.mas_equalTo(size.height);
make.leading.mas_equalTo(self.titleLabel.mas_leading);
make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(2);
}];
} else {
[self.titleLabel sizeToFit];
[self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(self.titleLabel.frame.size);
make.leading.mas_equalTo(self.switchData.margin);
make.centerY.mas_equalTo(self.contentView);
}];
}
}
- (void)switchClick {
if (self.switchData.cswitchSelector) {
UIViewController *vc = self.mm_viewController;
if ([vc respondsToSelector:self.switchData.cswitchSelector]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[vc performSelector:self.switchData.cswitchSelector withObject:self];
#pragma clang diagnostic pop
}
}
}
@end

View File

@@ -0,0 +1,42 @@
//
// TUIContactCommonTextCell.h
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/5.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUICommonContactTextCellData : TUICommonCellData
@property NSString *key;
@property NSString *value;
@property BOOL showAccessory;
@property UIColor *keyColor;
@property UIColor *valueColor;
/**
* valueLabel
* Allow valueLabel to be displayed on multiple lines
*/
@property BOOL enableMultiLineValue;
@property(nonatomic, assign) UIEdgeInsets keyEdgeInsets;
@end
@interface TUICommonContactTextCell : TUICommonTableViewCell
@property UILabel *keyLabel;
@property UILabel *valueLabel;
@property(readonly) TUICommonContactTextCellData *textData;
- (void)fillWithData:(TUICommonContactTextCellData *)data;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,132 @@
//
// TUIContactCommonTextCell.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/5.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUICommonContactTextCell.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIThemeManager.h>
@implementation TUICommonContactTextCellData
- (instancetype)init {
self = [super init];
self.keyEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0);
return self;
}
- (CGFloat)heightOfWidth:(CGFloat)width {
CGFloat height = [super heightOfWidth:width];
if (self.enableMultiLineValue) {
NSString *str = self.value;
NSDictionary *attribute = @{NSFontAttributeName : [UIFont systemFontOfSize:16]};
CGSize size = [str boundingRectWithSize:CGSizeMake(280, 999)
options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:attribute
context:nil]
.size;
height = size.height + 30;
}
return height;
}
@end
@interface TUICommonContactTextCell ()
@property TUICommonContactTextCellData *textData;
@end
@implementation TUICommonContactTextCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier]) {
self.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF");
self.contentView.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF");
_keyLabel = [[UILabel alloc] init];
_keyLabel.textColor = TIMCommonDynamicColor(@"form_key_text_color", @"#444444");
_keyLabel.font = [UIFont systemFontOfSize:16.0];
[self.contentView addSubview:_keyLabel];
[_keyLabel setRtlAlignment:TUITextRTLAlignmentTrailing];
_valueLabel = [[UILabel alloc] init];
[self.contentView addSubview:_valueLabel];
_valueLabel.textColor = TIMCommonDynamicColor(@"form_value_text_color", @"#000000");
_valueLabel.font = [UIFont systemFontOfSize:16.0];
[_valueLabel setRtlAlignment:TUITextRTLAlignmentTrailing];
self.selectionStyle = UITableViewCellSelectionStyleNone;
}
return self;
}
- (void)fillWithData:(TUICommonContactTextCellData *)textData {
[super fillWithData:textData];
self.textData = textData;
RAC(_keyLabel, text) = [RACObserve(textData, key) takeUntil:self.rac_prepareForReuseSignal];
RAC(_valueLabel, text) = [RACObserve(textData, value) takeUntil:self.rac_prepareForReuseSignal];
if (textData.showAccessory) {
self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else {
self.accessoryType = UITableViewCellAccessoryNone;
}
if (self.textData.keyColor) {
self.keyLabel.textColor = self.textData.keyColor;
}
if (self.textData.valueColor) {
self.valueLabel.textColor = self.textData.valueColor;
}
if (self.textData.enableMultiLineValue) {
self.valueLabel.numberOfLines = 0;
} else {
self.valueLabel.numberOfLines = 1;
}
// tell constraints they need updating
[self setNeedsUpdateConstraints];
// update constraints now so we can animate the change
[self updateConstraintsIfNeeded];
[self layoutIfNeeded];
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
[super updateConstraints];
[self.keyLabel sizeToFit];
[self.keyLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(self.keyLabel.frame.size);
make.leading.mas_equalTo(self.contentView).mas_offset(self.textData.keyEdgeInsets.left);
make.centerY.mas_equalTo(self.contentView);
}];
[self.valueLabel sizeToFit];
[self.valueLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.keyLabel.mas_trailing).mas_offset(10);
if (self.textData.showAccessory) {
make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10);
}
else {
make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-20);
}
make.centerY.mas_equalTo(self.contentView);
}];
}
@end

View File

@@ -0,0 +1,31 @@
//
// TCommonPendencyCell.h
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/7.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
#import "TUICommonPendencyCellData.h"
NS_ASSUME_NONNULL_BEGIN
@interface TUICommonPendencyCell : TUICommonTableViewCell
@property UIImageView *avatarView;
@property UILabel *titleLabel;
@property UILabel *addSourceLabel;
@property UILabel *addWordingLabel;
@property UIButton *agreeButton;
@property UIButton *rejectButton;
@property UIStackView *stackView;
@property(nonatomic) TUICommonPendencyCellData *pendencyData;
- (void)fillWithData:(TUICommonPendencyCellData *)pendencyData;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,216 @@
//
// TCommonPendencyCell.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/7.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUICommonPendencyCell.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIThemeManager.h>
@implementation TUICommonPendencyCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
self.avatarView = [[UIImageView alloc] initWithImage:DefaultAvatarImage];
[self.contentView addSubview:self.avatarView];
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[self.contentView addSubview:self.titleLabel];
self.titleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000");
self.addSourceLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[self.contentView addSubview:self.addSourceLabel];
self.addSourceLabel.textColor = [UIColor d_systemGrayColor];
self.addSourceLabel.font = [UIFont systemFontOfSize:15];
self.addWordingLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[self.contentView addSubview:self.addWordingLabel];
self.addWordingLabel.textColor = [UIColor d_systemGrayColor];
self.addWordingLabel.font = [UIFont systemFontOfSize:15];
self.agreeButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.agreeButton setTitleColor:TIMCommonDynamicColor(@"form_title_color", @"#000000") forState:UIControlStateNormal];
[self.agreeButton addTarget:self action:@selector(agreeClick) forControlEvents:UIControlEventTouchUpInside];
self.rejectButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.rejectButton setTitleColor:TIMCommonDynamicColor(@"form_title_color", @"#000000") forState:UIControlStateNormal];
[self.rejectButton addTarget:self action:@selector(rejectClick) forControlEvents:UIControlEventTouchUpInside];
UIStackView *stackView = [[UIStackView alloc] init];
[stackView addSubview:self.agreeButton];
[stackView addSubview:self.rejectButton];
stackView.axis = UILayoutConstraintAxisHorizontal;
stackView.alignment = UIStackViewAlignmentCenter;
[stackView sizeToFit];
self.stackView = stackView;
self.accessoryView = stackView;
}
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)fillWithData:(TUICommonPendencyCellData *)pendencyData {
[super fillWithData:pendencyData];
self.pendencyData = pendencyData;
self.titleLabel.text = pendencyData.title;
self.addSourceLabel.text = pendencyData.addSource;
self.addWordingLabel.text = pendencyData.addWording;
self.avatarView.image = DefaultAvatarImage;
if (pendencyData.avatarUrl) {
[self.avatarView sd_setImageWithURL:pendencyData.avatarUrl];
}
if (pendencyData.isAccepted) {
[self.agreeButton setTitle:TIMCommonLocalizableString(Agreed) forState:UIControlStateNormal];
self.agreeButton.enabled = NO;
self.agreeButton.layer.borderColor = [UIColor clearColor].CGColor;
[self.agreeButton setTitleColor:TIMCommonDynamicColor(@"form_title_color", @"#000000") forState:UIControlStateNormal];
self.agreeButton.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF");
} else {
[self.agreeButton setTitle:TIMCommonLocalizableString(Agree) forState:UIControlStateNormal];
self.agreeButton.enabled = YES;
self.agreeButton.layer.borderColor = [UIColor clearColor].CGColor;
self.agreeButton.layer.borderWidth = 1;
[self.agreeButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
self.agreeButton.backgroundColor = TIMCommonDynamicColor(@"primary_theme_color", @"#147AFF");
}
if (pendencyData.isRejected) {
[self.rejectButton setTitle:TIMCommonLocalizableString(Disclined) forState:UIControlStateNormal];
self.rejectButton.enabled = NO;
self.rejectButton.layer.borderColor = [UIColor clearColor].CGColor;
[self.rejectButton setTitleColor:TIMCommonDynamicColor(@"form_title_color", @"#000000") forState:UIControlStateNormal];
} else {
[self.rejectButton setTitle:TIMCommonLocalizableString(Discline) forState:UIControlStateNormal];
self.rejectButton.enabled = YES;
self.rejectButton.layer.borderColor = TUIDemoDynamicColor(@"separator_color", @"#DBDBDB").CGColor;
self.rejectButton.layer.borderWidth = 0.2;
[self.rejectButton setTitleColor:TIMCommonDynamicColor(@"primary_theme_color", @"#147AFF") forState:UIControlStateNormal];
}
if (self.pendencyData.isRejected && !self.pendencyData.isAccepted) {
self.agreeButton.hidden = YES;
self.rejectButton.hidden = NO;
} else if (self.pendencyData.isAccepted && !self.pendencyData.isRejected) {
self.agreeButton.hidden = NO;
self.rejectButton.hidden = YES;
} else {
self.agreeButton.hidden = NO;
self.rejectButton.hidden = NO;
}
self.addSourceLabel.hidden = self.pendencyData.hideSource;
// tell constraints they need updating
[self setNeedsUpdateConstraints];
// update constraints now so we can animate the change
[self updateConstraintsIfNeeded];
[self layoutIfNeeded];
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
[super updateConstraints];
CGSize headSize = CGSizeMake(70, 70);
[self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(headSize);
make.leading.mas_equalTo(12);
make.centerY.mas_equalTo(self.contentView);
}];
if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) {
self.avatarView.layer.masksToBounds = YES;
self.avatarView.layer.cornerRadius = headSize.height / 2;
} else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) {
self.avatarView.layer.masksToBounds = YES;
self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius;
}
[self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.contentView.mas_top).mas_offset(14);
make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12);
make.height.mas_equalTo(20);
make.width.mas_equalTo(120);
}];
[self.addSourceLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(6);
make.leading.mas_equalTo(self.titleLabel.mas_leading);
make.height.mas_equalTo(15);
make.width.mas_equalTo(120);
}];
[self.addWordingLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.addSourceLabel.mas_bottom).mas_offset(6);
make.leading.mas_equalTo(self.titleLabel.mas_leading);
make.height.mas_equalTo(15);
make.width.mas_equalTo(120);
}];
[self.agreeButton sizeToFit];
[self.agreeButton mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.stackView.mas_leading);
make.centerY.mas_equalTo(self.stackView);
make.height.mas_equalTo(self.agreeButton.frame.size.height);
make.width.mas_equalTo(self.agreeButton.frame.size.width + 20);
}];
[self.rejectButton sizeToFit];
[self.rejectButton mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.agreeButton.mas_trailing).mas_offset(10);
make.height.mas_equalTo(self.rejectButton.frame.size.height);
make.width.mas_equalTo(self.rejectButton.frame.size.width + 20);
}];
self.stackView.bounds = CGRectMake(0, 0, 3 * self.agreeButton.mm_w + 10, self.agreeButton.mm_h);
}
- (void)agreeClick {
if (self.pendencyData.cbuttonSelector) {
UIViewController *vc = self.mm_viewController;
if ([vc respondsToSelector:self.pendencyData.cbuttonSelector]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[vc performSelector:self.pendencyData.cbuttonSelector withObject:self];
#pragma clang diagnostic pop
}
}
}
- (void)rejectClick {
if (self.pendencyData.cRejectButtonSelector) {
UIViewController *vc = self.mm_viewController;
if ([vc respondsToSelector:self.pendencyData.cRejectButtonSelector]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[vc performSelector:self.pendencyData.cRejectButtonSelector withObject:self];
#pragma clang diagnostic pop
}
}
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ((touch.view == self.agreeButton)) {
return NO;
} else if (touch.view == self.rejectButton) {
return NO;
}
return YES;
}
@end

View File

@@ -0,0 +1,28 @@
//
// TUIContactActionCell.h
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/6/21.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
#import <UIKit/UIKit.h>
#import "TUIContactActionCellData.h"
NS_ASSUME_NONNULL_BEGIN
@interface TUIContactActionCell : TUICommonTableViewCell
@property UIImageView *avatarView;
@property UILabel *titleLabel;
@property TUIUnReadView *unRead;
@property(readonly) TUIContactActionCellData *actionData;
- (void)fillWithData:(TUIContactActionCellData *)contactData;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,107 @@
//
// TUIContactActionCell.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/6/21.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIContactActionCell.h"
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIThemeManager.h>
#import "TUICommonContactCellData.h"
@interface TUIContactActionCell ()
@property TUIContactActionCellData *actionData;
@end
@implementation TUIContactActionCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.avatarView = [[UIImageView alloc] initWithImage:DefaultAvatarImage];
[self.contentView addSubview:self.avatarView];
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[self.contentView addSubview:self.titleLabel];
self.titleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000");
self.unRead = [[TUIUnReadView alloc] init];
[self.contentView addSubview:self.unRead];
[self setSelectionStyle:UITableViewCellSelectionStyleNone];
//[self setSelectionStyle:UITableViewCellSelectionStyleDefault];
self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return self;
}
- (void)fillWithData:(TUIContactActionCellData *)actionData {
[super fillWithData:actionData];
self.actionData = actionData;
self.titleLabel.text = actionData.title;
if (actionData.icon) {
[self.avatarView setImage:actionData.icon];
}
@weakify(self);
[[RACObserve(self.actionData, readNum) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(NSNumber *x) {
@strongify(self);
[self.unRead setNum:[x integerValue]];
}];
// tell constraints they need updating
[self setNeedsUpdateConstraints];
// update constraints now so we can animate the change
[self updateConstraintsIfNeeded];
[self layoutIfNeeded];
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
[super updateConstraints];
CGFloat imgWidth = kScale390(34);
[self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(imgWidth);
make.centerY.mas_equalTo(self.contentView.mas_centerY);
make.leading.mas_equalTo(kScale390(12));
}];
if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) {
self.avatarView.layer.masksToBounds = YES;
self.avatarView.layer.cornerRadius = imgWidth / 2;
} else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) {
self.avatarView.layer.masksToBounds = YES;
self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius;
}
[self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.avatarView.mas_centerY);
make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12);
make.height.mas_equalTo(20);
make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing);
}];
[self.unRead.unReadLabel sizeToFit];
[self.unRead mas_remakeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.avatarView.mas_centerY);
make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-5);
make.width.mas_equalTo(kScale375(20));
make.height.mas_equalTo(kScale375(20));
}];
[self.unRead.unReadLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(self.unRead);
make.size.mas_equalTo(self.unRead.unReadLabel);
}];
self.unRead.layer.cornerRadius = kScale375(10);
[self.unRead.layer masksToBounds];
}
@end

View File

@@ -0,0 +1,25 @@
//
// TUIFindContactCell.h
// TUIContact
//
// Created by harvy on 2021/12/13.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "TUIFindContactCellModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface TUIFindContactCell : UITableViewCell
@property(nonatomic, strong) UIImageView *avatarView;
@property(nonatomic, strong) UILabel *mainTitleLabel;
@property(nonatomic, strong) UILabel *subTitleLabel;
@property(nonatomic, strong) UILabel *descLabel;
@property(nonatomic, strong) TUIFindContactCellModel *data;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,138 @@
//
// TUIFindContactCell.m
// TUIContact
//
// Created by harvy on 2021/12/13.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIFindContactCell.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIThemeManager.h>
#import <TUICore/UIView+TUILayout.h>
#define kScale UIScreen.mainScreen.bounds.size.width / 375.0
@implementation TUIFindContactCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
[self setupView];
}
return self;
}
- (void)setupView {
[self.contentView addSubview:self.avatarView];
[self.contentView addSubview:self.mainTitleLabel];
[self.contentView addSubview:self.subTitleLabel];
[self.contentView addSubview:self.descLabel];
}
- (void)setData:(TUIFindContactCellModel *)data {
_data = data;
self.mainTitleLabel.text = data.mainTitle;
self.subTitleLabel.text = data.subTitle;
self.descLabel.text = data.desc;
UIImage *placeHolder = (data.type == TUIFindContactTypeC2C) ? DefaultAvatarImage : DefaultGroupAvatarImageByGroupType(data.groupInfo.groupType);
[self.avatarView sd_setImageWithURL:data.avatarUrl placeholderImage:data.avatar ?: placeHolder];
self.descLabel.hidden = (data.type == TUIFindContactTypeC2C);
// tell constraints they need updating
[self setNeedsUpdateConstraints];
// update constraints now so we can animate the change
[self updateConstraintsIfNeeded];
[self layoutIfNeeded];
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
[super updateConstraints];
CGFloat imgWidth = kScale390(48);
[self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(imgWidth);
make.top.mas_equalTo(kScale390(10));
make.leading.mas_equalTo(kScale390(16));
}];
if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) {
self.avatarView.layer.masksToBounds = YES;
self.avatarView.layer.cornerRadius = imgWidth / 2;
} else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) {
self.avatarView.layer.masksToBounds = YES;
self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius;
}
[self.mainTitleLabel sizeToFit];
[self.mainTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.avatarView.mas_top);
make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12);
make.height.mas_equalTo(20);
make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- kScale390(12));
}];
[self.subTitleLabel sizeToFit];
[self.subTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.mainTitleLabel.mas_bottom).mas_offset(2);
make.leading.mas_equalTo(self.mainTitleLabel.mas_leading);
make.height.mas_equalTo(self.subTitleLabel.frame.size.height);
make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- kScale390(12));
}];
[self.descLabel sizeToFit];
[self.descLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.subTitleLabel.mas_bottom).mas_offset(2);
make.leading.mas_equalTo(self.mainTitleLabel.mas_leading);
make.height.mas_equalTo(self.subTitleLabel.frame.size.height);
make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- kScale390(12));
}];
}
- (void)layoutSubviews {
[super layoutSubviews];
}
- (UIImageView *)avatarView {
if (_avatarView == nil) {
_avatarView = [[UIImageView alloc] init];
_avatarView.layer.cornerRadius = 3 * kScale;
_avatarView.layer.masksToBounds = YES;
}
return _avatarView;
}
- (UILabel *)mainTitleLabel {
if (_mainTitleLabel == nil) {
_mainTitleLabel = [[UILabel alloc] init];
_mainTitleLabel.text = @"mainTitle";
_mainTitleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000");
_mainTitleLabel.font = [UIFont systemFontOfSize:18.0 * kScale];
}
return _mainTitleLabel;
}
- (UILabel *)subTitleLabel {
if (_subTitleLabel == nil) {
_subTitleLabel = [[UILabel alloc] init];
_subTitleLabel.text = @"subTitle";
_subTitleLabel.textColor = TIMCommonDynamicColor(@"form_subtitle_color", @"#888888");
_subTitleLabel.font = [UIFont systemFontOfSize:13.0 * kScale];
}
return _subTitleLabel;
}
- (UILabel *)descLabel {
if (_descLabel == nil) {
_descLabel = [[UILabel alloc] init];
_descLabel.text = @"descLabel";
_descLabel.textColor = TIMCommonDynamicColor(@"form_desc_color", @"#888888");
_descLabel.font = [UIFont systemFontOfSize:13.0 * kScale];
}
return _descLabel;
}
@end

View File

@@ -0,0 +1,18 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import <UIKit/UIKit.h>
#import <TIMCommon/TUICommonGroupInfoCellData.h>
@interface TUIGroupMemberCell : UICollectionViewCell
@property(nonatomic, strong) UIImageView *head;
@property(nonatomic, strong) UILabel *name;
+ (CGSize)getSize;
@property(nonatomic, strong) TUIGroupMemberCellData *data;
@end

View File

@@ -0,0 +1,97 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import "TUIGroupMemberCell.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/UIView+TUILayout.h>
#import "ReactiveObjC/ReactiveObjC.h"
#import "SDWebImage/UIImageView+WebCache.h"
@implementation TUIGroupMemberCell
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setupViews];
}
return self;
}
- (void)setupViews {
_head = [[UIImageView alloc] init];
_head.layer.cornerRadius = 5;
[_head.layer setMasksToBounds:YES];
[self.contentView addSubview:_head];
_name = [[UILabel alloc] init];
[_name setFont:[UIFont systemFontOfSize:13]];
[_name setTextColor:[UIColor grayColor]];
_name.textAlignment = NSTextAlignmentCenter;
[self.contentView addSubview:_name];
}
- (void)setData:(TUIGroupMemberCellData *)data {
_data = data;
if (data.avatarUrl) {
[self.head sd_setImageWithURL:[NSURL URLWithString:data.avatarUrl] placeholderImage:data.avatarImage ?: DefaultAvatarImage];
} else {
if (data.avatarImage) {
self.head.image = data.avatarImage;
} else {
self.head.image = DefaultAvatarImage;
}
}
if (data.name.length) {
self.name.text = data.name;
} else {
self.name.text = data.identifier;
}
// tell constraints they need updating
[self setNeedsUpdateConstraints];
// update constraints now so we can animate the change
[self updateConstraintsIfNeeded];
[self layoutIfNeeded];
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
[super updateConstraints];
CGSize headSize = [[self class] getSize];
[_head mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.top.mas_equalTo(self.contentView);
make.width.mas_equalTo(headSize.width);
make.height.mas_equalTo(headSize.width);
}];
[_name mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.head);
make.top.mas_equalTo(self.head.mas_bottom).mas_offset(TGroupMemberCell_Margin);
make.width.mas_equalTo(headSize.width);
make.height.mas_equalTo(TGroupMemberCell_Name_Height);
}];
if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) {
_head.layer.masksToBounds = YES;
_head.layer.cornerRadius = _head.frame.size.height / 2;
} else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) {
_head.layer.masksToBounds = YES;
_head.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius;
}
}
+ (CGSize)getSize {
CGSize headSize = TGroupMemberCell_Head_Size;
if (headSize.width * TGroupMembersCell_Column_Count + TGroupMembersCell_Margin * (TGroupMembersCell_Column_Count + 1) > Screen_Width) {
CGFloat wd = (Screen_Width - (TGroupMembersCell_Margin * (TGroupMembersCell_Column_Count + 1))) / TGroupMembersCell_Column_Count;
headSize = CGSizeMake(wd, wd);
}
return CGSizeMake(headSize.width, headSize.height + TGroupMemberCell_Name_Height + TGroupMemberCell_Margin);
}
@end

View File

@@ -0,0 +1,38 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import <UIKit/UIKit.h>
#import <TIMCommon/TUICommonGroupInfoCellData.h>
@class TUIGroupMembersCell;
/////////////////////////////////////////////////////////////////////////////////
//
// TUIGroupMembersCellDelegate
//
/////////////////////////////////////////////////////////////////////////////////
@protocol TUIGroupMembersCellDelegate <NSObject>
- (void)groupMembersCell:(TUIGroupMembersCell *)cell didSelectItemAtIndex:(NSInteger)index;
@end
/////////////////////////////////////////////////////////////////////////////////
//
// TUIGroupMembersCell
//
/////////////////////////////////////////////////////////////////////////////////
@interface TUIGroupMembersCell : UITableViewCell
@property(nonatomic, strong) UICollectionView *memberCollectionView;
@property(nonatomic, strong) UICollectionViewFlowLayout *memberFlowLayout;
@property(nonatomic, weak) id<TUIGroupMembersCellDelegate> delegate;
@property(nonatomic) TUIGroupMembersCellData *data;
+ (CGFloat)getHeight:(TUIGroupMembersCellData *)data;
@end

View File

@@ -0,0 +1,97 @@
//
// TUIGroupMembersCell.m
// UIKit
//
// Created by kennethmiao on 2018/9/25.
// Copyright © 2018 Tencent. All rights reserved.
//
#import "TUIGroupMembersCell.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIThemeManager.h>
#import "TUIGroupMemberCell.h"
@interface TUIGroupMembersCell () <UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
@end
@implementation TUIGroupMembersCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self setupViews];
}
return self;
}
- (void)setupViews {
_memberFlowLayout = [[UICollectionViewFlowLayout alloc] init];
CGSize cellSize = [TUIGroupMemberCell getSize];
_memberFlowLayout.itemSize = cellSize;
_memberFlowLayout.minimumInteritemSpacing =
(Screen_Width - cellSize.width * TGroupMembersCell_Column_Count - 2 * 20) / (TGroupMembersCell_Column_Count - 1);
_memberFlowLayout.minimumLineSpacing = TGroupMembersCell_Margin;
_memberFlowLayout.sectionInset = UIEdgeInsetsMake(TGroupMembersCell_Margin, 20, TGroupMembersCell_Margin, 20);
_memberCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:_memberFlowLayout];
[_memberCollectionView registerClass:[TUIGroupMemberCell class] forCellWithReuseIdentifier:TGroupMemberCell_ReuseId];
_memberCollectionView.collectionViewLayout = _memberFlowLayout;
_memberCollectionView.delegate = self;
_memberCollectionView.dataSource = self;
_memberCollectionView.showsHorizontalScrollIndicator = NO;
_memberCollectionView.showsVerticalScrollIndicator = NO;
_memberCollectionView.backgroundColor = self.backgroundColor;
[self.contentView addSubview:_memberCollectionView];
[self setSeparatorInset:UIEdgeInsetsMake(0, TGroupMembersCell_Margin, 0, 0)];
[self setSelectionStyle:UITableViewCellSelectionStyleNone];
}
- (void)updateLayout {
CGFloat height = [TUIGroupMembersCell getHeight:_data];
_memberCollectionView.frame = CGRectMake(0, 0, Screen_Width, height);
}
- (void)setData:(TUIGroupMembersCellData *)data {
_data = data;
[self updateLayout];
[_memberCollectionView reloadData];
}
+ (CGFloat)getHeight:(TUIGroupMembersCellData *)data {
NSInteger row = ceil(data.members.count * 1.0 / TGroupMembersCell_Column_Count);
if (row > TGroupMembersCell_Row_Count) {
row = TGroupMembersCell_Row_Count;
}
CGFloat height = row * [TUIGroupMemberCell getSize].height + (row + 1) * TGroupMembersCell_Margin;
return height;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return _data.members.count;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
TUIGroupMemberCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:TGroupMemberCell_ReuseId forIndexPath:indexPath];
TUIGroupMemberCellData *data = nil;
data = _data.members[indexPath.item];
[cell setData:data];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if (_delegate && [_delegate respondsToSelector:@selector(groupMembersCell:didSelectItemAtIndex:)]) {
[_delegate groupMembersCell:self didSelectItemAtIndex:indexPath.section * TGroupMembersCell_Column_Count + indexPath.row];
}
}
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return [TUIGroupMemberCell getSize];
}
@end

View File

@@ -0,0 +1,26 @@
//
// TUIMemberInfoCell.h
// TUIGroup
//
// Created by harvy on 2021/12/27.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <UIKit/UIKit.h>
@class TUIMemberInfoCellData;
NS_ASSUME_NONNULL_BEGIN
@interface TUIMemberTagView : UIView
@property(nonatomic, strong) UILabel *tagname;
@end
@interface TUIMemberInfoCell : UITableViewCell
@property(nonatomic, strong) UIImageView *avatarImageView;
@property(nonatomic, strong) UILabel *nameLabel;
@property(nonatomic, strong) TUIMemberInfoCellData *data;
@property(nonatomic, strong) TUIMemberTagView *tagView;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,180 @@
//
// TUIMemberInfoCell.m
// TUIGroup
//
// Created by harvy on 2021/12/27.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIMemberInfoCell.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIThemeManager.h>
#import <TUICore/UIView+TUILayout.h>
#import "TUIMemberInfoCellData.h"
#import "UIImageView+WebCache.h"
#define kScale UIScreen.mainScreen.bounds.size.width / 375.0
@implementation TUIMemberTagView : UIView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor tui_colorWithHex:@"#E7F3FC"];
self.layer.borderWidth = kScale390(1);
self.layer.cornerRadius = kScale390(3);
self.layer.borderColor = [UIColor tui_colorWithHex:@"#1890FF"].CGColor;
[self addSubview:self.tagname];
}
return self;
}
- (UILabel *)tagname {
if (!_tagname) {
_tagname = [[UILabel alloc] init];
_tagname.text = @"";
_tagname.textColor = [UIColor tui_colorWithHex:@"#1890FF"];
_tagname.font = [UIFont systemFontOfSize:kScale390(10)];
}
return _tagname;
}
- (void)layoutSubviews {
[super layoutSubviews];
[_tagname sizeToFit];
_tagname.frame = CGRectMake(kScale390(8), 0, _tagname.frame.size.width, self.frame.size.height);
}
@end
@implementation TUIMemberInfoCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
[self setupViews];
}
return self;
}
- (void)setupViews {
[self.contentView addSubview:self.avatarImageView];
[self.contentView addSubview:self.nameLabel];
[self.contentView addSubview:self.tagView];
}
- (void)layoutSubviews {
[super layoutSubviews];
}
- (void)setData:(TUIMemberInfoCellData *)data {
_data = data;
UIImage *defaultImage = DefaultAvatarImage;
[self.avatarImageView sd_setImageWithURL:[NSURL URLWithString:data.avatarUrl] placeholderImage:data.avatar ?: defaultImage];
self.nameLabel.text = data.name;
self.tagView.hidden = NO;
if (data.role == V2TIM_GROUP_MEMBER_ROLE_SUPER) {
self.tagView.tagname.text = TIMCommonLocalizableString(TUIKitMembersRoleSuper);
} else if (data.role == V2TIM_GROUP_MEMBER_ROLE_ADMIN) {
self.tagView.tagname.text = TIMCommonLocalizableString(TUIKitMembersRoleAdmin);
} else {
self.tagView.tagname.text = @"";
self.tagView.hidden = YES;
}
if (data.showAccessory) {
self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else {
self.accessoryType = UITableViewCellAccessoryNone;
}
// tell constraints they need updating
[self setNeedsUpdateConstraints];
// update constraints now so we can animate the change
[self updateConstraintsIfNeeded];
[self layoutIfNeeded];
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
[super updateConstraints];
if (self.data.style == TUIMemberInfoCellStyleAdd) {
[self.avatarImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(18.0 * kScale);
make.centerY.mas_equalTo(self.contentView);
make.width.height.mas_equalTo(20.0 * kScale);
}];
self.nameLabel.font = [UIFont systemFontOfSize:16.0 * kScale];
self.nameLabel.textColor = TIMCommonDynamicColor(@"form_value_text_color", @"#000000");
} else {
[self.avatarImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(16.0 * kScale);
make.centerY.mas_equalTo(self.contentView);
make.width.height.mas_equalTo(34.0 * kScale);
}];
self.nameLabel.font = [UIFont systemFontOfSize:16.0 * kScale];
self.nameLabel.textColor = TIMCommonDynamicColor(@"form_value_text_color", @"#000000");
}
if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) {
self.avatarImageView.layer.masksToBounds = YES;
self.avatarImageView.layer.cornerRadius = self.avatarImageView.frame.size.height / 2;
} else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) {
self.avatarImageView.layer.masksToBounds = YES;
self.avatarImageView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius;
}
[self.nameLabel sizeToFit];
[self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.avatarImageView.mas_trailing).mas_offset(14);
make.centerY.mas_equalTo(self.contentView);
make.size.mas_equalTo(self.nameLabel.frame.size);
if (self.tagView.tagname.text.length > 0) {
make.trailing.mas_lessThanOrEqualTo(self.tagView.mas_trailing).mas_offset(- 2.0 * kScale);
}
else {
make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- 2.0 * kScale);
}
}];
[self.tagView.tagname sizeToFit];
[self.tagView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.nameLabel.mas_trailing).mas_offset(kScale390(10));
make.width.mas_equalTo(self.tagView.tagname.frame.size.width + kScale390(16));
make.height.mas_equalTo(kScale390(15));
make.centerY.mas_equalTo(self.contentView.mas_centerY);
make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- 2.0 * kScale);
}];
}
- (UIImageView *)avatarImageView {
if (_avatarImageView == nil) {
_avatarImageView = [[UIImageView alloc] init];
}
return _avatarImageView;
}
- (UILabel *)nameLabel {
if (_nameLabel == nil) {
_nameLabel = [[UILabel alloc] init];
_nameLabel.font = [UIFont systemFontOfSize:18.0 * kScale];
_nameLabel.textColor = [UIColor colorWithRed:17 / 255.0 green:17 / 255.0 blue:17 / 255.0 alpha:1 / 1.0];
}
return _nameLabel;
}
- (TUIMemberTagView *)tagView {
if (_tagView == nil) {
_tagView = [[TUIMemberTagView alloc] init];
}
return _tagView;
}
@end

View File

@@ -0,0 +1,15 @@
//
// TUISelectedUserCollectionViewCell.h
// TXIMSDK_TUIKit_iOS
//
// Created by xiangzhang on 2020/7/6.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <TIMCommon/TIMCommonModel.h>
#import <TUICore/UIView+TUILayout.h>
#import <UIKit/UIKit.h>
@interface TUIMemberPanelCell : UICollectionViewCell
- (void)fillWithData:(TUIUserModel *)model;
@end

View File

@@ -0,0 +1,37 @@
//
// TUISelectedUserCollectionViewCell.m
// TXIMSDK_TUIKit_iOS
//
// Created by xiangzhang on 2020/7/6.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIMemberPanelCell.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIDarkModel.h>
#import <TUICore/TUIThemeManager.h>
#import "SDWebImage/UIImageView+WebCache.h"
@implementation TUIMemberPanelCell {
UIImageView *_imageView;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = TUIContactDynamicColor(@"group_controller_bg_color", @"#F2F3F5");
_imageView = [[UIImageView alloc] initWithFrame:self.bounds];
_imageView.backgroundColor = [UIColor clearColor];
_imageView.contentMode = UIViewContentModeScaleToFill;
[self addSubview:_imageView];
}
return self;
}
- (void)fillWithData:(TUIUserModel *)model {
[_imageView sd_setImageWithURL:[NSURL URLWithString:model.avatar]
placeholderImage:[UIImage imageNamed:TIMCommonImagePath(@"default_c2c_head")]
options:SDWebImageHighPriority];
}
@end

View File

@@ -0,0 +1,18 @@
//
// TUISelectMemberCell.h
// TXIMSDK_TUIKit_iOS
//
// Created by xiangzhang on 2021/8/26.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <TIMCommon/TIMCommonModel.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUISelectGroupMemberCell : UITableViewCell
- (void)fillWithData:(TUIUserModel *)model isSelect:(BOOL)isSelect;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,83 @@
//
// TUISelectMemberCell.m
// TXIMSDK_TUIKit_iOS
//
// Created by xiangzhang on 2021/8/26.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUISelectGroupMemberCell.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIDarkModel.h>
#import <TUICore/TUIThemeManager.h>
@implementation TUISelectGroupMemberCell {
UIImageView *_selectedMark;
UIImageView *_userImg;
UILabel *_nameLabel;
TUIUserModel *_userModel;
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#F2F3F5");
_selectedMark = [[UIImageView alloc] initWithFrame:CGRectZero];
[self addSubview:_selectedMark];
_userImg = [[UIImageView alloc] initWithFrame:CGRectZero];
[self addSubview:_userImg];
_nameLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_nameLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft;
[self addSubview:_nameLabel];
self.selectionStyle = UITableViewCellSelectionStyleNone;
}
return self;
}
- (void)fillWithData:(TUIUserModel *)model isSelect:(BOOL)isSelect {
_userModel = model;
_selectedMark.image = isSelect ? [UIImage imageNamed:TUIContactImagePath(@"ic_selected")] : [UIImage imageNamed:TUIContactImagePath(@"ic_unselect")];
[_userImg sd_setImageWithURL:[NSURL URLWithString:model.avatar] placeholderImage:DefaultAvatarImage];
_nameLabel.text = model.name;
// tell constraints they need updating
[self setNeedsUpdateConstraints];
// update constraints now so we can animate the change
[self updateConstraintsIfNeeded];
[self layoutIfNeeded];
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
[super updateConstraints];
[_selectedMark mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(20);
make.leading.mas_equalTo(self.contentView).mas_offset(12);
make.centerY.mas_equalTo(self.contentView);
}];
[_userImg mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(32);
make.leading.mas_equalTo(_selectedMark.mas_trailing).mas_offset(12);
make.centerY.mas_equalTo(self.contentView);
}];
[_nameLabel sizeToFit];
[_nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(_userImg.mas_trailing).mas_offset(12);
make.trailing.mas_equalTo(self.contentView.mas_trailing);
make.height.mas_equalTo(self.contentView);
make.centerY.mas_equalTo(self.contentView);
}];
}
- (void)layoutSubviews {
[super layoutSubviews];
}
@end