NIMSessionViewController.m 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. //
  2. // NIMSessionViewController.m
  3. // NIMKit
  4. //
  5. // Created by NetEase.
  6. // Copyright (c) 2015年 NetEase. All rights reserved.
  7. //
  8. #import "NIMSessionConfigurateProtocol.h"
  9. #import "NIMKit.h"
  10. #import "NIMMessageCellProtocol.h"
  11. #import "NIMMessageModel.h"
  12. #import "NIMKitUtil.h"
  13. #import "NIMCustomLeftBarView.h"
  14. #import "NIMBadgeView.h"
  15. #import "UITableView+NIMScrollToBottom.h"
  16. #import "NIMMessageMaker.h"
  17. #import "UIView+NIM.h"
  18. #import "NIMSessionConfigurator.h"
  19. #import "NIMKitInfoFetchOption.h"
  20. #import "NIMKitTitleView.h"
  21. #import "NIMKitKeyboardInfo.h"
  22. @interface NIMSessionViewController ()<NIMMediaManagerDelegate,NIMInputDelegate>
  23. @property (nonatomic,readwrite) NIMMessage *messageForMenu;
  24. @property (nonatomic,strong) UILabel *titleLabel;
  25. @property (nonatomic,strong) UILabel *subTitleLabel;
  26. @property (nonatomic,strong) NSIndexPath *lastVisibleIndexPathBeforeRotation;
  27. @property (nonatomic,strong) NIMSessionConfigurator *configurator;
  28. @property (nonatomic,weak) id<NIMSessionInteractor> interactor;
  29. @end
  30. @implementation NIMSessionViewController
  31. - (instancetype)initWithSession:(NIMSession *)session{
  32. self = [super initWithNibName:nil bundle:nil];
  33. if (self) {
  34. _session = session;
  35. }
  36. return self;
  37. }
  38. - (void)dealloc
  39. {
  40. [self removeListener];
  41. [[NIMKit sharedKit].robotTemplateParser clean];
  42. _tableView.delegate = nil;
  43. _tableView.dataSource = nil;
  44. }
  45. - (void)viewDidLoad {
  46. [super viewDidLoad];
  47. //导航栏
  48. [self youpaifsetupNav];
  49. //消息 tableView
  50. [self youpaifsetupTableView];
  51. //输入框 inputView
  52. [self youpaifsetupInputView];
  53. //会话相关逻辑配置器安装
  54. [self youpaifsetupConfigurator];
  55. //添加监听
  56. [self addListener];
  57. //进入会话时,标记所有消息已读,并发送已读回执
  58. [self markRead];
  59. //更新已读位置
  60. [self uiCheckReceipts:nil];
  61. }
  62. - (void)youpaifsetupNav
  63. {
  64. [self setUpTitleView];
  65. NIMCustomLeftBarView *leftBarView = [[NIMCustomLeftBarView alloc] init];
  66. UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithCustomView:leftBarView];
  67. if (@available(iOS 11.0, *)) {
  68. leftBarView.translatesAutoresizingMaskIntoConstraints = NO;
  69. }
  70. self.navigationItem.leftBarButtonItems = @[leftItem];
  71. self.navigationItem.leftItemsSupplementBackButton = YES;
  72. }
  73. - (void)youpaifsetupTableView
  74. {
  75. self.view.backgroundColor = [UIColor whiteColor];
  76. self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
  77. self.tableView.backgroundColor = LCBkgColor;
  78. self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  79. self.tableView.estimatedRowHeight = 0;
  80. self.tableView.estimatedSectionHeaderHeight = 0;
  81. self.tableView.estimatedSectionFooterHeight = 0;
  82. self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  83. if (@available(iOS 15.0, *)) {
  84. self.tableView.sectionHeaderTopPadding = 0;
  85. }
  86. if ([self.sessionConfig respondsToSelector:@selector(sessionBackgroundImage)] && [self.sessionConfig sessionBackgroundImage]) {
  87. UIImageView *imgView = [[UIImageView alloc] initWithFrame:self.view.bounds];
  88. imgView.image = [self.sessionConfig sessionBackgroundImage];
  89. imgView.contentMode = UIViewContentModeScaleAspectFill;
  90. self.tableView.backgroundView = imgView;
  91. }
  92. [self.view addSubview:self.tableView];
  93. }
  94. - (void)youpaifsetupInputView
  95. {
  96. if ([self shouldShowInputView])
  97. {
  98. self.sessionInputView = [[YOUPAINIMInputView alloc] initWithFrame:CGRectMake(0, 0, self.view.nim_width,0) config:self.sessionConfig];
  99. self.sessionInputView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
  100. [self.sessionInputView setSession:self.session];
  101. [self.sessionInputView setInputDelegate:self];
  102. [self.sessionInputView setInputActionDelegate:self];
  103. [self.sessionInputView refreshStatus:NIMInputStatusText];
  104. [self.view addSubview:_sessionInputView];
  105. }
  106. }
  107. - (void)youpaifsetupConfigurator
  108. {
  109. _configurator = [[NIMSessionConfigurator alloc] init];
  110. [_configurator youpaifsetup:self];
  111. BOOL needProximityMonitor = [self needProximityMonitor];
  112. [[NIMSDK sharedSDK].mediaManager setNeedProximityMonitor:needProximityMonitor];
  113. }
  114. - (void)viewWillAppear:(BOOL)animated
  115. {
  116. [super viewWillAppear:animated];
  117. [self.interactor onViewWillAppear];
  118. }
  119. - (void)viewWillDisappear:(BOOL)animated
  120. {
  121. [super viewWillDisappear:animated];
  122. [self.sessionInputView endEditing:YES];
  123. }
  124. - (void)viewDidDisappear:(BOOL)animated
  125. {
  126. [super viewDidDisappear:animated];
  127. [self.interactor onViewDidDisappear];
  128. }
  129. - (void)viewDidLayoutSubviews
  130. {
  131. [self changeLeftBarBadge:self.conversationManager.allUnreadCount];
  132. [self.interactor resetLayout];
  133. }
  134. #pragma mark - 消息收发接口
  135. - (void)sendMessage:(NIMMessage *)message
  136. {
  137. [self.interactor sendMessage:message];
  138. }
  139. #pragma mark - Touch Event
  140. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
  141. {
  142. [super touchesBegan:touches withEvent:event];
  143. [_sessionInputView endEditing:YES];
  144. }
  145. #pragma mark - NIMSessionConfiguratorDelegate
  146. - (void)didFetchMessageData
  147. {
  148. [self uiCheckReceipts:nil];
  149. [self.tableView reloadData];
  150. [self.tableView nim_scrollToBottom:NO];
  151. }
  152. - (void)didRefreshMessageData
  153. {
  154. [self refreshSessionTitle:self.youpaifsessionTitle];
  155. [self refreshSessionSubTitle:self.sessionSubTitle];
  156. [self.tableView reloadData];
  157. }
  158. - (void)didPullUpMessageData {}
  159. #pragma mark - 会话title
  160. - (NSString *)youpaifsessionTitle
  161. {
  162. NSString *title = @"";
  163. NIMSessionType type = self.session.sessionType;
  164. switch (type) {
  165. case NIMSessionTypeTeam:{
  166. NIMTeam *team = [[[NIMSDK sharedSDK] teamManager] teamById:self.session.sessionId];
  167. title = [NSString stringWithFormat:@"%@(%zd)",[team teamName],[team memberNumber]];
  168. }
  169. break;
  170. case NIMSessionTypeP2P:{
  171. title = [NIMKitUtil showNick:self.session.sessionId inSession:self.session];
  172. }
  173. break;
  174. default:
  175. break;
  176. }
  177. return title;
  178. }
  179. - (NSString *)sessionSubTitle{return @"";};
  180. #pragma mark - NIMChatManagerDelegate
  181. //开始发送
  182. - (void)willSendMessage:(NIMMessage *)message
  183. {
  184. id<NIMSessionInteractor> interactor = self.interactor;
  185. if ([message.session isEqual:self.session]) {
  186. if ([interactor findMessageModel:message]) {
  187. [interactor updateMessage:message];
  188. }else{
  189. [interactor addMessages:@[message]];
  190. }
  191. }
  192. }
  193. //上传资源文件成功
  194. - (void)uploadAttachmentSuccess:(NSString *)urlString
  195. forMessage:(NIMMessage *)message
  196. {
  197. //如果需要使用富文本推送,可以在这里进行 message apns payload 的设置
  198. }
  199. //发送结果
  200. - (void)sendMessage:(NIMMessage *)message didCompleteWithError:(NSError *)error
  201. {
  202. if ([message.session isEqual:_session])
  203. {
  204. [self.interactor updateMessage:message];
  205. if (message.session.sessionType == NIMSessionTypeTeam)
  206. {
  207. //如果是群的话需要检查一下回执显示情况
  208. NIMMessageReceipt *receipt = [[NIMMessageReceipt alloc] initWithMessage:message];
  209. [self.interactor checkReceipts:@[receipt]];
  210. }
  211. }
  212. }
  213. //发送进度
  214. -(void)sendMessage:(NIMMessage *)message progress:(float)progress
  215. {
  216. if ([message.session isEqual:_session]) {
  217. [self.interactor updateMessage:message];
  218. }
  219. }
  220. //接收消息
  221. - (void)onRecvMessages:(NSArray *)messages
  222. {
  223. if ([self shouldAddListenerForNewMsg])
  224. {
  225. NIMMessage *message = messages.firstObject;
  226. NIMSession *session = message.session;
  227. if (![session isEqual:self.session] || !messages.count)
  228. {
  229. return;
  230. }
  231. [self uiAddMessages:messages];
  232. [self.interactor markRead];
  233. }
  234. }
  235. - (void)fetchMessageAttachment:(NIMMessage *)message progress:(float)progress
  236. {
  237. if ([message.session isEqual:_session])
  238. {
  239. [self.interactor updateMessage:message];
  240. }
  241. }
  242. - (void)fetchMessageAttachment:(NIMMessage *)message didCompleteWithError:(NSError *)error
  243. {
  244. if ([message.session isEqual:_session])
  245. {
  246. NIMMessageModel *model = [self.interactor findMessageModel:message];
  247. //下完缩略图之后,因为比例有变化,重新刷下宽高。
  248. [model cleanCache];
  249. [self.interactor updateMessage:message];
  250. }
  251. }
  252. - (void)onRecvMessageReceipts:(NSArray<NIMMessageReceipt *> *)receipts
  253. {
  254. if ([self shouldAddListenerForNewMsg])
  255. {
  256. NSMutableArray *handledReceipts = [[NSMutableArray alloc] init];
  257. for (NIMMessageReceipt *receipt in receipts) {
  258. if ([receipt.session isEqual:self.session])
  259. {
  260. [handledReceipts addObject:receipt];
  261. }
  262. }
  263. if (handledReceipts.count)
  264. {
  265. [self uiCheckReceipts:handledReceipts];
  266. }
  267. }
  268. }
  269. #pragma mark - NIMConversationManagerDelegate
  270. - (void)messagesDeletedInSession:(NIMSession *)session{
  271. [self.interactor resetMessages:nil];
  272. [self.tableView reloadData];
  273. }
  274. - (void)didAddRecentSession:(NIMRecentSession *)recentSession
  275. totalUnreadCount:(NSInteger)totalUnreadCount{
  276. [self changeUnreadCount:recentSession totalUnreadCount:totalUnreadCount];
  277. }
  278. - (void)didUpdateRecentSession:(NIMRecentSession *)recentSession
  279. totalUnreadCount:(NSInteger)totalUnreadCount{
  280. [self changeUnreadCount:recentSession totalUnreadCount:totalUnreadCount];
  281. }
  282. - (void)didRemoveRecentSession:(NIMRecentSession *)recentSession
  283. totalUnreadCount:(NSInteger)totalUnreadCount{
  284. [self changeUnreadCount:recentSession totalUnreadCount:totalUnreadCount];
  285. }
  286. - (void)changeUnreadCount:(NIMRecentSession *)recentSession
  287. totalUnreadCount:(NSInteger)totalUnreadCount{
  288. if ([recentSession.session isEqual:self.session]) {
  289. return;
  290. }
  291. [self changeLeftBarBadge:totalUnreadCount];
  292. }
  293. #pragma mark - NIMMediaManagerDelegate
  294. - (void)recordAudio:(NSString *)filePath didBeganWithError:(NSError *)error {
  295. if (!filePath || error) {
  296. _sessionInputView.recording = NO;
  297. [self onRecordFailed:error];
  298. }
  299. }
  300. - (void)recordAudio:(NSString *)filePath didCompletedWithError:(NSError *)error {
  301. if(!error) {
  302. if ([self recordFileCanBeSend:filePath]) {
  303. [self sendMessage:[NIMMessageMaker msgWithAudio:filePath]];
  304. }else{
  305. [self showRecordFileNotSendReason];
  306. }
  307. } else {
  308. [self onRecordFailed:error];
  309. }
  310. _sessionInputView.recording = NO;
  311. }
  312. - (void)recordAudioDidCancelled {
  313. _sessionInputView.recording = NO;
  314. }
  315. - (void)recordAudioProgress:(NSTimeInterval)currentTime {
  316. [_sessionInputView updateAudioRecordTime:currentTime];
  317. }
  318. - (void)recordAudioInterruptionBegin {
  319. [[NIMSDK sharedSDK].mediaManager cancelRecord];
  320. }
  321. #pragma mark - 录音相关接口
  322. - (void)onRecordFailed:(NSError *)error{}
  323. - (BOOL)recordFileCanBeSend:(NSString *)filepath
  324. {
  325. return YES;
  326. }
  327. - (void)showRecordFileNotSendReason{}
  328. #pragma mark - NIMInputDelegate
  329. - (void)didChangeInputHeight:(CGFloat)inputHeight
  330. {
  331. [self.interactor changeLayout:inputHeight];
  332. }
  333. #pragma mark - NIMInputActionDelegate
  334. - (BOOL)onTapMediaItem:(NIMMediaItem *)item{
  335. SEL sel = item.selctor;
  336. BOOL handled = sel && [self respondsToSelector:sel];
  337. if (handled) {
  338. NIMKit_SuppressPerformSelectorLeakWarning([self performSelector:sel withObject:item]);
  339. handled = YES;
  340. }
  341. return handled;
  342. }
  343. - (void)onTextChanged:(id)sender{}
  344. - (void)onSendText:(NSString *)text atUsers:(NSArray *)atUsers
  345. {
  346. NSMutableArray *users = [NSMutableArray arrayWithArray:atUsers];
  347. if (self.session.sessionType == NIMSessionTypeP2P)
  348. {
  349. [users addObject:self.session.sessionId];
  350. }
  351. NSString *robotsToSend = [self robotsToSend:users];
  352. NIMMessage *message = nil;
  353. if (robotsToSend.length)
  354. {
  355. message = [NIMMessageMaker msgWithRobotQuery:text toRobot:robotsToSend];
  356. }
  357. else
  358. {
  359. message = [NIMMessageMaker msgWithText:text];
  360. }
  361. if (atUsers.count)
  362. {
  363. NIMMessageApnsMemberOption *apnsOption = [[NIMMessageApnsMemberOption alloc] init];
  364. apnsOption.userIds = atUsers;
  365. apnsOption.forcePush = YES;
  366. NIMKitInfoFetchOption *option = [[NIMKitInfoFetchOption alloc] init];
  367. option.session = self.session;
  368. NSString *me = [[NIMKit sharedKit].provider infoByUser:[NIMSDK sharedSDK].loginManager.currentAccount option:option].showName;
  369. apnsOption.apnsContent = [NSString stringWithFormat:@"%@在群里@了你",me];
  370. message.apnsMemberOption = apnsOption;
  371. }
  372. [self sendMessage:message];
  373. }
  374. - (NSString *)robotsToSend:(NSArray *)atUsers
  375. {
  376. for (NSString *userId in atUsers)
  377. {
  378. if ([[NIMSDK sharedSDK].robotManager isValidRobot:userId])
  379. {
  380. return userId;
  381. }
  382. }
  383. return nil;
  384. }
  385. - (void)onSelectChartlet:(NSString *)chartletId
  386. catalog:(NSString *)catalogId{}
  387. - (void)onCancelRecording
  388. {
  389. [[NIMSDK sharedSDK].mediaManager cancelRecord];
  390. }
  391. - (void)onStopRecording
  392. {
  393. [[NIMSDK sharedSDK].mediaManager stopRecord];
  394. }
  395. - (void)onStartRecording
  396. {
  397. _sessionInputView.recording = YES;
  398. NIMAudioType type = [self recordAudioType];
  399. NSTimeInterval duration = [NIMKit sharedKit].config.recordMaxDuration;
  400. [[NIMSDK sharedSDK].mediaManager addDelegate:self];
  401. [[NIMSDK sharedSDK].mediaManager record:type
  402. duration:duration];
  403. }
  404. #pragma mark - NIMMessageCellDelegate
  405. - (BOOL)onTapCell:(NIMKitEvent *)event{
  406. BOOL handle = NO;
  407. NSString *eventName = event.eventName;
  408. if ([eventName isEqualToString:NIMKitEventNameTapAudio])
  409. {
  410. [self.interactor mediaAudioPressed:event.messageModel];
  411. handle = YES;
  412. }
  413. if ([eventName isEqualToString:NIMKitEventNameTapRobotBlock]) {
  414. NSDictionary *param = event.data;
  415. NIMMessage *message = [NIMMessageMaker msgWithRobotSelect:param[@"text"] target:param[@"target"] params:param[@"param"] toRobot:param[@"robotId"]];
  416. [self sendMessage:message];
  417. handle = YES;
  418. }
  419. if ([eventName isEqualToString:NIMKitEventNameTapRobotContinueSession]) {
  420. NIMRobotObject *robotObject = (NIMRobotObject *)event.messageModel.message.messageObject;
  421. NIMRobot *robot = [[NIMSDK sharedSDK].robotManager robotInfo:robotObject.robotId];
  422. NSString *text = [NSString stringWithFormat:@"%@%@%@",NIMInputAtStartChar,robot.nickname,NIMInputAtEndChar];
  423. NIMInputAtItem *item = [[NIMInputAtItem alloc] init];
  424. item.uid = robot.userId;
  425. item.name = robot.nickname;
  426. [self.sessionInputView.atCache addAtItem:item];
  427. [self.sessionInputView.toolBar insertText:text];
  428. handle = YES;
  429. }
  430. return handle;
  431. }
  432. - (void)onRetryMessage:(NIMMessage *)message
  433. {
  434. if (message.isReceivedMsg) {
  435. [[[NIMSDK sharedSDK] chatManager] fetchMessageAttachment:message
  436. error:nil];
  437. }else{
  438. [[[NIMSDK sharedSDK] chatManager] resendMessage:message
  439. error:nil];
  440. }
  441. }
  442. - (BOOL)onLongPressCell:(NIMMessage *)message
  443. inView:(UIView *)view
  444. {
  445. BOOL handle = NO;
  446. NSArray *items = [self menusItems:message];
  447. if ([items count] && [self becomeFirstResponder]) {
  448. UIMenuController *controller = [UIMenuController sharedMenuController];
  449. controller.menuItems = items;
  450. _messageForMenu = message;
  451. [controller setTargetRect:view.bounds inView:view];
  452. [controller setMenuVisible:YES animated:YES];
  453. handle = YES;
  454. }
  455. return handle;
  456. }
  457. - (BOOL)disableAudioPlayedStatusIcon:(NIMMessage *)message
  458. {
  459. BOOL disable = NO;
  460. if ([self.sessionConfig respondsToSelector:@selector(disableAudioPlayedStatusIcon)])
  461. {
  462. disable = [self.sessionConfig disableAudioPlayedStatusIcon];
  463. }
  464. return disable;
  465. }
  466. #pragma mark - 配置项
  467. - (id<NIMSessionConfig>)sessionConfig
  468. {
  469. return nil; //使用默认配置
  470. }
  471. #pragma mark - 配置项列表
  472. //是否需要监听新消息通知 : 某些场景不需要监听新消息,如浏览服务器消息历史界面
  473. - (BOOL)shouldAddListenerForNewMsg
  474. {
  475. BOOL should = YES;
  476. if ([self.sessionConfig respondsToSelector:@selector(disableReceiveNewMessages)]) {
  477. should = ![self.sessionConfig disableReceiveNewMessages];
  478. }
  479. return should;
  480. }
  481. //是否需要显示输入框 : 某些场景不需要显示输入框,如使用 3D touch 的场景预览会话界面内容
  482. - (BOOL)shouldShowInputView
  483. {
  484. BOOL should = YES;
  485. if ([self.sessionConfig respondsToSelector:@selector(disableInputView)]) {
  486. should = ![self.sessionConfig disableInputView];
  487. }
  488. return should;
  489. }
  490. //当前录音格式 : NIMSDK 支持 aac 和 amr 两种格式
  491. - (NIMAudioType)recordAudioType
  492. {
  493. NIMAudioType type = NIMAudioTypeAAC;
  494. if ([self.sessionConfig respondsToSelector:@selector(recordType)]) {
  495. type = [self.sessionConfig recordType];
  496. }
  497. return type;
  498. }
  499. //是否需要监听感应器事件
  500. - (BOOL)needProximityMonitor
  501. {
  502. BOOL needProximityMonitor = YES;
  503. if ([self.sessionConfig respondsToSelector:@selector(disableProximityMonitor)]) {
  504. needProximityMonitor = !self.sessionConfig.disableProximityMonitor;
  505. }
  506. return needProximityMonitor;
  507. }
  508. #pragma mark - 菜单
  509. - (NSArray *)menusItems:(NIMMessage *)message
  510. {
  511. NSMutableArray *items = [NSMutableArray array];
  512. BOOL copyText = NO;
  513. if (message.messageType == NIMMessageTypeText)
  514. {
  515. copyText = YES;
  516. }
  517. if (message.messageType == NIMMessageTypeRobot)
  518. {
  519. NIMRobotObject *robotObject = (NIMRobotObject *)message.messageObject;
  520. copyText = !robotObject.isFromRobot;
  521. }
  522. if (copyText) {
  523. [items addObject:[[UIMenuItem alloc] initWithTitle:@"复制"
  524. action:@selector(copyText:)]];
  525. }
  526. [items addObject:[[UIMenuItem alloc] initWithTitle:@"删除"
  527. action:@selector(deleteMsg:)]];
  528. return items;
  529. }
  530. - (NIMMessage *)messageForMenu
  531. {
  532. return _messageForMenu;
  533. }
  534. - (BOOL)canBecomeFirstResponder
  535. {
  536. return YES;
  537. }
  538. - (BOOL)canPerformAction:(SEL)action withSender:(id)sender
  539. {
  540. NSArray *items = [[UIMenuController sharedMenuController] menuItems];
  541. for (UIMenuItem *item in items) {
  542. if (action == [item action]){
  543. return YES;
  544. }
  545. }
  546. return NO;
  547. }
  548. - (void)copyText:(id)sender
  549. {
  550. NIMMessage *message = [self messageForMenu];
  551. if (message.text.length) {
  552. UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
  553. [pasteboard setString:message.text];
  554. }
  555. }
  556. - (void)deleteMsg:(id)sender
  557. {
  558. NIMMessage *message = [self messageForMenu];
  559. [self uiDeleteMessage:message];
  560. [self.conversationManager deleteMessage:message];
  561. }
  562. - (void)menuDidHide:(NSNotification *)notification
  563. {
  564. [UIMenuController sharedMenuController].menuItems = nil;
  565. }
  566. #pragma mark - 操作接口
  567. - (void)uiAddMessages:(NSArray *)messages
  568. {
  569. [self.interactor addMessages:messages];
  570. }
  571. - (void)uiInsertMessages:(NSArray *)messages
  572. {
  573. [self.interactor insertMessages:messages];
  574. }
  575. - (NIMMessageModel *)uiDeleteMessage:(NIMMessage *)message{
  576. NIMMessageModel *model = [self.interactor deleteMessage:message];
  577. if (model.shouldShowReadLabel && model.message.session.sessionType == NIMSessionTypeP2P)
  578. {
  579. [self uiCheckReceipts:nil];
  580. }
  581. return model;
  582. }
  583. - (void)uiUpdateMessage:(NIMMessage *)message{
  584. [self.interactor updateMessage:message];
  585. }
  586. - (void)uiCheckReceipts:(NSArray<NIMMessageReceipt *> *)receipts
  587. {
  588. [self.interactor checkReceipts:receipts];
  589. }
  590. #pragma mark - NIMMeidaButton
  591. - (void)onTapMediaItemPicture:(NIMMediaItem *)item
  592. {
  593. [self.interactor mediaPicturePressed];
  594. }
  595. - (void)onTapMediaItemShoot:(NIMMediaItem *)item
  596. {
  597. [self.interactor mediaShootPressed];
  598. }
  599. - (void)onTapMediaItemLocation:(NIMMediaItem *)item
  600. {
  601. [self.interactor mediaLocationPressed];
  602. }
  603. #pragma mark - 旋转处理 (iOS8 or above)
  604. - (void)viewWillTransitionToSize:(CGSize)size
  605. withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
  606. {
  607. self.lastVisibleIndexPathBeforeRotation = [self.tableView indexPathsForVisibleRows].lastObject;
  608. [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
  609. if (self.view.window) {
  610. __weak typeof(self) wself = self;
  611. [coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context)
  612. {
  613. [[NIMSDK sharedSDK].mediaManager cancelRecord];
  614. [wself.interactor cleanCache];
  615. [wself.sessionInputView reset];
  616. [wself.tableView reloadData];
  617. [wself.tableView scrollToRowAtIndexPath:wself.lastVisibleIndexPathBeforeRotation atScrollPosition:UITableViewScrollPositionBottom animated:NO];
  618. } completion:nil];
  619. }
  620. }
  621. #pragma mark - 标记已读
  622. - (void)markRead
  623. {
  624. [self.interactor markRead];
  625. }
  626. #pragma mark - Private
  627. - (void)addListener
  628. {
  629. [[NIMSDK sharedSDK].chatManager addDelegate:self];
  630. [[NIMSDK sharedSDK].conversationManager addDelegate:self];
  631. }
  632. - (void)removeListener
  633. {
  634. [[NIMSDK sharedSDK].chatManager removeDelegate:self];
  635. [[NIMSDK sharedSDK].conversationManager removeDelegate:self];
  636. }
  637. - (void)changeLeftBarBadge:(NSInteger)unreadCount
  638. {
  639. NIMCustomLeftBarView *leftBarView = (NIMCustomLeftBarView *)self.navigationItem.leftBarButtonItem.customView;
  640. leftBarView.badgeView.badgeValue = @(unreadCount).stringValue;
  641. leftBarView.badgeView.hidden = !unreadCount;
  642. }
  643. - (id<NIMConversationManager>)conversationManager{
  644. switch (self.session.sessionType) {
  645. case NIMSessionTypeChatroom:
  646. return nil;
  647. break;
  648. case NIMSessionTypeP2P:
  649. case NIMSessionTypeTeam:
  650. default:
  651. return [NIMSDK sharedSDK].conversationManager;
  652. }
  653. }
  654. - (void)setUpTitleView
  655. {
  656. NIMKitTitleView *titleView = (NIMKitTitleView *)self.navigationItem.titleView;
  657. if (!titleView || ![titleView isKindOfClass:[NIMKitTitleView class]])
  658. {
  659. titleView = [[NIMKitTitleView alloc] initWithFrame:CGRectZero];
  660. self.navigationItem.titleView = titleView;
  661. titleView.titleLabel.text = self.youpaifsessionTitle;
  662. titleView.subtitleLabel.text = self.sessionSubTitle;
  663. self.titleLabel = titleView.titleLabel;
  664. self.subTitleLabel = titleView.subtitleLabel;
  665. }
  666. [titleView sizeToFit];
  667. }
  668. - (void)refreshSessionTitle:(NSString *)title
  669. {
  670. self.titleLabel.text = title;
  671. [self setUpTitleView];
  672. }
  673. - (void)refreshSessionSubTitle:(NSString *)title
  674. {
  675. self.subTitleLabel.text = title;
  676. [self setUpTitleView];
  677. }
  678. @end