Clean up old UI.
[ADDED] Password strength to type cells. [FIXED] Lots of misc UI fixes. [ADDED] Footer links in pull-down.
This commit is contained in:
parent
c8eb2fdde7
commit
c1c15ddb89
@ -1,41 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPAppViewController
|
||||
//
|
||||
// Created by Maarten Billemont on 2012-08-31.
|
||||
// Copyright 2012 lhunath (Maarten Billemont). All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPAppViewController.h"
|
||||
|
||||
@implementation MPAppViewController {
|
||||
}
|
||||
|
||||
- (IBAction)gorillas:(UIButton *)sender {
|
||||
|
||||
MPCheckpoint( MPCheckpointApp, @{
|
||||
@"app" : @"gorillas"
|
||||
} );
|
||||
|
||||
[UIApp openURL:[NSURL URLWithString:@"http://itunes.apple.com/app/lyndir/gorillas/id302275459?mt=8"]];
|
||||
}
|
||||
|
||||
- (IBAction)deblock:(UIButton *)sender {
|
||||
|
||||
MPCheckpoint( MPCheckpointApp, @{
|
||||
@"app" : @"deblock"
|
||||
} );
|
||||
|
||||
[UIApp openURL:[NSURL URLWithString:@"http://itunes.apple.com/app/lyndir/deblock/id325058485?mt=8"]];
|
||||
}
|
||||
|
||||
@end
|
@ -1,26 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPAppsViewController
|
||||
//
|
||||
// Created by Maarten Billemont on 2012-08-31.
|
||||
// Copyright 2012 lhunath (Maarten Billemont). All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface MPAppsViewController : UIViewController<UIPageViewControllerDataSource, UIPageViewControllerDelegate>
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UIImageView *pagePositionView;
|
||||
|
||||
- (IBAction)exit;
|
||||
|
||||
@end
|
@ -1,117 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPAppsViewController
|
||||
//
|
||||
// Created by Maarten Billemont on 2012-08-31.
|
||||
// Copyright 2012 lhunath (Maarten Billemont). All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPAppsViewController.h"
|
||||
|
||||
@interface MPAppsViewController()
|
||||
|
||||
@property(nonatomic, strong) NSMutableArray *pageVCs;
|
||||
@property(nonatomic, strong) UIPageViewController *pageViewController;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPAppsViewController {
|
||||
}
|
||||
|
||||
@synthesize pagePositionView = _pagePositionView;
|
||||
@synthesize pageVCs = _pageVCs;
|
||||
@synthesize pageViewController = _pageViewController;
|
||||
|
||||
- (void)viewDidLoad {
|
||||
|
||||
self.pageVCs = [NSMutableArray array];
|
||||
UIViewController *vc;
|
||||
@try {
|
||||
for (NSUInteger p = 0;
|
||||
(vc = [self.storyboard instantiateViewControllerWithIdentifier:PearlString( @"MPAppViewController_%lu", (long)p )]);
|
||||
++p)
|
||||
[self.pageVCs addObject:vc];
|
||||
}
|
||||
@catch (NSException *e) {
|
||||
if (![e.name isEqualToString:NSInvalidArgumentException])
|
||||
[e raise];
|
||||
}
|
||||
|
||||
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl
|
||||
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
|
||||
options:nil];
|
||||
self.pageViewController.dataSource = self;
|
||||
self.pageViewController.delegate = self;
|
||||
self.pageViewController.view.frame = CGRectFromOriginWithSize( CGPointZero, self.pagePositionView.bounds.size );
|
||||
[self addChildViewController:self.pageViewController];
|
||||
[self.pagePositionView addSubview:self.pageViewController.view];
|
||||
[self.pageViewController didMoveToParentViewController:self];
|
||||
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
|
||||
[UIApp setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
|
||||
MPCheckpoint( MPCheckpointApps, nil );
|
||||
|
||||
[self.pageViewController setViewControllers:@[ (self.pageVCs)[1] ] direction:UIPageViewControllerNavigationDirectionForward
|
||||
animated:NO completion:nil];
|
||||
|
||||
[super viewWillAppear:animated];
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
|
||||
[self.pageViewController setViewControllers:@[ (self.pageVCs)[0] ] direction:UIPageViewControllerNavigationDirectionForward
|
||||
animated:YES completion:nil];
|
||||
|
||||
[super viewDidAppear:animated];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
|
||||
[UIApp setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
|
||||
|
||||
[super viewWillDisappear:animated];
|
||||
}
|
||||
|
||||
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
|
||||
|
||||
return UIInterfaceOrientationPortrait;
|
||||
}
|
||||
|
||||
- (BOOL)shouldAutorotate {
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
|
||||
viewControllerBeforeViewController:(UIViewController *)viewController {
|
||||
|
||||
NSUInteger vcIndex = [self.pageVCs indexOfObject:viewController];
|
||||
return (self.pageVCs)[(vcIndex + [self.pageVCs count] - 1) % self.pageVCs.count];
|
||||
}
|
||||
|
||||
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
|
||||
viewControllerAfterViewController:(UIViewController *)viewController {
|
||||
|
||||
NSUInteger vcIndex = [self.pageVCs indexOfObject:viewController];
|
||||
return (self.pageVCs)[(vcIndex + 1) % self.pageVCs.count];
|
||||
}
|
||||
|
||||
- (IBAction)exit {
|
||||
|
||||
[self dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
|
||||
@end
|
@ -206,13 +206,11 @@ const long MPAvatarAdd = 10000;
|
||||
}
|
||||
|
||||
switch (self.mode) {
|
||||
|
||||
case MPAvatarModeLowered: {
|
||||
|
||||
self.avatarSizeConstraint.constant = self.avatarImageView.image.size.height;
|
||||
self.avatarRaisedConstraint.priority = UILayoutPriorityDefaultLow;
|
||||
self.avatarToTopConstraint.priority = UILayoutPriorityDefaultLow;
|
||||
self.nameToCenterConstraint.priority = UILayoutPriorityDefaultLow;
|
||||
[self.avatarSizeConstraint layoutWithConstant:self.avatarImageView.image.size.height];
|
||||
[self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
self.nameContainer.alpha = self.visibility;
|
||||
self.nameContainer.backgroundColor = [UIColor clearColor];
|
||||
self.avatarImageView.alpha = self.visibility / 0.7f + 0.3f;
|
||||
@ -220,10 +218,10 @@ const long MPAvatarAdd = 10000;
|
||||
break;
|
||||
}
|
||||
case MPAvatarModeRaisedButInactive: {
|
||||
self.avatarSizeConstraint.constant = self.avatarImageView.image.size.height;
|
||||
self.avatarRaisedConstraint.priority = UILayoutPriorityDefaultHigh;
|
||||
self.avatarToTopConstraint.priority = UILayoutPriorityDefaultLow;
|
||||
self.nameToCenterConstraint.priority = UILayoutPriorityDefaultLow;
|
||||
[self.avatarSizeConstraint layoutWithConstant:self.avatarImageView.image.size.height];
|
||||
[self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
self.nameContainer.alpha = self.visibility;
|
||||
self.nameContainer.backgroundColor = [UIColor clearColor];
|
||||
self.avatarImageView.alpha = 0;
|
||||
@ -231,10 +229,10 @@ const long MPAvatarAdd = 10000;
|
||||
break;
|
||||
}
|
||||
case MPAvatarModeRaisedAndActive: {
|
||||
self.avatarSizeConstraint.constant = self.avatarImageView.image.size.height;
|
||||
self.avatarRaisedConstraint.priority = UILayoutPriorityDefaultHigh;
|
||||
self.avatarToTopConstraint.priority = UILayoutPriorityDefaultLow;
|
||||
self.nameToCenterConstraint.priority = UILayoutPriorityDefaultHigh;
|
||||
[self.avatarSizeConstraint layoutWithConstant:self.avatarImageView.image.size.height];
|
||||
[self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
self.nameContainer.alpha = self.visibility;
|
||||
self.nameContainer.backgroundColor = [UIColor blackColor];
|
||||
self.avatarImageView.alpha = 1;
|
||||
@ -242,10 +240,10 @@ const long MPAvatarAdd = 10000;
|
||||
break;
|
||||
}
|
||||
case MPAvatarModeRaisedAndHidden: {
|
||||
self.avatarSizeConstraint.constant = self.avatarImageView.image.size.height;
|
||||
self.avatarRaisedConstraint.priority = UILayoutPriorityDefaultHigh;
|
||||
self.avatarToTopConstraint.priority = UILayoutPriorityDefaultLow;
|
||||
self.nameToCenterConstraint.priority = UILayoutPriorityDefaultHigh;
|
||||
[self.avatarSizeConstraint layoutWithConstant:self.avatarImageView.image.size.height];
|
||||
[self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
self.nameContainer.alpha = 0;
|
||||
self.nameContainer.backgroundColor = [UIColor blackColor];
|
||||
self.avatarImageView.alpha = 0;
|
||||
@ -253,20 +251,16 @@ const long MPAvatarAdd = 10000;
|
||||
break;
|
||||
}
|
||||
case MPAvatarModeRaisedAndMinimized: {
|
||||
self.avatarSizeConstraint.constant = 36;
|
||||
self.avatarRaisedConstraint.priority = UILayoutPriorityDefaultLow;
|
||||
self.avatarToTopConstraint.priority = UILayoutPriorityDefaultHigh;
|
||||
self.nameToCenterConstraint.priority = UILayoutPriorityDefaultHigh;
|
||||
[self.avatarSizeConstraint layoutWithConstant:36];
|
||||
[self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
[self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
self.nameContainer.alpha = 0;
|
||||
self.nameContainer.backgroundColor = [UIColor blackColor];
|
||||
self.avatarImageView.alpha = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
[self.avatarSizeConstraint apply];
|
||||
[self.avatarRaisedConstraint apply];
|
||||
[self.avatarToTopConstraint apply];
|
||||
[self.nameToCenterConstraint apply];
|
||||
|
||||
// Avatar minimized.
|
||||
if (self.mode == MPAvatarModeRaisedAndMinimized)
|
||||
|
@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPElementListAllViewController
|
||||
//
|
||||
// Created by Maarten Billemont on 2013-01-31.
|
||||
// Copyright 2013 lhunath (Maarten Billemont). All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "MPElementListController.h"
|
||||
|
||||
@interface MPElementListAllViewController : MPElementListController
|
||||
|
||||
- (IBAction)close:(id)sender;
|
||||
- (IBAction)add:(id)sender;
|
||||
|
||||
@end
|
@ -1,188 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPElementListAllViewController
|
||||
//
|
||||
// Created by Maarten Billemont on 2013-01-31.
|
||||
// Copyright 2013 lhunath (Maarten Billemont). All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPElementListAllViewController.h"
|
||||
#import "MPiOSAppDelegate.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
|
||||
#define MPElementUpgradeOldContentKey @"MPElementUpgradeOldContentKey"
|
||||
#define MPElementUpgradeNewContentKey @"MPElementUpgradeNewContentKey"
|
||||
|
||||
@implementation MPElementListAllViewController
|
||||
|
||||
- (BOOL)prefersStatusBarHidden {
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle {
|
||||
|
||||
return UIStatusBarStyleLightContent;
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
if ([self.filter isEqualToString:MPElementListFilterNone]) {
|
||||
self.navigationItem.title = @"All Sites";
|
||||
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]
|
||||
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(add:)];
|
||||
}
|
||||
else if ([self.filter isEqualToString:MPElementListFilterOutdated]) {
|
||||
self.navigationItem.title = @"Outdated";
|
||||
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]
|
||||
initWithTitle:@"Upgrade All" style:UIBarButtonItemStyleBordered target:self action:@selector(upgradeAll:)];
|
||||
}
|
||||
|
||||
[self updateData];
|
||||
}
|
||||
|
||||
- (IBAction)close:(id)sender {
|
||||
|
||||
[self dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (IBAction)add:(id)sender {
|
||||
|
||||
[PearlAlert showAlertWithTitle:@"Add Site" message:nil viewStyle:UIAlertViewStylePlainTextInput initAlert:nil
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (alert.cancelButtonIndex == buttonIndex)
|
||||
return;
|
||||
|
||||
__weak MPElementListAllViewController *wSelf = self;
|
||||
[[MPiOSAppDelegate get] addElementNamed:[alert textFieldAtIndex:0].text completion:^(MPElementEntity *element) {
|
||||
if (element)
|
||||
PearlMainQueue( ^{
|
||||
[wSelf.delegate didSelectElement:element];
|
||||
[wSelf close:nil];
|
||||
} );
|
||||
}];
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonOkay, nil];
|
||||
}
|
||||
|
||||
- (IBAction)upgradeAll:(id)sender {
|
||||
|
||||
[PearlAlert showAlertWithTitle:@"Upgrading All Sites"
|
||||
message:@"You are about to upgrade all outdated sites. This will cause passwords to change. "
|
||||
@"Afterwards, you can get an overview of the changes."
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:
|
||||
^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
PearlOverlay *activity = [PearlOverlay showProgressOverlayWithTitle:@"Upgrading Sites"];
|
||||
[self performUpgradeAllWithCompletion:^(BOOL success, NSDictionary *changes) {
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[self showUpgradeChanges:changes];
|
||||
[activity cancelOverlayAnimated:YES];
|
||||
} );
|
||||
}];
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
||||
}
|
||||
|
||||
- (void)performUpgradeAllWithCompletion:(void (^)(BOOL success, NSDictionary *changes))completion {
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
||||
fetchRequest.fetchBatchSize = 20;
|
||||
|
||||
NSError *error = nil;
|
||||
NSArray *elements = [moc executeFetchRequest:fetchRequest error:&error];
|
||||
if (!elements) {
|
||||
err(@"Failed to fetch outdated sites for upgrade: %@", error);
|
||||
completion( NO, nil );
|
||||
return;
|
||||
}
|
||||
|
||||
MPKey *key = [MPAppDelegate_Shared get].key;
|
||||
NSMutableDictionary *elementChanges = [NSMutableDictionary dictionaryWithCapacity:[elements count]];
|
||||
for (MPElementEntity *element in elements) {
|
||||
id oldContent = [element.algorithm resolveContentForElement:element usingKey:key];
|
||||
[element migrateExplicitly:YES];
|
||||
id newContent = [element.algorithm resolveContentForElement:element usingKey:key];
|
||||
|
||||
if (!(element.type & MPElementFeatureDevicePrivate) && (!oldContent || ![oldContent isEqual:newContent]))
|
||||
elementChanges[element.name] = @{
|
||||
MPElementUpgradeOldContentKey : oldContent,
|
||||
MPElementUpgradeNewContentKey : newContent,
|
||||
};
|
||||
}
|
||||
|
||||
[moc saveToStore];
|
||||
completion( YES, elementChanges );
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)showUpgradeChanges:(NSDictionary *)changes {
|
||||
|
||||
if (![changes count])
|
||||
return;
|
||||
|
||||
NSMutableString *formattedChanges = [NSMutableString new];
|
||||
for (NSString *changedElementName in changes) {
|
||||
NSDictionary *elementChanges = changes[changedElementName];
|
||||
id oldContent = elementChanges[MPElementUpgradeOldContentKey];
|
||||
id newContent = elementChanges[MPElementUpgradeNewContentKey];
|
||||
[formattedChanges appendFormat:@"%@: %@ -> %@\n", changedElementName, oldContent, newContent];
|
||||
}
|
||||
|
||||
[PearlAlert showAlertWithTitle:@"Sites Upgraded"
|
||||
message:PearlString( @"This upgrade has caused %lu passwords to change.\n"
|
||||
@"To make updating the actual passwords of these accounts easier, "
|
||||
@"you can email a summary of these changes to yourself.", (unsigned long)[changes count] )
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
[PearlEMail sendEMailTo:nil fromVC:self subject:@"[Master Password] Upgrade Changes" body:formattedChanges];
|
||||
} cancelTitle:@"Don't Email" otherTitles:@"Send Email", nil];
|
||||
}
|
||||
|
||||
- (NSFetchedResultsController *)fetchedResultsControllerByUses {
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)configureFetchRequest:(NSFetchRequest *)fetchRequest {
|
||||
|
||||
fetchRequest.fetchBatchSize = 10;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
|
||||
[self close:nil];
|
||||
}
|
||||
|
||||
@end
|
@ -1,253 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1552</int>
|
||||
<string key="IBDocument.SystemVersion">12D78</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
|
||||
<string key="IBDocument.AppKitVersion">1187.37</string>
|
||||
<string key="IBDocument.HIToolboxVersion">626.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="NS.object.0">2083</string>
|
||||
</object>
|
||||
<array key="IBDocument.IntegratedClassDependencies">
|
||||
<string>IBProxyObject</string>
|
||||
<string>IBUIImageView</string>
|
||||
<string>IBUILabel</string>
|
||||
<string>IBUITableViewCell</string>
|
||||
</array>
|
||||
<array key="IBDocument.PluginDependencies">
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</array>
|
||||
<object class="NSMutableDictionary" key="IBDocument.Metadata">
|
||||
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
|
||||
<integer value="1" key="NS.object.0"/>
|
||||
</object>
|
||||
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
|
||||
<object class="IBProxyObject" id="372490531">
|
||||
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBProxyObject" id="975951072">
|
||||
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBUITableViewCell" id="1072502652">
|
||||
<reference key="NSNextResponder"/>
|
||||
<int key="NSvFlags">1280</int>
|
||||
<array class="NSMutableArray" key="NSSubviews">
|
||||
<object class="IBUIView" id="70825627">
|
||||
<reference key="NSNextResponder" ref="1072502652"/>
|
||||
<int key="NSvFlags">1280</int>
|
||||
<array class="NSMutableArray" key="NSSubviews">
|
||||
<object class="IBUILabel" id="169671678">
|
||||
<reference key="NSNextResponder" ref="70825627"/>
|
||||
<int key="NSvFlags">1280</int>
|
||||
<object class="NSPSMatrix" key="NSFrameMatrix"/>
|
||||
<string key="NSFrame">{{10, 4}, {38, 22}}</string>
|
||||
<reference key="NSSuperview" ref="70825627"/>
|
||||
<reference key="NSNextKeyView" ref="35578451"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor" id="801193159">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MCAwAA</bytes>
|
||||
</object>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
<bool key="IBUIMultipleTouchEnabled">YES</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<string key="IBUIText">Title</string>
|
||||
<object class="NSColor" key="IBUITextColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
</object>
|
||||
<object class="NSColor" key="IBUIHighlightedColor" id="748798155">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MSAxIDEAA</bytes>
|
||||
</object>
|
||||
<int key="IBUIBaselineAdjustment">0</int>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription">
|
||||
<int key="type">2</int>
|
||||
<double key="pointSize">18</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont">
|
||||
<string key="NSName">Helvetica-Bold</string>
|
||||
<double key="NSSize">18</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
|
||||
</object>
|
||||
<object class="IBUILabel" id="35578451">
|
||||
<reference key="NSNextResponder" ref="70825627"/>
|
||||
<int key="NSvFlags">1280</int>
|
||||
<object class="NSPSMatrix" key="NSFrameMatrix"/>
|
||||
<string key="NSFrame">{{10, 26}, {47, 18}}</string>
|
||||
<reference key="NSSuperview" ref="70825627"/>
|
||||
<reference key="IBUIBackgroundColor" ref="801193159"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
<bool key="IBUIMultipleTouchEnabled">YES</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<string key="IBUIText">Subtitle</string>
|
||||
<object class="NSColor" key="IBUITextColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
|
||||
</object>
|
||||
<reference key="IBUIHighlightedColor" ref="748798155"/>
|
||||
<int key="IBUIBaselineAdjustment">0</int>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription">
|
||||
<int key="type">1</int>
|
||||
<double key="pointSize">14</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont">
|
||||
<string key="NSName">Helvetica</string>
|
||||
<double key="NSSize">14</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
|
||||
</object>
|
||||
</array>
|
||||
<object class="NSPSMatrix" key="NSFrameMatrix"/>
|
||||
<string key="NSFrameSize">{320, 47}</string>
|
||||
<reference key="NSSuperview" ref="1072502652"/>
|
||||
<reference key="NSNextKeyView" ref="169671678"/>
|
||||
<reference key="IBUIBackgroundColor" ref="801193159"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">4</int>
|
||||
<bool key="IBUIMultipleTouchEnabled">YES</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
</array>
|
||||
<object class="NSPSMatrix" key="NSFrameMatrix"/>
|
||||
<string key="NSFrameSize">{320, 48}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<reference key="NSNextKeyView" ref="70825627"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MAA</bytes>
|
||||
</object>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<bool key="IBUIHidesAccessoryWhenEditing">NO</bool>
|
||||
<int key="IBUIIndentationLevel">1</int>
|
||||
<float key="IBUIIndentationWidth">0.0</float>
|
||||
<reference key="IBUIContentView" ref="70825627"/>
|
||||
<string key="IBUIReuseIdentifier">MPElementListCell</string>
|
||||
<integer value="3" key="IBUIStyle"/>
|
||||
<reference key="IBUITextLabel" ref="169671678"/>
|
||||
<reference key="IBUIDetailTextLabel" ref="35578451"/>
|
||||
</object>
|
||||
<object class="IBUIImageView" id="410525493">
|
||||
<nil key="NSNextResponder"/>
|
||||
<int key="NSvFlags">274</int>
|
||||
<string key="NSFrameSize">{320, 48}</string>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<reference key="IBUIBackgroundColor" ref="801193159"/>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="IBUIContentStretch">{{0.10000000000000001, 0.10000000000000001}, {0.79999999999999982, 0.79999999999999982}}</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<object class="NSCustomResource" key="IBUIImage">
|
||||
<string key="NSClassName">NSImage</string>
|
||||
<string key="NSResourceName">ui_list_middle.png</string>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBObjectContainer" key="IBDocument.Objects">
|
||||
<array class="NSMutableArray" key="connectionRecords">
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">view</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="1072502652"/>
|
||||
</object>
|
||||
<int key="connectionID">11</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">backgroundView</string>
|
||||
<reference key="source" ref="1072502652"/>
|
||||
<reference key="destination" ref="410525493"/>
|
||||
</object>
|
||||
<int key="connectionID">10</int>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
<array key="orderedObjects">
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">0</int>
|
||||
<array key="object" id="0"/>
|
||||
<reference key="children" ref="1000"/>
|
||||
<nil key="parent"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-1</int>
|
||||
<reference key="object" ref="372490531"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
<string key="objectName">File's Owner</string>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-2</int>
|
||||
<reference key="object" ref="975951072"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">4</int>
|
||||
<reference key="object" ref="1072502652"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<reference ref="35578451"/>
|
||||
<reference ref="169671678"/>
|
||||
</array>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">5</int>
|
||||
<reference key="object" ref="35578451"/>
|
||||
<reference key="parent" ref="1072502652"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">6</int>
|
||||
<reference key="object" ref="169671678"/>
|
||||
<reference key="parent" ref="1072502652"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">8</int>
|
||||
<reference key="object" ref="410525493"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
||||
<string key="-1.CustomClassName">UIViewController</string>
|
||||
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="-2.CustomClassName">UIResponder</string>
|
||||
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="4.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<reference key="4.IBUserGuides" ref="0"/>
|
||||
<boolean value="NO" key="4.showNotes"/>
|
||||
<string key="5.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<reference key="5.IBUserGuides" ref="0"/>
|
||||
<boolean value="NO" key="5.showNotes"/>
|
||||
<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<reference key="6.IBUserGuides" ref="0"/>
|
||||
<boolean value="NO" key="6.showNotes"/>
|
||||
<string key="8.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
|
||||
<nil key="activeLocalization"/>
|
||||
<dictionary class="NSMutableDictionary" key="localizations"/>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">11</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes"/>
|
||||
<int key="IBDocument.localizationMode">0</int>
|
||||
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
||||
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||
<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
|
||||
<string key="NS.key.0">ui_list_middle.png</string>
|
||||
<string key="NS.object.0">{300, 34}</string>
|
||||
</object>
|
||||
<string key="IBCocoaTouchPluginVersion">2083</string>
|
||||
</data>
|
||||
</archive>
|
@ -1,21 +0,0 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "MPElementListDelegate.h"
|
||||
|
||||
#define MPElementListFilterNone @"MPElementListFilterNone"
|
||||
#define MPElementListFilterOutdated @"MPElementListFilterOutdated"
|
||||
|
||||
@interface MPElementListController : UITableViewController<NSFetchedResultsControllerDelegate>
|
||||
|
||||
@property(weak, nonatomic) IBOutlet id<MPElementListDelegate> delegate;
|
||||
@property(strong, nonatomic) NSString *filter;
|
||||
|
||||
@property(readonly) NSFetchedResultsController *fetchedResultsControllerByUses;
|
||||
@property(readonly) NSFetchedResultsController *fetchedResultsControllerByLastUsed;
|
||||
@property(readonly) NSDateFormatter *dateFormatter;
|
||||
|
||||
- (void)updateData;
|
||||
- (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atTableIndexPath:(NSIndexPath *)indexPath;
|
||||
- (void)customTableViewUpdates;
|
||||
|
||||
@end
|
@ -1,279 +0,0 @@
|
||||
#import "MPElementListController.h"
|
||||
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPiOSAppDelegate.h"
|
||||
|
||||
@interface MPElementListController()
|
||||
@end
|
||||
|
||||
@implementation MPElementListController {
|
||||
|
||||
NSFetchedResultsController *_fetchedResultsControllerByUses;
|
||||
NSFetchedResultsController *_fetchedResultsControllerByLastUsed;
|
||||
NSDateFormatter *_dateFormatter;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidChangeNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self updateData];
|
||||
}];
|
||||
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
- (NSFetchedResultsController *)fetchedResultsControllerByLastUsed {
|
||||
|
||||
NSAssert([[NSThread currentThread] isMainThread], @"The fetchedResultsController must be accessed from the main thread.");
|
||||
|
||||
if (!_fetchedResultsControllerByLastUsed) {
|
||||
NSManagedObjectContext *context = [MPiOSAppDelegate managedObjectContextForMainThreadIfReady];
|
||||
if (!context)
|
||||
return nil;
|
||||
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
||||
fetchRequest.sortDescriptors = @[ [[NSSortDescriptor alloc] initWithKey:NSStringFromSelector( @selector(lastUsed) ) ascending:NO] ];
|
||||
[self configureFetchRequest:fetchRequest];
|
||||
_fetchedResultsControllerByLastUsed = [[NSFetchedResultsController alloc]
|
||||
initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
|
||||
_fetchedResultsControllerByLastUsed.delegate = self;
|
||||
}
|
||||
|
||||
return _fetchedResultsControllerByLastUsed;
|
||||
}
|
||||
|
||||
- (NSFetchedResultsController *)fetchedResultsControllerByUses {
|
||||
|
||||
NSAssert([[NSThread currentThread] isMainThread], @"The fetchedResultsController must be accessed from the main thread.");
|
||||
|
||||
if (!_fetchedResultsControllerByUses) {
|
||||
NSManagedObjectContext *context = [MPiOSAppDelegate managedObjectContextForMainThreadIfReady];
|
||||
if (!context)
|
||||
return nil;
|
||||
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
||||
fetchRequest.sortDescriptors = @[ [[NSSortDescriptor alloc] initWithKey:NSStringFromSelector( @selector(uses_) ) ascending:NO] ];
|
||||
[self configureFetchRequest:fetchRequest];
|
||||
_fetchedResultsControllerByUses = [[NSFetchedResultsController alloc]
|
||||
initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
|
||||
_fetchedResultsControllerByUses.delegate = self;
|
||||
}
|
||||
|
||||
return _fetchedResultsControllerByUses;
|
||||
}
|
||||
|
||||
- (void)configureFetchRequest:(NSFetchRequest *)fetchRequest {
|
||||
|
||||
fetchRequest.fetchLimit = 5;
|
||||
}
|
||||
|
||||
- (NSDateFormatter *)dateFormatter {
|
||||
|
||||
if (!_dateFormatter)
|
||||
(_dateFormatter = [NSDateFormatter new]).dateStyle = NSDateFormatterShortStyle;
|
||||
|
||||
return _dateFormatter;
|
||||
}
|
||||
|
||||
- (void)updateData {
|
||||
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:self.fetchedResultsControllerByLastUsed.managedObjectContext];
|
||||
if (!activeUser) {
|
||||
_fetchedResultsControllerByLastUsed = nil;
|
||||
_fetchedResultsControllerByUses = nil;
|
||||
[self.tableView reloadData];
|
||||
return;
|
||||
}
|
||||
|
||||
// Build predicate.
|
||||
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"user == %@", activeUser];
|
||||
|
||||
// Add query predicate.
|
||||
UISearchBar *searchBar = self.searchDisplayController.searchBar;
|
||||
if (searchBar) {
|
||||
NSString *query = [searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
if (!query)
|
||||
return;
|
||||
|
||||
predicate = [NSCompoundPredicate andPredicateWithSubpredicates:
|
||||
@[ predicate, [NSPredicate predicateWithFormat:@"name BEGINSWITH[cd] %@", query] ]];
|
||||
}
|
||||
|
||||
// Add filter predicate.
|
||||
if ([self.filter isEqualToString:MPElementListFilterOutdated])
|
||||
predicate = [NSCompoundPredicate andPredicateWithSubpredicates:
|
||||
@[ [NSPredicate predicateWithFormat:@"requiresExplicitMigration_ == YES"], predicate ]];
|
||||
|
||||
// Fetch
|
||||
NSError *error;
|
||||
self.fetchedResultsControllerByLastUsed.fetchRequest.predicate = predicate;
|
||||
self.fetchedResultsControllerByUses.fetchRequest.predicate = predicate;
|
||||
if (self.fetchedResultsControllerByLastUsed && ![self.fetchedResultsControllerByLastUsed performFetch:&error])
|
||||
err(@"Couldn't fetch elements: %@", error);
|
||||
if (self.fetchedResultsControllerByUses && ![self.fetchedResultsControllerByUses performFetch:&error])
|
||||
err(@"Couldn't fetch elements: %@", error);
|
||||
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (void)customTableViewUpdates {
|
||||
}
|
||||
|
||||
// See MP-14, also crashes easily on internal assertions etc..
|
||||
//- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
|
||||
//
|
||||
// [self.tableView beginUpdates];
|
||||
//}
|
||||
//
|
||||
//- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
|
||||
// atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
|
||||
//
|
||||
// switch (type) {
|
||||
//
|
||||
// case NSFetchedResultsChangeInsert:
|
||||
// [self.tableView insertRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:newIndexPath] ]
|
||||
// withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
// break;
|
||||
//
|
||||
// case NSFetchedResultsChangeDelete:
|
||||
// [self.tableView deleteRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:indexPath] ]
|
||||
// withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
// break;
|
||||
//
|
||||
// case NSFetchedResultsChangeUpdate:
|
||||
// [self.tableView reloadRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:indexPath] ]
|
||||
// withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
// break;
|
||||
//
|
||||
// case NSFetchedResultsChangeMove:
|
||||
// [self.tableView deleteRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:indexPath] ]
|
||||
// withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
// [self.tableView insertRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:newIndexPath] ]
|
||||
// withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
|
||||
|
||||
// [self customTableViewUpdates];
|
||||
// [self.tableView endUpdates];
|
||||
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
|
||||
if (section == 0)
|
||||
return (NSInteger)[[[self.fetchedResultsControllerByLastUsed sections] lastObject] numberOfObjects];
|
||||
|
||||
if (section == 1)
|
||||
return (NSInteger)[[[self.fetchedResultsControllerByUses sections] lastObject] numberOfObjects];
|
||||
|
||||
Throw(@"Unsupported section: %ld", (long)section);
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MPElementListCell"];
|
||||
if (!cell)
|
||||
cell = (UITableViewCell *)[[UIViewController alloc] initWithNibName:@"MPElementListCellView" bundle:nil].view;
|
||||
|
||||
[self configureCell:cell inTableView:tableView atTableIndexPath:indexPath];
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atTableIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
MPElementEntity *element = [self elementForTableIndexPath:indexPath];
|
||||
|
||||
cell.textLabel.text = element.name;
|
||||
cell.detailTextLabel.text = PearlString( @"%lu views, last on %@: %@",
|
||||
(unsigned long)element.uses, [self.dateFormatter stringFromDate:element.lastUsed],
|
||||
[element.algorithm shortNameOfType:element.type] );
|
||||
}
|
||||
|
||||
- (NSIndexPath *)tableIndexPathForFetchController:(NSFetchedResultsController *)fetchedResultsController
|
||||
indexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
if (fetchedResultsController == self.fetchedResultsControllerByLastUsed)
|
||||
return [NSIndexPath indexPathForRow:indexPath.row inSection:0];
|
||||
if (fetchedResultsController == self.fetchedResultsControllerByUses)
|
||||
return [NSIndexPath indexPathForRow:indexPath.row inSection:1];
|
||||
|
||||
Throw(@"Unknown fetched results controller: %@, for index path: %@", fetchedResultsController, indexPath);
|
||||
}
|
||||
|
||||
- (NSIndexPath *)fetchedIndexPathForTableIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
return [NSIndexPath indexPathForRow:indexPath.row inSection:0];
|
||||
}
|
||||
|
||||
- (MPElementEntity *)elementForTableIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
if (indexPath.section == 0)
|
||||
return [self.fetchedResultsControllerByLastUsed objectAtIndexPath:[self fetchedIndexPathForTableIndexPath:indexPath]];
|
||||
|
||||
if (indexPath.section == 1)
|
||||
return [self.fetchedResultsControllerByUses objectAtIndexPath:[self fetchedIndexPathForTableIndexPath:indexPath]];
|
||||
|
||||
Throw(@"Unsupported section: %ld", (long)indexPath.section);
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
[self.delegate didSelectElement:[self elementForTableIndexPath:indexPath]];
|
||||
}
|
||||
|
||||
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
|
||||
|
||||
if (section == 0)
|
||||
return @"Most Recently Used";
|
||||
|
||||
if (section == 1)
|
||||
return @"Most Commonly Used";
|
||||
|
||||
Throw(@"Unsupported section: %ld", (long)section);
|
||||
}
|
||||
|
||||
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
|
||||
|
||||
return @[ @"recency", @"uses" ];
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
|
||||
forRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
if (editingStyle == UITableViewCellEditingStyleDelete) {
|
||||
NSManagedObjectID *elementOID = [self elementForTableIndexPath:indexPath].objectID;
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) {
|
||||
MPElementEntity *element = [MPElementEntity existingObjectWithID:elementOID inContext:context];
|
||||
if (!element)
|
||||
return;
|
||||
|
||||
inf(@"Deleting element: %@", element.name);
|
||||
[context deleteObject:element];
|
||||
[context saveToStore];
|
||||
|
||||
MPCheckpoint( MPCheckpointDeleteElement, @{
|
||||
@"type" : NilToNSNull(element.typeName),
|
||||
@"version" : @(element.version)
|
||||
} );
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
@ -1,24 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPElementListDelegate
|
||||
//
|
||||
// Created by Maarten Billemont on 2013-01-31.
|
||||
// Copyright 2013 lhunath (Maarten Billemont). All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPElementEntity.h"
|
||||
|
||||
@protocol MPElementListDelegate<NSObject>
|
||||
|
||||
- (void)didSelectElement:(MPElementEntity *)element;
|
||||
|
||||
@end
|
@ -1,19 +0,0 @@
|
||||
//
|
||||
// MPSearchDelegate.h
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 04/01/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPElementListController.h"
|
||||
|
||||
@interface MPElementListSearchController : MPElementListController<UISearchBarDelegate, UISearchDisplayDelegate>
|
||||
|
||||
@property(strong, nonatomic) UILabel *tipView;
|
||||
|
||||
@property(strong, nonatomic) IBOutlet UISearchDisplayController *searchDisplayController;
|
||||
@property(weak, nonatomic) IBOutlet UIView *searchTipContainer;
|
||||
|
||||
@end
|
@ -1,247 +0,0 @@
|
||||
//
|
||||
// MPSearchDelegate.m
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 04/01/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPElementListSearchController.h"
|
||||
#import "MPMainViewController.h"
|
||||
#import "MPiOSAppDelegate.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
|
||||
@interface MPElementListSearchController()
|
||||
|
||||
@property(nonatomic) BOOL newSiteSectionWasNeeded;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPElementListSearchController
|
||||
|
||||
@synthesize searchDisplayController;
|
||||
|
||||
- (id)init {
|
||||
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
self.tipView = [[UILabel alloc] initWithFrame:CGRectMake( 0, 0, 320, 170 )];
|
||||
self.tipView.textAlignment = NSTextAlignmentCenter;
|
||||
self.tipView.backgroundColor = [UIColor clearColor];
|
||||
self.tipView.textColor = [UIColor lightTextColor];
|
||||
self.tipView.shadowColor = [UIColor blackColor];
|
||||
self.tipView.shadowOffset = CGSizeMake( 0, -1 );
|
||||
self.tipView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight
|
||||
| UIViewAutoresizingFlexibleBottomMargin;
|
||||
self.tipView.numberOfLines = 0;
|
||||
self.tipView.font = [UIFont systemFontOfSize:14];
|
||||
self.tipView.text =
|
||||
@"Tip:\n"
|
||||
@"Name your sites by their domain name:\n"
|
||||
@"apple.com, twitter.com\n\n"
|
||||
@"For email accounts, use the address:\n"
|
||||
@"john@apple.com, john@gmail.com";
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar {
|
||||
|
||||
[((MPMainViewController *)self.delegate) performSegueWithIdentifier:@"MP_AllSites" sender:MPElementListFilterNone];
|
||||
}
|
||||
|
||||
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
|
||||
|
||||
// Simulate a tap on the first visible row.
|
||||
UITableView *tableView = self.searchDisplayController.searchResultsTableView;
|
||||
for (NSInteger section = 0; section < [self numberOfSectionsInTableView:tableView]; ++section) {
|
||||
|
||||
if (![self tableView:tableView numberOfRowsInSection:section])
|
||||
continue;
|
||||
|
||||
[self tableView:tableView didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
|
||||
|
||||
controller.searchBar.text = @"";
|
||||
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.searchTipContainer.alpha = 0;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
|
||||
|
||||
[self updateData];
|
||||
}
|
||||
|
||||
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
|
||||
|
||||
controller.searchBar.prompt = nil;
|
||||
controller.searchBar.searchResultsButtonSelected = NO;
|
||||
}
|
||||
|
||||
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView {
|
||||
|
||||
tableView.backgroundColor = [UIColor blackColor];
|
||||
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
|
||||
tableView.rowHeight = 48.0f;
|
||||
|
||||
self.tableView = tableView;
|
||||
}
|
||||
|
||||
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
|
||||
|
||||
[self updateData];
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)updateData {
|
||||
|
||||
[super updateData];
|
||||
|
||||
UISearchBar *searchBar = self.searchDisplayController.searchBar;
|
||||
CGRect searchBarFrame = searchBar.frame;
|
||||
[searchBar.superview enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||
|
||||
if ([subview isKindOfClass:[UIControl class]] &&
|
||||
CGPointEqualToPoint(
|
||||
CGPointDistanceBetweenCGPoints( searchBarFrame.origin, subview.frame.origin ),
|
||||
CGPointMake( 0, searchBarFrame.size.height ) )) {
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[self.tipView removeFromSuperview];
|
||||
[subview addSubview:self.tipView];
|
||||
} );
|
||||
|
||||
*stop = YES;
|
||||
}
|
||||
} recurse:NO];
|
||||
}
|
||||
|
||||
- (BOOL)newSiteSectionNeeded {
|
||||
|
||||
NSString *query = [self.searchDisplayController.searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
if (![query length])
|
||||
return NO;
|
||||
|
||||
__block BOOL hasExactQueryMatch = NO;
|
||||
id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsControllerByUses sections] lastObject];
|
||||
[[sectionInfo objects] enumerateObjectsUsingBlock:^(id obj_, NSUInteger idx_, BOOL *stop_) {
|
||||
if ([[obj_ name] isEqualToString:query]) {
|
||||
hasExactQueryMatch = YES;
|
||||
*stop_ = YES;
|
||||
}
|
||||
}];
|
||||
if (hasExactQueryMatch)
|
||||
return NO;
|
||||
|
||||
sectionInfo = [[self.fetchedResultsControllerByLastUsed sections] lastObject];
|
||||
[[sectionInfo objects] enumerateObjectsUsingBlock:^(id obj_, NSUInteger idx_, BOOL *stop_) {
|
||||
if ([[obj_ name] isEqualToString:query]) {
|
||||
hasExactQueryMatch = YES;
|
||||
*stop_ = YES;
|
||||
}
|
||||
}];
|
||||
if (hasExactQueryMatch)
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)customTableViewUpdates {
|
||||
|
||||
BOOL newSiteSectionIsNeeded = [self newSiteSectionNeeded];
|
||||
if (newSiteSectionIsNeeded && !self.newSiteSectionWasNeeded)
|
||||
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:2]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
else if (!newSiteSectionIsNeeded && self.newSiteSectionWasNeeded)
|
||||
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:2]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
self.newSiteSectionWasNeeded = newSiteSectionIsNeeded;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
|
||||
NSInteger sectionCount = [super numberOfSectionsInTableView:tableView];
|
||||
if ([self newSiteSectionNeeded])
|
||||
++sectionCount;
|
||||
|
||||
return sectionCount;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
|
||||
if (section < [super numberOfSectionsInTableView:tableView])
|
||||
// Section is one of super's sections.
|
||||
return [super tableView:tableView numberOfRowsInSection:section];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atTableIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
if (indexPath.section < [super numberOfSectionsInTableView:tableView]) {
|
||||
// Section is one of super's sections.
|
||||
[super configureCell:cell inTableView:tableView atTableIndexPath:indexPath];
|
||||
return;
|
||||
}
|
||||
|
||||
// "New" section
|
||||
NSString *query = [self.searchDisplayController.searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
cell.textLabel.text = query;
|
||||
cell.detailTextLabel.text = PearlString( @"New site: %@",
|
||||
[MPAlgorithmDefault shortNameOfType:[[MPiOSAppDelegate get] activeUserForMainThread].defaultType] );
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
if (indexPath.section < [super numberOfSectionsInTableView:tableView]) {
|
||||
// Section is one of super's sections.
|
||||
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
|
||||
return;
|
||||
}
|
||||
|
||||
// "New" section.
|
||||
NSString *siteName
|
||||
= [self.searchDisplayController.searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
|
||||
[PearlAlert showAlertWithTitle:@"New Site"
|
||||
message:PearlString( @"Do you want to create a new site named:\n%@", siteName )
|
||||
viewStyle:UIAlertViewStyleDefault
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
__weak MPElementListController *wSelf = self;
|
||||
[[MPiOSAppDelegate get] addElementNamed:siteName completion:^(MPElementEntity *element) {
|
||||
if (element)
|
||||
PearlMainQueue( ^{
|
||||
[wSelf.delegate didSelectElement:element];
|
||||
} );
|
||||
}];
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonYes, nil];
|
||||
}
|
||||
|
||||
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
|
||||
|
||||
if (section < [super numberOfSectionsInTableView:tableView])
|
||||
// Section is one of super's sections.
|
||||
return [super tableView:tableView titleForHeaderInSection:section];
|
||||
|
||||
return @"Create";
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
|
||||
forRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
if (indexPath.section < [super numberOfSectionsInTableView:tableView])
|
||||
// Section is one of super's sections.
|
||||
[super tableView:tableView commitEditingStyle:editingStyle forRowAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
@end
|
@ -1,74 +0,0 @@
|
||||
//
|
||||
// MPMainViewController.h
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 24/11/11.
|
||||
// Copyright (c) 2011 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import <MessageUI/MessageUI.h>
|
||||
#import "MPTypeViewController.h"
|
||||
#import "MPElementListSearchController.h"
|
||||
|
||||
@interface MPMainViewController : UIViewController<MPTypeDelegate, UITextFieldDelegate, MPElementListDelegate, UIWebViewDelegate, UIGestureRecognizerDelegate>
|
||||
|
||||
@property(assign, nonatomic) BOOL siteInfoHidden;
|
||||
@property(strong, nonatomic) IBOutlet MPElementListSearchController *searchDelegate;
|
||||
@property(strong, nonatomic) IBOutlet UIPanGestureRecognizer *pullDownGesture;
|
||||
@property(strong, nonatomic) IBOutlet UIPanGestureRecognizer *pullUpGesture;
|
||||
@property(weak, nonatomic) IBOutlet UITextField *contentField;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *typeButton;
|
||||
@property(weak, nonatomic) IBOutlet UIWebView *helpView;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *siteName;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *passwordCounter;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *passwordIncrementer;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *passwordEdit;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *passwordUpgrade;
|
||||
@property(weak, nonatomic) IBOutlet UIView *contentContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *displayContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *helpContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *contentTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *loginNameTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *alertContainer;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *alertTitle;
|
||||
@property(weak, nonatomic) IBOutlet UITextView *alertBody;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *contentTipBody;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *loginNameTipBody;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView *toolTipEditIcon;
|
||||
@property(weak, nonatomic) IBOutlet UIView *searchTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *actionsTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *typeTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *toolTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *toolTipBody;
|
||||
@property(weak, nonatomic) IBOutlet UIView *loginNameContainer;
|
||||
@property(weak, nonatomic) IBOutlet UITextField *loginNameField;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *passwordUser;
|
||||
@property(weak, nonatomic) IBOutlet UIView *outdatedAlertContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView *outdatedAlertBack;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *outdatedAlertCloseButton;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView *pullUpView;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView *pullDownView;
|
||||
|
||||
@property(copy, nonatomic) void (^contentTipCleanup)(BOOL finished);
|
||||
@property(copy, nonatomic) void (^toolTipCleanup)(BOOL finished);
|
||||
|
||||
- (IBAction)copyContent;
|
||||
- (IBAction)incrementPasswordCounter;
|
||||
- (IBAction)resetPasswordCounter:(UILongPressGestureRecognizer *)sender;
|
||||
- (IBAction)editLoginName:(UILongPressGestureRecognizer *)sender;
|
||||
- (IBAction)editPassword;
|
||||
- (IBAction)closeAlert;
|
||||
- (IBAction)upgradePassword;
|
||||
- (IBAction)action:(UIBarButtonItem *)sender;
|
||||
- (IBAction)toggleUser;
|
||||
- (IBAction)searchOutdatedElements;
|
||||
- (IBAction)closeOutdatedAlert;
|
||||
- (IBAction)infoOutdatedAlert;
|
||||
|
||||
- (void)toggleHelpAnimated:(BOOL)animated;
|
||||
- (void)setHelpHidden:(BOOL)hidden animated:(BOOL)animated;
|
||||
- (void)setHelpChapter:(NSString *)chapter;
|
||||
- (IBAction)panHelpDown:(UIPanGestureRecognizer *)sender;
|
||||
- (IBAction)panHelpUp:(UIPanGestureRecognizer *)sender;
|
||||
|
||||
@end
|
@ -1,887 +0,0 @@
|
||||
//
|
||||
// MPMainViewController.m
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 24/11/11.
|
||||
// Copyright (c) 2011 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPMainViewController.h"
|
||||
#import "MPiOSAppDelegate.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPElementListAllViewController.h"
|
||||
|
||||
@interface MPMainViewController()
|
||||
|
||||
@property(nonatomic) BOOL suppressOutdatedAlert;
|
||||
@end
|
||||
|
||||
@implementation MPMainViewController {
|
||||
NSManagedObjectID *_activeElementOID;
|
||||
}
|
||||
|
||||
#pragma mark - View lifecycle
|
||||
|
||||
- (BOOL)shouldAutorotate {
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSUInteger)supportedInterfaceOrientations {
|
||||
|
||||
return UIInterfaceOrientationMaskAllButUpsideDown;
|
||||
}
|
||||
|
||||
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
|
||||
|
||||
return UIInterfaceOrientationPortrait;
|
||||
}
|
||||
|
||||
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
|
||||
|
||||
[self updateHelpHiddenAnimated:NO];
|
||||
[self updateUserHiddenAnimated:NO];
|
||||
}
|
||||
|
||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
||||
|
||||
if ([[segue identifier] isEqualToString:@"MP_ChooseType"])
|
||||
((MPTypeViewController *)[segue destinationViewController]).delegate = self;
|
||||
if ([[segue identifier] isEqualToString:@"MP_AllSites"]) {
|
||||
((MPElementListAllViewController *)[[segue destinationViewController] topViewController]).delegate = self;
|
||||
((MPElementListAllViewController *)[[segue destinationViewController] topViewController]).filter = sender;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
|
||||
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"ui_background"]];
|
||||
|
||||
self.alertBody.text = nil;
|
||||
self.toolTipEditIcon.hidden = YES;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:self queue:nil usingBlock:
|
||||
^(NSNotification *note) {
|
||||
self.suppressOutdatedAlert = NO;
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPElementUpdatedNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
MPElementEntity *activeElement = [self activeElementForMainThread];
|
||||
if (activeElement.type & MPElementTypeClassStored &&
|
||||
![[activeElement.algorithm resolveContentForElement:activeElement usingKey:[MPAppDelegate_Shared get].key] length])
|
||||
[self showToolTip:@"Tap to set a password." withIcon:self.toolTipEditIcon];
|
||||
if (activeElement.requiresExplicitMigration)
|
||||
[self showToolTip:@"Password outdated. Tap to upgrade it." withIcon:nil];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedOutNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
BOOL animated = [(note.userInfo)[@"animated"] boolValue];
|
||||
|
||||
_activeElementOID = nil;
|
||||
self.suppressOutdatedAlert = NO;
|
||||
[self updateAnimated:NO];
|
||||
|
||||
[[[PearlSheet activeSheets] copy] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
[obj cancelSheetAnimated:NO];
|
||||
}];
|
||||
if (![self.navigationController presentedViewController])
|
||||
[self.navigationController popToRootViewControllerAnimated:animated];
|
||||
else
|
||||
[self.navigationController dismissViewControllerAnimated:animated completion:^{
|
||||
[self.navigationController popToRootViewControllerAnimated:animated];
|
||||
}];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidChangeNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
if (!self.activeElementForMainThread)
|
||||
[self didSelectElement:nil];
|
||||
}];
|
||||
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
|
||||
if (![super respondsToSelector:@selector(prefersStatusBarHidden)])
|
||||
[UIApp setStatusBarHidden:NO withAnimation:animated? UIStatusBarAnimationSlide: UIStatusBarAnimationNone];
|
||||
[self.navigationController setNavigationBarHidden:NO animated:animated];
|
||||
|
||||
MPElementEntity *activeElement = [self activeElementForMainThread];
|
||||
if (activeElement.user != [[MPiOSAppDelegate get] activeUserForMainThread])
|
||||
_activeElementOID = nil;
|
||||
|
||||
self.searchDisplayController.searchBar.text = nil;
|
||||
self.alertContainer.hidden = NO;
|
||||
self.outdatedAlertContainer.hidden = NO;
|
||||
self.searchTipContainer.hidden = NO;
|
||||
self.actionsTipContainer.hidden = NO;
|
||||
self.typeTipContainer.hidden = NO;
|
||||
self.toolTipContainer.hidden = NO;
|
||||
self.contentTipContainer.hidden = NO;
|
||||
self.loginNameTipContainer.hidden = NO;
|
||||
|
||||
[self updateAnimated:NO];
|
||||
|
||||
[super viewWillAppear:animated];
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
|
||||
inf(@"Main will appear");
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||
if ([MPAlgorithmDefault migrateUser:activeUser inContext:moc] && !self.suppressOutdatedAlert)
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.outdatedAlertContainer.alpha = 1;
|
||||
self.suppressOutdatedAlert = YES;
|
||||
}];
|
||||
[moc saveToStore];
|
||||
}];
|
||||
|
||||
if (![[MPiOSConfig get].actionsTipShown boolValue])
|
||||
[UIView animateWithDuration:animated? 0.3f: 0 animations:^{
|
||||
self.actionsTipContainer.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
if (!finished)
|
||||
return;
|
||||
|
||||
[MPiOSConfig get].actionsTipShown = @YES;
|
||||
|
||||
dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC) ), dispatch_get_main_queue(), ^{
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.actionsTipContainer.alpha = 0;
|
||||
} completion:^(BOOL finished_) {
|
||||
if (!_activeElementOID)
|
||||
[UIView animateWithDuration:animated? 0.3f: 0 animations:^{
|
||||
self.searchTipContainer.alpha = 1;
|
||||
}];
|
||||
}];
|
||||
} );
|
||||
}];
|
||||
|
||||
[super viewDidAppear:animated];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
|
||||
inf(@"Main will disappear.");
|
||||
[super viewWillDisappear:animated];
|
||||
}
|
||||
|
||||
- (void)updateAnimated:(BOOL)animated {
|
||||
|
||||
if (animated) {
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
[self updateAnimated:NO];
|
||||
}];
|
||||
return;
|
||||
}
|
||||
|
||||
MPElementEntity *activeElement = [self activeElementForMainThread];
|
||||
[self setHelpChapter:activeElement? @"2": @"1"];
|
||||
[self updateHelpHiddenAnimated:NO];
|
||||
|
||||
self.passwordCounter.alpha = 0;
|
||||
self.passwordIncrementer.alpha = 0;
|
||||
self.passwordEdit.alpha = 0;
|
||||
self.passwordUpgrade.alpha = 0;
|
||||
self.passwordUser.alpha = 0;
|
||||
self.displayContainer.alpha = 0;
|
||||
|
||||
if (activeElement) {
|
||||
self.passwordUser.alpha = 0.5f;
|
||||
self.displayContainer.alpha = 1.0f;
|
||||
}
|
||||
|
||||
if (activeElement.requiresExplicitMigration)
|
||||
self.passwordUpgrade.alpha = 0.5f;
|
||||
|
||||
else {
|
||||
if (activeElement.type & MPElementTypeClassGenerated) {
|
||||
self.passwordCounter.alpha = 0.5f;
|
||||
self.passwordIncrementer.alpha = 0.5f;
|
||||
}
|
||||
else if (activeElement.type & MPElementTypeClassStored)
|
||||
self.passwordEdit.alpha = 0.5f;
|
||||
}
|
||||
|
||||
self.siteName.text = activeElement.name;
|
||||
|
||||
self.typeButton.alpha = activeElement? 1: 0;
|
||||
[self.typeButton setTitle:activeElement.typeName
|
||||
forState:UIControlStateNormal];
|
||||
|
||||
if ([activeElement isKindOfClass:[MPElementGeneratedEntity class]])
|
||||
self.passwordCounter.text = PearlString( @"%lu", (unsigned long)((MPElementGeneratedEntity *)activeElement).counter );
|
||||
|
||||
self.contentField.enabled = NO;
|
||||
self.contentField.text = @"";
|
||||
if (activeElement.name && ![activeElement isDeleted])
|
||||
[activeElement.algorithm resolveContentForElement:activeElement usingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) {
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
self.contentField.text = result;
|
||||
} );
|
||||
}];
|
||||
|
||||
self.loginNameField.enabled = NO;
|
||||
self.loginNameField.text = activeElement.loginName;
|
||||
self.siteInfoHidden = !activeElement || ([[MPiOSConfig get].siteInfoHidden boolValue] && (activeElement.loginName == nil));
|
||||
[self updateUserHiddenAnimated:NO];
|
||||
}
|
||||
|
||||
- (void)toggleHelpAnimated:(BOOL)animated {
|
||||
|
||||
[self setHelpHidden:![[MPiOSConfig get].helpHidden boolValue] animated:animated];
|
||||
}
|
||||
|
||||
- (void)setHelpHidden:(BOOL)hidden animated:(BOOL)animated {
|
||||
|
||||
[MPiOSConfig get].helpHidden = @(hidden);
|
||||
[self updateHelpHiddenAnimated:animated];
|
||||
}
|
||||
|
||||
- (void)updateHelpHiddenAnimated:(BOOL)animated {
|
||||
|
||||
if (animated) {
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
[self updateHelpHiddenAnimated:NO];
|
||||
}];
|
||||
return;
|
||||
}
|
||||
|
||||
self.pullUpView.hidden = ![[MPiOSConfig get].helpHidden boolValue];
|
||||
self.pullDownView.hidden = [[MPiOSConfig get].helpHidden boolValue];
|
||||
|
||||
if ([[MPiOSConfig get].helpHidden boolValue]) {
|
||||
self.contentContainer.frame = CGRectSetHeight( self.contentContainer.frame, self.view.bounds.size.height - 44 /* search bar */);
|
||||
self.helpContainer.frame = CGRectSetY( self.helpContainer.frame, self.view.bounds.size.height - 20 /* pull-up */);
|
||||
}
|
||||
else {
|
||||
self.contentContainer.frame = CGRectSetHeight( self.contentContainer.frame, 225 );
|
||||
[self.helpContainer setFrameFromCurrentSizeAndParentPaddingTop:CGFLOAT_MAX right:0 bottom:0 left:0];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)toggleUser {
|
||||
|
||||
[self toggleUserAnimated:YES];
|
||||
}
|
||||
|
||||
- (void)toggleUserAnimated:(BOOL)animated {
|
||||
|
||||
[MPiOSConfig get].siteInfoHidden = @(!self.siteInfoHidden);
|
||||
self.siteInfoHidden = [[MPiOSConfig get].siteInfoHidden boolValue];
|
||||
[self updateUserHiddenAnimated:animated];
|
||||
}
|
||||
|
||||
- (void)updateUserHiddenAnimated:(BOOL)animated {
|
||||
|
||||
if (animated) {
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
[self updateUserHiddenAnimated:NO];
|
||||
}];
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.siteInfoHidden) {
|
||||
self.displayContainer.frame = CGRectSetHeight( self.displayContainer.frame, 87 );
|
||||
}
|
||||
else {
|
||||
self.displayContainer.frame = CGRectSetHeight( self.displayContainer.frame, 137 );
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setHelpChapter:(NSString *)chapter {
|
||||
|
||||
MPCheckpoint( MPCheckpointHelpChapter, @{
|
||||
@"chapter" : NilToNSNull(chapter)
|
||||
} );
|
||||
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
NSURL *url = [NSURL URLWithString:[@"#" stringByAppendingString:chapter]
|
||||
relativeToURL:[[NSBundle mainBundle] URLForResource:@"help" withExtension:@"html"]];
|
||||
[self.helpView loadRequest:[NSURLRequest requestWithURL:url]];
|
||||
} );
|
||||
}
|
||||
|
||||
- (IBAction)panHelpDown:(UIPanGestureRecognizer *)sender {
|
||||
|
||||
CGFloat targetY = MIN(self.view.bounds.size.height - 20, 246 + [sender translationInView:self.helpContainer].y);
|
||||
BOOL hideHelp = YES;
|
||||
if (targetY <= 246) {
|
||||
hideHelp = NO;
|
||||
targetY = 246;
|
||||
}
|
||||
|
||||
self.helpContainer.frame = CGRectSetY( self.helpContainer.frame, targetY );
|
||||
|
||||
if (sender.state == UIGestureRecognizerStateEnded)
|
||||
[self setHelpHidden:hideHelp animated:YES];
|
||||
}
|
||||
|
||||
- (IBAction)panHelpUp:(UIPanGestureRecognizer *)sender {
|
||||
|
||||
CGFloat targetY = MAX(246, self.view.bounds.size.height - 20 + [sender translationInView:self.helpContainer].y);
|
||||
BOOL hideHelp = NO;
|
||||
if (targetY >= self.view.bounds.size.height - 20) {
|
||||
hideHelp = YES;
|
||||
targetY = self.view.bounds.size.height - 20;
|
||||
}
|
||||
|
||||
self.helpContainer.frame = CGRectSetY( self.helpContainer.frame, targetY );
|
||||
|
||||
if (sender.state == UIGestureRecognizerStateEnded)
|
||||
[self setHelpHidden:hideHelp animated:YES];
|
||||
}
|
||||
|
||||
- (void)webViewDidFinishLoad:(UIWebView *)webView {
|
||||
|
||||
MPElementEntity *activeElement = [self activeElementForMainThread];
|
||||
NSString *error = [self.helpView stringByEvaluatingJavaScriptFromString:
|
||||
PearlString( @"setClass('%@');", activeElement.typeClassName )];
|
||||
if (error.length)
|
||||
err(@"helpView.setClass: %@", error);
|
||||
}
|
||||
|
||||
- (void)showContentTip:(NSString *)message withIcon:(UIImageView *)icon {
|
||||
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
if (self.contentTipCleanup)
|
||||
self.contentTipCleanup( NO );
|
||||
|
||||
__weak MPMainViewController *wSelf = self;
|
||||
self.contentTipBody.text = message;
|
||||
self.contentTipCleanup = ^(BOOL finished) {
|
||||
icon.hidden = YES;
|
||||
wSelf.contentTipCleanup = nil;
|
||||
};
|
||||
|
||||
icon.hidden = NO;
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.contentTipContainer.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished) {
|
||||
dispatch_time_t popTime = dispatch_time( DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC );
|
||||
dispatch_after( popTime, dispatch_get_main_queue(), ^(void) {
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.contentTipContainer.alpha = 0;
|
||||
} completion:self.contentTipCleanup];
|
||||
} );
|
||||
}
|
||||
}];
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)showLoginNameTip:(NSString *)message {
|
||||
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
self.loginNameTipBody.text = message;
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.loginNameTipContainer.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished) {
|
||||
dispatch_time_t popTime = dispatch_time( DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC );
|
||||
dispatch_after( popTime, dispatch_get_main_queue(), ^(void) {
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.loginNameTipContainer.alpha = 0;
|
||||
}];
|
||||
} );
|
||||
}
|
||||
}];
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)showToolTip:(NSString *)message withIcon:(UIImageView *)icon {
|
||||
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
if (self.toolTipCleanup)
|
||||
self.toolTipCleanup( NO );
|
||||
|
||||
__weak MPMainViewController *wSelf = self;
|
||||
self.toolTipBody.text = message;
|
||||
self.toolTipCleanup = ^(BOOL finished) {
|
||||
icon.hidden = YES;
|
||||
wSelf.toolTipCleanup = nil;
|
||||
};
|
||||
|
||||
icon.hidden = NO;
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.toolTipContainer.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished) {
|
||||
dispatch_time_t popTime = dispatch_time( DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC );
|
||||
dispatch_after( popTime, dispatch_get_main_queue(), ^(void) {
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.toolTipContainer.alpha = 0;
|
||||
} completion:self.toolTipCleanup];
|
||||
} );
|
||||
}
|
||||
}];
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message {
|
||||
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
self.alertTitle.text = title;
|
||||
NSRange scrollRange = NSMakeRange( self.alertBody.text.length, message.length );
|
||||
if ([self.alertBody.text length])
|
||||
self.alertBody.text = [NSString stringWithFormat:@"%@\n\n---\n\n%@", self.alertBody.text, message];
|
||||
else
|
||||
self.alertBody.text = message;
|
||||
[self.alertBody scrollRangeToVisible:scrollRange];
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.alertContainer.alpha = 1;
|
||||
}];
|
||||
} );
|
||||
}
|
||||
|
||||
#pragma mark - Protocols
|
||||
|
||||
- (IBAction)copyContent {
|
||||
|
||||
MPElementEntity *activeElement = [self activeElementForMainThread];
|
||||
inf(@"Copying password for: %@", activeElement.name);
|
||||
MPCheckpoint( MPCheckpointCopyToPasteboard, @{
|
||||
@"type" : NilToNSNull(activeElement.typeName),
|
||||
@"version" : @(activeElement.version),
|
||||
@"emergency" : @NO
|
||||
} );
|
||||
|
||||
[activeElement.algorithm resolveContentForElement:activeElement usingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) {
|
||||
if (!result)
|
||||
// Nothing to copy.
|
||||
return;
|
||||
|
||||
[UIPasteboard generalPasteboard].string = result;
|
||||
[self showContentTip:@"Copied!" withIcon:nil];
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)copyLoginName:(UITapGestureRecognizer *)sender {
|
||||
|
||||
MPElementEntity *activeElement = [self activeElementForMainThread];
|
||||
if (!activeElement.loginName)
|
||||
return;
|
||||
|
||||
inf(@"Copying user name for: %@", activeElement.name);
|
||||
[UIPasteboard generalPasteboard].string = activeElement.loginName;
|
||||
|
||||
[self showLoginNameTip:@"Copied!"];
|
||||
|
||||
MPCheckpoint( MPCheckpointCopyLoginNameToPasteboard, @{
|
||||
@"type" : NilToNSNull(activeElement.typeName),
|
||||
@"version" : @(activeElement.version)
|
||||
} );
|
||||
}
|
||||
|
||||
- (IBAction)incrementPasswordCounter {
|
||||
|
||||
[self changeActiveElementWithWarning:
|
||||
@"You are incrementing the site's password counter.\n\n"
|
||||
@"If you continue, a new password will be generated for this site. "
|
||||
@"You will then need to update your account's old password to this newly generated password.\n\n"
|
||||
@"You can reset the counter by holding down on this button."
|
||||
do:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) {
|
||||
if (![activeElement isKindOfClass:[MPElementGeneratedEntity class]]) {
|
||||
// Not of a type that supports a password counter.
|
||||
err(@"Cannot increment password counter: Element is not generated: %@", activeElement.name);
|
||||
return NO;
|
||||
}
|
||||
MPElementGeneratedEntity *activeGeneratedElement = (MPElementGeneratedEntity *)activeElement;
|
||||
|
||||
inf(@"Incrementing password counter for: %@", activeGeneratedElement.name);
|
||||
++activeGeneratedElement.counter;
|
||||
|
||||
MPCheckpoint( MPCheckpointIncrementPasswordCounter, @{
|
||||
@"type" : NilToNSNull(activeGeneratedElement.typeName),
|
||||
@"version" : @(activeGeneratedElement.version),
|
||||
@"counter" : @(activeGeneratedElement.counter)
|
||||
} );
|
||||
return YES;
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)resetPasswordCounter:(UILongPressGestureRecognizer *)sender {
|
||||
|
||||
if (sender.state != UIGestureRecognizerStateBegan)
|
||||
// Only fire when the gesture was first detected.
|
||||
return;
|
||||
MPElementEntity *activeElement = [self activeElementForMainThread];
|
||||
if (![activeElement isKindOfClass:[MPElementGeneratedEntity class]]) {
|
||||
// Not of a type that supports a password counter.
|
||||
err(@"Cannot reset password counter: Element is not generated: %@", activeElement.name);
|
||||
return;
|
||||
}
|
||||
else if (((MPElementGeneratedEntity *)activeElement).counter == 1)
|
||||
// Counter has initial value, no point resetting.
|
||||
return;
|
||||
|
||||
[self changeActiveElementWithWarning:
|
||||
@"You are resetting the site's password counter.\n\n"
|
||||
@"If you continue, the site's password will change back to its original value. "
|
||||
@"You will then need to update your account's password back to this original value."
|
||||
do:^BOOL(MPElementEntity *activeElement_, NSManagedObjectContext *context) {
|
||||
inf(@"Resetting password counter for: %@", activeElement_.name);
|
||||
((MPElementGeneratedEntity *)activeElement_).counter = 1;
|
||||
|
||||
MPCheckpoint( MPCheckpointResetPasswordCounter, @{
|
||||
@"type" : NilToNSNull(activeElement_.typeName),
|
||||
@"version" : @(activeElement_.version)
|
||||
} );
|
||||
return YES;
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)editLoginName:(UILongPressGestureRecognizer *)sender {
|
||||
|
||||
if (sender.state != UIGestureRecognizerStateBegan)
|
||||
// Only fire when the gesture was first detected.
|
||||
return;
|
||||
|
||||
MPElementEntity *activeElement = [self activeElementForMainThread];
|
||||
if (!activeElement)
|
||||
return;
|
||||
|
||||
self.loginNameField.enabled = YES;
|
||||
[self.loginNameField becomeFirstResponder];
|
||||
|
||||
MPCheckpoint( MPCheckpointEditLoginName, @{
|
||||
@"type" : NilToNSNull(activeElement.typeName),
|
||||
@"version" : @(activeElement.version)
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)changeActiveElementWithWarning:(NSString *)warning
|
||||
do:(BOOL (^)(MPElementEntity *activeElement, NSManagedObjectContext *context))task {
|
||||
|
||||
[PearlAlert showAlertWithTitle:@"Password Change" message:warning viewStyle:UIAlertViewStyleDefault
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
[self changeActiveElementWithoutWarningDo:task];
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
||||
}
|
||||
|
||||
- (void)changeActiveElementWithoutWarningDo:(BOOL (^)(MPElementEntity *, NSManagedObjectContext *context))task {
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementEntity *activeElement = [self activeElementInContext:context];
|
||||
if (!activeElement)
|
||||
return;
|
||||
|
||||
MPKey *key = [MPAppDelegate_Shared get].key;
|
||||
NSString *oldPassword = [activeElement.algorithm resolveContentForElement:activeElement usingKey:key];
|
||||
if (!task( activeElement, context ))
|
||||
return;
|
||||
|
||||
activeElement = [self activeElementInContext:context];
|
||||
NSString *newPassword = [activeElement.algorithm resolveContentForElement:activeElement usingKey:key];
|
||||
|
||||
// Save.
|
||||
[context saveToStore];
|
||||
|
||||
// Update the UI.
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[self updateAnimated:YES];
|
||||
|
||||
// Show new and old password.
|
||||
if ([oldPassword length] && ![oldPassword isEqualToString:newPassword])
|
||||
[self showAlertWithTitle:@"Password Changed!"
|
||||
message:PearlString( @"The password for %@ has changed.\n\n"
|
||||
@"IMPORTANT:\n"
|
||||
@"Don't forget to update the site with your new password! "
|
||||
@"Your old password was:\n"
|
||||
@"%@", activeElement.name, oldPassword )];
|
||||
} );
|
||||
}];
|
||||
}
|
||||
|
||||
- (MPElementEntity *)activeElementForMainThread {
|
||||
|
||||
return [self activeElementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
|
||||
}
|
||||
|
||||
- (MPElementEntity *)activeElementInContext:(NSManagedObjectContext *)moc {
|
||||
|
||||
if (!_activeElementOID)
|
||||
return nil;
|
||||
|
||||
NSError *error;
|
||||
MPElementEntity *activeElement = (MPElementEntity *)[moc existingObjectWithID:_activeElementOID error:&error];
|
||||
if (!activeElement)
|
||||
err(@"Couldn't retrieve active element: %@", error);
|
||||
|
||||
return activeElement;
|
||||
}
|
||||
|
||||
- (IBAction)editPassword {
|
||||
|
||||
MPElementEntity *activeElement = [self activeElementForMainThread];
|
||||
if (!(activeElement.type & MPElementTypeClassStored)) {
|
||||
// Not of a type that supports editing the content.
|
||||
err(@"Cannot edit content: Element is not stored: %@", activeElement.name);
|
||||
return;
|
||||
}
|
||||
|
||||
self.contentField.enabled = YES;
|
||||
[self.contentField becomeFirstResponder];
|
||||
|
||||
MPCheckpoint( MPCheckpointEditPassword, @{
|
||||
@"type" : NilToNSNull(activeElement.typeName),
|
||||
@"version" : @(activeElement.version)
|
||||
} );
|
||||
}
|
||||
|
||||
- (IBAction)upgradePassword {
|
||||
|
||||
MPElementEntity *activeElement = [self activeElementForMainThread];
|
||||
if (!activeElement)
|
||||
return;
|
||||
|
||||
NSString *warning = activeElement.type & MPElementTypeClassGenerated?
|
||||
@"You are upgrading the site.\n\n"
|
||||
@"This upgrade improves the site's compatibility with the latest version of Master Password.\n\n"
|
||||
@"Your password will change and you will need to update your site's account."
|
||||
:
|
||||
@"You are upgrading the site.\n\n"
|
||||
@"This upgrade improves the site's compatibility with the latest version of Master Password.";
|
||||
|
||||
[self changeActiveElementWithWarning:warning do:
|
||||
^BOOL(MPElementEntity *activeElement_, NSManagedObjectContext *context) {
|
||||
inf(@"Explicitly migrating element: %@", activeElement_);
|
||||
[activeElement_ migrateExplicitly:YES];
|
||||
|
||||
MPCheckpoint( MPCheckpointExplicitMigration, @{
|
||||
@"type" : NilToNSNull(activeElement_.typeName),
|
||||
@"version" : @(activeElement_.version)
|
||||
} );
|
||||
return YES;
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)searchOutdatedElements {
|
||||
|
||||
[self performSegueWithIdentifier:@"MP_AllSites" sender:MPElementListFilterOutdated];
|
||||
}
|
||||
|
||||
- (IBAction)closeAlert {
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.alertContainer.alpha = 0;
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished)
|
||||
self.alertBody.text = nil;
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)closeOutdatedAlert {
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.outdatedAlertContainer.alpha = 0;
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)infoOutdatedAlert {
|
||||
|
||||
[self setHelpChapter:@"outdated"];
|
||||
[self setHelpHidden:NO animated:YES];
|
||||
[self closeOutdatedAlert];
|
||||
self.suppressOutdatedAlert = NO;
|
||||
}
|
||||
|
||||
- (IBAction)action:(id)sender {
|
||||
|
||||
[PearlSheet showSheetWithTitle:nil viewStyle:UIActionSheetStyleAutomatic
|
||||
initSheet:nil tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [sheet cancelButtonIndex])
|
||||
return;
|
||||
|
||||
switch (buttonIndex - [sheet firstOtherButtonIndex]) {
|
||||
case 0: {
|
||||
inf(@"Action: FAQ");
|
||||
[self setHelpChapter:@"faq"];
|
||||
[self setHelpHidden:NO animated:YES];
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
inf(@"Action: Preferences");
|
||||
[self performSegueWithIdentifier:@"MP_UserProfile" sender:self];
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
inf(@"Action: Other Apps");
|
||||
[self performSegueWithIdentifier:@"MP_OtherApps" sender:self];
|
||||
break;
|
||||
}
|
||||
//#if defined(ADHOC) && defined(TESTFLIGHT_SDK_VERSION)
|
||||
// case 4: {
|
||||
// inf(@"Action: Feedback via TestFlight");
|
||||
// [TestFlight openFeedbackView];
|
||||
// break;
|
||||
// }
|
||||
//#else
|
||||
case 4: {
|
||||
inf(@"Action: Feedback via Mail");
|
||||
[[MPiOSAppDelegate get] showFeedbackWithLogs:YES forVC:self];
|
||||
break;
|
||||
}
|
||||
//#endif
|
||||
|
||||
default: {
|
||||
wrn(@"Unsupported action: %ld", (long)(buttonIndex - [sheet firstOtherButtonIndex]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonCancel destructiveTitle:nil otherTitles:
|
||||
@"FAQ",
|
||||
@"Overview",
|
||||
@"User Profile",
|
||||
@"Other Apps",
|
||||
@"Feedback",
|
||||
nil];
|
||||
}
|
||||
|
||||
- (MPElementType)selectedType {
|
||||
|
||||
return [self selectedElement].type;
|
||||
}
|
||||
|
||||
- (MPElementEntity *)selectedElement {
|
||||
|
||||
return [self activeElementForMainThread];
|
||||
}
|
||||
|
||||
- (void)didSelectType:(MPElementType)type {
|
||||
|
||||
[self changeActiveElementWithWarning:
|
||||
@"You are about to change the type of this password.\n\n"
|
||||
@"If you continue, the password for this site will change. "
|
||||
@"You will need to update your account's old password to the new one."
|
||||
do:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) {
|
||||
_activeElementOID = [[MPiOSAppDelegate get] changeElement:activeElement saveInContext:context
|
||||
toType:type].objectID;
|
||||
return YES;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)didSelectElement:(MPElementEntity *)element {
|
||||
|
||||
inf(@"Selected: %@", element.name);
|
||||
_activeElementOID = element.objectID;
|
||||
[self closeAlert];
|
||||
|
||||
if (element) {
|
||||
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) {
|
||||
if ([activeElement use] == 1)
|
||||
[self showAlertWithTitle:@"New Site" message:
|
||||
PearlString( @"You've just created a password for %@.\n\n"
|
||||
@"IMPORTANT:\n"
|
||||
@"Go to %@ and set or change the password for your account to the password above.\n"
|
||||
@"Do this right away: if you forget, you may have trouble remembering which password to use to log into the site later on.",
|
||||
activeElement.name, activeElement.name )];
|
||||
return YES;
|
||||
}];
|
||||
|
||||
if (![[MPiOSConfig get].typeTipShown boolValue])
|
||||
[UIView animateWithDuration:0.5f animations:^{
|
||||
self.typeTipContainer.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished) {
|
||||
[MPiOSConfig get].typeTipShown = PearlBool(YES);
|
||||
|
||||
dispatch_after(
|
||||
dispatch_time( DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC) ), dispatch_get_main_queue(), ^{
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.typeTipContainer.alpha = 0;
|
||||
}];
|
||||
} );
|
||||
}
|
||||
}];
|
||||
|
||||
MPCheckpoint( MPCheckpointUseType, @{
|
||||
@"type" : NilToNSNull(element.typeName),
|
||||
@"version" : @(element.version)
|
||||
} );
|
||||
}
|
||||
|
||||
[self.searchDisplayController setActive:NO animated:YES];
|
||||
self.searchDisplayController.searchBar.text = element.name;
|
||||
|
||||
[self updateAnimated:YES];
|
||||
}
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
||||
|
||||
if (textField == self.contentField)
|
||||
[self.contentField resignFirstResponder];
|
||||
if (textField == self.loginNameField)
|
||||
[self.loginNameField resignFirstResponder];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)textFieldDidEndEditing:(UITextField *)textField {
|
||||
|
||||
if (textField == self.contentField) {
|
||||
self.contentField.enabled = NO;
|
||||
MPElementEntity *activeElement = [self activeElementForMainThread];
|
||||
MPKey *key = [MPAppDelegate_Shared get].key;
|
||||
if (![activeElement isKindOfClass:[MPElementStoredEntity class]]) {
|
||||
// Not of a type whose content can be edited.
|
||||
err(@"Cannot update element content: Element is not stored: %@", activeElement.name);
|
||||
return;
|
||||
}
|
||||
else if ([[activeElement.algorithm resolveContentForElement:activeElement usingKey:key] isEqual:self.contentField.text])
|
||||
// Content hasn't changed.
|
||||
return;
|
||||
|
||||
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement_, NSManagedObjectContext *context) {
|
||||
[activeElement_.algorithm saveContent:self.contentField.text toElement:activeElement_ usingKey:key];
|
||||
return YES;
|
||||
}];
|
||||
}
|
||||
|
||||
if (textField == self.loginNameField) {
|
||||
self.loginNameField.enabled = NO;
|
||||
if (![[MPiOSConfig get].loginNameTipShown boolValue]) {
|
||||
[self showLoginNameTip:@"Tap to copy or hold to edit."];
|
||||
[MPiOSConfig get].loginNameTipShown = @YES;
|
||||
}
|
||||
|
||||
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) {
|
||||
if ([self.loginNameField.text length])
|
||||
activeElement.loginName = self.loginNameField.text;
|
||||
else
|
||||
activeElement.loginName = nil;
|
||||
|
||||
return YES;
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
|
||||
navigationType:(UIWebViewNavigationType)navigationType {
|
||||
|
||||
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
|
||||
if ([[[request URL] query] isEqualToString:@"outdated"]) {
|
||||
[self searchOutdatedElements];
|
||||
return NO;
|
||||
}
|
||||
|
||||
[UIApp openURL:[request URL]];
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
@ -9,17 +9,15 @@
|
||||
*/
|
||||
|
||||
//
|
||||
// MPAppViewController
|
||||
// MPNavigationController.h
|
||||
// MPNavigationController
|
||||
//
|
||||
// Created by Maarten Billemont on 2012-08-31.
|
||||
// Copyright 2012 lhunath (Maarten Billemont). All rights reserved.
|
||||
// Created by lhunath on 2014-06-03.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface MPAppViewController : UIViewController
|
||||
|
||||
- (IBAction)gorillas:(UIButton *)sender;
|
||||
- (IBAction)deblock:(UIButton *)sender;
|
||||
|
||||
@interface MPNavigationController : UINavigationController
|
||||
@end
|
30
MasterPassword/ObjC/iOS/MPNavigationController.m
Normal file
30
MasterPassword/ObjC/iOS/MPNavigationController.m
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPNavigationController.h
|
||||
// MPNavigationController
|
||||
//
|
||||
// Created by lhunath on 2014-06-03.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPNavigationController.h"
|
||||
#import "MPWebViewController.h"
|
||||
|
||||
@implementation MPNavigationController
|
||||
|
||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
||||
|
||||
if ([segue.identifier isEqualToString:@"web"])
|
||||
((MPWebViewController *)segue.destinationViewController).initialURL = [NSURL URLWithString:@"http://thanks.lhunath.com"];
|
||||
}
|
||||
|
||||
@end
|
@ -45,6 +45,7 @@ typedef NS_ENUM (NSUInteger, MPContentFieldMode) {
|
||||
- (void)resolveContentOfCellTypeForTransientSite:(NSString *)siteName usingKey:(MPKey *)key result:(void (^)(NSString *))resultBlock;
|
||||
- (void)resolveContentOfCellTypeForElement:(MPElementEntity *)element usingKey:(MPKey *)key result:(void (^)(NSString *))resultBlock;
|
||||
|
||||
- (void)willBeginDragging;
|
||||
- (MPElementEntity *)saveContentTypeWithElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context;
|
||||
|
||||
@end
|
||||
|
@ -152,6 +152,9 @@
|
||||
resultBlock( nil );
|
||||
}
|
||||
|
||||
- (void)willBeginDragging {
|
||||
}
|
||||
|
||||
- (MPElementEntity *)saveContentTypeWithElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context {
|
||||
|
||||
return [[MPiOSAppDelegate get] changeElement:element saveInContext:context toType:self.type];
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
@interface MPPasswordLargeGeneratedCell : MPPasswordLargeCell
|
||||
|
||||
@property(strong, nonatomic) IBOutlet UILabel *strengthLabel;
|
||||
@property(strong, nonatomic) IBOutlet UILabel *counterLabel;
|
||||
@property(strong, nonatomic) IBOutlet UIButton *counterButton;
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPPasswordLargeGeneratedCell.h
|
||||
@ -21,6 +21,11 @@
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPPasswordTypesCell.h"
|
||||
|
||||
@interface MPPasswordLargeGeneratedCell()
|
||||
|
||||
@property(nonatomic, weak) NSTimer *hideStrengthTimer;
|
||||
@end
|
||||
|
||||
@implementation MPPasswordLargeGeneratedCell
|
||||
|
||||
- (void)awakeFromNib {
|
||||
@ -28,10 +33,40 @@
|
||||
[super awakeFromNib];
|
||||
|
||||
UILongPressGestureRecognizer *gestureRecognizer = [[UILongPressGestureRecognizer alloc]
|
||||
initWithTarget:self action:@selector(doResetCounterRecognizer:)];
|
||||
initWithTarget:self action:@selector( doResetCounterRecognizer: )];
|
||||
[self.counterButton addGestureRecognizer:gestureRecognizer];
|
||||
}
|
||||
|
||||
- (void)prepareForReuse {
|
||||
|
||||
[super prepareForReuse];
|
||||
|
||||
self.strengthLabel.alpha = 0;
|
||||
}
|
||||
|
||||
- (void)willBeginDragging {
|
||||
|
||||
[super willBeginDragging];
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.strengthLabel.alpha = 1;
|
||||
}];
|
||||
|
||||
[self.hideStrengthTimer invalidate];
|
||||
self.hideStrengthTimer = [NSTimer scheduledTimerWithTimeInterval:1 block:^(NSTimer *timer) {
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.strengthLabel.alpha = 0;
|
||||
}];
|
||||
} repeats:NO];
|
||||
}
|
||||
|
||||
- (void)update {
|
||||
|
||||
[super update];
|
||||
|
||||
self.counterLabel.alpha = self.counterButton.alpha = 0;
|
||||
}
|
||||
|
||||
- (void)updateWithElement:(MPElementEntity *)mainElement {
|
||||
|
||||
[super updateWithElement:mainElement];
|
||||
@ -42,24 +77,18 @@
|
||||
else
|
||||
self.counterLabel.text = @"1";
|
||||
|
||||
if (!mainElement || mainElement.requiresExplicitMigration) {
|
||||
self.counterLabel.alpha = 0;
|
||||
self.counterButton.alpha = 0;
|
||||
}
|
||||
else {
|
||||
self.counterLabel.alpha = 1;
|
||||
self.counterButton.alpha = 1;
|
||||
}
|
||||
if (mainElement && !mainElement.requiresExplicitMigration)
|
||||
self.counterLabel.alpha = self.counterButton.alpha = 1;
|
||||
}
|
||||
|
||||
- (void)resolveContentOfCellTypeForTransientSite:(NSString *)siteName usingKey:(MPKey *)key result:(void (^)(NSString *))resultBlock {
|
||||
- (void)resolveContentOfCellTypeForTransientSite:(NSString *)siteName usingKey:(MPKey *)key result:(void ( ^ )(NSString *))resultBlock {
|
||||
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [MPAlgorithmDefault generateContentNamed:siteName ofType:self.type withCounter:1 usingKey:key] );
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)resolveContentOfCellTypeForElement:(MPElementEntity *)element usingKey:(MPKey *)key result:(void (^)(NSString *))resultBlock {
|
||||
- (void)resolveContentOfCellTypeForElement:(MPElementEntity *)element usingKey:(MPKey *)key result:(void ( ^ )(NSString *))resultBlock {
|
||||
|
||||
id<MPAlgorithm> algorithm = element.algorithm;
|
||||
NSString *siteName = element.name;
|
||||
@ -103,7 +132,7 @@
|
||||
|
||||
- (void)doResetCounterRecognizer:(UILongPressGestureRecognizer *)gestureRecognizer {
|
||||
|
||||
if (gestureRecognizer.state != UIGestureRecognizerStateEnded)
|
||||
if (gestureRecognizer.state != UIGestureRecognizerStateRecognized)
|
||||
return;
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
@ -123,6 +152,38 @@
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (void)setType:(MPElementType)type {
|
||||
|
||||
[super setType:type];
|
||||
|
||||
switch (type) {
|
||||
case MPElementTypeGeneratedMaximum:
|
||||
self.strengthLabel.text = @"> age of the universe";
|
||||
break;
|
||||
case MPElementTypeGeneratedLong:
|
||||
self.strengthLabel.text = @"196 billion years";
|
||||
break;
|
||||
case MPElementTypeGeneratedMedium:
|
||||
self.strengthLabel.text = @"5 months";
|
||||
break;
|
||||
case MPElementTypeGeneratedBasic:
|
||||
self.strengthLabel.text = @"12 days";
|
||||
break;
|
||||
case MPElementTypeGeneratedShort:
|
||||
self.strengthLabel.text = @"trivial";
|
||||
break;
|
||||
case MPElementTypeGeneratedPIN:
|
||||
self.strengthLabel.text = @"trivial";
|
||||
break;
|
||||
case MPElementTypeStoredPersonal:
|
||||
self.strengthLabel.text = @"";
|
||||
break;
|
||||
case MPElementTypeStoredDevicePrivate:
|
||||
self.strengthLabel.text = @"";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (MPElementGeneratedEntity *)generatedElementInContext:(NSManagedObjectContext *)context {
|
||||
|
||||
return [self generatedElement:[[MPPasswordTypesCell findAsSuperviewOf:self] elementInContext:context]];
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
@implementation MPPasswordTypesCell {
|
||||
NSManagedObjectID *_elementOID;
|
||||
BOOL _scrolling;
|
||||
}
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
@ -110,7 +111,9 @@
|
||||
[cell updateWithTransientSite:self.transientSite];
|
||||
else
|
||||
[cell updateWithElement:self.mainElement];
|
||||
dbg( @"cell %d, contentFieldMode: %d", indexPath.item, cell.contentFieldMode );
|
||||
|
||||
if (_scrolling)
|
||||
[cell willBeginDragging];
|
||||
|
||||
return cell;
|
||||
}
|
||||
@ -189,6 +192,13 @@
|
||||
|
||||
#pragma mark - UIScrollViewDelegate
|
||||
|
||||
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
|
||||
|
||||
_scrolling = YES;
|
||||
for (MPPasswordLargeCell *cell in [self.contentCollectionView visibleCells])
|
||||
[cell willBeginDragging];
|
||||
}
|
||||
|
||||
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity
|
||||
targetContentOffset:(inout CGPoint *)targetContentOffset {
|
||||
|
||||
@ -202,12 +212,14 @@
|
||||
|
||||
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
|
||||
|
||||
_scrolling = NO;
|
||||
if (scrollView == self.contentCollectionView && !decelerate)
|
||||
[self saveContentType];
|
||||
}
|
||||
|
||||
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
|
||||
|
||||
_scrolling = NO;
|
||||
if (scrollView == self.contentCollectionView)
|
||||
[self saveContentType];
|
||||
}
|
||||
|
@ -408,11 +408,8 @@ referenceSizeForHeaderInSection:(NSInteger)section {
|
||||
_active = active;
|
||||
|
||||
[UIView animateWithDuration:animated? 0.4f: 0 animations:^{
|
||||
self.navigationBarToTopConstraint.priority = active? 1: UILayoutPriorityDefaultHigh;
|
||||
self.passwordsToBottomConstraint.priority = active? 1: UILayoutPriorityDefaultHigh;
|
||||
|
||||
[self.navigationBarToTopConstraint apply];
|
||||
[self.passwordsToBottomConstraint apply];
|
||||
[self.navigationBarToTopConstraint layoutWithPriority:active? 1: UILayoutPriorityDefaultHigh];
|
||||
[self.passwordsToBottomConstraint layoutWithPriority:active? 1: UILayoutPriorityDefaultHigh];
|
||||
} completion:completion];
|
||||
}
|
||||
|
||||
|
@ -38,9 +38,8 @@
|
||||
metrics:nil views:NSDictionaryOfVariableBindings(popdownView)];
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
passwordsVC.popdownToTopConstraint.priority = 1;
|
||||
[passwordsVC.popdownToTopConstraint apply];
|
||||
} completion:^(BOOL finished) {
|
||||
[passwordsVC.popdownToTopConstraint layoutWithPriority:1];
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished)
|
||||
[popdownVC didMoveToParentViewController:passwordsVC];
|
||||
}];
|
||||
@ -51,8 +50,7 @@
|
||||
|
||||
[popdownVC willMoveToParentViewController:nil];
|
||||
[UIView animateWithDuration:0.3f delay:0 options:UIViewAnimationOptionOverrideInheritedDuration animations:^{
|
||||
passwordsVC.popdownToTopConstraint.priority = UILayoutPriorityDefaultHigh;
|
||||
[passwordsVC.popdownToTopConstraint apply];
|
||||
[passwordsVC.popdownToTopConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished) {
|
||||
[popdownVC.view removeFromSuperview];
|
||||
|
@ -24,5 +24,9 @@
|
||||
- (IBAction)previousAvatar:(id)sender;
|
||||
- (IBAction)nextAvatar:(id)sender;
|
||||
- (IBAction)valueChanged:(id)sender;
|
||||
- (IBAction)homePageButton:(id)sender;
|
||||
- (IBAction)securityButton:(id)sender;
|
||||
- (IBAction)sourceButton:(id)sender;
|
||||
- (IBAction)thanksButton:(id)sender;
|
||||
|
||||
@end
|
||||
|
@ -142,6 +142,30 @@
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)homePageButton:(id)sender {
|
||||
|
||||
[[self dismissPopup].navigationController performSegueWithIdentifier:@"web" sender:
|
||||
[NSURL URLWithString:@"http://masterpasswordapp.com"]];
|
||||
}
|
||||
|
||||
- (IBAction)securityButton:(id)sender {
|
||||
|
||||
[[self dismissPopup].navigationController performSegueWithIdentifier:@"web" sender:
|
||||
[NSURL URLWithString:@"http://masterpasswordapp.com/security.html"]];
|
||||
}
|
||||
|
||||
- (IBAction)sourceButton:(id)sender {
|
||||
|
||||
[[self dismissPopup].navigationController performSegueWithIdentifier:@"web" sender:
|
||||
[NSURL URLWithString:@"https://github.com/Lyndir/MasterPassword/"]];
|
||||
}
|
||||
|
||||
- (IBAction)thanksButton:(id)sender {
|
||||
|
||||
[[self dismissPopup].navigationController performSegueWithIdentifier:@"web" sender:
|
||||
[NSURL URLWithString:@"http://thanks.lhunath.com"]];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (MPPasswordsViewController *)dismissPopup {
|
||||
|
@ -1,23 +0,0 @@
|
||||
//
|
||||
// MPPreferencesViewController.h
|
||||
// MasterPassword-iOS
|
||||
//
|
||||
// Created by Maarten Billemont on 04/06/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "MPTypeViewController.h"
|
||||
|
||||
@interface MPPreferencesViewControllerOld : UITableViewController<MPTypeDelegate>
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UIScrollView *avatarsView;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *avatarTemplate;
|
||||
@property(weak, nonatomic) IBOutlet UISwitch *savePasswordSwitch;
|
||||
@property(weak, nonatomic) IBOutlet UITableViewCell *exportCell;
|
||||
@property(weak, nonatomic) IBOutlet UITableViewCell *changeMPCell;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *defaultTypeLabel;
|
||||
|
||||
- (IBAction)didToggleSwitch:(UISwitch *)sender;
|
||||
|
||||
@end
|
@ -1,163 +0,0 @@
|
||||
//
|
||||
// MPPreferencesViewController.m
|
||||
// MasterPassword-iOS
|
||||
//
|
||||
// Created by Maarten Billemont on 04/06/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
#import "MPPreferencesViewControllerOld.h"
|
||||
#import "MPiOSAppDelegate.h"
|
||||
#import "MPAppDelegate_Key.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
|
||||
@interface MPPreferencesViewControllerOld()
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPPreferencesViewControllerOld
|
||||
|
||||
- (void)viewDidLoad {
|
||||
|
||||
self.avatarTemplate.hidden = YES;
|
||||
|
||||
for (NSUInteger a = 0; a < MPAvatarCount; ++a) {
|
||||
UIButton *avatar = [self.avatarTemplate clone];
|
||||
avatar.tag = a;
|
||||
avatar.hidden = NO;
|
||||
avatar.center = CGPointMake(
|
||||
self.avatarTemplate.center.x * (a + 1) + self.avatarTemplate.bounds.size.width / 2 * a,
|
||||
self.avatarTemplate.center.y );
|
||||
[avatar setBackgroundImage:[UIImage imageNamed:PearlString( @"avatar-%ld", (long)a )]
|
||||
forState:UIControlStateNormal];
|
||||
[avatar setSelectionInSuperviewCandidate:YES isClearable:NO];
|
||||
|
||||
avatar.layer.cornerRadius = avatar.bounds.size.height / 2;
|
||||
avatar.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||
avatar.layer.shadowOpacity = 1;
|
||||
avatar.layer.shadowRadius = 5;
|
||||
avatar.backgroundColor = [UIColor clearColor];
|
||||
|
||||
[avatar onHighlightOrSelect:^(BOOL highlighted, BOOL selected) {
|
||||
if (highlighted || selected)
|
||||
avatar.backgroundColor = self.avatarTemplate.backgroundColor;
|
||||
else
|
||||
avatar.backgroundColor = [UIColor clearColor];
|
||||
} options:0];
|
||||
[avatar onSelect:^(BOOL selected) {
|
||||
if (selected) {
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
[[MPiOSAppDelegate get] activeUserInContext:moc].avatar = (unsigned)avatar.tag;
|
||||
[moc saveToStore];
|
||||
}];
|
||||
}
|
||||
} options:0];
|
||||
avatar.selected = (a == [[MPiOSAppDelegate get] activeUserForMainThread].avatar);
|
||||
}
|
||||
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
|
||||
inf(@"Preferences will appear");
|
||||
[self.avatarsView autoSizeContent];
|
||||
[self.avatarsView enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||
if (subview.tag && ((UIControl *)subview).selected) {
|
||||
[self.avatarsView setContentOffset:CGPointMake( subview.center.x - self.avatarsView.bounds.size.width / 2, 0 )
|
||||
animated:animated];
|
||||
}
|
||||
} recurse:NO];
|
||||
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForMainThread];
|
||||
self.savePasswordSwitch.on = activeUser.saveKey;
|
||||
self.defaultTypeLabel.text = [[MPiOSAppDelegate get].key.algorithm shortNameOfType:activeUser.defaultType];
|
||||
|
||||
[super viewWillAppear:animated];
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeFirstResponder {
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
|
||||
|
||||
if (motion == UIEventSubtypeMotionShake) {
|
||||
MPCheckpoint( MPCheckpointLogs, @{
|
||||
@"trace" : [MPiOSConfig get].traceMode
|
||||
} );
|
||||
[self performSegueWithIdentifier:@"MP_Logs" sender:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)shouldAutorotate {
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
|
||||
|
||||
return UIInterfaceOrientationPortrait;
|
||||
}
|
||||
|
||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
||||
|
||||
if ([[segue identifier] isEqualToString:@"MP_ChooseType"])
|
||||
((MPTypeViewController *)[segue destinationViewController]).delegate = self;
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
|
||||
if (cell == self.exportCell)
|
||||
[[MPiOSAppDelegate get] showExportForVC:self];
|
||||
|
||||
else if (cell == self.changeMPCell) {
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||
[[MPiOSAppDelegate get] changeMasterPasswordFor:activeUser saveInContext:moc didResetBlock:nil];
|
||||
}];
|
||||
}
|
||||
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
}
|
||||
|
||||
#pragma mark - MPTypeDelegate
|
||||
|
||||
- (void)didSelectType:(MPElementType)type {
|
||||
|
||||
self.defaultTypeLabel.text = [[MPiOSAppDelegate get].key.algorithm shortNameOfType:type];
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:context];
|
||||
activeUser.defaultType = type;
|
||||
[context saveToStore];
|
||||
}];
|
||||
}
|
||||
|
||||
- (MPElementType)selectedType {
|
||||
|
||||
return [[MPiOSAppDelegate get] activeUserForMainThread].defaultType;
|
||||
}
|
||||
|
||||
#pragma mark - IBActions
|
||||
|
||||
- (IBAction)didToggleSwitch:(UISwitch *)sender {
|
||||
|
||||
if (sender == self.savePasswordSwitch)
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||
if ((activeUser.saveKey = sender.on))
|
||||
[[MPiOSAppDelegate get] storeSavedKeyFor:activeUser];
|
||||
else
|
||||
[[MPiOSAppDelegate get] forgetSavedKeyFor:activeUser];
|
||||
[moc saveToStore];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
@ -1,54 +0,0 @@
|
||||
//
|
||||
// MBUnlockViewController.h
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 22/02/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "LLGitTip.h"
|
||||
|
||||
@interface MPUnlockViewController : UIViewController<UITextFieldDelegate, UIScrollViewDelegate, UIWebViewDelegate>
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UIImageView *spinner;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *passwordFieldLabel;
|
||||
@property(weak, nonatomic) IBOutlet UITextField *passwordField;
|
||||
@property(weak, nonatomic) IBOutlet UIView *passwordView;
|
||||
@property(weak, nonatomic) IBOutlet UIScrollView *avatarsView;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *nameLabel;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *oldNameLabel;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *avatarTemplate;
|
||||
@property(weak, nonatomic) IBOutlet UIView *createPasswordTipView;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *tip;
|
||||
@property(weak, nonatomic) IBOutlet UIView *passwordTipView;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *passwordTipLabel;
|
||||
@property(weak, nonatomic) IBOutlet UIView *wordWall;
|
||||
@property(strong, nonatomic) IBOutlet UILongPressGestureRecognizer *targetedUserActionGesture;
|
||||
@property(weak, nonatomic) IBOutlet UIView *uiContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *shareContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *tipsTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet LLGitTip *gitTipButton;
|
||||
@property(weak, nonatomic) IBOutlet UIWebView *newsView;
|
||||
@property(weak, nonatomic) IBOutlet UIView *emergencyGeneratorContainer;
|
||||
@property(weak, nonatomic) IBOutlet UITextField *emergencyName;
|
||||
@property(weak, nonatomic) IBOutlet UITextField *emergencyMasterPassword;
|
||||
@property(weak, nonatomic) IBOutlet UITextField *emergencySite;
|
||||
@property(weak, nonatomic) IBOutlet UIStepper *emergencyCounterStepper;
|
||||
@property(weak, nonatomic) IBOutlet UISegmentedControl *emergencyTypeControl;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *emergencyCounter;
|
||||
@property(weak, nonatomic) IBOutlet UIActivityIndicatorView *emergencyActivity;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *emergencyPassword;
|
||||
@property(weak, nonatomic) IBOutlet UIView *emergencyContentTipContainer;
|
||||
|
||||
- (IBAction)targetedUserAction:(UILongPressGestureRecognizer *)sender;
|
||||
- (IBAction)facebook:(id)sender;
|
||||
- (IBAction)twitter:(id)sender;
|
||||
- (IBAction)google:(id)sender;
|
||||
- (IBAction)mail:(id)sender;
|
||||
- (IBAction)add:(id)sender;
|
||||
- (IBAction)emergencyOpen:(id)sender;
|
||||
- (IBAction)emergencyClose:(id)sender;
|
||||
- (IBAction)emergencyCopy:(id)sender;
|
||||
|
||||
@end
|
File diff suppressed because it is too large
Load Diff
@ -805,7 +805,7 @@ typedef NS_ENUM(NSUInteger, MPActiveUserState) {
|
||||
case MPActiveUserStateUserName:
|
||||
case MPActiveUserStateMasterPasswordChoice:
|
||||
case MPActiveUserStateMasterPasswordConfirmation: {
|
||||
self.navigationBarToTopConstraint.priority = UILayoutPriorityDefaultHigh;
|
||||
[self.navigationBarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
self.avatarCollectionView.scrollEnabled = NO;
|
||||
self.entryContainer.alpha = 1;
|
||||
self.footerContainer.alpha = 1;
|
||||
@ -813,14 +813,13 @@ typedef NS_ENUM(NSUInteger, MPActiveUserState) {
|
||||
break;
|
||||
}
|
||||
case MPActiveUserStateMinimized: {
|
||||
self.navigationBarToTopConstraint.priority = 1;
|
||||
[self.navigationBarToTopConstraint layoutWithPriority:1];
|
||||
self.avatarCollectionView.scrollEnabled = NO;
|
||||
self.entryContainer.alpha = 0;
|
||||
self.footerContainer.alpha = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
[self.navigationBarToTopConstraint apply];
|
||||
} completion:^(BOOL finished) {
|
||||
dbg(@"resume updates");
|
||||
[_afterUpdates setSuspended:NO];
|
||||
|
@ -34,6 +34,8 @@
|
||||
if (!self.initialURL)
|
||||
self.initialURL = [NSURL URLWithString:@"http://masterpasswordapp.com"];
|
||||
|
||||
self.webNavigationItem.title = self.initialURL.host;
|
||||
|
||||
self.webView.alpha = 0;
|
||||
[self.webView loadRequest:[[NSURLRequest alloc] initWithURL:self.initialURL]];
|
||||
}
|
||||
|
@ -364,27 +364,34 @@
|
||||
|
||||
- (void)showExportForVC:(UIViewController *)viewController {
|
||||
|
||||
[PearlAlert showNotice:
|
||||
@"This will export all your site names.\n\n"
|
||||
@"You can open the export with a text editor to get an overview of all your sites.\n\n"
|
||||
@"The file also acts as a personal backup of your site list in case you don't sync with iCloud/iTunes."
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
[PearlAlert showAlertWithTitle:@"Reveal Passwords?" message:
|
||||
@"Would you like to make all your passwords visible in the export?\n\n"
|
||||
@"A safe export will only include your stored passwords, in an encrypted manner, "
|
||||
@"making the result safe from falling in the wrong hands.\n\n"
|
||||
@"If all your passwords are shown and somebody else finds the export, "
|
||||
@"they could gain access to all your sites!"
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil
|
||||
tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 0)
|
||||
// Safe Export
|
||||
[self showExportRevealPasswords:NO forVC:viewController];
|
||||
if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 1)
|
||||
// Show Passwords
|
||||
[self showExportRevealPasswords:YES forVC:viewController];
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Safe Export", @"Show Passwords", nil];
|
||||
} otherTitles:nil];
|
||||
[PearlAlert showAlertWithTitle:@"Exporting Your Sites"
|
||||
message:@"An export is great for keeping a "
|
||||
@"backup list of your accounts.\n\n"
|
||||
@"When the file is ready, you will be "
|
||||
@"able to mail it to yourself.\n"
|
||||
@"You can open it with a text editor or "
|
||||
@"with Master Password if you need to "
|
||||
@"restore your list of sites."
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex != [alert cancelButtonIndex])
|
||||
[PearlAlert showAlertWithTitle:@"Show Passwords?"
|
||||
message:@"Would you like to make all your passwords "
|
||||
@"visible in the export file?\n\n"
|
||||
@"A safe export will include all sites "
|
||||
@"but make their passwords invisible.\n"
|
||||
@"It is great as a backup and remains "
|
||||
@"safe when fallen in the wrong hands."
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil
|
||||
tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 0)
|
||||
// Safe Export
|
||||
[self showExportRevealPasswords:NO forVC:viewController];
|
||||
if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 1)
|
||||
// Show Passwords
|
||||
[self showExportRevealPasswords:YES forVC:viewController];
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Safe Export", @"Show Passwords", nil];
|
||||
} cancelTitle:@"Cancel" otherTitles:@"Export Sites", nil];
|
||||
}
|
||||
|
||||
- (void)showExportRevealPasswords:(BOOL)revealPasswords forVC:(UIViewController *)viewController {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -41,7 +41,6 @@
|
||||
93D399BBC0A7EC746CB1B19B /* MPLogsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D391943675426839501BB8 /* MPLogsViewController.h */; };
|
||||
93D39A5FF670957C0AF8298D /* MPPasswordCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39DEA995041A13DC9CAF7 /* MPPasswordCell.m */; };
|
||||
93D39A8EA1C49CE43B63F47B /* PearlUICollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D8A953779B35403AF6E /* PearlUICollectionView.m */; };
|
||||
93D39B21156EC9A0B4C2BC83 /* MPPreferencesViewControllerOld.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D390381D3D3AE241B5D341 /* MPPreferencesViewControllerOld.m */; };
|
||||
93D39B76DD5AB108BA8928E8 /* UIScrollView+PearlAdjustInsets.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39DE2CB351D4E3789462B /* UIScrollView+PearlAdjustInsets.h */; };
|
||||
93D39B842AB9A5D072810D76 /* NSError+PearlFullDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */; };
|
||||
93D39B8F90F58A5D158DDBA3 /* MPPasswordsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */; };
|
||||
@ -50,6 +49,7 @@
|
||||
93D39C8AD8EAB747856B3A8C /* LLModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3923B42DA2DA18F287092 /* LLModel.m */; };
|
||||
93D39CB5E2EC1078E898F46A /* MPPasswordLargeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3937863061C3916AF7AD2 /* MPPasswordLargeCell.m */; };
|
||||
93D39D596A2E376D6F6F5DA1 /* MPCombinedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D393310223DDB35218467A /* MPCombinedViewController.m */; };
|
||||
93D39D8F78978196D6ABDEDE /* MPNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39CC01630D0421205C4C4 /* MPNavigationController.m */; };
|
||||
93D39E281E3658B30550CB55 /* NSDictionary+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */; };
|
||||
93D39E34FD28D24FE3442C48 /* UITextView+PearlAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3977321EB249981821AB0 /* UITextView+PearlAttributes.m */; };
|
||||
93D39EAA4D064193074D3021 /* MPFixable.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A813CA9D7E192261ED2 /* MPFixable.m */; };
|
||||
@ -249,19 +249,10 @@
|
||||
DABD3C091711E2DC00CF925C /* MPUserEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BBA1711E2DC00CF925C /* MPUserEntity.m */; };
|
||||
DABD3C141711E2DC00CF925C /* MasterPassword.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BD01711E2DC00CF925C /* MasterPassword.xcdatamodeld */; };
|
||||
DABD3C151711E2DC00CF925C /* MPiOSAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BD91711E2DC00CF925C /* MPiOSAppDelegate.m */; };
|
||||
DABD3C161711E2DC00CF925C /* MPAppViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BDB1711E2DC00CF925C /* MPAppViewController.m */; };
|
||||
DABD3C171711E2DC00CF925C /* MPAppsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BDD1711E2DC00CF925C /* MPAppsViewController.m */; };
|
||||
DABD3C181711E2DC00CF925C /* MPElementListAllViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BDF1711E2DC00CF925C /* MPElementListAllViewController.m */; };
|
||||
DABD3C191711E2DC00CF925C /* MPElementListCellView.xib in Resources */ = {isa = PBXBuildFile; fileRef = DABD3BE01711E2DC00CF925C /* MPElementListCellView.xib */; };
|
||||
DABD3C1A1711E2DC00CF925C /* MPElementListController.m in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BE21711E2DC00CF925C /* MPElementListController.m */; };
|
||||
DABD3C1B1711E2DC00CF925C /* MPElementListSearchController.m in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BE51711E2DC00CF925C /* MPElementListSearchController.m */; };
|
||||
DABD3C1C1711E2DC00CF925C /* MPGuideViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BE71711E2DC00CF925C /* MPGuideViewController.m */; };
|
||||
DABD3C1D1711E2DC00CF925C /* MPMainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BE91711E2DC00CF925C /* MPMainViewController.m */; };
|
||||
DABD3C1E1711E2DC00CF925C /* MPPreferencesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BEB1711E2DC00CF925C /* MPPreferencesViewController.m */; };
|
||||
DABD3C1F1711E2DC00CF925C /* MPTypeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BED1711E2DC00CF925C /* MPTypeViewController.m */; };
|
||||
DABD3C201711E2DC00CF925C /* MPUnlockViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BEF1711E2DC00CF925C /* MPUnlockViewController.m */; };
|
||||
DABD3C211711E2DC00CF925C /* MPiOSConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = DABD3BF11711E2DC00CF925C /* MPiOSConfig.m */; };
|
||||
DABD3C221711E2DC00CF925C /* MainStoryboard_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DABD3BF21711E2DC00CF925C /* MainStoryboard_iPhone.storyboard */; };
|
||||
DABD3C241711E2DC00CF925C /* MasterPassword.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = DABD3BF81711E2DC00CF925C /* MasterPassword.entitlements */; };
|
||||
DABD3C251711E2DC00CF925C /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = DABD3BF91711E2DC00CF925C /* Settings.bundle */; };
|
||||
DABD3C261711E2DC00CF925C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DABD3BFA1711E2DC00CF925C /* InfoPlist.strings */; };
|
||||
@ -511,7 +502,6 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
93D390381D3D3AE241B5D341 /* MPPreferencesViewControllerOld.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPreferencesViewControllerOld.m; sourceTree = "<group>"; };
|
||||
93D390519405B76CC6A57C4F /* MPCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCell.h; sourceTree = "<group>"; };
|
||||
93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Indexing.m"; sourceTree = "<group>"; };
|
||||
93D39097C0AAE62C1C321BFC /* MPPasswordTypesCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordTypesCell.m; sourceTree = "<group>"; };
|
||||
@ -540,6 +530,7 @@
|
||||
93D395BA6B2CFF5F49A4D25F /* MPPasswordLargeStoredCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordLargeStoredCell.h; sourceTree = "<group>"; };
|
||||
93D3966B527CA47A0A661CE2 /* MPPasswordLargeDeleteCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordLargeDeleteCell.h; sourceTree = "<group>"; };
|
||||
93D396D04E57792A54D437AC /* NSArray+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Indexing.h"; sourceTree = "<group>"; };
|
||||
93D3970502644794E8A027BE /* MPNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNavigationController.h; sourceTree = "<group>"; };
|
||||
93D3971FE104BB4052484151 /* MPUsersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUsersViewController.h; sourceTree = "<group>"; };
|
||||
93D39730673227EFF6DEFF19 /* MPSetupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSetupViewController.h; sourceTree = "<group>"; };
|
||||
93D3977321EB249981821AB0 /* UITextView+PearlAttributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITextView+PearlAttributes.m"; sourceTree = "<group>"; };
|
||||
@ -551,7 +542,6 @@
|
||||
93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPWebViewController.m; sourceTree = "<group>"; };
|
||||
93D3993422E207BF0B21D089 /* MPPasswordLargeGeneratedCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordLargeGeneratedCell.m; sourceTree = "<group>"; };
|
||||
93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCoachmarkViewController.m; sourceTree = "<group>"; };
|
||||
93D39961CD6A43648CC0B0DB /* MPPreferencesViewControllerOld.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPreferencesViewControllerOld.h; sourceTree = "<group>"; };
|
||||
93D39975CE5AEC99E3F086C7 /* MPPasswordCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordCell.h; sourceTree = "<group>"; };
|
||||
93D3999693660C89A7465F4E /* MPCoachmarkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCoachmarkViewController.h; sourceTree = "<group>"; };
|
||||
93D399E571F61E50A9BF8FAF /* MPUsersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPUsersViewController.m; sourceTree = "<group>"; };
|
||||
@ -574,6 +564,7 @@
|
||||
93D39C44361BE57AF0B3071F /* MPPasswordsSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordsSegue.h; sourceTree = "<group>"; };
|
||||
93D39C86E984EC65DA5ACB1D /* MPAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppSettingsViewController.h; sourceTree = "<group>"; };
|
||||
93D39C8E26B06F01566785B7 /* LLToggleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLToggleViewController.m; sourceTree = "<group>"; };
|
||||
93D39CC01630D0421205C4C4 /* MPNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNavigationController.m; sourceTree = "<group>"; };
|
||||
93D39CDD434AFD6E1B0DA359 /* MPEmergencyViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEmergencyViewController.h; sourceTree = "<group>"; };
|
||||
93D39CE1138FDA4D3D1B847A /* MPPasswordLargeGeneratedCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordLargeGeneratedCell.h; sourceTree = "<group>"; };
|
||||
93D39CF8ADF4542CDC4CD385 /* MPCombinedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCombinedViewController.h; sourceTree = "<group>"; };
|
||||
@ -1310,31 +1301,14 @@
|
||||
DABD3BD41711E2DC00CF925C /* MasterPassword 4.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MasterPassword 4.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DABD3BD81711E2DC00CF925C /* MPiOSAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPiOSAppDelegate.h; sourceTree = "<group>"; };
|
||||
DABD3BD91711E2DC00CF925C /* MPiOSAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPiOSAppDelegate.m; sourceTree = "<group>"; };
|
||||
DABD3BDA1711E2DC00CF925C /* MPAppViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppViewController.h; sourceTree = "<group>"; };
|
||||
DABD3BDB1711E2DC00CF925C /* MPAppViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppViewController.m; sourceTree = "<group>"; };
|
||||
DABD3BDC1711E2DC00CF925C /* MPAppsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppsViewController.h; sourceTree = "<group>"; };
|
||||
DABD3BDD1711E2DC00CF925C /* MPAppsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppsViewController.m; sourceTree = "<group>"; };
|
||||
DABD3BDE1711E2DC00CF925C /* MPElementListAllViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementListAllViewController.h; sourceTree = "<group>"; };
|
||||
DABD3BDF1711E2DC00CF925C /* MPElementListAllViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementListAllViewController.m; sourceTree = "<group>"; };
|
||||
DABD3BE01711E2DC00CF925C /* MPElementListCellView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPElementListCellView.xib; sourceTree = "<group>"; };
|
||||
DABD3BE11711E2DC00CF925C /* MPElementListController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementListController.h; sourceTree = "<group>"; };
|
||||
DABD3BE21711E2DC00CF925C /* MPElementListController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementListController.m; sourceTree = "<group>"; };
|
||||
DABD3BE31711E2DC00CF925C /* MPElementListDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementListDelegate.h; sourceTree = "<group>"; };
|
||||
DABD3BE41711E2DC00CF925C /* MPElementListSearchController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementListSearchController.h; sourceTree = "<group>"; };
|
||||
DABD3BE51711E2DC00CF925C /* MPElementListSearchController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementListSearchController.m; sourceTree = "<group>"; };
|
||||
DABD3BE61711E2DC00CF925C /* MPGuideViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPGuideViewController.h; sourceTree = "<group>"; };
|
||||
DABD3BE71711E2DC00CF925C /* MPGuideViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPGuideViewController.m; sourceTree = "<group>"; };
|
||||
DABD3BE81711E2DC00CF925C /* MPMainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMainViewController.h; sourceTree = "<group>"; };
|
||||
DABD3BE91711E2DC00CF925C /* MPMainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMainViewController.m; sourceTree = "<group>"; };
|
||||
DABD3BEA1711E2DC00CF925C /* MPPreferencesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPreferencesViewController.h; sourceTree = "<group>"; };
|
||||
DABD3BEB1711E2DC00CF925C /* MPPreferencesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPreferencesViewController.m; sourceTree = "<group>"; };
|
||||
DABD3BEC1711E2DC00CF925C /* MPTypeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPTypeViewController.h; sourceTree = "<group>"; };
|
||||
DABD3BED1711E2DC00CF925C /* MPTypeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTypeViewController.m; sourceTree = "<group>"; };
|
||||
DABD3BEE1711E2DC00CF925C /* MPUnlockViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUnlockViewController.h; sourceTree = "<group>"; };
|
||||
DABD3BEF1711E2DC00CF925C /* MPUnlockViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPUnlockViewController.m; sourceTree = "<group>"; };
|
||||
DABD3BF01711E2DC00CF925C /* MPiOSConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPiOSConfig.h; sourceTree = "<group>"; };
|
||||
DABD3BF11711E2DC00CF925C /* MPiOSConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPiOSConfig.m; sourceTree = "<group>"; };
|
||||
DABD3BF21711E2DC00CF925C /* MainStoryboard_iPhone.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = MainStoryboard_iPhone.storyboard; sourceTree = "<group>"; };
|
||||
DABD3BF31711E2DC00CF925C /* MasterPassword-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "MasterPassword-Info.plist"; sourceTree = "<group>"; };
|
||||
DABD3BF41711E2DC00CF925C /* MasterPassword-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MasterPassword-Prefix.pch"; sourceTree = "<group>"; };
|
||||
DABD3BF81711E2DC00CF925C /* MasterPassword.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = MasterPassword.entitlements; sourceTree = "<group>"; };
|
||||
@ -2523,35 +2497,16 @@
|
||||
93D39DEA995041A13DC9CAF7 /* MPPasswordCell.m */,
|
||||
93D39ACBA9F4878B6A1CC33B /* MPEmergencyViewController.m */,
|
||||
93D39CDD434AFD6E1B0DA359 /* MPEmergencyViewController.h */,
|
||||
93D390381D3D3AE241B5D341 /* MPPreferencesViewControllerOld.m */,
|
||||
93D39961CD6A43648CC0B0DB /* MPPreferencesViewControllerOld.h */,
|
||||
DABD3BD81711E2DC00CF925C /* MPiOSAppDelegate.h */,
|
||||
DABD3BD91711E2DC00CF925C /* MPiOSAppDelegate.m */,
|
||||
DABD3BDA1711E2DC00CF925C /* MPAppViewController.h */,
|
||||
DABD3BDB1711E2DC00CF925C /* MPAppViewController.m */,
|
||||
DABD3BDC1711E2DC00CF925C /* MPAppsViewController.h */,
|
||||
DABD3BDD1711E2DC00CF925C /* MPAppsViewController.m */,
|
||||
DABD3BDE1711E2DC00CF925C /* MPElementListAllViewController.h */,
|
||||
DABD3BDF1711E2DC00CF925C /* MPElementListAllViewController.m */,
|
||||
DABD3BE01711E2DC00CF925C /* MPElementListCellView.xib */,
|
||||
DABD3BE11711E2DC00CF925C /* MPElementListController.h */,
|
||||
DABD3BE21711E2DC00CF925C /* MPElementListController.m */,
|
||||
DABD3BE31711E2DC00CF925C /* MPElementListDelegate.h */,
|
||||
DABD3BE41711E2DC00CF925C /* MPElementListSearchController.h */,
|
||||
DABD3BE51711E2DC00CF925C /* MPElementListSearchController.m */,
|
||||
DABD3BE61711E2DC00CF925C /* MPGuideViewController.h */,
|
||||
DABD3BE71711E2DC00CF925C /* MPGuideViewController.m */,
|
||||
DABD3BE81711E2DC00CF925C /* MPMainViewController.h */,
|
||||
DABD3BE91711E2DC00CF925C /* MPMainViewController.m */,
|
||||
DABD3BEA1711E2DC00CF925C /* MPPreferencesViewController.h */,
|
||||
DABD3BEB1711E2DC00CF925C /* MPPreferencesViewController.m */,
|
||||
DABD3BEC1711E2DC00CF925C /* MPTypeViewController.h */,
|
||||
DABD3BED1711E2DC00CF925C /* MPTypeViewController.m */,
|
||||
DABD3BEE1711E2DC00CF925C /* MPUnlockViewController.h */,
|
||||
DABD3BEF1711E2DC00CF925C /* MPUnlockViewController.m */,
|
||||
DABD3BF01711E2DC00CF925C /* MPiOSConfig.h */,
|
||||
DABD3BF11711E2DC00CF925C /* MPiOSConfig.m */,
|
||||
DABD3BF21711E2DC00CF925C /* MainStoryboard_iPhone.storyboard */,
|
||||
DABD3BF31711E2DC00CF925C /* MasterPassword-Info.plist */,
|
||||
DABD3BF41711E2DC00CF925C /* MasterPassword-Prefix.pch */,
|
||||
DABD3BF81711E2DC00CF925C /* MasterPassword.entitlements */,
|
||||
@ -2595,6 +2550,8 @@
|
||||
93D390FD93EFCFECB5193DEF /* MPPasswordsCoachmarkViewController.h */,
|
||||
93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */,
|
||||
93D39F556F2F142740A65E59 /* MPWebViewController.h */,
|
||||
93D39CC01630D0421205C4C4 /* MPNavigationController.m */,
|
||||
93D3970502644794E8A027BE /* MPNavigationController.h */,
|
||||
);
|
||||
path = iOS;
|
||||
sourceTree = "<group>";
|
||||
@ -3676,9 +3633,7 @@
|
||||
DADEF4121810D2940052CA3E /* love-lyndir.button.green.png in Resources */,
|
||||
DABD3B9D1711E29800CF925C /* social-twitter.png in Resources */,
|
||||
DABD3B9E1711E29800CF925C /* social-twitter@2x.png in Resources */,
|
||||
DABD3C191711E2DC00CF925C /* MPElementListCellView.xib in Resources */,
|
||||
DA854C8418D4CFBF00106317 /* avatar-add.png in Resources */,
|
||||
DABD3C221711E2DC00CF925C /* MainStoryboard_iPhone.storyboard in Resources */,
|
||||
DABD3C241711E2DC00CF925C /* MasterPassword.entitlements in Resources */,
|
||||
DABD3C251711E2DC00CF925C /* Settings.bundle in Resources */,
|
||||
DABD3C261711E2DC00CF925C /* InfoPlist.strings in Resources */,
|
||||
@ -3777,16 +3732,9 @@
|
||||
DABD3C091711E2DC00CF925C /* MPUserEntity.m in Sources */,
|
||||
DABD3C141711E2DC00CF925C /* MasterPassword.xcdatamodeld in Sources */,
|
||||
DABD3C151711E2DC00CF925C /* MPiOSAppDelegate.m in Sources */,
|
||||
DABD3C161711E2DC00CF925C /* MPAppViewController.m in Sources */,
|
||||
DABD3C171711E2DC00CF925C /* MPAppsViewController.m in Sources */,
|
||||
DABD3C181711E2DC00CF925C /* MPElementListAllViewController.m in Sources */,
|
||||
DABD3C1A1711E2DC00CF925C /* MPElementListController.m in Sources */,
|
||||
DABD3C1B1711E2DC00CF925C /* MPElementListSearchController.m in Sources */,
|
||||
DABD3C1C1711E2DC00CF925C /* MPGuideViewController.m in Sources */,
|
||||
DABD3C1D1711E2DC00CF925C /* MPMainViewController.m in Sources */,
|
||||
DABD3C1E1711E2DC00CF925C /* MPPreferencesViewController.m in Sources */,
|
||||
DABD3C1F1711E2DC00CF925C /* MPTypeViewController.m in Sources */,
|
||||
DABD3C201711E2DC00CF925C /* MPUnlockViewController.m in Sources */,
|
||||
DABD3C211711E2DC00CF925C /* MPiOSConfig.m in Sources */,
|
||||
DABD3C271711E2DC00CF925C /* main.m in Sources */,
|
||||
93D39F8A9254177891F38705 /* MPSetupViewController.m in Sources */,
|
||||
@ -3805,13 +3753,13 @@
|
||||
93D391ED37C9F687FA51EAA1 /* MPEmergencySegue.m in Sources */,
|
||||
93D394B5036C882B33C71872 /* MPPasswordsSegue.m in Sources */,
|
||||
93D39673DDC085BE72C34D7C /* MPPopdownSegue.m in Sources */,
|
||||
93D39B21156EC9A0B4C2BC83 /* MPPreferencesViewControllerOld.m in Sources */,
|
||||
93D39BA1EA3CAAC8A220B4A6 /* MPAppSettingsViewController.m in Sources */,
|
||||
93D396D8B67DA6522CDBA142 /* MPCoachmarkViewController.m in Sources */,
|
||||
93D391C07818F4C2DC1B6956 /* MPPasswordsCoachmarkViewController.m in Sources */,
|
||||
93D39EAA4D064193074D3021 /* MPFixable.m in Sources */,
|
||||
93D394982CBD25D46692DD7C /* MPWebViewController.m in Sources */,
|
||||
93D398BD8B83FEE8BE4EFFFC /* MPPasswordLargeDeleteCell.m in Sources */,
|
||||
93D39D8F78978196D6ABDEDE /* MPNavigationController.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -251,7 +251,7 @@
|
||||
<segue destination="Sd5-eW-Cx2" kind="modal" identifier="web" id="gtb-zE-u9H"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="069-Pu-yXe" userLabel="GitTip Tip">
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="069-Pu-yXe" userLabel="Thanks Tip">
|
||||
<rect key="frame" x="42" y="0.0" width="236" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
@ -410,7 +410,7 @@
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="bzn-yi-kMJ">
|
||||
<objects>
|
||||
<navigationController definesPresentationContext="YES" navigationBarHidden="YES" id="Q1S-vU-GGO" sceneMemberID="viewController">
|
||||
<navigationController definesPresentationContext="YES" navigationBarHidden="YES" id="Q1S-vU-GGO" customClass="MPNavigationController" sceneMemberID="viewController">
|
||||
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="lightContent"/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="4yl-zs-iUd">
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
@ -504,7 +504,7 @@
|
||||
<sections>
|
||||
<tableViewSection id="FEv-Rb-jst">
|
||||
<cells>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="97" id="R30-AU-bR6" userLabel="Sign Out">
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" rowHeight="97" id="R30-AU-bR6" userLabel="Sign Out">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="97"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="R30-AU-bR6" id="f6h-Ff-2Qc">
|
||||
@ -538,7 +538,7 @@
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="216" id="B8R-iE-Ffe" userLabel="Default Password Type">
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" rowHeight="216" id="B8R-iE-Ffe" userLabel="Default Password Type">
|
||||
<rect key="frame" x="0.0" y="97" width="320" height="216"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="B8R-iE-Ffe" id="8r5-Zc-TRj">
|
||||
@ -604,7 +604,7 @@
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="220" id="Sz1-JP-dw2" userLabel="Avatar">
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" rowHeight="220" id="Sz1-JP-dw2" userLabel="Avatar">
|
||||
<rect key="frame" x="0.0" y="313" width="320" height="220"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Sz1-JP-dw2" id="R4X-LE-ir9">
|
||||
@ -684,7 +684,7 @@
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="230" id="fRZ-Uh-FR8" userLabel="Save Password">
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" rowHeight="230" id="fRZ-Uh-FR8" userLabel="Save Password">
|
||||
<rect key="frame" x="0.0" y="533" width="320" height="230"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="fRZ-Uh-FR8" id="qCQ-L5-teL">
|
||||
@ -728,7 +728,7 @@
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="97" id="9QG-lM-ymM" userLabel="Feedback">
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" rowHeight="97" id="9QG-lM-ymM" userLabel="Feedback">
|
||||
<rect key="frame" x="0.0" y="763" width="320" height="97"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="9QG-lM-ymM" id="hK8-XQ-lLz">
|
||||
@ -762,7 +762,7 @@
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="97" id="eth-Dc-JYn" userLabel="Reveal Coachmarks">
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" rowHeight="97" id="eth-Dc-JYn" userLabel="Reveal Coachmarks">
|
||||
<rect key="frame" x="0.0" y="860" width="320" height="97"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="eth-Dc-JYn" id="8m6-pP-lda">
|
||||
@ -796,7 +796,7 @@
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="110" id="UdB-BV-AHA" userLabel="Check Inconsistencies">
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" rowHeight="110" id="UdB-BV-AHA" userLabel="Check Inconsistencies">
|
||||
<rect key="frame" x="0.0" y="957" width="320" height="110"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="UdB-BV-AHA" id="V2Y-nu-jhZ">
|
||||
@ -830,7 +830,7 @@
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="125" id="IVT-Rs-nTu" userLabel="Export">
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" rowHeight="125" id="IVT-Rs-nTu" userLabel="Export">
|
||||
<rect key="frame" x="0.0" y="1067" width="320" height="125"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="IVT-Rs-nTu" id="Q5J-2f-mmz">
|
||||
@ -865,6 +865,86 @@
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" rowHeight="153" id="hmf-Wz-9l2" userLabel="Footer">
|
||||
<rect key="frame" x="0.0" y="1192" width="320" height="153"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hmf-Wz-9l2" id="AL3-2q-tgO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="152"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" text="© 2012-2014, 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="280" height="12"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Thin" family="Exo 2.0" pointSize="10"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Rl7-cr-FHf">
|
||||
<rect key="frame" x="20" y="24" width="280" height="26"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="11"/>
|
||||
<state key="normal" title="Home Page">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="homePageButton:" destination="JFc-sj-awD" eventType="touchUpInside" id="ptD-cv-NMr"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="epW-Rm-9St">
|
||||
<rect key="frame" x="20" y="58" width="280" height="26"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="11"/>
|
||||
<state key="normal" title="Understanding Master Password's Security">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="securityButton:" destination="JFc-sj-awD" eventType="touchUpInside" id="Efv-cp-Xfh"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LTN-ch-h8D">
|
||||
<rect key="frame" x="20" y="92" width="280" height="26"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="11"/>
|
||||
<state key="normal" title="Get the Master Password source code">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="sourceButton:" destination="JFc-sj-awD" eventType="touchUpInside" id="Y3O-di-CZo"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Z60-lc-Nka">
|
||||
<rect key="frame" x="20" y="126" width="280" height="26"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="11"/>
|
||||
<state key="normal" title="Send Thanks">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="thanksButton:" destination="JFc-sj-awD" eventType="touchUpInside" id="SqG-hx-mzF"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="LTN-ch-h8D" secondAttribute="trailing" constant="20" symbolic="YES" id="1W6-6Q-Bdv"/>
|
||||
<constraint firstItem="LTN-ch-h8D" firstAttribute="top" secondItem="epW-Rm-9St" secondAttribute="bottom" constant="8" symbolic="YES" id="7YP-IL-yTY"/>
|
||||
<constraint firstItem="Z60-lc-Nka" firstAttribute="leading" secondItem="AL3-2q-tgO" secondAttribute="leading" constant="20" symbolic="YES" id="Fnk-lP-q0U"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Z60-lc-Nka" secondAttribute="bottom" id="Jbk-vs-bo1"/>
|
||||
<constraint firstItem="sPw-mV-mFF" firstAttribute="leading" secondItem="AL3-2q-tgO" secondAttribute="leading" constant="20" symbolic="YES" id="Jme-5a-dNH"/>
|
||||
<constraint firstItem="LTN-ch-h8D" firstAttribute="leading" secondItem="AL3-2q-tgO" secondAttribute="leading" constant="20" symbolic="YES" id="RpC-WA-bnf"/>
|
||||
<constraint firstItem="sPw-mV-mFF" firstAttribute="top" secondItem="AL3-2q-tgO" secondAttribute="top" constant="4" id="X4M-st-0KA"/>
|
||||
<constraint firstItem="Z60-lc-Nka" firstAttribute="top" secondItem="LTN-ch-h8D" secondAttribute="bottom" constant="8" symbolic="YES" id="YSW-fw-h4i"/>
|
||||
<constraint firstItem="epW-Rm-9St" firstAttribute="top" secondItem="Rl7-cr-FHf" secondAttribute="bottom" constant="8" symbolic="YES" id="b0H-uh-d3G"/>
|
||||
<constraint firstItem="Rl7-cr-FHf" firstAttribute="top" secondItem="sPw-mV-mFF" secondAttribute="bottom" constant="8" symbolic="YES" id="gwp-Uq-BEm"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Z60-lc-Nka" secondAttribute="trailing" constant="20" symbolic="YES" id="iCv-UX-pPf"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Rl7-cr-FHf" secondAttribute="trailing" constant="20" symbolic="YES" id="oej-WB-7Vb"/>
|
||||
<constraint firstItem="Rl7-cr-FHf" firstAttribute="leading" secondItem="AL3-2q-tgO" secondAttribute="leading" constant="20" symbolic="YES" id="r2V-pM-d9B"/>
|
||||
<constraint firstItem="epW-Rm-9St" firstAttribute="leading" secondItem="AL3-2q-tgO" secondAttribute="leading" constant="20" symbolic="YES" id="rve-aQ-Ggt"/>
|
||||
<constraint firstAttribute="trailing" secondItem="epW-Rm-9St" secondAttribute="trailing" constant="20" symbolic="YES" id="sHt-wW-wHU"/>
|
||||
<constraint firstAttribute="trailing" secondItem="sPw-mV-mFF" secondAttribute="trailing" constant="20" symbolic="YES" id="xjb-mS-yVZ"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
</sections>
|
||||
@ -1130,6 +1210,13 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="300" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<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="GrV-gX-eCo" userLabel="Strength">
|
||||
<rect key="frame" x="0.0" y="0.0" width="300" height="12"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="10"/>
|
||||
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.029999999999999999" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Long Password" lineBreakMode="clip" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qAD-3v-3aq" userLabel="Type">
|
||||
<rect key="frame" x="-10" y="19" width="604" height="101"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
@ -1251,10 +1338,13 @@
|
||||
<constraint firstAttribute="trailing" secondItem="q75-Uz-86O" secondAttribute="trailing" constant="8" id="ZsY-wg-aJt"/>
|
||||
<constraint firstItem="q75-Uz-86O" firstAttribute="leading" secondItem="302-fI-maQ" secondAttribute="leading" constant="8" id="cee-Hz-2IS"/>
|
||||
<constraint firstAttribute="trailing" secondItem="cOv-2G-EAP" secondAttribute="trailing" id="fNx-v1-XM3"/>
|
||||
<constraint firstItem="GrV-gX-eCo" firstAttribute="leading" secondItem="302-fI-maQ" secondAttribute="leading" id="hX4-Yf-rzp"/>
|
||||
<constraint firstItem="cOv-2G-EAP" firstAttribute="leading" secondItem="fQc-Fn-JDq" secondAttribute="trailing" constant="-9" id="hqr-ru-rB7"/>
|
||||
<constraint firstItem="GrV-gX-eCo" firstAttribute="top" secondItem="302-fI-maQ" secondAttribute="top" id="ptG-Jr-1R8"/>
|
||||
<constraint firstItem="cOv-2G-EAP" firstAttribute="centerY" secondItem="fQc-Fn-JDq" secondAttribute="centerY" id="rrx-LF-Hk9"/>
|
||||
<constraint firstItem="fQc-Fn-JDq" firstAttribute="centerY" secondItem="I2J-B6-5rE" secondAttribute="centerY" id="uR7-lg-A9q"/>
|
||||
<constraint firstItem="qek-2l-YQf" firstAttribute="leading" secondItem="302-fI-maQ" secondAttribute="leading" constant="8" id="wUJ-7N-Z1z"/>
|
||||
<constraint firstAttribute="trailing" secondItem="GrV-gX-eCo" secondAttribute="trailing" id="yDV-ZB-a8l"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="contentField" destination="q75-Uz-86O" id="nbM-vd-uZi"/>
|
||||
@ -1262,6 +1352,7 @@
|
||||
<outlet property="counterLabel" destination="I2J-B6-5rE" id="C4b-gE-XHW"/>
|
||||
<outlet property="loginButton" destination="cOv-2G-EAP" id="WoR-eP-Ztq"/>
|
||||
<outlet property="nameLabel" destination="qek-2l-YQf" id="CcC-PM-kMx"/>
|
||||
<outlet property="strengthLabel" destination="GrV-gX-eCo" id="e6J-5c-Dln"/>
|
||||
<outlet property="typeLabel" destination="qAD-3v-3aq" id="rAM-Kf-5xO"/>
|
||||
<outlet property="upgradeButton" destination="iLD-rv-uZZ" id="OKi-9X-R6F"/>
|
||||
</connections>
|
||||
|
Loading…
Reference in New Issue
Block a user