增加换肤功能

This commit is contained in:
启星
2025-08-14 10:07:49 +08:00
parent f6964c1e89
commit 4f9318d98e
8789 changed files with 978530 additions and 2 deletions

View File

@@ -0,0 +1,26 @@
//
// TUIGroupMemberCellData.h
// TXIMSDK_TUIKit_iOS
//
// Created by xiangzhang on 2021/6/25.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
@import UIKit;
NS_ASSUME_NONNULL_BEGIN
@interface TUIGroupMemberCellData : NSObject
@property(nonatomic, strong) NSString *identifier;
@property(nonatomic, strong) NSString *name;
@property(nonatomic, strong) UIImage *avatarImage;
@property(nonatomic, strong) NSString *avatarUrl;
@property NSInteger tag;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,13 @@
//
// TUIGroupMemberCellData.m
// TXIMSDK_TUIKit_iOS
//
// Created by xiangzhang on 2021/6/25.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIGroupMemberCellData.h"
@implementation TUIGroupMemberCellData
@end

View File

@@ -0,0 +1,17 @@
//
// TUIGroupMembersCellData.h
// TXIMSDK_TUIKit_iOS
//
// Created by xiangzhang on 2021/6/25.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUIGroupMembersCellData : NSObject
@property(nonatomic, strong) NSMutableArray *members;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,13 @@
//
// TUIGroupMembersCellData.m
// TXIMSDK_TUIKit_iOS
//
// Created by xiangzhang on 2021/6/25.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIGroupMembersCellData.h"
@implementation TUIGroupMembersCellData
@end

View File

