NTESSessionLocalHistoryViewController.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. //
  2. // NTESSessionLocalHistoryViewController.m
  3. // NIM
  4. //
  5. // Created by chris on 15/7/8.
  6. // Copyright © 2015年 Netease. All rights reserved.
  7. //
  8. #import "NTESSessionLocalHistoryViewController.h"
  9. #import "NTESSearchMessageEntraceCell.h"
  10. #import "NTESSearchMessageContentCell.h"
  11. #import "NTESSearchLocalHistoryObject.h"
  12. #import "NTESBundleSetting.h"
  13. #import "UIView+NTES.h"
  14. #import "NTESSessionViewController.h"
  15. #define EntranceCellIdentity @"entrance"
  16. #define EntranceCellHeight 45
  17. #define ContentCellIdentity @"content"
  18. #define ContentCellHeight 50
  19. #define SearchLimit 10
  20. @interface NTESSessionLocalHistoryViewController ()<UITableViewDataSource,UITableViewDelegate,UISearchResultsUpdating>
  21. @property (nonatomic,strong) UISearchController *searchController;
  22. @property (nonatomic,strong) UITableViewController *searchResultController;
  23. @property (nonatomic,strong) NTESSearchLocalHistoryObject *searchObject;
  24. @property (nonatomic,copy) NSString *keyWord;
  25. @property (nonatomic,strong) NSMutableArray *data;
  26. @property (nonatomic,strong) NIMSession *session;
  27. @property (nonatomic,strong) NIMMessageSearchOption *lastOption;
  28. @property (nonatomic,strong) NSArray *members;
  29. @property (nonatomic,strong) UILabel *noResultTip;
  30. @end
  31. @implementation NTESSessionLocalHistoryViewController
  32. - (instancetype)initWithSession:(NIMSession *)session{
  33. self = [super initWithNibName:nil bundle:nil];
  34. if (self) {
  35. _session = session;
  36. NTESSearchLocalHistoryObject *object = [[NTESSearchLocalHistoryObject alloc] init];
  37. _searchObject = object;
  38. _data = [[NSMutableArray alloc]init];
  39. }
  40. return self;
  41. }
  42. - (void)viewDidLoad {
  43. [super viewDidLoad];
  44. self.navigationItem.title = @"聊天记录";
  45. [self prepareMember];
  46. self.tableView.tableFooterView = [[UIView alloc] init];
  47. self.tableView.dataSource = self;
  48. self.tableView.delegate = self;
  49. self.refreshControl = [[UIRefreshControl alloc] init];
  50. [self.refreshControl addTarget:self action:@selector(onPull2Refresh:) forControlEvents:UIControlEventValueChanged];
  51. self.searchResultController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
  52. [self.searchResultController.tableView registerClass:[NTESSearchMessageEntraceCell class] forCellReuseIdentifier:EntranceCellIdentity];
  53. self.searchResultController.automaticallyAdjustsScrollViewInsets = NO;
  54. self.searchResultController.tableView.delegate = self;
  55. self.searchResultController.tableView.dataSource = self;
  56. self.searchResultController.tableView.separatorInset = UIEdgeInsetsZero;
  57. self.searchResultController.tableView.tableFooterView = [UIView new];
  58. self.searchController = [[UISearchController alloc] initWithSearchResultsController:self.searchResultController];
  59. self.searchController.searchResultsUpdater = self;
  60. self.searchController.searchBar.height = 44.f; // iOS8 下 searchBar 默认高度为 0,需要预设一个高度进去
  61. self.tableView.tableHeaderView = self.searchController.searchBar;
  62. [self.tableView registerClass:[NTESSearchMessageContentCell class] forCellReuseIdentifier:ContentCellIdentity];
  63. self.noResultTip = [[UILabel alloc] initWithFrame:CGRectZero];
  64. self.noResultTip.text = @"无结果";
  65. self.noResultTip.hidden = YES;
  66. [self.noResultTip sizeToFit];
  67. [self.tableView addSubview:self.noResultTip];
  68. [self adjustTableViewInset];
  69. }
  70. - (void)adjustTableViewInset
  71. {
  72. CGFloat resultInsetTop = self.searchController.searchBar.height + [UIApplication sharedApplication].statusBarFrame.size.height;
  73. UIEdgeInsets resultInsets = {resultInsetTop, 0, 0, 0};
  74. self.searchResultController.tableView.contentInset = resultInsets;
  75. }
  76. - (void)viewDidLayoutSubviews{
  77. self.noResultTip.centerX = self.tableView.width * .5f;
  78. self.noResultTip.centerY = self.tableView.height * .5f;
  79. }
  80. - (void)prepareMember{
  81. if (self.session.sessionType == NIMSessionTypeTeam) {
  82. __weak typeof(self) wself = self;
  83. [[NIMSDK sharedSDK].teamManager fetchTeamMembers:self.session.sessionId completion:^(NSError *error, NSArray *members) {
  84. NSMutableArray *data = [[NSMutableArray alloc] init];
  85. for (NIMTeamMember *member in members) {
  86. if(member.userId.length){
  87. [data addObject:member.userId];
  88. }
  89. }
  90. wself.members = data;
  91. }];
  92. }else{
  93. NSString *me = [[NIMSDK sharedSDK].loginManager currentAccount];
  94. self.members = @[self.session.sessionId,me];
  95. }
  96. }
  97. #pragma mark - UISearchResultsUpdating
  98. - (void)updateSearchResultsForSearchController:(UISearchController *)searchController{
  99. self.noResultTip.hidden = YES;
  100. self.keyWord = searchController.searchBar.text;
  101. [self.searchResultController.tableView reloadData];
  102. }
  103. #pragma mark - UITableViewDataSource
  104. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
  105. return [[self fetchData:tableView] count];
  106. }
  107. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
  108. NSString *identity;
  109. NSArray *data = [self fetchData:tableView];
  110. NTESSearchLocalHistoryObject *object = data[indexPath.row];
  111. if (object.type == SearchLocalHistoryTypeEntrance) {
  112. identity = EntranceCellIdentity;
  113. }else{
  114. identity = ContentCellIdentity;
  115. }
  116. UITableViewCell<NTESSearchObjectRefresh> *cell = [tableView dequeueReusableCellWithIdentifier:identity];
  117. [cell refresh:object];
  118. return cell;
  119. }
  120. #pragma mark - UITableViewDelegate
  121. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
  122. NSArray *data = [self fetchData:tableView];
  123. NTESSearchLocalHistoryObject *object = data[indexPath.row];
  124. return object.uiHeight;
  125. }
  126. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
  127. [tableView deselectRowAtIndexPath:indexPath animated:YES];
  128. NSArray *data = [self fetchData:tableView];
  129. NTESSearchLocalHistoryObject *object = data[indexPath.row];
  130. if (object.type == SearchLocalHistoryTypeEntrance) {
  131. [self.data removeAllObjects];
  132. NIMMessageSearchOption *option = [[NIMMessageSearchOption alloc] init];
  133. option.searchContent = self.keyWord;
  134. NSArray *uids = [self searchUsersByKeyword:self.keyWord users:self.members];
  135. option.fromIds = uids;
  136. option.limit = SearchLimit;
  137. option.order = [NTESBundleSetting sharedConfig].localSearchOrderByTimeDesc? NIMMessageSearchOrderDesc: NIMMessageSearchOrderAsc;
  138. self.lastOption = option;
  139. [self.searchController setActive:NO];
  140. [self showSearchData:option loadMore:YES];
  141. }
  142. else if(object.type == SearchLocalHistoryTypeContent)
  143. {
  144. NTESSessionViewController *sessionVC = [[NTESSessionViewController alloc] initWithSession:_session];
  145. sessionVC.scrollToMessage = object.message;
  146. [self.navigationController pushViewController:sessionVC animated:YES];
  147. }
  148. }
  149. #pragma mark - Action
  150. - (void)onPull2Refresh:(id)sender{
  151. if (!self.keyWord.length) {
  152. NTESSearchLocalHistoryObject *obj = self.data.firstObject;
  153. if ([NTESBundleSetting sharedConfig].localSearchOrderByTimeDesc == NIMMessageSearchOrderDesc) {
  154. self.lastOption.startTime = 0;
  155. self.lastOption.endTime = obj.message.timestamp;
  156. }else{
  157. self.lastOption.startTime = obj.message.timestamp;
  158. self.lastOption.endTime = 0;
  159. }
  160. [self showSearchData:self.lastOption loadMore:NO];
  161. }
  162. }
  163. - (void)loadMore:(id)sender{
  164. if (!self.keyWord.length) {
  165. NTESSearchLocalHistoryObject *obj = self.data.lastObject;
  166. if ([NTESBundleSetting sharedConfig].localSearchOrderByTimeDesc == NIMMessageSearchOrderDesc) {
  167. self.lastOption.startTime = obj.message.timestamp;
  168. self.lastOption.endTime = 0;
  169. }else{
  170. self.lastOption.startTime = 0;
  171. self.lastOption.endTime = obj.message.timestamp;
  172. }
  173. [self showSearchData:self.lastOption loadMore:YES];
  174. }
  175. }
  176. #pragma mark - Private
  177. - (NSArray *)fetchData:(UITableView *)tableView{
  178. if (tableView == self.tableView) {
  179. return self.data;
  180. }else{
  181. NTESSearchLocalHistoryObject *obj = [[NTESSearchLocalHistoryObject alloc] init];
  182. obj.content = self.keyWord.length? [NSString stringWithFormat:@"搜索:“%@”",self.keyWord] : @"";
  183. obj.type = SearchLocalHistoryTypeEntrance;
  184. obj.uiHeight = EntranceCellHeight;
  185. return [@[obj] mutableCopy];
  186. }
  187. }
  188. - (void)showSearchData:(NIMMessageSearchOption *)option loadMore:(BOOL)loadMore{
  189. __weak typeof(self) wself = self;
  190. [[NIMSDK sharedSDK].conversationManager searchMessages:self.session option:option result:^(NSError *error, NSArray *messages) {
  191. messages = [NTESBundleSetting sharedConfig].localSearchOrderByTimeDesc == NIMMessageSearchOrderAsc ? messages.reverseObjectEnumerator.allObjects : messages;
  192. NSMutableArray *array = [[NSMutableArray alloc]init];
  193. for (NIMMessage *message in messages) {
  194. NTESSearchLocalHistoryObject *obj = [[NTESSearchLocalHistoryObject alloc] initWithMessage:message];
  195. obj.type = SearchLocalHistoryTypeContent;
  196. [array addObject:obj];
  197. }
  198. if (loadMore) {
  199. [wself.data addObjectsFromArray:array];
  200. wself.tableView.tableFooterView = array.count == SearchLimit? wself.tableFooterView : [[UIView alloc]init];
  201. wself.noResultTip.hidden = wself.data.count != 0;
  202. }else{
  203. [array addObjectsFromArray:self.data];
  204. wself.data = array;
  205. }
  206. wself.keyWord = nil;
  207. [wself.tableView reloadData];
  208. [wself.refreshControl endRefreshing];
  209. }];
  210. }
  211. - (UIView *)tableFooterView{
  212. UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, UIScreenWidth, ContentCellHeight)];
  213. [btn addTarget:self action:@selector(loadMore:) forControlEvents:UIControlEventTouchUpInside];
  214. UILabel *lable = [[UILabel alloc] initWithFrame:CGRectZero];
  215. lable.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
  216. lable.text = @"点击加载更多";
  217. [lable sizeToFit];
  218. [btn addSubview:lable];
  219. lable.centerX = btn.width * .5f;
  220. lable.centerY = btn.height * .5f;
  221. UIView *sep = [[UIView alloc] initWithFrame:CGRectMake(0, 0, UIScreenWidth, 0.5f)];
  222. sep.backgroundColor = UIColorFromRGB(0xebebeb);
  223. [btn addSubview:sep];
  224. return btn;
  225. }
  226. - (NSArray *)searchUsersByKeyword:(NSString *)keyword users:(NSArray *)users{
  227. NSMutableArray *data = [[NSMutableArray alloc] init];
  228. for (NSString *uid in users) {
  229. NIMKitInfo *info = [[NIMKit sharedKit] infoByUser:uid option:nil];
  230. [data addObject:info];
  231. }
  232. NSPredicate *predicate = [NSPredicate predicateWithFormat: @"SELF.showName CONTAINS[cd] %@",keyword];
  233. NSArray *array = [data filteredArrayUsingPredicate:predicate];
  234. NSMutableArray *output = [[NSMutableArray alloc] init];
  235. for (NIMKitInfo *info in array) {
  236. [output addObject:info.infoId];
  237. }
  238. return output;
  239. }
  240. #pragma mark - 旋转处理 (iOS8 or above)
  241. - (void)viewWillTransitionToSize:(CGSize)size
  242. withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
  243. {
  244. [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
  245. if (self.searchController.isActive) {
  246. [self.searchController setActive:NO];
  247. }
  248. }
  249. @end