2
0

Add TestFlight.

[ADDED]     TestFlightSDK implemented.
This commit is contained in:
Maarten Billemont
2012-02-06 00:40:20 +01:00
parent 2b9fcfe030
commit 360f71c4fa
16 changed files with 701 additions and 99 deletions

View File

@@ -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"]];
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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
}];
}

View File

@@ -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);

View File

@@ -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