EMChatViewController.m 111 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780
  1. //
  2. // EMChatViewController.m
  3. // ChatDemo-UI3.0
  4. //
  5. // Created by XieYajie on 2019/1/18.
  6. // Copyright © 2019 XieYajie. All rights reserved.
  7. //
  8. #import <AVKit/AVKit.h>
  9. #import <Photos/Photos.h>
  10. #import <AVFoundation/AVFoundation.h>
  11. #import <AssetsLibrary/AssetsLibrary.h>
  12. #import <MobileCoreServices/MobileCoreServices.h>
  13. #import "EMChatViewController.h"
  14. #import "EMImageBrowser.h"
  15. #import "EMDateHelper.h"
  16. #import "EMAudioPlayerHelper.h"
  17. #import "EMConversationHelper.h"
  18. #import "EMMessageModel.h"
  19. #import "EMReadReceiptMemberModel.h"
  20. #import "EMChatBar.h"
  21. #import "EMMessageCell.h"
  22. #import "EMMessageTimeCell.h"
  23. #import "EMLocationViewController.h"
  24. #import "EMMsgTranspondViewController.h"
  25. #import "EMAtGroupMembersViewController.h"
  26. #import "FavoritesViewController.h"
  27. #import "ChatMsgDetailChatInfoVC.h"
  28. #import "ChatMsgPersonInfoVC.h"
  29. #import "ChatMsgListImModel.h"
  30. #import "MailListDetailVC.h"
  31. #import "FWZFileGetTool.h"
  32. #import "EMChatFileShowVC.h"
  33. #import "DrawerView.h"
  34. #import "TabBarController.h"
  35. #import "FWZGetNoteBookTool.h"
  36. #import "NoteBookVC.h"
  37. #import "OtherNoteBookVC.h"
  38. #import "MyFavoriteVC.h"
  39. #import "OtherFavoriteVC.h"
  40. #import "TDGroupInfoListVC.h"
  41. #import "DownFileViewController.h"
  42. #import "WorkFlowDetailsController.h"
  43. #import "MyTDGroupViewController.h"
  44. #import "HomeDetailController.h"
  45. #import "MyApprovalPageDetail.h"
  46. #import "NoteBookShareVC.h"
  47. #import "MoveViewController.h"
  48. @interface EMChatViewController ()<UIScrollViewDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, EMMultiDevicesDelegate, EMChatManagerDelegate, EMGroupManagerDelegate, EMChatroomManagerDelegate, EMChatBarDelegate, EMMessageCellDelegate, EMChatBarEmoticonViewDelegate, EMChatBarRecordAudioViewDelegate,EMMoreFunctionViewDelegate,EMReadReceiptMsgDelegate,NoteBookShareVCDelegate>
  49. @property (nonatomic, strong) dispatch_queue_t msgQueue;
  50. @property (nonatomic, strong) UIView * titleV;
  51. @property (nonatomic, strong) UIButton * backBtn;
  52. @property (nonatomic, strong) UIButton * tabBtn;
  53. @property (nonatomic, strong) UIButton * mangerBtn;
  54. @property (nonatomic, strong) UILabel * titleL;
  55. @property (strong,nonatomic) DrawerView *drawerView;
  56. @property (nonatomic) BOOL isFirstLoadMsg;
  57. @property (nonatomic) BOOL isViewDidAppear;
  58. @property (nonatomic, strong) EMConversationModel *conversationModel;
  59. @property (nonatomic, strong) NSString *moreMsgId; //第一条消息的消息id
  60. @property (nonatomic, strong) UILabel *titleLabel;
  61. @property (nonatomic, strong) UILabel *titleDetailLabel;
  62. @property (nonatomic, strong) EMChatBar *chatBar;
  63. @property (nonatomic, strong) UIImagePickerController *imagePicker;
  64. @property (nonatomic, strong) EMGroup *group;
  65. //阅读回执
  66. @property (nonatomic, strong) EMReadReceiptMsgViewController *readReceiptControl;
  67. //长按操作栏
  68. @property (strong, nonatomic) NSIndexPath *menuIndexPath;
  69. @property (nonatomic, strong) UIMenuController *menuController;
  70. @property (nonatomic, strong) UIMenuItem *deleteMenuItem;
  71. @property (nonatomic, strong) UIMenuItem *copyMenuItem;
  72. @property (nonatomic, strong) UIMenuItem *recallMenuItem;
  73. @property (nonatomic, strong) UIMenuItem *transpondMenuItem;
  74. @property (nonatomic, strong) UIMenuItem *playAndRecordMenuItem;
  75. //消息格式化
  76. @property (nonatomic) NSTimeInterval msgTimelTag;
  77. //@
  78. @property (nonatomic) BOOL isWillInputAt;
  79. @property (strong, nonatomic) NoteBookShareVC *noteBookShareVC;
  80. @property (strong, nonatomic) UIImage *sendImage;
  81. @property (copy, nonatomic) FlowAttachmentsModel *sendModel;
  82. //Typing
  83. @property (nonatomic) BOOL isTyping;
  84. @property (nonatomic) BOOL enableTyping;
  85. @property (nonatomic, copy) NSMutableArray *userInfoArray;
  86. @property (nonatomic, copy) NSMutableArray *chatDistoryArray;
  87. @property (nonatomic, assign) NSInteger UserId;
  88. @end
  89. @implementation EMChatViewController
  90. - (instancetype)initWithConversationId:(NSString *)aId
  91. type:(EMConversationType)aType
  92. createIfNotExist:(BOOL)aIsCreate
  93. {
  94. self = [super init];
  95. if (self) {
  96. EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:aId type:aType createIfNotExist:aIsCreate];
  97. _conversationModel = [[EMConversationModel alloc] initWithEMModel:conversation];
  98. }
  99. return self;
  100. }
  101. - (instancetype)initWithCoversationModel:(EMConversationModel *)aConversationModel
  102. {
  103. self = [super init];
  104. if (self) {
  105. _conversationModel = aConversationModel;
  106. }
  107. return self;
  108. }
  109. - (void)viewDidLoad {
  110. [super viewDidLoad];
  111. NSLog(@"conversationId===%@",_conversationModel.emModel.conversationId);
  112. // Do any additional setup after loading the view.
  113. self.msgQueue = dispatch_queue_create("emmessage.com", NULL);
  114. self.msgTimelTag = -1;
  115. [self _setupChatSubviews];
  116. [[EMClient sharedClient] addMultiDevicesDelegate:self delegateQueue:nil];
  117. [[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];
  118. [[EMClient sharedClient].groupManager addDelegate:self delegateQueue:nil];
  119. [[EMClient sharedClient].roomManager addDelegate:self delegateQueue:nil];
  120. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleWillPushCallController:) name:CALL_PUSH_VIEWCONTROLLER object:nil];
  121. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleCleanMessages:) name:CHAT_CLEANMESSAGES object:nil];
  122. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleGroupSubjectUpdated:) name:GROUP_SUBJECT_UPDATED object:nil];
  123. self.isTyping = NO;
  124. self.enableTyping = NO;
  125. if ([EMDemoOptions sharedOptions].isChatTyping && self.conversationModel.emModel.type == EMConversationTypeChat) {
  126. self.enableTyping = YES;
  127. }
  128. if (self.conversationModel.emModel.type == EMConversationTypeChatRoom) {
  129. [self _joinChatroom];
  130. } else {
  131. self.isFirstLoadMsg = YES;
  132. [self tableViewDidTriggerHeaderRefresh];
  133. }
  134. [self.view addSubview:self.noteBookShareVC.view];
  135. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapTableViewAction:)];
  136. [self.tableView addGestureRecognizer:tap];
  137. }
  138. - (void)viewWillAppear:(BOOL)animated
  139. {
  140. [super viewWillAppear:animated];
  141. self.isViewDidAppear = YES;
  142. [EMConversationHelper markAllAsRead:self.conversationModel];
  143. self.navigationController.navigationBar.hidden = YES;
  144. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deleteConversationMsg) name:DELETECONVERSATIONMSG object:nil];
  145. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardWillShow:) name:UIKeyboardWillShowNotification object:nil];
  146. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardWillHide:) name:UIKeyboardWillHideNotification object:nil];
  147. }
  148. - (void)viewWillDisappear:(BOOL)animated
  149. {
  150. [super viewWillDisappear:animated];
  151. self.isViewDidAppear = NO;
  152. if (self.enableTyping && self.isTyping) {
  153. [self _sendEndTyping];
  154. }
  155. if (self.chatBar.textView.text.length > 0) {
  156. [self saveUserInfoInDocument:self.chatBar.textView.text];
  157. }else{
  158. [self clearUserInfoInDocument];
  159. }
  160. [self.chatBar mas_updateConstraints:^(MASConstraintMaker *make) {
  161. if (@available(iOS 11.0, *)) {
  162. make.bottom.mas_equalTo(self.view.mas_safeAreaLayoutGuideBottom);
  163. } else {
  164. make.bottom.mas_equalTo(self.view.mas_bottom);
  165. }
  166. }];
  167. [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
  168. [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
  169. }
  170. - (void)dealloc
  171. {
  172. self.isViewDidAppear = NO;
  173. [self.chatBar removeFromSuperview];
  174. [[EMClient sharedClient] removeMultiDevicesDelegate:self];
  175. [[EMClient sharedClient].chatManager removeDelegate:self];
  176. [[EMClient sharedClient].groupManager removeDelegate:self];
  177. [[EMClient sharedClient].roomManager removeDelegate:self];
  178. [[NSNotificationCenter defaultCenter] removeObserver:self];
  179. }
  180. - (BOOL)canBecomeFirstResponder
  181. {
  182. return YES;
  183. }
  184. #pragma mark - Subviews
  185. - (void)_setupChatSubviews
  186. {
  187. NSLog(@"%@",self.conversationModel.emModel.conversationId);
  188. [self _setupNavigationBarTitle];
  189. self.view.backgroundColor = [UIColor whiteColor];
  190. self.showRefreshHeader = YES;
  191. self.chatBar = [[EMChatBar alloc] init];
  192. self.chatBar.delegate = self;
  193. [self.view addSubview:self.chatBar];
  194. [self.chatBar mas_makeConstraints:^(MASConstraintMaker *make) {
  195. make.left.mas_equalTo(self.view);
  196. make.right.mas_equalTo(self.view);
  197. if (@available(iOS 11.0, *)) {
  198. make.bottom.mas_equalTo(self.view.mas_safeAreaLayoutGuideBottom);
  199. } else {
  200. make.bottom.mas_equalTo(self.view.mas_bottom);
  201. }
  202. make.height.offset(56);
  203. }];
  204. if ([self getUserInfoInDocument].length > 0) {
  205. self.chatBar.textView.text = [self getUserInfoInDocument];
  206. }
  207. WS(weakSelf);
  208. self.chatBar.clickMore = ^(NSInteger index, NSString * _Nonnull title) {
  209. [weakSelf selectMoreMenu:index title:title];
  210. };
  211. [self _setupChatBarMoreViews];
  212. self.tableView.backgroundColor = kColor_LightGray;
  213. self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  214. self.tableView.rowHeight = UITableViewAutomaticDimension;
  215. self.tableView.estimatedRowHeight = 130;
  216. [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
  217. make.top.mas_equalTo(self.titleV.mas_bottom);
  218. make.left.mas_equalTo(self.view);
  219. make.right.mas_equalTo(self.view);
  220. make.bottom.mas_equalTo(self.chatBar.mas_top);
  221. }];
  222. }
  223. -(DrawerView *)drawerView{
  224. if(!_drawerView){
  225. _drawerView = [[DrawerView alloc] init];
  226. }
  227. return _drawerView;
  228. }
  229. - (void)_setupNavigationBarTitle
  230. {
  231. [self.view addSubview:self.titleV];
  232. [self.titleV mas_makeConstraints:^(MASConstraintMaker *make) {
  233. make.top.left.right.mas_equalTo(self.view);
  234. make.height.mas_offset(IS_IPHONEX?88:64);
  235. }];
  236. [self.titleV addSubview:self.backBtn];
  237. [self.titleV addSubview:self.tabBtn];
  238. [self.titleV addSubview:self.titleL];
  239. [self.titleV addSubview:self.mangerBtn];
  240. [self.backBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  241. make.left.bottom.mas_equalTo(self.titleV);
  242. make.size.mas_offset(CGSizeMake(50, 44));
  243. }];
  244. [self.tabBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  245. make.bottom.mas_equalTo(self.titleV);
  246. make.left.mas_equalTo(self.backBtn.mas_right);
  247. make.size.mas_offset(CGSizeMake(35, 44));
  248. }];
  249. [self.mangerBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  250. make.right.bottom.mas_equalTo(self.titleV);
  251. make.size.mas_offset(CGSizeMake(50, 44));
  252. }];
  253. [self.titleL mas_makeConstraints:^(MASConstraintMaker *make) {
  254. make.centerX.mas_equalTo(self.titleV);
  255. make.centerY.mas_equalTo(self.backBtn);
  256. make.height.mas_greaterThanOrEqualTo(10);
  257. make.width.mas_lessThanOrEqualTo(SCREEN_WIDTH - 160);
  258. }];
  259. self.titleL.text = self.conversationModel.name;
  260. WS(weakSelf);
  261. [self.backBtn setAction:^{
  262. weakSelf.hidesBottomBarWhenPushed = NO;
  263. [weakSelf.navigationController popViewControllerAnimated:YES];
  264. }];
  265. [self.tabBtn setAction:^{
  266. [[UtilsTools getWindow] addSubview:weakSelf.drawerView];
  267. weakSelf.drawerView.SelectDrawerBlock = ^(NSIndexPath * _Nonnull indexPath) {
  268. if ([weakSelf.navigationController.viewControllers count] > 1) {
  269. [weakSelf.navigationController popToRootViewControllerAnimated:NO];
  270. }
  271. if (indexPath.section == 0) {
  272. [[TabBarController sharedTabBarController] setSelectedIndex:indexPath.row];
  273. }else{
  274. ///@"站内信", @"通知", @"收藏",@"笔记", @"设置"
  275. switch (indexPath.row) {
  276. case 0:
  277. {
  278. [[TabBarController sharedTabBarController] setSelectedIndex:2];
  279. }
  280. break;
  281. case 1:
  282. {
  283. [[TabBarController sharedTabBarController] setSelectedIndex:2];
  284. }
  285. break;
  286. default:
  287. {
  288. [[TabBarController sharedTabBarController] setSelectedIndex:3];
  289. }
  290. break;
  291. }
  292. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  293. [[NSNotificationCenter defaultCenter] postNotificationName:DRAWERPUSHVC object:nil userInfo:@{VCINDEX:@(indexPath.row)}];
  294. });
  295. }
  296. };
  297. weakSelf.drawerView.frame = CGRectMake(0,0, SCREEN_WIDTH, SCREEN_HEIGHT);// - kNavigationHeight
  298. }];
  299. [self.mangerBtn setAction:^{
  300. if (weakSelf.chatType == ChatType_SingleChat) {
  301. ChatMsgPersonInfoVC * vc = [ChatMsgPersonInfoVC initChatMsgPersonInfoVC];
  302. vc.refreshStatus = ^(BOOL isTop) {
  303. weakSelf.isTop = isTop;
  304. };
  305. vc.listId = weakSelf.listId;
  306. vc.IsTop = weakSelf.isTop;
  307. vc.model = weakSelf.sModel;
  308. [weakSelf.navigationController pushViewController:vc animated:YES];
  309. }else{
  310. ChatMsgDetailChatInfoVC *vc = [ChatMsgDetailChatInfoVC initChatMsgDetailChatInfoVC];
  311. vc.GroupChatImId = weakSelf.toUserId;
  312. vc.GroupId = weakSelf.GroupId;
  313. vc.GroupName = weakSelf.conversationModel.name;
  314. vc.upDataChatBlock = ^(NSString * _Nonnull name) {
  315. weakSelf.titleL.text = name;
  316. };
  317. [weakSelf.navigationController pushViewController:vc animated:YES];
  318. }
  319. }];
  320. }
  321. - (void)_setupChatBarMoreViews
  322. {
  323. //语音
  324. NSString *path = [self _getAudioOrVideoPath];
  325. EMChatBarRecordAudioView *recordView = [[EMChatBarRecordAudioView alloc] initWithRecordPath:path];
  326. recordView.delegate = self;
  327. self.chatBar.recordAudioView = recordView;
  328. //表情
  329. EMChatBarEmoticonView *moreEmoticonView = [[EMChatBarEmoticonView alloc] init];
  330. moreEmoticonView.delegate = self;
  331. self.chatBar.moreEmoticonView = moreEmoticonView;
  332. //更多
  333. if (self.conversationModel.emModel.type == EMConversationTypeGroupChat) {
  334. EMMoreFunctionView *moreFunction = [[EMMoreFunctionView alloc]init];
  335. moreFunction.delegate = self;
  336. self.chatBar.moreFunctionView = moreFunction;
  337. }
  338. }
  339. - (NSString *)_getAudioOrVideoPath
  340. {
  341. NSString *path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
  342. path = [path stringByAppendingPathComponent:@"EMDemoRecord"];
  343. if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
  344. [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
  345. }
  346. return path;
  347. }
  348. #pragma mark - Table view data source
  349. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  350. return 1;
  351. }
  352. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  353. return [self.dataArray count];
  354. }
  355. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  356. id obj = [self.dataArray objectAtIndex:indexPath.row];
  357. NSString *cellString = nil;
  358. if ([obj isKindOfClass:[NSString class]]) {
  359. cellString = (NSString *)obj;
  360. } else if ([obj isKindOfClass:[EMMessageModel class]]) {
  361. EMMessageModel *model = (EMMessageModel *)obj;
  362. if (model.type == EMMessageTypeExtRecall) {
  363. cellString = @"您撤回一条消息";
  364. }
  365. }
  366. if ([cellString length] > 0) {
  367. EMMessageTimeCell *cell = (EMMessageTimeCell *)[tableView dequeueReusableCellWithIdentifier:@"EMMessageTimeCell"];
  368. // Configure the cell...
  369. if (cell == nil || !cell) {
  370. cell = [[EMMessageTimeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"EMMessageTimeCell"];
  371. }
  372. cell.timeLabel.text = cellString;
  373. return cell;
  374. } else {
  375. EMMessageModel *model = (EMMessageModel *)obj;
  376. if ([[model.emModel.ext objectForKey:@"app"] boolValue]) {
  377. model.type = EMMessageTypeExtApp;
  378. }
  379. NSString *identifier = [EMMessageCell cellIdentifierWithDirection:model.direction type:model.type];
  380. EMMessageCell *cell = (EMMessageCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
  381. // Configure the cell...
  382. if (cell == nil || !cell) {
  383. cell = [[EMMessageCell alloc] initWithDirection:model.direction type:model.type];
  384. cell.delegate = self;
  385. }
  386. if (self.chatType == ChatType_SingleChat) {
  387. if (model.emModel.direction == EMMessageDirectionSend){
  388. [cell setIconUrl:[AppUserModel sharedAppUserModel].AvatarUrl];
  389. }else{
  390. [cell setIconUrl:self.ReceiveIcon];
  391. }
  392. }else{
  393. [self.groupUserInfoArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  394. if ([obj isKindOfClass:[NSDictionary class]]) {
  395. if ([[obj objectForKey:@"ImId"] integerValue] == [model.emModel.from integerValue]) {
  396. [cell setIconUrl:[obj objectForKey:@"AvatarUrl"]];
  397. }
  398. }
  399. }];
  400. }
  401. cell.model = model;
  402. return cell;
  403. }
  404. }
  405. #pragma mark - UIScrollViewDelegate
  406. - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
  407. {
  408. [self.view endEditing:YES];
  409. [self.chatBar clearMoreViewAndSelectedButton];
  410. }
  411. #pragma mark - UIImagePickerControllerDelegate
  412. - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
  413. {
  414. NSString *mediaType = info[UIImagePickerControllerMediaType];
  415. if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]) {
  416. NSURL *videoURL = info[UIImagePickerControllerMediaURL];
  417. // we will convert it to mp4 format
  418. NSURL *mp4 = [self _videoConvert2Mp4:videoURL];
  419. NSFileManager *fileman = [NSFileManager defaultManager];
  420. if ([fileman fileExistsAtPath:videoURL.path]) {
  421. NSError *error = nil;
  422. [fileman removeItemAtURL:videoURL error:&error];
  423. if (error) {
  424. NSLog(@"failed to remove file, error:%@.", error);
  425. }
  426. }
  427. [self _sendVideoAction:mp4];
  428. } else {
  429. NSURL *url = info[UIImagePickerControllerReferenceURL];
  430. if (url == nil) {
  431. UIImage *orgImage = info[UIImagePickerControllerOriginalImage];
  432. NSData *data = UIImageJPEGRepresentation(orgImage, 1);
  433. [self _sendImageDataAction:data];
  434. } else {
  435. if ([[UIDevice currentDevice].systemVersion doubleValue] >= 9.0f) {
  436. PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:@[url] options:nil];
  437. [result enumerateObjectsUsingBlock:^(PHAsset *asset , NSUInteger idx, BOOL *stop){
  438. if (asset) {
  439. [[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData *data, NSString *uti, UIImageOrientation orientation, NSDictionary *dic){
  440. if (data != nil) {
  441. [self _sendImageDataAction:data];
  442. } else {
  443. [EMAlertController showErrorAlert:@"图片太大,请选择其他图片"];
  444. }
  445. }];
  446. }
  447. }];
  448. } else {
  449. ALAssetsLibrary *alasset = [[ALAssetsLibrary alloc] init];
  450. [alasset assetForURL:url resultBlock:^(ALAsset *asset) {
  451. if (asset) {
  452. ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
  453. Byte *buffer = (Byte*)malloc((size_t)[assetRepresentation size]);
  454. NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:0.0 length:(NSUInteger)[assetRepresentation size] error:nil];
  455. NSData *fileData = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];
  456. [self _sendImageDataAction:fileData];
  457. }
  458. } failureBlock:NULL];
  459. }
  460. }
  461. }
  462. [picker dismissViewControllerAnimated:YES completion:nil];
  463. }
  464. - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
  465. {
  466. [self.imagePicker dismissViewControllerAnimated:YES completion:nil];
  467. }
  468. #pragma mark - EMChatBarDelegate
  469. - (void)_willInputAt:(EMTextView *)aInputView
  470. {
  471. do {
  472. if (self.conversationModel.emModel.type != EMConversationTypeGroupChat) {
  473. break;
  474. }
  475. NSString *text = aInputView.text;
  476. // if (![text hasSuffix:@"@"]) {
  477. // break;
  478. // }
  479. EMGroup *group = [EMGroup groupWithId:self.conversationModel.emModel.conversationId];
  480. if (!group) {
  481. break;
  482. }
  483. [self.view endEditing:YES];
  484. EMAtGroupMembersViewController *controller = [[EMAtGroupMembersViewController alloc] initWithGroup:group];
  485. [self.navigationController pushViewController:controller animated:YES];
  486. [controller setSelectedCompletion:^(NSString * _Nonnull aName) {
  487. NSString *newStr = [NSString stringWithFormat:@"%@%@ ", text, aName];
  488. aInputView.text = newStr;
  489. aInputView.selectedRange = NSMakeRange(newStr.length, 0);
  490. [aInputView becomeFirstResponder];
  491. }];
  492. } while (0);
  493. }
  494. - (BOOL)inputView:(EMTextView *)aInputView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
  495. {
  496. self.isWillInputAt = NO;
  497. if ([text isEqualToString:@"\n"]) {
  498. [self _sendTextAction:aInputView.text ext:nil];
  499. return NO;
  500. } else if ([text isEqualToString:@"@"]) {
  501. self.isWillInputAt = YES;
  502. } else if ([text length] == 0) {
  503. }
  504. return YES;
  505. }
  506. - (void)inputViewDidChange:(EMTextView *)aInputView
  507. {
  508. if (self.isWillInputAt && self.conversationModel.emModel.type == EMConversationTypeGroupChat) {
  509. NSString *text = aInputView.text;
  510. if ([text hasSuffix:@"@"]) {
  511. self.isWillInputAt = NO;
  512. [self _willInputAt:aInputView];
  513. }
  514. }
  515. if (self.enableTyping) {
  516. if (!self.isTyping) {
  517. self.isTyping = YES;
  518. [self _sendBeginTyping];
  519. }
  520. }
  521. }
  522. - (void)chatBarClickMoreType:(SmartBarType)type
  523. {
  524. WS(weakSelf);
  525. switch (type) {
  526. case SmartBarPhoto:
  527. {
  528. [self chatBarDidPhotoAction];
  529. }
  530. break;
  531. case SmartBarCamera:
  532. {
  533. [self chatBarDidCameraAction];
  534. }
  535. break;
  536. case SmartBarNotes:
  537. {
  538. [[FWZGetNoteBookTool sharedTool] openNoteBookListChooseNoteBookBlock:^(NSMutableArray<MyNoteBookSubModel *> * _Nonnull noteArr) {
  539. NSLog(@"SmartBarNotes %@",noteArr);
  540. for (MyNoteBookSubModel * model in noteArr) {
  541. switch (model.AttributeValue) {
  542. case 1:
  543. {
  544. [weakSelf _sendTextAction:@"[笔记]" ext:@{@"app":@(YES),
  545. @"app_type":@(CollectModel_NoteBook),
  546. @"app_title":model.Title,
  547. @"app_id":@(model.MiddleId),
  548. @"app_content":@"来自-笔记",
  549. @"app_sourceUserId":@(model.SourceUserId),
  550. @"app_min_url":@"",
  551. @"app_url":@""
  552. }];
  553. }
  554. break;
  555. default:
  556. {
  557. [weakSelf _sendTextAction:@"[笔记]" ext:@{@"app":@(YES),
  558. @"app_type":@(CollectModel_NoteFile),
  559. @"app_title":model.FolderName,
  560. @"app_id":@(model.Id),
  561. @"app_sourceUserId":@(model.SourceUserId),
  562. @"app_content":@"来自-笔记",
  563. @"app_min_url":@"",
  564. @"app_url":@""
  565. }];
  566. }
  567. break;
  568. }
  569. }
  570. }];
  571. }
  572. break;
  573. case SmartBarCollection:
  574. {
  575. [[FWZGetNoteBookTool sharedTool] openCollectListChooseCollectBlock:^(NSMutableArray<MyFavoriteSubModel *> * _Nonnull collectArr) {
  576. NSLog(@"SmartBarCollection %@",collectArr);
  577. for (MyFavoriteSubModel * model in collectArr) {
  578. [weakSelf sendExtWithCollectModel:model];
  579. }
  580. }];
  581. }
  582. break;
  583. case SmartBarFile:
  584. {
  585. [self chatBarDidFileAction];
  586. }
  587. break;
  588. default:
  589. break;
  590. }
  591. }
  592. - (void)sendExtWithCollectModel:(MyFavoriteSubModel *)model
  593. {
  594. NSString * text = @"";
  595. switch (model.CollectionType) {
  596. case CollectModel_NewTopic:
  597. text = @"[话题]";
  598. break;
  599. case CollectModel_Toipc:
  600. text = @"[话题]";
  601. break;
  602. case CollectModel_Notice:
  603. text = @"[通知]";
  604. break;
  605. case CollectModel_NoteBook:
  606. text = @"[笔记]";
  607. break;
  608. case CollectModel_CollectFile:
  609. text = @"[文件夹]";
  610. break;
  611. case CollectModel_NoteFile:
  612. text = @"[文件夹]";
  613. break;
  614. case CollectModel_file:
  615. text = @"[文件]";
  616. break;
  617. case CollectModel_Image:
  618. text = @"[图片]";
  619. break;
  620. case CollectModel_meetMian:
  621. text = @"[会议纪要]";
  622. break;
  623. default:
  624. text = @"[话题]";
  625. break;
  626. }
  627. switch (model.AttributeValue) {
  628. case 1:
  629. {
  630. [self _sendTextAction:text ext:@{@"app":@(YES),
  631. @"app_type":@(model.CollectionType),
  632. @"app_title":model.Title,
  633. @"app_content":@"来自-收藏",
  634. @"app_sourceUserId":@(model.SourceUserId),
  635. @"app_id":@(model.CollectionDataId),
  636. @"app_min_url":model.Data.MinFile,
  637. @"app_url":model.Data.File
  638. }];
  639. }
  640. break;
  641. default:
  642. {
  643. [self _sendTextAction:text ext:@{@"app":@(YES),
  644. @"app_type":@(CollectModel_CollectFile),
  645. @"app_title":model.FolderName,
  646. @"app_content":@"来自-收藏",
  647. @"app_sourceUserId":@(model.SourceUserId),
  648. @"app_id":@(model.Id),
  649. @"app_min_url":model.Data.MinFile,
  650. @"app_url":model.Data.File
  651. }];
  652. }
  653. break;
  654. }
  655. }
  656. - (void)chatBarDidPhotoAction
  657. {
  658. WS(weakSelf);
  659. [self.view endEditing:YES];
  660. TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:9 delegate:nil];
  661. [imagePickerVc setNavLeftBarButtonSettingBlock:^(UIButton *leftButton){
  662. leftButton.hidden = YES;
  663. }];
  664. imagePickerVc.showSelectBtn = NO;
  665. imagePickerVc.allowCrop = YES;
  666. imagePickerVc.cropRect = CGRectMake(0, (SCREEN_HEIGHT - SCREEN_WIDTH) * 0.5, SCREEN_WIDTH, SCREEN_WIDTH);
  667. imagePickerVc.allowTakePicture = NO;
  668. imagePickerVc.allowTakeVideo = NO;
  669. imagePickerVc.allowPickingOriginalPhoto = NO;
  670. imagePickerVc.allowPickingGif = NO;
  671. [imagePickerVc setIsStatusBarDefault:YES];
  672. [imagePickerVc setNaviTitleColor:[UIColor blackColor]];
  673. [imagePickerVc setBarItemTextColor:[UIColor blackColor]];
  674. [imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {
  675. // if (assets.count > 0) {
  676. // for (PHAsset *asset in assets) {
  677. // PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
  678. // options.version = PHImageRequestOptionsVersionCurrent;
  679. // options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
  680. // PHImageManager *manager = [PHImageManager defaultManager];
  681. // [manager requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
  682. // AVURLAsset *urlAsset = (AVURLAsset *)asset;
  683. // NSURL *url = urlAsset.URL;
  684. // [weakSelf _sendVideoAction:url];
  685. // }];
  686. // }
  687. // }
  688. if (photos.count > 0) {
  689. for (UIImage * image in photos) {
  690. NSData *data = UIImageJPEGRepresentation(image, 1);
  691. [weakSelf _sendImageDataAction:data];
  692. }
  693. }
  694. }];
  695. [self presentViewController:imagePickerVc animated:YES completion:nil];
  696. }
  697. - (void)chatBarDidCameraAction
  698. {
  699. [self.view endEditing:YES];
  700. //#if TARGET_IPHONE_SIMULATOR
  701. // [EMAlertController showErrorAlert:@"模拟器不支持照相机"];
  702. //#elif TARGET_OS_IPHONE
  703. self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
  704. self.imagePicker.mediaTypes = @[(NSString *)kUTTypeImage, (NSString *)kUTTypeMovie];
  705. [self presentViewController:self.imagePicker animated:YES completion:nil];
  706. //#endif
  707. }
  708. - (void)chatBarDidFileAction
  709. {
  710. WS(weakSelf);
  711. [[FWZFileGetTool sharedTool] openFileWithCrop:YES showImgBlock:^(NSString * _Nonnull fileUrlStr) {
  712. } choosFileBlock:^(NSData * _Nonnull fileData, NSString * _Nonnull fileName) {
  713. // EMFileMessageBody * body = [[EMFileMessageBody alloc] initWithData:fileData displayName:fileName];
  714. // [weakSelf _sendMessageWithBody:body ext:nil isUpload:YES];
  715. SHOWLOADING
  716. [[HttpManager sharedHttpManager] HeaderUploadFileUrl:Host(Modify_UserImages_Post) parameters:@{} fileData:fileData fileKey:@"file" fileName:fileName mimeType:@"multipart/form-data" success:^(id _Nonnull responseObject) {
  717. REMOVESHOW
  718. NSDictionary * dict = responseObject[0];
  719. if ([dict[@"FileType"] isEqualToString:@"image"]) {
  720. [weakSelf _sendImageDataAction:fileData];
  721. }else{
  722. [weakSelf _sendTextAction:@"[文件]" ext:@{@"app":@(YES),
  723. @"app_type":@(CollectModel_file),
  724. @"app_title":fileName,
  725. @"app_content":@"",
  726. @"app_sourceUserId":@([AppUserModel sharedAppUserModel].Id),
  727. @"app_id":@([dict[@"FileId"] integerValue]),
  728. @"app_min_url":dict[@"MinAbsolutePath"],
  729. @"app_url":dict[@"AbsolutePath"]
  730. }];
  731. }
  732. } failure:^(NSError * _Nonnull error) {
  733. REMOVESHOW
  734. }];
  735. }];
  736. }
  737. - (void)chatBarDidLocationAction
  738. {
  739. EMLocationViewController *controller = [[EMLocationViewController alloc] init];
  740. [controller setSendCompletion:^(CLLocationCoordinate2D aCoordinate, NSString * _Nonnull aAddress) {
  741. [self _sendLocationAction:aCoordinate address:aAddress];
  742. }];
  743. UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
  744. [self.navigationController presentViewController:navController animated:YES completion:nil];
  745. }
  746. - (void)chatBarDidCallAction
  747. {
  748. self.alertController = [UIAlertController alertControllerWithTitle:@"实时通话类型" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
  749. __weak typeof(self) weakself = self;
  750. if (self.conversationModel.emModel.type == EMConversationTypeChat) {
  751. [self.alertController addAction:[UIAlertAction actionWithTitle:@"语音通话" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  752. [weakself.chatBar clearMoreViewAndSelectedButton];
  753. [[NSNotificationCenter defaultCenter] postNotificationName:CALL_MAKE1V1 object:@{CALL_CHATTER:weakself.conversationModel.emModel.conversationId, CALL_TYPE:@(EMCallTypeVoice)}];
  754. }]];
  755. [self.alertController addAction:[UIAlertAction actionWithTitle:@"视频通话" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  756. [weakself.chatBar clearMoreViewAndSelectedButton];
  757. [[NSNotificationCenter defaultCenter] postNotificationName:CALL_MAKE1V1 object:@{CALL_CHATTER:weakself.conversationModel.emModel.conversationId, CALL_TYPE:@(EMCallTypeVideo)}];
  758. }]];
  759. } else {
  760. [self.alertController addAction:[UIAlertAction actionWithTitle:@"会议模式" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  761. [weakself.chatBar clearMoreViewAndSelectedButton];
  762. [[NSNotificationCenter defaultCenter] postNotificationName:CALL_MAKECONFERENCE object:@{CALL_TYPE:@(EMConferenceTypeLargeCommunication), CALL_MODEL:weakself.conversationModel, NOTIF_NAVICONTROLLER:self.navigationController}];
  763. }]];
  764. [self.alertController addAction:[UIAlertAction actionWithTitle:@"互动模式" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  765. [weakself.chatBar clearMoreViewAndSelectedButton];
  766. [[NSNotificationCenter defaultCenter] postNotificationName:CALL_MAKECONFERENCE object:@{CALL_TYPE:@(EMConferenceTypeLive), CALL_MODEL:weakself.conversationModel, NOTIF_NAVICONTROLLER:self.navigationController}];
  767. }]];
  768. }
  769. [self.alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
  770. }]];
  771. [[NSNotificationCenter defaultCenter] postNotificationName:@"didAlert" object:@{@"alert":self.alertController}];
  772. [self presentViewController:self.alertController animated:YES completion:nil];
  773. }
  774. //阅读回执跳转
  775. - (void)chatBarMoreFunctionReadReceipt
  776. {
  777. self.readReceiptControl = [[EMReadReceiptMsgViewController alloc]init];
  778. self.readReceiptControl.delegate = self;
  779. self.readReceiptControl.modalPresentationStyle = 0;
  780. //[self.navigationController pushViewController:readReceipt animated:NO];
  781. [self presentViewController:self.readReceiptControl animated:NO completion:nil];
  782. }
  783. //阅读回执发送信息
  784. - (void)sendReadReceiptMsg:(NSString *)msg
  785. {
  786. NSString *str = msg;
  787. NSLog(@"\n%@",str);
  788. if (self.conversationModel.emModel.type == EMConversationTypeGroupChat) {
  789. [[EMClient sharedClient].groupManager getGroupSpecificationFromServerWithId:self.conversationModel.emModel.conversationId completion:^(EMGroup *aGroup, EMError *aError) {
  790. NSLog(@"\n -------- sendError: %@",aError);
  791. if (!aError) {
  792. self.group = aGroup;
  793. //是群主才可以发送阅读回执信息
  794. [self _sendTextAction:str ext:@{MSG_EXT_READ_RECEIPT:@"receipt"}];
  795. } else {
  796. [EMAlertController showErrorAlert:@"获取群组失败"];
  797. }
  798. }];
  799. }else {
  800. [self _sendTextAction:str ext:nil];
  801. }
  802. }
  803. - (void)chatBarDidShowMoreViewAction:(BOOL)isKeyBord
  804. {
  805. WS(weakSelf);
  806. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  807. dispatch_async(dispatch_get_main_queue(), ^{
  808. [weakSelf.tableView mas_updateConstraints:^(MASConstraintMaker *make) {
  809. make.bottom.mas_equalTo(weakSelf.chatBar.mas_top);
  810. }];
  811. [weakSelf performSelector:@selector(_scrollToBottomRow) withObject:nil afterDelay:0.1];
  812. });
  813. });
  814. }
  815. #pragma mark - EMChatBarRecordAudioViewDelegate
  816. - (void)chatBarRecordAudioViewStartRecord
  817. {
  818. }
  819. - (void)chatBarRecordAudioViewStopRecord:(NSString *)aPath
  820. timeLength:(NSInteger)aTimeLength
  821. {
  822. EMVoiceMessageBody *body = [[EMVoiceMessageBody alloc] initWithLocalPath:aPath displayName:@"audio"];
  823. body.duration = (int)aTimeLength;
  824. if(body.duration < 1){
  825. [self showHint:@"按键时间太短."];
  826. return;
  827. }
  828. [self _sendMessageWithBody:body ext:nil isUpload:YES];
  829. }
  830. - (void)chatBarRecordAudioViewCancelRecord
  831. {
  832. }
  833. #pragma mark - EMChatBarEmoticonViewDelegate
  834. - (void)didSelectedEmoticonModel:(EMEmoticonModel *)aModel
  835. {
  836. if (aModel.type == EMEmotionTypeEmoji) {
  837. [self.chatBar inputViewAppendText:aModel.name];
  838. } if (aModel.type == EMEmotionTypeGif) {
  839. NSDictionary *ext = @{MSG_EXT_GIF:@(YES), MSG_EXT_GIF_ID:aModel.eId};
  840. [self _sendTextAction:aModel.name ext:ext];
  841. }
  842. }
  843. - (void)didChatBarEmoticonViewSendAction
  844. {
  845. [self _sendTextAction:self.chatBar.textView.text ext:nil];
  846. }
  847. #pragma mark - EMMessageCellDelegate
  848. //阅读回执详情
  849. - (void)messageReadReceiptDetil:(EMMessageCell *)aCell
  850. {
  851. self.readReceiptControl = [[EMReadReceiptMsgViewController alloc] initWithMessageCell:aCell groupId:self.conversationModel.emModel.conversationId];
  852. self.readReceiptControl.modalPresentationStyle = 0;
  853. //[self.navigationController pushViewController:readReceiptControl animated:NO];
  854. [self presentViewController:self.readReceiptControl animated:NO completion:nil];
  855. }
  856. - (void)messageCellDidSelected:(EMMessageCell *)aCell
  857. {
  858. if (aCell.model.type == EMMessageTypeImage) {
  859. [self _imageMessageCellDidSelected:aCell];
  860. } else if (aCell.model.type == EMMessageTypeLocation) {
  861. [self _locationMessageCellDidSelected:aCell];
  862. } else if (aCell.model.type == EMMessageTypeVoice) {
  863. [self _audioMessageCellDidSelected:aCell];
  864. } else if (aCell.model.type == EMMessageTypeVideo) {
  865. [self _videoMessageCellDidSelected:aCell];
  866. } else if (aCell.model.type == EMMessageTypeFile) {
  867. [self _fileMessageCellDidSelected:aCell];
  868. } else if (aCell.model.type == EMMessageTypeExtCall) {
  869. [self _callMessageCellDidSelected:aCell];
  870. } else if (aCell.model.type == EMMessageTypeExtApp) {
  871. [self appPushWithDictionary:aCell.model.emModel.ext];
  872. } else if (aCell.model.type == EMMessageTypeText) {
  873. }
  874. }
  875. - (void)messageClickUserIcon:(EMMessageCell *)aCell
  876. {
  877. WS(weakSelf);
  878. EMMessage * eModel = (EMMessage *)aCell.model.emModel;
  879. if (self.chatType == ChatType_SingleChat) {
  880. if (eModel.direction == EMMessageDirectionSend){
  881. self.UserId = [AppUserModel sharedAppUserModel].Id;
  882. }else{
  883. self.UserId = self.toUserId;
  884. }
  885. }else{
  886. [self.groupUserInfoArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  887. if ([obj isKindOfClass:[NSDictionary class]]) {
  888. if ([[obj objectForKey:@"ImId"] integerValue] == [eModel.from integerValue]) {
  889. weakSelf.UserId = [[obj objectForKey:@"UserId"] integerValue];
  890. }
  891. }
  892. }];
  893. }
  894. MailListDetailVC * vc = [MailListDetailVC initMailListDetailVC];
  895. vc.indexId = self.UserId;
  896. [self.navigationController pushViewController:vc animated:YES];
  897. }
  898. - (void)appPushWithDictionary:(NSDictionary *)dict
  899. {
  900. WS(weakSelf);
  901. CollectModelType type = [[dict objectForKey:@"app_type"] intValue];
  902. NSInteger sourceUserId = [[dict objectForKey:@"app_sourceUserId"] integerValue];
  903. NSInteger Id = [[dict objectForKey:@"app_id"] integerValue];
  904. NSString * title = [dict objectForKey:@"app_title"];
  905. NSString * url = [dict objectForKey:@"app_url"];
  906. switch (type) {
  907. case CollectModel_Group:
  908. {
  909. TDGroupInfoListVC * vc = [TDGroupInfoListVC initTDGroupInfoListVC];
  910. vc.GroupId = Id;
  911. vc.titleStr = title;
  912. [self.navigationController pushViewController:vc animated:YES];
  913. }break;
  914. case CollectModel_file:{
  915. DownFileViewController * vc = [[DownFileViewController alloc] init];
  916. FlowAttachmentsModel * model = [[FlowAttachmentsModel alloc] init];
  917. model.Title = title;
  918. model.SoureId = Id;
  919. model.Url = url;
  920. model.MinUrl = dict[@"app_min_url"];
  921. vc.model = model;
  922. [self.navigationController pushViewController:vc animated:YES];
  923. }break;
  924. case CollectModel_Image:{
  925. DownFileViewController * vc = [[DownFileViewController alloc] init];
  926. FlowAttachmentsModel * model = [[FlowAttachmentsModel alloc] init];
  927. model.Title = title;
  928. model.SoureId = Id;
  929. model.Url = url;
  930. model.MinUrl = dict[@"app_min_url"];
  931. vc.model = model;
  932. [self.navigationController pushViewController:vc animated:YES];
  933. }break;
  934. case CollectModel_Aritle:{
  935. SHOWLOADING
  936. [[HttpManager sharedHttpManager] GETWithUrl:[NSString stringWithFormat:@"%@%ld",Article_Detail_Get,(long)Id] parameters:@{} success:^(id _Nonnull responseObject) {
  937. REMOVESHOW;
  938. Item *itemModel = [[Item alloc]initWithDictionary:responseObject error:nil];
  939. HomeDetailController *homeDetail = [[HomeDetailController alloc] init];
  940. [homeDetail loadCurrentModel:itemModel];
  941. [weakSelf.navigationController pushViewController:homeDetail animated:YES];
  942. } failure:^(NSError * _Nonnull error) {
  943. SHOWERROR([ZYCTool handerResultData:error]);
  944. }];
  945. }break;
  946. case CollectModel_Text:{
  947. SHOWLOADING
  948. [[HttpManager sharedHttpManager] GETWithUrl:[NSString stringWithFormat:@"%@%ld",Article_Detail_Get,(long)Id] parameters:@{} success:^(id _Nonnull responseObject) {
  949. REMOVESHOW;
  950. Item *itemModel = [[Item alloc]initWithDictionary:responseObject error:nil];
  951. HomeDetailController *homeDetail = [[HomeDetailController alloc] init];
  952. [homeDetail loadCurrentModel:itemModel];
  953. [weakSelf.navigationController pushViewController:homeDetail animated:YES];
  954. } failure:^(NSError * _Nonnull error) {
  955. SHOWERROR([ZYCTool handerResultData:error]);
  956. }];
  957. }break;
  958. case CollectModel_Notice:{
  959. MyTDTopicDetailVC * vc = [MyTDTopicDetailVC initMyTDTopicDetailVC];
  960. vc.type = CollectModel_Notice;
  961. vc.Id = Id;
  962. [self.navigationController pushViewController:vc animated:YES];
  963. }break;
  964. case CollectModel_Toipc:{
  965. MyTDTopicDetailVC * vc = [MyTDTopicDetailVC initMyTDTopicDetailVC];
  966. vc.type = CollectModel_Toipc;
  967. vc.Id = Id;
  968. [self.navigationController pushViewController:vc animated:YES];
  969. }break;
  970. case CollectModel_NewTopic:{
  971. MyTDTopicDetailVC * vc = [MyTDTopicDetailVC initMyTDTopicDetailVC];
  972. vc.type = CollectModel_NewTopic;
  973. vc.Id = Id;
  974. [self.navigationController pushViewController:vc animated:YES];
  975. }break;
  976. case CollectModel_NoteBook:{
  977. MyTDTopicDetailVC * vc = [MyTDTopicDetailVC initMyTDTopicDetailVC];
  978. vc.type = CollectModel_NoteBook;
  979. vc.Id = Id;
  980. [self.navigationController pushViewController:vc animated:YES];
  981. }break;
  982. case CollectModel_Collect:{
  983. }break;
  984. case CollectModel_CollectFile:{
  985. if (sourceUserId == [AppUserModel sharedAppUserModel].Id || sourceUserId == 0) {
  986. MyFavoriteVC *vc = [MyFavoriteVC initMyFavoriteVC];
  987. vc.listType = Id == 0 ? MyFavoriteListLevelTypeA : MyFavoriteListLevelTypeB;
  988. vc.FolderId = Id;
  989. vc.myTitle = title;
  990. [self.navigationController pushViewController:vc animated:YES];
  991. }else{
  992. OtherFavoriteVC *vc = [OtherFavoriteVC initOtherFavoriteVC];
  993. vc.listType = Id == 0 ? MyFavoriteListLevelTypeA : MyFavoriteListLevelTypeB;
  994. vc.FolderId = Id;
  995. vc.myTitle = title;
  996. vc.VisitUserId = sourceUserId;
  997. [self.navigationController pushViewController:vc animated:YES];
  998. }
  999. }break;
  1000. case CollectModel_NoteFile:{
  1001. if (sourceUserId == [AppUserModel sharedAppUserModel].Id || sourceUserId == 0) {
  1002. NoteBookVC *vc = [NoteBookVC initNoteBookVC];
  1003. vc.listType = Id == 0 ? MyFavoriteListLevelTypeA : MyFavoriteListLevelTypeB;
  1004. vc.FolderId = Id;
  1005. vc.myTitle = title;
  1006. vc.VisitUserId = 0;
  1007. [self.navigationController pushViewController:vc animated:YES];
  1008. }else{
  1009. OtherNoteBookVC *vc = [OtherNoteBookVC initOtherNoteBookVC];
  1010. vc.listType = Id == 0 ? MyFavoriteListLevelTypeA : MyFavoriteListLevelTypeB;
  1011. vc.FolderId = Id;
  1012. vc.myTitle = title;
  1013. vc.VisitUserId = sourceUserId;
  1014. [self.navigationController pushViewController:vc animated:YES];
  1015. }
  1016. }break;
  1017. case CollectModel_InterMail:{
  1018. MyTDTopicDetailVC * vc = [MyTDTopicDetailVC initMyTDTopicDetailVC];
  1019. vc.type = CollectModel_InterMail;
  1020. vc.Id = Id;
  1021. [self.navigationController pushViewController:vc animated:YES];
  1022. }break;
  1023. case CollectModel_meetDetail:{
  1024. WorkFlowDetailsController *vc = [[WorkFlowDetailsController alloc] initWithId:Id];
  1025. [self.navigationController pushViewController:vc animated:YES];
  1026. }break;
  1027. case CollectModel_work:{
  1028. MyApprovalPageDetail * vc = [[MyApprovalPageDetail alloc]init];
  1029. vc.pageType = Type_ONEC;
  1030. vc.indexId = Id;
  1031. vc.title = title;
  1032. vc.TodoId = Id;
  1033. [self.navigationController pushViewController:vc animated:YES];
  1034. }break;
  1035. case CollectModel_meetMian:{
  1036. MyTDTopicDetailVC * vc = [MyTDTopicDetailVC initMyTDTopicDetailVC];
  1037. vc.type = CollectModel_meetMian;
  1038. vc.Id = Id;
  1039. [self.navigationController pushViewController:vc animated:YES];
  1040. }break;
  1041. default:
  1042. break;
  1043. }
  1044. }
  1045. - (void)_imageMessageCellDidSelected:(EMMessageCell *)aCell
  1046. {
  1047. __weak typeof(self) weakself = self;
  1048. void (^downloadThumbBlock)(EMMessageModel *aModel) = ^(EMMessageModel *aModel) {
  1049. [weakself showHint:@"获取缩略图..."];
  1050. [[EMClient sharedClient].chatManager downloadMessageThumbnail:aModel.emModel progress:nil completion:^(EMMessage *message, EMError *error) {
  1051. if (!error) {
  1052. [weakself.tableView reloadData];
  1053. }
  1054. }];
  1055. };
  1056. EMImageMessageBody *body = (EMImageMessageBody*)aCell.model.emModel.body;
  1057. BOOL isCustomDownload = !([EMClient sharedClient].options.isAutoTransferMessageAttachments);
  1058. if (body.thumbnailDownloadStatus == EMDownloadStatusFailed) {
  1059. if (isCustomDownload) {
  1060. [self _showCustomTransferFileAlertView];
  1061. } else {
  1062. downloadThumbBlock(aCell.model);
  1063. }
  1064. return;
  1065. }
  1066. BOOL isAutoDownloadThumbnail = [EMClient sharedClient].options.isAutoDownloadThumbnail;
  1067. if (body.thumbnailDownloadStatus == EMDownloadStatusPending && !isAutoDownloadThumbnail) {
  1068. downloadThumbBlock(aCell.model);
  1069. return;
  1070. }
  1071. if (body.downloadStatus == EMDownloadStatusSucceed) {
  1072. UIImage *image = [UIImage imageWithContentsOfFile:body.localPath];
  1073. if (image) {
  1074. [[EMImageBrowser sharedBrowser] showImages:@[image] fromController:self];
  1075. return;
  1076. }
  1077. }
  1078. if (isCustomDownload) {
  1079. [self _showCustomTransferFileAlertView];
  1080. return;
  1081. }
  1082. [self showHudInView:self.view hint:@"下载原图..."];
  1083. [[EMClient sharedClient].chatManager downloadMessageAttachment:aCell.model.emModel progress:nil completion:^(EMMessage *message, EMError *error) {
  1084. [weakself hideHud];
  1085. if (error) {
  1086. [EMAlertController showErrorAlert:@"下载原图失败"];
  1087. } else {
  1088. if (message.direction == EMMessageDirectionReceive && !message.isReadAcked) {
  1089. [[EMClient sharedClient].chatManager sendMessageReadAck:message.messageId toUser:message.conversationId completion:nil];
  1090. }
  1091. NSString *localPath = [(EMImageMessageBody *)message.body localPath];
  1092. UIImage *image = [UIImage imageWithContentsOfFile:localPath];
  1093. if (image) {
  1094. [[EMImageBrowser sharedBrowser] showImages:@[image] fromController:self];
  1095. } else {
  1096. [EMAlertController showErrorAlert:@"获取原图失败"];
  1097. }
  1098. }
  1099. }];
  1100. }
  1101. - (void)_locationMessageCellDidSelected:(EMMessageCell *)aCell
  1102. {
  1103. EMLocationMessageBody *body = (EMLocationMessageBody *)aCell.model.emModel.body;
  1104. EMLocationViewController *controller = [[EMLocationViewController alloc] initWithLocation:CLLocationCoordinate2DMake(body.latitude, body.longitude)];
  1105. UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
  1106. [self.navigationController presentViewController:navController animated:YES completion:nil];
  1107. }
  1108. - (void)_audioMessageCellDidSelected:(EMMessageCell *)aCell
  1109. {
  1110. if (aCell.model.isPlaying) {
  1111. [[EMAudioPlayerHelper sharedHelper] stopPlayer];
  1112. aCell.model.isPlaying = NO;
  1113. [self.tableView reloadData];
  1114. return;
  1115. }
  1116. EMVoiceMessageBody *body = (EMVoiceMessageBody*)aCell.model.emModel.body;
  1117. if (body.downloadStatus == EMDownloadStatusDownloading) {
  1118. [EMAlertController showInfoAlert:@"正在下载语音,稍后点击"];
  1119. return;
  1120. }
  1121. __weak typeof(self) weakself = self;
  1122. void (^playBlock)(EMMessageModel *aModel) = ^(EMMessageModel *aModel) {
  1123. id model = [EMAudioPlayerHelper sharedHelper].model;
  1124. if (model && [model isKindOfClass:[EMMessageModel class]]) {
  1125. EMMessageModel *oldModel = (EMMessageModel *)model;
  1126. if (oldModel.isPlaying) {
  1127. oldModel.isPlaying = NO;
  1128. }
  1129. }
  1130. if (!aModel.emModel.isReadAcked) {
  1131. [[EMClient sharedClient].chatManager sendMessageReadAck:aModel.emModel.messageId toUser:aModel.emModel.conversationId completion:nil];
  1132. }
  1133. aModel.isPlaying = YES;
  1134. if (!aModel.emModel.isRead) {
  1135. aModel.emModel.isRead = YES;
  1136. }
  1137. [weakself.tableView reloadData];
  1138. [[EMAudioPlayerHelper sharedHelper] startPlayerWithPath:body.localPath model:aModel AVAudioSessionCategory:AVAudioSessionCategoryPlayback completion:^(NSError * _Nonnull error) {
  1139. aModel.isPlaying = NO;
  1140. [weakself.tableView reloadData];
  1141. }];
  1142. };
  1143. if (body.downloadStatus == EMDownloadStatusSucceed) {
  1144. playBlock(aCell.model);
  1145. return;
  1146. }
  1147. if (![EMClient sharedClient].options.isAutoTransferMessageAttachments) {
  1148. [self _showCustomTransferFileAlertView];
  1149. return;
  1150. }
  1151. [self showHudInView:self.view hint:@"下载语音..."];
  1152. [[EMClient sharedClient].chatManager downloadMessageAttachment:aCell.model.emModel progress:nil completion:^(EMMessage *message, EMError *error) {
  1153. [weakself hideHud];
  1154. if (error) {
  1155. [EMAlertController showErrorAlert:@"下载语音失败"];
  1156. } else {
  1157. playBlock(aCell.model);
  1158. }
  1159. }];
  1160. }
  1161. - (void)_videoMessageCellDidSelected:(EMMessageCell *)aCell
  1162. {
  1163. EMVideoMessageBody *body = (EMVideoMessageBody*)aCell.model.emModel.body;
  1164. NSFileManager *fileManager = [NSFileManager defaultManager];
  1165. BOOL isCustomDownload = !([EMClient sharedClient].options.isAutoTransferMessageAttachments);
  1166. if (body.thumbnailDownloadStatus == EMDownloadStatusFailed || ![fileManager fileExistsAtPath:body.thumbnailLocalPath]) {
  1167. [self showHint:@"下载缩略图"];
  1168. if (!isCustomDownload) {
  1169. [[EMClient sharedClient].chatManager downloadMessageThumbnail:aCell.model.emModel progress:nil completion:nil];
  1170. }
  1171. }
  1172. if (body.downloadStatus == EMDownloadStatusDownloading) {
  1173. [EMAlertController showInfoAlert:@"正在下载视频,稍后点击"];
  1174. return;
  1175. }
  1176. void (^playBlock)(NSString *aPath) = ^(NSString *aPathe) {
  1177. NSURL *videoURL = [NSURL fileURLWithPath:aPathe];
  1178. AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init];
  1179. playerViewController.player = [AVPlayer playerWithURL:videoURL];
  1180. playerViewController.videoGravity = AVLayerVideoGravityResizeAspect;
  1181. playerViewController.showsPlaybackControls = YES;
  1182. [self presentViewController:playerViewController animated:YES completion:^{
  1183. [playerViewController.player play];
  1184. }];
  1185. };
  1186. if (body.downloadStatus == EMDownloadStatusSuccessed && [fileManager fileExistsAtPath:body.localPath]) {
  1187. playBlock(body.localPath);
  1188. return;
  1189. }
  1190. if (isCustomDownload) {
  1191. [self _showCustomTransferFileAlertView];
  1192. } else {
  1193. [self showHudInView:self.view hint:@"下载视频..."];
  1194. __weak typeof(self) weakself = self;
  1195. [[EMClient sharedClient].chatManager downloadMessageAttachment:aCell.model.emModel progress:nil completion:^(EMMessage *message, EMError *error) {
  1196. [weakself hideHud];
  1197. if (error) {
  1198. [EMAlertController showErrorAlert:@"下载视频失败"];
  1199. } else {
  1200. if (!message.isReadAcked) {
  1201. [[EMClient sharedClient].chatManager sendMessageReadAck:message.messageId toUser:message.conversationId completion:nil];
  1202. }
  1203. playBlock([(EMVideoMessageBody*)message.body localPath]);
  1204. }
  1205. }];
  1206. }
  1207. }
  1208. - (void)_fileMessageCellDidSelected:(EMMessageCell *)aCell
  1209. {
  1210. WS(weakSelf);
  1211. [[EMClient sharedClient].chatManager downloadMessageAttachment:aCell.model.emModel progress:nil completion:^(EMMessage *message, EMError *error) {
  1212. [weakSelf hideHud];
  1213. if (error) {
  1214. [EMAlertController showErrorAlert:@"下载文件失败"];
  1215. } else {
  1216. if (message.direction == EMMessageDirectionReceive && !message.isReadAcked) {
  1217. [[EMClient sharedClient].chatManager sendMessageReadAck:message.messageId toUser:message.conversationId completion:nil];
  1218. }
  1219. NSString *remotePath = [(EMImageMessageBody *)message.body remotePath];
  1220. NSString *displayName = [(EMImageMessageBody *)message.body displayName];
  1221. dispatch_async(dispatch_get_main_queue(), ^{
  1222. EMChatFileShowVC * vc = [EMChatFileShowVC initEMChatFileShowVC];
  1223. vc.fileUrl = remotePath;
  1224. vc.titleStr = displayName;
  1225. [weakSelf.navigationController pushViewController:vc animated:YES];
  1226. });
  1227. }
  1228. }];
  1229. }
  1230. - (void)_callMessageCellDidSelected:(EMMessageCell *)aCell
  1231. {
  1232. [[NSNotificationCenter defaultCenter] postNotificationName:CALL_SELECTCONFERENCECELL object:aCell.model.emModel];
  1233. }
  1234. - (void)messageCellDidLongPress:(EMMessageCell *)aCell
  1235. {
  1236. self.menuIndexPath = [self.tableView indexPathForCell:aCell];
  1237. [self _showMenuViewController:aCell model:aCell.model];
  1238. }
  1239. - (void)messageCellDidResend:(EMMessageModel *)aModel
  1240. {
  1241. if (aModel.emModel.status != EMMessageStatusFailed && aModel.emModel.status != EMMessageStatusPending) {
  1242. return;
  1243. }
  1244. __weak typeof(self) weakself = self;
  1245. [[[EMClient sharedClient] chatManager] resendMessage:aModel.emModel progress:nil completion:^(EMMessage *message, EMError *error) {
  1246. [weakself.tableView reloadData];
  1247. }];
  1248. [self.tableView reloadData];
  1249. }
  1250. #pragma mark - EMMultiDevicesDelegate
  1251. - (void)multiDevicesGroupEventDidReceive:(EMMultiDevicesEvent)aEvent
  1252. groupId:(NSString *)aGroupId
  1253. ext:(id)aExt
  1254. {
  1255. if (aEvent == EMMultiDevicesEventGroupDestroy || aEvent == EMMultiDevicesEventGroupLeave) {
  1256. if ([self.conversationModel.emModel.conversationId isEqualToString:aGroupId]) {
  1257. [self.navigationController popToViewController:self animated:YES];
  1258. [self.navigationController popViewControllerAnimated:YES];
  1259. }
  1260. }
  1261. }
  1262. #pragma mark - EMChatManagerDelegate
  1263. - (BOOL)_isNeedSendReadAckForMessage:(EMMessage *)aMessage
  1264. isMarkRead:(BOOL)aIsMarkRead
  1265. {
  1266. if (!self.isViewDidAppear || aMessage.direction == EMMessageDirectionSend || aMessage.isReadAcked || aMessage.chatType != EMChatTypeChat) {
  1267. return NO;
  1268. }
  1269. EMMessageBody *body = aMessage.body;
  1270. if (!aIsMarkRead && (body.type == EMMessageBodyTypeVideo || body.type == EMMessageBodyTypeVoice || body.type == EMMessageBodyTypeImage)) {
  1271. return NO;
  1272. }
  1273. return YES;
  1274. }
  1275. - (void)messagesDidReceive:(NSArray *)aMessages
  1276. {
  1277. __weak typeof(self) weakself = self;
  1278. dispatch_async(self.msgQueue, ^{
  1279. NSString *conId = weakself.conversationModel.emModel.conversationId;
  1280. NSMutableArray *msgArray = [[NSMutableArray alloc] init];
  1281. for (int i = 0; i < [aMessages count]; i++) {
  1282. EMMessage *msg = aMessages[i];
  1283. if (![msg.conversationId isEqualToString:conId]) {
  1284. continue;
  1285. }
  1286. if (msg.isNeedGroupAck && !msg.isReadAcked) {
  1287. [[EMClient sharedClient].chatManager sendGroupMessageReadAck:msg.messageId toGroup:msg.conversationId content:@"123" completion:^(EMError *error) {
  1288. if (error) {
  1289. NSLog(@"\n ------ error %@",error.errorDescription);
  1290. }
  1291. }];
  1292. }
  1293. if ([weakself _isNeedSendReadAckForMessage:msg isMarkRead:NO]) {
  1294. [[EMClient sharedClient].chatManager sendMessageReadAck:msg.messageId toUser:msg.conversationId completion:nil];
  1295. }
  1296. [weakself.conversationModel.emModel markMessageAsReadWithId:msg.messageId error:nil];
  1297. [msgArray addObject:msg];
  1298. }
  1299. NSArray *formated = [weakself _formatMessages:msgArray];
  1300. [weakself.dataArray addObjectsFromArray:formated];
  1301. dispatch_async(dispatch_get_main_queue(), ^{
  1302. [weakself.tableView reloadData];
  1303. [weakself _scrollToBottomRow];
  1304. });
  1305. });
  1306. }
  1307. - (void)messagesDidRecall:(NSArray *)aMessages {
  1308. __block NSMutableArray *sameObject = [NSMutableArray array];
  1309. [aMessages enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  1310. EMMessage *msg = (EMMessage *)obj;
  1311. [self.dataArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  1312. if ([obj isKindOfClass:[EMMessageModel class]]) {
  1313. EMMessageModel *model = (EMMessageModel *)obj;
  1314. if ([model.emModel.messageId isEqualToString:msg.messageId]) {
  1315. // 如果上一行是时间,且下一行也是时间
  1316. if (idx - 1 >= 0) {
  1317. id nextMessage = nil;
  1318. id prevMessage = [self.dataArray objectAtIndex:(idx - 1)];
  1319. if (idx + 1 < [self.dataArray count]) {
  1320. nextMessage = [self.dataArray objectAtIndex:(idx + 1)];
  1321. }
  1322. if ((!nextMessage
  1323. || [nextMessage isKindOfClass:[NSString class]])
  1324. && [prevMessage isKindOfClass:[NSString class]]) {
  1325. [sameObject addObject:prevMessage];
  1326. }
  1327. }
  1328. [sameObject addObject:model];
  1329. *stop = YES;
  1330. }
  1331. }
  1332. }];
  1333. }];
  1334. if (sameObject.count > 0) {
  1335. for (id obj in sameObject) {
  1336. [self.dataArray removeObject:obj];
  1337. }
  1338. [self.tableView reloadData];
  1339. }
  1340. }
  1341. //为了从home会话列表切进来触发 群组阅读回执 和 消息已读回执
  1342. - (void)sendDidReadReceipt
  1343. {
  1344. __weak typeof(self) weakself = self;
  1345. NSString *conId = weakself.conversationModel.emModel.conversationId;
  1346. void (^block)(NSArray *aMessages, EMError *aError) = ^(NSArray *aMessages, EMError *aError) {
  1347. NSLog(@"\n-------unread: %d messageCount: %lu msgid: %@",self.conversationModel.emModel.unreadMessagesCount,(unsigned long)[aMessages count],self.moreMsgId);
  1348. if (!aError && [aMessages count]) {
  1349. for (int i = 0; i < [aMessages count]; i++) {
  1350. EMMessage *msg = aMessages[i];
  1351. if (![msg.conversationId isEqualToString:conId]) {
  1352. continue;
  1353. }
  1354. if (msg.isNeedGroupAck && !msg.isReadAcked) {
  1355. [[EMClient sharedClient].chatManager sendGroupMessageReadAck:msg.messageId toGroup:msg.conversationId content:@"123" completion:^(EMError *error) {
  1356. if (error) {
  1357. NSLog(@"\n ------ error %@",error.errorDescription);
  1358. }
  1359. }];
  1360. }
  1361. if ([weakself _isNeedSendReadAckForMessage:msg isMarkRead:NO] && (weakself.conversationModel.emModel.type == EMConversationTypeChat)) {
  1362. [[EMClient sharedClient].chatManager sendMessageReadAck:msg.messageId toUser:msg.conversationId completion:nil];
  1363. [weakself.conversationModel.emModel markMessageAsReadWithId:msg.messageId error:nil];
  1364. }
  1365. }
  1366. }
  1367. };
  1368. [self.conversationModel.emModel loadMessagesStartFromId:self.moreMsgId count:self.conversationModel.emModel.unreadMessagesCount searchDirection:EMMessageSearchDirectionUp completion:block];
  1369. }
  1370. //收到群消息已读回执
  1371. - (void)groupMessageDidRead:(EMMessage *)aMessage groupAcks:(NSArray *)aGroupAcks
  1372. {
  1373. EMMessageModel *msgModel;
  1374. EMGroupMessageAck *msgAck = aGroupAcks[0];
  1375. for (int i=0; i<[self.dataArray count]; i++) {
  1376. if([self.dataArray[i] isKindOfClass:[EMMessageModel class]]){
  1377. msgModel = (EMMessageModel *)self.dataArray[i];
  1378. }else{
  1379. continue;
  1380. }
  1381. if([msgModel.emModel.messageId isEqualToString:msgAck.messageId]){
  1382. msgModel.readReceiptCount = [NSString stringWithFormat:@"阅读回执,已读用户(%d)",msgModel.emModel.groupAckCount];
  1383. msgModel.emModel.isReadAcked = YES;
  1384. [[EMClient sharedClient].chatManager sendMessageReadAck:msgModel.emModel.messageId toUser:msgModel.emModel.conversationId completion:nil];
  1385. [self.dataArray setObject:msgModel atIndexedSubscript:i];
  1386. __weak typeof(self) weakself = self;
  1387. dispatch_async(dispatch_get_main_queue(), ^{
  1388. [weakself.tableView reloadData];
  1389. [weakself _scrollToBottomRow];
  1390. });
  1391. break;
  1392. }
  1393. }
  1394. }
  1395. // 收到已读回执
  1396. - (void)messagesDidRead:(NSArray *)aMessages
  1397. {
  1398. __weak typeof(self) weakself = self;
  1399. dispatch_async(self.msgQueue, ^{
  1400. NSString *conId = weakself.conversationModel.emModel.conversationId;
  1401. __block BOOL isReladView = NO;
  1402. for (EMMessage *message in aMessages) {
  1403. if (![conId isEqualToString:message.conversationId]){
  1404. continue;
  1405. }
  1406. [weakself.dataArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  1407. if ([obj isKindOfClass:[EMMessageModel class]]) {
  1408. EMMessageModel *model = (EMMessageModel *)obj;
  1409. if ([model.emModel.messageId isEqualToString:message.messageId]) {
  1410. model.emModel.isReadAcked = YES;
  1411. isReladView = YES;
  1412. *stop = YES;
  1413. }
  1414. }
  1415. }];
  1416. }
  1417. BOOL changeRead = NO;
  1418. NSInteger msgCount = weakself.dataArray.count - 1;
  1419. for (NSInteger i = msgCount; i >= 0; i --) {
  1420. if ([weakself.dataArray[i] isKindOfClass:[EMMessageModel class]]) {
  1421. EMMessageModel *model = (EMMessageModel *)weakself.dataArray[i];
  1422. if (model.emModel.isReadAcked == YES)
  1423. {
  1424. changeRead = YES;
  1425. }
  1426. if (changeRead) {
  1427. model.emModel.isReadAcked = YES;
  1428. }
  1429. }
  1430. }
  1431. if (isReladView) {
  1432. dispatch_async(dispatch_get_main_queue(), ^{
  1433. [weakself.tableView reloadData];
  1434. });
  1435. }
  1436. });
  1437. }
  1438. - (void)messageStatusDidChange:(EMMessage *)aMessage
  1439. error:(EMError *)aError
  1440. {
  1441. __weak typeof(self) weakself = self;
  1442. dispatch_async(self.msgQueue, ^{
  1443. NSString *conId = weakself.conversationModel.emModel.conversationId;
  1444. if (![conId isEqualToString:aMessage.conversationId]){
  1445. return ;
  1446. }
  1447. __block NSUInteger index = NSNotFound;
  1448. __block EMMessageModel *reloadModel = nil;
  1449. [self.dataArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  1450. if ([obj isKindOfClass:[EMMessageModel class]]) {
  1451. EMMessageModel *model = (EMMessageModel *)obj;
  1452. if ([model.emModel.messageId isEqualToString:aMessage.messageId]) {
  1453. reloadModel = model;
  1454. index = idx;
  1455. *stop = YES;
  1456. }
  1457. }
  1458. }];
  1459. if (index != NSNotFound) {
  1460. dispatch_async(dispatch_get_main_queue(), ^{
  1461. [weakself.dataArray replaceObjectAtIndex:index withObject:reloadModel];
  1462. [weakself.tableView beginUpdates];
  1463. [weakself.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
  1464. [weakself.tableView endUpdates];
  1465. });
  1466. }
  1467. });
  1468. }
  1469. - (void)cmdMessagesDidReceive:(NSArray *)aCmdMessages
  1470. {
  1471. __weak typeof(self) weakself = self;
  1472. dispatch_async(self.msgQueue, ^{
  1473. NSString *conId = weakself.conversationModel.emModel.conversationId;
  1474. for (EMMessage *message in aCmdMessages) {
  1475. if (![conId isEqualToString:message.conversationId]) {
  1476. continue;
  1477. }
  1478. EMCmdMessageBody *body = (EMCmdMessageBody *)message.body;
  1479. NSString *str = @"";
  1480. if ([body.action isEqualToString:MSG_TYPING_BEGIN]) {
  1481. str = @"正在输入...";
  1482. }
  1483. dispatch_async(dispatch_get_main_queue(), ^{
  1484. self.titleDetailLabel.text = str;
  1485. });
  1486. }
  1487. });
  1488. }
  1489. #pragma mark - EMGroupManagerDelegate
  1490. - (void)didLeaveGroup:(EMGroup *)aGroup
  1491. reason:(EMGroupLeaveReason)aReason
  1492. {
  1493. EMConversation *conversation = self.conversationModel.emModel;
  1494. if (conversation.type == EMChatTypeGroupChat && [aGroup.groupId isEqualToString:conversation.conversationId]) {
  1495. [self.navigationController popToViewController:self animated:YES];
  1496. [self.navigationController popViewControllerAnimated:YES];
  1497. }
  1498. }
  1499. #pragma mark - EMChatroomManagerDelegate
  1500. //有用户加入聊天室
  1501. - (void)userDidJoinChatroom:(EMChatroom *)aChatroom
  1502. user:(NSString *)aUsername
  1503. {
  1504. EMConversation *conversation = self.conversationModel.emModel;
  1505. if (conversation.type == EMChatTypeChatRoom && [aChatroom.chatroomId isEqualToString:conversation.conversationId]) {
  1506. NSString *str = [NSString stringWithFormat:@"%@ 进入聊天室", aUsername];
  1507. [self showHint:str];
  1508. }
  1509. }
  1510. - (void)userDidLeaveChatroom:(EMChatroom *)aChatroom
  1511. user:(NSString *)aUsername
  1512. {
  1513. EMConversation *conversation = self.conversationModel.emModel;
  1514. if (conversation.type == EMChatTypeChatRoom && [aChatroom.chatroomId isEqualToString:conversation.conversationId]) {
  1515. NSString *str = [NSString stringWithFormat:@"%@ 离开聊天室", aUsername];
  1516. [self showHint:str];
  1517. }
  1518. }
  1519. - (void)didDismissFromChatroom:(EMChatroom *)aChatroom
  1520. reason:(EMChatroomBeKickedReason)aReason
  1521. {
  1522. EMConversation *conversation = self.conversationModel.emModel;
  1523. if (conversation.type == EMChatTypeChatRoom && [aChatroom.chatroomId isEqualToString:conversation.conversationId]) {
  1524. [self.navigationController popToViewController:self animated:YES];
  1525. [self.navigationController popViewControllerAnimated:YES];
  1526. }
  1527. }
  1528. #pragma mark - KeyBoard
  1529. - (void)keyBoardWillShow:(NSNotification *)note
  1530. {
  1531. // 获取用户信息
  1532. NSDictionary *userInfo = [NSDictionary dictionaryWithDictionary:note.userInfo];
  1533. // 获取键盘高度
  1534. CGRect keyBoardBounds = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
  1535. CGFloat keyBoardHeight = keyBoardBounds.size.height;
  1536. // 获取键盘动画时间
  1537. CGFloat animationTime = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
  1538. // 定义好动作
  1539. WS(weakSelf);
  1540. void (^animation)(void) = ^void(void) {
  1541. [weakSelf.chatBar mas_updateConstraints:^(MASConstraintMaker *make) {
  1542. if (@available(iOS 11.0, *)) {
  1543. make.bottom.mas_equalTo(weakSelf.view.mas_safeAreaLayoutGuideBottom).offset(-keyBoardHeight + EMVIEWBOTTOMMARGIN);
  1544. } else {
  1545. make.bottom.mas_equalTo(weakSelf.view.mas_bottom).offset(-keyBoardHeight);
  1546. }
  1547. }];
  1548. };
  1549. if (animationTime > 0) {
  1550. [UIView animateWithDuration:animationTime animations:animation completion:^(BOOL finished) {
  1551. [weakSelf _scrollToBottomRow];
  1552. }];
  1553. } else {
  1554. animation();
  1555. }
  1556. }
  1557. - (void)keyBoardWillHide:(NSNotification *)note
  1558. {
  1559. // 获取用户信息
  1560. NSDictionary *userInfo = [NSDictionary dictionaryWithDictionary:note.userInfo];
  1561. // 获取键盘动画时间
  1562. CGFloat animationTime = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
  1563. // 定义好动作
  1564. WS(weakSelf);
  1565. void (^animation)(void) = ^void(void) {
  1566. [weakSelf.chatBar mas_updateConstraints:^(MASConstraintMaker *make) {
  1567. if (@available(iOS 11.0, *)) {
  1568. make.bottom.mas_equalTo(weakSelf.view.mas_safeAreaLayoutGuideBottom);
  1569. } else {
  1570. make.bottom.mas_equalTo(weakSelf.view.mas_bottom);
  1571. }
  1572. }];
  1573. };
  1574. if (animationTime > 0) {
  1575. [UIView animateWithDuration:animationTime animations:animation];
  1576. } else {
  1577. animation();
  1578. }
  1579. if (self.enableTyping) {
  1580. [self _sendEndTyping];
  1581. }
  1582. }
  1583. #pragma mark - NSNotification
  1584. - (UIImagePickerController *)imagePicker
  1585. {
  1586. if (!_imagePicker) {
  1587. _imagePicker = [[UIImagePickerController alloc] init];
  1588. _imagePicker.delegate = self;
  1589. }
  1590. return _imagePicker;
  1591. }
  1592. - (void)handleWillPushCallController:(NSNotification *)aNotif
  1593. {
  1594. [self.imagePicker dismissViewControllerAnimated:YES completion:nil];
  1595. [[EMImageBrowser sharedBrowser] dismissViewController];
  1596. [[EMAudioPlayerHelper sharedHelper] stopPlayer];
  1597. }
  1598. - (void)handleCleanMessages:(NSNotification *)aNotif
  1599. {
  1600. NSString *chatId = aNotif.object;
  1601. if (chatId && [chatId isEqualToString:self.conversationModel.emModel.conversationId]) {
  1602. [self.conversationModel.emModel deleteAllMessages:nil];
  1603. [self.dataArray removeAllObjects];
  1604. [self.tableView reloadData];
  1605. }
  1606. }
  1607. - (void)handleGroupSubjectUpdated:(NSNotification *)aNotif
  1608. {
  1609. EMGroup *group = aNotif.object;
  1610. if (!group) {
  1611. return;
  1612. }
  1613. NSString *groupId = group.groupId;
  1614. if ([groupId isEqualToString:self.conversationModel.emModel.conversationId]) {
  1615. self.conversationModel.name = group.subject;
  1616. self.titleLabel.text = group.subject;
  1617. }
  1618. }
  1619. #pragma mark - Gesture Recognizer
  1620. - (void)handleTapTableViewAction:(UITapGestureRecognizer *)aTap
  1621. {
  1622. if (aTap.state == UIGestureRecognizerStateEnded) {
  1623. [self.view endEditing:YES];
  1624. [self.chatBar clearMoreViewAndSelectedButton];
  1625. [self performSelector:@selector(_scrollToBottomRow) withObject:nil afterDelay:0.1];
  1626. }
  1627. }
  1628. #pragma mark - Private
  1629. - (void)_joinChatroom
  1630. {
  1631. __weak typeof(self) weakself = self;
  1632. [self showHudInView:self.view hint:@"加入聊天室..."];
  1633. [[EMClient sharedClient].roomManager joinChatroom:self.conversationModel.emModel.conversationId completion:^(EMChatroom *aChatroom, EMError *aError) {
  1634. [weakself hideHud];
  1635. if (aError) {
  1636. [EMAlertController showErrorAlert:@"加入聊天室失败"];
  1637. [weakself.navigationController popViewControllerAnimated:YES];
  1638. } else {
  1639. weakself.isFirstLoadMsg = YES;
  1640. [weakself tableViewDidTriggerHeaderRefresh];
  1641. }
  1642. }];
  1643. }
  1644. - (void)_scrollToBottomRow
  1645. {
  1646. if ([self.dataArray count] > 0) {
  1647. NSInteger toRow = self.dataArray.count - 1;
  1648. NSIndexPath *toIndexPath = [NSIndexPath indexPathForRow:toRow inSection:0];
  1649. [self.tableView scrollToRowAtIndexPath:toIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
  1650. }
  1651. }
  1652. - (void)_showCustomTransferFileAlertView
  1653. {
  1654. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"(づ。◕‿‿◕。)づ" message:@"需要自定义实现上传附件方法" preferredStyle:UIAlertControllerStyleAlert];
  1655. UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleCancel handler:nil];
  1656. [alertController addAction:okAction];
  1657. [self presentViewController:alertController animated:YES completion:nil];
  1658. }
  1659. - (NSURL *)_videoConvert2Mp4:(NSURL *)movUrl
  1660. {
  1661. NSURL *mp4Url = nil;
  1662. AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:movUrl options:nil];
  1663. NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];
  1664. if ([compatiblePresets containsObject:AVAssetExportPresetHighestQuality]) {
  1665. AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:avAsset presetName:AVAssetExportPresetHighestQuality];
  1666. NSString *mp4Path = [NSString stringWithFormat:@"%@/%d%d.mp4", [self _getAudioOrVideoPath], (int)[[NSDate date] timeIntervalSince1970], arc4random() % 100000];
  1667. mp4Url = [NSURL fileURLWithPath:mp4Path];
  1668. exportSession.outputURL = mp4Url;
  1669. exportSession.shouldOptimizeForNetworkUse = YES;
  1670. exportSession.outputFileType = AVFileTypeMPEG4;
  1671. dispatch_semaphore_t wait = dispatch_semaphore_create(0l);
  1672. [exportSession exportAsynchronouslyWithCompletionHandler:^{
  1673. switch ([exportSession status]) {
  1674. case AVAssetExportSessionStatusFailed: {
  1675. NSLog(@"failed, error:%@.", exportSession.error);
  1676. } break;
  1677. case AVAssetExportSessionStatusCancelled: {
  1678. NSLog(@"cancelled.");
  1679. } break;
  1680. case AVAssetExportSessionStatusCompleted: {
  1681. NSLog(@"completed.");
  1682. } break;
  1683. default: {
  1684. NSLog(@"others.");
  1685. } break;
  1686. }
  1687. dispatch_semaphore_signal(wait);
  1688. }];
  1689. long timeout = dispatch_semaphore_wait(wait, DISPATCH_TIME_FOREVER);
  1690. if (timeout) {
  1691. NSLog(@"timeout.");
  1692. }
  1693. if (wait) {
  1694. //dispatch_release(wait);
  1695. wait = nil;
  1696. }
  1697. }
  1698. return mp4Url;
  1699. }
  1700. #pragma mark - Menu Controller
  1701. - (UIMenuController *)menuController
  1702. {
  1703. if (_menuController == nil) {
  1704. _menuController = [UIMenuController sharedMenuController];
  1705. }
  1706. return _menuController;
  1707. }
  1708. - (UIMenuItem *)deleteMenuItem
  1709. {
  1710. if (_deleteMenuItem == nil) {
  1711. _deleteMenuItem = [[UIMenuItem alloc] initWithTitle:@"删除" action:@selector(deleteMenuItemAction:)];
  1712. }
  1713. return _deleteMenuItem;
  1714. }
  1715. - (UIMenuItem *)copyMenuItem
  1716. {
  1717. if (_copyMenuItem == nil) {
  1718. _copyMenuItem = [[UIMenuItem alloc] initWithTitle:@"复制" action:@selector(copyMenuItemAction:)];
  1719. }
  1720. return _copyMenuItem;
  1721. }
  1722. - (UIMenuItem *)transpondMenuItem
  1723. {
  1724. if (_transpondMenuItem == nil) {
  1725. _transpondMenuItem = [[UIMenuItem alloc] initWithTitle:@"转发" action:@selector(transpondMenuItemAction:)];
  1726. }
  1727. return _transpondMenuItem;
  1728. }
  1729. - (UIMenuItem *)recallMenuItem
  1730. {
  1731. if (_recallMenuItem == nil) {
  1732. _recallMenuItem = [[UIMenuItem alloc] initWithTitle:@"撤回" action:@selector(recallMenuItemAction:)];
  1733. }
  1734. return _recallMenuItem;
  1735. }
  1736. - (UIMenuItem *)playAndRecordMenuItem
  1737. {
  1738. if (_playAndRecordMenuItem == nil) {
  1739. _playAndRecordMenuItem = [[UIMenuItem alloc] initWithTitle:@"听筒播放" action:@selector(playAndRecordMenuItemAction:)];
  1740. }
  1741. return _playAndRecordMenuItem;
  1742. }
  1743. //删除消息
  1744. - (void)deleteMenuItemAction:(UIMenuItem *)aItem
  1745. {
  1746. if (self.menuIndexPath == nil) {
  1747. return;
  1748. }
  1749. EMMessageModel *model = [self.dataArray objectAtIndex:self.menuIndexPath.row];
  1750. [self.conversationModel.emModel deleteMessageWithId:model.emModel.messageId error:nil];
  1751. NSMutableIndexSet *indexs = [NSMutableIndexSet indexSetWithIndex:self.menuIndexPath.row];
  1752. NSMutableArray *indexPaths = [NSMutableArray arrayWithObjects:self.menuIndexPath, nil];
  1753. if (self.menuIndexPath.row - 1 >= 0) {
  1754. id nextMessage = nil;
  1755. id prevMessage = [self.dataArray objectAtIndex:(self.menuIndexPath.row - 1)];
  1756. if (self.menuIndexPath.row + 1 < [self.dataArray count]) {
  1757. nextMessage = [self.dataArray objectAtIndex:(self.menuIndexPath.row + 1)];
  1758. }
  1759. if ((!nextMessage || [nextMessage isKindOfClass:[NSString class]]) && [prevMessage isKindOfClass:[NSString class]]) {
  1760. [indexs addIndex:self.menuIndexPath.row - 1];
  1761. [indexPaths addObject:[NSIndexPath indexPathForRow:(self.menuIndexPath.row - 1) inSection:0]];
  1762. }
  1763. }
  1764. [self.dataArray removeObjectsAtIndexes:indexs];
  1765. [self.tableView beginUpdates];
  1766. [self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
  1767. [self.tableView endUpdates];
  1768. if ([self.dataArray count] == 0) {
  1769. self.msgTimelTag = -1;
  1770. }
  1771. self.menuIndexPath = nil;
  1772. }
  1773. - (void)copyMenuItemAction:(UIMenuItem *)aItem
  1774. {
  1775. if (self.menuIndexPath == nil) {
  1776. return;
  1777. }
  1778. EMMessageModel *model = [self.dataArray objectAtIndex:self.menuIndexPath.row];
  1779. if (model.type == EMMessageTypeText) {
  1780. EMTextMessageBody *body = (EMTextMessageBody *)model.emModel.body;
  1781. UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
  1782. pasteboard.string = body.text;
  1783. }
  1784. if (model.type == EMMessageTypeImage) {
  1785. EMMessageCell *cell = [self.tableView cellForRowAtIndexPath:self.menuIndexPath];
  1786. [[UIPasteboard generalPasteboard]setData:UIImagePNGRepresentation(cell.bubbleView.image) forPasteboardType:[UIPasteboardTypeListImage objectAtIndex:0]];
  1787. }
  1788. self.menuIndexPath = nil;
  1789. }
  1790. - (void)transpondMenuItemAction:(UIMenuItem *)aItem
  1791. {
  1792. if (self.menuIndexPath == nil) {
  1793. return;
  1794. }
  1795. EMMessageModel *model = [self.dataArray objectAtIndex:self.menuIndexPath.row];
  1796. // EMMsgTranspondViewController *controller = [[EMMsgTranspondViewController alloc] initWithModel:model];
  1797. // [self.navigationController pushViewController:controller animated:YES];
  1798. //
  1799. // __weak typeof(self) weakself = self;
  1800. // [controller setDoneCompletion:^(EMMessageModel * _Nonnull aModel, NSString * _Nonnull aUsername) {
  1801. // [weakself _transpondMsg:aModel toUser:aUsername];
  1802. // }];
  1803. // if (self.IsShareText) {
  1804. // model.Title = self.shareText;
  1805. // model.SoureTypeId = 1;
  1806. // }else{
  1807. // model.SoureId = self.Id;
  1808. // model.SoureTypeId = self.type;
  1809. // model.Title = self.currentNoteModel.Title;
  1810. // model.Author = self.currentNoteModel.UserName;
  1811. // vc.type = CollectModel_NewTopic;
  1812. // }
  1813. switch (model.type) {
  1814. case EMMessageTypeText:
  1815. {
  1816. FlowAttachmentsModel * sendModel = [[FlowAttachmentsModel alloc] init];
  1817. EMTextMessageBody *body = (EMTextMessageBody *)model.emModel.body;
  1818. sendModel.Title = body.text;
  1819. sendModel.SoureTypeId = 1;
  1820. self.sendModel = sendModel;
  1821. [self shareHander];
  1822. }
  1823. break;
  1824. case EMMessageTypeImage:
  1825. {
  1826. [self shareImage:model];
  1827. // EMTextMessageBody *body = (EMTextMessageBody *)model.emModel.body;
  1828. // self.sendModel.image = body.text;
  1829. // self.sendModel.SoureTypeId = 301;
  1830. }
  1831. break;
  1832. case EMMessageTypeExtApp:
  1833. {
  1834. NSDictionary * dict = model.emModel.ext;
  1835. CollectModelType type = [[dict objectForKey:@"app_type"] intValue];
  1836. NSInteger sourceUserId = [[dict objectForKey:@"app_sourceUserId"] integerValue];
  1837. NSInteger Id = [[dict objectForKey:@"app_id"] integerValue];
  1838. NSString * title = [dict objectForKey:@"app_title"];
  1839. NSString * url = [dict objectForKey:@"app_url"];
  1840. FlowAttachmentsModel * sendModel = [[FlowAttachmentsModel alloc] init];
  1841. sendModel.Title = title;
  1842. sendModel.SoureTypeId = type;
  1843. sendModel.SoureId = Id;
  1844. sendModel.Url = url;
  1845. sendModel.SourceUserId = sourceUserId;
  1846. self.sendModel = sendModel;
  1847. [self shareHander];
  1848. }
  1849. break;
  1850. default:
  1851. break;
  1852. }
  1853. self.menuIndexPath = nil;
  1854. }
  1855. - (void)shareImage:(EMMessageModel *)model
  1856. {
  1857. __weak typeof(self) weakself = self;
  1858. void (^downloadThumbBlock)(EMMessageModel *aModel) = ^(EMMessageModel *aModel) {
  1859. [weakself showHint:@"获取缩略图..."];
  1860. [[EMClient sharedClient].chatManager downloadMessageThumbnail:aModel.emModel progress:nil completion:^(EMMessage *message, EMError *error) {
  1861. if (!error) {
  1862. [weakself.tableView reloadData];
  1863. }
  1864. }];
  1865. };
  1866. EMImageMessageBody *body = (EMImageMessageBody*)model.emModel.body;
  1867. BOOL isCustomDownload = !([EMClient sharedClient].options.isAutoTransferMessageAttachments);
  1868. if (body.thumbnailDownloadStatus == EMDownloadStatusFailed) {
  1869. if (isCustomDownload) {
  1870. [self _showCustomTransferFileAlertView];
  1871. } else {
  1872. downloadThumbBlock(model);
  1873. }
  1874. return;
  1875. }
  1876. BOOL isAutoDownloadThumbnail = [EMClient sharedClient].options.isAutoDownloadThumbnail;
  1877. if (body.thumbnailDownloadStatus == EMDownloadStatusPending && !isAutoDownloadThumbnail) {
  1878. downloadThumbBlock(model);
  1879. return;
  1880. }
  1881. FlowAttachmentsModel * sendModel = [[FlowAttachmentsModel alloc] init];
  1882. sendModel.SoureTypeId = 301;
  1883. self.sendModel = sendModel;
  1884. if (body.downloadStatus == EMDownloadStatusSucceed) {
  1885. UIImage *image = [UIImage imageWithContentsOfFile:body.localPath];
  1886. if (image) {
  1887. self.sendImage = image;
  1888. [self shareHander];
  1889. // [[EMImageBrowser sharedBrowser] showImages:@[image] fromController:self];
  1890. return;
  1891. }
  1892. }
  1893. if (isCustomDownload) {
  1894. [self _showCustomTransferFileAlertView];
  1895. return;
  1896. }
  1897. [self showHudInView:self.view hint:@"下载原图..."];
  1898. [[EMClient sharedClient].chatManager downloadMessageAttachment:model.emModel progress:nil completion:^(EMMessage *message, EMError *error) {
  1899. [weakself hideHud];
  1900. if (error) {
  1901. [EMAlertController showErrorAlert:@"下载原图失败"];
  1902. } else {
  1903. if (message.direction == EMMessageDirectionReceive && !message.isReadAcked) {
  1904. [[EMClient sharedClient].chatManager sendMessageReadAck:message.messageId toUser:message.conversationId completion:nil];
  1905. }
  1906. NSString *localPath = [(EMImageMessageBody *)message.body localPath];
  1907. UIImage *image = [UIImage imageWithContentsOfFile:localPath];
  1908. if (image) {
  1909. weakself.sendImage = image;
  1910. [weakself shareHander];
  1911. // [[EMImageBrowser sharedBrowser] showImages:@[image] fromController:self];
  1912. } else {
  1913. [EMAlertController showErrorAlert:@"获取原图失败"];
  1914. }
  1915. }
  1916. }];
  1917. }
  1918. - (void)recallMenuItemAction:(UIMenuItem *)aItem
  1919. {
  1920. if (self.menuIndexPath == nil) {
  1921. return;
  1922. }
  1923. NSIndexPath *indexPath = self.menuIndexPath;
  1924. __weak typeof(self) weakself = self;
  1925. EMMessageModel *model = [self.dataArray objectAtIndex:self.menuIndexPath.row];
  1926. [[EMClient sharedClient].chatManager recallMessage:model.emModel completion:^(EMMessage *aMessage, EMError *aError) {
  1927. if (aError) {
  1928. [EMAlertController showErrorAlert:aError.errorDescription];
  1929. } else {
  1930. EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"您撤回一条消息"];
  1931. NSString *from = [[EMClient sharedClient] currentUsername];
  1932. NSString *to = self.conversationModel.emModel.conversationId;
  1933. EMMessage *message = [[EMMessage alloc] initWithConversationID:to from:from to:to body:body ext:@{MSG_EXT_RECALL:@(YES)}];
  1934. message.chatType = (EMChatType)self.conversationModel.emModel.type;
  1935. message.isRead = YES;
  1936. message.timestamp = model.emModel.timestamp;
  1937. message.localTime = model.emModel.localTime;
  1938. [weakself.conversationModel.emModel insertMessage:message error:nil];
  1939. EMMessageModel *model = [[EMMessageModel alloc] initWithEMMessage:message];
  1940. [weakself.dataArray replaceObjectAtIndex:indexPath.row withObject:model];
  1941. [weakself.tableView reloadData];
  1942. }
  1943. }];
  1944. self.menuIndexPath = nil;
  1945. }
  1946. - (void)playAndRecordMenuItemAction:(UIMenuItem *)aItem
  1947. {
  1948. if (self.menuIndexPath == nil) {
  1949. return;
  1950. }
  1951. EMMessageModel *model = [self.dataArray objectAtIndex:self.menuIndexPath.row];
  1952. [self playVoice:model];
  1953. self.menuIndexPath = nil;
  1954. }
  1955. - (void)playVoice:(EMMessageModel *)model
  1956. {
  1957. if (model.isPlaying) {
  1958. [[EMAudioPlayerHelper sharedHelper] stopPlayer];
  1959. model.isPlaying = NO;
  1960. [self.tableView reloadData];
  1961. return;
  1962. }
  1963. EMVoiceMessageBody *body = (EMVoiceMessageBody*)model.emModel.body;
  1964. if (body.downloadStatus == EMDownloadStatusDownloading) {
  1965. [EMAlertController showInfoAlert:@"正在下载语音,稍后点击"];
  1966. return;
  1967. }
  1968. __weak typeof(self) weakself = self;
  1969. void (^playBlock)(EMMessageModel *aModel) = ^(EMMessageModel *aModel) {
  1970. id model = [EMAudioPlayerHelper sharedHelper].model;
  1971. if (model && [model isKindOfClass:[EMMessageModel class]]) {
  1972. EMMessageModel *oldModel = (EMMessageModel *)model;
  1973. if (oldModel.isPlaying) {
  1974. oldModel.isPlaying = NO;
  1975. }
  1976. }
  1977. if (!aModel.emModel.isReadAcked) {
  1978. [[EMClient sharedClient].chatManager sendMessageReadAck:aModel.emModel.messageId toUser:aModel.emModel.conversationId completion:nil];
  1979. }
  1980. aModel.isPlaying = YES;
  1981. if (!aModel.emModel.isRead) {
  1982. aModel.emModel.isRead = YES;
  1983. }
  1984. [weakself.tableView reloadData];
  1985. [[EMAudioPlayerHelper sharedHelper] startPlayerWithPath:body.localPath model:aModel AVAudioSessionCategory:AVAudioSessionCategoryPlayAndRecord completion:^(NSError * _Nonnull error) {
  1986. aModel.isPlaying = NO;
  1987. [weakself.tableView reloadData];
  1988. }];
  1989. };
  1990. if (body.downloadStatus == EMDownloadStatusSucceed) {
  1991. playBlock(model);
  1992. return;
  1993. }
  1994. if (![EMClient sharedClient].options.isAutoTransferMessageAttachments) {
  1995. [self _showCustomTransferFileAlertView];
  1996. return;
  1997. }
  1998. [self showHudInView:self.view hint:@"下载语音..."];
  1999. [[EMClient sharedClient].chatManager downloadMessageAttachment:model.emModel progress:nil completion:^(EMMessage *message, EMError *error) {
  2000. [weakself hideHud];
  2001. if (error) {
  2002. [EMAlertController showErrorAlert:@"下载语音失败"];
  2003. } else {
  2004. playBlock(model);
  2005. }
  2006. }];
  2007. }
  2008. - (void)_showMenuViewController:(EMMessageCell *)aCell
  2009. model:(EMMessageModel *)aModel
  2010. {
  2011. [self becomeFirstResponder];
  2012. NSMutableArray *items = [[NSMutableArray alloc] init];
  2013. if (aModel.type == EMMessageTypeText || aModel.type == EMMessageTypeImage) {
  2014. [items addObject:self.copyMenuItem];
  2015. [items addObject:self.transpondMenuItem];
  2016. // } else if (aModel.type == EMMessageTypeLocation || aModel.type == EMMessageTypeImage || aModel.type == EMMessageTypeVideo) {
  2017. // [items addObject:self.transpondMenuItem];
  2018. }else if(aModel.type == EMMessageTypeExtApp){
  2019. [items addObject:self.transpondMenuItem];
  2020. }else if(aModel.type == EMMessageTypeVoice){
  2021. [items addObject:self.playAndRecordMenuItem];
  2022. }
  2023. if (aModel.emModel.direction == EMMessageDirectionSend) {
  2024. [items addObject:self.recallMenuItem];
  2025. }
  2026. [items addObject:self.deleteMenuItem];
  2027. [self.menuController setMenuItems:items];
  2028. [self.menuController setTargetRect:aCell.bubbleView.frame inView:aCell];
  2029. [self.menuController setMenuVisible:YES animated:NO];
  2030. }
  2031. #pragma mark - Transpond Message
  2032. - (void)_forwardMsgWithBody:(EMMessageBody *)aBody
  2033. to:(NSString *)aTo
  2034. ext:(NSDictionary *)aExt
  2035. completion:(void (^)(EMMessage *message))aCompletionBlock
  2036. {
  2037. NSString *from = [[EMClient sharedClient] currentUsername];
  2038. EMMessage *message = [[EMMessage alloc] initWithConversationID:aTo from:from to:aTo body:aBody ext:aExt];
  2039. message.chatType = EMChatTypeChat;
  2040. __weak typeof(self) weakself = self;
  2041. [[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:^(EMMessage *message, EMError *error) {
  2042. if (error) {
  2043. [weakself.conversationModel.emModel deleteMessageWithId:message.messageId error:nil];
  2044. [EMAlertController showErrorAlert:@"转发消息失败"];
  2045. } else {
  2046. if (aCompletionBlock) {
  2047. aCompletionBlock(message);
  2048. }
  2049. [EMAlertController showSuccessAlert:@"转发消息成功"];
  2050. }
  2051. }];
  2052. }
  2053. - (void)_forwardImageMsg:(EMMessage *)aMsg
  2054. toUser:(NSString *)aUsername
  2055. {
  2056. NSString *thumbnailLocalPath = [(EMImageMessageBody *)aMsg.body thumbnailLocalPath];
  2057. __weak typeof(self) weakself = self;
  2058. void (^block)(EMMessage *aMessage) = ^(EMMessage *aMessage) {
  2059. EMImageMessageBody *oldBody = (EMImageMessageBody *)aMessage.body;
  2060. EMImageMessageBody *newBody = [[EMImageMessageBody alloc] initWithData:nil thumbnailData:[NSData dataWithContentsOfFile:oldBody.thumbnailLocalPath]];
  2061. newBody.thumbnailRemotePath = oldBody.thumbnailRemotePath;
  2062. newBody.remotePath = oldBody.remotePath;
  2063. [weakself _forwardMsgWithBody:newBody to:aUsername ext:aMsg.ext completion:^(EMMessage *message) {
  2064. [(EMImageMessageBody *)message.body setLocalPath:oldBody.localPath];
  2065. [[EMClient sharedClient].chatManager updateMessage:message completion:nil];
  2066. }];
  2067. };
  2068. if (![[NSFileManager defaultManager] fileExistsAtPath:thumbnailLocalPath]) {
  2069. [[EMClient sharedClient].chatManager downloadMessageThumbnail:aMsg progress:nil completion:^(EMMessage *message, EMError *error) {
  2070. if (error) {
  2071. [EMAlertController showErrorAlert:@"转发消息失败"];
  2072. } else {
  2073. block(aMsg);
  2074. }
  2075. }];
  2076. } else {
  2077. block(aMsg);
  2078. }
  2079. }
  2080. - (void)_forwardVideoMsg:(EMMessage *)aMsg
  2081. toUser:(NSString *)aUsername
  2082. {
  2083. EMVideoMessageBody *oldBody = (EMVideoMessageBody *)aMsg.body;
  2084. __weak typeof(self) weakself = self;
  2085. void (^block)(EMMessage *aMessage) = ^(EMMessage *aMessage) {
  2086. EMVideoMessageBody *newBody = [[EMVideoMessageBody alloc] initWithLocalPath:oldBody.localPath displayName:oldBody.displayName];
  2087. newBody.thumbnailLocalPath = oldBody.thumbnailLocalPath;
  2088. [weakself _forwardMsgWithBody:newBody to:aUsername ext:aMsg.ext completion:^(EMMessage *message) {
  2089. [(EMVideoMessageBody *)message.body setLocalPath:[(EMVideoMessageBody *)aMessage.body localPath]];
  2090. [[EMClient sharedClient].chatManager updateMessage:message completion:nil];
  2091. }];
  2092. };
  2093. if (![[NSFileManager defaultManager] fileExistsAtPath:oldBody.localPath]) {
  2094. [[EMClient sharedClient].chatManager downloadMessageAttachment:aMsg progress:nil completion:^(EMMessage *message, EMError *error) {
  2095. if (error) {
  2096. [EMAlertController showErrorAlert:@"转发消息失败"];
  2097. } else {
  2098. block(aMsg);
  2099. }
  2100. }];
  2101. } else {
  2102. block(aMsg);
  2103. }
  2104. }
  2105. - (void)_transpondMsg:(EMMessageModel *)aModel
  2106. toUser:(NSString *)aUsername
  2107. {
  2108. EMMessageBodyType type = aModel.emModel.body.type;
  2109. if (type == EMMessageBodyTypeText || type == EMMessageBodyTypeLocation) {
  2110. [self _forwardMsgWithBody:aModel.emModel.body to:aUsername ext:aModel.emModel.ext completion:nil];
  2111. } else if (type == EMMessageBodyTypeImage) {
  2112. [self _forwardImageMsg:aModel.emModel toUser:aUsername];
  2113. } else if (type == EMMessageBodyTypeVideo) {
  2114. [self _forwardVideoMsg:aModel.emModel toUser:aUsername];
  2115. }
  2116. }
  2117. #pragma mark - Send Message
  2118. - (void)_sendTextAction:(NSString *)aText
  2119. ext:(NSDictionary *)aExt
  2120. {
  2121. [self.chatBar clearInputViewText];
  2122. [self clearUserInfoInDocument];
  2123. if ([aText length] == 0) {
  2124. return;
  2125. }
  2126. //TODO: 处理@
  2127. //messageExt
  2128. //TODO: 处理表情
  2129. // NSString *sendText = [EaseConvertToCommonEmoticonsHelper convertToCommonEmoticons:aText];
  2130. EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:aText];
  2131. [self _sendMessageWithBody:body ext:aExt isUpload:NO];
  2132. if (self.enableTyping) {
  2133. [self _sendEndTyping];
  2134. }
  2135. }
  2136. - (void)_sendImageDataAction:(NSData *)aImageData
  2137. {
  2138. EMImageMessageBody *body = [[EMImageMessageBody alloc] initWithData:aImageData displayName:@"image"];
  2139. [self _sendMessageWithBody:body ext:nil isUpload:YES];
  2140. }
  2141. - (void)_sendLocationAction:(CLLocationCoordinate2D)aCoord
  2142. address:(NSString *)aAddress
  2143. {
  2144. EMLocationMessageBody *body = [[EMLocationMessageBody alloc] initWithLatitude:aCoord.latitude longitude:aCoord.longitude address:aAddress];
  2145. [self _sendMessageWithBody:body ext:nil isUpload:NO];
  2146. }
  2147. - (void)_sendVideoAction:(NSURL *)aUrl
  2148. {
  2149. EMVideoMessageBody *body = [[EMVideoMessageBody alloc] initWithLocalPath:[aUrl path] displayName:@"video.mp4"];
  2150. [self _sendMessageWithBody:body ext:nil isUpload:YES];
  2151. }
  2152. - (void)_sendBeginTyping
  2153. {
  2154. NSString *from = [[EMClient sharedClient] currentUsername];
  2155. NSString *to = self.conversationModel.emModel.conversationId;
  2156. EMCmdMessageBody *body = [[EMCmdMessageBody alloc] initWithAction:MSG_TYPING_BEGIN];
  2157. body.isDeliverOnlineOnly = YES;
  2158. EMMessage *message = [[EMMessage alloc] initWithConversationID:to from:from to:to body:body ext:nil];
  2159. message.chatType = (EMChatType)self.conversationModel.emModel.type;
  2160. [[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:nil];
  2161. }
  2162. //正在输入
  2163. - (void)_sendEndTyping
  2164. {
  2165. self.isTyping = NO;
  2166. NSString *from = [[EMClient sharedClient] currentUsername];
  2167. NSString *to = self.conversationModel.emModel.conversationId;
  2168. EMCmdMessageBody *body = [[EMCmdMessageBody alloc] initWithAction:MSG_TYPING_END];
  2169. body.isDeliverOnlineOnly = YES;
  2170. EMMessage *message = [[EMMessage alloc] initWithConversationID:to from:from to:to body:body ext:nil];
  2171. message.chatType = (EMChatType)self.conversationModel.emModel.type;
  2172. [[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:nil];
  2173. }
  2174. #pragma mark - Data
  2175. - (NSArray *)_formatMessages:(NSArray<EMMessage *> *)aMessages
  2176. {
  2177. NSMutableArray *formated = [[NSMutableArray alloc] init];
  2178. for (int i = 0; i < [aMessages count]; i++) {
  2179. EMMessage *msg = aMessages[i];
  2180. // cmd消息不展示
  2181. if(msg.body.type == EMMessageBodyTypeCmd) {
  2182. continue;
  2183. }
  2184. if (msg.chatType == EMChatTypeChat && msg.isReadAcked && (msg.body.type == EMMessageBodyTypeText || msg.body.type == EMMessageBodyTypeLocation)) {
  2185. //
  2186. [[EMClient sharedClient].chatManager sendMessageReadAck:msg.messageId toUser:msg.conversationId completion:nil];
  2187. } else if (msg.chatType == EMChatTypeGroupChat && !msg.isReadAcked && (msg.body.type == EMMessageBodyTypeText || msg.body.type == EMMessageBodyTypeLocation)) {
  2188. }
  2189. CGFloat interval = (self.msgTimelTag - msg.timestamp) / 1000;
  2190. if (self.msgTimelTag < 0 || interval > 60 || interval < -60) {
  2191. NSString *timeStr = [EMDateHelper formattedTimeFromTimeInterval:msg.timestamp];
  2192. [formated addObject:timeStr];
  2193. self.msgTimelTag = msg.timestamp;
  2194. }
  2195. EMMessageModel *model = [[EMMessageModel alloc] initWithEMMessage:msg];
  2196. [formated addObject:model];
  2197. }
  2198. return formated;
  2199. }
  2200. - (void)tableViewDidTriggerHeaderRefresh
  2201. {
  2202. __weak typeof(self) weakself = self;
  2203. void (^block)(NSArray *aMessages, EMError *aError) = ^(NSArray *aMessages, EMError *aError) {
  2204. if (!aError && [aMessages count]) {
  2205. EMMessage *msg = aMessages[0];
  2206. weakself.moreMsgId = msg.messageId;
  2207. dispatch_async(self.msgQueue, ^{
  2208. NSArray *formated = [weakself _formatMessages:aMessages];
  2209. [weakself.dataArray insertObjects:formated atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [formated count])]];
  2210. if (![weakself.dataArray.firstObject isKindOfClass:[NSString class]]) {
  2211. [weakself.dataArray removeObjectAtIndex:0];
  2212. }
  2213. dispatch_async(dispatch_get_main_queue(), ^{
  2214. [weakself.tableView reloadData];
  2215. if (weakself.isFirstLoadMsg) {
  2216. weakself.isFirstLoadMsg = NO;
  2217. [weakself _scrollToBottomRow];
  2218. }
  2219. });
  2220. });
  2221. }
  2222. [weakself tableViewDidFinishTriggerHeader:YES reload:NO];
  2223. };
  2224. if ([EMDemoOptions sharedOptions].isPriorityGetMsgFromServer) {
  2225. EMConversation *conversation = self.conversationModel.emModel;
  2226. [EMClient.sharedClient.chatManager asyncFetchHistoryMessagesFromServer:conversation.conversationId
  2227. conversationType:conversation.type
  2228. startMessageId:self.moreMsgId
  2229. pageSize:50
  2230. completion:^(EMCursorResult *aResult, EMError *aError)
  2231. {
  2232. block(aResult.list, aError);
  2233. }];
  2234. } else {
  2235. [self.conversationModel.emModel loadMessagesStartFromId:self.moreMsgId
  2236. count:50
  2237. searchDirection:EMMessageSearchDirectionUp
  2238. completion:block];
  2239. if(self.conversationModel.emModel.unreadMessagesCount > 0){
  2240. [self sendDidReadReceipt];
  2241. }
  2242. }
  2243. }
  2244. #pragma mark - Action
  2245. - (void)backAction
  2246. {
  2247. [[EMAudioPlayerHelper sharedHelper] stopPlayer];
  2248. [EMConversationHelper resortConversationsLatestMessage];
  2249. EMConversation *conversation = self.conversationModel.emModel;
  2250. if (conversation.type == EMChatTypeChatRoom) {
  2251. [[EMClient sharedClient].roomManager leaveChatroom:conversation.conversationId completion:nil];
  2252. }
  2253. [self.navigationController popViewControllerAnimated:YES];
  2254. }
  2255. //删除该会话所有消息,同时清除内存和数据库中的消息
  2256. - (void)deleteAllMessageAction
  2257. {
  2258. EMError *error = nil;
  2259. [self.conversationModel.emModel deleteAllMessages:&error];
  2260. if (!error) {
  2261. [self.dataArray removeAllObjects];
  2262. [self.tableView reloadData];
  2263. }
  2264. }
  2265. - (void)groupOrChatroomInfoAction
  2266. {
  2267. if (self.conversationModel.emModel.type == EMConversationTypeGroupChat) {
  2268. [[NSNotificationCenter defaultCenter] postNotificationName:GROUP_INFO_PUSHVIEWCONTROLLER object:@{NOTIF_ID:self.conversationModel.emModel.conversationId, NOTIF_NAVICONTROLLER:self.navigationController}];
  2269. } else if (self.conversationModel.emModel.type == EMConversationTypeChatRoom) {
  2270. [[NSNotificationCenter defaultCenter] postNotificationName:CHATROOM_INFO_PUSHVIEWCONTROLLER object:@{NOTIF_ID:self.conversationModel.emModel.conversationId, NOTIF_NAVICONTROLLER:self.navigationController}];
  2271. }
  2272. }
  2273. //发送消息体
  2274. - (void)_sendMessageWithBody:(EMMessageBody *)aBody
  2275. ext:(NSDictionary *)aExt
  2276. isUpload:(BOOL)aIsUpload
  2277. {
  2278. if (!([EMClient sharedClient].options.isAutoTransferMessageAttachments) && aIsUpload) {
  2279. [self _showCustomTransferFileAlertView];
  2280. return;
  2281. }
  2282. NSString *from = [[EMClient sharedClient] currentUsername];
  2283. NSString *to = self.conversationModel.emModel.conversationId;
  2284. EMMessage *message = [[EMMessage alloc] initWithConversationID:to from:from to:to body:aBody ext:aExt];
  2285. //是否需要发送阅读回执
  2286. if([aExt objectForKey:MSG_EXT_READ_RECEIPT]) {
  2287. message.isNeedGroupAck = YES;
  2288. }
  2289. message.chatType = (EMChatType)self.conversationModel.emModel.type;
  2290. __weak typeof(self) weakself = self;
  2291. [[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:^(EMMessage *message, EMError *error) {
  2292. NSArray *formated = [weakself _formatMessages:@[message]];
  2293. [weakself.dataArray addObjectsFromArray:formated];
  2294. dispatch_async(dispatch_get_main_queue(), ^{
  2295. [weakself.tableView reloadData];
  2296. [weakself _scrollToBottomRow];
  2297. });
  2298. NSLog(@"%@",@{@"ContactUserId":[NSString stringWithFormat:@"%ld",(long)self.toUserId],@"IndividualGroupId":@(self.IndividualGroupId)});
  2299. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  2300. [[HttpManager sharedHttpManager] POSTUrl:Host(Often_Contact_Add_Post) parameters:@{@"ContactUserId":[NSString stringWithFormat:@"%ld",(long)self.toUserId],@"IndividualGroupId":@(self.IndividualGroupId),@"ChatType":@(self.chatType)} responseStyle:JOSN success:^(id _Nonnull responseObject) {
  2301. NSLog(@"%@",responseObject);
  2302. if ([responseObject isKindOfClass:[NSDictionary class]]) {
  2303. NSInteger listId = [[responseObject objectForKey:@"Id"] integerValue];
  2304. if (listId > 0) {
  2305. weakself.listId = listId;
  2306. weakself.isTop = [[responseObject objectForKey:@"IsTop"] integerValue];
  2307. }
  2308. }
  2309. } failure:^(NSError * _Nonnull error) {
  2310. }];
  2311. });
  2312. }];
  2313. }
  2314. #pragma mark - CustomView
  2315. - (UIView *)titleV
  2316. {
  2317. if (!_titleV) {
  2318. _titleV = [UIView new];
  2319. _titleV.backgroundColor = [UIColor whiteColor];
  2320. }
  2321. return _titleV;
  2322. }
  2323. - (UIButton *)backBtn
  2324. {
  2325. if (!_backBtn) {
  2326. _backBtn = [UIButton new];
  2327. [_backBtn setImage:[UIImage imageNamed:@"back_black_icon"] forState:UIControlStateNormal];
  2328. }
  2329. return _backBtn;
  2330. }
  2331. - (UIButton *)tabBtn
  2332. {
  2333. if (!_tabBtn) {
  2334. _tabBtn = [UIButton new];
  2335. [_tabBtn setImage:[UIImage imageNamed:@"menu_black_icon"] forState:UIControlStateNormal];
  2336. }
  2337. return _tabBtn;
  2338. }
  2339. - (UILabel *)titleL
  2340. {
  2341. if (!_titleL) {
  2342. _titleL = [UILabel new];
  2343. [_titleL setTextColor: UIColorHex(0A0A0A)];
  2344. _titleL.font = [UIFont systemFontOfSize:18];
  2345. }
  2346. return _titleL;
  2347. }
  2348. - (UIButton *)mangerBtn
  2349. {
  2350. if (!_mangerBtn) {
  2351. _mangerBtn = [UIButton new];
  2352. [_mangerBtn setImage:[UIImage imageNamed:@"chatmsg_detailchat_more_icon"] forState:UIControlStateNormal];
  2353. }
  2354. return _mangerBtn;
  2355. }
  2356. - (NSMutableArray *)userInfoArray
  2357. {
  2358. if (!_userInfoArray) {
  2359. _userInfoArray = [NSMutableArray array];
  2360. }
  2361. return _userInfoArray;
  2362. }
  2363. - (void)selectMoreMenu:(NSInteger)index title:(NSString *)title
  2364. {
  2365. switch (index) {
  2366. case 0:{
  2367. [self chatBarDidCameraAction];
  2368. }break;
  2369. case 1:{
  2370. [self chatBarDidPhotoAction];
  2371. }break;
  2372. case 2:{
  2373. FavoritesViewController *favorites = [[FavoritesViewController alloc] init];
  2374. favorites.title = @"我的笔记";
  2375. [self.navigationController pushViewController:favorites animated:YES];
  2376. }break;
  2377. case 3:{
  2378. FavoritesViewController *favorites = [[FavoritesViewController alloc] init];
  2379. favorites.title = @"我的收藏";
  2380. [self.navigationController pushViewController:favorites animated:YES];
  2381. }break;
  2382. default:
  2383. break;
  2384. }
  2385. }
  2386. - (NSMutableArray *)chatDistoryArray
  2387. {
  2388. if(!_chatDistoryArray)
  2389. {
  2390. _chatDistoryArray = [[NSMutableArray alloc] initWithArray:USERDEFAULTSGET(@"ChatList")];
  2391. }
  2392. return _chatDistoryArray;
  2393. }
  2394. - (NSString *)getUserInfoInDocument{
  2395. for (NSDictionary * dict in self.chatDistoryArray) {
  2396. if ([[dict objectForKey:@"ImId"] isEqualToString:self.conversationModel.emModel.conversationId]) {
  2397. NSString * text = [dict objectForKey:@"text"];
  2398. return text;
  2399. }
  2400. }
  2401. return @"";
  2402. }
  2403. - (void)clearUserInfoInDocument
  2404. {
  2405. for (NSDictionary * dict in self.chatDistoryArray) {
  2406. if ([[dict objectForKey:@"ImId"] isEqualToString:self.conversationModel.emModel.conversationId]) {
  2407. [self.chatDistoryArray removeObject:dict];
  2408. break;
  2409. }
  2410. }
  2411. USERDEFAULTSSET(self.chatDistoryArray,@"ChatList");
  2412. }
  2413. - (void)saveUserInfoInDocument:(NSString *)text{
  2414. for (NSDictionary * dict in self.chatDistoryArray) {
  2415. if ([[dict objectForKey:@"ImId"] isEqualToString:self.conversationModel.emModel.conversationId]) {
  2416. [self.chatDistoryArray removeObject:dict];
  2417. break;
  2418. }
  2419. }
  2420. [self.chatDistoryArray addObject:@{@"ImId":self.conversationModel.emModel.conversationId,@"text":text}];
  2421. USERDEFAULTSSET(self.chatDistoryArray,@"ChatList");
  2422. }
  2423. - (void)deleteConversationMsg
  2424. {
  2425. WS(weakSelf);
  2426. [[EMClient sharedClient].chatManager deleteConversation:self.conversationModel.emModel.conversationId isDeleteMessages:YES completion:^(NSString *aConversationId, EMError *aError) {
  2427. [weakSelf deleteAllMessageAction];
  2428. }];
  2429. }
  2430. #pragma mark - 转发
  2431. - (void)shareHander{
  2432. [self.noteBookShareVC initNoteBookShareData];
  2433. self.noteBookShareVC.view.hidden = !self.noteBookShareVC.view.hidden;
  2434. }
  2435. - (NoteBookShareVC *)noteBookShareVC{
  2436. if (_noteBookShareVC == nil) {
  2437. _noteBookShareVC = [NoteBookShareVC initNoteBookShareVC];
  2438. [_noteBookShareVC.view setFrame:CGRectMake(0,0, SCREEN_WIDTH, SCREEN_HEIGHT)];
  2439. [_noteBookShareVC.view setHidden:YES];
  2440. _noteBookShareVC.delegate = self;
  2441. }
  2442. return _noteBookShareVC;
  2443. }
  2444. -(void)userSelectType:(NSString *)typeName WithIndexPath:(NSIndexPath *)indexPath{
  2445. self.noteBookShareVC.view.hidden = !self.noteBookShareVC.view.hidden;
  2446. if ([typeName isEqualToString:@"发给微信好友"]) {
  2447. }else if ([typeName isEqualToString:@"发到朋友圈"]){
  2448. }else if ([typeName isEqualToString:@"发到微博"]){
  2449. }else if ([typeName isEqualToString:@"发给QQ好友"]){
  2450. }else if ([typeName isEqualToString:@"发到消息"]){
  2451. }else if ([typeName isEqualToString:@"发到小组"]){
  2452. // [self returnToGroup];
  2453. }else if ([typeName isEqualToString:@"发到笔记"]){
  2454. [self returnToNote];
  2455. }else if ([typeName isEqualToString:@"发到话题"]){
  2456. [self returnToTopic];
  2457. }else{
  2458. }
  2459. }
  2460. #pragma mark - 分享功能
  2461. //- (void)returnToGroup
  2462. //{
  2463. // MyTDGroupViewController * vc = [[MyTDGroupViewController alloc] init];
  2464. // vc.type = CollectModel_Group;
  2465. // FlowAttachmentsModel * model = [[FlowAttachmentsModel alloc] init];
  2466. // model.SoureId = self.Id;
  2467. // model.SoureTypeId = self.type;
  2468. // model.Title = self.currentNoteModel.Title;
  2469. // model.Author = self.currentNoteModel.UserName;
  2470. // vc.sendModel = model;
  2471. // vc.isReturn = YES;
  2472. // [self.navigationController pushViewController:vc animated:YES];
  2473. //}
  2474. - (void)returnToNote
  2475. {
  2476. MoveViewController * vc = [MoveViewController initMoveViewController];
  2477. vc.isFromCreateBookVc = YES;
  2478. vc.TypeId = CreateNotesType;
  2479. vc.ParentId = 0;
  2480. // if (self.IsShareText) {
  2481. // model.Title = self.shareText;
  2482. // model.SoureTypeId = 1;
  2483. // }else{
  2484. // model.SoureId = self.Id;
  2485. // model.SoureTypeId = self.type;
  2486. // model.Title = self.currentNoteModel.Title;
  2487. // model.Author = self.currentNoteModel.UserName;
  2488. // vc.type = CollectModel_NoteBook;
  2489. // }
  2490. vc.sendModel = self.sendModel;
  2491. vc.sendImage = self.sendImage;
  2492. vc.isReturn = YES;
  2493. [self.navigationController pushViewController:vc animated:YES];
  2494. }
  2495. - (void)returnToTopic
  2496. {
  2497. MyTDTopicCreateVC * vc = [MyTDTopicCreateVC initMyTDTopicCreateVC];
  2498. vc.type = CollectModel_NewTopic;
  2499. // if (self.IsShareText) {
  2500. // model.Title = self.shareText;
  2501. // model.SoureTypeId = 1;
  2502. // }else{
  2503. // model.SoureId = self.Id;
  2504. // model.SoureTypeId = self.type;
  2505. // model.Title = self.currentNoteModel.Title;
  2506. // model.Author = self.currentNoteModel.UserName;
  2507. // vc.type = CollectModel_NewTopic;
  2508. // }
  2509. vc.sendModel = self.sendModel;
  2510. vc.sendImage = self.sendImage;
  2511. vc.isReturn = YES;
  2512. [self.navigationController pushViewController:vc animated:YES];
  2513. }
  2514. @end