Avoid repaint by requestng contacts before Compose

This entailed passing callback params through the contact request.

// FREEBIE
pull/1/head
Michael Kirk 9 years ago
parent dc75e592c1
commit fee47efbea

@ -279,9 +279,18 @@ NSString *const SignalsViewControllerSegueShowIncomingCall = @"ShowIncomingCallS
- (IBAction)composeNew - (IBAction)composeNew
{ {
MessageComposeTableViewController *viewController = [MessageComposeTableViewController new]; MessageComposeTableViewController *viewController = [MessageComposeTableViewController new];
UINavigationController *navigationController =
[[UINavigationController alloc] initWithRootViewController:viewController]; [self.contactsManager requestSystemContactsOnceWithCompletion:^(NSError *_Nullable error) {
[self presentTopLevelModalViewController:navigationController animateDismissal:YES animatePresentation:YES]; DDLogError(@"%@ Error when requesting contacts: %@", self.tag, error);
// Even if there was an error fetching contacts we proceed to the next screen.
// As the compose view will present the proper thing depending on contact access.
//
// We just want to make sure contact access is *complete* before showing the compose
// screen to avoid flicker.
UINavigationController *navigationController =
[[UINavigationController alloc] initWithRootViewController:viewController];
[self presentTopLevelModalViewController:navigationController animateDismissal:YES animatePresentation:YES];
}];
} }
- (void)swappedSegmentedControl { - (void)swappedSegmentedControl {

@ -39,6 +39,7 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification;
// Request systems contacts and start syncing changes. The user will see an alert // Request systems contacts and start syncing changes. The user will see an alert
// if they haven't previously. // if they haven't previously.
- (void)requestSystemContactsOnce; - (void)requestSystemContactsOnce;
- (void)requestSystemContactsOnceWithCompletion:(void (^_Nullable)(NSError *_Nullable error))completion;
// Ensure's the app has the latest contacts, but won't prompt the user for contact // Ensure's the app has the latest contacts, but won't prompt the user for contact
// access if they haven't granted it. // access if they haven't granted it.

@ -54,9 +54,15 @@ NSString *const OWSContactsManagerSignalAccountsDidChangeNotification =
// Request contacts access if you haven't asked recently. // Request contacts access if you haven't asked recently.
- (void)requestSystemContactsOnce - (void)requestSystemContactsOnce
{ {
[self.systemContactsFetcher requestOnce]; [self requestSystemContactsOnceWithCompletion:nil];
} }
- (void)requestSystemContactsOnceWithCompletion:(void (^_Nullable)(NSError *_Nullable error))completion
{
[self.systemContactsFetcher requestOnceWithCompletion:completion];
}
- (void)fetchSystemContactsIfAlreadyAuthorized - (void)fetchSystemContactsIfAlreadyAuthorized
{ {
[self.systemContactsFetcher fetchIfAlreadyAuthorized]; [self.systemContactsFetcher fetchIfAlreadyAuthorized];

@ -39,11 +39,19 @@ class SystemContactsFetcher: NSObject {
CNContactEmailAddressesKey as CNKeyDescriptor CNContactEmailAddressesKey as CNKeyDescriptor
] ]
public func requestOnce() { /**
* Ensures we've requested access for system contacts. This can be used in multiple places,
* where we might need contact access, but will ensure we don't wastefully reload contacts
* if we have already fetched contacts.
*
* @param completion completion handler is called on main thread.
*/
public func requestOnce(completion: ((Error?) -> Void)?) {
AssertIsOnMainThread() AssertIsOnMainThread()
guard !systemContactsHaveBeenRequestedAtLeastOnce else { guard !systemContactsHaveBeenRequestedAtLeastOnce else {
Logger.debug("\(TAG) already requested system contacts") Logger.debug("\(TAG) already requested system contacts")
completion?(nil)
return return
} }
systemContactsHaveBeenRequestedAtLeastOnce = true systemContactsHaveBeenRequestedAtLeastOnce = true
@ -54,22 +62,32 @@ class SystemContactsFetcher: NSObject {
contactStore.requestAccess(for: .contacts) { (granted, error) in contactStore.requestAccess(for: .contacts) { (granted, error) in
if let error = error { if let error = error {
Logger.error("\(self.TAG) error fetching contacts: \(error)") Logger.error("\(self.TAG) error fetching contacts: \(error)")
assertionFailure() DispatchQueue.main.async {
completion?(error)
}
} }
guard granted else { guard granted else {
Logger.info("\(self.TAG) declined contact access.") Logger.info("\(self.TAG) declined contact access.")
// This case should have been caught be the error guard a few lines up.
assertionFailure()
DispatchQueue.main.async {
completion?(nil)
}
return return
} }
DispatchQueue.main.async { DispatchQueue.main.async {
self.updateContacts() self.updateContacts(completion: completion)
} }
} }
case .authorized: case .authorized:
self.updateContacts() self.updateContacts(completion: completion)
case .denied, .restricted: case .denied, .restricted:
Logger.debug("\(TAG) contacts were \(self.authorizationStatus)") Logger.debug("\(TAG) contacts were \(self.authorizationStatus)")
DispatchQueue.main.async {
completion?(nil)
}
} }
} }
@ -79,10 +97,10 @@ class SystemContactsFetcher: NSObject {
return return
} }
updateContacts() updateContacts(completion: nil)
} }
private func updateContacts() { private func updateContacts(completion: ((Error?) -> Void)?) {
AssertIsOnMainThread() AssertIsOnMainThread()
systemContactsHaveBeenRequestedAtLeastOnce = true systemContactsHaveBeenRequestedAtLeastOnce = true
@ -100,11 +118,16 @@ class SystemContactsFetcher: NSObject {
} catch let error as NSError { } catch let error as NSError {
Logger.error("\(self.TAG) Failed to fetch contacts with error:\(error)") Logger.error("\(self.TAG) Failed to fetch contacts with error:\(error)")
assertionFailure() assertionFailure()
DispatchQueue.main.async {
completion?(error)
}
return
} }
let contacts = systemContacts.map { Contact(systemContact: $0) } let contacts = systemContacts.map { Contact(systemContact: $0) }
DispatchQueue.main.async { DispatchQueue.main.async {
self.delegate?.systemContactsFetcher(self, updatedContacts: contacts) self.delegate?.systemContactsFetcher(self, updatedContacts: contacts)
completion?(nil)
} }
} }
} }
@ -118,7 +141,7 @@ class SystemContactsFetcher: NSObject {
@objc @objc
private func contactStoreDidChange() { private func contactStoreDidChange() {
updateContacts() updateContacts(completion: nil)
} }
} }

Loading…
Cancel
Save