diff --git a/External/Pearl b/External/Pearl index d4bbb48f..76449ca7 160000 --- a/External/Pearl +++ b/External/Pearl @@ -1 +1 @@ -Subproject commit d4bbb48f21af0323f887d8c869db90951e1f14f6 +Subproject commit 76449ca7a47814189ffffd7f34053c390085d7d2 diff --git a/MasterPassword/ObjC/iOS/MPAppSettingsViewController.h b/MasterPassword/ObjC/iOS/MPAppSettingsViewController.h new file mode 100644 index 00000000..937f0250 --- /dev/null +++ b/MasterPassword/ObjC/iOS/MPAppSettingsViewController.h @@ -0,0 +1,23 @@ +/** + * Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) + * + * See the enclosed file LICENSE for license information (LGPLv3). If you did + * not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt + * + * @author Maarten Billemont + * @license http://www.gnu.org/licenses/lgpl-3.0.txt + */ + +// +// MPAppSettingsViewController.h +// MPAppSettingsViewController +// +// Created by lhunath on 2014-04-18. +// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. +// + +#import +#import "IASKAppSettingsViewController.h" + +@interface MPAppSettingsViewController : IASKAppSettingsViewController +@end diff --git a/MasterPassword/ObjC/iOS/MPAppSettingsViewController.m b/MasterPassword/ObjC/iOS/MPAppSettingsViewController.m new file mode 100644 index 00000000..37e48c40 --- /dev/null +++ b/MasterPassword/ObjC/iOS/MPAppSettingsViewController.m @@ -0,0 +1,63 @@ +/** + * Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) + * + * See the enclosed file LICENSE for license information (LGPLv3). If you did + * not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt + * + * @author Maarten Billemont + * @license http://www.gnu.org/licenses/lgpl-3.0.txt + */ + +// +// MPAppSettingsViewController.h +// MPAppSettingsViewController +// +// Created by lhunath on 2014-04-18. +// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. +// + +#import "MPAppSettingsViewController.h" +#import "UIColor+Expanded.h" + +@interface MPTableView:UITableView +@end + +@implementation MPTableView + +- (void)layoutSubviews { + + [super layoutSubviews]; +} + +- (void)setContentInset:(UIEdgeInsets)contentInset { + + [super setContentInset:contentInset]; +} + +@end + +@implementation MPAppSettingsViewController { +} + +- (void)viewWillAppear:(BOOL)animated { + + [super viewWillAppear:animated]; + + self.tableView.contentInset = UIEdgeInsetsMake( 64, 0, 49, 0 ); +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; + cell.backgroundColor = [UIColor clearColor]; + cell.textLabel.textColor = [UIColor whiteColor]; + + if (cell.selectionStyle != UITableViewCellSelectionStyleNone) { + cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.bounds]; + cell.selectedBackgroundView.backgroundColor = [UIColor colorWithRGBAHex:0x78DDFB33]; + } + + return cell; +} + +@end diff --git a/MasterPassword/ObjC/iOS/MPElementListSearchController.m b/MasterPassword/ObjC/iOS/MPElementListSearchController.m index 58b995fe..88b04629 100644 --- a/MasterPassword/ObjC/iOS/MPElementListSearchController.m +++ b/MasterPassword/ObjC/iOS/MPElementListSearchController.m @@ -105,7 +105,7 @@ UISearchBar *searchBar = self.searchDisplayController.searchBar; CGRect searchBarFrame = searchBar.frame; - [searchBar.superview enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) { + [searchBar.superview enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) { if ([subview isKindOfClass:[UIControl class]] && CGPointEqualToPoint( @@ -118,7 +118,7 @@ *stop = YES; } - } recurse:NO]; + } recurse:NO]; } - (BOOL)newSiteSectionNeeded { diff --git a/MasterPassword/ObjC/iOS/MPLogsViewController.m b/MasterPassword/ObjC/iOS/MPLogsViewController.m index 3a926662..8136b42e 100644 --- a/MasterPassword/ObjC/iOS/MPLogsViewController.m +++ b/MasterPassword/ObjC/iOS/MPLogsViewController.m @@ -28,12 +28,12 @@ [super viewDidLoad]; + self.view.backgroundColor = [UIColor clearColor]; + [[NSNotificationCenter defaultCenter] addObserverForName:NSUserDefaultsDidChangeNotification object:nil - queue:nil usingBlock: + queue:[NSOperationQueue mainQueue] usingBlock: ^(NSNotification *note) { - dispatch_async( dispatch_get_main_queue(), ^{ - self.levelControl.selectedSegmentIndex = [[MPiOSConfig get].traceMode boolValue]? 1: 0; - } ); + self.levelControl.selectedSegmentIndex = [[MPiOSConfig get].traceMode boolValue]? 1: 0; }]; } @@ -41,6 +41,8 @@ [super viewWillAppear:animated]; + self.logView.contentInset = UIEdgeInsetsMake( 64, 0, 93, 0 ); + [self refresh:nil]; self.levelControl.selectedSegmentIndex = [[MPiOSConfig get].traceMode boolValue]? 1: 0; diff --git a/MasterPassword/ObjC/iOS/MPPasswordsViewController.h b/MasterPassword/ObjC/iOS/MPPasswordsViewController.h index e183b6c2..7d964563 100644 --- a/MasterPassword/ObjC/iOS/MPPasswordsViewController.h +++ b/MasterPassword/ObjC/iOS/MPPasswordsViewController.h @@ -23,16 +23,21 @@ @property(strong, nonatomic) IBOutlet UIView *passwordSelectionContainer; @property(strong, nonatomic) IBOutlet UICollectionView *passwordCollectionView; -@property (strong, nonatomic) IBOutlet UISearchBar *passwordsSearchBar; -@property (strong, nonatomic) IBOutlet NSLayoutConstraint *passwordsToBottomConstraint; -@property (strong, nonatomic) IBOutlet NSLayoutConstraint *navigationBarToTopConstraint; -@property (strong, nonatomic) IBOutlet NSLayoutConstraint *navigationBarToPasswordsConstraint; +@property(strong, nonatomic) IBOutlet UISearchBar *passwordsSearchBar; +@property(strong, nonatomic) IBOutlet NSLayoutConstraint *passwordsToBottomConstraint; +@property(strong, nonatomic) IBOutlet NSLayoutConstraint *navigationBarToTopConstraint; +@property(strong, nonatomic) IBOutlet NSLayoutConstraint *navigationBarToPasswordsConstraint; +@property(strong, nonatomic) IBOutlet NSLayoutConstraint *popdownToTopConstraint; +@property(strong, nonatomic) IBOutlet NSLayoutConstraint *popdownToNavigationBarConstraint; +@property(strong, nonatomic) IBOutlet UIView *popdownView; +@property(strong, nonatomic) IBOutlet UIView *popdownContainer; +@property (strong, nonatomic) IBOutlet UIBarButtonItem *actionBarButton; @property(assign, nonatomic) BOOL active; @property(nonatomic, copy) NSString *originalQuery; - (void)setActive:(BOOL)active animated:(BOOL)animated completion:(void (^)(BOOL finished))completion; -- (IBAction)action:(id)sender; +- (IBAction)dismissPopdown:(id)sender; @end diff --git a/MasterPassword/ObjC/iOS/MPPasswordsViewController.m b/MasterPassword/ObjC/iOS/MPPasswordsViewController.m index 6200d11b..8bfa6708 100644 --- a/MasterPassword/ObjC/iOS/MPPasswordsViewController.m +++ b/MasterPassword/ObjC/iOS/MPPasswordsViewController.m @@ -23,6 +23,7 @@ #import "MPPasswordTypesCell.h" #import "MPPasswordSmallCell.h" #import "UIColor+Expanded.h" +#import "MPPopdownSegue.h" @interface MPPasswordsViewController() @@ -41,8 +42,11 @@ NSMutableDictionary *_fetchedUpdates; UIColor *_backgroundColor; UIColor *_darkenedBackgroundColor; + __weak UIViewController *_popdownVC; } +#pragma mark - Life + - (void)viewDidLoad { [super viewDidLoad]; @@ -52,6 +56,8 @@ self.view.backgroundColor = [UIColor clearColor]; [self.passwordCollectionView automaticallyAdjustInsetsForKeyboard]; + + [self.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; } - (void)viewWillAppear:(BOOL)animated { @@ -71,6 +77,12 @@ [self stopObservingStore]; } +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + + if ([segue.identifier isEqualToString:@"popdown"]) + _popdownVC = segue.destinationViewController; +} + #pragma mark - UICollectionViewDelegateFlowLayout - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout @@ -182,12 +194,12 @@ [element resolveContentUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) { if (![result length]) { - PearlMainQueue(^{ + PearlMainQueue( ^{ NSIndexPath *indexPath_ = [collectionView indexPathForCell:cell]; [collectionView selectItemAtIndexPath:indexPath_ animated:NO scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; [collectionView deselectItemAtIndexPath:indexPath_ animated:YES]; - }); + } ); return; } @@ -575,46 +587,12 @@ #pragma mark - Actions -- (IBAction)action:(id)sender { +- (IBAction)dismissPopdown:(id)sender { - [PearlSheet showSheetWithTitle:nil viewStyle:UIActionSheetStyleAutomatic - initSheet:nil tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) { - if (buttonIndex == [sheet cancelButtonIndex]) - return; - - switch (buttonIndex - [sheet firstOtherButtonIndex]) { - case 0: { - inf(@"Action: Guide"); - [[MPiOSAppDelegate get] showGuide]; - break; - } - case 1: { - inf(@"Action: Preferences"); - [self performSegueWithIdentifier:@"MP_UserProfile" sender:self]; - break; - } - case 2: { - inf(@"Action: Other Apps"); - [self performSegueWithIdentifier:@"MP_OtherApps" sender:self]; - break; - } - case 3: { - inf(@"Action: Feedback via Mail"); - [[MPiOSAppDelegate get] showFeedbackWithLogs:YES forVC:self]; - break; - } - default: { - wrn(@"Unsupported action: %ld", (long)(buttonIndex - [sheet firstOtherButtonIndex])); - break; - } - } - } - cancelTitle:[PearlStrings get].commonButtonCancel destructiveTitle:nil otherTitles: - @"Overview", - @"User Profile", - @"Other Apps", - @"Feedback", - nil]; + if (_popdownVC) + [[[MPPopdownSegue alloc] initWithIdentifier:@"unwind-popdown" source:_popdownVC destination:self] perform]; + else + self.popdownToTopConstraint.priority = UILayoutPriorityDefaultHigh; } @end diff --git a/MasterPassword/ObjC/iOS/MPPopdownSegue.h b/MasterPassword/ObjC/iOS/MPPopdownSegue.h new file mode 100644 index 00000000..1d1e4f28 --- /dev/null +++ b/MasterPassword/ObjC/iOS/MPPopdownSegue.h @@ -0,0 +1,22 @@ +/** + * Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) + * + * See the enclosed file LICENSE for license information (LGPLv3). If you did + * not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt + * + * @author Maarten Billemont + * @license http://www.gnu.org/licenses/lgpl-3.0.txt + */ + +// +// MPPopdownSegue.h +// MPPopdownSegue +// +// Created by lhunath on 2014-04-17. +// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. +// + +#import + +@interface MPPopdownSegue : UIStoryboardSegue +@end diff --git a/MasterPassword/ObjC/iOS/MPPopdownSegue.m b/MasterPassword/ObjC/iOS/MPPopdownSegue.m new file mode 100644 index 00000000..57d1f842 --- /dev/null +++ b/MasterPassword/ObjC/iOS/MPPopdownSegue.m @@ -0,0 +1,71 @@ +/** + * Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) + * + * See the enclosed file LICENSE for license information (LGPLv3). If you did + * not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt + * + * @author Maarten Billemont + * @license http://www.gnu.org/licenses/lgpl-3.0.txt + */ + +// +// MPPopdownSegue.h +// MPPopdownSegue +// +// Created by lhunath on 2014-04-17. +// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. +// + +#import "MPPopdownSegue.h" +#import "MPPasswordsViewController.h" + +@implementation MPPopdownSegue { +} + +- (void)perform { + + MPPasswordsViewController *passwordsVC; + UIViewController *popdownVC; + if ([self.sourceViewController isKindOfClass:[MPPasswordsViewController class]]) { + passwordsVC = self.sourceViewController; + popdownVC = self.destinationViewController; + UIView *popdownView = popdownVC.view; + popdownView.translatesAutoresizingMaskIntoConstraints = NO; + + [passwordsVC addChildViewController:popdownVC]; + [passwordsVC.popdownContainer addSubview:popdownView]; + [passwordsVC.popdownContainer addConstraintsWithVisualFormats:@[ @"H:|[popdownView]|", @"V:|[popdownView]|" ] options:0 + metrics:nil views:NSDictionaryOfVariableBindings(popdownView)]; + + [UIView animateWithDuration:0.3f animations:^{ + passwordsVC.popdownToTopConstraint.priority = 1; + passwordsVC.popdownToNavigationBarConstraint.priority = UILayoutPriorityDefaultHigh; + + [passwordsVC.popdownToNavigationBarConstraint apply]; + [passwordsVC.popdownToTopConstraint apply]; + } completion:^(BOOL finished) { + if (finished) + [popdownVC didMoveToParentViewController:passwordsVC]; + }]; + } + else if ([self.destinationViewController isKindOfClass:[MPPasswordsViewController class]]) { + popdownVC = self.sourceViewController; + passwordsVC = self.destinationViewController; + + [popdownVC willMoveToParentViewController:nil]; + [UIView animateWithDuration:0.3f delay:0 options:UIViewAnimationOptionOverrideInheritedDuration animations:^{ + passwordsVC.popdownToTopConstraint.priority = UILayoutPriorityDefaultHigh; + passwordsVC.popdownToNavigationBarConstraint.priority = 1; + + [passwordsVC.popdownToNavigationBarConstraint apply]; + [passwordsVC.popdownToTopConstraint apply]; + } completion:^(BOOL finished) { + if (finished) { + [popdownVC.view removeFromSuperview]; + [popdownVC removeFromParentViewController]; + } + }]; + } +} + +@end diff --git a/MasterPassword/ObjC/iOS/MPPreferencesViewController.h b/MasterPassword/ObjC/iOS/MPPreferencesViewController.h index 3af98c05..049078be 100644 --- a/MasterPassword/ObjC/iOS/MPPreferencesViewController.h +++ b/MasterPassword/ObjC/iOS/MPPreferencesViewController.h @@ -9,15 +9,16 @@ #import #import "MPTypeViewController.h" -@interface MPPreferencesViewController : UITableViewController +@interface MPPreferencesViewController : UITableViewController -@property(weak, nonatomic) IBOutlet UIScrollView *avatarsView; -@property(weak, nonatomic) IBOutlet UIButton *avatarTemplate; @property(weak, nonatomic) IBOutlet UISwitch *savePasswordSwitch; +@property(weak, nonatomic) IBOutlet UITableViewCell *feedbackCell; @property(weak, nonatomic) IBOutlet UITableViewCell *exportCell; -@property(weak, nonatomic) IBOutlet UITableViewCell *changeMPCell; -@property(weak, nonatomic) IBOutlet UILabel *defaultTypeLabel; +@property(weak, nonatomic) IBOutlet UIImageView *avatarImage; +@property(weak, nonatomic) IBOutlet UISegmentedControl *typeControl; -- (IBAction)didToggleSwitch:(UISwitch *)sender; +- (IBAction)previousAvatar:(id)sender; +- (IBAction)nextAvatar:(id)sender; +- (IBAction)valueChanged:(id)sender; @end diff --git a/MasterPassword/ObjC/iOS/MPPreferencesViewController.m b/MasterPassword/ObjC/iOS/MPPreferencesViewController.m index 2b52922c..33e5bbd2 100644 --- a/MasterPassword/ObjC/iOS/MPPreferencesViewController.m +++ b/MasterPassword/ObjC/iOS/MPPreferencesViewController.m @@ -6,12 +6,11 @@ // Copyright (c) 2012 Lyndir. All rights reserved. // -#import - #import "MPPreferencesViewController.h" #import "MPiOSAppDelegate.h" #import "MPAppDelegate_Key.h" #import "MPAppDelegate_Store.h" +#import "UIColor+Expanded.h" @interface MPPreferencesViewController() @@ -21,158 +20,135 @@ - (void)viewDidLoad { - self.avatarTemplate.hidden = YES; - - for (NSUInteger a = 0; a < MPAvatarCount; ++a) { - UIButton *avatar = [self.avatarTemplate clone]; - 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-%ld", (long)a )] - forState:UIControlStateNormal]; - [avatar setSelectionInSuperviewCandidate:YES isClearable:NO]; - - 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]; - [avatar onSelect:^(BOOL selected) { - if (selected) { - [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) { - [[MPiOSAppDelegate get] activeUserInContext:moc].avatar = (unsigned)avatar.tag; - [moc saveToStore]; - }]; - } - } options:0]; - avatar.selected = (a == [[MPiOSAppDelegate get] activeUserForMainThread].avatar); - } - [super viewDidLoad]; + + self.view.backgroundColor = [UIColor clearColor]; } - (void)viewWillAppear:(BOOL)animated { inf(@"Preferences will appear"); - [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]; + [super viewWillAppear:animated]; MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForMainThread]; + self.typeControl.selectedSegmentIndex = [self segmentIndexForType:activeUser.defaultType]; + self.avatarImage.image = [UIImage imageNamed:strf( @"avatar-%ld", (long)activeUser.avatar )]; self.savePasswordSwitch.on = activeUser.saveKey; - self.defaultTypeLabel.text = [[MPiOSAppDelegate get].key.algorithm shortNameOfType:activeUser.defaultType]; - [super viewWillAppear:animated]; -} - -- (void)viewDidAppear:(BOOL)animated { - -#ifdef LOCALYTICS - [[LocalyticsSession sharedLocalyticsSession] tagScreen:@"Preferences"]; -#endif - - [super viewDidAppear:animated]; -} - -- (void)viewWillDisappear:(BOOL)animated { - - inf(@"Preferences will disappear"); - [super viewWillDisappear:animated]; -} - -- (BOOL)canBecomeFirstResponder { - - return YES; -} - -- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event { - - if (motion == UIEventSubtypeMotionShake) { - MPCheckpoint( MPCheckpointLogs, @{ - @"trace" : [MPiOSConfig get].traceMode - } ); - [self performSegueWithIdentifier:@"MP_Logs" sender:self]; - } -} - -- (BOOL)shouldAutorotate { - - return NO; -} - -- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { - - return UIInterfaceOrientationPortrait; -} - -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - - if ([[segue identifier] isEqualToString:@"MP_ChooseType"]) - ((MPTypeViewController *)[segue destinationViewController]).delegate = self; + self.tableView.contentInset = UIEdgeInsetsMake( 64, 0, 49, 0 ); } #pragma mark - UITableViewDelegate +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; + if (cell.selectionStyle != UITableViewCellSelectionStyleNone) { + cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.bounds]; + cell.selectedBackgroundView.backgroundColor = [UIColor colorWithRGBAHex:0x78DDFB33]; + } + + return cell; +} + - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath]; if (cell == self.exportCell) [[MPiOSAppDelegate get] export]; - else if (cell == self.changeMPCell) { - [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) { - MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc]; - [[MPiOSAppDelegate get] changeMasterPasswordFor:activeUser saveInContext:moc didResetBlock:nil]; - }]; - } - [tableView deselectRowAtIndexPath:indexPath animated:YES]; } -#pragma mark - MPTypeDelegate - -- (void)didSelectType:(MPElementType)type { - - self.defaultTypeLabel.text = [[MPiOSAppDelegate get].key.algorithm shortNameOfType:type]; - - [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { - MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:context]; - activeUser.defaultType = type; - [context saveToStore]; - }]; -} - -- (MPElementType)selectedType { - - return [[MPiOSAppDelegate get] activeUserForMainThread].defaultType; -} - #pragma mark - IBActions -- (IBAction)didToggleSwitch:(UISwitch *)sender { +- (IBAction)valueChanged:(id)sender { if (sender == self.savePasswordSwitch) - [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) { - MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc]; - if ((activeUser.saveKey = sender.on)) + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { + MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:context]; + if ((activeUser.saveKey = self.savePasswordSwitch.on)) [[MPiOSAppDelegate get] storeSavedKeyFor:activeUser]; else [[MPiOSAppDelegate get] forgetSavedKeyFor:activeUser]; - [moc saveToStore]; + [context saveToStore]; + }]; + + if (sender == self.typeControl) + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { + [[MPiOSAppDelegate get] activeUserInContext:context].defaultType = [self typeForSelectedSegment]; + [context saveToStore]; }]; } +- (IBAction)previousAvatar:(id)sender { + + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { + MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:context]; + activeUser.avatar = (activeUser.avatar - 1 + MPAvatarCount) % MPAvatarCount; + [context saveToStore]; + + long avatar = activeUser.avatar; + PearlMainQueue( ^{ + self.avatarImage.image = [UIImage imageNamed:strf( @"avatar-%ld", avatar )]; + } ); + }]; +} + +- (IBAction)nextAvatar:(id)sender { + + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { + MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:context]; + activeUser.avatar = (activeUser.avatar + 1 + MPAvatarCount) % MPAvatarCount; + [context saveToStore]; + + long avatar = activeUser.avatar; + PearlMainQueue( ^{ + self.avatarImage.image = [UIImage imageNamed:strf( @"avatar-%ld", avatar )]; + } ); + }]; +} + +#pragma mark - Private + +- (enum MPElementType)typeForSelectedSegment { + + switch (self.typeControl.selectedSegmentIndex) { + case 0: + return MPElementTypeGeneratedMaximum; + case 1: + return MPElementTypeGeneratedLong; + case 2: + return MPElementTypeGeneratedMedium; + case 3: + return MPElementTypeGeneratedBasic; + case 4: + return MPElementTypeGeneratedShort; + case 5: + return MPElementTypeGeneratedPIN; + default: + Throw(@"Unsupported type index: %ld", (long)self.typeControl.selectedSegmentIndex); + } +} + +- (NSInteger)segmentIndexForType:(MPElementType)type { + + switch (type) { + case MPElementTypeGeneratedMaximum: + return 0; + case MPElementTypeGeneratedLong: + return 1; + case MPElementTypeGeneratedMedium: + return 2; + case MPElementTypeGeneratedBasic: + return 3; + case MPElementTypeGeneratedShort: + return 4; + case MPElementTypeGeneratedPIN: + return 5; + default: + Throw(@"Unsupported type index: %ld", (long)self.typeControl.selectedSegmentIndex); + } +} + @end diff --git a/MasterPassword/ObjC/iOS/MPPreferencesViewControllerOld.h b/MasterPassword/ObjC/iOS/MPPreferencesViewControllerOld.h new file mode 100644 index 00000000..3561068b --- /dev/null +++ b/MasterPassword/ObjC/iOS/MPPreferencesViewControllerOld.h @@ -0,0 +1,23 @@ +// +// MPPreferencesViewController.h +// MasterPassword-iOS +// +// Created by Maarten Billemont on 04/06/12. +// Copyright (c) 2012 Lyndir. All rights reserved. +// + +#import +#import "MPTypeViewController.h" + +@interface MPPreferencesViewControllerOld : UITableViewController + +@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; +@property(weak, nonatomic) IBOutlet UILabel *defaultTypeLabel; + +- (IBAction)didToggleSwitch:(UISwitch *)sender; + +@end diff --git a/MasterPassword/ObjC/iOS/MPPreferencesViewControllerOld.m b/MasterPassword/ObjC/iOS/MPPreferencesViewControllerOld.m new file mode 100644 index 00000000..121658dd --- /dev/null +++ b/MasterPassword/ObjC/iOS/MPPreferencesViewControllerOld.m @@ -0,0 +1,178 @@ +// +// MPPreferencesViewController.m +// MasterPassword-iOS +// +// Created by Maarten Billemont on 04/06/12. +// Copyright (c) 2012 Lyndir. All rights reserved. +// + +#import + +#import "MPPreferencesViewControllerOld.h" +#import "MPiOSAppDelegate.h" +#import "MPAppDelegate_Key.h" +#import "MPAppDelegate_Store.h" + +@interface MPPreferencesViewControllerOld() + +@end + +@implementation MPPreferencesViewControllerOld + +- (void)viewDidLoad { + + self.avatarTemplate.hidden = YES; + + for (NSUInteger a = 0; a < MPAvatarCount; ++a) { + UIButton *avatar = [self.avatarTemplate clone]; + 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-%ld", (long)a )] + forState:UIControlStateNormal]; + [avatar setSelectionInSuperviewCandidate:YES isClearable:NO]; + + 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]; + [avatar onSelect:^(BOOL selected) { + if (selected) { + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) { + [[MPiOSAppDelegate get] activeUserInContext:moc].avatar = (unsigned)avatar.tag; + [moc saveToStore]; + }]; + } + } options:0]; + avatar.selected = (a == [[MPiOSAppDelegate get] activeUserForMainThread].avatar); + } + + [super viewDidLoad]; +} + +- (void)viewWillAppear:(BOOL)animated { + + inf(@"Preferences will appear"); + [self.avatarsView autoSizeContent]; + [self.avatarsView enumerateViews:^(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]; + + MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForMainThread]; + self.savePasswordSwitch.on = activeUser.saveKey; + self.defaultTypeLabel.text = [[MPiOSAppDelegate get].key.algorithm shortNameOfType:activeUser.defaultType]; + + [super viewWillAppear:animated]; +} + +- (void)viewDidAppear:(BOOL)animated { + +#ifdef LOCALYTICS + [[LocalyticsSession sharedLocalyticsSession] tagScreen:@"Preferences"]; +#endif + + [super viewDidAppear:animated]; +} + +- (void)viewWillDisappear:(BOOL)animated { + + inf(@"Preferences will disappear"); + [super viewWillDisappear:animated]; +} + +- (BOOL)canBecomeFirstResponder { + + return YES; +} + +- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event { + + if (motion == UIEventSubtypeMotionShake) { + MPCheckpoint( MPCheckpointLogs, @{ + @"trace" : [MPiOSConfig get].traceMode + } ); + [self performSegueWithIdentifier:@"MP_Logs" sender:self]; + } +} + +- (BOOL)shouldAutorotate { + + return NO; +} + +- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { + + return UIInterfaceOrientationPortrait; +} + +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + + if ([[segue identifier] isEqualToString:@"MP_ChooseType"]) + ((MPTypeViewController *)[segue destinationViewController]).delegate = self; +} + +#pragma mark - UITableViewDelegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + + UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath]; + if (cell == self.exportCell) + [[MPiOSAppDelegate get] export]; + + else if (cell == self.changeMPCell) { + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) { + MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc]; + [[MPiOSAppDelegate get] changeMasterPasswordFor:activeUser saveInContext:moc didResetBlock:nil]; + }]; + } + + [tableView deselectRowAtIndexPath:indexPath animated:YES]; +} + +#pragma mark - MPTypeDelegate + +- (void)didSelectType:(MPElementType)type { + + self.defaultTypeLabel.text = [[MPiOSAppDelegate get].key.algorithm shortNameOfType:type]; + + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { + MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:context]; + activeUser.defaultType = type; + [context saveToStore]; + }]; +} + +- (MPElementType)selectedType { + + return [[MPiOSAppDelegate get] activeUserForMainThread].defaultType; +} + +#pragma mark - IBActions + +- (IBAction)didToggleSwitch:(UISwitch *)sender { + + if (sender == self.savePasswordSwitch) + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) { + MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc]; + if ((activeUser.saveKey = sender.on)) + [[MPiOSAppDelegate get] storeSavedKeyFor:activeUser]; + else + [[MPiOSAppDelegate get] forgetSavedKeyFor:activeUser]; + [moc saveToStore]; + }]; +} + +@end diff --git a/MasterPassword/ObjC/iOS/MPUnlockViewController.m b/MasterPassword/ObjC/iOS/MPUnlockViewController.m index b5183caa..d939c5db 100644 --- a/MasterPassword/ObjC/iOS/MPUnlockViewController.m +++ b/MasterPassword/ObjC/iOS/MPUnlockViewController.m @@ -162,11 +162,11 @@ self.wordList = wordListLines; self.wordWall.alpha = 0; - [self.wordWall enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) { + [self.wordWall enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) { UILabel *wordLabel = (UILabel *)subview; [self initializeWordLabel:wordLabel]; - } recurse:NO]; + } recurse:NO]; [[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock: @@ -585,7 +585,7 @@ targetedUser = [self userForAvatar:targetedAvatar inContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]]; } - [self.avatarsView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) { + [self.avatarsView enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) { if (![[self.avatarToUserOID allKeys] containsObject:[NSValue valueWithNonretainedObject:subview]]) // This subview is not one of the user avatars. return; @@ -597,7 +597,7 @@ avatar.alpha = isTargeted? 1: [self selectedUserForThread]? 0.1F: 0.4F; [self updateAvatarShadowColor:avatar isTargeted:isTargeted]; - } recurse:NO]; + } recurse:NO]; if (allowScroll) { CGPoint targetContentOffset = CGPointMake( @@ -617,22 +617,22 @@ - (void)beginWordWallAnimation { - [self.wordWall enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) { + [self.wordWall enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) { UILabel *wordLabel = (UILabel *)subview; if (wordLabel.frame.origin.x < -self.wordWall.frame.size.width / 3) { wordLabel.frame = CGRectSetX( wordLabel.frame, wordLabel.frame.origin.x + self.wordWall.frame.size.width ); [self initializeWordLabel:wordLabel]; } - } recurse:NO]; + } recurse:NO]; if (self.wordWallAnimating) [UIView animateWithDuration:15 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ - [self.wordWall enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) { + [self.wordWall enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) { UILabel *wordLabel = (UILabel *)subview; wordLabel.frame = CGRectSetX( wordLabel.frame, wordLabel.frame.origin.x - self.wordWall.frame.size.width / 3 ); - } recurse:NO]; + } recurse:NO]; } completion:^(BOOL finished) { if (finished) [self beginWordWallAnimation]; diff --git a/MasterPassword/ObjC/iOS/MainStoryboard_iPhone.storyboard b/MasterPassword/ObjC/iOS/MainStoryboard_iPhone.storyboard index 19122c75..c35b254c 100644 --- a/MasterPassword/ObjC/iOS/MainStoryboard_iPhone.storyboard +++ b/MasterPassword/ObjC/iOS/MainStoryboard_iPhone.storyboard @@ -1,5 +1,5 @@ - + @@ -2266,7 +2266,7 @@ Only site names and custom passwords are sent to iCloud. Passwords are encrypte - + @@ -2323,7 +2323,7 @@ Only site names and custom passwords are sent to iCloud. Passwords are encrypte diff --git a/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj b/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj index 3a8f7038..f15c5ab0 100644 --- a/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj +++ b/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 93D3954FCE045A3CC7E804B7 /* MPUsersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399E571F61E50A9BF8FAF /* MPUsersViewController.m */; }; 93D3957237D303DE2D38C267 /* MPAvatarCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39B381350802A194BF332 /* MPAvatarCell.m */; }; 93D395F08A087F8A24689347 /* NSArray+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */; }; + 93D39673DDC085BE72C34D7C /* MPPopdownSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */; }; 93D396AA30690B256F30378A /* PearlNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3956915634581E737B38C /* PearlNavigationController.m */; }; 93D396BA1C74C4A06FD86437 /* PearlOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D3942A356B639724157982 /* PearlOverlay.h */; }; 93D397952F5635C793C24DF1 /* NSError+PearlFullDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */; }; @@ -34,9 +35,11 @@ 93D399BBC0A7EC746CB1B19B /* MPLogsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D391943675426839501BB8 /* MPLogsViewController.h */; }; 93D39A5FF670957C0AF8298D /* MPPasswordCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39DEA995041A13DC9CAF7 /* MPPasswordCell.m */; }; 93D39A8EA1C49CE43B63F47B /* PearlUICollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D8A953779B35403AF6E /* PearlUICollectionView.m */; }; + 93D39B21156EC9A0B4C2BC83 /* MPPreferencesViewControllerOld.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D390381D3D3AE241B5D341 /* MPPreferencesViewControllerOld.m */; }; 93D39B76DD5AB108BA8928E8 /* UIScrollView+PearlAdjustInsets.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39DE2CB351D4E3789462B /* UIScrollView+PearlAdjustInsets.h */; }; 93D39B842AB9A5D072810D76 /* NSError+PearlFullDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */; }; 93D39B8F90F58A5D158DDBA3 /* MPPasswordsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */; }; + 93D39BA1EA3CAAC8A220B4A6 /* MPAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.m */; }; 93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; }; 93D39C8AD8EAB747856B3A8C /* LLModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3923B42DA2DA18F287092 /* LLModel.m */; }; 93D39CB5E2EC1078E898F46A /* MPPasswordLargeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3937863061C3916AF7AD2 /* MPPasswordLargeCell.m */; }; @@ -48,6 +51,8 @@ 93D39F8A9254177891F38705 /* MPSetupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A28369954D147E239BA /* MPSetupViewController.m */; }; 93D39FA97F4C3F69A75D5A03 /* MPPasswordLargeGeneratedCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3993422E207BF0B21D089 /* MPPasswordLargeGeneratedCell.m */; }; DA04E33E14B1E70400ECA4F3 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA04E33D14B1E70400ECA4F3 /* MobileCoreServices.framework */; }; + DA071BF3190187FE00179766 /* empty@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA071BF1190187FE00179766 /* empty@2x.png */; }; + DA071BF4190187FE00179766 /* empty.png in Resources */ = {isa = PBXBuildFile; fileRef = DA071BF2190187FE00179766 /* empty.png */; }; DA095E75172F4CD8001C948B /* MPLogsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3979190DACEBD1F6AE9F4 /* MPLogsViewController.m */; }; DA2CA4DD18D28859007798F8 /* NSArray+Pearl.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2CA4D918D28859007798F8 /* NSArray+Pearl.m */; }; DA2CA4DE18D28859007798F8 /* NSArray+Pearl.h in Headers */ = {isa = PBXBuildFile; fileRef = DA2CA4DA18D28859007798F8 /* NSArray+Pearl.h */; }; @@ -67,6 +72,8 @@ DA38D6A318CCB5BF009AEB3E /* Storyboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DA38D6A218CCB5BF009AEB3E /* Storyboard.storyboard */; }; DA4425CC1557BED40052177D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; }; DA44260A1557D9E40052177D /* libUbiquityStoreManager.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA4425CB1557BED40052177D /* libUbiquityStoreManager.a */; }; + DA4522441902355C008F650A /* icon_book.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD370C1711E29500CF925C /* icon_book.png */; }; + DA4522451902355C008F650A /* icon_book@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD370D1711E29500CF925C /* icon_book@2x.png */; }; DA4DA1D91564471A00F6F596 /* libjrswizzle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC6326C148680650075AEA5 /* libjrswizzle.a */; }; DA4DA1DA1564471F00F6F596 /* libuicolor-utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC6325D1486805C0075AEA5 /* libuicolor-utilities.a */; }; DA5A09DF171A70E4005284AB /* play.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5A09DD171A70E4005284AB /* play.png */; }; @@ -517,6 +524,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 93D390381D3D3AE241B5D341 /* MPPreferencesViewControllerOld.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPreferencesViewControllerOld.m; sourceTree = ""; }; 93D390519405B76CC6A57C4F /* MPCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCell.h; sourceTree = ""; }; 93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Indexing.m"; sourceTree = ""; }; 93D39097C0AAE62C1C321BFC /* MPPasswordTypesCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordTypesCell.m; sourceTree = ""; }; @@ -525,9 +533,11 @@ 93D390FB3110DCCE68E600DC /* UIScrollView+PearlAdjustInsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+PearlAdjustInsets.m"; sourceTree = ""; }; 93D391243F64A77798B4D6A4 /* MPPasswordTypesCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordTypesCell.h; sourceTree = ""; }; 93D3914D7597F9A28DB9D85E /* MPPasswordsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordsViewController.h; sourceTree = ""; }; + 93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppSettingsViewController.m; sourceTree = ""; }; 93D391943675426839501BB8 /* MPLogsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLogsViewController.h; sourceTree = ""; }; 93D3923B42DA2DA18F287092 /* LLModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLModel.m; sourceTree = ""; }; 93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordsViewController.m; sourceTree = ""; }; + 93D392876BE5C011DE73B43F /* MPPopdownSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPopdownSegue.h; sourceTree = ""; }; 93D3932D6C25F2C2D929F8A1 /* MPPasswordElementCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordElementCell.h; sourceTree = ""; }; 93D393310223DDB35218467A /* MPCombinedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCombinedViewController.m; sourceTree = ""; }; 93D39342E5F115EFCC90E976 /* MPPasswordElementCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordElementCell.m; sourceTree = ""; }; @@ -553,6 +563,7 @@ 93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+PearlFullDescription.h"; sourceTree = ""; }; 93D398EBF99FF0C245FD561E /* NSManagedObject+Pearl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+Pearl.m"; sourceTree = ""; }; 93D3993422E207BF0B21D089 /* MPPasswordLargeGeneratedCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordLargeGeneratedCell.m; sourceTree = ""; }; + 93D39961CD6A43648CC0B0DB /* MPPreferencesViewControllerOld.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPreferencesViewControllerOld.h; sourceTree = ""; }; 93D39975CE5AEC99E3F086C7 /* MPPasswordCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordCell.h; sourceTree = ""; }; 93D399E571F61E50A9BF8FAF /* MPUsersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPUsersViewController.m; sourceTree = ""; }; 93D39A1DDFA09AE2E14D26DC /* UIResponder+PearlFirstResponder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIResponder+PearlFirstResponder.m"; sourceTree = ""; }; @@ -561,12 +572,14 @@ 93D39A41340CF778E00D0E6D /* MPEmergencySegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEmergencySegue.h; sourceTree = ""; }; 93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+Indexing.m"; sourceTree = ""; }; 93D39ACBA9F4878B6A1CC33B /* MPEmergencyViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPEmergencyViewController.m; sourceTree = ""; }; + 93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPopdownSegue.m; sourceTree = ""; }; 93D39B1D8177A86C5B9EDDE3 /* PearlUICollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlUICollectionView.h; sourceTree = ""; }; 93D39B381350802A194BF332 /* MPAvatarCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAvatarCell.m; sourceTree = ""; }; 93D39BA6C5CB452973918B7D /* LLButtonView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLButtonView.h; sourceTree = ""; }; 93D39BAA71DE51B4D8A1286C /* MPCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCell.m; sourceTree = ""; }; 93D39BF6BCBDFFE844E7D34C /* LLButtonView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLButtonView.m; sourceTree = ""; }; 93D39C44361BE57AF0B3071F /* MPPasswordsSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordsSegue.h; sourceTree = ""; }; + 93D39C86E984EC65DA5ACB1D /* MPAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppSettingsViewController.h; sourceTree = ""; }; 93D39C8E26B06F01566785B7 /* LLToggleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLToggleViewController.m; sourceTree = ""; }; 93D39CDD434AFD6E1B0DA359 /* MPEmergencyViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEmergencyViewController.h; sourceTree = ""; }; 93D39CE1138FDA4D3D1B847A /* MPPasswordLargeGeneratedCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordLargeGeneratedCell.h; sourceTree = ""; }; @@ -580,6 +593,8 @@ 93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlEMail.h; sourceTree = ""; }; 93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+PearlFullDescription.m"; sourceTree = ""; }; DA04E33D14B1E70400ECA4F3 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; + DA071BF1190187FE00179766 /* empty@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "empty@2x.png"; sourceTree = ""; }; + DA071BF2190187FE00179766 /* empty.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = empty.png; sourceTree = ""; }; DA2CA4D918D28859007798F8 /* NSArray+Pearl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Pearl.m"; sourceTree = ""; }; DA2CA4DA18D28859007798F8 /* NSArray+Pearl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Pearl.h"; sourceTree = ""; }; DA2CA4DB18D28859007798F8 /* NSTimer+PearlBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSTimer+PearlBlock.m"; sourceTree = ""; }; @@ -1720,6 +1735,8 @@ 93D39DEA995041A13DC9CAF7 /* MPPasswordCell.m */, 93D39ACBA9F4878B6A1CC33B /* MPEmergencyViewController.m */, 93D39CDD434AFD6E1B0DA359 /* MPEmergencyViewController.h */, + 93D390381D3D3AE241B5D341 /* MPPreferencesViewControllerOld.m */, + 93D39961CD6A43648CC0B0DB /* MPPreferencesViewControllerOld.h */, ); sourceTree = ""; }; @@ -1787,6 +1804,8 @@ DABD360D1711E29400CF925C /* Media */ = { isa = PBXGroup; children = ( + DA071BF1190187FE00179766 /* empty@2x.png */, + DA071BF2190187FE00179766 /* empty.png */, DADBB55918DB0CFC00D099FE /* keyboard-dark@2x.png */, DA945C8617E3F3FD0053236B /* Images.xcassets */, DA5E5C3C1723681B003798D8 /* Square-bottom.png */, @@ -2596,6 +2615,10 @@ 93D39A41340CF778E00D0E6D /* MPEmergencySegue.h */, 93D39E7A12CC352B2825AA66 /* MPPasswordsSegue.m */, 93D39C44361BE57AF0B3071F /* MPPasswordsSegue.h */, + 93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */, + 93D392876BE5C011DE73B43F /* MPPopdownSegue.h */, + 93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.m */, + 93D39C86E984EC65DA5ACB1D /* MPAppSettingsViewController.h */, ); path = iOS; sourceTree = ""; @@ -3661,10 +3684,12 @@ DABD39021711E29700CF925C /* ui_panel_container@2x.png in Resources */, DABD39031711E29700CF925C /* ui_panel_display.png in Resources */, DABD39041711E29700CF925C /* ui_panel_display@2x.png in Resources */, + DA071BF4190187FE00179766 /* empty.png in Resources */, DABD391D1711E29700CF925C /* ui_spinner.png in Resources */, DABD391E1711E29700CF925C /* ui_spinner@2x.png in Resources */, DA69540617D975D900BF294E /* icon_gears.png in Resources */, DA67460D18DE7F0C00DFE240 /* Exo2.0-Thin.otf in Resources */, + DA4522451902355C008F650A /* icon_book@2x.png in Resources */, DABD39271711E29700CF925C /* ui_textfield.png in Resources */, DABD39281711E29700CF925C /* ui_textfield@2x.png in Resources */, DABD39291711E29700CF925C /* ui_toolbar_container.png in Resources */, @@ -3694,6 +3719,7 @@ DABD394A1711E29700CF925C /* avatar-18.png in Resources */, DABD394B1711E29700CF925C /* avatar-18@2x.png in Resources */, DABD394C1711E29700CF925C /* avatar-1@2x.png in Resources */, + DA071BF3190187FE00179766 /* empty@2x.png in Resources */, DA67460E18DE7F0C00DFE240 /* Exo2.0-Regular.otf in Resources */, DABD394D1711E29700CF925C /* avatar-2.png in Resources */, DABD394E1711E29700CF925C /* avatar-2@2x.png in Resources */, @@ -3753,6 +3779,7 @@ DABD3B571711E29800CF925C /* tip_basic_black_bottom_right@2x.png in Resources */, DABD3B581711E29800CF925C /* tip_basic_black_top.png in Resources */, DABD3B591711E29800CF925C /* tip_basic_black_top@2x.png in Resources */, + DA4522441902355C008F650A /* icon_book.png in Resources */, DABD3B5A1711E29800CF925C /* tip_basic_black_top_right.png in Resources */, DABD3B5B1711E29800CF925C /* tip_basic_black_top_right@2x.png in Resources */, DABD3B881711E29800CF925C /* book.png in Resources */, @@ -3907,6 +3934,9 @@ 93D398ECD7D1A0DEDDADF516 /* MPEmergencyViewController.m in Sources */, 93D391ED37C9F687FA51EAA1 /* MPEmergencySegue.m in Sources */, 93D394B5036C882B33C71872 /* MPPasswordsSegue.m in Sources */, + 93D39673DDC085BE72C34D7C /* MPPopdownSegue.m in Sources */, + 93D39B21156EC9A0B4C2BC83 /* MPPreferencesViewControllerOld.m in Sources */, + 93D39BA1EA3CAAC8A220B4A6 /* MPAppSettingsViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MasterPassword/ObjC/iOS/Storyboard.storyboard b/MasterPassword/ObjC/iOS/Storyboard.storyboard index fc59aed7..2ccf8dfb 100644 --- a/MasterPassword/ObjC/iOS/Storyboard.storyboard +++ b/MasterPassword/ObjC/iOS/Storyboard.storyboard @@ -19,24 +19,29 @@ - - + + - - + + + + + + + - - + + @@ -131,23 +136,21 @@ - - - + + -