imchat视频聊天室 linux,QXShowing/QXShowing/Libs/IMChat/EaseUI/EMUIKit/ViewController/EaseMessageViewContr...

本文介绍了Hyphenate即时通讯库的集成过程,包括初始化、消息接收、显示和处理,如文本、语音、图片、表情等。还涉及到了长按操作、菜单显示、语音录制、录音按钮状态变化、地理位置消息发送等功能的实现。此外,文章还涵盖了聊天工具栏的交互、键盘隐藏、表情选择等交互细节。
摘要由CSDN通过智能技术生成

/************************************************************

* * Hyphenate CONFIDENTIAL

* __________________

* Copyright (C) 2016 Hyphenate Inc. All rights reserved.

*

* NOTICE: All information contained herein is, and remains

* the property of Hyphenate Inc.

* Dissemination of this information or reproduction of this material

* is strictly forbidden unless prior written permission is obtained

* from Hyphenate Inc.

*/

#import "EaseMessageViewController.h"

#import

#import

#import

#import "NSDate+Category.h"

#import "EaseUsersListViewController.h"

#import "EaseMessageReadManager.h"

#import "EaseEmotionManager.h"

#import "EaseEmoji.h"

#import "EaseEmotionEscape.h"

#import "EaseCustomMessageCell.h"

#import "UIImage+EMGIF.h"

#import "EaseLocalDefine.h"

#import "EaseSDKHelper.h"

#define KHintAdjustY 50

#define IOS_VERSION [[UIDevice currentDevice] systemVersion]>=9.0

typedef enum : NSUInteger {

EMRequestRecord,

EMCanRecord,

EMCanNotRecord,

} EMRecordResponse;

@implementation EaseAtTarget

- (instancetype)initWithUserId:(NSString*)userId andNickname:(NSString*)nickname

{

if (self = [super init]) {

_userId = [userId copy];

_nickname = [nickname copy];

}

return self;

}

@end

@interface EaseMessageViewController ()

{

UIMenuItem *_copyMenuItem;

UIMenuItem *_deleteMenuItem;

UILongPressGestureRecognizer *_lpgr;

NSMutableArray *_atTargets;

dispatch_queue_t _messageQueue;

BOOL _isRecording;

}

@property (strong, nonatomic) id playingVoiceModel;

@property (nonatomic) BOOL isKicked;

@property (nonatomic) BOOL isPlayingAudio;

@property (nonatomic, strong) NSMutableArray *atTargets;

@end

@implementation EaseMessageViewController

@synthesize conversation = _conversation;

@synthesize deleteConversationIfNull = _deleteConversationIfNull;

@synthesize messageCountOfPage = _messageCountOfPage;

@synthesize timeCellHeight = _timeCellHeight;

@synthesize messageTimeIntervalTag = _messageTimeIntervalTag;

- (instancetype)initWithConversationChatter:(NSString *)conversationChatter

conversationType:(EMConversationType)conversationType

{

if ([conversationChatter length] == 0) {

return nil;

}

self = [super initWithStyle:UITableViewStylePlain];

if (self) {

_conversation = [[EMClient sharedClient].chatManager getConversation:conversationChatter type:conversationType createIfNotExist:YES];

_messageCountOfPage = 10;

_timeCellHeight = 30;

_deleteConversationIfNull = YES;

_scrollToBottomWhenAppear = YES;

_messsagesSource = [NSMutableArray array];

[_conversation markAllMessagesAsRead:nil];

}

return self;

}

- (void)viewDidLoad {

[super viewDidLoad];

// Do any additional setup after loading the view.

self.view.backgroundColor = [UIColor colorWithRed:248 / 255.0 green:248 / 255.0 blue:248 / 255.0 alpha:1.0];

self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(hideImagePicker) name:@"hideImagePicker" object:nil];

//Initialization

CGFloat chatbarHeight = [EaseChatToolbar defaultHeight];

EMChatToolbarType barType = self.conversation.type == EMConversationTypeChat ? EMChatToolbarTypeChat : EMChatToolbarTypeGroup;

self.chatToolbar = [[EaseChatToolbar alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - chatbarHeight - iPhoneX_BOTTOM_HEIGHT, self.view.frame.size.width, chatbarHeight) type:barType];

self.chatToolbar.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;

//Initializa the gesture recognizer

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(keyBoardHidden:)];

[self.view addGestureRecognizer:tap];

_lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];

_lpgr.minimumPressDuration = 0.5;

[self.tableView addGestureRecognizer:_lpgr];

_messageQueue = dispatch_queue_create("hyphenate.com", NULL);

//Register the delegate

[EMCDDeviceManager sharedInstance].delegate = self;

[[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];

[[EMClient sharedClient].roomManager addDelegate:self delegateQueue:nil];

if (self.conversation.type == EMConversationTypeChatRoom)

{

[self joinChatroom:self.conversation.conversationId];

}

[[NSNotificationCenter defaultCenter] addObserver:self

selector:@selector(didBecomeActive)

name:UIApplicationDidBecomeActiveNotification

object:nil];

[[EaseBaseMessageCell appearance] setSendBubbleBackgroundImage:[[UIImage imageNamed:@"EaseUIResource.bundle/chat_sender_bg"] stretchableImageWithLeftCapWidth:5 topCapHeight:35]];

[[EaseBaseMessageCell appearance] setRecvBubbleBackgroundImage:[[UIImage imageNamed:@"EaseUIResource.bundle/chat_receiver_bg"] stretchableImageWithLeftCapWidth:35 topCapHeight:35]];

[[EaseBaseMessageCell appearance] setSendMessageVoiceAnimationImages:@[[UIImage imageNamed:@"EaseUIResource.bundle/chat_sender_audio_playing_full"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_sender_audio_playing_000"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_sender_audio_playing_001"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_sender_audio_playing_002"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_sender_audio_playing_003"]]];

[[EaseBaseMessageCell appearance] setRecvMessageVoiceAnimationImages:@[[UIImage imageNamed:@"EaseUIResource.bundle/chat_receiver_audio_playing_full"],[UIImage imageNamed:@"EaseUIResource.bundle/chat_receiver_audio_playing000"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_receiver_audio_playing001"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_receiver_audio_playing002"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_receiver_audio_playing003"]]];

[[EaseBaseMessageCell appearance] setAvatarSize:40.f];

[[EaseBaseMessageCell appearance] setAvatarCornerRadius:20.f];

[[EaseChatBarMoreView appearance] setMoreViewBackgroundColor:[UIColor colorWithRed:240 / 255.0 green:242 / 255.0 blue:247 / 255.0 alpha:1.0]];

[self tableViewDidTriggerHeaderRefresh];

[self setupEmotion];

self.tableView.estimatedRowHeight = 0;

self.tableView.estimatedSectionHeaderHeight = 0;

self.tableView.estimatedSectionFooterHeight = 0;

}

/*!

@method

@brief 设置表情

@discussion 加载默认表情,如果子类实现了dataSource的自定义表情回调,同时会加载自定义表情

@result

*/

- (void)setupEmotion

{

if ([self.dataSource respondsToSelector:@selector(emotionFormessageViewController:)]) {

NSArray* emotionManagers = [self.dataSource emotionFormessageViewController:self];

[self.faceView setEmotionManagers:emotionManagers];

} else {

NSMutableArray *emotions = [NSMutableArray array];

for (NSString *name in [EaseEmoji allEmoji]) {

EaseEmotion *emotion = [[EaseEmotion alloc] initWithName:@"" emotionId:name emotionThumbnail:name emotionOriginal:name emotionOriginalURL:@"" emotionType:EMEmotionDefault];

[emotions addObject:emotion];

}

EaseEmotion *emotion = [emotions objectAtIndex:0];

EaseEmotionManager *manager= [[EaseEmotionManager alloc] initWithType:EMEmotionDefault emotionRow:3 emotionCol:7 emotions:emotions tagImage:[UIImage imageNamed:emotion.emotionId]];

[self.faceView setEmotionManagers:@[manager]];

}

}

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

- (void)dealloc

{

[[NSNotificationCenter defaultCenter] removeObserver:self];

[[EMCDDeviceManager sharedInstance] stopPlaying];

[EMCDDeviceManager sharedInstance].delegate = nil;

if (_imagePicker){

[_imagePicker dismissViewControllerAnimated:NO completion:nil];

_imagePicker = nil;

}

}

- (void)viewWillAppear:(BOOL)animated

{

[super viewWillAppear:animated];

self.isViewDidAppear = YES;

[[EaseSDKHelper shareHelper] setIsShowingimagePicker:NO];

if (self.scrollToBottomWhenAppear) {

[self _scrollViewToBottom:NO];

}

self.scrollToBottomWhenAppear = YES;

}

- (void)viewWillDisappear:(BOOL)animated

{

[super viewWillDisappear:animated];

self.isViewDidAppear = NO;

[[EMCDDeviceManager sharedInstance] disableProximitySensor];

}

#pragma mark - chatroom

- (void)saveChatroom:(EMChatroom *)chatroom

{

NSString *chatroomName = chatroom.subject ? chatroom.subject : @"";

NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];

NSString *key = [NSString stringWithFormat:@"OnceJoinedChatrooms_%@", [[EMClient sharedClient] currentUsername]];

NSMutableDictionary *chatRooms = [NSMutableDictionary dictionaryWithDictionary:[ud objectForKey:key]];

if (![chatRooms objectForKey:chatroom.chatroomId])

{

[chatRooms setObject:chatroomName forKey:chatroom.chatroomId];

[ud setObject:chatRooms forKey:key];

[ud synchronize];

}

}

/*!

@method

@brief 加入聊天室

@discussion

@result

*/

- (void)joinChatroom:(NSString *)chatroomId

{

__weak typeof(self) weakSelf = self;

[self showHudInView:self.view hint:NSEaseLocalizedString(@"chatroom.joining",@"Joining the chatroom")];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

EMError *error = nil;

EMChatroom *chatroom = [[EMClient sharedClient].roomManager joinChatroom:chatroomId error:&error];

dispatch_async(dispatch_get_main_queue(), ^{

if (weakSelf) {

EaseMessageViewController *strongSelf = weakSelf;

[strongSelf hideHud];

if (error != nil) {

[strongSelf showHint:[NSString stringWithFormat:NSEaseLocalizedString(@"chatroom.joinFailed",@"join chatroom \'%@\' failed"), chatroomId]];

} else {

strongSelf.isJoinedChatroom = YES;

[strongSelf saveChatroom:chatroom];

}

} else {

if (!error || (error.code == EMErrorChatroomAlreadyJoined)) {

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

EMError *leaveError;

[[EMClient sharedClient].roomManager leaveChatroom:chatroomId error:&leaveError];

[[EMClient sharedClient].chatManager deleteConversation:chatroomId isDeleteMessages:YES completion:nil];

});

}

}

});

});

}

