mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-30 16:22:39 +00:00
-> the MXUsers were not always displayed at cold start : the mxSession was not yet initilized
-> application background/debackground management : do not remove the MXUsers before triggering the 3PIDs lookup. It avoid useless flickerings.
This commit is contained in:
parent
4051cf4fdb
commit
f0e9580df9
1 changed files with 185 additions and 90 deletions
|
@ -25,6 +25,14 @@
|
|||
// warn when there is a contacts list refresh
|
||||
NSString *const kContactManagerRefreshNotification = @"kContactManagerRefreshNotification";
|
||||
|
||||
@interface ContactManager() {
|
||||
NSDate *lastSyncDate;
|
||||
NSMutableArray* deviceContactsList;
|
||||
|
||||
BOOL hasStatusObserver;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation ContactManager
|
||||
@synthesize contacts;
|
||||
|
||||
|
@ -50,9 +58,16 @@ static ContactManager* sharedContactManager = nil;
|
|||
// put an empty array instead of nil
|
||||
contacts = [[NSMutableArray alloc] init];
|
||||
|
||||
// save the last sync date
|
||||
// to avoid resync the whole phonebook
|
||||
lastSyncDate = nil;
|
||||
|
||||
// check if the application is allowed to list the contacts
|
||||
ABAuthorizationStatus cbStatus = ABAddressBookGetAuthorizationStatus();
|
||||
|
||||
//
|
||||
hasStatusObserver = NO;
|
||||
|
||||
// did not yet request the access
|
||||
if (cbStatus == kABAuthorizationStatusNotDetermined) {
|
||||
// request address book access
|
||||
|
@ -75,29 +90,32 @@ static ContactManager* sharedContactManager = nil;
|
|||
}
|
||||
|
||||
-(void)dealloc {
|
||||
if (hasStatusObserver) {
|
||||
[[MatrixSDKHandler sharedHandler] removeObserver:self forKeyPath:@"status"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)refresh
|
||||
{
|
||||
// did not yet request the access
|
||||
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
|
||||
// wait that the user gives the Authorization
|
||||
return;
|
||||
MatrixSDKHandler* mxHandler = [MatrixSDKHandler sharedHandler];
|
||||
|
||||
// remove any observer
|
||||
if (hasStatusObserver) {
|
||||
[mxHandler removeObserver:self forKeyPath:@"status"];
|
||||
hasStatusObserver = NO;
|
||||
}
|
||||
|
||||
//
|
||||
matrixIDBy3PID = [[NSMutableDictionary alloc] init];
|
||||
|
||||
dispatch_async(processingQueue, ^{
|
||||
NSMutableArray* contactsList = [[NSMutableArray alloc] init];
|
||||
|
||||
// can list tocal contacts
|
||||
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
|
||||
|
||||
ABAddressBookRef ab = ABAddressBookCreateWithOptions(nil, nil);
|
||||
ABRecordRef contactRecord;
|
||||
int index;
|
||||
|
||||
//CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
|
||||
CFMutableArrayRef people = (CFMutableArrayRef)ABAddressBookCopyArrayOfAllPeople(ab);
|
||||
|
||||
NSMutableArray* contactsList = [[NSMutableArray alloc] init];
|
||||
|
||||
if (nil != people) {
|
||||
int peopleCount = CFArrayGetCount(people);
|
||||
|
||||
|
@ -112,23 +130,126 @@ static ContactManager* sharedContactManager = nil;
|
|||
if (ab) {
|
||||
CFRelease(ab);
|
||||
}
|
||||
}
|
||||
|
||||
contacts = contactsList;
|
||||
deviceContactsList = contactsList;
|
||||
|
||||
if (mxHandler.mxSession) {
|
||||
[self manage3PIDS];
|
||||
} else {
|
||||
// display what you could have read
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
contacts = deviceContactsList;
|
||||
|
||||
hasStatusObserver = YES;
|
||||
// wait that the mxSession is ready
|
||||
[mxHandler addObserver:self forKeyPath:@"status" options:0 context:nil];
|
||||
// at least, display the known contacts
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kContactManagerRefreshNotification object:nil userInfo:nil];
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// the local contacts are listed
|
||||
// update their 3PIDs and their update
|
||||
- (void) manage3PIDS {
|
||||
dispatch_async(processingQueue, ^{
|
||||
NSMutableArray* tmpContacts = nil;
|
||||
|
||||
// initial sync
|
||||
if (!lastSyncDate) {
|
||||
// display the current device contacts
|
||||
tmpContacts = deviceContactsList;
|
||||
} else {
|
||||
// update with the known dict 3PID -> matrix ID
|
||||
[self updateMatrixIDDeviceContactsList];
|
||||
|
||||
// build a merged contacts list until the 3PIDs lookups are performed
|
||||
NSMutableArray* mergedContactsList = [deviceContactsList mutableCopy];
|
||||
[self mergeMXUsers:mergedContactsList];
|
||||
tmpContacts = mergedContactsList;
|
||||
}
|
||||
lastSyncDate = [NSDate date];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// stored self.contacts in the right thread
|
||||
contacts = tmpContacts;
|
||||
// refresh the 3PIDS -> matrix IDs
|
||||
[self refreshMatrixIDs];
|
||||
// at least, display the known contacts
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kContactManagerRefreshNotification object:nil userInfo:nil];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
- (void) updateMatrixIDDeviceContactsList {
|
||||
// update the contacts info
|
||||
for(MXCContact* contact in deviceContactsList) {
|
||||
// the phonenumbers wil be managed later
|
||||
/*for(ConsolePhoneNumber* pn in contact.phoneNumbers) {
|
||||
if (pn.textNumber.length > 0) {
|
||||
|
||||
// not yet added
|
||||
if ([pids indexOfObject:pn.textNumber] == NSNotFound) {
|
||||
[pids addObject:pn.textNumber];
|
||||
[medias addObject:@"msisdn"];
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
for(MXCEmail* email in contact.emailAddresses) {
|
||||
if (email.emailAddress.length > 0) {
|
||||
id matrixID = [matrixIDBy3PID valueForKey:email.emailAddress];
|
||||
|
||||
if ([matrixID isKindOfClass:[NSString class]]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[email setMatrixID:matrixID];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// merge the knowns MXUsers with the contacts list
|
||||
// return the number of modified / added contacts
|
||||
- (int) mergeMXUsers:(NSMutableArray*)contactsList {
|
||||
// check if the some room users are not defined in the local contacts book
|
||||
MatrixSDKHandler *mxHandler = [MatrixSDKHandler sharedHandler];
|
||||
|
||||
// check if the user is already known
|
||||
NSArray* users = [mxHandler.mxSession users];
|
||||
NSArray* knownUserIDs = [matrixIDBy3PID allValues];
|
||||
|
||||
int count = 0;
|
||||
|
||||
for(MXUser* user in users) {
|
||||
|
||||
if ([knownUserIDs indexOfObject:user.userId] == NSNotFound) {
|
||||
NSString* dummyContactID = [NSString stringWithFormat:@"%lu", (unsigned long)user.userId.hash];
|
||||
|
||||
// with the current API, there is no way to get the email from the matrxID
|
||||
MXCEmail* email = [[MXCEmail alloc] initWithEmailAddress:user.userId type:@"" contactID:dummyContactID matrixID:user.userId];
|
||||
MXCContact* contact = [[MXCContact alloc] initWithDisplayName:(user.displayname ? user.displayname : user.userId) contactID:dummyContactID emails:@[email] phonenumbers:nil];
|
||||
|
||||
[contactsList addObject:contact];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// refresh the 3PIDs -> Matrix ID list
|
||||
// update the contact is required
|
||||
- (void)refreshMatrixIDs {
|
||||
|
||||
// build the request parameters
|
||||
NSMutableArray* pids = [[NSMutableArray alloc] init];
|
||||
NSMutableArray* medias = [[NSMutableArray alloc] init];
|
||||
|
||||
for(MXCContact* contact in contacts) {
|
||||
for(MXCContact* contact in deviceContactsList) {
|
||||
// the phonenumbers are not managed
|
||||
/*for(ConsolePhoneNumber* pn in contact.phoneNumbers) {
|
||||
if (pn.textNumber.length > 0) {
|
||||
|
@ -166,61 +287,16 @@ static ContactManager* sharedContactManager = nil;
|
|||
|
||||
matrixIDBy3PID = [[NSMutableDictionary alloc] initWithObjects:userIds forKeys:pids];
|
||||
|
||||
for(MXCContact* contact in contacts) {
|
||||
// the phonenumbers wil be managed later
|
||||
/*for(ConsolePhoneNumber* pn in contact.phoneNumbers) {
|
||||
if (pn.textNumber.length > 0) {
|
||||
[self updateMatrixIDDeviceContactsList];
|
||||
|
||||
// not yet added
|
||||
if ([pids indexOfObject:pn.textNumber] == NSNotFound) {
|
||||
[pids addObject:pn.textNumber];
|
||||
[medias addObject:@"msisdn"];
|
||||
}
|
||||
}
|
||||
}*/
|
||||
// add the MX users
|
||||
NSMutableArray* tmpContacts = [deviceContactsList mutableCopy];
|
||||
[self mergeMXUsers:tmpContacts];
|
||||
|
||||
for(MXCEmail* email in contact.emailAddresses) {
|
||||
if (email.emailAddress.length > 0) {
|
||||
id matrixID = [matrixIDBy3PID valueForKey:email.emailAddress];
|
||||
|
||||
if ([matrixID isKindOfClass:[NSString class]]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[email setMatrixID:matrixID];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if the some room users are not defined in the local contacts book
|
||||
MatrixSDKHandler *mxHandler = [MatrixSDKHandler sharedHandler];
|
||||
|
||||
// check if the user is already known
|
||||
NSArray* users = [mxHandler.mxSession users];
|
||||
|
||||
NSMutableArray* unknownRoomContacts = [[NSMutableArray alloc] init];
|
||||
|
||||
for(MXUser* user in users) {
|
||||
|
||||
if ([userIds indexOfObject:user.userId] == NSNotFound) {
|
||||
NSString* dummyContactID = [NSString stringWithFormat:@"%lu", (unsigned long)user.userId.hash];
|
||||
|
||||
// with the current API, there is no way to get the email from the matrxID
|
||||
MXCEmail* email = [[MXCEmail alloc] initWithEmailAddress:user.userId type:@"" contactID:dummyContactID matrixID:user.userId];
|
||||
MXCContact* contact = [[MXCContact alloc] initWithDisplayName:(user.displayname ? user.displayname : user.userId) contactID:dummyContactID emails:@[email] phonenumbers:nil];
|
||||
|
||||
[unknownRoomContacts addObject:contact];
|
||||
}
|
||||
}
|
||||
|
||||
// some members are not listed in the contacts
|
||||
if (unknownRoomContacts.count > 0) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.contacts addObjectsFromArray:unknownRoomContacts];
|
||||
contacts = tmpContacts;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kContactManagerRefreshNotification object:nil userInfo:nil];
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
failure:^(NSError *error) {
|
||||
|
@ -234,6 +310,25 @@ static ContactManager* sharedContactManager = nil;
|
|||
}
|
||||
}
|
||||
|
||||
#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 ([MatrixSDKHandler sharedHandler].status == MatrixSDKHandlerStatusServerSyncDone) {
|
||||
|
||||
if (hasStatusObserver) {
|
||||
[[MatrixSDKHandler sharedHandler] removeObserver:self forKeyPath:@"status"];
|
||||
hasStatusObserver = NO;
|
||||
}
|
||||
|
||||
[self manage3PIDS];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (SectionedContacts *)getSectionedContacts:(NSArray*)contactsList {
|
||||
UILocalizedIndexedCollation *collation = [UILocalizedIndexedCollation currentCollation];
|
||||
|
||||
|
|
Loading…
Reference in a new issue