@@ -0,0 +1,22 @@
//
// TUIGroupNoticeCellData.h
// TUIGroup
//
// Created by harvy on 2022/1/11.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUIGroupNoticeCellData : NSObject
@property(nonatomic, copy) NSString *name;
@property(nonatomic, copy) NSString *desc;
@property(nonatomic, weak) id target;
@property(nonatomic, assign) SEL selector;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,13 @@
//
// TUIGroupNoticeCellData.m
// TUIGroup
//
// Created by harvy on 2022/1/11.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIGroupNoticeCellData.h"
@implementation TUIGroupNoticeCellData
@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,18 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import <UIKit/UIKit.h>
#import "TUIGroupMemberCellData.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 "TUIGroupMembersCellData.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,24 @@
//
// TUIGroupNoticeCell.h
// TUIGroup
//
// Created by harvy on 2022/1/11.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "TUIGroupNoticeCellData.h"
NS_ASSUME_NONNULL_BEGIN
@interface TUIGroupNoticeCell : UITableViewCell
@property(nonatomic, strong) UILabel *nameLabel;
@property(nonatomic, strong) UILabel *descLabel;
@property(nonatomic, strong) UIImageView *iconView;
@property(nonatomic, strong) TUIGroupNoticeCellData *cellData;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,109 @@
//
// TUIGroupNoticeCell.m
// TUIGroup
//
// Created by harvy on 2022/1/11.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIGroupNoticeCell.h"
#import <TUICore/TUIThemeManager.h>
#import <TIMCommon/TIMDefine.h>
@implementation TUIGroupNoticeCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
[self setupViews];
}
return self;
}
- (void)setupViews {
self.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF");
self.contentView.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF");
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
[self.contentView addSubview:self.nameLabel];
[self.contentView addSubview:self.descLabel];
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGesture:)];
tapRecognizer.delegate = self;
tapRecognizer.cancelsTouchesInView = NO;
[self.contentView addGestureRecognizer:tapRecognizer];
}
- (void)tapGesture:(UIGestureRecognizer *)gesture {
if (self.cellData.selector && self.cellData.target) {
if ([self.cellData.target respondsToSelector:self.cellData.selector]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self.cellData.target performSelector:self.cellData.selector];
#pragma clang diagnostic pop
}
}
}
- (void)setCellData:(TUIGroupNoticeCellData *)cellData {
_cellData = cellData;
self.nameLabel.text = cellData.name;
self.descLabel.text = cellData.desc;
// 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.nameLabel sizeToFit];
[self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(20);
make.top.mas_equalTo(12);
make.trailing.mas_lessThanOrEqualTo(self.contentView).mas_offset(-20);
make.size.mas_equalTo(self.nameLabel.frame.size);
}];
[self.descLabel sizeToFit];
[self.descLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.nameLabel);
make.top.mas_equalTo(self.nameLabel.mas_bottom).mas_offset(4);
make.trailing.mas_lessThanOrEqualTo(self.contentView).mas_offset(-30);
make.size.mas_equalTo(self.descLabel.frame.size);
}];
}
- (void)layoutSubviews {
[super layoutSubviews];
}
- (UILabel *)nameLabel {
if (_nameLabel == nil) {
_nameLabel = [[UILabel alloc] init];
_nameLabel.text = @"";
_nameLabel.textColor = TIMCommonDynamicColor(@"form_key_text_color", @"#888888");
_nameLabel.font = [UIFont systemFontOfSize:16.0];
}
return _nameLabel;
}
- (UILabel *)descLabel {
if (_descLabel == nil) {
_descLabel = [[UILabel alloc] init];
_descLabel.text = @"neirong";
_descLabel.textColor = TIMCommonDynamicColor(@"form_subtitle_color", @"#BBBBBB");
_descLabel.font = [UIFont systemFontOfSize:12.0];
}
return _descLabel;
}
@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 = TUIGroupDynamicColor(@"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:TUIGroupImagePath(@"ic_selected")] : [UIImage imageNamed:TUIGroupImagePath(@"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

View File

@@ -0,0 +1,20 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import <Foundation/Foundation.h>
@import ImSDK_Plus;
NS_ASSUME_NONNULL_BEGIN
@interface V2TIMGroupInfo (TUIDataProvider)
- (BOOL)isMeOwner;
- (BOOL)isPrivate;
- (BOOL)canInviteMember;
- (BOOL)canRemoveMember;
- (BOOL)canDismissGroup;
- (BOOL)canSupportSetAdmain;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,46 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import <TUICore/TUIGlobalization.h>
#import "TIMGroupInfo+TUIDataProvider.h"
@implementation V2TIMGroupInfo (TUIDataProvider)
- (BOOL)isMeOwner {
return [self.owner isEqualToString:[[V2TIMManager sharedInstance] getLoginUser]] || (self.role == V2TIM_GROUP_MEMBER_ROLE_ADMIN);
}
- (BOOL)isPrivate {
return [self.groupType isEqualToString:@"Work"];
}
- (BOOL)canInviteMember {
return self.groupApproveOpt != V2TIM_GROUP_ADD_FORBID;
}
- (BOOL)canRemoveMember {
return [self isMeOwner] && (self.memberCount > 1);
}
- (BOOL)canDismissGroup {
if ([self isPrivate]) {
return NO;
} else {
if ([self.owner isEqualToString:[[V2TIMManager sharedInstance] getLoginUser]] || (self.role == V2TIM_GROUP_MEMBER_ROLE_SUPER)) {
return YES;
} else {
return NO;
}
}
}
- (BOOL)canSupportSetAdmain {
BOOL isMeSuper = [self.owner isEqualToString:[[V2TIMManager sharedInstance] getLoginUser]] || (self.role == V2TIM_GROUP_MEMBER_ROLE_SUPER);
BOOL isCurrentGroupTypeSupportSetAdmain = ([self.groupType isEqualToString:@"Public"] || [self.groupType isEqualToString:@"Meeting"] ||
[self.groupType isEqualToString:@"Community"] || [self.groupType isEqualToString:@"Private"]);
return isMeSuper && isCurrentGroupTypeSupportSetAdmain && (self.memberCount > 1);
}
@end

View File

@@ -0,0 +1,63 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
@import Foundation;
@import UIKit;
@import ImSDK_Plus;
@class TUICommonCellData;
@class TUICommonTextCell;
@class TUICommonSwitchCell;
@class TUIButtonCell;
@class TUIProfileCardCellData;
@class TUIProfileCardCell;
@class TUIGroupMemberCellData;
@class TUIGroupMembersCellData;
NS_ASSUME_NONNULL_BEGIN
@protocol TUIGroupInfoDataProviderDelegate <NSObject>
- (void)didSelectMembers;
- (void)didSelectGroupNick:(TUICommonTextCell *)cell;
- (void)didSelectAddOption:(UITableViewCell *)cell;
- (void)didSelectCommon;
- (void)didSelectOnNotDisturb:(TUICommonSwitchCell *)cell;
- (void)didSelectOnTop:(TUICommonSwitchCell *)cell;
- (void)didSelectOnFoldConversation:(TUICommonSwitchCell *)cell;
- (void)didSelectOnChangeBackgroundImage:(TUICommonTextCell *)cell;
- (void)didDeleteGroup:(TUIButtonCell *)cell;
- (void)didClearAllHistory:(TUIButtonCell *)cell;
- (void)didSelectGroupManage;
- (void)didSelectGroupNotice;
- (void)didTransferGroup:(TUIButtonCell *)cell;
@end
@interface TUIGroupInfoDataProvider : NSObject
@property(nonatomic, weak) id<TUIGroupInfoDataProviderDelegate> delegate;
@property(nonatomic, strong) V2TIMGroupInfo *groupInfo;
@property(nonatomic, strong) NSMutableArray *dataList;
@property(nonatomic, strong) NSMutableArray<TUIGroupMemberCellData *> *membersData;
@property(nonatomic, strong) TUIGroupMembersCellData *groupMembersCellData;
@property(nonatomic, strong, readonly) V2TIMGroupMemberFullInfo *selfInfo;
@property(nonatomic, strong, readonly) TUIProfileCardCellData *profileCellData;
- (instancetype)initWithGroupID:(NSString *)groupID;
- (void)loadData;
- (void)updateGroupInfo;
- (void)setGroupAddOpt:(V2TIMGroupAddOpt)opt;
- (void)setGroupApproveOpt:(V2TIMGroupAddOpt)opt;
- (void)setGroupReceiveMessageOpt:(V2TIMReceiveMessageOpt)opt Succ:(V2TIMSucc)succ fail:(V2TIMFail)fail;
- (void)setGroupName:(NSString *)groupName;
- (void)setGroupNotification:(NSString *)notification;
- (void)setGroupMemberNameCard:(NSString *)nameCard;
- (void)dismissGroup:(V2TIMSucc)succ fail:(V2TIMFail)fail;
- (void)quitGroup:(V2TIMSucc)succ fail:(V2TIMFail)fail;
- (void)clearAllHistory:(V2TIMSucc)succ fail:(V2TIMFail)fail;
- (void)updateGroupAvatar:(NSString *)url succ:(V2TIMSucc)succ fail:(V2TIMFail)fail;
- (void)transferGroupOwner:(NSString *)groupID member:(NSString *)userID succ:(V2TIMSucc)succ fail:(V2TIMFail)fail;
+ (BOOL)isMeOwner:(V2TIMGroupInfo *)groupInfo;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,720 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
#import "TIMGroupInfo+TUIDataProvider.h"
#import "TUIGroupInfoDataProvider.h"
#import "TUIGroupMemberCellData.h"
#import "TUIGroupMembersCellData.h"
#import "TUIGroupNoticeCell.h"
#import "TUIGroupConfig.h"
@interface TUIGroupInfoDataProvider () <V2TIMGroupListener>
@property(nonatomic, strong) TUICommonTextCellData *addOptionData;
@property(nonatomic, strong) TUICommonTextCellData *inviteOptionData;
@property(nonatomic, strong) TUICommonTextCellData *groupNickNameCellData;
@property(nonatomic, strong, readwrite) TUIProfileCardCellData *profileCellData;
@property(nonatomic, strong) V2TIMGroupMemberFullInfo *selfInfo;
@property(nonatomic, strong) NSString *groupID;
@end
@implementation TUIGroupInfoDataProvider
- (instancetype)initWithGroupID:(NSString *)groupID {
self = [super init];
if (self) {
self.groupID = groupID;
[[V2TIMManager sharedInstance] addGroupListener:self];
}
return self;
}
#pragma mark V2TIMGroupListener
- (void)onMemberEnter:(NSString *)groupID memberList:(NSArray<V2TIMGroupMemberInfo *> *)memberList {
[self loadData];
}
- (void)onMemberLeave:(NSString *)groupID member:(V2TIMGroupMemberInfo *)member {
[self loadData];
}
- (void)onMemberInvited:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser memberList:(NSArray<V2TIMGroupMemberInfo *> *)memberList {
[self loadData];
}
- (void)onMemberKicked:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser memberList:(NSArray<V2TIMGroupMemberInfo *> *)memberList {
[self loadData];
}
- (void)onGroupInfoChanged:(NSString *)groupID changeInfoList:(NSArray<V2TIMGroupChangeInfo *> *)changeInfoList {
if (![groupID isEqualToString:self.groupID]) {
return;
}
[self loadData];
}
- (void)loadData {
if (self.groupID.length == 0) {
[TUITool makeToastError:ERR_INVALID_PARAMETERS msg:@"invalid groupID"];
return;
}
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
[self getGroupInfo:^{
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
[self getGroupMembers:^{
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
[self getSelfInfoInGroup:^{
dispatch_group_leave(group);
}];
__weak typeof(self) weakSelf = self;
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
[weakSelf setupData];
});
}
- (void)updateGroupInfo {
@weakify(self);
[[V2TIMManager sharedInstance] getGroupsInfo:@[ self.groupID ]
succ:^(NSArray<V2TIMGroupInfoResult *> *groupResultList) {
@strongify(self);
if (groupResultList.count == 1) {
self.groupInfo = groupResultList[0].info;
[self setupData];
}
}
fail:^(int code, NSString *msg) {
[TUITool makeToastError:code msg:msg];
}];
}
- (void)transferGroupOwner:(NSString *)groupID member:(NSString *)userID succ:(V2TIMSucc)succ fail:(V2TIMFail)fail {
[V2TIMManager.sharedInstance transferGroupOwner:groupID
member:userID
succ:^{
succ();
}
fail:^(int code, NSString *desc) {
fail(code, desc);
}];
}
- (void)updateGroupAvatar:(NSString *)url succ:(V2TIMSucc)succ fail:(V2TIMFail)fail {
V2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init];
info.groupID = self.groupID;
info.faceURL = url;
[V2TIMManager.sharedInstance setGroupInfo:info succ:succ fail:fail];
}
- (void)getGroupInfo:(dispatch_block_t)callback {
__weak typeof(self) weakSelf = self;
[[V2TIMManager sharedInstance] getGroupsInfo:@[ self.groupID ]
succ:^(NSArray<V2TIMGroupInfoResult *> *groupResultList) {
weakSelf.groupInfo = groupResultList.firstObject.info;
if (callback) {
callback();
}
}
fail:^(int code, NSString *msg) {
if (callback) {
callback();
}
[TUITool makeToastError:code msg:msg];
}];
}
- (void)getGroupMembers:(dispatch_block_t)callback {
__weak typeof(self) weakSelf = self;
[[V2TIMManager sharedInstance] getGroupMemberList:self.groupID
filter:V2TIM_GROUP_MEMBER_FILTER_ALL
nextSeq:0
succ:^(uint64_t nextSeq, NSArray<V2TIMGroupMemberFullInfo *> *memberList) {
NSMutableArray *membersData = [NSMutableArray array];
for (V2TIMGroupMemberFullInfo *fullInfo in memberList) {
TUIGroupMemberCellData *data = [[TUIGroupMemberCellData alloc] init];
data.identifier = fullInfo.userID;
data.name = fullInfo.userID;
data.avatarUrl = fullInfo.faceURL;
if (fullInfo.nameCard.length > 0) {
data.name = fullInfo.nameCard;
} else if (fullInfo.friendRemark.length > 0) {
data.name = fullInfo.friendRemark;
} else if (fullInfo.nickName.length > 0) {
data.name = fullInfo.nickName;
}
[membersData addObject:data];
}
weakSelf.membersData = membersData;
if (callback) {
callback();
}
}
fail:^(int code, NSString *msg) {
[TUITool makeToastError:code msg:msg];
if (callback) {
callback();
}
}];
}
- (void)getSelfInfoInGroup:(dispatch_block_t)callback {
NSString *loginUserID = [[V2TIMManager sharedInstance] getLoginUser];
if (loginUserID.length == 0) {
if (callback) {
callback();
}
return;
}
__weak typeof(self) weakSelf = self;
[[V2TIMManager sharedInstance] getGroupMembersInfo:self.groupID
memberList:@[ loginUserID ]
succ:^(NSArray<V2TIMGroupMemberFullInfo *> *memberList) {
for (V2TIMGroupMemberFullInfo *item in memberList) {
if ([item.userID isEqualToString:loginUserID]) {
weakSelf.selfInfo = item;
break;
}
}
if (callback) {
callback();
}
}
fail:^(int code, NSString *desc) {
[TUITool makeToastError:code msg:desc];
if (callback) {
callback();
}
}];
}
- (void)setupData {
NSMutableArray *dataList = [NSMutableArray array];
if (self.groupInfo) {
NSMutableArray *commonArray = [NSMutableArray array];
TUIProfileCardCellData *commonData = [[TUIProfileCardCellData alloc] init];
commonData.avatarImage = DefaultGroupAvatarImageByGroupType(self.groupInfo.groupType);
commonData.avatarUrl = [NSURL URLWithString:self.groupInfo.faceURL];
commonData.name = self.groupInfo.groupName;
commonData.identifier = self.groupInfo.groupID;
commonData.signature = self.groupInfo.notification;
if ([TUIGroupInfoDataProvider isMeOwner:self.groupInfo] || [self.groupInfo isPrivate]) {
commonData.cselector = @selector(didSelectCommon);
commonData.showAccessory = YES;
}
self.profileCellData = commonData;
[commonArray addObject:commonData];
[dataList addObject:commonArray];
NSMutableArray *memberArray = [NSMutableArray array];
if (![TUIGroupConfig.sharedConfig isItemHiddenInGroupConfig:TUIGroupConfigItem_Members]) {
TUICommonTextCellData *countData = [[TUICommonTextCellData alloc] init];
countData.key = TIMCommonLocalizableString(TUIKitGroupProfileMember);
countData.value = [NSString stringWithFormat:TIMCommonLocalizableString(TUIKitGroupProfileMemberCount), self.groupInfo.memberCount];
countData.cselector = @selector(didSelectMembers);
countData.showAccessory = YES;
[memberArray addObject:countData];
NSMutableArray *tmpArray = [self getShowMembers:self.membersData];
TUIGroupMembersCellData *membersData = [[TUIGroupMembersCellData alloc] init];
membersData.members = tmpArray;
[memberArray addObject:membersData];
self.groupMembersCellData = membersData;
[dataList addObject:memberArray];
}
// group info
NSMutableArray *groupInfoArray = [NSMutableArray array];
if (![TUIGroupConfig.sharedConfig isItemHiddenInGroupConfig:TUIGroupConfigItem_Notice]) {
TUIGroupNoticeCellData *notice = [[TUIGroupNoticeCellData alloc] init];
notice.name = TIMCommonLocalizableString(TUIKitGroupNotice);
notice.desc = self.groupInfo.notification ?: TIMCommonLocalizableString(TUIKitGroupNoticeNull);
notice.target = self;
notice.selector = @selector(didSelectNotice);
[groupInfoArray addObject:notice];
}
if (![TUIGroupConfig.sharedConfig isItemHiddenInGroupConfig:TUIGroupConfigItem_Members]) {
TUICommonTextCellData *manageData = [[TUICommonTextCellData alloc] init];
manageData.key = TIMCommonLocalizableString(TUIKitGroupProfileManage);
manageData.value = @"";
manageData.showAccessory = YES;
manageData.cselector = @selector(didSelectGroupManage);
if (([TUIGroupInfoDataProvider isMeOwner:self.groupInfo])) {
[groupInfoArray addObject:manageData];
}
}
if (![TUIGroupConfig.sharedConfig isItemHiddenInGroupConfig:TUIGroupConfigItem_Manage]) {
TUICommonTextCellData *typeData = [[TUICommonTextCellData alloc] init];
typeData.key = TIMCommonLocalizableString(TUIKitGroupProfileType);
typeData.value = [TUIGroupInfoDataProvider getGroupTypeName:self.groupInfo];
[groupInfoArray addObject:typeData];
TUICommonTextCellData *addOptionData = [[TUICommonTextCellData alloc] init];
addOptionData.key = TIMCommonLocalizableString(TUIKitGroupProfileJoinType);
if ([self.groupInfo.groupType isEqualToString:@"Work"]) {
addOptionData.value = TIMCommonLocalizableString(TUIKitGroupProfileInviteJoin);
} else if ([self.groupInfo.groupType isEqualToString:@"Meeting"]) {
addOptionData.value = TIMCommonLocalizableString(TUIKitGroupProfileAutoApproval);
} else {
if ([TUIGroupInfoDataProvider isMeOwner:self.groupInfo]) {
addOptionData.cselector = @selector(didSelectAddOption:);
addOptionData.showAccessory = YES;
}
addOptionData.value = [TUIGroupInfoDataProvider getAddOption:self.groupInfo];
}
[groupInfoArray addObject:addOptionData];
self.addOptionData = addOptionData;
TUICommonTextCellData *inviteOptionData = [[TUICommonTextCellData alloc] init];
inviteOptionData.key = TIMCommonLocalizableString(TUIKitGroupProfileInviteType);
if ([TUIGroupInfoDataProvider isMeOwner:self.groupInfo]) {
inviteOptionData.cselector = @selector(didSelectAddOption:);
inviteOptionData.showAccessory = YES;
}
inviteOptionData.value = [TUIGroupInfoDataProvider getApproveOption:self.groupInfo];
[groupInfoArray addObject:inviteOptionData];
self.inviteOptionData = inviteOptionData;
[dataList addObject:groupInfoArray];
}
// personal info
if (![TUIGroupConfig.sharedConfig isItemHiddenInGroupConfig:TUIGroupConfigItem_Alias]) {
TUICommonTextCellData *nickData = [[TUICommonTextCellData alloc] init];
nickData.key = TIMCommonLocalizableString(TUIKitGroupProfileAlias);
nickData.value = self.selfInfo.nameCard;
nickData.cselector = @selector(didSelectGroupNick:);
nickData.showAccessory = YES;
self.groupNickNameCellData = nickData;
[dataList addObject:@[ nickData ]];
}
TUICommonSwitchCellData *markFold = [[TUICommonSwitchCellData alloc] init];
TUICommonSwitchCellData *switchData = [[TUICommonSwitchCellData alloc] init];
if (![TUIGroupConfig.sharedConfig isItemHiddenInGroupConfig:TUIGroupConfigItem_MuteAndPin]) {
NSMutableArray *personalArray = [NSMutableArray array];
TUICommonSwitchCellData *messageSwitchData = [[TUICommonSwitchCellData alloc] init];
if (![self.groupInfo.groupType isEqualToString:GroupType_Meeting]) {
messageSwitchData.on = (self.groupInfo.recvOpt == V2TIM_RECEIVE_NOT_NOTIFY_MESSAGE);
messageSwitchData.title = TIMCommonLocalizableString(TUIKitGroupProfileMessageDoNotDisturb);
messageSwitchData.cswitchSelector = @selector(didSelectOnNotDisturb:);
[personalArray addObject:messageSwitchData];
}
markFold.title = TIMCommonLocalizableString(TUIKitConversationMarkFold);
markFold.displaySeparatorLine = YES;
markFold.cswitchSelector = @selector(didSelectOnFoldConversation:);
if (messageSwitchData.on) {
[personalArray addObject:markFold];
}
switchData.title = TIMCommonLocalizableString(TUIKitGroupProfileStickyOnTop);
[personalArray addObject:switchData];
[dataList addObject:personalArray];
}
if (![TUIGroupConfig.sharedConfig isItemHiddenInGroupConfig:TUIGroupConfigItem_Background]) {
TUICommonTextCellData *changeBackgroundImageItem = [[TUICommonTextCellData alloc] init];
changeBackgroundImageItem.key = TIMCommonLocalizableString(ProfileSetBackgroundImage);
changeBackgroundImageItem.cselector = @selector(didSelectOnChangeBackgroundImage:);
changeBackgroundImageItem.showAccessory = YES;
[dataList addObject:@[ changeBackgroundImageItem ]];
}
NSMutableArray *buttonArray = [NSMutableArray array];
if (![TUIGroupConfig.sharedConfig isItemHiddenInGroupConfig:TUIGroupConfigItem_ClearChatHistory]) {
TUIButtonCellData *clearHistory = [[TUIButtonCellData alloc] init];
clearHistory.title = TIMCommonLocalizableString(TUIKitClearAllChatHistory);
clearHistory.style = ButtonRedText;
clearHistory.cbuttonSelector = @selector(didClearAllHistory:);
[buttonArray addObject:clearHistory];
}
if (![TUIGroupConfig.sharedConfig isItemHiddenInGroupConfig:TUIGroupConfigItem_DeleteAndLeave]) {
TUIButtonCellData *quitButton = [[TUIButtonCellData alloc] init];
quitButton.title = TIMCommonLocalizableString(TUIKitGroupProfileDeleteAndExit);
quitButton.style = ButtonRedText;
quitButton.cbuttonSelector = @selector(didDeleteGroup:);
[buttonArray addObject:quitButton];
}
if ([self.class isMeSuper:self.groupInfo] &&
![TUIGroupConfig.sharedConfig isItemHiddenInGroupConfig:TUIGroupConfigItem_Transfer]) {
TUIButtonCellData *transferButton = [[TUIButtonCellData alloc] init];
transferButton.title = TIMCommonLocalizableString(TUIKitGroupTransferOwner);
transferButton.style = ButtonRedText;
transferButton.cbuttonSelector = @selector(didTransferGroup:);
[buttonArray addObject:transferButton];
}
if ([self.groupInfo canDismissGroup] &&
![TUIGroupConfig.sharedConfig isItemHiddenInGroupConfig:TUIGroupConfigItem_Dismiss]) {
TUIButtonCellData *deletebutton = [[TUIButtonCellData alloc] init];
deletebutton.title = TIMCommonLocalizableString(TUIKitGroupProfileDissolve);
deletebutton.style = ButtonRedText;
deletebutton.cbuttonSelector = @selector(didDeleteGroup:);
[buttonArray addObject:deletebutton];
}
if (![TUIGroupConfig.sharedConfig isItemHiddenInGroupConfig:TUIGroupConfigItem_Report]) {
TUIButtonCellData *reportButton = [[TUIButtonCellData alloc] init];
reportButton.title = TIMCommonLocalizableString(TUIKitGroupProfileReport);
reportButton.style = ButtonRedText;
reportButton.cbuttonSelector = @selector(didReportGroup:);
[buttonArray addObject:reportButton];
}
TUIButtonCellData *lastCellData = [buttonArray lastObject];
lastCellData.hideSeparatorLine = YES;
[dataList addObject:buttonArray];
#ifndef SDKPlaceTop
#define SDKPlaceTop
#endif
#ifdef SDKPlaceTop
@weakify(self);
[V2TIMManager.sharedInstance getConversation:[NSString stringWithFormat:@"group_%@", self.groupID]
succ:^(V2TIMConversation *conv) {
@strongify(self);
markFold.on = [self.class isMarkedByFoldType:conv.markList];
switchData.cswitchSelector = @selector(didSelectOnTop:);
switchData.on = conv.isPinned;
if (markFold.on) {
switchData.on = NO;
switchData.disableChecked = YES;
}
self.dataList = dataList;
}
fail:^(int code, NSString *desc) {
NSLog(@"");
}];
#else
if ([[[TUIConversationPin sharedInstance] topConversationList] containsObject:[NSString stringWithFormat:@"group_%@", self.groupID]]) {
switchData.on = YES;
}
#endif
}
}
- (void)didSelectMembers {
if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectMembers)]) {
[self.delegate didSelectMembers];
}
}
- (void)didSelectGroupNick:(TUICommonTextCell *)cell {
if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectGroupNick:)]) {
[self.delegate didSelectGroupNick:cell];
}
}
- (void)didSelectAddOption:(UITableViewCell *)cell {
if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectAddOption:)]) {
[self.delegate didSelectAddOption:cell];
}
}
- (void)didSelectCommon {
if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectCommon)]) {
[self.delegate didSelectCommon];
}
}
- (void)didSelectOnNotDisturb:(TUICommonSwitchCell *)cell {
if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectOnNotDisturb:)]) {
[self.delegate didSelectOnNotDisturb:cell];
}
}
- (void)didSelectOnTop:(TUICommonSwitchCell *)cell {
if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectOnTop:)]) {
[self.delegate didSelectOnTop:cell];
}
}
- (void)didSelectOnFoldConversation:(TUICommonSwitchCell *)cell {
if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectOnFoldConversation:)]) {
[self.delegate didSelectOnFoldConversation:cell];
}
}
- (void)didSelectOnChangeBackgroundImage:(TUICommonTextCell *)cell {
if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectOnChangeBackgroundImage:)]) {
[self.delegate didSelectOnChangeBackgroundImage:cell];
}
}
- (void)didTransferGroup:(TUIButtonCell *)cell {
if (self.delegate && [self.delegate respondsToSelector:@selector(didTransferGroup:)]) {
[self.delegate didTransferGroup:cell];
}
}
- (void)didDeleteGroup:(TUIButtonCell *)cell {
if (self.delegate && [self.delegate respondsToSelector:@selector(didDeleteGroup:)]) {
[self.delegate didDeleteGroup:cell];
}
}
- (void)didClearAllHistory:(TUIButtonCell *)cell {
if (self.delegate && [self.delegate respondsToSelector:@selector(didClearAllHistory:)]) {
[self.delegate didClearAllHistory:cell];
}
}
- (void)didSelectGroupManage {
if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectGroupManage)]) {
[self.delegate didSelectGroupManage];
}
}
- (void)didSelectNotice {
if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectGroupNotice)]) {
[self.delegate didSelectGroupNotice];
}
}
- (void)didReportGroup:(TUIButtonCell *)cell {
NSURL *url = [NSURL URLWithString:@"https://cloud.tencent.com/act/event/report-platform"];
[TUITool openLinkWithURL:url];
}
- (NSMutableArray *)getShowMembers:(NSMutableArray *)members {
int maxCount = TGroupMembersCell_Column_Count * TGroupMembersCell_Row_Count;
if ([self.groupInfo canInviteMember]) maxCount--;
if ([self.groupInfo canRemoveMember]) maxCount--;
NSMutableArray *tmpArray = [NSMutableArray array];
for (NSInteger i = 0; i < members.count && i < maxCount; ++i) {
[tmpArray addObject:members[i]];
}
if ([self.groupInfo canInviteMember]) {
TUIGroupMemberCellData *add = [[TUIGroupMemberCellData alloc] init];
add.avatarImage = TUIGroupCommonBundleImage(@"add");
add.tag = 1;
[tmpArray addObject:add];
}
if ([self.groupInfo canRemoveMember]) {
TUIGroupMemberCellData *delete = [[TUIGroupMemberCellData alloc] init];
delete.avatarImage = TUIGroupCommonBundleImage(@"delete");
delete.tag = 2;
[tmpArray addObject:delete];
}
return tmpArray;
}
- (void)setGroupAddOpt:(V2TIMGroupAddOpt)opt {
@weakify(self);
V2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init];
info.groupID = self.groupID;
info.groupAddOpt = opt;
[[V2TIMManager sharedInstance] setGroupInfo:info
succ:^{
@strongify(self);
self.groupInfo.groupAddOpt = opt;
self.addOptionData.value = [TUIGroupInfoDataProvider getAddOptionWithV2AddOpt:opt];
}
fail:^(int code, NSString *desc) {
[TUITool makeToastError:code msg:desc];
}];
}
- (void)setGroupApproveOpt:(V2TIMGroupAddOpt)opt {
@weakify(self);
V2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init];
info.groupID = self.groupID;
info.groupApproveOpt = opt;
[[V2TIMManager sharedInstance] setGroupInfo:info
succ:^{
@strongify(self);
self.groupInfo.groupApproveOpt = opt;
self.inviteOptionData.value = [TUIGroupInfoDataProvider getApproveOption:self.groupInfo];
}
fail:^(int code, NSString *desc) {
[TUITool makeToastError:code msg:desc];
}];
}
- (void)setGroupReceiveMessageOpt:(V2TIMReceiveMessageOpt)opt Succ:(V2TIMSucc)succ fail:(V2TIMFail)fail {
[[V2TIMManager sharedInstance] setGroupReceiveMessageOpt:self.groupID opt:opt succ:succ fail:fail];
}
- (void)setGroupName:(NSString *)groupName {
V2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init];
info.groupID = self.groupID;
info.groupName = groupName;
@weakify(self);
[[V2TIMManager sharedInstance] setGroupInfo:info
succ:^{
@strongify(self);
self.profileCellData.name = groupName;
}
fail:^(int code, NSString *msg) {
[TUITool makeToastError:code msg:msg];
}];
}
- (void)setGroupNotification:(NSString *)notification {
V2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init];
info.groupID = self.groupID;
info.notification = notification;
@weakify(self);
[[V2TIMManager sharedInstance] setGroupInfo:info
succ:^{
@strongify(self);
self.profileCellData.signature = notification;
}
fail:^(int code, NSString *msg) {
[TUITool makeToastError:code msg:msg];
}];
}
- (void)setGroupMemberNameCard:(NSString *)nameCard {
NSString *userID = [V2TIMManager sharedInstance].getLoginUser;
V2TIMGroupMemberFullInfo *info = [[V2TIMGroupMemberFullInfo alloc] init];
info.userID = userID;
info.nameCard = nameCard;
@weakify(self);
[[V2TIMManager sharedInstance] setGroupMemberInfo:self.groupID
info:info
succ:^{
@strongify(self);
self.groupNickNameCellData.value = nameCard;
self.selfInfo.nameCard = nameCard;
}
fail:^(int code, NSString *msg) {
[TUITool makeToastError:code msg:msg];
}];
}
- (void)dismissGroup:(V2TIMSucc)succ fail:(V2TIMFail)fail {
[[V2TIMManager sharedInstance] dismissGroup:self.groupID succ:succ fail:fail];
}
- (void)quitGroup:(V2TIMSucc)succ fail:(V2TIMFail)fail {
[[V2TIMManager sharedInstance] quitGroup:self.groupID succ:succ fail:fail];
}
- (void)clearAllHistory:(V2TIMSucc)succ fail:(V2TIMFail)fail {
[V2TIMManager.sharedInstance clearGroupHistoryMessage:self.groupID succ:succ fail:fail];
}
+ (NSString *)getGroupTypeName:(V2TIMGroupInfo *)groupInfo {
if (groupInfo.groupType) {
if ([groupInfo.groupType isEqualToString:@"Work"]) {
return TIMCommonLocalizableString(TUIKitWorkGroup);
} else if ([groupInfo.groupType isEqualToString:@"Public"]) {
return TIMCommonLocalizableString(TUIKitPublicGroup);
} else if ([groupInfo.groupType isEqualToString:@"Meeting"]) {
return TIMCommonLocalizableString(TUIKitChatRoom);
} else if ([groupInfo.groupType isEqualToString:@"Community"]) {
return TIMCommonLocalizableString(TUIKitCommunity);
}
}
return @"";
}
+ (NSString *)getAddOption:(V2TIMGroupInfo *)groupInfo {
switch (groupInfo.groupAddOpt) {
case V2TIM_GROUP_ADD_FORBID:
return TIMCommonLocalizableString(TUIKitGroupProfileJoinDisable);
break;
case V2TIM_GROUP_ADD_AUTH:
return TIMCommonLocalizableString(TUIKitGroupProfileAdminApprove);
break;
case V2TIM_GROUP_ADD_ANY:
return TIMCommonLocalizableString(TUIKitGroupProfileAutoApproval);
break;
default:
break;
}
return @"";
}
+ (NSString *)getAddOptionWithV2AddOpt:(V2TIMGroupAddOpt)opt {
switch (opt) {
case V2TIM_GROUP_ADD_FORBID:
return TIMCommonLocalizableString(TUIKitGroupProfileJoinDisable);
break;
case V2TIM_GROUP_ADD_AUTH:
return TIMCommonLocalizableString(TUIKitGroupProfileAdminApprove);
break;
case V2TIM_GROUP_ADD_ANY:
return TIMCommonLocalizableString(TUIKitGroupProfileAutoApproval);
break;
default:
break;
}
return @"";
}
+ (NSString *)getApproveOption:(V2TIMGroupInfo *)groupInfo {
switch (groupInfo.groupApproveOpt) {
case V2TIM_GROUP_ADD_FORBID:
return TIMCommonLocalizableString(TUIKitGroupProfileInviteDisable);
break;
case V2TIM_GROUP_ADD_AUTH:
return TIMCommonLocalizableString(TUIKitGroupProfileAdminApprove);
break;
case V2TIM_GROUP_ADD_ANY:
return TIMCommonLocalizableString(TUIKitGroupProfileAutoApproval);
break;
default:
break;
}
return @"";
}
+ (BOOL)isMarkedByFoldType:(NSArray *)markList {
for (NSNumber *num in markList) {
if (num.unsignedLongValue == V2TIM_CONVERSATION_MARK_TYPE_FOLD) {
return YES;
}
}
return NO;
}
+ (BOOL)isMarkedByHideType:(NSArray *)markList {
for (NSNumber *num in markList) {
if (num.unsignedLongValue == V2TIM_CONVERSATION_MARK_TYPE_HIDE) {
return YES;
}
}
return NO;
}
+ (BOOL)isMeOwner:(V2TIMGroupInfo *)groupInfo {
return [groupInfo.owner isEqualToString:[[V2TIMManager sharedInstance] getLoginUser]] || (groupInfo.role == V2TIM_GROUP_MEMBER_ROLE_ADMIN);
}
+ (BOOL)isMeSuper:(V2TIMGroupInfo *)groupInfo {
return [groupInfo.owner isEqualToString:[[V2TIMManager sharedInstance] getLoginUser]] && (groupInfo.role == V2TIM_GROUP_MEMBER_ROLE_SUPER);
}
@end

View File