#pragma mark - EMChatManagerChatroomDelegate

- (void)didReceiveUserJoinedChatroom:(EMChatroom *)aChatroom

username:(NSString *)aUsername

{

CGRect frame = self.chatToolbar.frame;

[self showHint:[NSString stringWithFormat:NSEaseLocalizedString(@"chatroom.join", @"\'%@\'join chatroom\'%@\'"), aUsername, aChatroom.chatroomId] yOffset:-frame.size.height + KHintAdjustY];

}

- (void)didReceiveUserLeavedChatroom:(EMChatroom *)aChatroom

username:(NSString *)aUsername

{

CGRect frame = self.chatToolbar.frame;

[self showHint:[NSString stringWithFormat:NSEaseLocalizedString(@"chatroom.leave.hint", @"\'%@\'leave chatroom\'%@\'"), aUsername, aChatroom.chatroomId] yOffset:-frame.size.height + KHintAdjustY];

}

- (void)didReceiveKickedFromChatroom:(EMChatroom *)aChatroom

reason:(EMChatroomBeKickedReason)aReason

{

if ([_conversation.conversationId isEqualToString:aChatroom.chatroomId])

{

_isKicked = YES;

CGRect frame = self.chatToolbar.frame;

[self showHint:[NSString stringWithFormat:NSEaseLocalizedString(@"chatroom.remove", @"be removed from chatroom\'%@\'"), aChatroom.chatroomId] yOffset:-frame.size.height + KHintAdjustY];

[self.navigationController popToViewController:self animated:NO];

[self.navigationController popViewControllerAnimated:YES];

}

}

#pragma mark - getter

- (UIImagePickerController *)imagePicker

{

if (_imagePicker == nil) {

_imagePicker = [[UIImagePickerController alloc] init];

_imagePicker.modalPresentationStyle= UIModalPresentationOverFullScreen;

_imagePicker.delegate = self;

}

return _imagePicker;

}

- (NSMutableArray*)atTargets

{

if (!_atTargets) {

_atTargets = [NSMutableArray array];

}

return _atTargets;

}

#pragma mark - setter

- (void)setIsViewDidAppear:(BOOL)isViewDidAppear

{

_isViewDidAppear =isViewDidAppear;

if (_isViewDidAppear)

{

NSMutableArray *unreadMessages = [NSMutableArray array];

for (EMMessage *message in self.messsagesSource)

{

if ([self shouldSendHasReadAckForMessage:message read:NO])

{

[unreadMessages addObject:message];

}

}

if ([unreadMessages count])

{

[self _sendHasReadResponseForMessages:unreadMessages isRead:YES];

}

[_conversation markAllMessagesAsRead:nil];

}

}

- (void)setChatToolbar:(EaseChatToolbar *)chatToolbar

{

[_chatToolbar removeFromSuperview];

_chatToolbar = chatToolbar;

if (_chatToolbar) {

[self.view addSubview:_chatToolbar];

}

CGRect tableFrame = self.tableView.frame;

tableFrame.size.height = self.view.frame.size.height - _chatToolbar.frame.size.height - iPhoneX_BOTTOM_HEIGHT;

self.tableView.frame = tableFrame;

if ([chatToolbar isKindOfClass:[EaseChatToolbar class]]) {

[(EaseChatToolbar *)self.chatToolbar setDelegate:self];

self.chatBarMoreView = (EaseChatBarMoreView*)[(EaseChatToolbar *)self.chatToolbar moreView];

self.faceView = (EaseFaceView*)[(EaseChatToolbar *)self.chatToolbar faceView];

self.recordView = (EaseRecordView*)[(EaseChatToolbar *)self.chatToolbar recordView];

}

}

- (void)setDataSource:(id)dataSource

{

_dataSource = dataSource;

[self setupEmotion];

}

- (void)setDelegate:(id)delegate

{

_delegate = delegate;

}

#pragma mark - private helper

/*!

@method

@brief tableView滑动到底部

@discussion

@result

*/

- (void)_scrollViewToBottom:(BOOL)animated

{

if (self.tableView.contentSize.height > self.tableView.frame.size.height)

{

CGPoint offset = CGPointMake(0, self.tableView.contentSize.height - self.tableView.frame.size.height);

[self.tableView setContentOffset:offset animated:animated];

}

}

/*!

@method

@brief 当前设备是否可以录音

@discussion

@param aCompletion 判断结果

@result

*/

- (void)_canRecordCompletion:(void(^)(EMRecordResponse))aCompletion

{

AVAuthorizationStatus videoAuthStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];

if (videoAuthStatus == AVAuthorizationStatusNotDetermined) {

[[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {

}];

if (aCompletion) {

aCompletion(EMRequestRecord);

}

}

else if(videoAuthStatus == AVAuthorizationStatusRestricted || videoAuthStatus == AVAuthorizationStatusDenied) {

aCompletion(EMCanNotRecord);

}

else{

aCompletion(EMCanRecord);

}

}

- (void)showMenuViewController:(UIView *)showInView

andIndexPath:(NSIndexPath *)indexPath

messageType:(EMMessageBodyType)messageType

{

if (_menuController == nil) {

_menuController = [UIMenuController sharedMenuController];

}

if (_deleteMenuItem == nil) {

_deleteMenuItem = [[UIMenuItem alloc] initWithTitle:NSEaseLocalizedString(@"delete", @"Delete") action:@selector(deleteMenuAction:)];

}

if (_copyMenuItem == nil) {

_copyMenuItem = [[UIMenuItem alloc] initWithTitle:NSEaseLocalizedString(@"copy", @"Copy") action:@selector(copyMenuAction:)];

}

if (messageType == EMMessageBodyTypeText) {

[_menuController setMenuItems:@[_copyMenuItem, _deleteMenuItem]];

} else {

[_menuController setMenuItems:@[_deleteMenuItem]];

}

[_menuController setTargetRect:showInView.frame inView:showInView.superview];

[_menuController setMenuVisible:YES animated:YES];

}

- (void)_stopAudioPlayingWithChangeCategory:(BOOL)isChange

{

//停止音频播放及播放动画

[[EMCDDeviceManager sharedInstance] stopPlaying];

[[EMCDDeviceManager sharedInstance] disableProximitySensor];

[EMCDDeviceManager sharedInstance].delegate = nil;

// MessageModel *playingModel = [self.EaseMessageReadManager stopMessageAudioModel];

// NSIndexPath *indexPath = nil;

// if (playingModel) {

// indexPath = [NSIndexPath indexPathForRow:[self.dataSource indexOfObject:playingModel] inSection:0];

// }

//

// if (indexPath) {

// dispatch_async(dispatch_get_main_queue(), ^{

// [self.tableView beginUpdates];

// [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];

// [self.tableView endUpdates];

// });

// }

}

/*!

@method

@brief mov格式视频转换为MP4格式

@discussion

@param movUrl mov视频路径

@result MP4格式视频路径

*/

- (NSURL *)_convert2Mp4:(NSURL *)movUrl

{

NSURL *mp4Url = nil;

AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:movUrl options:nil];

NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];

if ([compatiblePresets containsObject:AVAssetExportPresetHighestQuality]) {

AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:avAsset

presetName:AVAssetExportPresetHighestQuality];

NSString *mp4Path = [NSString stringWithFormat:@"%@/%d%d.mp4", [EMCDDeviceManager dataPath], (int)[[NSDate date] timeIntervalSince1970], arc4random() % 100000];

mp4Url = [NSURL fileURLWithPath:mp4Path];

exportSession.outputURL = mp4Url;

exportSession.shouldOptimizeForNetworkUse = YES;

exportSession.outputFileType = AVFileTypeMPEG4;

dispatch_semaphore_t wait = dispatch_semaphore_create(0l);

[exportSession exportAsynchronouslyWithCompletionHandler:^{

switch ([exportSession status]) {

case AVAssetExportSessionStatusFailed: {

NSLog(@"failed, error:%@.", exportSession.error);

} break;

case AVAssetExportSessionStatusCancelled: {

NSLog(@"cancelled.");

} break;

case AVAssetExportSessionStatusCompleted: {

NSLog(@"completed.");

} break;

default: {

NSLog(@"others.");

} break;

}

dispatch_semaphore_signal(wait);

}];

long timeout = dispatch_semaphore_wait(wait, DISPATCH_TIME_FOREVER);

if (timeout) {

NSLog(@"timeout.");

}

if (wait) {

//dispatch_release(wait);

wait = nil;

}

}

return mp4Url;

}

/*!

@method

@brief 通过当前会话类型,返回消息聊天类型

@discussion

@result

*/

- (EMChatType)_messageTypeFromConversationType

{

EMChatType type = EMChatTypeChat;

switch (self.conversation.type) {

case EMConversationTypeChat:

type = EMChatTypeChat;

break;

case EMConversationTypeGroupChat:

type = EMChatTypeGroupChat;

break;

case EMConversationTypeChatRoom:

type = EMChatTypeChatRoom;

break;

default:

break;

}

return type;

}

