Add TestFlight.
[ADDED] TestFlightSDK implemented.
This commit is contained in:
@@ -66,6 +66,14 @@
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight takeOff:@"bd44885deee7adce0645ce8e5498d80a_NDQ5NDQyMDExLTEyLTAyIDExOjM1OjQ4LjQ2NjM4NA"];
|
||||
[TestFlight setOptions:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithBool:YES], @"logToConsole",
|
||||
nil]];
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointLaunched];
|
||||
#endif
|
||||
|
||||
UIImage *navBarImage = [[UIImage imageNamed:@"ui_navbar_container"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
|
||||
[[UINavigationBar appearance] setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsDefault];
|
||||
[[UINavigationBar appearance] setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsLandscapePhone];
|
||||
@@ -138,11 +146,19 @@
|
||||
[self showGuide];
|
||||
else
|
||||
[self loadKeyPhrase];
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointActivated];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)showGuide {
|
||||
|
||||
[self.navigationController performSegueWithIdentifier:@"MP_Guide" sender:self];
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointShowGuide];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)loadKeyPhrase {
|
||||
@@ -172,7 +188,7 @@
|
||||
@"Your old sites and passwords will then become available again."
|
||||
viewStyle:UIAlertViewStyleDefault
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert firstOtherButtonIndex]) {
|
||||
if (buttonIndex != [alert cancelButtonIndex]) {
|
||||
// Key phrase reset. Delete it.
|
||||
dbg(@"Deleting master key phrase and hash from key chain.");
|
||||
[KeyChain deleteItemForQuery:[MPAppDelegate keyPhraseQuery]];
|
||||
@@ -180,6 +196,10 @@
|
||||
}
|
||||
|
||||
[self loadKeyPhrase];
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointMPChanged];
|
||||
#endif
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonAbort
|
||||
otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
||||
@@ -200,6 +220,9 @@
|
||||
// Key phrase should not be stored in keychain. Delete it.
|
||||
dbg(@"Deleting master key phrase from key chain.");
|
||||
[KeyChain deleteItemForQuery:[MPAppDelegate keyPhraseQuery]];
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointMPUnstored];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,6 +259,9 @@
|
||||
if (![keyPhraseHash isEqual:answerHash]) {
|
||||
dbg(@"Key phrase hash mismatch. Expected: %@, answer: %@.", keyPhraseHash, answerHash);
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointMPMismatch];
|
||||
#endif
|
||||
[AlertViewController showAlertWithTitle:[PearlStrings get].commonTitleError
|
||||
message:
|
||||
@"Incorrect master password.\n\n"
|
||||
@@ -250,6 +276,10 @@
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointMPAsked];
|
||||
#endif
|
||||
|
||||
self.keyPhrase = answer;
|
||||
} cancelTitle:@"Quit" otherTitles:@"Unlock", nil];
|
||||
});
|
||||
@@ -261,11 +291,19 @@
|
||||
|
||||
if (![[MPConfig get].rememberKeyPhrase boolValue])
|
||||
self.keyPhrase = nil;
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointDeactivated];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
|
||||
[self saveContext];
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointTerminated];
|
||||
#endif
|
||||
}
|
||||
|
||||
+ (MPAppDelegate *)get {
|
||||
@@ -314,6 +352,10 @@
|
||||
kSecAttrAccessibleWhenUnlocked, (__bridge id)kSecAttrAccessible,
|
||||
nil]];
|
||||
}
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:[NSString stringWithFormat:MPTestFlightCheckpointSetKeyphraseLength, _keyPhrase.length]];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,6 +461,11 @@
|
||||
wrn(@"Deleted datastore: %@", storeURL);
|
||||
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];
|
||||
#endif
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointStoreIncompatible];
|
||||
#endif
|
||||
|
||||
@throw [NSException exceptionWithName:error.domain reason:error.localizedDescription
|
||||
userInfo:[NSDictionary dictionaryWithObject:error forKey:@"cause"]];
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
//
|
||||
// MPContentViewController.h
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 03/01/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "MPElementEntity.h"
|
||||
|
||||
@interface MPContentViewController : UIViewController
|
||||
|
||||
@property (nonatomic, weak) MPElementEntity *activeElement;
|
||||
|
||||
@end
|
||||
@@ -1,22 +0,0 @@
|
||||
//
|
||||
// MPContentViewController.m
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 03/01/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPContentViewController.h"
|
||||
|
||||
@implementation MPContentViewController
|
||||
@synthesize activeElement = _activeElement;
|
||||
|
||||
#pragma mark - View lifecycle
|
||||
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
||||
|
||||
// Return YES for supported orientations
|
||||
return (interfaceOrientation == UIInterfaceOrientationPortrait);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#import "MPMainViewController.h"
|
||||
#import "MPAppDelegate.h"
|
||||
#import "MPContentViewController.h"
|
||||
#import "MPElementGeneratedEntity.h"
|
||||
#import "MPElementStoredEntity.h"
|
||||
#import "IASKAppSettingsViewController.h"
|
||||
@@ -57,8 +56,6 @@
|
||||
|
||||
if ([[segue identifier] isEqualToString:@"MP_Main_ChooseType"])
|
||||
[[segue destinationViewController] setDelegate:self];
|
||||
if ([[segue identifier] isEqualToString:@"MP_Main_Content"])
|
||||
((MPContentViewController *)[segue destinationViewController]).activeElement = self.activeElement;
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
@@ -144,13 +141,6 @@
|
||||
[super viewDidUnload];
|
||||
}
|
||||
|
||||
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
|
||||
|
||||
[super setEditing:editing animated:animated];
|
||||
|
||||
[self updateAnimated:animated];
|
||||
}
|
||||
|
||||
- (void)updateAnimated:(BOOL)animated {
|
||||
|
||||
[[MPAppDelegate get] saveContext];
|
||||
@@ -218,6 +208,10 @@
|
||||
|
||||
- (void)setHelpChapter:(NSString *)chapter {
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:[NSString stringWithFormat:MPTestFlightCheckpointHelpChapter, chapter]];
|
||||
#endif
|
||||
|
||||
[self.helpView loadRequest:
|
||||
[NSURLRequest requestWithURL:
|
||||
[NSURL URLWithString:[NSString stringWithFormat:@"#%@", chapter] relativeToURL:
|
||||
@@ -276,6 +270,10 @@
|
||||
forPasteboardType:(id)kUTTypeUTF8PlainText];
|
||||
|
||||
[self showContentTip:@"Copied!" withIcon:nil];
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointCopyToPasteboard];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (IBAction)incrementPasswordCounter {
|
||||
@@ -287,6 +285,10 @@
|
||||
[self updateElement:^{
|
||||
++((MPElementGeneratedEntity *) self.activeElement).counter;
|
||||
}];
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointIncrementPasswordCounter];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)updateElement:(void (^)(void))updateElement {
|
||||
@@ -311,6 +313,10 @@
|
||||
self.contentField.enabled = YES;
|
||||
[self.contentField becomeFirstResponder];
|
||||
}
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointEditPassword];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (IBAction)closeAlert {
|
||||
@@ -320,6 +326,10 @@
|
||||
} completion:^(BOOL finished) {
|
||||
self.alertBody.text = nil;
|
||||
}];
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointCloseAlert];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (IBAction)action:(id)sender {
|
||||
@@ -346,9 +356,23 @@
|
||||
[self.navigationController pushViewController:settingsVC animated:YES];
|
||||
break;
|
||||
}
|
||||
#ifndef PRODUCTION
|
||||
case 4:
|
||||
[TestFlight openFeedbackView];
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointAction];
|
||||
#endif
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel destructiveTitle:nil
|
||||
otherTitles:[self isHelpVisible]? @"Hide Help": @"Show Help", @"FAQ", @"Tutorial", @"Settings", nil];
|
||||
otherTitles:
|
||||
[self isHelpVisible]? @"Hide Help": @"Show Help", @"FAQ", @"Tutorial", @"Settings",
|
||||
#ifndef PRODUCTION
|
||||
@"Feedback",
|
||||
#endif
|
||||
nil];
|
||||
}
|
||||
|
||||
- (void)didSelectType:(MPElementType)type {
|
||||
@@ -371,6 +395,10 @@
|
||||
|
||||
self.activeElement.type = type;
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:[NSString stringWithFormat:MPTestFlightCheckpointSelectType, NSStringFromMPElementType(type)]];
|
||||
#endif
|
||||
|
||||
if (type & MPElementTypeClassStored && ![self.activeElement.description length])
|
||||
[self showContentTip:@"Tap to set a password." withIcon:self.contentTipEditIcon];
|
||||
}];
|
||||
@@ -384,11 +412,19 @@
|
||||
[self.searchDisplayController setActive:NO animated:YES];
|
||||
self.searchDisplayController.searchBar.text = self.activeElement.name;
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointSelectElement];
|
||||
#endif
|
||||
|
||||
[self updateAnimated:YES];
|
||||
}
|
||||
|
||||
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointCancelSearch];
|
||||
#endif
|
||||
|
||||
[self updateAnimated:YES];
|
||||
}
|
||||
|
||||
@@ -420,7 +456,12 @@
|
||||
|
||||
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
|
||||
navigationType:(UIWebViewNavigationType)navigationType {
|
||||
|
||||
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointExternalLink];
|
||||
#endif
|
||||
|
||||
[[UIApplication sharedApplication] openURL:[request URL]];
|
||||
return NO;
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// MPRecentViewController.h
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 27/11/11.
|
||||
// Copyright (c) 2011 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface MPRecentViewController : UITableViewController
|
||||
|
||||
@property(nonatomic,retain) IBOutlet UITableView *tableView;
|
||||
|
||||
@end
|
||||
@@ -1,20 +0,0 @@
|
||||
//
|
||||
// MPRecentViewController.m
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 27/11/11.
|
||||
// Copyright (c) 2011 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPRecentViewController.h"
|
||||
|
||||
@implementation MPRecentViewController
|
||||
@dynamic tableView;
|
||||
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
|
||||
{
|
||||
// Return YES for supported orientations
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -252,6 +252,10 @@
|
||||
[self.fetchedResultsController.managedObjectContext performBlock:^{
|
||||
MPElementEntity *element = [self.fetchedResultsController objectAtIndexPath:indexPath];
|
||||
[self.fetchedResultsController.managedObjectContext deleteObject:element];
|
||||
|
||||
#ifndef PRODUCTION
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointDeleteElement];
|
||||
#endif
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,31 @@ typedef enum {
|
||||
MPElementTypeStoredDevicePrivate = MPElementTypeClassStored | 0x02,
|
||||
} MPElementType;
|
||||
|
||||
#ifndef PRODUCTION
|
||||
#define MPTestFlightCheckpointAction @"MPTestFlightCheckpointAction"
|
||||
#define MPTestFlightCheckpointHelpChapter @"MPTestFlightCheckpointHelpChapter_%@"
|
||||
#define MPTestFlightCheckpointCopyToPasteboard @"MPTestFlightCheckpointCopyToPasteboard"
|
||||
#define MPTestFlightCheckpointIncrementPasswordCounter @"MPTestFlightCheckpointIncrementPasswordCounter"
|
||||
#define MPTestFlightCheckpointEditPassword @"MPTestFlightCheckpointEditPassword"
|
||||
#define MPTestFlightCheckpointCloseAlert @"MPTestFlightCheckpointCloseAlert"
|
||||
#define MPTestFlightCheckpointSelectType @"MPTestFlightCheckpointSelectType_%@"
|
||||
#define MPTestFlightCheckpointSelectElement @"MPTestFlightCheckpointSelectElement"
|
||||
#define MPTestFlightCheckpointDeleteElement @"MPTestFlightCheckpointDeleteElement"
|
||||
#define MPTestFlightCheckpointCancelSearch @"MPTestFlightCheckpointCancelSearch"
|
||||
#define MPTestFlightCheckpointExternalLink @"MPTestFlightCheckpointExternalLink"
|
||||
#define MPTestFlightCheckpointLaunched @"MPTestFlightCheckpointLaunched"
|
||||
#define MPTestFlightCheckpointActivated @"MPTestFlightCheckpointActivated"
|
||||
#define MPTestFlightCheckpointDeactivated @"MPTestFlightCheckpointDeactivated"
|
||||
#define MPTestFlightCheckpointTerminated @"MPTestFlightCheckpointTerminated"
|
||||
#define MPTestFlightCheckpointShowGuide @"MPTestFlightCheckpointShowGuide"
|
||||
#define MPTestFlightCheckpointMPChanged @"MPTestFlightCheckpointMPChanged"
|
||||
#define MPTestFlightCheckpointMPUnstored @"MPTestFlightCheckpointMPUnstored"
|
||||
#define MPTestFlightCheckpointMPMismatch @"MPTestFlightCheckpointMPMismatch"
|
||||
#define MPTestFlightCheckpointMPAsked @"MPTestFlightCheckpointMPAsked"
|
||||
#define MPTestFlightCheckpointStoreIncompatible @"MPTestFlightCheckpointStoreIncompatible"
|
||||
#define MPTestFlightCheckpointSetKeyphraseLength @"MPTestFlightCheckpointSetKeyphraseLength_%d"
|
||||
#endif
|
||||
|
||||
NSString *NSStringFromMPElementType(MPElementType type);
|
||||
NSString *ClassNameFromMPElementType(MPElementType type);
|
||||
Class ClassFromMPElementType(MPElementType type);
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreData/CoreData.h>
|
||||
|
||||
#ifndef PRODUCTION
|
||||
#import "TestFlight.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define PEARL
|
||||
|
||||
Reference in New Issue
Block a user