@@ -0,0 +1,44 @@
//
// TUIGroupManageDataProvider.h
// TUIGroup
//
// Created by harvy on 2021/12/24.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
@class TUIUserModel;
NS_ASSUME_NONNULL_BEGIN
@protocol TUIGroupManageDataProviderDelegate <NSObject>
- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadData;
- (void)showCoverViewWhenMuteAll:(BOOL)show;
- (void)insertRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- (void)onError:(int)code desc:(NSString *)desc operate:(NSString *)operate;
@end
@interface TUIGroupManageDataProvider : NSObject
@property(nonatomic, assign) BOOL muteAll;
@property(nonatomic, copy) NSString *groupID;
@property(nonatomic, assign) BOOL currentGroupTypeSupportSettingAdmin;
@property(nonatomic, assign) BOOL currentGroupTypeSupportAddMemberOfBlocked;
@property(nonatomic, weak) id<TUIGroupManageDataProviderDelegate> delegate;
@property(nonatomic, strong, readonly) NSMutableArray *datas;
- (void)loadData;
- (void)mutedAll:(BOOL)mute completion:(void (^)(int, NSString *))completion;
- (void)mute:(BOOL)mute user:(TUIUserModel *)user;
- (void)updateMuteMembersFilterAdmins;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,285 @@
//
// TUIGroupManageDataProvider.m
// TUIGroup
//
// Created by harvy on 2021/12/24.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIGroupManageDataProvider.h"
#import <ImSDK_Plus/ImSDK_Plus.h>
#import <TUICore/TUIGlobalization.h>
#import "TUIMemberInfoCellData.h"
#import "TUISelectGroupMemberCell.h"
@interface TUIGroupManageDataProvider ()
@property(nonatomic, strong) NSMutableArray *datas;
@property(nonatomic, strong) NSMutableArray *groupInfoDatasArray;
@property(nonatomic, strong) NSMutableArray *muteMembersDataArray;
@property(nonatomic, strong) V2TIMGroupInfo *groupInfo;
@end
@implementation TUIGroupManageDataProvider
- (void)mutedAll:(BOOL)mute completion:(void (^)(int, NSString *))completion {
__weak typeof(self) weakSelf = self;
V2TIMGroupInfo *groupInfo = [[V2TIMGroupInfo alloc] init];
groupInfo.groupID = self.groupID;
groupInfo.allMuted = mute;
[V2TIMManager.sharedInstance setGroupInfo:groupInfo
succ:^{
weakSelf.muteAll = mute;
weakSelf.groupInfo.allMuted = mute;
[weakSelf setupGroupInfo:weakSelf.groupInfo];
if (completion) {
completion(0, nil);
}
}
fail:^(int code, NSString *desc) {
weakSelf.muteAll = !mute;
if (completion) {
completion(code, desc);
}
}];
}
- (void)mute:(BOOL)mute user:(TUIUserModel *)user {
if (!NSThread.isMainThread) {
@weakify(self);
dispatch_async(dispatch_get_main_queue(), ^{
@strongify(self);
[self mute:mute user:user];
});
return;
}
__weak typeof(self) weakSelf = self;
void (^callback)(int, NSString *, BOOL) = ^(int code, NSString *desc, BOOL mute) {
dispatch_async(dispatch_get_main_queue(), ^{
TUIMemberInfoCellData *existData = nil;
for (TUIMemberInfoCellData *data in weakSelf.muteMembersDataArray) {
if ([data.identifier isEqualToString:user.userId]) {
existData = data;
break;
}
}
if (code == 0 && mute) {
// mute succ
if (!existData) {
TUIMemberInfoCellData *cellData = [[TUIMemberInfoCellData alloc] init];
cellData.identifier = user.userId;
cellData.name = user.name ?: user.userId;
cellData.avatarUrl = user.avatar;
[weakSelf.muteMembersDataArray addObject:cellData];
}
} else if (code == 0 && !mute) {
// unmute succ
if (existData) {
[weakSelf.muteMembersDataArray removeObject:existData];
}
} else {
// fail
if ([weakSelf.delegate respondsToSelector:@selector(onError:desc:operate:)]) {
[weakSelf.delegate onError:code
desc:desc
operate:mute ?
TIMCommonLocalizableString(TUIKitGroupShutupOption) :
TIMCommonLocalizableString(TUIKitGroupDisShutupOption)
];
}
}
if ([weakSelf.delegate respondsToSelector:@selector(reloadData)]) {
[weakSelf.delegate reloadData];
}
});
};
[V2TIMManager.sharedInstance muteGroupMember:self.groupID
member:user.userId
muteTime:mute ? 365 * 24 * 3600 : 0
succ:^{
callback(0, nil, mute);
}
fail:^(int code, NSString *desc) {
callback(code, desc, mute);
}];
}
- (void)loadData {
self.groupInfoDatasArray = [NSMutableArray array];
self.muteMembersDataArray = [NSMutableArray array];
self.datas = [NSMutableArray arrayWithArray:@[ self.groupInfoDatasArray, self.muteMembersDataArray ]];
@weakify(self);
[V2TIMManager.sharedInstance getGroupsInfo:@[ self.groupID ?: @"" ]
succ:^(NSArray<V2TIMGroupInfoResult *> *groupResultList) {
@strongify(self);
V2TIMGroupInfoResult *result = groupResultList.firstObject;
if (result == nil || result.resultCode != 0) {
return;
}
V2TIMGroupInfo *groupInfo = result.info;
self.groupInfo = groupInfo;
[self setupGroupInfo:groupInfo];
self.muteAll = groupInfo.allMuted;
self.currentGroupTypeSupportSettingAdmin = [self canSupportSettingAdminAtThisGroupType:groupInfo.groupType];
self.currentGroupTypeSupportAddMemberOfBlocked = [self canSupportAddMemberOfBlockedAtThisGroupType:groupInfo.groupType];
}
fail:^(int code, NSString *desc) {
@strongify(self);
[self setupGroupInfo:nil];
}];
[self loadMuteMembers];
}
- (void)loadMuteMembers {
if (!NSThread.isMainThread) {
@weakify(self);
dispatch_async(dispatch_get_main_queue(), ^{
@strongify(self);
[self loadMuteMembers];
});
}
[self.muteMembersDataArray removeAllObjects];
if ([self.delegate respondsToSelector:@selector(reloadData)]) {
[self.delegate reloadData];
}
TUIMemberInfoCellData *add = [[TUIMemberInfoCellData alloc] init];
add.avatar = TUIGroupCommonBundleImage(@"icon_add");
add.name = TIMCommonLocalizableString(TUIKitGroupAddShutupMember);
add.style = TUIMemberInfoCellStyleAdd;
[self.muteMembersDataArray addObject:add];
if ([self.delegate respondsToSelector:@selector(insertRowsAtIndexPaths:withRowAnimation:)]) {
[self.delegate insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:0 inSection:1] ] withRowAnimation:UITableViewRowAnimationNone];
}
[self setupGroupMembers:0 first:YES];
}
- (void)setupGroupMembers:(uint64_t)seq first:(uint64_t)first {
if (seq == 0 && !first) {
return;
}
__weak typeof(self) weakSelf = self;
[V2TIMManager.sharedInstance
getGroupMemberList:self.groupID
filter:V2TIM_GROUP_MEMBER_FILTER_ALL
nextSeq:0
succ:^(uint64_t nextSeq, NSArray<V2TIMGroupMemberFullInfo *> *memberList) {
NSMutableArray *indexPaths = [NSMutableArray array];
for (V2TIMGroupMemberFullInfo *info in memberList) {
if (info.muteUntil && info.muteUntil > [NSDate.new timeIntervalSince1970]) {
TUIMemberInfoCellData *member = [[TUIMemberInfoCellData alloc] init];
member.avatarUrl = info.faceURL;
member.name = (info.nameCard ?: info.nickName) ?: info.userID;
member.identifier = info.userID;
BOOL exist = NO;
for (TUIMemberInfoCellData *data in weakSelf.muteMembersDataArray) {
if ([data.identifier isEqualToString:info.userID]) {
exist = YES;
break;
}
}
BOOL isSuper = (info.role == V2TIM_GROUP_MEMBER_ROLE_SUPER);
BOOL isAdMin = (info.role == V2TIM_GROUP_MEMBER_ROLE_ADMIN);
BOOL allowShowInMuteList = YES;
if (isSuper || isAdMin) {
allowShowInMuteList = NO;
}
if (!exist && allowShowInMuteList) {
[weakSelf.muteMembersDataArray addObject:member];
[indexPaths addObject:[NSIndexPath indexPathForRow:[weakSelf.muteMembersDataArray indexOfObject:member] inSection:1]];
}
}
}
if (indexPaths.count) {
if ([weakSelf.delegate respondsToSelector:@selector(insertRowsAtIndexPaths:withRowAnimation:)]) {
[weakSelf.delegate insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
}
}
[weakSelf setupGroupMembers:nextSeq first:NO];
}
fail:^(int code, NSString *desc){
}];
}
- (void)setupGroupInfo:(V2TIMGroupInfo *)groupInfo {
if (!NSThread.isMainThread) {
@weakify(self);
dispatch_async(dispatch_get_main_queue(), ^{
@strongify(self);
[self setupGroupInfo:groupInfo];
});
return;
}
if (groupInfo == nil) {
return;
}
[self.groupInfoDatasArray removeAllObjects];
TUICommonTextCellData *adminSetting = [[TUICommonTextCellData alloc] init];
adminSetting.key = TIMCommonLocalizableString(TUIKitGroupManageAdminSetting);
adminSetting.value = @"";
adminSetting.showAccessory = YES;
adminSetting.cselector = @selector(onSettingAdmin:);
[self.groupInfoDatasArray addObject:adminSetting];
TUICommonSwitchCellData *shutupAll = [[TUICommonSwitchCellData alloc] init];
shutupAll.title = TIMCommonLocalizableString(TUIKitGroupManageShutAll);
shutupAll.on = groupInfo.allMuted;
shutupAll.cswitchSelector = @selector(onMutedAll:);
[self.groupInfoDatasArray addObject:shutupAll];
if ([self.delegate respondsToSelector:@selector(reloadData)]) {
[self.delegate reloadData];
}
}
//- (void)onMutedAll:(TUICommonSwitchCellData *)switchData
//{
// if ([self.delegate respondsToSelector:@selector(onMutedAll:)]) {
// [self.delegate onMutedAll:switchData.isOn];
// }
//}
- (void)updateMuteMembersFilterAdmins {
[self loadMuteMembers];
}
- (NSMutableArray *)datas {
if (_datas == nil) {
_datas = [NSMutableArray array];
}
return _datas;
}
- (BOOL)canSupportSettingAdminAtThisGroupType:(NSString *)grouptype {
if ([grouptype isEqualToString:@"Work"] || [grouptype isEqualToString:@"AVChatRoom"]) {
return NO;
}
return YES;
}
- (BOOL)canSupportAddMemberOfBlockedAtThisGroupType:(NSString *)grouptype {
if ([grouptype isEqualToString:@"Work"]) {
return NO;
}
return YES;
}
@end

View File

@@ -0,0 +1,24 @@
//
// TUIGroupMemberDataProvider.h
// TXIMSDK_TUIKit_iOS
//
// Created by xiangzhang on 2021/7/2.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
@import ImSDK_Plus;
@class TUIGroupMemberCellData;
NS_ASSUME_NONNULL_BEGIN
@interface TUIGroupMemberDataProvider : NSObject
@property(nonatomic, strong) V2TIMGroupInfo *groupInfo;
@property(nonatomic, assign) BOOL isNoMoreData;
- (instancetype)initWithGroupID:(NSString *)groupID;
- (void)loadDatas:(void (^)(BOOL success, NSString *err, NSArray *datas))completion;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,86 @@
//
// TUIGroupMemberDataProvider.m
// TXIMSDK_TUIKit_iOS
//
// Created by xiangzhang on 2021/7/2.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIGroupMemberDataProvider.h"
#import <TIMCommon/TIMDefine.h>
#import "TUIMemberInfoCellData.h"
@interface TUIGroupMemberDataProvider ()
@property(nonatomic, strong) NSString *groupID;
@property(nonatomic, assign) NSUInteger index;
@end
@implementation TUIGroupMemberDataProvider
- (instancetype)initWithGroupID:(NSString *)groupID {
self = [super init];
if (self) {
self.groupID = groupID;
}
return self;
}
- (void)loadDatas:(void (^)(BOOL success, NSString *err, NSArray *datas))completion {
@weakify(self);
[[V2TIMManager sharedInstance] getGroupMemberList:self.groupID
filter:V2TIM_GROUP_MEMBER_FILTER_ALL
nextSeq:self.index
succ:^(uint64_t nextSeq, NSArray<V2TIMGroupMemberFullInfo *> *memberList) {
@strongify(self);
self.index = nextSeq;
self.isNoMoreData = (nextSeq == 0);
NSMutableArray *arrayM = [NSMutableArray array];
NSMutableArray *ids = [NSMutableArray array];
NSMutableDictionary *map = [NSMutableDictionary dictionary];
for (V2TIMGroupMemberFullInfo *member in memberList) {
TUIMemberInfoCellData *user = [[TUIMemberInfoCellData alloc] init];
user.identifier = member.userID;
user.role = member.role;
if (member.nameCard.length > 0) {
user.name = member.nameCard;
} else if (member.friendRemark.length > 0) {
user.name = member.friendRemark;
} else if (member.nickName.length > 0) {
user.name = member.nickName;
} else {
user.name = member.userID;
}
[arrayM addObject:user];
[ids addObject:user.identifier];
if (user.identifier && user) {
map[user.identifier] = user;
}
}
[[V2TIMManager sharedInstance] getUsersInfo:ids
succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
NSArray *userIDs = map.allKeys;
for (V2TIMUserFullInfo *info in infoList) {
if (![userIDs containsObject:info.userID]) {
continue;
}
TUIMemberInfoCellData *user = map[info.userID];
user.avatarUrl = info.faceURL;
}
if (completion) {
completion(YES, @"", arrayM);
}
}
fail:^(int code, NSString *desc) {
if (completion) {
completion(NO, desc, @[]);
}
}];
}
fail:^(int code, NSString *msg) {
if (completion) {
completion(NO, msg, @[]);
}
}];
}
@end

View File

@@ -0,0 +1,25 @@
//
// TUIGroupNoticeDataProvider.h
// TUIGroup
//
// Created by harvy on 2022/1/12.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <ImSDK_Plus/ImSDK_Plus.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUIGroupNoticeDataProvider : NSObject
@property(nonatomic, strong, readonly) V2TIMGroupInfo *groupInfo;
@property(nonatomic, copy) NSString *groupID;
- (void)getGroupInfo:(dispatch_block_t)callback;
- (BOOL)canEditNotice;
- (void)updateNotice:(NSString *)notice callback:(void (^)(int, NSString *))callback;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,76 @@
//
// TUIGroupNoticeDataProvider.m
// TUIGroup
//
// Created by harvy on 2022/1/12.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIGroupNoticeDataProvider.h"
@interface TUIGroupNoticeDataProvider ()
@property(nonatomic, strong) V2TIMGroupInfo *groupInfo;
@end
@implementation TUIGroupNoticeDataProvider
- (void)getGroupInfo:(dispatch_block_t)callback {
if (self.groupInfo && [self.groupInfo.groupID isEqual:self.groupID]) {
if (callback) {
callback();
}
return;
}
__weak typeof(self) weakSelf = self;
[V2TIMManager.sharedInstance getGroupsInfo:@[ self.groupID ?: @"" ]
succ:^(NSArray<V2TIMGroupInfoResult *> *groupResultList) {
V2TIMGroupInfoResult *result = groupResultList.firstObject;
if (result && result.resultCode == 0) {
weakSelf.groupInfo = result.info;
}
if (callback) {
callback();
}
}
fail:^(int code, NSString *desc) {
if (callback) {
callback();
}
}];
}
- (BOOL)canEditNotice {
return self.groupInfo.role == V2TIM_GROUP_MEMBER_ROLE_ADMIN || self.groupInfo.role == V2TIM_GROUP_MEMBER_ROLE_SUPER;
}
- (void)updateNotice:(NSString *)notice callback:(void (^)(int, NSString *))callback {
V2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init];
info.groupID = self.groupID;
info.notification = notice;
__weak typeof(self) weakSelf = self;
[V2TIMManager.sharedInstance setGroupInfo:info
succ:^{
if (callback) {
callback(0, nil);
}
[weakSelf sendNoticeMessage:notice];
}
fail:^(int code, NSString *desc) {
if (callback) {
callback(code, desc);
}
}];
}
- (void)sendNoticeMessage:(NSString *)notice {
if (notice.length == 0) {
return;
}
}
@end

View File