- (void)_customDownloadMessageFile:(EMMessage *)aMessage

{

dispatch_async(dispatch_get_main_queue(), ^{

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:NSLocalizedString(@"message.autoTransfer", @"Please customize the transfer attachment method") delegate:nil cancelButtonTitle:NSLocalizedString(@"sure", @"OK") otherButtonTitles:nil, nil];

[alertView show];

});

}

/*!

@method

@brief 下载消息附件

@discussion

@param message 待下载附件的消息

@result

*/

- (void)_downloadMessageAttachments:(EMMessage *)message

{

__weak typeof(self) weakSelf = self;

void (^completion)(EMMessage *aMessage, EMError *error) = ^(EMMessage *aMessage, EMError *error) {

if (!error)

{

[weakSelf _reloadTableViewDataWithMessage:message];

}

else

{

[weakSelf showHint:NSEaseLocalizedString(@"message.thumImageFail", @"thumbnail for failure!")];

}

};

// BOOL isCustomDownload = !([EMClient sharedClient].options.isAutoTransferMessageAttachments);

// BOOL isAutoDownloadThumbnail = ([EMClient sharedClient].options.isAutoDownloadThumbnail);

EMMessageBody *messageBody = message.body;

if ([messageBody type] == EMMessageBodyTypeImage) {

EMImageMessageBody *imageBody = (EMImageMessageBody *)messageBody;

if (imageBody.thumbnailDownloadStatus > EMDownloadStatusSuccessed)

{

//download the message thumbnail

// if (isCustomDownload) {

// [self _customDownloadMessageFile:message];

// } else {

// if (isAutoDownloadThumbnail) {

[[[EMClient sharedClient] chatManager] downloadMessageThumbnail:message progress:nil completion:completion];

// }

// }

}

}

else if ([messageBody type] == EMMessageBodyTypeVideo)

{

EMVideoMessageBody *videoBody = (EMVideoMessageBody *)messageBody;

if (videoBody.thumbnailDownloadStatus > EMDownloadStatusSuccessed)

{

//download the message thumbnail

// if (isCustomDownload) {

// [self _customDownloadMessageFile:message];

// } else {

// if (isAutoDownloadThumbnail) {

[[[EMClient sharedClient] chatManager] downloadMessageThumbnail:message progress:nil completion:completion];

// }

// }

}

}

else if ([messageBody type] == EMMessageBodyTypeVoice)

{

EMVoiceMessageBody *voiceBody = (EMVoiceMessageBody*)messageBody;

if (voiceBody.downloadStatus > EMDownloadStatusSuccessed)

{

//download the message attachment

// if (isCustomDownload) {

// [self _customDownloadMessageFile:message];

// } else {

// if (isAutoDownloadThumbnail) {

[[EMClient sharedClient].chatManager downloadMessageAttachment:message progress:nil completion:^(EMMessage *message, EMError *error) {

if (!error) {

[weakSelf _reloadTableViewDataWithMessage:message];

}

else {

[weakSelf showHint:NSEaseLocalizedString(@"message.voiceFail", @"voice for failure!")];

}

}];

// }

// }

}

}

}

/*!

@method

@brief 传入消息是否需要发动已读回执

@discussion

@param message 待判断的消息

@param read 消息是否已读

@result

*/

- (BOOL)shouldSendHasReadAckForMessage:(EMMessage *)message

read:(BOOL)read

{

if (message.chatType != EMChatTypeChat || message.isReadAcked || message.direction == EMMessageDirectionSend || ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) || !self.isViewDidAppear)

{

return NO;

}

EMMessageBody *body = message.body;

if (((body.type == EMMessageBodyTypeVideo) ||

(body.type == EMMessageBodyTypeVoice) ||

(body.type == EMMessageBodyTypeImage)) &&

!read)

{

return NO;

}

else

{

return YES;

}

}

/*!

@method

@brief 为传入的消息发送已读回执

@discussion

@param messages 待发送已读回执的消息数组

@param isRead 是否已读

@result

*/

- (void)_sendHasReadResponseForMessages:(NSArray*)messages

isRead:(BOOL)isRead

{

NSMutableArray *unreadMessages = [NSMutableArray array];

for (NSInteger i = 0; i < [messages count]; i++)

{

EMMessage *message = messages[i];

BOOL isSend = YES;

if (_dataSource && [_dataSource respondsToSelector:@selector(messageViewController:shouldSendHasReadAckForMessage:read:)]) {

isSend = [_dataSource messageViewController:self

shouldSendHasReadAckForMessage:message read:isRead];

}

else{

isSend = [self shouldSendHasReadAckForMessage:message

read:isRead];

}

if (isSend)

{

[unreadMessages addObject:message];

}

}

if ([unreadMessages count])

{

for (EMMessage *message in unreadMessages)

{

[[EMClient sharedClient].chatManager sendMessageReadAck:message completion:nil];

}

}

}

- (BOOL)_shouldMarkMessageAsRead

