diff --git a/External/LoveLyndir b/External/LoveLyndir index c2c0d1e4..fbb540d8 160000 --- a/External/LoveLyndir +++ b/External/LoveLyndir @@ -1 +1 @@ -Subproject commit c2c0d1e45adfcea88c95dfe8f5793654508d9fb2 +Subproject commit fbb540d8e8ea00896bb6c08a08d3080ad3eeed4e diff --git a/External/Pearl b/External/Pearl index 04d8ca58..66fe13f2 160000 --- a/External/Pearl +++ b/External/Pearl @@ -1 +1 @@ -Subproject commit 04d8ca58b5f01c985b7d32dfb2248328d1ca0130 +Subproject commit 66fe13f25f6ee09dc8ba48030ea2baaa11781ef5 diff --git a/MasterPassword/ObjC/iOS/MPUnlockViewController.m b/MasterPassword/ObjC/iOS/MPUnlockViewController.m index 0cb909ee..d34a8c5b 100644 --- a/MasterPassword/ObjC/iOS/MPUnlockViewController.m +++ b/MasterPassword/ObjC/iOS/MPUnlockViewController.m @@ -7,7 +7,6 @@ // #import -#import #import "MPUnlockViewController.h" #import "MPiOSAppDelegate.h" @@ -26,12 +25,18 @@ @property(nonatomic, strong) NSTimer *marqueeTipTimer; @property(nonatomic) NSUInteger marqueeTipTextIndex; @property(nonatomic, strong) NSArray *marqueeTipTexts; +@property(nonatomic, strong) id mocObserver; @end @implementation MPUnlockViewController { NSManagedObjectID *_selectedUserOID; } +- (void)dealloc { + if (self.mocObserver) + [[NSNotificationCenter defaultCenter] removeObserver:self.mocObserver]; +} + - (void)initializeAvatarAlert:(UIAlertView *)alert forUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc { UIScrollView *alertAvatarScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake( 12, 30, 260, 150 )]; @@ -240,7 +245,7 @@ [UIView animateWithDuration:1 animations:^{ self.uiContainer.alpha = 1; - } completion:^(BOOL finished) { + } completion:^(BOOL finished) { if (finished) [UIView animateWithDuration:1 animations:^{ self.shareContainer.alpha = 1; @@ -310,6 +315,17 @@ - (void)updateUsers { + NSManagedObjectContext *mainContext = [MPiOSAppDelegate managedObjectContextForMainThreadIfReady]; + if (mainContext) { + if (self.mocObserver) + [[NSNotificationCenter defaultCenter] removeObserver:self.mocObserver]; + self.mocObserver = [[NSNotificationCenter defaultCenter] + addObserverForName:NSManagedObjectContextObjectsDidChangeNotification object:mainContext + queue:nil usingBlock:^(NSNotification *note) { + [self updateUsers]; + }]; + } + [MPiOSAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) { NSError *error = nil; NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )]; @@ -367,7 +383,6 @@ [self didSelectNewUserAvatar:avatar]; else if ([self setSelectedUser:user]) [self didToggleUserSelection]; - } options:0]; (self.avatarToUserOID)[[NSValue valueWithNonretainedObject:avatar]] = NilToNSNull([user objectID]); @@ -432,7 +447,7 @@ [PearlAlert showAlertWithTitle:@"Name Is Required" message:nil viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) { [self showNewUserNameAlertFor:newUser saveInContext:context completion:completion]; - } cancelTitle:@"Try Again" otherTitles:nil]; + } cancelTitle:@"Try Again" otherTitles:nil]; return; } @@ -457,7 +472,7 @@ // Okay [self showNewUserConfirmationAlertFor:newUser saveInContext:context completion:completion]; - } cancelTitle:nil otherTitles:[PearlStrings get].commonButtonOkay, nil]; + } cancelTitle:nil otherTitles:[PearlStrings get].commonButtonOkay, nil]; } - (void)showNewUserConfirmationAlertFor:(MPUserEntity *)newUser saveInContext:(NSManagedObjectContext *)context @@ -740,7 +755,7 @@ if (![avatar.layer animationForKey:@"targetedShadow"]) { CABasicAnimation *toShadowColorAnimation = [CABasicAnimation animationWithKeyPath:@"shadowColor"]; toShadowColorAnimation.toValue = (__bridge id)(avatar.selected? self.avatarTemplate.backgroundColor - : [UIColor whiteColor]).CGColor; + : [UIColor whiteColor]).CGColor; toShadowColorAnimation.beginTime = 0.0f; toShadowColorAnimation.duration = 0.5f; toShadowColorAnimation.fillMode = kCAFillModeForwards; @@ -1194,8 +1209,11 @@ NSError *error; MPUserEntity *selectedUser = (MPUserEntity *)[moc existingObjectWithID:_selectedUserOID error:&error]; - if (!selectedUser) - err(@"Failed to retrieve selected user: %@", error); + if (!selectedUser) { + err(@"Failed to retrieve selected user: %@", error); + _selectedUserOID = nil; + [self updateUsers]; + } return selectedUser; } @@ -1207,8 +1225,11 @@ NSError *error = nil; if (selectedUser.objectID.isTemporaryID && - ![selectedUser.managedObjectContext obtainPermanentIDsForObjects:@[ selectedUser ] error:&error]) - err(@"Failed to obtain a permanent object ID after setting selected user: %@", error); + ![selectedUser.managedObjectContext obtainPermanentIDsForObjects:@[ selectedUser ] error:&error]) { + err(@"Failed to obtain a permanent object ID after setting selected user: %@", error); + _selectedUserOID = nil; + [self updateUsers]; + } _selectedUserOID = selectedUser.objectID; return YES; diff --git a/MasterPassword/Resources/Media/iTunesArtwork-Square.png b/MasterPassword/Resources/Media/iTunesArtwork-Square.png new file mode 100644 index 00000000..0ca44a31 Binary files /dev/null and b/MasterPassword/Resources/Media/iTunesArtwork-Square.png differ diff --git a/Site/2013-05/privacy.html b/Site/2013-05/privacy.html new file mode 100644 index 00000000..b209d8af --- /dev/null +++ b/Site/2013-05/privacy.html @@ -0,0 +1,188 @@ + + + + + + Master Password — Secure your life, forget your passwords. + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+

