2
0

Avatar display fixes.

[ADDED]     A new password type: Secure password.  20 characters, not
            word-based, very high entropy.
[FIXED]     UI bugs and improvements with the avatar display and
            password checking state display.
This commit is contained in:
Maarten Billemont 2012-06-06 22:38:43 +02:00
parent 77306e0046
commit b472c85c9d
12 changed files with 224 additions and 138 deletions

2
External/Pearl vendored

@ -1 +1 @@
Subproject commit e9dd56bc64735ebd28eef6c6dc748f480acc7c67
Subproject commit 3a61ba22afefb23c2f87a3836e8b996d2b5a96fb

View File

@ -81,6 +81,7 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
user.keyID = tryKeyID;
[[MPAppDelegate_Shared get] saveContext];
}
user.lastUsed = [NSDate date];
#ifdef TESTFLIGHT_SDK_VERSION
[TestFlight passCheckpoint:MPTestFlightCheckpointMPEntered];

View File

@ -31,11 +31,12 @@ typedef enum {
} MPElementFeature;
typedef enum {
MPElementTypeGeneratedLong = 0x0 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedMedium = 0x1 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedShort = 0x2 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedBasic = 0x3 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedPIN = 0x4 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedSecure = 0x0 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedLong = 0x1 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedMedium = 0x2 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedShort = 0x3 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedBasic = 0x4 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedPIN = 0x5 | MPElementTypeClassGenerated | 0x0,
MPElementTypeStoredPersonal = 0x0 | MPElementTypeClassStored | MPElementFeatureExportContent,
MPElementTypeStoredDevicePrivate = 0x1 | MPElementTypeClassStored | MPElementFeatureDevicePrivate,

View File

@ -40,6 +40,9 @@ NSString *NSStringFromMPElementType(MPElementType type) {
return nil;
switch (type) {
case MPElementTypeGeneratedSecure:
return @"Secure Password";
case MPElementTypeGeneratedLong:
return @"Long Password";
@ -72,6 +75,9 @@ Class ClassFromMPElementType(MPElementType type) {
return nil;
switch (type) {
case MPElementTypeGeneratedSecure:
return [MPElementGeneratedEntity class];
case MPElementTypeGeneratedLong:
return [MPElementGeneratedEntity class];
@ -135,7 +141,7 @@ NSString *MPCalculateContent(MPElementType type, NSString *name, NSData *key, ui
[name dataUsingEncoding:NSUTF8StringEncoding],
key,
[NSData dataWithBytes:&nsalt length:sizeof(nsalt)],
nil] hashWith:PearlDigestSHA1];
nil] hashWith:PearlDigestSHA256];
trc(@"seed is: %@", seed);
const char *seedBytes = seed.bytes;

View File

@ -4,7 +4,7 @@
<attribute name="content" optional="YES" transient="YES" attributeType="Transformable" syncable="YES"/>
<attribute name="lastUsed" attributeType="Date" syncable="YES"/>
<attribute name="name" attributeType="String" minValueString="1" indexed="YES" syncable="YES" isSyncIdentityProperty="YES"/>
<attribute name="type_" attributeType="Integer 16" defaultValueString="16" syncable="YES"/>
<attribute name="type_" attributeType="Integer 16" defaultValueString="17" syncable="YES"/>
<attribute name="uses_" attributeType="Integer 16" defaultValueString="0" syncable="YES"/>
<relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements" inverseEntity="MPUserEntity" syncable="YES"/>
</entity>
@ -15,17 +15,17 @@
<attribute name="contentObject" optional="YES" attributeType="Transformable" storedInTruthFile="YES" syncable="YES"/>
</entity>
<entity name="MPUserEntity" representedClassName="MPUserEntity" syncable="YES">
<attribute name="avatar_" optional="YES" attributeType="Integer 16" defaultValueString="0" syncable="YES"/>
<attribute name="avatar_" attributeType="Integer 16" defaultValueString="0" syncable="YES"/>
<attribute name="keyID" optional="YES" attributeType="Binary" syncable="YES"/>
<attribute name="lastUsed" optional="YES" attributeType="Date" syncable="YES"/>
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="saveKey_" optional="YES" attributeType="Boolean" syncable="YES"/>
<attribute name="name" attributeType="String" syncable="YES" isSyncIdentityProperty="YES"/>
<attribute name="saveKey_" attributeType="Boolean" defaultValueString="NO" syncable="YES"/>
<relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity" inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
</entity>
<elements>
<element name="MPElementEntity" positionX="160" positionY="192" width="128" height="120"/>
<element name="MPElementEntity" positionX="160" positionY="192" width="128" height="135"/>
<element name="MPElementGeneratedEntity" positionX="160" positionY="192" width="128" height="60"/>
<element name="MPElementStoredEntity" positionX="160" positionY="192" width="128" height="60"/>
<element name="MPUserEntity" positionX="160" positionY="192" width="128" height="120"/>
<element name="MPUserEntity" positionX="160" positionY="192" width="128" height="135"/>
</elements>
</model>

View File

@ -516,7 +516,7 @@
- (NSString *)testFlightToken {
return NullToNil([[self testFlightInfo] valueForKeyPath:@"Team Token"]);
return NSNullToNil([[self testFlightInfo] valueForKeyPath:@"Team Token"]);
}
@ -535,7 +535,7 @@
- (NSString *)crashlyticsAPIKey {
return NullToNil([[self crashlyticsInfo] valueForKeyPath:@"API Key"]);
return NSNullToNil([[self crashlyticsInfo] valueForKeyPath:@"API Key"]);
}
@ -554,7 +554,7 @@
- (NSString *)apptentiveAPIKey {
return NullToNil([[self apptentiveInfo] valueForKeyPath:@"API Key"]);
return NSNullToNil([[self apptentiveInfo] valueForKeyPath:@"API Key"]);
}
@ -574,7 +574,7 @@
- (NSString *)localyticsKey {
#ifdef DEBUG
return NullToNil([[self localyticsInfo] valueForKeyPath:@"Key.development"]);
return NSNullToNil([[self localyticsInfo] valueForKeyPath:@"Key.development"]);
#else
return NullToNil([[self localyticsInfo] valueForKeyPath:@"Key.distribution"]);
#endif

View File

@ -98,6 +98,8 @@
else if (cell == self.changeMPCell)
[[MPAppDelegate get] changeMP];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - IASKSettingsDelegate

View File

@ -131,7 +131,7 @@
assert(self.query);
self.fetchedResultsController.fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(%@ == '' OR name BEGINSWITH[cd] %@) AND user == %@",
self.query, self.query, NilToNull([MPAppDelegate get].activeUser)];
self.query, self.query, NilToNSNull([MPAppDelegate get].activeUser)];
NSError *error;
if (![self.fetchedResultsController performFetch:&error])

View File

@ -90,14 +90,18 @@
// Generated
switch (indexPath.row) {
case 0:
return MPElementTypeGeneratedLong;
return NSNotFound;
case 1:
return MPElementTypeGeneratedMedium;
return MPElementTypeGeneratedSecure;
case 2:
return MPElementTypeGeneratedShort;
return MPElementTypeGeneratedLong;
case 3:
return MPElementTypeGeneratedBasic;
return MPElementTypeGeneratedMedium;
case 4:
return MPElementTypeGeneratedShort;
case 5:
return MPElementTypeGeneratedBasic;
case 6:
return MPElementTypeGeneratedPIN;
default:
@ -109,8 +113,10 @@
// Stored
switch (indexPath.row) {
case 0:
return MPElementTypeStoredPersonal;
return NSNotFound;
case 1:
return MPElementTypeStoredPersonal;
case 2:
return MPElementTypeStoredDevicePrivate;
default:

View File

@ -18,6 +18,8 @@
@property (weak, nonatomic) IBOutlet UILabel *oldNameLabel;
@property (weak, nonatomic) IBOutlet UIButton *avatarTemplate;
@property (weak, nonatomic) IBOutlet UILabel *deleteTip;
@property (weak, nonatomic) IBOutlet UIView *passwordTipView;
@property (weak, nonatomic) IBOutlet UILabel *passwordTipLabel;
@property(nonatomic, strong) UIColor *avatarShadowColor;

View File

@ -30,6 +30,8 @@
@synthesize nameLabel, oldNameLabel;
@synthesize avatarTemplate;
@synthesize deleteTip;
@synthesize passwordTipView;
@synthesize passwordTipLabel;
@synthesize avatarShadowColor = _avatarShadowColor;
@ -52,6 +54,7 @@
self.nameLabel.layer.cornerRadius = 5;
self.avatarTemplate.hidden = YES;
self.spinner.alpha = 0;
self.passwordTipView.alpha = 0;
[self updateLayoutAnimated:NO allowScroll:YES completion:nil];
@ -67,6 +70,8 @@
[self setNameLabel:nil];
[self setAvatarTemplate:nil];
[self setDeleteTip:nil];
[self setPasswordTipView:nil];
[self setPasswordTipLabel:nil];
[super viewDidUnload];
}
@ -99,9 +104,10 @@
NSArray *users = [[MPAppDelegate managedObjectContext] executeFetchRequest:fetchRequest error:nil];
// Clean up avatars.
for (UIView *view in [self.avatarsView subviews])
if (view != self.avatarTemplate)
[view removeFromSuperview];
for (UIView *subview in [self.avatarsView subviews])
if ([[self.avatarToUser allKeys] containsObject:[NSValue valueWithNonretainedObject:subview]])
// This subview is a former avatar.
[subview removeFromSuperview];
[self.avatarToUser removeAllObjects];
// Create avatars.
@ -147,11 +153,11 @@
avatar.backgroundColor = [UIColor clearColor];
dbg(@"User: %@, avatar: %d", user.name, user.avatar);
avatar.tag = user.avatar;
[avatar setBackgroundImage:[UIImage imageNamed:PearlString(@"avatar-%u", user.avatar)]
forState:UIControlStateNormal];
if (user)
[self.avatarToUser setObject:user forKey:[NSValue valueWithNonretainedObject:avatar]];
[self.avatarToUser setObject:NilToNSNull(user) forKey:[NSValue valueWithNonretainedObject:avatar]];
if (self.selectedUser && user == self.selectedUser)
avatar.selected = YES;
@ -165,7 +171,8 @@
[self.passwordField resignFirstResponder];
[self updateLayoutAnimated:YES allowScroll:YES completion:^(BOOL finished) {
if (finished) if (self.selectedUser)
if (finished)
if (self.selectedUser)
[self.passwordField becomeFirstResponder];
}];
}
@ -242,16 +249,22 @@
}
[self.avatarsView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
const BOOL isTargeted = subview == targetedAvatar;
if (![[self.avatarToUser allKeys] containsObject:[NSValue valueWithNonretainedObject:subview]])
// This subview is not one of the user avatars.
return;
UIButton *avatar = (UIButton *)subview;
subview.userInteractionEnabled = isTargeted;
subview.alpha = isTargeted ? 1 : self.selectedUser ? 0.1 : 0.4;
BOOL isTargeted = avatar == targetedAvatar;
[self updateAvatarShadowColor:subview isTargeted:isTargeted];
avatar.userInteractionEnabled = isTargeted;
avatar.alpha = isTargeted ? 1 : self.selectedUser ? 0.1 : 0.4;
[self updateAvatarShadowColor:avatar isTargeted:isTargeted];
} recurse:NO];
if (allowScroll) {
CGPoint targetContentOffset = CGPointMake(targetedAvatar.center.x - self.avatarsView.bounds.size.width / 2, self.avatarsView.contentOffset.y);
CGPoint targetContentOffset = CGPointMake(MAX(0, targetedAvatar.center.x - self.avatarsView.bounds.size.width / 2),
self.avatarsView.contentOffset.y);
if (!CGPointEqualToPoint(self.avatarsView.contentOffset, targetContentOffset))
[self.avatarsView setContentOffset:targetContentOffset animated:animated];
}
@ -266,23 +279,30 @@
completion(YES);
}
- (void)setPasswordTip:(NSString *)string {
if (string.length)
self.passwordTipLabel.text = string;
[UIView animateWithDuration:0.3f animations:^{
self.passwordTipView.alpha = string.length? 1: 0;
}];
}
- (void)tryMasterPassword {
[self setSpinnerActive:YES];
[self changeAvatarShadowColorTo:[UIColor colorWithName:@"lightskyblue"]];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
BOOL unlocked = [[MPAppDelegate get] tryMasterPassword:self.passwordField.text forUser:self.selectedUser];
dispatch_async(dispatch_get_main_queue(), ^{
if (unlocked) {
[self changeAvatarShadowColorTo:[UIColor colorWithName:@"greenyellow"]];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long) (NSEC_PER_SEC * 1.5f)), dispatch_get_main_queue(), ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long) (NSEC_PER_SEC * 0.5f)), dispatch_get_main_queue(), ^{
[self dismissModalViewControllerAnimated:YES];
});
} else
[self changeAvatarShadowColorTo:[UIColor colorWithName:@"crimson"]];
[self setPasswordTip:@"Incorrect password."];
[self setSpinnerActive:NO];
});
@ -309,7 +329,7 @@
- (MPUserEntity *)userForAvatar:(UIButton *)avatar {
return NullToNil([self.avatarToUser objectForKey:[NSValue valueWithNonretainedObject:avatar]]);
return NSNullToNil([self.avatarToUser objectForKey:[NSValue valueWithNonretainedObject:avatar]]);
}
- (void)setSpinnerActive:(BOOL)active {
@ -342,23 +362,12 @@
});
}
- (void)changeAvatarShadowColorTo:(UIColor *)color {
self.avatarShadowColor = color;
if (self.selectedUser) {
UIButton *selectedAvatar = [self avatarForUser:self.selectedUser];
[selectedAvatar.layer removeAnimationForKey:@"targetedShadow"];
[self updateAvatarShadowColor:selectedAvatar isTargeted:YES];
}
}
- (void)updateAvatarShadowColor:(UIView *)avatar isTargeted:(BOOL)targeted {
- (void)updateAvatarShadowColor:(UIButton *)avatar isTargeted:(BOOL)targeted {
if (targeted) {
if (![avatar.layer animationForKey:@"targetedShadow"]) {
CABasicAnimation *toShadowColorAnimation = [CABasicAnimation animationWithKeyPath:@"shadowColor"];
toShadowColorAnimation.toValue = (__bridge id) self.avatarShadowColor.CGColor;
toShadowColorAnimation.toValue = (__bridge id) (avatar.selected? self.avatarTemplate.backgroundColor: [UIColor whiteColor]).CGColor;
toShadowColorAnimation.beginTime = 0.0f;
toShadowColorAnimation.duration = 0.5f;
toShadowColorAnimation.fillMode = kCAFillModeForwards;
@ -404,12 +413,16 @@
#pragma mark - UITextFieldDelegate
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[self setPasswordTip:nil];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
[self setSpinnerActive:YES];
[self changeAvatarShadowColorTo:[UIColor colorWithName:@"lightskyblue"]];
if (self.selectedUser.keyID)
[self tryMasterPassword];
@ -463,11 +476,7 @@
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// CGFloat xOfMiddle = scrollView.contentOffset.x + scrollView.bounds.size.width / 2;
// UIButton *middleAvatar = (UIButton *)[PearlUIUtils viewClosestTo:CGPointMake(xOfMiddle, scrollView.contentOffset.y) ofArray:scrollView.subviews];
//
[self updateLayoutAnimated:NO allowScroll:NO completion:nil];
// [self scrollToAvatar:middleAvatar animated:NO];
}
#pragma mark - IBActions

View File

@ -16,18 +16,18 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.12549020350000001" green="0.1411764771" blue="0.14901961389999999" alpha="1" colorSpace="calibratedRGB"/>
<view key="tableFooterView" contentMode="scaleToFill" id="aNa-wb-cYK">
<rect key="frame" x="0.0" y="588" width="320" height="20"/>
<rect key="frame" x="0.0" y="627" width="320" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<sections>
<tableViewSection id="gUv-FU-O36">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="204" id="NCB-rX-weq">
<rect key="frame" x="0.0" y="0.0" width="320" height="204"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="162" id="NCB-rX-weq">
<rect key="frame" x="0.0" y="0.0" width="320" height="162"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="203"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="161"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Generated" lineBreakMode="tailTruncation" minimumFontSize="10" id="azh-GA-KA1">
@ -39,30 +39,9 @@
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_list_first.png" id="WXs-ZQ-JuJ">
<rect key="frame" x="10" y="160" width="300" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Long Password" lineBreakMode="tailTruncation" minimumFontSize="10" id="QIm-RX-xY7">
<rect key="frame" x="20" y="160" width="280" height="24"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans" family="Gill Sans" pointSize="18"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Word-like, 14 characters, contains symbols." lineBreakMode="tailTruncation" minimumFontSize="10" id="6iu-aM-lJA">
<rect key="frame" x="20" y="183" width="280" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" id="E4a-XS-Qlz">
<rect key="frame" x="20" y="49" width="280" height="112"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<string key="text">These types create a safe password for your site.
The passwords aren't saved anywhere. This is a major advantage: if you lose your device, your passwords cannot be stolen. You can use any other device to get all your passwords back, no need for restoring backups or any other pains.</string>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
@ -71,31 +50,79 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" id="zRU-I1-av9">
<rect key="frame" x="55" y="123" width="210" height="60"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="44" id="PBE-wW-HXv">
<rect key="frame" x="0.0" y="162" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black.png" id="HHn-56-thS">
<rect key="frame" x="0.0" y="0.0" width="210" height="60"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_list_first.png" id="Uw9-CC-Snk">
<rect key="frame" x="10" y="0.0" width="300" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Safest and recommended." textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" id="lND-JD-bF8">
<rect key="frame" x="20" y="0.0" width="171" height="40"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Secure Password" lineBreakMode="tailTruncation" minimumFontSize="10" id="Twq-Pz-E1B">
<rect key="frame" x="20" y="0.0" width="280" height="24"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans" family="Gill Sans" pointSize="18"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="20 characters, contains symbols." lineBreakMode="tailTruncation" minimumFontSize="10" id="IOR-qB-kgm">
<rect key="frame" x="20" y="23" width="280" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="44" id="Fho-bQ-ENV">
<rect key="frame" x="0.0" y="206" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_list_middle.png" id="UNz-7Y-fyS">
<rect key="frame" x="10" y="0.0" width="300" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Long Password" lineBreakMode="tailTruncation" minimumFontSize="10" id="HAz-5s-UMX">
<rect key="frame" x="20" y="0.0" width="280" height="24"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans" family="Gill Sans" pointSize="18"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Word-like, 14 characters, contains symbols." lineBreakMode="tailTruncation" minimumFontSize="10" id="J9t-dg-gQm">
<rect key="frame" x="20" y="23" width="280" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="re0-ZT-bnP">
<rect key="frame" x="0.0" y="204" width="320" height="44"/>
<rect key="frame" x="0.0" y="250" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -128,7 +155,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="4pb-c9-i2D">
<rect key="frame" x="0.0" y="248" width="320" height="44"/>
<rect key="frame" x="0.0" y="294" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -148,7 +175,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Word-like, 4 characters." lineBreakMode="tailTruncation" minimumFontSize="10" id="Zi3-26-3iq">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Word-like, 4 characters, no symbols." lineBreakMode="tailTruncation" minimumFontSize="10" id="Zi3-26-3iq">
<rect key="frame" x="20" y="23" width="280" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
@ -161,7 +188,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="ywW-4w-Wej">
<rect key="frame" x="0.0" y="292" width="320" height="44"/>
<rect key="frame" x="0.0" y="338" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -181,7 +208,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="8 characters." lineBreakMode="tailTruncation" minimumFontSize="10" id="CYQ-D8-vNS">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="8 characters, no symbols." lineBreakMode="tailTruncation" minimumFontSize="10" id="CYQ-D8-vNS">
<rect key="frame" x="20" y="23" width="280" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
@ -194,7 +221,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="5p5-OD-zpn">
<rect key="frame" x="0.0" y="336" width="320" height="44"/>
<rect key="frame" x="0.0" y="382" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -230,11 +257,11 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
</tableViewSection>
<tableViewSection id="Jqk-Jl-vVm">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="164" id="OK2-fa-fDw">
<rect key="frame" x="0.0" y="380" width="320" height="164"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="113" id="OK2-fa-fDw">
<rect key="frame" x="0.0" y="426" width="320" height="113"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="163"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="112"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="User-specified" lineBreakMode="tailTruncation" minimumFontSize="10" id="146-3h-mdD">
@ -248,7 +275,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" id="Bbk-lL-BeB">
<rect key="frame" x="20" y="49" width="280" height="63"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<string key="text">If you need to specify a custom password for your site, use one of these types. The site's password will be encrypted using your master password.</string>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
@ -256,13 +283,25 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_list_first.png" id="fxL-ee-UVP">
<rect key="frame" x="10" y="120" width="300" height="44"/>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="44" id="Q2e-yF-SSN">
<rect key="frame" x="0.0" y="539" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_list_first.png" id="rqV-4z-jN8">
<rect key="frame" x="10" y="0.0" width="300" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Personal Password" lineBreakMode="tailTruncation" minimumFontSize="10" id="kzc-rQ-74F">
<rect key="frame" x="20" y="120" width="280" height="24"/>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Personal Password" lineBreakMode="tailTruncation" minimumFontSize="10" id="3I8-qH-HLG">
<rect key="frame" x="20" y="0.0" width="280" height="24"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans" family="Gill Sans" pointSize="18"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
@ -270,8 +309,8 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="AES-encrypted, iTunes backup, iCloud sync." lineBreakMode="tailTruncation" minimumFontSize="10" id="vNa-Yq-XIJ">
<rect key="frame" x="20" y="143" width="280" height="20"/>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="AES-encrypted, iTunes backup, iCloud sync." lineBreakMode="tailTruncation" minimumFontSize="10" id="m6n-Mf-g9m">
<rect key="frame" x="20" y="23" width="280" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
@ -283,7 +322,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="ePk-a9-aNi">
<rect key="frame" x="0.0" y="544" width="320" height="44"/>
<rect key="frame" x="0.0" y="583" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -324,9 +363,6 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
</connections>
</tableView>
<navigationItem key="navigationItem" title="Type" id="rak-Td-wu1"/>
<connections>
<outlet property="recommendedTipContainer" destination="zRU-I1-av9" id="dr4-Hl-iPb"/>
</connections>
</tableViewController>
</objects>
<point key="canvasLocation" x="996" y="182"/>
@ -779,6 +815,25 @@ L4m3P4sSw0rD</string>
<outlet property="delegate" destination="Nbn-Rv-sP1" id="Y0T-cI-gF1"/>
</connections>
</textField>
<view userInteractionEnabled="NO" contentMode="scaleToFill" id="NvG-0R-eTZ">
<rect key="frame" x="35" y="0.0" width="210" height="60"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black.png" id="3se-By-a9W">
<rect key="frame" x="0.0" y="0.0" width="210" height="60"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Incorrect password." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="gQ2-mB-BP4">
<rect key="frame" x="15" y="0.5" width="180" height="40"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
<color key="shadowColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
@ -786,12 +841,12 @@ L4m3P4sSw0rD</string>
<rect key="frame" x="105" y="30" width="110" height="110"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" delaysContentTouches="NO" id="Blg-F1-9NA">
<rect key="frame" x="0.0" y="20" width="320" height="160"/>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" indicatorStyle="white" delaysContentTouches="NO" id="Blg-F1-9NA">
<rect key="frame" x="0.0" y="0.0" width="320" height="200"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" id="Ten-ig-gog">
<rect key="frame" x="105" y="10" width="110" height="110"/>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" showsTouchWhenHighlighted="YES" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="Ten-ig-gog">
<rect key="frame" x="105" y="30" width="110" height="110"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
@ -841,6 +896,8 @@ L4m3P4sSw0rD</string>
<outlet property="nameLabel" destination="0NM-NI-7UR" id="GBg-Ry-sqj"/>
<outlet property="oldNameLabel" destination="8s0-nT-Aoq" id="plu-1H-MVc"/>
<outlet property="passwordField" destination="rTR-7Q-X8o" id="CDA-iP-kCm"/>
<outlet property="passwordTipLabel" destination="gQ2-mB-BP4" id="aHU-tn-duI"/>
<outlet property="passwordTipView" destination="NvG-0R-eTZ" id="4Mx-TL-yfu"/>
<outlet property="passwordView" destination="7cc-yu-i0m" id="WoF-Ab-PPC"/>
<outlet property="spinner" destination="27q-lX-0vy" id="CGK-G9-PRI"/>
</connections>
@ -1266,6 +1323,8 @@ L4m3P4sSw0rD</string>
<relationship kind="outlet" name="nameLabel" candidateClass="UILabel"/>
<relationship kind="outlet" name="oldNameLabel" candidateClass="UILabel"/>
<relationship kind="outlet" name="passwordField" candidateClass="UITextField"/>
<relationship kind="outlet" name="passwordTipLabel" candidateClass="UILabel"/>
<relationship kind="outlet" name="passwordTipView" candidateClass="UIView"/>
<relationship kind="outlet" name="passwordView" candidateClass="UIView"/>
<relationship kind="outlet" name="spinner" candidateClass="UIImageView"/>
</relationships>