{

BOOL isMark = YES;

if (_dataSource && [_dataSource respondsToSelector:@selector(messageViewControllerShouldMarkMessagesAsRead:)]) {

isMark = [_dataSource messageViewControllerShouldMarkMessagesAsRead:self];

}

else{

if (([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) || !self.isViewDidAppear)

{

isMark = NO;

}

}

return isMark;

}

/*!

@method

@brief 位置消息被点击选择

@discussion

@param model 消息model

@result

*/

- (void)_locationMessageCellSelected:(id)model

{

_scrollToBottomWhenAppear = NO;

EaseLocationViewController *locationController = [[EaseLocationViewController alloc] initWithLocation:CLLocationCoordinate2DMake(model.latitude, model.longitude)];

[self.navigationController pushViewController:locationController animated:YES];

}

/*!

@method

@brief 视频消息被点击选择

@discussion

@param model 消息model

@result

*/

- (void)_videoMessageCellSelected:(id)model

{

_scrollToBottomWhenAppear = NO;

EMVideoMessageBody *videoBody = (EMVideoMessageBody*)model.message.body;

NSString *localPath = [model.fileLocalPath length] > 0 ? model.fileLocalPath : videoBody.localPath;

if ([localPath length] == 0) {

[self showHint:NSEaseLocalizedString(@"message.videoFail", @"video for failure!")];

return;

}

dispatch_block_t block = ^{

//send the acknowledgement

[self _sendHasReadResponseForMessages:@[model.message]

isRead:YES];

NSURL *videoURL = [NSURL fileURLWithPath:localPath];

MPMoviePlayerViewController *moviePlayerController = [[MPMoviePlayerViewController alloc] initWithContentURL:videoURL];

[moviePlayerController.moviePlayer prepareToPlay];

moviePlayerController.moviePlayer.movieSourceType = MPMovieSourceTypeFile;

[self presentMoviePlayerViewControllerAnimated:moviePlayerController];

};

// BOOL isCustomDownload = !([EMClient sharedClient].options.isAutoTransferMessageAttachments);

__weak typeof(self) weakSelf = self;

void (^completion)(EMMessage *aMessage, EMError *error) = ^(EMMessage *aMessage, EMError *error) {

if (!error)

{

[weakSelf _reloadTableViewDataWithMessage:aMessage];

}

else

{

[weakSelf showHint:NSEaseLocalizedString(@"message.thumImageFail", @"thumbnail for failure!")];

}

};

if (videoBody.thumbnailDownloadStatus == EMDownloadStatusFailed || ![[NSFileManager defaultManager] fileExistsAtPath:videoBody.thumbnailLocalPath]) {

[self showHint:@"begin downloading thumbnail image, click later"];

// if (isCustomDownload) {

// [self _customDownloadMessageFile:model.message];

// } else {

[[EMClient sharedClient].chatManager downloadMessageThumbnail:model.message progress:nil completion:completion];

// }

return;

}

if (videoBody.downloadStatus == EMDownloadStatusSuccessed && [[NSFileManager defaultManager] fileExistsAtPath:localPath])

{

block();

return;

}

[self showHudInView:self.view hint:NSEaseLocalizedString(@"message.downloadingVideo", @"downloading video...")];

// if (isCustomDownload) {

// [self _customDownloadMessageFile:model.message];

// } else {

[[EMClient sharedClient].chatManager downloadMessageAttachment:model.message progress:nil completion:^(EMMessage *message, EMError *error) {

[weakSelf hideHud];

if (!error) {

block();

}else{

[weakSelf showHint:NSEaseLocalizedString(@"message.videoFail", @"video for failure!")];

}

}];

// }

}

/*!

@method

@brief 图片消息被点击选择

@discussion

@param model 消息model

@result

*/

- (void)_imageMessageCellSelected:(id)model

{

__weak EaseMessageViewController *weakSelf = self;

EMImageMessageBody *imageBody = (EMImageMessageBody*)[model.message body];

// BOOL isCustomDownload = !([EMClient sharedClient].options.isAutoTransferMessageAttachments);

if ([imageBody type] == EMMessageBodyTypeImage) {

if (imageBody.thumbnailDownloadStatus == EMDownloadStatusSuccessed) {

if (imageBody.downloadStatus == EMDownloadStatusSuccessed)

{

//send the acknowledgement

[weakSelf _sendHasReadResponseForMessages:@[model.message] isRead:YES];

NSString *localPath = model.message == nil ? model.fileLocalPath : [imageBody localPath];

if (localPath && localPath.length > 0) {

UIImage *image = [UIImage imageWithContentsOfFile:localPath];

if (image) {

[[EaseMessageReadManager defaultManager] showBrowserWithImages:@[image]];

return;

}

}

}

[weakSelf showHudInView:weakSelf.view hint:NSEaseLocalizedString(@"message.downloadingImage", @"downloading a image...")];

void (^completion)(EMMessage *aMessage, EMError *error) = ^(EMMessage *aMessage, EMError *error) {

[weakSelf hideHud];

if (!error) {

//send the acknowledgement

[weakSelf _sendHasReadResponseForMessages:@[model.message] isRead:YES];

NSString *localPath = aMessage == nil ? model.fileLocalPath : [(EMImageMessageBody*)aMessage.body localPath];

if (localPath && localPath.length > 0) {

UIImage *image = [UIImage imageWithContentsOfFile:localPath];

// weakSelf.isScrollToBottom = NO;

if (image)

{

[[EaseMessageReadManager defaultManager] showBrowserWithImages:@[image]];

}

else

{

NSLog(@"Read %@ failed!", localPath);

}

return ;

}

}

[weakSelf showHint:NSEaseLocalizedString(@"message.imageFail", @"image for failure!")];

};

// if (isCustomDownload) {

// [self _customDownloadMessageFile:model.message];

// } else {

[[EMClient sharedClient].chatManager downloadMessageAttachment:model.message progress:nil completion:completion];

// }

}else{

//get the message thumbnail

// if (isCustomDownload) {

// [self _customDownloadMessageFile:model.message];

// } else {

[[EMClient sharedClient].chatManager downloadMessageThumbnail:model.message progress:nil completion:^(EMMessage *message, EMError *error) {

if (!error) {

[weakSelf _reloadTableViewDataWithMessage:model.message];

}else{

[weakSelf showHint:NSEaseLocalizedString(@"message.thumImageFail", @"thumbnail for failure!")];

}

}];

// }

}

}

}

/*!

@method

@brief 语音消息被点击选择

@discussion

@param model 消息model

@result

*/

- (void)_audioMessageCellSelected:(id)model

{

_scrollToBottomWhenAppear = NO;

EMVoiceMessageBody *body = (EMVoiceMessageBody*)model.message.body;

EMDownloadStatus downloadStatus = [body downloadStatus];

if (downloadStatus == EMDownloadStatusDownloading) {

[self showHint:NSEaseLocalizedString(@"message.downloadingAudio", @"downloading voice, click later")];

return;

}

else if (downloadStatus == EMDownloadStatusFailed || downloadStatus == EMDownloadStatusPending)

{

[self showHint:NSEaseLocalizedString(@"message.downloadingAudio", @"downloading voice, click later")];

// BOOL isCustomDownload = !([EMClient sharedClient].options.isAutoTransferMessageAttachments);

// if (isCustomDownload) {

// [self _customDownloadMessageFile:model.message];

// } else {

[[EMClient sharedClient].chatManager downloadMessageAttachment:model.message progress:nil completion:nil];

// }

return;

}

// play the audio

if (model.bodyType == EMMessageBodyTypeVoice) {

//send the acknowledgement

[self _sendHasReadResponseForMessages:@[model.message] isRead:YES];

__weak EaseMessageViewController *weakSelf = self;

BOOL isPrepare = [[EaseMessageReadManager defaultManager] prepareMessageAudioModel:model updateViewCompletion:^(EaseMessageModel *prevAudioModel, EaseMessageModel *currentAudioModel) {

if (prevAudioModel || currentAudioModel) {

[weakSelf.tableView reloadData];

}

}];

if (isPrepare) {

_isPlayingAudio = YES;

__weak EaseMessageViewController *weakSelf = self;

[[EMCDDeviceManager sharedInstance] enableProximitySensor];

[[EMCDDeviceManager sharedInstance] asyncPlayingWithPath:model.fileLocalPath completion:^(NSError *error) {

[[EaseMessageReadManager defaultManager] stopMessageAudioModel];

dispatch_async(dispatch_get_main_queue(), ^{

[weakSelf.tableView reloadData];

weakSelf.isPlayingAudio = NO;

[[EMCDDeviceManager sharedInstance] disableProximitySensor];

});

}];

}

else{

_isPlayingAudio = NO;

}

}

}

#pragma mark - pivate data

/*!

@method

@brief 加载历史消息

@discussion

@param messageId 参考消息的ID

@param count 获取条数

@param isAppend 是否在dataArray直接添加

@result

*/

- (void)_loadMessagesBefore:(NSString*)messageId

count:(NSInteger)count

append:(BOOL)isAppend

{

__weak typeof(self) weakSelf = self;

void (^refresh)(NSArray *messages) = ^(NSArray *messages) {

dispatch_async(_messageQueue, ^{

//Format the message

NSArray *formattedMessages = [weakSelf formatMessages:messages];

//Refresh the page

dispatch_async(dispatch_get_main_queue(), ^{

EaseMessageViewController *strongSelf = weakSelf;

if (strongSelf) {

NSInteger scrollToIndex = 0;

if (isAppend) {

[strongSelf.messsagesSource insertObjects:messages atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [messages count])]];

//Combine the message

id object = [strongSelf.dataArray firstObject];

if ([object isKindOfClass:[NSString class]]) {

NSString *timestamp = object;

[formattedMessages enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id model, NSUInteger idx, BOOL *stop) {

if ([model isKindOfClass:[NSString class]] && [timestamp isEqualToString:model]) {

[strongSelf.dataArray removeObjectAtIndex:0];

*stop = YES;

}

}];

}

scrollToIndex = [strongSelf.dataArray count];

[strongSelf.dataArray insertObjects:formattedMessages atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [formattedMessages count])]];

}

else {

[strongSelf.messsagesSource removeAllObjects];

[strongSelf.messsagesSource addObjectsFromArray:messages];

[strongSelf.dataArray removeAllObjects];

[strongSelf.dataArray addObjectsFromArray:formattedMessages];

}

EMMessage *latest = [strongSelf.messsagesSource lastObject];

strongSelf.messageTimeIntervalTag = latest.timestamp;

[strongSelf.tableView reloadData];

[strongSelf.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[self.dataArray count] - scrollToIndex - 1 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];

}

});

//re-download all messages that are not successfully downloaded

for (EMMessage *message in messages)

{

[weakSelf _downloadMessageAttachments:message];

}

//send the read acknoledgement

[weakSelf _sendHasReadResponseForMessages:messages

isRead:NO];

});

};

[self.conversation loadMessagesStartFromId:messageId count:(int)count searchDirection:EMMessageSearchDirectionUp completion:^(NSArray *aMessages, EMError *aError) {

if (!aError && [aMessages count]) {

refresh(aMessages);

}

}];

}

#pragma mark - GestureRecognizer

-(void)keyBoardHidden:(UITapGestureRecognizer *)tapRecognizer

{

if (tapRecognizer.state == UIGestureRecognizerStateEnded) {

[self.chatToolbar endEditing:YES];

}

}

- (void)handleLongPress:(UILongPressGestureRecognizer *)recognizer

{

if (recognizer.state == UIGestureRecognizerStateBegan && [self.dataArray count] > 0)

{

CGPoint location = [recognizer locationInView:self.tableView];

NSIndexPath * indexPath = [self.tableView indexPathForRowAtPoint:location];

BOOL canLongPress = NO;

if (_dataSource && [_dataSource respondsToSelector:@selector(messageViewController:canLongPressRowAtIndexPath:)]) {

canLongPress = [_dataSource messageViewController:self

canLongPressRowAtIndexPath:indexPath];

}

if (!canLongPress) {

return;

}

if (_dataSource && [_dataSource respondsToSelector:@selector(messageViewController:didLongPressRowAtIndexPath:)]) {

[_dataSource messageViewController:self

didLongPressRowAtIndexPath:indexPath];

}

else{

id object = [self.dataArray objectAtIndex:indexPath.row];

if (![object isKindOfClass:[NSString class]]) {

EaseMessageCell *cell = (EaseMessageCell *)[self.tableView cellForRowAtIndexPath:indexPath];

[cell becomeFirstResponder];

_menuIndexPath = indexPath;

[self showMenuViewController:cell.bubbleView andIndexPath:indexPath messageType:cell.model.bodyType];

}

}

}

}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

{

// Return the number of sections.

return 1;

}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

// Return the number of rows in the section.

return [self.dataArray count];

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

id object = [self.dataArray objectAtIndex:indexPath.row];

//time cell

