mirror of
https://github.com/vector-im/element-ios.git
synced 2024-10-01 00:32:41 +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
|
// warn when there is a contacts list refresh
|
||||||
NSString *const kContactManagerRefreshNotification = @"kContactManagerRefreshNotification";
|
NSString *const kContactManagerRefreshNotification = @"kContactManagerRefreshNotification";
|
||||||
|
|
||||||
|
@interface ContactManager() {
|
||||||
|
NSDate *lastSyncDate;
|
||||||
|
NSMutableArray* deviceContactsList;
|
||||||
|
|
||||||
|
BOOL hasStatusObserver;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation ContactManager
|
@implementation ContactManager
|
||||||
@synthesize contacts;
|
@synthesize contacts;
|
||||||
|
|
||||||
|
@ -50,9 +58,16 @@ static ContactManager* sharedContactManager = nil;
|
||||||
// put an empty array instead of nil
|
// put an empty array instead of nil
|
||||||
contacts = [[NSMutableArray alloc] init];
|
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
|
// check if the application is allowed to list the contacts
|
||||||
ABAuthorizationStatus cbStatus = ABAddressBookGetAuthorizationStatus();
|
ABAuthorizationStatus cbStatus = ABAddressBookGetAuthorizationStatus();
|
||||||
|
|
||||||
|
//
|
||||||
|
hasStatusObserver = NO;
|
||||||
|
|
||||||
// did not yet request the access
|
// did not yet request the access
|
||||||
if (cbStatus == kABAuthorizationStatusNotDetermined) {
|
if (cbStatus == kABAuthorizationStatusNotDetermined) {
|
||||||
// request address book access
|
// request address book access
|
||||||
|
@ -75,29 +90,32 @@ static ContactManager* sharedContactManager = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)dealloc {
|
-(void)dealloc {
|
||||||
|
if (hasStatusObserver) {
|
||||||
|
[[MatrixSDKHandler sharedHandler] removeObserver:self forKeyPath:@"status"];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)refresh
|
- (void)refresh
|
||||||
{
|
{
|
||||||
// did not yet request the access
|
MatrixSDKHandler* mxHandler = [MatrixSDKHandler sharedHandler];
|
||||||
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
|
|
||||||
// wait that the user gives the Authorization
|
// remove any observer
|
||||||
return;
|
if (hasStatusObserver) {
|
||||||
|
[mxHandler removeObserver:self forKeyPath:@"status"];
|
||||||
|
hasStatusObserver = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
matrixIDBy3PID = [[NSMutableDictionary alloc] init];
|
|
||||||
|
|
||||||
dispatch_async(processingQueue, ^{
|
dispatch_async(processingQueue, ^{
|
||||||
|
NSMutableArray* contactsList = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
|
// can list tocal contacts
|
||||||
|
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
|
||||||
|
|
||||||
ABAddressBookRef ab = ABAddressBookCreateWithOptions(nil, nil);
|
ABAddressBookRef ab = ABAddressBookCreateWithOptions(nil, nil);
|
||||||
ABRecordRef contactRecord;
|
ABRecordRef contactRecord;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
//CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
|
|
||||||
CFMutableArrayRef people = (CFMutableArrayRef)ABAddressBookCopyArrayOfAllPeople(ab);
|
CFMutableArrayRef people = (CFMutableArrayRef)ABAddressBookCopyArrayOfAllPeople(ab);
|
||||||
|
|
||||||
NSMutableArray* contactsList = [[NSMutableArray alloc] init];
|
|
||||||
|
|
||||||
if (nil != people) {
|
if (nil != people) {
|
||||||
int peopleCount = CFArrayGetCount(people);
|
int peopleCount = CFArrayGetCount(people);
|
||||||
|
|
||||||
|
@ -112,23 +130,126 @@ static ContactManager* sharedContactManager = nil;
|
||||||
if (ab) {
|
if (ab) {
|
||||||
CFRelease(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(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
// stored self.contacts in the right thread
|
||||||
|
contacts = tmpContacts;
|
||||||
|
// refresh the 3PIDS -> matrix IDs
|
||||||
[self refreshMatrixIDs];
|
[self refreshMatrixIDs];
|
||||||
|
// at least, display the known contacts
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:kContactManagerRefreshNotification object:nil userInfo:nil];
|
[[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 {
|
- (void)refreshMatrixIDs {
|
||||||
|
|
||||||
// build the request parameters
|
// build the request parameters
|
||||||
NSMutableArray* pids = [[NSMutableArray alloc] init];
|
NSMutableArray* pids = [[NSMutableArray alloc] init];
|
||||||
NSMutableArray* medias = [[NSMutableArray alloc] init];
|
NSMutableArray* medias = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
for(MXCContact* contact in contacts) {
|
for(MXCContact* contact in deviceContactsList) {
|
||||||
// the phonenumbers are not managed
|
// the phonenumbers are not managed
|
||||||
/*for(ConsolePhoneNumber* pn in contact.phoneNumbers) {
|
/*for(ConsolePhoneNumber* pn in contact.phoneNumbers) {
|
||||||
if (pn.textNumber.length > 0) {
|
if (pn.textNumber.length > 0) {
|
||||||
|
@ -166,61 +287,16 @@ static ContactManager* sharedContactManager = nil;
|
||||||
|
|
||||||
matrixIDBy3PID = [[NSMutableDictionary alloc] initWithObjects:userIds forKeys:pids];
|
matrixIDBy3PID = [[NSMutableDictionary alloc] initWithObjects:userIds forKeys:pids];
|
||||||
|
|
||||||
for(MXCContact* contact in contacts) {
|
[self updateMatrixIDDeviceContactsList];
|
||||||
// the phonenumbers wil be managed later
|
|
||||||
/*for(ConsolePhoneNumber* pn in contact.phoneNumbers) {
|
|
||||||
if (pn.textNumber.length > 0) {
|
|
||||||
|
|
||||||
// not yet added
|
// add the MX users
|
||||||
if ([pids indexOfObject:pn.textNumber] == NSNotFound) {
|
NSMutableArray* tmpContacts = [deviceContactsList mutableCopy];
|
||||||
[pids addObject:pn.textNumber];
|
[self mergeMXUsers:tmpContacts];
|
||||||
[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(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[email setMatrixID:matrixID];
|
contacts = tmpContacts;
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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];
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:kContactManagerRefreshNotification object:nil userInfo:nil];
|
[[NSNotificationCenter defaultCenter] postNotificationName:kContactManagerRefreshNotification object:nil userInfo:nil];
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
failure:^(NSError *error) {
|
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 {
|
- (SectionedContacts *)getSectionedContacts:(NSArray*)contactsList {
|
||||||
UILocalizedIndexedCollation *collation = [UILocalizedIndexedCollation currentCollation];
|
UILocalizedIndexedCollation *collation = [UILocalizedIndexedCollation currentCollation];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue