This commit is contained in:
启星
2025-08-08 10:49:36 +08:00
parent 6400cf78bb
commit b5ce3d580a
8780 changed files with 978183 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
/**
*
* This file declares the view model used to implement the blocklist page.
* The view model is responsible for some data processing and business logic in the interface, such as pulling blacklist information and loading blocklist
* data.
*/
#import <Foundation/Foundation.h>
#import "TUICommonContactCell_Minimalist.h"
NS_ASSUME_NONNULL_BEGIN
/**
* 【Module name】 TUIBlackListViewModel
* 【Function description】It is responsible for pulling the user's blocklist information and displaying it on the page.
* The view model is also responsible for loading the pulled information to facilitate data processing in the client.
*/
@interface TUIBlackListViewDataProvider_Minimalist : NSObject
/**
* Bocklist data
* The blocklist stores the detailed information of the blocked users.
* Include details such as user avatar (URL and image), user ID, user nickname, etc. Used to display detailed information when you click to a detailed meeting.
*/
@property(readonly) NSArray<TUICommonContactCellData_Minimalist *> *blackListData;
@property(readonly) BOOL isLoadFinished;
- (void)loadBlackList;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,42 @@
//
// TUIBlackListViewModel.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/5.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIBlackListViewDataProvider_Minimalist.h"
#import <TIMCommon/TIMDefine.h>
@interface TUIBlackListViewDataProvider_Minimalist ()
@property NSArray<TUICommonContactCellData_Minimalist *> *blackListData;
@property BOOL isLoadFinished;
@property BOOL isLoading;
@end
@implementation TUIBlackListViewDataProvider_Minimalist
- (void)loadBlackList {
if (self.isLoading) return;
self.isLoading = YES;
self.isLoadFinished = NO;
@weakify(self);
[[V2TIMManager sharedInstance]
getBlackList:^(NSArray<V2TIMFriendInfo *> *infoList) {
@strongify(self);
NSMutableArray *list = @[].mutableCopy;
for (V2TIMFriendInfo *fd in infoList) {
TUICommonContactCellData_Minimalist *data = [[TUICommonContactCellData_Minimalist alloc] initWithFriend:fd];
[list addObject:data];
}
self.blackListData = list;
self.isLoadFinished = YES;
self.isLoading = NO;
}
fail:^(int code, NSString *msg) {
self.isLoading = NO;
}];
}
@end

View File

