Bug Fix - Performance on searching people when inviting is terrible.

#887

- Improve the contact search in the 'Start Chat' screen.
- TODO: Report this changes in 'Room Settings' to add new members, and in 'People Search' screen.
This commit is contained in:
giomfo
2017-01-03 17:52:42 +01:00
parent bdcf8f2011
commit 941bb3ea22
+115 -75
View File
@@ -43,11 +43,14 @@
// HTTP Request
MXHTTPOperation *roomCreationRequest;
// Search session
NSString *currentSearchText;
UIView* searchBarSeparator;
// Search processing
dispatch_queue_t searchProcessingQueue;
NSUInteger searchProcessingCount;
NSString *searchProcessingText;
NSMutableArray<MXKContact*> *searchProcessingContacts;
// Search results
NSString *currentSearchText;
NSMutableArray<MXKContact*> *invitableContacts;
// Contact instances by matrix user id, or email address.
@@ -150,6 +153,12 @@
// Prepare room participants
participants = [NSMutableArray array];
// Prepare search session
searchProcessingQueue = dispatch_queue_create("StartChatViewController", DISPATCH_QUEUE_SERIAL);
searchProcessingCount = 0;
searchProcessingText = nil;
searchProcessingContacts = nil;
// FIXME: Handle multi accounts
NSString *displayName = NSLocalizedStringFromTable(@"you", @"Vector", nil);
userContact = [[MXKContact alloc] initMatrixContactWithDisplayName:displayName andMatrixID:self.mainSession.myUser.userId];
@@ -187,6 +196,9 @@
currentAlert = nil;
}
searchProcessingQueue = nil;
searchProcessingContacts = nil;
[super destroy];
}
@@ -301,7 +313,7 @@
[participantsById setObject:userContact forKey:self.mainSession.myUser.userId];
}
- (void)sortInvitableContacts
- (void)sortContacts:(NSMutableArray*)contacts
{
// Sort invitable contacts by displaying local email first
// ...and then alphabetically.
@@ -323,7 +335,7 @@
};
// Sort invitable contacts list
[invitableContacts sortUsingComparator:comparator];
[contacts sortUsingComparator:comparator];
}
#pragma mark - UITableView data source
@@ -358,7 +370,7 @@
invitableContacts = [NSMutableArray arrayWithArray:[[MXKContactManager sharedManager] privateMatrixContacts:self.mainSession]];
// Sort the refreshed list of the invitable contacts
[self sortInvitableContacts];
[self sortContacts:invitableContacts];
}
count = invitableContacts.count;
@@ -722,95 +734,123 @@
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
// Update search results.
NSMutableArray<MXKContact*> *contacts;
searchText = [searchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if (currentSearchText.length && [searchText hasPrefix:currentSearchText])
{
contacts = invitableContacts;
}
else if (searchText.length)
{
// Retrieve all known matrix users
NSArray *matrixContacts = [NSMutableArray arrayWithArray:[MXKContactManager sharedManager].matrixContacts];
searchProcessingCount++;
[self startActivityIndicator];
dispatch_async(searchProcessingQueue, ^{
// Retrieve all known email addresses from local contacts
NSArray *localEmailContacts = [MXKContactManager sharedManager].localEmailContacts;
contacts = [NSMutableArray arrayWithCapacity:(matrixContacts.count + localEmailContacts.count)];
// Add first email contacts
for (MXKContact* contact in localEmailContacts)
if (!searchText.length)
{
// Remove the current emails listed in participants.
if ([participantsById objectForKey:contact.displayName] == nil)
{
[contacts addObject:contact];
}
searchProcessingContacts = nil;
}
// Matrix ids: split contacts with several ids, and remove the current participants.
for (MXKContact* contact in matrixContacts)
else if (!searchProcessingText.length || [searchText hasPrefix:searchProcessingText] == NO)
{
NSArray *identifiers = contact.matrixIdentifiers;
if (identifiers.count > 1)
// Retrieve all known matrix users
NSArray *matrixContacts = [NSMutableArray arrayWithArray:[MXKContactManager sharedManager].matrixContacts];
// Retrieve all known email addresses from local contacts
NSArray *localEmailContacts = [MXKContactManager sharedManager].localEmailContacts;
searchProcessingContacts = [NSMutableArray arrayWithCapacity:(matrixContacts.count + localEmailContacts.count)];
// Add first email contacts
for (MXKContact* contact in localEmailContacts)
{
for (NSString *userId in identifiers)
// Remove the current emails listed in participants.
if ([participantsById objectForKey:contact.displayName] == nil)
{
[searchProcessingContacts addObject:contact];
}
}
// Matrix ids: split contacts with several ids, and remove the current participants.
for (MXKContact* contact in matrixContacts)
{
NSArray *identifiers = contact.matrixIdentifiers;
if (identifiers.count > 1)
{
for (NSString *userId in identifiers)
{
if ([participantsById objectForKey:userId] == nil)
{
MXKContact *splitContact = [[MXKContact alloc] initMatrixContactWithDisplayName:contact.displayName andMatrixID:userId];
[searchProcessingContacts addObject:splitContact];
}
}
}
else if (identifiers.count)
{
NSString *userId = identifiers.firstObject;
if ([participantsById objectForKey:userId] == nil)
{
MXKContact *splitContact = [[MXKContact alloc] initMatrixContactWithDisplayName:contact.displayName andMatrixID:userId];
[contacts addObject:splitContact];
[searchProcessingContacts addObject:contact];
}
}
}
else if (identifiers.count)
}
// Check whether the search input is a valid email or a Matrix user ID
BOOL isValidInput = ([MXTools isEmailAddress:searchText] || [MXTools isMatrixUserIdentifier:searchText]);
for (NSUInteger index = 0; index < searchProcessingContacts.count;)
{
MXKContact* contact = searchProcessingContacts[index];
if (![contact hasPrefix:searchText])
{
NSString *userId = identifiers.firstObject;
if ([participantsById objectForKey:userId] == nil)
[searchProcessingContacts removeObjectAtIndex:index];
}
else
{
// Ignore the contact if it corresponds to the search input
if (isValidInput && [contact.displayName isEqualToString:searchText])
{
[contacts addObject:contact];
[searchProcessingContacts removeObjectAtIndex:index];
}
else
{
// Next
index++;
}
}
}
}
currentSearchText = searchText;
// Check whether the search input is a valid email or a Matrix user ID
BOOL isValidInput = ([MXTools isEmailAddress:currentSearchText] || [MXTools isMatrixUserIdentifier:currentSearchText]);
// Update invitable contacts list:
invitableContacts = [NSMutableArray array];
for (MXKContact* contact in contacts)
{
if ([contact hasPrefix:currentSearchText])
// Sort the refreshed list of the invitable contacts
[self sortContacts:searchProcessingContacts];
if (searchText.length)
{
// Ignore the contact if it corresponds to the search input
if (!isValidInput || [contact.displayName isEqualToString:currentSearchText] == NO)
{
[invitableContacts addObject:contact];
}
// Show what the user is typing in a cell. So that he can click on it
MXKContact *contact = [[MXKContact alloc] initMatrixContactWithDisplayName:searchText andMatrixID:nil];
[searchProcessingContacts insertObject:contact atIndex:0];
}
}
// Sort the refreshed list of the invitable contacts
[self sortInvitableContacts];
if (currentSearchText.length)
{
// Show what the user is typing in a cell. So that he can click on it
MXKContact *contact = [[MXKContact alloc] initMatrixContactWithDisplayName:searchText andMatrixID:nil];
[invitableContacts insertObject:contact atIndex:0];
}
// Refresh display
[self refreshTableView];
// Force scroll to top
[self.tableView setContentOffset:CGPointMake(-self.tableView.contentInset.left, -self.tableView.contentInset.top) animated:YES];
searchProcessingText = searchText;
dispatch_sync(dispatch_get_main_queue(), ^{
// Render the search result only if there is no other search in progress.
searchProcessingCount --;
if (!searchProcessingCount)
{
[self stopActivityIndicator];
// Update the invitable contacts.
currentSearchText = searchProcessingText;
invitableContacts = searchProcessingContacts;
// Refresh display
[self refreshTableView];
// Force scroll to top
[self.tableView setContentOffset:CGPointMake(-self.tableView.contentInset.left, -self.tableView.contentInset.top) animated:YES];
}
});
});
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar