2
0

Extract In-App logic into app delegate category & improvements to import file handling and advanced export + store fixes.

This commit is contained in:
Maarten Billemont 2014-09-21 10:29:18 -04:00
parent 4c12f368f5
commit 68e6106ee7
12 changed files with 98 additions and 122 deletions

2
External/Pearl vendored

@ -1 +1 @@
Subproject commit be82c9b4bfe8a58c72d1cc10d1a02e2d419edb38
Subproject commit 4afc758ce467cf75f2594512e2be3125c45d640c

View File

@ -18,6 +18,7 @@
#import "MPAlgorithmV0.h"
#import "MPEntities.h"
#import "MPAppDelegate_Shared.h"
#import "MPAppDelegate_InApp.h"
#include <openssl/bn.h>
#include <openssl/err.h>

View File

@ -9,6 +9,12 @@
#import "MPAppDelegate_Key.h"
#import "MPAppDelegate_Store.h"
@interface MPAppDelegate_Shared()
@property(strong, nonatomic) MPKey *key;
@end
@implementation MPAppDelegate_Shared(Key)
static NSDictionary *keyQuery(MPUserEntity *user) {

View File

@ -9,14 +9,13 @@
#import "MPEntities.h"
#if TARGET_OS_IPHONE
@interface MPAppDelegate_Shared : PearlAppDelegate
#else
@interface MPAppDelegate_Shared : NSObject <PearlConfigDelegate>
#endif
@property(strong, nonatomic) MPKey *key;
@property(strong, nonatomic) NSManagedObjectID *activeUserOID;
@property(strong, nonatomic, readonly) MPKey *key;
@property(strong, nonatomic, readonly) NSManagedObjectID *activeUserOID;
+ (instancetype)get;
@ -24,6 +23,4 @@
- (MPUserEntity *)activeUserInContext:(NSManagedObjectContext *)context;
- (void)setActiveUser:(MPUserEntity *)activeUser;
- (BOOL)isPurchased:(NSString *)productIdentifier;
@end

View File

@ -10,6 +10,13 @@
#import "MPAppDelegate_Store.h"
#import "MPAppDelegate_Key.h"
@interface MPAppDelegate_Shared ()
@property(strong, nonatomic) MPKey *key;
@property(strong, nonatomic) NSManagedObjectID *activeUserOID;
@end
@implementation MPAppDelegate_Shared
+ (MPAppDelegate_Shared *)get {
@ -50,9 +57,4 @@
self.activeUserOID = activeUser.objectID;
}
- (BOOL)isPurchased:(NSString *)productIdentifier {
return [[NSUserDefaults standardUserDefaults] objectForKey:productIdentifier] != nil;
}
@end

View File

@ -19,6 +19,10 @@
<string></string>
<key>CFBundleTypeIconFiles</key>
<array/>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>text/plain</string>
</array>
<key>CFBundleTypeName</key>
<string>Master Password sites</string>
<key>CFBundleTypeRole</key>
@ -27,8 +31,10 @@
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.lyndir.lhunath.MasterPassword.sites</string>
<string>com.lyndir.masterpassword.sites</string>
</array>
<key>LSTypeIsPackage</key>
<integer>0</integer>
</dict>
</array>
<key>CFBundleExecutable</key>
@ -47,19 +53,6 @@
<string>[auto]</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.lyndir.lhunath.MasterPassword</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.lyndir.lhunath.MasterPassword</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>[auto]</string>
<key>LSApplicationCategoryType</key>
@ -77,12 +70,16 @@
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.utf8-plain-text</string>
</array>
<key>UTTypeDescription</key>
<string>Master Password sites</string>
<key>UTTypeIconFile</key>
<string></string>
<key>UTTypeIdentifier</key>
<string>com.lyndir.lhunath.MasterPassword.sites</string>
<string>com.lyndir.masterpassword.sites</string>
<key>UTTypeSize320IconFile</key>
<string></string>
<key>UTTypeSize64IconFile</key>

View File

@ -20,6 +20,7 @@
#import "MPiOSAppDelegate.h"
#import "MPAppDelegate_Store.h"
#import "UIColor+Expanded.h"
#import "MPAppDelegate_InApp.h"
@interface MPPasswordCell()

View File

@ -14,6 +14,7 @@
#import "UIColor+Expanded.h"
#import "MPPasswordsViewController.h"
#import "MPCoachmarkViewController.h"
#import "MPAppDelegate_InApp.h"
@interface MPStoreViewController()
@ -53,7 +54,7 @@
[self updateWithProducts:to];
} );
}];
[[MPiOSAppDelegate get] observeKeyPath:@"productTransactions" withBlock:^(id from, id to, NSKeyValueChange cause, id _self) {
[[MPiOSAppDelegate get] observeKeyPath:@"paymentTransactions" withBlock:^(id from, id to, NSKeyValueChange cause, id _self) {
if (NSNullToNil( to ))
PearlMainQueue( ^{
[self updateWithTransactions:to];
@ -63,6 +64,8 @@
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
[self updateWithProducts:[MPiOSAppDelegate get].products];
}];
[[MPiOSAppDelegate get] updateProducts];
}
#pragma mark - UITableViewDelegate
@ -70,6 +73,10 @@
- (MPStoreProductCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MPStoreProductCell *cell = (MPStoreProductCell *)[super tableView:tableView cellForRowAtIndexPath:indexPath];
if (indexPath.section == 0)
cell.selectionStyle = [[MPiOSAppDelegate get] isPurchased:[self productForCell:cell].productIdentifier]?
UITableViewCellSelectionStyleDefault: UITableViewCellSelectionStyleNone;
if (cell.selectionStyle != UITableViewCellSelectionStyleNone) {
cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.bounds];
cell.selectedBackgroundView.backgroundColor = [UIColor colorWithRGBAHex:0x78DDFB33];
@ -80,24 +87,19 @@
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (![SKPaymentQueue canMakePayments]) {
[PearlAlert showAlertWithTitle:@"Store Not Set Up" message:
@"Try logging using the App Store or from Settings."
viewStyle:UIAlertViewStyleDefault initAlert:nil
tappedButtonBlock:nil cancelTitle:@"Thanks" otherTitles:nil];
return;
}
MPStoreProductCell *cell = (MPStoreProductCell *)[self tableView:tableView cellForRowAtIndexPath:indexPath];
SKProduct *product = [self productForCell:cell];
if (product && [SKPaymentQueue canMakePayments]) {
SKPayment *payment = nil;
if (cell == self.generateLoginCell)
payment = [SKPayment paymentWithProduct:product];
if (cell == self.generateAnswersCell) {
}
if (cell == self.advancedExportCell) {
}
if (cell == self.iOSIntegrationCell) {
}
if (cell == self.touchIDCell) {
}
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
if (product)
[[SKPaymentQueue defaultQueue] addPayment:[SKPayment paymentWithProduct:product]];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

View File

@ -14,10 +14,6 @@
@interface MPiOSAppDelegate : MPAppDelegate_Shared
@property(nonatomic, strong) NSArray /* SKProduct */ *products;
@property(nonatomic, strong) NSArray *productTransactions;
- (void)showFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController;
- (void)openFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController;

View File

@ -7,17 +7,20 @@
//
#import <Crashlytics/Crashlytics.h>
#import <MobileCoreServices/MobileCoreServices.h>
#import "MPiOSAppDelegate.h"
#import "MPAppDelegate_Key.h"
#import "MPAppDelegate_Store.h"
#import "IASKSettingsReader.h"
#import "MPAppDelegate_InApp.h"
@interface MPiOSAppDelegate()<SKProductsRequestDelegate, SKPaymentTransactionObserver>
@interface MPiOSAppDelegate()<UIDocumentInteractionControllerDelegate>
@property(nonatomic, weak) PearlAlert *handleCloudDisabledAlert;
@property(nonatomic, weak) PearlAlert *handleCloudContentAlert;
@property(nonatomic, weak) PearlAlert *fixCloudContentAlert;
@property(nonatomic, weak) PearlOverlay *storeLoadingOverlay;
@property(nonatomic, strong) UIDocumentInteractionController *interactionController;
@end
@implementation MPiOSAppDelegate
@ -148,12 +151,6 @@
@"legal" : @"YES",
#endif
} );
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[[NSSet alloc] initWithObjects:
MPProductGenerateLogins, nil]];
productsRequest.delegate = self;
[productsRequest start];
}
@catch (id exception) {
err( @"During Post-Startup: %@", exception );
@ -282,53 +279,6 @@
[super applicationDidBecomeActive:application];
}
#pragma mark - SKProductsRequestDelegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
inf( @"products: %@, invalid: %@", response.products, response.invalidProductIdentifiers );
self.products = response.products;
}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
err( @"StoreKit request (%@) failed: %@", request, error );
}
- (void)requestDidFinish:(SKRequest *)request {
dbg( @"StoreKit request (%@) finished.", request );
}
#pragma mark - SKPaymentTransactionObserver
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction *transaction in transactions) {
dbg( @"transaction updated: %@", transaction );
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased:
case SKPaymentTransactionStateRestored: {
inf( @"purchased: %@", transaction.payment.productIdentifier );
[[NSUserDefaults standardUserDefaults] setObject:transaction.transactionIdentifier
forKey:transaction.payment.productIdentifier];
break;
}
case SKPaymentTransactionStatePurchasing:
case SKPaymentTransactionStateFailed:
case SKPaymentTransactionStateDeferred:
break;
}
}
self.productTransactions = transactions;
}
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {
err( @"StoreKit restore failed: %@", error );
}
#pragma mark - Behavior
- (void)showReview {
@ -464,12 +414,30 @@
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"];
NSString *exportFileName = strf( @"%@ (%@).mpsites",
[self activeUserForMainThread].name, [exportDateFormatter stringFromDate:[NSDate date]] );
if (![[MPiOSAppDelegate get] isPurchased:MPProductAdvancedExport])
[PearlEMail sendEMailTo:nil fromVC:viewController subject:@"Master Password Export" body:message
attachments:[[PearlEMailAttachment alloc] initWithContent:[exportedSites dataUsingEncoding:NSUTF8StringEncoding]
mimeType:@"text/plain" fileName:
strf( @"%@ (%@).mpsites", [self activeUserForMainThread].name,
[exportDateFormatter stringFromDate:[NSDate date]] )],
mimeType:@"text/plain" fileName:exportFileName],
nil];
else {
NSURL *applicationSupportURL = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory
inDomains:NSUserDomainMask] lastObject];
NSURL *exportURL = [[applicationSupportURL
URLByAppendingPathComponent:[NSBundle mainBundle].bundleIdentifier isDirectory:YES]
URLByAppendingPathComponent:exportFileName isDirectory:NO];
NSError *error = nil;
if (![[exportedSites dataUsingEncoding:NSUTF8StringEncoding]
writeToURL:exportURL options:NSDataWritingFileProtectionComplete error:&error])
err( @"Failed to write export data to URL %@: %@", exportURL, error );
else {
self.interactionController = [UIDocumentInteractionController interactionControllerWithURL:exportURL];
self.interactionController.UTI = @"com.lyndir.masterpassword.sites";
self.interactionController.delegate = self;
[self.interactionController presentOpenInMenuFromRect:CGRectZero inView:viewController.view animated:YES];
}
}
}
- (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void ( ^ )(void))didReset {
@ -501,6 +469,13 @@
otherTitles:[PearlStrings get].commonButtonContinue, nil];
}
#pragma mark - UIDocumentInteractionControllerDelegate
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application {
// self.interactionController = nil;
}
#pragma mark - PearlConfigDelegate
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)value {

View File

@ -21,7 +21,7 @@
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.lyndir.lhunath.MasterPassword.sites</string>
<string>com.lyndir.masterpassword.sites</string>
</array>
</dict>
</array>
@ -39,19 +39,6 @@
<string>[auto]</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.lyndir.lhunath.MasterPassword</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.lyndir.lhunath.MasterPassword</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>[auto]</string>
<key>LSRequiresIPhoneOS</key>
@ -109,10 +96,14 @@
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.utf8-plain-text</string>
</array>
<key>UTTypeDescription</key>
<string>Master Password sites</string>
<key>UTTypeIdentifier</key>
<string>com.lyndir.lhunath.MasterPassword.sites</string>
<string>com.lyndir.masterpassword.sites</string>
<key>UTTypeSize320IconFile</key>
<string></string>
<key>UTTypeSize64IconFile</key>

View File

@ -42,6 +42,7 @@
93D39B8F90F58A5D158DDBA3 /* MPPasswordsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */; };
93D39BA1EA3CAAC8A220B4A6 /* MPAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.m */; };
93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; };
93D39D38356F59DBEF934D70 /* MPAppDelegate_InApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D394C78C7B879C9AD9152C /* MPAppDelegate_InApp.m */; };
93D39D47FC623E91FC39D20C /* UICollectionView+PearlReloadFromArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3908DF8EABBD952065DC0 /* UICollectionView+PearlReloadFromArray.m */; };
93D39D596A2E376D6F6F5DA1 /* MPCombinedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D393310223DDB35218467A /* MPCombinedViewController.m */; };
93D39D8F78978196D6ABDEDE /* MPNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39CC01630D0421205C4C4 /* MPNavigationController.m */; };
@ -408,6 +409,7 @@
93D394077F8FAB8167647187 /* Twitter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Twitter.framework; path = System/Library/Frameworks/Twitter.framework; sourceTree = SDKROOT; };
93D3942A356B639724157982 /* PearlOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlOverlay.h; sourceTree = "<group>"; };
93D394482BB07F90E8FD1314 /* UIResponder+PearlFirstResponder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIResponder+PearlFirstResponder.h"; sourceTree = "<group>"; };
93D394C78C7B879C9AD9152C /* MPAppDelegate_InApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppDelegate_InApp.m; sourceTree = "<group>"; };
93D3956915634581E737B38C /* PearlNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlNavigationController.m; sourceTree = "<group>"; };
93D3957D76F71A652716EECC /* MPStoreViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPStoreViewController.m; sourceTree = "<group>"; };
93D396D04E57792A54D437AC /* NSArray+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Indexing.h"; sourceTree = "<group>"; };
@ -440,6 +442,7 @@
93D39C86E984EC65DA5ACB1D /* MPAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppSettingsViewController.h; sourceTree = "<group>"; };
93D39CC01630D0421205C4C4 /* MPNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNavigationController.m; sourceTree = "<group>"; };
93D39CDD434AFD6E1B0DA359 /* MPEmergencyViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEmergencyViewController.h; sourceTree = "<group>"; };
93D39CECA10BCCB0BA581BF1 /* MPAppDelegate_InApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppDelegate_InApp.h; sourceTree = "<group>"; };
93D39CF8ADF4542CDC4CD385 /* MPCombinedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCombinedViewController.h; sourceTree = "<group>"; };
93D39D8A953779B35403AF6E /* PearlUICollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlUICollectionView.m; sourceTree = "<group>"; };
93D39DA27D768B53C8B1330C /* MPAvatarCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAvatarCell.h; sourceTree = "<group>"; };
@ -1370,6 +1373,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
DA04E33E14B1E70400ECA4F3 /* MobileCoreServices.framework in Frameworks */,
DAE2725A19C93B8E007C5262 /* StoreKit.framework in Frameworks */,
DAE2725919C93B80007C5262 /* libInAppSettingsKit.a in Frameworks */,
DA6701E016406BB400B61001 /* AdSupport.framework in Frameworks */,
@ -1381,7 +1385,6 @@
DA672D2F14F92C6B004A189C /* libz.dylib in Frameworks */,
DAEBC45314F6364500987BF6 /* QuartzCore.framework in Frameworks */,
DA95D5F214DF0B2C008D1B94 /* MessageUI.framework in Frameworks */,
DA04E33E14B1E70400ECA4F3 /* MobileCoreServices.framework in Frameworks */,
DA48856019A5A82E000C2D79 /* Crashlytics.framework in Frameworks */,
DAC632891486D9690075AEA5 /* Security.framework in Frameworks */,
DA72BD7919C137DE00E6ACFE /* libopensslcrypto-ios-dev.a in Frameworks */,
@ -2292,6 +2295,8 @@
DABD3BD01711E2DC00CF925C /* MasterPassword.xcdatamodeld */,
93D399F244BB522A317811BB /* MPFixable.h */,
93D39A813CA9D7E192261ED2 /* MPFixable.m */,
93D394C78C7B879C9AD9152C /* MPAppDelegate_InApp.m */,
93D39CECA10BCCB0BA581BF1 /* MPAppDelegate_InApp.h */,
);
name = ObjC;
path = ..;
@ -3231,6 +3236,9 @@
93D394982CBD25D46692DD7C /* MPWebViewController.m in Sources */,
93D39D8F78978196D6ABDEDE /* MPNavigationController.m in Sources */,
93D3939661CE37180AF7CD6A /* MPStoreViewController.m in Sources */,
DA9521AB19CEA3DE002E3AD5 /* MPSiteQuestion.m in Sources */,
93D39D38356F59DBEF934D70 /* MPAppDelegate_InApp.m in Sources */,
93D390C1B93F9D3AE37DD0A5 /* MPAnswersViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};