diff --git a/External/Pearl b/External/Pearl index f81514bf..cc97c1be 160000 --- a/External/Pearl +++ b/External/Pearl @@ -1 +1 @@ -Subproject commit f81514bfd87773c6b1ea202520d75841c159ce9f +Subproject commit cc97c1be4c0f2ee0080af417940244ac8f3e5f47 diff --git a/MasterPassword/MPAlgorithmV0.m b/MasterPassword/MPAlgorithmV0.m index dd77a21d..40763c7f 100644 --- a/MasterPassword/MPAlgorithmV0.m +++ b/MasterPassword/MPAlgorithmV0.m @@ -192,7 +192,7 @@ return nil; if (!(element.type & MPElementTypeClassGenerated)) { - err(@"Incorrect type (is not MPElementTypeClassGenerated): %d, for: %@", [self nameOfType:element.type], element.name); + err(@"Incorrect type (is not MPElementTypeClassGenerated): %@, for: %@", [self nameOfType:element.type], element.name); return nil; } if (!element.name.length) { diff --git a/MasterPassword/MPAlgorithmV1.m b/MasterPassword/MPAlgorithmV1.m index a650298b..e379a717 100644 --- a/MasterPassword/MPAlgorithmV1.m +++ b/MasterPassword/MPAlgorithmV1.m @@ -54,7 +54,7 @@ return nil; if (!(element.type & MPElementTypeClassGenerated)) { - err(@"Incorrect type (is not MPElementTypeClassGenerated): %d, for: %@", [self nameOfType:element.type], element.name); + err(@"Incorrect type (is not MPElementTypeClassGenerated): %@, for: %@", [self nameOfType:element.type], element.name); return nil; } if (!element.name.length) { diff --git a/MasterPassword/iOS/MPAppDelegate.m b/MasterPassword/iOS/MPAppDelegate.m index 540e8b7f..8298de6d 100644 --- a/MasterPassword/iOS/MPAppDelegate.m +++ b/MasterPassword/iOS/MPAppDelegate.m @@ -34,7 +34,7 @@ [MPiOSConfig get]; #ifdef DEBUG - [PearlLogger get].autoprintLevel = PearlLogLevelDebug; + [PearlLogger get].printLevel = PearlLogLevelDebug; //[NSClassFromString(@"WebView") performSelector:NSSelectorFromString(@"_enableRemoteInspector")]; #endif } @@ -49,16 +49,14 @@ [[[NSBundle mainBundle] mutableInfoDictionary] setObject:@"Master Password" forKey:@"CFBundleDisplayName"]; [[[NSBundle mainBundle] mutableLocalizedInfoDictionary] setObject:@"Master Password" forKey:@"CFBundleDisplayName"]; +#ifdef ADHOC @try { NSString *testFlightToken = [self testFlightToken]; if ([testFlightToken length]) { inf(@"Initializing TestFlight"); [TestFlight addCustomEnvironmentInformation:@"Anonymous" forKey:@"username"]; -#ifdef ADHOC [TestFlight setDeviceIdentifier:[(id)[UIDevice currentDevice] uniqueIdentifier]]; -#else - [TestFlight setDeviceIdentifier:[PearlKeyChain deviceIdentifier]]; -#endif +// [TestFlight setDeviceIdentifier:[PearlKeyChain deviceIdentifier]]; [TestFlight setOptions:[NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], @"logToConsole", [NSNumber numberWithBool:NO], @"logToSTDERR", @@ -81,6 +79,7 @@ @catch (id exception) { err(@"TestFlight: %@", exception); } +#endif @try { NSString *crashlyticsAPIKey = [self crashlyticsAPIKey]; if ([crashlyticsAPIKey length]) { @@ -115,13 +114,13 @@ [[LocalyticsSession sharedLocalyticsSession] startSession:localyticsKey]; [[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) { if (message.level >= PearlLogLevelWarn) - [[LocalyticsSession sharedLocalyticsSession] tagEvent:@"Problem" attributes: - [NSDictionary dictionaryWithObjectsAndKeys: - [message levelDescription], - @"level", - message.message, - @"message", - nil]]; + [[LocalyticsSession sharedLocalyticsSession] tagEvent:@"Problem" + attributes:[NSDictionary + dictionaryWithObjectsAndKeys: + [NSString stringWithCString:PearlLogLevelStr(message.level) + encoding:NSASCIIStringEncoding], @"level", + message.message, @"message", + nil]]; return YES; }]; @@ -155,7 +154,7 @@ [NSValue valueWithUIOffset:UIOffsetMake(0, 1)], UITextAttributeTextShadowOffset, [UIFont fontWithName:@"Helvetica-Neue" size:0.0f], UITextAttributeFont, nil] - forState:UIControlStateNormal]; + forState:UIControlStateNormal]; UIImage *toolBarImage = [[UIImage imageNamed:@"ui_toolbar_container"] resizableImageWithCapInsets:UIEdgeInsetsMake(25, 5, 5, 5)]; [[UISearchBar appearance] setBackgroundImage:toolBarImage]; @@ -190,7 +189,7 @@ [self.navigationController performSegueWithIdentifier:@"MP_Unlock" sender:nil]; else [self.navigationController presentViewController:[self.navigationController.storyboard instantiateViewControllerWithIdentifier:@"MPUnlockViewController"] - animated:NO completion:nil]; + animated:NO completion:nil]; }]; [[NSNotificationCenter defaultCenter] addObserverForName:kIASKAppSettingChanged object:nil queue:nil usingBlock:^(NSNotification *note) { @@ -224,7 +223,7 @@ __autoreleasing NSError *error; __autoreleasing NSURLResponse *response; NSData *importedSitesData = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url] - returningResponse:&response error:&error]; + returningResponse:&response error:&error]; if (error) err(@"While reading imported sites from %@: %@", url, error); if (!importedSitesData) @@ -237,33 +236,33 @@ ^(UIAlertView *alert, NSInteger buttonIndex) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ MPImportResult result = [self importSites:importedSitesString withPassword:[alert textFieldAtIndex:0].text - askConfirmation:^BOOL(NSUInteger importCount, NSUInteger deleteCount) { - __block BOOL confirmation = NO; + askConfirmation:^BOOL(NSUInteger importCount, NSUInteger deleteCount) { + __block BOOL confirmation = NO; - dispatch_group_t confirmationGroup = dispatch_group_create(); - dispatch_group_enter(confirmationGroup); - dispatch_async(dispatch_get_main_queue(), ^{ - [PearlAlert showAlertWithTitle:@"Import Sites?" - message:PearlString( - @"Import %d sites, overwriting %d existing sites?", - importCount, deleteCount) - viewStyle:UIAlertViewStyleDefault - initAlert:nil - tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) { - if (buttonIndex_ - != [alert_ cancelButtonIndex]) - confirmation = YES; + dispatch_group_t confirmationGroup = dispatch_group_create(); + dispatch_group_enter(confirmationGroup); + dispatch_async(dispatch_get_main_queue(), ^{ + [PearlAlert showAlertWithTitle:@"Import Sites?" + message:PearlString( + @"Import %d sites, overwriting %d existing sites?", + importCount, deleteCount) + viewStyle:UIAlertViewStyleDefault + initAlert:nil + tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) { + if (buttonIndex_ + != [alert_ cancelButtonIndex]) + confirmation = YES; - dispatch_group_leave(confirmationGroup); - } - cancelTitle:[PearlStrings get].commonButtonCancel - otherTitles:@"Import", nil]; - }); - dispatch_group_wait( - confirmationGroup, DISPATCH_TIME_FOREVER); + dispatch_group_leave(confirmationGroup); + } + cancelTitle:[PearlStrings get].commonButtonCancel + otherTitles:@"Import", nil]; + }); + dispatch_group_wait( + confirmationGroup, DISPATCH_TIME_FOREVER); - return confirmation; - }]; + return confirmation; + }]; switch (result) { case MPImportResultSuccess: @@ -281,15 +280,15 @@ } }); } - cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Unlock File", nil]; + cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Unlock File", nil]; return YES; } - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { - + wrn(@"Received memory warning."); - + [super applicationDidReceiveMemoryWarning:application]; } @@ -352,8 +351,8 @@ if ([[MPConfig get].iCloud boolValue] != [self.storeManager iCloudEnabled]) [self.storeManager useiCloudStore:[[MPConfig get].iCloud boolValue] alertUser:YES]; if ([[MPiOSConfig get].sendInfo boolValue]) { - if ([PearlLogger get].autoprintLevel > PearlLogLevelInfo) - [PearlLogger get].autoprintLevel = PearlLogLevelInfo; + if ([PearlLogger get].printLevel > PearlLogLevelInfo) + [PearlLogger get].printLevel = PearlLogLevelInfo; [[Crashlytics sharedInstance] setBoolValue:[[MPConfig get].rememberLogin boolValue] forKey:@"rememberLogin"]; [[Crashlytics sharedInstance] setBoolValue:[[MPConfig get].iCloud boolValue] forKey:@"iCloud"]; @@ -396,11 +395,14 @@ ? @"YES": @"NO", @"showQuickStart", [[PearlConfig get].firstRun boolValue] ? @"YES": @"NO", @"firstRun", - [[PearlConfig get].launchCount description], @"launchCount", + [[PearlConfig get].launchCount description], + @"launchCount", [[PearlConfig get].askForReviews boolValue] ? @"YES": @"NO", @"askForReviews", - [[PearlConfig get].reviewAfterLaunches description], @"reviewAfterLaunches", - [PearlConfig get].reviewedVersion, @"reviewedVersion", + [[PearlConfig get].reviewAfterLaunches description], + @"reviewAfterLaunches", + [PearlConfig get].reviewedVersion, + @"reviewedVersion", nil]]; } } @@ -433,8 +435,8 @@ if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 1) // Show Passwords [self exportShowPasswords:YES]; - } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Safe Export", @"Show Passwords", nil]; - } otherTitles:nil]; + } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Safe Export", @"Show Passwords", nil]; + } otherTitles:nil]; } - (void)exportShowPasswords:(BOOL)showPasswords { @@ -442,11 +444,10 @@ if (![MFMailComposeViewController canSendMail]) { [PearlAlert showAlertWithTitle:@"Cannot Send Mail" message: - @"Your device is not yet set up for sending mail.\n" - @"Close Master Password, go into Settings and add a Mail account." + @"Your device is not yet set up for sending mail.\n" + @"Close Master Password, go into Settings and add a Mail account." viewStyle:UIAlertViewStyleDefault - initAlert:nil tappedButtonBlock:nil - cancelTitle:[PearlStrings get].commonButtonOkay + initAlert:nil tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil]; return; } @@ -456,18 +457,18 @@ if (showPasswords) message = PearlString(@"Export of Master Password sites with passwords included.\n" - @"REMINDER: Make sure nobody else sees this file! Passwords are visible!\n\n\n" - @"--\n" - @"%@\n" - @"Master Password %@, build %@", + @"REMINDER: Make sure nobody else sees this file! Passwords are visible!\n\n\n" + @"--\n" + @"%@\n" + @"Master Password %@, build %@", self.activeUser.name, [PearlInfoPlist get].CFBundleShortVersionString, [PearlInfoPlist get].CFBundleVersion); else message = PearlString(@"Backup of Master Password sites.\n\n\n" - @"--\n" - @"%@\n" - @"Master Password %@, build %@", + @"--\n" + @"%@\n" + @"Master Password %@, build %@", self.activeUser.name, [PearlInfoPlist get].CFBundleShortVersionString, [PearlInfoPlist get].CFBundleVersion); @@ -481,13 +482,13 @@ [composer setMessageBody:message isHTML:NO]; [composer addAttachmentData: [exportedSites dataUsingEncoding:NSUTF8StringEncoding] mimeType:@"text/plain" - fileName:PearlString(@"%@ (%@).mpsites", - self.activeUser.name, - [exportDateFormatter stringFromDate:[NSDate date]])]; + fileName:PearlString(@"%@ (%@).mpsites", + self.activeUser.name, + [exportDateFormatter stringFromDate:[NSDate date]])]; [self.window.rootViewController presentModalViewController:composer animated:YES]; } -- (void)changeMasterPasswordFor:(MPUserEntity *)user didResetBlock:(void(^)(void))didReset { +- (void)changeMasterPasswordFor:(MPUserEntity *)user didResetBlock:(void (^)(void))didReset { [PearlAlert showAlertWithTitle:@"Changing Master Password" message: @@ -508,11 +509,10 @@ didReset(); [TestFlight passCheckpoint:MPCheckpointChangeMP]; - [[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointChangeMP - attributes:nil]; + [[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointChangeMP attributes:nil]; } - cancelTitle:[PearlStrings get].commonButtonAbort - otherTitles:[PearlStrings get].commonButtonContinue, nil]; + cancelTitle:[PearlStrings get].commonButtonAbort + otherTitles:[PearlStrings get].commonButtonContinue, nil]; } #pragma mark - PearlConfigDelegate @@ -540,7 +540,7 @@ tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { if (buttonIndex == [alert firstOtherButtonIndex]) return; - } otherTitles:@"Retry", nil]; + } otherTitles:@"Retry", nil]; return; case MFMailComposeResultCancelled: break; @@ -581,7 +581,7 @@ initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) { [self ubiquityStoreManager:manager didSwitchToiCloud:iCloudEnabled]; } - cancelTitle:[PearlStrings get].commonButtonThanks otherTitles:nil]; + cancelTitle:[PearlStrings get].commonButtonThanks otherTitles:nil]; return; } @@ -590,7 +590,7 @@ return; if (buttonIndex == [alert firstOtherButtonIndex] + 1) [manager useiCloudStore:YES alertUser:NO]; - } cancelTitle:@"Leave iCloud Off" otherTitles:@"Explain?", @"Enable iCloud", nil]; + } cancelTitle:@"Leave iCloud Off" otherTitles:@"Explain?", @"Enable iCloud", nil]; } } } diff --git a/MasterPassword/iOS/MPUnlockViewController.h b/MasterPassword/iOS/MPUnlockViewController.h index b4cb6693..ad57d1c4 100644 --- a/MasterPassword/iOS/MPUnlockViewController.h +++ b/MasterPassword/iOS/MPUnlockViewController.h @@ -19,11 +19,12 @@ @property (weak, nonatomic) IBOutlet UILabel *oldNameLabel; @property (weak, nonatomic) IBOutlet UIButton *avatarTemplate; @property (weak, nonatomic) IBOutlet UIView *createPasswordTipView; -@property (weak, nonatomic) IBOutlet UILabel *deleteTip; +@property (weak, nonatomic) IBOutlet UILabel *tip; @property (weak, nonatomic) IBOutlet UIView *passwordTipView; @property (weak, nonatomic) IBOutlet UILabel *passwordTipLabel; @property (weak, nonatomic) IBOutlet UIView *wordWall; @property (strong, nonatomic) IBOutlet UILongPressGestureRecognizer *targetedUserActionGesture; +@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *loadingUsersIndicator; @property (nonatomic, strong) UIColor *avatarShadowColor; diff --git a/MasterPassword/iOS/MPUnlockViewController.m b/MasterPassword/iOS/MPUnlockViewController.m index b81dc5da..715ecc9a 100644 --- a/MasterPassword/iOS/MPUnlockViewController.m +++ b/MasterPassword/iOS/MPUnlockViewController.m @@ -34,11 +34,12 @@ @synthesize nameLabel, oldNameLabel; @synthesize avatarTemplate; @synthesize createPasswordTipView; -@synthesize deleteTip; +@synthesize tip; @synthesize passwordTipView; @synthesize passwordTipLabel; @synthesize wordWall; @synthesize targetedUserActionGesture; +@synthesize loadingUsersIndicator; @synthesize avatarShadowColor = _avatarShadowColor; @synthesize wordWallAnimating = _wordWallAnimating; @synthesize wordList = _wordList; @@ -154,6 +155,8 @@ [self updateUsers]; }]; + [self updateLayoutAnimated:NO allowScroll:YES completion:nil]; + [super viewDidLoad]; } @@ -165,13 +168,14 @@ [self setAvatarsView:nil]; [self setNameLabel:nil]; [self setAvatarTemplate:nil]; - [self setDeleteTip:nil]; + [self setTip:nil]; [self setPasswordTipView:nil]; [self setPasswordTipLabel:nil]; [self setTargetedUserActionGesture:nil]; [self setWordWall:nil]; [self setCreatePasswordTipView:nil]; [self setPasswordFieldLabel:nil]; + [self setLoadingUsersIndicator:nil]; [super viewDidUnload]; } @@ -202,9 +206,19 @@ - (void)updateUsers { + NSManagedObjectContext *moc = [MPAppDelegate managedObjectContextIfReady]; + if (!moc) { + self.tip.text = @"Loading..."; + [self.loadingUsersIndicator startAnimating]; + return; + } + + self.tip.text = @"Tap and hold to delete or reset."; + [self.loadingUsersIndicator stopAnimating]; + NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPUserEntity class])]; fetchRequest.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO]]; - NSArray *users = [[MPAppDelegate managedObjectContextIfReady] executeFetchRequest:fetchRequest error:nil]; + NSArray *users = [moc executeFetchRequest:fetchRequest error:nil]; // Clean up avatars. for (UIView *subview in [self.avatarsView subviews]) @@ -390,7 +404,6 @@ self.nameLabel.backgroundColor = [UIColor blackColor]; self.oldNameLabel.center = self.nameLabel.center; self.avatarShadowColor = [UIColor whiteColor]; - self.deleteTip.alpha = 0; } else if (!self.selectedUser && self.passwordView.alpha == 1) { // User was just deselected. @@ -402,7 +415,6 @@ self.nameLabel.backgroundColor = [UIColor clearColor]; self.oldNameLabel.center = self.nameLabel.center; self.avatarShadowColor = [UIColor lightGrayColor]; - self.deleteTip.alpha = 0.5; } // Lay out the word wall. @@ -463,7 +475,7 @@ } // Lay out user name label. - self.nameLabel.text = targetedUser? targetedUser.name: @"New User"; + self.nameLabel.text = targetedAvatar? targetedUser? targetedUser.name: @"New User": nil; self.nameLabel.bounds = CGRectSetHeight(self.nameLabel.bounds, [self.nameLabel.text sizeWithFont:self.nameLabel.font constrainedToSize:CGSizeMake(self.nameLabel.bounds.size.width - 10, 100) diff --git a/MasterPassword/iOS/MainStoryboard_iPhone.storyboard b/MasterPassword/iOS/MainStoryboard_iPhone.storyboard index 40915bb3..9c69f411 100644 --- a/MasterPassword/iOS/MainStoryboard_iPhone.storyboard +++ b/MasterPassword/iOS/MainStoryboard_iPhone.storyboard @@ -1414,6 +1414,10 @@ You could use the word wall for inspiration in finding a memorable master passw + + + + @@ -1422,7 +1426,8 @@ You could use the word wall for inspiration in finding a memorable master passw - + + @@ -1853,6 +1858,7 @@ You could use the word wall for inspiration in finding a memorable master passw + @@ -1922,7 +1928,8 @@ You could use the word wall for inspiration in finding a memorable master passw - + + @@ -1944,4 +1951,4 @@ You could use the word wall for inspiration in finding a memorable master passw - \ No newline at end of file + diff --git a/Tests/Tests.m b/Tests/Tests.m index e2e243e7..e2b0d02c 100644 --- a/Tests/Tests.m +++ b/Tests/Tests.m @@ -13,7 +13,7 @@ - (void)setUp { dbg(@"======================= TEST SET-UP ======================"); - [PearlLogger get].autoprintLevel = PearlLogLevelTrace; + [PearlLogger get].printLevel = PearlLogLevelTrace; [super setUp];