// // SessionViewController.m // YUMI // // Created by zu on 2021/11/28. // #import "SessionViewController.h" #import #import #import #import #import ///Tool #import "XCCurrentVCStackManager.h" #import "NIMMessageMaker.h" #import "YUMIMacroUitls.h" #import "UITableView+NIMScrollToBottom.h" #import "DJDKMIMOMColor.h" #import "NSArray+Safe.h" #import "QEmotionHelper.h" #import "QKeyboardManager.h" #import "YYUtility.h" #import "TTPopup.h" #import "AccountInfoStorage.h" #import "NSDate+DateUtils.h" #import "PLTimeUtil.h" #import "NIMMessageUtils.h" #import "ClientConfig.h" ///Model #import "RoomInfoModel.h" #import "UserInfoModel.h" #import "MessageMenuModel.h" #import "SessionRiskCache.h" #import "QPhotoImageModel.h" #import "AttachmentModel.h" #import "MessageBaseModel.h" #import "MessageTextModel.h" #import "MessageAudioModel.h" #import "MessageTimeModel.h" #import "MessageImageModel.h" #import "MessageUnSupportModel.h" #import "MessageGiftModel.h" #import "PIMessageContentServiceReplyModel.h" #import "MessageTextClickModel.h" #import "MessageGuildModel.h" #import "MessageOpenLiveModel.h" #import "MessageRedPacketModel.h" #import "MessageMonentsAutoModel.h" #import "MessageMonentsModel.h" #import "MessageRiskAlertModel.h" #import "MessageFindNewGreetModel.h" #import "MessageSkillCardModel.h" #import "MessageTweetModel.h" #import "MessageLevelUpgradeModel.h" #import "MessageRevokeModel.h" #import "MessageTipsModel.h" #import "MessageTreasureFairyModel.h" #import "MessageCPNotifyModel.h" #import "MessagePublicEventModel.h" ///View #import "XPMineUserInfoViewController.h" #import "XPWebViewController.h" #import "XPRoomViewController.h" #import "RoomHostDelegate.h" #import "MessageCell.h" #import "SessionChatLimitView.h" #import "XPSendGiftView.h" #import "SessionNavView.h" #import "SessionInfoViewController.h" #import "SessionRiskView.h" #import "QInputBarView.h" #import "QKeyboardManager.h" #import "QEmotionBoardView.h" #import "QinputPhotoView.h" #import "SessionUserInfoTableViewCell.h" ///P #import "MessagePresenter.h" #import "MessageProtocol.h" #import "Api+Message.h" #import "MessageGameOrderModel.h" #import "VIPCenterViewController.h" #import "XPSkillCardPlayerManager.h" #import "AgentMessageModel.h" #import "XPMineUserInfoPresenter.h" @interface CheckLimitModel :PIBaseModel @property (nonatomic, assign) BOOL chat; @property (nonatomic, copy) NSString *message; @property (nonatomic, assign) NSInteger wealthLevel; @property (nonatomic, assign) NSInteger charmLevel; @property (nonatomic, strong) NSNumber *nextVipLevel; @property (nonatomic, strong) NSNumber *nextUserCountLimit; @end @implementation CheckLimitModel @end @interface SessionViewController () @property (nonatomic, strong) NIMSession * session; @property (nonatomic, strong) NSMutableArray * messages; ///导航栏 @property (nonatomic,strong) SessionNavView *sessionNavView; @property (nonatomic, strong) UITableView * sessionTableView; @property (nonatomic, strong) UserInfoModel *detailUserInfo; ///最后的一条消息 @property (nonatomic,strong) NIMMessage *lastMessage; ///私聊风险提示 @property (nonatomic,strong) SessionRiskView *riskAlertView; @property(nonatomic,strong)QInputBarView *inputBarView; @property(nonatomic,strong)QKeyboardManager *keyboardManager; ///相册 @property (nonatomic,strong) QinputPhotoView *photoView; /// @property (nonatomic,strong) NSArray *phototArray; @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; } return self; } - (void)viewDidLoad { [super viewDidLoad]; [self initViews]; [self initLayout]; [IQKeyboardManager sharedManager].enable = NO; [IQKeyboardManager sharedManager].enableAutoToolbar = NO; [self initHeaderAndFooterRrfresh]; [[NIMSDK sharedSDK].chatManager addDelegate:self]; [[NIMSDK sharedSDK].conversationManager addDelegate:self]; [self.presenter getUserInfoWithUid:[AccountInfoStorage instance].getUid]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (![NIMMessageUtils isOfficalAccount:self.session.sessionId]) { [self.presenter getFansLike:self.session.sessionId]; if (!self.userInfo) { [self.presenter getUserInfoWithUid: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 = [DJDKMIMOMColor secondTextColor]; header.lastUpdatedTimeLabel.textColor = [DJDKMIMOMColor secondTextColor]; self.sessionTableView.mj_header = header; [self headerRefresh]; [self initData]; } - (void)headerRefresh { @kWeakify(self); if (self.messages.count > 0) { MessageBaseModel * model = self.messages.firstObject; [[[NIMSDK sharedSDK] conversationManager] messagesInSession:self.session message:model.message limit:20 completion:^(NSError * _Nullable error, NSArray * _Nullable messages) { @kStrongify(self); [self.sessionTableView.mj_header endRefreshing]; if (error == nil && messages.count > 0) { for (int i = ((int)messages.count -1); i >= 0; i--) { NIMMessage * message = [messages xpSafeObjectAtIndex:i]; MessageBaseModel * model = [self modeTransformMessage:message]; [self.messages insertObject:model atIndex:0]; if ((i -1) > 0) { NIMMessage * message1 = [messages xpSafeObjectAtIndex:i -1]; CGFloat dur = message.timestamp - message1.timestamp; if (dur / 60 > 5) { MessageBaseModel * timeModel = [self createTimeMessage:message]; [self.messages insertObject:timeModel atIndex:0]; } } } } [self.sessionTableView reloadData]; }]; } else { [[[NIMSDK sharedSDK] conversationManager] messagesInSession:self.session message:nil limit:20 completion:^(NSError * _Nullable error, NSArray * _Nullable messages) { @kStrongify(self); NIMMessage * firstmessage = nil; [self.sessionTableView.mj_header endRefreshing]; if (error == nil) { for (int i = 0; i < messages.count; i++) { NIMMessage * message = [messages xpSafeObjectAtIndex:i]; if (!firstmessage) { firstmessage = message; } MessageBaseModel * model = [self modeTransformMessage:message]; if ((i + 1) < messages.count) { NIMMessage * message1 = [messages xpSafeObjectAtIndex:i + 1]; CGFloat dur = message1.timestamp - message.timestamp; if (dur / 60 > 5) { MessageBaseModel * timeModel = [self createTimeMessage:message]; [self.messages addObject:timeModel]; } } [self.messages addObject:model]; } } [self.sessionTableView reloadData]; [self.sessionTableView nim_scrollToBottom:YES]; }]; } } #pragma mark - 提前加载相册中的图片 - (void)loadAlbumPhotos { [YYUtility checkAssetsLibrayAvailable:^{ } denied:^{ } restriction:^{ }]; } #pragma mark - cell的样式 - (MessageBaseModel *)modeTransformMessage:(NIMMessage *)message { MessageBaseModel * model; //#if DEBUG // model = [[MessagePublicEventModel alloc] initWithMessage:message]; // return model; //#endif switch (message.messageType) { case NIMMessageTypeText: model = [[MessageTextModel alloc] initWithMessage:message]; break; case NIMMessageTypeAudio: model = [[MessageAudioModel alloc] initWithMessage:message]; break; case NIMMessageTypeImage: model = [[MessageImageModel alloc] initWithMessage:message]; break; case NIMMessageTypeTip: model = [[MessageTipsModel alloc] initWithMessage:message]; break; case NIMMessageTypeCustom: model = [self modelTransformCustomMessage:message]; break; default: model = [[MessageUnSupportModel alloc] initWithMessage:message]; break; } return model; } - (MessageBaseModel *)modelTransformCustomMessage:(NIMMessage *)message { MessageBaseModel * model; NIMCustomObject *obj = (NIMCustomObject *)message.messageObject; AttachmentModel *attachment = (AttachmentModel *)obj.attachment; NSInteger first = attachment.first; NSInteger second = attachment.second; switch (first) { case CustomMessageType_Public_Event: if (second == Custom_Message_Sub_Public_Event_message) { model = [[MessagePublicEventModel alloc] initWithMessage:message]; } break; case CustomMessageType_CP_message: if (second == Custom_Message_Sub_CP_message_request || second == Custom_Message_Sub_CP_message_result) { model = [[MessageCPNotifyModel alloc] initWithMessage:message]; } break; case CustomMessageType_Gift: if (second == Custom_Message_Sub_Gift_Send) { model = [[MessageGiftModel alloc] initWithMessage:message]; } break; case CustomMessageType_Secretary: model = [[MessageTextClickModel alloc] initWithMessage:message]; break; case CustomMessageType_Hall: case CustomMessageType_New_Hall: model = [[MessageGuildModel alloc] initWithMessage:message]; break; case CustomMessageType_Member_Online: if (second == Custom_Message_Type_Attention_Member_Online) { model = [[MessageOpenLiveModel alloc] initWithMessage:message]; } break; case CustomMessageType_Application_Share: if (second == Custom_Message_Sub_Application_Share_Room) { model = [[MessageOpenLiveModel alloc] initWithMessage:message]; } break; case CustomMessageType_User_UpGrade: if (second == Custom_Message_Sub_User_UpGrade_Charm || second == Custom_Message_Sub_User_UpGrade_Exper) { model = [[MessageLevelUpgradeModel alloc] initWithMessage:message]; } break; case CustomMessageType_Tweet: if (second == Custom_Message_Sub_Tweet_News) { model = [[MessageTweetModel alloc] initWithMessage:message]; } break; case CustomMessageType_Skill_Card: model = [[MessageSkillCardModel alloc] initWithMessage:message]; break; case CustomMessageType_FindNew: model = [[MessageFindNewGreetModel alloc] initWithMessage:message]; break; case CustomMessageType_Chat_Risk_Alert: model = [[MessageRiskAlertModel alloc] initWithMessage:message]; break; case CustomMessageType_Monents: if (second == Custom_Message_Sub_Monents_Share) { model = [[MessageMonentsModel alloc] initWithMessage:message]; } else if (second == Custom_Message_Sub_Monents_Approved || second == Custom_Message_Sub_Monents_Ban_Delete) { model = [[MessageMonentsAutoModel alloc] initWithMessage:message]; } break; case CustomMessageType_Message_Handle: if (second == Custom_Message_Sub_Message_Handle_Content) { model = [[MessageMonentsAutoModel alloc] initWithMessage:message]; } break; case CustomMessageType_RedPacket: if (second == Custom_Message_Sub_AllDiamandRedPacket) { model = [[MessageRedPacketModel alloc] initWithMessage:message]; } break; case CustomMessageType_Treasure_Fairy: if (second == Custom_Message_Sub_Treasure_Fairy_Ask_Fairy || second == Custom_Message_Sub_Treasure_Fairy_Send_Fairy) { model = [[MessageTreasureFairyModel alloc] initWithMessage:message]; } break; case CustomMessageType_Service_Reply: model = [[PIMessageContentServiceReplyModel alloc] initWithMessage:message]; break; case CustomMessageType_Game_Order: if (second == Custom_Message_Sub_Game_order) { model = [[MessageGameOrderModel alloc] initWithMessage:message]; } break; case CustomMessageType_Car_Notify: if (second == Custom_Message_Sub_Car_OutDate) { model = [[MessageTextClickModel alloc] initWithMessage:message]; } break; default: model = [[MessageUnSupportModel alloc] initWithMessage:message]; break; } if (model == nil) { model = [[MessageUnSupportModel alloc] initWithMessage:message]; } return model; } - (UINavigationController *)getKeyWindowNav { if ([XCCurrentVCStackManager shareManager].getCurrentVC) { return [XCCurrentVCStackManager shareManager].getCurrentVC.navigationController; } return self.navigationController; } - (MessageBaseModel *)createTimeMessage:(NIMMessage *)message { MessageTimeModel * timeModel = [[MessageTimeModel alloc] initWithMessage:message]; timeModel.time = [self timestrToTimeSecond:[NSString stringWithFormat:@"%f", message.timestamp]]; return timeModel; } - (NSString *)timestrToTimeSecond:(NSString *)timeStr {//timestr 豪秒 NSTimeInterval interval = [timeStr doubleValue]; NSDate *date = [NSDate dateWithTimeIntervalSince1970:interval]; return [NSDate stringFromDate:date]; } - (void)addTimeMessage:(NIMMessage *)message { if (self.messages.count > 0) { NIMMessage * lastMessage = self.messages.lastObject.message; CGFloat dur = message.timestamp - lastMessage.timestamp; if (dur / 60 > 5) { NIMMessage * newMessage = [[NIMMessage alloc] init]; newMessage.timestamp = message.timestamp; [newMessage setValue:self.session forKey:@"session"]; MessageBaseModel * timeModel = [self createTimeMessage:newMessage]; [self.messages addObject:timeModel]; } } } - (void)addRevokeMessage:(NIMMessage *)message title:(NSString *)title { NIMMessage * revokeMessage = [[NIMMessage alloc] init]; [revokeMessage setValue:self.session forKey:@"session"]; [revokeMessage setValue:@(NIMMessageTypeTip) forKey:@"messageType"]; revokeMessage.timestamp = [PLTimeUtil getNowTimeTimestampMillisecond].longLongValue; revokeMessage.text = title; [[NIMSDK sharedSDK].conversationManager saveMessage:revokeMessage forSession:self.session completion:nil]; } #pragma mark - Private Method - (void)initInputView { // 初始化输入工具条,frame可以先这样临时设置,下面的addBottomInputBarView方法会重置输入条frame // 如果你想要自定义输入条View,请参考TextFieldViewController代码 QInputBarViewConfiguration *inputBarViewConfiguration = [QInputBarViewConfiguration defaultInputBarViewConfiguration]; inputBarViewConfiguration.voiceButtonHidden = NO;//隐藏语音按钮 inputBarViewConfiguration.extendButtonHidden = YES;//隐藏拓展按钮 inputBarViewConfiguration.toolHidden = NO; inputBarViewConfiguration.giftButtonHidden = NO; inputBarViewConfiguration.cameraButtonHidden = NO; inputBarViewConfiguration.photoButtonHidden = NO; _inputBarView = [[QInputBarView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,inputBarViewConfiguration.inputViewHeight)]; [_inputBarView setupWithConfiguration:inputBarViewConfiguration]; _inputBarView.delegate = self; //keyboard管理类,用来管理键盘,各大面板的切换 _keyboardManager = [[QKeyboardManager alloc] initWithViewController:self]; _keyboardManager.dataSource = self; //因为addBottomInputBarView方法会立刻触发delegate,所以这里需要先设置delegate _keyboardManager.delegate = self; [_keyboardManager addBottomInputBarView:_inputBarView belowViewController:NO]; //把输入框(如果有的话)绑定给管理类 [_keyboardManager bindTextView:_inputBarView.inputTextView]; } - (void)initViews { self.sessionNavView.isInRoom = self.openType == SessionListOpenTypeRoom; [self.view addSubview:self.sessionNavView]; [self.view addSubview:self.sessionTableView]; [self initInputView]; } - (void)initLayout { [self.sessionNavView mas_makeConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(self.openType == SessionListOpenTypeRoom ? 44 : kNavigationHeight); make.leading.top.trailing.mas_equalTo(self.view); }]; } - (void)viewDidLayoutSubviews{ if (self.openType == SessionListOpenTypeRoom) { self.view.frame = CGRectMake(0, 0, KScreenWidth, kHalfScreenHeight); } } - (void)initData { NIMUser * user = [[NIMSDK sharedSDK].userManager userInfo:self.session.sessionId]; if (user) { self.sessionNavView.title = user.userInfo.nickName; } else { self.sessionNavView.title = YMLocalizedString(@"XNDJTDDLoadingTool0"); } [[NIMSDK sharedSDK].conversationManager markAllMessagesReadInSession:self.session]; [self.presenter getChatLimitReceiverUid:self.session.sessionId]; if (![[[ClientConfig shareConfig].configInfo officialAccountUids] containsObject:user.userId]) { [self.presenter getUserInfo: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 isEqualToString:message.messageId]) { model = item; isExist = YES; break; } } if (model) { model = message; } return isExist; } - (BOOL)showChatRiskView:(UserInfoModel *)userInfo { if (userInfo.banAccount) { return YES; } NSString * cacheUid = [[SessionRiskCache shareCache] getCloseChatRiskAlert:self.session.sessionId]; if (cacheUid && [cacheUid isEqualToString:self.session.sessionId]) { return NO; } if ([[NIMSDK sharedSDK].userManager isMyFriend:self.session.sessionId]) { return NO; } return YES; } #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.inputBarView.userInteractionEnabled = !chatDisabled; if (chatDisabled) { self.inputBarView.inputTextView.placeholder = YMLocalizedString(@"SessionViewController1"); } else { self.inputBarView.inputTextView.placeholder = YMLocalizedString(@"SessionViewController2"); } } ///获取用户信息成功 - (void)onGetSessionUserInfoSuccess:(UserInfoModel *)userInfo { // _userInfo = userInfo; self.sessionNavView.userInfo = userInfo; if (userInfo.roomUid && self.openType == SessionListOpenTypeDefault) { if ([self showChatRiskView:userInfo]) { self.riskAlertView.warning = userInfo.banAccount ? YMLocalizedString(@"SessionViewController17") : YMLocalizedString(@"SessionViewController18"); if (!self.riskAlertView.superview) { [self.view addSubview:self.riskAlertView]; [self.riskAlertView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.view); make.top.mas_equalTo(self.sessionNavView.mas_bottom); make.height.mas_equalTo(30); }]; } [self.sessionTableView mas_updateConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.sessionNavView.mas_bottom).mas_offset(30); }]; } else { [self.sessionTableView mas_updateConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.sessionNavView.mas_bottom).mas_offset(0); }]; } } else { if ([self showChatRiskView:userInfo]) { self.riskAlertView.warning = userInfo.banAccount ? YMLocalizedString(@"SessionViewController17") : YMLocalizedString(@"SessionViewController18"); if (!self.riskAlertView.superview) { [self.view addSubview:self.riskAlertView]; [self.riskAlertView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.view); make.top.mas_equalTo(self.sessionNavView.mas_bottom); make.height.mas_equalTo(30); }]; } [self.sessionTableView mas_updateConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.sessionNavView.mas_bottom).mas_offset(30); }]; } else { [self.sessionTableView mas_updateConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.sessionNavView.mas_bottom).mas_offset(0); }]; } } } - (void)getFansLikeSuccess:(BOOL)isLike { self.sessionNavView.isLike = isLike; if(self.isAttention == YES && isLike == NO){ [self startAttention]; } } - (void)attentionUserSuccess:(NSString *)uid { if ([uid isEqualToString:self.session.sessionId]) { [self showSuccessToast:YMLocalizedString(@"SessionViewController7")]; self.sessionNavView.isLike = YES; } } - (void)onGetUserInfoSuccess:(UserInfoModel *)userInfo { if (userInfo.uid == [AccountInfoStorage instance].getUid.integerValue) { [XPSkillCardPlayerManager shareInstance].userInfoModel = userInfo; } else { self.userInfo = userInfo; } [self.sessionTableView reloadData]; } #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 && ![NIMMessageUtils isOfficalAccount:uid]) { XPMineUserInfoViewController * infoVC = [[XPMineUserInfoViewController alloc] init]; infoVC.uid = uid.integerValue; [[self getKeyWindowNav] pushViewController:infoVC animated:YES]; } } - (void)deleteMessageSuccess:(NIMMessage *)message { MessageBaseModel * revokeMessage; for (int i = 0; i < self.messages.count; i++) { MessageBaseModel * message1 = [self.messages xpSafeObjectAtIndex:i]; if ([message.messageId isEqualToString: message1.message.messageId]) { revokeMessage = message1; break; } } if (revokeMessage) { [self.messages removeObject:revokeMessage]; [self.sessionTableView reloadData]; } } - (void)revokeMessageSuccess:(NIMMessage *)message { MessageBaseModel * revokeMessage; for (int i = 0; i < self.messages.count; i++) { MessageBaseModel * message1 = [self.messages xpSafeObjectAtIndex:i]; if ([message.messageId isEqualToString:message1.message.messageId]) { revokeMessage = message1; break; } } if (revokeMessage) { [self.messages removeObject:revokeMessage]; // 插入一条撤回消息 [self addRevokeMessage:message title:YMLocalizedString(@"SessionViewController8")]; } } -(void)startAttention{ [self.presenter attentionUser:self.session.sessionId]; } // - (void)didTapAccept:(NIMMessage *)message { XPMineUserInfoPresenter *presenter = [[XPMineUserInfoPresenter alloc] init]; MessageCPNotifyModel *model = [[MessageCPNotifyModel alloc] initWithMessage:message]; @kWeakify(self); [presenter updateRelationship:model.recordId status:1 success:^{ @kStrongify(self); [self updateCPMessageAccept:message]; } failure:^(NSError * _Nonnull error) { }]; } - (void)didTapReject:(NIMMessage *)message { XPMineUserInfoPresenter *presenter = [[XPMineUserInfoPresenter alloc] init]; MessageCPNotifyModel *model = [[MessageCPNotifyModel alloc] initWithMessage:message]; @kWeakify(self); [presenter updateRelationship:model.recordId status:2 success:^{ @kStrongify(self); [self updateCPMessageReject:message]; } failure:^(NSError * _Nonnull error) { }]; } - (void)updateCPMessageAccept:(NIMMessage *)message { NIMCustomObject *obj = (NIMCustomObject *)message.messageObject; AttachmentModel *attach = (AttachmentModel *)obj.attachment; NSMutableDictionary * dic = [attach.data mutableCopy]; [dic setObject:@(1) forKey:@"user_action"]; [dic setObject:@(1) forKey:@"status"]; attach.data = dic.copy; obj.attachment = attach; message.messageObject = obj; MessageCPNotifyModel *model = [[MessageCPNotifyModel alloc] initWithMessage:message]; @kWeakify(self); [[[NIMSDK sharedSDK] conversationManager] updateMessage:message forSession:self.session completion:^(NSError * _Nullable error) { @kStrongify(self); [self.messages enumerateObjectsUsingBlock:^(MessageBaseModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (obj.message.messageId == message.messageId) { [self.messages replaceObjectAtIndex:idx withObject:model]; [self.sessionTableView reloadData]; *stop = YES; } }]; }]; } - (void)updateCPMessageReject:(NIMMessage *)message { NIMCustomObject *obj = (NIMCustomObject *)message.messageObject; AttachmentModel *attach = (AttachmentModel *)obj.attachment; NSMutableDictionary * dic = [attach.data mutableCopy]; [dic setObject:@(2) forKey:@"user_action"]; [dic setObject:@(2) forKey:@"status"]; attach.data = dic.copy; obj.attachment = attach; message.messageObject = obj; MessageCPNotifyModel *model = [[MessageCPNotifyModel alloc] initWithMessage:message]; @kWeakify(self); [[[NIMSDK sharedSDK] conversationManager] updateMessage:message forSession:self.session completion:^(NSError * _Nullable error) { @kStrongify(self); [self.messages enumerateObjectsUsingBlock:^(MessageBaseModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (obj.message.messageId == message.messageId) { [self.messages replaceObjectAtIndex:idx withObject:model]; [self.sessionTableView reloadData]; *stop = YES; } }]; }]; } #pragma mark - SessionNavViewDelegate - (void)sessionNavView:(SessionNavView *)view didClickLike:(UIButton *)sender { [self.presenter attentionUser:self.session.sessionId]; } - (void)sessionNavView:(SessionNavView *)view didClickBack:(UIButton *)sender { if (self.openType == SessionListOpenTypeRoom) { CATransition *transition = [CATransition animation]; transition.duration = 0.3f; transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; transition.type = kCATransitionPush; transition.subtype = kCATransitionFromLeft; [self.view.superview.layer addAnimation:transition forKey:nil]; [self willMoveToParentViewController:nil]; //1 [self.view removeFromSuperview]; //2 [self removeFromParentViewController]; //3 return; } [self.navigationController popViewControllerAnimated:YES]; } - (void)sessionNavView:(SessionNavView *)view didClickReport:(UIButton *)sender { SessionInfoViewController * reportVC = [[SessionInfoViewController alloc] init]; reportVC.session = self.session; reportVC.stickTopMessages = self.stickTopMessages; reportVC.userInfo = self.userInfo; [self.getKeyWindowNav pushViewController:reportVC animated:YES]; } - (void)sessionNavView:(SessionNavView *)view didRoomLive:(NSString *)roomUid { if (self.openType == SessionListOpenTypeDefault) { __block BOOL isSameRoom = NO; __block RoomInfoModel *roomModel; [self.getKeyWindowNav.viewControllers enumerateObjectsUsingBlock:^(__kindof UIViewController * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if ([obj isKindOfClass:[XPRoomViewController class]]) { XPRoomViewController * rooomVC = obj; [[self getKeyWindowNav] 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]; } } } } #pragma mark - UITableViewDataSource - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 2; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section == 0) { if ([NIMMessageUtils isOfficalAccount:self.session.sessionId]) { return 0; } return self.userInfo ? 1 : 0; } else { return self.messages.count; } } - (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath { if (indexPath.section == 0) { SessionUserInfoTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([SessionUserInfoTableViewCell class])]; if (cell == nil) { ///如果没有的话 根据identifier 注册一下 重新获取一下即可 [tableView registerClass:[SessionUserInfoTableViewCell class] forCellReuseIdentifier:NSStringFromClass([SessionUserInfoTableViewCell class])]; cell = [[SessionUserInfoTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NSStringFromClass([SessionUserInfoTableViewCell class])]; } cell.userInfo = self.userInfo; cell.delegate = self; return cell; } else { MessageBaseModel * message = [self.messages xpSafeObjectAtIndex:indexPath.row]; NSString * identifier = [message 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:message]; return cell; } } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 0) { return 100;//self.userInfo.privatePhoto.count > 0 ? 182 : 100; } MessageBaseModel *msg = [self.messages xpSafeObjectAtIndex:indexPath.row]; return msg.height; } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { [self.keyboardManager hideAllBoardView]; } #pragma mark - NIMChatManagerDelegate - (void)onRecvMessages:(NSArray *)messages { if(!messages.count){ return; } NIMMessage *message = messages.firstObject; NIMSession *session = message.session; if (![session isEqual:self.session] ) { return; } // 不处理点击拒绝的显示 // NIMCustomObject *obj = (NIMCustomObject *)message.messageObject; // AttachmentModel *attachment = (AttachmentModel *)obj.attachment; // if (attachment.second == Custom_Message_Sub_CP_message_result) { // NSDictionary *data = attachment.data; // NSNumber *status = [data objectForKey:@"status"]; // if (status && status.integerValue == 2) { // [[NIMSDK sharedSDK].conversationManager deleteMessage:message]; // return; // } // } for (NIMMessage *message in messages) { [self addTimeMessage:message]; if (message.isDeleted) { continue; } MessageBaseModel * model = [self modeTransformMessage:message]; [self.messages addObject:model]; } [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; } [self addTimeMessage:message]; if (![self isExistMessages:message]) { MessageBaseModel * model = [self modeTransformMessage:message]; [self.messages addObject:model]; } // if (message.yidunAntiSpamRes) { // NSDictionary * spamRes = message.yidunAntiSpamRes.toJSONObject; // NSDictionary * spamResExt = ((NSString *)spamRes[@"ext"]).toJSONObject; // if ([spamResExt[@"antispam"][@"suggestion"] intValue] == 2) { // NSDictionary * dic = @{@"suggestion": @"2"}; // message.localExt = dic; // [[NIMSDK sharedSDK].conversationManager updateMessage:message forSession:self.session completion:nil]; // } // } if (message.yidunAntiSpamRes) { NSDictionary * spamRes = message.yidunAntiSpamRes.toJSONObject; id spamResExt = ((NSString *)spamRes[@"ext"]).toJSONObject; NSDictionary *antispamDic = nil; if ([spamResExt isKindOfClass:[NSArray class]]) { antispamDic = [spamResExt xpSafeObjectAtIndex:0]; } else if ([spamResExt isKindOfClass:[NSDictionary class]]) { antispamDic = spamResExt[@"antispam"]; } NSDictionary *realAntiDic = nil; if ([[antispamDic allKeys] containsObject:@"antispam"]) { realAntiDic = antispamDic[@"antispam"];; } else { realAntiDic = antispamDic; } if (realAntiDic) { NSInteger suggestion = [realAntiDic[@"suggestion"] integerValue]; if (suggestion == 2) { NSDictionary * dic = @{@"suggestion": @"2"}; message.localExt = dic; [[NIMSDK sharedSDK].conversationManager updateMessage:message forSession:self.session completion:nil]; [self showErrorToast:YMLocalizedString(@"XPRoomViewController10")]; } } } [self.sessionTableView reloadData]; [self.sessionTableView nim_scrollToBottom:YES]; } /** * 收到消息被撤回的通知 * * @param notification 被撤回的消息信息 * @discusssion 云信在收到消息撤回后,会先从本地数据库中找到对应消息并进行删除,之后通知上层消息已删除 */ - (void)onRecvRevokeMessageNotification:(NIMRevokeMessageNotification *)notification { MessageBaseModel * revokeMessage; for (int i = 0; i < self.messages.count; i++) { MessageBaseModel * message1 = [self.messages xpSafeObjectAtIndex:i]; if ([notification.message.messageId isEqualToString:message1.message.messageId]) { revokeMessage = message1; break; } } if (revokeMessage) { [self.messages removeObject:revokeMessage]; [self.sessionTableView reloadData]; } } - (void)displayLimitMessage:(CheckLimitModel *)model { TTAlertConfig * config = [[TTAlertConfig alloc] init]; config.title = YMLocalizedString(@"1.0.18_26"); BOOL confirmToBuyVIP = NO; if (!model.nextVipLevel && !model.nextUserCountLimit) { // 提示达到聊天上限 config.message = YMLocalizedString(@"1.0.18_29"); } else if (model.nextVipLevel && !model.nextUserCountLimit) { // 提示未达到对应 VIP,去买 VIP confirmToBuyVIP = YES; config.message = [NSString stringWithFormat:YMLocalizedString(@"1.0.18_27"), model.nextVipLevel]; config.confirmButtonConfig.title = [NSString stringWithFormat:YMLocalizedString(@"1.0.18_30"), model.nextVipLevel]; } else { //提示未达到对应 VIP,去买 VIP, 可以每天聊多少个 confirmToBuyVIP = YES; config.message = [NSString stringWithFormat:YMLocalizedString(@"1.0.18_28"), model.nextVipLevel, model.nextUserCountLimit]; config.confirmButtonConfig.title = [NSString stringWithFormat:YMLocalizedString(@"1.0.18_30"), model.nextVipLevel]; } [TTPopup alertWithConfig:config confirmHandler:^{ if (confirmToBuyVIP) { // VIPCenterViewController *nobleCenter = [[VIPCenterViewController alloc] initWithRoomUid:-1]; // [nobleCenter jumpToTargetVIP:model.nextVipLevel.integerValue]; // [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:nobleCenter animated:YES]; XPWebViewController * webVC =[[XPWebViewController alloc] initWithRoomUID:nil]; webVC.url = URLWithType(kVIP); [self.navigationController pushViewController:webVC animated:YES]; } } cancelHandler:^{ }]; } #pragma mark - NIMConversationManagerDelegate - (void)messagesDeletedInSession:(NIMSession *)session { [self.messages removeAllObjects]; [self initData]; } - (void)didFailRetry:(NIMMessage *)message { @kWeakify(self); [Api checkLimit:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { @kStrongify(self); if(code == 200){ CheckLimitModel *model = [CheckLimitModel modelWithJSON:data.data]; if (model.chat) { if (message.isReceivedMsg) { [[NIMSDK sharedSDK].chatManager fetchMessageAttachment:message error:nil]; } else { [[NIMSDK sharedSDK].chatManager resendMessage:message error:nil]; } } else { [self displayLimitMessage:model]; } } else { [self showErrorToast:msg]; } } receiverUid:self.session.sessionId]; } - (void)sendTextMessage:(NSString *)text { @kWeakify(self); [Api checkLimit:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { @kStrongify(self); if(code == 200){ CheckLimitModel *model = [CheckLimitModel modelWithJSON:data.data]; if (model.chat) { NIMMessage *message = [NIMMessageMaker msgWithText:text]; message.apnsPayload = @{@"uid": [AccountInfoStorage instance].getUid}; //表明该条消息的发送者的账号或者消息所属的群组 ID [[[NIMSDK sharedSDK] chatManager] sendMessage:message toSession:self.session error:nil]; } else { [self displayLimitMessage:model]; } } else { [self showErrorToast:msg]; } } receiverUid:self.session.sessionId]; } - (void)audioRecordCompletion:(NSString *)recordPath { @kWeakify(self); [Api checkLimit:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { @kStrongify(self); if(code == 200){ CheckLimitModel *model = [CheckLimitModel modelWithJSON:data.data]; if (model.chat) { NIMMessage *message = [NIMMessageMaker msgWithAudio:recordPath]; message.apnsPayload = @{@"uid": [AccountInfoStorage instance].getUid}; //表明该条消息的发送者的账号或者消息所属的群组 ID [[[NIMSDK sharedSDK] chatManager] sendMessage:message toSession:self.session error:nil]; } else { [self displayLimitMessage:model]; } } else { [self showErrorToast:msg]; } } receiverUid:self.session.sessionId]; } #pragma mark - TZImagePickerControllerDelegate - (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto infos:(NSArray *)infos { [photos enumerateObjectsUsingBlock:^(UIImage * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (obj) { @kWeakify(self); [Api checkLimit:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { @kStrongify(self); if(code == 200){ CheckLimitModel *model = [CheckLimitModel modelWithJSON:data.data]; if (model.chat) { // 构造出具体会话 NIMMessage * message = [NIMMessageMaker msgWithImage:obj]; message.apnsPayload = @{@"uid": [AccountInfoStorage instance].getUid}; //表明该条消息的发送者的账号或者消息所属的群组 ID // 发送消息 [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:self.session error:nil]; } else { [self displayLimitMessage:model]; } } else { [self showErrorToast:msg]; } } receiverUid:self.session.sessionId]; } }]; } #pragma mark - SessionRiskViewDelegate - (void)sessionRiskViewCloseButtonClick:(SessionRiskView *)view { [[SessionRiskCache shareCache] saveCloseRisk:self.session.sessionId]; [self.riskAlertView removeFromSuperview]; [self.sessionTableView mas_updateConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.sessionNavView.mas_bottom).mas_offset(0); }]; } #pragma mark - SessionUserInfoTableViewCellDelegate - (void)sessionUserInfoTableViewCell:(SessionUserInfoTableViewCell *)view showUserInfoVC:(UserInfoModel *)userInfo { [self didTapAvatar:[NSString stringWithFormat:@"%ld", userInfo.uid]]; } #pragma mark - InputBoardDataSource //@return 点加号按钮弹出的拓展面板View,且无需设置frame - (UIView *)keyboardManagerExtendBoardView:(QKeyboardManager *)keyboardManager { UIView *boardView = [UIView new]; boardView.backgroundColor = UIColor.clearColor; return boardView; } //@return 点表情按钮弹出的表情面板View,且无需设置frame - (UIView *)keyboardManagerEmotionBoardView:(QKeyboardManager *)keyboardManager { QEmotionBoardView *emotionView = [[QEmotionBoardView alloc] init]; QEmotionHelper *faceManager = [QEmotionHelper sharedEmotionHelper]; emotionView.emotions = faceManager.emotionArray; emotionView.delegate = self; if (@available(iOS 11.0, *)) { NSBundle *bundle = [NSBundle bundleForClass:[self class]]; emotionView.backgroundColor = [UIColor colorNamed:@"q_input_extend_bg" inBundle:bundle compatibleWithTraitCollection:nil]; } else { emotionView.backgroundColor = [UIColor colorWithRed:(246)/255.0f green:(246)/255.0f blue:(246)/255.0f alpha:1]; } return emotionView; } //@return 点表情按钮弹出的表情面板View,且无需设置frame - (UIView *)keyboardManagerPhotoBoardView:(QKeyboardManager *)keyboardManager{ QinputPhotoView *emotionView = [[QinputPhotoView alloc] init]; self.photoView = emotionView; emotionView.photoList = self.phototArray; emotionView.delegate = self; emotionView.backgroundColor = [UIColor colorWithRed:(246)/255.0f green:(246)/255.0f blue:(246)/255.0f alpha:1]; return emotionView; } //@return 点表情按钮弹出的表情面板View的高度 - (CGFloat)keyboardManagerEmotionBoardHeight:(QKeyboardManager *)keyboardManager { return 294; } //@return 点加号按钮弹出的拓展面板View的高度 - (CGFloat)keyboardManagerExtendBoardHeight:(QKeyboardManager *)keyboardManager { return 174; } - (CGFloat)keyboardManagerPhotoBoardHeight:(QKeyboardManager *)keyboardManager { return 184 + kSafeAreaBottomHeight; } //点击表情按钮,切换到表情面板 - (void)inputBarView:(QInputBarView *)inputBarView onEmotionButtonClick:(UIButton *)emotionSwitchButton { if (emotionSwitchButton.isSelected) { [_keyboardManager switchToEmotionBoardKeyboard]; } else { _inputBarView.inputTextView.text = @""; [_inputBarView textViewBecomeFirstResponder]; } } - (void)inputBarView:(QInputBarView *)inputBarView onVoiceSwitchButtonClick:(UIButton *)voiceSwitchButton { if (!voiceSwitchButton.isSelected) { _inputBarView.inputTextView.text = @""; [_inputBarView textViewBecomeFirstResponder]; } else { [_keyboardManager hideAllBoardView]; } } - (void)inputBarView:(QInputBarView *)inputBarView onGiftButtonClick:(UIButton *)emotionSwitchButton { [_keyboardManager hideAllBoardView]; 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]; } - (void)inputBarView:(QInputBarView *)inputBarView onCameraButtonClick:(UIButton *)emotionSwitchButton { [_keyboardManager hideAllBoardView]; @kWeakify(self); [YYUtility checkCameraAvailable:^{ @kStrongify(self); UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; imagePicker.delegate = self; imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; imagePicker.allowsEditing = YES; [self presentViewController:imagePicker animated:YES completion:NULL]; } denied:^{ @kStrongify(self); [self showNotPhoto:YMLocalizedString(@"SessionViewController19") content:YMLocalizedString(@"SessionViewController10")]; } restriction:^{ @kStrongify(self); [self showNotPhoto:YMLocalizedString(@"SessionViewController19") content:YMLocalizedString(@"SessionViewController12")]; }]; } - (void)inputBarView:(QInputBarView *)inputBarView onPhototButtonClick:(UIButton *)emotionSwitchButton { if (emotionSwitchButton.isSelected) { @kWeakify(self); [YYUtility checkAssetsLibrayAvailable:^{ @kStrongify(self); [TZImagePickerConfig sharedInstance].allowPickingImage = YES; dispatch_async(dispatch_get_global_queue(0, 0), ^{ [[TZImageManager manager] getCameraRollAlbumWithFetchAssets:NO completion:^(TZAlbumModel *model) { [[TZImageManager manager] getAssetsFromFetchResult:model.result completion:^(NSArray *models) { dispatch_async(dispatch_get_main_queue(), ^{ NSMutableArray * array = [NSMutableArray array]; if (models.count > 40) { for (int i = 0; i < 40; i++) { TZAssetModel * assets = [models xpSafeObjectAtIndex:i]; QPhotoImageModel * infor = [[QPhotoImageModel alloc] init]; infor.isOrigin = NO; infor.assetInfo = assets; [array addObject:infor]; } } else { for (int i = 0; i < models.count; i++) { TZAssetModel * assets = [models xpSafeObjectAtIndex:i]; QPhotoImageModel * infor = [[QPhotoImageModel alloc] init]; infor.isOrigin = NO; infor.assetInfo = assets; [array addObject:infor]; } } self.phototArray = array; if (self.phototArray.count > 0) { self.photoView.photoList = self.phototArray; [self.keyboardManager switchToPhotoBoardKeyboard]; } else { TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:1 delegate:self]; imagePickerVc.modalPresentationStyle = UIModalPresentationOverFullScreen; imagePickerVc.allowPickingVideo = NO; imagePickerVc.allowTakeVideo = NO; imagePickerVc.naviBgColor = [DJDKMIMOMColor appCellBackgroundColor]; imagePickerVc.naviTitleColor = [DJDKMIMOMColor mainTextColor]; imagePickerVc.barItemTextColor = [DJDKMIMOMColor mainTextColor]; [self presentViewController:imagePickerVc animated:YES completion:nil]; } }); }]; }]; }); } denied:^{ @kStrongify(self); [self showNotPhoto:YMLocalizedString(@"SessionViewController20") content:YMLocalizedString(@"SessionViewController14")]; } restriction:^{ @kStrongify(self); [self showNotPhoto:YMLocalizedString(@"SessionViewController20") content:YMLocalizedString(@"SessionViewController16")]; }]; } else { [_keyboardManager hideAllBoardView]; _inputBarView.inputTextView.text = @""; [_inputBarView textViewResignFirstResponder]; } } - (void)showNotPhoto:(NSString *)title content:(NSString *)content { TTAlertConfig *config = [[TTAlertConfig alloc] init]; config.title = title; config.message = content; [TTPopup alertWithConfig:config confirmHandler:^{ NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; if ([[UIApplication sharedApplication] canOpenURL:url]) { [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:^(BOOL success) { }]; } } cancelHandler:^{ }]; } #pragma mark - InputBoardDelegate - (void)keyboardManager:(QKeyboardManager *)keyboardManager onWholeInputViewHeightDidChange:(CGFloat)wholeInputViewHeight reason:(WholeInputViewHeightDidChangeReason)reason { [UIView animateWithDuration:0.2 animations:^{ [self.sessionTableView nim_scrollToBottom:NO]; [self.sessionTableView mas_remakeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.view); make.top.mas_equalTo(self.sessionNavView.mas_bottom); make.bottom.mas_equalTo(self.view).offset(-wholeInputViewHeight - kSafeAreaBottomHeight); }]; }]; } #pragma mark - QEmotionBoardViewDelegate /** * 选中表情时的回调 * @param index 被选中的表情在`emotions`里的索引 * @param emotion 被选中的表情对应的`QMUIEmotion`对象 */ - (void)emotionView:(QEmotionBoardView *)emotionView didSelectEmotion:(QEmotion *)emotion atIndex:(NSInteger)index { //把😊插入到输入栏 UIFont *font = [UIFont systemFontOfSize:17.5]; NSTextAttachment * emotionAtt = [[NSTextAttachment alloc] init]; UIImage *iconImage = emotion.image; emotionAtt.bounds = CGRectMake(0, roundf(font.capHeight - emotion.image.size.width)/2.f, emotion.image.size.width, emotion.image.size.height); emotionAtt.image = iconImage; emotionAtt.imageName = emotion.displayName; NSAttributedString *emotionAttribute = [NSMutableAttributedString attributedStringWithAttachment:(NSTextAttachment *)emotionAtt]; [_inputBarView insertEmotionAttributedString:emotionAttribute]; } // 删除按钮的点击事件回调 - (void)emotionViewDidSelectDeleteButton:(QEmotionBoardView *)emotionView { if (![_inputBarView deleteEmotion]){ //根据当前的光标,这次点击删除按钮并没有删除表情,那么就删除文字 [_inputBarView.inputTextView deleteBackward]; } } // 发送按钮的点击事件回调 - (void)emotionViewDidSelectSendButton:(QEmotionBoardView *)emotionView { [self sendTextMessage:[_inputBarView textViewInputNormalText]]; _inputBarView.inputTextView.text = @""; [_keyboardManager hideAllBoardView]; } /** * 点击了系统键盘的发送按钮 * @param inputNormalText :"害~你好啊[微笑]" */ - (void)inputBarView:(QInputBarView *)inputBarView onKeyboardSendClick:(NSString *)inputNormalText { [self sendTextMessage:inputNormalText]; _inputBarView.inputTextView.text = @""; [_keyboardManager hideAllBoardView]; } #pragma mark - QinputPhotoViewDelegate - (void)qinputPhotoView:(QinputPhotoView *)view didClickSend:(NSArray *)photoList { for (int i = 0; i < photoList.count; i++) { QPhotoImageModel * imageInfo = [photoList xpSafeObjectAtIndex:i]; UIImage * image; if (view.isOrigin) { image = imageInfo.originImage; } else { image = imageInfo.compressImage; } if (image == nil){ continue; } // 发送消息 NIMMessage * message = [NIMMessageMaker msgWithImage:image]; @kWeakify(self); [Api checkLimit:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { @kStrongify(self); if(code == 200){ CheckLimitModel *model = [CheckLimitModel modelWithJSON:data.data]; if (model.chat) { message.apnsPayload = @{@"uid": [AccountInfoStorage instance].getUid}; //表明该条消息的发送者的账号或者消息所属的群组 ID [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:self.session error:nil]; [view resetChoosePhotos]; } else { [self displayLimitMessage:model]; } } else { [self showErrorToast:msg]; } } receiverUid:self.session.sessionId]; } } - (void)qinputPhotoView:(QinputPhotoView *)view didClickPhoto:(UIButton *)sender { TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:1 delegate:self]; imagePickerVc.modalPresentationStyle = UIModalPresentationOverFullScreen; imagePickerVc.allowPickingVideo = NO; imagePickerVc.allowTakeVideo = NO; imagePickerVc.naviBgColor = [DJDKMIMOMColor appCellBackgroundColor]; imagePickerVc.naviTitleColor = [DJDKMIMOMColor mainTextColor]; imagePickerVc.barItemTextColor = [DJDKMIMOMColor mainTextColor]; [self presentViewController:imagePickerVc animated:YES completion:nil]; } #pragma mark - UIImagePickerControllerDelegate - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *selectedPhoto = [info objectForKey:UIImagePickerControllerEditedImage]; if (selectedPhoto) { if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) { UIImageWriteToSavedPhotosAlbum(selectedPhoto, nil, nil, nil); } @kWeakify(self); [Api checkLimit:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { @kStrongify(self); if(code == 200){ CheckLimitModel *model = [CheckLimitModel modelWithJSON:data.data]; if (model.chat) { // 构造出具体会话 NIMMessage * message = [NIMMessageMaker msgWithImage:selectedPhoto]; message.apnsPayload = @{@"uid": [AccountInfoStorage instance].getUid}; //表明该条消息的发送者的账号或者消息所属的群组 ID // 发送消息 [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:self.session error:nil]; } else { [self displayLimitMessage:model]; } } else { [self showErrorToast:msg]; } } receiverUid:self.session.sessionId]; } [picker dismissViewControllerAnimated:YES completion:^{}]; } - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{ [picker dismissViewControllerAnimated:YES completion:^{}]; } #pragma mark - Getters And Setters - (NSArray *)messages { if (!_messages) { _messages = [[NSMutableArray alloc] init]; } return _messages; } #pragma mark - Event Response - (void)closeKeyBoard { [self.view endEditing:YES]; [self.inputBarView textViewResignFirstResponder]; } - (UITableView *)sessionTableView { if (!_sessionTableView) { _sessionTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; _sessionTableView.delegate = self; _sessionTableView.dataSource = self; _sessionTableView.backgroundColor = UIColor.clearColor; _sessionTableView.separatorStyle = UITableViewCellSeparatorStyleNone; _sessionTableView.showsVerticalScrollIndicator = NO; if (@available(iOS 11.0, *)) { _sessionTableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } // UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyBoard)]; // [_sessionTableView addGestureRecognizer:tap]; } return _sessionTableView; } - (SessionNavView *)sessionNavView { if (!_sessionNavView) { _sessionNavView = [[SessionNavView alloc] init]; _sessionNavView.delegate = self; } return _sessionNavView; } - (SessionRiskView *)riskAlertView { if (!_riskAlertView) { _riskAlertView = [[SessionRiskView alloc] init]; _riskAlertView.delegate = self; } return _riskAlertView; } @end