element-ios/matrixConsole/ViewController/ContactsViewController.m
ylecollen 3b07ae6910 Add ContactDetailsViewController : tapping on a contact thumbnail will open this new viewController if it contains some matrixIDs.
So, the user will be able to see
- thumbnail
- display name
- list of matrix IDs + start a chat with one of them.
2015-01-28 08:25:34 +01:00

764 lines
29 KiB
Objective-C

/*
Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import "ContactsViewController.h"
// SDK api
#import "MatrixSDKHandler.h"
// application info
#import "AppDelegate.h"
// contacts management
#import "ContactManager.h"
#import "MXCContact.h"
#import "MXCEmail.h"
#import "MXCPhoneNumber.h"
// contact cell
#import "ContactTableCell.h"
// alert
#import "MXCAlert.h"
// settings
#import "AppSettings.h"
//
#import "ContactDetailsViewController.h"
NSString *const kInvitationMessage = @"I'd like to chat with you with matrix. Please, visit the website http://matrix.org to have more information.";
@interface ContactsViewController () {
// YES -> only matrix users
// NO -> display local contacts
BOOL displayMatrixUsers;
// screenshot of the local contacts
NSMutableArray* localContacts;
SectionedContacts* sectionedLocalContacts;
// screenshot of the matrix users
NSMutableDictionary* matrixUserByMatrixID;
SectionedContacts* sectionedMatrixContacts;
// tap on thumbnail to display contact info
MXCContact* selectedContact;
// Search
UISearchBar *contactsSearchBar;
NSMutableArray *filteredContacts;
SectionedContacts* sectionedFilteredContacts;
BOOL searchBarShouldEndEditing;
NSString* latestSearchedPattern;
}
@property (strong, nonatomic) MXCAlert *startChatMenu;
@property (strong, nonatomic) MXCAlert *allowContactSyncAlert;
@property (weak, nonatomic) IBOutlet UITableView* tableView;
@property (weak, nonatomic) IBOutlet UISegmentedControl* contactsControls;
@property (strong, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
@end
@implementation ContactsViewController
- (void)viewDidLoad {
[super viewDidLoad];
// get the system collation titles
collationTitles = [[UILocalizedIndexedCollation currentCollation]sectionTitles];
// global init
displayMatrixUsers = (0 == self.contactsControls.selectedSegmentIndex);
matrixUserByMatrixID = [[NSMutableDictionary alloc] init];
// event listener
[[MatrixSDKHandler sharedHandler] addObserver:self forKeyPath:@"status" options:0 context:nil];
// add the search icon on the right
// need to add more buttons ?
UIBarButtonItem *searchButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch target:self action:@selector(search:)];
self.navigationItem.rightBarButtonItems = @[searchButton];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onContactsRefresh:) name:kContactManagerContactsListRefreshNotification object:nil];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// required to reduce the tableview height while searching
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onKeyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// Leave potential search session
if (contactsSearchBar) {
[self searchBarCancelButtonClicked:contactsSearchBar];
}
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
}
- (void)startActivityIndicator {
[_activityIndicator.layer setCornerRadius:5];
_activityIndicator.hidden = NO;
[_activityIndicator startAnimating];
}
- (void)stopActivityIndicator {
[_activityIndicator stopAnimating];
_activityIndicator.hidden = YES;
}
- (void)scrollToTop {
// stop any scrolling effect
[UIView setAnimationsEnabled:NO];
// before scrolling to the tableview top
self.tableView.contentOffset = CGPointMake(-self.tableView.contentInset.left, -self.tableView.contentInset.top);
[UIView setAnimationsEnabled:YES];
}
// should be called when resetting the application
// the contact manager warn there is a contacts list update
// but the Matrix SDK handler has no more userID -> so assume there is a reset
- (void)reset {
// Leave potential search session
if (contactsSearchBar) {
[self searchBarCancelButtonClicked:contactsSearchBar];
}
localContacts = nil;
sectionedLocalContacts = nil;
matrixUserByMatrixID = [[NSMutableDictionary alloc] init];;
sectionedMatrixContacts = nil;
[self.contactsControls setSelectedSegmentIndex:0];
[self.tableView reloadData];
}
#pragma mark - Keyboard handling
- (void)onKeyboardWillShow:(NSNotification *)notif {
// get the keyboard size
NSValue *rectVal = notif.userInfo[UIKeyboardFrameEndUserInfoKey];
CGRect endRect = rectVal.CGRectValue;
// IOS 8 triggers some unexpected keyboard events
if ((endRect.size.height == 0) || (endRect.size.width == 0)) {
return;
}
CGFloat keyboardHeight = (endRect.origin.y == 0) ? endRect.size.width : endRect.size.height;
// the tableview bottom inset must also be updated
UIEdgeInsets insets = self.tableView.contentInset;
insets.bottom = keyboardHeight;
// get the animation info
NSNumber *curveValue = [[notif userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey];
UIViewAnimationCurve animationCurve = curveValue.intValue;
// the duration is ignored but it is better to define it
double animationDuration = [[[notif userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
[UIView animateWithDuration:animationDuration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | (animationCurve << 16) animations:^{
// reduce the tableview height
self.tableView.contentInset = insets;
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
}];
}
- (void)onKeyboardWillHide:(NSNotification *)notif {
// get the keyboard size
NSValue *rectVal = notif.userInfo[UIKeyboardFrameEndUserInfoKey];
CGRect endRect = rectVal.CGRectValue;
rectVal = notif.userInfo[UIKeyboardFrameBeginUserInfoKey];
CGRect beginRect = rectVal.CGRectValue;
UIEdgeInsets insets = self.tableView.contentInset;
insets.bottom = 0;
// do not animate if the both rect are the same
// but ensure that the fields are properly resetted
// e.g. when the user swipes to hide the keyboard
// this method is called with invalid rects
// animationDuration is ignored because of the animation curve
// use it to be sure that it will be broken with any new IOS update
if (CGRectEqualToRect(endRect, beginRect)) {
self.tableView.contentInset = insets;
[self.view layoutIfNeeded];
} else {
// get the animation info
NSNumber *curveValue = [[notif userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey];
UIViewAnimationCurve animationCurve = curveValue.intValue;
// the duration is ignored but it is better to define it
double animationDuration = [[[notif userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// animate the keyboard closing
[UIView animateWithDuration:animationDuration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | (animationCurve << 16) animations:^{
self.tableView.contentInset = insets;
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
}];
}
}
#pragma mark - UITableView delegate
- (void)updateSectionedLocalContacts {
[self stopActivityIndicator];
ContactManager* sharedManager = [ContactManager sharedManager];
if (!localContacts) {
localContacts = sharedManager.contacts;
}
if (!sectionedLocalContacts) {
sectionedLocalContacts = [sharedManager getSectionedContacts:sharedManager.contacts];
}
}
- (void)updateSectionedMatrixContacts {
// check if the user is already known
MatrixSDKHandler *mxHandler = [MatrixSDKHandler sharedHandler];
if ((mxHandler.status != MatrixSDKHandlerStatusServerSyncDone) && (mxHandler.status != MatrixSDKHandlerStatusStoreDataReady)) {
[self startActivityIndicator];
sectionedMatrixContacts = nil;
} else {
[self stopActivityIndicator];
//NSArray* users = [mxHandler.mxSession users];
NSArray* usersIDs = [mxHandler oneToOneRoomMemberMatrixIDs];
// return a MatrixIDs list of 1:1 room members
NSMutableArray* knownUserIDs = [[matrixUserByMatrixID allKeys] mutableCopy];
// list the contacts IDs
// avoid delete and create the same ones
// it could save thumbnail downloads
for(NSString* userID in usersIDs) {
//
MXUser* user = [mxHandler.mxSession userWithUserId:userID];
// sanity check
if (user) {
// managed UserID
[knownUserIDs removeObject:userID];
MXCContact* contact = [matrixUserByMatrixID objectForKey:userID];
// already defined
if (contact) {
contact.displayName = (user.displayname.length > 0) ? user.displayname : user.userId;
} else {
contact = [[MXCContact alloc] initWithDisplayName:((user.displayname.length > 0) ? user.displayname : user.userId) matrixID:user.userId];
[matrixUserByMatrixID setValue:contact forKey:userID];
}
}
}
// some userIDs don't exist anymore
for (NSString* userID in knownUserIDs) {
[matrixUserByMatrixID removeObjectForKey:userID];
}
sectionedMatrixContacts = [[ContactManager sharedManager] getSectionedContacts:[matrixUserByMatrixID allValues]];
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// search in progress
if (contactsSearchBar) {
return sectionedFilteredContacts.sectionedContacts.count;
}
else if (displayMatrixUsers) {
[self updateSectionedMatrixContacts];
return sectionedMatrixContacts.sectionedContacts.count;
} else {
[self updateSectionedLocalContacts];
return sectionedLocalContacts.sectionedContacts.count;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
SectionedContacts* sectionedContacts = contactsSearchBar ? sectionedFilteredContacts : (displayMatrixUsers ? sectionedMatrixContacts : sectionedLocalContacts);
return [[sectionedContacts.sectionedContacts objectAtIndex:section] count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 50;
}
- (NSString *)tableView:(UITableView *)aTableView titleForHeaderInSection:(NSInteger)section {
SectionedContacts* sectionedContacts = contactsSearchBar ? sectionedFilteredContacts : (displayMatrixUsers ? sectionedMatrixContacts : sectionedLocalContacts);
if (sectionedContacts.sectionTitles.count <= section) {
return nil;
}
else {
return (NSString*)[sectionedContacts.sectionTitles objectAtIndex:section];
}
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)aTableView {
// do not display the collation during a search
if (contactsSearchBar) {
return nil;
} else {
[self.tableView setSectionIndexColor:[AppDelegate theDelegate].masterTabBarController.tabBar.tintColor];
[self.tableView setSectionIndexBackgroundColor:[UIColor clearColor]];
return [[UILocalizedIndexedCollation currentCollation] sectionIndexTitles];
}
}
- (NSInteger)tableView:(UITableView *)aTableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
SectionedContacts* sectionedContacts = contactsSearchBar ? sectionedFilteredContacts : (displayMatrixUsers ? sectionedMatrixContacts : sectionedLocalContacts);
NSUInteger section = [sectionedContacts.sectionTitles indexOfObject:title];
// undefined title -> jump to the first valid non empty section
if (NSNotFound == section) {
NSUInteger systemCollationIndex = [collationTitles indexOfObject:title];
// find in the system collation
if (NSNotFound != systemCollationIndex) {
systemCollationIndex--;
while ((systemCollationIndex == 0) && (NSNotFound == section)) {
NSString* systemTitle = [collationTitles objectAtIndex:systemCollationIndex];
section = [sectionedContacts.sectionTitles indexOfObject:systemTitle];
systemCollationIndex--;
}
}
}
return section;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ContactTableCell* cell = [tableView dequeueReusableCellWithIdentifier:@"ContactCell" forIndexPath:indexPath];
SectionedContacts* sectionedContacts = contactsSearchBar ? sectionedFilteredContacts : (displayMatrixUsers ? sectionedMatrixContacts : sectionedLocalContacts);
MXCContact* contact = nil;
if (indexPath.section < sectionedContacts.sectionedContacts.count) {
NSArray *thisSection = [sectionedContacts.sectionedContacts objectAtIndex:indexPath.section];
if (indexPath.row < thisSection.count) {
contact = [thisSection objectAtIndex:indexPath.row];
}
}
// tap on matrix user thumbnail -> open a detailled sheet
UITapGestureRecognizer* tapGesture = nil;
// check if it is already defined
// gesture in storyboard does not seem to work properly
// it always triggers a tap event on the first cell
for (UIGestureRecognizer* gesture in cell.thumbnailView.gestureRecognizers) {
if ([gesture isKindOfClass:[UITapGestureRecognizer class]]) {
tapGesture = (UITapGestureRecognizer*)gesture;
break;
}
}
// add it if it is not yet defined
if (!tapGesture) {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onContactThumbnailTap:)];
[tap setNumberOfTouchesRequired:1];
[tap setNumberOfTapsRequired:1];
[tap setDelegate:self];
[cell.thumbnailView addGestureRecognizer:tap];
}
cell.contact = contact;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
SectionedContacts* sectionedContacts = contactsSearchBar ? sectionedFilteredContacts : (displayMatrixUsers ? sectionedMatrixContacts : sectionedLocalContacts);
MXCContact* contact = nil;
if (indexPath.section < sectionedContacts.sectionedContacts.count) {
NSArray *thisSection = [sectionedContacts.sectionedContacts objectAtIndex:indexPath.section];
if (indexPath.row < thisSection.count) {
contact = [thisSection objectAtIndex:indexPath.row];
}
}
__weak typeof(self) weakSelf = self;
NSArray* matrixIDs = contact.matrixIdentifiers;
// matrix user ?
if (matrixIDs.count) {
MatrixSDKHandler* mxHandler = [MatrixSDKHandler sharedHandler];
// display only if the matrix SDk is ready
if ((mxHandler.status == MatrixSDKHandlerStatusServerSyncDone) || (mxHandler.status == MatrixSDKHandlerStatusStoreDataReady)) {
// only 1 matrix ID
if (matrixIDs.count == 1) {
NSString* matrixID = [matrixIDs objectAtIndex:0];
self.startChatMenu = [[MXCAlert alloc] initWithTitle:[NSString stringWithFormat:@"Chat with %@", matrixID] message:nil style:MXCAlertStyleAlert];
[self.startChatMenu addActionWithTitle:@"Cancel" style:MXCAlertActionStyleDefault handler:^(MXCAlert *alert) {
weakSelf.startChatMenu = nil;
}];
[self.startChatMenu addActionWithTitle:@"OK" style:MXCAlertActionStyleDefault handler:^(MXCAlert *alert) {
weakSelf.startChatMenu = nil;
[mxHandler startPrivateOneToOneRoomWith:matrixID];
}];
} else {
self.startChatMenu = [[MXCAlert alloc] initWithTitle:[NSString stringWithFormat:@"Chat with "] message:nil style:MXCAlertStyleActionSheet];
for(NSString* matrixID in matrixIDs) {
[self.startChatMenu addActionWithTitle:matrixID style:MXCAlertActionStyleDefault handler:^(MXCAlert *alert) {
weakSelf.startChatMenu = nil;
[mxHandler startPrivateOneToOneRoomWith:matrixID];
}];
}
[self.startChatMenu addActionWithTitle:@"Cancel" style:MXCAlertActionStyleDefault handler:^(MXCAlert *alert) {
weakSelf.startChatMenu = nil;
}];
}
[self.startChatMenu showInViewController:self];
}
} else {
// invite to use matrix
if (([MFMessageComposeViewController canSendText] ? contact.emailAddresses.count : 0) + (contact.phoneNumbers.count > 0)) {
self.startChatMenu = [[MXCAlert alloc] initWithTitle:[NSString stringWithFormat:@"Invite this user to use matrix with"] message:nil style:MXCAlertStyleActionSheet];
// check if the target can send SMSes
if ([MFMessageComposeViewController canSendText]) {
// list phonenumbers
for(MXCPhoneNumber* phonenumber in contact.phoneNumbers) {
[self.startChatMenu addActionWithTitle:phonenumber.textNumber style:MXCAlertActionStyleDefault handler:^(MXCAlert *alert) {
weakSelf.startChatMenu = nil;
// launch SMS composer
MFMessageComposeViewController *messageComposer = [[MFMessageComposeViewController alloc] init];
if (messageComposer)
{
messageComposer.messageComposeDelegate = weakSelf;
messageComposer.body =kInvitationMessage;
messageComposer.recipients = [NSArray arrayWithObject:phonenumber.textNumber];
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf presentViewController:messageComposer animated:YES completion:nil];
});
}
}];
}
}
// list emails
for(MXCEmail* email in contact.emailAddresses) {
[self.startChatMenu addActionWithTitle:email.emailAddress style:MXCAlertActionStyleDefault handler:^(MXCAlert *alert) {
weakSelf.startChatMenu = nil;
dispatch_async(dispatch_get_main_queue(), ^{
NSString* subject = [ @"Matrix.org is magic" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString* body = [kInvitationMessage stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@&body=%@", email.emailAddress, subject, body]]];
});
}];
}
[self.startChatMenu addActionWithTitle:@"Cancel" style:MXCAlertActionStyleDefault handler:^(MXCAlert *alert) {
weakSelf.startChatMenu = nil;
}];
[self.startChatMenu showInViewController:self];
}
}
}
#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([@"status" isEqualToString:keyPath]) {
dispatch_async(dispatch_get_main_queue(), ^{
if (displayMatrixUsers) {
if (contactsSearchBar) {
[self updateSectionedMatrixContacts];
latestSearchedPattern = nil;
[self searchBar:contactsSearchBar textDidChange:contactsSearchBar.text];
} else {
[self.tableView reloadData];
}
}
});
}
}
#pragma mark - Actions
- (void)onContactsRefresh:(NSNotification *)notif {
localContacts = nil;
sectionedLocalContacts = nil;
// there is an user id
if ([[MatrixSDKHandler sharedHandler] userId]) {
[self updateSectionedLocalContacts];
//
if (!displayMatrixUsers) {
if (contactsSearchBar) {
latestSearchedPattern = nil;
[self searchBar:contactsSearchBar textDidChange:contactsSearchBar.text];
} else {
[self.tableView reloadData];
}
}
} else {
// the client could have been logged out
[self reset];
}
}
- (IBAction)onSegmentValueChange:(id)sender {
if (sender == self.contactsControls) {
displayMatrixUsers = (0 == self.contactsControls.selectedSegmentIndex);
if (contactsSearchBar) {
if (displayMatrixUsers) {
[self updateSectionedMatrixContacts];
} else {
[self updateSectionedLocalContacts];
}
latestSearchedPattern = nil;
[self searchBar:contactsSearchBar textDidChange:contactsSearchBar.text];
} else {
[self.tableView reloadData];
}
if (!displayMatrixUsers) {
AppSettings* appSettings = [AppSettings sharedSettings];
if (!appSettings.requestedLocalContactsSync) {
__weak typeof(self) weakSelf = self;
self.allowContactSyncAlert = [[MXCAlert alloc] initWithTitle:@"Allow local contacts synchronization ?" message:nil style:MXCAlertStyleAlert];
[self.allowContactSyncAlert addActionWithTitle:@"NO" style:MXCAlertActionStyleDefault handler:^(MXCAlert *alert) {
weakSelf.allowContactSyncAlert = nil;
}];
[self.allowContactSyncAlert addActionWithTitle:@"YES" style:MXCAlertActionStyleDefault handler:^(MXCAlert *alert) {
weakSelf.allowContactSyncAlert = nil;
dispatch_async(dispatch_get_main_queue(), ^{
appSettings.syncLocalContacts = YES;
[weakSelf.tableView reloadData];
});
}];
[self.allowContactSyncAlert showInViewController:self];
}
}
}
}
- (IBAction)onContactThumbnailTap:(id)sender {
if ([sender isKindOfClass:[UITapGestureRecognizer class]]) {
UIView* tappedView = ((UITapGestureRecognizer*)sender).view;
// search the parentce cell
while (tappedView && ![tappedView isKindOfClass:[ContactTableCell class]]) {
tappedView = tappedView.superview;
}
// find it ?
if ([tappedView isKindOfClass:[ContactTableCell class]]) {
MXCContact* contact = ((ContactTableCell*)tappedView).contact;
// open detailled sheet if there
if (contact.matrixIdentifiers.count > 0) {
selectedContact = ((ContactTableCell*)tappedView).contact;
[self performSegueWithIdentifier:@"showContactDetails" sender:self];
}
}
}
}
#pragma mark - Segues
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"showContactDetails"]) {
ContactDetailsViewController *contactDetailsViewController = segue.destinationViewController;
contactDetailsViewController.contact = selectedContact;
selectedContact = nil;
}
}
#pragma mark MFMessageComposeViewControllerDelegate
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result {
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark Search management
- (void)search:(id)sender {
if (!contactsSearchBar) {
SectionedContacts* sectionedContacts = displayMatrixUsers ? sectionedMatrixContacts : sectionedLocalContacts;
// Check whether there are data in which search
if (sectionedContacts.sectionedContacts.count > 0) {
// Create search bar
contactsSearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
contactsSearchBar.showsCancelButton = YES;
contactsSearchBar.returnKeyType = UIReturnKeyDone;
contactsSearchBar.delegate = self;
contactsSearchBar.tintColor = [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor;
searchBarShouldEndEditing = NO;
// init the table content
latestSearchedPattern = @"";
filteredContacts = [(displayMatrixUsers ? [matrixUserByMatrixID allValues] : localContacts) mutableCopy];
sectionedFilteredContacts = [[ContactManager sharedManager] getSectionedContacts:filteredContacts];
self.tableView.tableHeaderView = contactsSearchBar;
[self.tableView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
[contactsSearchBar becomeFirstResponder];
});
}
} else {
[self searchBarCancelButtonClicked:contactsSearchBar];
}
}
#pragma mark - UISearchBarDelegate
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
searchBarShouldEndEditing = NO;
return YES;
}
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar {
return searchBarShouldEndEditing;
}
- (NSArray*)patternsFromText:(NSString*)text {
NSArray* items = [text componentsSeparatedByString:@" "];
if (items.count <= 1) {
return items;
}
NSMutableArray* patterns = [[NSMutableArray alloc] init];
for (NSString* item in items) {
if (item.length > 0) {
[patterns addObject:item];
}
}
return patterns;
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if ((contactsSearchBar == searchBar) && (![latestSearchedPattern isEqualToString:searchText])) {
latestSearchedPattern = searchText;
// contacts
NSArray* contacts = displayMatrixUsers ? [matrixUserByMatrixID allValues] : localContacts;
// Update filtered list
if (searchText.length && contacts.count) {
filteredContacts = [[NSMutableArray alloc] init];
NSArray* patterns = [self patternsFromText:searchText];
for(MXCContact* contact in contacts) {
if ([contact matchedWithPatterns:patterns]) {
[filteredContacts addObject:contact];
}
}
} else {
filteredContacts = [contacts mutableCopy];
}
sectionedFilteredContacts = [[ContactManager sharedManager] getSectionedContacts:filteredContacts];
// Refresh display
[self.tableView reloadData];
[self scrollToTop];
}
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
if (contactsSearchBar == searchBar) {
// "Done" key has been pressed
searchBarShouldEndEditing = YES;
[contactsSearchBar resignFirstResponder];
}
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
if (contactsSearchBar == searchBar) {
// Leave search
searchBarShouldEndEditing = YES;
[contactsSearchBar resignFirstResponder];
contactsSearchBar = nil;
filteredContacts = nil;
sectionedFilteredContacts = nil;
latestSearchedPattern = nil;
self.tableView.tableHeaderView = nil;
[self.tableView reloadData];
[self scrollToTop];
}
}
@end