if ([object isKindOfClass:[NSString class]]) {

NSString *TimeCellIdentifier = [EaseMessageTimeCell cellIdentifier];

EaseMessageTimeCell *timeCell = (EaseMessageTimeCell *)[tableView dequeueReusableCellWithIdentifier:TimeCellIdentifier];

if (timeCell == nil) {

timeCell = [[EaseMessageTimeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TimeCellIdentifier];

timeCell.selectionStyle = UITableViewCellSelectionStyleNone;

}

timeCell.title = object;

return timeCell;

}

id model = object;

if (_delegate && [_delegate respondsToSelector:@selector(messageViewController:cellForMessageModel:)]) {

UITableViewCell *cell = [_delegate messageViewController:tableView cellForMessageModel:model];

if (cell) {

if ([cell isKindOfClass:[EaseMessageCell class]]) {

EaseMessageCell *emcell= (EaseMessageCell*)cell;

if (emcell.delegate == nil) {

emcell.delegate = self;

}

}

return cell;

}

}

if (_dataSource && [_dataSource respondsToSelector:@selector(isEmotionMessageFormessageViewController:messageModel:)]) {

BOOL flag = [_dataSource isEmotionMessageFormessageViewController:self messageModel:model];

if (flag) {

NSString *CellIdentifier = [EaseCustomMessageCell cellIdentifierWithModel:model];

//send cell

EaseCustomMessageCell *sendCell = (EaseCustomMessageCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

// Configure the cell...

if (sendCell == nil) {

sendCell = [[EaseCustomMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier model:model];

sendCell.selectionStyle = UITableViewCellSelectionStyleNone;

}

if (_dataSource && [_dataSource respondsToSelector:@selector(emotionURLFormessageViewController:messageModel:)]) {

EaseEmotion *emotion = [_dataSource emotionURLFormessageViewController:self messageModel:model];

if (emotion) {

model.image = [UIImage sd_animatedGIFNamed:emotion.emotionOriginal];

model.fileURLPath = emotion.emotionOriginalURL;

}

}

sendCell.model = model;

sendCell.delegate = self;

return sendCell;

}

}

NSString *CellIdentifier = [EaseMessageCell cellIdentifierWithModel:model];

EaseBaseMessageCell *sendCell = (EaseBaseMessageCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

// Configure the cell...

if (sendCell == nil) {

sendCell = [[EaseBaseMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier model:model];

sendCell.selectionStyle = UITableViewCellSelectionStyleNone;

sendCell.delegate = self;

}

sendCell.model = model;

return sendCell;

}

#pragma mark - Table view delegate

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

id object = [self.dataArray objectAtIndex:indexPath.row];

if ([object isKindOfClass:[NSString class]]) {

return self.timeCellHeight;

}

else{

id model = object;

if (_delegate && [_delegate respondsToSelector:@selector(messageViewController:heightForMessageModel:withCellWidth:)]) {

CGFloat height = [_delegate messageViewController:self heightForMessageModel:model withCellWidth:tableView.frame.size.width];

if (height) {

return height;

}

}

if (_dataSource && [_dataSource respondsToSelector:@selector(isEmotionMessageFormessageViewController:messageModel:)]) {

BOOL flag = [_dataSource isEmotionMessageFormessageViewController:self messageModel:model];

if (flag) {

return [EaseCustomMessageCell cellHeightWithModel:model];

}

}

return [EaseBaseMessageCell cellHeightWithModel:model];

}

}

#pragma mark - UIImagePickerControllerDelegate

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

{

NSString *mediaType = info[UIImagePickerControllerMediaType];

if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]) {

NSURL *videoURL = info[UIImagePickerControllerMediaURL];

// video url:

// file:///private/var/mobile/Applications/B3CDD0B2-2F19-432B-9CFA-158700F4DE8F/tmp/capture-T0x16e39100.tmp.9R8weF/capturedvideo.mp4

// we will convert it to mp4 format

NSURL *mp4 = [self _convert2Mp4:videoURL];

NSFileManager *fileman = [NSFileManager defaultManager];

if ([fileman fileExistsAtPath:videoURL.path]) {

NSError *error = nil;

[fileman removeItemAtURL:videoURL error:&error];

if (error) {

NSLog(@"failed to remove file, error:%@.", error);

}

}

[self sendVideoMessageWithURL:mp4];

}else{

NSURL *url = info[UIImagePickerControllerReferenceURL];

if (url == nil) {

UIImage *orgImage = info[UIImagePickerControllerOriginalImage];

[self sendImageMessage:orgImage];

} else {

if ([[UIDevice currentDevice].systemVersion doubleValue] >= 9.0f) {

PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:@[url] options:nil];

[result enumerateObjectsUsingBlock:^(PHAsset *asset , NSUInteger idx, BOOL *stop){

if (asset) {

[[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData *data, NSString *uti, UIImageOrientation orientation, NSDictionary *dic){

if (data != nil) {

[self sendImageMessageWithData:data];

} else {

[self showHint:NSEaseLocalizedString(@"message.smallerImage", @"The image size is too large, please choose another one")];

}

}];

}

}];

} else {

ALAssetsLibrary *alasset = [[ALAssetsLibrary alloc] init];

[alasset assetForURL:url resultBlock:^(ALAsset *asset) {

if (asset) {

ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];

Byte* buffer = (Byte*)malloc((size_t)[assetRepresentation size]);

NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:0.0 length:(NSUInteger)[assetRepresentation size] error:nil];

NSData* fileData = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];

[self sendImageMessageWithData:fileData];

}

} failureBlock:NULL];

}

}

}

[picker dismissViewControllerAnimated:YES completion:nil];

self.isViewDidAppear = YES;

[[EaseSDKHelper shareHelper] setIsShowingimagePicker:NO];

}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker

{

[self.imagePicker dismissViewControllerAnimated:YES completion:nil];

self.isViewDidAppear = YES;

[[EaseSDKHelper shareHelper] setIsShowingimagePicker:NO];

}

#pragma mark - EaseMessageCellDelegate

- (void)messageCellSelected:(id)model

{

if (_delegate && [_delegate respondsToSelector:@selector(messageViewController:didSelectMessageModel:)]) {

BOOL flag = [_delegate messageViewController:self didSelectMessageModel:model];

if (flag) {

[self _sendHasReadResponseForMessages:@[model.message] isRead:YES];

return;

}

}

switch (model.bodyType) {

case EMMessageBodyTypeImage:

{

_scrollToBottomWhenAppear = NO;

[self _imageMessageCellSelected:model];

}

break;

case EMMessageBodyTypeLocation:

{

[self _locationMessageCellSelected:model];

}

break;

case EMMessageBodyTypeVoice:

{

[self _audioMessageCellSelected:model];

}

break;

case EMMessageBodyTypeVideo:

{

[self _videoMessageCellSelected:model];

}

break;

case EMMessageBodyTypeFile:

{

_scrollToBottomWhenAppear = NO;

[self showHint:@"Custom implementation!"];

}

break;

default:

break;

}

}

- (void)statusButtonSelcted:(id)model withMessageCell:(EaseMessageCell*)messageCell

{

if ((model.messageStatus != EMMessageStatusFailed) && (model.messageStatus != EMMessageStatusPending))

{

return;

}

__weak typeof(self) weakself = self;

[[[EMClient sharedClient] chatManager] resendMessage:model.message progress:nil completion:^(EMMessage *message, EMError *error) {

if (!error) {

SGUserModel *userModel = [SGUserInfo getUserInfo];

NSDictionary *dic = @{@"easemobuserId":userModel.hx_user_name,@"userName":[BHSettingUtil dataAndStringIsNull:userModel.company_name]?@"":userModel.company_name,@"logo":userModel.logo};

[[ContactDataObject shareInstance]insertData:dic];

[weakself _refreshAfterSentMessage:message];

}

else {

[weakself.tableView reloadData];

}

}];

[self.tableView reloadData];

}

- (void)avatarViewSelcted:(id)model

{

if (_delegate && [_delegate respondsToSelector:@selector(messageViewController:didSelectAvatarMessageModel:)]) {

[_delegate messageViewController:self didSelectAvatarMessageModel:model];

return;

}

_scrollToBottomWhenAppear = NO;

}

#pragma mark - EMChatToolbarDelegate

- (void)chatToolbarDidChangeFrameToHeight:(CGFloat)toHeight

{

[UIView animateWithDuration:0.3 animations:^{

CGRect rect = self.tableView.frame;

rect.origin.y = 0;

rect.size.height = self.view.frame.size.height - toHeight - iPhoneX_BOTTOM_HEIGHT;

self.tableView.frame = rect;

}];

[self _scrollViewToBottom:NO];

}

- (void)inputTextViewWillBeginEditing:(EaseTextView *)inputTextView

{

if (_menuController == nil) {

_menuController = [UIMenuController sharedMenuController];

}

[_menuController setMenuItems:nil];

}

- (void)didSendText:(NSString *)text

{

if (text && text.length > 0) {

[self sendTextMessage:text];

[self.atTargets removeAllObjects];

}

}

- (BOOL)didInputAtInLocation:(NSUInteger)location

{

if ([self.delegate respondsToSelector:@selector(messageViewController:selectAtTarget:)] && self.conversation.type == EMConversationTypeGroupChat) {

location += 1;

__weak typeof(self) weakSelf = self;

[self.delegate messageViewController:self selectAtTarget:^(EaseAtTarget *target) {

__strong EaseMessageViewController *strongSelf = weakSelf;

if (strongSelf && target) {

if ([target.userId length] || [target.nickname length]) {

[strongSelf.atTargets addObject:target];

NSString *insertStr = [NSString stringWithFormat:@"%@ ", target.nickname ? target.nickname : target.userId];

EaseChatToolbar *toolbar = (EaseChatToolbar*)strongSelf.chatToolbar;

NSMutableString *originStr = [toolbar.inputTextView.text mutableCopy];

NSUInteger insertLocation = location > originStr.length ? originStr.length : location;

[originStr insertString:insertStr atIndex:insertLocation];

toolbar.inputTextView.text = originStr;

toolbar.inputTextView.selectedRange = NSMakeRange(insertLocation + insertStr.length, 0);

[toolbar.inputTextView becomeFirstResponder];

}

}

else if (strongSelf) {

EaseChatToolbar *toolbar = (EaseChatToolbar*)strongSelf.chatToolbar;

[toolbar.inputTextView becomeFirstResponder];

}

}];

EaseChatToolbar *toolbar = (EaseChatToolbar*)self.chatToolbar;

toolbar.inputTextView.text = [NSString stringWithFormat:@"%@@", toolbar.inputTextView.text];

[toolbar.inputTextView resignFirstResponder];

return YES;

}

else {

return NO;

}

}

- (BOOL)didDeleteCharacterFromLocation:(NSUInteger)location

{

EaseChatToolbar *toolbar = (EaseChatToolbar*)self.chatToolbar;

if ([toolbar.inputTextView.text length] == location + 1) {

//delete last character

NSString *inputText = toolbar.inputTextView.text;

NSRange range = [inputText rangeOfString:@"@" options:NSBackwardsSearch];

if (range.location != NSNotFound) {

if (location - range.location > 1) {

NSString *sub = [inputText substringWithRange:NSMakeRange(range.location + 1, location - range.location - 1)];

for (EaseAtTarget *target in self.atTargets) {

if ([sub isEqualToString:target.userId] || [sub isEqualToString:target.nickname]) {

inputText = range.location > 0 ? [inputText substringToIndex:range.location] : @"";

toolbar.inputTextView.text = inputText;

toolbar.inputTextView.selectedRange = NSMakeRange(inputText.length, 0);

[self.atTargets removeObject:target];

return YES;

}

}

}

}

}

return NO;

}

- (void)didSendText:(NSString *)text withExt:(NSDictionary*)ext

