Serious rewrite of site configuration UI.
This commit is contained in:
		@@ -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
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPAlgorithmV1
 | 
			
		||||
@@ -28,7 +28,7 @@
 | 
			
		||||
- (BOOL)migrateElement:(MPElementEntity *)element explicit:(BOOL)explicit {
 | 
			
		||||
 | 
			
		||||
    if (element.version != [self version] - 1)
 | 
			
		||||
            // Only migrate from previous version.
 | 
			
		||||
        // Only migrate from previous version.
 | 
			
		||||
        return NO;
 | 
			
		||||
 | 
			
		||||
    if (!explicit) {
 | 
			
		||||
@@ -49,16 +49,17 @@
 | 
			
		||||
 | 
			
		||||
    static __strong NSDictionary *MPTypes_ciphers = nil;
 | 
			
		||||
    static dispatch_once_t once = 0;
 | 
			
		||||
    dispatch_once(&once, ^{
 | 
			
		||||
    dispatch_once( &once, ^{
 | 
			
		||||
        MPTypes_ciphers = [NSDictionary dictionaryWithContentsOfURL:
 | 
			
		||||
                           [[NSBundle mainBundle] URLForResource:@"ciphers" withExtension:@"plist"]];
 | 
			
		||||
    });
 | 
			
		||||
                [[NSBundle mainBundle] URLForResource:@"ciphers" withExtension:@"plist"]];
 | 
			
		||||
    } );
 | 
			
		||||
 | 
			
		||||
    // Determine the seed whose bytes will be used for calculating a password
 | 
			
		||||
    uint32_t ncounter = htonl(counter), nnameLength = htonl(name.length);
 | 
			
		||||
    NSData *counterBytes = [NSData dataWithBytes:&ncounter length:sizeof(ncounter)];
 | 
			
		||||
    NSData *nameLengthBytes = [NSData dataWithBytes:&nnameLength length:sizeof(nnameLength)];
 | 
			
		||||
    trc(@"seed from: hmac-sha256(%@, 'com.lyndir.masterpassword' | %@ | %@ | %@)", [key.keyData encodeBase64], [nameLengthBytes encodeHex], name, [counterBytes encodeHex]);
 | 
			
		||||
    uint32_t ncounter = htonl( counter ), nnameLength = htonl( name.length );
 | 
			
		||||
    NSData *counterBytes = [NSData dataWithBytes:&ncounter length:sizeof( ncounter )];
 | 
			
		||||
    NSData *nameLengthBytes = [NSData dataWithBytes:&nnameLength length:sizeof( nnameLength )];
 | 
			
		||||
    trc( @"seed from: hmac-sha256(%@, 'com.lyndir.masterpassword' | %@ | %@ | %@)", [key.keyData encodeBase64], [nameLengthBytes encodeHex],
 | 
			
		||||
                    name, [counterBytes encodeHex] );
 | 
			
		||||
    NSData *seed = [[NSData dataByConcatenatingDatas:
 | 
			
		||||
            [@"com.lyndir.masterpassword" dataUsingEncoding:NSUTF8StringEncoding],
 | 
			
		||||
            nameLengthBytes,
 | 
			
		||||
@@ -66,17 +67,17 @@
 | 
			
		||||
            counterBytes,
 | 
			
		||||
            nil]
 | 
			
		||||
            hmacWith:PearlHashSHA256 key:key.keyData];
 | 
			
		||||
    trc(@"seed is: %@", [seed encodeBase64]);
 | 
			
		||||
    trc( @"seed is: %@", [seed encodeBase64] );
 | 
			
		||||
    const unsigned char *seedBytes = seed.bytes;
 | 
			
		||||
 | 
			
		||||
    // Determine the cipher from the first seed byte.
 | 
			
		||||
    NSAssert([seed length], @"Missing seed.");
 | 
			
		||||
    NSAssert( [seed length], @"Missing seed." );
 | 
			
		||||
    NSArray *typeCiphers = [[MPTypes_ciphers valueForKey:[self classNameOfType:type]] valueForKey:[self nameOfType:type]];
 | 
			
		||||
    NSString *cipher = typeCiphers[seedBytes[0] % [typeCiphers count]];
 | 
			
		||||
    trc(@"type %@, ciphers: %@, selected: %@", [self nameOfType:type], typeCiphers, cipher);
 | 
			
		||||
    trc( @"type %@, ciphers: %@, selected: %@", [self nameOfType:type], typeCiphers, cipher );
 | 
			
		||||
 | 
			
		||||
    // Encode the content, character by character, using subsequent seed bytes and the cipher.
 | 
			
		||||
    NSAssert([seed length] >= [cipher length] + 1, @"Insufficient seed bytes to encode cipher.");
 | 
			
		||||
    NSAssert( [seed length] >= [cipher length] + 1, @"Insufficient seed bytes to encode cipher." );
 | 
			
		||||
    NSMutableString *content = [NSMutableString stringWithCapacity:[cipher length]];
 | 
			
		||||
    for (NSUInteger c = 0; c < [cipher length]; ++c) {
 | 
			
		||||
        uint16_t keyByte = seedBytes[c + 1];
 | 
			
		||||
@@ -84,7 +85,7 @@
 | 
			
		||||
        NSString *cipherClassCharacters = [[MPTypes_ciphers valueForKey:@"MPCharacterClasses"] valueForKey:cipherClass];
 | 
			
		||||
        NSString *character = [cipherClassCharacters substringWithRange:NSMakeRange( keyByte % [cipherClassCharacters length], 1 )];
 | 
			
		||||
 | 
			
		||||
        trc(@"class %@ has characters: %@, index: %u, selected: %@", cipherClass, cipherClassCharacters, keyByte, character);
 | 
			
		||||
        trc( @"class %@ has characters: %@, index: %u, selected: %@", cipherClass, cipherClassCharacters, keyByte, character );
 | 
			
		||||
        [content appendString:character];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ typedef NS_ENUM( NSUInteger, MPImportResult ) {
 | 
			
		||||
- (MPFixableResult)findAndFixInconsistenciesSaveInContext:(NSManagedObjectContext *)context;
 | 
			
		||||
 | 
			
		||||
/** @param completion The block to execute after adding the element, executed from the main thread with the new element in the main MOC. */
 | 
			
		||||
- (void)addElementNamed:(NSString *)siteName completion:(void (^)(MPElementEntity *element))completion;
 | 
			
		||||
- (void)addElementNamed:(NSString *)siteName completion:(void ( ^ )(MPElementEntity *element, NSManagedObjectContext *context))completion;
 | 
			
		||||
- (MPElementEntity *)changeElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context toType:(MPElementType)type;
 | 
			
		||||
- (MPImportResult)importSites:(NSString *)importedSitesString
 | 
			
		||||
            askImportPassword:(NSString *(^)(NSString *userName))importPassword
 | 
			
		||||
 
 | 
			
		||||
@@ -435,10 +435,10 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
 | 
			
		||||
#pragma mark - Utilities
 | 
			
		||||
 | 
			
		||||
- (void)addElementNamed:(NSString *)siteName completion:(void ( ^ )(MPElementEntity *element))completion {
 | 
			
		||||
- (void)addElementNamed:(NSString *)siteName completion:(void ( ^ )(MPElementEntity *element, NSManagedObjectContext *context))completion {
 | 
			
		||||
 | 
			
		||||
    if (![siteName length]) {
 | 
			
		||||
        completion( nil );
 | 
			
		||||
        completion( nil, nil );
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -446,7 +446,7 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
        MPUserEntity *activeUser = [self activeUserInContext:context];
 | 
			
		||||
        NSAssert( activeUser, @"Missing user." );
 | 
			
		||||
        if (!activeUser) {
 | 
			
		||||
            completion( nil );
 | 
			
		||||
            completion( nil, nil );
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -466,7 +466,7 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
 | 
			
		||||
        [context saveToStore];
 | 
			
		||||
 | 
			
		||||
        completion( element );
 | 
			
		||||
        completion( element, context );
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,11 +20,11 @@
 | 
			
		||||
            @try {
 | 
			
		||||
                NSError *error = nil;
 | 
			
		||||
                if (!(success = [self save:&error]))
 | 
			
		||||
                err(@"While saving: %@", error);
 | 
			
		||||
                    err( @"While saving: %@", error );
 | 
			
		||||
            }
 | 
			
		||||
            @catch (NSException *exception) {
 | 
			
		||||
                success = NO;
 | 
			
		||||
                err(@"While saving: %@", exception);
 | 
			
		||||
                err( @"While saving: %@", exception );
 | 
			
		||||
            }
 | 
			
		||||
        }];
 | 
			
		||||
    }
 | 
			
		||||
@@ -115,7 +115,8 @@
 | 
			
		||||
- (NSString *)debugDescription {
 | 
			
		||||
 | 
			
		||||
    return strf( @"{%@: name=%@, user=%@, type=%lu, uses=%ld, lastUsed=%@, version=%ld, loginName=%@, requiresExplicitMigration=%d}",
 | 
			
		||||
            NSStringFromClass( [self class] ), self.name, self.user.name, (long)self.type, (long)self.uses, self.lastUsed, (long)self.version,
 | 
			
		||||
            NSStringFromClass( [self class] ), self.name, self.user.name, (long)self.type, (long)self.uses, self.lastUsed,
 | 
			
		||||
            (long)self.version,
 | 
			
		||||
            self.loginName, self.requiresExplicitMigration );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -123,9 +124,11 @@
 | 
			
		||||
 | 
			
		||||
    while (self.version < MPAlgorithmDefaultVersion)
 | 
			
		||||
        if ([MPAlgorithmForVersion( self.version + 1 ) migrateElement:self explicit:explicit])
 | 
			
		||||
        inf(@"%@ migration to version: %ld succeeded for element: %@", explicit? @"Explicit": @"Automatic", (long)self.version + 1, self);
 | 
			
		||||
            inf( @"%@ migration to version: %ld succeeded for element: %@",
 | 
			
		||||
                            explicit? @"Explicit": @"Automatic", (long)self.version + 1, self );
 | 
			
		||||
        else {
 | 
			
		||||
            wrn(@"%@ migration to version: %ld failed for element: %@", explicit? @"Explicit": @"Automatic", (long)self.version + 1, self);
 | 
			
		||||
            wrn( @"%@ migration to version: %ld failed for element: %@",
 | 
			
		||||
                            explicit? @"Explicit": @"Automatic", (long)self.version + 1, self );
 | 
			
		||||
            return NO;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -137,7 +140,7 @@
 | 
			
		||||
    return [self.algorithm resolveContentForElement:self usingKey:key];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)resolveContentUsingKey:(MPKey *)key result:(void (^)(NSString *))result {
 | 
			
		||||
- (void)resolveContentUsingKey:(MPKey *)key result:(void ( ^ )(NSString *))result {
 | 
			
		||||
 | 
			
		||||
    [self.algorithm resolveContentForElement:self usingKey:key result:result];
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -229,7 +229,7 @@
 | 
			
		||||
        switch (returnCode) {
 | 
			
		||||
            case NSAlertFirstButtonReturn: {
 | 
			
		||||
                // "Create" button.
 | 
			
		||||
                [[MPMacAppDelegate get] addElementNamed:[self.siteField stringValue] completion:^(MPElementEntity *element) {
 | 
			
		||||
                [[MPMacAppDelegate get] addElementNamed:[self.siteField stringValue] completion:^(MPElementEntity *element, NSManagedObjectContext *context) {
 | 
			
		||||
                    if (element)
 | 
			
		||||
                        PearlMainQueue( ^{ [self updateElements]; } );
 | 
			
		||||
                }];
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "MPAvatarCell.h"
 | 
			
		||||
#import "MPPasswordLargeCell.h"
 | 
			
		||||
 | 
			
		||||
const long MPAvatarAdd = 10000;
 | 
			
		||||
 | 
			
		||||
@@ -207,10 +206,10 @@ const long MPAvatarAdd = 10000;
 | 
			
		||||
 | 
			
		||||
        switch (self.mode) {
 | 
			
		||||
            case MPAvatarModeLowered: {
 | 
			
		||||
                [self.avatarSizeConstraint layoutWithConstant:self.avatarImageView.image.size.height];
 | 
			
		||||
                [self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
 | 
			
		||||
                [self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
 | 
			
		||||
                [self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
 | 
			
		||||
                [[self.avatarSizeConstraint updateConstant:self.avatarImageView.image.size.height] layoutIfNeeded];
 | 
			
		||||
                [[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultLow] layoutIfNeeded];
 | 
			
		||||
                [[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow] layoutIfNeeded];
 | 
			
		||||
                [[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultLow] layoutIfNeeded];
 | 
			
		||||
                self.nameContainer.alpha = self.visibility;
 | 
			
		||||
                self.nameContainer.backgroundColor = [UIColor clearColor];
 | 
			
		||||
                self.avatarImageView.alpha = self.visibility / 0.7f + 0.3f;
 | 
			
		||||
@@ -218,10 +217,10 @@ const long MPAvatarAdd = 10000;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MPAvatarModeRaisedButInactive: {
 | 
			
		||||
                [self.avatarSizeConstraint layoutWithConstant:self.avatarImageView.image.size.height];
 | 
			
		||||
                [self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
 | 
			
		||||
                [self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
 | 
			
		||||
                [self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
 | 
			
		||||
                [[self.avatarSizeConstraint updateConstant:self.avatarImageView.image.size.height] layoutIfNeeded];
 | 
			
		||||
                [[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
 | 
			
		||||
                [[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow] layoutIfNeeded];
 | 
			
		||||
                [[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultLow] layoutIfNeeded];
 | 
			
		||||
                self.nameContainer.alpha = self.visibility;
 | 
			
		||||
                self.nameContainer.backgroundColor = [UIColor clearColor];
 | 
			
		||||
                self.avatarImageView.alpha = 0;
 | 
			
		||||
@@ -229,10 +228,10 @@ const long MPAvatarAdd = 10000;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MPAvatarModeRaisedAndActive: {
 | 
			
		||||
                [self.avatarSizeConstraint layoutWithConstant:self.avatarImageView.image.size.height];
 | 
			
		||||
                [self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
 | 
			
		||||
                [self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
 | 
			
		||||
                [self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
 | 
			
		||||
                [[self.avatarSizeConstraint updateConstant:self.avatarImageView.image.size.height] layoutIfNeeded];
 | 
			
		||||
                [[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
 | 
			
		||||
                [[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow] layoutIfNeeded];
 | 
			
		||||
                [[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
 | 
			
		||||
                self.nameContainer.alpha = self.visibility;
 | 
			
		||||
                self.nameContainer.backgroundColor = [UIColor blackColor];
 | 
			
		||||
                self.avatarImageView.alpha = 1;
 | 
			
		||||
@@ -240,10 +239,10 @@ const long MPAvatarAdd = 10000;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MPAvatarModeRaisedAndHidden: {
 | 
			
		||||
                [self.avatarSizeConstraint layoutWithConstant:self.avatarImageView.image.size.height];
 | 
			
		||||
                [self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
 | 
			
		||||
                [self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
 | 
			
		||||
                [self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
 | 
			
		||||
                [[self.avatarSizeConstraint updateConstant:self.avatarImageView.image.size.height] layoutIfNeeded];
 | 
			
		||||
                [[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
 | 
			
		||||
                [[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow] layoutIfNeeded];
 | 
			
		||||
                [[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
 | 
			
		||||
                self.nameContainer.alpha = 0;
 | 
			
		||||
                self.nameContainer.backgroundColor = [UIColor blackColor];
 | 
			
		||||
                self.avatarImageView.alpha = 0;
 | 
			
		||||
@@ -251,10 +250,10 @@ const long MPAvatarAdd = 10000;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MPAvatarModeRaisedAndMinimized: {
 | 
			
		||||
                [self.avatarSizeConstraint layoutWithConstant:36];
 | 
			
		||||
                [self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
 | 
			
		||||
                [self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
 | 
			
		||||
                [self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
 | 
			
		||||
                [[self.avatarSizeConstraint updateConstant:36] layoutIfNeeded];
 | 
			
		||||
                [[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultLow] layoutIfNeeded];
 | 
			
		||||
                [[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
 | 
			
		||||
                [[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
 | 
			
		||||
                self.nameContainer.alpha = 0;
 | 
			
		||||
                self.nameContainer.backgroundColor = [UIColor blackColor];
 | 
			
		||||
                self.avatarImageView.alpha = 1;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,9 +20,15 @@
 | 
			
		||||
#import "MPEntities.h"
 | 
			
		||||
#import "MPCell.h"
 | 
			
		||||
 | 
			
		||||
@interface MPPasswordCell : MPCell
 | 
			
		||||
typedef NS_ENUM ( NSUInteger, MPPasswordCellMode ) {
 | 
			
		||||
    MPPasswordCellModePassword,
 | 
			
		||||
    MPPasswordCellModeSettings,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** Populate our UI to reflect the current state. */
 | 
			
		||||
- (void)updateAnimated:(BOOL)animated;
 | 
			
		||||
@interface MPPasswordCell : MPCell <UIScrollViewDelegate>
 | 
			
		||||
 | 
			
		||||
- (void)setElement:(MPElementEntity *)element animated:(BOOL)animated;
 | 
			
		||||
- (void)setTransientSite:(NSString *)siteName animated:(BOOL)animated;
 | 
			
		||||
- (void)setMode:(MPPasswordCellMode)mode animated:(BOOL)animated;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPAvatarCell.h
 | 
			
		||||
@@ -20,14 +20,62 @@
 | 
			
		||||
#import "MPiOSAppDelegate.h"
 | 
			
		||||
#import "MPAppDelegate_Store.h"
 | 
			
		||||
 | 
			
		||||
@implementation MPPasswordCell
 | 
			
		||||
 | 
			
		||||
//    return [[MPiOSAppDelegate get] changeElement:element saveInContext:context toType:self.type];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@interface MPPasswordCell()
 | 
			
		||||
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UILabel *siteNameLabel;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UITextField *passwordField;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UITextField *loginNameField;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UIPageControl *pageControl;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UILabel *strengthLabel;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UILabel *counterLabel;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UIButton *counterButton;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UIButton *upgradeButton;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UIButton *modeButton;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UIButton *passwordEditButton;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UIButton *usernameEditButton;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UIScrollView *modeScrollView;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UIButton *selectionButton;
 | 
			
		||||
 | 
			
		||||
@property(nonatomic) MPPasswordCellMode mode;
 | 
			
		||||
@property(nonatomic, copy) NSString *transientSite;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
 | 
			
		||||
@implementation MPPasswordCell {
 | 
			
		||||
    NSManagedObjectID *_elementOID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - Life cycle
 | 
			
		||||
 | 
			
		||||
- (void)prepareForReuse {
 | 
			
		||||
- (void)awakeFromNib {
 | 
			
		||||
 | 
			
		||||
    [super prepareForReuse];
 | 
			
		||||
    [self updateAnimated:NO];
 | 
			
		||||
    [super awakeFromNib];
 | 
			
		||||
 | 
			
		||||
    [self addGestureRecognizer:
 | 
			
		||||
            [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector( doRevealPassword: )]];
 | 
			
		||||
    [self.counterButton addGestureRecognizer:
 | 
			
		||||
            [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector( doResetCounter: )]];
 | 
			
		||||
 | 
			
		||||
    self.selectionButton.layer.cornerRadius = 5;
 | 
			
		||||
    self.selectionButton.layer.shadowOffset = CGSizeZero;
 | 
			
		||||
    self.selectionButton.layer.shadowRadius = 5;
 | 
			
		||||
    self.selectionButton.layer.shadowOpacity = 0;
 | 
			
		||||
    self.selectionButton.layer.shadowColor = [UIColor whiteColor].CGColor;
 | 
			
		||||
 | 
			
		||||
    self.pageControl.transform = CGAffineTransformMakeScale( 0.4f, 0.4f );
 | 
			
		||||
 | 
			
		||||
    [self.selectionButton observeKeyPath:@"highlighted"
 | 
			
		||||
               withBlock:^(id from, id to, NSKeyValueChange cause, UIButton *button) {
 | 
			
		||||
        button.layer.shadowOpacity = button.selected? 1: button.highlighted? 0.3f: 0;
 | 
			
		||||
    }];
 | 
			
		||||
    [self.selectionButton observeKeyPath:@"selected"
 | 
			
		||||
               withBlock:^(id from, id to, NSKeyValueChange cause, UIButton *button) {
 | 
			
		||||
        button.layer.shadowOpacity = button.selected? 1: button.highlighted? 0.3f: 0;
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unblocks animations for all CALayer properties (eg. shadowOpacity)
 | 
			
		||||
@@ -37,23 +85,204 @@
 | 
			
		||||
    if (defaultAction == (id)[NSNull null] && [event isEqualToString:@"position"])
 | 
			
		||||
        return defaultAction;
 | 
			
		||||
 | 
			
		||||
    return NSNullToNil(defaultAction);
 | 
			
		||||
    return NSNullToNil( defaultAction );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - Properties
 | 
			
		||||
#pragma mark - State
 | 
			
		||||
 | 
			
		||||
- (void)setSelected:(BOOL)selected {
 | 
			
		||||
- (void)setMode:(MPPasswordCellMode)mode animated:(BOOL)animated {
 | 
			
		||||
 | 
			
		||||
    [super setSelected:selected];
 | 
			
		||||
    if (mode == _mode)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    _mode = mode;
 | 
			
		||||
    [self updateAnimated:animated];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setElement:(MPElementEntity *)element animated:(BOOL)animated {
 | 
			
		||||
 | 
			
		||||
    _elementOID = [element objectID];
 | 
			
		||||
    [self updateAnimated:animated];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setTransientSite:(NSString *)siteName animated:(BOOL)animated {
 | 
			
		||||
 | 
			
		||||
    self.transientSite = siteName;
 | 
			
		||||
    [self updateAnimated:animated];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - UITextFieldDelegate
 | 
			
		||||
 | 
			
		||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
 | 
			
		||||
 | 
			
		||||
    [textField resignFirstResponder];
 | 
			
		||||
    return YES;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)textFieldDidBeginEditing:(UITextField *)textField {
 | 
			
		||||
 | 
			
		||||
    UICollectionView *collectionView = [UICollectionView findAsSuperviewOf:self];
 | 
			
		||||
    [collectionView scrollToItemAtIndexPath:[collectionView indexPathForCell:self]
 | 
			
		||||
                           atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:YES];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)textFieldDidEndEditing:(UITextField *)textField {
 | 
			
		||||
 | 
			
		||||
    if (textField == self.passwordField) {
 | 
			
		||||
        NSString *text = textField.text;
 | 
			
		||||
        textField.enabled = NO;
 | 
			
		||||
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
            MPElementEntity *element = [self elementInContext:context];
 | 
			
		||||
            if (!element)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            if (textField == self.passwordField) {
 | 
			
		||||
                [element.algorithm saveContent:text toElement:element usingKey:[MPiOSAppDelegate get].key];
 | 
			
		||||
                [PearlOverlay showTemporaryOverlayWithTitle:@"Password Updated" dismissAfter:2];
 | 
			
		||||
            }
 | 
			
		||||
            else if (textField == self.loginNameField) {
 | 
			
		||||
                element.loginName = text;
 | 
			
		||||
                [PearlOverlay showTemporaryOverlayWithTitle:@"Login Updated" dismissAfter:2];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [context saveToStore];
 | 
			
		||||
            [self updateAnimated:YES];
 | 
			
		||||
        }];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - Actions
 | 
			
		||||
 | 
			
		||||
- (IBAction)doEditPassword:(UIButton *)sender {
 | 
			
		||||
 | 
			
		||||
    self.passwordField.enabled = YES;
 | 
			
		||||
    [self.passwordField becomeFirstResponder];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (IBAction)doEditLoginName:(UIButton *)sender {
 | 
			
		||||
 | 
			
		||||
    self.loginNameField.enabled = YES;
 | 
			
		||||
    [self.loginNameField becomeFirstResponder];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (IBAction)doMode:(UIButton *)sender {
 | 
			
		||||
 | 
			
		||||
    switch (self.mode) {
 | 
			
		||||
        case MPPasswordCellModePassword:
 | 
			
		||||
            [self setMode:MPPasswordCellModeSettings animated:YES];
 | 
			
		||||
            break;
 | 
			
		||||
        case MPPasswordCellModeSettings:
 | 
			
		||||
            [self setMode:MPPasswordCellModePassword animated:YES];
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [self updateAnimated:YES];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setHighlighted:(BOOL)highlighted {
 | 
			
		||||
- (IBAction)doUpgrade:(UIButton *)sender {
 | 
			
		||||
 | 
			
		||||
    [super setHighlighted:highlighted];
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        if (![[self elementInContext:context] migrateExplicitly:YES]) {
 | 
			
		||||
            [PearlOverlay showTemporaryOverlayWithTitle:@"Couldn't Upgrade Site" dismissAfter:2];
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    [self updateAnimated:YES];
 | 
			
		||||
        [context saveToStore];
 | 
			
		||||
        [PearlOverlay showTemporaryOverlayWithTitle:@"Site Upgraded" dismissAfter:2];
 | 
			
		||||
        [self updateAnimated:YES];
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (IBAction)doIncrementCounter:(UIButton *)sender {
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        MPElementEntity *element = [self elementInContext:context];
 | 
			
		||||
        if (!element || ![element isKindOfClass:[MPElementGeneratedEntity class]])
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        ++((MPElementGeneratedEntity *)element).counter;
 | 
			
		||||
        [context saveToStore];
 | 
			
		||||
 | 
			
		||||
        [PearlOverlay showTemporaryOverlayWithTitle:@"Generating New Password" dismissAfter:2];
 | 
			
		||||
        [self updateAnimated:YES];
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (IBAction)doRevealPassword:(UILongPressGestureRecognizer *)recognizer {
 | 
			
		||||
 | 
			
		||||
    if (recognizer.state != UIGestureRecognizerStateBegan)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (self.passwordField.secureTextEntry) {
 | 
			
		||||
        self.passwordField.secureTextEntry = NO;
 | 
			
		||||
 | 
			
		||||
        PearlMainQueueAfter( 3, ^{
 | 
			
		||||
            self.passwordField.secureTextEntry = [[MPiOSConfig get].hidePasswords boolValue];
 | 
			
		||||
        } );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (IBAction)doResetCounter:(UILongPressGestureRecognizer *)recognizer {
 | 
			
		||||
 | 
			
		||||
    if (recognizer.state != UIGestureRecognizerStateBegan)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        MPElementEntity *element = [self elementInContext:context];
 | 
			
		||||
        if (!element || ![element isKindOfClass:[MPElementGeneratedEntity class]])
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        ((MPElementGeneratedEntity *)element).counter = 1;
 | 
			
		||||
        [context saveToStore];
 | 
			
		||||
 | 
			
		||||
        [PearlOverlay showTemporaryOverlayWithTitle:@"Counter Reset" dismissAfter:2];
 | 
			
		||||
        [self updateAnimated:YES];
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (IBAction)doUse:(id)sender {
 | 
			
		||||
 | 
			
		||||
    self.selectionButton.selected = YES;
 | 
			
		||||
 | 
			
		||||
    if (self.transientSite) {
 | 
			
		||||
        [[UIResponder findFirstResponder] resignFirstResponder];
 | 
			
		||||
        [PearlAlert showAlertWithTitle:@"Create Site"
 | 
			
		||||
                               message:strf( @"Remember site named:\n%@", self.transientSite )
 | 
			
		||||
                             viewStyle:UIAlertViewStyleDefault
 | 
			
		||||
                             initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
 | 
			
		||||
            if (buttonIndex == [alert cancelButtonIndex]) {
 | 
			
		||||
                self.selectionButton.selected = NO;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [[MPiOSAppDelegate get]
 | 
			
		||||
                    addElementNamed:self.transientSite completion:^(MPElementEntity *element, NSManagedObjectContext *context) {
 | 
			
		||||
                [self copyContentOfElement:element saveInContext:context];
 | 
			
		||||
                PearlMainQueue( ^{
 | 
			
		||||
                    self.selectionButton.selected = NO;
 | 
			
		||||
                } );
 | 
			
		||||
            }];
 | 
			
		||||
        }                  cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonYes, nil];
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        [self copyContentOfElement:[self elementInContext:context] saveInContext:context];
 | 
			
		||||
        PearlMainQueue( ^{
 | 
			
		||||
            self.selectionButton.selected = NO;
 | 
			
		||||
        } );
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - UIScrollViewDelegate
 | 
			
		||||
 | 
			
		||||
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
 | 
			
		||||
 | 
			
		||||
    if (roundf( scrollView.contentOffset.x / self.bounds.size.width ) == 0.0f)
 | 
			
		||||
        [self setMode:MPPasswordCellModePassword animated:YES];
 | 
			
		||||
    else
 | 
			
		||||
        [self setMode:MPPasswordCellModeSettings animated:YES];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - Private
 | 
			
		||||
@@ -68,8 +297,100 @@
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [UIView animateWithDuration:animated? 0.3f: 0 animations:^{
 | 
			
		||||
        self.layer.shadowOpacity = self.selected? 1: self.highlighted? 0.3f: 0;
 | 
			
		||||
        MPElementEntity *mainElement = [self elementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
 | 
			
		||||
 | 
			
		||||
        // UI
 | 
			
		||||
        self.selectionButton.layer.shadowOpacity = self.selectionButton.selected? 1: self.selectionButton.highlighted? 0.3f: 0;
 | 
			
		||||
        self.upgradeButton.alpha = mainElement.requiresExplicitMigration? 1: 0;
 | 
			
		||||
        self.passwordEditButton.alpha = self.transientSite || mainElement.type & MPElementTypeClassGenerated? 0: 1;
 | 
			
		||||
        self.modeButton.alpha = self.transientSite? 0: 1;
 | 
			
		||||
        self.counterLabel.alpha = self.counterButton.alpha = mainElement.type & MPElementTypeClassGenerated? 1: 0;
 | 
			
		||||
        self.modeButton.selected = self.mode == MPPasswordCellModeSettings;
 | 
			
		||||
        self.pageControl.currentPage = self.mode == MPPasswordCellModePassword? 0: 1;
 | 
			
		||||
        [self.modeScrollView setContentOffset:CGPointMake( self.mode * self.modeScrollView.frame.size.width, 0 ) animated:YES];
 | 
			
		||||
 | 
			
		||||
        // Site Name
 | 
			
		||||
        self.siteNameLabel.text = strl( @"%@ - %@", self.transientSite?: mainElement.name,
 | 
			
		||||
                self.transientSite? @"Tap to create": [mainElement.algorithm shortNameOfType:mainElement.type] );
 | 
			
		||||
 | 
			
		||||
        // Site Password
 | 
			
		||||
        self.passwordField.enabled = NO;
 | 
			
		||||
        self.passwordField.secureTextEntry = [[MPiOSConfig get].hidePasswords boolValue];
 | 
			
		||||
        self.passwordField.attributedPlaceholder = stra(
 | 
			
		||||
                mainElement.type & MPElementTypeClassStored? strl( @"Set custom password" ):
 | 
			
		||||
                mainElement.type & MPElementTypeClassGenerated? strl( @"Generating..." ): @"", @{
 | 
			
		||||
                        NSForegroundColorAttributeName : [UIColor whiteColor]
 | 
			
		||||
                } );
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
            NSString *password;
 | 
			
		||||
            if (self.transientSite)
 | 
			
		||||
                password = [MPAlgorithmDefault generateContentNamed:self.transientSite ofType:
 | 
			
		||||
                        [[MPiOSAppDelegate get] activeUserInContext:context].defaultType?: MPElementTypeGeneratedLong
 | 
			
		||||
                                                        withCounter:1 usingKey:[MPiOSAppDelegate get].key];
 | 
			
		||||
            else
 | 
			
		||||
                password = [[self elementInContext:context] resolveContentUsingKey:[MPiOSAppDelegate get].key];
 | 
			
		||||
 | 
			
		||||
            PearlMainQueue( ^{
 | 
			
		||||
                self.passwordField.text = password;
 | 
			
		||||
            } );
 | 
			
		||||
        }];
 | 
			
		||||
 | 
			
		||||
        // Site Counter
 | 
			
		||||
        if ([mainElement isKindOfClass:[MPElementGeneratedEntity class]])
 | 
			
		||||
            self.counterLabel.text = strf( @"%lu", (unsigned long)((MPElementGeneratedEntity *)mainElement).counter );
 | 
			
		||||
 | 
			
		||||
        // Site Login Name
 | 
			
		||||
        self.loginNameField.enabled = NO;
 | 
			
		||||
        self.loginNameField.text = mainElement.loginName;
 | 
			
		||||
        self.loginNameField.attributedPlaceholder = stra( strl( @"Set login name" ), @{
 | 
			
		||||
                NSForegroundColorAttributeName : [UIColor whiteColor]
 | 
			
		||||
        } );
 | 
			
		||||
 | 
			
		||||
        // Strength Label
 | 
			
		||||
//#warning TODO
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)copyContentOfElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
    // Copy content.
 | 
			
		||||
    switch (self.mode) {
 | 
			
		||||
        case MPPasswordCellModePassword: {
 | 
			
		||||
            inf( @"Copying password for: %@", element.name );
 | 
			
		||||
            NSString *password = [element resolveContentUsingKey:[MPAppDelegate_Shared get].key];
 | 
			
		||||
            if (![password length])
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            PearlMainQueue( ^{
 | 
			
		||||
                [PearlOverlay showTemporaryOverlayWithTitle:strl( @"Password Copied" ) dismissAfter:2];
 | 
			
		||||
                [UIPasteboard generalPasteboard].string = password;
 | 
			
		||||
            } );
 | 
			
		||||
 | 
			
		||||
            [element use];
 | 
			
		||||
            [context saveToStore];
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case MPPasswordCellModeSettings: {
 | 
			
		||||
            inf( @"Copying login for: %@", element.name );
 | 
			
		||||
            NSString *loginName = element.loginName;
 | 
			
		||||
            if (![loginName length])
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            PearlMainQueue( ^{
 | 
			
		||||
                [PearlOverlay showTemporaryOverlayWithTitle:strl( @"Login Name Copied" ) dismissAfter:2];
 | 
			
		||||
                [UIPasteboard generalPasteboard].string = loginName;
 | 
			
		||||
            } );
 | 
			
		||||
 | 
			
		||||
            [element use];
 | 
			
		||||
            [context saveToStore];
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementEntity *)elementInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
    return [MPElementEntity existingObjectWithID:_elementOID inContext:context];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
 
 | 
			
		||||
@@ -1,51 +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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPAvatarCell.h
 | 
			
		||||
//  MPAvatarCell
 | 
			
		||||
//
 | 
			
		||||
//  Created by lhunath on 2014-03-11.
 | 
			
		||||
//  Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import <Foundation/Foundation.h>
 | 
			
		||||
#import "MPEntities.h"
 | 
			
		||||
#import "MPCell.h"
 | 
			
		||||
#import "MPPasswordCell.h"
 | 
			
		||||
 | 
			
		||||
typedef NS_ENUM (NSUInteger, MPContentFieldMode) {
 | 
			
		||||
    MPContentFieldModePassword,
 | 
			
		||||
    MPContentFieldModeUser,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@interface MPPasswordLargeCell : MPPasswordCell <UITextFieldDelegate>
 | 
			
		||||
 | 
			
		||||
@property(nonatomic) MPElementType type;
 | 
			
		||||
@property(nonatomic) MPContentFieldMode contentFieldMode;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UILabel *typeLabel;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UITextField *contentField;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UIButton *upgradeButton;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UILabel *nameLabel;
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UIButton *loginButton;
 | 
			
		||||
 | 
			
		||||
+ (instancetype)dequeueCellWithType:(MPElementType)type fromCollectionView:(UICollectionView *)collectionView atIndexPath:(NSIndexPath *)indexPath;
 | 
			
		||||
 | 
			
		||||
- (void)update;
 | 
			
		||||
- (void)updateWithElement:(MPElementEntity *)mainElement;
 | 
			
		||||
- (void)updateWithTransientSite:(NSString *)siteName;
 | 
			
		||||
 | 
			
		||||
- (void)resolveContentOfCellTypeForTransientSite:(NSString *)siteName usingKey:(MPKey *)key result:(void (^)(NSString *result))resultBlock;
 | 
			
		||||
- (void)resolveContentOfCellTypeForElement:(MPElementEntity *)element usingKey:(MPKey *)key result:(void (^)(NSString *result))resultBlock;
 | 
			
		||||
 | 
			
		||||
- (void)willBeginDragging;
 | 
			
		||||
- (MPElementEntity *)saveContentTypeWithElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,271 +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
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPAvatarCell.h
 | 
			
		||||
//  MPAvatarCell
 | 
			
		||||
//
 | 
			
		||||
//  Created by lhunath on 2014-03-11.
 | 
			
		||||
//  Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "MPPasswordLargeCell.h"
 | 
			
		||||
#import "MPiOSAppDelegate.h"
 | 
			
		||||
#import "MPAppDelegate_Store.h"
 | 
			
		||||
#import "MPPasswordLargeGeneratedCell.h"
 | 
			
		||||
#import "MPPasswordLargeStoredCell.h"
 | 
			
		||||
#import "MPPasswordTypesCell.h"
 | 
			
		||||
 | 
			
		||||
@implementation MPPasswordLargeCell
 | 
			
		||||
 | 
			
		||||
#pragma mark - Life
 | 
			
		||||
 | 
			
		||||
+ (instancetype)dequeueCellWithType:(MPElementType)type fromCollectionView:(UICollectionView *)collectionView
 | 
			
		||||
                        atIndexPath:(NSIndexPath *)indexPath {
 | 
			
		||||
 | 
			
		||||
    NSAssert( type != 0 && type != (MPElementType)NSNotFound, @"Cannot dequeue a password cell without a type." );
 | 
			
		||||
 | 
			
		||||
    NSString *reuseIdentifier;
 | 
			
		||||
    if (type & MPElementTypeClassGenerated)
 | 
			
		||||
        reuseIdentifier = NSStringFromClass( [MPPasswordLargeGeneratedCell class] );
 | 
			
		||||
    else if (type & MPElementTypeClassStored)
 | 
			
		||||
        reuseIdentifier = NSStringFromClass( [MPPasswordLargeStoredCell class] );
 | 
			
		||||
    else
 | 
			
		||||
        Throw( @"Unexpected password type: %@", [MPAlgorithmDefault nameOfType:type] );
 | 
			
		||||
 | 
			
		||||
    MPPasswordLargeCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
 | 
			
		||||
    cell.type = type;
 | 
			
		||||
 | 
			
		||||
    return cell;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)awakeFromNib {
 | 
			
		||||
 | 
			
		||||
    [super awakeFromNib];
 | 
			
		||||
 | 
			
		||||
    self.layer.cornerRadius = 5;
 | 
			
		||||
    self.layer.shadowOffset = CGSizeZero;
 | 
			
		||||
    self.layer.shadowRadius = 5;
 | 
			
		||||
    self.layer.shadowOpacity = 0;
 | 
			
		||||
    self.layer.shadowColor = [UIColor whiteColor].CGColor;
 | 
			
		||||
 | 
			
		||||
    [self addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector( didLongPress: )]];
 | 
			
		||||
 | 
			
		||||
    [self prepareForReuse];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)didLongPress:(UILongPressGestureRecognizer *)recognizer {
 | 
			
		||||
 | 
			
		||||
    if (recognizer.state != UIGestureRecognizerStateBegan)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (self.contentField.secureTextEntry) {
 | 
			
		||||
        self.contentField.secureTextEntry = NO;
 | 
			
		||||
        PearlMainQueueAfter( 3, ^{
 | 
			
		||||
            self.contentField.secureTextEntry = [[MPiOSConfig get].hidePasswords boolValue];
 | 
			
		||||
        } );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)prepareForReuse {
 | 
			
		||||
 | 
			
		||||
    _contentFieldMode = 0;
 | 
			
		||||
    self.contentField.text = nil;
 | 
			
		||||
 | 
			
		||||
    [super prepareForReuse];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)update {
 | 
			
		||||
 | 
			
		||||
    self.loginButton.alpha = 0;
 | 
			
		||||
    self.upgradeButton.alpha = 0;
 | 
			
		||||
    self.nameLabel.text = @"";
 | 
			
		||||
    self.typeLabel.text = @"";
 | 
			
		||||
    self.contentField.text = @"";
 | 
			
		||||
    self.contentField.secureTextEntry = [[MPiOSConfig get].hidePasswords boolValue];
 | 
			
		||||
    self.contentField.attributedPlaceholder = nil;
 | 
			
		||||
    self.contentField.enabled = self.contentFieldMode == MPContentFieldModeUser;
 | 
			
		||||
    self.loginButton.selected = self.contentFieldMode == MPContentFieldModeUser;
 | 
			
		||||
 | 
			
		||||
    switch (self.contentFieldMode) {
 | 
			
		||||
        case MPContentFieldModePassword: {
 | 
			
		||||
            self.contentField.keyboardType = UIKeyboardTypeDefault;
 | 
			
		||||
            if (self.type & MPElementTypeClassStored)
 | 
			
		||||
                self.contentField.attributedPlaceholder = stra( strl( @"Set custom password" ), @{
 | 
			
		||||
                        NSForegroundColorAttributeName : [UIColor whiteColor]
 | 
			
		||||
                } );
 | 
			
		||||
            else if (self.type & MPElementTypeClassGenerated)
 | 
			
		||||
                self.contentField.attributedPlaceholder = stra( strl( @"Generating..." ), @{
 | 
			
		||||
                        NSForegroundColorAttributeName : [UIColor whiteColor]
 | 
			
		||||
                } );
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case MPContentFieldModeUser: {
 | 
			
		||||
            self.contentField.keyboardType = UIKeyboardTypeEmailAddress;
 | 
			
		||||
            self.contentField.attributedPlaceholder = stra( strl( @"Enter your login name" ), @{
 | 
			
		||||
                    NSForegroundColorAttributeName : [UIColor whiteColor]
 | 
			
		||||
            } );
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)updateWithTransientSite:(NSString *)siteName {
 | 
			
		||||
 | 
			
		||||
    [self update];
 | 
			
		||||
 | 
			
		||||
    self.nameLabel.text = strl( @"%@ - Tap to create", siteName );
 | 
			
		||||
    self.typeLabel.text = [MPAlgorithmDefault nameOfType:self.type];
 | 
			
		||||
 | 
			
		||||
    [self resolveContentOfCellTypeForTransientSite:siteName usingKey:[MPiOSAppDelegate get].key result:^(NSString *result) {
 | 
			
		||||
        PearlMainQueue( ^{ self.contentField.text = result; } );
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)updateWithElement:(MPElementEntity *)mainElement {
 | 
			
		||||
 | 
			
		||||
    [self update];
 | 
			
		||||
 | 
			
		||||
    if (!mainElement)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    self.loginButton.alpha = 1;
 | 
			
		||||
    if (mainElement.requiresExplicitMigration)
 | 
			
		||||
        self.upgradeButton.alpha = 1;
 | 
			
		||||
 | 
			
		||||
    self.nameLabel.text = mainElement.name;
 | 
			
		||||
    if (self.type == (MPElementType)NSNotFound)
 | 
			
		||||
        self.typeLabel.text = @"Delete";
 | 
			
		||||
    else
 | 
			
		||||
        self.typeLabel.text = [mainElement.algorithm nameOfType:self.type];
 | 
			
		||||
 | 
			
		||||
    switch (self.contentFieldMode) {
 | 
			
		||||
        case MPContentFieldModePassword: {
 | 
			
		||||
            MPKey *key = [MPiOSAppDelegate get].key;
 | 
			
		||||
            if (self.type == mainElement.type)
 | 
			
		||||
                [mainElement resolveContentUsingKey:key result:^(NSString *result) {
 | 
			
		||||
                    PearlMainQueue( ^{ self.contentField.text = result; } );
 | 
			
		||||
                }];
 | 
			
		||||
            else
 | 
			
		||||
                [self resolveContentOfCellTypeForElement:mainElement usingKey:key result:^(NSString *result) {
 | 
			
		||||
                    PearlMainQueue( ^{ self.contentField.text = result; } );
 | 
			
		||||
                }];
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case MPContentFieldModeUser: {
 | 
			
		||||
            self.contentField.text = mainElement.loginName;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)resolveContentOfCellTypeForTransientSite:(NSString *)siteName usingKey:(MPKey *)key result:(void ( ^ )(NSString *))resultBlock {
 | 
			
		||||
 | 
			
		||||
    resultBlock( nil );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)resolveContentOfCellTypeForElement:(MPElementEntity *)element usingKey:(MPKey *)key result:(void ( ^ )(NSString *))resultBlock {
 | 
			
		||||
 | 
			
		||||
    resultBlock( nil );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)willBeginDragging {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementEntity *)saveContentTypeWithElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
    return [[MPiOSAppDelegate get] changeElement:element saveInContext:context toType:self.type];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - UITextFieldDelegate
 | 
			
		||||
 | 
			
		||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
 | 
			
		||||
 | 
			
		||||
    [textField resignFirstResponder];
 | 
			
		||||
    return YES;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)textFieldDidBeginEditing:(UITextField *)textField {
 | 
			
		||||
 | 
			
		||||
    UICollectionView *collectionView = [UICollectionView findAsSuperviewOf:self];
 | 
			
		||||
    [collectionView scrollToItemAtIndexPath:[collectionView indexPathForCell:self]
 | 
			
		||||
                           atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)textFieldDidEndEditing:(UITextField *)textField {
 | 
			
		||||
 | 
			
		||||
    if (textField == self.contentField) {
 | 
			
		||||
        NSString *newContent = textField.text;
 | 
			
		||||
        textField.enabled = NO;
 | 
			
		||||
 | 
			
		||||
        if (self.contentFieldMode == MPContentFieldModeUser)
 | 
			
		||||
            [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
                MPElementEntity *element = [[MPPasswordTypesCell findAsSuperviewOf:self] elementInContext:context];
 | 
			
		||||
                if (!element)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                element.loginName = newContent;
 | 
			
		||||
                [context saveToStore];
 | 
			
		||||
 | 
			
		||||
                PearlMainQueue( ^{
 | 
			
		||||
                    [self updateAnimated:YES];
 | 
			
		||||
                    [PearlOverlay showTemporaryOverlayWithTitle:@"Login Updated" dismissAfter:2];
 | 
			
		||||
                } );
 | 
			
		||||
            }];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - Actions
 | 
			
		||||
 | 
			
		||||
- (IBAction)doUser:(id)sender {
 | 
			
		||||
 | 
			
		||||
    switch (self.contentFieldMode) {
 | 
			
		||||
        case MPContentFieldModePassword: {
 | 
			
		||||
            self.contentFieldMode = MPContentFieldModeUser;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case MPContentFieldModeUser: {
 | 
			
		||||
            self.contentFieldMode = MPContentFieldModePassword;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (IBAction)doUpgrade:(UIButton *)sender {
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        if ([[[MPPasswordTypesCell findAsSuperviewOf:self] elementInContext:context] migrateExplicitly:YES]) {
 | 
			
		||||
            [context saveToStore];
 | 
			
		||||
 | 
			
		||||
            PearlMainQueue( ^{
 | 
			
		||||
                [[MPPasswordTypesCell findAsSuperviewOf:self] reloadData];
 | 
			
		||||
                [PearlOverlay showTemporaryOverlayWithTitle:@"Site Upgraded" dismissAfter:2];
 | 
			
		||||
            } );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            PearlMainQueue( ^{
 | 
			
		||||
                [PearlOverlay showTemporaryOverlayWithTitle:@"Site Not Upgraded" dismissAfter:2];
 | 
			
		||||
            } );
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - Properties
 | 
			
		||||
 | 
			
		||||
- (void)setContentFieldMode:(MPContentFieldMode)contentFieldMode {
 | 
			
		||||
 | 
			
		||||
    if (_contentFieldMode == contentFieldMode)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    _contentFieldMode = contentFieldMode;
 | 
			
		||||
 | 
			
		||||
    [[MPPasswordTypesCell findAsSuperviewOf:self] reloadData:self];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,25 +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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPPasswordLargeDeleteCell.h
 | 
			
		||||
//  MPPasswordLargeDeleteCell
 | 
			
		||||
//
 | 
			
		||||
//  Created by lhunath on 2014-03-19.
 | 
			
		||||
//  Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import <Foundation/Foundation.h>
 | 
			
		||||
#import "MPPasswordLargeCell.h"
 | 
			
		||||
 | 
			
		||||
@interface MPPasswordLargeDeleteCell : MPPasswordLargeCell
 | 
			
		||||
 | 
			
		||||
+ (MPPasswordLargeCell *)dequeueCellFromCollectionView:(UICollectionView *)view atIndexPath:(NSIndexPath *)path;
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,39 +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
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPPasswordLargeDeleteCell.h
 | 
			
		||||
//  MPPasswordLargeDeleteCell
 | 
			
		||||
//
 | 
			
		||||
//  Created by lhunath on 2014-03-19.
 | 
			
		||||
//  Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "MPPasswordLargeDeleteCell.h"
 | 
			
		||||
 | 
			
		||||
@implementation MPPasswordLargeDeleteCell
 | 
			
		||||
 | 
			
		||||
#pragma mark - Lifecycle
 | 
			
		||||
 | 
			
		||||
+ (MPPasswordLargeCell *)dequeueCellFromCollectionView:(UICollectionView *)collectionView atIndexPath:(NSIndexPath *)indexPath {
 | 
			
		||||
 | 
			
		||||
    MPPasswordLargeCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass( [self class] )
 | 
			
		||||
                                                                          forIndexPath:indexPath];
 | 
			
		||||
    cell.type = (MPElementType)NSNotFound;
 | 
			
		||||
 | 
			
		||||
    return cell;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementEntity *)saveContentTypeWithElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
    return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,28 +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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPPasswordLargeGeneratedCell.h
 | 
			
		||||
//  MPPasswordLargeGeneratedCell
 | 
			
		||||
//
 | 
			
		||||
//  Created by lhunath on 2014-03-19.
 | 
			
		||||
//  Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import <Foundation/Foundation.h>
 | 
			
		||||
#import "MPPasswordLargeCell.h"
 | 
			
		||||
 | 
			
		||||
@interface MPPasswordLargeGeneratedCell : MPPasswordLargeCell
 | 
			
		||||
 | 
			
		||||
@property(strong, nonatomic) IBOutlet UILabel *strengthLabel;
 | 
			
		||||
@property(strong, nonatomic) IBOutlet UILabel *counterLabel;
 | 
			
		||||
@property(strong, nonatomic) IBOutlet UIButton *counterButton;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,200 +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
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPPasswordLargeGeneratedCell.h
 | 
			
		||||
//  MPPasswordLargeGeneratedCell
 | 
			
		||||
//
 | 
			
		||||
//  Created by lhunath on 2014-03-19.
 | 
			
		||||
//  Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "MPPasswordLargeGeneratedCell.h"
 | 
			
		||||
#import "MPiOSAppDelegate.h"
 | 
			
		||||
#import "MPAppDelegate_Store.h"
 | 
			
		||||
#import "MPPasswordTypesCell.h"
 | 
			
		||||
 | 
			
		||||
@interface MPPasswordLargeGeneratedCell()
 | 
			
		||||
 | 
			
		||||
@property(nonatomic, weak) NSTimer *hideStrengthTimer;
 | 
			
		||||
@end
 | 
			
		||||
 | 
			
		||||
@implementation MPPasswordLargeGeneratedCell
 | 
			
		||||
 | 
			
		||||
- (void)awakeFromNib {
 | 
			
		||||
 | 
			
		||||
    [super awakeFromNib];
 | 
			
		||||
 | 
			
		||||
    UILongPressGestureRecognizer *gestureRecognizer = [[UILongPressGestureRecognizer alloc]
 | 
			
		||||
            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];
 | 
			
		||||
 | 
			
		||||
    MPElementGeneratedEntity *generatedElement = [self generatedElement:mainElement];
 | 
			
		||||
    if (generatedElement)
 | 
			
		||||
        self.counterLabel.text = strf( @"%lu", (unsigned long)generatedElement.counter );
 | 
			
		||||
    else
 | 
			
		||||
        self.counterLabel.text = @"1";
 | 
			
		||||
 | 
			
		||||
    if (mainElement && !mainElement.requiresExplicitMigration)
 | 
			
		||||
        self.counterLabel.alpha = self.counterButton.alpha = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (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 {
 | 
			
		||||
 | 
			
		||||
    id<MPAlgorithm> algorithm = element.algorithm;
 | 
			
		||||
    NSString *siteName = element.name;
 | 
			
		||||
 | 
			
		||||
    PearlNotMainQueue( ^{
 | 
			
		||||
        resultBlock( [algorithm generateContentNamed:siteName ofType:self.type withCounter:1 usingKey:key] );
 | 
			
		||||
    } );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementEntity *)saveContentTypeWithElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
    element = [super saveContentTypeWithElement:element saveInContext:context];
 | 
			
		||||
 | 
			
		||||
    MPElementGeneratedEntity *generatedElement = [self generatedElement:element];
 | 
			
		||||
    if (generatedElement) {
 | 
			
		||||
        generatedElement.counter = [self.counterLabel.text intValue];
 | 
			
		||||
        [context saveToStore];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - Actions
 | 
			
		||||
 | 
			
		||||
- (IBAction)doIncrementCounter:(UIButton *)sender {
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        MPElementGeneratedEntity *generatedElement = [self generatedElementInContext:context];
 | 
			
		||||
        if (!generatedElement)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        ++generatedElement.counter;
 | 
			
		||||
        [context saveToStore];
 | 
			
		||||
 | 
			
		||||
        PearlMainQueue( ^{
 | 
			
		||||
            [self updateAnimated:YES];
 | 
			
		||||
            [PearlOverlay showTemporaryOverlayWithTitle:@"Counter Incremented" dismissAfter:2];
 | 
			
		||||
        } );
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)doResetCounterRecognizer:(UILongPressGestureRecognizer *)gestureRecognizer {
 | 
			
		||||
 | 
			
		||||
    if (gestureRecognizer.state != UIGestureRecognizerStateBegan)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        MPElementGeneratedEntity *generatedElement = [self generatedElementInContext:context];
 | 
			
		||||
        if (!generatedElement)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        generatedElement.counter = 1;
 | 
			
		||||
        [context saveToStore];
 | 
			
		||||
 | 
			
		||||
        PearlMainQueue( ^{
 | 
			
		||||
            [self updateAnimated:YES];
 | 
			
		||||
            [PearlOverlay showTemporaryOverlayWithTitle:@"Counter Reset" dismissAfter:2];
 | 
			
		||||
        } );
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - Properties
 | 
			
		||||
 | 
			
		||||
- (void)setType:(MPElementType)type {
 | 
			
		||||
 | 
			
		||||
    [super setType:type];
 | 
			
		||||
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case MPElementTypeGeneratedMaximum:
 | 
			
		||||
            self.strengthLabel.text = @"422 quintillion years";
 | 
			
		||||
            break;
 | 
			
		||||
        case MPElementTypeGeneratedLong:
 | 
			
		||||
            self.strengthLabel.text = @"1.4 years";
 | 
			
		||||
            break;
 | 
			
		||||
        case MPElementTypeGeneratedMedium:
 | 
			
		||||
            self.strengthLabel.text = @"2 seconds";
 | 
			
		||||
            break;
 | 
			
		||||
        case MPElementTypeGeneratedBasic:
 | 
			
		||||
            self.strengthLabel.text = @"trivial";
 | 
			
		||||
            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]];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementGeneratedEntity *)generatedElement:(MPElementEntity *)element {
 | 
			
		||||
 | 
			
		||||
    if (![element isKindOfClass:[MPElementGeneratedEntity class]])
 | 
			
		||||
        return nil;
 | 
			
		||||
 | 
			
		||||
    return (MPElementGeneratedEntity *)element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPPasswordLargeStoredCell.h
 | 
			
		||||
//  MPPasswordLargeStoredCell
 | 
			
		||||
//
 | 
			
		||||
//  Created by lhunath on 2014-03-19.
 | 
			
		||||
//  Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import <Foundation/Foundation.h>
 | 
			
		||||
#import "MPPasswordLargeCell.h"
 | 
			
		||||
 | 
			
		||||
@interface MPPasswordLargeStoredCell : MPPasswordLargeCell
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,102 +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
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPPasswordLargeGeneratedCell.h
 | 
			
		||||
//  MPPasswordLargeGeneratedCell
 | 
			
		||||
//
 | 
			
		||||
//  Created by lhunath on 2014-03-19.
 | 
			
		||||
//  Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "MPPasswordLargeStoredCell.h"
 | 
			
		||||
#import "MPiOSAppDelegate.h"
 | 
			
		||||
#import "MPAppDelegate_Store.h"
 | 
			
		||||
#import "MPPasswordTypesCell.h"
 | 
			
		||||
 | 
			
		||||
@interface MPPasswordLargeStoredCell()
 | 
			
		||||
 | 
			
		||||
@property(strong, nonatomic) IBOutlet UIButton *editButton;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
 | 
			
		||||
@implementation MPPasswordLargeStoredCell
 | 
			
		||||
 | 
			
		||||
#pragma mark - Lifecycle
 | 
			
		||||
 | 
			
		||||
- (void)resolveContentOfCellTypeForElement:(MPElementEntity *)element usingKey:(MPKey *)key result:(void ( ^ )(NSString *))resultBlock {
 | 
			
		||||
 | 
			
		||||
    if (element.type & MPElementTypeClassStored)
 | 
			
		||||
        [element resolveContentUsingKey:key result:resultBlock];
 | 
			
		||||
    else
 | 
			
		||||
        [super resolveContentOfCellTypeForElement:element usingKey:key result:resultBlock];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementEntity *)saveContentTypeWithElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
    element = [super saveContentTypeWithElement:element saveInContext:context];
 | 
			
		||||
    MPElementStoredEntity *storedElement = [self storedElement:element];
 | 
			
		||||
    [storedElement.algorithm saveContent:self.contentField.text toElement:storedElement usingKey:[MPiOSAppDelegate get].key];
 | 
			
		||||
    [context saveToStore];
 | 
			
		||||
 | 
			
		||||
    return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - Actions
 | 
			
		||||
 | 
			
		||||
- (IBAction)doEditContent:(UIButton *)sender {
 | 
			
		||||
 | 
			
		||||
    UITextField *textField = self.contentField;
 | 
			
		||||
    textField.enabled = YES;
 | 
			
		||||
    [textField becomeFirstResponder];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - UITextFieldDelegate
 | 
			
		||||
 | 
			
		||||
- (void)textFieldDidEndEditing:(UITextField *)textField {
 | 
			
		||||
 | 
			
		||||
    [super textFieldDidEndEditing:textField];
 | 
			
		||||
 | 
			
		||||
    if (textField == self.contentField) {
 | 
			
		||||
        NSString *newContent = textField.text;
 | 
			
		||||
 | 
			
		||||
        if (self.contentFieldMode == MPContentFieldModePassword)
 | 
			
		||||
            [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
                MPElementStoredEntity *storedElement = [self storedElementInContext:context];
 | 
			
		||||
                if (!storedElement)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                [storedElement.algorithm saveContent:newContent toElement:storedElement usingKey:[MPiOSAppDelegate get].key];
 | 
			
		||||
                [context saveToStore];
 | 
			
		||||
 | 
			
		||||
                PearlMainQueue( ^{
 | 
			
		||||
                    [self updateAnimated:YES];
 | 
			
		||||
                    [PearlOverlay showTemporaryOverlayWithTitle:@"Password Updated" dismissAfter:2];
 | 
			
		||||
                } );
 | 
			
		||||
            }];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - Properties
 | 
			
		||||
 | 
			
		||||
- (MPElementStoredEntity *)storedElementInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
    return [self storedElement:[[MPPasswordTypesCell findAsSuperviewOf:self] elementInContext:context]];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementStoredEntity *)storedElement:(MPElementEntity *)element {
 | 
			
		||||
 | 
			
		||||
    if (![element isKindOfClass:[MPElementStoredEntity class]])
 | 
			
		||||
        return nil;
 | 
			
		||||
 | 
			
		||||
    return (MPElementStoredEntity *)element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,46 +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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPPasswordTypesCell.h
 | 
			
		||||
//  MPPasswordTypesCell
 | 
			
		||||
//
 | 
			
		||||
//  Created by lhunath on 2014-03-27.
 | 
			
		||||
//  Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import <Foundation/Foundation.h>
 | 
			
		||||
#import "MPCell.h"
 | 
			
		||||
#import "MPPasswordCell.h"
 | 
			
		||||
#import "MPPasswordsViewController.h"
 | 
			
		||||
#import "MPPasswordLargeCell.h"
 | 
			
		||||
 | 
			
		||||
@interface MPPasswordTypesCell : MPPasswordCell <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
 | 
			
		||||
 | 
			
		||||
@property(nonatomic, strong) IBOutlet UICollectionView *contentCollectionView;
 | 
			
		||||
 | 
			
		||||
@property(nonatomic, weak) MPPasswordsViewController *passwordsViewController;
 | 
			
		||||
@property(nonatomic, copy) NSString *transientSite;
 | 
			
		||||
 | 
			
		||||
@property(nonatomic, strong) id<MPAlgorithm> algorithm;
 | 
			
		||||
@property(nonatomic) MPElementType activeType;
 | 
			
		||||
 | 
			
		||||
- (MPElementEntity *)mainElement;
 | 
			
		||||
- (MPElementEntity *)elementInContext:(NSManagedObjectContext *)context;
 | 
			
		||||
- (void)setElement:(MPElementEntity *)element;
 | 
			
		||||
- (void)reloadData;
 | 
			
		||||
- (void)reloadData:(MPPasswordLargeCell *)cell;
 | 
			
		||||
 | 
			
		||||
+ (instancetype)dequeueCellForElement:(MPElementEntity *)element
 | 
			
		||||
                   fromCollectionView:(UICollectionView *)collectionView atIndexPath:(NSIndexPath *)indexPath;
 | 
			
		||||
+ (instancetype)dequeueCellForTransientSite:(NSString *)siteName
 | 
			
		||||
                   fromCollectionView:(UICollectionView *)collectionView atIndexPath:(NSIndexPath *)indexPath;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,411 +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
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPPasswordTypesCell.h
 | 
			
		||||
//  MPPasswordTypesCell
 | 
			
		||||
//
 | 
			
		||||
//  Created by lhunath on 2014-03-27.
 | 
			
		||||
//  Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "MPPasswordTypesCell.h"
 | 
			
		||||
#import "MPPasswordLargeCell.h"
 | 
			
		||||
#import "MPiOSAppDelegate.h"
 | 
			
		||||
#import "MPAppDelegate_Store.h"
 | 
			
		||||
#import "MPPasswordLargeDeleteCell.h"
 | 
			
		||||
 | 
			
		||||
@implementation MPPasswordTypesCell {
 | 
			
		||||
    NSManagedObjectID *_elementOID;
 | 
			
		||||
    BOOL _scrolling;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - Lifecycle
 | 
			
		||||
 | 
			
		||||
+ (instancetype)dequeueCellForTransientSite:(NSString *)siteName fromCollectionView:(UICollectionView *)collectionView
 | 
			
		||||
                                atIndexPath:(NSIndexPath *)indexPath {
 | 
			
		||||
 | 
			
		||||
    MPPasswordTypesCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass( [MPPasswordTypesCell class] )
 | 
			
		||||
                                                                          forIndexPath:indexPath];
 | 
			
		||||
    [cell setTransientSite:siteName];
 | 
			
		||||
 | 
			
		||||
    return cell;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
+ (instancetype)dequeueCellForElement:(MPElementEntity *)element fromCollectionView:(UICollectionView *)collectionView
 | 
			
		||||
                          atIndexPath:(NSIndexPath *)indexPath {
 | 
			
		||||
 | 
			
		||||
    MPPasswordTypesCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass( [MPPasswordTypesCell class] )
 | 
			
		||||
                                                                          forIndexPath:indexPath];
 | 
			
		||||
    [cell setElement:element];
 | 
			
		||||
 | 
			
		||||
    return cell;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)awakeFromNib {
 | 
			
		||||
 | 
			
		||||
    [super awakeFromNib];
 | 
			
		||||
 | 
			
		||||
    self.backgroundColor = [UIColor clearColor];
 | 
			
		||||
    self.layer.shadowColor = [UIColor clearColor].CGColor;
 | 
			
		||||
 | 
			
		||||
    [self prepareForReuse];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)prepareForReuse {
 | 
			
		||||
 | 
			
		||||
    _elementOID = nil;
 | 
			
		||||
    _transientSite = nil;
 | 
			
		||||
    _activeType = 0;
 | 
			
		||||
    _algorithm = MPAlgorithmDefault;
 | 
			
		||||
 | 
			
		||||
    [super prepareForReuse];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
 | 
			
		||||
 | 
			
		||||
    [super applyLayoutAttributes:layoutAttributes];
 | 
			
		||||
 | 
			
		||||
    [self.contentCollectionView.collectionViewLayout invalidateLayout];
 | 
			
		||||
    [self scrollToActiveType];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - UICollectionViewDataSource
 | 
			
		||||
 | 
			
		||||
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout
 | 
			
		||||
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
 | 
			
		||||
 | 
			
		||||
    return collectionView.bounds.size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
 | 
			
		||||
 | 
			
		||||
    if (!self.algorithm)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    if (self.transientSite)
 | 
			
		||||
        return [[self.algorithm allTypes] count];
 | 
			
		||||
 | 
			
		||||
    return [[self.algorithm allTypes] count] + 1 /* Delete */;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPPasswordLargeCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
 | 
			
		||||
 | 
			
		||||
    MPPasswordLargeCell *cell;
 | 
			
		||||
    if (!self.transientSite && indexPath.item == 0) {
 | 
			
		||||
        cell = [MPPasswordLargeDeleteCell dequeueCellFromCollectionView:collectionView atIndexPath:indexPath];
 | 
			
		||||
        [cell updateWithElement:self.mainElement];
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        cell = [MPPasswordLargeCell dequeueCellWithType:[self typeForContentIndexPath:indexPath] fromCollectionView:collectionView
 | 
			
		||||
                                            atIndexPath:indexPath];
 | 
			
		||||
 | 
			
		||||
        [cell prepareForReuse];
 | 
			
		||||
 | 
			
		||||
        if (self.transientSite)
 | 
			
		||||
            [cell updateWithTransientSite:self.transientSite];
 | 
			
		||||
        else
 | 
			
		||||
            [cell updateWithElement:self.mainElement];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (_scrolling)
 | 
			
		||||
        [cell willBeginDragging];
 | 
			
		||||
 | 
			
		||||
    return cell;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - UICollectionViewDelegateFlowLayout
 | 
			
		||||
 | 
			
		||||
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
 | 
			
		||||
 | 
			
		||||
    NSString *newSiteName = self.transientSite;
 | 
			
		||||
    if (newSiteName) {
 | 
			
		||||
        [[UIResponder findFirstResponder] resignFirstResponder];
 | 
			
		||||
        [PearlAlert showAlertWithTitle:@"Create Site"
 | 
			
		||||
                               message:strf( @"Do you want to create a new site named:\n%@", newSiteName )
 | 
			
		||||
                             viewStyle:UIAlertViewStyleDefault
 | 
			
		||||
                             initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
 | 
			
		||||
            if (buttonIndex == [alert cancelButtonIndex]) {
 | 
			
		||||
                // Cancel
 | 
			
		||||
                for (NSIndexPath *selectedIndexPath in [collectionView indexPathsForSelectedItems])
 | 
			
		||||
                    [collectionView deselectItemAtIndexPath:selectedIndexPath animated:YES];
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Create
 | 
			
		||||
            [[MPiOSAppDelegate get] addElementNamed:newSiteName completion:^(MPElementEntity *element) {
 | 
			
		||||
                [self copyContentOfElement:element inCell:nil];
 | 
			
		||||
                PearlMainQueue( ^{
 | 
			
		||||
                    [self.passwordsViewController updatePasswords];
 | 
			
		||||
                } );
 | 
			
		||||
            }];
 | 
			
		||||
        }                  cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonYes, nil];
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        BOOL used = NO;
 | 
			
		||||
        MPElementEntity *element = [self elementInContext:context];
 | 
			
		||||
        MPPasswordLargeCell *cell = (MPPasswordLargeCell *)[self.contentCollectionView cellForItemAtIndexPath:indexPath];
 | 
			
		||||
        if (!element)
 | 
			
		||||
            wrn( @"No element to use for: %@", self );
 | 
			
		||||
        else if (indexPath.item == 0) {
 | 
			
		||||
            [context deleteObject:element];
 | 
			
		||||
            [context saveToStore];
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            used = [self copyContentOfElement:element inCell:cell];
 | 
			
		||||
 | 
			
		||||
        PearlMainQueueAfter( 0.2f, ^{
 | 
			
		||||
            for (NSIndexPath *selectedIndexPath in [collectionView indexPathsForSelectedItems])
 | 
			
		||||
                [collectionView deselectItemAtIndexPath:selectedIndexPath animated:YES];
 | 
			
		||||
 | 
			
		||||
            if (used)
 | 
			
		||||
                [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context_) {
 | 
			
		||||
                    [[self elementInContext:context_] use];
 | 
			
		||||
                    [context_ saveToStore];
 | 
			
		||||
                }];
 | 
			
		||||
        } );
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (BOOL)copyContentOfElement:(MPElementEntity *)element inCell:(MPPasswordLargeCell *)cell {
 | 
			
		||||
 | 
			
		||||
    NSString *used, *pasteboardContent;
 | 
			
		||||
    switch (cell.contentFieldMode) {
 | 
			
		||||
        case MPContentFieldModePassword:
 | 
			
		||||
            inf( @"Copying password for: %@", element.name );
 | 
			
		||||
            used = strl( @"Password" );
 | 
			
		||||
            pasteboardContent = [element resolveContentUsingKey:[MPAppDelegate_Shared get].key];
 | 
			
		||||
            break;
 | 
			
		||||
        case MPContentFieldModeUser:
 | 
			
		||||
            inf( @"Copying login for: %@", element.name );
 | 
			
		||||
            used = strl( @"Login" );
 | 
			
		||||
            pasteboardContent = element.loginName;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ([pasteboardContent length]) {
 | 
			
		||||
        [UIPasteboard generalPasteboard].string = pasteboardContent;
 | 
			
		||||
        [PearlOverlay showTemporaryOverlayWithTitle:strl(@"%@ Copied", used) dismissAfter:2];
 | 
			
		||||
        return YES;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return NO;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#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 {
 | 
			
		||||
 | 
			
		||||
    if (scrollView == self.contentCollectionView) {
 | 
			
		||||
        NSIndexPath *targetIndexPath = [self.contentCollectionView indexPathForItemAtPoint:
 | 
			
		||||
                CGPointPlusCGPoint( *targetContentOffset, self.contentCollectionView.center )];
 | 
			
		||||
        *targetContentOffset = CGRectGetTopLeft(
 | 
			
		||||
                [self.contentCollectionView layoutAttributesForItemAtIndexPath:targetIndexPath].frame );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (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];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - Private
 | 
			
		||||
 | 
			
		||||
- (void)reloadData {
 | 
			
		||||
 | 
			
		||||
    if (self.transientSite)
 | 
			
		||||
        PearlMainQueue( ^{
 | 
			
		||||
            self.algorithm = MPAlgorithmDefault;
 | 
			
		||||
            self.activeType = [[MPiOSAppDelegate get] activeUserForMainThread].defaultType?: MPElementTypeGeneratedLong;
 | 
			
		||||
 | 
			
		||||
            for (NSInteger section = 0; section < [self.contentCollectionView numberOfSections]; ++section)
 | 
			
		||||
                for (NSInteger item = 0; item < [self.contentCollectionView numberOfItemsInSection:section]; ++item)
 | 
			
		||||
                    [(MPPasswordLargeCell *)[self.contentCollectionView cellForItemAtIndexPath:
 | 
			
		||||
                            [NSIndexPath indexPathForItem:item inSection:section]] updateWithTransientSite:self.transientSite];
 | 
			
		||||
        } );
 | 
			
		||||
    else
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextForMainThreadPerformBlockAndWait:^(NSManagedObjectContext *mainContext) {
 | 
			
		||||
            MPElementEntity *mainElement = self.transientSite? nil: [self elementInContext:mainContext];
 | 
			
		||||
 | 
			
		||||
            self.algorithm = mainElement.algorithm?: MPAlgorithmDefault;
 | 
			
		||||
            self.activeType = mainElement.type?: [[MPiOSAppDelegate get] activeUserInContext:mainContext].defaultType?:
 | 
			
		||||
                                                 MPElementTypeGeneratedLong;
 | 
			
		||||
 | 
			
		||||
            for (NSInteger section = 0; section < [self.contentCollectionView numberOfSections]; ++section)
 | 
			
		||||
                for (NSInteger item = 0; item < [self.contentCollectionView numberOfItemsInSection:section]; ++item) {
 | 
			
		||||
                    MPPasswordLargeCell *cell = (MPPasswordLargeCell *)[self.contentCollectionView cellForItemAtIndexPath:
 | 
			
		||||
                            [NSIndexPath indexPathForItem:item inSection:section]];
 | 
			
		||||
                    [self reloadData:cell withElement:mainElement];
 | 
			
		||||
                }
 | 
			
		||||
        }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)reloadData:(MPPasswordLargeCell *)cell {
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextForMainThreadPerformBlockAndWait:^(NSManagedObjectContext *mainContext) {
 | 
			
		||||
        [self reloadData:cell withElement:[self elementInContext:mainContext]];
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)reloadData:(MPPasswordLargeCell *)cell withElement:(MPElementEntity *)element {
 | 
			
		||||
 | 
			
		||||
    if (element)
 | 
			
		||||
        [cell updateWithElement:element];
 | 
			
		||||
    else
 | 
			
		||||
        [cell updateWithTransientSite:self.transientSite];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)scrollToActiveType {
 | 
			
		||||
 | 
			
		||||
    if (self.activeType && self.activeType != (MPElementType)NSNotFound)
 | 
			
		||||
        [self.contentCollectionView scrollToItemAtIndexPath:[self contentIndexPathForType:self.activeType]
 | 
			
		||||
                                           atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementType)typeForContentIndexPath:(NSIndexPath *)indexPath {
 | 
			
		||||
 | 
			
		||||
    if (self.transientSite)
 | 
			
		||||
        return [[self.algorithm allTypesStartingWith:MPElementTypeGeneratedPIN][indexPath.item] unsignedIntegerValue];
 | 
			
		||||
 | 
			
		||||
    if (indexPath.item == 0)
 | 
			
		||||
        return (MPElementType)NSNotFound;
 | 
			
		||||
 | 
			
		||||
    return [[self.algorithm allTypesStartingWith:MPElementTypeGeneratedPIN][indexPath.item - 1] unsignedIntegerValue];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSIndexPath *)contentIndexPathForType:(MPElementType)type {
 | 
			
		||||
 | 
			
		||||
    NSArray *types = [self.algorithm allTypesStartingWith:MPElementTypeGeneratedPIN];
 | 
			
		||||
    for (NSInteger t = 0; t < [types count]; ++t)
 | 
			
		||||
        if ([types[t] unsignedIntegerValue] == type) {
 | 
			
		||||
            if (self.transientSite)
 | 
			
		||||
                return [NSIndexPath indexPathForItem:t inSection:0];
 | 
			
		||||
            else
 | 
			
		||||
                return [NSIndexPath indexPathForItem:t + 1 inSection:0];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    Throw( @"Unsupported type: %lud", (long)type );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)saveContentType {
 | 
			
		||||
 | 
			
		||||
    CGPoint centerPoint = CGRectGetCenter( self.contentCollectionView.bounds );
 | 
			
		||||
    NSIndexPath *centerIndexPath = [self.contentCollectionView indexPathForItemAtPoint:centerPoint];
 | 
			
		||||
    MPElementType type = [self typeForContentIndexPath:centerIndexPath];
 | 
			
		||||
    if (type == ((MPElementType)NSNotFound))
 | 
			
		||||
        // Active cell is not a type cell.
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    self.activeType = type;
 | 
			
		||||
 | 
			
		||||
    if (self.transientSite)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        MPPasswordLargeCell *cell = (MPPasswordLargeCell *)[self.contentCollectionView cellForItemAtIndexPath:centerIndexPath];
 | 
			
		||||
        if (!cell) {
 | 
			
		||||
            err( @"Couldn't find cell to change type: centerIndexPath=%@", centerIndexPath );
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        MPElementEntity *element = [self elementInContext:context];
 | 
			
		||||
        if (!element || element.type == cell.type)
 | 
			
		||||
            // Nothing changed.
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        self.element = [cell saveContentTypeWithElement:element saveInContext:context];
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - State
 | 
			
		||||
 | 
			
		||||
- (void)setTransientSite:(NSString *)transientSite {
 | 
			
		||||
 | 
			
		||||
    if ([_transientSite isEqualToString:transientSite])
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    dbg( @"transientSite: %@ -> %@", _transientSite, transientSite );
 | 
			
		||||
 | 
			
		||||
    _transientSite = transientSite;
 | 
			
		||||
    _elementOID = nil;
 | 
			
		||||
 | 
			
		||||
    [self updateAnimated:YES];
 | 
			
		||||
    [self reloadData];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setElement:(MPElementEntity *)element {
 | 
			
		||||
 | 
			
		||||
    NSManagedObjectID *newElementOID = element.objectID;
 | 
			
		||||
    NSAssert( !newElementOID.isTemporaryID, @"Element doesn't have a permanent objectID: %@", element );
 | 
			
		||||
    if ([_elementOID isEqual:newElementOID])
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    dbg( @"element: %@ -> %@", _elementOID, newElementOID );
 | 
			
		||||
 | 
			
		||||
    _transientSite = nil;
 | 
			
		||||
    _elementOID = newElementOID;
 | 
			
		||||
 | 
			
		||||
    [self updateAnimated:YES];
 | 
			
		||||
    [self reloadData];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementEntity *)mainElement {
 | 
			
		||||
 | 
			
		||||
    return [self elementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementEntity *)elementInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
    return [MPElementEntity existingObjectWithID:_elementOID inContext:context];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setActiveType:(MPElementType)activeType {
 | 
			
		||||
 | 
			
		||||
    _activeType = activeType;
 | 
			
		||||
 | 
			
		||||
    [self scrollToActiveType];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setSelected:(BOOL)selected {
 | 
			
		||||
 | 
			
		||||
    [super setSelected:selected];
 | 
			
		||||
 | 
			
		||||
    if (!selected)
 | 
			
		||||
        for (NSIndexPath *indexPath in [self.contentCollectionView indexPathsForSelectedItems])
 | 
			
		||||
            [self.contentCollectionView deselectItemAtIndexPath:indexPath animated:YES];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setAlgorithm:(id<MPAlgorithm>)algorithm {
 | 
			
		||||
 | 
			
		||||
    _algorithm = algorithm;
 | 
			
		||||
 | 
			
		||||
    [self.contentCollectionView reloadData];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,23 +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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPPasswordsCoachmarkViewController.h
 | 
			
		||||
//  MPPasswordsCoachmarkViewController
 | 
			
		||||
//
 | 
			
		||||
//  Created by lhunath on 2014-04-23.
 | 
			
		||||
//  Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import <Foundation/Foundation.h>
 | 
			
		||||
#import "MPCoachmarkViewController.h"
 | 
			
		||||
 | 
			
		||||
@interface MPPasswordsCoachmarkViewController : MPCoachmarkViewController <UICollectionViewDataSource>
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,51 +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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPPasswordsCoachmarkViewController.h
 | 
			
		||||
//  MPPasswordsCoachmarkViewController
 | 
			
		||||
//
 | 
			
		||||
//  Created by lhunath on 2014-04-23.
 | 
			
		||||
//  Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "MPPasswordsCoachmarkViewController.h"
 | 
			
		||||
#import "MPPasswordLargeGeneratedCell.h"
 | 
			
		||||
#import "MPPasswordLargeStoredCell.h"
 | 
			
		||||
 | 
			
		||||
@implementation MPPasswordsCoachmarkViewController
 | 
			
		||||
 | 
			
		||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
 | 
			
		||||
 | 
			
		||||
    return 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
 | 
			
		||||
 | 
			
		||||
    if (indexPath.item == 0) {
 | 
			
		||||
        MPPasswordLargeGeneratedCell *cell = [MPPasswordLargeGeneratedCell dequeueCellWithType:MPElementTypeGeneratedLong
 | 
			
		||||
                                                                            fromCollectionView:collectionView atIndexPath:indexPath];
 | 
			
		||||
        [cell updateWithTransientSite:@"apple.com"];
 | 
			
		||||
 | 
			
		||||
        return cell;
 | 
			
		||||
    }
 | 
			
		||||
    else if (indexPath.item == 1) {
 | 
			
		||||
        MPPasswordLargeStoredCell *cell = [MPPasswordLargeStoredCell dequeueCellWithType:MPElementTypeStoredPersonal
 | 
			
		||||
                                                                      fromCollectionView:collectionView atIndexPath:indexPath];
 | 
			
		||||
        [cell updateWithTransientSite:@"gmail.com"];
 | 
			
		||||
        [cell.contentField setText:@"PaS$w0rD"];
 | 
			
		||||
 | 
			
		||||
        return cell;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Throw(@"Unexpected item for indexPath: %@", indexPath);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -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
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  MPPasswordsViewController.h
 | 
			
		||||
@@ -19,11 +19,9 @@
 | 
			
		||||
#import "MPPasswordsViewController.h"
 | 
			
		||||
#import "MPiOSAppDelegate.h"
 | 
			
		||||
#import "MPAppDelegate_Store.h"
 | 
			
		||||
#import "MPPasswordLargeCell.h"
 | 
			
		||||
#import "MPPasswordTypesCell.h"
 | 
			
		||||
#import "MPPopdownSegue.h"
 | 
			
		||||
#import "MPAppDelegate_Key.h"
 | 
			
		||||
#import "MPCoachmarkViewController.h"
 | 
			
		||||
#import "MPPasswordCell.h"
 | 
			
		||||
 | 
			
		||||
@interface MPPasswordsViewController()<NSFetchedResultsControllerDelegate>
 | 
			
		||||
 | 
			
		||||
@@ -58,7 +56,7 @@
 | 
			
		||||
    [self.passwordsSearchBar enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
 | 
			
		||||
        if ([subview isKindOfClass:[UITextField class]])
 | 
			
		||||
            ((UITextField *)subview).keyboardAppearance = UIKeyboardAppearanceDark;
 | 
			
		||||
    } recurse:YES];
 | 
			
		||||
    }                               recurse:YES];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)viewWillAppear:(BOOL)animated {
 | 
			
		||||
@@ -103,54 +101,34 @@ referenceSizeForHeaderInSection:(NSInteger)section {
 | 
			
		||||
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout
 | 
			
		||||
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
 | 
			
		||||
 | 
			
		||||
    if (collectionView == self.passwordCollectionView) {
 | 
			
		||||
        UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)collectionViewLayout;
 | 
			
		||||
        CGFloat itemWidth = UIEdgeInsetsInsetRect(self.passwordCollectionView.bounds, layout.sectionInset).size.width;
 | 
			
		||||
        return CGSizeMake( itemWidth, 100 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Throw(@"Unexpected collection view: %@", collectionView);
 | 
			
		||||
    UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)collectionViewLayout;
 | 
			
		||||
    CGFloat itemWidth = UIEdgeInsetsInsetRect( self.passwordCollectionView.bounds, layout.sectionInset ).size.width;
 | 
			
		||||
    return CGSizeMake( itemWidth, 100 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - UICollectionViewDataSource
 | 
			
		||||
 | 
			
		||||
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
 | 
			
		||||
 | 
			
		||||
    if (collectionView == self.passwordCollectionView)
 | 
			
		||||
        return [self.fetchedResultsController.sections count];
 | 
			
		||||
 | 
			
		||||
    Throw(@"Unexpected collection view: %@", collectionView);
 | 
			
		||||
    return [self.fetchedResultsController.sections count];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
 | 
			
		||||
 | 
			
		||||
    if (collectionView == self.passwordCollectionView)
 | 
			
		||||
        return ![MPiOSAppDelegate get].activeUserOID? 0:
 | 
			
		||||
               ((id<NSFetchedResultsSectionInfo>)self.fetchedResultsController.sections[section]).numberOfObjects +
 | 
			
		||||
               (!_exactMatch && [[self query] length]? 1: 0);
 | 
			
		||||
 | 
			
		||||
    Throw(@"Unexpected collection view: %@", collectionView);
 | 
			
		||||
    return ![MPiOSAppDelegate get].activeUserOID? 0:
 | 
			
		||||
           ((id<NSFetchedResultsSectionInfo>)self.fetchedResultsController.sections[section]).numberOfObjects +
 | 
			
		||||
           (!_exactMatch && [[self query] length]? 1: 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
 | 
			
		||||
 | 
			
		||||
    if (collectionView == self.passwordCollectionView) {
 | 
			
		||||
        [UIView setAnimationsEnabled:NO];
 | 
			
		||||
        MPPasswordTypesCell *cell;
 | 
			
		||||
        if (indexPath.item < ((id<NSFetchedResultsSectionInfo>)self.fetchedResultsController.sections[indexPath.section]).numberOfObjects) {
 | 
			
		||||
            MPElementEntity *element = [self.fetchedResultsController objectAtIndexPath:indexPath];
 | 
			
		||||
            cell = [MPPasswordTypesCell dequeueCellForElement:element fromCollectionView:collectionView atIndexPath:indexPath];
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            // New Site.
 | 
			
		||||
            cell = [MPPasswordTypesCell dequeueCellForTransientSite:self.query fromCollectionView:collectionView atIndexPath:indexPath];
 | 
			
		||||
        cell.passwordsViewController = self;
 | 
			
		||||
    MPPasswordCell *cell = [MPPasswordCell dequeueCellFromCollectionView:collectionView indexPath:indexPath];
 | 
			
		||||
    if (indexPath.item < ((id<NSFetchedResultsSectionInfo>)self.fetchedResultsController.sections[indexPath.section]).numberOfObjects)
 | 
			
		||||
        [cell setElement:[self.fetchedResultsController objectAtIndexPath:indexPath] animated:NO];
 | 
			
		||||
    else
 | 
			
		||||
        [cell setTransientSite:self.query animated:NO];
 | 
			
		||||
 | 
			
		||||
        [UIView setAnimationsEnabled:YES];
 | 
			
		||||
        return cell;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Throw(@"Unexpected collection view: %@", collectionView);
 | 
			
		||||
    return cell;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind
 | 
			
		||||
@@ -159,15 +137,35 @@ referenceSizeForHeaderInSection:(NSInteger)section {
 | 
			
		||||
    return [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"MPPasswordHeader" forIndexPath:indexPath];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - UIScrollDelegate
 | 
			
		||||
 | 
			
		||||
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
 | 
			
		||||
 | 
			
		||||
    if (scrollView == self.passwordCollectionView)
 | 
			
		||||
        for (MPPasswordCell *cell in [self.passwordCollectionView visibleCells])
 | 
			
		||||
            [cell setMode:MPPasswordCellModePassword animated:YES];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - NSFetchedResultsControllerDelegate
 | 
			
		||||
 | 
			
		||||
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath
 | 
			
		||||
     forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
 | 
			
		||||
 | 
			
		||||
    if (controller == _fetchedResultsController) {
 | 
			
		||||
        [self.passwordCollectionView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section]];
 | 
			
		||||
        if (![newIndexPath isEqual:indexPath])
 | 
			
		||||
            [self.passwordCollectionView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section]];
 | 
			
		||||
        switch (type) {
 | 
			
		||||
            case NSFetchedResultsChangeInsert:
 | 
			
		||||
                [self.passwordCollectionView insertItemsAtIndexPaths:@[ newIndexPath ]];
 | 
			
		||||
                break;
 | 
			
		||||
            case NSFetchedResultsChangeDelete:
 | 
			
		||||
                [self.passwordCollectionView deleteItemsAtIndexPaths:@[ indexPath ]];
 | 
			
		||||
                break;
 | 
			
		||||
            case NSFetchedResultsChangeMove:
 | 
			
		||||
                [self.passwordCollectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath];
 | 
			
		||||
                break;
 | 
			
		||||
            case NSFetchedResultsChangeUpdate:
 | 
			
		||||
                [self.passwordCollectionView reloadItemsAtIndexPaths:@[ indexPath ]];
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -229,7 +227,6 @@ referenceSizeForHeaderInSection:(NSInteger)section {
 | 
			
		||||
        [self updatePasswords];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#pragma mark - Private
 | 
			
		||||
 | 
			
		||||
- (void)registerObservers {
 | 
			
		||||
@@ -237,19 +234,19 @@ referenceSizeForHeaderInSection:(NSInteger)section {
 | 
			
		||||
    if ([_notificationObservers count])
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    Weakify(self);
 | 
			
		||||
    Weakify( self );
 | 
			
		||||
    _notificationObservers = @[
 | 
			
		||||
            [[NSNotificationCenter defaultCenter]
 | 
			
		||||
                    addObserverForName:UIApplicationWillResignActiveNotification object:nil
 | 
			
		||||
                                 queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
 | 
			
		||||
                Strongify(self);
 | 
			
		||||
                Strongify( self );
 | 
			
		||||
 | 
			
		||||
                self.passwordSelectionContainer.alpha = 0;
 | 
			
		||||
            }],
 | 
			
		||||
            [[NSNotificationCenter defaultCenter]
 | 
			
		||||
                    addObserverForName:MPSignedOutNotification object:nil
 | 
			
		||||
                                 queue:nil usingBlock:^(NSNotification *note) {
 | 
			
		||||
                Strongify(self);
 | 
			
		||||
                Strongify( self );
 | 
			
		||||
 | 
			
		||||
                _fetchedResultsController = nil;
 | 
			
		||||
                self.passwordsSearchBar.text = nil;
 | 
			
		||||
@@ -258,7 +255,7 @@ referenceSizeForHeaderInSection:(NSInteger)section {
 | 
			
		||||
            [[NSNotificationCenter defaultCenter]
 | 
			
		||||
                    addObserverForName:UIApplicationDidBecomeActiveNotification object:nil
 | 
			
		||||
                                 queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
 | 
			
		||||
                Strongify(self);
 | 
			
		||||
                Strongify( self );
 | 
			
		||||
 | 
			
		||||
                [self updatePasswords];
 | 
			
		||||
                [UIView animateWithDuration:1 animations:^{
 | 
			
		||||
@@ -282,7 +279,7 @@ referenceSizeForHeaderInSection:(NSInteger)section {
 | 
			
		||||
 | 
			
		||||
- (void)observeStore {
 | 
			
		||||
 | 
			
		||||
    Weakify(self);
 | 
			
		||||
    Weakify( self );
 | 
			
		||||
 | 
			
		||||
    NSManagedObjectContext *mainContext = [MPiOSAppDelegate managedObjectContextForMainThreadIfReady];
 | 
			
		||||
    if (!_mocObserver && mainContext)
 | 
			
		||||
@@ -296,7 +293,7 @@ referenceSizeForHeaderInSection:(NSInteger)section {
 | 
			
		||||
        _storeObserver = [[NSNotificationCenter defaultCenter]
 | 
			
		||||
                addObserverForName:USMStoreDidChangeNotification object:nil
 | 
			
		||||
                             queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
 | 
			
		||||
                    Strongify(self);
 | 
			
		||||
                    Strongify( self );
 | 
			
		||||
                    _fetchedResultsController = nil;
 | 
			
		||||
                    [self updatePasswords];
 | 
			
		||||
                }];
 | 
			
		||||
@@ -312,9 +309,9 @@ referenceSizeForHeaderInSection:(NSInteger)section {
 | 
			
		||||
 | 
			
		||||
- (void)updateConfigKey:(NSString *)key {
 | 
			
		||||
 | 
			
		||||
    if (!key || [key isEqualToString:NSStringFromSelector( @selector(dictationSearch) )])
 | 
			
		||||
    if (!key || [key isEqualToString:NSStringFromSelector( @selector( dictationSearch ) )])
 | 
			
		||||
        self.passwordsSearchBar.keyboardType = [[MPiOSConfig get].dictationSearch boolValue]? UIKeyboardTypeDefault: UIKeyboardTypeURL;
 | 
			
		||||
    if (!key || [key isEqualToString:NSStringFromSelector( @selector(hidePasswords) )])
 | 
			
		||||
    if (!key || [key isEqualToString:NSStringFromSelector( @selector( hidePasswords ) )])
 | 
			
		||||
        [self updatePasswords];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -338,7 +335,7 @@ referenceSizeForHeaderInSection:(NSInteger)section {
 | 
			
		||||
                [NSPredicate predicateWithFormat:@"user == %@ AND name BEGINSWITH[cd] %@", activeUserOID, query]:
 | 
			
		||||
                [NSPredicate predicateWithFormat:@"user == %@", activeUserOID];
 | 
			
		||||
        if (![self.fetchedResultsController performFetch:&error])
 | 
			
		||||
        err(@"Couldn't fetch elements: %@", error);
 | 
			
		||||
            err( @"Couldn't fetch elements: %@", error );
 | 
			
		||||
 | 
			
		||||
        _exactMatch = NO;
 | 
			
		||||
        for (MPElementEntity *entity in self.fetchedResultsController.fetchedObjects)
 | 
			
		||||
@@ -351,17 +348,17 @@ referenceSizeForHeaderInSection:(NSInteger)section {
 | 
			
		||||
            [self.passwordCollectionView performBatchUpdates:^{
 | 
			
		||||
                NSInteger fromSections = self.passwordCollectionView.numberOfSections;
 | 
			
		||||
                NSInteger toSections = [self numberOfSectionsInCollectionView:self.passwordCollectionView];
 | 
			
		||||
                for (int section = 0; section < MAX(toSections, fromSections); section++) {
 | 
			
		||||
                for (int section = 0; section < MAX( toSections, fromSections ); section++) {
 | 
			
		||||
                    if (section >= fromSections) {
 | 
			
		||||
                        dbg(@"insertSections:%d", section);
 | 
			
		||||
                        dbg( @"insertSections:%d", section );
 | 
			
		||||
                        [self.passwordCollectionView insertSections:[NSIndexSet indexSetWithIndex:section]];
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (section >= toSections) {
 | 
			
		||||
                        dbg(@"deleteSections:%d", section);
 | 
			
		||||
                        dbg( @"deleteSections:%d", section );
 | 
			
		||||
                        [self.passwordCollectionView deleteSections:[NSIndexSet indexSetWithIndex:section]];
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        dbg(@"reloadSections:%d", section);
 | 
			
		||||
                        dbg( @"reloadSections:%d", section );
 | 
			
		||||
                        [self.passwordCollectionView reloadSections:[NSIndexSet indexSetWithIndex:section]];
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@@ -387,7 +384,7 @@ referenceSizeForHeaderInSection:(NSInteger)section {
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextForMainThreadPerformBlockAndWait:^(NSManagedObjectContext *mainContext) {
 | 
			
		||||
            NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
 | 
			
		||||
            fetchRequest.sortDescriptors = @[
 | 
			
		||||
                    [[NSSortDescriptor alloc] initWithKey:NSStringFromSelector( @selector(lastUsed) ) ascending:NO]
 | 
			
		||||
                    [[NSSortDescriptor alloc] initWithKey:NSStringFromSelector( @selector( lastUsed ) ) ascending:NO]
 | 
			
		||||
            ];
 | 
			
		||||
            fetchRequest.fetchBatchSize = 10;
 | 
			
		||||
            _fetchedResultsController = [[NSFetchedResultsController alloc]
 | 
			
		||||
@@ -405,13 +402,13 @@ referenceSizeForHeaderInSection:(NSInteger)section {
 | 
			
		||||
    [self setActive:active animated:NO completion:nil];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setActive:(BOOL)active animated:(BOOL)animated completion:(void (^)(BOOL finished))completion {
 | 
			
		||||
- (void)setActive:(BOOL)active animated:(BOOL)animated completion:(void ( ^ )(BOOL finished))completion {
 | 
			
		||||
 | 
			
		||||
    _active = active;
 | 
			
		||||
 | 
			
		||||
    [UIView animateWithDuration:animated? 0.4f: 0 animations:^{
 | 
			
		||||
        [self.navigationBarToTopConstraint layoutWithPriority:active? 1: UILayoutPriorityDefaultHigh];
 | 
			
		||||
        [self.passwordsToBottomConstraint layoutWithPriority:active? 1: UILayoutPriorityDefaultHigh];
 | 
			
		||||
        [[self.navigationBarToTopConstraint updatePriority:active? 1: UILayoutPriorityDefaultHigh] layoutIfNeeded];
 | 
			
		||||
        [[self.passwordsToBottomConstraint updatePriority:active? 1: UILayoutPriorityDefaultHigh] layoutIfNeeded];
 | 
			
		||||
    }                completion:completion];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@
 | 
			
		||||
                                                              metrics:nil views:NSDictionaryOfVariableBindings(popdownView)];
 | 
			
		||||
 | 
			
		||||
        [UIView animateWithDuration:0.3f animations:^{
 | 
			
		||||
            [passwordsVC.popdownToTopConstraint layoutWithPriority:1];
 | 
			
		||||
            [[passwordsVC.popdownToTopConstraint updatePriority:1] layoutIfNeeded];
 | 
			
		||||
        } completion:^(BOOL finished) {
 | 
			
		||||
            [popdownVC didMoveToParentViewController:passwordsVC];
 | 
			
		||||
        }];
 | 
			
		||||
@@ -49,7 +49,7 @@
 | 
			
		||||
 | 
			
		||||
        [popdownVC willMoveToParentViewController:nil];
 | 
			
		||||
        [UIView animateWithDuration:0.3f delay:0 options:UIViewAnimationOptionOverrideInheritedDuration animations:^{
 | 
			
		||||
            [passwordsVC.popdownToTopConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
 | 
			
		||||
            [[passwordsVC.popdownToTopConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
 | 
			
		||||
        }                completion:^(BOOL finished) {
 | 
			
		||||
            [popdownVC.view removeFromSuperview];
 | 
			
		||||
            [popdownVC removeFromParentViewController];
 | 
			
		||||
 
 | 
			
		||||
@@ -786,7 +786,7 @@ typedef NS_ENUM(NSUInteger, MPActiveUserState) {
 | 
			
		||||
        // Manage the entry container depending on whether a user is activate or not.
 | 
			
		||||
        switch (activeUserState) {
 | 
			
		||||
            case MPActiveUserStateNone: {
 | 
			
		||||
                self.navigationBarToTopConstraint.priority = UILayoutPriorityDefaultHigh;
 | 
			
		||||
                [[self.navigationBarToTopConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
 | 
			
		||||
                self.avatarCollectionView.scrollEnabled = YES;
 | 
			
		||||
                self.entryContainer.alpha = 0;
 | 
			
		||||
                self.footerContainer.alpha = 1;
 | 
			
		||||
@@ -796,7 +796,7 @@ typedef NS_ENUM(NSUInteger, MPActiveUserState) {
 | 
			
		||||
            case MPActiveUserStateUserName:
 | 
			
		||||
            case MPActiveUserStateMasterPasswordChoice:
 | 
			
		||||
            case MPActiveUserStateMasterPasswordConfirmation: {
 | 
			
		||||
                [self.navigationBarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
 | 
			
		||||
                [[self.navigationBarToTopConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
 | 
			
		||||
                self.avatarCollectionView.scrollEnabled = NO;
 | 
			
		||||
                self.entryContainer.alpha = 1;
 | 
			
		||||
                self.footerContainer.alpha = 1;
 | 
			
		||||
@@ -804,7 +804,7 @@ typedef NS_ENUM(NSUInteger, MPActiveUserState) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MPActiveUserStateMinimized: {
 | 
			
		||||
                [self.navigationBarToTopConstraint layoutWithPriority:1];
 | 
			
		||||
                [[self.navigationBarToTopConstraint updatePriority:1] layoutIfNeeded];
 | 
			
		||||
                self.avatarCollectionView.scrollEnabled = NO;
 | 
			
		||||
                self.entryContainer.alpha = 0;
 | 
			
		||||
                self.footerContainer.alpha = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@
 | 
			
		||||
 | 
			
		||||
    [super viewDidLoad];
 | 
			
		||||
 | 
			
		||||
    [self.view adjustContentInsets];
 | 
			
		||||
    [self.webView.scrollView insetOcclusion];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)viewWillAppear:(BOOL)animated {
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@
 | 
			
		||||
	objects = {
 | 
			
		||||
 | 
			
		||||
/* Begin PBXBuildFile section */
 | 
			
		||||
		93D391C07818F4C2DC1B6956 /* MPPasswordsCoachmarkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D397E3650384498E7E53C4 /* MPPasswordsCoachmarkViewController.m */; };
 | 
			
		||||
		93D391ECBD9BD2C64115B5DD /* PearlSizedTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39156E806BB78E04F78B9 /* PearlSizedTextView.m */; };
 | 
			
		||||
		93D391ED37C9F687FA51EAA1 /* MPEmergencySegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3937712BF1B67623E5764 /* MPEmergencySegue.m */; };
 | 
			
		||||
		93D3922A53E41A54832E90D9 /* PearlOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D390FADEB325D8D54A957D /* PearlOverlay.m */; };
 | 
			
		||||
@@ -19,7 +18,6 @@
 | 
			
		||||
		93D393DB5325820241BA90A7 /* PearlSizedTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39A4759186F6D2D34AA6B /* PearlSizedTextView.h */; };
 | 
			
		||||
		93D394982CBD25D46692DD7C /* MPWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */; };
 | 
			
		||||
		93D394B5036C882B33C71872 /* MPPasswordsSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39E7A12CC352B2825AA66 /* MPPasswordsSegue.m */; };
 | 
			
		||||
		93D394F6D3F6E2553AA0D684 /* MPPasswordLargeStoredCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3947F6BB69CA9A9124A5D /* MPPasswordLargeStoredCell.m */; };
 | 
			
		||||
		93D39536EB550E811CCD04BC /* UIResponder+PearlFirstResponder.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D394482BB07F90E8FD1314 /* UIResponder+PearlFirstResponder.h */; };
 | 
			
		||||
		93D3954E96236384AFA00453 /* UIScrollView+PearlAdjustInsets.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D390FB3110DCCE68E600DC /* UIScrollView+PearlAdjustInsets.m */; };
 | 
			
		||||
		93D3954FCE045A3CC7E804B7 /* MPUsersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399E571F61E50A9BF8FAF /* MPUsersViewController.m */; };
 | 
			
		||||
@@ -31,10 +29,8 @@
 | 
			
		||||
		93D396D8B67DA6522CDBA142 /* MPCoachmarkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */; };
 | 
			
		||||
		93D397952F5635C793C24DF1 /* NSError+PearlFullDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */; };
 | 
			
		||||
		93D3980046016EFD05B35BC5 /* PearlUICollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39B1D8177A86C5B9EDDE3 /* PearlUICollectionView.h */; };
 | 
			
		||||
		93D398BD8B83FEE8BE4EFFFC /* MPPasswordLargeDeleteCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39EFBC4D6BA3C8581865F /* MPPasswordLargeDeleteCell.m */; };
 | 
			
		||||
		93D398ECD7D1A0DEDDADF516 /* MPEmergencyViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39ACBA9F4878B6A1CC33B /* MPEmergencyViewController.m */; };
 | 
			
		||||
		93D399246DC90F50913A1287 /* UIResponder+PearlFirstResponder.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A1DDFA09AE2E14D26DC /* UIResponder+PearlFirstResponder.m */; };
 | 
			
		||||
		93D399278165FD6D950F0025 /* MPPasswordTypesCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39097C0AAE62C1C321BFC /* MPPasswordTypesCell.m */; };
 | 
			
		||||
		93D3992FA1546E01F498F665 /* PearlNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */; };
 | 
			
		||||
		93D399433EA75E50656040CB /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D394077F8FAB8167647187 /* Twitter.framework */; };
 | 
			
		||||
		93D399BBC0A7EC746CB1B19B /* MPLogsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D391943675426839501BB8 /* MPLogsViewController.h */; };
 | 
			
		||||
@@ -45,14 +41,12 @@
 | 
			
		||||
		93D39B8F90F58A5D158DDBA3 /* MPPasswordsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */; };
 | 
			
		||||
		93D39BA1EA3CAAC8A220B4A6 /* MPAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.m */; };
 | 
			
		||||
		93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; };
 | 
			
		||||
		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 */; };
 | 
			
		||||
		93D39F8A9254177891F38705 /* MPSetupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A28369954D147E239BA /* MPSetupViewController.m */; };
 | 
			
		||||
		93D39FA97F4C3F69A75D5A03 /* MPPasswordLargeGeneratedCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3993422E207BF0B21D089 /* MPPasswordLargeGeneratedCell.m */; };
 | 
			
		||||
		DA04E33E14B1E70400ECA4F3 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA04E33D14B1E70400ECA4F3 /* MobileCoreServices.framework */; };
 | 
			
		||||
		DA071BF3190187FE00179766 /* empty@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA071BF1190187FE00179766 /* empty@2x.png */; };
 | 
			
		||||
		DA071BF4190187FE00179766 /* empty.png in Resources */ = {isa = PBXBuildFile; fileRef = DA071BF2190187FE00179766 /* empty.png */; };
 | 
			
		||||
@@ -85,6 +79,8 @@
 | 
			
		||||
		DA250A18195665A100AC23F1 /* UITableView+PearlReloadFromArray.h in Headers */ = {isa = PBXBuildFile; fileRef = DA250A14195665A100AC23F1 /* UITableView+PearlReloadFromArray.h */; };
 | 
			
		||||
		DA250A19195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m in Sources */ = {isa = PBXBuildFile; fileRef = DA250A15195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m */; };
 | 
			
		||||
		DA250A1A195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.h in Headers */ = {isa = PBXBuildFile; fileRef = DA250A16195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.h */; };
 | 
			
		||||
		DA25C5F8197AFFB40046CDCF /* icon_tools.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD384C1711E29700CF925C /* icon_tools.png */; };
 | 
			
		||||
		DA25C5F9197AFFB40046CDCF /* icon_tools@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD384D1711E29700CF925C /* icon_tools@2x.png */; };
 | 
			
		||||
		DA2CA4DD18D28859007798F8 /* NSArray+Pearl.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2CA4D918D28859007798F8 /* NSArray+Pearl.m */; };
 | 
			
		||||
		DA2CA4DE18D28859007798F8 /* NSArray+Pearl.h in Headers */ = {isa = PBXBuildFile; fileRef = DA2CA4DA18D28859007798F8 /* NSArray+Pearl.h */; };
 | 
			
		||||
		DA2CA4DF18D28859007798F8 /* NSTimer+PearlBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2CA4DB18D28859007798F8 /* NSTimer+PearlBlock.m */; };
 | 
			
		||||
@@ -347,10 +343,10 @@
 | 
			
		||||
		DAEB938218AA537D000490CC /* x509_vfy.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB933118AA537D000490CC /* x509_vfy.h */; };
 | 
			
		||||
		DAEB938318AA537D000490CC /* x509v3.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB933218AA537D000490CC /* x509v3.h */; };
 | 
			
		||||
		DAEBC45314F6364500987BF6 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEBC45214F6364500987BF6 /* QuartzCore.framework */; };
 | 
			
		||||
		DAEC85B518E3DD9A007FC0DF /* PearlUIView.m in Sources */ = {isa = PBXBuildFile; fileRef = DAEC85B118E3DD9A007FC0DF /* PearlUIView.m */; };
 | 
			
		||||
		DAEC85B518E3DD9A007FC0DF /* UIView+Touches.m in Sources */ = {isa = PBXBuildFile; fileRef = DAEC85B118E3DD9A007FC0DF /* UIView+Touches.m */; };
 | 
			
		||||
		DAEC85B618E3DD9A007FC0DF /* PearlUINavigationBar.m in Sources */ = {isa = PBXBuildFile; fileRef = DAEC85B218E3DD9A007FC0DF /* PearlUINavigationBar.m */; };
 | 
			
		||||
		DAEC85B718E3DD9A007FC0DF /* PearlUINavigationBar.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEC85B318E3DD9A007FC0DF /* PearlUINavigationBar.h */; };
 | 
			
		||||
		DAEC85B818E3DD9A007FC0DF /* PearlUIView.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEC85B418E3DD9A007FC0DF /* PearlUIView.h */; };
 | 
			
		||||
		DAEC85B818E3DD9A007FC0DF /* UIView+Touches.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEC85B418E3DD9A007FC0DF /* UIView+Touches.h */; };
 | 
			
		||||
		DAF4EF50190A81E400023C90 /* NSManagedObject+Pearl.m in Sources */ = {isa = PBXBuildFile; fileRef = DAF4EF4E190A81E400023C90 /* NSManagedObject+Pearl.m */; };
 | 
			
		||||
		DAF4EF51190A81E400023C90 /* NSManagedObject+Pearl.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF4EF4F190A81E400023C90 /* NSManagedObject+Pearl.h */; };
 | 
			
		||||
		DAFC5656172C573B00CB5CC5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
 | 
			
		||||
@@ -455,11 +451,8 @@
 | 
			
		||||
/* Begin PBXFileReference section */
 | 
			
		||||
		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>"; };
 | 
			
		||||
		93D390FADEB325D8D54A957D /* PearlOverlay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlOverlay.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D390FB3110DCCE68E600DC /* UIScrollView+PearlAdjustInsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+PearlAdjustInsets.m"; sourceTree = "<group>"; };
 | 
			
		||||
		93D390FD93EFCFECB5193DEF /* MPPasswordsCoachmarkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordsCoachmarkViewController.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D391243F64A77798B4D6A4 /* MPPasswordTypesCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordTypesCell.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D3914D7597F9A28DB9D85E /* MPPasswordsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordsViewController.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D39156E806BB78E04F78B9 /* PearlSizedTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlSizedTextView.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppSettingsViewController.m; sourceTree = "<group>"; };
 | 
			
		||||
@@ -468,27 +461,21 @@
 | 
			
		||||
		93D392876BE5C011DE73B43F /* MPPopdownSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPopdownSegue.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D393310223DDB35218467A /* MPCombinedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCombinedViewController.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D3937712BF1B67623E5764 /* MPEmergencySegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPEmergencySegue.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D3937863061C3916AF7AD2 /* MPPasswordLargeCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordLargeCell.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = "<group>"; };
 | 
			
		||||
		93D393BB973253D4BAAC84AA /* PearlEMail.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlEMail.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D394077F8FAB8167647187 /* Twitter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Twitter.framework; path = System/Library/Frameworks/Twitter.framework; sourceTree = SDKROOT; };
 | 
			
		||||
		93D3942A356B639724157982 /* PearlOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlOverlay.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D394482BB07F90E8FD1314 /* UIResponder+PearlFirstResponder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIResponder+PearlFirstResponder.h"; sourceTree = "<group>"; };
 | 
			
		||||
		93D3947F6BB69CA9A9124A5D /* MPPasswordLargeStoredCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordLargeStoredCell.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D3956915634581E737B38C /* PearlNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlNavigationController.m; sourceTree = "<group>"; };
 | 
			
		||||
		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>"; };
 | 
			
		||||
		93D3979190DACEBD1F6AE9F4 /* MPLogsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPLogsViewController.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D397E3650384498E7E53C4 /* MPPasswordsCoachmarkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordsCoachmarkViewController.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlNavigationController.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+PearlFullDescription.h"; sourceTree = "<group>"; };
 | 
			
		||||
		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>"; };
 | 
			
		||||
		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>"; };
 | 
			
		||||
@@ -510,15 +497,12 @@
 | 
			
		||||
		93D39C86E984EC65DA5ACB1D /* MPAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppSettingsViewController.h; 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>"; };
 | 
			
		||||
		93D39D8A953779B35403AF6E /* PearlUICollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlUICollectionView.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D39DA27D768B53C8B1330C /* MPAvatarCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAvatarCell.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D39DE2CB351D4E3789462B /* UIScrollView+PearlAdjustInsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+PearlAdjustInsets.h"; sourceTree = "<group>"; };
 | 
			
		||||
		93D39DEA995041A13DC9CAF7 /* MPPasswordCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordCell.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D39E02F69CACAB61C056F8 /* MPPasswordLargeCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordLargeCell.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D39E7A12CC352B2825AA66 /* MPPasswordsSegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordsSegue.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D39EFBC4D6BA3C8581865F /* MPPasswordLargeDeleteCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordLargeDeleteCell.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D39F556F2F142740A65E59 /* MPWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPWebViewController.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlEMail.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+PearlFullDescription.m"; sourceTree = "<group>"; };
 | 
			
		||||
@@ -1380,10 +1364,10 @@
 | 
			
		||||
		DAEB933118AA537D000490CC /* x509_vfy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x509_vfy.h; sourceTree = "<group>"; };
 | 
			
		||||
		DAEB933218AA537D000490CC /* x509v3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x509v3.h; sourceTree = "<group>"; };
 | 
			
		||||
		DAEBC45214F6364500987BF6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
 | 
			
		||||
		DAEC85B118E3DD9A007FC0DF /* PearlUIView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlUIView.m; sourceTree = "<group>"; };
 | 
			
		||||
		DAEC85B118E3DD9A007FC0DF /* UIView+Touches.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Touches.m"; sourceTree = "<group>"; };
 | 
			
		||||
		DAEC85B218E3DD9A007FC0DF /* PearlUINavigationBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlUINavigationBar.m; sourceTree = "<group>"; };
 | 
			
		||||
		DAEC85B318E3DD9A007FC0DF /* PearlUINavigationBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlUINavigationBar.h; sourceTree = "<group>"; };
 | 
			
		||||
		DAEC85B418E3DD9A007FC0DF /* PearlUIView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlUIView.h; sourceTree = "<group>"; };
 | 
			
		||||
		DAEC85B418E3DD9A007FC0DF /* UIView+Touches.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Touches.h"; sourceTree = "<group>"; };
 | 
			
		||||
		DAF4EF4E190A81E400023C90 /* NSManagedObject+Pearl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+Pearl.m"; sourceTree = "<group>"; };
 | 
			
		||||
		DAF4EF4F190A81E400023C90 /* NSManagedObject+Pearl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+Pearl.h"; sourceTree = "<group>"; };
 | 
			
		||||
		DAFC5655172C573B00CB5CC5 /* libInAppSettingsKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libInAppSettingsKit.a; sourceTree = BUILT_PRODUCTS_DIR; };
 | 
			
		||||
@@ -1614,8 +1598,6 @@
 | 
			
		||||
				DACA22121705DDC5002C6C22 /* External */,
 | 
			
		||||
				DA5BFA47147E415C00F98B1E /* Frameworks */,
 | 
			
		||||
				DA5BFA45147E415C00F98B1E /* Products */,
 | 
			
		||||
				93D3966B527CA47A0A661CE2 /* MPPasswordLargeDeleteCell.h */,
 | 
			
		||||
				93D39EFBC4D6BA3C8581865F /* MPPasswordLargeDeleteCell.m */,
 | 
			
		||||
			);
 | 
			
		||||
			sourceTree = "<group>";
 | 
			
		||||
		};
 | 
			
		||||
@@ -2441,6 +2423,7 @@
 | 
			
		||||
		DABD3BD71711E2DC00CF925C /* iOS */ = {
 | 
			
		||||
			isa = PBXGroup;
 | 
			
		||||
			children = (
 | 
			
		||||
				DA38D6A218CCB5BF009AEB3E /* Storyboard.storyboard */,
 | 
			
		||||
				93D39975CE5AEC99E3F086C7 /* MPPasswordCell.h */,
 | 
			
		||||
				93D39DEA995041A13DC9CAF7 /* MPPasswordCell.m */,
 | 
			
		||||
				93D39ACBA9F4878B6A1CC33B /* MPEmergencyViewController.m */,
 | 
			
		||||
@@ -2469,21 +2452,12 @@
 | 
			
		||||
				93D3914D7597F9A28DB9D85E /* MPPasswordsViewController.h */,
 | 
			
		||||
				93D393310223DDB35218467A /* MPCombinedViewController.m */,
 | 
			
		||||
				93D39CF8ADF4542CDC4CD385 /* MPCombinedViewController.h */,
 | 
			
		||||
				DA38D6A218CCB5BF009AEB3E /* Storyboard.storyboard */,
 | 
			
		||||
				93D39B381350802A194BF332 /* MPAvatarCell.m */,
 | 
			
		||||
				93D39DA27D768B53C8B1330C /* MPAvatarCell.h */,
 | 
			
		||||
				93D3993422E207BF0B21D089 /* MPPasswordLargeGeneratedCell.m */,
 | 
			
		||||
				93D39CE1138FDA4D3D1B847A /* MPPasswordLargeGeneratedCell.h */,
 | 
			
		||||
				93D399E571F61E50A9BF8FAF /* MPUsersViewController.m */,
 | 
			
		||||
				93D3971FE104BB4052484151 /* MPUsersViewController.h */,
 | 
			
		||||
				93D39E02F69CACAB61C056F8 /* MPPasswordLargeCell.h */,
 | 
			
		||||
				93D3937863061C3916AF7AD2 /* MPPasswordLargeCell.m */,
 | 
			
		||||
				93D395BA6B2CFF5F49A4D25F /* MPPasswordLargeStoredCell.h */,
 | 
			
		||||
				93D3947F6BB69CA9A9124A5D /* MPPasswordLargeStoredCell.m */,
 | 
			
		||||
				93D39BAA71DE51B4D8A1286C /* MPCell.m */,
 | 
			
		||||
				93D390519405B76CC6A57C4F /* MPCell.h */,
 | 
			
		||||
				93D39097C0AAE62C1C321BFC /* MPPasswordTypesCell.m */,
 | 
			
		||||
				93D391243F64A77798B4D6A4 /* MPPasswordTypesCell.h */,
 | 
			
		||||
				93D3937712BF1B67623E5764 /* MPEmergencySegue.m */,
 | 
			
		||||
				93D39A41340CF778E00D0E6D /* MPEmergencySegue.h */,
 | 
			
		||||
				93D39E7A12CC352B2825AA66 /* MPPasswordsSegue.m */,
 | 
			
		||||
@@ -2494,8 +2468,6 @@
 | 
			
		||||
				93D39C86E984EC65DA5ACB1D /* MPAppSettingsViewController.h */,
 | 
			
		||||
				93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */,
 | 
			
		||||
				93D3999693660C89A7465F4E /* MPCoachmarkViewController.h */,
 | 
			
		||||
				93D397E3650384498E7E53C4 /* MPPasswordsCoachmarkViewController.m */,
 | 
			
		||||
				93D390FD93EFCFECB5193DEF /* MPPasswordsCoachmarkViewController.h */,
 | 
			
		||||
				93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */,
 | 
			
		||||
				93D39F556F2F142740A65E59 /* MPWebViewController.h */,
 | 
			
		||||
				93D39CC01630D0421205C4C4 /* MPNavigationController.m */,
 | 
			
		||||
@@ -2846,10 +2818,10 @@
 | 
			
		||||
				DA250A14195665A100AC23F1 /* UITableView+PearlReloadFromArray.h */,
 | 
			
		||||
				DA250A15195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m */,
 | 
			
		||||
				DA250A16195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.h */,
 | 
			
		||||
				DAEC85B118E3DD9A007FC0DF /* PearlUIView.m */,
 | 
			
		||||
				DAEC85B118E3DD9A007FC0DF /* UIView+Touches.m */,
 | 
			
		||||
				DAEC85B218E3DD9A007FC0DF /* PearlUINavigationBar.m */,
 | 
			
		||||
				DAEC85B318E3DD9A007FC0DF /* PearlUINavigationBar.h */,
 | 
			
		||||
				DAEC85B418E3DD9A007FC0DF /* PearlUIView.h */,
 | 
			
		||||
				DAEC85B418E3DD9A007FC0DF /* UIView+Touches.h */,
 | 
			
		||||
				DA2CA4E518D2AC10007798F8 /* NSLayoutConstraint+PearlUIKit.m */,
 | 
			
		||||
				DA2CA4E218D28866007798F8 /* NSLayoutConstraint+PearlUIKit.h */,
 | 
			
		||||
				93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */,
 | 
			
		||||
@@ -3016,7 +2988,7 @@
 | 
			
		||||
				DAEB933C18AA537D000490CC /* aes.h in Headers */,
 | 
			
		||||
				DAEB937618AA537D000490CC /* ssl2.h in Headers */,
 | 
			
		||||
				DAFE4A3C15039824003ABA7C /* Pearl-UIKit-Dependencies.h in Headers */,
 | 
			
		||||
				DAEC85B818E3DD9A007FC0DF /* PearlUIView.h in Headers */,
 | 
			
		||||
				DAEC85B818E3DD9A007FC0DF /* UIView+Touches.h in Headers */,
 | 
			
		||||
				DAEB935B18AA537D000490CC /* krb5_asn.h in Headers */,
 | 
			
		||||
				DAEB935818AA537D000490CC /* evp.h in Headers */,
 | 
			
		||||
				DAEB934118AA537D000490CC /* blowfish.h in Headers */,
 | 
			
		||||
@@ -3452,6 +3424,7 @@
 | 
			
		||||
				DABD3B8D1711E29800CF925C /* keypad.png in Resources */,
 | 
			
		||||
				DABD3B8E1711E29800CF925C /* logo-bare.png in Resources */,
 | 
			
		||||
				DA7304E6194E025900E72520 /* tip_basic_black@2x.png in Resources */,
 | 
			
		||||
				DA25C5F9197AFFB40046CDCF /* icon_tools@2x.png in Resources */,
 | 
			
		||||
				DABD3B8F1711E29800CF925C /* menu-icon.png in Resources */,
 | 
			
		||||
				DABD3B901711E29800CF925C /* menu-icon@2x.png in Resources */,
 | 
			
		||||
				DABD3B951711E29800CF925C /* pull-down.png in Resources */,
 | 
			
		||||
@@ -3466,6 +3439,7 @@
 | 
			
		||||
				DABD3C241711E2DC00CF925C /* MasterPassword.entitlements in Resources */,
 | 
			
		||||
				DABD3C251711E2DC00CF925C /* Settings.bundle in Resources */,
 | 
			
		||||
				DABD3C261711E2DC00CF925C /* InfoPlist.strings in Resources */,
 | 
			
		||||
				DA25C5F8197AFFB40046CDCF /* icon_tools.png in Resources */,
 | 
			
		||||
				DA2509FB1956484D00AC23F1 /* image-11@2x.png in Resources */,
 | 
			
		||||
				DA250A0B1956484D00AC23F1 /* image-3@2x.png in Resources */,
 | 
			
		||||
				DABD3FCA1712446200CF925C /* cloud.png in Resources */,
 | 
			
		||||
@@ -3560,11 +3534,7 @@
 | 
			
		||||
				93D3957237D303DE2D38C267 /* MPAvatarCell.m in Sources */,
 | 
			
		||||
				93D39B8F90F58A5D158DDBA3 /* MPPasswordsViewController.m in Sources */,
 | 
			
		||||
				93D3954FCE045A3CC7E804B7 /* MPUsersViewController.m in Sources */,
 | 
			
		||||
				93D39CB5E2EC1078E898F46A /* MPPasswordLargeCell.m in Sources */,
 | 
			
		||||
				93D39FA97F4C3F69A75D5A03 /* MPPasswordLargeGeneratedCell.m in Sources */,
 | 
			
		||||
				93D394F6D3F6E2553AA0D684 /* MPPasswordLargeStoredCell.m in Sources */,
 | 
			
		||||
				93D39392DEDA376F93C6C718 /* MPCell.m in Sources */,
 | 
			
		||||
				93D399278165FD6D950F0025 /* MPPasswordTypesCell.m in Sources */,
 | 
			
		||||
				93D39A5FF670957C0AF8298D /* MPPasswordCell.m in Sources */,
 | 
			
		||||
				93D398ECD7D1A0DEDDADF516 /* MPEmergencyViewController.m in Sources */,
 | 
			
		||||
				93D391ED37C9F687FA51EAA1 /* MPEmergencySegue.m in Sources */,
 | 
			
		||||
@@ -3572,10 +3542,8 @@
 | 
			
		||||
				93D39673DDC085BE72C34D7C /* MPPopdownSegue.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;
 | 
			
		||||
@@ -3643,7 +3611,7 @@
 | 
			
		||||
				DA30E9D815723E6900A68B4C /* PearlLazy.m in Sources */,
 | 
			
		||||
				DAFE4A63150399FF003ABA82 /* UIControl+PearlBlocks.m in Sources */,
 | 
			
		||||
				DAFE4A63150399FF003ABA86 /* NSObject+PearlKVO.m in Sources */,
 | 
			
		||||
				DAEC85B518E3DD9A007FC0DF /* PearlUIView.m in Sources */,
 | 
			
		||||
				DAEC85B518E3DD9A007FC0DF /* UIView+Touches.m in Sources */,
 | 
			
		||||
				DA2CA4DD18D28859007798F8 /* NSArray+Pearl.m in Sources */,
 | 
			
		||||
				DAFE4A63150399FF003ABA8A /* UIControl+PearlSelect.m in Sources */,
 | 
			
		||||
				DAFE4A63150399FF003ABA8E /* UIScrollView+PearlFlashingIndicators.m in Sources */,
 | 
			
		||||
@@ -3931,7 +3899,7 @@
 | 
			
		||||
					Reveal,
 | 
			
		||||
				);
 | 
			
		||||
				PROVISIONING_PROFILE = "";
 | 
			
		||||
				"PROVISIONING_PROFILE[sdk=iphoneos*]" = "1F49F193-0915-40B1-8792-BBDE74185E45";
 | 
			
		||||
				"PROVISIONING_PROFILE[sdk=iphoneos*]" = "94333D7F-68F7-473D-B3B1-86AA41F33449";
 | 
			
		||||
				SKIP_INSTALL = NO;
 | 
			
		||||
				TARGETED_DEVICE_FAMILY = 1;
 | 
			
		||||
			};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="5056" systemVersion="13D65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="Q1S-vU-GGO">
 | 
			
		||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="5056" systemVersion="13E28" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="Q1S-vU-GGO">
 | 
			
		||||
    <dependencies>
 | 
			
		||||
        <deployment defaultVersion="1792" identifier="iOS"/>
 | 
			
		||||
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3733"/>
 | 
			
		||||
@@ -150,7 +150,7 @@
 | 
			
		||||
                                            <action selector="changeAvatar:" destination="S8q-YF-Kt9" eventType="touchUpInside" id="kL5-zV-zbb"/>
 | 
			
		||||
                                        </connections>
 | 
			
		||||
                                    </button>
 | 
			
		||||
                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qp1-nX-o4i" userLabel="Entry" customClass="PearlUIView">
 | 
			
		||||
                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qp1-nX-o4i" userLabel="Entry" customClass="UIView+Touches">
 | 
			
		||||
                                        <rect key="frame" x="20" y="255" width="280" height="68"/>
 | 
			
		||||
                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                        <subviews>
 | 
			
		||||
@@ -236,7 +236,7 @@
 | 
			
		||||
                                            <userDefinedRuntimeAttribute type="boolean" keyPath="ignoreTouches" value="YES"/>
 | 
			
		||||
                                        </userDefinedRuntimeAttributes>
 | 
			
		||||
                                    </view>
 | 
			
		||||
                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XEP-O3-ayG" userLabel="Footer" customClass="PearlUIView">
 | 
			
		||||
                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XEP-O3-ayG" userLabel="Footer" customClass="UIView+Touches">
 | 
			
		||||
                                        <rect key="frame" x="0.0" y="477" width="320" height="71"/>
 | 
			
		||||
                                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                        <subviews>
 | 
			
		||||
@@ -980,11 +980,11 @@
 | 
			
		||||
                        <viewControllerLayoutGuide type="top" id="S9X-2T-e1e"/>
 | 
			
		||||
                        <viewControllerLayoutGuide type="bottom" id="c12-XI-Rv9"/>
 | 
			
		||||
                    </layoutGuides>
 | 
			
		||||
                    <view key="view" contentMode="scaleToFill" id="MSX-uI-cwS" userLabel="Root" customClass="PearlUIView">
 | 
			
		||||
                    <view key="view" contentMode="scaleToFill" id="MSX-uI-cwS" userLabel="Root" customClass="UIView+Touches">
 | 
			
		||||
                        <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
 | 
			
		||||
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                        <subviews>
 | 
			
		||||
                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tI8-OT-LrO" userLabel="Passwords Root" customClass="PearlUIView">
 | 
			
		||||
                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tI8-OT-LrO" userLabel="Passwords Root" customClass="UIView+Touches">
 | 
			
		||||
                                <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
 | 
			
		||||
                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                <subviews>
 | 
			
		||||
@@ -1004,371 +1004,322 @@
 | 
			
		||||
                                                    <inset key="sectionInset" minX="10" minY="10" maxX="10" maxY="10"/>
 | 
			
		||||
                                                </collectionViewFlowLayout>
 | 
			
		||||
                                                <cells>
 | 
			
		||||
                                                    <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MPPasswordTypesCell" id="vMF-fk-FYX" userLabel="Large" customClass="MPPasswordTypesCell">
 | 
			
		||||
                                                    <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MPPasswordCell" id="W2g-yv-V3V" customClass="MPPasswordCell">
 | 
			
		||||
                                                        <rect key="frame" x="10" y="118" width="300" height="100"/>
 | 
			
		||||
                                                        <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                                        <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
 | 
			
		||||
                                                            <rect key="frame" x="0.0" y="0.0" width="300" height="100"/>
 | 
			
		||||
                                                            <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                                            <subviews>
 | 
			
		||||
                                                                <collectionView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" minimumZoomScale="0.0" maximumZoomScale="0.0" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="7vV-gu-BNS" userLabel="Type Collection">
 | 
			
		||||
                                                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xph-TW-9QO" userLabel="Content">
 | 
			
		||||
                                                                    <rect key="frame" x="0.0" y="0.0" width="300" height="100"/>
 | 
			
		||||
                                                                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
 | 
			
		||||
                                                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                    <collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="ap6-LM-04C">
 | 
			
		||||
                                                                        <size key="itemSize" width="300" height="100"/>
 | 
			
		||||
                                                                        <size key="headerReferenceSize" width="0.0" height="0.0"/>
 | 
			
		||||
                                                                        <size key="footerReferenceSize" width="0.0" height="0.0"/>
 | 
			
		||||
                                                                        <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
 | 
			
		||||
                                                                    </collectionViewFlowLayout>
 | 
			
		||||
                                                                    <cells>
 | 
			
		||||
                                                                        <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MPPasswordLargeDeleteCell" id="GAB-fT-EFv" userLabel="Delete" customClass="MPPasswordLargeDeleteCell">
 | 
			
		||||
                                                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                    <subviews>
 | 
			
		||||
                                                                        <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" directionalLockEnabled="YES" pagingEnabled="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bff-RU-OcY">
 | 
			
		||||
                                                                            <rect key="frame" x="0.0" y="0.0" width="300" height="100"/>
 | 
			
		||||
                                                                            <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                                                            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
 | 
			
		||||
                                                                                <rect key="frame" x="0.0" y="0.0" width="300" height="100"/>
 | 
			
		||||
                                                                                <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                                                                <subviews>
 | 
			
		||||
                                                                                    <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.029999999999999999" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Delete" lineBreakMode="clip" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AAG-mH-nNg" userLabel="Type">
 | 
			
		||||
                                                                                        <rect key="frame" x="-10" y="19" width="261" height="101"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="84"/>
 | 
			
		||||
                                                                                        <color key="textColor" cocoaTouchSystemColor="lightTextColor"/>
 | 
			
		||||
                                                                                        <nil key="highlightedColor"/>
 | 
			
		||||
                                                                                    </label>
 | 
			
		||||
                                                                                    <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Delete Site" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="y9p-dE-unH" userLabel="Delete">
 | 
			
		||||
                                                                                        <rect key="frame" x="8" y="20" width="284" height="31"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="24"/>
 | 
			
		||||
                                                                                        <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        <nil key="highlightedColor"/>
 | 
			
		||||
                                                                                    </label>
 | 
			
		||||
                                                                                    <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.5" contentMode="left" text="apple.com" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="VNc-fL-Vfa" userLabel="Site Name">
 | 
			
		||||
                                                                                        <rect key="frame" x="8" y="71" width="284" height="14"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <accessibility key="accessibilityConfiguration" label="">
 | 
			
		||||
                                                                                            <accessibilityTraits key="traits" none="YES" staticText="YES" summaryElement="YES"/>
 | 
			
		||||
                                                                                        </accessibility>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" name="Copperplate" family="Copperplate" pointSize="12"/>
 | 
			
		||||
                                                                                        <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        <nil key="highlightedColor"/>
 | 
			
		||||
                                                                                        <color key="shadowColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        <size key="shadowOffset" width="0.0" height="1"/>
 | 
			
		||||
                                                                                    </label>
 | 
			
		||||
                                                                                </subviews>
 | 
			
		||||
                                                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                            </view>
 | 
			
		||||
                                                                            <color key="backgroundColor" red="0.50196081399917603" green="0.0" blue="0.0" alpha="0.5" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
 | 
			
		||||
                                                                            <subviews>
 | 
			
		||||
                                                                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aDw-qY-VjU">
 | 
			
		||||
                                                                                    <rect key="frame" x="0.0" y="0.0" width="300" height="100"/>
 | 
			
		||||
                                                                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                    <color key="backgroundColor" red="0.18431372549019609" green="0.15686274509803921" blue="0.15686274509803921" alpha="0.5" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                    <connections>
 | 
			
		||||
                                                                                        <action selector="doUse:" destination="W2g-yv-V3V" eventType="touchUpInside" id="ukg-D8-8O3"/>
 | 
			
		||||
                                                                                    </connections>
 | 
			
		||||
                                                                                </button>
 | 
			
		||||
                                                                                <view contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tl3-hd-x35" userLabel="Main">
 | 
			
		||||
                                                                                    <rect key="frame" x="300" y="0.0" width="300" height="99"/>
 | 
			
		||||
                                                                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                    <subviews>
 | 
			
		||||
                                                                                        <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="CuzaSasy3*Rimo" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="blw-Ou-8I8" userLabel="Password">
 | 
			
		||||
                                                                                            <rect key="frame" x="8" y="20" width="284" height="31"/>
 | 
			
		||||
                                                                                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                            <color key="textColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                            <fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="24"/>
 | 
			
		||||
                                                                                            <textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="alphabet" keyboardAppearance="alert" returnKeyType="done"/>
 | 
			
		||||
                                                                                            <connections>
 | 
			
		||||
                                                                                                <outlet property="delegate" destination="W2g-yv-V3V" id="YKp-IE-zEQ"/>
 | 
			
		||||
                                                                                            </connections>
 | 
			
		||||
                                                                                        </textField>
 | 
			
		||||
                                                                                        <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.5" contentMode="left" text="apple.com - long" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="OwP-sb-Wxl" userLabel="Site Name">
 | 
			
		||||
                                                                                            <rect key="frame" x="8" y="71" width="101" height="14"/>
 | 
			
		||||
                                                                                            <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                            <accessibility key="accessibilityConfiguration" label="">
 | 
			
		||||
                                                                                                <accessibilityTraits key="traits" none="YES" staticText="YES" summaryElement="YES"/>
 | 
			
		||||
                                                                                            </accessibility>
 | 
			
		||||
                                                                                            <fontDescription key="fontDescription" name="Copperplate" family="Copperplate" pointSize="12"/>
 | 
			
		||||
                                                                                            <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            <nil key="highlightedColor"/>
 | 
			
		||||
                                                                                            <color key="shadowColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            <size key="shadowOffset" width="0.0" height="1"/>
 | 
			
		||||
                                                                                        </label>
 | 
			
		||||
                                                                                        <button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Agd-0J-z5o" userLabel="Edit">
 | 
			
		||||
                                                                                            <rect key="frame" x="212" y="56" width="44" height="44"/>
 | 
			
		||||
                                                                                            <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                            <accessibility key="accessibilityConfiguration" hint="Edits the password."/>
 | 
			
		||||
                                                                                            <constraints>
 | 
			
		||||
                                                                                                <constraint firstAttribute="height" constant="44" id="6Pa-21-Lwi"/>
 | 
			
		||||
                                                                                                <constraint firstAttribute="width" constant="44" id="WTe-56-pc7"/>
 | 
			
		||||
                                                                                            </constraints>
 | 
			
		||||
                                                                                            <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
 | 
			
		||||
                                                                                            <inset key="contentEdgeInsets" minX="6" minY="6" maxX="6" maxY="6"/>
 | 
			
		||||
                                                                                            <state key="normal" image="icon_edit.png">
 | 
			
		||||
                                                                                                <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                                <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            </state>
 | 
			
		||||
                                                                                            <state key="highlighted">
 | 
			
		||||
                                                                                                <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            </state>
 | 
			
		||||
                                                                                            <connections>
 | 
			
		||||
                                                                                                <action selector="doEditPassword:" destination="W2g-yv-V3V" eventType="touchUpInside" id="CbH-c0-CJe"/>
 | 
			
		||||
                                                                                            </connections>
 | 
			
		||||
                                                                                        </button>
 | 
			
		||||
                                                                                    </subviews>
 | 
			
		||||
                                                                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                    <constraints>
 | 
			
		||||
                                                                                        <constraint firstAttribute="trailing" secondItem="Agd-0J-z5o" secondAttribute="trailing" constant="44" id="3Pc-mp-S6g"/>
 | 
			
		||||
                                                                                        <constraint firstItem="blw-Ou-8I8" firstAttribute="leading" secondItem="tl3-hd-x35" secondAttribute="leading" constant="8" id="UOV-qi-uhp"/>
 | 
			
		||||
                                                                                        <constraint firstItem="OwP-sb-Wxl" firstAttribute="leading" secondItem="tl3-hd-x35" secondAttribute="leading" constant="8" id="ec1-f1-mud"/>
 | 
			
		||||
                                                                                        <constraint firstItem="blw-Ou-8I8" firstAttribute="top" secondItem="tl3-hd-x35" secondAttribute="top" constant="20" symbolic="YES" id="lZT-Io-VJ2"/>
 | 
			
		||||
                                                                                        <constraint firstAttribute="trailing" secondItem="blw-Ou-8I8" secondAttribute="trailing" constant="8" id="qdj-gW-OpE"/>
 | 
			
		||||
                                                                                    </constraints>
 | 
			
		||||
                                                                                    <userDefinedRuntimeAttributes>
 | 
			
		||||
                                                                                        <userDefinedRuntimeAttribute type="boolean" keyPath="ignoreTouches" value="YES"/>
 | 
			
		||||
                                                                                    </userDefinedRuntimeAttributes>
 | 
			
		||||
                                                                                </view>
 | 
			
		||||
                                                                                <view contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LvK-28-fbm" userLabel="Settings">
 | 
			
		||||
                                                                                    <rect key="frame" x="0.0" y="0.0" width="300" height="99"/>
 | 
			
		||||
                                                                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                    <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="wfM-xz-roR" userLabel="Label">
 | 
			
		||||
                                                                                            <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>
 | 
			
		||||
                                                                                        <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="lhunath" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Bw8-sw-ZIS" userLabel="User Name">
 | 
			
		||||
                                                                                            <rect key="frame" x="8" y="20" width="284" height="31"/>
 | 
			
		||||
                                                                                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                            <color key="textColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                            <fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="24"/>
 | 
			
		||||
                                                                                            <textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="emailAddress" keyboardAppearance="alert" returnKeyType="done"/>
 | 
			
		||||
                                                                                            <connections>
 | 
			
		||||
                                                                                                <outlet property="delegate" destination="W2g-yv-V3V" id="iaV-Ff-u7e"/>
 | 
			
		||||
                                                                                            </connections>
 | 
			
		||||
                                                                                        </textField>
 | 
			
		||||
                                                                                        <button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vGk-t6-hZn" userLabel="Upgrade">
 | 
			
		||||
                                                                                            <rect key="frame" x="69" y="56" width="44" height="44"/>
 | 
			
		||||
                                                                                            <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                            <accessibility key="accessibilityConfiguration" hint="Upgrades the password."/>
 | 
			
		||||
                                                                                            <constraints>
 | 
			
		||||
                                                                                                <constraint firstAttribute="width" constant="44" id="8gK-8v-Q0K"/>
 | 
			
		||||
                                                                                                <constraint firstAttribute="height" constant="44" id="hQh-jZ-41x"/>
 | 
			
		||||
                                                                                            </constraints>
 | 
			
		||||
                                                                                            <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
 | 
			
		||||
                                                                                            <inset key="contentEdgeInsets" minX="6" minY="6" maxX="6" maxY="6"/>
 | 
			
		||||
                                                                                            <state key="normal" image="icon_up.png">
 | 
			
		||||
                                                                                                <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                                <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            </state>
 | 
			
		||||
                                                                                            <state key="highlighted">
 | 
			
		||||
                                                                                                <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            </state>
 | 
			
		||||
                                                                                            <connections>
 | 
			
		||||
                                                                                                <action selector="doUpgrade:" destination="W2g-yv-V3V" eventType="touchUpInside" id="H3Y-gA-0MY"/>
 | 
			
		||||
                                                                                            </connections>
 | 
			
		||||
                                                                                        </button>
 | 
			
		||||
                                                                                        <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.5" contentMode="left" text="1" textAlignment="right" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="PKP-M9-T8E" userLabel="Counter">
 | 
			
		||||
                                                                                            <rect key="frame" x="113" y="69" width="11" height="19"/>
 | 
			
		||||
                                                                                            <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                            <accessibility key="accessibilityConfiguration" hint="Site's counter."/>
 | 
			
		||||
                                                                                            <fontDescription key="fontDescription" name="Copperplate-Bold" family="Copperplate" pointSize="17"/>
 | 
			
		||||
                                                                                            <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            <nil key="highlightedColor"/>
 | 
			
		||||
                                                                                            <color key="shadowColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            <size key="shadowOffset" width="0.0" height="1"/>
 | 
			
		||||
                                                                                        </label>
 | 
			
		||||
                                                                                        <button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="uZi-FT-Fe8" userLabel="Incrementer">
 | 
			
		||||
                                                                                            <rect key="frame" x="124" y="56" width="44" height="44"/>
 | 
			
		||||
                                                                                            <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                            <accessibility key="accessibilityConfiguration" hint="Increments the site counter."/>
 | 
			
		||||
                                                                                            <gestureRecognizers/>
 | 
			
		||||
                                                                                            <constraints>
 | 
			
		||||
                                                                                                <constraint firstAttribute="width" constant="44" id="DWo-8r-QIJ"/>
 | 
			
		||||
                                                                                                <constraint firstAttribute="height" constant="44" id="GQS-qz-ufK"/>
 | 
			
		||||
                                                                                            </constraints>
 | 
			
		||||
                                                                                            <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
 | 
			
		||||
                                                                                            <inset key="contentEdgeInsets" minX="6" minY="6" maxX="6" maxY="6"/>
 | 
			
		||||
                                                                                            <state key="normal" image="icon_plus.png">
 | 
			
		||||
                                                                                                <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                                <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            </state>
 | 
			
		||||
                                                                                            <state key="highlighted">
 | 
			
		||||
                                                                                                <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            </state>
 | 
			
		||||
                                                                                            <connections>
 | 
			
		||||
                                                                                                <action selector="doIncrementCounter:" destination="W2g-yv-V3V" eventType="touchUpInside" id="eos-wE-4xq"/>
 | 
			
		||||
                                                                                            </connections>
 | 
			
		||||
                                                                                        </button>
 | 
			
		||||
                                                                                        <button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qBo-Kw-vN9" userLabel="Edit">
 | 
			
		||||
                                                                                            <rect key="frame" x="168" y="56" width="44" height="44"/>
 | 
			
		||||
                                                                                            <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                            <accessibility key="accessibilityConfiguration" hint="Edits the password."/>
 | 
			
		||||
                                                                                            <constraints>
 | 
			
		||||
                                                                                                <constraint firstAttribute="width" constant="44" id="j1z-K8-OXJ"/>
 | 
			
		||||
                                                                                                <constraint firstAttribute="height" constant="44" id="mEK-dW-ATd"/>
 | 
			
		||||
                                                                                            </constraints>
 | 
			
		||||
                                                                                            <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
 | 
			
		||||
                                                                                            <inset key="contentEdgeInsets" minX="6" minY="6" maxX="6" maxY="6"/>
 | 
			
		||||
                                                                                            <state key="normal" image="icon_edit.png">
 | 
			
		||||
                                                                                                <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                                <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            </state>
 | 
			
		||||
                                                                                            <state key="highlighted">
 | 
			
		||||
                                                                                                <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            </state>
 | 
			
		||||
                                                                                            <connections>
 | 
			
		||||
                                                                                                <action selector="doEditLoginName:" destination="W2g-yv-V3V" eventType="touchUpInside" id="iDD-3T-sqw"/>
 | 
			
		||||
                                                                                            </connections>
 | 
			
		||||
                                                                                        </button>
 | 
			
		||||
                                                                                        <button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="K8q-bM-tzh" userLabel="Type">
 | 
			
		||||
                                                                                            <rect key="frame" x="212" y="56" width="44" height="44"/>
 | 
			
		||||
                                                                                            <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                            <accessibility key="accessibilityConfiguration" hint="Edits the password."/>
 | 
			
		||||
                                                                                            <constraints>
 | 
			
		||||
                                                                                                <constraint firstAttribute="height" constant="44" id="K3c-Ok-krB"/>
 | 
			
		||||
                                                                                                <constraint firstAttribute="width" constant="44" id="wtJ-zb-FNx"/>
 | 
			
		||||
                                                                                            </constraints>
 | 
			
		||||
                                                                                            <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
 | 
			
		||||
                                                                                            <inset key="contentEdgeInsets" minX="6" minY="6" maxX="6" maxY="6"/>
 | 
			
		||||
                                                                                            <state key="normal" image="icon_list-names.png">
 | 
			
		||||
                                                                                                <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                                <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            </state>
 | 
			
		||||
                                                                                            <state key="highlighted">
 | 
			
		||||
                                                                                                <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                            </state>
 | 
			
		||||
                                                                                            <connections>
 | 
			
		||||
                                                                                                <action selector="doEditPassword:" destination="W2g-yv-V3V" eventType="touchUpInside" id="nPc-7S-Qr1"/>
 | 
			
		||||
                                                                                            </connections>
 | 
			
		||||
                                                                                        </button>
 | 
			
		||||
                                                                                    </subviews>
 | 
			
		||||
                                                                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                    <constraints>
 | 
			
		||||
                                                                                        <constraint firstItem="PKP-M9-T8E" firstAttribute="leading" secondItem="vGk-t6-hZn" secondAttribute="trailing" id="47y-gh-Ibs"/>
 | 
			
		||||
                                                                                        <constraint firstItem="wfM-xz-roR" firstAttribute="leading" secondItem="LvK-28-fbm" secondAttribute="leading" id="GrJ-MG-y1D"/>
 | 
			
		||||
                                                                                        <constraint firstItem="K8q-bM-tzh" firstAttribute="leading" secondItem="qBo-Kw-vN9" secondAttribute="trailing" id="IUs-a2-ccB"/>
 | 
			
		||||
                                                                                        <constraint firstItem="PKP-M9-T8E" firstAttribute="centerY" secondItem="uZi-FT-Fe8" secondAttribute="centerY" id="KEK-0r-cob"/>
 | 
			
		||||
                                                                                        <constraint firstItem="qBo-Kw-vN9" firstAttribute="leading" secondItem="uZi-FT-Fe8" secondAttribute="trailing" id="LLk-5B-1g9"/>
 | 
			
		||||
                                                                                        <constraint firstItem="Bw8-sw-ZIS" firstAttribute="leading" secondItem="LvK-28-fbm" secondAttribute="leading" constant="8" id="Rah-90-SEi"/>
 | 
			
		||||
                                                                                        <constraint firstItem="wfM-xz-roR" firstAttribute="top" secondItem="LvK-28-fbm" secondAttribute="top" id="aN2-fg-SRb"/>
 | 
			
		||||
                                                                                        <constraint firstAttribute="trailing" secondItem="wfM-xz-roR" secondAttribute="trailing" id="dhP-Oa-Xqk"/>
 | 
			
		||||
                                                                                        <constraint firstAttribute="trailing" secondItem="Bw8-sw-ZIS" secondAttribute="trailing" constant="8" id="gpv-Lv-mpk"/>
 | 
			
		||||
                                                                                        <constraint firstItem="Bw8-sw-ZIS" firstAttribute="top" secondItem="LvK-28-fbm" secondAttribute="top" constant="20" symbolic="YES" id="j6A-PP-KjZ"/>
 | 
			
		||||
                                                                                        <constraint firstAttribute="trailing" secondItem="K8q-bM-tzh" secondAttribute="trailing" constant="44" id="qQK-ts-seh"/>
 | 
			
		||||
                                                                                        <constraint firstItem="uZi-FT-Fe8" firstAttribute="leading" secondItem="PKP-M9-T8E" secondAttribute="trailing" id="xFJ-GZ-jp9"/>
 | 
			
		||||
                                                                                    </constraints>
 | 
			
		||||
                                                                                    <userDefinedRuntimeAttributes>
 | 
			
		||||
                                                                                        <userDefinedRuntimeAttribute type="boolean" keyPath="ignoreTouches" value="YES"/>
 | 
			
		||||
                                                                                    </userDefinedRuntimeAttributes>
 | 
			
		||||
                                                                                </view>
 | 
			
		||||
                                                                                <button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="b5f-wN-2xb" userLabel="Mode">
 | 
			
		||||
                                                                                    <rect key="frame" x="256" y="56" width="44" height="44"/>
 | 
			
		||||
                                                                                    <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                    <accessibility key="accessibilityConfiguration" hint="Upgrades the password."/>
 | 
			
		||||
                                                                                    <constraints>
 | 
			
		||||
                                                                                        <constraint firstAttribute="width" constant="44" id="I1C-Ok-DUv"/>
 | 
			
		||||
                                                                                        <constraint firstAttribute="height" constant="44" id="ZU3-Sg-was"/>
 | 
			
		||||
                                                                                    </constraints>
 | 
			
		||||
                                                                                    <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
 | 
			
		||||
                                                                                    <inset key="contentEdgeInsets" minX="6" minY="6" maxX="6" maxY="6"/>
 | 
			
		||||
                                                                                    <state key="normal" image="icon_tools.png">
 | 
			
		||||
                                                                                        <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                        <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                    </state>
 | 
			
		||||
                                                                                    <state key="selected" image="icon_key.png"/>
 | 
			
		||||
                                                                                    <state key="highlighted">
 | 
			
		||||
                                                                                        <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                    </state>
 | 
			
		||||
                                                                                    <connections>
 | 
			
		||||
                                                                                        <action selector="doMode:" destination="W2g-yv-V3V" eventType="touchUpInside" id="72U-sh-nce"/>
 | 
			
		||||
                                                                                    </connections>
 | 
			
		||||
                                                                                </button>
 | 
			
		||||
                                                                                <pageControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" numberOfPages="2" translatesAutoresizingMaskIntoConstraints="NO" id="5SS-x0-icl">
 | 
			
		||||
                                                                                    <rect key="frame" x="138" y="77.5" width="23" height="37"/>
 | 
			
		||||
                                                                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                    <color key="currentPageIndicatorTintColor" red="0.37254901959999998" green="0.3921568627" blue="0.42745098040000001" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                </pageControl>
 | 
			
		||||
                                                                            </subviews>
 | 
			
		||||
                                                                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                            <constraints>
 | 
			
		||||
                                                                                <constraint firstItem="y9p-dE-unH" firstAttribute="leading" secondItem="GAB-fT-EFv" secondAttribute="leading" constant="8" id="1pO-PG-Rci"/>
 | 
			
		||||
                                                                                <constraint firstItem="AAG-mH-nNg" firstAttribute="leading" secondItem="GAB-fT-EFv" secondAttribute="leading" constant="-10" id="4XF-xn-KAY"/>
 | 
			
		||||
                                                                                <constraint firstItem="y9p-dE-unH" firstAttribute="top" secondItem="GAB-fT-EFv" secondAttribute="top" constant="20" id="6Nq-f6-G38"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="bottom" secondItem="VNc-fL-Vfa" secondAttribute="bottom" constant="15" id="6kW-B3-DMz"/>
 | 
			
		||||
                                                                                <constraint firstItem="VNc-fL-Vfa" firstAttribute="leading" secondItem="GAB-fT-EFv" secondAttribute="leading" constant="8" id="6xg-dp-fSn"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="trailing" secondItem="y9p-dE-unH" secondAttribute="trailing" constant="8" id="CCh-3r-ImT"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="bottom" secondItem="AAG-mH-nNg" secondAttribute="bottom" constant="-20" id="btx-g1-Jei"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="trailing" secondItem="VNc-fL-Vfa" secondAttribute="trailing" constant="8" id="k3u-1Q-cKf"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="bottom" secondItem="tl3-hd-x35" secondAttribute="bottom" id="2x2-iA-utK"/>
 | 
			
		||||
                                                                                <constraint firstItem="LvK-28-fbm" firstAttribute="leading" secondItem="tl3-hd-x35" secondAttribute="trailing" id="NXL-Fd-whf"/>
 | 
			
		||||
                                                                                <constraint firstItem="b5f-wN-2xb" firstAttribute="centerY" secondItem="Agd-0J-z5o" secondAttribute="centerY" id="W01-oa-2rY"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="bottom" secondItem="LvK-28-fbm" secondAttribute="bottom" id="ZBx-Lf-XHF"/>
 | 
			
		||||
                                                                                <constraint firstItem="b5f-wN-2xb" firstAttribute="centerY" secondItem="vGk-t6-hZn" secondAttribute="centerY" id="fGB-8g-u5b"/>
 | 
			
		||||
                                                                                <constraint firstItem="tl3-hd-x35" firstAttribute="leading" secondItem="bff-RU-OcY" secondAttribute="leading" id="fx5-KQ-LSM"/>
 | 
			
		||||
                                                                                <constraint firstItem="tl3-hd-x35" firstAttribute="top" secondItem="bff-RU-OcY" secondAttribute="top" id="jc9-39-FY3"/>
 | 
			
		||||
                                                                                <constraint firstItem="OwP-sb-Wxl" firstAttribute="centerY" secondItem="b5f-wN-2xb" secondAttribute="centerY" id="m22-uE-sVm"/>
 | 
			
		||||
                                                                                <constraint firstItem="K8q-bM-tzh" firstAttribute="centerY" secondItem="b5f-wN-2xb" secondAttribute="centerY" id="ofO-r3-bjz"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="trailing" secondItem="LvK-28-fbm" secondAttribute="trailing" id="r9d-ym-Frs"/>
 | 
			
		||||
                                                                                <constraint firstItem="LvK-28-fbm" firstAttribute="top" secondItem="bff-RU-OcY" secondAttribute="top" id="uqb-hB-Iq8"/>
 | 
			
		||||
                                                                                <constraint firstItem="b5f-wN-2xb" firstAttribute="centerY" secondItem="uZi-FT-Fe8" secondAttribute="centerY" id="xz2-kK-B4g"/>
 | 
			
		||||
                                                                                <constraint firstItem="b5f-wN-2xb" firstAttribute="centerY" secondItem="qBo-Kw-vN9" secondAttribute="centerY" id="zaR-iF-Hea"/>
 | 
			
		||||
                                                                            </constraints>
 | 
			
		||||
                                                                            <connections>
 | 
			
		||||
                                                                                <outlet property="nameLabel" destination="VNc-fL-Vfa" id="kMh-xS-U1W"/>
 | 
			
		||||
                                                                                <outlet property="typeLabel" destination="AAG-mH-nNg" id="bBz-CA-Frx"/>
 | 
			
		||||
                                                                                <outlet property="delegate" destination="W2g-yv-V3V" id="HgX-fq-za5"/>
 | 
			
		||||
                                                                            </connections>
 | 
			
		||||
                                                                        </collectionViewCell>
 | 
			
		||||
                                                                        <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MPPasswordLargeStoredCell" id="W2g-yv-V3V" userLabel="Stored" customClass="MPPasswordLargeStoredCell">
 | 
			
		||||
                                                                            <rect key="frame" x="310" y="0.0" width="300" height="100"/>
 | 
			
		||||
                                                                            <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                                                            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
 | 
			
		||||
                                                                                <rect key="frame" x="0.0" y="0.0" width="300" height="100"/>
 | 
			
		||||
                                                                                <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                                                                <subviews>
 | 
			
		||||
                                                                                    <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.029999999329447746" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Personal Password" lineBreakMode="clip" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ESK-hm-pVB" userLabel="Type">
 | 
			
		||||
                                                                                        <rect key="frame" x="-10" y="19" width="763" height="101"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="84"/>
 | 
			
		||||
                                                                                        <color key="textColor" cocoaTouchSystemColor="lightTextColor"/>
 | 
			
		||||
                                                                                        <nil key="highlightedColor"/>
 | 
			
		||||
                                                                                    </label>
 | 
			
		||||
                                                                                    <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="SadwGafy7^Sidu" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="blw-Ou-8I8" userLabel="Content">
 | 
			
		||||
                                                                                        <rect key="frame" x="8" y="20" width="284" height="31"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <color key="textColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="24"/>
 | 
			
		||||
                                                                                        <textInputTraits key="textInputTraits" keyboardAppearance="alert"/>
 | 
			
		||||
                                                                                        <connections>
 | 
			
		||||
                                                                                            <outlet property="delegate" destination="W2g-yv-V3V" id="YKp-IE-zEQ"/>
 | 
			
		||||
                                                                                        </connections>
 | 
			
		||||
                                                                                    </textField>
 | 
			
		||||
                                                                                    <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.5" contentMode="left" text="apple.com" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="OwP-sb-Wxl" userLabel="Site Name">
 | 
			
		||||
                                                                                        <rect key="frame" x="8" y="71" width="284" height="14"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <accessibility key="accessibilityConfiguration" label="">
 | 
			
		||||
                                                                                            <accessibilityTraits key="traits" none="YES" staticText="YES" summaryElement="YES"/>
 | 
			
		||||
                                                                                        </accessibility>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" name="Copperplate" family="Copperplate" pointSize="12"/>
 | 
			
		||||
                                                                                        <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        <nil key="highlightedColor"/>
 | 
			
		||||
                                                                                        <color key="shadowColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        <size key="shadowOffset" width="0.0" height="1"/>
 | 
			
		||||
                                                                                    </label>
 | 
			
		||||
                                                                                    <button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KLg-Jf-XRN" userLabel="Upgrade">
 | 
			
		||||
                                                                                        <rect key="frame" x="221" y="56" width="44" height="44"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <accessibility key="accessibilityConfiguration" hint="Upgrades the password."/>
 | 
			
		||||
                                                                                        <constraints>
 | 
			
		||||
                                                                                            <constraint firstAttribute="width" constant="44" id="jRK-Pe-SFL"/>
 | 
			
		||||
                                                                                            <constraint firstAttribute="height" constant="44" id="mD9-bz-EEd"/>
 | 
			
		||||
                                                                                        </constraints>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
 | 
			
		||||
                                                                                        <inset key="contentEdgeInsets" minX="6" minY="6" maxX="6" maxY="6"/>
 | 
			
		||||
                                                                                        <state key="normal" image="icon_up.png">
 | 
			
		||||
                                                                                            <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        </state>
 | 
			
		||||
                                                                                        <state key="highlighted">
 | 
			
		||||
                                                                                            <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        </state>
 | 
			
		||||
                                                                                        <connections>
 | 
			
		||||
                                                                                            <action selector="doUpgrade:" destination="W2g-yv-V3V" eventType="touchUpInside" id="ALE-Na-KIS"/>
 | 
			
		||||
                                                                                        </connections>
 | 
			
		||||
                                                                                    </button>
 | 
			
		||||
                                                                                    <button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="b7E-cU-HB7" userLabel="Edit">
 | 
			
		||||
                                                                                        <rect key="frame" x="221" y="56" width="44" height="44"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <accessibility key="accessibilityConfiguration" hint="Edits the password."/>
 | 
			
		||||
                                                                                        <constraints>
 | 
			
		||||
                                                                                            <constraint firstAttribute="height" constant="44" id="dfA-95-6Om"/>
 | 
			
		||||
                                                                                            <constraint firstAttribute="width" constant="44" id="pQu-rk-Nay"/>
 | 
			
		||||
                                                                                        </constraints>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
 | 
			
		||||
                                                                                        <inset key="contentEdgeInsets" minX="6" minY="6" maxX="6" maxY="6"/>
 | 
			
		||||
                                                                                        <state key="normal" image="icon_edit.png">
 | 
			
		||||
                                                                                            <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        </state>
 | 
			
		||||
                                                                                        <state key="highlighted">
 | 
			
		||||
                                                                                            <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        </state>
 | 
			
		||||
                                                                                        <connections>
 | 
			
		||||
                                                                                            <action selector="doEditContent:" destination="W2g-yv-V3V" eventType="touchUpInside" id="N6m-Ib-LQO"/>
 | 
			
		||||
                                                                                        </connections>
 | 
			
		||||
                                                                                    </button>
 | 
			
		||||
                                                                                    <button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SfG-nt-NyC" userLabel="User">
 | 
			
		||||
                                                                                        <rect key="frame" x="256" y="56" width="44" height="44"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <accessibility key="accessibilityConfiguration" hint="Upgrades the password."/>
 | 
			
		||||
                                                                                        <constraints>
 | 
			
		||||
                                                                                            <constraint firstAttribute="height" constant="44" id="Am1-08-Pzm"/>
 | 
			
		||||
                                                                                            <constraint firstAttribute="width" constant="44" id="Jnj-oo-enC"/>
 | 
			
		||||
                                                                                        </constraints>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
 | 
			
		||||
                                                                                        <inset key="contentEdgeInsets" minX="6" minY="6" maxX="6" maxY="6"/>
 | 
			
		||||
                                                                                        <state key="normal" image="icon_person.png">
 | 
			
		||||
                                                                                            <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        </state>
 | 
			
		||||
                                                                                        <state key="selected" image="icon_key.png"/>
 | 
			
		||||
                                                                                        <state key="highlighted">
 | 
			
		||||
                                                                                            <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        </state>
 | 
			
		||||
                                                                                        <connections>
 | 
			
		||||
                                                                                            <action selector="doUser:" destination="W2g-yv-V3V" eventType="touchUpInside" id="jAs-zj-Nf9"/>
 | 
			
		||||
                                                                                        </connections>
 | 
			
		||||
                                                                                    </button>
 | 
			
		||||
                                                                                </subviews>
 | 
			
		||||
                                                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                            </view>
 | 
			
		||||
                                                                            <color key="backgroundColor" red="0.18823529410000001" green="0.15686274510000001" blue="0.15686274510000001" alpha="0.5" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                            <constraints>
 | 
			
		||||
                                                                                <constraint firstItem="b7E-cU-HB7" firstAttribute="centerX" secondItem="KLg-Jf-XRN" secondAttribute="centerX" id="34H-Ho-xNc"/>
 | 
			
		||||
                                                                                <constraint firstItem="ESK-hm-pVB" firstAttribute="leading" secondItem="W2g-yv-V3V" secondAttribute="leading" constant="-10" id="A0R-lu-9BO"/>
 | 
			
		||||
                                                                                <constraint firstItem="b7E-cU-HB7" firstAttribute="centerY" secondItem="SfG-nt-NyC" secondAttribute="centerY" id="ARa-xU-exW"/>
 | 
			
		||||
                                                                                <constraint firstItem="OwP-sb-Wxl" firstAttribute="centerY" secondItem="SfG-nt-NyC" secondAttribute="centerY" id="BcZ-r6-Kxd"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="trailing" secondItem="OwP-sb-Wxl" secondAttribute="trailing" constant="8" id="GGB-WN-PVI"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="trailing" secondItem="SfG-nt-NyC" secondAttribute="trailing" id="N2W-3R-jtc"/>
 | 
			
		||||
                                                                                <constraint firstItem="b7E-cU-HB7" firstAttribute="centerY" secondItem="KLg-Jf-XRN" secondAttribute="centerY" id="RAk-vW-n5T"/>
 | 
			
		||||
                                                                                <constraint firstItem="blw-Ou-8I8" firstAttribute="leading" secondItem="W2g-yv-V3V" secondAttribute="leading" constant="8" id="SNn-Z2-i9J"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="bottom" secondItem="ESK-hm-pVB" secondAttribute="bottom" constant="-20" id="UNw-PQ-JMk"/>
 | 
			
		||||
                                                                                <constraint firstItem="blw-Ou-8I8" firstAttribute="top" secondItem="W2g-yv-V3V" secondAttribute="top" constant="20" id="d5v-RM-TKj"/>
 | 
			
		||||
                                                                                <constraint firstItem="OwP-sb-Wxl" firstAttribute="leading" secondItem="W2g-yv-V3V" secondAttribute="leading" constant="8" id="mWV-lg-EAZ"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="trailing" secondItem="blw-Ou-8I8" secondAttribute="trailing" constant="8" id="qKQ-q9-lWu"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="bottom" secondItem="SfG-nt-NyC" secondAttribute="bottom" id="v0g-dJ-tbc"/>
 | 
			
		||||
                                                                                <constraint firstItem="SfG-nt-NyC" firstAttribute="leading" secondItem="b7E-cU-HB7" secondAttribute="trailing" constant="-9" id="zdQ-SJ-Cff"/>
 | 
			
		||||
                                                                            </constraints>
 | 
			
		||||
                                                                            <connections>
 | 
			
		||||
                                                                                <outlet property="contentField" destination="blw-Ou-8I8" id="bov-At-Wpd"/>
 | 
			
		||||
                                                                                <outlet property="editButton" destination="b7E-cU-HB7" id="0de-kq-frx"/>
 | 
			
		||||
                                                                                <outlet property="loginButton" destination="SfG-nt-NyC" id="hAn-7S-u9n"/>
 | 
			
		||||
                                                                                <outlet property="nameLabel" destination="OwP-sb-Wxl" id="Q6M-zX-g1z"/>
 | 
			
		||||
                                                                                <outlet property="typeLabel" destination="ESK-hm-pVB" id="w6J-OT-wfC"/>
 | 
			
		||||
                                                                                <outlet property="upgradeButton" destination="KLg-Jf-XRN" id="YtO-4G-lml"/>
 | 
			
		||||
                                                                            </connections>
 | 
			
		||||
                                                                        </collectionViewCell>
 | 
			
		||||
                                                                        <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MPPasswordLargeGeneratedCell" id="302-fI-maQ" userLabel="Generated" customClass="MPPasswordLargeGeneratedCell">
 | 
			
		||||
                                                                            <rect key="frame" x="620" y="0.0" width="300" height="100"/>
 | 
			
		||||
                                                                            <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                                                            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
 | 
			
		||||
                                                                                <rect key="frame" x="0.0" y="0.0" width="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"/>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="84"/>
 | 
			
		||||
                                                                                        <color key="textColor" cocoaTouchSystemColor="lightTextColor"/>
 | 
			
		||||
                                                                                        <nil key="highlightedColor"/>
 | 
			
		||||
                                                                                    </label>
 | 
			
		||||
                                                                                    <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="SadwGafy7^Sidu" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="q75-Uz-86O" userLabel="Content">
 | 
			
		||||
                                                                                        <rect key="frame" x="8" y="20" width="284" height="31"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <color key="textColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="24"/>
 | 
			
		||||
                                                                                        <textInputTraits key="textInputTraits" keyboardAppearance="alert"/>
 | 
			
		||||
                                                                                        <connections>
 | 
			
		||||
                                                                                            <outlet property="delegate" destination="302-fI-maQ" id="vji-9t-frp"/>
 | 
			
		||||
                                                                                        </connections>
 | 
			
		||||
                                                                                    </textField>
 | 
			
		||||
                                                                                    <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.5" contentMode="left" text="apple.com" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="qek-2l-YQf" userLabel="Site Name">
 | 
			
		||||
                                                                                        <rect key="frame" x="8" y="71" width="284" height="14"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <accessibility key="accessibilityConfiguration" label="">
 | 
			
		||||
                                                                                            <accessibilityTraits key="traits" none="YES" staticText="YES" summaryElement="YES"/>
 | 
			
		||||
                                                                                        </accessibility>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" name="Copperplate" family="Copperplate" pointSize="12"/>
 | 
			
		||||
                                                                                        <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        <nil key="highlightedColor"/>
 | 
			
		||||
                                                                                        <color key="shadowColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        <size key="shadowOffset" width="0.0" height="1"/>
 | 
			
		||||
                                                                                    </label>
 | 
			
		||||
                                                                                    <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.5" contentMode="left" text="1" textAlignment="right" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="I2J-B6-5rE" userLabel="Counter">
 | 
			
		||||
                                                                                        <rect key="frame" x="216" y="69" width="11" height="19"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <accessibility key="accessibilityConfiguration" hint="Site's counter."/>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" name="Copperplate-Bold" family="Copperplate" pointSize="17"/>
 | 
			
		||||
                                                                                        <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        <nil key="highlightedColor"/>
 | 
			
		||||
                                                                                        <color key="shadowColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        <size key="shadowOffset" width="0.0" height="1"/>
 | 
			
		||||
                                                                                    </label>
 | 
			
		||||
                                                                                    <button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="iLD-rv-uZZ" userLabel="Upgrade">
 | 
			
		||||
                                                                                        <rect key="frame" x="221" y="56" width="44" height="44"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <accessibility key="accessibilityConfiguration" hint="Upgrades the password."/>
 | 
			
		||||
                                                                                        <constraints>
 | 
			
		||||
                                                                                            <constraint firstAttribute="height" constant="44" id="1B8-GB-TBc"/>
 | 
			
		||||
                                                                                            <constraint firstAttribute="width" constant="44" id="b9e-xF-5OF"/>
 | 
			
		||||
                                                                                        </constraints>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
 | 
			
		||||
                                                                                        <inset key="contentEdgeInsets" minX="6" minY="6" maxX="6" maxY="6"/>
 | 
			
		||||
                                                                                        <state key="normal" image="icon_up.png">
 | 
			
		||||
                                                                                            <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        </state>
 | 
			
		||||
                                                                                        <state key="highlighted">
 | 
			
		||||
                                                                                            <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        </state>
 | 
			
		||||
                                                                                        <connections>
 | 
			
		||||
                                                                                            <action selector="doUpgrade:" destination="302-fI-maQ" eventType="touchUpInside" id="iaP-5Y-5re"/>
 | 
			
		||||
                                                                                        </connections>
 | 
			
		||||
                                                                                    </button>
 | 
			
		||||
                                                                                    <button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fQc-Fn-JDq" userLabel="Incrementer">
 | 
			
		||||
                                                                                        <rect key="frame" x="221" y="56" width="44" height="44"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <accessibility key="accessibilityConfiguration" hint="Increments the site counter."/>
 | 
			
		||||
                                                                                        <gestureRecognizers/>
 | 
			
		||||
                                                                                        <constraints>
 | 
			
		||||
                                                                                            <constraint firstAttribute="width" constant="44" id="1j5-Ke-znk"/>
 | 
			
		||||
                                                                                            <constraint firstAttribute="height" constant="44" id="BWc-06-jSP"/>
 | 
			
		||||
                                                                                        </constraints>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
 | 
			
		||||
                                                                                        <inset key="contentEdgeInsets" minX="6" minY="6" maxX="6" maxY="6"/>
 | 
			
		||||
                                                                                        <state key="normal" image="icon_plus.png">
 | 
			
		||||
                                                                                            <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        </state>
 | 
			
		||||
                                                                                        <state key="highlighted">
 | 
			
		||||
                                                                                            <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        </state>
 | 
			
		||||
                                                                                        <connections>
 | 
			
		||||
                                                                                            <action selector="doIncrementCounter:" destination="302-fI-maQ" eventType="touchUpInside" id="Aa1-tk-whD"/>
 | 
			
		||||
                                                                                        </connections>
 | 
			
		||||
                                                                                    </button>
 | 
			
		||||
                                                                                    <button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cOv-2G-EAP" userLabel="User">
 | 
			
		||||
                                                                                        <rect key="frame" x="256" y="56" width="44" height="44"/>
 | 
			
		||||
                                                                                        <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
 | 
			
		||||
                                                                                        <accessibility key="accessibilityConfiguration" hint="Upgrades the password."/>
 | 
			
		||||
                                                                                        <constraints>
 | 
			
		||||
                                                                                            <constraint firstAttribute="height" constant="44" id="63k-ii-B9M"/>
 | 
			
		||||
                                                                                            <constraint firstAttribute="width" constant="44" id="ovE-9u-ASE"/>
 | 
			
		||||
                                                                                        </constraints>
 | 
			
		||||
                                                                                        <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
 | 
			
		||||
                                                                                        <inset key="contentEdgeInsets" minX="6" minY="6" maxX="6" maxY="6"/>
 | 
			
		||||
                                                                                        <state key="normal" image="icon_person.png">
 | 
			
		||||
                                                                                            <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        </state>
 | 
			
		||||
                                                                                        <state key="selected" image="icon_key.png"/>
 | 
			
		||||
                                                                                        <state key="highlighted">
 | 
			
		||||
                                                                                            <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                                        </state>
 | 
			
		||||
                                                                                        <connections>
 | 
			
		||||
                                                                                            <action selector="doUser:" destination="302-fI-maQ" eventType="touchUpInside" id="Fp9-L4-hlU"/>
 | 
			
		||||
                                                                                        </connections>
 | 
			
		||||
                                                                                    </button>
 | 
			
		||||
                                                                                </subviews>
 | 
			
		||||
                                                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                            </view>
 | 
			
		||||
                                                                            <color key="backgroundColor" red="0.18823529411764706" green="0.18823529411764706" blue="0.18823529411764706" alpha="0.5" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                                            <constraints>
 | 
			
		||||
                                                                                <constraint firstItem="q75-Uz-86O" firstAttribute="top" secondItem="302-fI-maQ" secondAttribute="top" constant="20" id="4NG-CG-tXA"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="bottom" secondItem="cOv-2G-EAP" secondAttribute="bottom" id="7S8-gd-JGz"/>
 | 
			
		||||
                                                                                <constraint firstItem="iLD-rv-uZZ" firstAttribute="centerY" secondItem="fQc-Fn-JDq" secondAttribute="centerY" id="B7r-cy-SEz"/>
 | 
			
		||||
                                                                                <constraint firstItem="fQc-Fn-JDq" firstAttribute="leading" secondItem="I2J-B6-5rE" secondAttribute="trailing" constant="-6" id="BP2-UH-wUX"/>
 | 
			
		||||
                                                                                <constraint firstItem="qAD-3v-3aq" firstAttribute="leading" secondItem="302-fI-maQ" secondAttribute="leading" constant="-10" id="BxY-uQ-3gc"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="trailing" secondItem="qek-2l-YQf" secondAttribute="trailing" constant="8" id="MpX-WR-hsJ"/>
 | 
			
		||||
                                                                                <constraint firstItem="qek-2l-YQf" firstAttribute="centerY" secondItem="I2J-B6-5rE" secondAttribute="centerY" id="TlY-I8-4hD"/>
 | 
			
		||||
                                                                                <constraint firstAttribute="bottom" secondItem="qAD-3v-3aq" secondAttribute="bottom" constant="-20" id="Yc1-x1-kYs"/>
 | 
			
		||||
                                                                                <constraint firstItem="iLD-rv-uZZ" firstAttribute="centerX" secondItem="fQc-Fn-JDq" secondAttribute="centerX" id="Yiw-hl-6Vx"/>
 | 
			
		||||
                                                                                <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"/>
 | 
			
		||||
                                                                                <outlet property="counterButton" destination="fQc-Fn-JDq" id="1QL-JK-tHn"/>
 | 
			
		||||
                                                                                <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>
 | 
			
		||||
                                                                        </collectionViewCell>
 | 
			
		||||
                                                                    </cells>
 | 
			
		||||
                                                                    <connections>
 | 
			
		||||
                                                                        <outlet property="dataSource" destination="vMF-fk-FYX" id="gLv-f4-PXT"/>
 | 
			
		||||
                                                                        <outlet property="delegate" destination="vMF-fk-FYX" id="ch2-2f-37e"/>
 | 
			
		||||
                                                                    </connections>
 | 
			
		||||
                                                                </collectionView>
 | 
			
		||||
                                                                        </scrollView>
 | 
			
		||||
                                                                    </subviews>
 | 
			
		||||
                                                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                                    <constraints>
 | 
			
		||||
                                                                        <constraint firstAttribute="height" secondItem="tl3-hd-x35" secondAttribute="height" id="52G-c7-hIf"/>
 | 
			
		||||
                                                                        <constraint firstItem="aDw-qY-VjU" firstAttribute="leading" secondItem="xph-TW-9QO" secondAttribute="leading" id="CD9-Oa-unh"/>
 | 
			
		||||
                                                                        <constraint firstAttribute="bottom" secondItem="b5f-wN-2xb" secondAttribute="bottom" id="G0H-PL-lee"/>
 | 
			
		||||
                                                                        <constraint firstItem="bff-RU-OcY" firstAttribute="leading" secondItem="xph-TW-9QO" secondAttribute="leading" id="HqJ-3D-UKp"/>
 | 
			
		||||
                                                                        <constraint firstAttribute="bottom" secondItem="bff-RU-OcY" secondAttribute="bottom" id="LdO-Uh-meg"/>
 | 
			
		||||
                                                                        <constraint firstItem="LvK-28-fbm" firstAttribute="width" secondItem="xph-TW-9QO" secondAttribute="width" id="SI5-t4-8N0"/>
 | 
			
		||||
                                                                        <constraint firstAttribute="width" secondItem="tl3-hd-x35" secondAttribute="width" id="W1t-9b-nDP"/>
 | 
			
		||||
                                                                        <constraint firstAttribute="bottom" secondItem="5SS-x0-icl" secondAttribute="centerY" constant="4" id="WQK-m9-V2t"/>
 | 
			
		||||
                                                                        <constraint firstAttribute="trailing" secondItem="b5f-wN-2xb" secondAttribute="trailing" id="WgC-8z-VnB"/>
 | 
			
		||||
                                                                        <constraint firstItem="aDw-qY-VjU" firstAttribute="top" secondItem="xph-TW-9QO" secondAttribute="top" id="YVH-Wj-Ese"/>
 | 
			
		||||
                                                                        <constraint firstAttribute="bottom" secondItem="aDw-qY-VjU" secondAttribute="bottom" id="aQ3-1j-L38"/>
 | 
			
		||||
                                                                        <constraint firstAttribute="centerX" secondItem="5SS-x0-icl" secondAttribute="centerX" id="bGC-IS-Y3g"/>
 | 
			
		||||
                                                                        <constraint firstItem="bff-RU-OcY" firstAttribute="top" secondItem="xph-TW-9QO" secondAttribute="top" id="hCs-ZY-tmo"/>
 | 
			
		||||
                                                                        <constraint firstAttribute="trailing" secondItem="aDw-qY-VjU" secondAttribute="trailing" id="hsj-QF-2Oh"/>
 | 
			
		||||
                                                                        <constraint firstAttribute="trailing" secondItem="bff-RU-OcY" secondAttribute="trailing" id="o6W-1a-ia7"/>
 | 
			
		||||
                                                                        <constraint firstItem="LvK-28-fbm" firstAttribute="height" secondItem="xph-TW-9QO" secondAttribute="height" id="viy-di-Nag"/>
 | 
			
		||||
                                                                    </constraints>
 | 
			
		||||
                                                                    <userDefinedRuntimeAttributes>
 | 
			
		||||
                                                                        <userDefinedRuntimeAttribute type="boolean" keyPath="ignoreTouches" value="YES"/>
 | 
			
		||||
                                                                    </userDefinedRuntimeAttributes>
 | 
			
		||||
                                                                </view>
 | 
			
		||||
                                                            </subviews>
 | 
			
		||||
                                                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                        </view>
 | 
			
		||||
                                                        <color key="backgroundColor" red="0.18823529411764706" green="0.25098039215686274" blue="0.18823529411764706" alpha="0.5" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                        <gestureRecognizers/>
 | 
			
		||||
                                                        <constraints>
 | 
			
		||||
                                                            <constraint firstAttribute="trailing" secondItem="xph-TW-9QO" secondAttribute="trailing" id="Fmt-yZ-Vjo"/>
 | 
			
		||||
                                                            <constraint firstItem="xph-TW-9QO" firstAttribute="leading" secondItem="W2g-yv-V3V" secondAttribute="leading" id="IsM-Br-kMe"/>
 | 
			
		||||
                                                            <constraint firstItem="xph-TW-9QO" firstAttribute="top" secondItem="W2g-yv-V3V" secondAttribute="top" id="KDo-0Z-mc1"/>
 | 
			
		||||
                                                            <constraint firstAttribute="bottom" secondItem="xph-TW-9QO" secondAttribute="bottom" id="W1r-47-bqe"/>
 | 
			
		||||
                                                        </constraints>
 | 
			
		||||
                                                        <connections>
 | 
			
		||||
                                                            <outlet property="contentCollectionView" destination="7vV-gu-BNS" id="8KS-Ep-xTu"/>
 | 
			
		||||
                                                            <outlet property="counterButton" destination="uZi-FT-Fe8" id="oaF-bB-Sgc"/>
 | 
			
		||||
                                                            <outlet property="counterLabel" destination="PKP-M9-T8E" id="m9u-Qx-Z9N"/>
 | 
			
		||||
                                                            <outlet property="loginNameField" destination="Bw8-sw-ZIS" id="alI-eP-cvN"/>
 | 
			
		||||
                                                            <outlet property="modeButton" destination="b5f-wN-2xb" id="m2X-BZ-Lbv"/>
 | 
			
		||||
                                                            <outlet property="modeScrollView" destination="bff-RU-OcY" id="Mdp-fj-00L"/>
 | 
			
		||||
                                                            <outlet property="pageControl" destination="5SS-x0-icl" id="IGN-yI-5s0"/>
 | 
			
		||||
                                                            <outlet property="passwordEditButton" destination="Agd-0J-z5o" id="VQI-nl-5Yh"/>
 | 
			
		||||
                                                            <outlet property="passwordField" destination="blw-Ou-8I8" id="bov-At-Wpd"/>
 | 
			
		||||
                                                            <outlet property="selectionButton" destination="aDw-qY-VjU" id="R3R-kq-XMd"/>
 | 
			
		||||
                                                            <outlet property="siteNameLabel" destination="OwP-sb-Wxl" id="6GN-Ou-K0F"/>
 | 
			
		||||
                                                            <outlet property="strengthLabel" destination="wfM-xz-roR" id="dzk-dB-OfP"/>
 | 
			
		||||
                                                            <outlet property="upgradeButton" destination="vGk-t6-hZn" id="m2T-CA-HmJ"/>
 | 
			
		||||
                                                            <outlet property="usernameEditButton" destination="qBo-Kw-vN9" id="g0S-0o-e3D"/>
 | 
			
		||||
                                                        </connections>
 | 
			
		||||
                                                    </collectionViewCell>
 | 
			
		||||
                                                </cells>
 | 
			
		||||
@@ -1527,7 +1478,7 @@
 | 
			
		||||
                </viewController>
 | 
			
		||||
                <placeholder placeholderIdentifier="IBFirstResponder" id="APh-u5-vFI" userLabel="First Responder" sceneMemberID="firstResponder"/>
 | 
			
		||||
            </objects>
 | 
			
		||||
            <point key="canvasLocation" x="1350" y="1200"/>
 | 
			
		||||
            <point key="canvasLocation" x="1355" y="1200"/>
 | 
			
		||||
        </scene>
 | 
			
		||||
        <!--Emergency View Controller-->
 | 
			
		||||
        <scene sceneID="c0a-VZ-JJf">
 | 
			
		||||
@@ -2541,8 +2492,10 @@ See </string>
 | 
			
		||||
        <image name="icon_edit.png" width="32" height="32"/>
 | 
			
		||||
        <image name="icon_gears.png" width="32" height="32"/>
 | 
			
		||||
        <image name="icon_key.png" width="32" height="32"/>
 | 
			
		||||
        <image name="icon_list-names.png" width="32" height="32"/>
 | 
			
		||||
        <image name="icon_person.png" width="32" height="32"/>
 | 
			
		||||
        <image name="icon_plus.png" width="32" height="32"/>
 | 
			
		||||
        <image name="icon_tools.png" width="32" height="32"/>
 | 
			
		||||
        <image name="icon_up.png" width="32" height="32"/>
 | 
			
		||||
        <image name="identity.png" width="82" height="80"/>
 | 
			
		||||
        <image name="image-0.png" width="256" height="384"/>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user