@@ -0,0 +1,64 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
/**
*
* This file declares the view model for the friend selection interface
* The view model is responsible for pulling friend data through the IM SDK interface and loading the data.
*/
#import <Foundation/Foundation.h>
@class TUICommonContactSelectCellData_Minimalist;
NS_ASSUME_NONNULL_BEGIN
typedef BOOL (^ContactSelectFilterBlock_Minimalist)(TUICommonContactSelectCellData_Minimalist *data);
/**
* 【Module name】Friend selection interface view model (TContactSelectViewModel)
* 【Function description】Implement the friend selection interface view model.
* This view model is responsible for pulling friend lists, friend requests and loading related data from the server.
* At the same time, this view model will also group friends according to the initials of their nicknames, which helps the view maintain an "alphabet" on the
* right side of the interface to quickly retrieve friends.
*/
@interface TUIContactSelectViewDataProvider_Minimalist : NSObject
/**
* Data dictionary, responsible for classifying friend information (TCommonContactCellData) by initials.
* For example, Jack and James are stored in "J".
*/
@property(readonly) NSDictionary<NSString *, NSArray<TUICommonContactSelectCellData_Minimalist *> *> *dataDict;
/**
* The group list, that is, the group information of the current friend.
* For example, if the current user has only one friend "Jack", there is only one element "J" in this list.
* The grouping information is up to 26 letters from A - Z and "#".
*/
@property(readonly) NSArray *groupList;
/**
* An identifier indicating whether the current loading process is complete
* YES: Loading is done; NO: Loading
* With this identifier, we can avoid reloading the data.
*/
@property(readonly) BOOL isLoadFinished;
/**
*
* Filter to disable contacts
*/
@property(copy) ContactSelectFilterBlock_Minimalist disableFilter;
/**
*
* Filter to display contacts
*/
@property(copy) ContactSelectFilterBlock_Minimalist avaliableFilter;
- (void)loadContacts;
- (void)setSourceIds:(NSArray<NSString *> *)ids;
- (void)setSourceIds:(NSArray<NSString *> *)ids displayNames:(NSDictionary *__nullable)displayNames;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,106 @@
//
// TContactSelectViewModel.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/8.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIContactSelectViewDataProvider_Minimalist.h"
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
#import <TUICore/NSString+TUIUtil.h>
#import "TUICommonContactSelectCell_Minimalist.h"
@interface TUIContactSelectViewDataProvider_Minimalist ()
@property NSDictionary<NSString *, NSArray<TUICommonContactSelectCellData_Minimalist *> *> *dataDict;
@property NSArray *groupList;
@property BOOL isLoadFinished;
@end
@implementation TUIContactSelectViewDataProvider_Minimalist
- (void)loadContacts {
self.isLoadFinished = NO;
@weakify(self);
[[V2TIMManager sharedInstance]
getFriendList:^(NSArray<V2TIMFriendInfo *> *infoList) {
@strongify(self);
NSMutableArray *arr = [NSMutableArray new];
for (V2TIMFriendInfo *fr in infoList) {
[arr addObject:fr.userFullInfo];
}
[self fillList:arr displayNames:nil];
}
fail:nil];
}
- (void)setSourceIds:(NSArray<NSString *> *)ids {
[self setSourceIds:ids displayNames:nil];
}
- (void)setSourceIds:(NSArray<NSString *> *)ids displayNames:(NSDictionary *__nullable)displayNames {
[[V2TIMManager sharedInstance] getUsersInfo:ids
succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
[self fillList:infoList displayNames:displayNames];
}
fail:nil];
}
- (void)fillList:(NSArray<V2TIMUserFullInfo *> *)profiles displayNames:(NSDictionary *__nullable)displayNames {
NSMutableDictionary *dataDict = @{}.mutableCopy;
NSMutableArray *groupList = @[].mutableCopy;
NSMutableArray *nonameList = @[].mutableCopy;
for (V2TIMUserFullInfo *profile in profiles) {
TUICommonContactSelectCellData_Minimalist *data = [[TUICommonContactSelectCellData_Minimalist alloc] init];
NSString *showName = @"";
if (displayNames && [displayNames.allKeys containsObject:profile.userID]) {
showName = [displayNames objectForKey:profile.userID];
}
if (showName.length == 0) {
showName = profile.showName;
}
data.title = showName;
if (profile.faceURL.length) {
data.avatarUrl = [NSURL URLWithString:profile.faceURL];
}
data.identifier = profile.userID;
if (self.avaliableFilter && !self.avaliableFilter(data)) {
continue;
}
if (self.disableFilter) {
data.enabled = !self.disableFilter(data);
}
NSString *group = [[data.title firstPinYin] uppercaseString];
if (group.length == 0 || !isalpha([group characterAtIndex:0])) {
[nonameList addObject:data];
continue;
}
NSMutableArray *list = [dataDict objectForKey:group];
if (!list) {
list = @[].mutableCopy;
dataDict[group] = list;
[groupList addObject:group];
}
[list addObject:data];
}
[groupList sortUsingSelector:@selector(localizedStandardCompare:)];
if (nonameList.count) {
[groupList addObject:@"#"];
dataDict[@"#"] = nonameList;
}
for (NSMutableArray *list in [self.dataDict allValues]) {
[list sortUsingSelector:@selector(compare:)];
}
self.groupList = groupList;
self.dataDict = dataDict;
self.isLoadFinished = YES;
}
@end

View File

