Files
yinmeng-ios/xplan-ios/Main/Message/View/Session/SessionViewController.m

500 lines
17 KiB
Objective-C

//
// SessionViewController.m
// xplan-ios
//
// Created by zu on 2021/11/28.
//
#import "SessionViewController.h"
#import <Masonry/Masonry.h>
#import <IQKeyboardManager/IQKeyboardManager.h>
#import <TZImagePickerController/TZImagePickerController.h>
#import <MJRefresh/MJRefresh.h>
///Tool
#import "XCCurrentVCStackManager.h"
#import "NIMMessageMaker.h"
#import "XPMacro.h"
#import "UITableView+NIMScrollToBottom.h"
#import "ThemeColor.h"
///Model
#import "RoomInfoModel.h"
#import "UserInfoModel.h"
#import "MessageMenuModel.h"
///View
#import "XPSessionMessageHeadView.h"
#import "XPMineUserInfoViewController.h"
#import "XPRoomViewController.h"
#import "RoomHostDelegate.h"
#import "SessionToolbarView.h"
#import "MessageCell.h"
#import "SessionChatLimitView.h"
#import "XPSendGiftView.h"
#import "SessionNavView.h"
#import "SessionInfoViewController.h"
///P
#import "MessagePresenter.h"
#import "MessageProtocol.h"
@interface SessionViewController ()<MessageProtocol, UITableViewDelegate, UITableViewDataSource, NIMChatManagerDelegate, NIMConversationManagerDelegate, NIMMediaManagerDelegate, XPSessionMessageHeadViewDelegate, MessageCellDelegate, SessionToolbarViewDelegate, TZImagePickerControllerDelegate, SessionNavViewDelegate>
@property (nonatomic, strong) NIMSession * session;
@property (nonatomic, strong) NSMutableArray<NIMMessage *> * messages;
///导航栏
@property (nonatomic,strong) SessionNavView *sessionNavView;
@property (nonatomic, strong) UITableView * sessionTableView;
///跟随进房卡片
@property (nonatomic, strong) XPSessionMessageHeadView *followInRoomView;
@property (nonatomic, strong) UserInfoModel *userInfo;
///输入框
@property (nonatomic,strong) SessionToolbarView *toolbarView;
///最后的一条消息
@property (nonatomic,strong) NIMMessage *lastMessage;
@end
@implementation SessionViewController
- (BOOL)isHiddenNavBar {
return YES;
}
- (void)dealloc {
[[NIMSDK sharedSDK].chatManager removeDelegate:self];
[[NIMSDK sharedSDK].conversationManager removeDelegate:self];
[[NIMSDK sharedSDK].mediaManager removeDelegate:self];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (MessagePresenter *)createPresenter {
return [[MessagePresenter alloc] init];
}
- (instancetype)initWithSession:(NIMSession *)session {
self = [super init];
if (self) {
_session = session;
[self initViews];
[self initLayout];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[IQKeyboardManager sharedManager].enable = NO;
[IQKeyboardManager sharedManager].enableAutoToolbar = NO;
[self initHeaderAndFooterRrfresh];
[[NIMSDK sharedSDK].chatManager addDelegate:self];
[[NIMSDK sharedSDK].conversationManager addDelegate:self];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.presenter getFansLike:self.session.sessionId];
self.sessionNavView.userId = self.session.sessionId;
}
- (void)initHeaderAndFooterRrfresh {
MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(headerRefresh)];
header.stateLabel.font = [UIFont systemFontOfSize:10.0];
header.lastUpdatedTimeLabel.font = [UIFont systemFontOfSize:10.0];
header.stateLabel.textColor = [ThemeColor secondTextColor];
header.lastUpdatedTimeLabel.textColor = [ThemeColor secondTextColor];
self.sessionTableView.mj_header = header;
[self headerRefresh];
[self initData];
}
- (void)headerRefresh {
if (self.messages.count > 0) {
[[[NIMSDK sharedSDK] conversationManager] messagesInSession:self.session message:self.messages.firstObject limit:20 completion:^(NSError * _Nullable error, NSArray<NIMMessage *> * _Nullable messages) {
[self.sessionTableView.mj_header endRefreshing];
if (error == nil && messages.count > 0) {
for (int i = ((int)messages.count -1); i > 0; i--) {
NIMMessage * message = [messages objectAtIndex:i];
[self.messages insertObject:message atIndex:0];
}
}
[self.sessionTableView reloadData];
}];
} else {
[[[NIMSDK sharedSDK] conversationManager] messagesInSession:self.session message:nil limit:20 completion:^(NSError * _Nullable error, NSArray<NIMMessage *> * _Nullable messages) {
[self.sessionTableView.mj_header endRefreshing];
if (error == nil) {
[self.messages addObjectsFromArray:messages];
}
[self.sessionTableView reloadData];
[self.sessionTableView nim_scrollToBottom:NO];
}];
}
}
#pragma mark - Private Method
- (void)initViews {
[self.view addSubview:self.sessionNavView];
[self.view addSubview:self.followInRoomView];
[self.view addSubview:self.sessionTableView];
[self.view addSubview:self.toolbarView];
}
- (void)initLayout {
[self.sessionNavView mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(kNavigationHeight);
make.left.top.right.mas_equalTo(self.view);
}];
[self.followInRoomView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(self.view);
make.top.mas_equalTo(self.sessionNavView.mas_bottom);
make.height.mas_equalTo(80);
}];
[self.sessionTableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(self.view);
make.top.mas_equalTo(self.sessionNavView.mas_bottom);
make.bottom.mas_equalTo(self.toolbarView.mas_top);
}];
[self.toolbarView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(self.view);
make.bottom.mas_equalTo(self.view);
}];
}
- (void)initData {
NIMUser * user = [[NIMSDK sharedSDK].userManager userInfo:self.session.sessionId];
if (user) {
self.sessionNavView.title = user.userInfo.nickName;
} else {
self.sessionNavView.title = @"加载中……";
}
[[NIMSDK sharedSDK].conversationManager markAllMessagesReadInSession:self.session];
[self.presenter getChatLimitReceiverUid:self.session.sessionId];
[self.presenter getUserInfo:self.session.sessionId];
self.sessionNavView.userId = self.session.sessionId;
}
- (BOOL)isExistMessages:(NIMMessage *)message{
BOOL isExist = NO;
NIMMessage * model;
for (NIMMessage *item in self.messages.reverseObjectEnumerator.allObjects) {
if ([item isKindOfClass:[NIMMessage class]] && [item.messageId isEqual:message.messageId]) {
model = item;
isExist = YES;
break;
}
}
if (model) {
model = message;
}
return isExist;
}
#pragma mark - MessageProtocol
- (void)onGetLimitChat:(ChatLimitModel *)chatLimit {
BOOL chatDisabled = !chatLimit.chat && self.messages.count <= 0;
if (chatDisabled) {
SessionChatLimitView *chatLimitView = [[SessionChatLimitView alloc] initWithChatLimit:chatLimit];
self.sessionTableView.tableHeaderView = chatLimitView;
} else {
self.sessionTableView.tableHeaderView = nil;
}
self.toolbarView.sendDisabled = chatDisabled;
}
///获取用户信息成功
- (void)onGetSessionUserInfoSuccess:(UserInfoModel *)userInfo {
_userInfo = userInfo;
if (userInfo.nick.length > 0) {
self.sessionNavView.title = userInfo.nick;
}
if (userInfo.roomUid) {
self.followInRoomView.hidden = NO;
self.followInRoomView.userInfo = userInfo;
[self.sessionTableView mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.sessionNavView.mas_bottom).mas_offset(80);
}];
}
}
- (void)getFansLikeSuccess:(BOOL)isLike {
self.sessionNavView.isLike = isLike;
}
- (void)attentionUserSuccess:(NSString *)uid {
if ([uid isEqualToString:self.session.sessionId]) {
self.sessionNavView.isLike = YES;
}
}
#pragma mark - MessageCellDelegate
- (void)updateMessageSuccess:(NIMMessage *)message {
if ([message.session.sessionId isEqualToString:self.session.sessionId]) {
[self.sessionTableView reloadData];
}
}
- (void)didTapAvatar:(NSString *)uid {
if (uid.length > 0) {
XPMineUserInfoViewController * infoVC = [[XPMineUserInfoViewController alloc] init];
infoVC.uid = uid.integerValue;
[self.navigationController pushViewController:infoVC animated:YES];
}
}
#pragma mark - SessionNavViewDelegate
- (void)sessionNavView:(SessionNavView *)view didClickLike:(UIButton *)sender {
[self.presenter attentionUser:self.session.sessionId];
}
- (void)sessionNavView:(SessionNavView *)view didClickBack:(UIButton *)sender {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)sessionNavView:(SessionNavView *)view didClickReport:(UIButton *)sender {
SessionInfoViewController * reportVC = [[SessionInfoViewController alloc] init];
reportVC.userId = self.session.sessionId;
[self.navigationController pushViewController:reportVC animated:YES];
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.messages.count;
}
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
NIMMessage * message = [self.messages objectAtIndex:indexPath.row];
NSString * identifier = [MessageCell cellContent:message];
///从复用池中获取所需要的cell
MessageCell * cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
///如果没有的话 根据identifier 注册一下 重新获取一下即可
[tableView registerClass:[MessageCell class] forCellReuseIdentifier:identifier];
///如果注册过了 就不需要判断cell是否为空
cell = [tableView dequeueReusableCellWithIdentifier:identifier];
}
cell.delegate = self;
[cell renderWithMessage:[self.messages objectAtIndex:indexPath.row]];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NIMMessage *msg = [self.messages objectAtIndex:indexPath.row];
return [MessageCell measureHeight:msg];
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self.toolbarView foldMenuView];
}
#pragma mark - NIMChatManagerDelegate
- (void)onRecvMessages:(NSArray<NIMMessage *> *)messages {
NIMMessage *message = messages.firstObject;
NIMSession *session = message.session;
if (![session isEqual:self.session] || !messages.count) {
return;
}
for (NIMMessage *message in messages) {
if (message.isDeleted) {
continue;
}
[self.messages addObject:message];
}
[self.sessionTableView reloadData];
[self.sessionTableView nim_scrollToBottom:YES];
[[NIMSDK sharedSDK].conversationManager markAllMessagesReadInSession:self.session];
}
- (void)sendMessage:(NIMMessage *)message didCompleteWithError:(NSError *)error {
if (message.session.sessionType != NIMSessionTypeP2P) {
return;
}
if (![self isExistMessages:message]) {
[self.messages addObject:message];
}
[self.sessionTableView reloadData];
[self.sessionTableView nim_scrollToBottom:YES];
}
- (void)fetchMessageAttachment:(NIMMessage *)message didCompleteWithError:(NSError *)error {
if (![message.session isEqual:self.session]) return;
for (NIMMessage * msg in self.messages) {
if ([msg.messageId isEqualToString:message.messageId]) {
NSInteger index = [self.messages indexOfObject:msg];
[self.messages replaceObjectAtIndex:index withObject:message];
[self.sessionTableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
break;
}
}
}
#pragma mark - NIMConversationManagerDelegate
- (void)messagesDeletedInSession:(NIMSession *)session {
[self.messages removeAllObjects];
[self initData];
}
#pragma mark - XPSessionMessageHeadViewDelegate
- (void)onAvatarClick:(NSInteger)uid {
XPMineUserInfoViewController * infoVC = [[XPMineUserInfoViewController alloc] init];
infoVC.uid = uid;
[self.navigationController pushViewController:infoVC animated:YES];
}
- (void)onFollowInRoom:(NSString *)roomUid {
__block BOOL isSameRoom = NO;
__block RoomInfoModel *roomModel;
[self.navigationController.viewControllers enumerateObjectsUsingBlock:^(__kindof UIViewController * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:[XPRoomViewController class]]) {
XPRoomViewController<RoomHostDelegate> * rooomVC = obj;
[self.navigationController popToRootViewControllerAnimated:NO];
roomModel = rooomVC.getRoomInfo;
if(rooomVC.getRoomInfo.uid == [roomUid integerValue]) {
isSameRoom = YES;
} else {
[rooomVC exitRoom];
}
*stop = YES;
}
}];
if (!isSameRoom) {
if (roomModel.type == RoomType_MiniGame) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[XPRoomViewController openRoom:roomUid fromNick:self.userInfo.nick fromType:UserEnterRoomFromType_Follow_User fromUid:[NSString stringWithFormat:@"%ld", self.userInfo.uid] viewController:[[XCCurrentVCStackManager shareManager] getCurrentVC]];
});
} else {
[XPRoomViewController openRoom:roomUid fromNick:self.userInfo.nick fromType:UserEnterRoomFromType_Follow_User fromUid:[NSString stringWithFormat:@"%ld", self.userInfo.uid] viewController:self];
}
}
}
- (void)didFailRetry:(NIMMessage *)message {
if (message.isReceivedMsg) {
[[NIMSDK sharedSDK].chatManager fetchMessageAttachment:message error:nil];
} else {
[[NIMSDK sharedSDK].chatManager resendMessage:message error:nil];
}
}
#pragma mark - MessageToolbarViewDelegate
- (void)keyboardWillChangeFrame:(CGRect)rect {
CGFloat heightFromBottom = rect.size.height;
heightFromBottom = MAX(0.0, heightFromBottom);
[self.toolbarView mas_updateConstraints:^(MASConstraintMaker *make) {
make.bottom.mas_equalTo(self.view).offset(-heightFromBottom);
}];
[self.sessionTableView nim_scrollToBottom:NO];
}
- (void)sendTextMessage:(NSString *)text {
NIMMessage *message = [NIMMessageMaker msgWithText:text];
[[[NIMSDK sharedSDK] chatManager] sendMessage:message toSession:self.session error:nil];
}
- (void)didSelectMenuItem:(MessageMenuModel *)info {
switch (info.type) {
case MessageMenuType_Photo:
{
TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:1 delegate:self];
imagePickerVc.modalPresentationStyle = UIModalPresentationOverFullScreen;
imagePickerVc.allowPickingVideo = NO;
imagePickerVc.allowTakeVideo = NO;
imagePickerVc.naviBgColor = [ThemeColor appCellBackgroundColor];
imagePickerVc.naviTitleColor = [ThemeColor mainTextColor];
imagePickerVc.barItemTextColor = [ThemeColor mainTextColor];
[self presentViewController:imagePickerVc animated:YES completion:nil];
}
break;
case MessageMenuType_Gift:
{
XPSendGiftView * giftView = [[XPSendGiftView alloc] initWithType:SendGiftType_User uid:nil];
XPGiftUserInfoModel * userModel = [[XPGiftUserInfoModel alloc] init];
userModel.avatar = self.userInfo.avatar;
userModel.nick = self.userInfo.nick;
userModel.uid = self.session.sessionId.integerValue;
userModel.isSelect = YES;
[giftView configGiftUsers:@[userModel]];
[self presentViewController:giftView animated:YES completion:nil];
}
break;
default:
break;
}
}
- (void)audioRecordCompletion:(NSString *)recordPath {
NIMMessage *message = [NIMMessageMaker msgWithAudio:recordPath];
[[[NIMSDK sharedSDK] chatManager] sendMessage:message toSession:self.session error:nil];
}
#pragma mark - TZImagePickerControllerDelegate
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray<UIImage *> *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto infos:(NSArray<NSDictionary *> *)infos {
[photos enumerateObjectsUsingBlock:^(UIImage * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (obj) {
// 构造出具体会话
NIMMessage * message = [NIMMessageMaker msgWithImage:obj];
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:self.session error:nil];
}
}];
}
#pragma mark - Getters And Setters
- (NSArray<NIMMessage *> *)messages {
if (!_messages) {
_messages = [[NSMutableArray alloc] init];
}
return _messages;
}
#pragma mark - Event Response
- (void)closeKeyBoard {
[self.view endEditing:YES];
[self.toolbarView foldMenuView];
}
- (UITableView *)sessionTableView {
if (!_sessionTableView) {
_sessionTableView = [[UITableView alloc] init];
_sessionTableView.delegate = self;
_sessionTableView.dataSource = self;
_sessionTableView.backgroundColor = UIColor.clearColor;
_sessionTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_sessionTableView.showsVerticalScrollIndicator = NO;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyBoard)];
[_sessionTableView addGestureRecognizer:tap];
}
return _sessionTableView;
}
- (XPSessionMessageHeadView *)followInRoomView {
if (!_followInRoomView) {
_followInRoomView = [[XPSessionMessageHeadView alloc] init];
_followInRoomView.delegate = self;
_followInRoomView.hidden = YES;
}
return _followInRoomView;
}
- (SessionToolbarView *)toolbarView {
if (!_toolbarView) {
_toolbarView = [[SessionToolbarView alloc] init];
_toolbarView.delegate = self;
}
return _toolbarView;
}
- (SessionNavView *)sessionNavView {
if (!_sessionNavView) {
_sessionNavView = [[SessionNavView alloc] init];
_sessionNavView.delegate = self;
}
return _sessionNavView;
}
@end