{

if ([ext objectForKey:EASEUI_EMOTION_DEFAULT_EXT]) {

EaseEmotion *emotion = [ext objectForKey:EASEUI_EMOTION_DEFAULT_EXT];

if (self.dataSource && [self.dataSource respondsToSelector:@selector(emotionExtFormessageViewController:easeEmotion:)]) {

NSDictionary *ext = [self.dataSource emotionExtFormessageViewController:self easeEmotion:emotion];

[self sendTextMessage:emotion.emotionTitle withExt:ext];

} else {

[self sendTextMessage:emotion.emotionTitle withExt:@{MESSAGE_ATTR_EXPRESSION_ID:emotion.emotionId,MESSAGE_ATTR_IS_BIG_EXPRESSION:@(YES)}];

}

return;

}

if (text && text.length > 0) {

[self sendTextMessage:text withExt:ext];

}

}

- (void)didStartRecordingVoiceAction:(UIView *)recordView

{

__weak typeof(self) weakSelf = self;

[self _canRecordCompletion:^(EMRecordResponse recordResponse) {

switch (recordResponse) {

case EMRequestRecord:

break;

case EMCanRecord:

{

if ([weakSelf.delegate respondsToSelector:@selector(messageViewController:didSelectRecordView:withEvenType:)]) {

[weakSelf.delegate messageViewController:weakSelf

didSelectRecordView:recordView

withEvenType:EaseRecordViewTypeTouchDown];

} else {

if ([weakSelf.recordView isKindOfClass:[EaseRecordView class]]) {

[(EaseRecordView *)weakSelf.recordView recordButtonTouchDown];

}

}

_isRecording = YES;

EaseRecordView *tmpView = (EaseRecordView *)recordView;

tmpView.center = self.view.center;

[weakSelf.view addSubview:tmpView];

[weakSelf.view bringSubviewToFront:recordView];

int x = arc4random() % 100000;

NSTimeInterval time = [[NSDate date] timeIntervalSince1970];

NSString *fileName = [NSString stringWithFormat:@"%d%d",(int)time,x];

[[EMCDDeviceManager sharedInstance] asyncStartRecordingWithFileName:fileName completion:^(NSError *error)

{

if (error) {

NSLog(@"%@",NSEaseLocalizedString(@"message.startRecordFail", @"failure to start recording"));

_isRecording = NO;

}

}];

}

break;

case EMCanNotRecord:

{

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"prompt", @"Prompt") message:NSLocalizedString(@"record.failToPermission", @"No recording permission") delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil, nil];

[alertView show];

}

break;

default:

break;

}

}];

}

- (void)didCancelRecordingVoiceAction:(UIView *)recordView

{

if(_isRecording) {

[[EMCDDeviceManager sharedInstance] cancelCurrentRecording];

if ([self.delegate respondsToSelector:@selector(messageViewController:didSelectRecordView:withEvenType:)]) {

[self.delegate messageViewController:self didSelectRecordView:recordView withEvenType:EaseRecordViewTypeTouchUpOutside];

} else {

if ([self.recordView isKindOfClass:[EaseRecordView class]]) {

[(EaseRecordView *)self.recordView recordButtonTouchUpOutside];

}

[self.recordView removeFromSuperview];

}

_isRecording = NO;

}

}

- (void)didFinishRecoingVoiceAction:(UIView *)recordView

{

if (_isRecording) {

if ([self.delegate respondsToSelector:@selector(messageViewController:didSelectRecordView:withEvenType:)]) {

[self.delegate messageViewController:self didSelectRecordView:recordView withEvenType:EaseRecordViewTypeTouchUpInside];

} else {

if ([self.recordView isKindOfClass:[EaseRecordView class]]) {

[(EaseRecordView *)self.recordView recordButtonTouchUpInside];

}

[self.recordView removeFromSuperview];

}

__weak typeof(self) weakSelf = self;

[[EMCDDeviceManager sharedInstance] asyncStopRecordingWithCompletion:^(NSString *recordPath, NSInteger aDuration, NSError *error) {

if (!error) {

[weakSelf sendVoiceMessageWithLocalPath:recordPath duration:aDuration];

}

else {

[weakSelf showHudInView:self.view hint:error.domain];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

[weakSelf hideHud];

});

}

}];

_isRecording = NO;

}

}

- (void)didDragInsideAction:(UIView *)recordView

{

if ([self.delegate respondsToSelector:@selector(messageViewController:didSelectRecordView:withEvenType:)]) {

[self.delegate messageViewController:self didSelectRecordView:recordView withEvenType:EaseRecordViewTypeDragInside];

} else {

if ([self.recordView isKindOfClass:[EaseRecordView class]]) {

[(EaseRecordView *)self.recordView recordButtonDragInside];

}

}

}

- (void)didDragOutsideAction:(UIView *)recordView

{

if ([self.delegate respondsToSelector:@selector(messageViewController:didSelectRecordView:withEvenType:)]) {

[self.delegate messageViewController:self didSelectRecordView:recordView withEvenType:EaseRecordViewTypeDragOutside];

} else {

if ([self.recordView isKindOfClass:[EaseRecordView class]]) {

[(EaseRecordView *)self.recordView recordButtonDragOutside];

}

}

}

#pragma mark - EaseChatBarMoreViewDelegate

- (void)moreView:(EaseChatBarMoreView *)moreView didItemInMoreViewAtIndex:(NSInteger)index

{

if ([self.delegate respondsToSelector:@selector(messageViewController:didSelectMoreView:AtIndex:)]) {

[self.delegate messageViewController:self didSelectMoreView:moreView AtIndex:index];

return;

}

}

- (void)moreViewPhotoAction:(EaseChatBarMoreView *)moreView

{

// Hide the keyboard

[self.chatToolbar endEditing:YES];

// Pop image picker

self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

self.imagePicker.mediaTypes = @[(NSString *)kUTTypeImage];

[self presentViewController:self.imagePicker animated:YES completion:NULL];

self.isViewDidAppear = NO;

[[EaseSDKHelper shareHelper] setIsShowingimagePicker:YES];

}

- (void)moreViewTakePicAction:(EaseChatBarMoreView *)moreView

{

// Hide the keyboard

[self.chatToolbar endEditing:YES];

#if TARGET_IPHONE_SIMULATOR

[self showHint:NSEaseLocalizedString(@"message.simulatorNotSupportCamera", @"simulator does not support taking picture")];

#elif TARGET_OS_IPHONE

self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;

self.imagePicker.mediaTypes = @[(NSString *)kUTTypeImage,(NSString *)kUTTypeMovie];

[self presentViewController:self.imagePicker animated:YES completion:NULL];

self.isViewDidAppear = NO;

[[EaseSDKHelper shareHelper] setIsShowingimagePicker:YES];

#endif

}

- (void)moreViewLocationAction:(EaseChatBarMoreView *)moreView

{

// Hide the keyboard

[self.chatToolbar endEditing:YES];

EaseLocationViewController *locationController = [[EaseLocationViewController alloc] init];

locationController.delegate = self;

[self.navigationController pushViewController:locationController animated:YES];

}

- (void)moreViewAudioCallAction:(EaseChatBarMoreView *)moreView

{

// Hide the keyboard

[self.chatToolbar endEditing:YES];

[[NSNotificationCenter defaultCenter] postNotificationName:KNOTIFICATION_CALL object:@{@"chatter":self.conversation.conversationId, @"type":[NSNumber numberWithInt:0]}];

}

- (void)moreViewVideoCallAction:(EaseChatBarMoreView *)moreView

{

// Hide the keyboard

[self.chatToolbar endEditing:YES];

[[NSNotificationCenter defaultCenter] postNotificationName:KNOTIFICATION_CALL object:@{@"chatter":self.conversation.conversationId, @"type":[NSNumber numberWithInt:1]}];

}

#pragma mark - EMLocationViewDelegate

-(void)sendLocationLatitude:(double)latitude

longitude:(double)longitude

andAddress:(NSString *)address

{

[self sendLocationMessageLatitude:latitude longitude:longitude andAddress:address];

}

#pragma mark - Hyphenate

#pragma mark - EMChatManagerDelegate

- (void)messagesDidReceive:(NSArray *)aMessages

{

for (EMMessage *message in aMessages) {

if ([self.conversation.conversationId isEqualToString:message.conversationId]) {

[self addMessageToDataSource:message progress:nil];

[self _sendHasReadResponseForMessages:@[message]

isRead:NO];

if ([self _shouldMarkMessageAsRead])

{

[self.conversation markMessageAsReadWithId:message.messageId error:nil];

}

}

}

}

- (void)cmdMessagesDidReceive:(NSArray *)aCmdMessages

{

for (EMMessage *message in aCmdMessages) {

if ([self.conversation.conversationId isEqualToString:message.conversationId]) {

[self showHint:NSEaseLocalizedString(@"receiveCmd", @"receive cmd message")];

break;

}

}

}

- (void)didReceiveHasDeliveredAcks:(NSArray *)aMessages

{

for(EMMessage *message in aMessages){

[self _updateMessageStatus:message];

}

}

- (void)didReceiveHasReadAcks:(NSArray *)aMessages

{

for (EMMessage *message in aMessages) {

if (![self.conversation.conversationId isEqualToString:message.conversationId]){

continue;

}

__block id model = nil;

__block BOOL isHave = NO;

[self.dataArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)

{

if ([obj conformsToProtocol:@protocol(IMessageModel)])

{

model = (id)obj;

if ([model.messageId isEqualToString:message.messageId])

{

model.message.isReadAcked = YES;

isHave = YES;

*stop = YES;

}

}

}];

if(!isHave){

return;

}

if (_delegate && [_delegate respondsToSelector:@selector(messageViewController:didReceiveHasReadAckForModel:)]) {

[_delegate messageViewController:self didReceiveHasReadAckForModel:model];

}

else{

[self.tableView reloadData];

}

}

}

- (void)didMessageStatusChanged:(EMMessage *)aMessage

error:(EMError *)aError;

{

[self _updateMessageStatus:aMessage];

}

- (void)didMessageAttachmentsStatusChanged:(EMMessage *)message

error:(EMError *)error{

if (!error) {

EMFileMessageBody *fileBody = (EMFileMessageBody*)[message body];

if ([fileBody type] == EMMessageBodyTypeImage) {

EMImageMessageBody *imageBody = (EMImageMessageBody *)fileBody;

if ([imageBody thumbnailDownloadStatus] == EMDownloadStatusSuccessed)

{

[self _reloadTableViewDataWithMessage:message];

}

}else if([fileBody type] == EMMessageBodyTypeVideo){

EMVideoMessageBody *videoBody = (EMVideoMessageBody *)fileBody;

if ([videoBody thumbnailDownloadStatus] == EMDownloadStatusSuccessed)

{

[self _reloadTableViewDataWithMessage:message];

}

}else if([fileBody type] == EMMessageBodyTypeVoice){

if ([fileBody downloadStatus] == EMDownloadStatusSuccessed)

{

[self _reloadTableViewDataWithMessage:message];

}

}

}else{

}

}

#pragma mark - EMCDDeviceManagerProximitySensorDelegate

- (void)proximitySensorChanged:(BOOL)isCloseToUser

{

AVAudioSession *audioSession = [AVAudioSession sharedInstance];

if (isCloseToUser)

{

[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];

} else {

[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];

if (self.playingVoiceModel == nil) {

[[EMCDDeviceManager sharedInstance] disableProximitySensor];

}

}

[audioSession setActive:YES error:nil];

}

#pragma mark - action

- (void)copyMenuAction:(id)sender

{

UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];

if (self.menuIndexPath && self.menuIndexPath.row > 0) {

id model = [self.dataArray objectAtIndex:self.menuIndexPath.row];

pasteboard.string = model.text;

}

self.menuIndexPath = nil;

}

- (void)deleteMenuAction:(id)sender

{

if (self.menuIndexPath && self.menuIndexPath.row > 0) {

id model = [self.dataArray objectAtIndex:self.menuIndexPath.row];

NSMutableIndexSet *indexs = [NSMutableIndexSet indexSetWithIndex:self.menuIndexPath.row];

NSMutableArray *indexPaths = [NSMutableArray arrayWithObjects:self.menuIndexPath, nil];

[self.conversation deleteMessageWithId:model.message.messageId error:nil];

[self.messsagesSource removeObject:model.message];

if (self.menuIndexPath.row - 1 >= 0) {

id nextMessage = nil;

id prevMessage = [self.dataArray objectAtIndex:(self.menuIndexPath.row - 1)];

if (self.menuIndexPath.row + 1 < [self.dataArray count]) {

nextMessage = [self.dataArray objectAtIndex:(self.menuIndexPath.row + 1)];

}

if ((!nextMessage || [nextMessage isKindOfClass:[NSString class]]) && [prevMessage isKindOfClass:[NSString class]]) {

[indexs addIndex:self.menuIndexPath.row - 1];

[indexPaths addObject:[NSIndexPath indexPathForRow:(self.menuIndexPath.row - 1) inSection:0]];

}

}

[self.dataArray removeObjectsAtIndexes:indexs];

[self.tableView beginUpdates];

[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];

[self.tableView endUpdates];

}

self.menuIndexPath = nil;

}

#pragma mark - public

- (NSArray *)formatMessages:(NSArray *)messages

{

NSMutableArray *formattedArray = [[NSMutableArray alloc] init];

if ([messages count] == 0) {

return formattedArray;

}

for (EMMessage *message in messages) {

//Calculate time interval

CGFloat interval = (self.messageTimeIntervalTag - message.timestamp) / 1000;

if (self.messageTimeIntervalTag < 0 || interval > 60 || interval < -60) {

NSDate *messageDate = [NSDate dateWithTimeIntervalInMilliSecondSince1970:(NSTimeInterval)message.timestamp];

NSString *timeStr = @"";

if (_dataSource && [_dataSource respondsToSelector:@selector(messageViewController:stringForDate:)]) {

timeStr = [_dataSource messageViewController:self stringForDate:messageDate];

}

else{

timeStr = [messageDate formattedTime];

}

[formattedArray addObject:timeStr];

self.messageTimeIntervalTag = message.timestamp;

}

//Construct message model

id model = nil;

if (_dataSource && [_dataSource respondsToSelector:@selector(messageViewController:modelForMessage:)]) {

model = [_dataSource messageViewController:self modelForMessage:message];

}

else{

model = [[EaseMessageModel alloc] initWithMessage:message];

model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];

// model.avatarImage = [UIImage imageNamed:@"image123"];

model.failImageName = @"imageDownloadFail";

}

if (model) {

[formattedArray addObject:model];

}

}

return formattedArray;

}

-(void)addMessageToDataSource:(EMMessage *)message

progress:(id)progress

{

[self.messsagesSource addObject:message];

__weak EaseMessageViewController *weakSelf = self;

dispatch_async(_messageQueue, ^{

NSArray *messages = [weakSelf formatMessages:@[message]];

dispatch_async(dispatch_get_main_queue(), ^{

[weakSelf.dataArray addObjectsFromArray:messages];

[weakSelf.tableView reloadData];

[weakSelf.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[weakSelf.dataArray count] - 1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];

});

});

}

#pragma mark - public

- (void)tableViewDidTriggerHeaderRefresh

{

self.messageTimeIntervalTag = -1;

NSString *messageId = nil;

if ([self.messsagesSource count] > 0) {

messageId = [(EMMessage *)self.messsagesSource.firstObject messageId];

}

else {

messageId = nil;

}

[self _loadMessagesBefore:messageId count:self.messageCountOfPage append:YES];

[self tableViewDidFinishTriggerHeader:YES reload:YES];

}

#pragma mark - send message

- (void)_refreshAfterSentMessage:(EMMessage*)aMessage

{

if ([self.messsagesSource count] && [EMClient sharedClient].options.sortMessageByServerTime) {

NSString *msgId = aMessage.messageId;

EMMessage *last = self.messsagesSource.lastObject;

if ([last isKindOfClass:[EMMessage class]]) {

__block NSUInteger index = NSNotFound;

index = NSNotFound;

[self.messsagesSource enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(EMMessage *obj, NSUInteger idx, BOOL *stop) {

if ([obj isKindOfClass:[EMMessage class]] && [obj.messageId isEqualToString:msgId]) {

index = idx;

*stop = YES;

}

}];

if (index != NSNotFound) {

[self.messsagesSource removeObjectAtIndex:index];

[self.messsagesSource addObject:aMessage];

//格式化消息

self.messageTimeIntervalTag = -1;

NSArray *formattedMessages = [self formatMessages:self.messsagesSource];

[self.dataArray removeAllObjects];

[self.dataArray addObjectsFromArray:formattedMessages];

[self.tableView reloadData];

[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[self.dataArray count] - 1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO];

return;

}

}

}

[self.tableView reloadData];

}

- (void)sendMessage:(EMMessage *)message isNeedUploadFile:(BOOL)isUploadFile

{

if (self.conversation.type == EMConversationTypeGroupChat){

message.chatType = EMChatTypeGroupChat;

}

else if (self.conversation.type == EMConversationTypeChatRoom){

message.chatType = EMChatTypeChatRoom;

}

__weak typeof(self) weakself = self;

// if (!([EMClient sharedClient].options.isAutoTransferMessageAttachments) && isUploadFile) {

// UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:NSLocalizedString(@"message.autoTransfer", @"Please customize the transfer attachment method") delegate:nil cancelButtonTitle:NSLocalizedString(@"sure", @"OK") otherButtonTitles:nil, nil];

// [alertView show];

// } else {

[self addMessageToDataSource:message

progress:nil];

[[EMClient sharedClient].chatManager sendMessage:message progress:^(int progress) {

if (weakself.dataSource && [weakself.dataSource respondsToSelector:@selector(messageViewController:updateProgress:messageModel:messageBody:)]) {

[weakself.dataSource messageViewController:weakself updateProgress:progress messageModel:nil messageBody:message.body];

}

} completion:^(EMMessage *aMessage, EMError *aError) {

if (!aError) {

SGUserModel *userModel = [SGUserInfo getUserInfo];

NSDictionary *dic = @{@"easemobuserId":userModel.hx_user_name,@"userName":[BHSettingUtil dataAndStringIsNull:userModel.company_name]?@"":userModel.company_name,@"logo":userModel.logo};

[[ContactDataObject shareInstance]insertData:dic];

[weakself _refreshAfterSentMessage:aMessage];

}

else {

[weakself.tableView reloadData];

}

}];

// }

}

- (void)sendTextMessage:(NSString *)text

{

NSDictionary *ext = nil;

if (self.conversation.type == EMConversationTypeGroupChat) {

NSArray *targets = [self _searchAtTargets:text];

if ([targets count]) {

__block BOOL atAll = NO;

[targets enumerateObjectsUsingBlock:^(NSString *target, NSUInteger idx, BOOL *stop) {

if ([target compare:kGroupMessageAtAll options:NSCaseInsensitiveSearch] == NSOrderedSame) {

atAll = YES;

*stop = YES;

}

}];

if (atAll) {

ext = @{kGroupMessageAtList: kGroupMessageAtAll};

}

else {

ext = @{kGroupMessageAtList: targets};

}

}

}

[self sendTextMessage:text withExt:ext];

}

- (void)sendTextMessage:(NSString *)text withExt:(NSDictionary*)ext

{

EMMessage *message = [EaseSDKHelper getTextMessage:text to:self.conversation.conversationId messageType:[self _messageTypeFromConversationType] messageExt:ext];

[self sendMessage:message isNeedUploadFile:NO];

}

- (void)sendLocationMessageLatitude:(double)latitude

longitude:(double)longitude

andAddress:(NSString *)address

