mirror of
https://github.com/TencentCloud/TIMSDK.git
synced 2026-10-21 08:46:21 +08:00
369 lines
14 KiB
Objective-C
369 lines
14 KiB
Objective-C
//
|
|
// ChatViewController.m
|
|
// TUIKitDemo
|
|
//
|
|
// Created by kennethmiao on 2018/10/10.
|
|
// Copyright © 2018年 Tencent. All rights reserved.
|
|
//
|
|
/** 腾讯云IM Demo 聊天视图
|
|
* 本文件实现了聊天视图
|
|
* 在用户需要收发群组、以及其他用户消息时提供UI
|
|
*
|
|
* 本类依赖于腾讯云 TUIKit和IMSDK 实现
|
|
*
|
|
*/
|
|
#import "ChatViewController.h"
|
|
#import "GroupInfoController.h"
|
|
#import "TUserProfileController.h"
|
|
#import "TUIC2CChatViewController.h"
|
|
#import "TUIGroupChatViewController.h"
|
|
#import "TFriendProfileController.h"
|
|
#import "TUIVideoMessageCell.h"
|
|
#import "TUIFileMessageCell.h"
|
|
#import "TUITextMessageCell.h"
|
|
#import "TUISystemMessageCell.h"
|
|
#import "TUIVoiceMessageCell.h"
|
|
#import "TUIImageMessageCell.h"
|
|
#import "TUIFaceMessageCell.h"
|
|
#import "TUIVideoMessageCell.h"
|
|
#import "TUIFileMessageCell.h"
|
|
#import "TUIJoinGroupMessageCell.h"
|
|
#import "GroupCreateCell.h"
|
|
#import "TUIKit.h"
|
|
#import "TCUtil.h"
|
|
#import "TCConstants.h"
|
|
#import "GenerateTestUserSig.h"
|
|
#import "TUIChatDataProvider.h"
|
|
#import "TUIMessageDataProvider.h"
|
|
#import "ReactiveObjC/ReactiveObjC.h"
|
|
#import "UIView+TUILayout.h"
|
|
#import "UIView+TUIToast.h"
|
|
#import "TUIGlobalization.h"
|
|
#import <MobileCoreServices/MobileCoreServices.h>
|
|
#import "TUIThemeManager.h"
|
|
#import "TUINaviBarIndicatorView.h"
|
|
|
|
// MLeaksFinder 会对这个类误报,这里需要关闭一下
|
|
@implementation UIImagePickerController (Leak)
|
|
|
|
- (BOOL)willDealloc {
|
|
return NO;
|
|
}
|
|
|
|
@end
|
|
|
|
@interface ChatViewController () <
|
|
TUIChatControllerListener,
|
|
V2TIMConversationListener,
|
|
TUIJoinGroupMessageCellDelegate,
|
|
UIImagePickerControllerDelegate,
|
|
UINavigationControllerDelegate,
|
|
UIDocumentPickerDelegate>
|
|
@property (nonatomic, strong) TUIBaseChatViewController *chat;
|
|
@property (nonatomic, strong) TUINaviBarIndicatorView *titleView;
|
|
@end
|
|
|
|
@implementation ChatViewController
|
|
|
|
#pragma mark - Life Cycle
|
|
- (void)viewDidLoad {
|
|
[super viewDidLoad];
|
|
[[V2TIMManager sharedInstance] addConversationListener:self];
|
|
|
|
if (self.conversationData.groupID.length > 0) {
|
|
_chat = [[TUIGroupChatViewController alloc] init];
|
|
@weakify(self);
|
|
((TUIGroupChatViewController *)_chat).openUserProfileVCBlock = ^(TUIGroupPendencyCell * _Nonnull cell) {
|
|
@strongify(self);
|
|
|
|
TUserProfileController *controller = [[TUserProfileController alloc] init];
|
|
[[V2TIMManager sharedInstance] getUsersInfo:@[cell.pendencyData.fromUser] succ:^(NSArray<V2TIMUserFullInfo *> *profiles) {
|
|
controller.userFullInfo = profiles.firstObject;
|
|
controller.groupPendency = cell.pendencyData;
|
|
controller.actionType = PCA_GROUP_CONFIRM;
|
|
[self.navigationController pushViewController:controller animated:YES];
|
|
} fail:nil];
|
|
|
|
};
|
|
} else if (self.conversationData.userID.length > 0) {
|
|
_chat = [[TUIC2CChatViewController alloc] init];
|
|
}
|
|
[_chat setDelegate:self];
|
|
[_chat setConversationData:self.conversationData];
|
|
[self addChildViewController:_chat];
|
|
[self.view addSubview:_chat.view];
|
|
|
|
_titleView = [[TUINaviBarIndicatorView alloc] init];
|
|
self.navigationItem.titleView = _titleView;
|
|
self.navigationItem.title = @"";
|
|
__weak typeof (self)weakSelf = self;
|
|
[[RACObserve(_conversationData, title) distinctUntilChanged] subscribeNext:^(NSString *title) {
|
|
[weakSelf.titleView setTitle:title];
|
|
}];
|
|
[self checkTitle:NO];
|
|
|
|
// 导航栏
|
|
[self setupNavigator];
|
|
|
|
// 刷新未读数
|
|
[TUIChatDataProvider getTotalUnreadMessageCountWithSuccBlock:^(UInt64 totalCount) {
|
|
[weakSelf onChangeUnReadCount:totalCount];
|
|
} fail:nil];
|
|
|
|
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(onFriendInfoChanged:) name:@"FriendInfoChangedNotification" object:nil];
|
|
}
|
|
|
|
- (void)viewDidAppear:(BOOL)animated
|
|
{
|
|
[super viewDidAppear:animated];
|
|
// 发送第一条消息
|
|
if (self.waitToSendMsg) {
|
|
[self.chat sendMessage:self.waitToSendMsg];
|
|
self.waitToSendMsg = nil;
|
|
}
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
}
|
|
|
|
- (void)setupNavigator
|
|
{
|
|
//left
|
|
_unRead = [[TUIUnReadView alloc] init];
|
|
|
|
// _unRead.backgroundColor = [UIColor colorWithRed:170/255.0 green:188/255.0 blue:209/255.0 alpha:1/1.0]; // 默认使用红色未读视图
|
|
// UIBarButtonItem *urBtn = [[UIBarButtonItem alloc] initWithCustomView:_unRead];
|
|
// self.navigationItem.leftBarButtonItems = @[urBtn];
|
|
// //既显示返回按钮,又显示未读视图
|
|
// self.navigationItem.leftItemsSupplementBackButton = YES;
|
|
|
|
//right,根据当前聊天页类型设置右侧按钮格式
|
|
UIButton *rightButton = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 30, 30)];
|
|
[rightButton addTarget:self action:@selector(rightBarButtonClick) forControlEvents:UIControlEventTouchUpInside];
|
|
UIImage *img = TUIDemoDynamicImage(@"nav_more_menu_img", [UIImage imageNamed:@"nav_more_item"]);
|
|
[rightButton setImage:TUIDemoDynamicImage(@"nav_more_menu_img", [UIImage imageNamed:@"nav_more_item"]) forState:UIControlStateNormal];
|
|
[rightButton setTitleColor:[UIColor colorWithRed:102/255.0 green:102/255.0 blue:102/255.0 alpha:1.0] forState:UIControlStateNormal];
|
|
rightButton.titleLabel.font = [UIFont boldSystemFontOfSize:16.0];
|
|
UIBarButtonItem *rightItem = [[UIBarButtonItem alloc] initWithCustomView:rightButton];
|
|
self.navigationItem.rightBarButtonItems = @[rightItem];
|
|
}
|
|
|
|
- (void)willMoveToParentViewController:(UIViewController *)parent
|
|
{
|
|
if (parent == nil) {
|
|
[_chat saveDraft];
|
|
}
|
|
}
|
|
|
|
#pragma mark - V2TIMConversationListener
|
|
- (void)onConversationChanged:(NSArray<V2TIMConversation*> *) conversationList {
|
|
// 聊天窗口标题由上层维护,需要自行设置标题
|
|
for (V2TIMConversation *conv in conversationList) {
|
|
if ([conv.conversationID isEqualToString:self.conversationData.conversationID]) {
|
|
self.conversationData.title = conv.showName;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)onTotalUnreadMessageCountChanged:(UInt64)totalUnreadCount {
|
|
[self onChangeUnReadCount:totalUnreadCount];
|
|
}
|
|
|
|
#pragma mark - TUIChatControllerListener
|
|
- (void)chatController:(TUIBaseChatViewController *)controller didSendMessage:(V2TIMMessage *)message {
|
|
//write code
|
|
}
|
|
|
|
- (void)chatController:(TUIBaseChatViewController *)chatController onSelectMoreCell:(TUIInputMoreCell *)cell {
|
|
//write code
|
|
}
|
|
|
|
- (TUIMessageCellData *)chatController:(TUIBaseChatViewController *)controller onNewMessage:(V2TIMMessage *)msg
|
|
{
|
|
if (V2TIM_ELEM_TYPE_CUSTOM == msg.elemType) {
|
|
NSDictionary *param = [TCUtil jsonData2Dictionary:msg.customElem.data];
|
|
if (param != nil) {
|
|
NSString *businessID = param[@"businessID"];
|
|
if (![businessID isKindOfClass:[NSString class]]) {
|
|
return nil;
|
|
}
|
|
// 判断是不是群创建自定义消息
|
|
if ([businessID isEqualToString:BussinessID_GroupCreate] || [param.allKeys containsObject:BussinessID_GroupCreate]) {
|
|
GroupCreateCellData *cellData = [[GroupCreateCellData alloc] initWithDirection:msg.isSelf ? MsgDirectionOutgoing : MsgDirectionIncoming];
|
|
cellData.content = [NSString stringWithFormat:@"\"%@\"%@",param[@"opUser"],param[@"content"]];
|
|
return cellData;
|
|
}
|
|
}
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
- (TUIMessageCell *)chatController:(TUIBaseChatViewController *)controller onShowMessageData:(TUIMessageCellData *)cellData
|
|
{
|
|
if ([cellData isKindOfClass:[GroupCreateCellData class]]) {
|
|
GroupCreateCell *groupCell = [[GroupCreateCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"GroupCreateCell"];
|
|
[groupCell fillWithData:(GroupCreateCellData *)cellData];
|
|
return groupCell;
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
- (void)chatController:(TUIBaseChatViewController *)controller willDisplayCell:(TUIMessageCell *)cell withData:(TUIMessageCellData *)cellData {
|
|
//对于入群小灰条,需要进一步设置其委托。
|
|
if([cell isKindOfClass:[TUIJoinGroupMessageCell class]]){
|
|
TUIJoinGroupMessageCell *joinCell = (TUIJoinGroupMessageCell *)cell;
|
|
joinCell.joinGroupDelegate = self;
|
|
}
|
|
}
|
|
|
|
- (NSString *)chatController:(TUIBaseChatViewController *)controller onGetMessageAbstact:(V2TIMMessage *)message
|
|
{
|
|
if (V2TIM_ELEM_TYPE_CUSTOM == message.elemType) {
|
|
NSDictionary *param = [TCUtil jsonData2Dictionary:message.customElem.data];
|
|
if (param != nil) {
|
|
NSString *businessID = param[@"businessID"];
|
|
// 判断是不是群创建自定义消息
|
|
if ([businessID isKindOfClass:NSString.class] && ([businessID isEqualToString:BussinessID_GroupCreate] || [param.allKeys containsObject:BussinessID_GroupCreate])) {
|
|
return [NSString stringWithFormat:@"\"%@\"%@",param[@"opUser"],param[@"content"]];
|
|
}
|
|
}
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
- (void)chatController:(TUIBaseChatViewController *)controller onSelectMessageAvatar:(TUIMessageCell *)cell {
|
|
@weakify(self);
|
|
[ChatViewController getUserOrFriendProfileVCWithUserID:cell.messageData.identifier
|
|
SuccBlock:^(UIViewController * _Nonnull vc) {
|
|
@strongify(self);
|
|
[self.navigationController pushViewController:(UIViewController *)vc animated:YES];
|
|
} failBlock:^(int code, NSString * _Nonnull desc) {
|
|
[TUITool makeToastError:code msg:desc];
|
|
}];
|
|
}
|
|
|
|
#pragma mark - TUIJoinGroupMessageCellDelegate
|
|
- (void)didTapOnRestNameLabel:(TUIJoinGroupMessageCell *)cell withIndex:(NSInteger)index{
|
|
NSString *userId = cell.joinData.userIDList[index];
|
|
|
|
@weakify(self);
|
|
[ChatViewController getUserOrFriendProfileVCWithUserID:userId SuccBlock:^(UIViewController *vc) {
|
|
@strongify(self);
|
|
[self.navigationController pushViewController:vc animated:YES];
|
|
} failBlock:^(int code, NSString *desc) {
|
|
[TUITool makeToastError:code msg:desc];
|
|
}];
|
|
}
|
|
|
|
#pragma mark - Event Response
|
|
|
|
- (void)onChangeUnReadCount:(UInt64)totalCount {
|
|
|
|
// 此处异步的原因:当前聊天页面连续频繁收到消息,可能还没标记已读,此时也会收到未读数变更。理论上此时未读数不会包括当前会话的。
|
|
__weak typeof(self) weakSelf = self;
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[weakSelf.unRead setNum:totalCount];
|
|
});
|
|
}
|
|
|
|
- (void)onFriendInfoChanged:(NSNotification *)notice
|
|
{
|
|
[self checkTitle:YES];
|
|
}
|
|
|
|
- (void)checkTitle:(BOOL)force {
|
|
|
|
if (force || self.conversationData.title.length == 0) {
|
|
if (self.conversationData.userID.length > 0) {
|
|
self.conversationData.title = self.conversationData.userID;
|
|
@weakify(self);
|
|
|
|
[TUIChatDataProvider getFriendInfoWithUserId:self.conversationData.userID
|
|
SuccBlock:^(V2TIMFriendInfoResult * _Nonnull friendInfoResult) {
|
|
@strongify(self);
|
|
if (friendInfoResult.relation & V2TIM_FRIEND_RELATION_TYPE_IN_MY_FRIEND_LIST
|
|
&& friendInfoResult.friendInfo.friendRemark.length > 0) {
|
|
self.conversationData.title = friendInfoResult.friendInfo.friendRemark;
|
|
} else {
|
|
[TUIChatDataProvider getUserInfoWithUserId:self.conversationData.userID
|
|
SuccBlock:^(V2TIMUserFullInfo * _Nonnull userInfo) {
|
|
if (userInfo.nickName.length > 0) {
|
|
self.conversationData.title = userInfo.nickName;
|
|
}
|
|
} failBlock:nil];
|
|
}
|
|
} failBlock:nil];
|
|
}
|
|
else if (self.conversationData.groupID.length > 0) {
|
|
[TUIChatDataProvider getGroupInfoWithGroupID:self.conversationData.groupID
|
|
SuccBlock:^(V2TIMGroupInfoResult * _Nonnull groupResult) {
|
|
if (groupResult.info.groupName.length > 0) {
|
|
self.conversationData.title = groupResult.info.groupName;
|
|
}
|
|
} failBlock:nil];
|
|
}
|
|
}
|
|
}
|
|
|
|
-(void)leftBarButtonClick
|
|
{
|
|
[self.navigationController popViewControllerAnimated:YES];
|
|
}
|
|
|
|
- (void)rightBarButtonClick
|
|
{
|
|
//当前为用户和用户之间通信时,右侧按钮响应为用户信息视图入口
|
|
if (_conversationData.userID.length > 0) {
|
|
|
|
@weakify(self);
|
|
[ChatViewController getUserOrFriendProfileVCWithUserID:self.conversationData.userID
|
|
SuccBlock:^(UIViewController * _Nonnull vc) {
|
|
@strongify(self);
|
|
[self.navigationController pushViewController:(UIViewController *)vc animated:YES];
|
|
} failBlock:^(int code, NSString * _Nonnull desc) {
|
|
[TUITool makeToastError:code msg:desc];
|
|
}];
|
|
|
|
//当前为群组通信时,右侧按钮响应为群组信息入口
|
|
} else {
|
|
GroupInfoController *groupInfo = [[GroupInfoController alloc] init];
|
|
groupInfo.groupId = _conversationData.groupID;
|
|
[self.navigationController pushViewController:groupInfo animated:YES];
|
|
}
|
|
}
|
|
|
|
+ (void)getUserOrFriendProfileVCWithUserID:(NSString *)userID
|
|
SuccBlock:(void(^)(UIViewController *vc))succ
|
|
failBlock:(nullable V2TIMFail)fail
|
|
{
|
|
[TUIChatDataProvider getFriendInfoWithUserId:userID
|
|
SuccBlock:^(V2TIMFriendInfoResult * _Nonnull friendInfoResult) {
|
|
if (friendInfoResult.relation & V2TIM_FRIEND_RELATION_TYPE_IN_MY_FRIEND_LIST) {
|
|
// 如果是好友, 则跳转到好友信息页
|
|
TFriendProfileController *vc = [[TFriendProfileController alloc] init];
|
|
vc.friendProfile = friendInfoResult.friendInfo;
|
|
succ((UIViewController *)vc);
|
|
|
|
} else {
|
|
// 非好友, 则跳转到用户信息页
|
|
[TUIChatDataProvider getUserInfoWithUserId:userID
|
|
SuccBlock:^(V2TIMUserFullInfo * _Nonnull userInfo) {
|
|
TUserProfileController *vc = [[TUserProfileController alloc] init];
|
|
vc.userFullInfo = userInfo;
|
|
if ([userInfo.userID isEqualToString:[[V2TIMManager sharedInstance] getLoginUser]]) {
|
|
vc.actionType = PCA_NONE;
|
|
} else {
|
|
vc.actionType = PCA_ADD_FRIEND;
|
|
}
|
|
succ((UIViewController *)vc);
|
|
|
|
} failBlock:fail];
|
|
}
|
|
|
|
} failBlock:fail];
|
|
}
|
|
@end
|