@@ -0,0 +1,58 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
/**
* This file declares the view model for the Contacts interface.
* The view model is responsible for pulling friend lists, friend requests from the server and loading related data.
*/
#import <Foundation/Foundation.h>
#import "TUICommonContactCell_Minimalist.h"
NS_ASSUME_NONNULL_BEGIN
/**
* 【Module name】Message List View Model (TContactViewModel)
* 【Function description】A view model that implements a message list.
* 1. This view model is responsible for pulling friend lists, friend requests and loading related data from the server.
* 2. At the same time, this view model will also group friends by the first latter of their nicknames, which helps the view maintain an "alphabet" on the
* right side of the interface to facilitate quick retrieval of friends.
*/
@interface TUIContactViewDataProvider_Minimalist : NSObject
/**
* Data dictionary, responsible for classifying friend information (TCommonContactCellData) by initials.
* For example, Jack and James are stored in "J".
*/
@property(readonly) NSDictionary<NSString *, NSArray<TUICommonContactCellData_Minimalist *> *> *dataDict;
/**
* The group list, that is, the group information of the current friend.
* For example, if the current user has only one friend "Jack", there is only one element "J" in this list.
* The grouping information is up to 26 letters from A - Z and "#".
*/
@property(readonly) NSArray *groupList;
/**
* An identifier indicating whether the current loading process is complete
* YES: Loading is done; NO: Loading
* With this identifier, we can avoid reloading the data.
*/
@property(readonly) BOOL isLoadFinished;
/**
* Count of pending friend requests
*/
@property(readonly) NSUInteger pendencyCnt;
@property(readonly) NSDictionary *contactMap;
- (void)loadContacts;
- (void)loadFriendApplication;
- (void)clearApplicationCnt;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,255 @@
//
// TContactViewModel.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/5.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIContactViewDataProvider_Minimalist.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/NSString+TUIUtil.h>
#define kGetUserStatusPageCount 500
@interface TUIContactViewDataProvider_Minimalist () <V2TIMFriendshipListener, V2TIMSDKListener>
@property NSDictionary<NSString *, NSArray<TUICommonContactCellData_Minimalist *> *> *dataDict;
@property NSArray *groupList;
@property BOOL isLoadFinished;
@property NSUInteger pendencyCnt;
@property(nonatomic, strong) NSDictionary *contactMap;
@end
@implementation TUIContactViewDataProvider_Minimalist
- (instancetype)init {
if (self = [super init]) {
[[V2TIMManager sharedInstance] addFriendListener:self];
[[V2TIMManager sharedInstance] addIMSDKListener:self];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)loadContacts {
self.isLoadFinished = NO;
@weakify(self);
[[V2TIMManager sharedInstance]
getFriendList:^(NSArray<V2TIMFriendInfo *> *infoList) {
@strongify(self);
NSMutableDictionary *dataDict = @{}.mutableCopy;
NSMutableArray *groupList = @[].mutableCopy;
NSMutableArray *nonameList = @[].mutableCopy;
NSMutableDictionary *contactMap = [NSMutableDictionary dictionary];
NSMutableArray *userIDList = [NSMutableArray array];
for (V2TIMFriendInfo *friend in infoList) {
TUICommonContactCellData_Minimalist *data = [[TUICommonContactCellData_Minimalist alloc] initWithFriend:friend];
// for online status
data.onlineStatus = TUIContactOnlineStatusUnknown_Minimalist;
if (data.identifier) {
[contactMap setObject:data forKey:data.identifier];
[userIDList addObject:data.identifier];
}
NSString *group = [[data.title firstPinYin] uppercaseString];
if (group.length == 0 || !isalpha([group characterAtIndex:0])) {
[nonameList addObject:data];
continue;
}
NSMutableArray *list = [dataDict objectForKey:group];
if (!list) {
list = @[].mutableCopy;
dataDict[group] = list;
[groupList addObject:group];
}
[list addObject:data];
}
[groupList sortUsingSelector:@selector(localizedStandardCompare:)];
if (nonameList.count) {
[groupList addObject:@"#"];
dataDict[@"#"] = nonameList;
}
for (NSMutableArray *list in [dataDict allValues]) {
[list sortUsingSelector:@selector(compare:)];
}
self.groupList = groupList;
self.dataDict = dataDict;
self.contactMap = [NSDictionary dictionaryWithDictionary:contactMap];
self.isLoadFinished = YES;
// refresh online status async
[self asyncGetOnlineStatus:userIDList];
}
fail:^(int code, NSString *desc) {
NSLog(@"getFriendList failed, code:%d desc:%@", code, desc);
}];
[self loadFriendApplication];
}
- (void)loadFriendApplication {
@weakify(self);
[[V2TIMManager sharedInstance]
getFriendApplicationList:^(V2TIMFriendApplicationResult *result) {
@strongify(self);
self.pendencyCnt = result.unreadCount;
}
fail:nil];
}
- (void)asyncGetOnlineStatus:(NSArray *)userIDList {
if (NSThread.isMainThread) {
@weakify(self);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
@strongify(self);
[self asyncGetOnlineStatus:userIDList];
});
return;
}
if (userIDList.count == 0) {
return;
}
@weakify(self);
void (^getUserStatus)(NSArray *userIDList) = ^(NSArray *userIDList) {
@strongify(self);
@weakify(self);
[V2TIMManager.sharedInstance getUserStatus:userIDList
succ:^(NSArray<V2TIMUserStatus *> *result) {
@strongify(self);
[self handleOnlineStatus:result];
}
fail:^(int code, NSString *desc) {
#if DEBUG
if (code == ERR_SDK_INTERFACE_NOT_SUPPORT && TUIConfig.defaultConfig.displayOnlineStatusIcon) {
[TUITool makeToast:desc];
}
#endif
}];
};
NSInteger count = kGetUserStatusPageCount;
if (userIDList.count > count) {
NSArray *subUserIDList = [userIDList subarrayWithRange:NSMakeRange(0, count)];
NSArray *pendingUserIDList = [userIDList subarrayWithRange:NSMakeRange(count, userIDList.count - count)];
getUserStatus(subUserIDList);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
@strongify(self);
[self asyncGetOnlineStatus:pendingUserIDList];
});
} else {
getUserStatus(userIDList);
}
}
- (void)asyncUpdateOnlineStatus {
if (NSThread.isMainThread) {
@weakify(self);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
@strongify(self);
[self asyncUpdateOnlineStatus];
});
return;
}
// reset
NSMutableArray *userIDList = [NSMutableArray array];
for (TUICommonContactCellData_Minimalist *contact in self.contactMap.allValues) {
contact.onlineStatus = TUIContactOnlineStatusOffline_Minimalist;
if (contact.identifier) {
[userIDList addObject:contact.identifier];
}
}
// refresh table view on the main thread
@weakify(self);
dispatch_async(dispatch_get_main_queue(), ^{
@strongify(self);
self.isLoadFinished = YES;
// fetch
[self asyncGetOnlineStatus:userIDList];
});
}
- (void)handleOnlineStatus:(NSArray<V2TIMUserStatus *> *)userStatusList {
NSInteger changed = 0;
for (V2TIMUserStatus *userStatus in userStatusList) {
if ([self.contactMap.allKeys containsObject:userStatus.userID]) {
changed++;
TUICommonContactCellData_Minimalist *contact = [self.contactMap objectForKey:userStatus.userID];
contact.onlineStatus =
(userStatus.statusType == V2TIM_USER_STATUS_ONLINE) ? TUIContactOnlineStatusOnline_Minimalist : TUIContactOnlineStatusOffline_Minimalist;
}
}
if (changed == 0) {
return;
}
// refresh table view on the main thread
@weakify(self);
dispatch_async(dispatch_get_main_queue(), ^{
@strongify(self);
self.isLoadFinished = YES;
});
}
- (void)clearApplicationCnt {
@weakify(self);
[[V2TIMManager sharedInstance]
setFriendApplicationRead:^{
@strongify(self);
(self).pendencyCnt = 0;
}
fail:nil];
}
#pragma mark - V2TIMSDKListener
- (void)onUserStatusChanged:(NSArray<V2TIMUserStatus *> *)userStatusList {
[self handleOnlineStatus:userStatusList];
}
- (void)onConnectFailed:(int)code err:(NSString *)err {
NSLog(@"%s", __func__);
}
- (void)onConnectSuccess {
NSLog(@"%s", __func__);
[self asyncUpdateOnlineStatus];
}
#pragma mark - V2TIMFriendshipListener
- (void)onFriendApplicationListAdded:(NSArray<V2TIMFriendApplication *> *)applicationList {
[self loadFriendApplication];
}
- (void)onFriendApplicationListDeleted:(NSArray *)userIDList {
[self loadFriendApplication];
}
- (void)onFriendApplicationListRead {
[self loadFriendApplication];
}
- (void)onFriendListAdded:(NSArray<V2TIMFriendInfo *> *)infoList {
[self loadContacts];
}
- (void)onFriendListDeleted:(NSArray *)userIDList {
[self loadContacts];
}
- (void)onFriendProfileChanged:(NSArray<V2TIMFriendInfo *> *)infoList {
[self loadContacts];
}
@end