@@ -0,0 +1,29 @@
//
// TUISettingAdminDataProvider.h
// TUIGroup
//
// Created by harvy on 2021/12/28.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
@class TUIUserModel;
NS_ASSUME_NONNULL_BEGIN
@interface TUISettingAdminDataProvider : NSObject
@property(nonatomic, copy) NSString *groupID;
@property(nonatomic, strong, readonly) NSMutableArray *datas;
@property(nonatomic, strong, readonly) NSMutableArray *owners;
@property(nonatomic, strong, readonly) NSMutableArray *admins;
- (void)loadData:(void (^)(int, NSString *))callback;
- (void)removeAdmin:(NSString *)userID callback:(void (^)(int, NSString *))callback;
- (void)settingAdmins:(NSArray<TUIUserModel *> *)userModels callback:(void (^)(int, NSString *))callback;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,212 @@
//
// TUISettingAdminDataProvider.m
// TUIGroup
//
// Created by harvy on 2021/12/28.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUISettingAdminDataProvider.h"
#import <ImSDK_Plus/ImSDK_Plus.h>
#import <TIMCommon/TIMDefine.h>
#import "TUIMemberInfoCellData.h"
@interface TUISettingAdminDataProvider ()
@property(nonatomic, strong) NSMutableArray *datas;
@property(nonatomic, strong) NSMutableArray *owners;
@property(nonatomic, strong) NSMutableArray *admins;
@end
@implementation TUISettingAdminDataProvider
- (void)removeAdmin:(NSString *)userID callback:(void (^)(int, NSString *))callback {
__weak typeof(self) weakSelf = self;
[V2TIMManager.sharedInstance setGroupMemberRole:self.groupID
member:userID
newRole:V2TIM_GROUP_MEMBER_ROLE_MEMBER
succ:^{
TUIMemberInfoCellData *exist = [self existAdmin:userID];
if (exist) {
[weakSelf.admins removeObject:exist];
}
if (callback) {
callback(0, nil);
}
}
fail:^(int code, NSString *desc) {
if (callback) {
callback(code, desc);
}
}];
}
- (void)settingAdmins:(NSArray<TUIUserModel *> *)userModels callback:(void (^)(int, NSString *))callback;
{
NSMutableArray *validUsers = [NSMutableArray array];
for (TUIUserModel *user in userModels) {
TUIMemberInfoCellData *exist = [self existAdmin:user.userId];
if (!exist) {
TUIMemberInfoCellData *data = [[TUIMemberInfoCellData alloc] init];
data.identifier = user.userId;
data.name = user.name;
data.avatarUrl = user.avatar;
[validUsers addObject:data];
}
}
if (validUsers.count == 0) {
if (callback) {
callback(0, nil);
}
return;
}
if (self.admins.count + validUsers.count > 11) {
if (callback) {
callback(-1, @"The number of administrator must be less than ten");
}
return;
}
__block int errorCode = 0;
__block NSString *errorMsg = nil;
NSMutableArray *results = [NSMutableArray array];
dispatch_group_t group = dispatch_group_create();
for (TUIMemberInfoCellData *data in validUsers) {
dispatch_group_enter(group);
[V2TIMManager.sharedInstance setGroupMemberRole:self.groupID
member:data.identifier
newRole:V2TIM_GROUP_MEMBER_ROLE_ADMIN
succ:^{
[results addObject:data];
dispatch_group_leave(group);
}
fail:^(int code, NSString *desc) {
if (errorCode == 0) {
errorCode = code;
errorMsg = desc;
}
dispatch_group_leave(group);
}];
}
__weak typeof(self) weakSelf = self;
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
[weakSelf.admins addObjectsFromArray:results];
if (callback) {
callback(errorCode, errorMsg);
}
});
}
- (void)loadData:(void (^)(int, NSString *))callback {
{
TUIMemberInfoCellData *add = [[TUIMemberInfoCellData alloc] init];
add.style = TUIMemberInfoCellStyleAdd;
add.name = TIMCommonLocalizableString(TUIKitGroupAddAdmins);
add.avatar = TUIGroupCommonBundleImage(@"icon_add");
[self.admins addObject:add];
}
__weak typeof(self) weakSelf = self;
__block int errorCode = 0;
__block NSString *errorMsg = nil;
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
[V2TIMManager.sharedInstance getGroupMemberList:self.groupID
filter:V2TIM_GROUP_MEMBER_FILTER_OWNER
nextSeq:0
succ:^(uint64_t nextSeq, NSArray<V2TIMGroupMemberFullInfo *> *memberList) {
for (V2TIMGroupMemberFullInfo *info in memberList) {
TUIMemberInfoCellData *cellData = [[TUIMemberInfoCellData alloc] init];
cellData.identifier = info.userID;
cellData.name = (info.nameCard ?: info.nickName) ?: info.userID;
cellData.avatarUrl = info.faceURL;
if (info.role == V2TIM_GROUP_MEMBER_ROLE_SUPER) {
[weakSelf.owners addObject:cellData];
}
}
dispatch_group_leave(group);
}
fail:^(int code, NSString *desc) {
if (errorCode == 0) {
errorCode = code;
errorMsg = desc;
}
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
[V2TIMManager.sharedInstance getGroupMemberList:self.groupID
filter:V2TIM_GROUP_MEMBER_FILTER_ADMIN
nextSeq:0
succ:^(uint64_t nextSeq, NSArray<V2TIMGroupMemberFullInfo *> *memberList) {
for (V2TIMGroupMemberFullInfo *info in memberList) {
TUIMemberInfoCellData *cellData = [[TUIMemberInfoCellData alloc] init];
cellData.identifier = info.userID;
cellData.name = (info.nameCard ?: info.nickName) ?: info.userID;
cellData.avatarUrl = info.faceURL;
if (info.role == V2TIM_GROUP_MEMBER_ROLE_ADMIN) {
[weakSelf.admins addObject:cellData];
}
}
dispatch_group_leave(group);
}
fail:^(int code, NSString *desc) {
if (errorCode == 0) {
errorCode = code;
errorMsg = desc;
}
dispatch_group_leave(group);
}];
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
weakSelf.datas = [NSMutableArray arrayWithArray:@[ weakSelf.owners, weakSelf.admins ]];
if (callback) {
callback(errorCode, errorMsg);
}
});
}
- (TUIMemberInfoCellData *)existAdmin:(NSString *)userID {
TUIMemberInfoCellData *exist = nil;
for (TUIMemberInfoCellData *data in self.admins) {
if ([data.identifier isEqual:userID]) {
exist = data;
break;
}
}
return exist;
}
- (NSMutableArray *)datas {
if (_datas == nil) {
_datas = [NSMutableArray array];
}
return _datas;
}
- (NSMutableArray *)owners {
if (_owners == nil) {
_owners = [NSMutableArray array];
}
return _owners;
}
- (NSMutableArray *)admins {
if (_admins == nil) {
_admins = [NSMutableArray array];
}
return _admins;
}
@end

View File

@@ -0,0 +1,42 @@
//
// TUIGroupConfig.h
// TUIGroup
//
// Created by Tencent on 2024/9/6.
// Copyright © 2024 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_OPTIONS(NSInteger, TUIGroupConfigItem) {
TUIGroupConfigItem_None = 0,
TUIGroupConfigItem_Members = 1 << 0,
TUIGroupConfigItem_Notice = 1 << 1,
TUIGroupConfigItem_Manage = 1 << 2,
TUIGroupConfigItem_Alias = 1 << 3,
TUIGroupConfigItem_MuteAndPin = 1 << 4,
TUIGroupConfigItem_Background = 1 << 5,
TUIGroupConfigItem_ClearChatHistory = 1 << 6,
TUIGroupConfigItem_DeleteAndLeave = 1 << 7,
TUIGroupConfigItem_Transfer = 1 << 8,
TUIGroupConfigItem_Dismiss = 1 << 9,
TUIGroupConfigItem_Report = 1 << 10,
};
@interface TUIGroupConfig : NSObject
+ (TUIGroupConfig *)sharedConfig;
/**
* Hide items in group config interface.
*/
- (void)hideItemsInGroupConfig:(TUIGroupConfigItem)items;
/**
* Get the hidden status of specified item.
*/
- (BOOL)isItemHiddenInGroupConfig:(TUIGroupConfigItem)item;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,75 @@
//
// TUIGroupConfig.m
// TUIGroup
//
// Created by Tencent on 2024/9/6.
// Copyright © 2024 Tencent. All rights reserved.
//
#import "TUIGroupConfig.h"
@interface TUIGroupConfig()
@property (nonatomic, assign) BOOL hideGroupMembersItems;
@property (nonatomic, assign) BOOL hideGroupNoticeItem;
@property (nonatomic, assign) BOOL hideGroupManageItems;
@property (nonatomic, assign) BOOL hideGroupAliasItem;
@property (nonatomic, assign) BOOL hideGroupMuteAndPinItems;
@property (nonatomic, assign) BOOL hideGroupBackgroundItem;
@property (nonatomic, assign) BOOL hideGroupClearChatHistory;
@property (nonatomic, assign) BOOL hideGroupDeleteAndLeave;
@property (nonatomic, assign) BOOL hideGroupTransfer;
@property (nonatomic, assign) BOOL hideGroupDismiss;
@property (nonatomic, assign) BOOL hideGroupReport;
@end
@implementation TUIGroupConfig
+ (TUIGroupConfig *)sharedConfig {
static dispatch_once_t onceToken;
static TUIGroupConfig *config;
dispatch_once(&onceToken, ^{
config = [[TUIGroupConfig alloc] init];
});
return config;
}
- (void)hideItemsInGroupConfig:(TUIGroupConfigItem)items {
self.hideGroupMuteAndPinItems = items & TUIGroupConfigItem_MuteAndPin;
self.hideGroupManageItems = items & TUIGroupConfigItem_Manage;
self.hideGroupAliasItem = items & TUIGroupConfigItem_Alias;
self.hideGroupBackgroundItem = items & TUIGroupConfigItem_Background;
self.hideGroupMembersItems = items & TUIGroupConfigItem_Members;
self.hideGroupClearChatHistory = items & TUIGroupConfigItem_ClearChatHistory;
self.hideGroupDeleteAndLeave = items & TUIGroupConfigItem_DeleteAndLeave;
self.hideGroupTransfer = items & TUIGroupConfigItem_Transfer;
self.hideGroupDismiss = items & TUIGroupConfigItem_Dismiss;
self.hideGroupReport = items & TUIGroupConfigItem_Report;
}
- (BOOL)isItemHiddenInGroupConfig:(TUIGroupConfigItem)item {
if (item & TUIGroupConfigItem_MuteAndPin) {
return self.hideGroupMuteAndPinItems;
} else if (item & TUIGroupConfigItem_Manage) {
return self.hideGroupManageItems;
} else if (item & TUIGroupConfigItem_Alias) {
return self.hideGroupAliasItem;
} else if (item & TUIGroupConfigItem_Background) {
return self.hideGroupBackgroundItem;
} else if (item & TUIGroupConfigItem_Members) {
return self.hideGroupMembersItems;
} else if (item & TUIGroupConfigItem_ClearChatHistory) {
return self.hideGroupClearChatHistory;
} else if (item & TUIGroupConfigItem_DeleteAndLeave) {
return self.hideGroupDeleteAndLeave;
} else if (item & TUIGroupConfigItem_Transfer) {
return self.hideGroupTransfer;
} else if (item & TUIGroupConfigItem_Dismiss) {
return self.hideGroupDismiss;
} else if (item & TUIGroupConfigItem_Report) {
return self.hideGroupReport;
} else {
return NO;
}
}
@end

View File

@@ -0,0 +1,23 @@
//
// TUIChatDefine.h
// Pods
//
// Created by xiangzhang on 2022/10/14.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <TIMCommon/TIMCommonModel.h>
#ifndef TUIGroupDefine_h
#define TUIGroupDefine_h
typedef NS_ENUM(NSInteger, TUISelectMemberOptionalStyle) {
TUISelectMemberOptionalStyleNone = 0,
TUISelectMemberOptionalStyleAtAll = 1 << 0,
TUISelectMemberOptionalStyleTransferOwner = 1 << 1,
TUISelectMemberOptionalStylePublicMan = 1 << 2
};
typedef void (^SelectedFinished)(NSMutableArray<TUIUserModel *> *modelList);
#endif /* TUIGroupDefine_h */

View File

@@ -0,0 +1,39 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import <UIKit/UIKit.h>
#import "TUIGroupMemberCell.h"
@class TUIGroupMembersView;
/////////////////////////////////////////////////////////////////////////////////
//
// TUIGroupMembersViewDelegate
//
/////////////////////////////////////////////////////////////////////////////////
@protocol TUIGroupMembersViewDelegate <NSObject>
- (void)groupMembersView:(TUIGroupMembersView *)groupMembersView didSelectGroupMember:(TUIGroupMemberCellData *)groupMember;
- (void)groupMembersView:(TUIGroupMembersView *)groupMembersView didLoadMoreData:(void (^)(NSArray<TUIGroupMemberCellData *> *))completion;
@end
/////////////////////////////////////////////////////////////////////////////////
//
// TUIGroupMembersView
//
/////////////////////////////////////////////////////////////////////////////////
@interface TUIGroupMembersView : UIView
@property(nonatomic, strong) UISearchBar *searchBar;
@property(nonatomic, strong) UICollectionView *collectionView;
@property(nonatomic, strong) UICollectionViewFlowLayout *flowLayout;
@property(nonatomic, weak) id<TUIGroupMembersViewDelegate> delegate;
@property(nonatomic, strong) UIActivityIndicatorView *indicatorView;
- (void)setData:(NSMutableArray<TUIGroupMemberCellData *> *)data;
@end

View File

@@ -0,0 +1,142 @@
//
// TUIGroupMembersView.m
// TUIKit
//
// Created by kennethmiao on 2018/10/11.
// Copyright © 2018 Tencent. All rights reserved.
//
#import "TUIGroupMembersView.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIGlobalization.h>
@interface TUIGroupMembersView () <UISearchBarDelegate, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
@property(nonatomic, strong) NSMutableArray<TUIGroupMemberCellData *> *data;
@end
@implementation TUIGroupMembersView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setupViews];
}
return self;
}
- (void)setupViews {
self.backgroundColor = [UIColor whiteColor];
_flowLayout = [[UICollectionViewFlowLayout alloc] init];
_flowLayout.headerReferenceSize = CGSizeMake(self.frame.size.width, TGroupMembersController_Margin);
CGSize cellSize = [TUIGroupMemberCell getSize];
CGFloat y = _searchBar.frame.origin.y + _searchBar.frame.size.height;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(TGroupMembersController_Margin, y,
self.frame.size.width - 2 * TGroupMembersController_Margin, self.frame.size.height - y)
collectionViewLayout:_flowLayout];
[_collectionView registerClass:[TUIGroupMemberCell class] forCellWithReuseIdentifier:TGroupMemberCell_ReuseId];
_collectionView.collectionViewLayout = _flowLayout;
_collectionView.delegate = self;
_collectionView.dataSource = self;
_collectionView.showsHorizontalScrollIndicator = NO;
_collectionView.showsVerticalScrollIndicator = NO;
_collectionView.backgroundColor = [UIColor clearColor];
_collectionView.contentInset = UIEdgeInsetsMake(0, 0, TMessageController_Header_Height, 0);
[self addSubview:_collectionView];
_indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
_indicatorView.hidesWhenStopped = YES;
[self.collectionView addSubview:_indicatorView];
_flowLayout.minimumLineSpacing =
(_collectionView.frame.size.width - cellSize.width * TGroupMembersController_Row_Count) / (TGroupMembersController_Row_Count - 1);
;
_flowLayout.minimumInteritemSpacing = _flowLayout.minimumLineSpacing;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return _data.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
TUIGroupMemberCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:TGroupMemberCell_ReuseId forIndexPath:indexPath];
TUIGroupMemberCellData *data = _data[indexPath.row];
[cell setData:data];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
}
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return [TUIGroupMemberCell getSize];
}
#pragma mark - Load
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (scrollView.contentOffset.y > 0 && (scrollView.contentOffset.y >= scrollView.bounds.origin.y)) {
[self loadMoreData];
}
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
searchBar.showsCancelButton = YES;
UIButton *cancleBtn = [searchBar valueForKey:@"cancelButton"];
[cancleBtn setTitle:TIMCommonLocalizableString(Cancel) forState:UIControlStateNormal];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
searchBar.showsCancelButton = NO;
searchBar.text = @"";
[searchBar resignFirstResponder];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
searchBar.showsCancelButton = NO;
[searchBar resignFirstResponder];
[self reloadData];
}
- (void)setData:(NSMutableArray<TUIGroupMemberCellData *> *)data {
_data = data;
[self reloadData];
}
- (void)reloadData {
[self.collectionView reloadData];
[self.collectionView layoutIfNeeded];
self.indicatorView.frame = CGRectMake(0, self.collectionView.contentSize.height, self.collectionView.bounds.size.width, TMessageController_Header_Height);
if (self.collectionView.contentSize.height > self.collectionView.frame.size.height) {
[self.indicatorView startAnimating];
} else {
[self.indicatorView stopAnimating];
}
}
- (void)loadMoreData {
if (![self.delegate respondsToSelector:@selector(groupMembersView:didLoadMoreData:)]) {
CGPoint point = self.collectionView.contentOffset;
point.y -= TMessageController_Header_Height;
[self.collectionView setContentOffset:point animated:YES];
return;
}
static BOOL isLoading = NO;
if (isLoading) {
return;
}
isLoading = YES;
__weak typeof(self) weakSelf = self;
[self.delegate groupMembersView:self
didLoadMoreData:^(NSArray<TUIGroupMemberCellData *> *moreData) {
isLoading = NO;
[weakSelf.data addObjectsFromArray:moreData];
CGPoint point = self.collectionView.contentOffset;
point.y -= TMessageController_Header_Height;
[weakSelf.collectionView setContentOffset:point animated:YES];
[weakSelf reloadData];
}];
}
@end

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeUserID</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeProductPersonalization</string>
</array>
</dict>
</array>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
</dict>
</plist>

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>id</key>
<string>dark</string>
<key>name</key>
<string>黑夜</string>
<key>name_en</key>
<string>Dark</string>
<key>group_modify_view_bg_color</key>
<string>#0000007F</string>
<key>group_modify_container_view_bg_color</key>
<string>#222632</string>
<key>group_modify_title_color</key>
<string>#FFFFFFCC</string>
<key>group_modify_desc_color</key>
<string>#FFFFFF66</string>
<key>group_modify_input_bg_color</key>
<string>#FFFFFF19</string>
<key>group_modify_input_text_color</key>
<string>#FFFFFFCC</string>
<key>group_modify_confirm_enable_bg_color</key>
<string>#147AFF</string>
<key>group_nav_back_img</key>
<string>nav_back.png</string>
<key>chat_nav_more_menu_img</key>
<string>chat_nav_more_menu.png</string>
<key>group_controller_bg_color</key>
<string>#111111</string>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1020 B

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>id</key>
<string>light</string>
<key>name</key>
<string>轻量</string>
<key>name_en</key>
<string>Light</string>
<key>group_modify_view_bg_color</key>
<string>#0000007F</string>
<key>group_modify_container_view_bg_color</key>
<string>#FFFFFF</string>
<key>group_modify_title_color</key>
<string>#000000</string>
<key>group_modify_desc_color</key>
<string>#888888</string>
<key>group_modify_input_bg_color</key>
<string>#F5F5F5</string>
<key>group_modify_input_text_color</key>
<string>#000000</string>
<key>group_modify_confirm_enable_bg_color</key>
<string>#147AFF</string>
<key>group_nav_back_img</key>
<string>nav_back.png</string>
<key>chat_nav_more_menu_img</key>
<string>chat_nav_more_menu.png</string>
<key>group_controller_bg_color</key>
<string>#FFFFFF</string>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>id</key>
<string>lively</string>
<key>name</key>
<string>活泼</string>
<key>name_en</key>
<string>Lively</string>
<key>group_modify_view_bg_color</key>
<string>#0000007F</string>
<key>group_modify_container_view_bg_color</key>
<string>#FFFFFF</string>
<key>group_modify_title_color</key>
<string>#000000</string>
<key>group_modify_desc_color</key>
<string>#888888</string>
<key>group_modify_input_bg_color</key>
<string>#F5F5F5</string>
<key>group_modify_input_text_color</key>
<string>#000000</string>
<key>group_modify_confirm_enable_bg_color</key>
<string>#FF8E82</string>
<key>group_nav_back_img</key>
<string>nav_back.png</string>
<key>chat_nav_more_menu_img</key>
<string>chat_nav_more_menu.png</string>
<key>group_controller_bg_color</key>
<string>#FFFFFF</string>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 979 B

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>id</key>
<string>serious</string>
<key>name</key>
<string>严肃</string>
<key>name_en</key>
<string>Business</string>
<key>group_modify_view_bg_color</key>
<string>#0000007F</string>
<key>group_modify_container_view_bg_color</key>
<string>#FFFFFF</string>
<key>group_modify_title_color</key>
<string>#000000</string>
<key>group_modify_desc_color</key>
<string>#888888</string>
<key>group_modify_input_bg_color</key>
<string>#F5F5F5</string>
<key>group_modify_input_text_color</key>
<string>#000000</string>
<key>group_modify_confirm_enable_bg_color</key>
<string>#0052FF</string>
<key>group_nav_back_img</key>
<string>nav_back.png</string>
<key>chat_nav_more_menu_img</key>
<string>chat_nav_more_menu.png</string>
<key>group_controller_bg_color</key>
<string>#FFFFFF</string>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 979 B

View File

