Convert store into template cells for products.
This commit is contained in:
parent
834e94ebd5
commit
cf2c30cfe6
2
platform-darwin/External/Pearl
vendored
2
platform-darwin/External/Pearl
vendored
@ -1 +1 @@
|
||||
Subproject commit 284cd041f8d48301044cf85a7ac4a9abf030e170
|
||||
Subproject commit 1a3e1ea0379fe8d0f1b06ce98cd6394654679682
|
@ -25,17 +25,20 @@
|
||||
#define MPProductTouchID @"com.lyndir.masterpassword.products.touchid"
|
||||
#define MPProductFuel @"com.lyndir.masterpassword.products.fuel"
|
||||
|
||||
#define MP_FUEL_HOURLY_RATE 30.f /* Tier 1 purchases/h ~> USD/h */
|
||||
#define MP_FUEL_HOURLY_RATE 40.f /* payment in tier 1 purchases / h (≅ USD / h) */
|
||||
|
||||
@protocol MPInAppDelegate
|
||||
|
||||
- (void)updateWithProducts:(NSDictionary<NSString *, SKProduct *> *)products;
|
||||
- (void)updateWithTransaction:(SKPaymentTransaction *)transaction;
|
||||
- (void)updateWithProducts:(NSDictionary<NSString *, SKProduct *> *)products
|
||||
transactions:(NSDictionary<NSString *, SKPaymentTransaction *> *)transactions;
|
||||
|
||||
@end
|
||||
|
||||
@interface MPAppDelegate_Shared(InApp)
|
||||
|
||||
- (NSDictionary<NSString *, SKProduct *> *)products;
|
||||
- (NSDictionary<NSString *, SKPaymentTransaction *> *)transactions;
|
||||
|
||||
- (void)registerProductsObserver:(id<MPInAppDelegate>)delegate;
|
||||
- (void)removeProductsObserver:(id<MPInAppDelegate>)delegate;
|
||||
|
||||
|
@ -27,6 +27,16 @@ PearlAssociatedObjectProperty( NSDictionary*, Products, products );
|
||||
|
||||
PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObservers );
|
||||
|
||||
- (NSDictionary<NSString *, SKPaymentTransaction *> *)transactions {
|
||||
|
||||
NSMutableDictionary<NSString *, SKPaymentTransaction *> *transactions =
|
||||
[NSMutableDictionary dictionaryWithCapacity:self.paymentQueue.transactions.count];
|
||||
for (SKPaymentTransaction *transaction in self.paymentQueue.transactions)
|
||||
transactions[transaction.payment.productIdentifier] = transaction;
|
||||
|
||||
return transactions;
|
||||
}
|
||||
|
||||
- (void)registerProductsObserver:(id<MPInAppDelegate>)delegate {
|
||||
|
||||
if (!self.productObservers)
|
||||
@ -34,7 +44,7 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
|
||||
[self.productObservers addObject:delegate];
|
||||
|
||||
if (self.products)
|
||||
[delegate updateWithProducts:self.products];
|
||||
[delegate updateWithProducts:self.products transactions:[self transactions]];
|
||||
else
|
||||
[self reloadProducts];
|
||||
}
|
||||
@ -108,18 +118,6 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
|
||||
if (payment) {
|
||||
payment.quantity = quantity;
|
||||
[[self paymentQueue] addPayment:payment];
|
||||
|
||||
if ([[MPConfig get].sendInfo boolValue]) {
|
||||
#ifdef CRASHLYTICS
|
||||
[Answers logAddToCartWithPrice:product.price currency:product.priceLocale.currencyCode itemName:product.localizedTitle
|
||||
itemType:@"InApp" itemId:product.productIdentifier
|
||||
customAttributes:nil];
|
||||
[Answers logStartCheckoutWithPrice:product.price currency:product.priceLocale.currencyCode itemCount:@(quantity)
|
||||
customAttributes:@{
|
||||
@"products": @[ productIdentifier ],
|
||||
}];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -138,7 +136,7 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
|
||||
self.products = products;
|
||||
|
||||
for (id<MPInAppDelegate> productObserver in self.productObservers)
|
||||
[productObserver updateWithProducts:self.products];
|
||||
[productObserver updateWithProducts:self.products transactions:[self transactions]];
|
||||
}
|
||||
|
||||
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
|
||||
@ -166,6 +164,7 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
|
||||
|
||||
for (SKPaymentTransaction *transaction in transactions) {
|
||||
dbg( @"transaction updated: %@ -> %d", transaction.payment.productIdentifier, (int)(transaction.transactionState) );
|
||||
|
||||
switch (transaction.transactionState) {
|
||||
case SKPaymentTransactionStatePurchased: {
|
||||
inf( @"Purchased: %@", transaction.payment.productIdentifier );
|
||||
@ -190,9 +189,10 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
|
||||
if ([[MPConfig get].sendInfo boolValue]) {
|
||||
#ifdef CRASHLYTICS
|
||||
SKProduct *product = self.products[transaction.payment.productIdentifier];
|
||||
[Answers logPurchaseWithPrice:product.price currency:product.priceLocale.currencyCode success:@YES
|
||||
itemName:product.localizedTitle itemType:@"InApp" itemId:product.productIdentifier
|
||||
customAttributes:attributes];
|
||||
for (int q = 0; q < transaction.payment.quantity; ++q)
|
||||
[Answers logPurchaseWithPrice:product.price currency:[product.priceLocale objectForKey:NSLocaleCurrencyCode]
|
||||
success:@YES itemName:product.localizedTitle itemType:@"InApp"
|
||||
itemId:product.productIdentifier customAttributes:attributes];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
@ -208,28 +208,33 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
|
||||
case SKPaymentTransactionStateDeferred:
|
||||
break;
|
||||
case SKPaymentTransactionStateFailed:
|
||||
err( @"Transaction failed: %@, reason: %@", transaction.payment.productIdentifier, [transaction.error fullDescription] );
|
||||
MPError( transaction.error, @"Transaction failed: %@.", transaction.payment.productIdentifier );
|
||||
[queue finishTransaction:transaction];
|
||||
|
||||
if ([[MPConfig get].sendInfo boolValue]) {
|
||||
#ifdef CRASHLYTICS
|
||||
SKProduct *product = self.products[transaction.payment.productIdentifier];
|
||||
[Answers logPurchaseWithPrice:product.price currency:product.priceLocale.currencyCode success:@YES
|
||||
itemName:product.localizedTitle itemType:@"InApp" itemId:product.productIdentifier
|
||||
[Answers logPurchaseWithPrice:product.price currency:[product.priceLocale objectForKey:NSLocaleCurrencyCode]
|
||||
success:@NO itemName:product.localizedTitle itemType:@"InApp" itemId:product.productIdentifier
|
||||
customAttributes:@{
|
||||
@"state" : @"Failed",
|
||||
@"reason": [transaction.error fullDescription],
|
||||
@"quantity": @(transaction.payment.quantity),
|
||||
@"reason" : [transaction.error localizedFailureReason]?: [transaction.error localizedDescription],
|
||||
}];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (id<MPInAppDelegate> productObserver in self.productObservers)
|
||||
[productObserver updateWithTransaction:transaction];
|
||||
}
|
||||
|
||||
if (![[NSUserDefaults standardUserDefaults] synchronize])
|
||||
wrn( @"Couldn't synchronize after transaction updates." );
|
||||
|
||||
NSMutableDictionary<NSString *, SKPaymentTransaction *> *allTransactions = [[self transactions] mutableCopy];
|
||||
for (SKPaymentTransaction *transaction in transactions)
|
||||
allTransactions[transaction.payment.productIdentifier] = transaction;
|
||||
for (id<MPInAppDelegate> productObserver in self.productObservers)
|
||||
[productObserver updateWithProducts:self.products transactions:allTransactions];
|
||||
}
|
||||
|
||||
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
@implementation MPAppDelegate_Shared(Key)
|
||||
|
||||
static NSDictionary *createKeyQuery(MPUserEntity *user, BOOL newItem, MPKeyOrigin *keyOrigin) {
|
||||
- (NSDictionary *)createKeyQueryforUser:(MPUserEntity *)user origin:(out MPKeyOrigin *)keyOrigin {
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
if (user.touchID && kSecUseAuthenticationUI) {
|
||||
@ -38,8 +38,8 @@ static NSDictionary *createKeyQuery(MPUserEntity *user, BOOL newItem, MPKeyOrigi
|
||||
CFErrorRef acError = NULL;
|
||||
id accessControl = (__bridge_transfer id)SecAccessControlCreateWithFlags( kCFAllocatorDefault,
|
||||
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAccessControlTouchIDCurrentSet, &acError );
|
||||
if (!accessControl || acError)
|
||||
err( @"Could not use TouchID on this device: %@", acError );
|
||||
if (!accessControl)
|
||||
MPError( (__bridge_transfer NSError *)acError, @"Could not use TouchID on this device." );
|
||||
|
||||
else
|
||||
return [PearlKeyChain createQueryForClass:kSecClassGenericPassword
|
||||
@ -47,7 +47,7 @@ static NSDictionary *createKeyQuery(MPUserEntity *user, BOOL newItem, MPKeyOrigi
|
||||
(__bridge id)kSecAttrService : @"Saved Master Password",
|
||||
(__bridge id)kSecAttrAccount : user.name?: @"",
|
||||
(__bridge id)kSecAttrAccessControl : accessControl,
|
||||
(__bridge id)kSecUseAuthenticationUI : (__bridge id)kSecUseAuthenticationUIAllow,
|
||||
(__bridge id)kSecUseAuthenticationUI: (__bridge id)kSecUseAuthenticationUIAllow,
|
||||
(__bridge id)kSecUseOperationPrompt :
|
||||
strf( @"Access %@'s master password.", user.name ),
|
||||
}
|
||||
@ -60,10 +60,10 @@ static NSDictionary *createKeyQuery(MPUserEntity *user, BOOL newItem, MPKeyOrigi
|
||||
|
||||
return [PearlKeyChain createQueryForClass:kSecClassGenericPassword
|
||||
attributes:@{
|
||||
(__bridge id)kSecAttrService: @"Saved Master Password",
|
||||
(__bridge id)kSecAttrAccount: user.name?: @"",
|
||||
(__bridge id)kSecAttrService : @"Saved Master Password",
|
||||
(__bridge id)kSecAttrAccount : user.name?: @"",
|
||||
#if TARGET_OS_IPHONE
|
||||
(__bridge id)kSecAttrAccessible : (__bridge id)(kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly?: kSecAttrAccessibleWhenUnlockedThisDeviceOnly),
|
||||
(__bridge id)kSecAttrAccessible: (__bridge id)(kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly?: kSecAttrAccessibleWhenUnlockedThisDeviceOnly),
|
||||
#endif
|
||||
}
|
||||
matches:nil];
|
||||
@ -72,7 +72,7 @@ static NSDictionary *createKeyQuery(MPUserEntity *user, BOOL newItem, MPKeyOrigi
|
||||
- (MPKey *)loadSavedKeyFor:(MPUserEntity *)user {
|
||||
|
||||
MPKeyOrigin keyOrigin;
|
||||
NSDictionary *keyQuery = createKeyQuery( user, NO, &keyOrigin );
|
||||
NSDictionary *keyQuery = [self createKeyQueryforUser:user origin:&keyOrigin];
|
||||
id<MPAlgorithm> keyAlgorithm = user.algorithm;
|
||||
MPKey *key = [[MPKey alloc] initForFullName:user.name withKeyResolver:^NSData *(id<MPAlgorithm> algorithm) {
|
||||
return ![algorithm isEqual:keyAlgorithm]? nil:
|
||||
@ -100,7 +100,7 @@ static NSDictionary *createKeyQuery(MPUserEntity *user, BOOL newItem, MPKeyOrigi
|
||||
[self forgetSavedKeyFor:user];
|
||||
|
||||
inf( @"Saving key in keychain for user: %@", user.userID );
|
||||
[PearlKeyChain addOrUpdateItemForQuery:createKeyQuery( user, YES, nil )
|
||||
[PearlKeyChain addOrUpdateItemForQuery:[self createKeyQueryforUser:user origin:nil]
|
||||
withAttributes:@{ (__bridge id)kSecValueData: keyData }];
|
||||
}
|
||||
}
|
||||
@ -108,7 +108,7 @@ static NSDictionary *createKeyQuery(MPUserEntity *user, BOOL newItem, MPKeyOrigi
|
||||
|
||||
- (void)forgetSavedKeyFor:(MPUserEntity *)user {
|
||||
|
||||
OSStatus result = [PearlKeyChain deleteItemForQuery:createKeyQuery( user, NO, nil )];
|
||||
OSStatus result = [PearlKeyChain deleteItemForQuery:[self createKeyQueryforUser:user origin:nil]];
|
||||
if (result == noErr) {
|
||||
inf( @"Removed key from keychain for user: %@", user.userID );
|
||||
|
||||
|
@ -17,20 +17,11 @@
|
||||
//==============================================================================
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <StoreKit/StoreKit.h>
|
||||
|
||||
@class MPStoreProductCell;
|
||||
|
||||
@interface MPStoreViewController : PearlMutableStaticTableViewController
|
||||
|
||||
@property(weak, nonatomic) IBOutlet MPStoreProductCell *generateLoginCell;
|
||||
@property(weak, nonatomic) IBOutlet MPStoreProductCell *generateAnswersCell;
|
||||
@property(weak, nonatomic) IBOutlet MPStoreProductCell *iOSIntegrationCell;
|
||||
@property(weak, nonatomic) IBOutlet MPStoreProductCell *touchIDCell;
|
||||
@property(weak, nonatomic) IBOutlet MPStoreProductCell *fuelCell;
|
||||
@property(weak, nonatomic) IBOutlet UITableViewCell *loadingCell;
|
||||
@property(weak, nonatomic) IBOutlet NSLayoutConstraint *fuelMeterConstraint;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *fuelSpeedButton;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *fuelStatusLabel;
|
||||
@interface MPStoreViewController : UITableViewController
|
||||
|
||||
+ (NSString *)latestStoreFeatures;
|
||||
|
||||
@ -44,4 +35,17 @@
|
||||
@property(nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
|
||||
@property(nonatomic) IBOutlet UIView *purchasedIndicator;
|
||||
|
||||
@property(nonatomic, readonly) SKProduct *product;
|
||||
@property(nonatomic, readonly) NSInteger quantity;
|
||||
|
||||
- (void)updateWithProduct:(SKProduct *)product transaction:(SKPaymentTransaction *)transaction;
|
||||
|
||||
@end
|
||||
|
||||
@interface MPStoreFuelProductCell : MPStoreProductCell
|
||||
|
||||
@property(weak, nonatomic) IBOutlet NSLayoutConstraint *fuelMeterConstraint;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *fuelSpeedButton;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *fuelStatusLabel;
|
||||
|
||||
@end
|
||||
|
@ -27,8 +27,9 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
|
||||
@interface MPStoreViewController()<MPInAppDelegate>
|
||||
|
||||
@property(nonatomic, strong) NSNumberFormatter *currencyFormatter;
|
||||
@property(nonatomic, strong) NSDictionary<NSString *, SKProduct *> *products;
|
||||
@property(nonatomic, strong) NSDictionary<NSString *, SKPaymentTransaction *> *transactions;
|
||||
@property(nonatomic, strong) NSMutableArray<NSArray *> *dataSource;
|
||||
|
||||
@end
|
||||
|
||||
@ -57,14 +58,13 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
|
||||
[super viewDidLoad];
|
||||
|
||||
self.currencyFormatter = [NSNumberFormatter new];
|
||||
self.currencyFormatter.numberStyle = NSNumberFormatterCurrencyStyle;
|
||||
|
||||
self.tableView.tableHeaderView = [UIView new];
|
||||
self.tableView.tableFooterView = [UIView new];
|
||||
self.tableView.rowHeight = UITableViewAutomaticDimension;
|
||||
self.tableView.estimatedRowHeight = 400;
|
||||
self.view.backgroundColor = [UIColor clearColor];
|
||||
|
||||
self.dataSource = [@[ @[], @[ @"MPStoreCellSpinner", @"MPStoreCellFooter" ] ] mutableCopy];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
@ -73,50 +73,44 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
|
||||
self.tableView.contentInset = UIEdgeInsetsMake( 64, 0, 49, 0 );
|
||||
|
||||
[self updateCellsHiding:self.allCellsBySection[0] showing:@[ self.loadingCell ]];
|
||||
[self.allCellsBySection[0] enumerateObjectsUsingBlock:^(MPStoreProductCell *cell, NSUInteger idx, BOOL *stop) {
|
||||
if ([cell isKindOfClass:[MPStoreProductCell class]]) {
|
||||
cell.purchasedIndicator.visible = NO;
|
||||
[cell.activityIndicator stopAnimating];
|
||||
}
|
||||
}];
|
||||
|
||||
PearlAddNotificationObserver( NSUserDefaultsDidChangeNotification, nil, [NSOperationQueue mainQueue],
|
||||
^(MPStoreViewController *self, NSNotification *note) {
|
||||
[self updateProducts];
|
||||
[self updateFuel];
|
||||
} );
|
||||
[[MPiOSAppDelegate get] registerProductsObserver:self];
|
||||
[self updateFuel];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
|
||||
[super viewWillDisappear:animated];
|
||||
|
||||
PearlRemoveNotificationObservers();
|
||||
[[MPiOSAppDelegate get] removeProductsObserver:self];
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDataSource
|
||||
|
||||
- (MPStoreProductCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
|
||||
MPStoreProductCell *cell = (MPStoreProductCell *)[super tableView:tableView cellForRowAtIndexPath:indexPath];
|
||||
if (indexPath.section == 0)
|
||||
cell.selectionStyle = [[MPiOSAppDelegate get] isFeatureUnlocked:[self productForCell:cell].productIdentifier]?
|
||||
UITableViewCellSelectionStyleNone: UITableViewCellSelectionStyleDefault;
|
||||
|
||||
if (cell.selectionStyle != UITableViewCellSelectionStyleNone) {
|
||||
cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.bounds];
|
||||
cell.selectedBackgroundView.backgroundColor = [UIColor colorWithRGBAHex:0x78DDFB33];
|
||||
}
|
||||
|
||||
return cell;
|
||||
return [self.dataSource count];
|
||||
}
|
||||
|
||||
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
|
||||
return NO;
|
||||
return [self.dataSource[(NSUInteger)section] count];
|
||||
}
|
||||
|
||||
- (MPStoreProductCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
id content = self.dataSource[(NSUInteger)indexPath.section][(NSUInteger)indexPath.row];
|
||||
if ([content isKindOfClass:[SKProduct class]]) {
|
||||
SKProduct *product = content;
|
||||
MPStoreProductCell *cell;
|
||||
if ([product.productIdentifier isEqualToString:MPProductFuel])
|
||||
cell = [MPStoreFuelProductCell dequeueCellFromTableView:tableView indexPath:indexPath];
|
||||
else
|
||||
cell = [MPStoreProductCell dequeueCellFromTableView:tableView indexPath:indexPath];
|
||||
[cell updateWithProduct:product transaction:self.transactions[product.productIdentifier]];
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
return [tableView dequeueReusableCellWithIdentifier:content forIndexPath:indexPath];
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate
|
||||
@ -128,14 +122,13 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
MPStoreProductCell *cell = (MPStoreProductCell *)[self tableView:tableView cellForRowAtIndexPath:indexPath];
|
||||
if (cell.selectionStyle == UITableViewCellSelectionStyleNone)
|
||||
return;
|
||||
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
|
||||
if (cell.selectionStyle != UITableViewCellSelectionStyleNone && [cell isKindOfClass:[MPStoreProductCell class]]) {
|
||||
MPStoreProductCell *productCell = (MPStoreProductCell *)cell;
|
||||
|
||||
SKProduct *product = [self productForCell:cell];
|
||||
if (product && ![[MPAppDelegate_Shared get] isFeatureUnlocked:product.productIdentifier])
|
||||
[[MPAppDelegate_Shared get] purchaseProductWithIdentifier:product.productIdentifier
|
||||
quantity:[self quantityForProductIdentifier:product.productIdentifier]];
|
||||
if (productCell.product && ![[MPAppDelegate_Shared get] isFeatureUnlocked:productCell.product.productIdentifier])
|
||||
[[MPAppDelegate_Shared get] purchaseProductWithIdentifier:productCell.product.productIdentifier quantity:productCell.quantity];
|
||||
}
|
||||
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
}
|
||||
@ -146,7 +139,9 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
|
||||
NSUInteger fuelConsumption = [[MPiOSConfig get].developmentFuelConsumption unsignedIntegerValue];
|
||||
[MPiOSConfig get].developmentFuelConsumption = @((fuelConsumption + 1) % MPDevelopmentFuelConsumptionCount);
|
||||
[self updateProducts];
|
||||
|
||||
[self.tableView updateDataSource:self.dataSource toSections:nil reloadItems:@[ self.products[MPProductFuel] ]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
}
|
||||
|
||||
- (IBAction)restorePurchases:(id)sender {
|
||||
@ -170,36 +165,28 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
|
||||
#pragma mark - MPInAppDelegate
|
||||
|
||||
- (void)updateWithProducts:(NSDictionary<NSString *, SKProduct *> *)products {
|
||||
- (void)updateWithProducts:(NSDictionary<NSString *, SKProduct *> *)products
|
||||
transactions:(NSDictionary<NSString *, SKPaymentTransaction *> *)transactions {
|
||||
|
||||
self.products = products;
|
||||
self.transactions = transactions;
|
||||
NSMutableArray *newDataSource = [NSMutableArray arrayWithCapacity:2];
|
||||
|
||||
[self updateProducts];
|
||||
}
|
||||
// Section 0: products
|
||||
[newDataSource addObject:[[products allValues] sortedArrayUsingComparator:
|
||||
^NSComparisonResult(SKProduct *p1, SKProduct *p2) {
|
||||
return [p1.productIdentifier compare:p2.productIdentifier];
|
||||
}]];
|
||||
NSArray *reloadProducts = [newDataSource[0] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:
|
||||
^BOOL(SKProduct *product, NSDictionary *bindings) {
|
||||
return self.transactions[product.productIdentifier] != nil;
|
||||
}]];
|
||||
|
||||
- (void)updateWithTransaction:(SKPaymentTransaction *)transaction {
|
||||
// Section 1: information cells
|
||||
[newDataSource addObject:@[ @"MPStoreCellFooter" ]];
|
||||
|
||||
MPStoreProductCell *cell = [self cellForProductIdentifier:transaction.payment.productIdentifier];
|
||||
if (!cell)
|
||||
return;
|
||||
|
||||
switch (transaction.transactionState) {
|
||||
case SKPaymentTransactionStatePurchasing:
|
||||
[cell.activityIndicator startAnimating];
|
||||
break;
|
||||
case SKPaymentTransactionStatePurchased:
|
||||
[cell.activityIndicator stopAnimating];
|
||||
break;
|
||||
case SKPaymentTransactionStateFailed:
|
||||
[cell.activityIndicator stopAnimating];
|
||||
break;
|
||||
case SKPaymentTransactionStateRestored:
|
||||
[cell.activityIndicator stopAnimating];
|
||||
break;
|
||||
case SKPaymentTransactionStateDeferred:
|
||||
[cell.activityIndicator startAnimating];
|
||||
break;
|
||||
}
|
||||
[self.tableView updateDataSource:self.dataSource toSections:newDataSource
|
||||
reloadItems:reloadProducts withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
@ -216,60 +203,63 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (SKProduct *)productForCell:(MPStoreProductCell *)cell {
|
||||
@end
|
||||
|
||||
for (SKProduct *product in [self.products allValues])
|
||||
if ([self cellForProductIdentifier:product.productIdentifier] == cell)
|
||||
return product;
|
||||
@implementation MPStoreProductCell
|
||||
|
||||
return nil;
|
||||
- (void)updateWithProduct:(SKProduct *)product transaction:(SKPaymentTransaction *)transaction {
|
||||
|
||||
_product = product;
|
||||
|
||||
BOOL purchased = [[MPiOSAppDelegate get] isFeatureUnlocked:self.product.productIdentifier];
|
||||
self.selectionStyle = purchased? UITableViewCellSelectionStyleNone: UITableViewCellSelectionStyleDefault;
|
||||
self.selectedBackgroundView = self.selectionStyle == UITableViewCellSelectionStyleNone? nil: [[UIView alloc] initWithFrame:self.bounds];
|
||||
self.selectedBackgroundView.backgroundColor = [UIColor colorWithRGBAHex:0x78DDFB33];
|
||||
|
||||
self.purchasedIndicator.visible = purchased;
|
||||
self.priceLabel.text = purchased? @"": [self price];
|
||||
self.titleLabel.text = product.localizedTitle;
|
||||
self.descriptionLabel.text = product.localizedDescription;
|
||||
|
||||
if (transaction && (transaction.transactionState == SKPaymentTransactionStateDeferred ||
|
||||
transaction.transactionState == SKPaymentTransactionStatePurchasing))
|
||||
[self.activityIndicator startAnimating];
|
||||
else
|
||||
[self.activityIndicator stopAnimating];
|
||||
}
|
||||
|
||||
- (MPStoreProductCell *)cellForProductIdentifier:(NSString *)productIdentifier {
|
||||
- (NSString *)price {
|
||||
|
||||
if ([productIdentifier isEqualToString:MPProductGenerateLogins])
|
||||
return self.generateLoginCell;
|
||||
if ([productIdentifier isEqualToString:MPProductGenerateAnswers])
|
||||
return self.generateAnswersCell;
|
||||
if ([productIdentifier isEqualToString:MPProductOSIntegration])
|
||||
return self.iOSIntegrationCell;
|
||||
if ([productIdentifier isEqualToString:MPProductTouchID])
|
||||
return self.touchIDCell;
|
||||
if ([productIdentifier isEqualToString:MPProductFuel])
|
||||
return self.fuelCell;
|
||||
NSNumberFormatter *currencyFormatter = [NSNumberFormatter new];
|
||||
currencyFormatter.numberStyle = NSNumberFormatterCurrencyStyle;
|
||||
currencyFormatter.locale = self.product.priceLocale;
|
||||
|
||||
return nil;
|
||||
return [currencyFormatter stringFromNumber:@([self.product.price floatValue] * self.quantity)];
|
||||
}
|
||||
|
||||
- (void)updateProducts {
|
||||
- (NSInteger)quantity {
|
||||
|
||||
NSMutableArray *showCells = [NSMutableArray array];
|
||||
NSMutableArray *hideCells = [NSMutableArray array];
|
||||
[hideCells addObjectsFromArray:[self.allCellsBySection[0] array]];
|
||||
[hideCells addObject:self.loadingCell];
|
||||
|
||||
for (SKProduct *product in [self.products allValues]) {
|
||||
[self showCellForProductWithIdentifier:MPProductGenerateLogins ifProduct:product showingCells:showCells];
|
||||
[self showCellForProductWithIdentifier:MPProductGenerateAnswers ifProduct:product showingCells:showCells];
|
||||
[self showCellForProductWithIdentifier:MPProductOSIntegration ifProduct:product showingCells:showCells];
|
||||
[self showCellForProductWithIdentifier:MPProductTouchID ifProduct:product showingCells:showCells];
|
||||
[self showCellForProductWithIdentifier:MPProductFuel ifProduct:product showingCells:showCells];
|
||||
}
|
||||
|
||||
[hideCells removeObjectsInArray:showCells];
|
||||
[self updateCellsHiding:hideCells showing:showCells];
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (void)updateFuel {
|
||||
@end
|
||||
|
||||
@implementation MPStoreFuelProductCell
|
||||
|
||||
- (void)updateWithProduct:(SKProduct *)product transaction:(SKPaymentTransaction *)transaction {
|
||||
|
||||
[super updateWithProduct:product transaction:transaction];
|
||||
|
||||
CGFloat weeklyFuelConsumption = [self weeklyFuelConsumption]; /* consume x fuel / week */
|
||||
[self.fuelSpeedButton setTitle:[self weeklyFuelConsumptionTitle] forState:UIControlStateNormal];
|
||||
|
||||
NSTimeInterval fuelSecondsElapsed = 0;
|
||||
CGFloat fuelRemaining = [[MPiOSConfig get].developmentFuelRemaining floatValue]; /* x fuel left */
|
||||
CGFloat fuelInvested = [[MPiOSConfig get].developmentFuelInvested floatValue]; /* x fuel left */
|
||||
NSDate *now = [NSDate date];
|
||||
NSTimeInterval fuelSecondsElapsed = -[[MPiOSConfig get].developmentFuelChecked timeIntervalSinceDate:now];
|
||||
if (fuelSecondsElapsed > 3600 || ![MPiOSConfig get].developmentFuelChecked) {
|
||||
NSDate *now = [NSDate date], *checked = [MPiOSConfig get].developmentFuelChecked;
|
||||
if (!checked || 3600 < (fuelSecondsElapsed = [now timeIntervalSinceDate:checked])) {
|
||||
NSTimeInterval weeksElapsed = fuelSecondsElapsed / (3600 * 24 * 7 /* 1 week */); /* x weeks elapsed */
|
||||
NSTimeInterval fuelConsumed = weeklyFuelConsumption * weeksElapsed;
|
||||
NSTimeInterval fuelConsumed = MIN( fuelRemaining, weeklyFuelConsumption * weeksElapsed );
|
||||
fuelRemaining -= fuelConsumed;
|
||||
fuelInvested += fuelConsumed;
|
||||
[MPiOSConfig get].developmentFuelChecked = now;
|
||||
@ -277,56 +267,43 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
[MPiOSConfig get].developmentFuelInvested = @(fuelInvested);
|
||||
}
|
||||
|
||||
CGFloat fuelRatio = weeklyFuelConsumption == 0? 0: fuelRemaining / weeklyFuelConsumption; /* x weeks worth of fuel left */
|
||||
[self.fuelMeterConstraint updateConstant:MIN( 0.5f, fuelRatio - 0.5f ) * 160]; /* -80pt = 0 weeks left, 80pt = >=1 week left */
|
||||
self.fuelStatusLabel.text = strf( @"fuel left: %0.1f work hours\ninvested: %0.1f work hours", fuelRemaining, fuelInvested );
|
||||
CGFloat fuelRatio = weeklyFuelConsumption? fuelRemaining / weeklyFuelConsumption: 0; /* x weeks worth of fuel left */
|
||||
[self.fuelMeterConstraint updateConstant:MIN( 0.5f, fuelRatio - 0.5f ) * 160]; /* -80pt = 0 weeks left, +80pt = >=1 week left */
|
||||
self.fuelStatusLabel.text = strf( @"Fuel left: %0.1f work hours\nFunded: %0.1f work hours", fuelRemaining, fuelInvested );
|
||||
self.fuelStatusLabel.hidden = (fuelRemaining + fuelInvested) == 0;
|
||||
}
|
||||
|
||||
- (NSInteger)quantity {
|
||||
|
||||
return MAX( 1, (NSInteger)ceil( MP_FUEL_HOURLY_RATE * [self weeklyFuelConsumption] ) );
|
||||
}
|
||||
|
||||
- (CGFloat)weeklyFuelConsumption {
|
||||
|
||||
switch ((MPDevelopmentFuelConsumption)[[MPiOSConfig get].developmentFuelConsumption unsignedIntegerValue]) {
|
||||
case MPDevelopmentFuelConsumptionQuarterly:
|
||||
[self.fuelSpeedButton setTitle:@"1h / quarter" forState:UIControlStateNormal];
|
||||
return 1.f / 12 /* 12 weeks */;
|
||||
case MPDevelopmentFuelConsumptionMonthly:
|
||||
[self.fuelSpeedButton setTitle:@"1h / month" forState:UIControlStateNormal];
|
||||
return 1.f / 4 /* 4 weeks */;
|
||||
case MPDevelopmentFuelWeekly:
|
||||
[self.fuelSpeedButton setTitle:@"1h / week" forState:UIControlStateNormal];
|
||||
return 1.f;
|
||||
return 1.f /* 1 week */;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (void)showCellForProductWithIdentifier:(NSString *)productIdentifier ifProduct:(SKProduct *)product
|
||||
showingCells:(NSMutableArray *)showCells {
|
||||
- (NSString *)weeklyFuelConsumptionTitle {
|
||||
|
||||
if (![product.productIdentifier isEqualToString:productIdentifier])
|
||||
return;
|
||||
switch ((MPDevelopmentFuelConsumption)[[MPiOSConfig get].developmentFuelConsumption unsignedIntegerValue]) {
|
||||
case MPDevelopmentFuelConsumptionQuarterly:
|
||||
return @"1h / quarter";
|
||||
case MPDevelopmentFuelConsumptionMonthly:
|
||||
return @"1h / month";
|
||||
case MPDevelopmentFuelWeekly:
|
||||
return @"1h / week";
|
||||
}
|
||||
|
||||
MPStoreProductCell *cell = [self cellForProductIdentifier:productIdentifier];
|
||||
[showCells addObject:cell];
|
||||
|
||||
self.currencyFormatter.locale = product.priceLocale;
|
||||
BOOL purchased = [[MPiOSAppDelegate get] isFeatureUnlocked:productIdentifier];
|
||||
NSInteger quantity = [self quantityForProductIdentifier:productIdentifier];
|
||||
cell.priceLabel.text = purchased? @"": [self.currencyFormatter stringFromNumber:@([product.price floatValue] * quantity)];
|
||||
cell.titleLabel.text = product.localizedTitle;
|
||||
cell.descriptionLabel.text = product.localizedDescription;
|
||||
cell.purchasedIndicator.visible = purchased;
|
||||
}
|
||||
|
||||
- (NSInteger)quantityForProductIdentifier:(NSString *)productIdentifier {
|
||||
|
||||
if ([productIdentifier isEqualToString:MPProductFuel])
|
||||
return (NSInteger)(MP_FUEL_HOURLY_RATE * [self weeklyFuelConsumption] + .5f);
|
||||
|
||||
return 1;
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPStoreProductCell
|
||||
@end
|
||||
|
@ -1039,7 +1039,7 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="249.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="999" verticalCompressionResistancePriority="1000" text="© 2012-2014, Maarten Billemont (lhunath)" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sPw-mV-mFF">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="999" verticalCompressionResistancePriority="1000" text="© 2011-2017, Maarten Billemont (lhunath)" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sPw-mV-mFF">
|
||||
<rect key="frame" x="20" y="4" width="335" height="105"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="11"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
@ -1158,16 +1158,15 @@
|
||||
<collectionView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" minimumZoomScale="0.0" maximumZoomScale="0.0" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="aXw-tn-8Sj" userLabel="Password Collection">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<inset key="scrollIndicatorInsets" minX="0.0" minY="108" maxX="0.0" maxY="0.0"/>
|
||||
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="Mv1-29-TWx">
|
||||
<size key="itemSize" width="355" height="100"/>
|
||||
<size key="headerReferenceSize" width="0.0" height="0.0"/>
|
||||
<size key="footerReferenceSize" width="0.0" height="0.0"/>
|
||||
<inset key="sectionInset" minX="10" minY="10" maxX="10" maxY="10"/>
|
||||
<inset key="sectionInset" minX="10" minY="250" maxX="10" maxY="10"/>
|
||||
</collectionViewFlowLayout>
|
||||
<cells>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MPPasswordCell" id="W2g-yv-V3V" customClass="MPPasswordCell">
|
||||
<rect key="frame" x="10" y="10" width="355" height="100"/>
|
||||
<rect key="frame" x="10" y="250" width="355" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="355" height="100"/>
|
||||
@ -1247,12 +1246,12 @@
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="2tX-WK-ASq" userLabel="Password Container">
|
||||
<rect key="frame" x="0.0" y="20" width="355" height="43"/>
|
||||
<rect key="frame" x="0.0" y="19.5" width="355" height="44"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="CuzaSasy3*Rimo" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="blw-Ou-8I8" userLabel="Password">
|
||||
<rect key="frame" x="8" y="0.0" width="339" height="31"/>
|
||||
<rect key="frame" x="8" y="0.0" width="339" height="32"/>
|
||||
<color key="textColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="24"/>
|
||||
<fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="25"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="alphabet" keyboardAppearance="alert" returnKeyType="next"/>
|
||||
<connections>
|
||||
<action selector="textFieldDidChange:" destination="W2g-yv-V3V" eventType="editingChanged" id="gTE-0d-r2l"/>
|
||||
@ -1260,7 +1259,7 @@
|
||||
</connections>
|
||||
</textField>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="3" contentMode="left" text="> age of the universe" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="wfM-xz-roR" userLabel="Strength">
|
||||
<rect key="frame" x="0.0" y="31" width="355" height="12"/>
|
||||
<rect key="frame" x="0.0" y="32" width="355" height="12"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="10"/>
|
||||
<color key="textColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@ -1611,7 +1610,7 @@
|
||||
<outlet property="delegate" destination="nkY-z6-8jd" id="ENG-q5-XwX"/>
|
||||
</connections>
|
||||
</searchBar>
|
||||
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LEX-BK-PdS" userLabel="Bad Name Tip">
|
||||
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LEX-BK-PdS" userLabel="Bad Name Tip">
|
||||
<rect key="frame" x="37.5" y="86" width="300.5" height="75.5"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black_top.png" translatesAutoresizingMaskIntoConstraints="NO" id="Rt5-v4-I0R">
|
||||
@ -2550,31 +2549,29 @@ See </string>
|
||||
<scene sceneID="j3J-72-mva">
|
||||
<objects>
|
||||
<tableViewController automaticallyAdjustsScrollViewInsets="NO" id="pdl-xv-zjX" customClass="MPStoreViewController" sceneMemberID="viewController">
|
||||
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="400" sectionHeaderHeight="22" sectionFooterHeight="22" id="Yd8-L6-OMk">
|
||||
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="380" sectionHeaderHeight="22" sectionFooterHeight="22" id="Yd8-L6-OMk">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.12549020350000001" green="0.1411764771" blue="0.14901961389999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<inset key="scrollIndicatorInsets" minX="0.0" minY="64" maxX="0.0" maxY="49"/>
|
||||
<color key="separatorColor" red="0.37254901959999998" green="0.3921568627" blue="0.42745098040000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<sections>
|
||||
<tableViewSection id="efu-Mw-9J5">
|
||||
<cells>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPStoreProductCellGenerateLogin" id="JVW-tG-xxe" userLabel="Generate Login" customClass="MPStoreProductCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="400"/>
|
||||
<prototypes>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPStoreProductCell" id="JVW-tG-xxe" userLabel="Product" customClass="MPStoreProductCell">
|
||||
<rect key="frame" x="0.0" y="22" width="375" height="380"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="JVW-tG-xxe" id="CLQ-CW-NGn">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="399.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="379.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Generate Login Names" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Pax-1J-IZi">
|
||||
<rect key="frame" x="20" y="226" width="291" height="20"/>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Negare non possum" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Pax-1J-IZi">
|
||||
<rect key="frame" x="20" y="226" width="291" height="21"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalCompressionResistancePriority="749" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ra0-yS-99P">
|
||||
<rect key="frame" x="20" y="254" width="335" height="125"/>
|
||||
<string key="text">Master Password is great for making your passwords immune to loss, and it even lets you save your login name. But saved login names can't be recovered when all is lost. Generated login names use the same algorithm to generate a good login name to use for each of your sites. In addition, using unique non-identifying login names for your sites helps protect against companies working together to build a bigger picture on your identity.</string>
|
||||
<rect key="frame" x="20" y="255" width="335" height="104.5"/>
|
||||
<string key="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. At multis se probavit. Sic consequentibus vestris sublatis prima tolluntur. Nescio quo modo praetervolavit oratio. Reguli reiciendam; Theophrastus mediocriterne delectat, cum tractat locos ab Aristotele ante tractatos? Duo Reges: constructio interrete.</string>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@ -2592,7 +2589,7 @@ See </string>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="$0.95" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="68f-wn-UlS">
|
||||
<rect key="frame" x="319" y="226" width="36" height="20"/>
|
||||
<rect key="frame" x="319" y="226" width="36" height="21"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@ -2626,212 +2623,11 @@ See </string>
|
||||
<outlet property="titleLabel" destination="Pax-1J-IZi" id="kVH-n6-mDs"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPStoreProductCellGenerateAnswers" id="l1g-Ul-Vg8" userLabel="Generate Answers" customClass="MPStoreProductCell">
|
||||
<rect key="frame" x="0.0" y="400" width="375" height="400"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="l1g-Ul-Vg8" id="FWE-cE-L02">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="399.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Generate Security Answers" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Kkl-gT-YAO">
|
||||
<rect key="frame" x="20" y="226" width="291" height="20"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalCompressionResistancePriority="749" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yRH-27-edZ">
|
||||
<rect key="frame" x="20" y="254" width="335" height="125"/>
|
||||
<string key="text">The infamous security questions are in fact a veritable assault on your security. For starters, they weaken the protection of your account by allowing an attacker in by simply knowing enough about you, allowing him to bypass guessing your strong password. Arguably worse is the amount of highly personal and private information you're "willingly" divulging to these websites, under the assumption that only you know the answers. Generating security answers allows you to stop sharing your highly personal details and weakening your acccounts by generating unguessable answers to these questions.</string>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="thumb_generated_answers.png" translatesAutoresizingMaskIntoConstraints="NO" id="6km-y3-4gu">
|
||||
<rect key="frame" x="88.5" y="20" width="198" height="198"/>
|
||||
</imageView>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" tag="2" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="X2g-Go-2Hz">
|
||||
<rect key="frame" x="169.5" y="100" width="37" height="37"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="✔︎" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="N9y-ue-L8d">
|
||||
<rect key="frame" x="200.5" y="-6" width="93" height="132"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="110"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="$0.95" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9ct-IM-QKR">
|
||||
<rect key="frame" x="319" y="226" width="36" height="20"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="6km-y3-4gu" firstAttribute="centerY" secondItem="X2g-Go-2Hz" secondAttribute="centerY" id="8cn-tp-Vfc"/>
|
||||
<constraint firstItem="yRH-27-edZ" firstAttribute="leading" secondItem="FWE-cE-L02" secondAttribute="leading" constant="20" symbolic="YES" id="DSv-a4-VPg"/>
|
||||
<constraint firstItem="9ct-IM-QKR" firstAttribute="leading" secondItem="Kkl-gT-YAO" secondAttribute="trailing" constant="8" symbolic="YES" id="Fov-kQ-Wkn"/>
|
||||
<constraint firstItem="6km-y3-4gu" firstAttribute="top" secondItem="FWE-cE-L02" secondAttribute="top" constant="20" symbolic="YES" id="Kdx-UC-Q2x"/>
|
||||
<constraint firstItem="Kkl-gT-YAO" firstAttribute="leading" secondItem="FWE-cE-L02" secondAttribute="leading" constant="20" symbolic="YES" id="Nsd-7W-1Tq"/>
|
||||
<constraint firstItem="Kkl-gT-YAO" firstAttribute="bottom" secondItem="9ct-IM-QKR" secondAttribute="bottom" id="Oo3-Q5-Dzd"/>
|
||||
<constraint firstItem="N9y-ue-L8d" firstAttribute="centerX" secondItem="6km-y3-4gu" secondAttribute="trailing" constant="-40" id="PNi-RN-ybE"/>
|
||||
<constraint firstItem="Kkl-gT-YAO" firstAttribute="top" secondItem="6km-y3-4gu" secondAttribute="bottom" constant="8" symbolic="YES" id="UPs-VG-2ND"/>
|
||||
<constraint firstItem="6km-y3-4gu" firstAttribute="centerX" secondItem="X2g-Go-2Hz" secondAttribute="centerX" id="Zpt-vq-iVk"/>
|
||||
<constraint firstItem="yRH-27-edZ" firstAttribute="top" secondItem="Kkl-gT-YAO" secondAttribute="bottom" constant="8" symbolic="YES" id="eHf-L3-Ong"/>
|
||||
<constraint firstAttribute="trailing" secondItem="yRH-27-edZ" secondAttribute="trailing" constant="20" id="eUN-6Y-FEC"/>
|
||||
<constraint firstAttribute="centerX" secondItem="6km-y3-4gu" secondAttribute="centerX" id="gv6-jC-Gaa"/>
|
||||
<constraint firstAttribute="trailing" secondItem="9ct-IM-QKR" secondAttribute="trailing" constant="20" id="iAM-za-9Ev"/>
|
||||
<constraint firstAttribute="bottom" secondItem="yRH-27-edZ" secondAttribute="bottom" constant="20" symbolic="YES" id="krK-MM-VKm"/>
|
||||
<constraint firstItem="Kkl-gT-YAO" firstAttribute="top" secondItem="9ct-IM-QKR" secondAttribute="top" id="lie-rM-flE"/>
|
||||
<constraint firstItem="6km-y3-4gu" firstAttribute="top" secondItem="N9y-ue-L8d" secondAttribute="centerY" constant="-40" id="z16-aI-lwY"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="X2g-Go-2Hz" id="PvQ-bP-exW"/>
|
||||
<outlet property="descriptionLabel" destination="yRH-27-edZ" id="pfv-na-UM3"/>
|
||||
<outlet property="priceLabel" destination="9ct-IM-QKR" id="UTQ-L7-vbu"/>
|
||||
<outlet property="purchasedIndicator" destination="N9y-ue-L8d" id="Ppv-ay-M1J"/>
|
||||
<outlet property="titleLabel" destination="Kkl-gT-YAO" id="cHy-iU-oHr"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPStoreProductCellOSIntegration" id="9Na-CL-jBq" userLabel="iOS Integration" customClass="MPStoreProductCell">
|
||||
<rect key="frame" x="0.0" y="800" width="375" height="400"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="9Na-CL-jBq" id="ETY-Ou-DW7">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="399.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="iOS Integration" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Zch-DS-J3I">
|
||||
<rect key="frame" x="20" y="226" width="244" height="20"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalCompressionResistancePriority="749" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="riF-bB-x5g">
|
||||
<rect key="frame" x="20" y="254" width="335" height="125"/>
|
||||
<string key="text">Up to now, the best way to use your passwords in other iOS apps was by copy/pasting them from Master Password. With iOS integration, you can access your Master Password passwords directly from other applications, without having to switch back and forth between it and Master Password.</string>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="thumb_ios_integration.png" translatesAutoresizingMaskIntoConstraints="NO" id="yAc-Sm-IVo">
|
||||
<rect key="frame" x="88.5" y="20" width="198" height="198"/>
|
||||
</imageView>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" tag="2" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="yUe-TX-fli">
|
||||
<rect key="frame" x="169.5" y="100" width="37" height="37"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="✔︎" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ec8-P9-KPY">
|
||||
<rect key="frame" x="200.5" y="-6" width="93" height="132"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="110"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Coming Soon" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3jH-eX-9N2">
|
||||
<rect key="frame" x="272" y="226" width="83" height="20"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Zch-DS-J3I" firstAttribute="top" secondItem="yAc-Sm-IVo" secondAttribute="bottom" constant="8" symbolic="YES" id="0M4-0I-kCB"/>
|
||||
<constraint firstItem="ec8-P9-KPY" firstAttribute="centerX" secondItem="yAc-Sm-IVo" secondAttribute="trailing" constant="-40" id="31k-Co-bGU"/>
|
||||
<constraint firstItem="yAc-Sm-IVo" firstAttribute="top" secondItem="ETY-Ou-DW7" secondAttribute="top" constant="20" symbolic="YES" id="PnQ-1d-y9S"/>
|
||||
<constraint firstItem="Zch-DS-J3I" firstAttribute="bottom" secondItem="3jH-eX-9N2" secondAttribute="bottom" id="XMk-An-t5v"/>
|
||||
<constraint firstItem="riF-bB-x5g" firstAttribute="top" secondItem="Zch-DS-J3I" secondAttribute="bottom" constant="8" symbolic="YES" id="ZMH-Sv-ttk"/>
|
||||
<constraint firstAttribute="trailing" secondItem="3jH-eX-9N2" secondAttribute="trailing" constant="20" id="diQ-Rs-Vrj"/>
|
||||
<constraint firstAttribute="centerX" secondItem="yAc-Sm-IVo" secondAttribute="centerX" id="fsX-dO-EGx"/>
|
||||
<constraint firstItem="Zch-DS-J3I" firstAttribute="top" secondItem="3jH-eX-9N2" secondAttribute="top" id="gZU-lV-XZJ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="riF-bB-x5g" secondAttribute="bottom" constant="20" symbolic="YES" id="hQZ-Qb-A7u"/>
|
||||
<constraint firstAttribute="trailing" secondItem="riF-bB-x5g" secondAttribute="trailing" constant="20" id="iCn-kq-xNy"/>
|
||||
<constraint firstItem="yAc-Sm-IVo" firstAttribute="centerX" secondItem="yUe-TX-fli" secondAttribute="centerX" id="kUQ-lP-EQP"/>
|
||||
<constraint firstItem="3jH-eX-9N2" firstAttribute="leading" secondItem="Zch-DS-J3I" secondAttribute="trailing" constant="8" symbolic="YES" id="qqB-1E-QPE"/>
|
||||
<constraint firstItem="yAc-Sm-IVo" firstAttribute="top" secondItem="ec8-P9-KPY" secondAttribute="centerY" constant="-40" id="swf-Ua-uwD"/>
|
||||
<constraint firstItem="yAc-Sm-IVo" firstAttribute="centerY" secondItem="yUe-TX-fli" secondAttribute="centerY" id="tha-UC-Hwi"/>
|
||||
<constraint firstItem="Zch-DS-J3I" firstAttribute="leading" secondItem="ETY-Ou-DW7" secondAttribute="leading" constant="20" symbolic="YES" id="uV9-xY-ayE"/>
|
||||
<constraint firstItem="riF-bB-x5g" firstAttribute="leading" secondItem="ETY-Ou-DW7" secondAttribute="leading" constant="20" symbolic="YES" id="y9l-fO-HMK"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="yUe-TX-fli" id="DH6-pK-fse"/>
|
||||
<outlet property="descriptionLabel" destination="riF-bB-x5g" id="3v9-6H-PAK"/>
|
||||
<outlet property="priceLabel" destination="3jH-eX-9N2" id="agT-az-dVU"/>
|
||||
<outlet property="purchasedIndicator" destination="ec8-P9-KPY" id="M39-bc-Ksp"/>
|
||||
<outlet property="titleLabel" destination="Zch-DS-J3I" id="cY2-FQ-q69"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPStoreProductCellTouchID" id="8en-6R-GvR" userLabel="TouchID" customClass="MPStoreProductCell">
|
||||
<rect key="frame" x="0.0" y="1200" width="375" height="400"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="8en-6R-GvR" id="NKB-rd-1Vy">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="399.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="TouchID Login" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="e1D-jp-GBs">
|
||||
<rect key="frame" x="20" y="226" width="291.5" height="20"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalCompressionResistancePriority="749" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Yxc-Lr-382">
|
||||
<rect key="frame" x="20" y="254" width="335" height="125"/>
|
||||
<string key="text">Since the iPhone 5s, all iPhones are now equipped with an advanced Touch ID fingerprint sensor in the home button. This sensor allows you to quickly and easily identify yourself to the system. With Touch ID support, you will be able to skip the step of entering your Master Password manually and gain the ability to unlock your user using Touch ID instead.</string>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="thumb_touch_id.png" translatesAutoresizingMaskIntoConstraints="NO" id="8v7-JH-mzu">
|
||||
<rect key="frame" x="88.5" y="20" width="198" height="198"/>
|
||||
</imageView>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" tag="2" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="Dv5-t7-lL1">
|
||||
<rect key="frame" x="169.5" y="100" width="37" height="37"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="✔︎" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yZX-ns-8oV">
|
||||
<rect key="frame" x="200.5" y="-6" width="93" height="132"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="110"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="$0.95" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZGg-O6-rsg">
|
||||
<rect key="frame" x="319.5" y="226" width="35.5" height="20"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Yxc-Lr-382" firstAttribute="top" secondItem="e1D-jp-GBs" secondAttribute="bottom" constant="8" symbolic="YES" id="BMp-dh-Elb"/>
|
||||
<constraint firstItem="e1D-jp-GBs" firstAttribute="top" secondItem="8v7-JH-mzu" secondAttribute="bottom" constant="8" symbolic="YES" id="CCe-dk-eBT"/>
|
||||
<constraint firstItem="Dv5-t7-lL1" firstAttribute="centerY" secondItem="8v7-JH-mzu" secondAttribute="centerY" id="DUJ-Xb-503"/>
|
||||
<constraint firstItem="e1D-jp-GBs" firstAttribute="bottom" secondItem="ZGg-O6-rsg" secondAttribute="bottom" id="MPG-Zj-vDr"/>
|
||||
<constraint firstItem="e1D-jp-GBs" firstAttribute="leading" secondItem="NKB-rd-1Vy" secondAttribute="leading" constant="20" symbolic="YES" id="N8Z-X2-ir7"/>
|
||||
<constraint firstItem="8v7-JH-mzu" firstAttribute="top" secondItem="NKB-rd-1Vy" secondAttribute="top" constant="20" symbolic="YES" id="PEc-aa-i3N"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ZGg-O6-rsg" secondAttribute="trailing" constant="20" id="QAy-Rp-XJc"/>
|
||||
<constraint firstItem="Yxc-Lr-382" firstAttribute="leading" secondItem="NKB-rd-1Vy" secondAttribute="leading" constant="20" symbolic="YES" id="UvU-wL-3WN"/>
|
||||
<constraint firstAttribute="centerX" secondItem="8v7-JH-mzu" secondAttribute="centerX" id="XVh-6p-4qT"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Yxc-Lr-382" secondAttribute="trailing" constant="20" id="YMA-ID-9KD"/>
|
||||
<constraint firstItem="Dv5-t7-lL1" firstAttribute="centerX" secondItem="8v7-JH-mzu" secondAttribute="centerX" id="bWe-Wx-6CH"/>
|
||||
<constraint firstItem="8v7-JH-mzu" firstAttribute="top" secondItem="yZX-ns-8oV" secondAttribute="centerY" constant="-40" id="n0h-tr-yA0"/>
|
||||
<constraint firstItem="e1D-jp-GBs" firstAttribute="top" secondItem="ZGg-O6-rsg" secondAttribute="top" id="oZN-4h-Awv"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Yxc-Lr-382" secondAttribute="bottom" constant="20" symbolic="YES" id="pFY-vd-3UR"/>
|
||||
<constraint firstItem="ZGg-O6-rsg" firstAttribute="leading" secondItem="e1D-jp-GBs" secondAttribute="trailing" constant="8" symbolic="YES" id="stO-51-Mlk"/>
|
||||
<constraint firstItem="yZX-ns-8oV" firstAttribute="centerX" secondItem="8v7-JH-mzu" secondAttribute="trailing" constant="-40" id="yyS-FS-gvJ"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="Dv5-t7-lL1" id="AFu-Dd-TgU"/>
|
||||
<outlet property="descriptionLabel" destination="Yxc-Lr-382" id="47I-83-lgP"/>
|
||||
<outlet property="priceLabel" destination="ZGg-O6-rsg" id="dAn-xu-gut"/>
|
||||
<outlet property="purchasedIndicator" destination="yZX-ns-8oV" id="7x0-eq-oSs"/>
|
||||
<outlet property="titleLabel" destination="e1D-jp-GBs" id="jFw-dm-vp6"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPStoreProductCellFuel" id="le3-Q5-MSO" userLabel="Fuel" customClass="MPStoreProductCell">
|
||||
<rect key="frame" x="0.0" y="1600" width="375" height="400"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPStoreFuelProductCell" id="le3-Q5-MSO" userLabel="Fuel" customClass="MPStoreFuelProductCell">
|
||||
<rect key="frame" x="0.0" y="402" width="375" height="380"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="le3-Q5-MSO" id="SzQ-Y5-XIF">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="399.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="379.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Fuel Top-Up" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Jnv-uN-xeg">
|
||||
@ -2841,14 +2637,8 @@ See </string>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalCompressionResistancePriority="749" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fz2-AO-aGW">
|
||||
<rect key="frame" x="20" y="254" width="335" height="125"/>
|
||||
<string key="text">You really love Master Password and how it's solving your password problems. You're eager to encourage the maintenance, technical support and development of new features. I am a one-man shop, fuel enables me to allocate more work hours to Master Password.
|
||||
|
||||
UPCOMING:
|
||||
– Safari integration
|
||||
– Touch ID support
|
||||
– Multi-platform support
|
||||
– Your feedback</string>
|
||||
<rect key="frame" x="20" y="254" width="335" height="105.5"/>
|
||||
<string key="text">You really love Master Password and how it's solving your password problems. You're eager to encourage the maintenance, technical support and development of new features. I am a one-man shop, fuel enables me to allocate more work hours to Master Password.</string>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@ -2857,7 +2647,7 @@ UPCOMING:
|
||||
<rect key="frame" x="88.5" y="20" width="198" height="198"/>
|
||||
</imageView>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" tag="2" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="eS4-59-Xny">
|
||||
<rect key="frame" x="169.5" y="100" width="37" height="37"/>
|
||||
<rect key="frame" x="169.5" y="101" width="37" height="37"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="$2.95" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EbU-DV-fKF">
|
||||
<rect key="frame" x="320" y="226" width="35" height="20"/>
|
||||
@ -2882,9 +2672,9 @@ UPCOMING:
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kYb-j4-32C">
|
||||
<rect key="frame" x="20" y="64" width="131.5" height="29"/>
|
||||
<string key="text">fuel left: 0.3 work hours
|
||||
invested: 3.7 work hours</string>
|
||||
<rect key="frame" x="20" y="64" width="132" height="29"/>
|
||||
<string key="text">Fuel left: 0.3 work hours
|
||||
Invested: 3.7 work hours</string>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@ -2917,93 +2707,91 @@ invested: 3.7 work hours</string>
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="eS4-59-Xny" id="kGW-fn-VqH"/>
|
||||
<outlet property="descriptionLabel" destination="fz2-AO-aGW" id="xkc-xV-Z6Y"/>
|
||||
<outlet property="fuelMeterConstraint" destination="eMa-Gj-BUc" id="1uc-fa-b20"/>
|
||||
<outlet property="fuelSpeedButton" destination="dsR-fr-dY4" id="7yS-9g-xkM"/>
|
||||
<outlet property="fuelStatusLabel" destination="kYb-j4-32C" id="ctc-ES-lGR"/>
|
||||
<outlet property="priceLabel" destination="EbU-DV-fKF" id="pg2-8o-7We"/>
|
||||
<outlet property="titleLabel" destination="Jnv-uN-xeg" id="Kxi-RE-ipa"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection id="hN1-J4-w3w">
|
||||
<cells>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPStoreCellSpinner" rowHeight="150" id="u3P-ng-YHc" userLabel="Spinner">
|
||||
<rect key="frame" x="0.0" y="2000" width="375" height="150"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPStoreCellSpinner" rowHeight="170" id="LOh-72-Ifp" userLabel="Spinner">
|
||||
<rect key="frame" x="0.0" y="782" width="375" height="170"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="u3P-ng-YHc" id="y85-0Q-tbK">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="149.5"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="LOh-72-Ifp" id="gjr-8l-JJ0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="169.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" animating="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="Vjt-7c-BJ4">
|
||||
<rect key="frame" x="169" y="20" width="37" height="21"/>
|
||||
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" animating="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="MIJ-rP-BeU">
|
||||
<rect key="frame" x="169" y="20" width="37" height="37"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Loading products..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ARC-xH-0U0">
|
||||
<rect key="frame" x="115" y="81" width="145.5" height="20"/>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Loading products..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NPg-it-juF">
|
||||
<rect key="frame" x="115" y="97" width="145.5" height="24.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="ARC-xH-0U0" secondAttribute="bottom" constant="48" id="5L9-Ag-d1G"/>
|
||||
<constraint firstAttribute="centerX" secondItem="ARC-xH-0U0" secondAttribute="centerX" id="asI-QK-u6O"/>
|
||||
<constraint firstItem="ARC-xH-0U0" firstAttribute="top" secondItem="Vjt-7c-BJ4" secondAttribute="bottom" constant="40" id="g1T-rA-vOW"/>
|
||||
<constraint firstAttribute="centerX" secondItem="Vjt-7c-BJ4" secondAttribute="centerX" id="j2l-mA-Duf"/>
|
||||
<constraint firstItem="Vjt-7c-BJ4" firstAttribute="top" secondItem="y85-0Q-tbK" secondAttribute="top" constant="20" id="v16-PA-82f"/>
|
||||
<constraint firstAttribute="centerX" secondItem="MIJ-rP-BeU" secondAttribute="centerX" id="DXM-74-LKR"/>
|
||||
<constraint firstAttribute="bottom" secondItem="NPg-it-juF" secondAttribute="bottom" constant="48" id="aCB-sK-ZCP"/>
|
||||
<constraint firstAttribute="centerX" secondItem="NPg-it-juF" secondAttribute="centerX" id="fGb-Sq-nBz"/>
|
||||
<constraint firstItem="MIJ-rP-BeU" firstAttribute="top" secondItem="gjr-8l-JJ0" secondAttribute="top" constant="20" id="nh6-ca-qKI"/>
|
||||
<constraint firstItem="NPg-it-juF" firstAttribute="top" secondItem="MIJ-rP-BeU" secondAttribute="bottom" constant="40" id="s5N-EF-Rd4"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPStoreCellFooter" id="UUA-xl-CAh" userLabel="Footer">
|
||||
<rect key="frame" x="0.0" y="2150" width="375" height="400"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPStoreCellFooter" rowHeight="100" id="jsY-TE-4y5" userLabel="Footer">
|
||||
<rect key="frame" x="0.0" y="952" width="375" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="UUA-xl-CAh" id="4Zu-Ig-Ws4">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="399.5"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="jsY-TE-4y5" id="guB-Eb-KpI">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="99.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="749" verticalCompressionResistancePriority="751" text="© 2012-2014, Maarten Billemont (lhunath)" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DxV-2L-bxL">
|
||||
<rect key="frame" x="20" y="4" width="335" height="305.5"/>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999998807907104" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="749" verticalCompressionResistancePriority="751" text="© 2012-2014, Maarten Billemont (lhunath)" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="26U-st-xNs">
|
||||
<rect key="frame" x="20" y="4" width="335" height="21.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="11"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" verticalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IOk-WZ-HJ8">
|
||||
<rect key="frame" x="20" y="317.5" width="335" height="27"/>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" verticalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="lQ1-b9-Xp4">
|
||||
<rect key="frame" x="20" y="33.5" width="335" height="27"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="12"/>
|
||||
<state key="normal" title="Restore Previous Purchases">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="restorePurchases:" destination="pdl-xv-zjX" eventType="touchUpInside" id="lKu-PL-PfX"/>
|
||||
<action selector="restorePurchases:" destination="pdl-xv-zjX" eventType="touchUpInside" id="Q8M-ud-OHL"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bCe-a3-cDC">
|
||||
<rect key="frame" x="8" y="352.5" width="359" height="27"/>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eus-kQ-emn">
|
||||
<rect key="frame" x="8" y="68.5" width="359" height="27"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/>
|
||||
<state key="normal" title="Send Thanks">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="sendThanks:" destination="pdl-xv-zjX" eventType="touchUpInside" id="r5l-3U-jCA"/>
|
||||
<action selector="sendThanks:" destination="pdl-xv-zjX" eventType="touchUpInside" id="IrU-IR-em1"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="bCe-a3-cDC" secondAttribute="bottom" constant="20" symbolic="YES" id="84k-uv-gb7"/>
|
||||
<constraint firstAttribute="trailing" secondItem="IOk-WZ-HJ8" secondAttribute="trailing" constant="20" symbolic="YES" id="CuJ-h7-aGJ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="bCe-a3-cDC" secondAttribute="trailing" constant="8" id="Lfp-Hx-vLN"/>
|
||||
<constraint firstAttribute="trailing" secondItem="DxV-2L-bxL" secondAttribute="trailing" constant="20" symbolic="YES" id="QHU-Jw-LPy"/>
|
||||
<constraint firstItem="bCe-a3-cDC" firstAttribute="top" secondItem="IOk-WZ-HJ8" secondAttribute="bottom" constant="8" symbolic="YES" id="XJh-dK-J4C"/>
|
||||
<constraint firstItem="DxV-2L-bxL" firstAttribute="leading" secondItem="4Zu-Ig-Ws4" secondAttribute="leading" constant="20" symbolic="YES" id="fAD-At-gqS"/>
|
||||
<constraint firstItem="DxV-2L-bxL" firstAttribute="top" secondItem="4Zu-Ig-Ws4" secondAttribute="top" constant="4" id="hTN-Cx-hOS"/>
|
||||
<constraint firstItem="bCe-a3-cDC" firstAttribute="leading" secondItem="4Zu-Ig-Ws4" secondAttribute="leading" constant="8" id="l4A-fH-9fA"/>
|
||||
<constraint firstItem="IOk-WZ-HJ8" firstAttribute="top" secondItem="DxV-2L-bxL" secondAttribute="bottom" constant="8" symbolic="YES" id="lq6-sj-DVg"/>
|
||||
<constraint firstItem="IOk-WZ-HJ8" firstAttribute="leading" secondItem="4Zu-Ig-Ws4" secondAttribute="leading" constant="20" symbolic="YES" id="mx2-Jk-5jo"/>
|
||||
<constraint firstItem="lQ1-b9-Xp4" firstAttribute="leading" secondItem="guB-Eb-KpI" secondAttribute="leading" constant="20" symbolic="YES" id="A2j-I5-HlU"/>
|
||||
<constraint firstAttribute="bottom" secondItem="eus-kQ-emn" secondAttribute="bottom" constant="4" id="Cw6-qh-jbe"/>
|
||||
<constraint firstAttribute="trailing" secondItem="lQ1-b9-Xp4" secondAttribute="trailing" constant="20" symbolic="YES" id="I2K-u3-cOn"/>
|
||||
<constraint firstItem="26U-st-xNs" firstAttribute="top" secondItem="guB-Eb-KpI" secondAttribute="top" constant="4" id="I2p-hX-EOW"/>
|
||||
<constraint firstItem="lQ1-b9-Xp4" firstAttribute="top" secondItem="26U-st-xNs" secondAttribute="bottom" constant="8" symbolic="YES" id="IXV-6Z-hyF"/>
|
||||
<constraint firstItem="eus-kQ-emn" firstAttribute="leading" secondItem="guB-Eb-KpI" secondAttribute="leading" constant="8" id="Kkk-AE-iWm"/>
|
||||
<constraint firstItem="eus-kQ-emn" firstAttribute="top" secondItem="lQ1-b9-Xp4" secondAttribute="bottom" constant="8" symbolic="YES" id="UMw-e1-O9o"/>
|
||||
<constraint firstAttribute="trailing" secondItem="26U-st-xNs" secondAttribute="trailing" constant="20" symbolic="YES" id="eOG-B5-WwQ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="eus-kQ-emn" secondAttribute="trailing" constant="8" id="hYo-sy-8wY"/>
|
||||
<constraint firstItem="26U-st-xNs" firstAttribute="leading" secondItem="guB-Eb-KpI" secondAttribute="leading" constant="20" symbolic="YES" id="xfW-Sz-Kuz"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
</sections>
|
||||
</prototypes>
|
||||
<sections/>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="pdl-xv-zjX" id="ZOr-qJ-zl2"/>
|
||||
<outlet property="delegate" destination="pdl-xv-zjX" id="xkn-ZJ-BPX"/>
|
||||
@ -3012,17 +2800,6 @@ invested: 3.7 work hours</string>
|
||||
<tabBarItem key="tabBarItem" title="Store" image="icon_star-hollow.png" id="j4c-Kp-fnH"/>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<nil key="simulatedBottomBarMetrics"/>
|
||||
<connections>
|
||||
<outlet property="fuelCell" destination="le3-Q5-MSO" id="oAk-6g-cFj"/>
|
||||
<outlet property="fuelMeterConstraint" destination="eMa-Gj-BUc" id="9iF-EO-UU6"/>
|
||||
<outlet property="fuelSpeedButton" destination="dsR-fr-dY4" id="XGI-PE-9mh"/>
|
||||
<outlet property="fuelStatusLabel" destination="kYb-j4-32C" id="o5R-0u-kGL"/>
|
||||
<outlet property="generateAnswersCell" destination="l1g-Ul-Vg8" id="GlG-iZ-7FP"/>
|
||||
<outlet property="generateLoginCell" destination="JVW-tG-xxe" id="PXM-WX-8Qe"/>
|
||||
<outlet property="iOSIntegrationCell" destination="9Na-CL-jBq" id="LSO-OV-9KA"/>
|
||||
<outlet property="loadingCell" destination="u3P-ng-YHc" id="gzb-K3-nKN"/>
|
||||
<outlet property="touchIDCell" destination="8en-6R-GvR" id="edt-KM-iU1"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="WvF-bk-cgx" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
@ -3327,11 +3104,11 @@ You can temporarily reveal a password by holding your finger down on the site's
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" barStyle="black" translatesAutoresizingMaskIntoConstraints="NO" id="aNU-Nq-clY">
|
||||
<rect key="frame" x="0.0" y="342.5" width="375" height="324.5"/>
|
||||
<rect key="frame" x="0.0" y="341.5" width="375" height="325.5"/>
|
||||
<items/>
|
||||
</toolbar>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="You have sites that can be upgraded." lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3Qi-GN-vhQ" userLabel="Title Label">
|
||||
<rect key="frame" x="16" y="362.5" width="343" height="20"/>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Lorem ipsum dolor sit amet." lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3Qi-GN-vhQ" userLabel="Title Label">
|
||||
<rect key="frame" x="16" y="361.5" width="343" height="21"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@ -3340,49 +3117,13 @@ You can temporarily reveal a password by holding your finger down on the site's
|
||||
<rect key="frame" x="16" y="390.5" width="343" height="216.5"/>
|
||||
<attributedString key="attributedText">
|
||||
<fragment>
|
||||
<string key="content">Upgrading a site allows it to take advantage of
|
||||
the latest improvements in the Master Password algorithm.
|
||||
</string>
|
||||
<attributes>
|
||||
<color key="NSBackgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="NSColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<font key="NSFont" size="12" name="Exo2.0-Regular"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="left" lineBreakMode="wordWrapping" baseWritingDirection="natural"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
<fragment>
|
||||
<string key="content">
|
||||
When you upgrade a site, </string>
|
||||
<attributes>
|
||||
<color key="NSBackgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="NSColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<font key="NSFont" size="12" name="Exo2.0-Regular"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="justified" lineBreakMode="wordWrapping" baseWritingDirection="natural"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
<fragment content="a new and stronger password will be generated for it">
|
||||
<attributes>
|
||||
<color key="NSBackgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="NSColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<font key="NSFont" size="12" name="Exo2.0-Bold"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="justified" lineBreakMode="wordWrapping" baseWritingDirection="natural"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
<fragment>
|
||||
<string key="content">. To upgrade a site, first log into the site, navigate to your account preferences where you can change the site's password. Make sure you fill in any "current password" fields on the website first, then press the upgrade button here to get your new site password.
|
||||
</string>
|
||||
<attributes>
|
||||
<color key="NSBackgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="NSColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<font key="NSFont" size="12" name="Exo2.0-Regular"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="justified" lineBreakMode="wordWrapping" baseWritingDirection="natural"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
<fragment>
|
||||
<string key="content">
|
||||
You can then update your site's account with the new and stronger password.
|
||||
<mutableString key="content">Prodest, inquit, mihi eo esse animo. Sed residamus, inquit, si placet. Istam voluptatem, inquit, Epicurus ignorat?
|
||||
|
||||
</string>
|
||||
Qualem igitur hominem natura inchoavit? Duo Reges: constructio interrete. Iam id ipsum absurdum, maximum malum neglegi. Quod cum dixissent, ille contra.
|
||||
|
||||
Nihil sane. Erat enim Polemonis. Sumenda potius quam expetenda. Sed ad illum redeo. Equidem e Cn.
|
||||
|
||||
Ut in geometria, prima si dederis, danda sunt omnia. Nonne igitur tibi videntur, inquit, mala? Quasi vero, inquit, perpetua oratio rhetorum solum, non etiam philosophorum sit. Tuo vero id quidem, inquam, arbitratu. A mene tu? Quid enim ab antiquis ex eo genere, quod ad disserendum valet, praetermissum est.</mutableString>
|
||||
<attributes>
|
||||
<color key="NSBackgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="NSColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
@ -3390,14 +3131,6 @@ You can then update your site's account with the new and stronger password.
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="left" lineBreakMode="wordWrapping" baseWritingDirection="natural"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
<fragment content="The upgrade button can be found in the site's settings and looks like this:">
|
||||
<attributes>
|
||||
<color key="NSBackgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="NSColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<font key="NSFont" size="12" name="Exo2.0-Regular"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
</attributedString>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
@ -3528,10 +3261,7 @@ You can then update your site's account with the new and stronger password.
|
||||
<image name="initial.png" width="320" height="568"/>
|
||||
<image name="meter_fuel.png" width="11" height="9"/>
|
||||
<image name="thumb_fuel.png" width="198" height="198"/>
|
||||
<image name="thumb_generated_answers.png" width="198" height="198"/>
|
||||
<image name="thumb_generated_login.png" width="198" height="198"/>
|
||||
<image name="thumb_ios_integration.png" width="198" height="198"/>
|
||||
<image name="thumb_touch_id.png" width="198" height="198"/>
|
||||
<image name="tip_basic_black.png" width="210" height="60"/>
|
||||
<image name="tip_basic_black_top.png" width="210" height="60"/>
|
||||
<image name="ui_spinner.png" width="75" height="75"/>
|
||||
|
Loading…
Reference in New Issue
Block a user