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; user.keyID = tryKeyID;
[[MPAppDelegate_Shared get] saveContext]; [[MPAppDelegate_Shared get] saveContext];
} }
user.lastUsed = [NSDate date];
#ifdef TESTFLIGHT_SDK_VERSION #ifdef TESTFLIGHT_SDK_VERSION
[TestFlight passCheckpoint:MPTestFlightCheckpointMPEntered]; [TestFlight passCheckpoint:MPTestFlightCheckpointMPEntered];

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -131,7 +131,7 @@
assert(self.query); assert(self.query);
self.fetchedResultsController.fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(%@ == '' OR name BEGINSWITH[cd] %@) AND user == %@", 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; NSError *error;
if (![self.fetchedResultsController performFetch:&error]) if (![self.fetchedResultsController performFetch:&error])

View File

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

View File

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

View File

@ -30,6 +30,8 @@
@synthesize nameLabel, oldNameLabel; @synthesize nameLabel, oldNameLabel;
@synthesize avatarTemplate; @synthesize avatarTemplate;
@synthesize deleteTip; @synthesize deleteTip;
@synthesize passwordTipView;
@synthesize passwordTipLabel;
@synthesize avatarShadowColor = _avatarShadowColor; @synthesize avatarShadowColor = _avatarShadowColor;
@ -52,6 +54,7 @@
self.nameLabel.layer.cornerRadius = 5; self.nameLabel.layer.cornerRadius = 5;
self.avatarTemplate.hidden = YES; self.avatarTemplate.hidden = YES;
self.spinner.alpha = 0; self.spinner.alpha = 0;
self.passwordTipView.alpha = 0;
[self updateLayoutAnimated:NO allowScroll:YES completion:nil]; [self updateLayoutAnimated:NO allowScroll:YES completion:nil];
@ -67,6 +70,8 @@
[self setNameLabel:nil]; [self setNameLabel:nil];
[self setAvatarTemplate:nil]; [self setAvatarTemplate:nil];
[self setDeleteTip:nil]; [self setDeleteTip:nil];
[self setPasswordTipView:nil];
[self setPasswordTipLabel:nil];
[super viewDidUnload]; [super viewDidUnload];
} }
@ -93,22 +98,23 @@
} }
- (void)updateUsers { - (void)updateUsers {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPUserEntity class])]; NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPUserEntity class])];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO]]; fetchRequest.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO]];
NSArray *users = [[MPAppDelegate managedObjectContext] executeFetchRequest:fetchRequest error:nil]; NSArray *users = [[MPAppDelegate managedObjectContext] executeFetchRequest:fetchRequest error:nil];
// Clean up avatars. // Clean up avatars.
for (UIView *view in [self.avatarsView subviews]) for (UIView *subview in [self.avatarsView subviews])
if (view != self.avatarTemplate) if ([[self.avatarToUser allKeys] containsObject:[NSValue valueWithNonretainedObject:subview]])
[view removeFromSuperview]; // This subview is a former avatar.
[subview removeFromSuperview];
[self.avatarToUser removeAllObjects]; [self.avatarToUser removeAllObjects];
// Create avatars. // Create avatars.
for (MPUserEntity *user in users) for (MPUserEntity *user in users)
[self setupAvatar:[self.avatarTemplate clone] forUser:user]; [self setupAvatar:[self.avatarTemplate clone] forUser:user];
[self setupAvatar:[self.avatarTemplate clone] forUser:nil]; [self setupAvatar:[self.avatarTemplate clone] forUser:nil];
// Scroll view's content changed, update its content size. // Scroll view's content changed, update its content size.
[self.avatarsView autoSizeContentIgnoreHidden:YES ignoreInvisible:YES limitPadding:NO ignoreSubviews:nil]; [self.avatarsView autoSizeContentIgnoreHidden:YES ignoreInvisible:YES limitPadding:NO ignoreSubviews:nil];
@ -147,11 +153,11 @@
avatar.backgroundColor = [UIColor clearColor]; avatar.backgroundColor = [UIColor clearColor];
dbg(@"User: %@, avatar: %d", user.name, user.avatar); dbg(@"User: %@, avatar: %d", user.name, user.avatar);
avatar.tag = user.avatar;
[avatar setBackgroundImage:[UIImage imageNamed:PearlString(@"avatar-%u", user.avatar)] [avatar setBackgroundImage:[UIImage imageNamed:PearlString(@"avatar-%u", user.avatar)]
forState:UIControlStateNormal]; forState:UIControlStateNormal];
if (user) [self.avatarToUser setObject:NilToNSNull(user) forKey:[NSValue valueWithNonretainedObject:avatar]];
[self.avatarToUser setObject:user forKey:[NSValue valueWithNonretainedObject:avatar]];
if (self.selectedUser && user == self.selectedUser) if (self.selectedUser && user == self.selectedUser)
avatar.selected = YES; avatar.selected = YES;
@ -165,8 +171,9 @@
[self.passwordField resignFirstResponder]; [self.passwordField resignFirstResponder];
[self updateLayoutAnimated:YES allowScroll:YES completion:^(BOOL finished) { [self updateLayoutAnimated:YES allowScroll:YES completion:^(BOOL finished) {
if (finished) if (self.selectedUser) if (finished)
[self.passwordField becomeFirstResponder]; if (self.selectedUser)
[self.passwordField becomeFirstResponder];
}]; }];
} }
@ -197,7 +204,7 @@
} }
- (void)updateLayoutAnimated:(BOOL)animated allowScroll:(BOOL)allowScroll completion:(void (^)(BOOL finished))completion { - (void)updateLayoutAnimated:(BOOL)animated allowScroll:(BOOL)allowScroll completion:(void (^)(BOOL finished))completion {
if (animated) { if (animated) {
self.oldNameLabel.text = self.nameLabel.text; self.oldNameLabel.text = self.nameLabel.text;
self.oldNameLabel.alpha = 1; self.oldNameLabel.alpha = 1;
@ -232,7 +239,7 @@
self.oldNameLabel.center = self.nameLabel.center; self.oldNameLabel.center = self.nameLabel.center;
self.avatarShadowColor = [UIColor lightGrayColor]; self.avatarShadowColor = [UIColor lightGrayColor];
} }
MPUserEntity *targetedUser = self.selectedUser; MPUserEntity *targetedUser = self.selectedUser;
UIButton *selectedAvatar = [self avatarForUser:self.selectedUser]; UIButton *selectedAvatar = [self avatarForUser:self.selectedUser];
UIButton *targetedAvatar = selectedAvatar; UIButton *targetedAvatar = selectedAvatar;
@ -242,20 +249,26 @@
} }
[self.avatarsView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) { [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;
BOOL isTargeted = avatar == targetedAvatar;
avatar.userInteractionEnabled = isTargeted;
avatar.alpha = isTargeted ? 1 : self.selectedUser ? 0.1 : 0.4;
subview.userInteractionEnabled = isTargeted; [self updateAvatarShadowColor:avatar isTargeted:isTargeted];
subview.alpha = isTargeted ? 1 : self.selectedUser ? 0.1 : 0.4;
[self updateAvatarShadowColor:subview isTargeted:isTargeted];
} recurse:NO]; } recurse:NO];
if (allowScroll) { 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)) if (!CGPointEqualToPoint(self.avatarsView.contentOffset, targetContentOffset))
[self.avatarsView setContentOffset:targetContentOffset animated:animated]; [self.avatarsView setContentOffset:targetContentOffset animated:animated];
} }
self.nameLabel.text = targetedUser ? targetedUser.name : @"New User"; self.nameLabel.text = targetedUser ? targetedUser.name : @"New User";
self.nameLabel.bounds = CGRectSetHeight(self.nameLabel.bounds, self.nameLabel.bounds = CGRectSetHeight(self.nameLabel.bounds,
[self.nameLabel.text sizeWithFont:self.nameLabel.font [self.nameLabel.text sizeWithFont:self.nameLabel.font
@ -266,23 +279,30 @@
completion(YES); 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 { - (void)tryMasterPassword {
[self setSpinnerActive:YES]; [self setSpinnerActive:YES];
[self changeAvatarShadowColorTo:[UIColor colorWithName:@"lightskyblue"]];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
BOOL unlocked = [[MPAppDelegate get] tryMasterPassword:self.passwordField.text forUser:self.selectedUser]; BOOL unlocked = [[MPAppDelegate get] tryMasterPassword:self.passwordField.text forUser:self.selectedUser];
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
if (unlocked) { if (unlocked) {
[self changeAvatarShadowColorTo:[UIColor colorWithName:@"greenyellow"]]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long) (NSEC_PER_SEC * 0.5f)), dispatch_get_main_queue(), ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long) (NSEC_PER_SEC * 1.5f)), dispatch_get_main_queue(), ^{
[self dismissModalViewControllerAnimated:YES]; [self dismissModalViewControllerAnimated:YES];
}); });
} else } else
[self changeAvatarShadowColorTo:[UIColor colorWithName:@"crimson"]]; [self setPasswordTip:@"Incorrect password."];
[self setSpinnerActive:NO]; [self setSpinnerActive:NO];
}); });
@ -309,7 +329,7 @@
- (MPUserEntity *)userForAvatar:(UIButton *)avatar { - (MPUserEntity *)userForAvatar:(UIButton *)avatar {
return NullToNil([self.avatarToUser objectForKey:[NSValue valueWithNonretainedObject:avatar]]); return NSNullToNil([self.avatarToUser objectForKey:[NSValue valueWithNonretainedObject:avatar]]);
} }
- (void)setSpinnerActive:(BOOL)active { - (void)setSpinnerActive:(BOOL)active {
@ -342,23 +362,12 @@
}); });
} }
- (void)changeAvatarShadowColorTo:(UIColor *)color { - (void)updateAvatarShadowColor:(UIButton *)avatar isTargeted:(BOOL)targeted {
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 {
if (targeted) { if (targeted) {
if (![avatar.layer animationForKey:@"targetedShadow"]) { if (![avatar.layer animationForKey:@"targetedShadow"]) {
CABasicAnimation *toShadowColorAnimation = [CABasicAnimation animationWithKeyPath:@"shadowColor"]; 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.beginTime = 0.0f;
toShadowColorAnimation.duration = 0.5f; toShadowColorAnimation.duration = 0.5f;
toShadowColorAnimation.fillMode = kCAFillModeForwards; toShadowColorAnimation.fillMode = kCAFillModeForwards;
@ -404,13 +413,17 @@
#pragma mark - UITextFieldDelegate #pragma mark - UITextFieldDelegate
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[self setPasswordTip:nil];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField { - (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder]; [textField resignFirstResponder];
[self setSpinnerActive:YES]; [self setSpinnerActive:YES];
[self changeAvatarShadowColorTo:[UIColor colorWithName:@"lightskyblue"]];
if (self.selectedUser.keyID) if (self.selectedUser.keyID)
[self tryMasterPassword]; [self tryMasterPassword];
@ -463,11 +476,7 @@
- (void)scrollViewDidScroll:(UIScrollView *)scrollView { - (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 updateLayoutAnimated:NO allowScroll:NO completion:nil];
// [self scrollToAvatar:middleAvatar animated:NO];
} }
#pragma mark - IBActions #pragma mark - IBActions

View File

@ -16,18 +16,18 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.12549020350000001" green="0.1411764771" blue="0.14901961389999999" alpha="1" colorSpace="calibratedRGB"/> <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"> <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"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view> </view>
<sections> <sections>
<tableViewSection id="gUv-FU-O36"> <tableViewSection id="gUv-FU-O36">
<cells> <cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="204" id="NCB-rX-weq"> <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="204"/> <rect key="frame" x="0.0" y="0.0" width="320" height="162"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> <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"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Generated" lineBreakMode="tailTruncation" minimumFontSize="10" id="azh-GA-KA1"> <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"/> <color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/> <size key="shadowOffset" width="0.0" height="1"/>
</label> </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"> <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"/> <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. <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> 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"/> <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"/> <color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/> <size key="shadowOffset" width="0.0" height="1"/>
</label> </label>
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" id="zRU-I1-av9"> </subviews>
<rect key="frame" x="55" y="123" width="210" height="60"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/> </view>
<subviews> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black.png" id="HHn-56-thS"> </tableViewCell>
<rect key="frame" x="0.0" y="0.0" width="210" height="60"/> <tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="44" id="PBE-wW-HXv">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <rect key="frame" x="0.0" y="162" width="320" height="44"/>
</imageView> <autoresizingMask key="autoresizingMask"/>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Safest and recommended." textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" id="lND-JD-bF8"> <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="20" y="0.0" width="171" height="40"/> <rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/> <subviews>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/> <imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_list_first.png" id="Uw9-CC-Snk">
<nil key="highlightedColor"/> <rect key="frame" x="10" y="0.0" width="300" height="44"/>
</label> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
</subviews> <rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> </imageView>
</view> <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> </subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view> </view>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell> </tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="re0-ZT-bnP"> <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"/> <autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/> <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"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell> </tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="4pb-c9-i2D"> <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"/> <autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/> <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"/> <color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/> <size key="shadowOffset" width="0.0" height="1"/>
</label> </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"/> <rect key="frame" x="20" y="23" width="280" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/> <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"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell> </tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="ywW-4w-Wej"> <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"/> <autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/> <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"/> <color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/> <size key="shadowOffset" width="0.0" height="1"/>
</label> </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"/> <rect key="frame" x="20" y="23" width="280" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/> <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"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell> </tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="5p5-OD-zpn"> <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"/> <autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/> <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>
<tableViewSection id="Jqk-Jl-vVm"> <tableViewSection id="Jqk-Jl-vVm">
<cells> <cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="164" id="OK2-fa-fDw"> <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="380" width="320" height="164"/> <rect key="frame" x="0.0" y="426" width="320" height="113"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> <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"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="User-specified" lineBreakMode="tailTruncation" minimumFontSize="10" id="146-3h-mdD"> <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>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" id="Bbk-lL-BeB"> <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"/> <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> <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"/> <fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <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"/> <color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/> <size key="shadowOffset" width="0.0" height="1"/>
</label> </label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_list_first.png" id="fxL-ee-UVP"> </subviews>
<rect key="frame" x="10" y="120" width="300" height="44"/> <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"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/> <rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/>
</imageView> </imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Personal Password" lineBreakMode="tailTruncation" minimumFontSize="10" id="kzc-rQ-74F"> <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="120" width="280" height="24"/> <rect key="frame" x="20" y="0.0" width="280" height="24"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans" family="Gill Sans" pointSize="18"/> <fontDescription key="fontDescription" name="GillSans" family="Gill Sans" pointSize="18"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <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"/> <color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/> <size key="shadowOffset" width="0.0" height="1"/>
</label> </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"> <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="143" width="280" height="20"/> <rect key="frame" x="20" y="23" width="280" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/> <fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/> <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"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell> </tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="ePk-a9-aNi"> <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"/> <autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/> <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> </connections>
</tableView> </tableView>
<navigationItem key="navigationItem" title="Type" id="rak-Td-wu1"/> <navigationItem key="navigationItem" title="Type" id="rak-Td-wu1"/>
<connections>
<outlet property="recommendedTipContainer" destination="zRU-I1-av9" id="dr4-Hl-iPb"/>
</connections>
</tableViewController> </tableViewController>
</objects> </objects>
<point key="canvasLocation" x="996" y="182"/> <point key="canvasLocation" x="996" y="182"/>
@ -779,6 +815,25 @@ L4m3P4sSw0rD</string>
<outlet property="delegate" destination="Nbn-Rv-sP1" id="Y0T-cI-gF1"/> <outlet property="delegate" destination="Nbn-Rv-sP1" id="Y0T-cI-gF1"/>
</connections> </connections>
</textField> </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> </subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view> </view>
@ -786,12 +841,12 @@ L4m3P4sSw0rD</string>
<rect key="frame" x="105" y="30" width="110" height="110"/> <rect key="frame" x="105" y="30" width="110" height="110"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView> </imageView>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" delaysContentTouches="NO" id="Blg-F1-9NA"> <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="20" width="320" height="160"/> <rect key="frame" x="0.0" y="0.0" width="320" height="200"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews> <subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" id="Ten-ig-gog"> <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="10" width="110" height="110"/> <rect key="frame" x="105" y="30" width="110" height="110"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/> <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/> <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="nameLabel" destination="0NM-NI-7UR" id="GBg-Ry-sqj"/>
<outlet property="oldNameLabel" destination="8s0-nT-Aoq" id="plu-1H-MVc"/> <outlet property="oldNameLabel" destination="8s0-nT-Aoq" id="plu-1H-MVc"/>
<outlet property="passwordField" destination="rTR-7Q-X8o" id="CDA-iP-kCm"/> <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="passwordView" destination="7cc-yu-i0m" id="WoF-Ab-PPC"/>
<outlet property="spinner" destination="27q-lX-0vy" id="CGK-G9-PRI"/> <outlet property="spinner" destination="27q-lX-0vy" id="CGK-G9-PRI"/>
</connections> </connections>
@ -1266,6 +1323,8 @@ L4m3P4sSw0rD</string>
<relationship kind="outlet" name="nameLabel" candidateClass="UILabel"/> <relationship kind="outlet" name="nameLabel" candidateClass="UILabel"/>
<relationship kind="outlet" name="oldNameLabel" candidateClass="UILabel"/> <relationship kind="outlet" name="oldNameLabel" candidateClass="UILabel"/>
<relationship kind="outlet" name="passwordField" candidateClass="UITextField"/> <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="passwordView" candidateClass="UIView"/>
<relationship kind="outlet" name="spinner" candidateClass="UIImageView"/> <relationship kind="outlet" name="spinner" candidateClass="UIImageView"/>
</relationships> </relationships>