diff --git a/.gitmodules b/.gitmodules index 8826ade3..28f506ee 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,7 +6,7 @@ url = git://github.com/futuretap/InAppSettingsKit.git [submodule "External/iCloudStoreManager"] path = External/iCloudStoreManager - url = git://github.com/alekseyn/iCloudStoreManager.git + url = git://github.com/lhunath/iCloudStoreManager.git [submodule "External/apptentive"] path = External/apptentive url = git://github.com/apptentive/apptentive-ios.git diff --git a/External/Pearl b/External/Pearl index f92b0b14..046dba15 160000 --- a/External/Pearl +++ b/External/Pearl @@ -1 +1 @@ -Subproject commit f92b0b1490e483d1bd4b8b6d1b9482c7ecfd4e44 +Subproject commit 046dba155843d7a10d5c087e5b1d698ab271df67 diff --git a/External/iCloudStoreManager b/External/iCloudStoreManager index 6c19d5aa..84c718a5 160000 --- a/External/iCloudStoreManager +++ b/External/iCloudStoreManager @@ -1 +1 @@ -Subproject commit 6c19d5aa27b07d9a55cd19b003c4383b055b995f +Subproject commit 84c718a57d64933e626d3756993fce513ad2bc2a diff --git a/MasterPassword-iOS.xcodeproj/project.pbxproj b/MasterPassword-iOS.xcodeproj/project.pbxproj index 9595b487..8733ebb7 100644 --- a/MasterPassword-iOS.xcodeproj/project.pbxproj +++ b/MasterPassword-iOS.xcodeproj/project.pbxproj @@ -18,6 +18,13 @@ DA0A1D1215690AD40092735D /* tip_arrow_wood.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D0C15690AD40092735D /* tip_arrow_wood.png */; }; DA0A1D1515690AF40092735D /* Icon-72@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D1315690AF30092735D /* Icon-72@2x.png */; }; DA0A1D1615690AF40092735D /* Icon-Small-50@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D1415690AF40092735D /* Icon-Small-50@2x.png */; }; + DA30E9CE15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA30E9CB15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h */; }; + DA30E9CF15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9CC15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m */; }; + DA30E9D015722ECA00A68B4C /* Pearl.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9CD15722ECA00A68B4C /* Pearl.m */; }; + DA30E9D215722EE500A68B4C /* Pearl-Crypto.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */; }; + DA30E9D415722EF400A68B4C /* Pearl-UIKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D315722EF400A68B4C /* Pearl-UIKit.m */; }; + DA30E9D715723E6900A68B4C /* PearlLazy.h in Headers */ = {isa = PBXBuildFile; fileRef = DA30E9D515723E6900A68B4C /* PearlLazy.h */; }; + DA30E9D815723E6900A68B4C /* PearlLazy.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D615723E6900A68B4C /* PearlLazy.m */; }; DA4425CC1557BED40052177D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; }; DA4426001557BF260052177D /* UbiquityStoreManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DA4425F11557BF260052177D /* UbiquityStoreManager.h */; }; DA4426011557BF260052177D /* UbiquityStoreManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4425F21557BF260052177D /* UbiquityStoreManager.m */; }; @@ -925,6 +932,13 @@ DA0A1D0C15690AD40092735D /* tip_arrow_wood.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = tip_arrow_wood.png; path = Resources/Tooltips/tip_arrow_wood.png; sourceTree = SOURCE_ROOT; }; DA0A1D1315690AF30092735D /* Icon-72@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-72@2x.png"; sourceTree = ""; }; DA0A1D1415690AF40092735D /* Icon-Small-50@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-50@2x.png"; sourceTree = ""; }; + DA30E9CB15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSBundle_PearlMutableInfo.h; sourceTree = ""; }; + DA30E9CC15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSBundle_PearlMutableInfo.m; sourceTree = ""; }; + DA30E9CD15722ECA00A68B4C /* Pearl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Pearl.m; sourceTree = ""; }; + DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Pearl-Crypto.m"; sourceTree = ""; }; + DA30E9D315722EF400A68B4C /* Pearl-UIKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Pearl-UIKit.m"; sourceTree = ""; }; + DA30E9D515723E6900A68B4C /* PearlLazy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlLazy.h; sourceTree = ""; }; + DA30E9D615723E6900A68B4C /* PearlLazy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlLazy.m; sourceTree = ""; }; DA4425CB1557BED40052177D /* libiCloudStoreManager.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libiCloudStoreManager.a; sourceTree = BUILT_PRODUCTS_DIR; }; DA4425F11557BF260052177D /* UbiquityStoreManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UbiquityStoreManager.h; sourceTree = ""; }; DA4425F21557BF260052177D /* UbiquityStoreManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UbiquityStoreManager.m; sourceTree = ""; }; @@ -2892,6 +2906,8 @@ DAFE45D715039823003ABA7C /* Pearl */ = { isa = PBXGroup; children = ( + DA30E9CB15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h */, + DA30E9CC15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m */, DAFE45D815039823003ABA7C /* NSObject_PearlExport.h */, DAFE45D915039823003ABA7C /* NSObject_PearlExport.m */, DAFE45DA15039823003ABA7C /* NSString_PearlNSArrayFormat.h */, @@ -2899,6 +2915,7 @@ DAFE45DC15039823003ABA7C /* NSString_PearlSEL.h */, DAFE45DD15039823003ABA7C /* NSString_PearlSEL.m */, DAFE45DE15039823003ABA7C /* Pearl.h */, + DA30E9CD15722ECA00A68B4C /* Pearl.m */, DAFE45DF15039823003ABA7C /* PearlAbstractStrings.h */, DAFE45E015039823003ABA7C /* PearlAbstractStrings.m */, DAFE45E315039823003ABA7C /* PearlCodeUtils.h */, @@ -2909,6 +2926,8 @@ DAFE45E815039823003ABA7C /* PearlDeviceUtils.m */, DAFE45E915039823003ABA7C /* PearlInfoPlist.h */, DAFE45EA15039823003ABA7C /* PearlInfoPlist.m */, + DA30E9D515723E6900A68B4C /* PearlLazy.h */, + DA30E9D615723E6900A68B4C /* PearlLazy.m */, DAFE45EB15039823003ABA7C /* PearlLogger.h */, DAFE45EC15039823003ABA7C /* PearlLogger.m */, DAFE45ED15039823003ABA7C /* PearlMathUtils.h */, @@ -2940,6 +2959,7 @@ children = ( DA79A9BB1557DB6F00BAA07A /* libscryptenc-ios.a */, DAFE45FD15039823003ABA7C /* Pearl-Crypto.h */, + DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */, DAFE45FE15039823003ABA7C /* PearlCryptUtils.h */, DAFE45FF15039823003ABA7C /* PearlCryptUtils.m */, DAFE460015039823003ABA7C /* PearlKeyChain.h */, @@ -2959,6 +2979,7 @@ children = ( DAFE460815039823003ABA7C /* Pearl-UIKit-Dependencies.h */, DAFE460915039823003ABA7C /* Pearl-UIKit.h */, + DA30E9D315722EF400A68B4C /* Pearl-UIKit.m */, DAFE460A15039823003ABA7C /* PearlAlert.h */, DAFE460B15039823003ABA7C /* PearlAlert.m */, DAFE4A60150399FF003ABA7C /* PearlAppDelegate.m */, @@ -3094,6 +3115,8 @@ DAFE4A5615039824003ABA7C /* PearlWebViewController.h in Headers */, DAFE4A5815039824003ABA7C /* UIImage_PearlScaling.h in Headers */, DAFE4A63150399FF003ABA7C /* PearlAppDelegate.h in Headers */, + DA30E9CE15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h in Headers */, + DA30E9D715723E6900A68B4C /* PearlLazy.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4141,6 +4164,11 @@ DAFE4A5715039824003ABA7C /* PearlWebViewController.m in Sources */, DAFE4A5915039824003ABA7C /* UIImage_PearlScaling.m in Sources */, DAFE4A62150399FF003ABA7C /* PearlAppDelegate.m in Sources */, + DA30E9CF15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m in Sources */, + DA30E9D015722ECA00A68B4C /* Pearl.m in Sources */, + DA30E9D215722EE500A68B4C /* Pearl-Crypto.m in Sources */, + DA30E9D415722EF400A68B4C /* Pearl-UIKit.m in Sources */, + DA30E9D815723E6900A68B4C /* PearlLazy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MasterPassword-iOS.xcodeproj/xcshareddata/xcschemes/MasterPassword (App Store).xcscheme b/MasterPassword-iOS.xcodeproj/xcshareddata/xcschemes/MasterPassword (App Store).xcscheme index 4d6449d1..8ee8e2a9 100644 --- a/MasterPassword-iOS.xcodeproj/xcshareddata/xcschemes/MasterPassword (App Store).xcscheme +++ b/MasterPassword-iOS.xcodeproj/xcshareddata/xcschemes/MasterPassword (App Store).xcscheme @@ -63,14 +63,23 @@ shouldUseLaunchSchemeArgsEnv = "YES" savedToolIdentifier = "" useCustomWorkingDirectory = "NO" - buildConfiguration = "Production" + buildConfiguration = "AppStore" debugDocumentVersioning = "YES"> + + + + diff --git a/MasterPassword/MPAppDelegate_Store.m b/MasterPassword/MPAppDelegate_Store.m index f98fea68..bb1875eb 100644 --- a/MasterPassword/MPAppDelegate_Store.m +++ b/MasterPassword/MPAppDelegate_Store.m @@ -42,28 +42,37 @@ static NSDateFormatter *rfc3339DateFormatter = nil; if (managedObjectContext) return managedObjectContext; - NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; - assert(coordinator); - - managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; - [managedObjectContext performBlockAndWait:^{ - managedObjectContext.persistentStoreCoordinator = coordinator; - managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; + return [PearlLazy lazyObjectLoadedFrom:^id{ + NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; + assert(coordinator); + + managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; + [managedObjectContext performBlockAndWait:^{ + managedObjectContext.persistentStoreCoordinator = coordinator; + managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; + }]; + + return managedObjectContext; }]; - - return managedObjectContext; } - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { + + // Start loading the store. + [self storeManager]; - // Wait until the storeManager is ready. - for(__block BOOL isReady = [self storeManager].isReady; !isReady;) - dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - isReady = [self storeManager].isReady; - }); - - assert([self storeManager].isReady); - return [self storeManager].persistentStoreCoordinator; + return [PearlLazy lazyObjectLoadedFrom:^id{ + // Wait until the storeManager is ready. + for(__block BOOL isReady = [self storeManager].isReady; !isReady;) { + [NSThread sleepForTimeInterval:0.1]; + dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + isReady = [self storeManager].isReady; + }); + } + + assert([self storeManager].isReady); + return [self storeManager].persistentStoreCoordinator; + }]; } - (UbiquityStoreManager *)storeManager { diff --git a/MasterPassword/iOS/MPAppDelegate.m b/MasterPassword/iOS/MPAppDelegate.m index c208cba5..c2dbe87d 100644 --- a/MasterPassword/iOS/MPAppDelegate.m +++ b/MasterPassword/iOS/MPAppDelegate.m @@ -148,6 +148,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [[[NSBundle mainBundle] mutableLocalizedInfoDictionary] setObject:@"Master Password" forKey:@"CFBundleDisplayName"]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ #ifndef DEBUG @try { @@ -207,20 +209,39 @@ } #endif }); - + @try { NSString *apptentiveAPIKey = [self apptentiveAPIKey]; if ([apptentiveAPIKey length]) { dbg(@"Initializing Apptentive"); + ATConnect *connection = [ATConnect sharedConnection]; - connection.shouldTakeScreenshot = NO; - connection.apiKey = apptentiveAPIKey; + [connection setApiKey:apptentiveAPIKey]; + [connection setShouldTakeScreenshot:NO]; + [connection addAdditionalInfoToFeedback:[PearlInfoPlist get].CFBundleVersion withKey:@"CFBundleVersion"]; + + ATAppRatingFlow *ratingsFlow = [ATAppRatingFlow sharedRatingFlowWithAppID:[PearlConfig get].iTunesID]; + [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification object:nil queue:nil + usingBlock:^(NSNotification *note) { + dispatch_async(dispatch_get_main_queue(), ^{ + [ratingsFlow appDidEnterForeground:YES + viewController:self.navigationController]; + }); + }]; + [[NSNotificationCenter defaultCenter] addObserverForName:MPNotificationKeySet object:nil queue:nil + usingBlock:^(NSNotification *note) { + dispatch_async(dispatch_get_main_queue(), ^{ + [ratingsFlow userDidPerformSignificantEvent:YES + viewController:self.navigationController]; + }); + }]; + [ratingsFlow appDidLaunch:YES viewController:self.navigationController]; } } @catch (NSException *exception) { err(@"Apptentive: %@", exception); } - + UIImage *navBarImage = [[UIImage imageNamed:@"ui_navbar_container"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)]; [[UINavigationBar appearance] setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsDefault]; [[UINavigationBar appearance] setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsLandscapePhone]; @@ -288,19 +309,11 @@ @"https://youtrack.lyndir.com\n" viewStyle:UIAlertViewStyleDefault tappedButtonBlock:nil cancelTitle:nil otherTitles:[PearlStrings get].commonButtonOkay, nil]; -#else - @try { - ATAppRatingFlow *sharedFlow = [ATAppRatingFlow sharedRatingFlowWithAppID:[PearlConfig get].iTunesID]; - [sharedFlow appDidLaunch:YES viewController:self.navigationController]; - } - @catch (NSException *exception) { - err(@"Apptentive: %@", exception); - } #endif [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide]; - + return [super application:application didFinishLaunchingWithOptions:launchOptions]; } @@ -378,9 +391,6 @@ [TestFlight passCheckpoint:MPTestFlightCheckpointActivated]; - ATAppRatingFlow *sharedFlow = [ATAppRatingFlow sharedRatingFlowWithAppID:[PearlConfig get].iTunesID]; - [sharedFlow appDidEnterForeground:YES viewController:self.navigationController]; - [super applicationDidBecomeActive:application]; } @@ -484,7 +494,7 @@ cancelTitle:[PearlStrings get].commonButtonThanks otherTitles:nil]; return; } - + [MPConfig get].iCloudDecided = [NSNumber numberWithBool:YES]; if (buttonIndex == [alert cancelButtonIndex]) return; @@ -541,7 +551,7 @@ static NSDictionary *apptentiveInfo = nil; if (apptentiveInfo == nil) apptentiveInfo = [[NSDictionary alloc] initWithContentsOfURL: - [[NSBundle mainBundle] URLForResource:@"Apptentive" withExtension:@"plist"]]; + [[NSBundle mainBundle] URLForResource:@"Apptentive" withExtension:@"plist"]]; return apptentiveInfo; } diff --git a/MasterPassword/iOS/MPMainViewController.m b/MasterPassword/iOS/MPMainViewController.m index 3b8d4a28..60b969a0 100644 --- a/MasterPassword/iOS/MPMainViewController.m +++ b/MasterPassword/iOS/MPMainViewController.m @@ -146,8 +146,6 @@ - (void)updateAnimated:(BOOL)animated { - [[MPAppDelegate get] saveContext]; - dispatch_async(dispatch_get_main_queue(), ^{ if (animated) [UIView animateWithDuration:0.3f animations:^{ @@ -352,6 +350,7 @@ NSString *oldPassword = [self.activeElement.content description]; task(); NSString *newPassword = [self.activeElement.content description]; + [[MPAppDelegate get] saveContext]; [self updateAnimated:YES]; // Show new and old password. diff --git a/MasterPassword/iOS/MPSearchDelegate.m b/MasterPassword/iOS/MPSearchDelegate.m index a0faa4b5..1eccf950 100644 --- a/MasterPassword/iOS/MPSearchDelegate.m +++ b/MasterPassword/iOS/MPSearchDelegate.m @@ -14,7 +14,6 @@ @interface MPSearchDelegate (Private) - (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath; -- (void)update; @end @@ -38,10 +37,14 @@ NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])]; fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses" ascending:NO]]; - self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest - managedObjectContext:[MPAppDelegate managedObjectContext] - sectionNameKeyPath:nil cacheName:nil]; - self.fetchedResultsController.delegate = self; + self.fetchedResultsController = [PearlLazy lazyObjectLoadedFrom:^id{ + NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest + managedObjectContext:[MPAppDelegate managedObjectContext] + sectionNameKeyPath:nil cacheName:nil]; + controller.delegate = self; + + return controller; + }]; self.tipView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 170)]; self.tipView.textAlignment = UITextAlignmentCenter; @@ -123,12 +126,8 @@ - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { - [self update]; - - return NO; -} - -- (void)update { + if (!controller.active) + return NO; assert(self.query); @@ -138,7 +137,6 @@ NSError *error; if (![self.fetchedResultsController performFetch:&error]) err(@"Couldn't fetch elements: %@", error); - [self.searchDisplayController.searchResultsTableView reloadData]; NSArray *subviews = self.searchDisplayController.searchBar.superview.subviews; NSUInteger overlayIndex = [subviews indexOfObject:self.searchDisplayController.searchBar] + 1; @@ -149,6 +147,8 @@ [self.tipView removeFromSuperview]; [overlay addSubview:self.tipView]; } + + return YES; } // See MP-14, also crashes easily on internal assertions etc.. diff --git a/MasterPassword/iOS/MPUnlockViewController.m b/MasterPassword/iOS/MPUnlockViewController.m index e5128bf8..6ec0f48b 100644 --- a/MasterPassword/iOS/MPUnlockViewController.m +++ b/MasterPassword/iOS/MPUnlockViewController.m @@ -152,73 +152,69 @@ typedef enum { - (void)textFieldDidEndEditing:(UITextField *)textField { + CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; + rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; + rotate.fromValue = [NSNumber numberWithFloat:0]; + rotate.toValue = [NSNumber numberWithFloat:2 * M_PI]; + rotate.repeatCount = MAXFLOAT; + rotate.duration = 3.0; + + [self.spinner.layer removeAllAnimations]; + [self.spinner.layer addAnimation:rotate forKey:@"transform"]; + + [UIView animateWithDuration:0.3f animations:^{ + self.spinner.alpha = 1.0f; + }]; + + [self showMessage:@"Checking password..." state:MPLockscreenProgress]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - @try { - dispatch_async(dispatch_get_main_queue(), ^{ - CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; - rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; - rotate.fromValue = [NSNumber numberWithFloat:0]; - rotate.toValue = [NSNumber numberWithFloat:2 * M_PI]; - rotate.repeatCount = MAXFLOAT; - rotate.duration = 3.0; + BOOL unlocked = [[MPAppDelegate get] tryMasterPassword:textField.text]; + dispatch_async(dispatch_get_main_queue(), ^{ + if (unlocked) { + [self showMessage:@"Success!" state:MPLockscreenSuccess]; - [self.spinner.layer removeAllAnimations]; - [self.spinner.layer addAnimation:rotate forKey:@"transform"]; - - [UIView animateWithDuration:0.3f animations:^{ - self.spinner.alpha = 1.0f; - }]; - - [self showMessage:@"Checking password..." state:MPLockscreenProgress]; - }); - - if ([[MPAppDelegate get] tryMasterPassword:textField.text]) - dispatch_async(dispatch_get_main_queue(), ^{ - [self showMessage:@"Success!" state:MPLockscreenSuccess]; - - NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])]; - fetchRequest.predicate = [NSPredicate predicateWithFormat:@"keyID == %@", [MPAppDelegate get].keyID]; - fetchRequest.fetchLimit = 1; - BOOL keyIDHasElements = [[[MPAppDelegate managedObjectContext] executeFetchRequest:fetchRequest error:nil] count] > 0; - if (keyIDHasElements) - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long)(NSEC_PER_SEC * 1.5f)), dispatch_get_main_queue(), ^{ - [self dismissModalViewControllerAnimated:YES]; - }); - else { - [PearlAlert showAlertWithTitle:@"New Master Password" - message: - @"Please confirm the spelling of this new master password." - viewStyle:UIAlertViewStyleSecureTextInput - tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - if (buttonIndex == [alert cancelButtonIndex]) { - [[MPAppDelegate get] updateKey:nil]; - return; - } - if (![[alert textFieldAtIndex:0].text isEqualToString:textField.text]) { - [PearlAlert showAlertWithTitle:@"Incorrect Master Password" - message: - @"The password you entered doesn't match with the master password you tried to use. " - @"You've probably mistyped one of them.\n\n" - @"Give it another try." - viewStyle:UIAlertViewStyleDefault tappedButtonBlock:nil - cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil]; - return; - } - [self dismissModalViewControllerAnimated:YES]; + NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])]; + fetchRequest.predicate = [NSPredicate predicateWithFormat:@"keyID == %@", [MPAppDelegate get].keyID]; + fetchRequest.fetchLimit = 1; + BOOL keyIDHasElements = [[[MPAppDelegate managedObjectContext] executeFetchRequest:fetchRequest error:nil] count] > 0; + if (keyIDHasElements) + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long)(NSEC_PER_SEC * 1.5f)), dispatch_get_main_queue(), ^{ + [self dismissModalViewControllerAnimated:YES]; + }); + else { + [PearlAlert showAlertWithTitle:@"New Master Password" + message: + @"Please confirm the spelling of this new master password." + viewStyle:UIAlertViewStyleSecureTextInput + tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { + if (buttonIndex == [alert cancelButtonIndex]) { + [[MPAppDelegate get] updateKey:nil]; + return; } - cancelTitle:[PearlStrings get].commonButtonCancel - otherTitles:[PearlStrings get].commonButtonContinue, nil]; - } - }); - else - dispatch_async(dispatch_get_main_queue(), ^{ - [self showMessage:@"Not valid." state:MPLockscreenError]; - [UIView animateWithDuration:0.5f animations:^{ - self.changeMPView.alpha = 1.0f; - }]; - }); - } - @finally { + if (![[alert textFieldAtIndex:0].text isEqualToString:textField.text]) { + [PearlAlert showAlertWithTitle:@"Incorrect Master Password" + message: + @"The password you entered doesn't match with the master password you tried to use. " + @"You've probably mistyped one of them.\n\n" + @"Give it another try." + viewStyle:UIAlertViewStyleDefault tappedButtonBlock:nil + cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil]; + return; + } + [self dismissModalViewControllerAnimated:YES]; + } + cancelTitle:[PearlStrings get].commonButtonCancel + otherTitles:[PearlStrings get].commonButtonContinue, nil]; + } + } else { + [self showMessage:@"Not valid." state:MPLockscreenError]; + + [UIView animateWithDuration:0.5f animations:^{ + self.changeMPView.alpha = 1.0f; + }]; + } + dispatch_async(dispatch_get_main_queue(), ^{ [UIView animateWithDuration:0.3f animations:^{ self.spinner.alpha = 0.0f; @@ -226,7 +222,7 @@ typedef enum { [self.spinner.layer removeAllAnimations]; }]; }); - } + }); }); } diff --git a/Site/1/img/SolvingThePasswordProblem.png b/Site/1/img/SolvingThePasswordProblem.png new file mode 100644 index 00000000..55d6a5ab Binary files /dev/null and b/Site/1/img/SolvingThePasswordProblem.png differ