View File

@@ -0,0 +1,27 @@
//
// TUIFindContactViewDataProvider.h
// TUIContact
//
// Created by harvy on 2021/12/13.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "TUIFindContactCellModel_Minimalist.h"
NS_ASSUME_NONNULL_BEGIN
@interface TUIFindContactViewDataProvider_Minimalist : NSObject
@property(nonatomic, strong, readonly) NSArray<TUIFindContactCellModel_Minimalist *> *users;
@property(nonatomic, strong, readonly) NSArray<TUIFindContactCellModel_Minimalist *> *groups;
- (void)findUser:(NSString *)userID completion:(dispatch_block_t)completion;
- (void)findGroup:(NSString *)groupID completion:(dispatch_block_t)completion;
- (NSString *)getMyUserIDDescription;
- (void)clear;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,100 @@
//
// TUIFindContactViewDataProvider.m
// TUIContact
//
// Created by harvy on 2021/12/13.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIFindContactViewDataProvider_Minimalist.h"
#import <ImSDK_Plus/ImSDK_Plus.h>
#import <TUICore/TUIGlobalization.h>
#import "TUIFindContactCellModel_Minimalist.h"
@interface TUIFindContactViewDataProvider_Minimalist ()
@property(nonatomic, strong) NSArray<TUIFindContactCellModel_Minimalist *> *users;
@property(nonatomic, strong) NSArray<TUIFindContactCellModel_Minimalist *> *groups;
@end
@implementation TUIFindContactViewDataProvider_Minimalist
- (void)findUser:(NSString *)userID completion:(dispatch_block_t)completion {
if (!completion) {
return;
}
if (userID == nil) {
self.users = @[];
completion();
return;
}
__weak typeof(self) weakSelf = self;
[[V2TIMManager sharedInstance] getUsersInfo:@[ userID ]
succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
V2TIMUserFullInfo *userInfo = infoList.firstObject;
if (userInfo) {
TUIFindContactCellModel_Minimalist *cellModel = [[TUIFindContactCellModel_Minimalist alloc] init];
cellModel.avatarUrl = [NSURL URLWithString:userInfo.faceURL];
cellModel.mainTitle = userInfo.nickName ?: userInfo.userID;
cellModel.subTitle = userInfo.userID ?: userInfo.userID;
cellModel.desc = @"";
cellModel.type = TUIFindContactTypeC2C_Minimalist;
cellModel.contactID = userInfo.userID;
cellModel.userInfo = userInfo;
weakSelf.users = @[ cellModel ];
}
completion();
}
fail:^(int code, NSString *msg) {
weakSelf.users = @[];
completion();
}];
}
- (void)findGroup:(NSString *)groupID completion:(dispatch_block_t)completion {
if (!completion) {
return;
}
if (groupID == nil) {
self.groups = @[];
completion();
return;
}
__weak typeof(self) weakSelf = self;
[[V2TIMManager sharedInstance] getGroupsInfo:@[ groupID ]
succ:^(NSArray<V2TIMGroupInfoResult *> *groupResultList) {
V2TIMGroupInfoResult *result = groupResultList.firstObject;
if (result && result.resultCode == 0) {
V2TIMGroupInfo *info = result.info;
TUIFindContactCellModel_Minimalist *cellModel = [[TUIFindContactCellModel_Minimalist alloc] init];
cellModel.avatarUrl = [NSURL URLWithString:info.faceURL];
cellModel.mainTitle = info.groupName;
cellModel.subTitle = info.groupID;
cellModel.desc = [NSString stringWithFormat:@"%@: %@",TIMCommonLocalizableString(TUIKitGroupProfileType),info.groupType];
cellModel.type = TUIFindContactTypeGroup_Minimalist;
cellModel.contactID = info.groupID;
cellModel.groupInfo = info;
weakSelf.groups = @[ cellModel ];
} else {
weakSelf.groups = @[];
}
completion();
}
fail:^(int code, NSString *desc) {
weakSelf.groups = @[];
completion();
}];
}
- (NSString *)getMyUserIDDescription {
NSString *loginUser = V2TIMManager.sharedInstance.getLoginUser;
return [NSString stringWithFormat:TIMCommonLocalizableString(TUIKitAddContactMyUserIDFormat), loginUser];
}
- (void)clear {
self.users = @[];
self.groups = @[];
}
@end

