diff --git a/MasterPassword/ObjC/MPAlgorithm.m b/MasterPassword/ObjC/MPAlgorithm.m index 7b92652d..39e9ad90 100644 --- a/MasterPassword/ObjC/MPAlgorithm.m +++ b/MasterPassword/ObjC/MPAlgorithm.m @@ -1,12 +1,12 @@ /** - * 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 - */ +* 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 +*/ // // MPAlgorithm @@ -24,7 +24,7 @@ id MPAlgorithmForVersion(NSUInteger version) { versionToAlgorithm = [NSMutableDictionary dictionary]; id algorithm = versionToAlgorithm[@(version)]; - if (!algorithm) if ((algorithm = [NSClassFromString( strf( @"MPAlgorithmV%lu", (unsigned long)version ) ) new])) + if (!algorithm && (algorithm = (id)[NSClassFromString( strf( @"MPAlgorithmV%lu", (unsigned long)version ) ) new])) versionToAlgorithm[@(version)] = algorithm; return algorithm; @@ -33,7 +33,7 @@ id MPAlgorithmForVersion(NSUInteger version) { id MPAlgorithmDefaultForBundleVersion(NSString *bundleVersion) { if (PearlCFBundleVersionCompare( bundleVersion, @"1.3" ) == NSOrderedAscending) - // Pre-1.3 + // Pre-1.3 return MPAlgorithmForVersion( 0 ); return MPAlgorithmDefault; diff --git a/MasterPassword/ObjC/MPAppDelegate_InApp.h b/MasterPassword/ObjC/MPAppDelegate_InApp.h index 14340372..e702484c 100644 --- a/MasterPassword/ObjC/MPAppDelegate_InApp.h +++ b/MasterPassword/ObjC/MPAppDelegate_InApp.h @@ -6,15 +6,21 @@ // Copyright (c) 2011 Lyndir. All rights reserved. // -#import #import "MPAppDelegate_Shared.h" -@interface MPAppDelegate_Shared(InApp) +#define MPProductGenerateLogins @"com.lyndir.masterpassword.products.generatelogins" +#define MPProductGenerateAnswers @"com.lyndir.masterpassword.products.generateanswers" + +@interface MPAppDelegate_Shared(InApp) @property(nonatomic, strong) NSArray /* SKProduct */ *products; @property(nonatomic, strong) NSArray /* SKPaymentTransaction */ *paymentTransactions; - (void)updateProducts; +- (BOOL)canMakePayments; - (BOOL)isPurchased:(NSString *)productIdentifier; +- (void)restoreCompletedTransactions; +- (void)purchaseProductWithIdentifier:(NSString *)productIdentifier; + @end diff --git a/MasterPassword/ObjC/MPAppDelegate_InApp.m b/MasterPassword/ObjC/MPAppDelegate_InApp.m index d5782c1a..43d34198 100644 --- a/MasterPassword/ObjC/MPAppDelegate_InApp.m +++ b/MasterPassword/ObjC/MPAppDelegate_InApp.m @@ -7,6 +7,10 @@ // #import "MPAppDelegate_InApp.h" +#import + +@interface MPAppDelegate_Shared(InApp_Private) +@end @implementation MPAppDelegate_Shared(InApp) @@ -15,22 +19,46 @@ PearlAssociatedObjectProperty( NSArray*, PaymentTransactions, paymentTransaction - (void)updateProducts { - static dispatch_once_t once = 0; - dispatch_once( &once, ^{ - [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; - } ); - SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers: [[NSSet alloc] initWithObjects:MPProductGenerateLogins, MPProductGenerateAnswers, nil]]; productsRequest.delegate = self; [productsRequest start]; } +- (SKPaymentQueue *)paymentQueue { + + static dispatch_once_t once = 0; + dispatch_once( &once, ^{ + [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; + } ); + + return [SKPaymentQueue defaultQueue]; +} + +- (BOOL)canMakePayments { + + return [SKPaymentQueue canMakePayments]; +} + - (BOOL)isPurchased:(NSString *)productIdentifier { return YES; //[[NSUserDefaults standardUserDefaults] objectForKey:productIdentifier] != nil; } +- (void)restoreCompletedTransactions { + + [[self paymentQueue] restoreCompletedTransactions]; +} + +- (void)purchaseProductWithIdentifier:(NSString *)productIdentifier { + + for (SKProduct *product in self.products) + if ([product.productIdentifier isEqualToString:productIdentifier]) { + [[self paymentQueue] addPayment:[SKPayment paymentWithProduct:product]]; + return; + } +} + #pragma mark - SKProductsRequestDelegate - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { diff --git a/MasterPassword/ObjC/MPAppDelegate_Shared.m b/MasterPassword/ObjC/MPAppDelegate_Shared.m index 463aeaf2..1d72f074 100644 --- a/MasterPassword/ObjC/MPAppDelegate_Shared.m +++ b/MasterPassword/ObjC/MPAppDelegate_Shared.m @@ -6,6 +6,7 @@ // Copyright (c) 2011 Lyndir. All rights reserved. // +#import #import "MPAppDelegate_Shared.h" #import "MPAppDelegate_Store.h" #import "MPAppDelegate_Key.h" diff --git a/MasterPassword/ObjC/MPTypes.h b/MasterPassword/ObjC/MPTypes.h index 3a910833..2b28a159 100644 --- a/MasterPassword/ObjC/MPTypes.h +++ b/MasterPassword/ObjC/MPTypes.h @@ -87,9 +87,6 @@ typedef NS_ENUM(NSUInteger, MPSiteType) { #define MPSitesImportedNotificationUserKey @"MPSitesImportedNotificationUserKey" #define MPInconsistenciesFixResultUserKey @"MPInconsistenciesFixResultUserKey" -#define MPProductGenerateLogins @"com.lyndir.masterpassword.products.generatelogins" -#define MPProductGenerateAnswers @"com.lyndir.masterpassword.products.generateanswers" - static void MPCheckpoint(NSString *checkpoint, NSDictionary *attributes) { inf(@"%@: %@", checkpoint, attributes); diff --git a/MasterPassword/ObjC/iOS/MPAnswersViewController.m b/MasterPassword/ObjC/iOS/MPAnswersViewController.m index 7c5a52d1..a161f917 100644 --- a/MasterPassword/ObjC/iOS/MPAnswersViewController.m +++ b/MasterPassword/ObjC/iOS/MPAnswersViewController.m @@ -32,10 +32,14 @@ self.tableView.tableHeaderView = [UIView new]; self.tableView.tableFooterView = [UIView new]; - self.tableView.layer.shadowOpacity = 1; self.view.backgroundColor = [UIColor clearColor]; } +- (UIStatusBarStyle)preferredStatusBarStyle { + + return UIStatusBarStyleLightContent; +} + #pragma mark - State - (void)setSite:(MPSiteEntity *)site { @@ -203,6 +207,7 @@ - (void)setSite:(MPSiteEntity *)site { + self.titleLabel.text = strl( @"Answer for %@:", site.name ); self.answerField.text = @"..."; [site.algorithm resolveAnswerForSite:site usingKey:[MPiOSAppDelegate get].key result:^(NSString *result) { PearlMainQueue( ^{ diff --git a/MasterPassword/ObjC/iOS/MPAppSettingsViewController.m b/MasterPassword/ObjC/iOS/MPAppSettingsViewController.m index 37e48c40..fa107c1f 100644 --- a/MasterPassword/ObjC/iOS/MPAppSettingsViewController.m +++ b/MasterPassword/ObjC/iOS/MPAppSettingsViewController.m @@ -19,23 +19,6 @@ #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 { } diff --git a/MasterPassword/ObjC/iOS/MPEmergencyViewController.m b/MasterPassword/ObjC/iOS/MPEmergencyViewController.m index 785e1c9d..6384789c 100644 --- a/MasterPassword/ObjC/iOS/MPEmergencyViewController.m +++ b/MasterPassword/ObjC/iOS/MPEmergencyViewController.m @@ -53,6 +53,11 @@ [self reset]; } +- (UIStatusBarStyle)preferredStatusBarStyle { + + return UIStatusBarStyleLightContent; +} + #pragma mark - UITextFieldDelegate - (BOOL)textFieldShouldReturn:(UITextField *)textField { diff --git a/MasterPassword/ObjC/iOS/MPOverlayViewController.m b/MasterPassword/ObjC/iOS/MPOverlayViewController.m index ea95b357..891c4dd2 100644 --- a/MasterPassword/ObjC/iOS/MPOverlayViewController.m +++ b/MasterPassword/ObjC/iOS/MPOverlayViewController.m @@ -1,12 +1,12 @@ /** - * 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 - */ +* 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 +*/ // // MPOverlayViewController.h @@ -18,8 +18,16 @@ #import "MPOverlayViewController.h" +@implementation MPOverlayViewController { + NSMutableDictionary *_dismissSegueByButton; +} -@implementation MPOverlayViewController +- (void)awakeFromNib { + + [super awakeFromNib]; + + _dismissSegueByButton = [NSMutableDictionary dictionary]; +} - (void)viewWillAppear:(BOOL)animated { @@ -29,12 +37,62 @@ [self performSegueWithIdentifier:@"root" sender:self]; } +- (UIViewController *)childViewControllerForStatusBarStyle { + + return [self.childViewControllers lastObject]; +} + +- (UIViewController *)childViewControllerForStatusBarHidden { + + return self.childViewControllerForStatusBarStyle; +} + - (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier { return [[MPOverlaySegue alloc] initWithIdentifier:identifier source:fromViewController destination:toViewController]; } +- (void)addDismissButtonForSegue:(MPOverlaySegue *)segue { + + UIButton *dismissButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [dismissButton addTarget:self action:@selector( dismissOverlay: ) forControlEvents:UIControlEventTouchUpInside]; + dismissButton.backgroundColor = [UIColor colorWithWhite:0 alpha:0.3f]; + dismissButton.frame = self.view.bounds; + dismissButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _dismissSegueByButton[[NSValue valueWithNonretainedObject:dismissButton]] = + [[MPOverlaySegue alloc] initWithIdentifier:@"dismiss-overlay" + source:segue.destinationViewController destination:segue.sourceViewController]; + [self.view addSubview:dismissButton]; +} + +- (void)dismissOverlay:(UIButton *)dismissButton { + + NSValue *dismissSegueKey = [NSValue valueWithNonretainedObject:dismissButton]; + [((UIStoryboardSegue *)_dismissSegueByButton[dismissSegueKey]) perform]; +} + +- (void)removeDismissButtonForViewController:(UIViewController *)viewController { + + UIButton *dismissButton = nil; + for (NSValue *dismissButtonValue in [_dismissSegueByButton allKeys]) + if (((UIStoryboardSegue *)_dismissSegueByButton[dismissButtonValue]).sourceViewController == viewController) { + dismissButton = [dismissButtonValue nonretainedObjectValue]; + NSAssert([self.view.subviews containsObject:dismissButton], @"Missing dismiss button in dictionary."); + } + if (!dismissButton) + return; + + NSValue *dismissSegueKey = [NSValue valueWithNonretainedObject:dismissButton]; + [_dismissSegueByButton removeObjectForKey:dismissSegueKey]; + + [UIView animateWithDuration:0.1f animations:^{ + dismissButton.alpha = 0; + } completion:^(BOOL finished) { + [dismissButton removeFromSuperview]; + }]; +} + @end @implementation MPOverlaySegue @@ -44,7 +102,7 @@ UIViewController *sourceViewController = self.sourceViewController; UIViewController *destinationViewController = self.destinationViewController; MPOverlayViewController *containerViewController = self.sourceViewController; - while (![containerViewController isKindOfClass:[MPOverlayViewController class]]) + while (containerViewController && ![(id)containerViewController isKindOfClass:[MPOverlayViewController class]]) containerViewController = (id)containerViewController.parentViewController; NSAssert( [containerViewController isKindOfClass:[MPOverlayViewController class]], @"Not an overlay container: %@", containerViewController ); @@ -52,11 +110,23 @@ if (!destinationViewController.parentViewController) { // Winding [containerViewController addChildViewController:destinationViewController]; + [containerViewController setNeedsStatusBarAppearanceUpdate]; + + [containerViewController addDismissButtonForSegue:self]; + destinationViewController.view.frame = containerViewController.view.bounds; + destinationViewController.view.translatesAutoresizingMaskIntoConstraints = YES; + destinationViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [containerViewController.view addSubview:destinationViewController.view]; - CGRectSetY( destinationViewController.view.frame, containerViewController.view.frame.size.height ); - [UIView transitionWithView:containerViewController.view duration:0.3f + + CGRectSetY( destinationViewController.view.frame, 100 ); + destinationViewController.view.transform = CGAffineTransformMakeScale( 1.2f, 1.2f ); + destinationViewController.view.alpha = 0; + + [UIView transitionWithView:containerViewController.view duration:[self.identifier isEqualToString:@"root"]? 0: 0.3f options:UIViewAnimationOptionAllowAnimatedContent animations:^{ + destinationViewController.view.transform = CGAffineTransformIdentity; CGRectSetY( destinationViewController.view.frame, 0 ); + destinationViewController.view.alpha = 1; } completion:^(BOOL finished) { if (finished) [destinationViewController didMoveToParentViewController:containerViewController]; @@ -65,13 +135,17 @@ else { // Unwinding [sourceViewController willMoveToParentViewController:nil]; - [UIView transitionWithView:containerViewController.view duration:0.3f + [UIView transitionWithView:containerViewController.view duration:0.2f options:UIViewAnimationOptionAllowAnimatedContent animations:^{ - CGRectSetY( sourceViewController.view.bounds, containerViewController.view.frame.size.height ); + CGRectSetY( sourceViewController.view.frame, 100 ); + sourceViewController.view.transform = CGAffineTransformMakeScale( 0.8f, 0.8f ); + sourceViewController.view.alpha = 0; + [containerViewController removeDismissButtonForViewController:sourceViewController]; } completion:^(BOOL finished) { if (finished) { [sourceViewController.view removeFromSuperview]; [sourceViewController removeFromParentViewController]; + [containerViewController setNeedsStatusBarAppearanceUpdate]; } }]; } diff --git a/MasterPassword/ObjC/iOS/MPPasswordCell.m b/MasterPassword/ObjC/iOS/MPPasswordCell.m index f931a703..26eadc78 100644 --- a/MasterPassword/ObjC/iOS/MPPasswordCell.m +++ b/MasterPassword/ObjC/iOS/MPPasswordCell.m @@ -62,11 +62,10 @@ [self setupLayer]; - [self observeKeyPath:@"bounds" withBlock:^(id from, id to, NSKeyValueChange cause, id _self) { + [self observeKeyPath:@"bounds" withBlock:^(id from, id to, NSKeyValueChange cause, MPPasswordCell *_self) { if (from && !CGSizeEqualToSize( [from CGRectValue].size, [to CGRectValue].size )) [_self setupLayer]; }]; - [self.contentButton observeKeyPath:@"highlighted" withBlock:^(id from, id to, NSKeyValueChange cause, UIButton *button) { [UIView animateWithDuration:.2f delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ @@ -141,6 +140,7 @@ - (void)dealloc { + [self removeKeyPathObservers]; [self.contentButton removeKeyPathObservers]; [self.loginNameButton removeKeyPathObservers]; } diff --git a/MasterPassword/ObjC/iOS/MPStoreViewController.h b/MasterPassword/ObjC/iOS/MPStoreViewController.h index f875fe58..285a1718 100644 --- a/MasterPassword/ObjC/iOS/MPStoreViewController.h +++ b/MasterPassword/ObjC/iOS/MPStoreViewController.h @@ -7,7 +7,7 @@ // #import -#import "MPTypeViewController.h" + @class MPStoreProductCell; @interface MPStoreViewController : PearlMutableStaticTableViewController diff --git a/MasterPassword/ObjC/iOS/MPStoreViewController.m b/MasterPassword/ObjC/iOS/MPStoreViewController.m index c93039f7..7381acf5 100644 --- a/MasterPassword/ObjC/iOS/MPStoreViewController.m +++ b/MasterPassword/ObjC/iOS/MPStoreViewController.m @@ -6,15 +6,11 @@ // Copyright (c) 2012 Lyndir. All rights reserved. // -#import #import "MPStoreViewController.h" #import "MPiOSAppDelegate.h" -#import "MPAppDelegate_Key.h" -#import "MPAppDelegate_Store.h" #import "UIColor+Expanded.h" -#import "MPPasswordsViewController.h" -#import "MPCoachmarkViewController.h" #import "MPAppDelegate_InApp.h" +#import @interface MPStoreViewController() @@ -31,6 +27,9 @@ self.currencyFormatter = [NSNumberFormatter new]; self.currencyFormatter.numberStyle = NSNumberFormatterCurrencyStyle; + self.tableView.tableHeaderView = [UIView new]; + self.tableView.tableFooterView = [UIView new]; + self.tableView.estimatedRowHeight = 400; self.view.backgroundColor = [UIColor clearColor]; } @@ -73,6 +72,13 @@ - (MPStoreProductCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { MPStoreProductCell *cell = (MPStoreProductCell *)[super tableView:tableView cellForRowAtIndexPath:indexPath]; + if (cell.contentView.translatesAutoresizingMaskIntoConstraints) { + cell.contentView.translatesAutoresizingMaskIntoConstraints = NO; + [cell addConstraint: + [NSLayoutConstraint constraintWithItem:cell attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual + toItem:cell.contentView attribute:NSLayoutAttributeWidth multiplier:1 constant:0]]; + } + if (indexPath.section == 0) cell.selectionStyle = [[MPiOSAppDelegate get] isPurchased:[self productForCell:cell].productIdentifier]? UITableViewCellSelectionStyleDefault: UITableViewCellSelectionStyleNone; @@ -85,11 +91,19 @@ return cell; } +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + + UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath]; + [cell layoutIfNeeded]; + + return cell.contentView.bounds.size.height; +} + - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (![SKPaymentQueue canMakePayments]) { + if (![[MPAppDelegate_Shared get] canMakePayments]) { [PearlAlert showAlertWithTitle:@"Store Not Set Up" message: - @"Try logging using the App Store or from Settings." + @"Try logging using the App Store or from Settings." viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:nil cancelTitle:@"Thanks" otherTitles:nil]; return; @@ -99,7 +113,7 @@ SKProduct *product = [self productForCell:cell]; if (product) - [[SKPaymentQueue defaultQueue] addPayment:[SKPayment paymentWithProduct:product]]; + [[MPAppDelegate_Shared get] purchaseProductWithIdentifier:product.productIdentifier]; [tableView deselectRowAtIndexPath:indexPath animated:YES]; } @@ -115,7 +129,7 @@ if (buttonIndex == [alert cancelButtonIndex]) return; - [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]; + [[MPAppDelegate_Shared get] restoreCompletedTransactions]; } cancelTitle:@"Cancel" otherTitles:@"Find Purchases", nil]; } diff --git a/MasterPassword/ObjC/iOS/MPUsersViewController.m b/MasterPassword/ObjC/iOS/MPUsersViewController.m index 7bb88403..bd5a06fe 100644 --- a/MasterPassword/ObjC/iOS/MPUsersViewController.m +++ b/MasterPassword/ObjC/iOS/MPUsersViewController.m @@ -74,6 +74,8 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) { self.view.backgroundColor = [UIColor clearColor]; self.avatarCollectionView.allowsMultipleSelection = YES; [self.entryField addTarget:self action:@selector( textFieldEditingChanged: ) forControlEvents:UIControlEventEditingChanged]; + + [self setActive:YES animated:NO]; } - (void)viewWillAppear:(BOOL)animated { @@ -81,7 +83,6 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) { [super viewWillAppear:animated]; self.userSelectionContainer.alpha = 0; - [self setActive:YES animated:NO]; } - (void)viewWillDisappear:(BOOL)animated { diff --git a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.h b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.h index afeff347..617fe7e9 100644 --- a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.h +++ b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.h @@ -7,8 +7,6 @@ // #import -#import -#import #import "MPAppDelegate_Shared.h" diff --git a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m index 423fab83..dcfb8ec6 100644 --- a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m +++ b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m @@ -6,13 +6,10 @@ // Copyright (c) 2011 Lyndir. All rights reserved. // -#import -#import #import "MPiOSAppDelegate.h" #import "MPAppDelegate_Key.h" #import "MPAppDelegate_Store.h" #import "IASKSettingsReader.h" -#import "MPAppDelegate_InApp.h" @interface MPiOSAppDelegate() diff --git a/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj b/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj index e8a6d37d..e3a693d3 100644 --- a/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj +++ b/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj @@ -123,6 +123,9 @@ DA32D01B19D046E1004F3F0E /* PearlFixedTableView.h in Headers */ = {isa = PBXBuildFile; fileRef = DA32D01919D046E1004F3F0E /* PearlFixedTableView.h */; }; DA32D03C19D111EB004F3F0E /* NSManagedObjectModel+KCOrderedAccessorFix.m in Sources */ = {isa = PBXBuildFile; fileRef = DA32D03A19D111EB004F3F0E /* NSManagedObjectModel+KCOrderedAccessorFix.m */; }; DA32D03E19D11293004F3F0E /* libKCOrderedAccessorFix.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA32D02019D111C6004F3F0E /* libKCOrderedAccessorFix.a */; }; + DA32D04219D27093004F3F0E /* thumb_generated_answers@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA32D03F19D27093004F3F0E /* thumb_generated_answers@3x.png */; }; + DA32D04319D27093004F3F0E /* thumb_generated_answers@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA32D04019D27093004F3F0E /* thumb_generated_answers@2x.png */; }; + DA32D04419D27093004F3F0E /* thumb_generated_answers.png in Resources */ = {isa = PBXBuildFile; fileRef = DA32D04119D27093004F3F0E /* thumb_generated_answers.png */; }; DA3509FE15F101A500C14A8E /* PearlQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = DA3509FC15F101A500C14A8E /* PearlQueue.h */; }; DA3509FF15F101A500C14A8E /* PearlQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3509FD15F101A500C14A8E /* PearlQueue.m */; }; DA38D6A318CCB5BF009AEB3E /* Storyboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DA38D6A218CCB5BF009AEB3E /* Storyboard.storyboard */; }; @@ -543,6 +546,9 @@ DA32D02019D111C6004F3F0E /* libKCOrderedAccessorFix.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libKCOrderedAccessorFix.a; sourceTree = BUILT_PRODUCTS_DIR; }; DA32D03919D111EB004F3F0E /* NSManagedObjectModel+KCOrderedAccessorFix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectModel+KCOrderedAccessorFix.h"; sourceTree = ""; }; DA32D03A19D111EB004F3F0E /* NSManagedObjectModel+KCOrderedAccessorFix.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectModel+KCOrderedAccessorFix.m"; sourceTree = ""; }; + DA32D03F19D27093004F3F0E /* thumb_generated_answers@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "thumb_generated_answers@3x.png"; sourceTree = ""; }; + DA32D04019D27093004F3F0E /* thumb_generated_answers@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "thumb_generated_answers@2x.png"; sourceTree = ""; }; + DA32D04119D27093004F3F0E /* thumb_generated_answers.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_generated_answers.png; sourceTree = ""; }; DA3509FC15F101A500C14A8E /* PearlQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlQueue.h; sourceTree = ""; }; DA3509FD15F101A500C14A8E /* PearlQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlQueue.m; sourceTree = ""; }; DA38D6A218CCB5BF009AEB3E /* Storyboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Storyboard.storyboard; sourceTree = ""; }; @@ -1597,6 +1603,9 @@ DABD360D1711E29400CF925C /* Media */ = { isa = PBXGroup; children = ( + DA32D03F19D27093004F3F0E /* thumb_generated_answers@3x.png */, + DA32D04019D27093004F3F0E /* thumb_generated_answers@2x.png */, + DA32D04119D27093004F3F0E /* thumb_generated_answers.png */, DA29993119C9132F00AF7DF1 /* thumb_generated_login@3x.png */, DA29992D19C86F5700AF7DF1 /* thumb_generated_login@2x.png */, DA29992E19C86F5700AF7DF1 /* thumb_generated_login.png */, @@ -3116,9 +3125,11 @@ DABD394A1711E29700CF925C /* avatar-18.png in Resources */, DABD394B1711E29700CF925C /* avatar-18@2x.png in Resources */, DABD394C1711E29700CF925C /* avatar-1@2x.png in Resources */, + DA32D04319D27093004F3F0E /* thumb_generated_answers@2x.png in Resources */, DA29993319C9214600AF7DF1 /* icon_star-hollow.png in Resources */, DA29993019C86F5700AF7DF1 /* thumb_generated_login.png in Resources */, DA071BF3190187FE00179766 /* empty@2x.png in Resources */, + DA32D04219D27093004F3F0E /* thumb_generated_answers@3x.png in Resources */, DA67460E18DE7F0C00DFE240 /* Exo2.0-Regular.otf in Resources */, DABD394D1711E29700CF925C /* avatar-2.png in Resources */, DABD394E1711E29700CF925C /* avatar-2@2x.png in Resources */, @@ -3181,6 +3192,7 @@ DABD3ABF1711E29800CF925C /* icon_plus@2x.png in Resources */, DA69540717D975D900BF294E /* icon_gears@2x.png in Resources */, DABD3B1C1711E29800CF925C /* icon_up.png in Resources */, + DA32D04419D27093004F3F0E /* thumb_generated_answers.png in Resources */, DABD3B1D1711E29800CF925C /* icon_up@2x.png in Resources */, DA3BCFCB19BD09D5006B2681 /* SourceCodePro-Regular.otf in Resources */, DA250A121956484D00AC23F1 /* image-0.png in Resources */, diff --git a/MasterPassword/ObjC/iOS/Storyboard.storyboard b/MasterPassword/ObjC/iOS/Storyboard.storyboard index 45edf3c4..f1d5a2e6 100644 --- a/MasterPassword/ObjC/iOS/Storyboard.storyboard +++ b/MasterPassword/ObjC/iOS/Storyboard.storyboard @@ -5,6 +5,7 @@ + @@ -612,7 +613,7 @@ - + @@ -1166,7 +1167,7 @@ - + @@ -1189,9 +1190,9 @@ - + - + @@ -1638,238 +1639,220 @@ - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - - + + + + + @@ -2440,7 +2423,7 @@ See - + @@ -2462,7 +2445,7 @@ See - - + @@ -2959,20 +2932,18 @@ See - - - - + + + - @@ -2995,6 +2966,7 @@ See + @@ -3008,7 +2980,7 @@ See - + diff --git a/MasterPassword/Resources/Media/thumb_generated_answers.png b/MasterPassword/Resources/Media/thumb_generated_answers.png new file mode 100644 index 00000000..0674b676 Binary files /dev/null and b/MasterPassword/Resources/Media/thumb_generated_answers.png differ diff --git a/MasterPassword/Resources/Media/thumb_generated_answers@2x.png b/MasterPassword/Resources/Media/thumb_generated_answers@2x.png new file mode 100644 index 00000000..5842273f Binary files /dev/null and b/MasterPassword/Resources/Media/thumb_generated_answers@2x.png differ diff --git a/MasterPassword/Resources/Media/thumb_generated_answers@3x.png b/MasterPassword/Resources/Media/thumb_generated_answers@3x.png new file mode 100644 index 00000000..1e366a26 Binary files /dev/null and b/MasterPassword/Resources/Media/thumb_generated_answers@3x.png differ