From aa461b73c8a244f303e53513cc17e3cf40b9d28d Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Thu, 24 Apr 2014 21:43:47 -0400 Subject: [PATCH] Fixed sending emails when the key window is an alert window + added coachmarks. --- External/Pearl | 2 +- MasterPassword/ObjC/MPAppDelegate_Store.h | 2 +- MasterPassword/ObjC/MPAppDelegate_Store.m | 12 +- .../ObjC/iOS/MPCoachmarkViewController.h | 37 + .../ObjC/iOS/MPCoachmarkViewController.m | 53 + .../ObjC/iOS/MPElementListAllViewController.m | 2 +- .../ObjC/iOS/MPMainViewController.m | 5 - .../iOS/MPPasswordsCoachmarkViewController.h | 23 + .../iOS/MPPasswordsCoachmarkViewController.m | 51 + .../ObjC/iOS/MPPasswordsViewController.h | 3 + .../ObjC/iOS/MPPasswordsViewController.m | 23 +- .../ObjC/iOS/MPPreferencesViewController.h | 1 + .../ObjC/iOS/MPPreferencesViewController.m | 15 +- .../ObjC/iOS/MPPreferencesViewControllerOld.m | 2 +- .../ObjC/iOS/MPSetupViewController.m | 8 - .../ObjC/iOS/MPUnlockViewController.m | 2 +- MasterPassword/ObjC/iOS/MPiOSAppDelegate.h | 4 +- MasterPassword/ObjC/iOS/MPiOSAppDelegate.m | 31 +- .../project.pbxproj | 24 + MasterPassword/ObjC/iOS/Storyboard.storyboard | 1013 +++++++++++++++-- 20 files changed, 1173 insertions(+), 140 deletions(-) create mode 100644 MasterPassword/ObjC/iOS/MPCoachmarkViewController.h create mode 100644 MasterPassword/ObjC/iOS/MPCoachmarkViewController.m create mode 100644 MasterPassword/ObjC/iOS/MPPasswordsCoachmarkViewController.h create mode 100644 MasterPassword/ObjC/iOS/MPPasswordsCoachmarkViewController.m diff --git a/External/Pearl b/External/Pearl index 9a506ea9..2e328ecf 160000 --- a/External/Pearl +++ b/External/Pearl @@ -1 +1 @@ -Subproject commit 9a506ea9d153dfee48b6d67babf7d33e7aaa5982 +Subproject commit 2e328ecff09d7d271e75f8521112aa8698e852f0 diff --git a/MasterPassword/ObjC/MPAppDelegate_Store.h b/MasterPassword/ObjC/MPAppDelegate_Store.h index 5f701e16..ef8cc1c5 100644 --- a/MasterPassword/ObjC/MPAppDelegate_Store.h +++ b/MasterPassword/ObjC/MPAppDelegate_Store.h @@ -34,6 +34,6 @@ typedef enum { - (MPImportResult)importSites:(NSString *)importedSitesString askImportPassword:(NSString *(^)(NSString *userName))importPassword askUserPassword:(NSString *(^)(NSString *userName, NSUInteger importCount, NSUInteger deleteCount))userPassword; -- (NSString *)exportSitesShowingPasswords:(BOOL)showPasswords; +- (NSString *)exportSitesRevealPasswords:(BOOL)revealPasswords; @end diff --git a/MasterPassword/ObjC/MPAppDelegate_Store.m b/MasterPassword/ObjC/MPAppDelegate_Store.m index eb02ce0d..0b9f399c 100644 --- a/MasterPassword/ObjC/MPAppDelegate_Store.m +++ b/MasterPassword/ObjC/MPAppDelegate_Store.m @@ -694,15 +694,15 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext, return MPImportResultSuccess; } -- (NSString *)exportSitesShowingPasswords:(BOOL)showPasswords { +- (NSString *)exportSitesRevealPasswords:(BOOL)revealPasswords { MPUserEntity *activeUser = [self activeUserForMainThread]; - inf(@"Exporting sites, %@, for: %@", showPasswords? @"showing passwords": @"omitting passwords", activeUser.userID); + inf(@"Exporting sites, %@, for: %@", revealPasswords? @"revealing passwords": @"omitting passwords", activeUser.userID); // Header. NSMutableString *export = [NSMutableString new]; [export appendFormat:@"# Master Password site export\n"]; - if (showPasswords) + if (revealPasswords) [export appendFormat:@"# Export of site names and passwords in clear-text.\n"]; else [export appendFormat:@"# Export of site names and stored passwords (unless device-private) encrypted with the master key.\n"]; @@ -712,7 +712,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext, [export appendFormat:@"# User Name: %@\n", activeUser.name]; [export appendFormat:@"# Key ID: %@\n", [activeUser.keyID encodeHex]]; [export appendFormat:@"# Date: %@\n", [[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]]]; - if (showPasswords) + if (revealPasswords) [export appendFormat:@"# Passwords: VISIBLE\n"]; else [export appendFormat:@"# Passwords: PROTECTED\n"]; @@ -732,7 +732,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext, // Determine the content to export. if (!(type & MPElementFeatureDevicePrivate)) { - if (showPasswords) + if (revealPasswords) content = [element.algorithm resolveContentForElement:element usingKey:self.key]; else if (type & MPElementFeatureExportContent) content = [element.algorithm exportContentForElement:element usingKey:self.key]; @@ -745,7 +745,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext, } MPCheckpoint( MPCheckpointSitesExported, @{ - @"showPasswords" : @(showPasswords) + @"showPasswords" : @(revealPasswords) } ); return export; diff --git a/MasterPassword/ObjC/iOS/MPCoachmarkViewController.h b/MasterPassword/ObjC/iOS/MPCoachmarkViewController.h new file mode 100644 index 00000000..c1f27b30 --- /dev/null +++ b/MasterPassword/ObjC/iOS/MPCoachmarkViewController.h @@ -0,0 +1,37 @@ +/** + * 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 + * @license http://www.gnu.org/licenses/lgpl-3.0.txt + */ + +// +// MPCoachmarkViewController.h +// MPCoachmarkViewController +// +// Created by lhunath on 2014-04-22. +// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. +// + +#import + +@interface MPCoachmark : NSObject + +@property(nonatomic, strong) Class coachedClass; +@property(nonatomic) int coachedVersion; +@property(nonatomic) BOOL coached; + ++ (instancetype)coachmarkForClass:(Class)class version:(NSInteger)version; + +@end + +@interface MPCoachmarkViewController : UIViewController + +@property(nonatomic, strong) MPCoachmark *coachmark; + +- (IBAction)close:(id)sender; + +@end diff --git a/MasterPassword/ObjC/iOS/MPCoachmarkViewController.m b/MasterPassword/ObjC/iOS/MPCoachmarkViewController.m new file mode 100644 index 00000000..f4ef41ea --- /dev/null +++ b/MasterPassword/ObjC/iOS/MPCoachmarkViewController.m @@ -0,0 +1,53 @@ +/** + * 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 + * @license http://www.gnu.org/licenses/lgpl-3.0.txt + */ + +// +// MPCoachmarkViewController.h +// MPCoachmarkViewController +// +// Created by lhunath on 2014-04-22. +// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. +// + +#import "MPCoachmarkViewController.h" + +@implementation MPCoachmarkViewController { +} + +- (IBAction)close:(id)sender { + + [self dismissViewControllerAnimated:YES completion:^{ + self.coachmark.coached = YES; + }]; +} + +@end + +@implementation MPCoachmark + ++ (instancetype)coachmarkForClass:(Class)coachedClass version:(NSInteger)coachedVersion { + MPCoachmark *coachmark = [self new]; + coachmark.coachedClass = coachedClass; + coachmark.coachedVersion = coachedVersion; + + return coachmark; +} + +- (BOOL)coached { + + return [[NSUserDefaults standardUserDefaults] boolForKey:strf( @"%@.%d.coached", self.coachedClass, self.coachedVersion )]; +} + +- (void)setCoached:(BOOL)coached { + + [[NSUserDefaults standardUserDefaults] setBool:coached forKey:strf( @"%@.%d.coached", self.coachedClass, self.coachedVersion )]; +} + +@end diff --git a/MasterPassword/ObjC/iOS/MPElementListAllViewController.m b/MasterPassword/ObjC/iOS/MPElementListAllViewController.m index 2cf9243b..6c46ff69 100644 --- a/MasterPassword/ObjC/iOS/MPElementListAllViewController.m +++ b/MasterPassword/ObjC/iOS/MPElementListAllViewController.m @@ -150,7 +150,7 @@ if (buttonIndex == [alert cancelButtonIndex]) return; - [PearlEMail sendEMailTo:nil subject:@"[Master Password] Upgrade Changes" body:formattedChanges]; + [PearlEMail sendEMailTo:nil fromVC:self subject:@"[Master Password] Upgrade Changes" body:formattedChanges]; } cancelTitle:@"Don't Email" otherTitles:@"Send Email", nil]; } diff --git a/MasterPassword/ObjC/iOS/MPMainViewController.m b/MasterPassword/ObjC/iOS/MPMainViewController.m index 2637e252..e862deb9 100644 --- a/MasterPassword/ObjC/iOS/MPMainViewController.m +++ b/MasterPassword/ObjC/iOS/MPMainViewController.m @@ -715,11 +715,6 @@ [self setHelpHidden:NO animated:YES]; break; } - case 1: { - inf(@"Action: Guide"); - [[MPiOSAppDelegate get] showGuide]; - break; - } case 2: { inf(@"Action: Preferences"); [self performSegueWithIdentifier:@"MP_UserProfile" sender:self]; diff --git a/MasterPassword/ObjC/iOS/MPPasswordsCoachmarkViewController.h b/MasterPassword/ObjC/iOS/MPPasswordsCoachmarkViewController.h new file mode 100644 index 00000000..4d224383 --- /dev/null +++ b/MasterPassword/ObjC/iOS/MPPasswordsCoachmarkViewController.h @@ -0,0 +1,23 @@ +/** + * 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 + * @license http://www.gnu.org/licenses/lgpl-3.0.txt + */ + +// +// MPPasswordsCoachmarkViewController.h +// MPPasswordsCoachmarkViewController +// +// Created by lhunath on 2014-04-23. +// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. +// + +#import +#import "MPCoachmarkViewController.h" + +@interface MPPasswordsCoachmarkViewController : MPCoachmarkViewController +@end diff --git a/MasterPassword/ObjC/iOS/MPPasswordsCoachmarkViewController.m b/MasterPassword/ObjC/iOS/MPPasswordsCoachmarkViewController.m new file mode 100644 index 00000000..15db14b4 --- /dev/null +++ b/MasterPassword/ObjC/iOS/MPPasswordsCoachmarkViewController.m @@ -0,0 +1,51 @@ +/** + * 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 + * @license http://www.gnu.org/licenses/lgpl-3.0.txt + */ + +// +// MPPasswordsCoachmarkViewController.h +// MPPasswordsCoachmarkViewController +// +// Created by lhunath on 2014-04-23. +// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. +// + +#import "MPPasswordsCoachmarkViewController.h" +#import "MPPasswordLargeGeneratedCell.h" +#import "MPPasswordLargeStoredCell.h" + +@implementation MPPasswordsCoachmarkViewController + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + + return 2; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + + if (indexPath.item == 0) { + MPPasswordLargeGeneratedCell *cell = [MPPasswordLargeGeneratedCell dequeueCellWithType:MPElementTypeGeneratedLong + fromCollectionView:collectionView atIndexPath:indexPath]; + [cell reloadWithTransientSite:@"apple.com"]; + + return cell; + } + else if (indexPath.item == 1) { + MPPasswordLargeStoredCell *cell = [MPPasswordLargeStoredCell dequeueCellWithType:MPElementTypeStoredPersonal + fromCollectionView:collectionView atIndexPath:indexPath]; + [cell reloadWithTransientSite:@"gmail.com"]; + [cell.contentField setText:@"PaS$w0rD"]; + + return cell; + } + + Throw(@"Unexpected item for indexPath: %@", indexPath); +} + +@end diff --git a/MasterPassword/ObjC/iOS/MPPasswordsViewController.h b/MasterPassword/ObjC/iOS/MPPasswordsViewController.h index 10c43afb..887af0a2 100644 --- a/MasterPassword/ObjC/iOS/MPPasswordsViewController.h +++ b/MasterPassword/ObjC/iOS/MPPasswordsViewController.h @@ -18,6 +18,7 @@ #import "LLGitTip.h" @class MPElementEntity; +@class MPCoachmark; @interface MPPasswordsViewController : UIViewController @@ -33,6 +34,8 @@ @property(assign, nonatomic) BOOL active; @property(nonatomic, copy) NSString *originalQuery; +@property(nonatomic, readonly) MPCoachmark *coachmark; + - (void)setActive:(BOOL)active animated:(BOOL)animated completion:(void (^)(BOOL finished))completion; - (IBAction)dismissPopdown:(id)sender; diff --git a/MasterPassword/ObjC/iOS/MPPasswordsViewController.m b/MasterPassword/ObjC/iOS/MPPasswordsViewController.m index 7e45dc64..852ddd6a 100644 --- a/MasterPassword/ObjC/iOS/MPPasswordsViewController.m +++ b/MasterPassword/ObjC/iOS/MPPasswordsViewController.m @@ -22,9 +22,9 @@ #import "MPPasswordLargeCell.h" #import "MPPasswordTypesCell.h" #import "MPPasswordSmallCell.h" -#import "UIColor+Expanded.h" #import "MPPopdownSegue.h" #import "MPAppDelegate_Key.h" +#import "MPCoachmarkViewController.h" @interface MPPasswordsViewController() @@ -53,8 +53,9 @@ [super viewDidLoad]; _fetchedUpdates = [NSMutableDictionary dictionaryWithCapacity:4]; - _backgroundColor = [UIColor clearColor]; - _darkenedBackgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6f]; + _backgroundColor = self.passwordCollectionView.backgroundColor; + _darkenedBackgroundColor = [_backgroundColor colorWithAlphaComponent:0.6f]; + _coachmark = [MPCoachmark coachmarkForClass:[self class] version:0]; self.view.backgroundColor = [UIColor clearColor]; self.passwordCollectionView.contentInset = UIEdgeInsetsMake( 108, 0, 0, 0 ); @@ -70,6 +71,16 @@ [self updatePasswords]; } +- (void)viewDidAppear:(BOOL)animated { + + [super viewDidAppear:animated]; + + PearlMainQueueAfter( 1, ^{ + if (!self.coachmark.coached) + [self performSegueWithIdentifier:@"coachmarks" sender:self]; + } ); +} + - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; @@ -82,6 +93,8 @@ if ([segue.identifier isEqualToString:@"popdown"]) _popdownVC = segue.destinationViewController; + if ([segue.identifier isEqualToString:@"coachmarks"]) + ((MPCoachmarkViewController *)segue.destinationViewController).coachmark = self.coachmark; } #pragma mark - UICollectionViewDelegateFlowLayout @@ -376,7 +389,7 @@ _passwordsDismissRecognizer = [self.view dismissKeyboardForField:self.passwordsSearchBar onTouchForced:NO]; [UIView animateWithDuration:0.3f animations:^{ - searchBar.superview.backgroundColor = _darkenedBackgroundColor; + self.passwordCollectionView.backgroundColor = _darkenedBackgroundColor; }]; } } @@ -389,7 +402,7 @@ [self.view removeGestureRecognizer:_passwordsDismissRecognizer]; [UIView animateWithDuration:0.3f animations:^{ - searchBar.superview.backgroundColor = _backgroundColor; + self.passwordCollectionView.backgroundColor = _backgroundColor; }]; } } diff --git a/MasterPassword/ObjC/iOS/MPPreferencesViewController.h b/MasterPassword/ObjC/iOS/MPPreferencesViewController.h index 049078be..6d44f504 100644 --- a/MasterPassword/ObjC/iOS/MPPreferencesViewController.h +++ b/MasterPassword/ObjC/iOS/MPPreferencesViewController.h @@ -13,6 +13,7 @@ @property(weak, nonatomic) IBOutlet UISwitch *savePasswordSwitch; @property(weak, nonatomic) IBOutlet UITableViewCell *feedbackCell; +@property(weak, nonatomic) IBOutlet UITableViewCell *coachmarksCell; @property(weak, nonatomic) IBOutlet UITableViewCell *exportCell; @property(weak, nonatomic) IBOutlet UIImageView *avatarImage; @property(weak, nonatomic) IBOutlet UISegmentedControl *typeControl; diff --git a/MasterPassword/ObjC/iOS/MPPreferencesViewController.m b/MasterPassword/ObjC/iOS/MPPreferencesViewController.m index 33e5bbd2..7d11585b 100644 --- a/MasterPassword/ObjC/iOS/MPPreferencesViewController.m +++ b/MasterPassword/ObjC/iOS/MPPreferencesViewController.m @@ -11,6 +11,8 @@ #import "MPAppDelegate_Key.h" #import "MPAppDelegate_Store.h" #import "UIColor+Expanded.h" +#import "MPPasswordsViewController.h" +#import "MPCoachmarkViewController.h" @interface MPPreferencesViewController() @@ -54,8 +56,19 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath]; + if (cell == self.feedbackCell) + [[MPiOSAppDelegate get] showFeedbackWithLogs:YES forVC:self]; if (cell == self.exportCell) - [[MPiOSAppDelegate get] export]; + [[MPiOSAppDelegate get] showExportForVC:self]; + if (cell == self.coachmarksCell) { + for (UIViewController *vc = self; (vc = vc.parentViewController); ) + if ([vc isKindOfClass:[MPPasswordsViewController class]]) { + MPPasswordsViewController *passwordsVC = (MPPasswordsViewController *)vc; + passwordsVC.coachmark.coached = NO; + [passwordsVC dismissPopdown:self]; + [vc performSegueWithIdentifier:@"coachmarks" sender:self]; + } + } [tableView deselectRowAtIndexPath:indexPath animated:YES]; } diff --git a/MasterPassword/ObjC/iOS/MPPreferencesViewControllerOld.m b/MasterPassword/ObjC/iOS/MPPreferencesViewControllerOld.m index 121658dd..ac481a6d 100644 --- a/MasterPassword/ObjC/iOS/MPPreferencesViewControllerOld.m +++ b/MasterPassword/ObjC/iOS/MPPreferencesViewControllerOld.m @@ -130,7 +130,7 @@ UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath]; if (cell == self.exportCell) - [[MPiOSAppDelegate get] export]; + [[MPiOSAppDelegate get] showExportForVC:self]; else if (cell == self.changeMPCell) { [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) { diff --git a/MasterPassword/ObjC/iOS/MPSetupViewController.m b/MasterPassword/ObjC/iOS/MPSetupViewController.m index 34495bba..4b812d52 100644 --- a/MasterPassword/ObjC/iOS/MPSetupViewController.m +++ b/MasterPassword/ObjC/iOS/MPSetupViewController.m @@ -54,12 +54,4 @@ [self dismissViewControllerAnimated:YES completion:nil]; } -- (IBAction)showGuide:(UIBarButtonItem *)sender { - - [MPiOSConfig get].showSetup = @NO; - [self dismissViewControllerAnimated:YES completion:^{ - [[MPiOSAppDelegate get] showGuide]; - }]; -} - @end diff --git a/MasterPassword/ObjC/iOS/MPUnlockViewController.m b/MasterPassword/ObjC/iOS/MPUnlockViewController.m index d939c5db..3643b2fa 100644 --- a/MasterPassword/ObjC/iOS/MPUnlockViewController.m +++ b/MasterPassword/ObjC/iOS/MPUnlockViewController.m @@ -1178,7 +1178,7 @@ } if (buttonIndex == [sheet firstOtherButtonIndex] + 3) { // Mailing List - [PearlEMail sendEMailTo:@"masterpassword-join@lists.lyndir.com" subject:@"Subscribe" + [PearlEMail sendEMailTo:@"masterpassword-join@lists.lyndir.com" fromVC:self subject:@"Subscribe" body:@"Press 'Send' now to subscribe to the Master Password mailing list.\n\n" @"You'll be kept up-to-date on the evolution of and discussions revolving Master Password."]; return; diff --git a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.h b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.h index 0d67edff..c806cb75 100644 --- a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.h +++ b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.h @@ -14,12 +14,10 @@ @interface MPiOSAppDelegate : MPAppDelegate_Shared -- (void)showGuide; -- (void)showSetup; - (void)showFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController; - (void)openFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController; -- (void)export; +- (void)showExportForVC:(UIViewController *)viewController; - (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset; @end diff --git a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m index d31dc4d5..3529e5c6 100644 --- a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m +++ b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m @@ -10,7 +10,6 @@ #import "MPAppDelegate_Key.h" #import "MPAppDelegate_Store.h" #import "IASKSettingsReader.h" -#import "JRSwizzle.h" @interface MPiOSAppDelegate() @@ -221,7 +220,7 @@ dispatch_async( dispatch_get_main_queue(), ^{ if ([[MPiOSConfig get].showSetup boolValue]) - [[MPiOSAppDelegate get] showSetup]; + [self.navigationController performSegueWithIdentifier:@"setup" sender:self]; } ); MPCheckpoint( MPCheckpointStarted, @{ @@ -410,20 +409,6 @@ #pragma mark - Behavior -- (void)showGuide { - - //TODO [self.navigationController performSegueWithIdentifier:@"MP_Guide" sender:self]; - - MPCheckpoint( MPCheckpointShowGuide, nil ); -} - -- (void)showSetup { - - //TODO [self.navigationController performSegueWithIdentifier:@"MP_Setup" sender:self]; - - MPCheckpoint( MPCheckpointShowSetup, nil ); -} - - (void)showReview { [super showReview]; @@ -487,7 +472,7 @@ showComposerForVC:viewController]; } -- (void)export { +- (void)showExportForVC:(UIViewController *)viewController { [PearlAlert showNotice: @"This will export all your site names.\n\n" @@ -504,15 +489,15 @@ tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) { if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 0) // Safe Export - [self exportShowPasswords:NO]; + [self showExportRevealPasswords:NO forVC:viewController]; if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 1) // Show Passwords - [self exportShowPasswords:YES]; + [self showExportRevealPasswords:YES forVC:viewController]; } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Safe Export", @"Show Passwords", nil]; } otherTitles:nil]; } -- (void)exportShowPasswords:(BOOL)showPasswords { +- (void)showExportRevealPasswords:(BOOL)revealPasswords forVC:(UIViewController *)viewController { if (![PearlEMail canSendMail]) { [PearlAlert showAlertWithTitle:@"Cannot Send Mail" @@ -525,10 +510,10 @@ return; } - NSString *exportedSites = [self exportSitesShowingPasswords:showPasswords]; + NSString *exportedSites = [self exportSitesRevealPasswords:revealPasswords]; NSString *message; - if (showPasswords) + if (revealPasswords) message = PearlString( @"Export of Master Password sites with passwords included.\n\n" @"REMINDER: Make sure nobody else sees this file! Passwords are visible!\n\n\n" @"--\n" @@ -549,7 +534,7 @@ NSDateFormatter *exportDateFormatter = [NSDateFormatter new]; [exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"]; - [PearlEMail sendEMailTo:nil subject:@"Master Password Export" body:message + [PearlEMail sendEMailTo:nil fromVC:viewController subject:@"Master Password Export" body:message attachments:[[PearlEMailAttachment alloc] initWithContent:[exportedSites dataUsingEncoding:NSUTF8StringEncoding] mimeType:@"text/plain" fileName: PearlString( @"%@ (%@).mpsites", [self activeUserForMainThread].name, diff --git a/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj b/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj index f15c5ab0..9f1d4f79 100644 --- a/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj +++ b/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 93D391C07818F4C2DC1B6956 /* MPPasswordsCoachmarkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D397E3650384498E7E53C4 /* MPPasswordsCoachmarkViewController.m */; }; 93D391ED37C9F687FA51EAA1 /* MPEmergencySegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3937712BF1B67623E5764 /* MPEmergencySegue.m */; }; 93D3922A53E41A54832E90D9 /* PearlOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D390FADEB325D8D54A957D /* PearlOverlay.m */; }; 93D39233C3EDD9A947ABA52D /* LLButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39BF6BCBDFFE844E7D34C /* LLButtonView.m */; }; @@ -25,6 +26,7 @@ 93D39673DDC085BE72C34D7C /* MPPopdownSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */; }; 93D396AA30690B256F30378A /* PearlNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3956915634581E737B38C /* PearlNavigationController.m */; }; 93D396BA1C74C4A06FD86437 /* PearlOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D3942A356B639724157982 /* PearlOverlay.h */; }; + 93D396D8B67DA6522CDBA142 /* MPCoachmarkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */; }; 93D397952F5635C793C24DF1 /* NSError+PearlFullDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */; }; 93D3980046016EFD05B35BC5 /* PearlUICollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39B1D8177A86C5B9EDDE3 /* PearlUICollectionView.h */; }; 93D398ECD7D1A0DEDDADF516 /* MPEmergencyViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39ACBA9F4878B6A1CC33B /* MPEmergencyViewController.m */; }; @@ -74,6 +76,12 @@ DA44260A1557D9E40052177D /* libUbiquityStoreManager.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA4425CB1557BED40052177D /* libUbiquityStoreManager.a */; }; DA4522441902355C008F650A /* icon_book.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD370C1711E29500CF925C /* icon_book.png */; }; DA4522451902355C008F650A /* icon_book@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD370D1711E29500CF925C /* icon_book@2x.png */; }; + DA45224719062899008F650A /* icon_settings.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38141711E29600CF925C /* icon_settings.png */; }; + DA45224819062899008F650A /* icon_settings@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38151711E29600CF925C /* icon_settings@2x.png */; }; + DA452249190628A1008F650A /* icon_wrench.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD386A1711E29700CF925C /* icon_wrench.png */; }; + DA45224A190628A1008F650A /* icon_wrench@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD386B1711E29700CF925C /* icon_wrench@2x.png */; }; + DA45224B190628B2008F650A /* icon_gear.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37821711E29500CF925C /* icon_gear.png */; }; + DA45224C190628B2008F650A /* icon_gear@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37831711E29500CF925C /* icon_gear@2x.png */; }; DA4DA1D91564471A00F6F596 /* libjrswizzle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC6326C148680650075AEA5 /* libjrswizzle.a */; }; DA4DA1DA1564471F00F6F596 /* libuicolor-utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC6325D1486805C0075AEA5 /* libuicolor-utilities.a */; }; DA5A09DF171A70E4005284AB /* play.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5A09DD171A70E4005284AB /* play.png */; }; @@ -531,6 +539,7 @@ 93D390A66F69AB1CDB0BFF93 /* LLModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLModel.h; sourceTree = ""; }; 93D390FADEB325D8D54A957D /* PearlOverlay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlOverlay.m; sourceTree = ""; }; 93D390FB3110DCCE68E600DC /* UIScrollView+PearlAdjustInsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+PearlAdjustInsets.m"; sourceTree = ""; }; + 93D390FD93EFCFECB5193DEF /* MPPasswordsCoachmarkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordsCoachmarkViewController.h; sourceTree = ""; }; 93D391243F64A77798B4D6A4 /* MPPasswordTypesCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordTypesCell.h; sourceTree = ""; }; 93D3914D7597F9A28DB9D85E /* MPPasswordsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordsViewController.h; sourceTree = ""; }; 93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppSettingsViewController.m; sourceTree = ""; }; @@ -557,14 +566,17 @@ 93D3971FE104BB4052484151 /* MPUsersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUsersViewController.h; sourceTree = ""; }; 93D39730673227EFF6DEFF19 /* MPSetupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSetupViewController.h; sourceTree = ""; }; 93D3979190DACEBD1F6AE9F4 /* MPLogsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPLogsViewController.m; sourceTree = ""; }; + 93D397E3650384498E7E53C4 /* MPPasswordsCoachmarkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordsCoachmarkViewController.m; sourceTree = ""; }; 93D3983278751A530262F64E /* LLConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLConfig.h; sourceTree = ""; }; 93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlNavigationController.h; sourceTree = ""; }; 93D39888EE06F06264CC963B /* MPPasswordSmallCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordSmallCell.h; sourceTree = ""; }; 93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+PearlFullDescription.h"; sourceTree = ""; }; 93D398EBF99FF0C245FD561E /* NSManagedObject+Pearl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+Pearl.m"; sourceTree = ""; }; 93D3993422E207BF0B21D089 /* MPPasswordLargeGeneratedCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordLargeGeneratedCell.m; sourceTree = ""; }; + 93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCoachmarkViewController.m; sourceTree = ""; }; 93D39961CD6A43648CC0B0DB /* MPPreferencesViewControllerOld.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPreferencesViewControllerOld.h; sourceTree = ""; }; 93D39975CE5AEC99E3F086C7 /* MPPasswordCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordCell.h; sourceTree = ""; }; + 93D3999693660C89A7465F4E /* MPCoachmarkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCoachmarkViewController.h; sourceTree = ""; }; 93D399E571F61E50A9BF8FAF /* MPUsersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPUsersViewController.m; sourceTree = ""; }; 93D39A1DDFA09AE2E14D26DC /* UIResponder+PearlFirstResponder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIResponder+PearlFirstResponder.m"; sourceTree = ""; }; 93D39A28369954D147E239BA /* MPSetupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSetupViewController.m; sourceTree = ""; }; @@ -2619,6 +2631,10 @@ 93D392876BE5C011DE73B43F /* MPPopdownSegue.h */, 93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.m */, 93D39C86E984EC65DA5ACB1D /* MPAppSettingsViewController.h */, + 93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */, + 93D3999693660C89A7465F4E /* MPCoachmarkViewController.h */, + 93D397E3650384498E7E53C4 /* MPPasswordsCoachmarkViewController.m */, + 93D390FD93EFCFECB5193DEF /* MPPasswordsCoachmarkViewController.h */, ); path = iOS; sourceTree = ""; @@ -3675,12 +3691,14 @@ DABD38FA1711E29700CF925C /* ui_list_middle@2x.png in Resources */, DABD38FB1711E29700CF925C /* ui_navbar_back.png in Resources */, DABD38FC1711E29700CF925C /* ui_navbar_back@2x.png in Resources */, + DA45224C190628B2008F650A /* icon_gear@2x.png in Resources */, DABD38FD1711E29700CF925C /* ui_navbar_button.png in Resources */, DABD38FE1711E29700CF925C /* ui_navbar_button@2x.png in Resources */, DABD38FF1711E29700CF925C /* ui_navbar_container.png in Resources */, DABD39001711E29700CF925C /* ui_navbar_container@2x.png in Resources */, DABD39011711E29700CF925C /* ui_panel_container.png in Resources */, DA854C8318D4CFBF00106317 /* avatar-add@2x.png in Resources */, + DA45224A190628A1008F650A /* icon_wrench@2x.png in Resources */, DABD39021711E29700CF925C /* ui_panel_container@2x.png in Resources */, DABD39031711E29700CF925C /* ui_panel_display.png in Resources */, DABD39041711E29700CF925C /* ui_panel_display@2x.png in Resources */, @@ -3740,6 +3758,7 @@ DABD395B1711E29700CF925C /* avatar-9.png in Resources */, DABD395C1711E29700CF925C /* avatar-9@2x.png in Resources */, DABD395D1711E29700CF925C /* background.png in Resources */, + DA45224719062899008F650A /* icon_settings.png in Resources */, DABD395E1711E29700CF925C /* background@2x.png in Resources */, DA945C8717E3F3FD0053236B /* Images.xcassets in Resources */, DABD39871711E29700CF925C /* SourceCodePro-Black.otf in Resources */, @@ -3799,7 +3818,9 @@ DABD3B971711E29800CF925C /* pull-up.png in Resources */, DABD3B981711E29800CF925C /* pull-up@2x.png in Resources */, DABD3B991711E29800CF925C /* social-facebook.png in Resources */, + DA452249190628A1008F650A /* icon_wrench.png in Resources */, DABD3B9A1711E29800CF925C /* social-facebook@2x.png in Resources */, + DA45224819062899008F650A /* icon_settings@2x.png in Resources */, DABD3B9B1711E29800CF925C /* social-google+.png in Resources */, DADEF4121810D2940052CA3E /* love-lyndir.button.green.png in Resources */, DABD3B9C1711E29800CF925C /* social-google+@2x.png in Resources */, @@ -3816,6 +3837,7 @@ DABD3FCE1714F45C00CF925C /* identity.png in Resources */, DABD3FCF1714F45C00CF925C /* identity@2x.png in Resources */, DADEF4151810D2940052CA3E /* love-lyndir.button.grey@2x.png in Resources */, + DA45224B190628B2008F650A /* icon_gear.png in Resources */, DAE1EF2217E942DE00BC0086 /* Localizable.strings in Resources */, DA38D6A318CCB5BF009AEB3E /* Storyboard.storyboard in Resources */, DA5A09DF171A70E4005284AB /* play.png in Resources */, @@ -3937,6 +3959,8 @@ 93D39673DDC085BE72C34D7C /* MPPopdownSegue.m in Sources */, 93D39B21156EC9A0B4C2BC83 /* MPPreferencesViewControllerOld.m in Sources */, 93D39BA1EA3CAAC8A220B4A6 /* MPAppSettingsViewController.m in Sources */, + 93D396D8B67DA6522CDBA142 /* MPCoachmarkViewController.m in Sources */, + 93D391C07818F4C2DC1B6956 /* MPPasswordsCoachmarkViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MasterPassword/ObjC/iOS/Storyboard.storyboard b/MasterPassword/ObjC/iOS/Storyboard.storyboard index 078aa9a9..fbe4ef53 100644 --- a/MasterPassword/ObjC/iOS/Storyboard.storyboard +++ b/MasterPassword/ObjC/iOS/Storyboard.storyboard @@ -1,5 +1,5 @@ - + @@ -10,7 +10,7 @@ - + @@ -371,6 +371,7 @@ + @@ -455,42 +456,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -542,8 +509,8 @@ - - + + @@ -622,8 +589,8 @@ - - + + @@ -646,7 +613,7 @@ - - + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - @@ -1175,7 +1191,8 @@ - + + @@ -1186,6 +1203,19 @@ + + + + + + + + + + + + + @@ -1234,21 +1264,27 @@ - + - + + + + + + - + + @@ -1258,7 +1294,7 @@ - + @@ -1269,14 +1305,15 @@ - + - + + @@ -1622,7 +1659,7 @@ - + @@ -1640,7 +1677,7 @@ - + @@ -1682,8 +1719,9 @@ 119-20:52:17 MPMainViewController.m:187 | INFO : Main will disappear. - - + + + @@ -1744,10 +1782,815 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1756,9 +2599,11 @@ + +