Reformat.
This commit is contained in:
parent
c0d57b5561
commit
95d5d8b40c
2
External/Pearl
vendored
2
External/Pearl
vendored
@ -1 +1 @@
|
||||
Subproject commit 737b198043a3acb3a262a38a8b14e265801ce682
|
||||
Subproject commit affcd43c4e50b99f12da5b3cf342bc6fab6e0298
|
@ -24,8 +24,7 @@ id<MPAlgorithm> MPAlgorithmForVersion(NSUInteger version) {
|
||||
versionToAlgorithm = [NSMutableDictionary dictionary];
|
||||
|
||||
id<MPAlgorithm> algorithm = [versionToAlgorithm objectForKey:@(version)];
|
||||
if (!algorithm)
|
||||
if ((algorithm = [NSClassFromString(PearlString(@"MPAlgorithmV%lu", (unsigned long)version)) new]))
|
||||
if (!algorithm) if ((algorithm = [NSClassFromString( PearlString( @"MPAlgorithmV%lu", (unsigned long)version ) ) new]))
|
||||
[versionToAlgorithm setObject:algorithm forKey:@(version)];
|
||||
|
||||
return algorithm;
|
||||
@ -33,9 +32,9 @@ id<MPAlgorithm> MPAlgorithmForVersion(NSUInteger version) {
|
||||
|
||||
id<MPAlgorithm> MPAlgorithmDefaultForBundleVersion(NSString *bundleVersion) {
|
||||
|
||||
if (PearlCFBundleVersionCompare(bundleVersion, @"1.3") == NSOrderedAscending)
|
||||
if (PearlCFBundleVersionCompare( bundleVersion, @"1.3" ) == NSOrderedAscending)
|
||||
// Pre-1.3
|
||||
return MPAlgorithmForVersion(0);
|
||||
return MPAlgorithmForVersion( 0 );
|
||||
|
||||
return MPAlgorithmDefault;
|
||||
}
|
||||
|
@ -17,5 +17,5 @@
|
||||
|
||||
#import "MPAlgorithm.h"
|
||||
|
||||
@interface MPAlgorithmV0 : NSObject <MPAlgorithm>
|
||||
@interface MPAlgorithmV0 : NSObject<MPAlgorithm>
|
||||
@end
|
||||
|
@ -34,7 +34,7 @@
|
||||
- (BOOL)migrateUser:(MPUserEntity *)user {
|
||||
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *migrationRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
|
||||
NSFetchRequest *migrationRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
||||
migrationRequest.predicate = [NSPredicate predicateWithFormat:@"version_ < %d AND user == %@", self.version, user];
|
||||
NSArray *migrationElements = [user.managedObjectContext executeFetchRequest:migrationRequest error:&error];
|
||||
if (!migrationElements) {
|
||||
@ -166,7 +166,7 @@
|
||||
|
||||
- (NSString *)classNameOfType:(MPElementType)type {
|
||||
|
||||
return NSStringFromClass([self classOfType:type]);
|
||||
return NSStringFromClass( [self classOfType:type] );
|
||||
}
|
||||
|
||||
- (Class)classOfType:(MPElementType)type {
|
||||
@ -258,10 +258,10 @@
|
||||
NSMutableString *content = [NSMutableString stringWithCapacity:[cipher length]];
|
||||
for (NSUInteger c = 0; c < [cipher length]; ++c) {
|
||||
uint16_t keyByte = htons(seedBytes[c + 1]);
|
||||
NSString *cipherClass = [cipher substringWithRange:NSMakeRange(c, 1)];
|
||||
NSString *cipherClass = [cipher substringWithRange:NSMakeRange( c, 1 )];
|
||||
NSString *cipherClassCharacters = [[MPTypes_ciphers valueForKey:@"MPCharacterClasses"] valueForKey:cipherClass];
|
||||
NSString *character = [cipherClassCharacters substringWithRange:NSMakeRange(keyByte % [cipherClassCharacters length],
|
||||
1)];
|
||||
NSString *character = [cipherClassCharacters substringWithRange:NSMakeRange( keyByte % [cipherClassCharacters length],
|
||||
1 )];
|
||||
|
||||
trc(@"class %@ has characters: %@, index: %u, selected: %@", cipherClass, cipherClassCharacters, keyByte, character);
|
||||
[content appendString:character];
|
||||
|
@ -17,6 +17,5 @@
|
||||
|
||||
#import "MPAlgorithmV0.h"
|
||||
|
||||
|
||||
@interface MPAlgorithmV1 : MPAlgorithmV0
|
||||
@end
|
||||
|
@ -18,7 +18,6 @@
|
||||
#import "MPAlgorithmV1.h"
|
||||
#import "MPEntities.h"
|
||||
|
||||
|
||||
@implementation MPAlgorithmV1
|
||||
|
||||
- (NSUInteger)version {
|
||||
@ -80,10 +79,10 @@
|
||||
NSMutableString *content = [NSMutableString stringWithCapacity:[cipher length]];
|
||||
for (NSUInteger c = 0; c < [cipher length]; ++c) {
|
||||
uint16_t keyByte = seedBytes[c + 1];
|
||||
NSString *cipherClass = [cipher substringWithRange:NSMakeRange(c, 1)];
|
||||
NSString *cipherClass = [cipher substringWithRange:NSMakeRange( c, 1 )];
|
||||
NSString *cipherClassCharacters = [[MPTypes_ciphers valueForKey:@"MPCharacterClasses"] valueForKey:cipherClass];
|
||||
NSString *character = [cipherClassCharacters substringWithRange:NSMakeRange(keyByte % [cipherClassCharacters length],
|
||||
1)];
|
||||
NSString *character = [cipherClassCharacters substringWithRange:NSMakeRange( keyByte % [cipherClassCharacters length],
|
||||
1 )];
|
||||
|
||||
trc(@"class %@ has characters: %@, index: %u, selected: %@", cipherClass, cipherClassCharacters, keyByte, character);
|
||||
[content appendString:character];
|
||||
@ -92,5 +91,4 @@
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#import "MPAppDelegate_Shared.h"
|
||||
|
||||
@interface MPAppDelegate_Shared (Key)
|
||||
@interface MPAppDelegate_Shared(Key)
|
||||
|
||||
- (BOOL)signInAsUser:(MPUserEntity *)user usingMasterPassword:(NSString *)password;
|
||||
- (void)signOutAnimated:(BOOL)animated;
|
||||
|
@ -9,21 +9,21 @@
|
||||
#import "MPAppDelegate_Key.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
|
||||
@implementation MPAppDelegate_Shared (Key)
|
||||
@implementation MPAppDelegate_Shared(Key)
|
||||
|
||||
static NSDictionary *keyQuery(MPUserEntity *user) {
|
||||
|
||||
return [PearlKeyChain createQueryForClass:kSecClassGenericPassword
|
||||
attributes:@{
|
||||
(__bridge id)kSecAttrService: @"Saved Master Password",
|
||||
(__bridge id)kSecAttrAccount: IfNotNilElse(user.name, @"")
|
||||
(__bridge id)kSecAttrService : @"Saved Master Password",
|
||||
(__bridge id)kSecAttrAccount : IfNotNilElse(user.name, @"")
|
||||
}
|
||||
matches:nil];
|
||||
}
|
||||
|
||||
- (MPKey *)loadSavedKeyFor:(MPUserEntity *)user {
|
||||
|
||||
NSData *keyData = [PearlKeyChain dataOfItemForQuery:keyQuery(user)];
|
||||
NSData *keyData = [PearlKeyChain dataOfItemForQuery:keyQuery( user )];
|
||||
if (keyData)
|
||||
inf(@"Found key in keychain for: %@", user.userID);
|
||||
|
||||
@ -38,12 +38,12 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
||||
- (void)storeSavedKeyFor:(MPUserEntity *)user {
|
||||
|
||||
if (user.saveKey) {
|
||||
NSData *existingKeyData = [PearlKeyChain dataOfItemForQuery:keyQuery(user)];
|
||||
NSData *existingKeyData = [PearlKeyChain dataOfItemForQuery:keyQuery( user )];
|
||||
|
||||
if (![existingKeyData isEqualToData:self.key.keyData]) {
|
||||
inf(@"Saving key in keychain for: %@", user.userID);
|
||||
|
||||
[PearlKeyChain addOrUpdateItemForQuery:keyQuery(user)
|
||||
[PearlKeyChain addOrUpdateItemForQuery:keyQuery( user )
|
||||
withAttributes:@{
|
||||
(__bridge id)kSecValueData : self.key.keyData,
|
||||
#if TARGET_OS_IPHONE
|
||||
@ -56,7 +56,7 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
||||
|
||||
- (void)forgetSavedKeyFor:(MPUserEntity *)user {
|
||||
|
||||
OSStatus result = [PearlKeyChain deleteItemForQuery:keyQuery(user)];
|
||||
OSStatus result = [PearlKeyChain deleteItemForQuery:keyQuery( user )];
|
||||
if (result == noErr || result == errSecItemNotFound) {
|
||||
user.saveKey = NO;
|
||||
|
||||
@ -74,7 +74,7 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
||||
self.key = nil;
|
||||
|
||||
self.activeUser = nil;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPSignedOutNotification object:self userInfo:@{@"animated": @(animated)}];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPSignedOutNotification object:self userInfo:@{ @"animated" : @(animated) }];
|
||||
}
|
||||
|
||||
- (BOOL)signInAsUser:(MPUserEntity *)user usingMasterPassword:(NSString *)password {
|
||||
@ -84,8 +84,7 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
||||
|
||||
// Method 1: When the user has no keyID set, set a new key from the given master password.
|
||||
if (!user.keyID) {
|
||||
if ([password length])
|
||||
if ((tryKey = [MPAlgorithmDefault keyForPassword:password ofUserNamed:user.name])) {
|
||||
if ([password length]) if ((tryKey = [MPAlgorithmDefault keyForPassword:password ofUserNamed:user.name])) {
|
||||
user.keyID = tryKey.keyID;
|
||||
|
||||
// Migrate existing elements.
|
||||
@ -98,11 +97,9 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
||||
// Key should not be stored in keychain. Delete it.
|
||||
[self forgetSavedKeyFor:user];
|
||||
|
||||
else
|
||||
if (!tryKey) {
|
||||
else if (!tryKey) {
|
||||
// Key should be saved in keychain. Load it.
|
||||
if ((tryKey = [self loadSavedKeyFor:user]))
|
||||
if (![user.keyID isEqual:tryKey.keyID]) {
|
||||
if ((tryKey = [self loadSavedKeyFor:user])) if (![user.keyID isEqual:tryKey.keyID]) {
|
||||
// Loaded password doesn't match user's keyID. Forget saved password: it is incorrect.
|
||||
inf(@"Saved password doesn't match keyID for: %@", user.userID);
|
||||
|
||||
@ -113,9 +110,8 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
||||
|
||||
// Method 3: Check the given master password string.
|
||||
if (!tryKey) {
|
||||
if ([password length])
|
||||
if ((tryKey = [MPAlgorithmDefault keyForPassword:password ofUserNamed:user.name]))
|
||||
if (![user.keyID isEqual:tryKey.keyID]) {
|
||||
if ([password length]) if ((tryKey = [MPAlgorithmDefault keyForPassword:password
|
||||
ofUserNamed:user.name])) if (![user.keyID isEqual:tryKey.keyID]) {
|
||||
inf(@"Key derived from password doesn't match keyID for: %@", user.userID);
|
||||
|
||||
tryKey = nil;
|
||||
|
@ -15,7 +15,7 @@
|
||||
@interface MPAppDelegate_Shared : NSObject <PearlConfigDelegate>
|
||||
#endif
|
||||
|
||||
@property (strong, nonatomic) MPKey *key;
|
||||
@property(strong, nonatomic) MPKey *key;
|
||||
|
||||
+ (instancetype)get;
|
||||
|
||||
|
@ -18,7 +18,7 @@ typedef enum {
|
||||
MPImportResultInternalError,
|
||||
} MPImportResult;
|
||||
|
||||
@interface MPAppDelegate_Shared (Store)<UbiquityStoreManagerDelegate>
|
||||
@interface MPAppDelegate_Shared(Store)<UbiquityStoreManagerDelegate>
|
||||
|
||||
+ (NSManagedObjectContext *)managedObjectContextForThreadIfReady;
|
||||
+ (BOOL)managedObjectContextPerformBlock:(void (^)(NSManagedObjectContext *moc))mocBlock;
|
||||
|
@ -15,8 +15,8 @@
|
||||
#define STORE_OPTIONS
|
||||
#endif
|
||||
|
||||
@implementation MPAppDelegate_Shared (Store)
|
||||
PearlAssociatedObjectProperty(PearlAlert*, HandleCloudContentAlert, handleCloudContentAlert);
|
||||
@implementation MPAppDelegate_Shared(Store)
|
||||
PearlAssociatedObjectProperty(PearlAlert*, HandleCloudContentAlert, handleCloudContentAlert);
|
||||
PearlAssociatedObjectProperty(PearlAlert*, FixCloudContentAlert, fixCloudContentAlert);
|
||||
PearlAssociatedObjectProperty(PearlOverlay*, StoreLoading, storeLoading);
|
||||
PearlAssociatedObjectProperty(NSManagedObjectContext*, PrivateManagedObjectContext, privateManagedObjectContext);
|
||||
@ -31,7 +31,8 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
if ([[NSThread currentThread] isMainThread])
|
||||
return mainManagedObjectContext;
|
||||
|
||||
NSManagedObjectContext *threadManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
|
||||
NSManagedObjectContext
|
||||
*threadManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
|
||||
threadManagedObjectContext.parentContext = mainManagedObjectContext;
|
||||
|
||||
return threadManagedObjectContext;
|
||||
@ -46,7 +47,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||
moc.parentContext = mainManagedObjectContext;
|
||||
[moc performBlock:^{
|
||||
mocBlock(moc);
|
||||
mocBlock( moc );
|
||||
}];
|
||||
|
||||
return YES;
|
||||
@ -61,7 +62,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||
moc.parentContext = mainManagedObjectContext;
|
||||
[moc performBlockAndWait:^{
|
||||
mocBlock(moc);
|
||||
mocBlock( moc );
|
||||
}];
|
||||
|
||||
return YES;
|
||||
@ -87,7 +88,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
|
||||
storeManager = [[UbiquityStoreManager alloc] initStoreNamed:nil withManagedObjectModel:nil localStoreURL:nil
|
||||
containerIdentifier:@"HL3Q45LX9N.com.lyndir.lhunath.MasterPassword.shared"
|
||||
additionalStoreOptions:@{STORE_OPTIONS}
|
||||
additionalStoreOptions:@{ STORE_OPTIONS }
|
||||
delegate:self];
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
@ -321,10 +322,10 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
self.privateManagedObjectContext = nil;
|
||||
self.mainManagedObjectContext = nil;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
if (![self.storeLoading isVisible])
|
||||
self.storeLoading = [PearlOverlay showOverlayWithTitle:@"Opening Your Data"];
|
||||
});
|
||||
} );
|
||||
|
||||
[self migrateStoreForManager:manager isCloud:isCloudStore];
|
||||
}
|
||||
@ -338,7 +339,8 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
} );
|
||||
|
||||
// Create our contexts.
|
||||
NSManagedObjectContext *privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||
NSManagedObjectContext
|
||||
*privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||
[privateManagedObjectContext performBlockAndWait:^{
|
||||
privateManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
|
||||
privateManagedObjectContext.persistentStoreCoordinator = coordinator;
|
||||
@ -433,7 +435,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
NSAssert(![[NSThread currentThread] isMainThread], @"This method should not be invoked from the main thread.");
|
||||
NSManagedObjectContext *moc;
|
||||
while (!(moc = [MPAppDelegate_Shared managedObjectContextForThreadIfReady]))
|
||||
usleep((useconds_t)(USEC_PER_SEC * 0.2));
|
||||
usleep( (useconds_t)(USEC_PER_SEC * 0.2) );
|
||||
|
||||
// Parse import data.
|
||||
inf(@"Importing sites.");
|
||||
@ -445,7 +447,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
NSArray *importedSiteLines = [importedSitesString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
|
||||
NSMutableSet *elementsToDelete = [NSMutableSet set];
|
||||
NSMutableArray *importedSiteElements = [NSMutableArray arrayWithCapacity:[importedSiteLines count]];
|
||||
NSFetchRequest *elementFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
|
||||
NSFetchRequest *elementFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
||||
for (NSString *importedSiteLine in importedSiteLines) {
|
||||
if ([importedSiteLine hasPrefix:@"#"]) {
|
||||
// Comment or header
|
||||
@ -468,13 +470,13 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
return MPImportResultMalformedInput;
|
||||
}
|
||||
NSTextCheckingResult *headerElements = [[headerPattern matchesInString:importedSiteLine options:(NSMatchingOptions)0
|
||||
range:NSMakeRange(0, [importedSiteLine length])] lastObject];
|
||||
range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
|
||||
NSString *headerName = [importedSiteLine substringWithRange:[headerElements rangeAtIndex:1]];
|
||||
NSString *headerValue = [importedSiteLine substringWithRange:[headerElements rangeAtIndex:2]];
|
||||
if ([headerName isEqualToString:@"User Name"]) {
|
||||
importUserName = headerValue;
|
||||
|
||||
NSFetchRequest *userFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPUserEntity class])];
|
||||
NSFetchRequest *userFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
|
||||
userFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@", importUserName];
|
||||
NSArray *users = [moc executeFetchRequest:userFetchRequest error:&error];
|
||||
if (!users) {
|
||||
@ -493,7 +495,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
importKeyID = [headerValue decodeHex];
|
||||
if ([headerName isEqualToString:@"Version"]) {
|
||||
importBundleVersion = headerValue;
|
||||
importAlgorithm = MPAlgorithmDefaultForBundleVersion(importBundleVersion);
|
||||
importAlgorithm = MPAlgorithmDefaultForBundleVersion( importBundleVersion );
|
||||
}
|
||||
if ([headerName isEqualToString:@"Passwords"]) {
|
||||
if ([headerValue isEqualToString:@"VISIBLE"])
|
||||
@ -516,7 +518,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
return MPImportResultMalformedInput;
|
||||
}
|
||||
NSTextCheckingResult *siteElements = [[sitePattern matchesInString:importedSiteLine options:(NSMatchingOptions)0
|
||||
range:NSMakeRange(0, [importedSiteLine length])] lastObject];
|
||||
range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
|
||||
NSString *lastUsed = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:1]];
|
||||
NSString *uses = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:2]];
|
||||
NSString *type = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:3]];
|
||||
@ -531,18 +533,18 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
if (!existingSites) {
|
||||
err(@"Lookup of existing sites failed for site: %@, user: %@, error: %@", name, user.userID, error);
|
||||
return MPImportResultInternalError;
|
||||
} else
|
||||
if (existingSites.count)
|
||||
}
|
||||
else if (existingSites.count)
|
||||
dbg(@"Existing sites: %@", existingSites);
|
||||
|
||||
[elementsToDelete addObjectsFromArray:existingSites];
|
||||
[importedSiteElements addObject:@[lastUsed, uses, type, version, name, exportContent]];
|
||||
[importedSiteElements addObject:@[ lastUsed, uses, type, version, name, exportContent ]];
|
||||
}
|
||||
}
|
||||
|
||||
// Ask for confirmation to import these sites and the master password of the user.
|
||||
inf(@"Importing %lu sites, deleting %lu sites, for user: %@", (unsigned long)[importedSiteElements count], (unsigned long)[elementsToDelete count], [MPUserEntity idFor:importUserName]);
|
||||
NSString *userMasterPassword = userPassword(user.name, [importedSiteElements count], [elementsToDelete count]);
|
||||
NSString *userMasterPassword = userPassword( user.name, [importedSiteElements count], [elementsToDelete count] );
|
||||
if (!userMasterPassword) {
|
||||
inf(@"Import cancelled.");
|
||||
return MPImportResultCancelled;
|
||||
@ -563,7 +565,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
|
||||
// Make sure there is a user.
|
||||
if (!user) {
|
||||
user = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MPUserEntity class])
|
||||
user = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass( [MPUserEntity class] )
|
||||
inManagedObjectContext:moc];
|
||||
user.name = importUserName;
|
||||
user.keyID = importKeyID;
|
||||
@ -580,7 +582,8 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
NSString *exportContent = [siteElements objectAtIndex:5];
|
||||
|
||||
// Create new site.
|
||||
MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:[MPAlgorithmForVersion(version) classNameOfType:type]
|
||||
MPElementEntity
|
||||
*element = [NSEntityDescription insertNewObjectForEntityForName:[MPAlgorithmForVersion( version ) classNameOfType:type]
|
||||
inManagedObjectContext:moc];
|
||||
element.name = name;
|
||||
element.user = user;
|
||||
@ -593,7 +596,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
[element importClearTextContent:exportContent usingKey:userKey];
|
||||
else {
|
||||
if (!importKey)
|
||||
importKey = [importAlgorithm keyForPassword:importPassword(user.name) ofUserNamed:user.name];
|
||||
importKey = [importAlgorithm keyForPassword:importPassword( user.name ) ofUserNamed:user.name];
|
||||
if (![importKey.keyID isEqualToData:importKeyID])
|
||||
return MPImportResultInvalidPassword;
|
||||
|
||||
@ -655,14 +658,13 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
if (!(type & MPElementFeatureDevicePrivate)) {
|
||||
if (showPasswords)
|
||||
content = element.content;
|
||||
else
|
||||
if (type & MPElementFeatureExportContent)
|
||||
else if (type & MPElementFeatureExportContent)
|
||||
content = element.exportContent;
|
||||
}
|
||||
|
||||
[export appendFormat:@"%@ %8ld %8s %20s\t%@\n",
|
||||
[[NSDateFormatter rfc3339DateFormatter] stringFromDate:lastUsed], (long)uses,
|
||||
[PearlString(@"%u:%lu", type, (unsigned long)version) UTF8String], [name UTF8String], content
|
||||
[PearlString( @"%u:%lu", type, (unsigned long)version ) UTF8String], [name UTF8String], content
|
||||
? content: @""];
|
||||
}
|
||||
|
||||
|
@ -10,9 +10,9 @@
|
||||
|
||||
@interface MPConfig : PearlConfig
|
||||
|
||||
@property (nonatomic, retain) NSNumber *sendInfo;
|
||||
@property (nonatomic, retain) NSNumber *rememberLogin;
|
||||
@property(nonatomic, retain) NSNumber *sendInfo;
|
||||
@property(nonatomic, retain) NSNumber *rememberLogin;
|
||||
|
||||
@property (nonatomic, retain) NSNumber *iCloudDecided;
|
||||
@property(nonatomic, retain) NSNumber *iCloudDecided;
|
||||
|
||||
@end
|
||||
|
@ -9,6 +9,7 @@
|
||||
#import "MPAppDelegate.h"
|
||||
|
||||
@implementation MPConfig
|
||||
|
||||
@dynamic sendInfo, rememberLogin, iCloudDecided;
|
||||
|
||||
- (id)init {
|
||||
@ -16,11 +17,13 @@
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
[self.defaults registerDefaults:@{NSStringFromSelector(@selector(askForReviews)): @YES,
|
||||
[self.defaults registerDefaults:@{
|
||||
NSStringFromSelector( @selector(askForReviews) ) : @YES,
|
||||
|
||||
NSStringFromSelector(@selector(sendInfo)): @NO,
|
||||
NSStringFromSelector(@selector(rememberLogin)): @NO,
|
||||
NSStringFromSelector(@selector(iCloudDecided)): @NO}];
|
||||
NSStringFromSelector( @selector(sendInfo) ) : @NO,
|
||||
NSStringFromSelector( @selector(rememberLogin) ) : @NO,
|
||||
NSStringFromSelector( @selector(iCloudDecided) ) : @NO
|
||||
}];
|
||||
|
||||
self.delegate = [MPAppDelegate get];
|
||||
|
||||
|
@ -13,14 +13,14 @@
|
||||
|
||||
@interface MPElementEntity : NSManagedObject
|
||||
|
||||
@property (nonatomic, retain) id content;
|
||||
@property (nonatomic, retain) NSDate * lastUsed;
|
||||
@property (nonatomic, retain) NSString * loginName;
|
||||
@property (nonatomic, retain) NSString * name;
|
||||
@property (nonatomic, retain) NSNumber * requiresExplicitMigration_;
|
||||
@property (nonatomic, retain) NSNumber * type_;
|
||||
@property (nonatomic, retain) NSNumber * uses_;
|
||||
@property (nonatomic, retain) NSNumber * version_;
|
||||
@property (nonatomic, retain) MPUserEntity *user;
|
||||
@property(nonatomic, retain) id content;
|
||||
@property(nonatomic, retain) NSDate *lastUsed;
|
||||
@property(nonatomic, retain) NSString *loginName;
|
||||
@property(nonatomic, retain) NSString *name;
|
||||
@property(nonatomic, retain) NSNumber *requiresExplicitMigration_;
|
||||
@property(nonatomic, retain) NSNumber *type_;
|
||||
@property(nonatomic, retain) NSNumber *uses_;
|
||||
@property(nonatomic, retain) NSNumber *version_;
|
||||
@property(nonatomic, retain) MPUserEntity *user;
|
||||
|
||||
@end
|
||||
|
@ -7,8 +7,6 @@
|
||||
//
|
||||
|
||||
#import "MPElementEntity.h"
|
||||
#import "MPUserEntity.h"
|
||||
|
||||
|
||||
@implementation MPElementEntity
|
||||
|
||||
|
@ -10,9 +10,8 @@
|
||||
#import <CoreData/CoreData.h>
|
||||
#import "MPElementEntity.h"
|
||||
|
||||
|
||||
@interface MPElementGeneratedEntity : MPElementEntity
|
||||
|
||||
@property (nonatomic, retain) NSNumber * counter_;
|
||||
@property(nonatomic, retain) NSNumber *counter_;
|
||||
|
||||
@end
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
#import "MPElementGeneratedEntity.h"
|
||||
|
||||
|
||||
@implementation MPElementGeneratedEntity
|
||||
|
||||
@dynamic counter_;
|
||||
|
@ -10,9 +10,8 @@
|
||||
#import <CoreData/CoreData.h>
|
||||
#import "MPElementEntity.h"
|
||||
|
||||
|
||||
@interface MPElementStoredEntity : MPElementEntity
|
||||
|
||||
@property (nonatomic, retain) id contentObject;
|
||||
@property(nonatomic, retain) id contentObject;
|
||||
|
||||
@end
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
#import "MPElementStoredEntity.h"
|
||||
|
||||
|
||||
@implementation MPElementStoredEntity
|
||||
|
||||
@dynamic contentObject;
|
||||
|
@ -21,17 +21,17 @@
|
||||
|
||||
@end
|
||||
|
||||
@interface MPElementEntity (MP)
|
||||
@interface MPElementEntity(MP)
|
||||
|
||||
@property (assign) MPElementType type;
|
||||
@property (readonly) NSString *typeName;
|
||||
@property (readonly) NSString *typeShortName;
|
||||
@property (readonly) NSString *typeClassName;
|
||||
@property (readonly) Class typeClass;
|
||||
@property (assign) NSUInteger uses;
|
||||
@property (assign) NSUInteger version;
|
||||
@property (assign) BOOL requiresExplicitMigration;
|
||||
@property (readonly) id<MPAlgorithm> algorithm;
|
||||
@property(assign) MPElementType type;
|
||||
@property(readonly) NSString *typeName;
|
||||
@property(readonly) NSString *typeShortName;
|
||||
@property(readonly) NSString *typeClassName;
|
||||
@property(readonly) Class typeClass;
|
||||
@property(assign) NSUInteger uses;
|
||||
@property(assign) NSUInteger version;
|
||||
@property(assign) BOOL requiresExplicitMigration;
|
||||
@property(readonly) id<MPAlgorithm> algorithm;
|
||||
|
||||
- (id)contentUsingKey:(MPKey *)key;
|
||||
- (void)setContent:(id)content usingKey:(MPKey *)key;
|
||||
@ -44,18 +44,18 @@
|
||||
|
||||
@end
|
||||
|
||||
@interface MPElementGeneratedEntity (MP)
|
||||
@interface MPElementGeneratedEntity(MP)
|
||||
|
||||
@property (assign) NSUInteger counter;
|
||||
@property(assign) NSUInteger counter;
|
||||
|
||||
@end
|
||||
|
||||
@interface MPUserEntity (MP)
|
||||
@interface MPUserEntity(MP)
|
||||
|
||||
@property (assign) NSUInteger avatar;
|
||||
@property (assign) BOOL saveKey;
|
||||
@property (assign) MPElementType defaultType;
|
||||
@property (readonly) NSString *userID;
|
||||
@property(assign) NSUInteger avatar;
|
||||
@property(assign) BOOL saveKey;
|
||||
@property(assign) MPElementType defaultType;
|
||||
@property(readonly) NSString *userID;
|
||||
|
||||
+ (NSString *)idFor:(NSString *)userName;
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#import "MPEntities.h"
|
||||
#import "MPAppDelegate.h"
|
||||
|
||||
@implementation NSManagedObjectContext (MP)
|
||||
@implementation NSManagedObjectContext(MP)
|
||||
|
||||
- (BOOL)saveToStore {
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPElementEntity (MP)
|
||||
@implementation MPElementEntity(MP)
|
||||
|
||||
- (MPElementType)type {
|
||||
|
||||
@ -101,7 +101,7 @@
|
||||
|
||||
- (id<MPAlgorithm>)algorithm {
|
||||
|
||||
return MPAlgorithmForVersion(self.version);
|
||||
return MPAlgorithmForVersion( self.version );
|
||||
}
|
||||
|
||||
- (NSUInteger)use {
|
||||
@ -146,29 +146,27 @@
|
||||
}
|
||||
|
||||
- (void)importProtectedContent:(NSString *)protectedContent protectedByKey:(MPKey *)contentProtectionKey usingKey:(MPKey *)key {
|
||||
|
||||
}
|
||||
|
||||
- (void)importClearTextContent:(NSString *)clearContent usingKey:(MPKey *)key {
|
||||
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
|
||||
return PearlString(@"%@:%@", [self class], [self name]);
|
||||
return PearlString( @"%@:%@", [self class], [self name] );
|
||||
}
|
||||
|
||||
- (NSString *)debugDescription {
|
||||
|
||||
return PearlString(@"{%@: name=%@, user=%@, type=%d, uses=%ld, lastUsed=%@, version=%ld, loginName=%@, requiresExplicitMigration=%d}",
|
||||
NSStringFromClass([self class]), self.name, self.user.name, self.type, (long)self.uses, self.lastUsed, (long)self.version,
|
||||
self.loginName, self.requiresExplicitMigration);
|
||||
return PearlString( @"{%@: name=%@, user=%@, type=%d, uses=%ld, lastUsed=%@, version=%ld, loginName=%@, requiresExplicitMigration=%d}",
|
||||
NSStringFromClass( [self class] ), self.name, self.user.name, self.type, (long)self.uses, self.lastUsed, (long)self.version,
|
||||
self.loginName, self.requiresExplicitMigration );
|
||||
}
|
||||
|
||||
- (BOOL)migrateExplicitly:(BOOL)explicit {
|
||||
|
||||
while (self.version < MPAlgorithmDefaultVersion)
|
||||
if ([MPAlgorithmForVersion(self.version + 1) migrateElement:self explicit:explicit])
|
||||
if ([MPAlgorithmForVersion( self.version + 1 ) migrateElement:self explicit:explicit])
|
||||
inf(@"%@ migration to version: %ld succeeded for element: %@", explicit? @"Explicit": @"Automatic", (long)self.version + 1, self);
|
||||
else {
|
||||
wrn(@"%@ migration to version: %ld failed for element: %@", explicit? @"Explicit": @"Automatic", (long)self.version + 1, self);
|
||||
@ -180,7 +178,7 @@
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPElementGeneratedEntity (MP)
|
||||
@implementation MPElementGeneratedEntity(MP)
|
||||
|
||||
- (NSUInteger)counter {
|
||||
|
||||
@ -204,16 +202,17 @@
|
||||
return [self.algorithm generateContentForElement:self usingKey:key];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPElementStoredEntity (MP)
|
||||
@implementation MPElementStoredEntity(MP)
|
||||
|
||||
+ (NSDictionary *)queryForDevicePrivateElementNamed:(NSString *)name {
|
||||
|
||||
return [PearlKeyChain createQueryForClass:kSecClassGenericPassword
|
||||
attributes:@{(__bridge id)kSecAttrService: @"DevicePrivate",
|
||||
(__bridge id)kSecAttrAccount: name}
|
||||
attributes:@{
|
||||
(__bridge id)kSecAttrService : @"DevicePrivate",
|
||||
(__bridge id)kSecAttrAccount : name
|
||||
}
|
||||
matches:nil];
|
||||
}
|
||||
|
||||
@ -263,7 +262,8 @@
|
||||
#endif
|
||||
nil]];
|
||||
self.contentObject = nil;
|
||||
} else
|
||||
}
|
||||
else
|
||||
self.contentObject = encryptedContent;
|
||||
}
|
||||
|
||||
@ -293,7 +293,7 @@
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPUserEntity (MP)
|
||||
@implementation MPUserEntity(MP)
|
||||
|
||||
- (NSUInteger)avatar {
|
||||
|
||||
|
@ -19,12 +19,11 @@
|
||||
|
||||
@protocol MPAlgorithm;
|
||||
|
||||
|
||||
@interface MPKey : NSObject
|
||||
|
||||
@property (nonatomic, readonly, strong) id<MPAlgorithm> algorithm;
|
||||
@property (nonatomic, readonly, strong) NSData *keyData;
|
||||
@property (nonatomic, readonly, strong) NSData *keyID;
|
||||
@property(nonatomic, readonly, strong) id<MPAlgorithm> algorithm;
|
||||
@property(nonatomic, readonly, strong) NSData *keyData;
|
||||
@property(nonatomic, readonly, strong) NSData *keyID;
|
||||
|
||||
- (id)initWithKeyData:(NSData *)keyData algorithm:(id<MPAlgorithm>)algorithm;
|
||||
- (MPKey *)subKeyOfLength:(NSUInteger)subKeyLength;
|
||||
|
@ -17,16 +17,16 @@
|
||||
|
||||
#import "MPAlgorithm.h"
|
||||
|
||||
@interface MPKey()
|
||||
|
||||
@interface MPKey ()
|
||||
|
||||
@property (nonatomic, readwrite, strong) id<MPAlgorithm> algorithm;
|
||||
@property (nonatomic, readwrite, strong) NSData *keyData;
|
||||
@property (nonatomic, readwrite, strong) NSData *keyID;
|
||||
@property(nonatomic, readwrite, strong) id<MPAlgorithm> algorithm;
|
||||
@property(nonatomic, readwrite, strong) NSData *keyData;
|
||||
@property(nonatomic, readwrite, strong) NSData *keyID;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPKey
|
||||
|
||||
@synthesize algorithm = _algorithm, keyData = _keyData, keyID = _keyID;
|
||||
|
||||
- (id)initWithKeyData:(NSData *)keyData algorithm:(id<MPAlgorithm>)algorithm {
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
- (MPKey *)subKeyOfLength:(NSUInteger)subKeyLength {
|
||||
|
||||
NSData *subKeyData = [self.keyData subdataWithRange:NSMakeRange(0, MIN(subKeyLength, self.keyData.length))];
|
||||
NSData *subKeyData = [self.keyData subdataWithRange:NSMakeRange( 0, MIN(subKeyLength, self.keyData.length) )];
|
||||
|
||||
return [self.algorithm keyFromKeyData:subKeyData];
|
||||
}
|
||||
@ -61,5 +61,4 @@
|
||||
return [self isEqualToKey:object];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
@ -13,16 +13,16 @@
|
||||
|
||||
@interface MPUserEntity : NSManagedObject
|
||||
|
||||
@property (nonatomic, retain) NSNumber * avatar_;
|
||||
@property (nonatomic, retain) NSNumber * defaultType_;
|
||||
@property (nonatomic, retain) NSData * keyID;
|
||||
@property (nonatomic, retain) NSDate * lastUsed;
|
||||
@property (nonatomic, retain) NSString * name;
|
||||
@property (nonatomic, retain) NSNumber * saveKey_;
|
||||
@property (nonatomic, retain) NSSet *elements;
|
||||
@property(nonatomic, retain) NSNumber *avatar_;
|
||||
@property(nonatomic, retain) NSNumber *defaultType_;
|
||||
@property(nonatomic, retain) NSData *keyID;
|
||||
@property(nonatomic, retain) NSDate *lastUsed;
|
||||
@property(nonatomic, retain) NSString *name;
|
||||
@property(nonatomic, retain) NSNumber *saveKey_;
|
||||
@property(nonatomic, retain) NSSet *elements;
|
||||
@end
|
||||
|
||||
@interface MPUserEntity (CoreDataGeneratedAccessors)
|
||||
@interface MPUserEntity(CoreDataGeneratedAccessors)
|
||||
|
||||
- (void)addElementsObject:(MPElementEntity *)value;
|
||||
- (void)removeElementsObject:(MPElementEntity *)value;
|
||||
|
@ -7,8 +7,6 @@
|
||||
//
|
||||
|
||||
#import "MPUserEntity.h"
|
||||
#import "MPElementEntity.h"
|
||||
|
||||
|
||||
@implementation MPUserEntity
|
||||
|
||||
|
@ -12,16 +12,16 @@
|
||||
|
||||
@interface MPAppDelegate : MPAppDelegate_Shared<NSApplicationDelegate>
|
||||
|
||||
@property (nonatomic, strong) NSStatusItem *statusItem;
|
||||
@property (nonatomic, strong) MPPasswordWindowController *passwordWindow;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *lockItem;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *showItem;
|
||||
@property (nonatomic, strong) IBOutlet NSMenu *statusMenu;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *useICloudItem;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *rememberPasswordItem;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *savePasswordItem;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *createUserItem;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *usersItem;
|
||||
@property(nonatomic, strong) NSStatusItem *statusItem;
|
||||
@property(nonatomic, strong) MPPasswordWindowController *passwordWindow;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *lockItem;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *showItem;
|
||||
@property(nonatomic, strong) IBOutlet NSMenu *statusMenu;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *useICloudItem;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *rememberPasswordItem;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *savePasswordItem;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *createUserItem;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *usersItem;
|
||||
|
||||
- (IBAction)activate:(id)sender;
|
||||
- (IBAction)togglePreference:(NSMenuItem *)sender;
|
||||
|
@ -11,8 +11,8 @@
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import <Carbon/Carbon.h>
|
||||
|
||||
|
||||
@implementation MPAppDelegate
|
||||
|
||||
@synthesize statusItem;
|
||||
@synthesize lockItem;
|
||||
@synthesize showItem;
|
||||
@ -26,28 +26,28 @@
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wfour-char-constants"
|
||||
static EventHotKeyID MPShowHotKey = {.signature = 'show', .id = 1};
|
||||
static EventHotKeyID MPLockHotKey = {.signature = 'lock', .id = 1};
|
||||
static EventHotKeyID MPShowHotKey = { .signature = 'show', .id = 1 };
|
||||
static EventHotKeyID MPLockHotKey = { .signature = 'lock', .id = 1 };
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
+ (void)initialize {
|
||||
|
||||
static dispatch_once_t initialize;
|
||||
dispatch_once(&initialize, ^{
|
||||
dispatch_once( &initialize, ^{
|
||||
[MPMacConfig get];
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
[PearlLogger get].printLevel = PearlLogLevelDebug;//Trace;
|
||||
#endif
|
||||
});
|
||||
#endif
|
||||
} );
|
||||
}
|
||||
|
||||
static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData) {
|
||||
|
||||
// Extract the hotkey ID.
|
||||
EventHotKeyID hotKeyID;
|
||||
GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID,
|
||||
NULL, sizeof(hotKeyID), NULL, &hotKeyID);
|
||||
GetEventParameter( theEvent, kEventParamDirectObject, typeEventHotKeyID,
|
||||
NULL, sizeof(hotKeyID), NULL, &hotKeyID );
|
||||
|
||||
// Check which hotkey this was.
|
||||
if (hotKeyID.signature == MPShowHotKey.signature && hotKeyID.id == MPShowHotKey.id) {
|
||||
@ -84,8 +84,8 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
self.createUserItem.toolTip = nil;
|
||||
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPUserEntity class])];
|
||||
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO]];
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
|
||||
fetchRequest.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO] ];
|
||||
NSArray *users = [moc executeFetchRequest:fetchRequest error:&error];
|
||||
if (!users)
|
||||
err(@"Failed to load users: %@", error);
|
||||
@ -163,8 +163,8 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)oldValue {
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification
|
||||
object:NSStringFromSelector(configKey) userInfo:nil];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:MPCheckConfigNotification object:NSStringFromSelector( configKey ) userInfo:nil];
|
||||
}
|
||||
|
||||
#pragma mark - NSApplicationDelegate
|
||||
@ -204,8 +204,8 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UbiquityManagedStoreDidImportChangesNotification object:nil queue:nil
|
||||
usingBlock:
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:UbiquityManagedStoreDidImportChangesNotification object:nil queue:nil usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
@ -218,16 +218,16 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
// Global hotkey.
|
||||
EventHotKeyRef hotKeyRef;
|
||||
EventTypeSpec hotKeyEvents[1] = {{.eventClass = kEventClassKeyboard, .eventKind = kEventHotKeyPressed}};
|
||||
OSStatus status = InstallApplicationEventHandler(NewEventHandlerUPP(MPHotKeyHander), GetEventTypeCount(hotKeyEvents),
|
||||
EventTypeSpec hotKeyEvents[1] = { { .eventClass = kEventClassKeyboard, .eventKind = kEventHotKeyPressed } };
|
||||
OSStatus status = InstallApplicationEventHandler(NewEventHandlerUPP( MPHotKeyHander ), GetEventTypeCount( hotKeyEvents ),
|
||||
hotKeyEvents,
|
||||
(__bridge void *)self, NULL);
|
||||
if (status != noErr)
|
||||
err(@"Error installing application event handler: %d", status);
|
||||
status = RegisterEventHotKey(35 /* p */, controlKey + cmdKey, MPShowHotKey, GetApplicationEventTarget(), 0, &hotKeyRef);
|
||||
status = RegisterEventHotKey( 35 /* p */, controlKey + cmdKey, MPShowHotKey, GetApplicationEventTarget(), 0, &hotKeyRef );
|
||||
if (status != noErr)
|
||||
err(@"Error registering 'show' hotkey: %d", status);
|
||||
status = RegisterEventHotKey(35 /* p */, controlKey + optionKey + cmdKey, MPLockHotKey, GetApplicationEventTarget(), 0, &hotKeyRef);
|
||||
status = RegisterEventHotKey( 35 /* p */, controlKey + optionKey + cmdKey, MPLockHotKey, GetApplicationEventTarget(), 0, &hotKeyRef );
|
||||
if (status != noErr)
|
||||
err(@"Error registering 'lock' hotkey: %d", status);
|
||||
}
|
||||
@ -237,10 +237,12 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
if (!(self.showItem.enabled = ![self.passwordWindow.window isVisible])) {
|
||||
self.showItem.title = @"Show (Showing)";
|
||||
self.showItem.toolTip = @"Master Password is already showing.";
|
||||
} else if (!(self.showItem.enabled = (self.activeUser != nil))) {
|
||||
}
|
||||
else if (!(self.showItem.enabled = (self.activeUser != nil))) {
|
||||
self.showItem.title = @"Show (No user)";
|
||||
self.showItem.toolTip = @"First select the user to show passwords for.";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
self.showItem.title = @"Show";
|
||||
self.showItem.toolTip = nil;
|
||||
}
|
||||
@ -249,7 +251,8 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
self.lockItem.title = @"Lock";
|
||||
self.lockItem.enabled = YES;
|
||||
self.lockItem.toolTip = nil;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
self.lockItem.title = @"Lock (Locked)";
|
||||
self.lockItem.enabled = NO;
|
||||
self.lockItem.toolTip = @"Master Password is currently locked.";
|
||||
@ -262,11 +265,13 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
self.savePasswordItem.title = @"Save Password (No user)";
|
||||
self.savePasswordItem.enabled = NO;
|
||||
self.savePasswordItem.toolTip = @"First select your user and unlock by showing the Master Password window.";
|
||||
} else if (!self.key) {
|
||||
}
|
||||
else if (!self.key) {
|
||||
self.savePasswordItem.title = @"Save Password (Locked)";
|
||||
self.savePasswordItem.enabled = NO;
|
||||
self.savePasswordItem.toolTip = @"First unlock by showing the Master Password window.";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
self.savePasswordItem.title = @"Save Password";
|
||||
self.savePasswordItem.enabled = YES;
|
||||
self.savePasswordItem.toolTip = nil;
|
||||
|
@ -10,6 +10,6 @@
|
||||
|
||||
@interface MPMacConfig : MPConfig
|
||||
|
||||
@property (nonatomic, retain) NSString *usedUserName;
|
||||
@property(nonatomic, retain) NSString *usedUserName;
|
||||
|
||||
@end
|
||||
|
@ -15,7 +15,7 @@
|
||||
if (!(self = [super init]))
|
||||
return self;
|
||||
|
||||
[self.defaults registerDefaults:@{NSStringFromSelector(@selector(iTunesID)): @"510296984"}];
|
||||
[self.defaults registerDefaults:@{ NSStringFromSelector( @selector(iTunesID) ) : @"510296984" }];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -13,14 +13,14 @@
|
||||
NSString *_content;
|
||||
}
|
||||
|
||||
@property (nonatomic, strong) NSString *content;
|
||||
@property(nonatomic, strong) NSString *content;
|
||||
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *siteField;
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *contentField;
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *tipField;
|
||||
@property (nonatomic, weak) IBOutlet NSView *contentContainer;
|
||||
@property (nonatomic, weak) IBOutlet NSProgressIndicator *progressView;
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *userLabel;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *siteField;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *contentField;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *tipField;
|
||||
@property(nonatomic, weak) IBOutlet NSView *contentContainer;
|
||||
@property(nonatomic, weak) IBOutlet NSProgressIndicator *progressView;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *userLabel;
|
||||
|
||||
- (void)unlock;
|
||||
|
||||
|
@ -14,12 +14,11 @@
|
||||
#define MPAlertUnlockMP @"MPAlertUnlockMP"
|
||||
#define MPAlertIncorrectMP @"MPAlertIncorrectMP"
|
||||
|
||||
@interface MPPasswordWindowController()
|
||||
|
||||
@interface MPPasswordWindowController ()
|
||||
|
||||
@property (nonatomic, strong) NSArray /* MPElementEntity */ *siteResults;
|
||||
@property (nonatomic) BOOL inProgress;
|
||||
@property (nonatomic) BOOL siteFieldPreventCompletion;
|
||||
@property(nonatomic, strong) NSArray /* MPElementEntity */ *siteResults;
|
||||
@property(nonatomic) BOOL inProgress;
|
||||
@property(nonatomic) BOOL siteFieldPreventCompletion;
|
||||
|
||||
@end
|
||||
|
||||
@ -31,7 +30,7 @@
|
||||
[self.tipField setStringValue:@""];
|
||||
|
||||
[[MPAppDelegate get] addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
[self.userLabel setStringValue:PearlString(@"%@'s password for:", [MPAppDelegate get].activeUser.name)];
|
||||
[self.userLabel setStringValue:PearlString( @"%@'s password for:", [MPAppDelegate get].activeUser.name )];
|
||||
} forKeyPath:@"activeUser" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
[[MPAppDelegate get] addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
if (![MPAppDelegate get].key) {
|
||||
@ -49,18 +48,18 @@
|
||||
[moc saveToStore];
|
||||
}];
|
||||
} forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification object:self.window queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:NSWindowDidBecomeKeyNotification object:self.window queue:nil usingBlock:^(NSNotification *note) {
|
||||
if (!self.inProgress)
|
||||
[self unlock];
|
||||
[self.siteField selectText:self];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:self.window queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:NSWindowWillCloseNotification object:self.window queue:nil usingBlock:^(NSNotification *note) {
|
||||
[[NSApplication sharedApplication] hide:self];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedOutNotification object:nil queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:MPSignedOutNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
|
||||
[self.window close];
|
||||
}];
|
||||
|
||||
@ -81,7 +80,7 @@
|
||||
|
||||
if (![MPAppDelegate get].key)
|
||||
// Ask the user to set the key through his master password.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
if ([MPAppDelegate get].key)
|
||||
return;
|
||||
|
||||
@ -91,14 +90,15 @@
|
||||
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"Master Password is locked."
|
||||
defaultButton:@"Unlock" alternateButton:@"Change" otherButton:@"Cancel"
|
||||
informativeTextWithFormat:@"The master password is required to unlock the application for:\n\n%@", [MPAppDelegate get].activeUser.name];
|
||||
NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 22)];
|
||||
informativeTextWithFormat:@"The master password is required to unlock the application for:\n\n%@",
|
||||
[MPAppDelegate get].activeUser.name];
|
||||
NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||
[alert setAccessoryView:passwordField];
|
||||
[alert layout];
|
||||
[passwordField becomeFirstResponder];
|
||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertUnlockMP];
|
||||
});
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
||||
@ -136,25 +136,25 @@
|
||||
self.contentContainer.alphaValue = 0;
|
||||
[self.progressView startAnimation:nil];
|
||||
self.inProgress = YES;
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0 ), ^{
|
||||
BOOL success = [[MPAppDelegate get] signInAsUser:[MPAppDelegate get].activeUser
|
||||
usingMasterPassword:[(NSSecureTextField *)alert.accessoryView stringValue]];
|
||||
self.inProgress = NO;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[self.progressView stopAnimation:nil];
|
||||
|
||||
if (success)
|
||||
self.contentContainer.alphaValue = 1;
|
||||
else {
|
||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey : PearlString(@"Incorrect master password for user %@",
|
||||
[MPAppDelegate get].activeUser.name)
|
||||
NSLocalizedDescriptionKey : PearlString( @"Incorrect master password for user %@",
|
||||
[MPAppDelegate get].activeUser.name )
|
||||
}]] beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertIncorrectMP];
|
||||
}
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
default:
|
||||
@ -172,7 +172,7 @@
|
||||
if (![query length] || ![MPAppDelegate get].key)
|
||||
return nil;
|
||||
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
||||
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses_" ascending:NO]];
|
||||
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(name BEGINSWITH[cd] %@) AND user == %@",
|
||||
query, [MPAppDelegate get].activeUser];
|
||||
@ -184,7 +184,7 @@
|
||||
|
||||
if ([self.siteResults count] == 1) {
|
||||
[textView setString:[(MPElementEntity *)[self.siteResults objectAtIndex:0] name]];
|
||||
[textView setSelectedRange:NSMakeRange([query length], [[textView string] length] - [query length])];
|
||||
[textView setSelectedRange:NSMakeRange( [query length], [[textView string] length] - [query length] )];
|
||||
if ([self trySite])
|
||||
return nil;
|
||||
}
|
||||
@ -204,7 +204,7 @@
|
||||
[self.window close];
|
||||
return YES;
|
||||
}
|
||||
if ((self.siteFieldPreventCompletion = [NSStringFromSelector(commandSelector) hasPrefix:@"delete"]))
|
||||
if ((self.siteFieldPreventCompletion = [NSStringFromSelector( commandSelector ) hasPrefix:@"delete"]))
|
||||
return NO;
|
||||
if (commandSelector == @selector(insertNewline:) && [self.content length]) {
|
||||
if ([self trySite])
|
||||
@ -223,17 +223,17 @@
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
self.tipField.alphaValue = 1;
|
||||
[self.tipField setStringValue:@"Copied! Hit ⎋ (ESC) to close window."];
|
||||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC));
|
||||
dispatch_after(popTime, dispatch_get_main_queue(), ^{
|
||||
dispatch_time_t popTime = dispatch_time( DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC) );
|
||||
dispatch_after( popTime, dispatch_get_main_queue(), ^{
|
||||
[NSAnimationContext beginGrouping];
|
||||
[[NSAnimationContext currentContext] setDuration:0.2f];
|
||||
[self.tipField.animator setAlphaValue:0];
|
||||
[NSAnimationContext endGrouping];
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
|
||||
[[self findElement] use];
|
||||
}
|
||||
@ -298,17 +298,17 @@
|
||||
return NO;
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{
|
||||
NSString *description = [result.content description];
|
||||
if (!description)
|
||||
description = @"";
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[self setContent:description];
|
||||
[self.tipField setStringValue:@"Hit ⌤ (ENTER) to copy the password."];
|
||||
self.tipField.alphaValue = 1;
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
|
||||
// For when the app should be able to create new sites.
|
||||
/*
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
@ -34,5 +34,5 @@
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#import "Pearl-Prefix.pch"
|
||||
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
@ -6,9 +6,7 @@
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
return NSApplicationMain(argc, (const char **)argv);
|
||||
return NSApplicationMain( argc, (const char **)argv );
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="1171" systemVersion="11E53" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
|
||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0"
|
||||
lastSavedToolsVersion="1171" systemVersion="11E53" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
|
||||
<entity name="MPElementEntity" representedClassName="MPElementEntity" isAbstract="YES" syncable="YES">
|
||||
<attribute name="content" optional="YES" transient="YES" attributeType="Transformable" syncable="YES"/>
|
||||
<attribute name="lastUsed" attributeType="Date" syncable="YES"/>
|
||||
<attribute name="name" attributeType="String" minValueString="1" indexed="YES" syncable="YES"/>
|
||||
<attribute name="type_" attributeType="Integer 16" defaultValueString="17" syncable="YES"/>
|
||||
<attribute name="uses_" attributeType="Integer 16" defaultValueString="0" syncable="YES"/>
|
||||
<relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements" inverseEntity="MPUserEntity" syncable="YES"/>
|
||||
<relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements"
|
||||
inverseEntity="MPUserEntity" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="MPElementGeneratedEntity" representedClassName="MPElementGeneratedEntity" parentEntity="MPElementEntity" syncable="YES">
|
||||
<attribute name="counter_" optional="YES" attributeType="Integer 32" defaultValueString="1" syncable="YES"/>
|
||||
@ -21,7 +23,8 @@
|
||||
<attribute name="lastUsed" optional="YES" attributeType="Date" syncable="YES"/>
|
||||
<attribute name="name" attributeType="String" syncable="YES"/>
|
||||
<attribute name="saveKey_" attributeType="Boolean" defaultValueString="NO"/>
|
||||
<relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity" inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
|
||||
<relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity"
|
||||
inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="MPElementEntity" positionX="160" positionY="192" width="128" height="135"/>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="2057" systemVersion="12C60" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
|
||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0"
|
||||
lastSavedToolsVersion="2057" systemVersion="12C60" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
|
||||
<entity name="MPElementEntity" representedClassName="MPElementEntity" isAbstract="YES" syncable="YES">
|
||||
<attribute name="content" optional="YES" transient="YES" attributeType="Transformable" syncable="YES"/>
|
||||
<attribute name="lastUsed" attributeType="Date" indexed="YES" syncable="YES"/>
|
||||
@ -11,7 +12,8 @@
|
||||
<attribute name="userName" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="uses_" attributeType="Integer 16" defaultValueString="0" indexed="YES" syncable="YES"/>
|
||||
<attribute name="version_" attributeType="Integer 16" minValueString="0" defaultValueString="0" syncable="YES"/>
|
||||
<relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements" inverseEntity="MPUserEntity" syncable="YES"/>
|
||||
<relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements"
|
||||
inverseEntity="MPUserEntity" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="MPElementGeneratedEntity" representedClassName="MPElementGeneratedEntity" parentEntity="MPElementEntity" syncable="YES">
|
||||
<attribute name="counter_" optional="YES" attributeType="Integer 32" defaultValueString="1" syncable="YES"/>
|
||||
@ -29,7 +31,8 @@
|
||||
<attribute name="saveKey_" attributeType="Boolean" defaultValueString="NO">
|
||||
<userInfo/>
|
||||
</attribute>
|
||||
<relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity" inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
|
||||
<relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity"
|
||||
inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="MPElementEntity" positionX="0" positionY="0" width="128" height="180"/>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="1810" systemVersion="12B19" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
|
||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0"
|
||||
lastSavedToolsVersion="1810" systemVersion="12B19" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
|
||||
<entity name="MPElementEntity" representedClassName="MPElementEntity" isAbstract="YES" syncable="YES">
|
||||
<attribute name="content" optional="YES" transient="YES" attributeType="Transformable" syncable="YES"/>
|
||||
<attribute name="lastUsed" attributeType="Date" indexed="YES" syncable="YES"/>
|
||||
@ -11,7 +12,8 @@
|
||||
<attribute name="type_" attributeType="Integer 16" defaultValueString="17" syncable="YES"/>
|
||||
<attribute name="uses_" attributeType="Integer 16" defaultValueString="0" indexed="YES" syncable="YES"/>
|
||||
<attribute name="version_" attributeType="Integer 16" minValueString="0" defaultValueString="0" syncable="YES"/>
|
||||
<relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements" inverseEntity="MPUserEntity" syncable="YES"/>
|
||||
<relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements"
|
||||
inverseEntity="MPUserEntity" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="MPElementGeneratedEntity" representedClassName="MPElementGeneratedEntity" parentEntity="MPElementEntity" syncable="YES">
|
||||
<attribute name="counter_" optional="YES" attributeType="Integer 32" defaultValueString="1" syncable="YES"/>
|
||||
@ -29,7 +31,8 @@
|
||||
<attribute name="saveKey_" attributeType="Boolean" defaultValueString="NO">
|
||||
<userInfo/>
|
||||
</attribute>
|
||||
<relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity" inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
|
||||
<relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity"
|
||||
inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="MPElementEntity" positionX="-0" positionY="-286" width="128" height="178"/>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="2057" systemVersion="12C60" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
|
||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0"
|
||||
lastSavedToolsVersion="2057" systemVersion="12C60" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
|
||||
<entity name="MPElementEntity" representedClassName="MPElementEntity" isAbstract="YES" syncable="YES">
|
||||
<attribute name="content" optional="YES" transient="YES" attributeType="Transformable" syncable="YES"/>
|
||||
<attribute name="lastUsed" attributeType="Date" indexed="YES" syncable="YES"/>
|
||||
@ -11,7 +12,8 @@
|
||||
<attribute name="type_" attributeType="Integer 16" defaultValueString="17" syncable="YES"/>
|
||||
<attribute name="uses_" attributeType="Integer 16" defaultValueString="0" indexed="YES" syncable="YES"/>
|
||||
<attribute name="version_" attributeType="Integer 16" minValueString="0" defaultValueString="0" syncable="YES"/>
|
||||
<relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements" inverseEntity="MPUserEntity" syncable="YES"/>
|
||||
<relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements"
|
||||
inverseEntity="MPUserEntity" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="MPElementGeneratedEntity" representedClassName="MPElementGeneratedEntity" parentEntity="MPElementEntity" syncable="YES">
|
||||
<attribute name="counter_" optional="YES" attributeType="Integer 32" defaultValueString="1" syncable="YES"/>
|
||||
@ -28,7 +30,8 @@
|
||||
<attribute name="saveKey_" attributeType="Boolean" defaultValueString="NO">
|
||||
<userInfo/>
|
||||
</attribute>
|
||||
<relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity" inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
|
||||
<relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity"
|
||||
inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="MPElementEntity" positionX="-0" positionY="-286" width="128" height="178"/>
|
||||
|
@ -3,7 +3,7 @@
|
||||
//
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#endif
|
||||
|
||||
#define PEARL_WITH_SCRYPT
|
||||
|
@ -14,13 +14,13 @@
|
||||
|
||||
@interface MPAppDelegate : MPAppDelegate_Shared
|
||||
|
||||
@property (nonatomic, readonly) GPPShare *googlePlus;
|
||||
@property(nonatomic, readonly) GPPShare *googlePlus;
|
||||
|
||||
- (void)showGuide;
|
||||
- (void)showSetup;
|
||||
- (void)showFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController;
|
||||
|
||||
- (void)export;
|
||||
- (void)changeMasterPasswordFor:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc didResetBlock:(void(^)(void))didReset;
|
||||
- (void)changeMasterPasswordFor:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset;
|
||||
|
||||
@end
|
||||
|
@ -12,13 +12,12 @@
|
||||
|
||||
#import "IASKSettingsReader.h"
|
||||
|
||||
@interface MPAppDelegate ()
|
||||
@interface MPAppDelegate()
|
||||
|
||||
@property (nonatomic, readwrite) GPPShare *googlePlus;
|
||||
@property(nonatomic, readwrite) GPPShare *googlePlus;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation MPAppDelegate
|
||||
|
||||
+ (void)initialize {
|
||||
@ -59,12 +58,12 @@
|
||||
level = PearlLogLevelInfo;
|
||||
|
||||
if (message.level >= level)
|
||||
TFLog(@"%@", [message messageDescription]);
|
||||
TFLog( @"%@", [message messageDescription] );
|
||||
|
||||
return YES;
|
||||
}];
|
||||
TFLog(@"TestFlight (%@) initialized for: %@ v%@.", //
|
||||
TESTFLIGHT_SDK_VERSION, [PearlInfoPlist get].CFBundleName, [PearlInfoPlist get].CFBundleVersion);
|
||||
TFLog( @"TestFlight (%@) initialized for: %@ v%@.", //
|
||||
TESTFLIGHT_SDK_VERSION, [PearlInfoPlist get].CFBundleName, [PearlInfoPlist get].CFBundleVersion );
|
||||
}
|
||||
}
|
||||
@catch (id exception) {
|
||||
@ -99,12 +98,12 @@
|
||||
level = PearlLogLevelInfo;
|
||||
|
||||
if (message.level >= level)
|
||||
CLSLog(@"%@", [message messageDescription]);
|
||||
CLSLog( @"%@", [message messageDescription] );
|
||||
|
||||
return YES;
|
||||
}];
|
||||
CLSLog(@"Crashlytics (%@) initialized for: %@ v%@.", //
|
||||
[Crashlytics sharedInstance].version, [PearlInfoPlist get].CFBundleName, [PearlInfoPlist get].CFBundleVersion);
|
||||
CLSLog( @"Crashlytics (%@) initialized for: %@ v%@.", //
|
||||
[Crashlytics sharedInstance].version, [PearlInfoPlist get].CFBundleName, [PearlInfoPlist get].CFBundleVersion );
|
||||
}
|
||||
}
|
||||
@catch (id exception) {
|
||||
@ -133,34 +132,34 @@
|
||||
err(@"Localytics exception: %@", exception);
|
||||
}
|
||||
|
||||
UIImage *navBarImage = [[UIImage imageNamed:@"ui_navbar_container"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
|
||||
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];
|
||||
[[UINavigationBar appearance] setTitleTextAttributes:
|
||||
@{
|
||||
UITextAttributeTextColor: [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f],
|
||||
UITextAttributeTextShadowColor: [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.8f],
|
||||
UITextAttributeTextShadowOffset: [NSValue valueWithUIOffset:UIOffsetMake(0, -1)],
|
||||
UITextAttributeFont: [UIFont fontWithName:@"Exo-Bold" size:20.0f]
|
||||
UITextAttributeTextColor : [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f],
|
||||
UITextAttributeTextShadowColor : [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.8f],
|
||||
UITextAttributeTextShadowOffset : [NSValue valueWithUIOffset:UIOffsetMake( 0, -1 )],
|
||||
UITextAttributeFont : [UIFont fontWithName:@"Exo-Bold" size:20.0f]
|
||||
}];
|
||||
|
||||
UIImage *navBarButton = [[UIImage imageNamed:@"ui_navbar_button"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
|
||||
UIImage *navBarBack = [[UIImage imageNamed:@"ui_navbar_back"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 13, 0, 5)];
|
||||
UIImage *navBarButton = [[UIImage imageNamed:@"ui_navbar_button"] resizableImageWithCapInsets:UIEdgeInsetsMake( 0, 5, 0, 5 )];
|
||||
UIImage *navBarBack = [[UIImage imageNamed:@"ui_navbar_back"] resizableImageWithCapInsets:UIEdgeInsetsMake( 0, 13, 0, 5 )];
|
||||
[[UIBarButtonItem appearance] setBackgroundImage:navBarButton forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
|
||||
[[UIBarButtonItem appearance] setBackgroundImage:nil forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone];
|
||||
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:navBarBack forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
|
||||
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:nil forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone];
|
||||
[[UIBarButtonItem appearance] setTitleTextAttributes:
|
||||
@{
|
||||
UITextAttributeTextColor: [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f],
|
||||
UITextAttributeTextShadowColor: [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f],
|
||||
UITextAttributeTextShadowOffset: [NSValue valueWithUIOffset:UIOffsetMake(0, 1)]//,
|
||||
UITextAttributeTextColor : [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f],
|
||||
UITextAttributeTextShadowColor : [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f],
|
||||
UITextAttributeTextShadowOffset : [NSValue valueWithUIOffset:UIOffsetMake( 0, 1 )]//,
|
||||
// Causes a bug in iOS where image views get oddly stretched... or something.
|
||||
//UITextAttributeFont: [UIFont fontWithName:@"HelveticaNeue" size:13.0f]
|
||||
}
|
||||
forState:UIControlStateNormal];
|
||||
|
||||
UIImage *toolBarImage = [[UIImage imageNamed:@"ui_toolbar_container"] resizableImageWithCapInsets:UIEdgeInsetsMake(25, 5, 5, 5)];
|
||||
UIImage *toolBarImage = [[UIImage imageNamed:@"ui_toolbar_container"] resizableImageWithCapInsets:UIEdgeInsetsMake( 25, 5, 5, 5 )];
|
||||
[[UISearchBar appearance] setBackgroundImage:toolBarImage];
|
||||
[[UIToolbar appearance] setBackgroundImage:toolBarImage forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
|
||||
|
||||
@ -202,43 +201,47 @@
|
||||
[[Crashlytics sharedInstance] setBoolValue:[[PearlConfig get].firstRun boolValue] forKey:@"firstRun"];
|
||||
[[Crashlytics sharedInstance] setIntValue:[[PearlConfig get].launchCount intValue] forKey:@"launchCount"];
|
||||
[[Crashlytics sharedInstance] setBoolValue:[[PearlConfig get].askForReviews boolValue] forKey:@"askForReviews"];
|
||||
[[Crashlytics sharedInstance] setIntValue:[[PearlConfig get].reviewAfterLaunches intValue] forKey:@"reviewAfterLaunches"];
|
||||
[[Crashlytics sharedInstance]
|
||||
setIntValue:[[PearlConfig get].reviewAfterLaunches intValue] forKey:@"reviewAfterLaunches"];
|
||||
[[Crashlytics sharedInstance] setObjectValue:[PearlConfig get].reviewedVersion forKey:@"reviewedVersion"];
|
||||
|
||||
#ifdef TESTFLIGHT_SDK_VERSION
|
||||
[TestFlight addCustomEnvironmentInformation:[[MPConfig get].rememberLogin boolValue]? @"YES": @"NO" forKey:@"rememberLogin"];
|
||||
[TestFlight addCustomEnvironmentInformation:[self storeManager].cloudEnabled? @"YES": @"NO" forKey:@"iCloud"];
|
||||
[TestFlight addCustomEnvironmentInformation:[[MPConfig get].iCloudDecided boolValue]? @"YES": @"NO" forKey:@"iCloudDecided"];
|
||||
[TestFlight addCustomEnvironmentInformation:[[MPiOSConfig get].sendInfo boolValue]? @"YES": @"NO" forKey:@"sendInfo"];
|
||||
[TestFlight addCustomEnvironmentInformation:[[MPiOSConfig get].helpHidden boolValue]? @"YES": @"NO" forKey:@"helpHidden"];
|
||||
[TestFlight addCustomEnvironmentInformation:[[MPiOSConfig get].showSetup boolValue]? @"YES": @"NO"
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[MPConfig get].rememberLogin boolValue]) description]
|
||||
forKey:@"rememberLogin"];
|
||||
[TestFlight addCustomEnvironmentInformation:[@([self storeManager].cloudEnabled) description] forKey:@"iCloud"];
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[MPConfig get].iCloudDecided boolValue]) description]
|
||||
forKey:@"iCloudDecided"];
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[MPiOSConfig get].sendInfo boolValue]) description] forKey:@"sendInfo"];
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[MPiOSConfig get].helpHidden boolValue]) description]
|
||||
forKey:@"helpHidden"];
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[MPiOSConfig get].showSetup boolValue]) description]
|
||||
forKey:@"showQuickStart"];
|
||||
[TestFlight addCustomEnvironmentInformation:[[PearlConfig get].firstRun boolValue]? @"YES": @"NO" forKey:@"firstRun"];
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[PearlConfig get].firstRun boolValue]) description] forKey:@"firstRun"];
|
||||
[TestFlight addCustomEnvironmentInformation:[[PearlConfig get].launchCount description] forKey:@"launchCount"];
|
||||
[TestFlight addCustomEnvironmentInformation:[[PearlConfig get].askForReviews boolValue]? @"YES": @"NO"
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[PearlConfig get].askForReviews boolValue]) description]
|
||||
forKey:@"askForReviews"];
|
||||
[TestFlight addCustomEnvironmentInformation:[[PearlConfig get].reviewAfterLaunches description] forKey:@"reviewAfterLaunches"];
|
||||
[TestFlight addCustomEnvironmentInformation:[[PearlConfig get].reviewAfterLaunches description]
|
||||
forKey:@"reviewAfterLaunches"];
|
||||
[TestFlight addCustomEnvironmentInformation:[PearlConfig get].reviewedVersion forKey:@"reviewedVersion"];
|
||||
#endif
|
||||
MPCheckpoint( MPCheckpointConfig, @{
|
||||
@"rememberLogin" : [[MPConfig get].rememberLogin boolValue]? @"YES": @"NO",
|
||||
@"iCloud" : [self storeManager].cloudEnabled? @"YES": @"NO",
|
||||
@"iCloudDecided" : [[MPConfig get].iCloudDecided boolValue]? @"YES": @"NO",
|
||||
@"sendInfo" : [[MPiOSConfig get].sendInfo boolValue]? @"YES": @"NO",
|
||||
@"helpHidden" : [[MPiOSConfig get].helpHidden boolValue]? @"YES": @"NO",
|
||||
@"showQuickStart" : [[MPiOSConfig get].showSetup boolValue]? @"YES": @"NO",
|
||||
@"firstRun" : [[PearlConfig get].firstRun boolValue]? @"YES": @"NO",
|
||||
@"rememberLogin" : @([[MPConfig get].rememberLogin boolValue]),
|
||||
@"iCloud" : @([self storeManager].cloudEnabled),
|
||||
@"iCloudDecided" : @([[MPConfig get].iCloudDecided boolValue]),
|
||||
@"sendInfo" : @([[MPiOSConfig get].sendInfo boolValue]),
|
||||
@"helpHidden" : @([[MPiOSConfig get].helpHidden boolValue]),
|
||||
@"showQuickStart" : @([[MPiOSConfig get].showSetup boolValue]),
|
||||
@"firstRun" : @([[PearlConfig get].firstRun boolValue]),
|
||||
@"launchCount" : NilToNSNull([[PearlConfig get].launchCount description]),
|
||||
@"askForReviews" : [[PearlConfig get].askForReviews boolValue]? @"YES": @"NO",
|
||||
@"askForReviews" : @([[PearlConfig get].askForReviews boolValue]),
|
||||
@"reviewAfterLaunches" : NilToNSNull([[PearlConfig get].reviewAfterLaunches description]),
|
||||
@"reviewedVersion" : NilToNSNull([PearlConfig get].reviewedVersion)
|
||||
} );
|
||||
}
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:kIASKAppSettingChanged object:nil queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification
|
||||
object:note userInfo:nil];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:kIASKAppSettingChanged object:nil queue:nil usingBlock:^(NSNotification *note) {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification object:note userInfo:nil];
|
||||
}];
|
||||
|
||||
#ifdef ADHOC
|
||||
@ -257,10 +260,10 @@
|
||||
|
||||
inf(@"Started up with device identifier: %@", [PearlKeyChain deviceIdentifier]);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
if ([[MPiOSConfig get].showSetup boolValue])
|
||||
[[MPAppDelegate get] showSetup];
|
||||
});
|
||||
} );
|
||||
|
||||
return YES;
|
||||
}
|
||||
@ -277,7 +280,7 @@
|
||||
return YES;
|
||||
|
||||
// Arbitrary URL to mpsites data.
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
|
||||
NSError *error;
|
||||
NSURLResponse *response;
|
||||
NSData *importedSitesData = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url]
|
||||
@ -294,11 +297,11 @@
|
||||
__block NSString *masterPassword = nil;
|
||||
|
||||
dispatch_group_t importPasswordGroup = dispatch_group_create();
|
||||
dispatch_group_enter(importPasswordGroup);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_group_enter( importPasswordGroup );
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[PearlAlert showAlertWithTitle:@"Import File's Master Password"
|
||||
message:PearlString(@"%@'s export was done using a different master password.\n"
|
||||
@"Enter that master password to unlock the exported data.", userName)
|
||||
message:PearlString( @"%@'s export was done using a different master password.\n"
|
||||
@"Enter that master password to unlock the exported data.", userName )
|
||||
viewStyle:UIAlertViewStyleSecureTextInput
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
@try {
|
||||
@ -308,23 +311,23 @@
|
||||
masterPassword = [alert_ textFieldAtIndex:0].text;
|
||||
}
|
||||
@finally {
|
||||
dispatch_group_leave(importPasswordGroup);
|
||||
dispatch_group_leave( importPasswordGroup );
|
||||
}
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Unlock Import", nil];
|
||||
});
|
||||
dispatch_group_wait(importPasswordGroup, DISPATCH_TIME_FOREVER);
|
||||
} );
|
||||
dispatch_group_wait( importPasswordGroup, DISPATCH_TIME_FOREVER );
|
||||
|
||||
return masterPassword;
|
||||
} askUserPassword:^NSString *(NSString *userName, NSUInteger importCount, NSUInteger deleteCount) {
|
||||
__block NSString *masterPassword = nil;
|
||||
|
||||
dispatch_group_t userPasswordGroup = dispatch_group_create();
|
||||
dispatch_group_enter(userPasswordGroup);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[PearlAlert showAlertWithTitle:PearlString(@"Master Password for\n%@", userName)
|
||||
message:PearlString(@"Imports %d sites, overwriting %d.", importCount,
|
||||
deleteCount)
|
||||
dispatch_group_enter( userPasswordGroup );
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[PearlAlert showAlertWithTitle:PearlString( @"Master Password for\n%@", userName )
|
||||
message:PearlString( @"Imports %d sites, overwriting %d.", importCount,
|
||||
deleteCount )
|
||||
viewStyle:UIAlertViewStyleSecureTextInput
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
@try {
|
||||
@ -334,12 +337,12 @@
|
||||
masterPassword = [alert_ textFieldAtIndex:0].text;
|
||||
}
|
||||
@finally {
|
||||
dispatch_group_leave(userPasswordGroup);
|
||||
dispatch_group_leave( userPasswordGroup );
|
||||
}
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Import", nil];
|
||||
});
|
||||
dispatch_group_wait(userPasswordGroup, DISPATCH_TIME_FOREVER);
|
||||
} );
|
||||
dispatch_group_wait( userPasswordGroup, DISPATCH_TIME_FOREVER );
|
||||
|
||||
return masterPassword;
|
||||
}];
|
||||
@ -360,7 +363,7 @@
|
||||
}
|
||||
|
||||
[activityAlert cancelAlertAnimated:YES];
|
||||
});
|
||||
} );
|
||||
|
||||
return YES;
|
||||
}
|
||||
@ -411,8 +414,7 @@
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||
|
||||
inf(@"Re-activated");
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification
|
||||
object:application userInfo:nil];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification object:application userInfo:nil];
|
||||
|
||||
[[LocalyticsSession sharedLocalyticsSession] resume];
|
||||
[[LocalyticsSession sharedLocalyticsSession] upload];
|
||||
@ -460,8 +462,7 @@
|
||||
initAlert:nil tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay
|
||||
otherTitles:nil];
|
||||
|
||||
else
|
||||
if (logs)
|
||||
else if (logs)
|
||||
[PearlAlert showAlertWithTitle:@"Feedback"
|
||||
message:
|
||||
@"Have a question, comment, issue or just saying thanks?\n\n"
|
||||
@ -481,22 +482,24 @@
|
||||
PearlLogLevel logLevel = [[MPiOSConfig get].sendInfo boolValue]? PearlLogLevelDebug: PearlLogLevelInfo;
|
||||
|
||||
[[[PearlEMail alloc] initForEMailTo:@"Master Password Development <masterpassword@lyndir.com>"
|
||||
subject:PearlString(@"Feedback for Master Password [%@]",
|
||||
[[PearlKeyChain deviceIdentifier] stringByDeletingMatchesOf:@"-.*"])
|
||||
body:PearlString(@"\n\n\n"
|
||||
subject:PearlString( @"Feedback for Master Password [%@]",
|
||||
[[PearlKeyChain deviceIdentifier] stringByDeletingMatchesOf:@"-.*"] )
|
||||
body:PearlString( @"\n\n\n"
|
||||
@"--\n"
|
||||
@"%@"
|
||||
@"Master Password %@, build %@",
|
||||
userName? ([userName stringByAppendingString:@"\n"]): @"",
|
||||
[PearlInfoPlist get].CFBundleShortVersionString,
|
||||
[PearlInfoPlist get].CFBundleVersion)
|
||||
[PearlInfoPlist get].CFBundleVersion )
|
||||
|
||||
attachments:(logs
|
||||
? [[PearlEMailAttachment alloc] initWithContent:[[[PearlLogger get] formatMessagesWithLevel:logLevel] dataUsingEncoding:NSUTF8StringEncoding]
|
||||
? [[PearlEMailAttachment alloc]
|
||||
initWithContent:[[[PearlLogger get] formatMessagesWithLevel:logLevel]
|
||||
dataUsingEncoding:NSUTF8StringEncoding]
|
||||
mimeType:@"text/plain"
|
||||
fileName:PearlString(@"%@-%@.log",
|
||||
fileName:PearlString( @"%@-%@.log",
|
||||
[[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]],
|
||||
[PearlKeyChain deviceIdentifier])]
|
||||
[PearlKeyChain deviceIdentifier] )]
|
||||
: nil), nil]
|
||||
showComposerForVC:viewController];
|
||||
}
|
||||
@ -543,22 +546,22 @@
|
||||
NSString *message;
|
||||
|
||||
if (showPasswords)
|
||||
message = PearlString(@"Export of Master Password sites with passwords included.\n\n"
|
||||
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"
|
||||
@"%@\n"
|
||||
@"Master Password %@, build %@",
|
||||
[self activeUserForThread].name,
|
||||
[PearlInfoPlist get].CFBundleShortVersionString,
|
||||
[PearlInfoPlist get].CFBundleVersion);
|
||||
[PearlInfoPlist get].CFBundleVersion );
|
||||
else
|
||||
message = PearlString(@"Backup of Master Password sites.\n\n\n"
|
||||
message = PearlString( @"Backup of Master Password sites.\n\n\n"
|
||||
@"--\n"
|
||||
@"%@\n"
|
||||
@"Master Password %@, build %@",
|
||||
[self activeUserForThread].name,
|
||||
[PearlInfoPlist get].CFBundleShortVersionString,
|
||||
[PearlInfoPlist get].CFBundleVersion);
|
||||
[PearlInfoPlist get].CFBundleVersion );
|
||||
|
||||
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
|
||||
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"];
|
||||
@ -566,7 +569,8 @@
|
||||
[PearlEMail sendEMailTo:nil subject:@"Master Password Export" body:message
|
||||
attachments:[[PearlEMailAttachment alloc] initWithContent:[exportedSites dataUsingEncoding:NSUTF8StringEncoding]
|
||||
mimeType:@"text/plain" fileName:
|
||||
PearlString(@"%@ (%@).mpsites", [self activeUserForThread].name, [exportDateFormatter stringFromDate:[NSDate date]])],
|
||||
PearlString( @"%@ (%@).mpsites", [self activeUserForThread].name,
|
||||
[exportDateFormatter stringFromDate:[NSDate date]] )],
|
||||
nil];
|
||||
}
|
||||
|
||||
@ -603,8 +607,8 @@
|
||||
|
||||
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)value {
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification
|
||||
object:NSStringFromSelector(configKey) userInfo:nil];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:MPCheckConfigNotification object:NSStringFromSelector( configKey ) userInfo:nil];
|
||||
}
|
||||
|
||||
#pragma mark - UbiquityStoreManagerDelegate
|
||||
@ -621,8 +625,7 @@
|
||||
[PearlAlert showAlertWithTitle:@"iCloud" message:
|
||||
@"iCloud is now disabled.\n\n"
|
||||
@"It is highly recommended you enable iCloud."
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert firstOtherButtonIndex] + 0) {
|
||||
[PearlAlert showAlertWithTitle:@"About iCloud" message:
|
||||
@"iCloud is Apple's solution for saving your data in \"the cloud\" "
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
@interface MPAppViewController : UIViewController
|
||||
|
||||
- (IBAction)gorillas:(UIButton *)sender;
|
||||
|
@ -17,12 +17,9 @@
|
||||
|
||||
#import "MPAppViewController.h"
|
||||
|
||||
|
||||
@implementation MPAppViewController {
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (IBAction)gorillas:(UIButton *)sender {
|
||||
|
||||
MPCheckpoint( MPCheckpointApp, @{
|
||||
@ -35,7 +32,7 @@
|
||||
- (IBAction)deblock:(UIButton *)sender {
|
||||
|
||||
MPCheckpoint( MPCheckpointApp, @{
|
||||
@"app": @"deblock"
|
||||
@"app" : @"deblock"
|
||||
} );
|
||||
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://itunes.apple.com/app/lyndir/deblock/id325058485?mt=8"]];
|
||||
|
@ -17,10 +17,9 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface MPAppsViewController : UIViewController<UIPageViewControllerDataSource, UIPageViewControllerDelegate>
|
||||
|
||||
@interface MPAppsViewController : UIViewController <UIPageViewControllerDataSource, UIPageViewControllerDelegate>
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *pagePositionView;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView *pagePositionView;
|
||||
|
||||
- (IBAction)exit;
|
||||
|
||||
|
@ -17,30 +17,27 @@
|
||||
|
||||
#import "MPAppsViewController.h"
|
||||
|
||||
@interface MPAppsViewController()
|
||||
|
||||
@interface MPAppsViewController ()
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray *pageVCs;
|
||||
@property (nonatomic, strong) UIPageViewController *pageViewController;
|
||||
|
||||
@property(nonatomic, strong) NSMutableArray *pageVCs;
|
||||
@property(nonatomic, strong) UIPageViewController *pageViewController;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPAppsViewController {
|
||||
|
||||
}
|
||||
|
||||
@synthesize pagePositionView = _pagePositionView;
|
||||
@synthesize pageVCs = _pageVCs;
|
||||
@synthesize pageViewController = _pageViewController;
|
||||
|
||||
|
||||
- (void)viewDidLoad {
|
||||
|
||||
self.pageVCs = [NSMutableArray array];
|
||||
UIViewController *vc;
|
||||
@try {
|
||||
for (NSUInteger p = 0;
|
||||
(vc = [self.storyboard instantiateViewControllerWithIdentifier:PearlString(@"MPAppViewController_%u", p)]);
|
||||
(vc = [self.storyboard instantiateViewControllerWithIdentifier:PearlString( @"MPAppViewController_%u", p )]);
|
||||
++p)
|
||||
[self.pageVCs addObject:vc];
|
||||
}
|
||||
@ -101,7 +98,6 @@
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
|
||||
viewControllerBeforeViewController:(UIViewController *)viewController {
|
||||
|
||||
|
@ -20,7 +20,8 @@
|
||||
#import "MPElementListController.h"
|
||||
|
||||
@interface MPElementListAllViewController : MPElementListController
|
||||
@property (weak, nonatomic) IBOutlet UINavigationBar *navigationBar;
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UINavigationBar *navigationBar;
|
||||
|
||||
- (IBAction)close:(id)sender;
|
||||
- (IBAction)add:(id)sender;
|
||||
|
@ -83,7 +83,7 @@
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
||||
}
|
||||
|
||||
- (void)performUpgradeAllWithCompletion:(void(^)(BOOL success, NSDictionary *changes))completion {
|
||||
- (void)performUpgradeAllWithCompletion:(void (^)(BOOL success, NSDictionary *changes))completion {
|
||||
|
||||
[MPAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
||||
@ -93,7 +93,7 @@
|
||||
NSArray *elements = [moc executeFetchRequest:fetchRequest error:&error];
|
||||
if (!elements) {
|
||||
err(@"Failed to fetch outdated sites for upgrade: %@", error);
|
||||
completion(NO, nil);
|
||||
completion( NO, nil );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@
|
||||
}
|
||||
|
||||
[moc saveToStore];
|
||||
completion(YES, elementChanges);
|
||||
completion( YES, elementChanges );
|
||||
}];
|
||||
}
|
||||
|
||||
@ -131,9 +131,8 @@
|
||||
[PearlAlert showAlertWithTitle:@"Sites Upgraded"
|
||||
message:PearlString( @"This upgrade has caused %d passwords to change.\n"
|
||||
@"To make updating the actual passwords of these accounts easier, "
|
||||
@"you can email a summary of these changes to yourself.", [changes count])
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
@"you can email a summary of these changes to yourself.", [changes count] )
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
|
@ -5,14 +5,14 @@
|
||||
#define MPElementListFilterNone @"MPElementListFilterNone"
|
||||
#define MPElementListFilterOutdated @"MPElementListFilterOutdated"
|
||||
|
||||
@interface MPElementListController : UITableViewController <NSFetchedResultsControllerDelegate>
|
||||
@interface MPElementListController : UITableViewController<NSFetchedResultsControllerDelegate>
|
||||
|
||||
@property (weak, nonatomic) IBOutlet id<MPElementListDelegate> delegate;
|
||||
@property (strong, nonatomic) NSString *filter;
|
||||
@property(weak, nonatomic) IBOutlet id<MPElementListDelegate> delegate;
|
||||
@property(strong, nonatomic) NSString *filter;
|
||||
|
||||
@property (readonly) NSFetchedResultsController *fetchedResultsControllerByUses;
|
||||
@property (readonly) NSFetchedResultsController *fetchedResultsControllerByLastUsed;
|
||||
@property (readonly) NSDateFormatter *dateFormatter;
|
||||
@property(readonly) NSFetchedResultsController *fetchedResultsControllerByUses;
|
||||
@property(readonly) NSFetchedResultsController *fetchedResultsControllerByLastUsed;
|
||||
@property(readonly) NSDateFormatter *dateFormatter;
|
||||
|
||||
- (void)updateData;
|
||||
- (void)addElementNamed:(NSString *)siteName completion:(void (^)(BOOL success))completion;
|
||||
|
@ -3,7 +3,7 @@
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPAppDelegate.h"
|
||||
|
||||
@interface MPElementListController ()
|
||||
@interface MPElementListController()
|
||||
@end
|
||||
|
||||
@implementation MPElementListController {
|
||||
@ -13,11 +13,11 @@
|
||||
NSDateFormatter *_dateFormatter;
|
||||
}
|
||||
|
||||
- (void)addElementNamed:(NSString *)siteName completion:(void(^)(BOOL success))completion {
|
||||
- (void)addElementNamed:(NSString *)siteName completion:(void (^)(BOOL success))completion {
|
||||
|
||||
if (![siteName length]) {
|
||||
if (completion)
|
||||
completion(false);
|
||||
completion( false );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -41,13 +41,13 @@
|
||||
[moc saveToStore];
|
||||
|
||||
NSManagedObjectID *elementOID = [element objectID];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
MPElementEntity *element_ = (MPElementEntity *) [[MPAppDelegate managedObjectContextForThreadIfReady]
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
MPElementEntity *element_ = (MPElementEntity *)[[MPAppDelegate managedObjectContextForThreadIfReady]
|
||||
objectRegisteredForID:elementOID];
|
||||
[self.delegate didSelectElement:element_];
|
||||
if (completion)
|
||||
completion(true);
|
||||
});
|
||||
completion( true );
|
||||
} );
|
||||
}];
|
||||
}
|
||||
|
||||
@ -59,8 +59,8 @@
|
||||
if (!moc)
|
||||
return nil;
|
||||
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
|
||||
fetchRequest.sortDescriptors = @[[[NSSortDescriptor alloc] initWithKey:NSStringFromSelector( @selector(lastUsed) ) ascending:NO]];
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
||||
fetchRequest.sortDescriptors = @[ [[NSSortDescriptor alloc] initWithKey:NSStringFromSelector( @selector(lastUsed) ) ascending:NO] ];
|
||||
[self configureFetchRequest:fetchRequest];
|
||||
_fetchedResultsControllerByLastUsed = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:moc
|
||||
sectionNameKeyPath:nil cacheName:nil];
|
||||
@ -119,13 +119,13 @@
|
||||
return;
|
||||
|
||||
predicate = [NSCompoundPredicate andPredicateWithSubpredicates:
|
||||
@[predicate, [NSPredicate predicateWithFormat:@"name BEGINSWITH[cd] %@", query]]];
|
||||
@[ predicate, [NSPredicate predicateWithFormat:@"name BEGINSWITH[cd] %@", query] ]];
|
||||
}
|
||||
|
||||
// Add filter predicate.
|
||||
if ([self.filter isEqualToString:MPElementListFilterOutdated])
|
||||
predicate = [NSCompoundPredicate andPredicateWithSubpredicates:
|
||||
@[[NSPredicate predicateWithFormat:@"requiresExplicitMigration_ == YES"], predicate]];
|
||||
@[ [NSPredicate predicateWithFormat:@"requiresExplicitMigration_ == YES"], predicate ]];
|
||||
|
||||
// Fetch
|
||||
NSError *error;
|
||||
@ -140,13 +140,12 @@
|
||||
}
|
||||
|
||||
- (void)customTableViewUpdates {
|
||||
|
||||
}
|
||||
|
||||
// See MP-14, also crashes easily on internal assertions etc..
|
||||
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
|
||||
|
||||
dbg(@"%@", NSStringFromSelector(_cmd));
|
||||
dbg(@"%@", NSStringFromSelector( _cmd ));
|
||||
[self.tableView beginUpdates];
|
||||
}
|
||||
|
||||
@ -156,25 +155,25 @@
|
||||
switch (type) {
|
||||
|
||||
case NSFetchedResultsChangeInsert:
|
||||
dbg(@"%@ -- NSFetchedResultsChangeInsert:%@", NSStringFromSelector(_cmd), anObject);
|
||||
dbg(@"%@ -- NSFetchedResultsChangeInsert:%@", NSStringFromSelector( _cmd ), anObject);
|
||||
[self.tableView insertRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:newIndexPath] ]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
break;
|
||||
|
||||
case NSFetchedResultsChangeDelete:
|
||||
dbg(@"%@ -- NSFetchedResultsChangeDelete:%@", NSStringFromSelector(_cmd), anObject);
|
||||
dbg(@"%@ -- NSFetchedResultsChangeDelete:%@", NSStringFromSelector( _cmd ), anObject);
|
||||
[self.tableView deleteRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:indexPath] ]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
break;
|
||||
|
||||
case NSFetchedResultsChangeUpdate:
|
||||
dbg(@"%@ -- NSFetchedResultsChangeUpdate:%@", NSStringFromSelector(_cmd), anObject);
|
||||
dbg(@"%@ -- NSFetchedResultsChangeUpdate:%@", NSStringFromSelector( _cmd ), anObject);
|
||||
[self.tableView reloadRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:indexPath] ]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
break;
|
||||
|
||||
case NSFetchedResultsChangeMove:
|
||||
dbg(@"%@ -- NSFetchedResultsChangeMove:%@", NSStringFromSelector(_cmd), anObject);
|
||||
dbg(@"%@ -- NSFetchedResultsChangeMove:%@", NSStringFromSelector( _cmd ), anObject);
|
||||
[self.tableView deleteRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:indexPath] ]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
[self.tableView insertRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:newIndexPath] ]
|
||||
@ -185,7 +184,7 @@
|
||||
|
||||
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
|
||||
|
||||
dbg(@"%@ on %@", NSStringFromSelector(_cmd), [NSThread currentThread].name);
|
||||
dbg(@"%@ on %@", NSStringFromSelector( _cmd ), [NSThread currentThread].name);
|
||||
[self customTableViewUpdates];
|
||||
[self.tableView endUpdates];
|
||||
}
|
||||
@ -210,7 +209,7 @@
|
||||
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MPElementListCell"];
|
||||
if (!cell)
|
||||
cell = (UITableViewCell *) [[UIViewController alloc] initWithNibName:@"MPElementListCellView" bundle:nil].view;
|
||||
cell = (UITableViewCell *)[[UIViewController alloc] initWithNibName:@"MPElementListCellView" bundle:nil].view;
|
||||
|
||||
[self configureCell:cell inTableView:tableView atTableIndexPath:indexPath];
|
||||
|
||||
@ -222,11 +221,12 @@
|
||||
MPElementEntity *element = [self elementForTableIndexPath:indexPath];
|
||||
|
||||
cell.textLabel.text = element.name;
|
||||
cell.detailTextLabel.text = PearlString(@"%d views, last on %@: %@",
|
||||
element.uses, [self.dateFormatter stringFromDate:element.lastUsed], [element.algorithm shortNameOfType:element.type]);
|
||||
cell.detailTextLabel.text = PearlString( @"%d views, last on %@: %@",
|
||||
element.uses, [self.dateFormatter stringFromDate:element.lastUsed], [element.algorithm shortNameOfType:element.type] );
|
||||
}
|
||||
|
||||
- (NSIndexPath *)tableIndexPathForFetchController:(NSFetchedResultsController *)fetchedResultsController indexPath:(NSIndexPath *)indexPath {
|
||||
- (NSIndexPath *)tableIndexPathForFetchController:(NSFetchedResultsController *)fetchedResultsController
|
||||
indexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
if (fetchedResultsController == self.fetchedResultsControllerByLastUsed)
|
||||
return [NSIndexPath indexPathForRow:indexPath.row inSection:0];
|
||||
@ -270,7 +270,7 @@
|
||||
|
||||
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
|
||||
|
||||
return @[@"recency", @"uses"];
|
||||
return @[ @"recency", @"uses" ];
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
|
||||
@ -292,7 +292,7 @@ forRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
MPCheckpoint( MPCheckpointDeleteElement, @{
|
||||
@"type" : element.typeName,
|
||||
@"version" : @(element.version)
|
||||
});
|
||||
} );
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#import "MPElementEntity.h"
|
||||
|
||||
@protocol MPElementListDelegate <NSObject>
|
||||
@protocol MPElementListDelegate<NSObject>
|
||||
|
||||
- (void)didSelectElement:(MPElementEntity *)element;
|
||||
|
||||
|
@ -11,9 +11,9 @@
|
||||
|
||||
@interface MPElementListSearchController : MPElementListController<UISearchBarDelegate, UISearchDisplayDelegate>
|
||||
|
||||
@property (strong, nonatomic) UILabel *tipView;
|
||||
@property(strong, nonatomic) UILabel *tipView;
|
||||
|
||||
@property (strong, nonatomic) IBOutlet UISearchDisplayController *searchDisplayController;
|
||||
@property (weak, nonatomic) IBOutlet UIView *searchTipContainer;
|
||||
@property(strong, nonatomic) IBOutlet UISearchDisplayController *searchDisplayController;
|
||||
@property(weak, nonatomic) IBOutlet UIView *searchTipContainer;
|
||||
|
||||
@end
|
||||
|
@ -10,13 +10,14 @@
|
||||
#import "MPMainViewController.h"
|
||||
#import "MPAppDelegate.h"
|
||||
|
||||
@interface MPElementListSearchController ()
|
||||
@interface MPElementListSearchController()
|
||||
|
||||
@property (nonatomic) BOOL newSiteSectionWasNeeded;
|
||||
@property(nonatomic) BOOL newSiteSectionWasNeeded;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPElementListSearchController
|
||||
|
||||
@synthesize searchDisplayController;
|
||||
|
||||
- (id)init {
|
||||
@ -24,12 +25,12 @@
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
self.tipView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 170)];
|
||||
self.tipView = [[UILabel alloc] initWithFrame:CGRectMake( 0, 0, 320, 170 )];
|
||||
self.tipView.textAlignment = NSTextAlignmentCenter;
|
||||
self.tipView.backgroundColor = [UIColor clearColor];
|
||||
self.tipView.textColor = [UIColor lightTextColor];
|
||||
self.tipView.shadowColor = [UIColor blackColor];
|
||||
self.tipView.shadowOffset = CGSizeMake(0, -1);
|
||||
self.tipView.shadowOffset = CGSizeMake( 0, -1 );
|
||||
self.tipView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight
|
||||
| UIViewAutoresizingFlexibleBottomMargin;
|
||||
self.tipView.numberOfLines = 0;
|
||||
@ -112,12 +113,12 @@
|
||||
|
||||
if ([subview isKindOfClass:[UIControl class]] &&
|
||||
CGPointEqualToPoint(
|
||||
CGPointDistanceBetweenCGPoints(searchBarFrame.origin, subview.frame.origin),
|
||||
CGPointMake(0, searchBarFrame.size.height))) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
CGPointDistanceBetweenCGPoints( searchBarFrame.origin, subview.frame.origin ),
|
||||
CGPointMake( 0, searchBarFrame.size.height ) )) {
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[self.tipView removeFromSuperview];
|
||||
[subview addSubview:self.tipView];
|
||||
});
|
||||
} );
|
||||
|
||||
*stop = YES;
|
||||
}
|
||||
@ -131,7 +132,7 @@
|
||||
return NO;
|
||||
|
||||
__block BOOL hasExactQueryMatch = NO;
|
||||
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsControllerByUses sections] lastObject];
|
||||
id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsControllerByUses sections] lastObject];
|
||||
[[sectionInfo objects] enumerateObjectsUsingBlock:^(id obj_, NSUInteger idx_, BOOL *stop_) {
|
||||
if ([[obj_ name] isEqualToString:query]) {
|
||||
hasExactQueryMatch = YES;
|
||||
@ -195,8 +196,8 @@
|
||||
// "New" section
|
||||
NSString *query = [self.searchDisplayController.searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
cell.textLabel.text = query;
|
||||
cell.detailTextLabel.text = PearlString(@"New site: %@",
|
||||
[MPAlgorithmDefault shortNameOfType:[[[MPAppDelegate get] activeUserForThread] defaultType]]);
|
||||
cell.detailTextLabel.text = PearlString( @"New site: %@",
|
||||
[MPAlgorithmDefault shortNameOfType:[[[MPAppDelegate get] activeUserForThread] defaultType]] );
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
@ -208,10 +209,11 @@
|
||||
}
|
||||
|
||||
// "New" section.
|
||||
NSString *siteName = [self.searchDisplayController.searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
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)
|
||||
message:PearlString( @"Do you want to create a new site named:\n%@", siteName )
|
||||
viewStyle:UIAlertViewStyleDefault
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
@ -240,5 +242,4 @@ forRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
[super tableView:tableView commitEditingStyle:editingStyle forRowAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
@ -8,24 +8,24 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface MPGuideViewController : UIViewController <UIScrollViewDelegate>
|
||||
@interface MPGuideViewController : UIViewController<UIScrollViewDelegate>
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIView *siteNameTip;
|
||||
@property (weak, nonatomic) IBOutlet UIView *contentTip;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *contentTipText;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *usernameButton;
|
||||
@property (weak, nonatomic) IBOutlet UIView *usernameTip;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *typeButton;
|
||||
@property (weak, nonatomic) IBOutlet UIView *typeTip;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *toolButton;
|
||||
@property (weak, nonatomic) IBOutlet UIView *toolTip;
|
||||
@property (weak, nonatomic) IBOutlet UIProgressView *progress;
|
||||
@property (weak, nonatomic) IBOutlet UIView *content;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *contentButton;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *contentText;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *volumeButton;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *largePlayButton;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *smallPlayButton;
|
||||
@property(weak, nonatomic) IBOutlet UIView *siteNameTip;
|
||||
@property(weak, nonatomic) IBOutlet UIView *contentTip;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *contentTipText;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *usernameButton;
|
||||
@property(weak, nonatomic) IBOutlet UIView *usernameTip;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *typeButton;
|
||||
@property(weak, nonatomic) IBOutlet UIView *typeTip;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *toolButton;
|
||||
@property(weak, nonatomic) IBOutlet UIView *toolTip;
|
||||
@property(weak, nonatomic) IBOutlet UIProgressView *progress;
|
||||
@property(weak, nonatomic) IBOutlet UIView *content;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *contentButton;
|
||||
@property(weak, nonatomic) IBOutlet UITextField *contentText;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *volumeButton;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *largePlayButton;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *smallPlayButton;
|
||||
|
||||
- (IBAction)play;
|
||||
- (IBAction)close;
|
||||
|
@ -12,46 +12,45 @@
|
||||
|
||||
@interface MPMainViewController : UIViewController<MPTypeDelegate, UITextFieldDelegate, MPElementListDelegate, UIWebViewDelegate, UIGestureRecognizerDelegate>
|
||||
|
||||
@property (assign, nonatomic) BOOL siteInfoHidden;
|
||||
@property (strong, nonatomic) IBOutlet MPElementListSearchController *searchDelegate;
|
||||
@property (strong, nonatomic) IBOutlet UIPanGestureRecognizer *pullDownGesture;
|
||||
@property (strong, nonatomic) IBOutlet UIPanGestureRecognizer *pullUpGesture;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *contentField;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *typeButton;
|
||||
@property (weak, nonatomic) IBOutlet UIWebView *helpView;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *siteName;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *passwordCounter;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *passwordIncrementer;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *passwordEdit;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *passwordUpgrade;
|
||||
@property (weak, nonatomic) IBOutlet UIView *contentContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIView *displayContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIView *helpContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIView *contentTipContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIView *loginNameTipContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIView *alertContainer;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *alertTitle;
|
||||
@property (weak, nonatomic) IBOutlet UITextView *alertBody;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *contentTipBody;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *loginNameTipBody;
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *toolTipEditIcon;
|
||||
@property (weak, nonatomic) IBOutlet UIView *searchTipContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIView *actionsTipContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIView *typeTipContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIView *toolTipContainer;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *toolTipBody;
|
||||
@property (weak, nonatomic) IBOutlet UIView *loginNameContainer;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *loginNameField;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *passwordUser;
|
||||
@property (weak, nonatomic) IBOutlet UIView *outdatedAlertContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *outdatedAlertBack;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *outdatedAlertCloseButton;
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *pullUpView;
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *pullDownView;
|
||||
@property(assign, nonatomic) BOOL siteInfoHidden;
|
||||
@property(strong, nonatomic) IBOutlet MPElementListSearchController *searchDelegate;
|
||||
@property(strong, nonatomic) IBOutlet UIPanGestureRecognizer *pullDownGesture;
|
||||
@property(strong, nonatomic) IBOutlet UIPanGestureRecognizer *pullUpGesture;
|
||||
@property(weak, nonatomic) IBOutlet UITextField *contentField;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *typeButton;
|
||||
@property(weak, nonatomic) IBOutlet UIWebView *helpView;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *siteName;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *passwordCounter;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *passwordIncrementer;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *passwordEdit;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *passwordUpgrade;
|
||||
@property(weak, nonatomic) IBOutlet UIView *contentContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *displayContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *helpContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *contentTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *loginNameTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *alertContainer;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *alertTitle;
|
||||
@property(weak, nonatomic) IBOutlet UITextView *alertBody;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *contentTipBody;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *loginNameTipBody;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView *toolTipEditIcon;
|
||||
@property(weak, nonatomic) IBOutlet UIView *searchTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *actionsTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *typeTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIView *toolTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *toolTipBody;
|
||||
@property(weak, nonatomic) IBOutlet UIView *loginNameContainer;
|
||||
@property(weak, nonatomic) IBOutlet UITextField *loginNameField;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *passwordUser;
|
||||
@property(weak, nonatomic) IBOutlet UIView *outdatedAlertContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView *outdatedAlertBack;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *outdatedAlertCloseButton;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView *pullUpView;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView *pullDownView;
|
||||
|
||||
|
||||
@property (copy, nonatomic) void (^contentTipCleanup)(BOOL finished);
|
||||
@property (copy, nonatomic) void (^toolTipCleanup)(BOOL finished);
|
||||
@property(copy, nonatomic) void (^contentTipCleanup)(BOOL finished);
|
||||
@property(copy, nonatomic) void (^toolTipCleanup)(BOOL finished);
|
||||
|
||||
- (IBAction)copyContent;
|
||||
- (IBAction)incrementPasswordCounter;
|
||||
|
@ -11,9 +11,9 @@
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPElementListAllViewController.h"
|
||||
|
||||
|
||||
@interface MPMainViewController()
|
||||
@property (nonatomic)BOOL suppressOutdatedAlert;
|
||||
|
||||
@property(nonatomic) BOOL suppressOutdatedAlert;
|
||||
@end
|
||||
|
||||
@implementation MPMainViewController {
|
||||
@ -43,7 +43,6 @@
|
||||
[self updateUserHiddenAnimated:NO];
|
||||
}
|
||||
|
||||
|
||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
||||
|
||||
if ([[segue identifier] isEqualToString:@"MP_ChooseType"])
|
||||
@ -78,8 +77,8 @@
|
||||
self.alertBody.text = nil;
|
||||
self.toolTipEditIcon.hidden = YES;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:self queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:UIApplicationDidEnterBackgroundNotification object:self queue:nil usingBlock:^(NSNotification *note) {
|
||||
self.suppressOutdatedAlert = NO;
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPElementUpdatedNotification object:nil queue:nil usingBlock:
|
||||
@ -142,7 +141,7 @@
|
||||
|
||||
// Needed for when we appear after a modal VC dismisses:
|
||||
// We can't present until the other modal VC has been fully dismissed and presenting in -viewWillAppear: will fail.
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{
|
||||
MPUserEntity *activeUser = [[MPAppDelegate get] activeUserForThread];
|
||||
if ([MPAlgorithmDefault migrateUser:activeUser] && !self.suppressOutdatedAlert)
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
@ -150,7 +149,7 @@
|
||||
self.suppressOutdatedAlert = YES;
|
||||
}];
|
||||
[activeUser.managedObjectContext saveToStore];
|
||||
});
|
||||
} );
|
||||
|
||||
if (![[MPiOSConfig get].actionsTipShown boolValue])
|
||||
[UIView animateWithDuration:animated? 0.3f: 0 animations:^{
|
||||
@ -161,7 +160,7 @@
|
||||
|
||||
[MPiOSConfig get].actionsTipShown = @YES;
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC) ), dispatch_get_main_queue(), ^{
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.actionsTipContainer.alpha = 0;
|
||||
} completion:^(BOOL finished_) {
|
||||
@ -170,7 +169,7 @@
|
||||
self.searchTipContainer.alpha = 1;
|
||||
}];
|
||||
}];
|
||||
});
|
||||
} );
|
||||
}];
|
||||
|
||||
[[LocalyticsSession sharedLocalyticsSession] tagScreen:@"Main"];
|
||||
@ -216,8 +215,8 @@
|
||||
if (activeElement.type & MPElementTypeClassGenerated) {
|
||||
self.passwordCounter.alpha = 0.5f;
|
||||
self.passwordIncrementer.alpha = 0.5f;
|
||||
} else
|
||||
if (activeElement.type & MPElementTypeClassStored)
|
||||
}
|
||||
else if (activeElement.type & MPElementTypeClassStored)
|
||||
self.passwordEdit.alpha = 0.5f;
|
||||
}
|
||||
|
||||
@ -228,18 +227,18 @@
|
||||
forState:UIControlStateNormal];
|
||||
|
||||
if ([activeElement isKindOfClass:[MPElementGeneratedEntity class]])
|
||||
self.passwordCounter.text = PearlString(@"%u", ((MPElementGeneratedEntity *)activeElement).counter);
|
||||
self.passwordCounter.text = PearlString( @"%u", ((MPElementGeneratedEntity *)activeElement).counter );
|
||||
|
||||
self.contentField.enabled = NO;
|
||||
self.contentField.text = @"";
|
||||
if (activeElement.name && ![activeElement isDeleted])
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{
|
||||
NSString *description = [activeElement.content description];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
self.contentField.text = description;
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
|
||||
self.loginNameField.enabled = NO;
|
||||
self.loginNameField.text = activeElement.loginName;
|
||||
@ -271,10 +270,11 @@
|
||||
self.pullDownView.hidden = [[MPiOSConfig get].helpHidden boolValue];
|
||||
|
||||
if ([[MPiOSConfig get].helpHidden boolValue]) {
|
||||
self.contentContainer.frame = CGRectSetHeight(self.contentContainer.frame, self.view.bounds.size.height - 44 /* search bar */);
|
||||
self.helpContainer.frame = CGRectSetY(self.helpContainer.frame, self.view.bounds.size.height - 20 /* pull-up */);
|
||||
} else {
|
||||
self.contentContainer.frame = CGRectSetHeight(self.contentContainer.frame, 225);
|
||||
self.contentContainer.frame = CGRectSetHeight( self.contentContainer.frame, self.view.bounds.size.height - 44 /* search bar */);
|
||||
self.helpContainer.frame = CGRectSetY( self.helpContainer.frame, self.view.bounds.size.height - 20 /* pull-up */);
|
||||
}
|
||||
else {
|
||||
self.contentContainer.frame = CGRectSetHeight( self.contentContainer.frame, 225 );
|
||||
[self.helpContainer setFrameFromCurrentSizeAndParentPaddingTop:CGFLOAT_MAX right:0 bottom:0 left:0];
|
||||
}
|
||||
}
|
||||
@ -301,11 +301,11 @@
|
||||
}
|
||||
|
||||
if (self.siteInfoHidden) {
|
||||
self.displayContainer.frame = CGRectSetHeight(self.displayContainer.frame, 87);
|
||||
} else {
|
||||
self.displayContainer.frame = CGRectSetHeight(self.displayContainer.frame, 137);
|
||||
self.displayContainer.frame = CGRectSetHeight( self.displayContainer.frame, 87 );
|
||||
}
|
||||
else {
|
||||
self.displayContainer.frame = CGRectSetHeight( self.displayContainer.frame, 137 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)setHelpChapter:(NSString *)chapter {
|
||||
@ -314,11 +314,11 @@
|
||||
@"chapter" : chapter
|
||||
} );
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
NSURL *url = [NSURL URLWithString:[@"#" stringByAppendingString:chapter]
|
||||
relativeToURL:[[NSBundle mainBundle] URLForResource:@"help" withExtension:@"html"]];
|
||||
[self.helpView loadRequest:[NSURLRequest requestWithURL:url]];
|
||||
});
|
||||
} );
|
||||
}
|
||||
|
||||
- (IBAction)panHelpDown:(UIPanGestureRecognizer *)sender {
|
||||
@ -330,7 +330,7 @@
|
||||
targetY = 246;
|
||||
}
|
||||
|
||||
self.helpContainer.frame = CGRectSetY(self.helpContainer.frame, targetY);
|
||||
self.helpContainer.frame = CGRectSetY( self.helpContainer.frame, targetY );
|
||||
|
||||
if (sender.state == UIGestureRecognizerStateEnded)
|
||||
[self setHelpHidden:hideHelp animated:YES];
|
||||
@ -342,10 +342,10 @@
|
||||
BOOL hideHelp = NO;
|
||||
if (targetY >= self.view.bounds.size.height - 20) {
|
||||
hideHelp = YES;
|
||||
targetY = self.view.bounds.size.height - 20 ;
|
||||
targetY = self.view.bounds.size.height - 20;
|
||||
}
|
||||
|
||||
self.helpContainer.frame = CGRectSetY(self.helpContainer.frame, targetY);
|
||||
self.helpContainer.frame = CGRectSetY( self.helpContainer.frame, targetY );
|
||||
|
||||
if (sender.state == UIGestureRecognizerStateEnded)
|
||||
[self setHelpHidden:hideHelp animated:YES];
|
||||
@ -355,16 +355,16 @@
|
||||
|
||||
MPElementEntity *activeElement = [self activeElementForThread];
|
||||
NSString *error = [self.helpView stringByEvaluatingJavaScriptFromString:
|
||||
PearlString(@"setClass('%@');", activeElement.typeClassName)];
|
||||
PearlString( @"setClass('%@');", activeElement.typeClassName )];
|
||||
if (error.length)
|
||||
err(@"helpView.setClass: %@", error);
|
||||
}
|
||||
|
||||
- (void)showContentTip:(NSString *)message withIcon:(UIImageView *)icon {
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
if (self.contentTipCleanup)
|
||||
self.contentTipCleanup(NO);
|
||||
self.contentTipCleanup( NO );
|
||||
|
||||
__weak MPMainViewController *wSelf = self;
|
||||
self.contentTipBody.text = message;
|
||||
@ -378,42 +378,42 @@
|
||||
self.contentTipContainer.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished) {
|
||||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC);
|
||||
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
|
||||
dispatch_time_t popTime = dispatch_time( DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC );
|
||||
dispatch_after( popTime, dispatch_get_main_queue(), ^(void) {
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.contentTipContainer.alpha = 0;
|
||||
} completion:self.contentTipCleanup];
|
||||
});
|
||||
} );
|
||||
}
|
||||
}];
|
||||
});
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)showLoginNameTip:(NSString *)message {
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
self.loginNameTipBody.text = message;
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.loginNameTipContainer.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished) {
|
||||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC);
|
||||
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
|
||||
dispatch_time_t popTime = dispatch_time( DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC );
|
||||
dispatch_after( popTime, dispatch_get_main_queue(), ^(void) {
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.loginNameTipContainer.alpha = 0;
|
||||
}];
|
||||
});
|
||||
} );
|
||||
}
|
||||
}];
|
||||
});
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)showToolTip:(NSString *)message withIcon:(UIImageView *)icon {
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
if (self.toolTipCleanup)
|
||||
self.toolTipCleanup(NO);
|
||||
self.toolTipCleanup( NO );
|
||||
|
||||
__weak MPMainViewController *wSelf = self;
|
||||
self.toolTipBody.text = message;
|
||||
@ -427,22 +427,22 @@
|
||||
self.toolTipContainer.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished) {
|
||||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC);
|
||||
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
|
||||
dispatch_time_t popTime = dispatch_time( DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC );
|
||||
dispatch_after( popTime, dispatch_get_main_queue(), ^(void) {
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.toolTipContainer.alpha = 0;
|
||||
} completion:self.toolTipCleanup];
|
||||
});
|
||||
} );
|
||||
}
|
||||
}];
|
||||
});
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message {
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
self.alertTitle.text = title;
|
||||
NSRange scrollRange = NSMakeRange(self.alertBody.text.length, message.length);
|
||||
NSRange scrollRange = NSMakeRange( self.alertBody.text.length, message.length );
|
||||
if ([self.alertBody.text length])
|
||||
self.alertBody.text = [NSString stringWithFormat:@"%@\n\n---\n\n%@", self.alertBody.text, message];
|
||||
else
|
||||
@ -452,7 +452,7 @@
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.alertContainer.alpha = 1;
|
||||
}];
|
||||
});
|
||||
} );
|
||||
}
|
||||
|
||||
#pragma mark - Protocols
|
||||
@ -531,8 +531,8 @@
|
||||
// Not of a type that supports a password counter.
|
||||
err(@"Cannot reset password counter: Element is not generated: %@", activeElement.name);
|
||||
return;
|
||||
} else
|
||||
if (((MPElementGeneratedEntity *)activeElement).counter == 1)
|
||||
}
|
||||
else if (((MPElementGeneratedEntity *)activeElement).counter == 1)
|
||||
// Counter has initial value, no point resetting.
|
||||
return;
|
||||
|
||||
@ -540,7 +540,7 @@
|
||||
@"You are resetting the site's password counter.\n\n"
|
||||
@"If you continue, the site's password will change back to its original value. "
|
||||
@"You will then need to update your account's password back to this original value."
|
||||
do:^BOOL(MPElementEntity *activeElement_){
|
||||
do:^BOOL(MPElementEntity *activeElement_) {
|
||||
inf(@"Resetting password counter for: %@", activeElement_.name);
|
||||
((MPElementGeneratedEntity *)activeElement_).counter = 1;
|
||||
|
||||
@ -625,7 +625,6 @@
|
||||
return activeElement;
|
||||
}
|
||||
|
||||
|
||||
- (IBAction)editPassword {
|
||||
|
||||
MPElementEntity *activeElement = [self activeElementForThread];
|
||||
@ -775,10 +774,11 @@
|
||||
@"You are about to change the type of this password.\n\n"
|
||||
@"If you continue, the password for this site will change. "
|
||||
@"You will need to update your account's old password to the new one."
|
||||
do:^BOOL(MPElementEntity *activeElement){
|
||||
do:^BOOL(MPElementEntity *activeElement) {
|
||||
if ([activeElement.algorithm classOfType:type] != activeElement.typeClass) {
|
||||
// Type requires a different class of element. Recreate the element.
|
||||
MPElementEntity *newElement = [NSEntityDescription insertNewObjectForEntityForName:[activeElement.algorithm classNameOfType:type]
|
||||
MPElementEntity *newElement
|
||||
= [NSEntityDescription insertNewObjectForEntityForName:[activeElement.algorithm classNameOfType:type]
|
||||
inManagedObjectContext:activeElement.managedObjectContext];
|
||||
newElement.name = activeElement.name;
|
||||
newElement.user = activeElement.user;
|
||||
@ -793,8 +793,8 @@
|
||||
}
|
||||
activeElement.type = type;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPElementUpdatedNotification
|
||||
object:activeElement.objectID];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:MPElementUpdatedNotification object:activeElement.objectID];
|
||||
return YES;
|
||||
}];
|
||||
}
|
||||
@ -809,11 +809,11 @@
|
||||
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement) {
|
||||
if ([activeElement use] == 1)
|
||||
[self showAlertWithTitle:@"New Site" message:
|
||||
PearlString(@"You've just created a password for %@.\n\n"
|
||||
PearlString( @"You've just created a password for %@.\n\n"
|
||||
@"IMPORTANT:\n"
|
||||
@"Go to %@ and set or change the password for your account to the password above.\n"
|
||||
@"Do this right away: if you forget, you may have trouble remembering which password to use to log into the site later on.",
|
||||
activeElement.name, activeElement.name)];
|
||||
activeElement.name, activeElement.name )];
|
||||
return YES;
|
||||
}];
|
||||
|
||||
@ -828,11 +828,11 @@
|
||||
[MPiOSConfig get].typeTipShown = PearlBool(YES);
|
||||
|
||||
dispatch_after(
|
||||
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
dispatch_time( DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC) ), dispatch_get_main_queue(), ^{
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.typeTipContainer.alpha = 0;
|
||||
}];
|
||||
});
|
||||
} );
|
||||
}
|
||||
}];
|
||||
|
||||
@ -866,7 +866,8 @@
|
||||
// Not of a type whose content can be edited.
|
||||
err(@"Cannot update element content: Element is not stored: %@", activeElement.name);
|
||||
return;
|
||||
} else if ([((MPElementStoredEntity *)activeElement).content isEqual:self.contentField.text])
|
||||
}
|
||||
else if ([((MPElementStoredEntity *)activeElement).content isEqual:self.contentField.text])
|
||||
// Content hasn't changed.
|
||||
return;
|
||||
|
||||
|
@ -12,12 +12,12 @@
|
||||
|
||||
@interface MPPreferencesViewController : UITableViewController<IASKSettingsDelegate, MPTypeDelegate>
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIScrollView *avatarsView;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *avatarTemplate;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *savePasswordSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UITableViewCell *exportCell;
|
||||
@property (weak, nonatomic) IBOutlet UITableViewCell *changeMPCell;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *defaultTypeLabel;
|
||||
@property(weak, nonatomic) IBOutlet UIScrollView *avatarsView;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *avatarTemplate;
|
||||
@property(weak, nonatomic) IBOutlet UISwitch *savePasswordSwitch;
|
||||
@property(weak, nonatomic) IBOutlet UITableViewCell *exportCell;
|
||||
@property(weak, nonatomic) IBOutlet UITableViewCell *changeMPCell;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *defaultTypeLabel;
|
||||
|
||||
- (IBAction)didToggleSwitch:(UISwitch *)sender;
|
||||
- (IBAction)settings:(id)sender;
|
||||
|
@ -12,7 +12,7 @@
|
||||
#import "MPAppDelegate_Key.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
|
||||
@interface MPPreferencesViewController ()
|
||||
@interface MPPreferencesViewController()
|
||||
|
||||
@end
|
||||
|
||||
@ -28,8 +28,8 @@
|
||||
avatar.hidden = NO;
|
||||
avatar.center = CGPointMake(
|
||||
self.avatarTemplate.center.x * (a + 1) + self.avatarTemplate.bounds.size.width / 2 * a,
|
||||
self.avatarTemplate.center.y);
|
||||
[avatar setBackgroundImage:[UIImage imageNamed:PearlString(@"avatar-%d", a)]
|
||||
self.avatarTemplate.center.y );
|
||||
[avatar setBackgroundImage:[UIImage imageNamed:PearlString( @"avatar-%d", a )]
|
||||
forState:UIControlStateNormal];
|
||||
[avatar setSelectionInSuperviewCandidate:YES isClearable:NO];
|
||||
|
||||
@ -64,7 +64,8 @@
|
||||
[self.avatarsView autoSizeContent];
|
||||
[self.avatarsView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||
if (subview.tag && ((UIControl *)subview).selected) {
|
||||
[self.avatarsView setContentOffset:CGPointMake(subview.center.x - self.avatarsView.bounds.size.width / 2, 0) animated:animated];
|
||||
[self.avatarsView setContentOffset:CGPointMake( subview.center.x - self.avatarsView.bounds.size.width / 2, 0 )
|
||||
animated:animated];
|
||||
}
|
||||
} recurse:NO];
|
||||
|
||||
@ -112,8 +113,7 @@
|
||||
if (cell == self.exportCell)
|
||||
[[MPAppDelegate get] export];
|
||||
|
||||
else
|
||||
if (cell == self.changeMPCell) {
|
||||
else if (cell == self.changeMPCell) {
|
||||
MPUserEntity *activeUser = [[MPAppDelegate get] activeUserForThread];
|
||||
[[MPAppDelegate get] changeMasterPasswordFor:activeUser inContext:activeUser.managedObjectContext didResetBlock:nil];
|
||||
}
|
||||
|
@ -20,8 +20,8 @@
|
||||
|
||||
@interface MPSetupViewController : UIViewController
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *cloudSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *rememberLoginSwitch;
|
||||
@property(weak, nonatomic) IBOutlet UISwitch *cloudSwitch;
|
||||
@property(weak, nonatomic) IBOutlet UISwitch *rememberLoginSwitch;
|
||||
|
||||
- (IBAction)close:(UIBarButtonItem *)sender;
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#import "MPEntities.h"
|
||||
|
||||
|
||||
@protocol MPTypeDelegate<NSObject>
|
||||
|
||||
@required
|
||||
@ -24,7 +23,7 @@
|
||||
|
||||
@interface MPTypeViewController : UITableViewController
|
||||
|
||||
@property (nonatomic, weak) id<MPTypeDelegate> delegate;
|
||||
@property (weak, nonatomic) IBOutlet UIView *recommendedTipContainer;
|
||||
@property(nonatomic, weak) id<MPTypeDelegate> delegate;
|
||||
@property(weak, nonatomic) IBOutlet UIView *recommendedTipContainer;
|
||||
|
||||
@end
|
||||
|
@ -9,10 +9,8 @@
|
||||
#import "MPTypeViewController.h"
|
||||
#import "MPAppDelegate.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPAppDelegate_Key.h"
|
||||
|
||||
|
||||
@interface MPTypeViewController ()
|
||||
@interface MPTypeViewController()
|
||||
|
||||
- (MPElementType)typeAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
@ -37,11 +35,11 @@
|
||||
self.recommendedTipContainer.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished) {
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC) ), dispatch_get_main_queue(), ^{
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.recommendedTipContainer.alpha = 0;
|
||||
}];
|
||||
});
|
||||
} );
|
||||
}
|
||||
}];
|
||||
|
||||
@ -76,7 +74,7 @@
|
||||
cell.selected = (selectedType == cellType);
|
||||
|
||||
if (cellType != NSNotFound && cellType & MPElementTypeClassGenerated) {
|
||||
[(UITextField *) [cell viewWithTag:2] setText:@"..."];
|
||||
[(UITextField *)[cell viewWithTag:2] setText:@"..."];
|
||||
|
||||
NSString *name = selectedElement.name;
|
||||
NSUInteger counter = ((MPElementGeneratedEntity *)selectedElement).counter;
|
||||
|
@ -10,34 +10,34 @@
|
||||
|
||||
@interface MPUnlockViewController : UIViewController<UITextFieldDelegate, UIScrollViewDelegate, UIWebViewDelegate>
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *spinner;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *passwordFieldLabel;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *passwordField;
|
||||
@property (weak, nonatomic) IBOutlet UIView *passwordView;
|
||||
@property (weak, nonatomic) IBOutlet UIScrollView *avatarsView;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *oldNameLabel;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *avatarTemplate;
|
||||
@property (weak, nonatomic) IBOutlet UIView *createPasswordTipView;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *tip;
|
||||
@property (weak, nonatomic) IBOutlet UIView *passwordTipView;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *passwordTipLabel;
|
||||
@property (weak, nonatomic) IBOutlet UIView *wordWall;
|
||||
@property (strong, nonatomic) IBOutlet UILongPressGestureRecognizer *targetedUserActionGesture;
|
||||
@property (weak, nonatomic) IBOutlet UIView *uiContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIWebView *newsView;
|
||||
@property (weak, nonatomic) IBOutlet UIView *emergencyGeneratorContainer;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *emergencyName;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *emergencyMasterPassword;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *emergencySite;
|
||||
@property (weak, nonatomic) IBOutlet UIStepper *emergencyCounterStepper;
|
||||
@property (weak, nonatomic) IBOutlet UISegmentedControl *emergencyTypeControl;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *emergencyCounter;
|
||||
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *emergencyActivity;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *emergencyPassword;
|
||||
@property (weak, nonatomic) IBOutlet UIView *emergencyContentTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView *spinner;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *passwordFieldLabel;
|
||||
@property(weak, nonatomic) IBOutlet UITextField *passwordField;
|
||||
@property(weak, nonatomic) IBOutlet UIView *passwordView;
|
||||
@property(weak, nonatomic) IBOutlet UIScrollView *avatarsView;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *nameLabel;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *oldNameLabel;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *avatarTemplate;
|
||||
@property(weak, nonatomic) IBOutlet UIView *createPasswordTipView;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *tip;
|
||||
@property(weak, nonatomic) IBOutlet UIView *passwordTipView;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *passwordTipLabel;
|
||||
@property(weak, nonatomic) IBOutlet UIView *wordWall;
|
||||
@property(strong, nonatomic) IBOutlet UILongPressGestureRecognizer *targetedUserActionGesture;
|
||||
@property(weak, nonatomic) IBOutlet UIView *uiContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIWebView *newsView;
|
||||
@property(weak, nonatomic) IBOutlet UIView *emergencyGeneratorContainer;
|
||||
@property(weak, nonatomic) IBOutlet UITextField *emergencyName;
|
||||
@property(weak, nonatomic) IBOutlet UITextField *emergencyMasterPassword;
|
||||
@property(weak, nonatomic) IBOutlet UITextField *emergencySite;
|
||||
@property(weak, nonatomic) IBOutlet UIStepper *emergencyCounterStepper;
|
||||
@property(weak, nonatomic) IBOutlet UISegmentedControl *emergencyTypeControl;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *emergencyCounter;
|
||||
@property(weak, nonatomic) IBOutlet UIActivityIndicatorView *emergencyActivity;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *emergencyPassword;
|
||||
@property(weak, nonatomic) IBOutlet UIView *emergencyContentTipContainer;
|
||||
|
||||
@property (nonatomic, strong) UIColor *avatarShadowColor;
|
||||
@property(nonatomic, strong) UIColor *avatarShadowColor;
|
||||
|
||||
- (IBAction)targetedUserAction:(UILongPressGestureRecognizer *)sender;
|
||||
- (IBAction)facebook:(UIButton *)sender;
|
||||
|
@ -14,11 +14,11 @@
|
||||
#import "MPAppDelegate_Key.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
|
||||
@interface MPUnlockViewController ()
|
||||
@interface MPUnlockViewController()
|
||||
|
||||
@property (strong, nonatomic) NSMutableDictionary *avatarToUserOID;
|
||||
@property (nonatomic) BOOL wordWallAnimating;
|
||||
@property (nonatomic, strong) NSArray *wordList;
|
||||
@property(strong, nonatomic) NSMutableDictionary *avatarToUserOID;
|
||||
@property(nonatomic) BOOL wordWallAnimating;
|
||||
@property(nonatomic, strong) NSArray *wordList;
|
||||
|
||||
@property(nonatomic, strong) NSOperationQueue *emergencyQueue;
|
||||
@property(nonatomic, strong) MPKey *emergencyKey;
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
- (void)initializeAvatarAlert:(UIAlertView *)alert forUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc {
|
||||
|
||||
UIScrollView *alertAvatarScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(12, 30, 260, 150)];
|
||||
UIScrollView *alertAvatarScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake( 12, 30, 260, 150 )];
|
||||
alertAvatarScrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
|
||||
[alertAvatarScrollView flashScrollIndicatorsContinuously];
|
||||
[alert addSubview:alertAvatarScrollView];
|
||||
@ -47,8 +47,8 @@
|
||||
avatar.hidden = NO;
|
||||
avatar.center = CGPointMake(
|
||||
(20 + self.avatarTemplate.bounds.size.width / 2) * (a + 1) + self.avatarTemplate.bounds.size.width / 2 * a,
|
||||
20 + self.avatarTemplate.bounds.size.height / 2);
|
||||
[avatar setBackgroundImage:[UIImage imageNamed:PearlString(@"avatar-%d", a)] forState:UIControlStateNormal];
|
||||
20 + self.avatarTemplate.bounds.size.height / 2 );
|
||||
[avatar setBackgroundImage:[UIImage imageNamed:PearlString( @"avatar-%d", a )] forState:UIControlStateNormal];
|
||||
[avatar setSelectionInSuperviewCandidate:YES isClearable:NO];
|
||||
|
||||
avatar.layer.cornerRadius = avatar.bounds.size.height / 2;
|
||||
@ -71,7 +71,7 @@
|
||||
} options:0];
|
||||
avatar.selected = (a == user.avatar);
|
||||
if (avatar.selected)
|
||||
selectedOffset = CGPointMake(avatar.center.x - alertAvatarScrollView.bounds.size.width / 2, 0);
|
||||
selectedOffset = CGPointMake( avatar.center.x - alertAvatarScrollView.bounds.size.width / 2, 0 );
|
||||
}
|
||||
|
||||
[alertAvatarScrollView autoSizeContent];
|
||||
@ -80,26 +80,26 @@
|
||||
|
||||
- (void)initializeConfirmationAlert:(UIAlertView *)alert forUser:(MPUserEntity *)user {
|
||||
|
||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(12, 70, 260, 110)];
|
||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake( 12, 70, 260, 110 )];
|
||||
[alert addSubview:container];
|
||||
|
||||
UIButton *alertAvatar = [self.avatarTemplate cloneAddedTo:container];
|
||||
alertAvatar.center = CGPointMake(130, 55);
|
||||
alertAvatar.center = CGPointMake( 130, 55 );
|
||||
alertAvatar.hidden = NO;
|
||||
alertAvatar.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||
alertAvatar.layer.shadowOpacity = 1;
|
||||
alertAvatar.layer.shadowRadius = 5;
|
||||
alertAvatar.backgroundColor = [UIColor clearColor];
|
||||
[alertAvatar setBackgroundImage:[UIImage imageNamed:PearlString(@"avatar-%d", user.avatar)] forState:UIControlStateNormal];
|
||||
[alertAvatar setBackgroundImage:[UIImage imageNamed:PearlString( @"avatar-%d", user.avatar )] forState:UIControlStateNormal];
|
||||
|
||||
UILabel *alertNameLabel = [self.nameLabel cloneAddedTo:container];
|
||||
alertNameLabel.center = alertAvatar.center;
|
||||
alertNameLabel.text = user.name;
|
||||
alertNameLabel.bounds = CGRectSetHeight(alertNameLabel.bounds,
|
||||
alertNameLabel.bounds = CGRectSetHeight( alertNameLabel.bounds,
|
||||
[alertNameLabel.text sizeWithFont:self.nameLabel.font
|
||||
constrainedToSize:CGSizeMake(alertNameLabel.bounds.size.width - 10,
|
||||
100)
|
||||
lineBreakMode:self.nameLabel.lineBreakMode].height);
|
||||
constrainedToSize:CGSizeMake( alertNameLabel.bounds.size.width - 10,
|
||||
100 )
|
||||
lineBreakMode:self.nameLabel.lineBreakMode].height );
|
||||
alertNameLabel.layer.cornerRadius = 5;
|
||||
alertNameLabel.backgroundColor = [UIColor blackColor];
|
||||
}
|
||||
@ -134,7 +134,7 @@
|
||||
self.emergencyGeneratorContainer.hidden = YES;
|
||||
self.emergencyQueue = [NSOperationQueue new];
|
||||
[self.emergencyCounterStepper addTargetBlock:^(id sender, UIControlEvents event) {
|
||||
self.emergencyCounter.text = PearlString( @"%d", (NSUInteger)self.emergencyCounterStepper.value);
|
||||
self.emergencyCounter.text = PearlString( @"%d", (NSUInteger)self.emergencyCounterStepper.value );
|
||||
|
||||
[self updateEmergencyPassword];
|
||||
} forControlEvents:UIControlEventValueChanged];
|
||||
@ -143,8 +143,10 @@
|
||||
} forControlEvents:UIControlEventValueChanged];
|
||||
self.emergencyContentTipContainer.alpha = 0;
|
||||
self.emergencyContentTipContainer.hidden = NO;
|
||||
self.marqueeTipTexts = @[ @"Tap and hold to delete or reset user.",
|
||||
@"Shake for emergency generator." ];
|
||||
self.marqueeTipTexts = @[
|
||||
@"Tap and hold to delete or reset user.",
|
||||
@"Shake for emergency generator."
|
||||
];
|
||||
|
||||
NSMutableArray *wordListLines = [NSMutableArray arrayWithCapacity:27413];
|
||||
[[[NSString alloc] initWithData:[NSData dataWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"dictionary" withExtension:@"lst"]]
|
||||
@ -160,21 +162,21 @@
|
||||
[self initializeWordLabel:wordLabel];
|
||||
} recurse:NO];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UbiquityManagedStoreDidChangeNotification object:nil queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:UbiquityManagedStoreDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UbiquityManagedStoreDidImportChangesNotification object:nil queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:UbiquityManagedStoreDidImportChangesNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification object:nil queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:UIApplicationWillResignActiveNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
|
||||
[self emergencyCloseAnimated:NO];
|
||||
self.uiContainer.alpha = 0;
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
|
||||
[self updateLayoutAnimated:NO allowScroll:NO completion:nil];
|
||||
[UIView animateWithDuration:1 animations:^{
|
||||
self.uiContainer.alpha = 1;
|
||||
@ -257,6 +259,7 @@
|
||||
}
|
||||
|
||||
- (void)marqueeTip {
|
||||
|
||||
[UIView animateWithDuration:0.5 animations:^{
|
||||
self.tip.alpha = 0;
|
||||
} completion:^(BOOL finished) {
|
||||
@ -279,8 +282,8 @@
|
||||
__block NSArray *users = nil;
|
||||
[moc performBlockAndWait:^{
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPUserEntity class])];
|
||||
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO]];
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
|
||||
fetchRequest.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO] ];
|
||||
users = [moc executeFetchRequest:fetchRequest error:&error];
|
||||
if (!users)
|
||||
err(@"Failed to load users: %@", error);
|
||||
@ -308,7 +311,7 @@
|
||||
|
||||
- (UIButton *)setupAvatar:(UIButton *)avatar forUser:(MPUserEntity *)user {
|
||||
|
||||
avatar.center = CGPointMake(avatar.center.x + [self.avatarToUserOID count] * 160, avatar.center.y);
|
||||
avatar.center = CGPointMake( avatar.center.x + [self.avatarToUserOID count] * 160, avatar.center.y );
|
||||
avatar.hidden = NO;
|
||||
avatar.layer.cornerRadius = avatar.bounds.size.height / 2;
|
||||
avatar.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||
@ -318,7 +321,7 @@
|
||||
avatar.backgroundColor = [UIColor clearColor];
|
||||
avatar.tag = user.avatar;
|
||||
|
||||
[avatar setBackgroundImage:[UIImage imageNamed:PearlString(@"avatar-%u", user.avatar)]
|
||||
[avatar setBackgroundImage:[UIImage imageNamed:PearlString( @"avatar-%u", user.avatar )]
|
||||
forState:UIControlStateNormal];
|
||||
[avatar setSelectionInSuperviewCandidate:YES isClearable:YES];
|
||||
[avatar onHighlightOrSelect:^(BOOL highlighted, BOOL selected) {
|
||||
@ -331,7 +334,8 @@
|
||||
if (!selected) {
|
||||
self.selectedUser = nil;
|
||||
[self didToggleUserSelection];
|
||||
} else if ((self.selectedUser = user))
|
||||
}
|
||||
else if ((self.selectedUser = user))
|
||||
[self didToggleUserSelection];
|
||||
else
|
||||
[self didSelectNewUserAvatar:avatar];
|
||||
@ -352,8 +356,7 @@
|
||||
MPUserEntity *selectedUser = self.selectedUser;
|
||||
if (!selectedUser)
|
||||
[self.passwordField resignFirstResponder];
|
||||
else
|
||||
if ([[MPAppDelegate get] signInAsUser:selectedUser usingMasterPassword:nil]) {
|
||||
else if ([[MPAppDelegate get] signInAsUser:selectedUser usingMasterPassword:nil]) {
|
||||
[self performSegueWithIdentifier:@"MP_Unlock" sender:self];
|
||||
return;
|
||||
}
|
||||
@ -367,7 +370,8 @@
|
||||
- (void)didSelectNewUserAvatar:(UIButton *)newUserAvatar {
|
||||
|
||||
[MPAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *newUser = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MPUserEntity class]) inManagedObjectContext:moc];
|
||||
MPUserEntity *newUser = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass( [MPUserEntity class] )
|
||||
inManagedObjectContext:moc];
|
||||
|
||||
[self showNewUserNameAlertFor:newUser inContext:moc completion:^(BOOL finished) {
|
||||
newUserAvatar.selected = NO;
|
||||
@ -390,7 +394,7 @@
|
||||
}
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert cancelButtonIndex]) {
|
||||
completion(NO);
|
||||
completion( NO );
|
||||
return;
|
||||
}
|
||||
NSString *name = [alert textFieldAtIndex:0].text;
|
||||
@ -445,7 +449,7 @@
|
||||
|
||||
// Confirm
|
||||
[moc saveToStore];
|
||||
completion(YES);
|
||||
completion( YES );
|
||||
|
||||
[self updateUsers];
|
||||
}
|
||||
@ -466,7 +470,7 @@
|
||||
self.nameLabel.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
if (completion)
|
||||
completion(finished);
|
||||
completion( finished );
|
||||
}];
|
||||
return;
|
||||
}
|
||||
@ -475,20 +479,20 @@
|
||||
if (self.selectedUser && !self.passwordView.alpha) {
|
||||
// User was just selected.
|
||||
self.passwordView.alpha = 1;
|
||||
self.avatarsView.center = CGPointMake(160, 180);
|
||||
self.avatarsView.center = CGPointMake( 160, 180 );
|
||||
self.avatarsView.scrollEnabled = NO;
|
||||
self.nameLabel.center = CGPointMake(160, 94);
|
||||
self.nameLabel.center = CGPointMake( 160, 94 );
|
||||
self.nameLabel.backgroundColor = [UIColor blackColor];
|
||||
self.oldNameLabel.center = self.nameLabel.center;
|
||||
self.avatarShadowColor = [UIColor whiteColor];
|
||||
} else
|
||||
if (!self.selectedUser && self.passwordView.alpha == 1) {
|
||||
}
|
||||
else if (!self.selectedUser && self.passwordView.alpha == 1) {
|
||||
// User was just deselected.
|
||||
self.passwordField.text = nil;
|
||||
self.passwordView.alpha = 0;
|
||||
self.avatarsView.center = CGPointMake(160, 310);
|
||||
self.avatarsView.center = CGPointMake( 160, 310 );
|
||||
self.avatarsView.scrollEnabled = YES;
|
||||
self.nameLabel.center = CGPointMake(160, 296);
|
||||
self.nameLabel.center = CGPointMake( 160, 296 );
|
||||
self.nameLabel.backgroundColor = [UIColor clearColor];
|
||||
self.oldNameLabel.center = self.nameLabel.center;
|
||||
self.avatarShadowColor = [UIColor lightGrayColor];
|
||||
@ -501,7 +505,8 @@
|
||||
self.wordWall.alpha = 0;
|
||||
self.createPasswordTipView.alpha = 0;
|
||||
self.wordWallAnimating = NO;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
self.passwordFieldLabel.text = @"Create your master password:";
|
||||
|
||||
if (!self.wordWallAnimating) {
|
||||
@ -509,15 +514,15 @@
|
||||
self.wordWall.alpha = 1;
|
||||
self.createPasswordTipView.alpha = 1;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
// Jump out of our UIView animation block.
|
||||
[self beginWordWallAnimation];
|
||||
});
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 15 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
||||
} );
|
||||
dispatch_after( dispatch_time( DISPATCH_TIME_NOW, 15 * NSEC_PER_SEC ), dispatch_get_main_queue(), ^{
|
||||
[UIView animateWithDuration:1 animations:^{
|
||||
self.createPasswordTipView.alpha = 0;
|
||||
}];
|
||||
});
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
@ -545,21 +550,21 @@
|
||||
} recurse:NO];
|
||||
|
||||
if (allowScroll) {
|
||||
CGPoint targetContentOffset = CGPointMake(MAX(0, targetedAvatar.center.x - self.avatarsView.bounds.size.width / 2),
|
||||
self.avatarsView.contentOffset.y);
|
||||
if (!CGPointEqualToPoint(self.avatarsView.contentOffset, targetContentOffset))
|
||||
CGPoint targetContentOffset = CGPointMake( MAX(0, targetedAvatar.center.x - self.avatarsView.bounds.size.width / 2),
|
||||
self.avatarsView.contentOffset.y );
|
||||
if (!CGPointEqualToPoint( self.avatarsView.contentOffset, targetContentOffset ))
|
||||
[self.avatarsView setContentOffset:targetContentOffset animated:animated];
|
||||
}
|
||||
|
||||
// Lay out user name label.
|
||||
self.nameLabel.text = targetedAvatar? (targetedUser? targetedUser.name: @"New User"): nil;
|
||||
self.nameLabel.bounds = CGRectSetHeight(self.nameLabel.bounds,
|
||||
self.nameLabel.bounds = CGRectSetHeight( self.nameLabel.bounds,
|
||||
[self.nameLabel.text sizeWithFont:self.nameLabel.font
|
||||
constrainedToSize:CGSizeMake(self.nameLabel.bounds.size.width - 10, 100)
|
||||
lineBreakMode:self.nameLabel.lineBreakMode].height);
|
||||
constrainedToSize:CGSizeMake( self.nameLabel.bounds.size.width - 10, 100 )
|
||||
lineBreakMode:self.nameLabel.lineBreakMode].height );
|
||||
self.oldNameLabel.bounds = self.nameLabel.bounds;
|
||||
if (completion)
|
||||
completion(YES);
|
||||
completion( YES );
|
||||
}
|
||||
|
||||
- (void)beginWordWallAnimation {
|
||||
@ -568,7 +573,7 @@
|
||||
UILabel *wordLabel = (UILabel *)subview;
|
||||
|
||||
if (wordLabel.frame.origin.x < -self.wordWall.frame.size.width / 3) {
|
||||
wordLabel.frame = CGRectSetX(wordLabel.frame, wordLabel.frame.origin.x + self.wordWall.frame.size.width);
|
||||
wordLabel.frame = CGRectSetX( wordLabel.frame, wordLabel.frame.origin.x + self.wordWall.frame.size.width );
|
||||
[self initializeWordLabel:wordLabel];
|
||||
}
|
||||
} recurse:NO];
|
||||
@ -578,7 +583,7 @@
|
||||
[self.wordWall enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||
UILabel *wordLabel = (UILabel *)subview;
|
||||
|
||||
wordLabel.frame = CGRectSetX(wordLabel.frame, wordLabel.frame.origin.x - self.wordWall.frame.size.width / 3);
|
||||
wordLabel.frame = CGRectSetX( wordLabel.frame, wordLabel.frame.origin.x - self.wordWall.frame.size.width / 3 );
|
||||
} recurse:NO];
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished)
|
||||
@ -610,10 +615,10 @@
|
||||
|
||||
[self setSpinnerActive:YES];
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
|
||||
BOOL unlocked = [[MPAppDelegate get] signInAsUser:self.selectedUser usingMasterPassword:self.passwordField.text];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
if (unlocked)
|
||||
[self performSegueWithIdentifier:@"MP_Unlock" sender:self];
|
||||
|
||||
@ -623,14 +628,14 @@
|
||||
|
||||
[self setSpinnerActive:NO];
|
||||
}
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
- (UIButton *)findTargetedAvatar {
|
||||
|
||||
CGFloat xOfMiddle = self.avatarsView.contentOffset.x + self.avatarsView.bounds.size.width / 2;
|
||||
return (UIButton *)[PearlUIUtils viewClosestTo:CGPointMake(xOfMiddle, self.avatarsView.contentOffset.y)
|
||||
return (UIButton *)[PearlUIUtils viewClosestTo:CGPointMake( xOfMiddle, self.avatarsView.contentOffset.y )
|
||||
ofArray:self.avatarsView.subviews];
|
||||
}
|
||||
|
||||
@ -676,7 +681,8 @@
|
||||
rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
|
||||
rotate.fromValue = [NSNumber numberWithFloat:0];
|
||||
rotate.repeatCount = MAXFLOAT;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
|
||||
rotate.repeatCount = 1;
|
||||
}
|
||||
@ -719,13 +725,14 @@
|
||||
pulseShadowOpacityAnimation.repeatCount = MAXFLOAT;
|
||||
|
||||
CAAnimationGroup *group = [[CAAnimationGroup alloc] init];
|
||||
group.animations = @[toShadowColorAnimation, toShadowOpacityAnimation, pulseShadowOpacityAnimation];
|
||||
group.animations = @[ toShadowColorAnimation, toShadowOpacityAnimation, pulseShadowOpacityAnimation ];
|
||||
group.duration = MAXFLOAT;
|
||||
|
||||
[avatar.layer removeAnimationForKey:@"inactiveShadow"];
|
||||
[avatar.layer addAnimation:group forKey:@"targetedShadow"];
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if ([avatar.layer animationForKey:@"targetedShadow"]) {
|
||||
CABasicAnimation *toShadowColorAnimation = [CABasicAnimation animationWithKeyPath:@"shadowColor"];
|
||||
toShadowColorAnimation.toValue = (__bridge id)[UIColor blackColor].CGColor;
|
||||
@ -736,7 +743,7 @@
|
||||
toShadowOpacityAnimation.duration = 0.5f;
|
||||
|
||||
CAAnimationGroup *group = [[CAAnimationGroup alloc] init];
|
||||
group.animations = @[toShadowColorAnimation, toShadowOpacityAnimation];
|
||||
group.animations = @[ toShadowColorAnimation, toShadowOpacityAnimation ];
|
||||
group.duration = 0.5f;
|
||||
|
||||
[avatar.layer removeAnimationForKey:@"targetedShadow"];
|
||||
@ -933,9 +940,9 @@
|
||||
targetContentOffset:(inout CGPoint *)targetContentOffset {
|
||||
|
||||
CGFloat xOfMiddle = targetContentOffset->x + scrollView.bounds.size.width / 2;
|
||||
UIButton *middleAvatar = (UIButton *)[PearlUIUtils viewClosestTo:CGPointMake(xOfMiddle, targetContentOffset->y)
|
||||
UIButton *middleAvatar = (UIButton *)[PearlUIUtils viewClosestTo:CGPointMake( xOfMiddle, targetContentOffset->y )
|
||||
ofArray:scrollView.subviews];
|
||||
*targetContentOffset = CGPointMake(middleAvatar.center.x - scrollView.bounds.size.width / 2, targetContentOffset->y);
|
||||
*targetContentOffset = CGPointMake( middleAvatar.center.x - scrollView.bounds.size.width / 2, targetContentOffset->y );
|
||||
|
||||
[self updateLayoutAnimated:NO allowScroll:NO completion:nil];
|
||||
}
|
||||
@ -989,18 +996,18 @@
|
||||
[moc deleteObject:targetedUser];
|
||||
[moc saveToStore];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[self updateUsers];
|
||||
});
|
||||
} );
|
||||
}];
|
||||
return;
|
||||
}
|
||||
|
||||
if (buttonIndex == [sheet firstOtherButtonIndex])
|
||||
[[MPAppDelegate get] changeMasterPasswordFor:targetedUser inContext:moc didResetBlock:^{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[[self avatarForUser:targetedUser] setSelected:YES];
|
||||
});
|
||||
} );
|
||||
}];
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel
|
||||
destructiveTitle:@"Delete User" otherTitles:@"Reset Password", nil];
|
||||
@ -1079,8 +1086,9 @@
|
||||
@"simplytweet:?link=http://twitter.com/%@", // SimplyTweet
|
||||
@"icebird://user?screen_name=%@", // IceBird
|
||||
@"fluttr://user/%@", // Fluttr
|
||||
@"http://twitter.com/%@"]) {
|
||||
NSURL *url = [NSURL URLWithString:PearlString(candidate, @"master_password")];
|
||||
@"http://twitter.com/%@"
|
||||
]) {
|
||||
NSURL *url = [NSURL URLWithString:PearlString( candidate, @"master_password" )];
|
||||
|
||||
if ([application canOpenURL:url]) {
|
||||
[application openURL:url];
|
||||
|
@ -10,11 +10,11 @@
|
||||
|
||||
@interface MPiOSConfig : MPConfig
|
||||
|
||||
@property (nonatomic, retain) NSNumber *helpHidden;
|
||||
@property (nonatomic, retain) NSNumber *siteInfoHidden;
|
||||
@property (nonatomic, retain) NSNumber *showSetup;
|
||||
@property (nonatomic, retain) NSNumber *actionsTipShown;
|
||||
@property (nonatomic, retain) NSNumber *typeTipShown;
|
||||
@property (nonatomic, retain) NSNumber *loginNameTipShown;
|
||||
@property(nonatomic, retain) NSNumber *helpHidden;
|
||||
@property(nonatomic, retain) NSNumber *siteInfoHidden;
|
||||
@property(nonatomic, retain) NSNumber *showSetup;
|
||||
@property(nonatomic, retain) NSNumber *actionsTipShown;
|
||||
@property(nonatomic, retain) NSNumber *typeTipShown;
|
||||
@property(nonatomic, retain) NSNumber *loginNameTipShown;
|
||||
|
||||
@end
|
||||
|
@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
@implementation MPiOSConfig
|
||||
|
||||
@dynamic sendInfo, helpHidden, siteInfoHidden, showSetup, actionsTipShown, typeTipShown, loginNameTipShown;
|
||||
|
||||
- (id)init {
|
||||
@ -14,13 +15,15 @@
|
||||
if (!(self = [super init]))
|
||||
return self;
|
||||
|
||||
[self.defaults registerDefaults:@{ NSStringFromSelector(@selector(helpHidden)): @NO,
|
||||
NSStringFromSelector(@selector(siteInfoHidden)): @YES,
|
||||
NSStringFromSelector(@selector(showSetup)): @YES,
|
||||
NSStringFromSelector(@selector(iTunesID)): @"510296984",
|
||||
NSStringFromSelector(@selector(actionsTipShown)): PearlBoolNot(self.firstRun),
|
||||
NSStringFromSelector(@selector(typeTipShown)): PearlBoolNot(self.firstRun),
|
||||
NSStringFromSelector(@selector(loginNameTipShown)): PearlBool(NO)}];
|
||||
[self.defaults registerDefaults:@{
|
||||
NSStringFromSelector( @selector(helpHidden) ) : @NO,
|
||||
NSStringFromSelector( @selector(siteInfoHidden) ) : @YES,
|
||||
NSStringFromSelector( @selector(showSetup) ) : @YES,
|
||||
NSStringFromSelector( @selector(iTunesID) ) : @"510296984",
|
||||
NSStringFromSelector( @selector(actionsTipShown) ) : PearlBoolNot(self.firstRun),
|
||||
NSStringFromSelector( @selector(typeTipShown) ) : PearlBoolNot(self.firstRun),
|
||||
NSStringFromSelector( @selector(loginNameTipShown) ) : PearlBool(NO)
|
||||
}];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
@ -161,5 +161,5 @@
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -1,12 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<dict>
|
||||
<key>PreferenceSpecifiers</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>If you're experiencing problems, enabling this will send us details that can help diagnose and resolve them. You will remain completely anonymous amongst the other thousands of users. No sensitive information is ever sent.</string>
|
||||
<string>If you're experiencing problems, enabling this will send us details that can help diagnose and resolve them.
|
||||
You will remain completely anonymous amongst the other thousands of users. No sensitive information is ever sent.
|
||||
</string>
|
||||
<key>Title</key>
|
||||
<string></string>
|
||||
<key>Type</key>
|
||||
@ -54,7 +56,9 @@
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>When enabled, closing the application will not log out the user. Similar to your phone's SIM lock, you only need to log in once after powering on.</string>
|
||||
<string>When enabled, closing the application will not log out the user. Similar to your phone's SIM lock, you only
|
||||
need to log in once after powering on.
|
||||
</string>
|
||||
<key>Title</key>
|
||||
<string>Master Password</string>
|
||||
<key>Type</key>
|
||||
@ -76,7 +80,9 @@
|
||||
<key>Title</key>
|
||||
<string></string>
|
||||
<key>FooterText</key>
|
||||
<string>Makes your sites available to all your Apple devices. This also works as a way of automatically keeping a back-up of your sites. Apple cannot see any of your passwords.</string>
|
||||
<string>Makes your sites available to all your Apple devices. This also works as a way of automatically keeping a back-up of
|
||||
your sites. Apple cannot see any of your passwords.
|
||||
</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Type</key>
|
||||
@ -91,5 +97,5 @@
|
||||
</array>
|
||||
<key>StringsTable</key>
|
||||
<string>Root</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -11,6 +11,6 @@
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([MPAppDelegate class]));
|
||||
return UIApplicationMain( argc, argv, nil, NSStringFromClass( [MPAppDelegate class] ) );
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user