@@ -0,0 +1,28 @@
Pod::Spec.new do |spec|
spec.name = 'TUIGroup'
spec.version = '8.3.6498'
spec.platform = :ios
spec.ios.deployment_target = '9.0'
spec.license = { :type => 'Proprietary',
:text => <<-LICENSE
copyright 2017 tencent Ltd. All rights reserved.
LICENSE
}
spec.homepage = 'https://cloud.tencent.com/document/product/269/3794'
spec.documentation_url = 'https://cloud.tencent.com/document/product/269/9147'
spec.authors = 'tencent video cloud'
spec.summary = 'TUIGroup'
spec.dependency 'TUICore'
spec.dependency 'TIMCommon'
spec.dependency 'ReactiveObjC'
spec.requires_arc = true
spec.source = { :path => './' }
spec.source_files = '**/*.{h,m,mm,c}'
spec.resource = ['Resources/*.bundle']
spec.resource_bundle = {
"#{spec.module_name}_Privacy" => 'Resources/PrivacyInfo.xcprivacy'
}
end

View File

@@ -0,0 +1,20 @@
//
// TUIGroup.h
// Pods
//
// Created by harvy on 2022/6/9.
// Copyright © 2023 Tencent. All rights reserved.
//
#ifndef TUIGroup_h
#define TUIGroup_h
#import "TUIGroupInfoController.h"
#import "TUIGroupManageController.h"
#import "TUIGroupMemberController.h"
#import "TUIGroupRequestViewController.h"
#import "TUISearchGroupViewController.h"
#import "TUISelectGroupMemberViewController.h"
#import "TUISettingAdminController.h"
#endif /* TUIGroup_h */

View File

@@ -0,0 +1,17 @@
//
// TUIGroupExtensionObserver.h
// TUIGroup
//
// Created by harvy on 2023/3/29.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUIGroupExtensionObserver : NSObject
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,68 @@
//
// TUIGroupExtensionObserver.m
// TUIGroup
//
// Created by harvy on 2023/3/29.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIGroupExtensionObserver.h"
#import <TIMCommon/TIMCommonModel.h>
#import <TUICore/TUICore.h>
#import "TUIGroupInfoController.h"
@interface TUIGroupExtensionObserver () <TUIExtensionProtocol>
@end
@implementation TUIGroupExtensionObserver
+ (void)load {
[TUICore registerExtension:TUICore_TUIChatExtension_NavigationMoreItem_ClassicExtensionID object:TUIGroupExtensionObserver.shareInstance];
}
+ (instancetype)shareInstance {
static dispatch_once_t onceToken;
static id instance = nil;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
#pragma mark - TUIExtensionProtocol
- (NSArray<TUIExtensionInfo *> *)onGetExtension:(NSString *)extensionID param:(NSDictionary *)param {
if (![extensionID isKindOfClass:NSString.class]) {
return nil;
}
if ([extensionID isEqualToString:TUICore_TUIChatExtension_NavigationMoreItem_ClassicExtensionID]) {
return [self getNavigationMoreItemExtensionForClassicChat:param];
} else {
return nil;
}
}
- (NSArray<TUIExtensionInfo *> *)getNavigationMoreItemExtensionForClassicChat:(NSDictionary *)param {
if (![param isKindOfClass:NSDictionary.class]) {
return nil;
}
NSString *groupID = [param tui_objectForKey:TUICore_TUIChatExtension_NavigationMoreItem_GroupID asClass:NSString.class];
if (groupID.length > 0) {
TUIExtensionInfo *info = [[TUIExtensionInfo alloc] init];
info.icon = TUIGroupBundleThemeImage(@"chat_nav_more_menu_img", @"chat_nav_more_menu");
info.onClicked = ^(NSDictionary *_Nonnull param) {
UINavigationController *pushVC = [param tui_objectForKey:TUICore_TUIChatExtension_NavigationMoreItem_PushVC asClass:UINavigationController.class];
if (pushVC) {
TUIGroupInfoController *vc = [[TUIGroupInfoController alloc] init];
vc.groupId = groupID;
[pushVC pushViewController:vc animated:YES];
}
};
return @[ info ];
} else {
return nil;
}
}
@end

View File

@@ -0,0 +1,41 @@
//
// TUIGroupObjectFactory.h
// TUIGroup
//
// Created by wyl on 2023/3/20.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUICore.h>
NS_ASSUME_NONNULL_BEGIN
/**
*
* TUIGroupObjectFactory currently provides a service:
* Create group member selector
*
* You can call the service through the [TUICore callService:..] method. The different service parameters are as follows:
* > Create group information interface:
* serviceName: TUICore_TUIGroupObjectFactory
* method: TUICore_TUIGroupObjectFactory_GetGroupInfoVC_Classic
* param: @{
* TUICore_TUIGroupObjectFactory_GetGroupInfoVC_GroupID; @"groupID"
* };
* > Create group member selector:
* serviceName: TUICore_TUIGroupObjectFactory
* method: TUICore_TUIGroupObjectFactory_GetSelectGroupMemberViewControllerMethod
* param: @{
* TUICore_TUIGroupObjectFactory_GetSelectGroupMemberViewControllerMethod_GroupIDKey : @"groupID",
* TUICore_TUIGroupObjectFactory_GetSelectGroupMemberViewControllerMethod_NameKey : @"name",
* TUICore_TUIGroupObjectFactory_GetSelectGroupMemberViewControllerMethod_OptionalStyleKey : style
* };
*/
@interface TUIGroupObjectFactory : NSObject
+ (TUIGroupObjectFactory *)shareInstance;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,99 @@
//
// TUIGroupObjectFactory.m
// TUIGroup
//
// Created by wyl on 2023/3/20.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIGroupObjectFactory.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/NSDictionary+TUISafe.h>
#import <TUICore/TUIGlobalization.h>
#import <TUICore/TUIThemeManager.h>
#import "TUIGroupInfoController.h"
#import "TUIGroupRequestViewController.h"
#import "TUISelectGroupMemberViewController.h"
@interface TUIGroupObjectFactory () <TUIObjectProtocol>
@end
@implementation TUIGroupObjectFactory
+ (void)load {
[TUICore registerObjectFactory:TUICore_TUIGroupObjectFactory objectFactory:[TUIGroupObjectFactory shareInstance]];
}
+ (TUIGroupObjectFactory *)shareInstance {
static dispatch_once_t onceToken;
static TUIGroupObjectFactory *g_sharedInstance = nil;
dispatch_once(&onceToken, ^{
g_sharedInstance = [[TUIGroupObjectFactory alloc] init];
});
return g_sharedInstance;
}
#pragma mark - TUIObjectProtocol
- (id)onCreateObject:(NSString *)method param:(nullable NSDictionary *)param {
id returnObject = nil;
if ([method isEqualToString:TUICore_TUIGroupObjectFactory_GetGroupRequestViewControllerMethod]) {
returnObject =
[self createGroupRequestViewController:[param tui_objectForKey:TUICore_TUIGroupObjectFactory_GetGroupRequestViewControllerMethod_GroupInfoKey
asClass:V2TIMGroupInfo.class]];
} else if ([method isEqualToString:TUICore_TUIGroupObjectFactory_GetGroupInfoVC_Classic]) {
returnObject = [self createGroupInfoController:[param tui_objectForKey:TUICore_TUIGroupObjectFactory_GetGroupInfoVC_GroupID asClass:NSString.class]];
} else if ([method isEqualToString:TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_Classic]) {
NSString *groupID = [param tui_objectForKey:TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_GroupID asClass:NSString.class];
NSString *title = [param tui_objectForKey:TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_Name asClass:NSString.class];
NSNumber *optionalStyleNum = [param tui_objectForKey:TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_OptionalStyle asClass:NSNumber.class];
NSArray *selectedUserIDList = [param tui_objectForKey:TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_SelectedUserIDList asClass:NSArray.class];
returnObject = [self createSelectGroupMemberViewController:groupID
name:title
optionalStyle:[optionalStyleNum integerValue]
selectedUserIDList:selectedUserIDList
userData:@""];
}
return returnObject;
}
- (UIViewController *)createGroupRequestViewController:(V2TIMGroupInfo *)groupInfo {
TUIGroupRequestViewController *vc = [[TUIGroupRequestViewController alloc] init];
vc.groupInfo = groupInfo;
return vc;
}
- (UIViewController *)createGroupInfoController:(NSString *)groupID {
TUIGroupInfoController *vc = [[TUIGroupInfoController alloc] init];
vc.groupId = groupID;
return vc;
}
- (UIViewController *)createSelectGroupMemberViewController:(NSString *)groupID
name:(NSString *)name
optionalStyle:(TUISelectMemberOptionalStyle)optionalStyle {
return [self createSelectGroupMemberViewController:groupID name:name optionalStyle:optionalStyle selectedUserIDList:@[]];
}
- (UIViewController *)createSelectGroupMemberViewController:(NSString *)groupID
name:(NSString *)name
optionalStyle:(TUISelectMemberOptionalStyle)optionalStyle
selectedUserIDList:(NSArray *)userIDList {
return [self createSelectGroupMemberViewController:groupID name:name optionalStyle:optionalStyle selectedUserIDList:@[] userData:@""];
}
- (UIViewController *)createSelectGroupMemberViewController:(NSString *)groupID
name:(NSString *)name
optionalStyle:(TUISelectMemberOptionalStyle)optionalStyle
selectedUserIDList:(NSArray *)userIDList
userData:(NSString *)userData {
TUISelectGroupMemberViewController *vc = [[TUISelectGroupMemberViewController alloc] init];
vc.groupId = groupID;
vc.name = name;
vc.optionalStyle = optionalStyle;
vc.selectedUserIDList = userIDList;
vc.userData = userData;
return vc;
}
@end

View File

@@ -0,0 +1,17 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import <Foundation/Foundation.h>
#import <TIMCommon/TIMCommonModel.h>
#import <TUICore/TUICore.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUIGroupService : NSObject <TUIServiceProtocol>
+ (TUIGroupService *)shareInstance;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,127 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import "TUIGroupService.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/NSDictionary+TUISafe.h>
#import <TUICore/TUIGlobalization.h>
#import <TUICore/TUIThemeManager.h>
#import "TUIGroupInfoController.h"
#import "TUIGroupRequestViewController.h"
#import "TUISelectGroupMemberViewController.h"
@implementation TUIGroupService
static NSString *gServiceName = nil;
+ (void)load {
[TUICore registerService:TUICore_TUIGroupService object:[TUIGroupService shareInstance]];
TUIRegisterThemeResourcePath(TUIGroupThemePath, TUIThemeModuleGroup);
}
+ (TUIGroupService *)shareInstance {
static dispatch_once_t onceToken;
static TUIGroupService *g_sharedInstance = nil;
dispatch_once(&onceToken, ^{
g_sharedInstance = [[TUIGroupService alloc] init];
});
return g_sharedInstance;
}
- (void)createGroup:(NSString *)groupType
createOption:(V2TIMGroupAddOpt)createOption
contacts:(NSArray<TUICommonContactSelectCellData *> *)contacts
completion:(void (^)(BOOL success, NSString *groupID, NSString *groupName))completion {
NSString *loginUser = [[V2TIMManager sharedInstance] getLoginUser];
[[V2TIMManager sharedInstance] getUsersInfo:@[ loginUser ]
succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
NSString *showName = loginUser;
if (infoList.firstObject.nickName.length > 0) {
showName = infoList.firstObject.nickName;
}
NSMutableString *groupName = [NSMutableString stringWithString:showName];
NSMutableArray *members = [NSMutableArray array];
for (TUICommonContactSelectCellData *item in contacts) {
V2TIMCreateGroupMemberInfo *member = [[V2TIMCreateGroupMemberInfo alloc] init];
member.userID = item.identifier;
member.role = V2TIM_GROUP_MEMBER_ROLE_MEMBER;
[groupName appendFormat:@"、%@", item.title];
[members addObject:member];
}
if ([groupName length] > 10) {
groupName = [groupName substringToIndex:10].mutableCopy;
}
V2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init];
info.groupName = groupName;
info.groupType = groupType;
if (![info.groupType isEqualToString:GroupType_Work]) {
info.groupAddOpt = createOption;
}
[[V2TIMManager sharedInstance] createGroup:info
memberList:members
succ:^(NSString *groupID) {
NSString *content = TIMCommonLocalizableString(TUIGroupCreateTipsMessage);
if ([info.groupType isEqualToString:GroupType_Community]) {
content = TIMCommonLocalizableString(TUICommunityCreateTipsMessage);
}
NSDictionary *dic = @{
@"version" : @(GroupCreate_Version),
BussinessID : BussinessID_GroupCreate,
@"opUser" : showName,
@"content" : content,
@"cmd" : [info.groupType isEqualToString:GroupType_Community] ? @1 : @0
};
NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];
V2TIMMessage *msg = [[V2TIMManager sharedInstance] createCustomMessage:data];
[[V2TIMManager sharedInstance] sendMessage:msg
receiver:nil
groupID:groupID
priority:V2TIM_PRIORITY_DEFAULT
onlineUserOnly:NO
offlinePushInfo:nil
progress:nil
succ:nil
fail:nil];
// wait for a second to ensure the group created message arrives first
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.15 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (completion) {
completion(YES, groupID, groupName);
}
});
}
fail:^(int code, NSString *msg) {
if (completion) {
completion(NO, nil, nil);
}
if (code == ERR_SDK_INTERFACE_NOT_SUPPORT) {
[TUITool postUnsupportNotificationOfService:TIMCommonLocalizableString(TUIKitErrorUnsupportIntefaceCommunity)
serviceDesc:TIMCommonLocalizableString(TUIKitErrorUnsupportIntefaceCommunityDesc)
debugOnly:YES];
}
}];
}
fail:^(int code, NSString *msg) {
if (completion) {
completion(NO, nil, nil);
}
}];
}
#pragma mark - TUIServiceProtocol
- (id)onCall:(NSString *)method param:(NSDictionary *)param {
id returnObject = nil;
if ([method isEqualToString:TUICore_TUIGroupService_CreateGroupMethod]) {
NSString *groupType = [param tui_objectForKey:TUICore_TUIGroupService_CreateGroupMethod_GroupTypeKey asClass:NSString.class];
NSNumber *option = [param tui_objectForKey:TUICore_TUIGroupService_CreateGroupMethod_OptionKey asClass:NSNumber.class];
NSArray *contacts = [param tui_objectForKey:TUICore_TUIGroupService_CreateGroupMethod_ContactsKey asClass:NSArray.class];
void (^completion)(BOOL, NSString *, NSString *) = [param objectForKey:TUICore_TUIGroupService_CreateGroupMethod_CompletionKey];
[self createGroup:groupType createOption:[option intValue] contacts:contacts completion:completion];
}
return returnObject;
}
@end

View File

@@ -0,0 +1,23 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import <UIKit/UIKit.h>
@class TUIGroupInfoController;
@class TUIGroupMemberCellData;
@class V2TIMGroupInfo;
/////////////////////////////////////////////////////////////////////////////////
//
// TUIGroupInfoController
//
/////////////////////////////////////////////////////////////////////////////////
@interface TUIGroupInfoController : UITableViewController
@property(nonatomic, strong) NSString *groupId;
- (void)updateData;
- (void)updateGroupInfo;
@end

View File