View File

@@ -0,0 +1,35 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
/**
* This file declares the view model for the group list interface.
* The view model is responsible for pulling and loading the group list data through the interface provided by the IM SDK, which is convenient for the page to
* display the group list.
*/
#import <Foundation/Foundation.h>
#import "TUICommonContactCell_Minimalist.h"
NS_ASSUME_NONNULL_BEGIN
/**
* 【Module name】Group List View Model (TUIGroupConversationListViewModel)
* 【Function description】It is responsible for pulling the group information of the user and loading the obtained data.
* The view model pulls the group information of the user through the interface provided by the IM SDK. The group information is classified and stored
* according to the first latter of the name.
*/
@interface TUIGroupConversationListViewDataProvider_Minimalist : NSObject
@property(readonly) NSDictionary<NSString *, NSArray<TUICommonContactCellData_Minimalist *> *> *dataDict;
@property(readonly) NSArray *groupList;
@property(readonly) BOOL isLoadFinished;
- (void)loadConversation;
- (void)removeData:(TUICommonContactCellData_Minimalist *)data;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,81 @@
//
// TUIGroupConversationListModel.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/6/11.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIGroupConversationListViewDataProvider_Minimalist.h"
#import <TIMCommon/TIMDefine.h>
#import <TUICore/NSString+TUIUtil.h>
@interface TUIGroupConversationListViewDataProvider_Minimalist ()
@property BOOL isLoadFinished;
@property BOOL isLoading;
@property NSDictionary<NSString *, NSArray<TUICommonContactCellData_Minimalist *> *> *dataDict;
@property NSArray *groupList;
@end
@implementation TUIGroupConversationListViewDataProvider_Minimalist
- (void)loadConversation {
if (self.isLoading) return;
self.isLoading = NO;
self.isLoadFinished = NO;
NSMutableDictionary *dataDict = @{}.mutableCopy;
NSMutableArray *groupList = @[].mutableCopy;
NSMutableArray *nonameList = @[].mutableCopy;
@weakify(self);
[[V2TIMManager sharedInstance]
getJoinedGroupList:^(NSArray<V2TIMGroupInfo *> *infoList) {
@strongify(self);
for (V2TIMGroupInfo *group in infoList) {
TUICommonContactCellData_Minimalist *data = [[TUICommonContactCellData_Minimalist alloc] initWithGroupInfo:group];
NSString *group = [[data.title firstPinYin] uppercaseString];
if (group.length == 0 || !isalpha([group characterAtIndex:0])) {
[nonameList addObject:data];
continue;
}
NSMutableArray *list = [dataDict objectForKey:group];
if (!list) {
list = @[].mutableCopy;
dataDict[group] = list;
[groupList addObject:group];
}
[list addObject:data];
}
[groupList sortUsingSelector:@selector(localizedStandardCompare:)];
if (nonameList.count) {
[groupList addObject:@"#"];
dataDict[@"#"] = nonameList;
}
for (NSMutableArray *list in [self.dataDict allValues]) {
[list sortUsingSelector:@selector(compare:)];
}
self.groupList = groupList;
self.dataDict = dataDict;
self.isLoadFinished = YES;
}
fail:nil];
}
- (void)removeData:(TUICommonContactCellData_Minimalist *)data {
NSMutableDictionary *dictDict = [NSMutableDictionary dictionaryWithDictionary:self.dataDict];
for (NSString *key in self.dataDict) {
NSMutableArray *list = [NSMutableArray arrayWithArray:self.dataDict[key]];
if ([list containsObject:data]) {
[list removeObject:data];
dictDict[key] = list;
break;
}
}
self.dataDict = dictDict;
}
@end

