Compare commits
26 Commits
1.4
...
1.4-appsto
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3963a72ad | ||
|
|
cefe8d144d | ||
|
|
076cfb1257 | ||
|
|
71e3f44c8c | ||
|
|
c36f34346d | ||
|
|
cd6b83ffe8 | ||
|
|
d110fd18c1 | ||
|
|
e45b9985c2 | ||
|
|
8f4eb6df84 | ||
|
|
809bd60169 | ||
|
|
802c5949da | ||
|
|
407c5528ee | ||
|
|
fed3a2bc10 | ||
|
|
7329353c6c | ||
|
|
a7c861d1b0 | ||
|
|
9af8ab3360 | ||
|
|
ddb5328019 | ||
|
|
96d97d95e1 | ||
|
|
ab15694d9a | ||
|
|
81312e3ff4 | ||
|
|
5e1e88bdeb | ||
|
|
9882bf408c | ||
|
|
40f34f3d77 | ||
|
|
0ee1e176ed | ||
|
|
c73f89e4a1 | ||
|
|
fe9a1cdbc4 |
Binary file not shown.
@@ -170,6 +170,16 @@ OBJC_EXTERN void CLSNSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
|
||||
**/
|
||||
@property (nonatomic, readonly) NSDate *crashedOnDate;
|
||||
|
||||
/**
|
||||
* Returns the os version that the application crashed on.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSString *OSVersion;
|
||||
|
||||
/**
|
||||
* Returns the os build version that the application crashed on.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSString *OSBuildVersion;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.0.8</string>
|
||||
<string>2.0.9</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>iPhoneOS</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0200.08.00</string>
|
||||
<string>0200.09.00</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>iphoneos</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
|
||||
2
External/Pearl
vendored
2
External/Pearl
vendored
Submodule External/Pearl updated: e9b731dca8...a2a43a63e2
2
External/UbiquityStoreManager
vendored
2
External/UbiquityStoreManager
vendored
Submodule External/UbiquityStoreManager updated: 9a4d52c382...8c7d9d629e
@@ -25,7 +25,7 @@
|
||||
|
||||
@required
|
||||
- (NSUInteger)version;
|
||||
- (BOOL)migrateUser:(MPUserEntity *)user;
|
||||
- (BOOL)migrateUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc;
|
||||
- (BOOL)migrateElement:(MPElementEntity *)element explicit:(BOOL)explicit;
|
||||
|
||||
- (MPKey *)keyForPassword:(NSString *)password ofUserNamed:(NSString *)userName;
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (BOOL)migrateUser:(MPUserEntity *)user {
|
||||
- (BOOL)migrateUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc {
|
||||
|
||||
NSError *error = nil;
|
||||
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];
|
||||
NSArray *migrationElements = [moc executeFetchRequest:migrationRequest error:&error];
|
||||
if (!migrationElements) {
|
||||
err(@"While looking for elements to migrate: %@", error);
|
||||
return NO;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
@interface MPAppDelegate_Shared(Key)
|
||||
|
||||
- (BOOL)signInAsUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc usingMasterPassword:(NSString *)password;
|
||||
- (BOOL)signInAsUser:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc usingMasterPassword:(NSString *)password;
|
||||
- (void)signOutAnimated:(BOOL)animated;
|
||||
|
||||
- (void)storeSavedKeyFor:(MPUserEntity *)user;
|
||||
|
||||
@@ -77,7 +77,7 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPSignedOutNotification object:self userInfo:@{ @"animated" : @(animated) }];
|
||||
}
|
||||
|
||||
- (BOOL)signInAsUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc usingMasterPassword:(NSString *)password {
|
||||
- (BOOL)signInAsUser:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc usingMasterPassword:(NSString *)password {
|
||||
|
||||
if (password)
|
||||
NSAssert(![NSThread isMainThread], @"Computing key may not happen from the main thread.");
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
|
||||
- (void)setActiveUser:(MPUserEntity *)activeUser {
|
||||
|
||||
NSError *error;
|
||||
if (activeUser.objectID.isTemporaryID && ![activeUser.managedObjectContext obtainPermanentIDsForObjects:@[ activeUser ] error:&error])
|
||||
err(@"Failed to obtain a permanent object ID after setting active user: %@", error);
|
||||
|
||||
_activeUserOID = activeUser.objectID;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ typedef enum {
|
||||
+ (BOOL)managedObjectContextPerformBlockAndWait:(void (^)(NSManagedObjectContext *))mocBlock;
|
||||
|
||||
- (UbiquityStoreManager *)storeManager;
|
||||
|
||||
- (void)addElementNamed:(NSString *)siteName completion:(void (^)(MPElementEntity *element))completion;
|
||||
- (MPImportResult)importSites:(NSString *)importedSitesString
|
||||
askImportPassword:(NSString *(^)(NSString *userName))importPassword
|
||||
askUserPassword:(NSString *(^)(NSString *userName, NSUInteger importCount, NSUInteger deleteCount))userPassword;
|
||||
|
||||
@@ -15,13 +15,25 @@
|
||||
#define STORE_OPTIONS
|
||||
#endif
|
||||
|
||||
#define MPCloudContainerIdentifier @"HL3Q45LX9N.com.lyndir.lhunath.MasterPassword.shared"
|
||||
#define MPMigrationLevelLocalStoreKey @"MPMigrationLevelLocalStoreKey"
|
||||
#define MPMigrationLevelCloudStoreKey @"MPMigrationLevelCloudStoreKey"
|
||||
|
||||
typedef NS_ENUM(NSInteger, MPMigrationLevelLocalStore) {
|
||||
MPMigrationLevelLocalStoreV1,
|
||||
MPMigrationLevelLocalStoreV2,
|
||||
MPMigrationLevelLocalStoreCurrent = MPMigrationLevelLocalStoreV2,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, MPMigrationLevelCloudStore) {
|
||||
MPMigrationLevelCloudStoreV1,
|
||||
MPMigrationLevelCloudStoreV2,
|
||||
MPMigrationLevelCloudStoreV3,
|
||||
MPMigrationLevelCloudStoreCurrent = MPMigrationLevelCloudStoreV3,
|
||||
};
|
||||
|
||||
@implementation MPAppDelegate_Shared(Store)
|
||||
#if TARGET_OS_IPHONE
|
||||
PearlAssociatedObjectProperty(PearlAlert*, HandleCloudContentAlert, handleCloudContentAlert);
|
||||
PearlAssociatedObjectProperty(PearlAlert*, FixCloudContentAlert, fixCloudContentAlert);
|
||||
PearlAssociatedObjectProperty(PearlOverlay*, StoreLoading, storeLoading);
|
||||
#endif
|
||||
PearlAssociatedObjectProperty(NSManagedObjectContext*, PrivateManagedObjectContext, privateManagedObjectContext);
|
||||
PearlAssociatedObjectProperty(NSManagedObjectContext*, PrivateManagedObjectContext, privateManagedObjectContext);
|
||||
PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext, mainManagedObjectContext);
|
||||
|
||||
|
||||
@@ -91,7 +103,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
return storeManager;
|
||||
|
||||
storeManager = [[UbiquityStoreManager alloc] initStoreNamed:nil withManagedObjectModel:nil localStoreURL:nil
|
||||
containerIdentifier:@"HL3Q45LX9N.com.lyndir.lhunath.MasterPassword.shared"
|
||||
containerIdentifier:MPCloudContainerIdentifier
|
||||
additionalStoreOptions:@{ STORE_OPTIONS }
|
||||
delegate:self];
|
||||
|
||||
@@ -99,18 +111,21 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillTerminateNotification
|
||||
object:[UIApplication sharedApplication] queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[self saveContexts];
|
||||
[[self mainManagedObjectContext] saveToStore];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification
|
||||
object:[UIApplication sharedApplication] queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[self saveContexts];
|
||||
[[self mainManagedObjectContext] saveToStore];
|
||||
}];
|
||||
#else
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillTerminateNotification
|
||||
object:[NSApplication sharedApplication] queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[self saveContexts];
|
||||
NSManagedObjectContext *moc = self.mainManagedObjectContextIfReady;
|
||||
[moc performBlockAndWait:^{
|
||||
[moc saveToStore];
|
||||
}];
|
||||
}];
|
||||
#endif
|
||||
|
||||
@@ -119,33 +134,113 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
|
||||
- (void)migrateStoreForManager:(UbiquityStoreManager *)manager isCloud:(BOOL)isCloudStore {
|
||||
|
||||
[self migrateLocalStoreForManager:manager];
|
||||
[self migrateLocalStore];
|
||||
|
||||
if (isCloudStore)
|
||||
[self migrateCloudStoreForManager:manager];
|
||||
[self migrateCloudStore];
|
||||
}
|
||||
|
||||
- (void)migrateLocalStoreForManager:(UbiquityStoreManager *)manager {
|
||||
- (void)migrateLocalStore {
|
||||
|
||||
MPMigrationLevelLocalStore migrationLevel = (signed)[[NSUserDefaults standardUserDefaults] integerForKey:MPMigrationLevelLocalStoreKey];
|
||||
if (migrationLevel >= MPMigrationLevelLocalStoreCurrent)
|
||||
// Local store up-to-date.
|
||||
return;
|
||||
|
||||
inf(@"Local store migration level: %d (current %d)", (signed)migrationLevel, (signed)MPMigrationLevelLocalStoreCurrent);
|
||||
if (migrationLevel <= MPMigrationLevelLocalStoreV1)
|
||||
[self migrateV1LocalStore];
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:MPMigrationLevelLocalStoreCurrent forKey:MPMigrationLevelLocalStoreKey];
|
||||
inf(@"Successfully migrated old to new local store.");
|
||||
}
|
||||
|
||||
- (void)migrateCloudStore {
|
||||
|
||||
MPMigrationLevelCloudStore migrationLevel = (signed)[[NSUserDefaults standardUserDefaults] integerForKey:MPMigrationLevelCloudStoreKey];
|
||||
if (migrationLevel >= MPMigrationLevelCloudStoreCurrent)
|
||||
// Cloud store up-to-date.
|
||||
return;
|
||||
|
||||
inf(@"Cloud store migration level: %d (current %d)", (signed)migrationLevel, (signed)MPMigrationLevelCloudStoreCurrent);
|
||||
if (migrationLevel <= MPMigrationLevelCloudStoreV1)
|
||||
[self migrateV1CloudStore];
|
||||
else if (migrationLevel <= MPMigrationLevelCloudStoreV2)
|
||||
[self migrateV2CloudStore];
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:MPMigrationLevelCloudStoreCurrent forKey:MPMigrationLevelCloudStoreKey];
|
||||
}
|
||||
|
||||
- (void)migrateV1CloudStore {
|
||||
|
||||
// Migrate cloud enabled preference.
|
||||
NSNumber *oldCloudEnabled = [[NSUserDefaults standardUserDefaults] objectForKey:@"iCloudEnabledKey"];
|
||||
if ([oldCloudEnabled boolValue])
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:USMCloudEnabledKey];
|
||||
|
||||
// Migrate cloud store.
|
||||
NSString *uuid = [[NSUserDefaults standardUserDefaults] stringForKey:@"LocalUUIDKey"];
|
||||
if (!uuid) {
|
||||
inf(@"No V1 cloud store to migrate.");
|
||||
return;
|
||||
}
|
||||
|
||||
inf(@"Migrating V1 cloud store: %@ -> %@", uuid, [self.storeManager valueForKey:@"storeUUID"]);
|
||||
NSURL *cloudContainerURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:MPCloudContainerIdentifier];
|
||||
NSURL *oldCloudContentURL = [[cloudContainerURL
|
||||
URLByAppendingPathComponent:@"Data" isDirectory:YES]
|
||||
URLByAppendingPathComponent:uuid isDirectory:YES];
|
||||
NSURL *oldCloudStoreURL = [[[cloudContainerURL
|
||||
URLByAppendingPathComponent:@"Database.nosync" isDirectory:YES]
|
||||
URLByAppendingPathComponent:uuid isDirectory:NO] URLByAppendingPathExtension:@"sqlite"];
|
||||
|
||||
[self migrateFromCloudStore:oldCloudStoreURL cloudContent:oldCloudContentURL contentName:uuid];
|
||||
}
|
||||
|
||||
- (void)migrateV2CloudStore {
|
||||
|
||||
// Migrate cloud store.
|
||||
NSString *uuid = [[NSUbiquitousKeyValueStore defaultStore] stringForKey:@"USMStoreUUIDKey"];
|
||||
if (!uuid) {
|
||||
inf(@"No V2 cloud store to migrate.");
|
||||
return;
|
||||
}
|
||||
|
||||
inf(@"Migrating V2 cloud store: %@ -> %@", uuid, [self.storeManager valueForKey:@"storeUUID"]);
|
||||
NSURL *cloudContainerURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:MPCloudContainerIdentifier];
|
||||
NSURL *oldCloudContentURL = [[cloudContainerURL
|
||||
URLByAppendingPathComponent:@"CloudLogs" isDirectory:YES]
|
||||
URLByAppendingPathComponent:uuid isDirectory:YES];
|
||||
NSURL *oldCloudStoreURL = [[[cloudContainerURL
|
||||
URLByAppendingPathComponent:@"CloudStore.nosync" isDirectory:YES]
|
||||
URLByAppendingPathComponent:uuid isDirectory:NO] URLByAppendingPathExtension:@"sqlite"];
|
||||
|
||||
[self migrateFromCloudStore:oldCloudStoreURL cloudContent:oldCloudContentURL contentName:uuid];
|
||||
}
|
||||
|
||||
- (void)migrateV1LocalStore {
|
||||
|
||||
NSURL *applicationFilesDirectory = [[[NSFileManager defaultManager]
|
||||
URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
|
||||
NSURL *oldLocalStoreURL = [[applicationFilesDirectory
|
||||
URLByAppendingPathComponent:@"MasterPassword" isDirectory:NO] URLByAppendingPathExtension:@"sqlite"];
|
||||
NSURL *newLocalStoreURL = [manager URLForLocalStore];
|
||||
if ([newLocalStoreURL isEqual:oldLocalStoreURL]) {
|
||||
// Old store migration failed earlier and we set the old URL as the manager's local store.
|
||||
return;
|
||||
}
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:oldLocalStoreURL.path isDirectory:NO]) {
|
||||
// No local store to migrate.
|
||||
return;
|
||||
}
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:newLocalStoreURL.path isDirectory:NO]) {
|
||||
wrn(@"Can't migrate old local store: A new local store already exists.");
|
||||
inf(@"No V1 local store to migrate.");
|
||||
return;
|
||||
}
|
||||
|
||||
inf(@"Migrating V1 local store");
|
||||
[self migrateFromLocalStore:oldLocalStoreURL];
|
||||
}
|
||||
|
||||
- (void)migrateFromLocalStore:(NSURL *)oldLocalStoreURL {
|
||||
|
||||
NSURL *newLocalStoreURL = [self.storeManager URLForLocalStore];
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:newLocalStoreURL.path isDirectory:NO]) {
|
||||
wrn(@"Can't migrate local store: A new local store already exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
inf(@"Migrating local store...");
|
||||
NSError *error = nil;
|
||||
NSDictionary *oldLocalStoreOptions = @{
|
||||
STORE_OPTIONS
|
||||
@@ -159,69 +254,38 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
};
|
||||
|
||||
// Create the directory to hold the new local store.
|
||||
if (![[NSFileManager defaultManager] createDirectoryAtPath:[manager URLForLocalStoreDirectory].path
|
||||
withIntermediateDirectories:YES attributes:nil error:&error]) {
|
||||
err(@"While creating directory for new local store: %@", error);
|
||||
manager.localStoreURL = oldLocalStoreURL;
|
||||
return;
|
||||
}
|
||||
if (![[NSFileManager defaultManager] createDirectoryAtPath:[self.storeManager URLForLocalStoreDirectory].path
|
||||
withIntermediateDirectories:YES attributes:nil error:&error])
|
||||
err(@"While creating directory for new local store: %@", error);
|
||||
|
||||
if (![manager copyMigrateStore:oldLocalStoreURL withOptions:oldLocalStoreOptions
|
||||
toStore:newLocalStoreURL withOptions:newLocalStoreOptions
|
||||
error:nil cause:nil context:nil]) {
|
||||
manager.localStoreURL = oldLocalStoreURL;
|
||||
if (![self.storeManager copyMigrateStore:oldLocalStoreURL withOptions:oldLocalStoreOptions
|
||||
toStore:newLocalStoreURL withOptions:newLocalStoreOptions
|
||||
error:nil cause:nil context:nil])
|
||||
return;
|
||||
}
|
||||
|
||||
inf(@"Successfully migrated old to new local store.");
|
||||
inf(@"Successfully migrated to new local store.");
|
||||
}
|
||||
|
||||
- (void)migrateCloudStoreForManager:(UbiquityStoreManager *)manager {
|
||||
- (void)migrateFromCloudStore:(NSURL *)oldCloudStoreURL cloudContent:(NSURL *)oldCloudContentURL contentName:(NSString *)contentName {
|
||||
|
||||
// Migrate cloud enabled preference.
|
||||
NSNumber *oldCloudEnabled = [[NSUserDefaults standardUserDefaults] objectForKey:@"iCloudEnabledKey"];
|
||||
if ([oldCloudEnabled boolValue]) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:USMCloudEnabledKey];
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"iCloudEnabledKey"];
|
||||
}
|
||||
|
||||
// Migrate cloud store.
|
||||
NSString *uuid = [[NSUserDefaults standardUserDefaults] stringForKey:@"LocalUUIDKey"];
|
||||
if (!uuid)
|
||||
// No old cloud store to migrate.
|
||||
return;
|
||||
|
||||
if (![manager cloudSafeForSeeding]) {
|
||||
wrn(@"Can't migrate old cloud store: A new cloud store already exists.");
|
||||
if (![self.storeManager cloudSafeForSeeding]) {
|
||||
inf(@"Can't migrate cloud store: A new cloud store already exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
NSURL *cloudContainerURL = [[NSFileManager defaultManager]
|
||||
URLForUbiquityContainerIdentifier:@"HL3Q45LX9N.com.lyndir.lhunath.MasterPassword.shared"];
|
||||
NSURL *newCloudStoreURL = [manager URLForCloudStore];
|
||||
NSURL *newCloudContentURL = [manager URLForCloudContent];
|
||||
NSURL *oldCloudContentURL = [[cloudContainerURL URLByAppendingPathComponent:@"Data" isDirectory:YES]
|
||||
URLByAppendingPathComponent:uuid isDirectory:YES];
|
||||
NSURL *oldCloudStoreDirectoryURL = [cloudContainerURL URLByAppendingPathComponent:@"Database.nosync" isDirectory:YES];
|
||||
NSURL *oldCloudStoreURL = [[oldCloudStoreDirectoryURL URLByAppendingPathComponent:uuid isDirectory:NO]
|
||||
URLByAppendingPathExtension:@"sqlite"];
|
||||
inf(@"Migrating cloud store: %@ -> %@", uuid, [manager valueForKey:@"storeUUID"]);
|
||||
NSURL *newCloudStoreURL = [self.storeManager URLForCloudStore];
|
||||
NSURL *newCloudContentURL = [self.storeManager URLForCloudContent];
|
||||
|
||||
NSError *error = nil;
|
||||
NSDictionary *oldCloudStoreOptions = @{
|
||||
STORE_OPTIONS
|
||||
// This is here in an attempt to have iCloud recreate the old store file from
|
||||
// the baseline and transaction logs from the iCloud account.
|
||||
// In my tests however only the baseline was used to recreate the store which then ended up being empty.
|
||||
NSPersistentStoreUbiquitousContentNameKey : uuid,
|
||||
NSPersistentStoreUbiquitousContentNameKey : contentName,
|
||||
NSPersistentStoreUbiquitousContentURLKey : oldCloudContentURL,
|
||||
// So instead, we'll just open up the old store as read-only, if it exists.
|
||||
NSReadOnlyPersistentStoreOption : @YES,
|
||||
NSInferMappingModelAutomaticallyOption : @YES
|
||||
};
|
||||
NSDictionary *newCloudStoreOptions = @{
|
||||
STORE_OPTIONS
|
||||
NSPersistentStoreUbiquitousContentNameKey : [manager valueForKey:@"contentName"],
|
||||
NSPersistentStoreUbiquitousContentNameKey : [self.storeManager valueForKey:@"contentName"],
|
||||
NSPersistentStoreUbiquitousContentURLKey : newCloudContentURL,
|
||||
NSMigratePersistentStoresAutomaticallyOption : @YES,
|
||||
NSInferMappingModelAutomaticallyOption : @YES
|
||||
@@ -229,48 +293,32 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
|
||||
// Create the directory to hold the new cloud store.
|
||||
// This is only necessary if we want to try to rebuild the old store. See comment above about how that failed.
|
||||
if (![[NSFileManager defaultManager] createDirectoryAtPath:oldCloudStoreDirectoryURL.path
|
||||
withIntermediateDirectories:YES attributes:nil error:&error]) {
|
||||
err(@"While creating directory for old cloud store: %@", error);
|
||||
return;
|
||||
}
|
||||
if (![[NSFileManager defaultManager] createDirectoryAtPath:[manager URLForCloudStoreDirectory].path
|
||||
withIntermediateDirectories:YES attributes:nil error:&error]) {
|
||||
err(@"While creating directory for new cloud store: %@", error);
|
||||
return;
|
||||
}
|
||||
if (![[NSFileManager defaultManager] createDirectoryAtPath:[oldCloudStoreURL URLByDeletingLastPathComponent].path
|
||||
withIntermediateDirectories:YES attributes:nil error:&error])
|
||||
err(@"While creating directory for old cloud store: %@", error);
|
||||
if (![[NSFileManager defaultManager] createDirectoryAtPath:oldCloudContentURL.path
|
||||
withIntermediateDirectories:YES attributes:nil error:&error])
|
||||
err(@"While creating directory for old cloud content: %@", error);
|
||||
if (![[NSFileManager defaultManager] createDirectoryAtPath:[self.storeManager URLForCloudStoreDirectory].path
|
||||
withIntermediateDirectories:YES attributes:nil error:&error])
|
||||
err(@"While creating directory for new cloud store: %@", error);
|
||||
if (![[NSFileManager defaultManager] createDirectoryAtPath:[self.storeManager URLForCloudContent].path
|
||||
withIntermediateDirectories:YES attributes:nil error:&error])
|
||||
err(@"While creating directory for new cloud content: %@", error);
|
||||
|
||||
if (![manager copyMigrateStore:oldCloudStoreURL withOptions:oldCloudStoreOptions
|
||||
toStore:newCloudStoreURL withOptions:newCloudStoreOptions
|
||||
error:nil cause:nil context:nil])
|
||||
if (![self.storeManager copyMigrateStore:oldCloudStoreURL withOptions:oldCloudStoreOptions
|
||||
toStore:newCloudStoreURL withOptions:newCloudStoreOptions
|
||||
error:nil cause:nil context:nil])
|
||||
return;
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"LocalUUIDKey"];
|
||||
inf(@"Successfully migrated old to new cloud store.");
|
||||
}
|
||||
|
||||
- (void)saveContexts {
|
||||
|
||||
NSManagedObjectContext *mainManagedObjectContext = self.mainManagedObjectContext;
|
||||
[mainManagedObjectContext performBlockAndWait:^{
|
||||
NSError *error = nil;
|
||||
if (![mainManagedObjectContext save:&error])
|
||||
err(@"While saving main context: %@", error);
|
||||
}];
|
||||
|
||||
NSManagedObjectContext *privateManagedObjectContext = [self privateManagedObjectContextIfReady];
|
||||
[privateManagedObjectContext performBlockAndWait:^{
|
||||
NSError *error = nil;
|
||||
if (![privateManagedObjectContext save:&error])
|
||||
err(@"While saving private context: %@", error);
|
||||
}];
|
||||
inf(@"Successfully migrated to new cloud store.");
|
||||
}
|
||||
|
||||
#pragma mark - UbiquityStoreManagerDelegate
|
||||
|
||||
- (NSManagedObjectContext *)managedObjectContextForUbiquityStoreManager:(UbiquityStoreManager *)usm {
|
||||
- (NSManagedObjectContext *)managedObjectContextForUbiquityChangesInManager:(UbiquityStoreManager *)manager {
|
||||
|
||||
return [self privateManagedObjectContextIfReady];
|
||||
return [self mainManagedObjectContextIfReady];
|
||||
}
|
||||
|
||||
- (void)ubiquityStoreManager:(UbiquityStoreManager *)manager log:(NSString *)message {
|
||||
@@ -280,15 +328,13 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
|
||||
- (void)ubiquityStoreManager:(UbiquityStoreManager *)manager willLoadStoreIsCloud:(BOOL)isCloudStore {
|
||||
|
||||
self.privateManagedObjectContext = nil;
|
||||
self.mainManagedObjectContext = nil;
|
||||
NSManagedObjectContext *moc = [self mainManagedObjectContextIfReady];
|
||||
[moc performBlockAndWait:^{
|
||||
[moc saveToStore];
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
if (![self.storeLoading isVisible])
|
||||
self.storeLoading = [PearlOverlay showOverlayWithTitle:@"Opening Your Data"];
|
||||
} );
|
||||
#endif
|
||||
self.privateManagedObjectContext = nil;
|
||||
self.mainManagedObjectContext = nil;
|
||||
}];
|
||||
|
||||
[self migrateStoreForManager:manager isCloud:isCloudStore];
|
||||
}
|
||||
@@ -307,6 +353,20 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
[privateManagedObjectContext performBlockAndWait:^{
|
||||
privateManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
|
||||
privateManagedObjectContext.persistentStoreCoordinator = coordinator;
|
||||
|
||||
// dbg(@"===");
|
||||
// NSError *error;
|
||||
// for (NSEntityDescription *entityDescription in [coordinator.managedObjectModel entities]) {
|
||||
// dbg(@"Entities: %@", entityDescription.name);
|
||||
// NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:entityDescription.name];
|
||||
// NSArray *entities = [privateManagedObjectContext executeFetchRequest:request error:&error];
|
||||
// if (!entities)
|
||||
// err(@" - Error: %@", error);
|
||||
// else
|
||||
// for (id entity in entities)
|
||||
// dbg(@" - %@", [entity debugDescription]);
|
||||
// }
|
||||
// dbg(@"===");
|
||||
}];
|
||||
|
||||
NSManagedObjectContext *mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
|
||||
@@ -314,12 +374,6 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
|
||||
self.privateManagedObjectContext = privateManagedObjectContext;
|
||||
self.mainManagedObjectContext = mainManagedObjectContext;
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
[self.handleCloudContentAlert cancelAlertAnimated:YES];
|
||||
[self.fixCloudContentAlert cancelAlertAnimated:YES];
|
||||
[self.storeLoading cancelOverlay];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)ubiquityStoreManager:(UbiquityStoreManager *)manager didEncounterError:(NSError *)error cause:(UbiquityStoreErrorCause)cause
|
||||
@@ -333,48 +387,45 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
} );
|
||||
}
|
||||
|
||||
- (BOOL)ubiquityStoreManager:(UbiquityStoreManager *)manager handleCloudContentCorruptionWithHealthyStore:(BOOL)storeHealthy {
|
||||
#pragma mark - Utilities
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
if (manager.cloudEnabled && !storeHealthy && !([self.handleCloudContentAlert.alertView isVisible] || [self.fixCloudContentAlert.alertView isVisible]))
|
||||
- (void)addElementNamed:(NSString *)siteName completion:(void (^)(MPElementEntity *element))completion {
|
||||
|
||||
if (![siteName length]) {
|
||||
completion( nil );
|
||||
return;
|
||||
}
|
||||
|
||||
[MPAppDelegate_Shared managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *activeUser = [self activeUserInContext:moc];
|
||||
assert(activeUser);
|
||||
|
||||
MPElementType type = activeUser.defaultType;
|
||||
if (!type)
|
||||
type = activeUser.defaultType = MPElementTypeGeneratedLong;
|
||||
NSString *typeEntityClassName = [MPAlgorithmDefault classNameOfType:type];
|
||||
|
||||
MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:typeEntityClassName
|
||||
inManagedObjectContext:moc];
|
||||
|
||||
element.name = siteName;
|
||||
element.user = activeUser;
|
||||
element.type = type;
|
||||
element.lastUsed = [NSDate date];
|
||||
element.version = MPAlgorithmDefaultVersion;
|
||||
[moc saveToStore];
|
||||
|
||||
NSError *error = nil;
|
||||
if (element.objectID.isTemporaryID && ![moc obtainPermanentIDsForObjects:@[ element ] error:&error])
|
||||
err(@"Failed to obtain a permanent object ID after creating new element: %@", error);
|
||||
|
||||
NSManagedObjectID *elementOID = [element objectID];
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[self showCloudContentAlert];
|
||||
completion( (MPElementEntity *)[[MPAppDelegate_Shared managedObjectContextForThreadIfReady] objectRegisteredForID:elementOID] );
|
||||
} );
|
||||
#endif
|
||||
|
||||
return NO;
|
||||
}];
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
- (void)showCloudContentAlert {
|
||||
|
||||
__weak MPAppDelegate_Shared *wSelf = self;
|
||||
[self.handleCloudContentAlert cancelAlertAnimated:NO];
|
||||
self.handleCloudContentAlert = [PearlAlert showActivityWithTitle:@"iCloud Sync Problem" message:
|
||||
@"Waiting for your other device to auto‑correct the problem..."
|
||||
initAlert:^(UIAlertView *alert) {
|
||||
[alert addButtonWithTitle:@"Fix Now"];
|
||||
}];
|
||||
|
||||
self.handleCloudContentAlert.tappedButtonBlock = ^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
wSelf.fixCloudContentAlert = [PearlAlert showAlertWithTitle:@"Fix iCloud Now" message:
|
||||
@"This problem can usually be auto‑corrected by opening the app on another device where you recently made changes.\n"
|
||||
@"You can correct the problem from this device anyway, but recent changes made on another device might get lost."
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:
|
||||
^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
if (buttonIndex_ == alert_.cancelButtonIndex)
|
||||
[wSelf showCloudContentAlert];
|
||||
if (buttonIndex_ == [alert_ firstOtherButtonIndex])
|
||||
[wSelf.storeManager rebuildCloudContentFromCloudStoreOrLocalStore:YES];
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonBack otherTitles:@"Fix Anyway", nil];
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#pragma mark - Import / Export
|
||||
|
||||
- (MPImportResult)importSites:(NSString *)importedSitesString
|
||||
askImportPassword:(NSString *(^)(NSString *userName))importPassword
|
||||
askUserPassword:(NSString *(^)(NSString *userName, NSUInteger importCount, NSUInteger deleteCount))userPassword {
|
||||
@@ -493,6 +544,8 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
NSString *uses = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:2]];
|
||||
NSString *type = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:3]];
|
||||
NSString *version = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:4]];
|
||||
if ([version length])
|
||||
version = [version substringFromIndex:1]; // Strip the leading colon.
|
||||
NSString *name = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:5]];
|
||||
NSString *exportContent = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:6]];
|
||||
|
||||
@@ -509,6 +562,8 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
|
||||
[elementsToDelete addObjectsFromArray:existingSites];
|
||||
[importedSiteElements addObject:@[ lastUsed, uses, type, version, name, exportContent ]];
|
||||
dbg(@"Will import site: lastUsed=%@, uses=%@, type=%@, version=%@, name=%@, exportContent=%@",
|
||||
lastUsed, uses, type, version, name, exportContent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,11 +13,12 @@
|
||||
|
||||
- (BOOL)saveToStore {
|
||||
|
||||
NSError *error;
|
||||
if (![self save:&error]) {
|
||||
err(@"While saving: %@", error);
|
||||
return NO;
|
||||
}
|
||||
__block BOOL success = NO;
|
||||
[self performBlockAndWait:^{
|
||||
NSError *error = nil;
|
||||
if (!(success = [self save:&error]))
|
||||
err(@"While saving: %@", error);
|
||||
}];
|
||||
|
||||
return !self.parentContext || [self.parentContext saveToStore];
|
||||
}
|
||||
|
||||
@@ -68,6 +68,8 @@ typedef enum {
|
||||
#define MPCheckpointApps @"MPCheckpointApps"
|
||||
#define MPCheckpointApp @"MPCheckpointApp"
|
||||
#define MPCheckpointEmergencyGenerator @"MPCheckpointEmergencyGenerator"
|
||||
#define MPCheckpointLogs @"MPCheckpointLogs"
|
||||
#define MPCheckpointStarted @"MPCheckpointStarted"
|
||||
|
||||
#define MPSignedInNotification @"MPSignedInNotification"
|
||||
#define MPSignedOutNotification @"MPSignedOutNotification"
|
||||
@@ -77,7 +79,11 @@ typedef enum {
|
||||
|
||||
static void MPCheckpoint(NSString *checkpoint, NSDictionary *attributes) {
|
||||
|
||||
inf(@"%@: %@", checkpoint, attributes);
|
||||
#ifdef LOCALYTICS
|
||||
[[LocalyticsSession sharedLocalyticsSession] tagEvent:checkpoint attributes:attributes];
|
||||
#endif
|
||||
#ifdef TESTFLIGHT_SDK_VERSION
|
||||
[TestFlight passCheckpoint:checkpoint];
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -25,9 +25,10 @@
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *dialogStyleRegular;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *dialogStyleHUD;
|
||||
|
||||
- (IBAction)activate:(id)sender;
|
||||
- (IBAction)showPasswordWindow;
|
||||
- (IBAction)togglePreference:(NSMenuItem *)sender;
|
||||
- (IBAction)newUser:(NSMenuItem *)sender;
|
||||
- (IBAction)lock:(id)sender;
|
||||
- (IBAction)rebuildCloud:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
@@ -11,12 +11,6 @@
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import <Carbon/Carbon.h>
|
||||
|
||||
@interface MPMacAppDelegate()
|
||||
|
||||
@property(nonatomic) BOOL wasRunning;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPMacAppDelegate
|
||||
|
||||
#pragma clang diagnostic push
|
||||
@@ -46,7 +40,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
// Check which hotkey this was.
|
||||
if (hotKeyID.signature == MPShowHotKey.signature && hotKeyID.id == MPShowHotKey.id) {
|
||||
[((__bridge MPMacAppDelegate *)userData) activate:nil];
|
||||
[((__bridge MPMacAppDelegate *)userData) showPasswordWindow];
|
||||
return noErr;
|
||||
}
|
||||
if (hotKeyID.signature == MPLockHotKey.signature && hotKeyID.id == MPLockHotKey.id) {
|
||||
@@ -92,19 +86,24 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
@"Then give iCloud some time to sync the new user to your Mac.";
|
||||
}
|
||||
|
||||
MPUserEntity *activeUser = self.activeUserForThread;
|
||||
for (MPUserEntity *user in users) {
|
||||
NSMenuItem *userItem = [[NSMenuItem alloc] initWithTitle:user.name action:@selector(selectUser:) keyEquivalent:@""];
|
||||
[userItem setTarget:self];
|
||||
[userItem setRepresentedObject:[user objectID]];
|
||||
[[self.usersItem submenu] addItem:userItem];
|
||||
|
||||
if ([user.name isEqualToString:[MPMacConfig get].usedUserName])
|
||||
if (!activeUser && [user.name isEqualToString:[MPMacConfig get].usedUserName])
|
||||
[self selectUser:userItem];
|
||||
}
|
||||
|
||||
[self updateMenuItems];
|
||||
}
|
||||
|
||||
- (void)selectUser:(NSMenuItem *)item {
|
||||
|
||||
[self signOutAnimated:NO];
|
||||
|
||||
NSError *error = nil;
|
||||
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
||||
self.activeUser = (MPUserEntity *)[moc existingObjectWithID:[item representedObject] error:&error];
|
||||
@@ -120,18 +119,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
[self.statusItem popUpStatusItemMenu:self.statusMenu];
|
||||
}
|
||||
|
||||
- (IBAction)activate:(id)sender {
|
||||
|
||||
if (![self activeUserForThread])
|
||||
// No user, can't activate.
|
||||
return;
|
||||
|
||||
if ([[NSApplication sharedApplication] isActive])
|
||||
[self applicationDidBecomeActive:nil];
|
||||
else
|
||||
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
|
||||
}
|
||||
|
||||
- (IBAction)togglePreference:(NSMenuItem *)sender {
|
||||
|
||||
if (sender == self.useICloudItem)
|
||||
@@ -139,12 +126,13 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
if (sender == self.rememberPasswordItem)
|
||||
[MPConfig get].rememberLogin = [NSNumber numberWithBool:![[MPConfig get].rememberLogin boolValue]];
|
||||
if (sender == self.savePasswordItem) {
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserForThread];
|
||||
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc];
|
||||
if ((activeUser.saveKey = !activeUser.saveKey))
|
||||
[[MPMacAppDelegate get] storeSavedKeyFor:activeUser];
|
||||
else
|
||||
[[MPMacAppDelegate get] forgetSavedKeyFor:activeUser];
|
||||
[activeUser.managedObjectContext saveToStore];
|
||||
[moc saveToStore];
|
||||
}
|
||||
if (sender == self.dialogStyleRegular)
|
||||
[MPMacConfig get].dialogStyleHUD = @NO;
|
||||
@@ -153,6 +141,35 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
}
|
||||
|
||||
- (IBAction)newUser:(NSMenuItem *)sender {
|
||||
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"New User"
|
||||
defaultButton:@"Create User" alternateButton:nil otherButton:@"Cancel"
|
||||
informativeTextWithFormat:@"To begin, enter your full name.\n\n"
|
||||
@"IMPORTANT: Enter your name correctly, including the right capitalization, "
|
||||
@"as you would on an official document."];
|
||||
NSTextField *nameField = [[NSTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||
[alert setAccessoryView:nameField];
|
||||
[alert layout];
|
||||
[nameField becomeFirstResponder];
|
||||
if ([alert runModal] != NSAlertDefaultReturn)
|
||||
return;
|
||||
|
||||
NSString *name = [(NSSecureTextField *)alert.accessoryView stringValue];
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *newUser = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass( [MPUserEntity class] )
|
||||
inManagedObjectContext:moc];
|
||||
newUser.name = name;
|
||||
[moc saveToStore];
|
||||
NSError *error = nil;
|
||||
if (![moc obtainPermanentIDsForObjects:@[ newUser ] error:&error])
|
||||
err(@"Failed to obtain permanent object ID for new user: %@", error);
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
[self updateUsers];
|
||||
[self setActiveUser:newUser];
|
||||
[self showPasswordWindow];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)lock:(id)sender {
|
||||
@@ -160,6 +177,16 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
self.key = nil;
|
||||
}
|
||||
|
||||
- (IBAction)rebuildCloud:(id)sender {
|
||||
|
||||
if ([[NSAlert alertWithMessageText:@"iCloud Truth Sync" defaultButton:@"Continue"
|
||||
alternateButton:nil otherButton:@"Cancel"
|
||||
informativeTextWithFormat:@"This action will force all your iCloud enabled devices to revert to this device's version of the truth."
|
||||
@"\n\nThis is only necessary if you notice that your devices aren't syncing properly anymore. "
|
||||
"Any data on other devices not available from here will be lost."] runModal] == NSAlertDefaultReturn)
|
||||
[self.storeManager rebuildCloudContentFromCloudStoreOrLocalStore:NO];
|
||||
}
|
||||
|
||||
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)oldValue {
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
@@ -188,12 +215,12 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
self.statusItem.target = self;
|
||||
self.statusItem.action = @selector(showMenu);
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UbiquityManagedStoreDidChangeNotification object:nil queue:nil usingBlock:
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidChangeNotification object:nil queue:nil usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:UbiquityManagedStoreDidImportChangesNotification object:nil queue:nil usingBlock:
|
||||
addObserverForName:USMStoreDidImportChangesNotification object:nil queue:nil usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
@@ -315,20 +342,24 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
- (void)applicationDidBecomeActive:(NSNotification *)notification {
|
||||
|
||||
[self showPasswordWindow];
|
||||
// [self showPasswordWindow];
|
||||
}
|
||||
|
||||
- (void)showPasswordWindow {
|
||||
- (IBAction)showPasswordWindow {
|
||||
|
||||
// If no user, can't activate.
|
||||
if (![self activeUserForThread])
|
||||
return;
|
||||
|
||||
// Activate the app if not active.
|
||||
if (![[NSApplication sharedApplication] isActive])
|
||||
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
|
||||
|
||||
// Don't show window if we weren't already running (ie. if we haven't been activated before).
|
||||
if (!self.wasRunning)
|
||||
self.wasRunning = YES;
|
||||
else {
|
||||
if (!self.passwordWindow)
|
||||
self.passwordWindow = [[MPPasswordWindowController alloc] initWithWindowNibName:@"MPPasswordWindowController"];
|
||||
if (!self.passwordWindow)
|
||||
self.passwordWindow = [[MPPasswordWindowController alloc] initWithWindowNibName:@"MPPasswordWindowController"];
|
||||
|
||||
[self.passwordWindow showWindow:self];
|
||||
}
|
||||
[self.passwordWindow showWindow:self];
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(NSNotification *)notification {
|
||||
|
||||
@@ -13,12 +13,14 @@
|
||||
|
||||
#define MPAlertUnlockMP @"MPAlertUnlockMP"
|
||||
#define MPAlertIncorrectMP @"MPAlertIncorrectMP"
|
||||
#define MPAlertCreateSite @"MPAlertCreateSite"
|
||||
|
||||
@interface MPPasswordWindowController()
|
||||
|
||||
@property(nonatomic) BOOL inProgress;
|
||||
@property(nonatomic) BOOL siteFieldPreventCompletion;
|
||||
|
||||
@property(nonatomic, strong) NSOperationQueue *backgroundQueue;
|
||||
@end
|
||||
|
||||
@implementation MPPasswordWindowController {
|
||||
@@ -32,6 +34,9 @@
|
||||
else
|
||||
self.window.styleMask = NSTexturedBackgroundWindowMask | NSResizableWindowMask | NSTitledWindowMask | NSClosableWindowMask;
|
||||
|
||||
self.backgroundQueue = [NSOperationQueue new];
|
||||
self.backgroundQueue.maxConcurrentOperationCount = 1;
|
||||
|
||||
[self setContent:@""];
|
||||
[self.tipField setStringValue:@""];
|
||||
|
||||
@@ -48,6 +53,8 @@
|
||||
// } forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:NSWindowDidBecomeKeyNotification object:self.window queue:nil usingBlock:^(NSNotification *note) {
|
||||
if (![MPMacAppDelegate managedObjectContextForThreadIfReady])
|
||||
[self waitUntilStoreLoaded];
|
||||
if (!self.inProgress)
|
||||
[self unlock];
|
||||
[self.siteField selectText:self];
|
||||
@@ -58,28 +65,37 @@
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:MPSignedOutNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
|
||||
_activeElementOID = nil;
|
||||
[self.window close];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:USMStoreDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
|
||||
[self waitUntilStoreLoaded];
|
||||
}];
|
||||
|
||||
[super windowDidLoad];
|
||||
}
|
||||
|
||||
- (void)waitUntilStoreLoaded {
|
||||
}
|
||||
|
||||
- (void)unlock {
|
||||
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserForThread];
|
||||
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc];
|
||||
if (!activeUser)
|
||||
// No user to sign in with.
|
||||
return;
|
||||
if ([MPMacAppDelegate get].key)
|
||||
// Already logged in.
|
||||
return;
|
||||
if ([[MPMacAppDelegate get] signInAsUser:activeUser usingMasterPassword:nil])
|
||||
if ([[MPMacAppDelegate get] signInAsUser:activeUser saveInContext:moc usingMasterPassword:nil])
|
||||
// Load the key from the keychain.
|
||||
return;
|
||||
|
||||
if (![MPMacAppDelegate get].key)
|
||||
// Ask the user to set the key through his master password.
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
if ([MPMacAppDelegate get].key)
|
||||
return;
|
||||
|
||||
@@ -97,7 +113,7 @@
|
||||
[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 {
|
||||
@@ -107,11 +123,11 @@
|
||||
return;
|
||||
}
|
||||
if (contextInfo == MPAlertUnlockMP) {
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserForThread];
|
||||
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc];
|
||||
switch (returnCode) {
|
||||
case NSAlertAlternateReturn:
|
||||
case NSAlertAlternateReturn: {
|
||||
// "Change" button.
|
||||
{
|
||||
NSInteger returnCode_ = [[NSAlert
|
||||
alertWithMessageText:@"Changing Master Password" defaultButton:nil
|
||||
alternateButton:[PearlStrings get].commonButtonCancel otherButton:nil informativeTextWithFormat:
|
||||
@@ -126,39 +142,48 @@
|
||||
activeUser.keyID = nil;
|
||||
[[MPMacAppDelegate get] forgetSavedKeyFor:activeUser];
|
||||
[[MPMacAppDelegate get] signOutAnimated:YES];
|
||||
[moc saveToStore];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NSAlertOtherReturn:
|
||||
case NSAlertOtherReturn: {
|
||||
// "Cancel" button.
|
||||
[self.window close];
|
||||
return;
|
||||
}
|
||||
|
||||
case NSAlertDefaultReturn: {
|
||||
// "Unlock" button.
|
||||
self.contentContainer.alphaValue = 0;
|
||||
[self.progressView startAnimation:nil];
|
||||
self.inProgress = YES;
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0 ), ^{
|
||||
BOOL success = [[MPMacAppDelegate get] signInAsUser:activeUser
|
||||
usingMasterPassword:[(NSSecureTextField *)alert.accessoryView stringValue]];
|
||||
|
||||
NSString *password = [(NSSecureTextField *)alert.accessoryView stringValue];
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc_) {
|
||||
NSError *error = nil;
|
||||
MPUserEntity *activeUser_ = (MPUserEntity *)[moc_ existingObjectWithID:activeUser.objectID error:&error];
|
||||
if (!activeUser_)
|
||||
err(@"Failed to retrieve active use while logging in: %@", error);
|
||||
|
||||
BOOL success = [[MPMacAppDelegate get] signInAsUser:activeUser saveInContext:moc_
|
||||
usingMasterPassword:password];
|
||||
self.inProgress = NO;
|
||||
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
[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 %@",
|
||||
activeUser.name )
|
||||
NSLocalizedDescriptionKey : PearlString( @"Incorrect master password for user %@", activeUser.name )
|
||||
}]] beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertIncorrectMP];
|
||||
}
|
||||
} );
|
||||
} );
|
||||
}];
|
||||
}];
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -167,12 +192,27 @@
|
||||
|
||||
return;
|
||||
}
|
||||
if (contextInfo == MPAlertCreateSite) {
|
||||
switch (returnCode) {
|
||||
case NSAlertDefaultReturn: {
|
||||
[[MPMacAppDelegate get] addElementNamed:[self.siteField stringValue] completion:^(MPElementEntity *element) {
|
||||
if (element) {
|
||||
_activeElementOID = element.objectID;
|
||||
[self trySiteWithAction:NO];
|
||||
}
|
||||
}];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *)control:(NSControl *)control textView:(NSTextView *)textView completions:(NSArray *)words
|
||||
forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(NSInteger *)index {
|
||||
|
||||
NSString *query = [[control stringValue] substringWithRange:charRange];
|
||||
NSString *query = [[textView string] substringWithRange:charRange];
|
||||
if (![query length] || ![MPMacAppDelegate get].key)
|
||||
return nil;
|
||||
|
||||
@@ -185,20 +225,22 @@
|
||||
|
||||
NSError *error = nil;
|
||||
NSArray *siteResults = [context executeFetchRequest:fetchRequest error:&error];
|
||||
if (error)
|
||||
if (!siteResults)
|
||||
err(@"While fetching elements for completion: %@", error);
|
||||
|
||||
if (siteResults) {
|
||||
else if ([siteResults count]) {
|
||||
_activeElementOID = ((NSManagedObject *)[siteResults objectAtIndex:0]).objectID;
|
||||
for (MPElementEntity *element in siteResults)
|
||||
[mutableResults addObject:element.name];
|
||||
//[mutableResults addObject:query]; // For when the app should be able to create new sites.
|
||||
}
|
||||
else
|
||||
_activeElementOID = nil;
|
||||
}];
|
||||
|
||||
if ([mutableResults count] == 1) {
|
||||
if ([mutableResults count] < 2) {
|
||||
//[textView setString:[(MPElementEntity *)[siteResults objectAtIndex:0] name]];
|
||||
//[textView setSelectedRange:NSMakeRange( [query length], [[textView string] length] - [query length] )];
|
||||
[self trySiteAndCopyContent:NO];
|
||||
[self trySiteWithAction:NO];
|
||||
}
|
||||
|
||||
return mutableResults;
|
||||
@@ -206,29 +248,29 @@
|
||||
|
||||
- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector {
|
||||
|
||||
if (commandSelector == @selector(cancel:)) {
|
||||
if (commandSelector == @selector(cancel:)) { // Escape without completion.
|
||||
[self.window close];
|
||||
return YES;
|
||||
}
|
||||
if ((self.siteFieldPreventCompletion = [NSStringFromSelector( commandSelector ) hasPrefix:@"delete"]))
|
||||
if ((self.siteFieldPreventCompletion = [NSStringFromSelector( commandSelector ) hasPrefix:@"delete"])) { // Backspace any time.
|
||||
_activeElementOID = nil;
|
||||
[self trySiteWithAction:NO];
|
||||
return NO;
|
||||
if (commandSelector == @selector(insertNewline:)) {
|
||||
[self trySiteAndCopyContent:YES];
|
||||
}
|
||||
if (commandSelector == @selector(insertNewline:)) { // Return without completion.
|
||||
[self trySiteWithAction:YES];
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)copyContents {
|
||||
}
|
||||
|
||||
- (void)controlTextDidEndEditing:(NSNotification *)note {
|
||||
|
||||
if (note.object != self.siteField)
|
||||
return;
|
||||
|
||||
[self trySiteAndCopyContent:NO];
|
||||
[self trySiteWithAction:NO];
|
||||
}
|
||||
|
||||
- (void)controlTextDidChange:(NSNotification *)note {
|
||||
@@ -237,12 +279,18 @@
|
||||
return;
|
||||
|
||||
// Update the site content as the site name changes.
|
||||
BOOL enterPressed = [[NSApp currentEvent] type] == NSKeyDown &&
|
||||
[[[NSApp currentEvent] charactersIgnoringModifiers] isEqualToString:@"\r"];
|
||||
[self trySiteAndCopyContent:enterPressed];
|
||||
|
||||
if (enterPressed)
|
||||
if ([[NSApp currentEvent] type] == NSKeyDown &&
|
||||
[[[NSApp currentEvent] charactersIgnoringModifiers] isEqualToString:@"\r"]) { // Return while completing.
|
||||
[self trySiteWithAction:YES];
|
||||
return;
|
||||
}
|
||||
|
||||
if ([[NSApp currentEvent] type] == NSKeyDown &&
|
||||
[[[NSApp currentEvent] charactersIgnoringModifiers] characterAtIndex:0] == 0x1b) { // Escape while completing.
|
||||
_activeElementOID = nil;
|
||||
[self trySiteWithAction:NO];
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.siteFieldPreventCompletion) {
|
||||
self.siteFieldPreventCompletion = NO;
|
||||
@@ -256,11 +304,12 @@
|
||||
|
||||
- (MPElementEntity *)activeElementForThread {
|
||||
|
||||
if (!_activeElementOID)
|
||||
return nil;
|
||||
return [self activeElementInContext:[MPMacAppDelegate managedObjectContextForThreadIfReady]];
|
||||
}
|
||||
|
||||
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
||||
if (!moc)
|
||||
- (MPElementEntity *)activeElementInContext:(NSManagedObjectContext *)moc {
|
||||
|
||||
if (!_activeElementOID)
|
||||
return nil;
|
||||
|
||||
NSError *error;
|
||||
@@ -281,66 +330,75 @@
|
||||
}]];
|
||||
}
|
||||
|
||||
- (void)trySiteAndCopyContent:(BOOL)copyContent {
|
||||
- (void)trySiteWithAction:(BOOL)doAction {
|
||||
|
||||
[self setContent:@""];
|
||||
[self.tipField setStringValue:@"Generating..."];
|
||||
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{
|
||||
NSString *siteName = [self.siteField stringValue];
|
||||
[self.backgroundQueue addOperationWithBlock:^{
|
||||
NSString *content = [[self activeElementForThread].content description];
|
||||
if (!content)
|
||||
content = @"";
|
||||
if (copyContent) {
|
||||
[[NSPasteboard generalPasteboard] declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
|
||||
if (![[NSPasteboard generalPasteboard] setString:content forType:NSPasteboardTypeString]) {
|
||||
wrn(@"Couldn't copy password to pasteboard.");
|
||||
|
||||
dbg(@"name: %@, action: %d", siteName, doAction);
|
||||
if (doAction) {
|
||||
if ([content length]) {
|
||||
// Performing action while content is available. Copy it.
|
||||
[self copyContent:content];
|
||||
}
|
||||
else if ([siteName length]) {
|
||||
// Performing action without content but a site name is written.
|
||||
[self createNewSite:siteName];
|
||||
return;
|
||||
}
|
||||
|
||||
MPElementEntity *activeElement = [self activeElementForThread];
|
||||
[activeElement use];
|
||||
[activeElement.managedObjectContext saveToStore];
|
||||
}
|
||||
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
[self setContent:content];
|
||||
|
||||
self.tipField.alphaValue = 1;
|
||||
if (!copyContent)
|
||||
if ([content length] == 0) {
|
||||
if ([siteName length])
|
||||
[self.tipField setStringValue:@"Hit ⌤ (ENTER) to create a new site."];
|
||||
else
|
||||
[self.tipField setStringValue:@""];
|
||||
}
|
||||
else if (!doAction)
|
||||
[self.tipField setStringValue:@"Hit ⌤ (ENTER) to copy the password."];
|
||||
else {
|
||||
[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_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC) ), dispatch_get_main_queue(), ^{
|
||||
[NSAnimationContext beginGrouping];
|
||||
[[NSAnimationContext currentContext] setDuration:0.2f];
|
||||
[self.tipField.animator setAlphaValue:0];
|
||||
[NSAnimationContext endGrouping];
|
||||
} );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
// For when the app should be able to create new sites.
|
||||
/*
|
||||
else
|
||||
[[MPMacAppDelegate get].managedObjectContext performBlock:^{
|
||||
MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MPElementGeneratedEntity class])
|
||||
inManagedObjectContext:[MPMacAppDelegate get].managedObjectContext];
|
||||
assert([element isKindOfClass:ClassFromMPElementType(element.type)]);
|
||||
assert([MPMacAppDelegate get].keyID);
|
||||
- (void)copyContent:(NSString *)content {
|
||||
|
||||
element.name = siteName;
|
||||
element.keyID = [MPMacAppDelegate get].keyID;
|
||||
[[NSPasteboard generalPasteboard] declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
|
||||
if (![[NSPasteboard generalPasteboard] setString:content forType:NSPasteboardTypeString]) {
|
||||
wrn(@"Couldn't copy password to pasteboard.");
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *description = [element.content description];
|
||||
[element use];
|
||||
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
||||
MPElementEntity *activeElement = [self activeElementInContext:moc];
|
||||
[activeElement use];
|
||||
[moc saveToStore];
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self setContent:description];
|
||||
});
|
||||
}];
|
||||
*/
|
||||
- (void)createNewSite:(NSString *)siteName {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"Create site?"
|
||||
defaultButton:@"Create" alternateButton:nil otherButton:@"Cancel"
|
||||
informativeTextWithFormat:@"Do you want to create a new site named:\n\n%@", siteName];
|
||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertCreateSite];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -63,6 +63,14 @@
|
||||
<reference key="NSSuperview" ref="1072816887"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="402376051"/>
|
||||
<object class="NSShadow" key="NSViewShadow">
|
||||
<double key="NSShadowVert">1</double>
|
||||
<double key="NSShadowBlurRadius">1</double>
|
||||
<object class="NSColor" key="NSShadowColor" id="546806116">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MCAwLjYAA</bytes>
|
||||
</object>
|
||||
</object>
|
||||
<string key="NSReuseIdentifierKey">_NS:1535</string>
|
||||
<bool key="NSEnabled">YES</bool>
|
||||
<object class="NSTextFieldCell" key="NSCell" id="406294418">
|
||||
@@ -99,6 +107,14 @@
|
||||
<reference key="NSSuperview" ref="1072816887"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="104294954"/>
|
||||
<object class="NSShadow" key="NSViewShadow">
|
||||
<double key="NSShadowVert">1</double>
|
||||
<double key="NSShadowBlurRadius">1</double>
|
||||
<object class="NSColor" key="NSShadowColor" id="227321360">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MCAwLjYAA</bytes>
|
||||
</object>
|
||||
</object>
|
||||
<string key="NSReuseIdentifierKey">_NS:1505</string>
|
||||
<bool key="NSEnabled">YES</bool>
|
||||
<object class="NSTextFieldCell" key="NSCell" id="249851874">
|
||||
@@ -173,7 +189,6 @@
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="49669222"/>
|
||||
<object class="NSShadow" key="NSViewShadow">
|
||||
<double key="NSShadowHoriz">1</double>
|
||||
<double key="NSShadowVert">1</double>
|
||||
<double key="NSShadowBlurRadius">1</double>
|
||||
<object class="NSColor" key="NSShadowColor" id="444840817">
|
||||
@@ -181,6 +196,17 @@
|
||||
<bytes key="NSWhite">MCAwLjYAA</bytes>
|
||||
</object>
|
||||
</object>
|
||||
<array key="NSViewContentFilters">
|
||||
<object class="CIGaussianBlur">
|
||||
<real value="0.40000000000000002" key="CI_inputRadius"/>
|
||||
<bool key="CIEnabled">YES</bool>
|
||||
</object>
|
||||
<object class="CIBloom">
|
||||
<real value="10" key="CI_inputRadius"/>
|
||||
<real value="0.5" key="CI_inputIntensity"/>
|
||||
<bool key="CIEnabled">YES</bool>
|
||||
</object>
|
||||
</array>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<string key="NSAntiCompressionPriority">{250, 750}</string>
|
||||
<bool key="NSEnabled">YES</bool>
|
||||
@@ -218,6 +244,7 @@
|
||||
<string key="NSFrame">{{224, 84}, {32, 32}}</string>
|
||||
<reference key="NSSuperview" ref="258451033"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:945</string>
|
||||
<int key="NSpiFlags">28682</int>
|
||||
<double key="NSMaxValue">100</double>
|
||||
@@ -833,7 +860,7 @@
|
||||
<real value="1" key="181.IBViewIntegration.shadowBlurRadius"/>
|
||||
<reference key="181.IBViewIntegration.shadowColor" ref="444840817"/>
|
||||
<real value="1" key="181.IBViewIntegration.shadowOffsetHeight"/>
|
||||
<real value="1" key="181.IBViewIntegration.shadowOffsetWidth"/>
|
||||
<real value="0.0" key="181.IBViewIntegration.shadowOffsetWidth"/>
|
||||
<array class="NSMutableArray" key="182.IBNSViewMetadataConstraints">
|
||||
<reference ref="102475933"/>
|
||||
</array>
|
||||
@@ -845,6 +872,10 @@
|
||||
<real value="0.0" key="182.IBViewIntegration.shadowOffsetWidth"/>
|
||||
<boolean value="NO" key="183.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
|
||||
<string key="183.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<real value="1" key="183.IBViewIntegration.shadowBlurRadius"/>
|
||||
<reference key="183.IBViewIntegration.shadowColor" ref="227321360"/>
|
||||
<real value="1" key="183.IBViewIntegration.shadowOffsetHeight"/>
|
||||
<real value="0.0" key="183.IBViewIntegration.shadowOffsetWidth"/>
|
||||
<string key="184.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="185.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="186.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
@@ -859,6 +890,10 @@
|
||||
<string key="210.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<boolean value="NO" key="216.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
|
||||
<string key="216.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<real value="1" key="216.IBViewIntegration.shadowBlurRadius"/>
|
||||
<reference key="216.IBViewIntegration.shadowColor" ref="546806116"/>
|
||||
<real value="1" key="216.IBViewIntegration.shadowOffsetHeight"/>
|
||||
<real value="0.0" key="216.IBViewIntegration.shadowOffsetWidth"/>
|
||||
<string key="217.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="218.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="219.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>MasterPassword</string>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
DA3EF17B15A47744003ABF4E /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3EF17A15A47744003ABF4E /* SenTestingKit.framework */; };
|
||||
DA3EF17D15A47744003ABF4E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
|
||||
DA4425CC1557BED40052177D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
|
||||
DA4C45F4173B57B700745CC5 /* NSURL+UbiquityStoreManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DA4C45F2173B57B700745CC5 /* NSURL+UbiquityStoreManager.h */; };
|
||||
DA4C45F5173B57B700745CC5 /* NSURL+UbiquityStoreManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4C45F3173B57B700745CC5 /* NSURL+UbiquityStoreManager.m */; };
|
||||
DA4DA1D91564471A00F6F596 /* libjrswizzle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC6326C148680650075AEA5 /* libjrswizzle.a */; };
|
||||
DA5E5C8817248AA1003798D8 /* crypto_aesctr.h in Headers */ = {isa = PBXBuildFile; fileRef = DA5E5C7B17248AA1003798D8 /* crypto_aesctr.h */; };
|
||||
DA5E5C8917248AA1003798D8 /* crypto_scrypt.h in Headers */ = {isa = PBXBuildFile; fileRef = DA5E5C7C17248AA1003798D8 /* crypto_scrypt.h */; };
|
||||
@@ -201,7 +203,9 @@
|
||||
DA3EF17915A47744003ABF4E /* Tests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.octest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA3EF17A15A47744003ABF4E /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
DA4425CB1557BED40052177D /* libUbiquityStoreManager.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libUbiquityStoreManager.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA5BFA44147E415C00F98B1E /* MasterPassword-Mac.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "MasterPassword-Mac.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA4C45F2173B57B700745CC5 /* NSURL+UbiquityStoreManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+UbiquityStoreManager.h"; sourceTree = "<group>"; };
|
||||
DA4C45F3173B57B700745CC5 /* NSURL+UbiquityStoreManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+UbiquityStoreManager.m"; sourceTree = "<group>"; };
|
||||
DA5BFA44147E415C00F98B1E /* MasterPassword.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MasterPassword.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA5BFA4A147E415C00F98B1E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
||||
DA5BFA4E147E415C00F98B1E /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
|
||||
@@ -440,7 +444,7 @@
|
||||
DA5BFA45147E415C00F98B1E /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA5BFA44147E415C00F98B1E /* MasterPassword-Mac.app */,
|
||||
DA5BFA44147E415C00F98B1E /* MasterPassword.app */,
|
||||
DAC77CAD148291A600BCF976 /* libPearl.a */,
|
||||
DAC6326C148680650075AEA5 /* libjrswizzle.a */,
|
||||
DA4425CB1557BED40052177D /* libUbiquityStoreManager.a */,
|
||||
@@ -577,6 +581,8 @@
|
||||
DACA22B61705DE7D002C6C22 /* UbiquityStoreManager */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA4C45F2173B57B700745CC5 /* NSURL+UbiquityStoreManager.h */,
|
||||
DA4C45F3173B57B700745CC5 /* NSURL+UbiquityStoreManager.m */,
|
||||
DACA22BA1705DE7D002C6C22 /* UbiquityStoreManager.h */,
|
||||
DACA22B71705DE7D002C6C22 /* UbiquityStoreManager.m */,
|
||||
DACA22B81705DE7D002C6C22 /* NSError+UbiquityStoreManager.h */,
|
||||
@@ -800,6 +806,7 @@
|
||||
files = (
|
||||
DACA22BC1705DE7D002C6C22 /* NSError+UbiquityStoreManager.h in Headers */,
|
||||
DACA22BE1705DE7D002C6C22 /* UbiquityStoreManager.h in Headers */,
|
||||
DA4C45F4173B57B700745CC5 /* NSURL+UbiquityStoreManager.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -893,9 +900,9 @@
|
||||
productReference = DA4425CB1557BED40052177D /* libUbiquityStoreManager.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
DA5BFA43147E415C00F98B1E /* MasterPassword-Mac */ = {
|
||||
DA5BFA43147E415C00F98B1E /* MasterPassword */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword-Mac" */;
|
||||
buildConfigurationList = DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword" */;
|
||||
buildPhases = (
|
||||
DA5BFA40147E415C00F98B1E /* Sources */,
|
||||
DA5BFA41147E415C00F98B1E /* Frameworks */,
|
||||
@@ -907,9 +914,9 @@
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "MasterPassword-Mac";
|
||||
name = MasterPassword;
|
||||
productName = MasterPassword;
|
||||
productReference = DA5BFA44147E415C00F98B1E /* MasterPassword-Mac.app */;
|
||||
productReference = DA5BFA44147E415C00F98B1E /* MasterPassword.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
DAC6326B148680650075AEA5 /* jrswizzle */ = {
|
||||
@@ -971,7 +978,7 @@
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
DA5BFA43147E415C00F98B1E /* MasterPassword-Mac */,
|
||||
DA5BFA43147E415C00F98B1E /* MasterPassword */,
|
||||
DAC77CAC148291A600BCF976 /* Pearl */,
|
||||
DAC6326B148680650075AEA5 /* jrswizzle */,
|
||||
DA4425CA1557BED40052177D /* UbiquityStoreManager */,
|
||||
@@ -1116,6 +1123,7 @@
|
||||
files = (
|
||||
DACA22BB1705DE7D002C6C22 /* UbiquityStoreManager.m in Sources */,
|
||||
DACA22BD1705DE7D002C6C22 /* NSError+UbiquityStoreManager.m in Sources */,
|
||||
DA4C45F5173B57B700745CC5 /* NSURL+UbiquityStoreManager.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1190,7 +1198,7 @@
|
||||
/* Begin PBXTargetDependency section */
|
||||
DA3EF19E15A47AEB003ABF4E /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = DA5BFA43147E415C00F98B1E /* MasterPassword-Mac */;
|
||||
target = DA5BFA43147E415C00F98B1E /* MasterPassword */;
|
||||
targetProxy = DA3EF19D15A47AEB003ABF4E /* PBXContainerItemProxy */;
|
||||
};
|
||||
DAC63286148681200075AEA5 /* PBXTargetDependency */ = {
|
||||
@@ -1717,7 +1725,7 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = "AdHoc-Mac";
|
||||
};
|
||||
DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword-Mac" */ = {
|
||||
DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DA5BFA6E147E415C00F98B1E /* Debug-Mac */,
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "MasterPassword-Mac.app"
|
||||
BlueprintName = "MasterPassword-Mac"
|
||||
BuildableName = "MasterPassword.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
@@ -43,8 +43,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "MasterPassword-Mac.app"
|
||||
BlueprintName = "MasterPassword-Mac"
|
||||
BuildableName = "MasterPassword.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
@@ -61,8 +61,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "MasterPassword-Mac.app"
|
||||
BlueprintName = "MasterPassword-Mac"
|
||||
BuildableName = "MasterPassword.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "MasterPassword-Mac.app"
|
||||
BlueprintName = "MasterPassword-Mac"
|
||||
BuildableName = "MasterPassword.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
@@ -43,11 +43,18 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "MasterPassword-Mac.app"
|
||||
BlueprintName = "MasterPassword-Mac"
|
||||
BuildableName = "MasterPassword.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariable
|
||||
key = "CA_DEBUG_TRANSACTIONS"
|
||||
value = "1"
|
||||
isEnabled = "YES">
|
||||
</EnvironmentVariable>
|
||||
</EnvironmentVariables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
@@ -61,8 +68,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "MasterPassword-Mac.app"
|
||||
BlueprintName = "MasterPassword-Mac"
|
||||
BuildableName = "MasterPassword.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
|
||||
@@ -201,6 +201,41 @@
|
||||
</array>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMenuItem" id="939693094">
|
||||
<reference key="NSMenu" ref="800575174"/>
|
||||
<string key="NSTitle">Advanced</string>
|
||||
<string key="NSKeyEquiv"/>
|
||||
<int key="NSMnemonicLoc">2147483647</int>
|
||||
<reference key="NSOnImage" ref="269450960"/>
|
||||
<reference key="NSMixedImage" ref="977440657"/>
|
||||
<string key="NSAction">submenuAction:</string>
|
||||
<object class="NSMenu" key="NSSubmenu" id="534220172">
|
||||
<string key="NSTitle">Advanced</string>
|
||||
<array class="NSMutableArray" key="NSMenuItems">
|
||||
<object class="NSMenuItem" id="842321178">
|
||||
<reference key="NSMenu" ref="534220172"/>
|
||||
<string key="NSTitle">iCloud Truth Sync</string>
|
||||
<string key="NSKeyEquiv"/>
|
||||
<int key="NSMnemonicLoc">2147483647</int>
|
||||
<reference key="NSOnImage" ref="269450960"/>
|
||||
<reference key="NSMixedImage" ref="977440657"/>
|
||||
</object>
|
||||
<object class="NSMenuItem" id="946018575">
|
||||
<reference key="NSMenu" ref="534220172"/>
|
||||
<bool key="NSIsDisabled">YES</bool>
|
||||
<string key="NSTitle">Force this device's version of the truth upon all others.</string>
|
||||
<string key="NSKeyEquiv"/>
|
||||
<int key="NSMnemonicLoc">2147483647</int>
|
||||
<reference key="NSOnImage" ref="269450960"/>
|
||||
<reference key="NSMixedImage" ref="977440657"/>
|
||||
<object class="NSAttributedString" key="NSAttributedTitle">
|
||||
<string key="NSString">Force this device's version of the truth upon all others.</string>
|
||||
<reference key="NSAttributes" ref="583461090"/>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
<bool key="NSNoAutoenable">YES</bool>
|
||||
</object>
|
||||
@@ -288,14 +323,6 @@
|
||||
</object>
|
||||
<int key="connectionID">731</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBActionConnection" key="connection">
|
||||
<string key="label">activate:</string>
|
||||
<reference key="source" ref="976324537"/>
|
||||
<reference key="destination" ref="846612332"/>
|
||||
</object>
|
||||
<int key="connectionID">736</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBOutletConnection" key="connection">
|
||||
<string key="label">useICloudItem</string>
|
||||
@@ -408,6 +435,22 @@
|
||||
</object>
|
||||
<int key="connectionID">774</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBActionConnection" key="connection">
|
||||
<string key="label">rebuildCloud:</string>
|
||||
<reference key="source" ref="976324537"/>
|
||||
<reference key="destination" ref="842321178"/>
|
||||
</object>
|
||||
<int key="connectionID">780</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBActionConnection" key="connection">
|
||||
<string key="label">showPasswordWindow</string>
|
||||
<reference key="source" ref="976324537"/>
|
||||
<reference key="destination" ref="846612332"/>
|
||||
</object>
|
||||
<int key="connectionID">781</int>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
<array key="orderedObjects">
|
||||
@@ -503,6 +546,7 @@
|
||||
<reference ref="110488020"/>
|
||||
<reference ref="123831322"/>
|
||||
<reference ref="123543264"/>
|
||||
<reference ref="939693094"/>
|
||||
</array>
|
||||
<reference key="parent" ref="851296005"/>
|
||||
</object>
|
||||
@@ -590,6 +634,33 @@
|
||||
<reference key="object" ref="117792016"/>
|
||||
<reference key="parent" ref="293904698"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">776</int>
|
||||
<reference key="object" ref="939693094"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<reference ref="534220172"/>
|
||||
</array>
|
||||
<reference key="parent" ref="800575174"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">777</int>
|
||||
<reference key="object" ref="534220172"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<reference ref="842321178"/>
|
||||
<reference ref="946018575"/>
|
||||
</array>
|
||||
<reference key="parent" ref="939693094"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">778</int>
|
||||
<reference key="object" ref="842321178"/>
|
||||
<reference key="parent" ref="534220172"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">779</int>
|
||||
<reference key="object" ref="946018575"/>
|
||||
<reference key="parent" ref="534220172"/>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
||||
@@ -628,14 +699,158 @@
|
||||
<string key="766.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="767.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="768.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="776.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="777.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="778.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="779.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
|
||||
<nil key="activeLocalization"/>
|
||||
<dictionary class="NSMutableDictionary" key="localizations"/>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">774</int>
|
||||
<int key="maxID">781</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">MPAppDelegate_Shared</string>
|
||||
<string key="superclassName">PearlAppDelegate</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/MPAppDelegate_Shared.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">MPMacAppDelegate</string>
|
||||
<string key="superclassName">MPAppDelegate_Shared</string>
|
||||
<dictionary class="NSMutableDictionary" key="actions">
|
||||
<string key="activate:">id</string>
|
||||
<string key="lock:">id</string>
|
||||
<string key="newUser:">NSMenuItem</string>
|
||||
<string key="rebuildCloud:">id</string>
|
||||
<string key="togglePreference:">NSMenuItem</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="actionInfosByName">
|
||||
<object class="IBActionInfo" key="activate:">
|
||||
<string key="name">activate:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo" key="lock:">
|
||||
<string key="name">lock:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo" key="newUser:">
|
||||
<string key="name">newUser:</string>
|
||||
<string key="candidateClassName">NSMenuItem</string>
|
||||
</object>
|
||||
<object class="IBActionInfo" key="rebuildCloud:">
|
||||
<string key="name">rebuildCloud:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo" key="togglePreference:">
|
||||
<string key="name">togglePreference:</string>
|
||||
<string key="candidateClassName">NSMenuItem</string>
|
||||
</object>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="outlets">
|
||||
<string key="createUserItem">NSMenuItem</string>
|
||||
<string key="dialogStyleHUD">NSMenuItem</string>
|
||||
<string key="dialogStyleRegular">NSMenuItem</string>
|
||||
<string key="lockItem">NSMenuItem</string>
|
||||
<string key="rememberPasswordItem">NSMenuItem</string>
|
||||
<string key="savePasswordItem">NSMenuItem</string>
|
||||
<string key="showItem">NSMenuItem</string>
|
||||
<string key="statusMenu">NSMenu</string>
|
||||
<string key="useICloudItem">NSMenuItem</string>
|
||||
<string key="usersItem">NSMenuItem</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<object class="IBToOneOutletInfo" key="createUserItem">
|
||||
<string key="name">createUserItem</string>
|
||||
<string key="candidateClassName">NSMenuItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="dialogStyleHUD">
|
||||
<string key="name">dialogStyleHUD</string>
|
||||
<string key="candidateClassName">NSMenuItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="dialogStyleRegular">
|
||||
<string key="name">dialogStyleRegular</string>
|
||||
<string key="candidateClassName">NSMenuItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="lockItem">
|
||||
<string key="name">lockItem</string>
|
||||
<string key="candidateClassName">NSMenuItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="rememberPasswordItem">
|
||||
<string key="name">rememberPasswordItem</string>
|
||||
<string key="candidateClassName">NSMenuItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="savePasswordItem">
|
||||
<string key="name">savePasswordItem</string>
|
||||
<string key="candidateClassName">NSMenuItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="showItem">
|
||||
<string key="name">showItem</string>
|
||||
<string key="candidateClassName">NSMenuItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="statusMenu">
|
||||
<string key="name">statusMenu</string>
|
||||
<string key="candidateClassName">NSMenu</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="useICloudItem">
|
||||
<string key="name">useICloudItem</string>
|
||||
<string key="candidateClassName">NSMenuItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="usersItem">
|
||||
<string key="name">usersItem</string>
|
||||
<string key="candidateClassName">NSMenuItem</string>
|
||||
</object>
|
||||
</dictionary>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/MPMacAppDelegate.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">PearlAppDelegate</string>
|
||||
<string key="superclassName">UIResponder</string>
|
||||
<dictionary class="NSMutableDictionary" key="outlets">
|
||||
<string key="navigationController">UINavigationController</string>
|
||||
<string key="window">UIWindow</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<object class="IBToOneOutletInfo" key="navigationController">
|
||||
<string key="name">navigationController</string>
|
||||
<string key="candidateClassName">UINavigationController</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="window">
|
||||
<string key="name">window</string>
|
||||
<string key="candidateClassName">UIWindow</string>
|
||||
</object>
|
||||
</dictionary>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/PearlAppDelegate.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UINavigationController</string>
|
||||
<string key="superclassName">UIViewController</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/UINavigationController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIWindow</string>
|
||||
<string key="superclassName">UIView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/UIWindow.h</string>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes"/>
|
||||
<int key="IBDocument.localizationMode">0</int>
|
||||
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
|
||||
|
||||
@@ -55,9 +55,11 @@
|
||||
return;
|
||||
|
||||
__weak MPElementListAllViewController *wSelf = self;
|
||||
[self addElementNamed:[alert textFieldAtIndex:0].text completion:^(BOOL success) {
|
||||
if (success)
|
||||
[[MPiOSAppDelegate get] addElementNamed:[alert textFieldAtIndex:0].text completion:^(MPElementEntity *element) {
|
||||
if (element) {
|
||||
[wSelf.delegate didSelectElement:element];
|
||||
[wSelf close:nil];
|
||||
}
|
||||
}];
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonOkay, nil];
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
@property(readonly) NSDateFormatter *dateFormatter;
|
||||
|
||||
- (void)updateData;
|
||||
- (void)addElementNamed:(NSString *)siteName completion:(void (^)(BOOL success))completion;
|
||||
- (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atTableIndexPath:(NSIndexPath *)indexPath;
|
||||
- (void)customTableViewUpdates;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
- (void)viewDidLoad {
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UbiquityManagedStoreDidChangeNotification object:nil queue:nil usingBlock:
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidChangeNotification object:nil queue:nil usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self updateData];
|
||||
}];
|
||||
@@ -23,44 +23,6 @@
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
- (void)addElementNamed:(NSString *)siteName completion:(void (^)(BOOL success))completion {
|
||||
|
||||
if (![siteName length]) {
|
||||
if (completion)
|
||||
completion( false );
|
||||
return;
|
||||
}
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||
assert(activeUser);
|
||||
|
||||
MPElementType type = activeUser.defaultType;
|
||||
if (!type)
|
||||
type = activeUser.defaultType = MPElementTypeGeneratedLong;
|
||||
NSString *typeEntityClassName = [MPAlgorithmDefault classNameOfType:type];
|
||||
|
||||
MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:typeEntityClassName
|
||||
inManagedObjectContext:moc];
|
||||
|
||||
element.name = siteName;
|
||||
element.user = activeUser;
|
||||
element.type = type;
|
||||
element.lastUsed = [NSDate date];
|
||||
element.version = MPAlgorithmDefaultVersion;
|
||||
[moc saveToStore];
|
||||
|
||||
NSManagedObjectID *elementOID = [element objectID];
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
MPElementEntity *element_ = (MPElementEntity *)[[MPiOSAppDelegate managedObjectContextForThreadIfReady]
|
||||
objectRegisteredForID:elementOID];
|
||||
[self.delegate didSelectElement:element_];
|
||||
if (completion)
|
||||
completion( true );
|
||||
} );
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSFetchedResultsController *)fetchedResultsControllerByLastUsed {
|
||||
|
||||
if (!_fetchedResultsControllerByLastUsed) {
|
||||
@@ -145,9 +107,9 @@
|
||||
NSError *error;
|
||||
self.fetchedResultsControllerByLastUsed.fetchRequest.predicate = predicate;
|
||||
self.fetchedResultsControllerByUses.fetchRequest.predicate = predicate;
|
||||
if (![self.fetchedResultsControllerByLastUsed performFetch:&error])
|
||||
if (self.fetchedResultsControllerByLastUsed && ![self.fetchedResultsControllerByLastUsed performFetch:&error])
|
||||
err(@"Couldn't fetch elements: %@", error);
|
||||
if (![self.fetchedResultsControllerByUses performFetch:&error])
|
||||
if (self.fetchedResultsControllerByUses && ![self.fetchedResultsControllerByUses performFetch:&error])
|
||||
err(@"Couldn't fetch elements: %@", error);
|
||||
|
||||
[self.tableView reloadData];
|
||||
@@ -157,50 +119,46 @@
|
||||
}
|
||||
|
||||
// See MP-14, also crashes easily on internal assertions etc..
|
||||
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
|
||||
|
||||
dbg(@"%@", NSStringFromSelector( _cmd ));
|
||||
[self.tableView beginUpdates];
|
||||
}
|
||||
|
||||
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
|
||||
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
|
||||
|
||||
switch (type) {
|
||||
|
||||
case NSFetchedResultsChangeInsert:
|
||||
dbg(@"%@ -- NSFetchedResultsChangeInsert:%@", NSStringFromSelector( _cmd ), anObject);
|
||||
[self.tableView insertRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:newIndexPath] ]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
break;
|
||||
|
||||
case NSFetchedResultsChangeDelete:
|
||||
dbg(@"%@ -- NSFetchedResultsChangeDelete:%@", NSStringFromSelector( _cmd ), anObject);
|
||||
[self.tableView deleteRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:indexPath] ]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
break;
|
||||
|
||||
case NSFetchedResultsChangeUpdate:
|
||||
dbg(@"%@ -- NSFetchedResultsChangeUpdate:%@", NSStringFromSelector( _cmd ), anObject);
|
||||
[self.tableView reloadRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:indexPath] ]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
break;
|
||||
|
||||
case NSFetchedResultsChangeMove:
|
||||
dbg(@"%@ -- NSFetchedResultsChangeMove:%@", NSStringFromSelector( _cmd ), anObject);
|
||||
[self.tableView deleteRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:indexPath] ]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
[self.tableView insertRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:newIndexPath] ]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
break;
|
||||
}
|
||||
}
|
||||
//- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
|
||||
//
|
||||
// [self.tableView beginUpdates];
|
||||
//}
|
||||
//
|
||||
//- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
|
||||
// atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
|
||||
//
|
||||
// switch (type) {
|
||||
//
|
||||
// case NSFetchedResultsChangeInsert:
|
||||
// [self.tableView insertRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:newIndexPath] ]
|
||||
// withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
// break;
|
||||
//
|
||||
// case NSFetchedResultsChangeDelete:
|
||||
// [self.tableView deleteRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:indexPath] ]
|
||||
// withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
// break;
|
||||
//
|
||||
// case NSFetchedResultsChangeUpdate:
|
||||
// [self.tableView reloadRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:indexPath] ]
|
||||
// withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
// break;
|
||||
//
|
||||
// case NSFetchedResultsChangeMove:
|
||||
// [self.tableView deleteRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:indexPath] ]
|
||||
// withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
// [self.tableView insertRowsAtIndexPaths:@[ [self tableIndexPathForFetchController:controller indexPath:newIndexPath] ]
|
||||
// withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
|
||||
|
||||
dbg(@"%@ on %@", NSStringFromSelector( _cmd ), [NSThread currentThread].name);
|
||||
[self customTableViewUpdates];
|
||||
[self.tableView endUpdates];
|
||||
// [self customTableViewUpdates];
|
||||
// [self.tableView endUpdates];
|
||||
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
@@ -296,12 +254,18 @@
|
||||
forRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
if (editingStyle == UITableViewCellEditingStyleDelete) {
|
||||
MPElementEntity *element = [self elementForTableIndexPath:indexPath];
|
||||
[element.managedObjectContext performBlockAndWait:^{
|
||||
NSManagedObjectID *elementOID = [self elementForTableIndexPath:indexPath].objectID;
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) {
|
||||
NSError *error = nil;
|
||||
MPElementEntity *element = (MPElementEntity *)[context existingObjectWithID:elementOID error:&error];
|
||||
if (!element) {
|
||||
err(@"Failed to retrieve element to delete: %@", error);
|
||||
return;
|
||||
}
|
||||
|
||||
inf(@"Deleting element: %@", element.name);
|
||||
[element.managedObjectContext deleteObject:element];
|
||||
[element.managedObjectContext saveToStore];
|
||||
[context deleteObject:element];
|
||||
[context saveToStore];
|
||||
|
||||
MPCheckpoint( MPCheckpointDeleteElement, @{
|
||||
@"type" : element.typeName,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#import "MPElementListSearchController.h"
|
||||
#import "MPMainViewController.h"
|
||||
#import "MPiOSAppDelegate.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
|
||||
@interface MPElementListSearchController()
|
||||
|
||||
@@ -216,7 +217,11 @@
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
[self addElementNamed:siteName completion:nil];
|
||||
__weak MPElementListController *wSelf = self;
|
||||
[[MPiOSAppDelegate get] addElementNamed:siteName completion:^(MPElementEntity *element) {
|
||||
if (element)
|
||||
[wSelf.delegate didSelectElement:element];
|
||||
}];
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonYes, nil];
|
||||
}
|
||||
|
||||
|
||||
29
MasterPassword/ObjC/iOS/MPLogsViewController.h
Normal file
29
MasterPassword/ObjC/iOS/MPLogsViewController.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPLogsViewController.h
|
||||
// MPLogsViewController
|
||||
//
|
||||
// Created by lhunath on 2013-04-29.
|
||||
// Copyright, lhunath (Maarten Billemont) 2013. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface MPLogsViewController : UIViewController
|
||||
@property (weak, nonatomic) IBOutlet UITextView *logView;
|
||||
@property (weak, nonatomic) IBOutlet UISegmentedControl *levelControl;
|
||||
- (IBAction)toggleLevelControl:(UISegmentedControl *)sender;
|
||||
- (IBAction)close:(UIBarButtonItem *)sender;
|
||||
- (IBAction)refresh:(UIBarButtonItem *)sender;
|
||||
- (IBAction)mail:(UIBarButtonItem *)sender;
|
||||
@end
|
||||
87
MasterPassword/ObjC/iOS/MPLogsViewController.m
Normal file
87
MasterPassword/ObjC/iOS/MPLogsViewController.m
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPLogsViewController.h
|
||||
// MPLogsViewController
|
||||
//
|
||||
// Created by lhunath on 2013-04-29.
|
||||
// Copyright, lhunath (Maarten Billemont) 2013. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPLogsViewController.h"
|
||||
#import "MPiOSAppDelegate.h"
|
||||
|
||||
@implementation MPLogsViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
|
||||
[super viewDidLoad];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSUserDefaultsDidChangeNotification object:nil queue:nil usingBlock:
|
||||
^(NSNotification *note) {
|
||||
self.levelControl.selectedSegmentIndex = [[MPiOSConfig get].traceMode boolValue]? 1: 0;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
[self refresh:nil];
|
||||
|
||||
self.levelControl.selectedSegmentIndex = [[MPiOSConfig get].traceMode boolValue]? 1: 0;
|
||||
}
|
||||
|
||||
- (IBAction)toggleLevelControl:(UISegmentedControl *)sender {
|
||||
|
||||
BOOL traceEnabled = (BOOL)self.levelControl.selectedSegmentIndex;
|
||||
if (traceEnabled) {
|
||||
[PearlAlert showAlertWithTitle:@"Enable Trace Mode?" message:
|
||||
@"Trace mode will log the internal operation of the application.\n"
|
||||
@"Unless you're looking for the cause of a problem, you should leave this off to save memory."
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
[MPiOSConfig get].traceMode = @YES;
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Enable Trace", nil];
|
||||
}
|
||||
else
|
||||
[MPiOSConfig get].traceMode = @NO;
|
||||
}
|
||||
|
||||
- (IBAction)close:(UIBarButtonItem *)sender {
|
||||
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
- (IBAction)refresh:(UIBarButtonItem *)sender {
|
||||
|
||||
self.logView.text = [[PearlLogger get] formatMessagesWithLevel:PearlLogLevelTrace];
|
||||
}
|
||||
|
||||
- (IBAction)mail:(UIBarButtonItem *)sender {
|
||||
|
||||
if ([[MPiOSConfig get].traceMode boolValue]) {
|
||||
[PearlAlert showAlertWithTitle:@"Hiding Trace Messages" message:
|
||||
@"Trace-level log messages will not be mailed. "
|
||||
@"These messages contain sensitive and personal information."
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil
|
||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
[[MPiOSAppDelegate get] openFeedbackWithLogs:YES forVC:self];
|
||||
} cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil];
|
||||
}
|
||||
else
|
||||
[[MPiOSAppDelegate get] openFeedbackWithLogs:YES forVC:self];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -107,7 +107,7 @@
|
||||
[self.navigationController popToRootViewControllerAnimated:animated];
|
||||
}];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UbiquityManagedStoreDidChangeNotification object:nil queue:nil usingBlock:
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidChangeNotification object:nil queue:nil usingBlock:
|
||||
^(NSNotification *note) {
|
||||
if (!self.activeElementForThread)
|
||||
[self didSelectElement:nil];
|
||||
@@ -146,15 +146,15 @@
|
||||
|
||||
// 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 ), ^{
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread];
|
||||
if ([MPAlgorithmDefault migrateUser:activeUser] && !self.suppressOutdatedAlert)
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||
if ([MPAlgorithmDefault migrateUser:activeUser inContext:moc] && !self.suppressOutdatedAlert)
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.outdatedAlertContainer.alpha = 1;
|
||||
self.suppressOutdatedAlert = YES;
|
||||
}];
|
||||
[activeUser.managedObjectContext saveToStore];
|
||||
} );
|
||||
[moc saveToStore];
|
||||
}];
|
||||
|
||||
if (![[MPiOSConfig get].actionsTipShown boolValue])
|
||||
[UIView animateWithDuration:animated? 0.3f: 0 animations:^{
|
||||
@@ -506,7 +506,7 @@
|
||||
@"If you continue, a new password will be generated for this site. "
|
||||
@"You will then need to update your account's old password to this newly generated password.\n\n"
|
||||
@"You can reset the counter by holding down on this button."
|
||||
do:^BOOL(MPElementEntity *activeElement) {
|
||||
do:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) {
|
||||
if (![activeElement isKindOfClass:[MPElementGeneratedEntity class]]) {
|
||||
// Not of a type that supports a password counter.
|
||||
err(@"Cannot increment password counter: Element is not generated: %@", activeElement.name);
|
||||
@@ -545,7 +545,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_, NSManagedObjectContext *context) {
|
||||
inf(@"Resetting password counter for: %@", activeElement_.name);
|
||||
((MPElementGeneratedEntity *)activeElement_).counter = 1;
|
||||
|
||||
@@ -576,7 +576,8 @@
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)changeActiveElementWithWarning:(NSString *)warning do:(BOOL (^)(MPElementEntity *activeElement))task; {
|
||||
- (void)changeActiveElementWithWarning:(NSString *)warning
|
||||
do:(BOOL (^)(MPElementEntity *activeElement, NSManagedObjectContext *context))task {
|
||||
|
||||
[PearlAlert showAlertWithTitle:@"Password Change" message:warning viewStyle:UIAlertViewStyleDefault
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
@@ -587,7 +588,7 @@
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
||||
}
|
||||
|
||||
- (void)changeActiveElementWithoutWarningDo:(BOOL (^)(MPElementEntity *activeElement))task; {
|
||||
- (void)changeActiveElementWithoutWarningDo:(BOOL (^)(MPElementEntity *, NSManagedObjectContext *context))task {
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementEntity *activeElement = [self activeElementInContext:context];
|
||||
@@ -595,8 +596,10 @@
|
||||
return;
|
||||
|
||||
NSString *oldPassword = [activeElement.content description];
|
||||
if (!task( activeElement ))
|
||||
if (!task( activeElement, context ))
|
||||
return;
|
||||
|
||||
activeElement = [self activeElementInContext:context];
|
||||
NSString *newPassword = [activeElement.content description];
|
||||
|
||||
// Save.
|
||||
@@ -669,7 +672,7 @@
|
||||
@"This upgrade improves the site's compatibility with the latest version of Master Password.";
|
||||
|
||||
[self changeActiveElementWithWarning:warning do:
|
||||
^BOOL(MPElementEntity *activeElement_) {
|
||||
^BOOL(MPElementEntity *activeElement_, NSManagedObjectContext *context) {
|
||||
inf(@"Explicitly migrating element: %@", activeElement_);
|
||||
[activeElement_ migrateExplicitly:YES];
|
||||
|
||||
@@ -785,12 +788,16 @@
|
||||
@"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) {
|
||||
if ([activeElement.algorithm classOfType:type] != activeElement.typeClass) {
|
||||
do:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) {
|
||||
if ([activeElement.algorithm classOfType:type] == activeElement.typeClass)
|
||||
activeElement.type = type;
|
||||
|
||||
else {
|
||||
// Type requires a different class of element. Recreate the element.
|
||||
MPElementEntity *newElement
|
||||
= [NSEntityDescription insertNewObjectForEntityForName:[activeElement.algorithm classNameOfType:type]
|
||||
inManagedObjectContext:activeElement.managedObjectContext];
|
||||
inManagedObjectContext:context];
|
||||
newElement.type = type;
|
||||
newElement.name = activeElement.name;
|
||||
newElement.user = activeElement.user;
|
||||
newElement.uses = activeElement.uses;
|
||||
@@ -798,11 +805,16 @@
|
||||
newElement.version = activeElement.version;
|
||||
newElement.loginName = activeElement.loginName;
|
||||
|
||||
[activeElement.managedObjectContext deleteObject:activeElement];
|
||||
[context deleteObject:activeElement];
|
||||
[context saveToStore];
|
||||
|
||||
NSError *error;
|
||||
if (![context obtainPermanentIDsForObjects:@[ newElement ] error:&error])
|
||||
err(@"Failed to obtain a permanent object ID after changing object type: %@", error);
|
||||
|
||||
_activeElementOID = newElement.objectID;
|
||||
activeElement = newElement;
|
||||
}
|
||||
activeElement.type = type;
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:MPElementUpdatedNotification object:activeElement.objectID];
|
||||
@@ -817,7 +829,7 @@
|
||||
[self closeAlert];
|
||||
|
||||
if (element) {
|
||||
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement) {
|
||||
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) {
|
||||
if ([activeElement use] == 1)
|
||||
[self showAlertWithTitle:@"New Site" message:
|
||||
PearlString( @"You've just created a password for %@.\n\n"
|
||||
@@ -843,16 +855,16 @@
|
||||
} );
|
||||
}
|
||||
}];
|
||||
|
||||
MPCheckpoint( MPCheckpointUseType, @{
|
||||
@"type" : element.typeName,
|
||||
@"version" : @(element.version)
|
||||
} );
|
||||
}
|
||||
|
||||
[self.searchDisplayController setActive:NO animated:YES];
|
||||
self.searchDisplayController.searchBar.text = element.name;
|
||||
|
||||
MPCheckpoint( MPCheckpointUseType, @{
|
||||
@"type" : element.typeName,
|
||||
@"version" : @(element.version)
|
||||
} );
|
||||
|
||||
[self updateAnimated:YES];
|
||||
}
|
||||
|
||||
@@ -880,7 +892,7 @@
|
||||
// Content hasn't changed.
|
||||
return;
|
||||
|
||||
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement_) {
|
||||
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement_, NSManagedObjectContext *context) {
|
||||
((MPElementStoredEntity *)activeElement_).content = self.contentField.text;
|
||||
return YES;
|
||||
}];
|
||||
@@ -893,7 +905,7 @@
|
||||
[MPiOSConfig get].loginNameTipShown = @YES;
|
||||
}
|
||||
|
||||
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement) {
|
||||
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) {
|
||||
if ([self.loginNameField.text length])
|
||||
activeElement.loginName = self.loginNameField.text;
|
||||
else
|
||||
|
||||
@@ -47,9 +47,13 @@
|
||||
} options:0];
|
||||
[avatar onSelect:^(BOOL selected) {
|
||||
if (selected) {
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread];
|
||||
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
||||
if (!moc)
|
||||
return;
|
||||
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||
activeUser.avatar = (unsigned)avatar.tag;
|
||||
[activeUser.managedObjectContext saveToStore];
|
||||
[moc saveToStore];
|
||||
}
|
||||
} options:0];
|
||||
avatar.selected = (a == [[MPiOSAppDelegate get] activeUserForThread].avatar);
|
||||
@@ -89,6 +93,21 @@
|
||||
[super viewWillDisappear:animated];
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeFirstResponder {
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
|
||||
|
||||
if (motion == UIEventSubtypeMotionShake) {
|
||||
MPCheckpoint( MPCheckpointLogs, @{
|
||||
@"trace": [MPiOSConfig get].traceMode
|
||||
} );
|
||||
[self performSegueWithIdentifier:@"MP_Logs" sender:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)shouldAutorotate {
|
||||
|
||||
return NO;
|
||||
@@ -114,8 +133,12 @@
|
||||
[[MPiOSAppDelegate get] export];
|
||||
|
||||
else if (cell == self.changeMPCell) {
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread];
|
||||
[[MPiOSAppDelegate get] changeMasterPasswordFor:activeUser inContext:activeUser.managedObjectContext didResetBlock:nil];
|
||||
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
||||
if (!moc)
|
||||
return;
|
||||
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||
[[MPiOSAppDelegate get] changeMasterPasswordFor:activeUser saveInContext:moc didResetBlock:nil];
|
||||
}
|
||||
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
@@ -125,9 +148,13 @@
|
||||
|
||||
- (void)didSelectType:(MPElementType)type {
|
||||
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread];
|
||||
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
||||
if (!moc)
|
||||
return;
|
||||
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||
activeUser.defaultType = type;
|
||||
[activeUser.managedObjectContext saveToStore];
|
||||
[moc saveToStore];
|
||||
|
||||
self.defaultTypeLabel.text = [[MPiOSAppDelegate get].key.algorithm shortNameOfType:activeUser.defaultType];
|
||||
}
|
||||
@@ -141,12 +168,16 @@
|
||||
|
||||
- (IBAction)didToggleSwitch:(UISwitch *)sender {
|
||||
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread];
|
||||
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
||||
if (!moc)
|
||||
return;
|
||||
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||
if ((activeUser.saveKey = sender.on))
|
||||
[[MPiOSAppDelegate get] storeSavedKeyFor:activeUser];
|
||||
else
|
||||
[[MPiOSAppDelegate get] forgetSavedKeyFor:activeUser];
|
||||
[activeUser.managedObjectContext saveToStore];
|
||||
[moc saveToStore];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -77,7 +77,9 @@
|
||||
[(UITextField *)[cell viewWithTag:2] setText:@"..."];
|
||||
|
||||
NSString *name = selectedElement.name;
|
||||
NSUInteger counter = ((MPElementGeneratedEntity *)selectedElement).counter;
|
||||
NSUInteger counter = 0;
|
||||
if ([selectedElement isKindOfClass:[MPElementGeneratedEntity class]])
|
||||
counter = ((MPElementGeneratedEntity *)selectedElement).counter;
|
||||
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{
|
||||
NSString *typeContent = [MPAlgorithmDefault generateContentNamed:name ofType:cellType
|
||||
|
||||
@@ -8,12 +8,14 @@
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import <Social/Social.h>
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
#import "MPUnlockViewController.h"
|
||||
#import "MPiOSAppDelegate.h"
|
||||
#import "MPAppDelegate_Key.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
|
||||
|
||||
@interface MPUnlockViewController()
|
||||
|
||||
@property(strong, nonatomic) NSMutableDictionary *avatarToUserOID;
|
||||
@@ -28,6 +30,7 @@
|
||||
@property(nonatomic, strong) NSArray *marqueeTipTexts;
|
||||
@end
|
||||
|
||||
|
||||
@implementation MPUnlockViewController {
|
||||
NSManagedObjectID *_selectedUserOID;
|
||||
}
|
||||
@@ -116,7 +119,8 @@
|
||||
|
||||
- (void)viewDidLoad {
|
||||
|
||||
[self.newsView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.masterpasswordapp.com/news.html"]]];
|
||||
NSString *newsURL = PearlString( @"http://www.masterpasswordapp.com/news.html?version=%@", [[PearlInfoPlist get] CFBundleVersion] );
|
||||
[self.newsView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:newsURL]]];
|
||||
|
||||
self.avatarToUserOID = [NSMutableDictionary dictionaryWithCapacity:3];
|
||||
|
||||
@@ -161,11 +165,11 @@
|
||||
[self initializeWordLabel:wordLabel];
|
||||
} recurse:NO];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UbiquityManagedStoreDidChangeNotification object:nil queue:nil usingBlock:
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidChangeNotification object:nil queue:nil usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UbiquityManagedStoreDidImportChangesNotification object:nil queue:nil
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidImportChangesNotification object:nil queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
@@ -206,6 +210,8 @@
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
|
||||
[self becomeFirstResponder];
|
||||
|
||||
if (!animated && !self.navigationController.presentedViewController)
|
||||
[[self findTargetedAvatar] setSelected:YES];
|
||||
else
|
||||
@@ -251,10 +257,21 @@
|
||||
|
||||
self.emergencyGeneratorContainer.alpha = 0;
|
||||
self.emergencyGeneratorContainer.hidden = NO;
|
||||
[UIView animateWithDuration:0.5 animations:^{
|
||||
self.emergencyGeneratorContainer.frame = CGRectSetX( self.emergencyGeneratorContainer.frame,
|
||||
self.emergencyGeneratorContainer.frame.origin.x - 100 );
|
||||
[UIView animateWithDuration:0.3 animations:^{
|
||||
self.emergencyGeneratorContainer.frame = CGRectSetX( self.emergencyGeneratorContainer.frame,
|
||||
self.emergencyGeneratorContainer.frame.origin.x + 150 );
|
||||
self.emergencyGeneratorContainer.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
if (!finished)
|
||||
return;
|
||||
|
||||
[self.emergencyName becomeFirstResponder];
|
||||
[UIView animateWithDuration:0.2 animations:^{
|
||||
self.emergencyGeneratorContainer.frame = CGRectSetX( self.emergencyGeneratorContainer.frame,
|
||||
self.emergencyGeneratorContainer.frame.origin.x - 50 );
|
||||
}];
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -344,20 +361,19 @@
|
||||
|
||||
[self.avatarToUserOID setObject:NilToNSNull([user objectID]) forKey:[NSValue valueWithNonretainedObject:avatar]];
|
||||
|
||||
if ([_selectedUserOID isEqual:[user objectID]]) {
|
||||
self.selectedUser = user;
|
||||
if ([_selectedUserOID isEqual:[user objectID]])
|
||||
avatar.selected = YES;
|
||||
}
|
||||
|
||||
return avatar;
|
||||
}
|
||||
|
||||
- (void)didToggleUserSelection {
|
||||
|
||||
MPUserEntity *selectedUser = [self selectedUserForThread];
|
||||
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
||||
MPUserEntity *selectedUser = [self selectedUserInContext:moc];
|
||||
if (!selectedUser)
|
||||
[self.passwordField resignFirstResponder];
|
||||
else if ([[MPiOSAppDelegate get] signInAsUser:selectedUser inContext:selectedUser.managedObjectContext usingMasterPassword:nil]) {
|
||||
else if ([[MPiOSAppDelegate get] signInAsUser:selectedUser saveInContext:moc usingMasterPassword:nil]) {
|
||||
[self performSegueWithIdentifier:@"MP_Unlock" sender:self];
|
||||
return;
|
||||
}
|
||||
@@ -370,15 +386,17 @@
|
||||
|
||||
- (void)didSelectNewUserAvatar:(UIButton *)newUserAvatar {
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *newUser = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass( [MPUserEntity class] )
|
||||
inManagedObjectContext:moc];
|
||||
if (![MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity
|
||||
*newUser = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass( [MPUserEntity class] )
|
||||
inManagedObjectContext:moc];
|
||||
|
||||
[self showNewUserNameAlertFor:newUser inContext:moc completion:^(BOOL finished) {
|
||||
newUserAvatar.selected = NO;
|
||||
self.selectedUser = newUser;
|
||||
}];
|
||||
}];
|
||||
}])
|
||||
newUserAvatar.selected = NO;
|
||||
}
|
||||
|
||||
- (void)showNewUserNameAlertFor:(MPUserEntity *)newUser inContext:(NSManagedObjectContext *)moc
|
||||
@@ -449,7 +467,12 @@
|
||||
}
|
||||
|
||||
// Confirm
|
||||
[moc saveToStore];
|
||||
[moc performBlockAndWait:^{
|
||||
[moc saveToStore];
|
||||
NSError *error = nil;
|
||||
if (![moc obtainPermanentIDsForObjects:@[ newUser ] error:&error])
|
||||
err(@"Failed to obtain permanent object ID for new user: %@", error);
|
||||
}];
|
||||
completion( YES );
|
||||
|
||||
[self updateUsers];
|
||||
@@ -481,7 +504,7 @@
|
||||
if (selectedUser && !self.passwordView.alpha) {
|
||||
// User was just selected.
|
||||
self.passwordView.alpha = 1;
|
||||
self.avatarsView.center = CGPointMake( 160, 180 );
|
||||
self.avatarsView.frame = CGRectSetY( self.avatarsView.frame, 16 );
|
||||
self.avatarsView.scrollEnabled = NO;
|
||||
self.nameLabel.center = CGPointMake( 160, 94 );
|
||||
self.nameLabel.backgroundColor = [UIColor blackColor];
|
||||
@@ -492,7 +515,7 @@
|
||||
// User was just deselected.
|
||||
self.passwordField.text = nil;
|
||||
self.passwordView.alpha = 0;
|
||||
self.avatarsView.center = CGPointMake( 160, 310 );
|
||||
self.avatarsView.frame = CGRectSetY( self.avatarsView.frame, 140 );
|
||||
self.avatarsView.scrollEnabled = YES;
|
||||
self.nameLabel.center = CGPointMake( 160, 296 );
|
||||
self.nameLabel.backgroundColor = [UIColor clearColor];
|
||||
@@ -534,7 +557,7 @@
|
||||
UIButton *targetedAvatar = selectedAvatar;
|
||||
if (!targetedAvatar) {
|
||||
targetedAvatar = [self findTargetedAvatar];
|
||||
targetedUser = [self userForAvatar:targetedAvatar];
|
||||
targetedUser = [self userForAvatar:targetedAvatar inContext:[MPiOSAppDelegate managedObjectContextForThreadIfReady]];
|
||||
}
|
||||
|
||||
[self.avatarsView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||
@@ -552,7 +575,8 @@
|
||||
} recurse:NO];
|
||||
|
||||
if (allowScroll) {
|
||||
CGPoint targetContentOffset = CGPointMake( MAX(0, targetedAvatar.center.x - self.avatarsView.bounds.size.width / 2),
|
||||
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];
|
||||
@@ -618,7 +642,7 @@
|
||||
[self setSpinnerActive:YES];
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
BOOL unlocked = [[MPiOSAppDelegate get] signInAsUser:[self selectedUserInContext:moc] inContext:moc
|
||||
BOOL unlocked = [[MPiOSAppDelegate get] signInAsUser:[self selectedUserInContext:moc] saveInContext:moc
|
||||
usingMasterPassword:self.passwordField.text];
|
||||
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
@@ -655,11 +679,7 @@
|
||||
return avatar;
|
||||
}
|
||||
|
||||
- (MPUserEntity *)userForAvatar:(UIButton *)avatar {
|
||||
|
||||
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
||||
if (!moc)
|
||||
return nil;
|
||||
- (MPUserEntity *)userForAvatar:(UIButton *)avatar inContext:(NSManagedObjectContext *)moc {
|
||||
|
||||
NSManagedObjectID *userOID = NSNullToNil([self.avatarToUserOID objectForKey:[NSValue valueWithNonretainedObject:avatar]]);
|
||||
if (!userOID)
|
||||
@@ -919,7 +939,7 @@
|
||||
[[self.emergencyGeneratorContainer findFirstResponderInHierarchy] resignFirstResponder];
|
||||
|
||||
if (animated) {
|
||||
[UIView animateWithDuration:0.5 animations:^{
|
||||
[UIView animateWithDuration:0.2 animations:^{
|
||||
self.emergencyGeneratorContainer.alpha = 0;
|
||||
} completion:^(BOOL finished) {
|
||||
[self emergencyCloseAnimated:NO];
|
||||
@@ -983,11 +1003,11 @@
|
||||
if ([self selectedUserForThread])
|
||||
return;
|
||||
|
||||
MPUserEntity *targetedUser = [self userForAvatar:[self findTargetedAvatar]];
|
||||
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
||||
MPUserEntity *targetedUser = [self userForAvatar:[self findTargetedAvatar] inContext:moc];
|
||||
if (!targetedUser)
|
||||
return;
|
||||
|
||||
NSManagedObjectContext *moc = targetedUser.managedObjectContext;
|
||||
[PearlSheet showSheetWithTitle:targetedUser.name
|
||||
viewStyle:UIActionSheetStyleBlackTranslucent
|
||||
initSheet:nil tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) {
|
||||
@@ -1007,7 +1027,7 @@
|
||||
}
|
||||
|
||||
if (buttonIndex == [sheet firstOtherButtonIndex])
|
||||
[[MPiOSAppDelegate get] changeMasterPasswordFor:targetedUser inContext:moc didResetBlock:^{
|
||||
[[MPiOSAppDelegate get] changeMasterPasswordFor:targetedUser saveInContext:moc didResetBlock:^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[[self avatarForUser:targetedUser] setSelected:YES];
|
||||
} );
|
||||
@@ -1138,6 +1158,11 @@
|
||||
|
||||
- (void)setSelectedUser:(MPUserEntity *)selectedUser {
|
||||
|
||||
NSError *error = nil;
|
||||
if (selectedUser.objectID.isTemporaryID &&
|
||||
![selectedUser.managedObjectContext obtainPermanentIDsForObjects:@[ selectedUser ] error:&error])
|
||||
err(@"Failed to obtain a permanent object ID after setting selected user: %@", error);
|
||||
|
||||
_selectedUserOID = selectedUser.objectID;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
- (void)showGuide;
|
||||
- (void)showSetup;
|
||||
- (void)showFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController;
|
||||
- (void)openFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController;
|
||||
|
||||
- (void)export;
|
||||
- (void)changeMasterPasswordFor:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset;
|
||||
- (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset;
|
||||
|
||||
@end
|
||||
|
||||
@@ -12,15 +12,25 @@
|
||||
#import "IASKSettingsReader.h"
|
||||
#import "GPPSignIn.h"
|
||||
|
||||
@interface MPiOSAppDelegate()
|
||||
|
||||
@property(nonatomic, strong) PearlAlert *handleCloudContentAlert;
|
||||
@property(nonatomic, strong) PearlAlert *fixCloudContentAlert;
|
||||
@property(nonatomic, strong) PearlOverlay *storeLoading;
|
||||
@end
|
||||
|
||||
@implementation MPiOSAppDelegate
|
||||
|
||||
+ (void)initialize {
|
||||
|
||||
[MPiOSConfig get];
|
||||
|
||||
[PearlLogger get].historyLevel = [[MPiOSConfig get].traceMode boolValue]? PearlLogLevelTrace: PearlLogLevelInfo;
|
||||
#ifdef DEBUG
|
||||
[PearlLogger get].printLevel = PearlLogLevelDebug;
|
||||
//[NSClassFromString(@"WebView") performSelector:NSSelectorFromString(@"_enableRemoteInspector")];
|
||||
#else
|
||||
if ([[MPiOSConfig get].sendInfo boolValue])
|
||||
[PearlLogger get].printLevel = PearlLogLevelInfo;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -202,23 +212,28 @@
|
||||
[[Crashlytics sharedInstance] setObjectValue:[PearlConfig get].reviewedVersion forKey:@"reviewedVersion"];
|
||||
|
||||
#ifdef TESTFLIGHT_SDK_VERSION
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[MPConfig get].rememberLogin boolValue]) description]
|
||||
[TestFlight addCustomEnvironmentInformation:PearlStringNSB([MPConfig get].rememberLogin)
|
||||
forKey:@"rememberLogin"];
|
||||
[TestFlight addCustomEnvironmentInformation:[@([self storeManager].cloudEnabled) description] forKey:@"iCloud"];
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[MPConfig get].iCloudDecided boolValue]) description]
|
||||
[TestFlight addCustomEnvironmentInformation:PearlStringB([self storeManager].cloudEnabled)
|
||||
forKey:@"iCloud"];
|
||||
[TestFlight addCustomEnvironmentInformation:PearlStringNSB([MPConfig get].iCloudDecided)
|
||||
forKey:@"iCloudDecided"];
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[MPiOSConfig get].sendInfo boolValue]) description] forKey:@"sendInfo"];
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[MPiOSConfig get].helpHidden boolValue]) description]
|
||||
[TestFlight addCustomEnvironmentInformation:PearlStringNSB([MPiOSConfig get].sendInfo)
|
||||
forKey:@"sendInfo"];
|
||||
[TestFlight addCustomEnvironmentInformation:PearlStringNSB([MPiOSConfig get].helpHidden)
|
||||
forKey:@"helpHidden"];
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[MPiOSConfig get].showSetup boolValue]) description]
|
||||
[TestFlight addCustomEnvironmentInformation:PearlStringNSB([MPiOSConfig get].showSetup)
|
||||
forKey:@"showQuickStart"];
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[PearlConfig get].firstRun boolValue]) description] forKey:@"firstRun"];
|
||||
[TestFlight addCustomEnvironmentInformation:[[PearlConfig get].launchCount description] forKey:@"launchCount"];
|
||||
[TestFlight addCustomEnvironmentInformation:[@([[PearlConfig get].askForReviews boolValue]) description]
|
||||
[TestFlight addCustomEnvironmentInformation:PearlStringNSB([PearlConfig get].firstRun)
|
||||
forKey:@"firstRun"];
|
||||
[TestFlight addCustomEnvironmentInformation:PearlStringNSB([PearlConfig get].launchCount)
|
||||
forKey:@"launchCount"];
|
||||
[TestFlight addCustomEnvironmentInformation:PearlStringNSB([PearlConfig get].askForReviews)
|
||||
forKey:@"askForReviews"];
|
||||
[TestFlight addCustomEnvironmentInformation:[[PearlConfig get].reviewAfterLaunches description]
|
||||
[TestFlight addCustomEnvironmentInformation:PearlStringNSB([PearlConfig get].reviewAfterLaunches)
|
||||
forKey:@"reviewAfterLaunches"];
|
||||
[TestFlight addCustomEnvironmentInformation:[PearlConfig get].reviewedVersion forKey:@"reviewedVersion"];
|
||||
[TestFlight addCustomEnvironmentInformation:[PearlConfig get].reviewedVersion
|
||||
forKey:@"reviewedVersion"];
|
||||
#endif
|
||||
MPCheckpoint( MPCheckpointConfig, @{
|
||||
@"rememberLogin" : @([[MPConfig get].rememberLogin boolValue]),
|
||||
@@ -228,9 +243,9 @@
|
||||
@"helpHidden" : @([[MPiOSConfig get].helpHidden boolValue]),
|
||||
@"showQuickStart" : @([[MPiOSConfig get].showSetup boolValue]),
|
||||
@"firstRun" : @([[PearlConfig get].firstRun boolValue]),
|
||||
@"launchCount" : NilToNSNull([[PearlConfig get].launchCount description]),
|
||||
@"launchCount" : NilToNSNull([PearlConfig get].launchCount),
|
||||
@"askForReviews" : @([[PearlConfig get].askForReviews boolValue]),
|
||||
@"reviewAfterLaunches" : NilToNSNull([[PearlConfig get].reviewAfterLaunches description]),
|
||||
@"reviewAfterLaunches" : NilToNSNull([PearlConfig get].reviewAfterLaunches),
|
||||
@"reviewedVersion" : NilToNSNull([PearlConfig get].reviewedVersion)
|
||||
} );
|
||||
}
|
||||
@@ -261,6 +276,18 @@
|
||||
[[MPiOSAppDelegate get] showSetup];
|
||||
} );
|
||||
|
||||
MPCheckpoint(MPCheckpointStarted, @{
|
||||
@"simulator" : PearlStringB([PearlDeviceUtils isSimulator]),
|
||||
@"encrypted" : PearlStringB([PearlDeviceUtils isAppEncrypted]),
|
||||
@"jailbroken" : PearlStringB([PearlDeviceUtils isJailbroken]),
|
||||
@"platform" : [PearlDeviceUtils platform],
|
||||
#ifdef APPSTORE
|
||||
@"legal" : PearlStringB([PearlDeviceUtils isAppEncrypted]),
|
||||
#else
|
||||
@"legal" : @"YES",
|
||||
#endif
|
||||
});
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -434,11 +461,6 @@
|
||||
MPCheckpoint( MPCheckpointShowSetup, nil );
|
||||
}
|
||||
|
||||
- (void)showFeedback {
|
||||
|
||||
[self showFeedbackWithLogs:NO forVC:nil];
|
||||
}
|
||||
|
||||
- (void)showReview {
|
||||
|
||||
MPCheckpoint( MPCheckpointReview, nil );
|
||||
@@ -475,7 +497,9 @@
|
||||
- (void)openFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController {
|
||||
|
||||
NSString *userName = [[MPiOSAppDelegate get] activeUserForThread].name;
|
||||
PearlLogLevel logLevel = [[MPiOSConfig get].sendInfo boolValue]? PearlLogLevelDebug: PearlLogLevelInfo;
|
||||
PearlLogLevel logLevel = PearlLogLevelInfo;
|
||||
if (logs && ([[MPiOSConfig get].sendInfo boolValue] || [[MPiOSConfig get].traceMode boolValue]))
|
||||
logLevel = PearlLogLevelDebug;
|
||||
|
||||
[[[PearlEMail alloc] initForEMailTo:@"Master Password Development <masterpassword@lyndir.com>"
|
||||
subject:PearlString( @"Feedback for Master Password [%@]",
|
||||
@@ -570,7 +594,7 @@
|
||||
nil];
|
||||
}
|
||||
|
||||
- (void)changeMasterPasswordFor:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset {
|
||||
- (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset {
|
||||
|
||||
[PearlAlert showAlertWithTitle:@"Changing Master Password"
|
||||
message:
|
||||
@@ -603,11 +627,77 @@
|
||||
|
||||
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)value {
|
||||
|
||||
if (configKey == @selector(traceMode)) {
|
||||
[PearlLogger get].historyLevel = [[MPiOSConfig get].traceMode boolValue]? PearlLogLevelTrace: PearlLogLevelInfo;
|
||||
inf(@"Trace is now: %@", [[MPiOSConfig get].traceMode boolValue]? @"ON": @"OFF");
|
||||
}
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:MPCheckConfigNotification object:NSStringFromSelector( configKey ) userInfo:nil];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Google+
|
||||
- (void)ubiquityStoreManager:(UbiquityStoreManager *)manager willLoadStoreIsCloud:(BOOL)isCloudStore {
|
||||
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[self.handleCloudContentAlert cancelAlertAnimated:YES];
|
||||
if (![self.storeLoading isVisible])
|
||||
self.storeLoading = [PearlOverlay showOverlayWithTitle:@"Opening Your Data"];
|
||||
} );
|
||||
|
||||
[super ubiquityStoreManager:manager willLoadStoreIsCloud:isCloudStore];
|
||||
}
|
||||
|
||||
- (void)ubiquityStoreManager:(UbiquityStoreManager *)manager didLoadStoreForCoordinator:(NSPersistentStoreCoordinator *)coordinator
|
||||
isCloud:(BOOL)isCloudStore {
|
||||
|
||||
[super ubiquityStoreManager:manager didLoadStoreForCoordinator:coordinator isCloud:isCloudStore];
|
||||
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[self.handleCloudContentAlert cancelAlertAnimated:YES];
|
||||
[self.fixCloudContentAlert cancelAlertAnimated:YES];
|
||||
[self.storeLoading cancelOverlayAnimated:YES];
|
||||
} );
|
||||
}
|
||||
|
||||
- (BOOL)ubiquityStoreManager:(UbiquityStoreManager *)manager handleCloudContentCorruptionWithHealthyStore:(BOOL)storeHealthy {
|
||||
|
||||
if (manager.cloudEnabled && !storeHealthy && !([self.handleCloudContentAlert.alertView isVisible] || [self.fixCloudContentAlert.alertView isVisible]))
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[self.storeLoading cancelOverlayAnimated:YES];
|
||||
[self showCloudContentAlert];
|
||||
} );
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)showCloudContentAlert {
|
||||
|
||||
__weak MPiOSAppDelegate *wSelf = self;
|
||||
[self.handleCloudContentAlert cancelAlertAnimated:NO];
|
||||
self.handleCloudContentAlert = [PearlAlert showActivityWithTitle:@"iCloud Sync Problem" message:
|
||||
@"Waiting for your other device to auto‑correct the problem..."
|
||||
initAlert:^(UIAlertView *alert) {
|
||||
[alert addButtonWithTitle:@"Fix Now"];
|
||||
}];
|
||||
|
||||
self.handleCloudContentAlert.tappedButtonBlock = ^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
wSelf.fixCloudContentAlert = [PearlAlert showAlertWithTitle:@"Fix iCloud Now" message:
|
||||
@"This problem can usually be auto‑corrected by opening the app on another device where you recently made changes.\n"
|
||||
@"You can correct the problem from this device anyway, but recent changes made on another device might get lost."
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:
|
||||
^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
if (buttonIndex_ == alert_.cancelButtonIndex)
|
||||
[wSelf showCloudContentAlert];
|
||||
if (buttonIndex_ == [alert_ firstOtherButtonIndex])
|
||||
[wSelf.storeManager rebuildCloudContentFromCloudStoreOrLocalStore:YES];
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonBack otherTitles:@"Fix Anyway", nil];
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Google+
|
||||
|
||||
- (NSDictionary *)googlePlusInfo {
|
||||
|
||||
@@ -16,5 +16,6 @@
|
||||
@property(nonatomic, retain) NSNumber *actionsTipShown;
|
||||
@property(nonatomic, retain) NSNumber *typeTipShown;
|
||||
@property(nonatomic, retain) NSNumber *loginNameTipShown;
|
||||
@property(nonatomic, retain) NSNumber *traceMode;
|
||||
|
||||
@end
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
@implementation MPiOSConfig
|
||||
|
||||
@dynamic sendInfo, helpHidden, siteInfoHidden, showSetup, actionsTipShown, typeTipShown, loginNameTipShown;
|
||||
@dynamic helpHidden, siteInfoHidden, showSetup, actionsTipShown, typeTipShown, loginNameTipShown, traceMode;
|
||||
|
||||
- (id)init {
|
||||
|
||||
@@ -20,9 +20,10 @@
|
||||
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)
|
||||
NSStringFromSelector( @selector(actionsTipShown) ) : @(!self.firstRun),
|
||||
NSStringFromSelector( @selector(typeTipShown) ) : @(!self.firstRun),
|
||||
NSStringFromSelector( @selector(loginNameTipShown) ) : @NO,
|
||||
NSStringFromSelector( @selector(traceMode) ) : @NO
|
||||
}];
|
||||
|
||||
return self;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<objects>
|
||||
<tableViewController id="NKe-nv-566" customClass="MPTypeViewController" sceneMemberID="viewController">
|
||||
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="none" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="btl-G4-V0S">
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="416"/>
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.12549020350000001" green="0.1411764771" blue="0.14901961389999999" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<view key="tableFooterView" contentMode="scaleToFill" id="aNa-wb-cYK">
|
||||
@@ -476,16 +476,109 @@ Your passwords will be AES-encrypted with your master password.</string>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1537" y="145"/>
|
||||
</scene>
|
||||
<!--Logs View Controller - Log Inspector-->
|
||||
<scene sceneID="AKo-Ze-vcJ">
|
||||
<objects>
|
||||
<viewController id="Tx0-mM-kHk" customClass="MPLogsViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="3oc-v8-YGP">
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="center" image="background.png" id="mtJ-9r-6yT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="504"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</imageView>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" id="ojc-Tn-DM1">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<string key="text">119-20:51:52 MPiOSAppDelegate.m:36 | INFO : Initializing TestFlight
|
||||
119-20:51:52 MPiOSAppDelegate.m:70 | INFO : Initializing Google+
|
||||
119-20:51:52 MPiOSAppDelegate.m:80 | INFO : Initializing Crashlytics
|
||||
119-20:51:52 MPiOSAppDelegate.m:109 | INFO : Initializing Localytics
|
||||
119-20:51:53 PearlAppDelegate.m:71 | INFO : Master Password (MasterPassword) 1.4 (1.4.0) (GIT: 1.4-0-g8a4eecd-dirty)
|
||||
119-20:51:53 MPiOSAppDelegate.m:257 | INFO : Started up with device identifier: A8C51CDA-6F60-4F0C-BFC9-68A08F2F2DD7
|
||||
119-20:51:59 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] (Re)loading store...
|
||||
119-20:51:59 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Will load cloud store: 0B3CA2DF-5796-44DF-B5E0-121EC3846464 (definite).
|
||||
119-20:51:59 PearlConfig.m:193 | INFO : Lock screen will appear
|
||||
119-20:51:59 MPiOSAppDelegate.m:412 | INFO : Re-activated
|
||||
119-20:51:59 PearlConfig.m:180 | DEBUG : MPiOSConfig.launchCount = [70 ->] 71
|
||||
119-20:52:02 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Clearing stores...
|
||||
119-20:52:03 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Loading store without seeding.
|
||||
119-20:52:09 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Cloud enabled and successfully loaded cloud store.
|
||||
119-20:52:09 MPAppDelegate_Store.m:299 | INFO : Using iCloud? 1
|
||||
119-20:52:12 MPAppDelegate_Key.m:28 | INFO : Found key in keychain for: b55911588b178466be1d6392597e899b8de46f9a
|
||||
119-20:52:12 MPAppDelegate_Key.m:132 | INFO : Logged in: b55911588b178466be1d6392597e899b8de46f9a
|
||||
119-20:52:13 MPUnlockViewController.m:229 | INFO : Lock screen will disappear
|
||||
119-20:52:13 MPMainViewController.m:142 | INFO : Main will appear
|
||||
119-20:52:16 MPMainViewController.m:734 | INFO : Action: Preferences
|
||||
119-20:52:17 MPMainViewController.m:187 | INFO : Main will disappear.
|
||||
</string>
|
||||
<color key="textColor" cocoaTouchSystemColor="lightTextColor"/>
|
||||
<fontDescription key="fontDescription" name="AmericanTypewriter" family="American Typewriter" pointSize="9"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
</textView>
|
||||
<toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="QPO-l8-Opz">
|
||||
<rect key="frame" x="0.0" y="460" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<items>
|
||||
<barButtonItem systemItem="compose" id="Yvq-If-VqG">
|
||||
<connections>
|
||||
<action selector="mail:" destination="Tx0-mM-kHk" id="Efg-Nz-tf2"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<barButtonItem systemItem="refresh" id="fzf-tt-Vc3">
|
||||
<connections>
|
||||
<action selector="refresh:" destination="Tx0-mM-kHk" id="Xur-Ed-PN7"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<barButtonItem systemItem="flexibleSpace" id="GcH-O1-v3J"/>
|
||||
<barButtonItem style="plain" id="yi1-I8-uzn">
|
||||
<segmentedControl key="customView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="0" id="lzO-Kl-IPf">
|
||||
<rect key="frame" x="191" y="8" width="123" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<segments>
|
||||
<segment title="Normal"/>
|
||||
<segment title="Debug"/>
|
||||
</segments>
|
||||
<color key="tintColor" red="0.37254901959999998" green="0.3921568627" blue="0.42745098040000001" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<connections>
|
||||
<action selector="toggleLevelControl:" destination="Tx0-mM-kHk" eventType="valueChanged" id="Snn-NE-BnD"/>
|
||||
</connections>
|
||||
</segmentedControl>
|
||||
<color key="tintColor" red="0.37254901959999998" green="0.3921568627" blue="0.42745098040000001" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</barButtonItem>
|
||||
</items>
|
||||
</toolbar>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" title="Log Inspector" id="RrC-3Q-nBN">
|
||||
<barButtonItem key="rightBarButtonItem" systemItem="done" id="RYe-xc-zYv">
|
||||
<connections>
|
||||
<action selector="close:" destination="Tx0-mM-kHk" id="KrS-tQ-IOf"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<connections>
|
||||
<outlet property="levelControl" destination="lzO-Kl-IPf" id="B7k-yM-dR0"/>
|
||||
<outlet property="logView" destination="ojc-Tn-DM1" id="mOS-LG-HHA"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="2Jl-Qq-bOz" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2078" y="145"/>
|
||||
</scene>
|
||||
<!--Main View Controller - Master Password-->
|
||||
<scene sceneID="U26-Zf-euQ">
|
||||
<objects>
|
||||
<viewController id="PQa-Xl-A3x" customClass="MPMainViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ep0-Hn-5TR">
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="416"/>
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="center" image="background.png" id="0hY-LL-ITu">
|
||||
<rect key="frame" x="0.0" y="44" width="320" height="372"/>
|
||||
<rect key="frame" x="0.0" y="44" width="320" height="460"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" id="Juh-jm-UDr" userLabel="View - Content">
|
||||
@@ -665,7 +758,7 @@ Your passwords will be AES-encrypted with your master password.</string>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" id="61G-By-qLB" userLabel="View - Help">
|
||||
<rect key="frame" x="0.0" y="246" width="320" height="170"/>
|
||||
<rect key="frame" x="0.0" y="334" width="320" height="170"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="top" image="Square-bottom.png" id="lbm-A0-3PK">
|
||||
@@ -828,7 +921,7 @@ Your passwords will be AES-encrypted with your master password.</string>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view hidden="YES" alpha="0.0" contentMode="scaleToFill" id="6wk-NU-VQG" userLabel="View - Outdated Alert">
|
||||
<rect key="frame" x="10" y="230" width="300" height="180"/>
|
||||
<rect key="frame" x="10" y="318" width="300" height="180"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<imageView contentMode="scaleToFill" image="tip_alert_black.png" id="f30-i7-VBv">
|
||||
@@ -906,7 +999,7 @@ These sites should be upgraded and their account's passwords updated as soon as
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view hidden="YES" alpha="0.0" contentMode="scaleToFill" id="yRY-qt-gz8" userLabel="View - Alert">
|
||||
<rect key="frame" x="10" y="230" width="300" height="180"/>
|
||||
<rect key="frame" x="10" y="318" width="300" height="180"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_alert_black.png" id="TUv-Tl-xTc">
|
||||
@@ -1085,20 +1178,20 @@ L4m3P4sSw0rD</string>
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="MPUnlockViewController" wantsFullScreenLayout="YES" modalTransitionStyle="flipHorizontal" id="Nbn-Rv-sP1" customClass="MPUnlockViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="GeE-5J-ZZO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="center" image="background.png" id="QWe-Gw-rD3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" id="PHH-XC-9QQ" userLabel="View - UI Container">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_spinner.png" id="27q-lX-0vy">
|
||||
<rect key="frame" x="105" y="40" width="110" height="110"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<rect key="frame" x="105" y="46" width="110" height="110"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" id="JTj-nh-BWs" userLabel="Word Wall">
|
||||
<rect key="frame" x="0.0" y="0.0" width="960" height="200"/>
|
||||
@@ -1252,7 +1345,7 @@ L4m3P4sSw0rD</string>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.5" contentMode="left" text="Tap and hold to delete or reset user." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="DBJ-Qi-ZcF">
|
||||
<rect key="frame" x="20" y="460" width="280" height="20"/>
|
||||
<rect key="frame" x="20" y="548" width="280" height="20"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<fontDescription key="fontDescription" name="Copperplate" family="Copperplate" pointSize="12"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="lightTextColor"/>
|
||||
@@ -1444,7 +1537,7 @@ You could use the word wall for inspiration in finding a memorable master passw
|
||||
</connections>
|
||||
</button>
|
||||
<webView opaque="NO" contentMode="scaleToFill" id="rGU-aZ-XVm">
|
||||
<rect key="frame" x="0.0" y="411" width="320" height="44"/>
|
||||
<rect key="frame" x="0.0" y="499" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<dataDetectorType key="dataDetectorTypes"/>
|
||||
@@ -1456,15 +1549,15 @@ You could use the word wall for inspiration in finding a memorable master passw
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view hidden="YES" alpha="0.30000000000000016" contentMode="scaleToFill" id="KNa-Xb-RuE" userLabel="View - Emergency Generator">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
|
||||
<rect key="frame" x="-100" y="0.0" width="520" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" id="vdf-Kn-Sle">
|
||||
<rect key="frame" x="0.0" y="20" width="320" height="346"/>
|
||||
<rect key="frame" x="100" y="20" width="320" height="434"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_panel_display.png" id="jLf-TI-anP">
|
||||
<rect key="frame" x="11" y="0.0" width="298" height="346"/>
|
||||
<rect key="frame" x="11" y="0.0" width="298" height="434"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<rect key="contentStretch" x="0.050000000000000003" y="0.10000000000000001" width="0.89999999999999991" height="0.79999999999999982"/>
|
||||
</imageView>
|
||||
@@ -1563,11 +1656,11 @@ You could use the word wall for inspiration in finding a memorable master passw
|
||||
</connections>
|
||||
</button>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" hidesWhenStopped="YES" style="whiteLarge" id="3Ax-91-gVM">
|
||||
<rect key="frame" x="141.5" y="300" width="37" height="37"/>
|
||||
<rect key="frame" x="141" y="388" width="37" height="37"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</activityIndicatorView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="r9J-C9-Bt1">
|
||||
<rect key="frame" x="20" y="292" width="280" height="54"/>
|
||||
<rect key="frame" x="20" y="380" width="280" height="54"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<fontDescription key="fontDescription" name="AmericanTypewriter-Bold" family="American Typewriter" pointSize="30"/>
|
||||
<size key="titleShadowOffset" width="0.0" height="1"/>
|
||||
@@ -1583,7 +1676,7 @@ You could use the word wall for inspiration in finding a memorable master passw
|
||||
</connections>
|
||||
</button>
|
||||
<view hidden="YES" userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" id="sD9-hR-UAI" userLabel="View - Content Tip">
|
||||
<rect key="frame" x="55" y="266" width="210" height="60"/>
|
||||
<rect key="frame" x="55" y="354" width="210" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black.png" id="Lua-xm-WX6">
|
||||
@@ -1679,11 +1772,11 @@ You could use the word wall for inspiration in finding a memorable master passw
|
||||
<objects>
|
||||
<viewController id="Q4b-t4-pwH" customClass="MPSetupViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="FnB-rI-puV">
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="416"/>
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="center" image="background.png" id="RjU-5e-mti">
|
||||
<rect key="frame" x="0.0" y="-64" width="320" height="480"/>
|
||||
<rect key="frame" x="0.0" y="-64" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" contentMode="top" image="cloud.png" id="Ahr-aa-V1N">
|
||||
@@ -1737,7 +1830,7 @@ If you set a custom password, it will be encrypted before it is saved to the clo
|
||||
<objects>
|
||||
<tableViewController id="idA-Pj-1U9" customClass="MPElementListAllViewController" sceneMemberID="viewController">
|
||||
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="48" sectionHeaderHeight="22" sectionFooterHeight="22" id="N83-sj-4tl">
|
||||
<rect key="frame" x="0.0" y="20" width="320" height="460"/>
|
||||
<rect key="frame" x="0.0" y="20" width="320" height="548"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<navigationBar key="tableHeaderView" contentMode="scaleToFill" id="l0p-Tu-L9k">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
@@ -1776,11 +1869,11 @@ If you set a custom password, it will be encrypted before it is saved to the clo
|
||||
<objects>
|
||||
<viewController wantsFullScreenLayout="YES" id="2Th-Tb-22a" customClass="MPAppsViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="AhE-Ed-ajP">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" id="DHZ-5g-6vT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
|
||||
<rect key="frame" x="0.0" y="44" width="320" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="center" image="book.png" id="wjL-OU-K7k">
|
||||
@@ -1850,7 +1943,7 @@ If you set a custom password, it will be encrypted before it is saved to the clo
|
||||
<objects>
|
||||
<tableViewController id="oLN-6u-GLb" customClass="MPPreferencesViewController" sceneMemberID="viewController">
|
||||
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="none" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="oSh-Ap-kLt">
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="416"/>
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.12549020350000001" green="0.1411764771" blue="0.14901961389999999" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<view key="tableFooterView" contentMode="scaleToFill" id="63M-7L-M7o">
|
||||
@@ -2172,6 +2265,7 @@ If you set a custom password, it will be encrypted before it is saved to the clo
|
||||
<outlet property="defaultTypeLabel" destination="vKJ-1b-NeO" id="4vz-2l-xXk"/>
|
||||
<outlet property="exportCell" destination="X2m-92-Qzh" id="zjs-9C-uKX"/>
|
||||
<outlet property="savePasswordSwitch" destination="ilG-0h-SOb" id="iZD-gQ-pve"/>
|
||||
<segue destination="Tx0-mM-kHk" kind="push" identifier="MP_Logs" id="rWT-Kr-cAs"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="CEl-jQ-l9k" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
@@ -2183,7 +2277,7 @@ If you set a custom password, it will be encrypted before it is saved to the clo
|
||||
<objects>
|
||||
<tableViewController id="Vrp-Gl-7qn" customClass="IASKAppSettingsViewController" sceneMemberID="viewController">
|
||||
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="singleLineEtched" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" id="NCp-ii-ux0">
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="416"/>
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<prototypes>
|
||||
@@ -2267,11 +2361,11 @@ If you set a custom password, it will be encrypted before it is saved to the clo
|
||||
<objects>
|
||||
<viewController id="ZgN-2j-05b" customClass="MPSetupViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="QIH-dS-sqD">
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="416"/>
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="center" image="background.png" id="FTf-06-1Pg">
|
||||
<rect key="frame" x="0.0" y="-64" width="320" height="480"/>
|
||||
<rect key="frame" x="0.0" y="-64" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</imageView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Getting Started" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="FkR-cP-Y7K">
|
||||
@@ -2282,7 +2376,7 @@ If you set a custom password, it will be encrypted before it is saved to the clo
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" usesAttributedText="YES" id="hwP-ds-GDh">
|
||||
<rect key="frame" x="20" y="137" width="280" height="279"/>
|
||||
<rect key="frame" x="20" y="137" width="280" height="367"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<attributedString key="attributedText">
|
||||
@@ -2394,11 +2488,11 @@ You can make passwords for anything, like email addresses, sites or real-world t
|
||||
<objects>
|
||||
<viewController id="myN-X7-9Tg" customClass="MPGuideViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="vkG-Oi-PHo">
|
||||
<rect key="frame" x="0.0" y="20" width="320" height="460"/>
|
||||
<rect key="frame" x="0.0" y="20" width="320" height="548"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="center" image="background.png" id="C2i-R4-36i">
|
||||
<rect key="frame" x="0.0" y="44" width="320" height="416"/>
|
||||
<rect key="frame" x="0.0" y="44" width="320" height="504"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</imageView>
|
||||
<view clipsSubviews="YES" contentMode="scaleToFill" id="vSk-nT-Vwf" userLabel="View - Display">
|
||||
@@ -2538,7 +2632,7 @@ You can make passwords for anything, like email addresses, sites or real-world t
|
||||
</scopeButtonTitles>
|
||||
</searchBar>
|
||||
<view alpha="0.60000000000000009" contentMode="scaleToFill" id="Ahl-o0-lMv">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="548"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="3wI-lo-tWc">
|
||||
@@ -2558,7 +2652,7 @@ You can make passwords for anything, like email addresses, sites or real-world t
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="UHf-cp-97W">
|
||||
<rect key="frame" x="33" y="414" width="44" height="44"/>
|
||||
<rect key="frame" x="33" y="502" width="44" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" hint="" label="Close"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
@@ -2574,7 +2668,7 @@ You can make passwords for anything, like email addresses, sites or real-world t
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="jDS-Vh-ETL">
|
||||
<rect key="frame" x="124" y="190" width="72" height="80"/>
|
||||
<rect key="frame" x="124" y="234" width="72" height="80"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" hint="" label="Close"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
@@ -2590,7 +2684,7 @@ You can make passwords for anything, like email addresses, sites or real-world t
|
||||
</connections>
|
||||
</button>
|
||||
<progressView opaque="NO" contentMode="scaleToFill" id="nf7-oM-7dh">
|
||||
<rect key="frame" x="85" y="431" width="150" height="9"/>
|
||||
<rect key="frame" x="85" y="519" width="150" height="9"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<color key="progressTintColor" red="0.37254901959999998" green="0.3921568627" blue="0.42745098040000001" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</progressView>
|
||||
@@ -2729,11 +2823,11 @@ You can make passwords for anything, like email addresses, sites or real-world t
|
||||
<objects>
|
||||
<viewController id="kSj-yX-DmT" customClass="MPSetupViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="sT4-Jb-e5D">
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="416"/>
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="center" image="background.png" id="Eqt-R0-LTj">
|
||||
<rect key="frame" x="0.0" y="-64" width="320" height="480"/>
|
||||
<rect key="frame" x="0.0" y="-64" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" contentMode="top" image="unlocked.png" id="4ah-P0-2DG">
|
||||
@@ -2869,7 +2963,6 @@ However, it means that anyone who finds your device unlocked can do the same.</s
|
||||
<relationships>
|
||||
<relationship kind="action" name="close"/>
|
||||
<relationship kind="action" name="play"/>
|
||||
<relationship kind="action" name="toggleVolume"/>
|
||||
<relationship kind="outlet" name="content" candidateClass="UIView"/>
|
||||
<relationship kind="outlet" name="contentButton" candidateClass="UIButton"/>
|
||||
<relationship kind="outlet" name="contentText" candidateClass="UITextField"/>
|
||||
@@ -2885,7 +2978,17 @@ However, it means that anyone who finds your device unlocked can do the same.</s
|
||||
<relationship kind="outlet" name="typeTip" candidateClass="UIView"/>
|
||||
<relationship kind="outlet" name="usernameButton" candidateClass="UIButton"/>
|
||||
<relationship kind="outlet" name="usernameTip" candidateClass="UIView"/>
|
||||
<relationship kind="outlet" name="volumeButton" candidateClass="UIButton"/>
|
||||
</relationships>
|
||||
</class>
|
||||
<class className="MPLogsViewController" superclassName="UIViewController">
|
||||
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPLogsViewController.h"/>
|
||||
<relationships>
|
||||
<relationship kind="action" name="close:" candidateClass="UIBarButtonItem"/>
|
||||
<relationship kind="action" name="mail:" candidateClass="UIBarButtonItem"/>
|
||||
<relationship kind="action" name="refresh:" candidateClass="UIBarButtonItem"/>
|
||||
<relationship kind="action" name="toggleLevelControl:" candidateClass="UISegmentedControl"/>
|
||||
<relationship kind="outlet" name="levelControl" candidateClass="UISegmentedControl"/>
|
||||
<relationship kind="outlet" name="logView" candidateClass="UITextView"/>
|
||||
</relationships>
|
||||
</class>
|
||||
<class className="MPMainViewController" superclassName="UIViewController">
|
||||
@@ -3014,7 +3117,7 @@ However, it means that anyone who finds your device unlocked can do the same.</s
|
||||
<simulatedMetricsContainer key="defaultSimulatedMetrics">
|
||||
<nil key="statusBar"/>
|
||||
<simulatedOrientationMetrics key="orientation"/>
|
||||
<simulatedScreenMetrics key="destination"/>
|
||||
<simulatedScreenMetrics key="destination" type="retina4"/>
|
||||
</simulatedMetricsContainer>
|
||||
<inferredMetricsTieBreakers>
|
||||
<segue reference="jgo-j3-gbW"/>
|
||||
|
||||
@@ -39,28 +39,19 @@
|
||||
<string>Icon-72</string>
|
||||
<string>Icon-Small</string>
|
||||
<string>Icon-Small-50</string>
|
||||
<string>Icon.png</string>
|
||||
<string>Icon@2x.png</string>
|
||||
</array>
|
||||
<key>UIPrerenderedIcon</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>UINewsstandIcon</key>
|
||||
<dict>
|
||||
<key>CFBundleIconFiles</key>
|
||||
<array>
|
||||
<string></string>
|
||||
</array>
|
||||
<key>UINewsstandBindingEdge</key>
|
||||
<string>UINewsstandBindingEdgeLeft</string>
|
||||
<key>UINewsstandBindingType</key>
|
||||
<string>UINewsstandBindingTypeMagazine</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.lyndir.lhunath.MasterPassword</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>MasterPassword</string>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
|
||||
@@ -16,10 +16,14 @@
|
||||
93D396BA1C74C4A06FD86437 /* PearlOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D3942A356B639724157982 /* PearlOverlay.h */; };
|
||||
93D3992FA1546E01F498F665 /* PearlNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */; };
|
||||
93D399433EA75E50656040CB /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D394077F8FAB8167647187 /* Twitter.framework */; };
|
||||
93D399A3008C590EE104F856 /* NSURL+UbiquityStoreManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3970B24FC0B53D989F7E3 /* NSURL+UbiquityStoreManager.m */; };
|
||||
93D399BBC0A7EC746CB1B19B /* MPLogsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D391943675426839501BB8 /* MPLogsViewController.h */; };
|
||||
93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; };
|
||||
93D39E281E3658B30550CB55 /* NSDictionary+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */; };
|
||||
93D39EC9C559D2922B048CFE /* NSURL+UbiquityStoreManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D3957F61D8AFE3B6580C32 /* NSURL+UbiquityStoreManager.h */; };
|
||||
93D39F8A9254177891F38705 /* MPSetupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A28369954D147E239BA /* MPSetupViewController.m */; };
|
||||
DA04E33E14B1E70400ECA4F3 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA04E33D14B1E70400ECA4F3 /* MobileCoreServices.framework */; };
|
||||
DA095E75172F4CD8001C948B /* MPLogsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3979190DACEBD1F6AE9F4 /* MPLogsViewController.m */; };
|
||||
DA30E9CE15722ECA00A68B4C /* NSBundle+PearlMutableInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA30E9CB15722ECA00A68B4C /* NSBundle+PearlMutableInfo.h */; };
|
||||
DA30E9CF15722ECA00A68B4C /* NSBundle+PearlMutableInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9CC15722ECA00A68B4C /* NSBundle+PearlMutableInfo.m */; };
|
||||
DA30E9D015722ECA00A68B4C /* Pearl.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9CD15722ECA00A68B4C /* Pearl.m */; };
|
||||
@@ -968,13 +972,17 @@
|
||||
/* Begin PBXFileReference section */
|
||||
93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Indexing.m"; sourceTree = "<group>"; };
|
||||
93D390FADEB325D8D54A957D /* PearlOverlay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlOverlay.m; sourceTree = "<group>"; };
|
||||
93D391943675426839501BB8 /* MPLogsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLogsViewController.h; sourceTree = "<group>"; };
|
||||
93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = "<group>"; };
|
||||
93D393BB973253D4BAAC84AA /* PearlEMail.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlEMail.m; sourceTree = "<group>"; };
|
||||
93D394077F8FAB8167647187 /* Twitter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Twitter.framework; path = System/Library/Frameworks/Twitter.framework; sourceTree = SDKROOT; };
|
||||
93D3942A356B639724157982 /* PearlOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlOverlay.h; sourceTree = "<group>"; };
|
||||
93D3956915634581E737B38C /* PearlNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlNavigationController.m; sourceTree = "<group>"; };
|
||||
93D3957F61D8AFE3B6580C32 /* NSURL+UbiquityStoreManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+UbiquityStoreManager.h"; sourceTree = "<group>"; };
|
||||
93D396D04E57792A54D437AC /* NSArray+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Indexing.h"; sourceTree = "<group>"; };
|
||||
93D3970B24FC0B53D989F7E3 /* NSURL+UbiquityStoreManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+UbiquityStoreManager.m"; sourceTree = "<group>"; };
|
||||
93D39730673227EFF6DEFF19 /* MPSetupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSetupViewController.h; sourceTree = "<group>"; };
|
||||
93D3979190DACEBD1F6AE9F4 /* MPLogsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPLogsViewController.m; sourceTree = "<group>"; };
|
||||
93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlNavigationController.h; sourceTree = "<group>"; };
|
||||
93D39A28369954D147E239BA /* MPSetupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSetupViewController.m; sourceTree = "<group>"; };
|
||||
93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+Indexing.m"; sourceTree = "<group>"; };
|
||||
@@ -997,7 +1005,7 @@
|
||||
DA5A09DE171A70E4005284AB /* play@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "play@2x.png"; sourceTree = "<group>"; };
|
||||
DA5A09E8171BB0F7005284AB /* unlocked.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = unlocked.png; sourceTree = "<group>"; };
|
||||
DA5A09E9171BB0F7005284AB /* unlocked@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "unlocked@2x.png"; sourceTree = "<group>"; };
|
||||
DA5BFA44147E415C00F98B1E /* MasterPassword-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "MasterPassword-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA5BFA44147E415C00F98B1E /* MasterPassword.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MasterPassword.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA5BFA48147E415C00F98B1E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
DA5BFA4A147E415C00F98B1E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
||||
@@ -2131,7 +2139,7 @@
|
||||
DA5BFA45147E415C00F98B1E /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA5BFA44147E415C00F98B1E /* MasterPassword-iOS.app */,
|
||||
DA5BFA44147E415C00F98B1E /* MasterPassword.app */,
|
||||
DAC77CAD148291A600BCF976 /* libPearl.a */,
|
||||
DAC6325D1486805C0075AEA5 /* libuicolor-utilities.a */,
|
||||
DAC6326C148680650075AEA5 /* libjrswizzle.a */,
|
||||
@@ -3007,6 +3015,8 @@
|
||||
DABD3BFC1711E2DC00CF925C /* main.m */,
|
||||
93D39A28369954D147E239BA /* MPSetupViewController.m */,
|
||||
93D39730673227EFF6DEFF19 /* MPSetupViewController.h */,
|
||||
93D3979190DACEBD1F6AE9F4 /* MPLogsViewController.m */,
|
||||
93D391943675426839501BB8 /* MPLogsViewController.h */,
|
||||
);
|
||||
path = iOS;
|
||||
sourceTree = "<group>";
|
||||
@@ -3066,6 +3076,8 @@
|
||||
DACA22B71705DE7D002C6C22 /* UbiquityStoreManager.m */,
|
||||
DACA22B81705DE7D002C6C22 /* NSError+UbiquityStoreManager.h */,
|
||||
DACA22B91705DE7D002C6C22 /* NSError+UbiquityStoreManager.m */,
|
||||
93D3970B24FC0B53D989F7E3 /* NSURL+UbiquityStoreManager.m */,
|
||||
93D3957F61D8AFE3B6580C32 /* NSURL+UbiquityStoreManager.h */,
|
||||
);
|
||||
name = UbiquityStoreManager;
|
||||
path = UbiquityStoreManager/UbiquityStoreManager;
|
||||
@@ -3523,6 +3535,8 @@
|
||||
files = (
|
||||
DACA22BC1705DE7D002C6C22 /* NSError+UbiquityStoreManager.h in Headers */,
|
||||
DACA22BE1705DE7D002C6C22 /* UbiquityStoreManager.h in Headers */,
|
||||
93D399BBC0A7EC746CB1B19B /* MPLogsViewController.h in Headers */,
|
||||
93D39EC9C559D2922B048CFE /* NSURL+UbiquityStoreManager.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -3685,9 +3699,9 @@
|
||||
productReference = DA497B9715E8C90E00B52167 /* libGoogle+.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
DA5BFA43147E415C00F98B1E /* MasterPassword-iOS */ = {
|
||||
DA5BFA43147E415C00F98B1E /* MasterPassword */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword-iOS" */;
|
||||
buildConfigurationList = DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword" */;
|
||||
buildPhases = (
|
||||
DA5BFA40147E415C00F98B1E /* Sources */,
|
||||
DA5BFA41147E415C00F98B1E /* Frameworks */,
|
||||
@@ -3699,9 +3713,9 @@
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "MasterPassword-iOS";
|
||||
name = MasterPassword;
|
||||
productName = MasterPassword;
|
||||
productReference = DA5BFA44147E415C00F98B1E /* MasterPassword-iOS.app */;
|
||||
productReference = DA5BFA44147E415C00F98B1E /* MasterPassword.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
DA829E50159847E0002417D3 /* FontReplacer */ = {
|
||||
@@ -3912,7 +3926,7 @@
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
DA5BFA43147E415C00F98B1E /* MasterPassword-iOS */,
|
||||
DA5BFA43147E415C00F98B1E /* MasterPassword */,
|
||||
DAC77CAC148291A600BCF976 /* Pearl */,
|
||||
DAC6325C1486805C0075AEA5 /* uicolor-utilities */,
|
||||
DAC6326B148680650075AEA5 /* jrswizzle */,
|
||||
@@ -4655,7 +4669,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = "/bin/bash -e";
|
||||
shellScript = "PATH+=:/usr/libexec\n\naddPlistWithKey() {\n local key=$1 type=$2 value=$3 plist=${4:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n \n PlistBuddy -c \"Delete :'$key'\" \"$plist\" 2>/dev/null || true\n PlistBuddy -c \"Add :'$key' '$type' '$value'\" \"$plist\"\n}\nsetPlistWithKey() {\n local key=$1 value=$2 plist=${3:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n \n PlistBuddy -c \"Set :'$key' '$value'\" \"$plist\"\n}\ngetPlistWithKey() {\n local key=$1 plist=${2:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n \n PlistBuddy -c \"Print :'$key'\" \"$plist\"\n}\nsetSettingWithTitle() {\n local i title=$1 value=$2 plist=${3:-\"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Settings.bundle/Root.plist\"}\n \n for (( i=0; 1; ++i )); do\n PlistBuddy -c \"Print :PreferenceSpecifiers:$i\" \"$plist\" &>/dev/null || break\n echo \"Checking preference specifier $i\"\n \n [[ $(PlistBuddy -c \"Print :PreferenceSpecifiers:$i:Title\" \"$plist\" 2>/dev/null) = $title ]] || continue\n \n echo \"Correct title, setting value.\"\n PlistBuddy -c \"Set :PreferenceSpecifiers:$i:DefaultValue $value\" \"$plist\"\n break\n done\n}\n\ndescription=$(git describe --always --dirty --long)\nbuild=${description%-g*} build=${build//-/.}\ntag=${description%%-*}\n\naddPlistWithKey GITDescription string \"$description\"\nsetPlistWithKey CFBundleVersion \"$build\"\nsetPlistWithKey CFBundleShortVersionString \"$tag\"\n\nsetSettingWithTitle \"Build\" \"$build\"\nsetSettingWithTitle \"Version\" \"$tag\"\nsetSettingWithTitle \"Copyright\" \"$(getPlistWithKey NSHumanReadableCopyright)\"\n";
|
||||
shellScript = "PATH+=:/usr/libexec\n\naddPlistWithKey() {\n local key=$1 type=$2 value=$3 plist=${4:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n \n PlistBuddy -c \"Delete :'$key'\" \"$plist\" 2>/dev/null || true\n PlistBuddy -c \"Add :'$key' '$type' '$value'\" \"$plist\"\n}\nsetPlistWithKey() {\n local key=$1 value=$2 plist=${3:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n \n PlistBuddy -c \"Set :'$key' '$value'\" \"$plist\"\n}\ngetPlistWithKey() {\n local key=$1 plist=${2:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n \n PlistBuddy -c \"Print :'$key'\" \"$plist\"\n}\nsetSettingWithTitle() {\n local i title=$1 value=$2 plist=${3:-\"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Settings.bundle/Root.plist\"}\n \n for (( i=0; 1; ++i )); do\n PlistBuddy -c \"Print :PreferenceSpecifiers:$i\" \"$plist\" &>/dev/null || break\n echo \"Checking preference specifier $i\"\n \n [[ $(PlistBuddy -c \"Print :PreferenceSpecifiers:$i:Title\" \"$plist\" 2>/dev/null) = $title ]] || continue\n \n echo \"Correct title, setting value.\"\n PlistBuddy -c \"Set :PreferenceSpecifiers:$i:DefaultValue $value\" \"$plist\"\n break\n done\n}\n\ndescription=$(git describe --always --dirty --long)\ncommit=${description##*-g} commit=$((0x$commit))\nversion=${description%-g*} version=${version//-/.}\n\naddPlistWithKey GITDescription string \"$description\"\nsetPlistWithKey CFBundleVersion \"$commit\"\nsetPlistWithKey CFBundleShortVersionString \"$version\"\n\nsetSettingWithTitle \"Build\" \"$commit\"\nsetSettingWithTitle \"Version\" \"$version\"\nsetSettingWithTitle \"Copyright\" \"$(getPlistWithKey NSHumanReadableCopyright)\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DAD3125D155288AA00A3F9ED /* Run Script: Crashlytics */ = {
|
||||
@@ -4689,6 +4703,7 @@
|
||||
files = (
|
||||
DACA22BB1705DE7D002C6C22 /* UbiquityStoreManager.m in Sources */,
|
||||
DACA22BD1705DE7D002C6C22 /* NSError+UbiquityStoreManager.m in Sources */,
|
||||
93D399A3008C590EE104F856 /* NSURL+UbiquityStoreManager.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -4771,6 +4786,7 @@
|
||||
DABD3C211711E2DC00CF925C /* MPiOSConfig.m in Sources */,
|
||||
DABD3C271711E2DC00CF925C /* main.m in Sources */,
|
||||
93D39F8A9254177891F38705 /* MPSetupViewController.m in Sources */,
|
||||
DA095E75172F4CD8001C948B /* MPLogsViewController.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -4890,7 +4906,7 @@
|
||||
/* Begin PBXTargetDependency section */
|
||||
DA3EF19E15A47AEB003ABF4E /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = DA5BFA43147E415C00F98B1E /* MasterPassword-iOS */;
|
||||
target = DA5BFA43147E415C00F98B1E /* MasterPassword */;
|
||||
targetProxy = DA3EF19D15A47AEB003ABF4E /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
@@ -5084,7 +5100,7 @@
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES;
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
|
||||
GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES;
|
||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
@@ -5154,7 +5170,7 @@
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES;
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
|
||||
GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES;
|
||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
@@ -5279,7 +5295,7 @@
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES;
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
|
||||
GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES;
|
||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
@@ -5563,7 +5579,7 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = "AdHoc-iOS";
|
||||
};
|
||||
DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword-iOS" */ = {
|
||||
DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DA5BFA6E147E415C00F98B1E /* Debug-iOS */,
|
||||
@@ -5631,6 +5647,7 @@
|
||||
DAFC5661172C573B00CB5CC5 /* AppStore-iOS */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = "AdHoc-iOS";
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "MasterPassword-iOS.app"
|
||||
BlueprintName = "MasterPassword-iOS"
|
||||
BuildableName = "MasterPassword.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-iOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
@@ -43,8 +43,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "MasterPassword-iOS.app"
|
||||
BlueprintName = "MasterPassword-iOS"
|
||||
BuildableName = "MasterPassword.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-iOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
@@ -61,8 +61,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "MasterPassword-iOS.app"
|
||||
BlueprintName = "MasterPassword-iOS"
|
||||
BuildableName = "MasterPassword.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-iOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "MasterPassword-iOS.app"
|
||||
BlueprintName = "MasterPassword-iOS"
|
||||
BuildableName = "MasterPassword.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-iOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
@@ -33,8 +33,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "MasterPassword-iOS.app"
|
||||
BlueprintName = "MasterPassword-iOS"
|
||||
BuildableName = "MasterPassword.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-iOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
@@ -52,8 +52,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "MasterPassword-iOS.app"
|
||||
BlueprintName = "MasterPassword-iOS"
|
||||
BuildableName = "MasterPassword.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-iOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
@@ -70,8 +70,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "MasterPassword-iOS.app"
|
||||
BlueprintName = "MasterPassword-iOS"
|
||||
BuildableName = "MasterPassword.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-iOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
|
||||
2
Press
2
Press
Submodule Press updated: 59d660c6de...88f1de4ef2
Reference in New Issue
Block a user