Privacy Policy

+
+ +
+
+ +
+ +

We take personal satisfaction and your security very seriously. If you have any questions about features, usability, technical details, or any other topic, don't hesitate to get in touch with us. We try to give thorough, detailed and personal assistance to everyone. + +

+

Your Privacy

+

When you use Master Password for iOS, the app records some annonymous usage data for the purpose of troubleshooting. This includes logs which can be viewed using the Log Viewer, stack traces of running threads when the app crashes, and usage metrics. Any logged data has been carefully anonymized either by pruning user-specific information or cryptographically hashing it, making it impossible to reverse. Some of this data may be sent over the network, such as in the + case of app crashes, to provide us with the information necessary to resolve any issues in a timely manner.

+ +

Love Lyndir

+

Master Password is made available under the Love Lyndir campaign. This means it is now free of charge for everyone and offers a completely optional in-app way for people to contribute.

+

If you choose to contribute to the Love Lyndir campaign, you will need to make an in-app purchase via the app, which will bill your iTunes account. Additionally, our servers keep track of your active subscription with us, so that we can unlock your contribution level across all of Lyndir's apps. To do this, you'll be asked for your email address as an identifier to link your subscriptions to. This email address is currently only used as a unique identifier, but may be + used to notify subscribed users of changes or updates with regards to the Love Lyndir campaign. The email address will never be shared with any external parties.

+
+ +
+

Contact Us

+

If you have any concerns or questions, please send us a message at masterpassword@lyndir.com. You should get a personal reply within the hour if not in minutes.

+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +