Unlock and user preferences implementation.
[FIXED] Unlock screen. [FIXED] Internal fixes. [ADDED] Avatar selection in preferences. [ADDED] Implementation of the other preferences. [IMPROVED] UI of unlock and preferences screens.
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import "MPAppDelegate_Key.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
|
||||
@implementation MPAppDelegate_Shared (Key)
|
||||
|
||||
@@ -63,10 +64,10 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
||||
|
||||
NSData *tryKey = keyForPassword(tryPassword);
|
||||
NSData *tryKeyID = keyIDForKey(tryKey);
|
||||
inf(@"Key ID known? %@.", user.keyID? @"YES": @"NO");
|
||||
if (user.keyID)
|
||||
// A key ID is known -> a password is set.
|
||||
// Make sure the user's entered password matches it.
|
||||
inf(@"Key ID was known? %@.", user.keyID? @"YES": @"NO");
|
||||
if (user.keyID) {
|
||||
// A key ID is known -> a master password is set.
|
||||
// Make sure the user's entered master password matches it.
|
||||
if (![user.keyID isEqual:tryKeyID]) {
|
||||
wrn(@"Key ID mismatch. Expected: %@, answer: %@.", [user.keyID encodeHex], [tryKeyID encodeHex]);
|
||||
|
||||
@@ -75,7 +76,12 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
||||
#endif
|
||||
return NO;
|
||||
}
|
||||
|
||||
} else {
|
||||
// A key ID is not known -> recording a new master password.
|
||||
user.keyID = tryKeyID;
|
||||
[[MPAppDelegate_Shared get] saveContext];
|
||||
}
|
||||
|
||||
#ifdef TESTFLIGHT_SDK_VERSION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointMPEntered];
|
||||
#endif
|
||||
|
@@ -12,6 +12,8 @@
|
||||
#import "MPElementGeneratedEntity.h"
|
||||
#import "MPUserEntity.h"
|
||||
|
||||
#define MPAvatarCount 19
|
||||
|
||||
@interface MPElementEntity (MP)
|
||||
|
||||
@property (assign) MPElementType type;
|
||||
|
@@ -12,7 +12,7 @@
|
||||
|
||||
|
||||
#define MP_salt nil
|
||||
#define MP_N 16384
|
||||
#define MP_N 131072
|
||||
#define MP_r 8
|
||||
#define MP_p 1
|
||||
#define MP_dkLen 64
|
||||
|
@@ -114,7 +114,7 @@
|
||||
return nil;
|
||||
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
|
||||
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses" ascending:NO]];
|
||||
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses_" ascending:NO]];
|
||||
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(%@ == '' OR name BEGINSWITH[cd] %@) AND user == %@",
|
||||
query, query, [MPAppDelegate get].activeUser];
|
||||
|
||||
|
@@ -18,5 +18,6 @@
|
||||
- (void)loadKey:(BOOL)animated;
|
||||
|
||||
- (void)export;
|
||||
- (void)changeMP;
|
||||
|
||||
@end
|
||||
|
@@ -117,6 +117,29 @@
|
||||
[self.window.rootViewController presentModalViewController:composer animated:YES];
|
||||
}
|
||||
|
||||
- (void)changeMP {
|
||||
|
||||
[PearlAlert showAlertWithTitle:@"Changing Master Password"
|
||||
message:
|
||||
@"This will allow you to log in with a different master password.\n\n"
|
||||
@"Note that you will only see the sites and passwords for the master password you log in with.\n"
|
||||
@"If you log in with a different master password, your current sites will be unavailable.\n\n"
|
||||
@"You can always change back to your current master password later.\n"
|
||||
@"Your current sites and passwords will then become available again."
|
||||
viewStyle:UIAlertViewStyleDefault
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
[[MPAppDelegate get] forgetSavedKey];
|
||||
[[MPAppDelegate get] loadKey:YES];
|
||||
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointMPChanged];
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonAbort
|
||||
otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
||||
}
|
||||
|
||||
#pragma mark - PearlConfigDelegate
|
||||
|
||||
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)value {
|
||||
|
@@ -404,23 +404,19 @@
|
||||
[self performSegueWithIdentifier:@"UserProfile" sender:self];
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
[[MPAppDelegate get] export];
|
||||
break;
|
||||
}
|
||||
#ifdef ADHOC
|
||||
case 5: {
|
||||
case 4: {
|
||||
[TestFlight openFeedbackView];
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
case 5:
|
||||
#else
|
||||
case 5: {
|
||||
case 4: {
|
||||
ATConnect *connection = [ATConnect sharedConnection];
|
||||
[connection presentFeedbackControllerFromViewController:self];
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
case 5:
|
||||
#endif
|
||||
{
|
||||
[[MPAppDelegate get] signOut:self];
|
||||
|
@@ -11,6 +11,12 @@
|
||||
|
||||
@interface MPPreferencesViewController : UITableViewController <IASKSettingsDelegate>
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIScrollView *avatarScrollView;
|
||||
@property (weak, nonatomic) IBOutlet UIScrollView *avatarsView;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *avatarTemplate;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *savePasswordSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UITableViewCell *exportCell;
|
||||
@property (weak, nonatomic) IBOutlet UITableViewCell *changeMPCell;
|
||||
|
||||
- (IBAction)didToggleSwitch:(UISwitch *)sender;
|
||||
|
||||
@end
|
||||
|
@@ -6,6 +6,7 @@
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import "MPPreferencesViewController.h"
|
||||
#import "MPAppDelegate.h"
|
||||
|
||||
@@ -14,31 +15,60 @@
|
||||
@end
|
||||
|
||||
@implementation MPPreferencesViewController
|
||||
@synthesize avatarScrollView;
|
||||
@synthesize avatarsView;
|
||||
@synthesize avatarTemplate;
|
||||
@synthesize savePasswordSwitch;
|
||||
@synthesize exportCell;
|
||||
@synthesize changeMPCell;
|
||||
|
||||
|
||||
- (void)viewDidLoad {
|
||||
|
||||
__block NSInteger avatarIndex = 0;
|
||||
[self.avatarScrollView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||
UIButton *avatar = (UIButton *)subview;
|
||||
avatar.toggleSelectionWhenTouchedInside = YES;
|
||||
avatar.tag = avatarIndex++;
|
||||
|
||||
[avatar onSelect:^(BOOL selected) {
|
||||
[MPAppDelegate get].activeUser.avatar = (unsigned)avatar.tag;
|
||||
[self.avatarScrollView enumerateSubviews:^(UIView *subview_, BOOL *stop_, BOOL *recurse_) {
|
||||
UIButton *avatar_ = (UIButton *)subview_;
|
||||
avatar_.selected = ([MPAppDelegate get].activeUser.avatar == (unsigned)avatar_.tag);
|
||||
} recurse:NO];
|
||||
self.avatarTemplate.hidden = YES;
|
||||
|
||||
for (int a = 0; a < MPAvatarCount; ++a) {
|
||||
UIButton *avatar = [self.avatarTemplate clone];
|
||||
avatar.togglesSelectionInSuperview = YES;
|
||||
avatar.tag = a;
|
||||
avatar.hidden = NO;
|
||||
avatar.center = CGPointMake(
|
||||
self.avatarTemplate.center.x * (a + 1) + self.avatarTemplate.bounds.size.width / 2 * a,
|
||||
self.avatarTemplate.center.y);
|
||||
[avatar setBackgroundImage:[UIImage imageNamed:PearlString(@"avatar-%d", a)]
|
||||
forState:UIControlStateNormal];
|
||||
|
||||
avatar.layer.cornerRadius = avatar.bounds.size.height / 2;
|
||||
avatar.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||
avatar.layer.shadowOpacity = 1;
|
||||
avatar.layer.shadowRadius = 5;
|
||||
avatar.backgroundColor = [UIColor clearColor];
|
||||
|
||||
[avatar onHighlightOrSelect:^(BOOL highlighted, BOOL selected) {
|
||||
if (highlighted || selected)
|
||||
avatar.backgroundColor = self.avatarTemplate.backgroundColor;
|
||||
else
|
||||
avatar.backgroundColor = [UIColor clearColor];
|
||||
} options:0];
|
||||
} recurse:NO];
|
||||
|
||||
[avatar onSelect:^(BOOL selected) {
|
||||
if (selected)
|
||||
[MPAppDelegate get].activeUser.avatar = (unsigned)avatar.tag;
|
||||
} options:0];
|
||||
avatar.selected = (a == [MPAppDelegate get].activeUser.avatar);
|
||||
}
|
||||
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
|
||||
[self.avatarScrollView autoSizeContent];
|
||||
[self.avatarsView autoSizeContent];
|
||||
[self.avatarsView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||
if (subview.tag && ((UIControl *) subview).selected) {
|
||||
[self.avatarsView setContentOffset:CGPointMake(subview.center.x - self.avatarsView.bounds.size.width / 2, 0) animated:animated];
|
||||
}
|
||||
} recurse:NO];
|
||||
|
||||
self.savePasswordSwitch.on = [MPAppDelegate get].activeUser.saveKey;
|
||||
|
||||
[super viewWillAppear:animated];
|
||||
}
|
||||
@@ -48,7 +78,29 @@
|
||||
return (interfaceOrientation == UIInterfaceOrientationPortrait);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
- (void)viewDidUnload {
|
||||
[self setAvatarsView:nil];
|
||||
[self setAvatarTemplate:nil];
|
||||
[self setAvatarsView:nil];
|
||||
[self setSavePasswordSwitch:nil];
|
||||
[self setExportCell:nil];
|
||||
[self setChangeMPCell:nil];
|
||||
[super viewDidUnload];
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
|
||||
if (cell == self.exportCell)
|
||||
[[MPAppDelegate get] export];
|
||||
|
||||
else if (cell == self.changeMPCell)
|
||||
[[MPAppDelegate get] changeMP];
|
||||
}
|
||||
|
||||
#pragma mark - IASKSettingsDelegate
|
||||
|
||||
- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController *)sender {
|
||||
|
||||
@@ -56,8 +108,11 @@
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
- (void)viewDidUnload {
|
||||
[self setAvatarScrollView:nil];
|
||||
[super viewDidUnload];
|
||||
#pragma mark - IBActions
|
||||
|
||||
- (IBAction)didToggleSwitch:(UISwitch *)sender {
|
||||
|
||||
[MPAppDelegate get].activeUser.saveKey = sender.on;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@@ -35,7 +35,7 @@
|
||||
self.query = @"";
|
||||
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
|
||||
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses" ascending:NO]];
|
||||
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses_" ascending:NO]];
|
||||
self.fetchedResultsController = [PearlLazy lazyObjectLoadedFrom:^id{
|
||||
NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
|
||||
managedObjectContext:[MPAppDelegate managedObjectContext]
|
||||
|
@@ -13,12 +13,14 @@
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *spinner;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *passwordField;
|
||||
@property (weak, nonatomic) IBOutlet UIView *passwordView;
|
||||
@property (weak, nonatomic) IBOutlet UIScrollView *usersView;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *usernameLabel;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *oldUsernameLabel;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *userButtonTemplate;
|
||||
@property (weak, nonatomic) IBOutlet UIScrollView *avatarsView;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *oldNameLabel;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *avatarTemplate;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *deleteTip;
|
||||
|
||||
@property(nonatomic, strong) UIColor *avatarShadowColor;
|
||||
|
||||
- (IBAction)deleteTargetedUser:(UILongPressGestureRecognizer *)sender;
|
||||
|
||||
@end
|
||||
|
@@ -15,8 +15,8 @@
|
||||
|
||||
@interface MPUnlockViewController ()
|
||||
|
||||
@property (strong, nonatomic) MPUserEntity *selectedUser;
|
||||
@property (strong, nonatomic) NSMutableDictionary *avatarToUser;
|
||||
@property(strong, nonatomic) MPUserEntity *selectedUser;
|
||||
@property(strong, nonatomic) NSMutableDictionary *avatarToUser;
|
||||
|
||||
@end
|
||||
|
||||
@@ -26,10 +26,12 @@
|
||||
@synthesize spinner;
|
||||
@synthesize passwordField;
|
||||
@synthesize passwordView;
|
||||
@synthesize usersView;
|
||||
@synthesize usernameLabel, oldUsernameLabel;
|
||||
@synthesize userButtonTemplate;
|
||||
@synthesize avatarsView;
|
||||
@synthesize nameLabel, oldNameLabel;
|
||||
@synthesize avatarTemplate;
|
||||
@synthesize deleteTip;
|
||||
@synthesize avatarShadowColor = _avatarShadowColor;
|
||||
|
||||
|
||||
// [UIView animateWithDuration:1.0f delay:0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse animations:^{
|
||||
// self.lock.alpha = 0.5f;
|
||||
@@ -44,12 +46,12 @@
|
||||
|
||||
self.avatarToUser = [NSMutableDictionary dictionaryWithCapacity:3];
|
||||
|
||||
self.spinner.alpha = 0;
|
||||
self.passwordField.text = nil;
|
||||
self.usersView.decelerationRate = UIScrollViewDecelerationRateFast;
|
||||
self.usersView.clipsToBounds = NO;
|
||||
self.usernameLabel.layer.cornerRadius = 5;
|
||||
self.userButtonTemplate.hidden = YES;
|
||||
self.avatarsView.decelerationRate = UIScrollViewDecelerationRateFast;
|
||||
self.avatarsView.clipsToBounds = NO;
|
||||
self.nameLabel.layer.cornerRadius = 5;
|
||||
self.avatarTemplate.hidden = YES;
|
||||
self.spinner.alpha = 0;
|
||||
|
||||
[self updateLayoutAnimated:NO allowScroll:YES completion:nil];
|
||||
|
||||
@@ -61,15 +63,15 @@
|
||||
[self setSpinner:nil];
|
||||
[self setPasswordField:nil];
|
||||
[self setPasswordView:nil];
|
||||
[self setUsersView:nil];
|
||||
[self setUsernameLabel:nil];
|
||||
[self setUserButtonTemplate:nil];
|
||||
[self setAvatarsView:nil];
|
||||
[self setNameLabel:nil];
|
||||
[self setAvatarTemplate:nil];
|
||||
[self setDeleteTip:nil];
|
||||
[super viewDidUnload];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
|
||||
|
||||
self.selectedUser = nil;
|
||||
[self updateUsers];
|
||||
|
||||
@@ -78,42 +80,40 @@
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
|
||||
[[UIApplication sharedApplication] setStatusBarHidden:YES
|
||||
withAnimation:animated? UIStatusBarAnimationSlide: UIStatusBarAnimationNone];
|
||||
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:animated ? UIStatusBarAnimationSlide : UIStatusBarAnimationNone];
|
||||
|
||||
[super viewDidAppear:animated];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
|
||||
[[UIApplication sharedApplication] setStatusBarHidden:NO
|
||||
withAnimation:animated? UIStatusBarAnimationSlide: UIStatusBarAnimationNone];
|
||||
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:animated ? UIStatusBarAnimationSlide : UIStatusBarAnimationNone];
|
||||
|
||||
[super viewWillDisappear:animated];
|
||||
}
|
||||
|
||||
- (void)updateUsers {
|
||||
|
||||
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPUserEntity class])];
|
||||
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO]];
|
||||
NSArray *users = [[MPAppDelegate managedObjectContext] executeFetchRequest:fetchRequest error:nil];
|
||||
|
||||
|
||||
// Clean up avatars.
|
||||
for (UIView *view in [self.usersView subviews])
|
||||
if (view != self.userButtonTemplate)
|
||||
for (UIView *view in [self.avatarsView subviews])
|
||||
if (view != self.avatarTemplate)
|
||||
[view removeFromSuperview];
|
||||
[self.avatarToUser removeAllObjects];
|
||||
|
||||
|
||||
// Create avatars.
|
||||
for (MPUserEntity *user in users)
|
||||
[self setupAvatar:[self.userButtonTemplate clone] forUser:user];
|
||||
[self setupAvatar:[self.userButtonTemplate clone] forUser:nil];
|
||||
|
||||
[self setupAvatar:[self.avatarTemplate clone] forUser:user];
|
||||
[self setupAvatar:[self.avatarTemplate clone] forUser:nil];
|
||||
|
||||
// Scroll view's content changed, update its content size.
|
||||
[self.usersView autoSizeContentIgnoreHidden:YES ignoreInvisible:YES limitPadding:NO ignoreSubviews:nil];
|
||||
|
||||
[self.avatarsView autoSizeContentIgnoreHidden:YES ignoreInvisible:YES limitPadding:NO ignoreSubviews:nil];
|
||||
|
||||
[self updateLayoutAnimated:YES allowScroll:YES completion:nil];
|
||||
|
||||
|
||||
self.deleteTip.alpha = 0;
|
||||
if ([users count] > 1)
|
||||
[UIView animateWithDuration:0.5f animations:^{
|
||||
@@ -122,89 +122,92 @@
|
||||
}
|
||||
|
||||
- (UIButton *)setupAvatar:(UIButton *)avatar forUser:(MPUserEntity *)user {
|
||||
|
||||
|
||||
[avatar onHighlightOrSelect:^(BOOL highlighted, BOOL selected) {
|
||||
if (highlighted || selected)
|
||||
avatar.backgroundColor = self.userButtonTemplate.backgroundColor;
|
||||
avatar.backgroundColor = self.avatarTemplate.backgroundColor;
|
||||
else
|
||||
avatar.backgroundColor = [UIColor clearColor];
|
||||
} options:0];
|
||||
[avatar onSelect:^(BOOL selected) {
|
||||
self.selectedUser = selected? user: nil;
|
||||
self.selectedUser = selected ? user : nil;
|
||||
if (user)
|
||||
[self didToggleUserSelection];
|
||||
else if (selected)
|
||||
[self didSelectNewUserAvatar:avatar];
|
||||
} options:0];
|
||||
avatar.toggleSelectionWhenTouchedInside = YES;
|
||||
avatar.togglesSelectionInSuperview = YES;
|
||||
avatar.center = CGPointMake(avatar.center.x + [self.avatarToUser count] * 160, avatar.center.y);
|
||||
avatar.hidden = NO;
|
||||
avatar.layer.cornerRadius = 5;
|
||||
avatar.layer.cornerRadius = avatar.bounds.size.height / 2;
|
||||
avatar.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||
avatar.layer.shadowOpacity = 1;
|
||||
avatar.layer.shadowRadius = 20;
|
||||
avatar.layer.masksToBounds = NO;
|
||||
avatar.backgroundColor = [UIColor clearColor];
|
||||
|
||||
|
||||
dbg(@"User: %@, avatar: %d", user.name, user.avatar);
|
||||
[avatar setBackgroundImage:[UIImage imageNamed:PearlString(@"avatar-%u", user.avatar)]
|
||||
forState:UIControlStateNormal];
|
||||
|
||||
if (user)
|
||||
[self.avatarToUser setObject:user forKey:[NSValue valueWithNonretainedObject:avatar]];
|
||||
|
||||
|
||||
if (self.selectedUser && user == self.selectedUser)
|
||||
avatar.selected = YES;
|
||||
|
||||
|
||||
return avatar;
|
||||
}
|
||||
|
||||
- (void)didToggleUserSelection {
|
||||
|
||||
|
||||
if (!self.selectedUser)
|
||||
[self.passwordField resignFirstResponder];
|
||||
|
||||
|
||||
[self updateLayoutAnimated:YES allowScroll:YES completion:^(BOOL finished) {
|
||||
if (finished)
|
||||
if (self.selectedUser)
|
||||
[self.passwordField becomeFirstResponder];
|
||||
if (finished) if (self.selectedUser)
|
||||
[self.passwordField becomeFirstResponder];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)didSelectNewUserAvatar:(UIButton *)newUserAvatar {
|
||||
|
||||
[PearlAlert showAlertWithTitle:@"New User"
|
||||
message:@"Enter your name:" viewStyle:UIAlertViewStylePlainTextInput
|
||||
initAlert:^(UIAlertView *alert, UITextField *firstField) {
|
||||
firstField.autocapitalizationType = UITextAutocapitalizationTypeWords;
|
||||
firstField.autocorrectionType = UITextAutocorrectionTypeYes;
|
||||
firstField.spellCheckingType = UITextSpellCheckingTypeYes;
|
||||
firstField.keyboardType = UIKeyboardTypeAlphabet;
|
||||
}
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
newUserAvatar.selected = NO;
|
||||
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
MPUserEntity *newUser = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MPUserEntity class])
|
||||
inManagedObjectContext:[MPAppDelegate managedObjectContext]];
|
||||
newUser.name = [alert textFieldAtIndex:0].text;
|
||||
self.selectedUser = newUser;
|
||||
|
||||
[self updateUsers];
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonSave, nil];
|
||||
|
||||
[PearlAlert showAlertWithTitle:@"New User"
|
||||
message:@"Enter your name:" viewStyle:UIAlertViewStylePlainTextInput
|
||||
initAlert:^(UIAlertView *alert, UITextField *firstField) {
|
||||
firstField.autocapitalizationType = UITextAutocapitalizationTypeWords;
|
||||
firstField.autocorrectionType = UITextAutocorrectionTypeYes;
|
||||
firstField.spellCheckingType = UITextSpellCheckingTypeYes;
|
||||
firstField.keyboardType = UIKeyboardTypeAlphabet;
|
||||
}
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
newUserAvatar.selected = NO;
|
||||
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
MPUserEntity *newUser = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MPUserEntity class])
|
||||
inManagedObjectContext:[MPAppDelegate managedObjectContext]];
|
||||
newUser.name = [alert textFieldAtIndex:0].text;
|
||||
self.selectedUser = newUser;
|
||||
|
||||
[self updateUsers];
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonSave, nil];
|
||||
}
|
||||
|
||||
- (void)updateLayoutAnimated:(BOOL)animated allowScroll:(BOOL)allowScroll completion:(void (^)(BOOL finished))completion {
|
||||
|
||||
|
||||
if (animated) {
|
||||
self.oldUsernameLabel.text = self.usernameLabel.text;
|
||||
self.oldUsernameLabel.alpha = 1;
|
||||
self.usernameLabel.alpha = 0;
|
||||
|
||||
self.oldNameLabel.text = self.nameLabel.text;
|
||||
self.oldNameLabel.alpha = 1;
|
||||
self.nameLabel.alpha = 0;
|
||||
|
||||
[UIView animateWithDuration:0.5f animations:^{
|
||||
[self updateLayoutAnimated:NO allowScroll:allowScroll completion:nil];
|
||||
|
||||
self.oldUsernameLabel.alpha = 0;
|
||||
self.usernameLabel.alpha = 1;
|
||||
|
||||
self.oldNameLabel.alpha = 0;
|
||||
self.nameLabel.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
if (completion)
|
||||
completion(finished);
|
||||
@@ -214,20 +217,22 @@
|
||||
|
||||
if (self.selectedUser && !self.passwordView.alpha) {
|
||||
self.passwordView.alpha = 1;
|
||||
self.usersView.center = CGPointMake(160, 100);
|
||||
self.usersView.scrollEnabled = NO;
|
||||
self.usernameLabel.center = CGPointMake(160, 84);
|
||||
self.usernameLabel.backgroundColor = [UIColor blackColor];
|
||||
self.oldUsernameLabel.center = self.usernameLabel.center;
|
||||
} else if (self.passwordView.alpha == 1) {
|
||||
self.avatarsView.center = CGPointMake(160, 100);
|
||||
self.avatarsView.scrollEnabled = NO;
|
||||
self.nameLabel.center = CGPointMake(160, 84);
|
||||
self.nameLabel.backgroundColor = [UIColor blackColor];
|
||||
self.oldNameLabel.center = self.nameLabel.center;
|
||||
self.avatarShadowColor = [UIColor whiteColor];
|
||||
} else if (!self.selectedUser && self.passwordView.alpha == 1) {
|
||||
self.passwordView.alpha = 0;
|
||||
self.usersView.center = CGPointMake(160, 240);
|
||||
self.usersView.scrollEnabled = YES;
|
||||
self.usernameLabel.center = CGPointMake(160, 296);
|
||||
self.usernameLabel.backgroundColor = [UIColor clearColor];
|
||||
self.oldUsernameLabel.center = self.usernameLabel.center;
|
||||
self.avatarsView.center = CGPointMake(160, 240);
|
||||
self.avatarsView.scrollEnabled = YES;
|
||||
self.nameLabel.center = CGPointMake(160, 296);
|
||||
self.nameLabel.backgroundColor = [UIColor clearColor];
|
||||
self.oldNameLabel.center = self.nameLabel.center;
|
||||
self.avatarShadowColor = [UIColor lightGrayColor];
|
||||
}
|
||||
|
||||
|
||||
MPUserEntity *targetedUser = self.selectedUser;
|
||||
UIButton *selectedAvatar = [self avatarForUser:self.selectedUser];
|
||||
UIButton *targetedAvatar = selectedAvatar;
|
||||
@@ -235,178 +240,205 @@
|
||||
targetedAvatar = [self findTargetedAvatar];
|
||||
targetedUser = [self userForAvatar:targetedAvatar];
|
||||
}
|
||||
|
||||
[self.usersView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||
|
||||
[self.avatarsView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||
const BOOL isTargeted = subview == targetedAvatar;
|
||||
|
||||
|
||||
subview.userInteractionEnabled = isTargeted;
|
||||
subview.alpha = isTargeted ? 1: self.selectedUser? 0.1: 0.4;
|
||||
if (!isTargeted && [subview.layer animationForKey:@"targetedShadow"]) {
|
||||
CABasicAnimation *toShadowColorAnimation = [CABasicAnimation animationWithKeyPath:@"shadowColor"];
|
||||
toShadowColorAnimation.toValue = (__bridge id)[UIColor blackColor].CGColor;
|
||||
toShadowColorAnimation.duration = 0.5f;
|
||||
|
||||
CABasicAnimation *toShadowOpacityAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOpacity"];
|
||||
toShadowOpacityAnimation.toValue = PearlFloat(1);
|
||||
toShadowOpacityAnimation.duration = 0.5f;
|
||||
|
||||
CAAnimationGroup *group = [[CAAnimationGroup alloc] init];
|
||||
group.animations = [NSArray arrayWithObjects:toShadowColorAnimation, toShadowOpacityAnimation, nil];
|
||||
group.duration = 0.5f;
|
||||
|
||||
[subview.layer removeAnimationForKey:@"targetedShadow"];
|
||||
[subview.layer addAnimation:group forKey:@"inactiveShadow"];
|
||||
}
|
||||
subview.alpha = isTargeted ? 1 : self.selectedUser ? 0.1 : 0.4;
|
||||
|
||||
[self updateAvatarShadowColor:subview isTargeted:isTargeted];
|
||||
} recurse:NO];
|
||||
|
||||
if (![targetedAvatar.layer animationForKey:@"targetedShadow"]) {
|
||||
CABasicAnimation *toShadowColorAnimation = [CABasicAnimation animationWithKeyPath:@"shadowColor"];
|
||||
toShadowColorAnimation.toValue = (__bridge id)[UIColor whiteColor].CGColor;
|
||||
toShadowColorAnimation.beginTime = 0.0f;
|
||||
toShadowColorAnimation.duration = 0.5f;
|
||||
toShadowColorAnimation.fillMode = kCAFillModeForwards;
|
||||
|
||||
CABasicAnimation *toShadowOpacityAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOpacity"];
|
||||
toShadowOpacityAnimation.toValue = PearlFloat(0.2);
|
||||
toShadowOpacityAnimation.duration = 0.5f;
|
||||
|
||||
CABasicAnimation *pulseShadowOpacityAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOpacity"];
|
||||
pulseShadowOpacityAnimation.fromValue = PearlFloat(0.2);
|
||||
pulseShadowOpacityAnimation.toValue = PearlFloat(0.6);
|
||||
pulseShadowOpacityAnimation.beginTime = 0.5f;
|
||||
pulseShadowOpacityAnimation.duration = 2.0f;
|
||||
pulseShadowOpacityAnimation.autoreverses = YES;
|
||||
pulseShadowOpacityAnimation.repeatCount = NSIntegerMax;
|
||||
|
||||
CAAnimationGroup *group = [[CAAnimationGroup alloc] init];
|
||||
group.animations = [NSArray arrayWithObjects:toShadowColorAnimation, toShadowOpacityAnimation, pulseShadowOpacityAnimation, nil];
|
||||
group.duration = CGFLOAT_MAX;
|
||||
|
||||
[targetedAvatar.layer removeAnimationForKey:@"inactiveShadow"];
|
||||
[targetedAvatar.layer addAnimation:group forKey:@"targetedShadow"];
|
||||
}
|
||||
|
||||
|
||||
if (allowScroll) {
|
||||
CGPoint targetContentOffset = CGPointMake(targetedAvatar.center.x - self.usersView.bounds.size.width / 2, self.usersView.contentOffset.y);
|
||||
if (!CGPointEqualToPoint(self.usersView.contentOffset, targetContentOffset))
|
||||
[self.usersView setContentOffset:targetContentOffset animated:animated];
|
||||
CGPoint targetContentOffset = CGPointMake(targetedAvatar.center.x - self.avatarsView.bounds.size.width / 2, self.avatarsView.contentOffset.y);
|
||||
if (!CGPointEqualToPoint(self.avatarsView.contentOffset, targetContentOffset))
|
||||
[self.avatarsView setContentOffset:targetContentOffset animated:animated];
|
||||
}
|
||||
|
||||
self.usernameLabel.text = targetedUser? targetedUser.name: @"New User";
|
||||
self.usernameLabel.bounds = CGRectSetHeight(self.usernameLabel.bounds,
|
||||
[self.usernameLabel.text sizeWithFont:self.usernameLabel.font
|
||||
constrainedToSize:CGSizeMake(self.usernameLabel.bounds.size.width - 10, 100)
|
||||
lineBreakMode:self.usernameLabel.lineBreakMode].height);
|
||||
self.oldUsernameLabel.bounds = self.usernameLabel.bounds;
|
||||
|
||||
self.nameLabel.text = targetedUser ? targetedUser.name : @"New User";
|
||||
self.nameLabel.bounds = CGRectSetHeight(self.nameLabel.bounds,
|
||||
[self.nameLabel.text sizeWithFont:self.nameLabel.font
|
||||
constrainedToSize:CGSizeMake(self.nameLabel.bounds.size.width - 10, 100)
|
||||
lineBreakMode:self.nameLabel.lineBreakMode].height);
|
||||
self.oldNameLabel.bounds = self.nameLabel.bounds;
|
||||
if (completion)
|
||||
completion(YES);
|
||||
}
|
||||
|
||||
- (UIButton *)findTargetedAvatar {
|
||||
- (void)tryMasterPassword {
|
||||
|
||||
[self setSpinnerActive:YES];
|
||||
[self changeAvatarShadowColorTo:[UIColor colorWithName:@"lightskyblue"]];
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
BOOL unlocked = [[MPAppDelegate get] tryMasterPassword:self.passwordField.text forUser:self.selectedUser];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (unlocked) {
|
||||
[self changeAvatarShadowColorTo:[UIColor colorWithName:@"greenyellow"]];
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long) (NSEC_PER_SEC * 1.5f)), dispatch_get_main_queue(), ^{
|
||||
[self dismissModalViewControllerAnimated:YES];
|
||||
});
|
||||
} else
|
||||
[self changeAvatarShadowColorTo:[UIColor colorWithName:@"crimson"]];
|
||||
|
||||
[self setSpinnerActive:NO];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
CGFloat xOfMiddle = self.usersView.contentOffset.x + self.usersView.bounds.size.width / 2;
|
||||
return (UIButton *)[PearlUIUtils viewClosestTo:CGPointMake(xOfMiddle, self.usersView.contentOffset.y) ofArray:self.usersView.subviews];
|
||||
- (UIButton *)findTargetedAvatar {
|
||||
|
||||
CGFloat xOfMiddle = self.avatarsView.contentOffset.x + self.avatarsView.bounds.size.width / 2;
|
||||
return (UIButton *) [PearlUIUtils viewClosestTo:CGPointMake(xOfMiddle, self.avatarsView.contentOffset.y) ofArray:self.avatarsView.subviews];
|
||||
}
|
||||
|
||||
- (UIButton *)avatarForUser:(MPUserEntity *)user {
|
||||
|
||||
|
||||
__block UIButton *avatar = nil;
|
||||
if (user)
|
||||
[self.avatarToUser enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
||||
if (obj == user)
|
||||
avatar = [key nonretainedObjectValue];
|
||||
}];
|
||||
|
||||
|
||||
return avatar;
|
||||
}
|
||||
|
||||
- (MPUserEntity *)userForAvatar:(UIButton *)avatar {
|
||||
|
||||
|
||||
return NullToNil([self.avatarToUser objectForKey:[NSValue valueWithNonretainedObject:avatar]]);
|
||||
}
|
||||
|
||||
- (void)setSpinnerActive:(BOOL)active {
|
||||
|
||||
PearlMainThread(^{
|
||||
CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
|
||||
rotate.toValue = [NSNumber numberWithDouble:2 * M_PI];
|
||||
rotate.duration = 5.0;
|
||||
|
||||
if (active) {
|
||||
rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
|
||||
rotate.fromValue = [NSNumber numberWithFloat:0];
|
||||
rotate.repeatCount = MAXFLOAT;
|
||||
} else {
|
||||
rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
|
||||
rotate.repeatCount = 1;
|
||||
}
|
||||
|
||||
[self.spinner.layer removeAnimationForKey:@"rotation"];
|
||||
[self.spinner.layer addAnimation:rotate forKey:@"rotation"];
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.spinner.alpha = active? 1: 0;
|
||||
|
||||
if (active)
|
||||
[self avatarForUser:self.selectedUser].backgroundColor = [UIColor clearColor];
|
||||
else
|
||||
[self avatarForUser:self.selectedUser].backgroundColor = self.avatarTemplate.backgroundColor;
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)changeAvatarShadowColorTo:(UIColor *)color {
|
||||
|
||||
self.avatarShadowColor = color;
|
||||
|
||||
if (self.selectedUser) {
|
||||
UIButton *selectedAvatar = [self avatarForUser:self.selectedUser];
|
||||
[selectedAvatar.layer removeAnimationForKey:@"targetedShadow"];
|
||||
[self updateAvatarShadowColor:selectedAvatar isTargeted:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateAvatarShadowColor:(UIView *)avatar isTargeted:(BOOL)targeted {
|
||||
|
||||
if (targeted) {
|
||||
if (![avatar.layer animationForKey:@"targetedShadow"]) {
|
||||
CABasicAnimation *toShadowColorAnimation = [CABasicAnimation animationWithKeyPath:@"shadowColor"];
|
||||
toShadowColorAnimation.toValue = (__bridge id) self.avatarShadowColor.CGColor;
|
||||
toShadowColorAnimation.beginTime = 0.0f;
|
||||
toShadowColorAnimation.duration = 0.5f;
|
||||
toShadowColorAnimation.fillMode = kCAFillModeForwards;
|
||||
|
||||
CABasicAnimation *toShadowOpacityAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOpacity"];
|
||||
toShadowOpacityAnimation.toValue = PearlFloat(0.2);
|
||||
toShadowOpacityAnimation.duration = 0.5f;
|
||||
|
||||
CABasicAnimation *pulseShadowOpacityAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOpacity"];
|
||||
pulseShadowOpacityAnimation.fromValue = PearlFloat(0.2);
|
||||
pulseShadowOpacityAnimation.toValue = PearlFloat(0.6);
|
||||
pulseShadowOpacityAnimation.beginTime = 0.5f;
|
||||
pulseShadowOpacityAnimation.duration = 2.0f;
|
||||
pulseShadowOpacityAnimation.autoreverses = YES;
|
||||
pulseShadowOpacityAnimation.repeatCount = MAXFLOAT;
|
||||
|
||||
CAAnimationGroup *group = [[CAAnimationGroup alloc] init];
|
||||
group.animations = [NSArray arrayWithObjects:toShadowColorAnimation, toShadowOpacityAnimation, pulseShadowOpacityAnimation, nil];
|
||||
group.duration = MAXFLOAT;
|
||||
|
||||
[avatar.layer removeAnimationForKey:@"inactiveShadow"];
|
||||
[avatar.layer addAnimation:group forKey:@"targetedShadow"];
|
||||
}
|
||||
} else {
|
||||
if ([avatar.layer animationForKey:@"targetedShadow"]) {
|
||||
CABasicAnimation *toShadowColorAnimation = [CABasicAnimation animationWithKeyPath:@"shadowColor"];
|
||||
toShadowColorAnimation.toValue = (__bridge id) [UIColor blackColor].CGColor;
|
||||
toShadowColorAnimation.duration = 0.5f;
|
||||
|
||||
CABasicAnimation *toShadowOpacityAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOpacity"];
|
||||
toShadowOpacityAnimation.toValue = PearlFloat(1);
|
||||
toShadowOpacityAnimation.duration = 0.5f;
|
||||
|
||||
CAAnimationGroup *group = [[CAAnimationGroup alloc] init];
|
||||
group.animations = [NSArray arrayWithObjects:toShadowColorAnimation, toShadowOpacityAnimation, nil];
|
||||
group.duration = 0.5f;
|
||||
|
||||
[avatar.layer removeAnimationForKey:@"targetedShadow"];
|
||||
[avatar.layer addAnimation:group forKey:@"inactiveShadow"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UITextFieldDelegate
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
||||
|
||||
if (![textField.text length])
|
||||
return NO;
|
||||
|
||||
[textField resignFirstResponder];
|
||||
|
||||
CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
|
||||
rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
|
||||
rotate.fromValue = [NSNumber numberWithFloat:0];
|
||||
rotate.toValue = [NSNumber numberWithDouble:2 * M_PI];
|
||||
rotate.repeatCount = MAXFLOAT;
|
||||
rotate.duration = 3.0;
|
||||
[self setSpinnerActive:YES];
|
||||
[self changeAvatarShadowColorTo:[UIColor colorWithName:@"lightskyblue"]];
|
||||
|
||||
[self.spinner.layer removeAllAnimations];
|
||||
[self.spinner.layer addAnimation:rotate forKey:@"transform"];
|
||||
if (self.selectedUser.keyID)
|
||||
[self tryMasterPassword];
|
||||
|
||||
[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), ^{
|
||||
BOOL unlocked = [[MPAppDelegate get] tryMasterPassword:textField.text forUser:self.selectedUser];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (unlocked) {
|
||||
// [self showMessage:@"Success!" state:MPLockscreenSuccess];
|
||||
if ([selectedUser.keyID length])
|
||||
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
|
||||
initAlert:nil
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert cancelButtonIndex]) {
|
||||
[[MPAppDelegate get] unsetKey];
|
||||
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 initAlert:nil tappedButtonBlock:nil
|
||||
cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
self.selectedUser.keyID = [MPAppDelegate get].activeUser.keyID;
|
||||
[[MPAppDelegate get] saveContext];
|
||||
|
||||
[self dismissModalViewControllerAnimated:YES];
|
||||
else
|
||||
[PearlAlert showAlertWithTitle:@"New Master Password"
|
||||
message:@"Please confirm the spelling of this new master password."
|
||||
viewStyle:UIAlertViewStyleSecureTextInput
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
[self setSpinnerActive:NO];
|
||||
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
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 initAlert:nil tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil];
|
||||
return;
|
||||
}
|
||||
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;
|
||||
} completion:^(BOOL finished) {
|
||||
[self.spinner.layer removeAllAnimations];
|
||||
}];
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
[self tryMasterPassword];
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonCancel
|
||||
otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
@@ -416,54 +448,30 @@
|
||||
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
|
||||
|
||||
CGFloat xOfMiddle = targetContentOffset->x + scrollView.bounds.size.width / 2;
|
||||
UIButton *middleAvatar = (UIButton *)[PearlUIUtils viewClosestTo:CGPointMake(xOfMiddle, targetContentOffset->y) ofArray:scrollView.subviews];
|
||||
UIButton *middleAvatar = (UIButton *) [PearlUIUtils viewClosestTo:CGPointMake(xOfMiddle, targetContentOffset->y) ofArray:scrollView.subviews];
|
||||
*targetContentOffset = CGPointMake(middleAvatar.center.x - scrollView.bounds.size.width / 2, targetContentOffset->y);
|
||||
|
||||
|
||||
[self updateLayoutAnimated:NO allowScroll:NO completion:nil];
|
||||
// [self scrollToAvatar:middleAvatar animated:YES];
|
||||
// [self scrollToAvatar:middleAvatar animated:YES];
|
||||
}
|
||||
|
||||
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
|
||||
|
||||
[self updateLayoutAnimated:YES allowScroll:YES completion:nil];
|
||||
// [self scrollToAvatar:middleAvatar animated:YES];
|
||||
// [self scrollToAvatar:middleAvatar animated:YES];
|
||||
}
|
||||
|
||||
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
|
||||
|
||||
// CGFloat xOfMiddle = scrollView.contentOffset.x + scrollView.bounds.size.width / 2;
|
||||
// UIButton *middleAvatar = (UIButton *)[PearlUIUtils viewClosestTo:CGPointMake(xOfMiddle, scrollView.contentOffset.y) ofArray:scrollView.subviews];
|
||||
//
|
||||
// CGFloat xOfMiddle = scrollView.contentOffset.x + scrollView.bounds.size.width / 2;
|
||||
// UIButton *middleAvatar = (UIButton *)[PearlUIUtils viewClosestTo:CGPointMake(xOfMiddle, scrollView.contentOffset.y) ofArray:scrollView.subviews];
|
||||
//
|
||||
[self updateLayoutAnimated:NO allowScroll:NO completion:nil];
|
||||
// [self scrollToAvatar:middleAvatar animated:NO];
|
||||
// [self scrollToAvatar:middleAvatar animated:NO];
|
||||
}
|
||||
|
||||
#pragma mark - IBActions
|
||||
|
||||
- (IBAction)changeMP {
|
||||
|
||||
[PearlAlert showAlertWithTitle:@"Changing Master Password"
|
||||
message:
|
||||
@"This will allow you to log in with a different master password.\n\n"
|
||||
@"Note that you will only see the sites and passwords for the master password you log in with.\n"
|
||||
@"If you log in with a different master password, your current sites will be unavailable.\n\n"
|
||||
@"You can always change back to your current master password later.\n"
|
||||
@"Your current sites and passwords will then become available again."
|
||||
viewStyle:UIAlertViewStyleDefault
|
||||
initAlert:nil
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
[[MPAppDelegate get] forgetSavedKey];
|
||||
[[MPAppDelegate get] loadKey:YES];
|
||||
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointMPChanged];
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonAbort
|
||||
otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
||||
}
|
||||
|
||||
- (IBAction)deleteTargetedUser:(UILongPressGestureRecognizer *)sender {
|
||||
|
||||
if (sender.state != UIGestureRecognizerStateBegan)
|
||||
@@ -479,15 +487,14 @@
|
||||
[PearlAlert showAlertWithTitle:@"Delete User" message:
|
||||
PearlString(@"Do you want to delete all record of the following user?\n\n%@", targetedUser.name)
|
||||
viewStyle:UIAlertViewStyleDefault
|
||||
initAlert:nil
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
[[MPAppDelegate get].managedObjectContext deleteObject:targetedUser];
|
||||
[[MPAppDelegate get] saveContext];
|
||||
|
||||
[self updateUsers];
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Delete", nil];
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
[[MPAppDelegate get].managedObjectContext deleteObject:targetedUser];
|
||||
[[MPAppDelegate get] saveContext];
|
||||
|
||||
[self updateUsers];
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Delete", nil];
|
||||
}
|
||||
@end
|
||||
|
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="1.1" toolsVersion="2182" systemVersion="11E53" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" initialViewController="KZF-fe-y9n">
|
||||
<dependencies>
|
||||
<deployment defaultVersion="1296" identifier="iOS"/>
|
||||
<development defaultVersion="4200" identifier="xcode"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="1181"/>
|
||||
</dependencies>
|
||||
@@ -782,7 +783,7 @@ L4m3P4sSw0rD</string>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_spinner.png" id="27q-lX-0vy">
|
||||
<rect key="frame" x="105" y="29" width="110" height="110"/>
|
||||
<rect key="frame" x="105" y="30" width="110" height="110"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" delaysContentTouches="NO" id="Blg-F1-9NA">
|
||||
@@ -792,9 +793,9 @@ L4m3P4sSw0rD</string>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" id="Ten-ig-gog">
|
||||
<rect key="frame" x="105" y="10" width="110" height="110"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" red="0.40000000596046448" green="0.80000001192092896" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<state key="normal" backgroundImage="avatar-male-1.png">
|
||||
<state key="normal" backgroundImage="avatar-0.png">
|
||||
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
@@ -834,14 +835,14 @@ L4m3P4sSw0rD</string>
|
||||
</view>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<connections>
|
||||
<outlet property="avatarTemplate" destination="Ten-ig-gog" id="0ZZ-z5-d5m"/>
|
||||
<outlet property="avatarsView" destination="Blg-F1-9NA" id="2NL-jU-IMI"/>
|
||||
<outlet property="deleteTip" destination="DBJ-Qi-ZcF" id="VXD-Zc-UYi"/>
|
||||
<outlet property="oldUsernameLabel" destination="8s0-nT-Aoq" id="mXR-VG-2js"/>
|
||||
<outlet property="nameLabel" destination="0NM-NI-7UR" id="GBg-Ry-sqj"/>
|
||||
<outlet property="oldNameLabel" destination="8s0-nT-Aoq" id="plu-1H-MVc"/>
|
||||
<outlet property="passwordField" destination="rTR-7Q-X8o" id="CDA-iP-kCm"/>
|
||||
<outlet property="passwordView" destination="7cc-yu-i0m" id="WoF-Ab-PPC"/>
|
||||
<outlet property="spinner" destination="27q-lX-0vy" id="jUx-GK-Lgf"/>
|
||||
<outlet property="userButtonTemplate" destination="Ten-ig-gog" id="hSM-hh-ofy"/>
|
||||
<outlet property="usernameLabel" destination="0NM-NI-7UR" id="Sa4-pY-87O"/>
|
||||
<outlet property="usersView" destination="Blg-F1-9NA" id="SsC-1H-fIB"/>
|
||||
<outlet property="spinner" destination="27q-lX-0vy" id="CGK-G9-PRI"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<pongPressGestureRecognizer allowableMovement="10" minimumPressDuration="0.5" id="9WS-yS-aqQ">
|
||||
@@ -892,14 +893,14 @@ L4m3P4sSw0rD</string>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.12549020350000001" green="0.1411764771" blue="0.14901961389999999" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<view key="tableFooterView" contentMode="scaleToFill" id="63M-7L-M7o">
|
||||
<rect key="frame" x="0.0" y="508" width="320" height="20"/>
|
||||
<rect key="frame" x="0.0" y="492" width="320" height="20"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<sections>
|
||||
<tableViewSection id="OJv-8V-W2l">
|
||||
<cells>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="226" id="9gC-Vq-Ta8">
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="226" id="9gC-Vq-Ta8">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="226"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
@@ -924,77 +925,23 @@ L4m3P4sSw0rD</string>
|
||||
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<size key="shadowOffset" width="0.0" height="1"/>
|
||||
</label>
|
||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="TMH-Xt-EnD">
|
||||
<scrollView multipleTouchEnabled="YES" contentMode="scaleToFill" id="TMH-Xt-EnD">
|
||||
<rect key="frame" x="0.0" y="95" width="320" height="130"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" id="jEL-UA-da6">
|
||||
<rect key="frame" x="0.0" y="0.0" width="614" height="130"/>
|
||||
<autoresizingMask key="autoresizingMask" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" lineBreakMode="middleTruncation" id="6ap-Xw-Ubd">
|
||||
<rect key="frame" x="20" y="10" width="110" height="110"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<state key="normal" image="avatar-male-1.png">
|
||||
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<state key="highlighted">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" lineBreakMode="middleTruncation" id="DwC-Fa-yaI">
|
||||
<rect key="frame" x="138" y="10" width="110" height="110"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<state key="normal" image="avatar-female-1.png">
|
||||
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<state key="highlighted">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" lineBreakMode="middleTruncation" id="TF1-Zi-jZK">
|
||||
<rect key="frame" x="256" y="10" width="110" height="110"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<state key="normal" image="avatar-male-2.png">
|
||||
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<state key="highlighted">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" lineBreakMode="middleTruncation" id="32d-Yo-SGt">
|
||||
<rect key="frame" x="366" y="10" width="110" height="110"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<state key="normal" image="avatar-female-2.png">
|
||||
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<state key="highlighted">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" lineBreakMode="middleTruncation" id="LTD-gI-8bH">
|
||||
<rect key="frame" x="484" y="10" width="110" height="110"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<state key="normal" image="avatar-male-3.png">
|
||||
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<state key="highlighted">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<button opaque="NO" contentMode="scaleToFill" selected="YES" contentHorizontalAlignment="center" contentVerticalAlignment="top" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" id="6ap-Xw-Ubd">
|
||||
<rect key="frame" x="20" y="10" width="110" height="110"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<state key="normal" backgroundImage="avatar-0.png">
|
||||
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<state key="highlighted">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
</button>
|
||||
</subviews>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
@@ -1006,11 +953,11 @@ L4m3P4sSw0rD</string>
|
||||
</tableViewSection>
|
||||
<tableViewSection id="TRa-Gy-tG5">
|
||||
<cells>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="119" id="n1H-sG-HDc">
|
||||
<rect key="frame" x="0.0" y="226" width="320" height="119"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="66" id="n1H-sG-HDc">
|
||||
<rect key="frame" x="0.0" y="226" width="320" height="66"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="118"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="65"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Preferences" lineBreakMode="tailTruncation" minimumFontSize="10" id="ylz-i5-tem">
|
||||
@@ -1031,18 +978,30 @@ L4m3P4sSw0rD</string>
|
||||
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<size key="shadowOffset" width="0.0" height="1"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="top" image="ui_list_first.png" id="tK4-bL-QK1">
|
||||
<rect key="frame" x="10" y="75" width="300" height="50"/>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="44" id="0jz-0D-ggZ">
|
||||
<rect key="frame" x="0.0" y="292" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="top" image="ui_list_first.png" id="8dk-FW-Tse">
|
||||
<rect key="frame" x="10" y="0.0" width="300" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" contentMode="bottom" image="ui_list_last.png" id="fAY-fK-Uzn">
|
||||
<rect key="frame" x="10" y="109" width="300" height="10"/>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="bottom" image="ui_list_last.png" id="5oz-I2-Nos">
|
||||
<rect key="frame" x="10" y="34" width="300" height="10"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/>
|
||||
</imageView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Save Password" lineBreakMode="tailTruncation" minimumFontSize="10" id="mmP-r2-iNF">
|
||||
<rect key="frame" x="20" y="75" width="280" height="23"/>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Save Password" lineBreakMode="tailTruncation" minimumFontSize="10" id="0Mf-7e-quo">
|
||||
<rect key="frame" x="20" y="0.0" width="280" height="23"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<fontDescription key="fontDescription" name="GillSans" family="Gill Sans" pointSize="18"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -1050,17 +1009,20 @@ L4m3P4sSw0rD</string>
|
||||
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<size key="shadowOffset" width="0.0" height="1"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Stores your password on the device." lineBreakMode="tailTruncation" minimumFontSize="10" id="LRv-ac-sdH">
|
||||
<rect key="frame" x="20" y="98" width="280" height="20"/>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Stores your password on the device." lineBreakMode="tailTruncation" minimumFontSize="10" id="Hfj-40-OHR">
|
||||
<rect key="frame" x="20" y="23" width="280" height="20"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
|
||||
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" id="seh-qE-k6P">
|
||||
<rect key="frame" x="221" y="83" width="79" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<switch opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" id="ilG-0h-SOb">
|
||||
<rect key="frame" x="221" y="8" width="79" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<color key="onTintColor" red="0.12549020350000001" green="0.1411764771" blue="0.14901961389999999" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<connections>
|
||||
<action selector="didToggleSwitch:" destination="oLN-6u-GLb" eventType="valueChanged" id="e5q-mf-XK7"/>
|
||||
</connections>
|
||||
</switch>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
@@ -1071,11 +1033,11 @@ L4m3P4sSw0rD</string>
|
||||
</tableViewSection>
|
||||
<tableViewSection id="dN3-cJ-9WA">
|
||||
<cells>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="119" id="xBt-OT-BYA">
|
||||
<rect key="frame" x="0.0" y="345" width="320" height="119"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="68" id="xBt-OT-BYA">
|
||||
<rect key="frame" x="0.0" y="336" width="320" height="68"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="118"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="67"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Operations" lineBreakMode="tailTruncation" minimumFontSize="10" id="VI9-uT-nrJ">
|
||||
@@ -1096,13 +1058,25 @@ L4m3P4sSw0rD</string>
|
||||
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<size key="shadowOffset" width="0.0" height="1"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_list_first.png" id="zeK-qR-5wK">
|
||||
<rect key="frame" x="10" y="75" width="300" height="44"/>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="44" id="X2m-92-Qzh">
|
||||
<rect key="frame" x="0.0" y="404" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_list_first.png" id="s1D-Yv-FNl">
|
||||
<rect key="frame" x="10" y="0.0" width="300" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/>
|
||||
</imageView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Export" lineBreakMode="tailTruncation" minimumFontSize="10" id="DTP-qu-VqT">
|
||||
<rect key="frame" x="20" y="75" width="280" height="23"/>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Export" lineBreakMode="tailTruncation" minimumFontSize="10" id="Sw0-Yj-Xh0">
|
||||
<rect key="frame" x="20" y="0.0" width="280" height="23"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<fontDescription key="fontDescription" name="GillSans" family="Gill Sans" pointSize="18"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -1110,8 +1084,8 @@ L4m3P4sSw0rD</string>
|
||||
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<size key="shadowOffset" width="0.0" height="1"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Save all your sites to a file." lineBreakMode="tailTruncation" minimumFontSize="10" id="oi9-2Y-2KM">
|
||||
<rect key="frame" x="20" y="98" width="280" height="20"/>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Save all your sites to a file." lineBreakMode="tailTruncation" minimumFontSize="10" id="DwF-cT-vUT">
|
||||
<rect key="frame" x="20" y="23" width="280" height="20"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
|
||||
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -1123,7 +1097,7 @@ L4m3P4sSw0rD</string>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="glr-eJ-qKq">
|
||||
<rect key="frame" x="0.0" y="464" width="320" height="44"/>
|
||||
<rect key="frame" x="0.0" y="448" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
|
||||
@@ -1171,7 +1145,11 @@ L4m3P4sSw0rD</string>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<connections>
|
||||
<outlet property="avatarScrollView" destination="TMH-Xt-EnD" id="zdf-xt-piZ"/>
|
||||
<outlet property="avatarTemplate" destination="6ap-Xw-Ubd" id="WW7-3k-5QJ"/>
|
||||
<outlet property="avatarsView" destination="TMH-Xt-EnD" id="zdf-xt-piZ"/>
|
||||
<outlet property="changeMPCell" destination="glr-eJ-qKq" id="EpZ-xu-JGh"/>
|
||||
<outlet property="exportCell" destination="X2m-92-Qzh" id="zjs-9C-uKX"/>
|
||||
<outlet property="savePasswordSwitch" destination="ilG-0h-SOb" id="iZD-gQ-pve"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
</objects>
|
||||
@@ -1180,11 +1158,7 @@ L4m3P4sSw0rD</string>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="Square-bottom.png" width="551" height="58"/>
|
||||
<image name="avatar-female-1.png" width="110" height="110"/>
|
||||
<image name="avatar-female-2.png" width="110" height="110"/>
|
||||
<image name="avatar-male-1.png" width="110" height="110"/>
|
||||
<image name="avatar-male-2.png" width="110" height="110"/>
|
||||
<image name="avatar-male-3.png" width="110" height="110"/>
|
||||
<image name="avatar-0.png" width="110" height="110"/>
|
||||
<image name="background.png" width="480" height="480"/>
|
||||
<image name="guide_page_0.png" width="320" height="480"/>
|
||||
<image name="guide_page_1.png" width="320" height="480"/>
|
||||
@@ -1260,7 +1234,12 @@ L4m3P4sSw0rD</string>
|
||||
<class className="MPPreferencesViewController" superclassName="UITableViewController">
|
||||
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPPreferencesViewController.h"/>
|
||||
<relationships>
|
||||
<relationship kind="outlet" name="avatarScrollView" candidateClass="UIScrollView"/>
|
||||
<relationship kind="action" name="didToggleSwitch:" candidateClass="UISwitch"/>
|
||||
<relationship kind="outlet" name="avatarTemplate" candidateClass="UIButton"/>
|
||||
<relationship kind="outlet" name="avatarsView" candidateClass="UIScrollView"/>
|
||||
<relationship kind="outlet" name="changeMPCell" candidateClass="UITableViewCell"/>
|
||||
<relationship kind="outlet" name="exportCell" candidateClass="UITableViewCell"/>
|
||||
<relationship kind="outlet" name="savePasswordSwitch" candidateClass="UISwitch"/>
|
||||
</relationships>
|
||||
</class>
|
||||
<class className="MPSearchDelegate" superclassName="NSObject">
|
||||
@@ -1281,14 +1260,14 @@ L4m3P4sSw0rD</string>
|
||||
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPUnlockViewController.h"/>
|
||||
<relationships>
|
||||
<relationship kind="action" name="deleteTargetedUser:" candidateClass="UILongPressGestureRecognizer"/>
|
||||
<relationship kind="outlet" name="avatarTemplate" candidateClass="UIButton"/>
|
||||
<relationship kind="outlet" name="avatarsView" candidateClass="UIScrollView"/>
|
||||
<relationship kind="outlet" name="deleteTip" candidateClass="UILabel"/>
|
||||
<relationship kind="outlet" name="oldUsernameLabel" candidateClass="UILabel"/>
|
||||
<relationship kind="outlet" name="nameLabel" candidateClass="UILabel"/>
|
||||
<relationship kind="outlet" name="oldNameLabel" candidateClass="UILabel"/>
|
||||
<relationship kind="outlet" name="passwordField" candidateClass="UITextField"/>
|
||||
<relationship kind="outlet" name="passwordView" candidateClass="UIView"/>
|
||||
<relationship kind="outlet" name="spinner" candidateClass="UIImageView"/>
|
||||
<relationship kind="outlet" name="userButtonTemplate" candidateClass="UIButton"/>
|
||||
<relationship kind="outlet" name="usernameLabel" candidateClass="UILabel"/>
|
||||
<relationship kind="outlet" name="usersView" candidateClass="UIScrollView"/>
|
||||
</relationships>
|
||||
</class>
|
||||
</classes>
|
||||
|
Reference in New Issue
Block a user