2
0

Listing all sites now with bookmark button and modal VC.

[ADDED]     Modal VC to show all sites.
[UPDATED]   All sites button on search bar now uses bookmark button.
[REMOVED]   Query string hack for search results button.
This commit is contained in:
Maarten Billemont 2013-02-01 01:13:45 -05:00
parent 2bb0e2e3ef
commit 9a68cbf533
18 changed files with 601 additions and 101 deletions

View File

@ -17,6 +17,7 @@
93D399433EA75E50656040CB /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D394077F8FAB8167647187 /* Twitter.framework */; };
93D399B873AF89808151D2F5 /* MPAppsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D390DABAE4368E90E37340 /* MPAppsViewController.m */; };
93D39BCE5F69D8EBE7E9F6EC /* MPAppViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39E070BD3F45B3045A1DA /* MPAppViewController.m */; };
93D39BD0F5C7C76678712500 /* MPAllSitesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39F16ADA770D8C13B4555 /* MPAllSitesViewController.m */; };
93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; };
93D39DC7A7282137B08C8D82 /* MPAlgorithmV1.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39E9D7B9005211E7D5262 /* MPAlgorithmV1.m */; };
93D39E281E3658B30550CB55 /* NSDictionary+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */; };
@ -972,6 +973,7 @@
/* Begin PBXFileReference section */
93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Indexing.m"; sourceTree = "<group>"; };
93D390B3209212B3049BEC2D /* MPAllSitesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAllSitesViewController.h; sourceTree = "<group>"; };
93D390DABAE4368E90E37340 /* MPAppsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppsViewController.m; sourceTree = "<group>"; };
93D3938863322199C3E7E2E3 /* MPAlgorithmV0.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV0.m; sourceTree = "<group>"; };
93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = "<group>"; };
@ -989,6 +991,8 @@
93D39E070BD3F45B3045A1DA /* MPAppViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppViewController.m; sourceTree = "<group>"; };
93D39E81EFABC6085AC8AE69 /* MPKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPKey.m; sourceTree = "<group>"; };
93D39E9D7B9005211E7D5262 /* MPAlgorithmV1.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV1.m; sourceTree = "<group>"; };
93D39F16ADA770D8C13B4555 /* MPAllSitesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAllSitesViewController.m; sourceTree = "<group>"; };
93D39F37240730C6311B8FBD /* MPElementPickerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementPickerDelegate.h; sourceTree = "<group>"; };
93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlEMail.h; sourceTree = "<group>"; };
DA04E33D14B1E70400ECA4F3 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
DA0A1D0315690A9A0092735D /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Default.png; path = Resources/Default.png; sourceTree = SOURCE_ROOT; };
@ -2542,6 +2546,9 @@
DAB8D45215036BCF00CED3BC /* MPUnlockViewController.h */,
DAB8D45315036BCF00CED3BC /* MPUnlockViewController.m */,
DAB8D45415036BCF00CED3BC /* Settings.bundle */,
93D39F16ADA770D8C13B4555 /* MPAllSitesViewController.m */,
93D390B3209212B3049BEC2D /* MPAllSitesViewController.h */,
93D39F37240730C6311B8FBD /* MPElementPickerDelegate.h */,
);
path = iOS;
sourceTree = "<group>";
@ -4716,6 +4723,7 @@
DA81253816B8546B00F4732F /* MPElementStoredEntity.m in Sources */,
DA81253B16B8546B00F4732F /* MPUserEntity.m in Sources */,
DA81253E16B8546C00F4732F /* MPElementGeneratedEntity.m in Sources */,
93D39BD0F5C7C76678712500 /* MPAllSitesViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -18,6 +18,8 @@
@property (strong, nonatomic) MPUserEntity *activeUser;
@property (strong, nonatomic) MPKey *key;
+ (instancetype)get;
- (MPUserEntity *)activeUserInContext:(NSManagedObjectContext *)moc;
@end

View File

@ -28,9 +28,4 @@
return self;
}
+ (MPConfig *)get {
return (MPConfig *)[super get];
}
@end

View File

@ -42,11 +42,6 @@ static EventHotKeyID MPLockHotKey = {.signature = 'lock', .id = 1};
});
}
+ (MPAppDelegate *)get {
return (MPAppDelegate *)[super get];
}
static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData) {
// Extract the hotkey ID.

View File

@ -20,9 +20,4 @@
return self;
}
+ (MPMacConfig *)get {
return (MPMacConfig *)[super get];
}
@end

View File

@ -0,0 +1,28 @@
/**
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
*
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
//
// MPAllSitesViewController
//
// Created by Maarten Billemont on 2013-01-31.
// Copyright 2013 lhunath (Maarten Billemont). All rights reserved.
//
#import <Foundation/Foundation.h>
#import "MPElementPickerDelegate.h"
@interface MPAllSitesViewController : UITableViewController
@property (weak, nonatomic) IBOutlet id<MPElementPickerDelegate> delegate;
- (IBAction)close:(id)sender;
@end

View File

@ -0,0 +1,240 @@
/**
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
*
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
//
// MPAllSitesViewController
//
// Created by Maarten Billemont on 2013-01-31.
// Copyright 2013 lhunath (Maarten Billemont). All rights reserved.
//
#import "MPAllSitesViewController.h"
#import "MPAppDelegate.h"
#import "MPAppDelegate_Store.h"
@interface MPAllSitesViewController() <NSFetchedResultsControllerDelegate>
@property (nonatomic,strong)NSDateFormatter *dateFormatter;
@end
@implementation MPAllSitesViewController {
NSFetchedResultsController *_fetchedResultsController;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.dateFormatter = [NSDateFormatter new];
self.dateFormatter.dateStyle = NSDateFormatterShortStyle;
}
- (IBAction)close:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (NSFetchedResultsController *)fetchedResultsController {
if (!_fetchedResultsController) {
NSAssert([[NSThread currentThread] isMainThread], @"The fetchedResultsController must run on the main thread.");
NSManagedObjectContext *moc = [MPAppDelegate managedObjectContextForThreadIfReady];
if (!moc)
return nil;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
fetchRequest.sortDescriptors = @[[[NSSortDescriptor alloc] initWithKey:@"uses_" ascending:NO]];
fetchRequest.fetchBatchSize = 20;
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:moc
sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self;
}
return _fetchedResultsController;
}
- (void)fetchData {
MPUserEntity *activeUser = [MPAppDelegate get].activeUser;
if (!activeUser)
return;
self.fetchedResultsController.fetchRequest.predicate = [NSPredicate predicateWithFormat:@"user == %@", activeUser];
NSError *error;
if (![self.fetchedResultsController performFetch:&error])
err(@"Couldn't fetch elements: %@", error);
[self.tableView reloadData];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self fetchData];
}
// See MP-14, also crashes easily on internal assertions etc..
//- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
//
// [self.searchDisplayController.searchResultsTableView beginUpdates];
//}
//
//- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
// atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
//
// UITableView *tableView = self.searchDisplayController.searchResultsTableView;
// switch(type) {
//
// case NSFetchedResultsChangeInsert:
// [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
// break;
//
// case NSFetchedResultsChangeDelete:
// [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
// break;
//
// case NSFetchedResultsChangeUpdate:
// [self configureCell:[tableView cellForRowAtIndexPath:indexPath]
// inTableView:tableView atIndexPath:indexPath];
// break;
//
// case NSFetchedResultsChangeMove:
// [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
// withRowAnimation:UITableViewRowAnimationFade];
// [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
// withRowAnimation:UITableViewRowAnimationFade];
// break;
// }
//}
//
//
//- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo
// atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
//
// UITableView *tableView = self.searchDisplayController.searchResultsTableView;
// switch(type) {
//
// case NSFetchedResultsChangeInsert:
// [tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
// withRowAnimation:UITableViewRowAnimationFade];
// break;
//
// case NSFetchedResultsChangeDelete:
// [tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
// withRowAnimation:UITableViewRowAnimationFade];
// break;
// }
//}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
dbg(@"controllerDidChangeContent on thread: %@", [NSThread currentThread].name);
[self.tableView reloadData];
//[self.tableView endUpdates];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return (NSInteger)[[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return (NSInteger)[[[self.fetchedResultsController sections] objectAtIndex:(unsigned)section] numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MPElementSearch"];
if (!cell.backgroundView) {
// cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MPElementSearch"];
UIImage *backgroundImage = [[UIImage imageNamed:@"ui_list_middle"] resizableImageWithCapInsets:UIEdgeInsetsMake(3, 3, 3, 3)
resizingMode:UIImageResizingModeStretch];
UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:backgroundImage];
backgroundImageView.frame = CGRectMake(-5, 0, 330, 34);
backgroundImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
UIView *backgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 34)];
[backgroundView addSubview:backgroundImageView];
backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
cell.backgroundView = backgroundView;
// cell.textLabel.backgroundColor = [UIColor clearColor];
// cell.textLabel.textColor = [UIColor whiteColor];
// cell.detailTextLabel.backgroundColor = [UIColor clearColor];
// cell.detailTextLabel.textColor = [UIColor lightGrayColor];
// cell.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
// cell.clipsToBounds = YES;
}
[self configureCell:cell inTableView:tableView atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath {
MPElementEntity *element = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = element.name;
cell.detailTextLabel.text = PearlString(@"Used %d times, last on %@",
element.uses, [self.dateFormatter stringFromDate:element.lastUsed]);
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.delegate didSelectElement:[self.fetchedResultsController objectAtIndexPath:indexPath]];
[self close:nil];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [[[self.fetchedResultsController sections] objectAtIndex:(unsigned)section] name];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return [self.fetchedResultsController sectionIndexTitles];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return [self.fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete)
[self.fetchedResultsController.managedObjectContext performBlock:^{
MPElementEntity *element = [self.fetchedResultsController objectAtIndexPath:indexPath];
inf(@"Deleting element: %@", element.name);
[self.fetchedResultsController.managedObjectContext deleteObject:element];
#ifdef TESTFLIGHT_SDK_VERSION
[TestFlight passCheckpoint:MPCheckpointDeleteElement];
#endif
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointDeleteElement attributes:@{
@"type" : element.typeName,
@"version" : @(element.version)}];
}];
}
@end

View File

@ -92,6 +92,16 @@
[super viewWillDisappear:animated];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate {
return NO;
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController {

View File

@ -0,0 +1,24 @@
/**
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
*
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
//
// MPElementPickerDelegate
//
// Created by Maarten Billemont on 2013-01-31.
// Copyright 2013 lhunath (Maarten Billemont). All rights reserved.
//
#import "MPElementEntity.h"
@protocol MPElementPickerDelegate<NSObject>
- (void)didSelectElement:(MPElementEntity *)element;
@end

View File

@ -10,7 +10,7 @@
#import "MPTypeViewController.h"
#import "MPSearchDelegate.h"
@interface MPMainViewController : UIViewController<MPTypeDelegate, UITextFieldDelegate, MPSearchResultsDelegate, UIWebViewDelegate, UIGestureRecognizerDelegate>
@interface MPMainViewController : UIViewController<MPTypeDelegate, UITextFieldDelegate, MPElementPickerDelegate, UIWebViewDelegate, UIGestureRecognizerDelegate>
@property (assign, nonatomic) BOOL siteInfoHidden;
@property (strong, nonatomic) IBOutlet MPSearchDelegate *searchDelegate;

View File

@ -10,6 +10,7 @@
#import "MPAppDelegate.h"
#import "MPAppDelegate_Key.h"
#import "MPAppDelegate_Store.h"
#import "MPAllSitesViewController.h"
@interface MPMainViewController()
@ -48,6 +49,8 @@
if ([[segue identifier] isEqualToString:@"MP_ChooseType"])
((MPTypeViewController *)[segue destinationViewController]).delegate = self;
if ([[segue identifier] isEqualToString:@"MP_AllSites"])
((MPAllSitesViewController *)[((UINavigationController *)[segue destinationViewController]) topViewController]).delegate = self;
}
- (void)viewDidLoad {
@ -753,12 +756,12 @@
}
case 2: {
inf(@"Action: Preferences");
[self performSegueWithIdentifier:@"UserProfile" sender:self];
[self performSegueWithIdentifier:@"MP_UserProfile" sender:self];
break;
}
case 3: {
inf(@"Action: Other Apps");
[self performSegueWithIdentifier:@"OtherApps" sender:self];
[self performSegueWithIdentifier:@"MP_OtherApps" sender:self];
break;
}
//#if defined(ADHOC) && defined(TESTFLIGHT_SDK_VERSION)

View File

@ -7,27 +7,22 @@
//
#import <Foundation/Foundation.h>
#import "MPElementEntity.h"
#import "MPElementPickerDelegate.h"
typedef enum {
MPSearchScopeAll,
MPSearchScopeOutdated,
} MPSearchScope;
@protocol MPSearchResultsDelegate<NSObject>
- (void)didSelectElement:(MPElementEntity *)element;
@end
@interface MPSearchDelegate : NSObject<UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, UISearchDisplayDelegate, NSFetchedResultsControllerDelegate>
@property (strong, nonatomic) NSDateFormatter *dateFormatter;
@property (strong, readonly) NSFetchedResultsController *fetchedResultsController;
@property (strong, nonatomic) NSString *query;
@property (strong, nonatomic) UILabel *tipView;
@property (weak, nonatomic) IBOutlet id<MPSearchResultsDelegate> delegate;
@property (weak, nonatomic) IBOutlet id<MPElementPickerDelegate> delegate;
@property (strong, nonatomic) IBOutlet UISearchDisplayController *searchDisplayController;
@property (weak, nonatomic) IBOutlet UIView *searchTipContainer;

View File

@ -9,12 +9,7 @@
#import "MPSearchDelegate.h"
#import "MPAppDelegate.h"
#import "MPAppDelegate_Store.h"
@interface MPSearchDelegate (Private)
- (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath;
@end
#import "MPMainViewController.h"
@implementation MPSearchDelegate {
@ -28,7 +23,6 @@
self.dateFormatter = [NSDateFormatter new];
self.dateFormatter.dateStyle = NSDateFormatterShortStyle;
self.query = @"";
self.tipView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 170)];
self.tipView.textAlignment = NSTextAlignmentCenter;
@ -60,6 +54,7 @@
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
fetchRequest.sortDescriptors = @[[[NSSortDescriptor alloc] initWithKey:@"uses_" ascending:NO]];
fetchRequest.fetchBatchSize = 20;
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:moc
sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self;
@ -68,6 +63,11 @@
return _fetchedResultsController;
}
- (void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar {
[((MPMainViewController *)self.delegate) performSegueWithIdentifier:@"MP_AllSites" sender:self];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
UITableView *tableView = self.searchDisplayController.searchResultsTableView;
@ -89,12 +89,6 @@
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (searchBar.searchResultsButtonSelected && !searchText.length)
searchBar.text = @" ";
self.query = [searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if (!self.query)
self.query = @"";
}
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
@ -113,8 +107,6 @@
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
controller.searchBar.text = controller.searchBar.searchResultsButtonSelected? @" ": @"";
self.query = @"";
}
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
@ -154,24 +146,23 @@
- (void)fetchData {
NSString *query = [self.searchDisplayController.searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if (!query)
return;
MPUserEntity *activeUser = [MPAppDelegate get].activeUser;
assert(self.query);
assert(activeUser);
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"user == %@", activeUser];
if (self.query.length)
predicate = [NSCompoundPredicate
andPredicateWithSubpredicates:@[[NSPredicate predicateWithFormat:@"name BEGINSWITH[cd] %@", self.query],
predicate]];
if (!activeUser)
return;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"user == %@ AND name BEGINSWITH[cd] %@", activeUser, query];
switch ((MPSearchScope)self.searchDisplayController.searchBar.selectedScopeButtonIndex) {
case MPSearchScopeAll:
break;
case MPSearchScopeOutdated:
predicate = [NSCompoundPredicate
andPredicateWithSubpredicates:@[[NSPredicate predicateWithFormat:@"requiresExplicitMigration_ == YES"],
predicate]];
andPredicateWithSubpredicates:@[[NSPredicate predicateWithFormat:@"requiresExplicitMigration_ == YES"], predicate]];
break;
}
self.fetchedResultsController.fetchRequest.predicate = predicate;
@ -258,12 +249,13 @@
NSArray *sections = [self.fetchedResultsController sections];
NSUInteger sectionCount = [sections count];
if ([self.query length]) {
NSString *query = [self.searchDisplayController.searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if ([query length]) {
__block BOOL hasExactQueryMatch = NO;
[sections enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
id<NSFetchedResultsSectionInfo> sectionInfo = obj;
[[sectionInfo objects] enumerateObjectsUsingBlock:^(id obj_, NSUInteger idx_, BOOL *stop_) {
if ([[obj_ name] isEqualToString:self.query]) {
if ([[obj_ name] isEqualToString:query]) {
hasExactQueryMatch = YES;
*stop_ = YES;
}
@ -327,7 +319,8 @@
element.uses, [self.dateFormatter stringFromDate:element.lastUsed]];
} else {
// "New" section
cell.textLabel.text = self.query;
NSString *query = [self.searchDisplayController.searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
cell.textLabel.text = query;
cell.detailTextLabel.text = @"Create a new site.";
}
}
@ -339,7 +332,7 @@
else {
// "New" section.
NSString *siteName = self.query;
NSString *siteName = [self.searchDisplayController.searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
[PearlAlert showAlertWithTitle:@"New Site"
message:PearlString(@"Do you want to create a new site named:\n%@", siteName)
viewStyle:UIAlertViewStyleDefault

View File

@ -496,7 +496,6 @@
// Lay out user name label.
self.nameLabel.text = targetedAvatar? (targetedUser? targetedUser.name: @"New User"): nil;
dbg(@"targetedAvatar: %@, targetedUser: %@, nameLabel: %@", targetedAvatar, targetedUser, self.nameLabel.text);
self.nameLabel.bounds = CGRectSetHeight(self.nameLabel.bounds,
[self.nameLabel.text sizeWithFont:self.nameLabel.font
constrainedToSize:CGSizeMake(self.nameLabel.bounds.size.width - 10, 100)

View File

@ -25,9 +25,4 @@
return self;
}
+ (MPiOSConfig *)get {
return (MPiOSConfig *)[super get];
}
@end

View File

@ -633,7 +633,7 @@ Your passwords will be AES-encrypted with your master password.</string>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<searchBar contentMode="redraw" barStyle="blackOpaque" placeholder="Site name" showsSearchResultsButton="YES" id="qeo-n2-WVh">
<searchBar contentMode="redraw" barStyle="blackOpaque" placeholder="Site name" showsBookmarkButton="YES" id="qeo-n2-WVh">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<gestureRecognizers/>
@ -643,25 +643,6 @@ Your passwords will be AES-encrypted with your master password.</string>
<string>Outdated</string>
</scopeButtonTitles>
</searchBar>
<view userInteractionEnabled="NO" contentMode="scaleToFill" id="zOR-Du-qRL" userLabel="View - Search Tip">
<rect key="frame" x="10" y="15" width="300" height="60"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black_top.png" id="ORD-Xv-bOQ">
<rect key="frame" x="0.0" y="0.0" width="300" height="60"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<rect key="contentStretch" x="0.15000000000000002" y="0.15000000000000002" width="0.69999999999999973" height="0.69999999999999973"/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Begin by entering the name of your site." textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" id="21b-bH-lR9">
<rect key="frame" x="-20" y="26" width="340" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<view userInteractionEnabled="NO" contentMode="scaleToFill" id="foz-tW-xGw" userLabel="View - Action Tip">
<rect key="frame" x="10" y="0.0" width="300" height="60"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
@ -685,6 +666,25 @@ Your passwords will be AES-encrypted with your master password.</string>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<view userInteractionEnabled="NO" contentMode="scaleToFill" id="zOR-Du-qRL" userLabel="View - Search Tip">
<rect key="frame" x="10" y="15" width="300" height="60"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black_top.png" id="ORD-Xv-bOQ">
<rect key="frame" x="0.0" y="0.0" width="300" height="60"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<rect key="contentStretch" x="0.15000000000000002" y="0.15000000000000002" width="0.69999999999999973" height="0.69999999999999973"/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Begin by entering the name of your site." textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" id="21b-bH-lR9">
<rect key="frame" x="-20" y="26" width="340" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<view userInteractionEnabled="NO" contentMode="scaleToFill" id="UM8-56-kAO" userLabel="View - Tool Tip">
<rect key="frame" x="10" y="15" width="266" height="60"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
@ -935,8 +935,9 @@ L4m3P4sSw0rD</string>
<outlet property="toolTipEditIcon" destination="KEn-n3-qhX" id="zEV-tR-Egq"/>
<outlet property="typeButton" destination="xYM-e3-BMg" id="xvn-nR-MRV"/>
<outlet property="typeTipContainer" destination="g55-0m-WjS" id="KZ9-KV-NMh"/>
<segue destination="oLN-6u-GLb" kind="push" identifier="UserProfile" id="tKN-Sw-S5J"/>
<segue destination="2Th-Tb-22a" kind="modal" identifier="OtherApps" id="Io5-cz-v9Y"/>
<segue destination="oLN-6u-GLb" kind="push" identifier="MP_UserProfile" id="tKN-Sw-S5J"/>
<segue destination="2Th-Tb-22a" kind="modal" identifier="MP_OtherApps" id="Io5-cz-v9Y"/>
<segue destination="KZ9-Bb-FN7" kind="modal" identifier="MP_AllSites" id="18w-AW-e8A"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="mK2-p1-3zC" userLabel="First Responder" sceneMemberID="firstResponder"/>
@ -1214,7 +1215,7 @@ Pink fluffy door frame.</string>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="hkm-U7-Dm7" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="463" y="-381"/>
<point key="canvasLocation" x="455" y="-381"/>
</scene>
<!--Unlock View Controller-->
<scene sceneID="HkH-JR-Fhy">
@ -1628,6 +1629,77 @@ You could use the word wall for inspiration in finding a memorable master passw
</objects>
<point key="canvasLocation" x="455" y="1425"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="rAg-OU-9QV">
<objects>
<navigationController definesPresentationContext="YES" id="KZ9-Bb-FN7" sceneMemberID="viewController">
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" barStyle="blackOpaque" prompted="NO"/>
<navigationBar key="navigationBar" contentMode="scaleToFill" barStyle="blackOpaque" id="s0n-kY-htJ">
<rect key="frame" x="0.0" y="-44" width="0.0" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="idA-Pj-1U9" kind="relationship" relationship="rootViewController" id="dmZ-bA-SbA"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="vJs-4S-qNG" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="996" y="1425"/>
</scene>
<!--All Sites View Controller - All Sites-->
<scene sceneID="I7c-vt-d2s">
<objects>
<tableViewController id="idA-Pj-1U9" customClass="MPAllSitesViewController" sceneMemberID="viewController">
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="48" sectionHeaderHeight="22" sectionFooterHeight="22" id="N83-sj-4tl">
<rect key="frame" x="0.0" y="64" width="320" height="416"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="MPElementSearch" textLabel="UGt-vQ-i5K" detailTextLabel="Xv8-kG-Tap" style="IBUITableViewCellStyleSubtitle" id="3eb-mJ-xFj">
<rect key="frame" x="0.0" y="22" width="320" height="48"/>
<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="47"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="UGt-vQ-i5K">
<rect key="frame" x="10" y="4" width="38" height="22"/>
<autoresizingMask key="autoresizingMask"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="18"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</label>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="Subtitle" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Xv8-kG-Tap">
<rect key="frame" x="10" y="26" width="47" height="18"/>
<autoresizingMask key="autoresizingMask"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="idA-Pj-1U9" id="yPh-6k-Ba9"/>
<outlet property="delegate" destination="idA-Pj-1U9" id="bdk-Iu-Hpv"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="All Sites" id="Ipv-Tt-WPc">
<barButtonItem key="leftBarButtonItem" systemItem="cancel" id="Mnn-6X-DgP">
<connections>
<action selector="close:" destination="idA-Pj-1U9" id="qqC-U7-8Ci"/>
</connections>
</barButtonItem>
</navigationItem>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="abw-PC-pyQ" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1537" y="1425"/>
</scene>
<!--Apps View Controller-->
<scene sceneID="3cC-Qq-rgU">
<objects>
@ -2077,13 +2149,13 @@ You could use the word wall for inspiration in finding a memorable master passw
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="LHv-Mk-8Kp" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1004" y="-381"/>
<point key="canvasLocation" x="996" y="-381"/>
</scene>
</scenes>
<resources>
<image name="Square-bottom.png" width="551" height="58"/>
<image name="avatar-0.png" width="110" height="110"/>
<image name="background.png" width="480" height="480"/>
<image name="background.png" width="568" height="568"/>
<image name="book.png" width="320" height="480"/>
<image name="guide_page_0.png" width="320" height="480"/>
<image name="guide_page_1.png" width="320" height="480"/>
@ -2121,6 +2193,146 @@ You could use the word wall for inspiration in finding a memorable master passw
<image name="ui_spinner.png" width="75" height="75"/>
<image name="ui_textfield.png" width="158" height="34"/>
</resources>
<classes>
<class className="MPAllSitesViewController" superclassName="UITableViewController">
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPAllSitesViewController.h"/>
<relationships>
<relationship kind="action" name="close:"/>
<relationship kind="outlet" name="delegate"/>
</relationships>
</class>
<class className="MPAppViewController" superclassName="UIViewController">
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPAppViewController.h"/>
<relationships>
<relationship kind="action" name="deblock:" candidateClass="UIButton"/>
<relationship kind="action" name="gorillas:" candidateClass="UIButton"/>
</relationships>
</class>
<class className="MPAppsViewController" superclassName="UIViewController">
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPAppsViewController.h"/>
<relationships>
<relationship kind="action" name="exit"/>
<relationship kind="outlet" name="pagePositionView" candidateClass="UIImageView"/>
</relationships>
</class>
<class className="MPGuideViewController" superclassName="UIViewController">
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPGuideViewController.h"/>
<relationships>
<relationship kind="action" name="close"/>
<relationship kind="outlet" name="pageControl" candidateClass="UIPageControl"/>
<relationship kind="outlet" name="scrollView" candidateClass="UIScrollView"/>
</relationships>
</class>
<class className="MPMainViewController" superclassName="UIViewController">
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPMainViewController.h"/>
<relationships>
<relationship kind="action" name="action:" candidateClass="UIBarButtonItem"/>
<relationship kind="action" name="closeAlert"/>
<relationship kind="action" name="closeOutdatedAlert"/>
<relationship kind="action" name="copyContent"/>
<relationship kind="action" name="editLoginName:" candidateClass="UILongPressGestureRecognizer"/>
<relationship kind="action" name="editPassword"/>
<relationship kind="action" name="incrementPasswordCounter"/>
<relationship kind="action" name="infoOutdatedAlert"/>
<relationship kind="action" name="panHelpDown:" candidateClass="UIPanGestureRecognizer"/>
<relationship kind="action" name="panHelpUp:" candidateClass="UIPanGestureRecognizer"/>
<relationship kind="action" name="resetPasswordCounter:" candidateClass="UILongPressGestureRecognizer"/>
<relationship kind="action" name="searchOutdatedElements"/>
<relationship kind="action" name="toggleUser"/>
<relationship kind="action" name="upgradePassword"/>
<relationship kind="outlet" name="actionsTipContainer" candidateClass="UIView"/>
<relationship kind="outlet" name="alertBody" candidateClass="UITextView"/>
<relationship kind="outlet" name="alertContainer" candidateClass="UIView"/>
<relationship kind="outlet" name="alertTitle" candidateClass="UILabel"/>
<relationship kind="outlet" name="contentContainer" candidateClass="UIView"/>
<relationship kind="outlet" name="contentField" candidateClass="UITextField"/>
<relationship kind="outlet" name="contentTipBody" candidateClass="UILabel"/>
<relationship kind="outlet" name="contentTipContainer" candidateClass="UIView"/>
<relationship kind="outlet" name="displayContainer" candidateClass="UIView"/>
<relationship kind="outlet" name="helpContainer" candidateClass="UIView"/>
<relationship kind="outlet" name="helpView" candidateClass="UIWebView"/>
<relationship kind="outlet" name="loginNameContainer" candidateClass="UIView"/>
<relationship kind="outlet" name="loginNameField" candidateClass="UITextField"/>
<relationship kind="outlet" name="loginNameTipBody" candidateClass="UILabel"/>
<relationship kind="outlet" name="loginNameTipContainer" candidateClass="UIView"/>
<relationship kind="outlet" name="outdatedAlertBack" candidateClass="UIImageView"/>
<relationship kind="outlet" name="outdatedAlertCloseButton" candidateClass="UIButton"/>
<relationship kind="outlet" name="outdatedAlertContainer" candidateClass="UIView"/>
<relationship kind="outlet" name="passwordCounter" candidateClass="UILabel"/>
<relationship kind="outlet" name="passwordEdit" candidateClass="UIButton"/>
<relationship kind="outlet" name="passwordIncrementer" candidateClass="UIButton"/>
<relationship kind="outlet" name="passwordUpgrade" candidateClass="UIButton"/>
<relationship kind="outlet" name="passwordUser" candidateClass="UIButton"/>
<relationship kind="outlet" name="pullDownGesture" candidateClass="UIPanGestureRecognizer"/>
<relationship kind="outlet" name="pullDownView" candidateClass="UIImageView"/>
<relationship kind="outlet" name="pullUpGesture" candidateClass="UIPanGestureRecognizer"/>
<relationship kind="outlet" name="pullUpView" candidateClass="UIImageView"/>
<relationship kind="outlet" name="searchDelegate" candidateClass="MPSearchDelegate"/>
<relationship kind="outlet" name="searchTipContainer" candidateClass="UIView"/>
<relationship kind="outlet" name="siteName" candidateClass="UILabel"/>
<relationship kind="outlet" name="toolTipBody" candidateClass="UILabel"/>
<relationship kind="outlet" name="toolTipContainer" candidateClass="UIView"/>
<relationship kind="outlet" name="toolTipEditIcon" candidateClass="UIImageView"/>
<relationship kind="outlet" name="typeButton" candidateClass="UIButton"/>
<relationship kind="outlet" name="typeTipContainer" candidateClass="UIView"/>
</relationships>
</class>
<class className="MPPreferencesViewController" superclassName="UITableViewController">
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPPreferencesViewController.h"/>
<relationships>
<relationship kind="action" name="didToggleSwitch:" candidateClass="UISwitch"/>
<relationship kind="action" name="settings:"/>
<relationship kind="outlet" name="avatarTemplate" candidateClass="UIButton"/>
<relationship kind="outlet" name="avatarsView" candidateClass="UIScrollView"/>
<relationship kind="outlet" name="changeMPCell" candidateClass="UITableViewCell"/>
<relationship kind="outlet" name="defaultTypeLabel" candidateClass="UILabel"/>
<relationship kind="outlet" name="exportCell" candidateClass="UITableViewCell"/>
<relationship kind="outlet" name="savePasswordSwitch" candidateClass="UISwitch"/>
</relationships>
</class>
<class className="MPSearchDelegate" superclassName="NSObject">
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPSearchDelegate.h"/>
<relationships>
<relationship kind="outlet" name="delegate"/>
<relationship kind="outlet" name="searchDisplayController" candidateClass="UISearchDisplayController"/>
<relationship kind="outlet" name="searchTipContainer" candidateClass="UIView"/>
</relationships>
</class>
<class className="MPTypeViewController" superclassName="UITableViewController">
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPTypeViewController.h"/>
<relationships>
<relationship kind="outlet" name="recommendedTipContainer" candidateClass="UIView"/>
</relationships>
</class>
<class className="MPUnlockViewController" superclassName="UIViewController">
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPUnlockViewController.h"/>
<relationships>
<relationship kind="action" name="add:" candidateClass="UIButton"/>
<relationship kind="action" name="facebook:" candidateClass="UIButton"/>
<relationship kind="action" name="google:" candidateClass="UIButton"/>
<relationship kind="action" name="mail:" candidateClass="UIButton"/>
<relationship kind="action" name="targetedUserAction:" candidateClass="UILongPressGestureRecognizer"/>
<relationship kind="action" name="twitter:" candidateClass="UIButton"/>
<relationship kind="outlet" name="avatarTemplate" candidateClass="UIButton"/>
<relationship kind="outlet" name="avatarsView" candidateClass="UIScrollView"/>
<relationship kind="outlet" name="createPasswordTipView" candidateClass="UIView"/>
<relationship kind="outlet" name="loadingUsersIndicator" candidateClass="UIActivityIndicatorView"/>
<relationship kind="outlet" name="nameLabel" candidateClass="UILabel"/>
<relationship kind="outlet" name="newsView" candidateClass="UIWebView"/>
<relationship kind="outlet" name="oldNameLabel" candidateClass="UILabel"/>
<relationship kind="outlet" name="passwordField" candidateClass="UITextField"/>
<relationship kind="outlet" name="passwordFieldLabel" candidateClass="UILabel"/>
<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"/>
<relationship kind="outlet" name="targetedUserActionGesture" candidateClass="UILongPressGestureRecognizer"/>
<relationship kind="outlet" name="tip" candidateClass="UILabel"/>
<relationship kind="outlet" name="uiContainer" candidateClass="UIView"/>
<relationship kind="outlet" name="wordWall" candidateClass="UIView"/>
</relationships>
</class>
</classes>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<nil key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>

View File

@ -0,0 +1,6 @@
SourceCodePro-Light
LucidaGrande
HelveticaNeue-Medium
LucidaGrande
HelveticaNeue-Light
Inconsolata

View File

@ -341,20 +341,7 @@
</ul>
</p>
<p>
By default, Master Password uses the <em>Long Password</em> type for any new passwords. The user is able to choose a different password type, which is normally only done if the site's password policy is incompatible with the output password produced by this type.
</p>
<p>
To create the create the output password, the bytes in the <code>seed</code> are encoded according to the template. The first <code>seed</code> byte is used to determine which of the type's templates to use for encoding an output password. We take the byte value of the first <code>seed</code> byte modulo the amount of templates set for the chosen password type and use the result as a zero-based index in the template list for the password type.
</p>
<code><pre>
templates = [ "CvcvCvcvnoCvcv", "CvcvnoCvcvCvcv", "CvcvCvcvCvcvno", ... ]
template = templates[ seed[0] % count( templates ) ]
</pre></code>
<p>
Now that we know what template to use for building our output password, all that's left is to iterate the template, and produce a character of password output for each step. When we iterate the template (index <code>i</code>), we look in the character group identified by the character (string <code>passChars</code>) in the template at index <code>i</code>.
</p>
<p>
The following character groups (<code>passChars</code>) are defined:
Where each of the letters above expand any of the characters in their respective character group:
<ul>
<li><p>Template character: <code>V</code>
<ul>
@ -403,6 +390,19 @@
</p></li>
</ul>
</p>
<p>
By default, Master Password uses the <em>Long Password</em> type for any new passwords. The user is able to choose a different password type, which is normally only done if the site's password policy is incompatible with the output password produced by this type.
</p>
<p>
To create the output password, the bytes in the <code>seed</code> are encoded according to the template. The first <code>seed</code> byte is used to determine which of the type's templates to use for encoding an output password. We take the byte value of the first <code>seed</code> byte modulo the amount of templates set for the chosen password type and use the result as a zero-based index in the template list for the password type.
</p>
<code><pre>
templates = [ "CvcvCvcvnoCvcv", "CvcvnoCvcvCvcv", "CvcvCvcvCvcvno", ... ]
template = templates[ seed[0] % count( templates ) ]
</pre></code>
<p>
Now that we know what template to use for building our output password, all that's left is to iterate the template, and produce a character of password output for each step. When we iterate the template (index <code>i</code>), we look in the character group identified by the character (string <code>passChars</code>) in the template at index <code>i</code>.
</p>
<p>
We use the <code>seed</code>'s byte value at index <code>i + 1</code> modulo the amount of characters in the character class to determine which character (<code>passChar</code>) in the class to use for the output password at index <code>i</code>.
</p>