View File

@@ -0,0 +1,44 @@
//
// TUIGroupManageDataProvider_Minimalist.h
// TUIGroup
//
// Created by wyl on 2023/1/9.
// Copyright © 2023 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
@class TUIUserModel;
NS_ASSUME_NONNULL_BEGIN
@protocol TUIGroupManageDataProviderDelegate_Minimalist <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_Minimalist : 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_Minimalist> 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,284 @@
//
// TUIGroupManageDataProvider_Minimalist.m
// TUIGroup
//
// Created by wyl on 2023/1/9.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUIGroupManageDataProvider_Minimalist.h"
#import <ImSDK_Plus/ImSDK_Plus.h>
#import <TIMCommon/TIMCommonModel.h>
#import <TUICore/TUIGlobalization.h>
#import "TUIMemberInfoCellData_Minimalist.h"
#import "TUISelectGroupMemberCell.h"
@interface TUIGroupManageDataProvider_Minimalist ()
@property(nonatomic, strong) NSMutableArray *datas;
@property(nonatomic, strong) NSMutableArray *groupInfoDatasArray;
@property(nonatomic, strong) NSMutableArray *muteMembersDataArray;
@property(nonatomic, strong) V2TIMGroupInfo *groupInfo;
@end
@implementation TUIGroupManageDataProvider_Minimalist
- (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;
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_Minimalist *existData = nil;
for (TUIMemberInfoCellData_Minimalist *data in weakSelf.muteMembersDataArray) {
if ([data.identifier isEqualToString:user.userId]) {
existData = data;
break;
}
}
if (code == 0 && mute) {
// mute succ
if (!existData) {
TUIMemberInfoCellData_Minimalist *cellData = [[TUIMemberInfoCellData_Minimalist 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_Minimalist *add = [[TUIMemberInfoCellData_Minimalist alloc] init];
add.avatar = TUIContactCommonBundleImage(@"icon_group_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_Minimalist *member = [[TUIMemberInfoCellData_Minimalist alloc] init];
member.avatarUrl = info.faceURL;
member.name = (info.nameCard ?: info.nickName) ?: info.userID;
member.identifier = info.userID;
BOOL exist = NO;
for (TUIMemberInfoCellData_Minimalist *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,34 @@
// Created by Tencent on 2023/06/09.
// Copyright © 2023 Tencent. All rights reserved.
/**
* This file declares the view model for the friend request interface.
* The view model can pull the friend application information through the interface provided by the IM SDK, and load the pulled information to facilitate the
* further display of the friend application interface.
*/
#import <Foundation/Foundation.h>
#import "TUICommonPendencyCell_Minimalist.h"
NS_ASSUME_NONNULL_BEGIN
@interface TUINewFriendViewDataProvider_Minimalist : NSObject
@property(readonly) NSArray *dataList;
/**
* Has data not shown.
* YESThere are unshown requestsNOAll requests are loaded.
*/
@property BOOL hasNextData;
@property BOOL isLoading;
- (void)loadData;
- (void)removeData:(TUICommonPendencyCellData_Minimalist *)data;
- (void)agreeData:(TUICommonPendencyCellData_Minimalist *)data;
- (void)rejectData:(TUICommonPendencyCellData_Minimalist *)data;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,83 @@
//
// TUINewFriendViewModel.m
// TXIMSDK_TUIKit_iOS
//
// Created by annidyfeng on 2019/5/7.
// Copyright © 2023 Tencent. All rights reserved.
//
#import "TUINewFriendViewDataProvider_Minimalist.h"
#import <TIMCommon/TIMDefine.h>
@interface TUINewFriendViewDataProvider_Minimalist ()
@property NSArray *dataList;
@property(nonatomic, assign) uint64_t origSeq;
@property(nonatomic, assign) uint64_t seq;
@property(nonatomic, assign) uint64_t timestamp;
@property(nonatomic, assign) uint64_t numPerPage;
@end
@implementation TUINewFriendViewDataProvider_Minimalist
- (instancetype)init {
self = [super init];
_numPerPage = 5;
_dataList = @[];
return self;
}
- (void)loadData {
if (self.isLoading) return;
self.isLoading = YES;
@weakify(self);
[[V2TIMManager sharedInstance]
getFriendApplicationList:^(V2TIMFriendApplicationResult *result) {
@strongify(self);
NSMutableArray *list = @[].mutableCopy;
for (V2TIMFriendApplication *item in result.applicationList) {
if (item.type == V2TIM_FRIEND_APPLICATION_COME_IN) {
TUICommonPendencyCellData_Minimalist *data = [[TUICommonPendencyCellData_Minimalist alloc] initWithPendency:item];
data.hideSource = YES;
[list addObject:data];
}
}
self.dataList = list;
self.isLoading = NO;
self.hasNextData = YES;
}
fail:nil];
}
- (void)removeData:(TUICommonPendencyCellData_Minimalist *)data {
NSMutableArray *dataList = [NSMutableArray arrayWithArray:self.dataList];
[dataList removeObject:data];
self.dataList = dataList;
[[V2TIMManager sharedInstance] deleteFriendApplication:data.application succ:nil fail:nil];
}
- (void)agreeData:(TUICommonPendencyCellData_Minimalist *)data {
[[V2TIMManager sharedInstance] acceptFriendApplication:data.application type:V2TIM_FRIEND_ACCEPT_AGREE_AND_ADD succ:nil fail:nil];
data.isAccepted = YES;
}
- (void)rejectData:(TUICommonPendencyCellData_Minimalist *)data {
[V2TIMManager.sharedInstance refuseFriendApplication:data.application
succ:^(V2TIMFriendOperationResult *result) {
}
fail:^(int code, NSString *desc){
}];
data.isRejected = YES;
}
@end