{

EMMessage *message = [EaseSDKHelper getLocationMessageWithLatitude:latitude longitude:longitude address:address to:self.conversation.conversationId messageType:[self _messageTypeFromConversationType] messageExt:nil];

[self sendMessage:message isNeedUploadFile:NO];

}

- (void)sendImageMessageWithData:(NSData *)imageData

{

id progress = nil;

if (_dataSource && [_dataSource respondsToSelector:@selector(messageViewController:progressDelegateForMessageBodyType:)]) {

progress = [_dataSource messageViewController:self progressDelegateForMessageBodyType:EMMessageBodyTypeImage];

}

else{

progress = self;

}

EMMessage *message = [EaseSDKHelper getImageMessageWithImageData:imageData to:self.conversation.conversationId messageType:[self _messageTypeFromConversationType] messageExt:nil];

[self sendMessage:message isNeedUploadFile:YES];

}

- (void)sendImageMessage:(UIImage *)image

{

id progress = nil;

if (_dataSource && [_dataSource respondsToSelector:@selector(messageViewController:progressDelegateForMessageBodyType:)]) {

progress = [_dataSource messageViewController:self progressDelegateForMessageBodyType:EMMessageBodyTypeImage];

}

else{

progress = self;

}

EMMessage *message = [EaseSDKHelper getImageMessageWithImage:image to:self.conversation.conversationId messageType:[self _messageTypeFromConversationType] messageExt:nil];

[self sendMessage:message isNeedUploadFile:YES];

}

- (void)sendVoiceMessageWithLocalPath:(NSString *)localPath

duration:(NSInteger)duration

{

id progress = nil;

if (_dataSource && [_dataSource respondsToSelector:@selector(messageViewController:progressDelegateForMessageBodyType:)]) {

progress = [_dataSource messageViewController:self progressDelegateForMessageBodyType:EMMessageBodyTypeVoice];

}

else{

progress = self;

}

EMMessage *message = [EaseSDKHelper getVoiceMessageWithLocalPath:localPath duration:duration to:self.conversation.conversationId messageType:[self _messageTypeFromConversationType] messageExt:nil];

[self sendMessage:message isNeedUploadFile:YES];

}

- (void)sendVideoMessageWithURL:(NSURL *)url

{

id progress = nil;

if (_dataSource && [_dataSource respondsToSelector:@selector(messageViewController:progressDelegateForMessageBodyType:)]) {

progress = [_dataSource messageViewController:self progressDelegateForMessageBodyType:EMMessageBodyTypeVideo];

}

else{

progress = self;

}

EMMessage *message = [EaseSDKHelper getVideoMessageWithURL:url to:self.conversation.conversationId messageType:[self _messageTypeFromConversationType] messageExt:nil];

[self sendMessage:message isNeedUploadFile:YES];

}

- (void)sendFileMessageWith:(EMMessage *)message {

[self sendMessage:message isNeedUploadFile:YES];

}

#pragma mark - notifycation

- (void)didBecomeActive

{

self.messageTimeIntervalTag = -1;

self.dataArray = [[self formatMessages:self.messsagesSource] mutableCopy];

[self.tableView reloadData];

if (self.isViewDidAppear)

{

NSMutableArray *unreadMessages = [NSMutableArray array];

for (EMMessage *message in self.messsagesSource)

{

if ([self shouldSendHasReadAckForMessage:message read:NO])

{

[unreadMessages addObject:message];

}

}

if ([unreadMessages count])

{

[self _sendHasReadResponseForMessages:unreadMessages isRead:YES];

}

[_conversation markAllMessagesAsRead:nil];

if (self.dataSource && [self.dataSource respondsToSelector:@selector(messageViewControllerMarkAllMessagesAsRead:)]) {

[self.dataSource messageViewControllerMarkAllMessagesAsRead:self];

}

}

}

- (void)hideImagePicker

{

if (_imagePicker && [EaseSDKHelper shareHelper].isShowingimagePicker) {

[_imagePicker dismissViewControllerAnimated:NO completion:nil];

}

}

#pragma mark - private

- (void)_reloadTableViewDataWithMessage:(EMMessage *)message

{

if ([self.conversation.conversationId isEqualToString:message.conversationId])

{

for (int i = 0; i < self.dataArray.count; i ++) {

id object = [self.dataArray objectAtIndex:i];

if ([object isKindOfClass:[EaseMessageModel class]]) {

id model = object;

if ([message.messageId isEqualToString:model.messageId]) {

id model = nil;

if (self.dataSource && [self.dataSource respondsToSelector:@selector(messageViewController:modelForMessage:)]) {

model = [self.dataSource messageViewController:self modelForMessage:message];

}

else{

model = [[EaseMessageModel alloc] initWithMessage:message];

model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];

model.failImageName = @"imageDownloadFail";

}

[self.tableView beginUpdates];

[self.dataArray replaceObjectAtIndex:i withObject:model];

[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:i inSection:0]] withRowAnimation:UITableViewRowAnimationNone];

[self.tableView endUpdates];

break;

}

}

}

}

}

- (void)_updateMessageStatus:(EMMessage *)aMessage

{

BOOL isChatting = [aMessage.conversationId isEqualToString:self.conversation.conversationId];

if (aMessage && isChatting) {

id model = nil;

if (_dataSource && [_dataSource respondsToSelector:@selector(messageViewController:modelForMessage:)]) {

model = [_dataSource messageViewController:self modelForMessage:aMessage];

}

else{

model = [[EaseMessageModel alloc] initWithMessage:aMessage];

model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];

model.failImageName = @"imageDownloadFail";

}

if (model) {

__block NSUInteger index = NSNotFound;

[self.dataArray enumerateObjectsUsingBlock:^(EaseMessageModel *model, NSUInteger idx, BOOL *stop){

if ([model conformsToProtocol:@protocol(IMessageModel)]) {

if ([aMessage.messageId isEqualToString:model.message.messageId])

{

index = idx;

*stop = YES;

}

}

}];

if (index != NSNotFound)

{

[self.dataArray replaceObjectAtIndex:index withObject:model];

[self.tableView beginUpdates];

[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:0]] withRowAnimation:UITableViewRowAnimationNone];

[self.tableView endUpdates];

}

}

}

}

- (NSArray*)_searchAtTargets:(NSString*)text

{

NSMutableArray *targets = nil;

if (text.length > 1) {

targets = [NSMutableArray array];

NSArray *splits = [text componentsSeparatedByString:@"@"];

if ([splits count]) {

for (NSString *split in splits) {

if (split.length) {

NSString *atALl = NSEaseLocalizedString(@"group.atAll", @"all");

if (split.length >= atALl.length && [split compare:atALl options:NSCaseInsensitiveSearch range:NSMakeRange(0, atALl.length)] == NSOrderedSame) {

[targets removeAllObjects];

[targets addObject:kGroupMessageAtAll];

return targets;

}

for (EaseAtTarget *target in self.atTargets) {

if ([target.userId length]) {

if ([split hasPrefix:target.userId] || (target.nickname && [split hasPrefix:target.nickname])) {

[targets addObject:target.userId];

[self.atTargets removeObject:target];

break;

}

}

}

}

}

}

}

return targets;

}

@end

一键复制

编辑

原始数据

按行查看

历史

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这是一个Python第三方库的网站,提供了许多Windows平台下的二进制安装包,方便用户快速安装使用。其中包括了许多常用的科学计算、数据处理、图像处理等库,如numpy、scipy、matplotlib等。 ### 回答2: https://www.lfd.uci.edu/~gohlke/pythonlibs 主要是一个Python第三方库的下载站点,它提供了大量的Python第三方库的安装包,覆盖了Windows和Mac平台,并支持Python的不同版本。 这个网站的提供者是UCI(加利福尼亚大学欧文分校)的LFD(实验室 for Fluorescence Dynamics)实验室,这个实验室主要从事生物荧光动力学的研究。由此可见,这个网站的目的主要是为了让大家更加方便、快捷地获取Python第三方库,以提高研究和工作效率。 在这个网站上,我们可以通过输入搜索关键词或选择Python版本、操作系统等方式来定位需要的第三方库。下载安装包后,我们可以使用命令行工具pip安装或直接解压到Python的site-packages目录中即可开始使用。 总之,https://www.lfd.uci.edu/~gohlke/pythonlibs 是一个非常实用的Python第三方库下载站点,可以为我们的编程工作提供很大的便利,是Python爱好者们不可错过的好资源。 ### 回答3: Python 是一种非常流行的编程语言,有着大量的第三方库可以使用。https://www.lfd.uci.edu/~gohlke/pythonlibs 是一个著名的 Python 库集合网站,上面收录了许多常用的、高质量的 Python 库。 这个网站上的库涵盖了众多领域,比如数据处理、机器学习、网络编程等。其中比较著名的库包括 NumPy、Pandas、Matplotlib、Scipy、Scikit-learn 等。这些库不仅功能强大,而且经过了长期的持续更新和完善,因此使用它们可以提高开发效率和代码的鲁棒性。 此外,https://www.lfd.uci.edu/~gohlke/pythonlibs 还有一些针对 Windows 平台的特别优化的库,比如 OpenCV、Pygame 等。这些库的安装在 Windows 上可能比在其他平台上更为困难,但在这个网站上找到它们的预编译版本可以大大简化安装过程。 为了使用这些库,我们可以下载适合自己 Python 版本和位数(32 位或 64 位)的预编译二进制版本直接安装即可。当然,有些库还需要在系统上安装其他依赖库或者配置环境变量才能正常使用,因此需要仔细阅读库的文档和安装说明。 总之,https://www.lfd.uci.edu/~gohlke/pythonlibs 这个网站是 Python 开发者不可多得的一个资源,收录了丰富的高质量 Python 库,并且对于 Windows 平台的用户提供了便利。使用这些库可以大大提高开发效率和代码质量,因此我们应该熟悉这个网站并尽可能熟练地使用这些库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值