// // YOUPAIBBNIMInputView.m // VQU // // Created by Elaine on 2021/10/26. // Copyright © 2021 MS. All rights reserved. // #import "YOUPAIBBNIMInputView.h" #import #import "YOUPAINIMInputMoreContainerView.h" #import "YOUPAINIMInputEmoticonContainerView.h" #import "YOUPAINIMInputAudioRecordIndicatorView.h" #import "UIView+NIM.h" #import "NIMInputEmoticonDefine.h" #import "YOUPAINIMInputEmoticonManager.h" #import "YOUPAIBBNIMInputToolBar.h" #import "UIImage+NIMKit.h" #import "NIMGlobalMacro.h" #import "NIMContactSelectViewController.h" #import "NIMKit.h" #import "NIMKitInfoFetchOption.h" #import "NIMKitKeyboardInfo.h" @interface YOUPAIBBNIMInputView() { UIView *_youpaipemoticonView; } //@property (nonatomic, strong) YOUPAINIMInputAudioRecordIndicatorView *youpaipaudioRecordIndicator; @property (nonatomic, assign) NIMAudioRecordPhase youpaiprecordPhase; @property (nonatomic, weak) id youpaipinputConfig; @property (nonatomic, weak) id inputDelegate; @property (nonatomic, weak) id actionDelegate; @property (nonatomic, assign) CGFloat youpaipkeyBoardFrameTop; //键盘的frame的top值,屏幕高度 - 键盘高度,由于有旋转的可能,这个值只有当 键盘弹出时才有意义。 @end @implementation YOUPAIBBNIMInputView @synthesize youpaipemoticonContainer = _youpaipemoticonContainer; @synthesize youpaipmoreContainer = _youpaipmoreContainer; - (instancetype)initWithFrame:(CGRect)frame config:(id)config { self = [super initWithFrame:frame]; if (self) { _youpaiprecording = NO; _youpaiprecordPhase = AudioRecordPhaseEnd; _youpaipatCache = [[YOUPAINIMInputAtCache alloc] init]; _youpaipinputConfig = config; self.backgroundColor = LCBkgColor; } return self; } - (void)didMoveToWindow { [self youpaifsetup]; } - (CGSize)sizeThatFits:(CGSize)size { //这里不做.语法 get 操作,会提前初始化组件导致卡顿 CGFloat toolBarHeight = _youpaiptoolBar.nim_height; CGFloat containerHeight = 0; switch (self.youpaipstatus) { case BBNIMInputStatusEmoticon: _youpaiptoolBar.youpaipemoticonBtn.selected = YES; _youpaiptoolBar.youpaiprecordBtn.selected = NO; containerHeight = _youpaipemoticonContainer.nim_height; break; case BBNIMInputStatusMore: _youpaiptoolBar.youpaipemoticonBtn.selected = NO; _youpaiptoolBar.youpaiprecordBtn.selected = YES; containerHeight = _youpaipvoiceViewContainer.nim_height; break; default: { _youpaiptoolBar.youpaipemoticonBtn.selected = NO; _youpaiptoolBar.youpaiprecordBtn.selected = NO; UIEdgeInsets safeArea = UIEdgeInsetsZero; if (@available(iOS 11.0, *)) { safeArea = self.superview.safeAreaInsets; } //键盘是从最底下弹起的,需要减去安全区域底部的高度 CGFloat keyboardDelta = [NIMKitKeyboardInfo instance].keyboardHeight - safeArea.bottom; //如果键盘还没有安全区域高,容器的初始值为0;否则则为键盘和安全区域的高度差值,这样可以保证 youpaiptoolBar 始终在键盘上面 containerHeight = keyboardDelta>0 ? keyboardDelta : 0; } break; } CGFloat height = toolBarHeight + containerHeight; CGFloat width = self.superview? self.superview.nim_width : self.nim_width; return CGSizeMake(width, height); } - (void)youpaifsetInputDelegate:(id)delegate { _inputDelegate = delegate; } - (void)youpaifsetInputActionDelegate:(id)actionDelegate { _actionDelegate = actionDelegate; } - (void)youpaifreset { self.nim_width = self.superview.nim_width; [self youpaifrefreshStatus:BBNIMInputStatusText]; [self sizeToFit]; } - (void)youpaifrefreshStatus:(BBNIMInputStatus)status { self.youpaipstatus = status; [self.youpaiptoolBar youpaifupdate:status]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.youpaipvoiceViewContainer.hidden = status != BBNIMInputStatusMore; self.youpaipemoticonContainer.hidden = status != BBNIMInputStatusEmoticon; }); } //- (YOUPAINIMInputAudioRecordIndicatorView *)youpaipaudioRecordIndicator { // if(!_youpaipaudioRecordIndicator) { // _youpaipaudioRecordIndicator = [[YOUPAINIMInputAudioRecordIndicatorView alloc] init]; // } // return _youpaipaudioRecordIndicator; //} - (void)setYoupaiprecordPhase:(NIMAudioRecordPhase)youpaiprecordPhase { NIMAudioRecordPhase prevPhase = _youpaiprecordPhase; _youpaiprecordPhase = youpaiprecordPhase; // self.youpaipaudioRecordIndicator.phase = _youpaiprecordPhase; if(prevPhase == AudioRecordPhaseEnd) { if(AudioRecordPhaseStart == _youpaiprecordPhase) { if ([_actionDelegate respondsToSelector:@selector(onStartRecording)]) { [_actionDelegate onStartRecording]; } } } else if (prevPhase == AudioRecordPhaseStart || prevPhase == AudioRecordPhaseRecording) { if (AudioRecordPhaseEnd == _youpaiprecordPhase) { if ([_actionDelegate respondsToSelector:@selector(onStopRecording)]) { [_actionDelegate onStopRecording]; } } } else if (prevPhase == AudioRecordPhaseCancelling) { if(AudioRecordPhaseEnd == _youpaiprecordPhase) { if ([_actionDelegate respondsToSelector:@selector(onCancelRecording)]) { [_actionDelegate onCancelRecording]; } } } } - (void)youpaifsetup { if (!_youpaiptoolBar) { _youpaiptoolBar = [[YOUPAIBBNIMInputToolBar alloc] initWithFrame:CGRectMake(0, 0, self.nim_width, 0)]; } [self addSubview:_youpaiptoolBar]; //设置placeholder NSString *placeholder = [NIMKit sharedKit].config.placeholder; placeholder = @" 请输入消息…"; [_youpaiptoolBar youpaifsetPlaceHolder:placeholder]; _youpaiptoolBar.backgroundColor = HexColorFromRGB(0x2A2935); //设置input bar 上的按钮 if ([_youpaipinputConfig respondsToSelector:@selector(inputBarItemTypes)]) { NSArray *types = [_youpaipinputConfig inputBarItemTypes]; [_youpaiptoolBar setYoupaipinputBarItemTypes:types]; } _youpaiptoolBar.delegate = self; [_youpaiptoolBar.youpaiprecordBtn addTarget:self action:@selector(youpaifonTouchRecordBtn:) forControlEvents:UIControlEventTouchUpInside]; [_youpaiptoolBar.youpaipcameraBtn addTarget:self action:@selector(youpaifonTouchCameraBtn:) forControlEvents:UIControlEventTouchUpInside]; [_youpaiptoolBar.youpaipphotoBtn addTarget:self action:@selector(youpaifonTouchPhotoBtn:) forControlEvents:UIControlEventTouchUpInside]; [_youpaiptoolBar.youpaipgiftBtn addTarget:self action:@selector(youpaifonTouchGiftBtn:) forControlEvents:UIControlEventTouchUpInside]; [_youpaiptoolBar.youpaipvideoBtn addTarget:self action:@selector(youpaifonTouchVideoBtn:) forControlEvents:UIControlEventTouchUpInside]; [_youpaiptoolBar.youpaipemoticonBtn addTarget:self action:@selector(youpaifonTouchEmoticonBtn:) forControlEvents:UIControlEventTouchUpInside]; [_youpaiptoolBar.youpaipmoreMediaBtn addTarget:self action:@selector(youpaifonTouchMoreBtn:) forControlEvents:UIControlEventTouchUpInside]; [_youpaiptoolBar.youpaipvoiceBtn addTarget:self action:@selector(youpaifonTouchVoiceBtn:) forControlEvents:UIControlEventTouchUpInside]; _youpaiptoolBar.nim_size = [_youpaiptoolBar sizeThatFits:CGSizeMake(self.nim_width, CGFLOAT_MAX)]; _youpaiptoolBar.autoresizingMask = UIViewAutoresizingFlexibleWidth; [_youpaiptoolBar.youpaiprecordButton setTitle:@"按住 说话" forState:UIControlStateNormal]; [_youpaiptoolBar.youpaiprecordButton setTitle:@"松开 结束" forState:UIControlStateSelected]; [_youpaiptoolBar.youpaiprecordButton setHidden:YES]; //设置最大输入字数 NSInteger textInputLength = [NIMKit sharedKit].config.inputMaxLength; self.youpaipmaxTextLength = textInputLength; [self youpaifrefreshStatus:BBNIMInputStatusText]; [self sizeToFit]; } - (void)youpaifcheckMoreContainer { if (!_youpaipmoreContainer) { YOUPAINIMInputMoreContainerView *youpaipmoreContainer = [[YOUPAINIMInputMoreContainerView alloc] initWithFrame:CGRectZero]; youpaipmoreContainer.nim_size = [youpaipmoreContainer sizeThatFits:CGSizeMake(self.nim_width, CGFLOAT_MAX)]; youpaipmoreContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth; youpaipmoreContainer.hidden = YES; youpaipmoreContainer.config = _youpaipinputConfig; youpaipmoreContainer.actionDelegate = self.actionDelegate; _youpaipmoreContainer = youpaipmoreContainer; } //可能是外部主动设置进来的,统一放在这里添加 subview if (!_youpaipmoreContainer.superview) { [self addSubview:_youpaipmoreContainer]; } } - (void)setYoupaipmoreContainer:(UIView *)youpaipmoreContainer { _youpaipmoreContainer = youpaipmoreContainer; [self sizeToFit]; } //- (YOUPAINIMInputVoiceView *)youpaipvoiceViewContainer //{ // if (!_youpaipvoiceViewContainer) { // _youpaipvoiceViewContainer = [[YOUPAINIMInputVoiceView alloc] initWithFrame:CGRectMake(0,_youpaiptoolBar.nim_height, self.nim_width,216.0f)]; // _youpaipvoiceViewContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth; // _youpaipvoiceViewContainer.hidden = YES; // } // return _youpaipvoiceViewContainer; //} - (void)youpaifcheckVoiceViewContainer{ if (!_youpaipvoiceViewContainer) { YOUPAINIMInputVoiceView *voiceContainer = [[YOUPAINIMInputVoiceView alloc] initWithFrame:CGRectMake(0,_youpaiptoolBar.nim_height, self.nim_width,216.0f)]; voiceContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth; voiceContainer.hidden = YES; _youpaipvoiceViewContainer = voiceContainer; [_youpaipvoiceViewContainer.recordBt addTarget:self action:@selector(youpaifonTouchRecordBtnDown:) forControlEvents:UIControlEventTouchDown]; [_youpaipvoiceViewContainer.recordBt addTarget:self action:@selector(youpaifonTouchRecordBtnDragInside:) forControlEvents:UIControlEventTouchDragInside]; [_youpaipvoiceViewContainer.recordBt addTarget:self action:@selector(youpaifonTouchRecordBtnDragOutside:) forControlEvents:UIControlEventTouchDragOutside]; [_youpaipvoiceViewContainer.recordBt addTarget:self action:@selector(youpaifonTouchRecordBtnUpInside:) forControlEvents:UIControlEventTouchUpInside]; [_youpaipvoiceViewContainer.recordBt addTarget:self action:@selector(youpaifonTouchRecordBtnUpOutside:) forControlEvents:UIControlEventTouchUpOutside]; } //可能是外部主动设置进来的,统一放在这里添加 subview if (!_youpaipvoiceViewContainer.superview) { [self addSubview:_youpaipvoiceViewContainer]; } } - (void)setYoupaipvoiceViewContainer:(YOUPAINIMInputVoiceView *)youpaipvoiceViewContainer { _youpaipvoiceViewContainer = youpaipvoiceViewContainer; [self sizeToFit]; } - (void)youpaifcheckEmoticonContainer { if (!_youpaipemoticonContainer) { YOUPAINIMInputEmoticonContainerView *youpaipemoticonContainer = [[YOUPAINIMInputEmoticonContainerView alloc] initWithFrame:CGRectZero]; youpaipemoticonContainer.nim_size = [youpaipemoticonContainer sizeThatFits:CGSizeMake(self.nim_width, CGFLOAT_MAX)]; youpaipemoticonContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth; youpaipemoticonContainer.delegate = self; youpaipemoticonContainer.hidden = YES; youpaipemoticonContainer.config = _youpaipinputConfig; _youpaipemoticonContainer = youpaipemoticonContainer; } //可能是外部主动设置进来的,统一放在这里添加 subview if (!_youpaipemoticonContainer.superview) { [self addSubview:_youpaipemoticonContainer]; } } - (void)setYoupaipemoticonContainer:(UIView *)youpaipemoticonContainer { _youpaipemoticonContainer = youpaipemoticonContainer; [self sizeToFit]; } - (void)setYoupaiprecording:(BOOL)youpaiprecording { if(youpaiprecording) { // self.youpaipaudioRecordIndicator.center = self.superview.center; // [self.superview addSubview:self.youpaipaudioRecordIndicator]; self.youpaiprecordPhase = AudioRecordPhaseRecording; } else { // [self.youpaipaudioRecordIndicator removeFromSuperview]; self.youpaiprecordPhase = AudioRecordPhaseEnd; } _youpaiprecording = youpaiprecording; } #pragma mark - 外部接口 - (void)youpaifsetInputTextPlaceHolder:(NSString*)placeHolder { [_youpaiptoolBar youpaifsetPlaceHolder:placeHolder]; } - (void)youpaifupdateAudioRecordTime:(NSTimeInterval)time { // self.youpaipaudioRecordIndicator.recordTime = time; self.youpaipvoiceViewContainer.recordTime = time; } - (void)youpaifupdateVoicePower:(float)power { } #pragma mark - private methods - (void)setFrame:(CGRect)frame { CGFloat height = self.frame.size.height; [super setFrame:frame]; if (frame.size.height != height) { [self youpaifcallDidChangeHeight]; } } - (void)youpaifcallDidChangeHeight { if (_inputDelegate && [_inputDelegate respondsToSelector:@selector(didChangeInputHeight:)]) { if (self.youpaipstatus == BBNIMInputStatusMore || self.youpaipstatus == BBNIMInputStatusEmoticon || self.youpaipstatus == BBNIMInputStatusAudio) { //这个时候需要一个动画来模拟键盘 [UIView animateWithDuration:0.25 delay:0 options:7 animations:^{ [_inputDelegate didChangeInputHeight:self.nim_height]; } completion:nil]; } else { [_inputDelegate didChangeInputHeight:self.nim_height]; } } } - (void)layoutSubviews { [super layoutSubviews]; //这里不做.语法 get 操作,会提前初始化组件导致卡顿 _youpaipmoreContainer.nim_top = self.youpaiptoolBar.nim_bottom; _youpaipemoticonContainer.nim_top = self.youpaiptoolBar.nim_bottom; } #pragma mark - button actions - (void)youpaifonTouchVoiceBtn:(id)sender { // image change if (self.youpaipstatus!= BBNIMInputStatusAudio) { if ([self.actionDelegate respondsToSelector:@selector(onTapVoiceBtn:)]) { [self.actionDelegate onTapVoiceBtn:sender]; } __weak typeof(self) weakSelf = self; if ([[AVAudioSession sharedInstance] respondsToSelector:@selector(requestRecordPermission:)]) { [[AVAudioSession sharedInstance] performSelector:@selector(requestRecordPermission:) withObject:^(BOOL granted) { if (granted) { dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf youpaifrefreshStatus:BBNIMInputStatusAudio]; if (weakSelf.youpaiptoolBar.youpaipshowsKeyboard) { weakSelf.youpaiptoolBar.youpaipshowsKeyboard = NO; } [self sizeToFit]; }); } else { dispatch_async(dispatch_get_main_queue(), ^{ [[[UIAlertView alloc] initWithTitle:nil message:@"没有麦克风权限" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil] show]; }); } }]; } } else { if ([self.youpaiptoolBar.youpaipinputBarItemTypes containsObject:@(NIMInputBarItemTypeTextAndRecord)]) { [self youpaifrefreshStatus:BBNIMInputStatusText]; self.youpaiptoolBar.youpaipshowsKeyboard = YES; } } } - (IBAction)youpaifonTouchRecordBtnDown:(id)sender { self.youpaiprecordPhase = AudioRecordPhaseStart; self.youpaipvoiceViewContainer.titleLabel.text = @""; [self.youpaipvoiceViewContainer.recordBt setImage:[UIImage imageNamed:@"vqu_images_vqu_images_IM_im_record_ing"] forState:UIControlStateNormal];; } - (IBAction)youpaifonTouchRecordBtnUpInside:(id)sender { // finish Recording self.youpaiprecordPhase = AudioRecordPhaseEnd; self.youpaipvoiceViewContainer.titleLabel.text = @"按住说话"; self.youpaipvoiceViewContainer.timeLabel.text = @""; self.youpaipvoiceViewContainer.titleLabel.textColor = [UIColor whiteColor]; [self.youpaipvoiceViewContainer.recordBt setImage:[UIImage imageNamed:@"vqu_images_vqu_images_IM_im_record_Voice"] forState:UIControlStateNormal]; } - (IBAction)youpaifonTouchRecordBtnUpOutside:(id)sender { // cancel Recording self.youpaiprecordPhase = AudioRecordPhaseEnd; self.youpaipvoiceViewContainer.titleLabel.text = @"按住说话"; self.youpaipvoiceViewContainer.timeLabel.text = @""; self.youpaipvoiceViewContainer.titleLabel.textColor = LZFAFAFCColor; [self.youpaipvoiceViewContainer.recordBt setImage:[UIImage imageNamed:@"vqu_images_vqu_images_IM_im_record_Voice"] forState:UIControlStateNormal]; } - (IBAction)youpaifonTouchRecordBtnDragInside:(id)sender { // "手指上滑,取消发送" self.youpaipvoiceViewContainer.titleLabel.text = @"手指上滑,取消发送"; self.youpaipvoiceViewContainer.titleLabel.textColor = HexColorFromRGB(0x9F9DA5); self.youpaipvoiceViewContainer.timeLabel.textColor = [UIColor whiteColor]; self.youpaiprecordPhase = AudioRecordPhaseRecording; [self.youpaipvoiceViewContainer.recordBt setImage:[UIImage imageNamed:@"vqu_images_vqu_images_IM_im_record_ing"] forState:UIControlStateNormal];; } - (IBAction)youpaifonTouchRecordBtnDragOutside:(id)sender { // "松开手指,取消发送" self.youpaipvoiceViewContainer.titleLabel.text = @"松开手指,取消发送"; self.youpaipvoiceViewContainer.titleLabel.textColor = HexColorFromRGB(0x79262C); self.youpaipvoiceViewContainer.timeLabel.textColor = HexColorFromRGB(0xD63641); self.youpaiprecordPhase = AudioRecordPhaseCancelling; [self.youpaipvoiceViewContainer.recordBt setImage:[UIImage imageNamed:@"vqu_images_vqu_images_IM_im_record_stop"] forState:UIControlStateNormal];; } - (void)youpaifonTouchCameraBtn:(UIButton*)btn{ if (self.actionDelegate && [self.actionDelegate respondsToSelector:@selector(onCameraClick)]) { [self.actionDelegate onCameraClick]; } } - (void)youpaifonTouchPhotoBtn:(UIButton*)btn{ if (self.actionDelegate && [self.actionDelegate respondsToSelector:@selector(onPhotoClick)]) { [self.actionDelegate onPhotoClick]; } } - (void)youpaifonTouchGiftBtn:(UIButton*)btn{ if (self.actionDelegate && [self.actionDelegate respondsToSelector:@selector(onGiftClick)]) { [self.actionDelegate onGiftClick]; } } - (void)youpaifonTouchVideoBtn:(UIButton*)btn{ if (self.actionDelegate && [self.actionDelegate respondsToSelector:@selector(onVideoClick)]) { [self.actionDelegate onVideoClick]; } } - (void)youpaifonTouchRecordBtn:(id)sender{ if (self.youpaipstatus != NIMInputStatusMore) { // if ([self.actionDelegate respondsToSelector:@selector(onTapMoreBtn:)]) { // [self.actionDelegate onTapMoreBtn:sender]; // } [self youpaifcheckVoiceViewContainer]; [self bringSubviewToFront:self.youpaipvoiceViewContainer]; [self.youpaipvoiceViewContainer setHidden:NO]; [self.youpaipemoticonContainer setHidden:YES]; [self youpaifrefreshStatus:BBNIMInputStatusMore]; [self sizeToFit]; if (self.youpaiptoolBar.youpaipshowsKeyboard) { self.youpaiptoolBar.youpaipshowsKeyboard = NO; } } else { [self youpaifrefreshStatus:BBNIMInputStatusText]; self.youpaiptoolBar.youpaipshowsKeyboard = YES; } } - (void)youpaifonTouchEmoticonBtn:(id)sender { if (self.youpaipstatus != BBNIMInputStatusEmoticon) { if ([self.actionDelegate respondsToSelector:@selector(onTapEmoticonBtn:)]) { [self.actionDelegate onTapEmoticonBtn:sender]; } [self youpaifcheckEmoticonContainer]; [self bringSubviewToFront:self.youpaipemoticonContainer]; [self.youpaipemoticonContainer setHidden:NO]; [self.youpaipvoiceViewContainer setHidden:YES]; [self youpaifrefreshStatus:BBNIMInputStatusEmoticon]; [self sizeToFit]; if (self.youpaiptoolBar.youpaipshowsKeyboard) { self.youpaiptoolBar.youpaipshowsKeyboard = NO; } } else { [self youpaifrefreshStatus:BBNIMInputStatusText]; self.youpaiptoolBar.youpaipshowsKeyboard = YES; } } - (void)youpaifonTouchMoreBtn:(id)sender { if (self.youpaipstatus != BBNIMInputStatusMore) { if ([self.actionDelegate respondsToSelector:@selector(onTapMoreBtn:)]) { [self.actionDelegate onTapMoreBtn:sender]; } [self youpaifcheckMoreContainer]; [self bringSubviewToFront:self.youpaipmoreContainer]; [self.youpaipmoreContainer setHidden:NO]; [self.youpaipemoticonContainer setHidden:YES]; [self youpaifrefreshStatus:BBNIMInputStatusMore]; [self sizeToFit]; if (self.youpaiptoolBar.youpaipshowsKeyboard) { self.youpaiptoolBar.youpaipshowsKeyboard = NO; } } else { [self youpaifrefreshStatus:BBNIMInputStatusText]; self.youpaiptoolBar.youpaipshowsKeyboard = YES; } } - (BOOL)endEditing:(BOOL)force { BOOL endEditing = [super endEditing:force]; if (!self.youpaiptoolBar.youpaipshowsKeyboard) { UIViewAnimationCurve curve = UIViewAnimationCurveEaseInOut; void(^animations)(void) = ^{ [self youpaifrefreshStatus:BBNIMInputStatusText]; [self sizeToFit]; if (self.inputDelegate && [self.inputDelegate respondsToSelector:@selector(didChangeInputHeight:)]) { [self.inputDelegate didChangeInputHeight:self.nim_height]; } }; NSTimeInterval duration = 0.25; [UIView animateWithDuration:duration delay:0.0f options:(curve << 16 | UIViewAnimationOptionBeginFromCurrentState) animations:animations completion:nil]; } return endEditing; } #pragma mark - NIMInputToolBarDelegate - (BOOL)textViewShouldBeginEditing { [self youpaifrefreshStatus:BBNIMInputStatusText]; return YES; } - (BOOL)shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if ([text isEqualToString:@"\n"]) { [self youpaifdidPressSend:nil]; return NO; } if ([text isEqualToString:@""] && range.length == 1 ) { //非选择删除 return [self youpaifonTextDelete]; } if ([self shouldCheckAt]) { // @ 功能 [self checkAt:text]; } NSString *str = [self.youpaiptoolBar.youpaipcontentText stringByAppendingString:text]; if (str.length > self.youpaipmaxTextLength) { return NO; } return YES; } - (BOOL)shouldCheckAt { BOOL youpaipdisable = NO; if ([self.youpaipinputConfig respondsToSelector:@selector(disableAt)]) { youpaipdisable = [self.youpaipinputConfig disableAt]; } return !youpaipdisable; } - (void)checkAt:(NSString *)text { if ([text isEqualToString:NIMInputAtStartChar]) { switch (self.session.sessionType) { case NIMSessionTypeTeam:{ NIMContactTeamMemberSelectConfig *config = [[NIMContactTeamMemberSelectConfig alloc] init]; if ([self.youpaipinputConfig respondsToSelector:@selector(enableRobot)]) { config.enableRobot = [self.youpaipinputConfig enableRobot]; } else { config.enableRobot = YES; } config.needMutiSelected = NO; config.teamId = self.session.sessionId; config.filterIds = @[[NIMSDK sharedSDK].loginManager.currentAccount]; NIMContactSelectViewController *vc = [[NIMContactSelectViewController alloc] initWithConfig:config]; vc.delegate = self; dispatch_async(dispatch_get_main_queue(), ^{ [vc show]; }); } break; case NIMSessionTypeP2P: case NIMSessionTypeChatroom:{ if (([self.youpaipinputConfig respondsToSelector:@selector(enableRobot)] && self.youpaipinputConfig.enableRobot) || [NIMSDK sharedSDK].isUsingDemoAppKey) { NIMContactRobotSelectConfig *config = [[NIMContactRobotSelectConfig alloc] init]; config.needMutiSelected = NO; NIMContactSelectViewController *vc = [[NIMContactSelectViewController alloc] initWithConfig:config]; vc.delegate = self; dispatch_async(dispatch_get_main_queue(), ^{ [vc show]; }); } } break; default: break; } } } - (void)textViewDidChange { if (self.actionDelegate && [self.actionDelegate respondsToSelector:@selector(onTextChanged:)]) { [self.actionDelegate onTextChanged:self]; } } - (void)toolBarDidChangeHeight:(CGFloat)height { [self sizeToFit]; } #pragma mark - NIMContactSelectDelegate - (void)didFinishedSelect:(NSArray *)selectedContacts { NSMutableString *str = [[NSMutableString alloc] initWithString:@""]; NIMKitInfoFetchOption *option = [[NIMKitInfoFetchOption alloc] init]; option.session = self.session; option.forbidaAlias = YES; for (NSString *uid in selectedContacts) { NSString *nick = [[NIMKit sharedKit].provider infoByUser:uid option:option].showName; [str appendString:nick]; [str appendString:NIMInputAtEndChar]; if (![selectedContacts.lastObject isEqualToString:uid]) { [str appendString:NIMInputAtStartChar]; } NIMInputAtItem *item = [[NIMInputAtItem alloc] init]; item.uid = uid; item.name = nick; [self.youpaipatCache addAtItem:item]; } [self.youpaiptoolBar youpaifinsertText:str]; } #pragma mark - InputEmoticonProtocol - (void)selectedEmoticon:(NSString*)emoticonID catalog:(NSString*)emotCatalogID description:(NSString *)description{ if (!emotCatalogID) { //删除键 [self youpaifonTextDelete]; }else{ if ([emotCatalogID isEqualToString:NIMKit_EmojiCatalog]) { [self.youpaiptoolBar youpaifinsertText:description]; }else{ //发送贴图消息 if ([self.actionDelegate respondsToSelector:@selector(onSelectChartlet:catalog:)]) { [self.actionDelegate onSelectChartlet:emoticonID catalog:emotCatalogID]; } } } } - (void)youpaifdidPressSend:(id)sender{ if ([self.actionDelegate respondsToSelector:@selector(onSendText:atUsers:)] && [self.youpaiptoolBar.youpaipcontentText length] > 0) { NSString *sendText = self.youpaiptoolBar.youpaipcontentText; [self.actionDelegate onSendText:sendText atUsers:[self.youpaipatCache youpaifallAtUid:sendText]]; [self.youpaipatCache clean]; self.youpaiptoolBar.youpaipcontentText = @""; [self.youpaiptoolBar layoutIfNeeded]; } } - (BOOL)youpaifonTextDelete { NSRange range = [self youpaifdelRangeForEmoticon]; if (range.length == 1) { //删的不是表情,可能是@ NIMInputAtItem *item = [self delRangeForAt]; if (item) { range = item.range; } } if (range.length == 1) { //自动删除 return YES; } [self.youpaiptoolBar youpaifdeleteText:range]; return NO; } - (NSRange)youpaifdelRangeForEmoticon { NSString *text = self.youpaiptoolBar.youpaipcontentText; NSRange range = [self youpaifrangeForPrefix:@"[" suffix:@"]"]; NSRange selectedRange = [self.youpaiptoolBar youpaifselectedRange]; if (range.length > 1) { NSString *name = [text substringWithRange:range]; NIMInputEmoticon *icon = [[YOUPAINIMInputEmoticonManager sharedManager] emoticonByTag:name]; range = icon? range : NSMakeRange(selectedRange.location - 1, 1); } return range; } - (NIMInputAtItem *)delRangeForAt { NSString *text = self.youpaiptoolBar.youpaipcontentText; NSRange range = [self youpaifrangeForPrefix:NIMInputAtStartChar suffix:NIMInputAtEndChar]; NSRange selectedRange = [self.youpaiptoolBar youpaifselectedRange]; NIMInputAtItem *item = nil; if (range.length > 1) { NSString *name = [text substringWithRange:range]; NSString *set = [NIMInputAtStartChar stringByAppendingString:NIMInputAtEndChar]; name = [name stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:set]]; item = [self.youpaipatCache item:name]; range = item? range : NSMakeRange(selectedRange.location - 1, 1); } item.range = range; return item; } - (NSRange)youpaifrangeForPrefix:(NSString *)prefix suffix:(NSString *)suffix { NSString *text = self.youpaiptoolBar.youpaipcontentText; NSRange range = [self.youpaiptoolBar youpaifselectedRange]; NSString *selectedText = range.length ? [text substringWithRange:range] : text; NSInteger endLocation = range.location; if (endLocation <= 0) { return NSMakeRange(NSNotFound, 0); } NSInteger index = -1; if ([selectedText hasSuffix:suffix]) { //往前搜最多20个字符,一般来讲是够了... NSInteger p = 20; for (NSInteger i = endLocation; i >= endLocation - p && i-1 >= 0 ; i--) { NSRange subRange = NSMakeRange(i - 1, 1); NSString *subString = [text substringWithRange:subRange]; if ([subString compare:prefix] == NSOrderedSame) { index = i - 1; break; } } } return index == -1? NSMakeRange(endLocation - 1, 1) : NSMakeRange(index, endLocation - index); } @end