@@ -0,0 +1,729 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import "TUIGroupInfoController.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUICore.h>
#import <TUICore/TUILogin.h>
#import <TUICore/TUIThemeManager.h>
#import "TIMGroupInfo+TUIDataProvider.h"
#import "TUIGroupInfoDataProvider.h"
#import "TUIGroupManageController.h"
#import "TUIGroupMemberCell.h"
#import "TUIGroupMemberController.h"
#import "TUIGroupMembersCell.h"
#import "TUIGroupNoticeCell.h"
#import "TUIGroupNoticeController.h"
#import "TUISelectGroupMemberViewController.h"
#define ADD_TAG @"-1"
#define DEL_TAG @"-2"
@interface TUIGroupInfoController () <TUIModifyViewDelegate, TUIGroupMembersCellDelegate, TUIProfileCardDelegate, TUIGroupInfoDataProviderDelegate>
@property(nonatomic, strong) TUIGroupInfoDataProvider *dataProvider;
@property(nonatomic, strong) TUINaviBarIndicatorView *titleView;
@property(nonatomic, strong) UIViewController *showContactSelectVC;
@property NSInteger tag;
@end
@implementation TUIGroupInfoController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupViews];
self.dataProvider = [[TUIGroupInfoDataProvider alloc] initWithGroupID:self.groupId];
self.dataProvider.delegate = self;
[self.dataProvider loadData];
@weakify(self);
[RACObserve(self.dataProvider, dataList) subscribeNext:^(id _Nullable x) {
@strongify(self);
[self.tableView reloadData];
}];
_titleView = [[TUINaviBarIndicatorView alloc] init];
self.navigationItem.titleView = _titleView;
self.navigationItem.title = @"";
[_titleView setTitle:TIMCommonLocalizableString(ProfileDetails)];
}
- (void)setupViews {
self.tableView.tableFooterView = [[UIView alloc] init];
self.tableView.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#F2F3F5");
self.tableView.delaysContentTouches = NO;
if (@available(iOS 15.0, *)) {
self.tableView.sectionHeaderTopPadding = 0;
}
}
- (void)updateData {
[self.dataProvider loadData];
}
- (void)updateGroupInfo {
[self.dataProvider updateGroupInfo];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.dataProvider.dataList.count;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *view = [[UIView alloc] init];
view.backgroundColor = [UIColor clearColor];
return view;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 10;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSMutableArray *array = self.dataProvider.dataList[section];
return array.count;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray *array = self.dataProvider.dataList[indexPath.section];
NSObject *data = array[indexPath.row];
if ([data isKindOfClass:[TUIProfileCardCellData class]]) {
return [(TUIProfileCardCellData *)data heightOfWidth:Screen_Width];
} else if ([data isKindOfClass:[TUIGroupMembersCellData class]]) {
return [TUIGroupMembersCell getHeight:(TUIGroupMembersCellData *)data];
} else if ([data isKindOfClass:[TUIButtonCellData class]]) {
return [(TUIButtonCellData *)data heightOfWidth:Screen_Width];
;
} else if ([data isKindOfClass:[TUICommonSwitchCellData class]]) {
return [(TUICommonSwitchCellData *)data heightOfWidth:Screen_Width];
;
} else if ([data isKindOfClass:TUIGroupNoticeCellData.class]) {
return 72.0;
}
return 44;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray *array = self.dataProvider.dataList[indexPath.section];
NSObject *data = array[indexPath.row];
if ([data isKindOfClass:[TUIProfileCardCellData class]]) {
TUIProfileCardCell *cell = [tableView dequeueReusableCellWithIdentifier:TGroupCommonCell_ReuseId];
if (!cell) {
cell = [[TUIProfileCardCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TGroupCommonCell_ReuseId];
}
cell.delegate = self;
[cell fillWithData:(TUIProfileCardCellData *)data];
return cell;
} else if ([data isKindOfClass:[TUICommonTextCellData class]]) {
TUICommonTextCell *cell = [tableView dequeueReusableCellWithIdentifier:TKeyValueCell_ReuseId];
if (!cell) {
cell = [[TUICommonTextCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TKeyValueCell_ReuseId];
}
[cell fillWithData:(TUICommonTextCellData *)data];
return cell;
} else if ([data isKindOfClass:[TUIGroupMembersCellData class]]) {
TUIGroupMembersCell *cell = [tableView dequeueReusableCellWithIdentifier:TGroupMembersCell_ReuseId];
if (!cell) {
cell = [[TUIGroupMembersCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TGroupMembersCell_ReuseId];
cell.delegate = self;
}
[cell setData:(TUIGroupMembersCellData *)data];
return cell;
} else if ([data isKindOfClass:[TUICommonSwitchCellData class]]) {
TUICommonSwitchCell *cell = [tableView dequeueReusableCellWithIdentifier:TSwitchCell_ReuseId];
if (!cell) {
cell = [[TUICommonSwitchCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TSwitchCell_ReuseId];
}
[cell fillWithData:(TUICommonSwitchCellData *)data];
return cell;
} else if ([data isKindOfClass:[TUIButtonCellData class]]) {
TUIButtonCell *cell = [tableView dequeueReusableCellWithIdentifier:TButtonCell_ReuseId];
if (!cell) {
cell = [[TUIButtonCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TButtonCell_ReuseId];
}
[cell fillWithData:(TUIButtonCellData *)data];
return cell;
} else if ([data isKindOfClass:TUIGroupNoticeCellData.class]) {
TUIGroupNoticeCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TUIGroupNoticeCell"];
if (cell == nil) {
cell = [[TUIGroupNoticeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"TUIGroupNoticeCell"];
}
cell.cellData = data;
return cell;
}
return nil;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
- (void)leftBarButtonClick:(UIButton *)sender {
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark TUIGroupInfoDataProviderDelegate
- (void)didSelectMembers {
TUIGroupMemberController *membersController = [[TUIGroupMemberController alloc] init];
membersController.groupId = _groupId;
membersController.groupInfo = self.dataProvider.groupInfo;
[self.navigationController pushViewController:membersController animated:YES];
}
- (void)didSelectAddOption:(TUICommonTextCell *)cell {
TUICommonTextCellData *data = cell.textData;
BOOL isApprove = [data.key isEqualToString:TIMCommonLocalizableString(TUIKitGroupProfileInviteType)];
__weak typeof(self) weakSelf = self;
UIAlertController *ac = [UIAlertController
alertControllerWithTitle:nil
message:isApprove ? TIMCommonLocalizableString(TUIKitGroupProfileInviteType) : TIMCommonLocalizableString(TUIKitGroupProfileJoinType)
preferredStyle:UIAlertControllerStyleActionSheet];
NSArray *actionList = @[
@{
@(V2TIM_GROUP_ADD_FORBID) : isApprove ? TIMCommonLocalizableString(TUIKitGroupProfileInviteDisable)
: TIMCommonLocalizableString(TUIKitGroupProfileJoinDisable)
},
@{@(V2TIM_GROUP_ADD_AUTH) : TIMCommonLocalizableString(TUIKitGroupProfileAdminApprove)},
@{@(V2TIM_GROUP_ADD_ANY) : TIMCommonLocalizableString(TUIKitGroupProfileAutoApproval)}
];
for (NSDictionary *map in actionList) {
[ac tuitheme_addAction:[UIAlertAction actionWithTitle:map.allValues.firstObject
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *_Nonnull action) {
V2TIMGroupAddOpt opt = (V2TIMGroupAddOpt)[map.allKeys.firstObject intValue];
if (isApprove) {
[weakSelf.dataProvider setGroupApproveOpt:opt];
} else {
[weakSelf.dataProvider setGroupAddOpt:opt];
}
}]];
}
[ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(Cancel) style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:ac animated:YES completion:nil];
}
- (void)didSelectGroupNick:(TUICommonTextCell *)cell {
TUIModifyViewData *data = [[TUIModifyViewData alloc] init];
data.title = TIMCommonLocalizableString(TUIKitGroupProfileEditAlias);
data.content = self.dataProvider.selfInfo.nameCard;
data.desc = TIMCommonLocalizableString(TUIKitGroupProfileEditAliasDesc);
TUIModifyView *modify = [[TUIModifyView alloc] init];
modify.tag = 2;
modify.delegate = self;
[modify setData:data];
[modify showInWindow:self.view.window];
}
- (void)didSelectCommon {
UIAlertController *ac = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
__weak typeof(self) weakSelf = self;
if ([self.dataProvider.groupInfo isPrivate] || [TUIGroupInfoDataProvider isMeOwner:self.dataProvider.groupInfo]) {
[ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(TUIKitGroupProfileEditGroupName)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *_Nonnull action) {
TUIModifyViewData *data = [[TUIModifyViewData alloc] init];
data.title = TIMCommonLocalizableString(TUIKitGroupProfileEditGroupName);
data.content = weakSelf.dataProvider.groupInfo.groupName;
data.desc = TIMCommonLocalizableString(TUIKitGroupProfileEditGroupName);
TUIModifyView *modify = [[TUIModifyView alloc] init];
modify.tag = 0;
modify.delegate = weakSelf;
[modify setData:data];
[modify showInWindow:weakSelf.view.window];
}]];
}
if ([TUIGroupInfoDataProvider isMeOwner:self.dataProvider.groupInfo]) {
[ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(TUIKitGroupProfileEditAnnouncement)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *_Nonnull action) {
TUIModifyViewData *data = [[TUIModifyViewData alloc] init];
data.title = TIMCommonLocalizableString(TUIKitGroupProfileEditAnnouncement);
TUIModifyView *modify = [[TUIModifyView alloc] init];
modify.tag = 1;
modify.delegate = weakSelf;
[modify setData:data];
[modify showInWindow:weakSelf.view.window];
}]];
}
if ([TUIGroupInfoDataProvider isMeOwner:self.dataProvider.groupInfo]) {
@weakify(self);
[ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(TUIKitGroupProfileEditAvatar)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *_Nonnull action) {
@strongify(self);
TUISelectAvatarController *vc = [[TUISelectAvatarController alloc] init];
vc.selectAvatarType = TUISelectAvatarTypeGroupAvatar;
vc.profilFaceURL = self.dataProvider.groupInfo.faceURL;
[self.navigationController pushViewController:vc animated:YES];
vc.selectCallBack = ^(NSString *_Nonnull urlStr) {
if (urlStr.length > 0) {
V2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init];
info.groupID = self.groupId;
info.faceURL = urlStr;
[[V2TIMManager sharedInstance] setGroupInfo:info
succ:^{
[self updateGroupInfo];
}
fail:^(int code, NSString *msg) {
[TUITool makeToastError:code msg:msg];
}];
}
};
}]];
}
[ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(Cancel) style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:ac animated:YES completion:nil];
}
- (void)didSelectOnNotDisturb:(TUICommonSwitchCell *)cell {
V2TIMReceiveMessageOpt opt;
if (cell.switcher.on) {
opt = V2TIM_RECEIVE_NOT_NOTIFY_MESSAGE;
} else {
opt = V2TIM_RECEIVE_MESSAGE;
}
@weakify(self);
[V2TIMManager.sharedInstance markConversation:@[ [NSString stringWithFormat:@"group_%@", self.groupId] ]
markType:@(V2TIM_CONVERSATION_MARK_TYPE_FOLD)
enableMark:NO
succ:nil
fail:nil];
[self.dataProvider setGroupReceiveMessageOpt:opt
Succ:^{
@strongify(self);
[self updateGroupInfo];
}
fail:^(int code, NSString *desc){
}];
}
- (void)didSelectOnTop:(TUICommonSwitchCell *)cell {
if (cell.switcher.on) {
[[TUIConversationPin sharedInstance] addTopConversation:[NSString stringWithFormat:@"group_%@", _groupId]
callback:^(BOOL success, NSString *_Nonnull errorMessage) {
if (success) {
return;
}
cell.switcher.on = !cell.switcher.isOn;
[TUITool makeToast:errorMessage];
}];
} else {
[[TUIConversationPin sharedInstance] removeTopConversation:[NSString stringWithFormat:@"group_%@", _groupId]
callback:^(BOOL success, NSString *_Nonnull errorMessage) {
if (success) {
return;
}
cell.switcher.on = !cell.switcher.isOn;
[TUITool makeToast:errorMessage];
}];
}
}
- (void)didDeleteGroup:(TUIButtonCell *)cell {
UIAlertController *ac = [UIAlertController alertControllerWithTitle:nil
message:TIMCommonLocalizableString(TUIKitGroupProfileDeleteGroupTips)
preferredStyle:UIAlertControllerStyleActionSheet];
@weakify(self);
[ac tuitheme_addAction:[UIAlertAction
actionWithTitle:TIMCommonLocalizableString(Confirm)
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction *_Nonnull action) {
@strongify(self);
@weakify(self);
if ([self.dataProvider.groupInfo canDismissGroup]) {
[self.dataProvider
dismissGroup:^{
@strongify(self);
@weakify(self);
dispatch_async(dispatch_get_main_queue(), ^{
@strongify(self);
UIViewController *vc = [self findConversationListViewController];
[[TUIConversationPin sharedInstance]
removeTopConversation:[NSString stringWithFormat:@"group_%@", self.groupId]
callback:nil];
[V2TIMManager.sharedInstance markConversation:@[ [NSString stringWithFormat:@"group_%@", self.groupId] ]
markType:@(V2TIM_CONVERSATION_MARK_TYPE_FOLD)
enableMark:NO
succ:^(NSArray<V2TIMConversationOperationResult *> *result) {
[self.navigationController popToViewController:vc animated:YES];
}
fail:^(int code, NSString *desc) {
[self.navigationController popToViewController:vc animated:YES];
}];
});
}
fail:^(int code, NSString *msg) {
[TUITool makeToastError:code msg:msg];
}];
} else {
[self.dataProvider
quitGroup:^{
@strongify(self);
@weakify(self);
dispatch_async(dispatch_get_main_queue(), ^{
@strongify(self);
UIViewController *vc = [self findConversationListViewController];
[[TUIConversationPin sharedInstance]
removeTopConversation:[NSString stringWithFormat:@"group_%@", self.groupId]
callback:nil];
[V2TIMManager.sharedInstance markConversation:@[ [NSString stringWithFormat:@"group_%@", self.groupId] ]
markType:@(V2TIM_CONVERSATION_MARK_TYPE_FOLD)
enableMark:NO
succ:^(NSArray<V2TIMConversationOperationResult *> *result) {
[self.navigationController popToViewController:vc animated:YES];
}
fail:^(int code, NSString *desc) {
[self.navigationController popToViewController:vc animated:YES];
}];
});
}
fail:^(int code, NSString *msg) {
[TUITool makeToastError:code msg:msg];
}];
}
}]];
[ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(Cancel) style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:ac animated:YES completion:nil];
}
- (void)didReportGroup:(TUIButtonCell *)cell {
NSURL *url = [NSURL URLWithString:@"https://cloud.tencent.com/act/event/report-platform"];
[TUITool openLinkWithURL:url];
}
- (UIViewController *)findConversationListViewController {
UIViewController *vc = self.navigationController.viewControllers[0];
for (UIViewController *vc in self.navigationController.viewControllers) {
if ([vc isKindOfClass:NSClassFromString(@"TUIFoldListViewController")]) {
return vc;
}
}
return vc;
}
- (void)didSelectOnFoldConversation:(TUICommonSwitchCell *)cell {
BOOL enableMark = NO;
if (cell.switcher.on) {
enableMark = YES;
}
@weakify(self);
[V2TIMManager.sharedInstance markConversation:@[ [NSString stringWithFormat:@"group_%@", self.groupId] ]
markType:@(V2TIM_CONVERSATION_MARK_TYPE_FOLD)
enableMark:enableMark
succ : ^(NSArray<V2TIMConversationOperationResult *> *result) {
cell.switchData.on = enableMark;
[[TUIConversationPin sharedInstance] removeTopConversation:[NSString stringWithFormat:@"group_%@", self.groupId]
callback:^(BOOL success, NSString *_Nonnull errorMessage) {
@strongify(self);
[self updateGroupInfo];
}];
} fail:nil];
}
- (void)didSelectOnChangeBackgroundImage:(TUICommonTextCell *)cell {
@weakify(self);
NSString *conversationID = [NSString stringWithFormat:@"group_%@", self.groupId];
TUISelectAvatarController *vc = [[TUISelectAvatarController alloc] init];
vc.selectAvatarType = TUISelectAvatarTypeConversationBackGroundCover;
vc.profilFaceURL = [self getBackgroundImageUrlByConversationID:conversationID];
[self.navigationController pushViewController:vc animated:YES];
vc.selectCallBack = ^(NSString *_Nonnull urlStr) {
@strongify(self);
[self appendBackgroundImage:urlStr conversationID:conversationID];
if (IS_NOT_EMPTY_NSSTRING(conversationID)) {
[TUICore notifyEvent:TUICore_TUIGroupNotify
subKey:TUICore_TUIGroupNotify_UpdateConversationBackgroundImageSubKey
object:self
param:@{TUICore_TUIGroupNotify_UpdateConversationBackgroundImageSubKey_ConversationID : conversationID}];
}
};
}
- (NSString *)getBackgroundImageUrlByConversationID:(NSString *)targerConversationID {
if (targerConversationID.length == 0) {
return nil;
}
NSDictionary *dict = [NSUserDefaults.standardUserDefaults objectForKey:@"conversation_backgroundImage_map"];
if (dict == nil) {
dict = @{};
}
NSString *conversationID_UserID = [NSString stringWithFormat:@"%@_%@", targerConversationID, [TUILogin getUserID]];
if (![dict isKindOfClass:NSDictionary.class] || ![dict.allKeys containsObject:conversationID_UserID]) {
return nil;
}
return [dict objectForKey:conversationID_UserID];
}
- (void)appendBackgroundImage:(NSString *)imgUrl conversationID:(NSString *)conversationID {
if (conversationID.length == 0) {
return;
}
NSDictionary *dict = [NSUserDefaults.standardUserDefaults objectForKey:@"conversation_backgroundImage_map"];
if (dict == nil) {
dict = @{};
}
if (![dict isKindOfClass:NSDictionary.class]) {
return;
}
NSString *conversationID_UserID = [NSString stringWithFormat:@"%@_%@", conversationID, [TUILogin getUserID]];
NSMutableDictionary *originDataDict = [NSMutableDictionary dictionaryWithDictionary:dict];
if (imgUrl.length == 0) {
[originDataDict removeObjectForKey:conversationID_UserID];
} else {
[originDataDict setObject:imgUrl forKey:conversationID_UserID];
}
[NSUserDefaults.standardUserDefaults setObject:originDataDict forKey:@"conversation_backgroundImage_map"];
[NSUserDefaults.standardUserDefaults synchronize];
}
- (void)didTransferGroup:(TUIButtonCell *)cell {
TUISelectGroupMemberViewController *vc = [[TUISelectGroupMemberViewController alloc] init];
vc.optionalStyle = TUISelectMemberOptionalStyleTransferOwner;
vc.groupId = self.groupId;
vc.name = TIMCommonLocalizableString(TUIKitGroupTransferOwner);
@weakify(self);
vc.selectedFinished = ^(NSMutableArray<TUIUserModel *> *_Nonnull modelList) {
@strongify(self);
TUIUserModel *userModel = modelList[0];
NSString *groupId = self.groupId;
NSString *member = userModel.userId;
if (userModel && [userModel isKindOfClass:[TUIUserModel class]]) {
@weakify(self);
[self.dataProvider transferGroupOwner:groupId
member:member
succ:^{
@strongify(self);
[self updateGroupInfo];
[TUITool makeToast:TIMCommonLocalizableString(TUIKitGroupTransferOwnerSuccess)];
}
fail:^(int code, NSString *desc) {
[TUITool makeToastError:code msg:desc];
}];
}
};
[self.navigationController pushViewController:vc animated:YES];
}
- (void)didClearAllHistory:(TUIButtonCell *)cell {
@weakify(self);
UIAlertController *ac = [UIAlertController alertControllerWithTitle:nil
message:TIMCommonLocalizableString(TUIKitClearAllChatHistoryTips)
preferredStyle:UIAlertControllerStyleAlert];
[ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(Confirm)
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction *_Nonnull action) {
@strongify(self);
[self.dataProvider
clearAllHistory:^{
[TUICore notifyEvent:TUICore_TUIConversationNotify
subKey:TUICore_TUIConversationNotify_ClearConversationUIHistorySubKey
object:self
param:nil];
[TUITool makeToast:@"success"];
}
fail:^(int code, NSString *desc) {
[TUITool makeToastError:code msg:desc];
}];
}]];
[ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(Cancel) style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:ac animated:YES completion:nil];
}
- (void)didSelectGroupManage {
TUIGroupManageController *vc = [[TUIGroupManageController alloc] init];
vc.groupID = self.groupId;
[self.navigationController pushViewController:vc animated:YES];
}
- (void)didSelectGroupNotice {
TUIGroupNoticeController *vc = [[TUIGroupNoticeController alloc] init];
vc.groupID = self.groupId;
__weak typeof(self) weakSelf = self;
vc.onNoticeChanged = ^{
[weakSelf updateGroupInfo];
};
[self.navigationController pushViewController:vc animated:YES];
}
#pragma mark TUIProfileCardDelegate
- (void)didTapOnAvatar:(TUIProfileCardCell *)cell {
TUISelectAvatarController *vc = [[TUISelectAvatarController alloc] init];
vc.selectAvatarType = TUISelectAvatarTypeGroupAvatar;
vc.profilFaceURL = self.dataProvider.groupInfo.faceURL;
[self.navigationController pushViewController:vc animated:YES];
@weakify(self);
vc.selectCallBack = ^(NSString *_Nonnull urlStr) {
@strongify(self);
if (urlStr.length > 0) {
V2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init];
info.groupID = self.groupId;
info.faceURL = urlStr;
[[V2TIMManager sharedInstance] setGroupInfo:info
succ:^{
[self updateGroupInfo];
}
fail:^(int code, NSString *msg) {
[TUITool makeToastError:code msg:msg];
}];
}
};
}
#pragma mark TUIGroupMembersCellDelegate
- (void)groupMembersCell:(TUIGroupMembersCell *)cell didSelectItemAtIndex:(NSInteger)index {
TUIGroupMemberCellData *mem = self.dataProvider.groupMembersCellData.members[index];
NSMutableArray *ids = [NSMutableArray array];
NSMutableDictionary *displayNames = [NSMutableDictionary dictionary];
for (TUIGroupMemberCellData *cd in self.dataProvider.membersData) {
if (![cd.identifier isEqualToString:[[V2TIMManager sharedInstance] getLoginUser]]) {
[ids addObject:cd.identifier];
[displayNames setObject:cd.name ?: @"" forKey:cd.identifier ?: @""];
}
}
@weakify(self);
void (^selectContactCompletion)(NSArray<TUICommonContactSelectCellData *> *) = ^(NSArray<TUICommonContactSelectCellData *> *array) {
@strongify(self);
if (self.tag == 1) {
// add
NSMutableArray *list = @[].mutableCopy;
for (TUICommonContactSelectCellData *data in array) {
[list addObject:data.identifier];
}
[self.navigationController popToViewController:self animated:YES];
[self addGroupId:self.groupId memebers:list];
} else if (self.tag == 2) {
// delete
NSMutableArray *list = @[].mutableCopy;
for (TUICommonContactSelectCellData *data in array) {
[list addObject:data.identifier];
}
[self.navigationController popToViewController:self animated:YES];
[self deleteGroupId:self.groupId memebers:list];
}
};
self.tag = mem.tag;
if (self.tag == 1) {
// add
NSMutableDictionary *param = [NSMutableDictionary dictionary];
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_TitleKey] = TIMCommonLocalizableString(GroupAddFirend);
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_DisableIdsKey] = ids;
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_DisplayNamesKey] = displayNames;
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_CompletionKey] = selectContactCompletion;
self.showContactSelectVC = [TUICore createObject:TUICore_TUIContactObjectFactory
key:TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod
param:param];
[self.navigationController pushViewController:self.showContactSelectVC animated:YES];
} else if (self.tag == 2) {
// delete
NSMutableDictionary *param = [NSMutableDictionary dictionary];
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_TitleKey] = TIMCommonLocalizableString(GroupDeleteFriend);
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_SourceIdsKey] = ids;
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_DisplayNamesKey] = displayNames;
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_CompletionKey] = selectContactCompletion;
self.showContactSelectVC = [TUICore createObject:TUICore_TUIContactObjectFactory
key:TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod
param:param];
[self.navigationController pushViewController:self.showContactSelectVC animated:YES];
} else {
[self didCurrentMemberAtCellData:mem];
}
}
- (void)didCurrentMemberAtCellData:(TUIGroupMemberCellData *)mem {
NSString *userID = mem.identifier;
@weakify(self);
[self getUserOrFriendProfileVCWithUserID:userID
succBlock:^(UIViewController *vc) {
@strongify(self);
[self.navigationController pushViewController:vc animated:YES];
}
failBlock:^(int code, NSString *desc){
}];
}
- (void)getUserOrFriendProfileVCWithUserID:(NSString *)userID succBlock:(void (^)(UIViewController *vc))succ failBlock:(nullable V2TIMFail)fail {
NSDictionary *param = @{
TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod_UserIDKey: userID ? : @"",
TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod_SuccKey: succ ? : ^(UIViewController *vc){},
TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod_FailKey: fail ? : ^(int code, NSString * desc){}
};
[TUICore createObject:TUICore_TUIContactObjectFactory key:TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod param:param];
}
- (void)addGroupId:(NSString *)groupId memebers:(NSArray *)members {
@weakify(self);
[[V2TIMManager sharedInstance] inviteUserToGroup:_groupId
userList:members
succ:^(NSArray<V2TIMGroupMemberOperationResult *> *resultList) {
@strongify(self);
[self updateData];
[TUITool makeToast:TIMCommonLocalizableString(add_success)];
}
fail:^(int code, NSString *desc) {
[TUITool makeToastError:code msg:desc];
}];
}
- (void)deleteGroupId:(NSString *)groupId memebers:(NSArray *)members {
@weakify(self);
[[V2TIMManager sharedInstance] kickGroupMember:groupId
memberList:members
reason:@""
succ:^(NSArray<V2TIMGroupMemberOperationResult *> *resultList) {
@strongify(self);
[self updateData];
[TUITool makeToast:TIMCommonLocalizableString(delete_success)];
}
fail:^(int code, NSString *desc) {
[TUITool makeToastError:code msg:desc];
}];
}
#pragma mark TUIModifyViewDelegate
- (void)modifyView:(TUIModifyView *)modifyView didModiyContent:(NSString *)content {
if (modifyView.tag == 0) {
[self.dataProvider setGroupName:content];
} else if (modifyView.tag == 1) {
[self.dataProvider setGroupNotification:content];
} else if (modifyView.tag == 2) {
[self.dataProvider setGroupMemberNameCard:content];
}
}
@end
@interface IUGroupView : UIView
@property(nonatomic, strong) UIView *view;
@end
@implementation IUGroupView
- (instancetype)init {
self = [super init];
if (self) {
self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
[self addSubview:self.view];
}
return self;
}
@end

