2015-01-20 12:33:01 +00:00
|
|
|
/*
|
|
|
|
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 "ContactManager.h"
|
|
|
|
|
2015-01-23 13:22:02 +00:00
|
|
|
#import "MXCContact.h"
|
|
|
|
#import "MXCPhoneNumber.h"
|
|
|
|
#import "MXCEmail.h"
|
2015-01-22 11:01:12 +00:00
|
|
|
|
2015-01-23 14:53:39 +00:00
|
|
|
#import "MatrixSDKHandler.h"
|
2015-01-20 12:33:01 +00:00
|
|
|
|
2015-01-26 17:06:13 +00:00
|
|
|
#import "AppSettings.h"
|
|
|
|
|
2015-01-20 12:33:01 +00:00
|
|
|
// warn when there is a contacts list refresh
|
2015-01-26 10:05:53 +00:00
|
|
|
NSString *const kContactManagerContactsListRefreshNotification = @"kContactManagerContactsListRefreshNotification";
|
|
|
|
|
|
|
|
// get the 3PIDS in one requests
|
|
|
|
//#define CONTACTS_3PIDS_SYNC 1
|
|
|
|
// else checks the matrix IDs for each displayed contact
|
2015-01-20 12:33:01 +00:00
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
@interface ContactManager() {
|
|
|
|
NSDate *lastSyncDate;
|
|
|
|
NSMutableArray* deviceContactsList;
|
|
|
|
|
2015-01-26 10:05:53 +00:00
|
|
|
//
|
|
|
|
NSMutableArray* pending3PIDs;
|
|
|
|
NSMutableArray* checked3PIDs;
|
|
|
|
|
|
|
|
NSMutableDictionary* matrixContactByMatrixUserID;
|
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
BOOL hasStatusObserver;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
2015-01-20 12:33:01 +00:00
|
|
|
@implementation ContactManager
|
|
|
|
@synthesize contacts;
|
|
|
|
|
|
|
|
#pragma mark Singleton Methods
|
|
|
|
static ContactManager* sharedContactManager = nil;
|
|
|
|
|
|
|
|
+ (id)sharedManager {
|
|
|
|
@synchronized(self) {
|
2015-01-23 15:04:11 +00:00
|
|
|
if(sharedContactManager == nil)
|
2015-01-20 12:33:01 +00:00
|
|
|
sharedContactManager = [[self alloc] init];
|
|
|
|
}
|
|
|
|
return sharedContactManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
-(ContactManager *)init {
|
|
|
|
if (self = [super init]) {
|
|
|
|
NSString *label = [NSString stringWithFormat:@"ConsoleMatrix.%@.Contacts", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]];
|
|
|
|
|
|
|
|
processingQueue = dispatch_queue_create([label UTF8String], NULL);
|
|
|
|
|
|
|
|
// put an empty array instead of nil
|
|
|
|
contacts = [[NSMutableArray alloc] init];
|
|
|
|
|
2015-01-26 10:05:53 +00:00
|
|
|
// other inits
|
|
|
|
matrixContactByMatrixUserID = [[NSMutableDictionary alloc] init];
|
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
// save the last sync date
|
|
|
|
// to avoid resync the whole phonebook
|
|
|
|
lastSyncDate = nil;
|
|
|
|
|
2015-01-26 17:06:13 +00:00
|
|
|
// wait that the mxSession is ready
|
|
|
|
[[AppSettings sharedSettings] addObserver:self forKeyPath:@"syncLocalContacts" options:0 context:nil];
|
2015-01-20 12:33:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
-(void)dealloc {
|
2015-01-23 15:04:11 +00:00
|
|
|
if (hasStatusObserver) {
|
|
|
|
[[MatrixSDKHandler sharedHandler] removeObserver:self forKeyPath:@"status"];
|
2015-01-26 17:06:13 +00:00
|
|
|
[[AppSettings sharedSettings] removeObserver:self forKeyPath:@"syncLocalContacts"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// delete contacts info
|
|
|
|
- (void)reset {
|
|
|
|
contacts = nil;
|
|
|
|
|
|
|
|
lastSyncDate = nil;
|
|
|
|
deviceContactsList = nil;
|
|
|
|
matrixContactByMatrixUserID = nil;
|
|
|
|
if (hasStatusObserver) {
|
|
|
|
[[MatrixSDKHandler sharedHandler] removeObserver:self forKeyPath:@"status"];
|
|
|
|
hasStatusObserver = NO;
|
2015-01-23 15:04:11 +00:00
|
|
|
}
|
2015-01-26 17:06:13 +00:00
|
|
|
|
|
|
|
[self saveMatrixIDsDict];
|
2015-01-20 12:33:01 +00:00
|
|
|
}
|
|
|
|
|
2015-01-26 10:05:53 +00:00
|
|
|
- (void)fullRefresh {
|
2015-01-26 17:06:13 +00:00
|
|
|
|
|
|
|
// check if the user allowed to sync local contacts
|
|
|
|
if (![[AppSettings sharedSettings] syncLocalContacts]) {
|
|
|
|
// if the user did not allow to sync local contacts
|
|
|
|
// ignore this sync
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
ABAddressBookRef ab = ABAddressBookCreateWithOptions(nil, nil);
|
|
|
|
|
|
|
|
if (ab) {
|
|
|
|
ABAddressBookRequestAccessWithCompletion(ab, ^(bool granted, CFErrorRef error) {
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
[self fullRefresh];
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
CFRelease(ab);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
MatrixSDKHandler* mxHandler = [MatrixSDKHandler sharedHandler];
|
2015-01-20 12:33:01 +00:00
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
// remove any observer
|
|
|
|
if (hasStatusObserver) {
|
|
|
|
[mxHandler removeObserver:self forKeyPath:@"status"];
|
|
|
|
hasStatusObserver = NO;
|
|
|
|
}
|
2015-01-22 11:01:12 +00:00
|
|
|
|
2015-01-26 10:05:53 +00:00
|
|
|
pending3PIDs = [[NSMutableArray alloc] init];
|
|
|
|
checked3PIDs = [[NSMutableArray alloc] init];
|
|
|
|
|
2015-01-26 10:55:04 +00:00
|
|
|
// cold start
|
|
|
|
// launch the dict from the file system
|
|
|
|
// It is cached to improve UX.
|
|
|
|
if (!matrixIDBy3PID) {
|
|
|
|
[self loadMatrixIDsDict];
|
|
|
|
}
|
|
|
|
|
2015-01-20 12:33:01 +00:00
|
|
|
dispatch_async(processingQueue, ^{
|
|
|
|
NSMutableArray* contactsList = [[NSMutableArray alloc] init];
|
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
// can list tocal contacts
|
|
|
|
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
|
|
|
|
|
|
|
|
ABAddressBookRef ab = ABAddressBookCreateWithOptions(nil, nil);
|
|
|
|
ABRecordRef contactRecord;
|
|
|
|
int index;
|
|
|
|
CFMutableArrayRef people = (CFMutableArrayRef)ABAddressBookCopyArrayOfAllPeople(ab);
|
2015-01-20 12:33:01 +00:00
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
if (nil != people) {
|
|
|
|
int peopleCount = CFArrayGetCount(people);
|
|
|
|
|
|
|
|
for (index = 0; index < peopleCount; index++) {
|
|
|
|
contactRecord = (ABRecordRef)CFArrayGetValueAtIndex(people, index);
|
|
|
|
[contactsList addObject:[[MXCContact alloc] initWithABRecord:contactRecord]];
|
|
|
|
}
|
|
|
|
|
|
|
|
CFRelease(people);
|
2015-01-20 12:33:01 +00:00
|
|
|
}
|
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
if (ab) {
|
|
|
|
CFRelease(ab);
|
|
|
|
}
|
2015-01-20 12:33:01 +00:00
|
|
|
}
|
2015-01-23 15:04:11 +00:00
|
|
|
|
|
|
|
deviceContactsList = contactsList;
|
|
|
|
|
|
|
|
if (mxHandler.mxSession) {
|
|
|
|
[self manage3PIDS];
|
|
|
|
} else {
|
|
|
|
// display what you could have read
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
contacts = deviceContactsList;
|
2015-01-20 12:33:01 +00:00
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
hasStatusObserver = YES;
|
|
|
|
// wait that the mxSession is ready
|
|
|
|
[mxHandler addObserver:self forKeyPath:@"status" options:0 context:nil];
|
|
|
|
// at least, display the known contacts
|
2015-01-26 10:05:53 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:kContactManagerContactsListRefreshNotification object:nil userInfo:nil];
|
2015-01-23 15:04:11 +00:00
|
|
|
});
|
2015-01-20 12:33:01 +00:00
|
|
|
}
|
2015-01-23 15:04:11 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// the local contacts are listed
|
|
|
|
// update their 3PIDs and their update
|
|
|
|
- (void) manage3PIDS {
|
|
|
|
dispatch_async(processingQueue, ^{
|
|
|
|
NSMutableArray* tmpContacts = nil;
|
2015-01-20 12:33:01 +00:00
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
// initial sync
|
|
|
|
if (!lastSyncDate) {
|
|
|
|
// display the current device contacts
|
|
|
|
tmpContacts = deviceContactsList;
|
|
|
|
} else {
|
|
|
|
// update with the known dict 3PID -> matrix ID
|
|
|
|
[self updateMatrixIDDeviceContactsList];
|
|
|
|
|
2015-01-27 07:36:21 +00:00
|
|
|
tmpContacts = [deviceContactsList mutableCopy];
|
2015-01-23 15:04:11 +00:00
|
|
|
}
|
|
|
|
lastSyncDate = [NSDate date];
|
2015-01-20 12:33:01 +00:00
|
|
|
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
2015-01-23 15:04:11 +00:00
|
|
|
// stored self.contacts in the right thread
|
|
|
|
contacts = tmpContacts;
|
2015-01-26 10:05:53 +00:00
|
|
|
#if CONTACTS_3PIDS_SYNC
|
2015-01-23 15:04:11 +00:00
|
|
|
// refresh the 3PIDS -> matrix IDs
|
2015-01-22 11:01:12 +00:00
|
|
|
[self refreshMatrixIDs];
|
2015-01-26 10:05:53 +00:00
|
|
|
#else
|
2015-01-27 07:36:21 +00:00
|
|
|
// nop
|
|
|
|
// wait that refreshContactMatrixIDs is called
|
2015-01-26 10:05:53 +00:00
|
|
|
|
|
|
|
#endif
|
2015-01-23 15:04:11 +00:00
|
|
|
// at least, display the known contacts
|
2015-01-26 10:05:53 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:kContactManagerContactsListRefreshNotification object:nil userInfo:nil];
|
2015-01-20 12:33:01 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-01-26 10:05:53 +00:00
|
|
|
- (void) updateContactMatrixIDs:(MXCContact*) contact {
|
|
|
|
// 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];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
- (void) updateMatrixIDDeviceContactsList {
|
|
|
|
// update the contacts info
|
|
|
|
for(MXCContact* contact in deviceContactsList) {
|
2015-01-26 10:05:53 +00:00
|
|
|
[self updateContactMatrixIDs:contact];
|
2015-01-23 15:04:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-26 10:05:53 +00:00
|
|
|
#ifdef CONTACTS_3PIDS_SYNC
|
2015-01-23 15:04:11 +00:00
|
|
|
// refresh the 3PIDs -> Matrix ID list
|
|
|
|
// update the contact is required
|
2015-01-22 11:01:12 +00:00
|
|
|
- (void)refreshMatrixIDs {
|
|
|
|
|
|
|
|
// build the request parameters
|
|
|
|
NSMutableArray* pids = [[NSMutableArray alloc] init];
|
|
|
|
NSMutableArray* medias = [[NSMutableArray alloc] init];
|
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
for(MXCContact* contact in deviceContactsList) {
|
2015-01-22 11:01:12 +00:00
|
|
|
// the phonenumbers are not managed
|
|
|
|
/*for(ConsolePhoneNumber* pn in contact.phoneNumbers) {
|
2015-01-23 15:04:11 +00:00
|
|
|
if (pn.textNumber.length > 0) {
|
|
|
|
|
|
|
|
// not yet added
|
|
|
|
if ([pids indexOfObject:pn.textNumber] == NSNotFound) {
|
|
|
|
[pids addObject:pn.textNumber];
|
|
|
|
[medias addObject:@"msisdn"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}*/
|
2015-01-22 11:01:12 +00:00
|
|
|
|
2015-01-23 13:22:02 +00:00
|
|
|
for(MXCEmail* email in contact.emailAddresses) {
|
2015-01-22 11:01:12 +00:00
|
|
|
if (email.emailAddress.length > 0) {
|
|
|
|
|
|
|
|
// not yet added
|
|
|
|
if ([pids indexOfObject:email.emailAddress] == NSNotFound) {
|
|
|
|
[pids addObject:email.emailAddress];
|
|
|
|
[medias addObject:@"email"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// get some pids
|
|
|
|
if (pids.count > 0) {
|
2015-01-23 14:53:39 +00:00
|
|
|
MatrixSDKHandler *mxHandler = [MatrixSDKHandler sharedHandler];
|
2015-01-23 15:04:11 +00:00
|
|
|
|
2015-01-22 11:01:12 +00:00
|
|
|
if (mxHandler.mxRestClient) {
|
|
|
|
[mxHandler.mxRestClient lookup3pids:pids
|
|
|
|
forMedia:medias
|
|
|
|
success:^(NSArray *userIds) {
|
|
|
|
// sanity check
|
|
|
|
if (userIds.count == pids.count) {
|
|
|
|
|
|
|
|
matrixIDBy3PID = [[NSMutableDictionary alloc] initWithObjects:userIds forKeys:pids];
|
2015-01-26 10:55:04 +00:00
|
|
|
[self saveMatrixIDsDict];
|
2015-01-23 15:04:11 +00:00
|
|
|
[self updateMatrixIDDeviceContactsList];
|
2015-01-22 11:01:12 +00:00
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
// add the MX users
|
|
|
|
NSMutableArray* tmpContacts = [deviceContactsList mutableCopy];
|
|
|
|
[self mergeMXUsers:tmpContacts];
|
2015-01-22 11:01:12 +00:00
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
contacts = tmpContacts;
|
2015-01-26 10:05:53 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:kContactManagerContactsListRefreshNotification object:nil userInfo:nil];
|
2015-01-23 15:04:11 +00:00
|
|
|
});
|
2015-01-22 11:01:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
failure:^(NSError *error) {
|
|
|
|
// try later
|
|
|
|
dispatch_after(dispatch_walltime(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
|
|
|
[self refreshMatrixIDs];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-26 10:05:53 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// refresh matrix IDs
|
|
|
|
- (void)refreshContactMatrixIDs:(MXCContact*)contact {
|
|
|
|
#ifndef CONTACTS_3PIDS_SYNC
|
|
|
|
if (!contact.isMatrixContact) {
|
|
|
|
|
|
|
|
// check pending requests
|
|
|
|
NSMutableArray* pids = [[NSMutableArray alloc] init];
|
|
|
|
NSMutableArray* medias = [[NSMutableArray alloc] init];
|
|
|
|
|
|
|
|
for(MXCEmail* email in contact.emailAddresses) {
|
|
|
|
if (([pending3PIDs indexOfObject:email.emailAddress] == NSNotFound) && ([checked3PIDs indexOfObject:email.emailAddress] == NSNotFound)) {
|
|
|
|
[pids addObject:email.emailAddress];
|
|
|
|
[medias addObject:@"email"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pids.count > 0) {
|
|
|
|
[pending3PIDs addObjectsFromArray:pids];
|
|
|
|
|
|
|
|
MatrixSDKHandler *mxHandler = [MatrixSDKHandler sharedHandler];
|
|
|
|
|
|
|
|
if (mxHandler) {
|
|
|
|
[mxHandler.mxRestClient lookup3pids:pids
|
|
|
|
forMedia:medias
|
|
|
|
success:^(NSArray *userIds) {
|
|
|
|
// sanity check
|
|
|
|
if (userIds.count == pids.count) {
|
|
|
|
|
|
|
|
// update statuses table
|
|
|
|
[checked3PIDs addObjectsFromArray:pids];
|
|
|
|
for(NSString* pid in pids) {
|
|
|
|
[pending3PIDs removeObject:pid];
|
|
|
|
}
|
2015-01-26 10:55:04 +00:00
|
|
|
|
|
|
|
BOOL isUpdated = NO;
|
2015-01-26 10:05:53 +00:00
|
|
|
NSMutableArray* matrixContactsToRemove = [[NSMutableArray alloc] init];
|
|
|
|
|
2015-01-26 10:55:04 +00:00
|
|
|
// apply updates
|
|
|
|
if (pids.count > 0) {
|
|
|
|
for(int index = 0; index < pids.count; index++) {
|
|
|
|
NSString* matrixID = [userIds objectAtIndex:index];
|
|
|
|
NSString* pid = [pids objectAtIndex:index];
|
|
|
|
|
|
|
|
// the dict is created on demand
|
|
|
|
if (!matrixIDBy3PID) {
|
|
|
|
[self loadMatrixIDsDict];
|
|
|
|
}
|
|
|
|
|
|
|
|
id currentMatrixID = [matrixIDBy3PID valueForKey:pid];
|
|
|
|
|
|
|
|
// do not keep useless info
|
|
|
|
if ([matrixID isKindOfClass:[NSString class]]) {
|
|
|
|
|
|
|
|
// do not update if not required
|
|
|
|
if (![currentMatrixID isKindOfClass:[NSString class]] || ![(NSString*)currentMatrixID isEqualToString:matrixID]) {
|
|
|
|
[matrixIDBy3PID setValue:matrixID forKey:pid];
|
|
|
|
isUpdated = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (currentMatrixID) {
|
|
|
|
[matrixIDBy3PID removeObjectForKey:pid];
|
|
|
|
isUpdated = YES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// is there a matrix contact with the same
|
|
|
|
if ([matrixContactByMatrixUserID objectForKey:matrixID]) {
|
|
|
|
[matrixContactsToRemove addObject:[matrixContactByMatrixUserID objectForKey:matrixID]];
|
|
|
|
}
|
2015-01-26 10:05:53 +00:00
|
|
|
}
|
|
|
|
|
2015-01-26 10:55:04 +00:00
|
|
|
if (isUpdated) {
|
|
|
|
[self saveMatrixIDsDict];
|
2015-01-26 10:05:53 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-26 10:55:04 +00:00
|
|
|
|
2015-01-26 10:05:53 +00:00
|
|
|
// some matrix contacts will be replaced by this contact
|
|
|
|
if (matrixContactsToRemove.count > 0) {
|
|
|
|
[self updateContactMatrixIDs:contact];
|
|
|
|
|
|
|
|
for(MXCContact* contactToRemove in matrixContactsToRemove) {
|
|
|
|
[self.contacts removeObject:contactToRemove];
|
|
|
|
}
|
|
|
|
|
|
|
|
// warn there is a global refresh
|
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:kContactManagerContactsListRefreshNotification object:nil userInfo:nil];
|
|
|
|
} else {
|
|
|
|
// update only this contact
|
|
|
|
[self updateContactMatrixIDs:contact];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
failure:^(NSError *error) {
|
|
|
|
// try later
|
|
|
|
dispatch_after(dispatch_walltime(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
|
|
|
[self refreshContactMatrixIDs:contact];
|
|
|
|
});
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dispatch_after(dispatch_walltime(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
|
|
|
[self refreshContactMatrixIDs:contact];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2015-01-22 11:01:12 +00:00
|
|
|
|
2015-01-23 15:04:11 +00:00
|
|
|
#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];
|
|
|
|
}
|
|
|
|
});
|
2015-01-26 17:06:13 +00:00
|
|
|
} else if ([@"syncLocalContacts" isEqualToString:keyPath]) {
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
[self fullRefresh];
|
|
|
|
});
|
2015-01-23 15:04:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-20 12:33:01 +00:00
|
|
|
- (SectionedContacts *)getSectionedContacts:(NSArray*)contactsList {
|
|
|
|
UILocalizedIndexedCollation *collation = [UILocalizedIndexedCollation currentCollation];
|
|
|
|
|
|
|
|
int indexOffset = 0;
|
|
|
|
|
|
|
|
NSInteger index, sectionTitlesCount = [[collation sectionTitles] count];
|
|
|
|
NSMutableArray *tmpSectionsArray = [[NSMutableArray alloc] initWithCapacity:(sectionTitlesCount)];
|
|
|
|
|
|
|
|
sectionTitlesCount += indexOffset;
|
|
|
|
|
|
|
|
for (index = 0; index < sectionTitlesCount; index++) {
|
|
|
|
NSMutableArray *array = [[NSMutableArray alloc] init];
|
|
|
|
[tmpSectionsArray addObject:array];
|
|
|
|
}
|
|
|
|
|
|
|
|
int contactsCount = 0;
|
|
|
|
|
2015-01-23 13:22:02 +00:00
|
|
|
for (MXCContact *aContact in contactsList)
|
2015-01-20 12:33:01 +00:00
|
|
|
{
|
|
|
|
NSInteger section = [collation sectionForObject:aContact collationStringSelector:@selector(displayName)] + indexOffset;
|
|
|
|
|
|
|
|
[[tmpSectionsArray objectAtIndex:section] addObject:aContact];
|
|
|
|
++contactsCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSMutableArray *tmpSectionedContactsTitle = [[NSMutableArray alloc] initWithCapacity:sectionTitlesCount];
|
|
|
|
NSMutableArray *shortSectionsArray = [[NSMutableArray alloc] initWithCapacity:sectionTitlesCount];
|
|
|
|
|
|
|
|
for (index = indexOffset; index < sectionTitlesCount; index++) {
|
|
|
|
|
|
|
|
NSMutableArray *usersArrayForSection = [tmpSectionsArray objectAtIndex:index];
|
|
|
|
|
|
|
|
if ([usersArrayForSection count] != 0) {
|
|
|
|
NSArray* sortedUsersArrayForSection = [collation sortedArrayFromArray:usersArrayForSection collationStringSelector:@selector(displayName)];
|
|
|
|
[shortSectionsArray addObject:sortedUsersArrayForSection];
|
|
|
|
[tmpSectionedContactsTitle addObject:[[[UILocalizedIndexedCollation currentCollation] sectionTitles] objectAtIndex:(index - indexOffset)]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return [[SectionedContacts alloc] initWithContacts:shortSectionsArray andTitles:tmpSectionedContactsTitle andCount:contactsCount];
|
|
|
|
}
|
|
|
|
|
2015-01-26 10:55:04 +00:00
|
|
|
#pragma mark - file caches
|
|
|
|
|
|
|
|
static NSString *matrixIDsDictFile = @"matrixIDsDict";
|
|
|
|
|
|
|
|
- (void)saveMatrixIDsDict
|
|
|
|
{
|
|
|
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
|
|
|
NSString *documentsDirectory = [paths objectAtIndex:0];
|
|
|
|
NSString *dataFilePath = [documentsDirectory stringByAppendingPathComponent:matrixIDsDictFile];
|
|
|
|
|
|
|
|
if (matrixIDBy3PID)
|
|
|
|
{
|
|
|
|
NSMutableData *theData = [NSMutableData data];
|
|
|
|
NSKeyedArchiver *encoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:theData];
|
|
|
|
|
|
|
|
[encoder encodeObject:matrixIDBy3PID forKey:@"matrixIDsDict"];
|
|
|
|
[encoder finishEncoding];
|
|
|
|
|
|
|
|
[theData writeToFile:dataFilePath atomically:YES];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSFileManager *fileManager = [[NSFileManager alloc] init];
|
|
|
|
[fileManager removeItemAtPath:dataFilePath error:nil];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)loadMatrixIDsDict
|
|
|
|
{
|
|
|
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
|
|
|
NSString *documentsDirectory = [paths objectAtIndex:0];
|
|
|
|
NSString *dataFilePath = [documentsDirectory stringByAppendingPathComponent:matrixIDsDictFile];
|
|
|
|
|
|
|
|
NSFileManager *fileManager = [[NSFileManager alloc] init];
|
|
|
|
|
|
|
|
if ([fileManager fileExistsAtPath:dataFilePath])
|
|
|
|
{
|
|
|
|
// the file content could be corrupted
|
|
|
|
@try {
|
|
|
|
NSData* filecontent = [NSData dataWithContentsOfFile:dataFilePath options:(NSDataReadingMappedAlways | NSDataReadingUncached) error:nil];
|
|
|
|
|
|
|
|
NSKeyedUnarchiver *decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:filecontent];
|
|
|
|
|
|
|
|
id object = [decoder decodeObjectForKey:@"matrixIDsDict"];
|
|
|
|
|
|
|
|
if ([object isKindOfClass:[NSDictionary class]]) {
|
|
|
|
matrixIDBy3PID = [object mutableCopy];
|
|
|
|
}
|
|
|
|
|
|
|
|
[decoder finishDecoding];
|
|
|
|
} @catch (NSException *exception) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!matrixIDBy3PID) {
|
|
|
|
matrixIDBy3PID = [[NSMutableDictionary alloc] init];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-20 12:33:01 +00:00
|
|
|
@end
|