View File

@@ -0,0 +1,19 @@
//
// TUIGroupManageController.h
// TUIGroup
//
// Created by harvy on 2021/12/24.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUIGroupManageController : UIViewController
@property(nonatomic, copy) NSString *groupID;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,260 @@
//
// TUIGroupManageController.m
// TUIGroup
//
// Created by harvy on 2021/12/24.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIGroupManageController.h"
#import <TUICore/TUIGlobalization.h>
#import <TUICore/TUIThemeManager.h>
#import "TUIGroupManageDataProvider.h"
#import "TUIMemberInfoCell.h"
#import "TUIMemberInfoCellData.h"
#import "TUISelectGroupMemberViewController.h"
#import "TUISettingAdminController.h"
@interface TUIGroupManageController () <UITableViewDelegate, UITableViewDataSource, TUIGroupManageDataProviderDelegate>
@property(nonatomic, strong) UITableView *tableView;
@property(nonatomic, strong) TUIGroupManageDataProvider *dataProvider;
@property(nonatomic, strong) UIView *coverView;
@end
@implementation TUIGroupManageController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupViews];
self.dataProvider.groupID = self.groupID;
[self showCoverViewWhenMuteAll:YES];
[self.dataProvider loadData];
}
- (void)setupViews {
UILabel *titleLabel = [[UILabel alloc] init];
titleLabel.text = TIMCommonLocalizableString(TUIKitGroupProfileManage);
titleLabel.font = [UIFont boldSystemFontOfSize:17.0];
titleLabel.textColor = TIMCommonDynamicColor(@"nav_title_text_color", @"#000000");
[titleLabel sizeToFit];
self.navigationItem.titleView = titleLabel;
[self.view addSubview:self.tableView];
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
self.tableView.frame = self.view.bounds;
}
- (void)onSettingAdmin:(TUICommonTextCellData *)textData {
if (!self.dataProvider.currentGroupTypeSupportSettingAdmin) {
[TUITool makeToast:TIMCommonLocalizableString(TUIKitGroupSetAdminsForbidden)];
return;
}
TUISettingAdminController *vc = [[TUISettingAdminController alloc] init];
vc.groupID = self.groupID;
__weak typeof(self) weakSelf = self;
vc.settingAdminDissmissCallBack = ^{
[weakSelf.dataProvider updateMuteMembersFilterAdmins];
[weakSelf.tableView reloadData];
};
[self.navigationController pushViewController:vc animated:YES];
}
- (void)onMutedAll:(TUICommonSwitchCell *)switchCell {
__weak typeof(self) weakSelf = self;
[self.dataProvider mutedAll:switchCell.switcher.isOn
completion:^(int code, NSString *error) {
if (code != 0) {
switchCell.switcher.on = !switchCell.switcher.isOn;
[weakSelf.view makeToast:error];
return;
}
[weakSelf showCoverViewWhenMuteAll:switchCell.switcher.isOn];
}];
}
#pragma mark - TUIGroupManageDataProviderDelegate
- (void)onError:(int)code desc:(NSString *)desc operate:(NSString *)operate {
if (code != 0) {
[TUITool makeToast:[NSString stringWithFormat:@"%d, %@", code, desc]];
}
}
- (void)showCoverViewWhenMuteAll:(BOOL)show {
[self.coverView removeFromSuperview];
if (show) {
CGFloat y = 0;
if (self.dataProvider.datas.count == 0) {
y = 100;
} else {
CGRect rect = [self.tableView rectForSection:0];
y = CGRectGetMaxY(rect);
}
self.coverView.frame = CGRectMake(0, y, self.tableView.mm_w, self.tableView.mm_h);
[self.tableView addSubview:self.coverView];
}
}
- (void)reloadData {
[self.tableView reloadData];
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf showCoverViewWhenMuteAll:weakSelf.dataProvider.muteAll];
});
}
- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation {
[self.tableView insertSections:sections withRowAnimation:animation];
}
- (void)reloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation {
[self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:animation];
}
- (void)insertRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation {
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:animation];
}
#pragma mark - UITableViewDelegate, UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.dataProvider.datas.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *subArray = self.dataProvider.datas[section];
return subArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
NSArray *subArray = self.dataProvider.datas[indexPath.section];
TUICommonCellData *data = subArray[indexPath.row];
if ([data isKindOfClass:TUICommonTextCellData.class]) {
cell = [[TUICommonTextCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:NSStringFromClass(TUICommonTextCell.class)];
[(TUICommonTextCell *)cell fillWithData:(TUICommonTextCellData *)data];
} else if ([data isKindOfClass:TUICommonSwitchCellData.class]) {
cell = [[TUICommonSwitchCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:NSStringFromClass(TUICommonSwitchCell.class)];
[(TUICommonSwitchCell *)cell fillWithData:(TUICommonSwitchCellData *)data];
} else if ([data isKindOfClass:TUIMemberInfoCellData.class]) {
cell = [[TUIMemberInfoCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:NSStringFromClass(TUIMemberInfoCell.class)];
[(TUIMemberInfoCell *)cell setData:(TUIMemberInfoCellData *)data];
} else {
cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
cell.textLabel.text = @"";
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 48.0;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return section == 0 ? 30 : 0;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 0;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
UIView *view = [[UIView alloc] init];
view.backgroundColor = [UIColor groupTableViewBackgroundColor];
UILabel *label = [[UILabel alloc] init];
label.text = TIMCommonLocalizableString(TUIKitGroupManageShutupAllTips);
label.textColor = [UIColor colorWithRed:136 / 255.0 green:136 / 255.0 blue:136 / 255.0 alpha:1 / 1.0];
label.font = [UIFont systemFontOfSize:14.0];
[view addSubview:label];
[label sizeToFit];
label.mm_x = 20;
label.mm_y = 10;
return view;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
if (indexPath.section == 1 && indexPath.row == 0) {
if (!self.dataProvider.currentGroupTypeSupportAddMemberOfBlocked) {
[TUITool makeToast:TIMCommonLocalizableString(TUIKitGroupAddMemberOfBlockedForbidden)];
return;
}
TUISelectGroupMemberViewController *vc = [[TUISelectGroupMemberViewController alloc] init];
vc.optionalStyle = TUISelectMemberOptionalStylePublicMan;
vc.groupId = self.groupID;
vc.name = TIMCommonLocalizableString(TUIKitGroupProfileMember);
__weak typeof(self) weakSelf = self;
vc.selectedFinished = ^(NSMutableArray<TUIUserModel *> *_Nonnull modelList) {
for (TUIUserModel *userModel in modelList) {
[weakSelf.dataProvider mute:YES user:userModel];
}
};
[self.navigationController pushViewController:vc animated:YES];
}
}
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
return TIMCommonLocalizableString(Delete);
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 1 && indexPath.row > 0) {
return YES;
}
return NO;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
TUIMemberInfoCellData *cellData = self.dataProvider.datas[indexPath.section][indexPath.row];
if (![cellData isKindOfClass:TUIMemberInfoCellData.class]) {
return;
}
TUIUserModel *userModel = [[TUIUserModel alloc] init];
userModel.userId = cellData.identifier;
[self.dataProvider mute:NO user:userModel];
}
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
return [[UIView alloc] init];
}
- (UITableView *)tableView {
if (_tableView == nil) {
_tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
_tableView.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#F2F3F5");
_tableView.delaysContentTouches = NO;
_tableView.delegate = self;
_tableView.dataSource = self;
}
return _tableView;
}
- (TUIGroupManageDataProvider *)dataProvider {
if (_dataProvider == nil) {
_dataProvider = [[TUIGroupManageDataProvider alloc] init];
_dataProvider.delegate = self;
}
return _dataProvider;
}
- (UIView *)coverView {
if (_coverView == nil) {
_coverView = [[UIView alloc] init];
_coverView.backgroundColor = self.tableView.backgroundColor;
}
return _coverView;
}
@end

View File

@@ -0,0 +1,27 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
#import <UIKit/UIKit.h>
#import "TUIGroupMembersView.h"
@class TUIGroupMemberController;
@class V2TIMGroupInfo;
/////////////////////////////////////////////////////////////////////////////////
//
// TUIGroupMemberController
//
/////////////////////////////////////////////////////////////////////////////////
@interface TUIGroupMemberController : UIViewController
@property(nonatomic, strong) UITableView *tableView;
@property(nonatomic, strong) NSString *groupId;
@property(nonatomic, strong) V2TIMGroupInfo *groupInfo;
- (void)refreshData;
@end

View File

@@ -0,0 +1,311 @@
//
// GroupMemberController.m
// UIKit
//
// Created by kennethmiao on 2018/9/27.
// Copyright © 2018 Tencent. All rights reserved.
//
#import "TUIGroupMemberController.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUICore.h>
#import "TIMGroupInfo+TUIDataProvider.h"
#import "TUIGroupMemberCell.h"
#import "TUIGroupMemberDataProvider.h"
#import <TUICore/TUILogin.h>
#import <TUICore/TUIThemeManager.h>
#import "TUIMemberInfoCell.h"
#import "TUIMemberInfoCellData.h"
@interface TUIGroupMemberController () <UITableViewDelegate, UITableViewDataSource>
@property(nonatomic, strong) UIActivityIndicatorView *indicatorView;
@property(nonatomic, strong) TUINaviBarIndicatorView *titleView;
@property(nonatomic, strong) UIViewController *showContactSelectVC;
@property(nonatomic, strong) TUIGroupMemberDataProvider *dataProvider;
@property(nonatomic, strong) NSMutableArray<TUIMemberInfoCellData *> *members;
@property NSInteger tag;
@end
@implementation TUIGroupMemberController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupViews];
self.dataProvider = [[TUIGroupMemberDataProvider alloc] initWithGroupID:self.groupId];
self.dataProvider.groupInfo = self.groupInfo;
[self refreshData];
}
- (void)refreshData {
@weakify(self);
[self.dataProvider loadDatas:^(BOOL success, NSString *_Nonnull err, NSArray *_Nonnull datas) {
@strongify(self);
NSString *title = [NSString stringWithFormat:TIMCommonLocalizableString(TUIKitGroupProfileGroupCountFormat), (long)datas.count];
self.title = title;
self.members = [NSMutableArray arrayWithArray:datas];
[self.tableView reloadData];
}];
}
- (void)setupViews {
self.view.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#F2F3F5");
// left
UIImage *image = TUIGroupDynamicImage(@"group_nav_back_img", [UIImage imageNamed:TUIGroupImagePath(@"back")]);
image = [image rtl_imageFlippedForRightToLeftLayoutDirection];
UIButton *leftButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
[leftButton addTarget:self action:@selector(leftBarButtonClick) forControlEvents:UIControlEventTouchUpInside];
[leftButton setImage:image forState:UIControlStateNormal];
UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithCustomView:leftButton];
UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
spaceItem.width = -10.0f;
if (([[TUITool deviceVersion] floatValue] >= 11.0)) {
leftButton.contentEdgeInsets = UIEdgeInsetsMake(0, -15, 0, 0);
leftButton.imageEdgeInsets = UIEdgeInsetsMake(0, -15, 0, 0);
}
self.navigationItem.leftBarButtonItems = @[ spaceItem, leftItem ];
self.parentViewController.navigationItem.leftBarButtonItems = @[ spaceItem, leftItem ];
// right
UIButton *rightButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
[rightButton addTarget:self action:@selector(rightBarButtonClick) forControlEvents:UIControlEventTouchUpInside];
[rightButton setTitle:TIMCommonLocalizableString(TUIKitGroupProfileManage) forState:UIControlStateNormal];
[rightButton setTitleColor:TIMCommonDynamicColor(@"nav_title_text_color", @"#000000") forState:UIControlStateNormal];
rightButton.titleLabel.font = [UIFont systemFontOfSize:16];
UIBarButtonItem *rightItem = [[UIBarButtonItem alloc] initWithCustomView:rightButton];
self.navigationItem.rightBarButtonItem = rightItem;
self.parentViewController.navigationItem.rightBarButtonItem = rightItem;
self.indicatorView.frame = CGRectMake(0, 0, self.view.bounds.size.width, TMessageController_Header_Height);
self.tableView.frame = self.view.bounds;
self.tableView.tableFooterView = self.indicatorView;
[self.view addSubview:self.tableView];
_titleView = [[TUINaviBarIndicatorView alloc] init];
self.navigationItem.titleView = _titleView;
self.navigationItem.title = @"";
[_titleView setTitle:TIMCommonLocalizableString(GroupMember)];
}
- (void)leftBarButtonClick {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)rightBarButtonClick {
UIAlertController *ac = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
NSMutableArray *ids = [NSMutableArray array];
NSMutableDictionary *displayNames = [NSMutableDictionary dictionary];
for (TUIGroupMemberCellData *cd in self.members) {
if (![cd.identifier isEqualToString:[[V2TIMManager sharedInstance] getLoginUser]]) {
[ids addObject:cd.identifier];
[displayNames setObject:cd.name ?: @"" forKey:cd.identifier ?: @""];
}
}
@weakify(self);
void (^selectContactCompletion)(NSArray<TUICommonContactSelectCellData *> *) = ^(NSArray<TUICommonContactSelectCellData *> *array) {
@strongify(self);
if (self.tag == 1) {
// add
NSMutableArray *list = @[].mutableCopy;
for (TUICommonContactSelectCellData *data in array) {
[list addObject:data.identifier];
}
[self.navigationController popToViewController:self animated:YES];
[self addGroupId:self.groupId memebers:list];
} else if (self.tag == 2) {
// delete
NSMutableArray *list = @[].mutableCopy;
for (TUICommonContactSelectCellData *data in array) {
[list addObject:data.identifier];
}
[self.navigationController popToViewController:self animated:YES];
[self deleteGroupId:self.groupId memebers:list];
}
};
if ([self.dataProvider.groupInfo canInviteMember]) {
[ac tuitheme_addAction:[UIAlertAction
actionWithTitle:TIMCommonLocalizableString(TUIKitGroupProfileManageAdd)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *_Nonnull action) {
// add
self.tag = 1;
NSMutableDictionary *param = [NSMutableDictionary dictionary];
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_TitleKey] =
TIMCommonLocalizableString(GroupAddFirend);
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_DisableIdsKey] = ids;
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_DisplayNamesKey] = displayNames;
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_CompletionKey] = selectContactCompletion;
self.showContactSelectVC = [TUICore createObject:TUICore_TUIContactObjectFactory
key:TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod
param:param];
[self.navigationController pushViewController:self.showContactSelectVC animated:YES];
}]];
}
if ([self.dataProvider.groupInfo canRemoveMember]) {
[ac tuitheme_addAction:[UIAlertAction
actionWithTitle:TIMCommonLocalizableString(TUIKitGroupProfileManageDelete)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *_Nonnull action) {
// delete
self.tag = 2;
NSMutableDictionary *param = [NSMutableDictionary dictionary];
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_TitleKey] =
TIMCommonLocalizableString(GroupDeleteFriend);
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_SourceIdsKey] = ids;
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_DisplayNamesKey] = displayNames;
param[TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod_CompletionKey] = selectContactCompletion;
self.showContactSelectVC = [TUICore createObject:TUICore_TUIContactObjectFactory
key:TUICore_TUIContactObjectFactory_GetContactSelectControllerMethod
param:param];
[self.navigationController pushViewController:self.showContactSelectVC animated:YES];
}]];
}
[ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(Cancel) style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:ac animated:YES completion:nil];
}
- (void)addGroupId:(NSString *)groupId memebers:(NSArray *)members {
@weakify(self);
[[V2TIMManager sharedInstance] inviteUserToGroup:_groupId
userList:members
succ:^(NSArray<V2TIMGroupMemberOperationResult *> *resultList) {
@strongify(self);
[self refreshData];
[TUITool makeToast:TIMCommonLocalizableString(add_success)];
}
fail:^(int code, NSString *desc) {
[TUITool makeToastError:code msg:desc];
}];
}
- (void)deleteGroupId:(NSString *)groupId memebers:(NSArray *)members {
@weakify(self);
[[V2TIMManager sharedInstance] kickGroupMember:groupId
memberList:members
reason:@""
succ:^(NSArray<V2TIMGroupMemberOperationResult *> *resultList) {
@strongify(self);
[self refreshData];
[TUITool makeToast:TIMCommonLocalizableString(delete_success)];
}
fail:^(int code, NSString *desc) {
[TUITool makeToastError:code msg:desc];
}];
}
#pragma mark - UITableViewDelegate, UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.members.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TUIMemberInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
TUIMemberInfoCellData *data = self.members[indexPath.row];
cell.data = data;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
TUIMemberInfoCellData *data = self.members[indexPath.row];
if (data) {
[self didCurrentMemberAtCellData:data];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 0;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
return [UIView new];
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
return [UIView new];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (scrollView.contentOffset.y > 0 && (scrollView.contentOffset.y >= scrollView.bounds.origin.y)) {
if (self.indicatorView.isAnimating) {
return;
}
[self.indicatorView startAnimating];
// There's no more data, stop loading.
if (self.dataProvider.isNoMoreData) {
[self.indicatorView stopAnimating];
[TUITool makeToast:TIMCommonLocalizableString(TUIKitMessageReadNoMoreData)];
return;
}
@weakify(self);
[self.dataProvider loadDatas:^(BOOL success, NSString *_Nonnull err, NSArray *_Nonnull datas) {
@strongify(self);
[self.indicatorView stopAnimating];
if (!success) {
return;
}
[self.members addObjectsFromArray:datas];
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
if (datas.count == 0) {
[self.tableView setContentOffset:CGPointMake(0, scrollView.contentOffset.y - TMessageController_Header_Height) animated:YES];
}
}];
}
}
- (void)didCurrentMemberAtCellData:(TUIMemberInfoCellData *)mem {
NSString *userID = mem.identifier;
@weakify(self);
[self getUserOrFriendProfileVCWithUserID:userID
succBlock:^(UIViewController *vc) {
@strongify(self);
[self.navigationController pushViewController:vc animated:YES];
}
failBlock:^(int code, NSString *desc){
}];
}
- (void)getUserOrFriendProfileVCWithUserID:(NSString *)userID succBlock:(void (^)(UIViewController *vc))succ failBlock:(nullable V2TIMFail)fail {
NSDictionary *param = @{
TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod_UserIDKey: userID ? : @"",
TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod_SuccKey: succ ? : ^(UIViewController *vc){},
TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod_FailKey: fail ? : ^(int code, NSString * desc){}
};
[TUICore createObject:TUICore_TUIContactObjectFactory key:TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod param:param];
}
- (UIActivityIndicatorView *)indicatorView {
if (_indicatorView == nil) {
_indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
_indicatorView.hidesWhenStopped = YES;
}
return _indicatorView;
}
- (UITableView *)tableView {
if (_tableView == nil) {
_tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
_tableView.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#F2F3F5");
_tableView.delegate = self;
_tableView.dataSource = self;
[_tableView registerClass:TUIMemberInfoCell.class forCellReuseIdentifier:@"cell"];
_tableView.rowHeight = 48.0;
}
return _tableView;
}
@end

View File

@@ -0,0 +1,19 @@
//
// TUIGroupNoticeController.h
// TUIGroup
//
// Created by harvy on 2022/1/11.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUIGroupNoticeController : UIViewController
@property(nonatomic, copy) dispatch_block_t onNoticeChanged;
@property(nonatomic, copy) NSString *groupID;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,114 @@
//
// TUIGroupNoticeController.m
// TUIGroup
//
// Created by harvy on 2022/1/11.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIGroupNoticeController.h"
#import <TUICore/TUIThemeManager.h>
#import "TUIGroupNoticeDataProvider.h"
@interface TUIGroupNoticeController ()
@property(nonatomic, strong) UITextView *textView;
@property(nonatomic, weak) UIButton *rightButton;
@property(nonatomic, strong) TUIGroupNoticeDataProvider *dataProvider;
@end
@implementation TUIGroupNoticeController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#F2F3F5");
[self.view addSubview:self.textView];
UIButton *rightBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[rightBtn setTitleColor:TIMCommonDynamicColor(@"nav_title_text_color", @"#000000") forState:UIControlStateNormal];
[rightBtn setTitleColor:TIMCommonDynamicColor(@"nav_title_text_color", @"#000000") forState:UIControlStateSelected];
[rightBtn setTitle:TIMCommonLocalizableString(Edit) forState:UIControlStateNormal];
[rightBtn setTitle:TIMCommonLocalizableString(Done) forState:UIControlStateSelected];
[rightBtn sizeToFit];
[rightBtn addTarget:self action:@selector(onClickRight:) forControlEvents:UIControlEventTouchUpInside];
self.rightButton = rightBtn;
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:rightBtn];
self.rightButton.hidden = YES;
UILabel *titleLabel = [[UILabel alloc] init];
titleLabel.text = TIMCommonLocalizableString(TUIKitGroupNotice);
titleLabel.font = [UIFont boldSystemFontOfSize:17.0];
titleLabel.textColor = TIMCommonDynamicColor(@"nav_title_text_color", @"#000000");
[titleLabel sizeToFit];
self.navigationItem.titleView = titleLabel;
__weak typeof(self) weakSelf = self;
self.dataProvider.groupID = self.groupID;
[self.dataProvider getGroupInfo:^{
weakSelf.textView.text = weakSelf.dataProvider.groupInfo.notification;
weakSelf.textView.editable = NO;
weakSelf.rightButton.hidden = !weakSelf.dataProvider.canEditNotice;
}];
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
self.textView.frame = self.view.bounds;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (self.dataProvider.canEditNotice && self.textView.text.length == 0) {
[self onClickRight:self.rightButton];
}
}
- (void)onClickRight:(UIButton *)button {
if (button.isSelected) {
self.textView.editable = NO;
[self.textView resignFirstResponder];
[self updateNotice];
} else {
self.textView.editable = YES;
[self.textView becomeFirstResponder];
}
button.selected = !button.isSelected;
}
- (void)updateNotice {
__weak typeof(self) weakSelf = self;
[self.dataProvider updateNotice:self.textView.text
callback:^(int code, NSString *desc) {
if (code != 0) {
[TUITool makeToastError:code msg:desc];
return;
}
if (weakSelf.onNoticeChanged) {
weakSelf.onNoticeChanged();
}
}];
}
- (UITextView *)textView {
if (_textView == nil) {
_textView = [[UITextView alloc] init];
_textView.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft;
_textView.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#F2F3F5");
_textView.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000");
_textView.font = [UIFont systemFontOfSize:17];
}
return _textView;
}
- (TUIGroupNoticeDataProvider *)dataProvider {
if (_dataProvider == nil) {
_dataProvider = [[TUIGroupNoticeDataProvider alloc] init];
}
return _dataProvider;
}
@end

View File

@@ -0,0 +1,17 @@
//
// TUIGroupRequestViewController.h
// TUIKitDemo
//
// Created by annidyfeng on 2019/5/20.
// Copyright © 2019 Tencent. All rights reserved.
//
#import <TIMCommon/TIMDefine.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface TUIGroupRequestViewController : UIViewController
@property V2TIMGroupInfo *groupInfo;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,168 @@
//
// TUIGroupRequestViewController.m
// TUIKitDemo
//
// Created by annidyfeng on 2019/5/20.
// Copyright © 2019 Tencent. All rights reserved.
//
#import "TUIGroupRequestViewController.h"
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
@interface TUIGroupRequestViewController () <UITableViewDataSource, UITableViewDelegate, TUIProfileCardDelegate>
@property UITableView *tableView;
@property UITextView *addMsgTextView;
@property TUIProfileCardCellData *cardCellData;
@end
@implementation TUIGroupRequestViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
[self.view addSubview:self.tableView];
self.tableView.mm_fill();
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.addMsgTextView = [[UITextView alloc] initWithFrame:CGRectZero];
self.addMsgTextView.font = [UIFont systemFontOfSize:14];
self.addMsgTextView.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft;
NSString *loginUser = [[V2TIMManager sharedInstance] getLoginUser];
[[V2TIMManager sharedInstance] getUsersInfo:@[ loginUser ]
succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
self.addMsgTextView.text = [NSString
stringWithFormat:TIMCommonLocalizableString(GroupRequestJoinGroupFormat), [[infoList firstObject] showName]];
}
fail:^(int code, NSString *msg){
}];
TUIProfileCardCellData *data = [TUIProfileCardCellData new];
data.name = self.groupInfo.groupName;
data.identifier = self.groupInfo.groupID;
data.avatarImage = DefaultGroupAvatarImageByGroupType(self.groupInfo.groupType);
data.avatarUrl = [NSURL URLWithString:self.groupInfo.faceURL];
self.cardCellData = data;
self.title = TIMCommonLocalizableString(GroupJoin);
[TUITool addUnsupportNotificationInVC:self];
}
- (void)dealloc {
NSLog(@"%s dealloc", __FUNCTION__);
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
if (indexPath.section == 0) {
return [self.cardCellData heightOfWidth:Screen_Width];
}
if (indexPath.section == 1) {
return 120;
}
if (indexPath.section == 2) {
return 54;
}
return 0.;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
UIView *view = [[UIView alloc] init];
return view;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *view = [[UIView alloc] init];
view.backgroundColor = [UIColor clearColor];
UILabel *label = [[UILabel alloc] init];
label.text = TIMCommonLocalizableString(please_fill_in_verification_information);
label.textColor = [UIColor colorWithRed:136 / 255.0 green:136 / 255.0 blue:136 / 255.0 alpha:1 / 1.0];
label.font = [UIFont systemFontOfSize:14.0];
label.frame = CGRectMake(10, 0, self.tableView.bounds.size.width - 20, 40);
[view addSubview:label];
return section == 1 ? view : nil;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
if (section == 1) {
return 40;
}
if (section == 2) {
return 10;
}
return 0;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
{ return 3; }
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
TUIProfileCardCell *cell = [[TUIProfileCardCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"TPersonalCommonCell_ReuseId"];
cell.delegate = self;
[cell fillWithData:self.cardCellData];
return cell;
}
if (indexPath.section == 1) {
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"AddWord"];
[cell.contentView addSubview:self.addMsgTextView];
self.addMsgTextView.mm_width(Screen_Width).mm_height(120);
return cell;
}
if (indexPath.section == 2) {
TUIButtonCell *cell = [[TUIButtonCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"send"];
TUIButtonCellData *cellData = [[TUIButtonCellData alloc] init];
cellData.title = TIMCommonLocalizableString(Send);
cellData.style = ButtonWhite;
cellData.cselector = @selector(onSend);
cellData.textColor = [UIColor colorWithRed:20 / 255.0 green:122 / 255.0 blue:255 / 255.0 alpha:1 / 1.0];
[cell fillWithData:cellData];
return cell;
}
return nil;
}
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
- (void)onSend {
// display toast with an activity spinner
[TUITool makeToastActivity];
[[V2TIMManager sharedInstance] joinGroup:self.groupInfo.groupID
msg:self.addMsgTextView.text
succ:^{
[TUITool hideToastActivity];
[TUITool makeToast:TIMCommonLocalizableString(send_success) duration:3.0 idposition:TUICSToastPositionBottom];
}
fail:^(int code, NSString *desc) {
[TUITool hideToastActivity];
[TUITool makeToastError:code msg:desc];
if (code == ERR_SDK_INTERFACE_NOT_SUPPORT) {
[TUITool postUnsupportNotificationOfService:TIMCommonLocalizableString(TUIKitErrorUnsupportIntefaceCommunity)
serviceDesc:TIMCommonLocalizableString(TUIKitErrorUnsupportIntefaceCommunityDesc)
debugOnly:YES];
}
}];
}
- (void)didTapOnAvatar:(TUIProfileCardCell *)cell {
TUIAvatarViewController *image = [[TUIAvatarViewController alloc] init];
image.avatarData = cell.cardData;
[self.navigationController pushViewController:image animated:YES];
}
@end

View File

@@ -0,0 +1,22 @@
//
// TUISearchGroupViewController.h
// TUIKitDemo
//
// Created by annidyfeng on 2019/5/20.
// Copyright © 2019 Tencent. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface SearchGroupSearchResultViewController : UIViewController
@end
@interface TUISearchGroupViewController : UIViewController
@property(nonatomic, retain) UISearchController *searchController;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,186 @@
//
// TUISearchGroupViewController.m
// TUIKitDemo
//
// Created by annidyfeng on 2019/5/20.
// Copyright © 2019 Tencent. All rights reserved.
//
#import "TUISearchGroupViewController.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUIThemeManager.h>
#import "TUIGroupRequestViewController.h"
@implementation UISearchController (Leak)
- (BOOL)willDealloc {
return NO;
}
@end
@interface AddGroupItemView : UIView
@property(nonatomic) V2TIMGroupInfo *groupInfo;
@end
@implementation AddGroupItemView {
UILabel *_idLabel;
UIView *_line;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
_idLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[self addSubview:_idLabel];
_line = [[UIView alloc] initWithFrame:CGRectZero];
_line.backgroundColor = [UIColor grayColor];
[self addSubview:_line];
return self;
}
- (void)setGroupInfo:(V2TIMGroupInfo *)groupInfo {
if (groupInfo) {
if (groupInfo.groupName.length > 0) {
_idLabel.text = [NSString stringWithFormat:@"%@ (group id: %@)", groupInfo.groupName, groupInfo.groupID];
} else {
_idLabel.text = groupInfo.groupID;
}
_idLabel.mm_sizeToFit().tui_mm_center().mm_left(8);
_line.mm_height(1).mm_width(self.mm_w).mm_bottom(0);
_line.hidden = NO;
} else {
_idLabel.text = @"";
_line.hidden = YES;
}
_groupInfo = groupInfo;
}
@end
@interface TUISearchGroupViewController () <UISearchBarDelegate>
@property(nonatomic, strong) AddGroupItemView *userView;
;
@end
@interface TUISearchGroupViewController () <UISearchControllerDelegate, UISearchBarDelegate>
@end
@implementation TUISearchGroupViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = TIMCommonLocalizableString(ContactsJoinGroup);
self.view.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#F2F3F5");
self.edgesForExtendedLayout = UIRectEdgeNone;
self.automaticallyAdjustsScrollViewInsets = NO;
self.definesPresentationContext = YES;
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.delegate = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
_searchController.searchBar.placeholder = @"group ID";
_searchController.searchBar.delegate = self;
[self.view addSubview:_searchController.searchBar];
[self setSearchIconCenter:YES];
self.userView = [[AddGroupItemView alloc] initWithFrame:CGRectZero];
[self.view addSubview:self.userView];
UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleUserTap:)];
[self.userView addGestureRecognizer:singleFingerTap];
}
- (void)setSearchIconCenter:(BOOL)center {
if (center) {
CGSize size = [self.searchController.searchBar.placeholder sizeWithAttributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14.0]}];
CGFloat width = size.width + 60;
[self.searchController.searchBar setPositionAdjustment:UIOffsetMake(0.5 * (self.searchController.searchBar.bounds.size.width - width), 0)
forSearchBarIcon:UISearchBarIconSearch];
} else {
[self.searchController.searchBar setPositionAdjustment:UIOffsetZero forSearchBarIcon:UISearchBarIconSearch];
}
}
#pragma mark - UISearchControllerDelegate
- (void)didPresentSearchController:(UISearchController *)searchController {
NSLog(@"didPresentSearchController");
[self.view addSubview:self.searchController.searchBar];
self.searchController.searchBar.mm_top([self safeAreaTopGap]);
self.userView.mm_top(self.searchController.searchBar.mm_maxY).mm_height(44).mm_width(Screen_Width);
}
- (void)willPresentSearchController:(UISearchController *)searchController {
[self setSearchIconCenter:NO];
}
- (void)willDismissSearchController:(UISearchController *)searchController {
[self setSearchIconCenter:YES];
}
- (CGFloat)safeAreaTopGap {
NSNumber *gap;
if (gap == nil) {
if (@available(iOS 11, *)) {
gap = @(self.view.safeAreaLayoutGuide.layoutFrame.origin.y);
} else {
gap = @(0);
}
}
return gap.floatValue;
}
- (void)didDismissSearchController:(UISearchController *)searchController {
NSLog(@"didDismissSearchController");
self.searchController.searchBar.mm_top(0);
self.userView.groupInfo = nil;
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
self.searchController.active = YES;
return YES;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
self.searchController.active = NO;
}
- (void)handleUserTap:(id)sender {
if (self.userView.groupInfo) {
TUIGroupRequestViewController *frc = [[TUIGroupRequestViewController alloc] init];
frc.groupInfo = self.userView.groupInfo;
[self.navigationController pushViewController:frc animated:YES];
}
}
#pragma mark - UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
NSString *inputStr = searchBar.text;
[[V2TIMManager sharedInstance] getGroupsInfo:@[ inputStr ]
succ:^(NSArray<V2TIMGroupInfoResult *> *groupResultList) {
if (groupResultList.count > 0) {
V2TIMGroupInfoResult *result = groupResultList.firstObject;
if (0 == result.resultCode) {
self.userView.groupInfo = result.info;
} else {
self.userView.groupInfo = nil;
}
} else {
self.userView.groupInfo = nil;
}
}
fail:^(int code, NSString *desc) {
self.userView.groupInfo = nil;
}];
}
@end

View File

@@ -0,0 +1,25 @@
//
// TUISelectGroupMemberViewController.h
// TXIMSDK_TUIKit_iOS
//
// Created by xiangzhang on 2020/7/6.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <TIMCommon/TIMDefine.h>
#import <UIKit/UIKit.h>
#import "TUIGroupDefine.h"
#import "TUISelectGroupMemberCell.h"
NS_ASSUME_NONNULL_BEGIN
@interface TUISelectGroupMemberViewController : UIViewController
@property(nonatomic, copy) NSString *groupId;
@property(nonatomic, copy) NSString *name;
@property(nonatomic, strong) SelectedFinished selectedFinished;
@property(nonatomic, assign) TUISelectMemberOptionalStyle optionalStyle;
@property(nonatomic, strong) NSArray *selectedUserIDList;
@property(nonatomic, copy) NSString *userData;
@end
NS_ASSUME_NONNULL_END

Some files were not shown because too many files have changed in this diff Show More