2
0

Improved migration, file-based StoreUUID, Mac fixes.

[ADDED]     Migration to file-based StoreUUID.
[IMPROVED]  Cleaner, more modular, migration code.
[FIXED]     Don't hook activation to show password window: too annoying when focus shifts.
[FIXED]     Don't set the active user when just importing ubiquity changes, it causes a log-out.
[ADDED]     Mac: Ability to rebuild iCloud.
[REMOVED]   Mac: wasRunning logic to avoid password window appearance on first activation.
[FIXED]     Mac: Retrieve siteName from main thread.
This commit is contained in:
Maarten Billemont 2013-05-10 11:13:55 -04:00
parent c36f34346d
commit 71e3f44c8c
11 changed files with 446 additions and 141 deletions

@ -1 +1 @@
Subproject commit 2586f75779570ae43442ed52a82ac0acb55caa01 Subproject commit 226619a45744dd4aefbbdb948d7e44ab3ecad341

View File

@ -15,19 +15,22 @@
#define STORE_OPTIONS #define STORE_OPTIONS
#endif #endif
#define MPCloudContainerIdentifier @"HL3Q45LX9N.com.lyndir.lhunath.MasterPassword.shared"
#define MPMigrationLevelLocalStoreKey @"MPMigrationLevelLocalStoreKey" #define MPMigrationLevelLocalStoreKey @"MPMigrationLevelLocalStoreKey"
typedef enum {
MPMigrationLevelLocalStoreV13,
MPMigrationLevelLocalStoreV14,
MPMigrationLevelLocalStoreCurrent = MPMigrationLevelLocalStoreV14,
} MPMigrationLevelLocalStore;
#define MPMigrationLevelCloudStoreKey @"MPMigrationLevelCloudStoreKey" #define MPMigrationLevelCloudStoreKey @"MPMigrationLevelCloudStoreKey"
typedef enum {
MPMigrationLevelCloudStoreV13, typedef NS_ENUM(NSInteger, MPMigrationLevelLocalStore) {
MPMigrationLevelCloudStoreV14, MPMigrationLevelLocalStoreV1,
MPMigrationLevelCloudStoreCurrent = MPMigrationLevelCloudStoreV14, MPMigrationLevelLocalStoreV2,
} MPMigrationLevelCloudStore; MPMigrationLevelLocalStoreCurrent = MPMigrationLevelLocalStoreV2,
};
typedef NS_ENUM(NSInteger, MPMigrationLevelCloudStore) {
MPMigrationLevelCloudStoreV1,
MPMigrationLevelCloudStoreV2,
MPMigrationLevelCloudStoreV3,
MPMigrationLevelCloudStoreCurrent = MPMigrationLevelCloudStoreV3,
};
@implementation MPAppDelegate_Shared(Store) @implementation MPAppDelegate_Shared(Store)
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
@ -35,7 +38,7 @@ typedef enum {
PearlAssociatedObjectProperty(PearlAlert*, FixCloudContentAlert, fixCloudContentAlert); PearlAssociatedObjectProperty(PearlAlert*, FixCloudContentAlert, fixCloudContentAlert);
PearlAssociatedObjectProperty(PearlOverlay*, StoreLoading, storeLoading); PearlAssociatedObjectProperty(PearlOverlay*, StoreLoading, storeLoading);
#endif #endif
PearlAssociatedObjectProperty(NSManagedObjectContext*, PrivateManagedObjectContext, privateManagedObjectContext); PearlAssociatedObjectProperty(NSManagedObjectContext*, PrivateManagedObjectContext, privateManagedObjectContext);
PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext, mainManagedObjectContext); PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext, mainManagedObjectContext);
@ -49,7 +52,8 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
if ([[NSThread currentThread] isMainThread]) if ([[NSThread currentThread] isMainThread])
return mainManagedObjectContext; return mainManagedObjectContext;
NSManagedObjectContext *threadManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType]; NSManagedObjectContext
*threadManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
threadManagedObjectContext.parentContext = mainManagedObjectContext; threadManagedObjectContext.parentContext = mainManagedObjectContext;
return threadManagedObjectContext; return threadManagedObjectContext;
@ -104,7 +108,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
return storeManager; return storeManager;
storeManager = [[UbiquityStoreManager alloc] initStoreNamed:nil withManagedObjectModel:nil localStoreURL:nil storeManager = [[UbiquityStoreManager alloc] initStoreNamed:nil withManagedObjectModel:nil localStoreURL:nil
containerIdentifier:@"HL3Q45LX9N.com.lyndir.lhunath.MasterPassword.shared" containerIdentifier:MPCloudContainerIdentifier
additionalStoreOptions:@{ STORE_OPTIONS } additionalStoreOptions:@{ STORE_OPTIONS }
delegate:self]; delegate:self];
@ -132,40 +136,113 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
- (void)migrateStoreForManager:(UbiquityStoreManager *)manager isCloud:(BOOL)isCloudStore { - (void)migrateStoreForManager:(UbiquityStoreManager *)manager isCloud:(BOOL)isCloudStore {
[self migrateLocalStoreForManager:manager]; [self migrateLocalStore];
if (isCloudStore) if (isCloudStore)
[self migrateCloudStoreForManager:manager]; [self migrateCloudStore];
} }
- (void)migrateLocalStoreForManager:(UbiquityStoreManager *)manager { - (void)migrateLocalStore {
MPMigrationLevelLocalStore migrationLevel = (unsigned)[[NSUserDefaults standardUserDefaults] integerForKey:@"MPMigrationLevelLocalStore"]; MPMigrationLevelLocalStore migrationLevel = (signed)[[NSUserDefaults standardUserDefaults] integerForKey:MPMigrationLevelLocalStoreKey];
if (migrationLevel >= MPMigrationLevelLocalStoreCurrent) if (migrationLevel >= MPMigrationLevelLocalStoreCurrent)
// Local store up-to-date. // Local store up-to-date.
return; 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] NSURL *applicationFilesDirectory = [[[NSFileManager defaultManager]
URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *oldLocalStoreURL = [[applicationFilesDirectory NSURL *oldLocalStoreURL = [[applicationFilesDirectory
URLByAppendingPathComponent:@"MasterPassword" isDirectory:NO] URLByAppendingPathExtension:@"sqlite"]; 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]) { if (![[NSFileManager defaultManager] fileExistsAtPath:oldLocalStoreURL.path isDirectory:NO]) {
// No local store to migrate. inf(@"No V1 local store to migrate.");
[[NSUserDefaults standardUserDefaults] setInteger:MPMigrationLevelLocalStoreCurrent forKey:MPMigrationLevelLocalStoreKey]; return;
return; }
}
if ([[NSFileManager defaultManager] fileExistsAtPath:newLocalStoreURL.path isDirectory:NO]) { inf(@"Migrating V1 local store");
wrn(@"Can't migrate old local store: A new local store already exists."); [self migrateFromLocalStore:oldLocalStoreURL];
[[NSUserDefaults standardUserDefaults] setInteger:MPMigrationLevelLocalStoreCurrent forKey:MPMigrationLevelLocalStoreKey]; }
- (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; return;
} }
inf(@"Migrating local store...");
NSError *error = nil; NSError *error = nil;
NSDictionary *oldLocalStoreOptions = @{ NSDictionary *oldLocalStoreOptions = @{
STORE_OPTIONS STORE_OPTIONS
@ -179,78 +256,38 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
}; };
// Create the directory to hold the new local store. // Create the directory to hold the new local store.
if (![[NSFileManager defaultManager] createDirectoryAtPath:[manager URLForLocalStoreDirectory].path if (![[NSFileManager defaultManager] createDirectoryAtPath:[self.storeManager URLForLocalStoreDirectory].path
withIntermediateDirectories:YES attributes:nil error:&error]) { withIntermediateDirectories:YES attributes:nil error:&error])
err(@"While creating directory for new local store: %@", error); err(@"While creating directory for new local store: %@", error);
manager.localStoreURL = oldLocalStoreURL;
return;
}
if (![manager copyMigrateStore:oldLocalStoreURL withOptions:oldLocalStoreOptions if (![self.storeManager copyMigrateStore:oldLocalStoreURL withOptions:oldLocalStoreOptions
toStore:newLocalStoreURL withOptions:newLocalStoreOptions toStore:newLocalStoreURL withOptions:newLocalStoreOptions
error:nil cause:nil context:nil]) { error:nil cause:nil context:nil])
manager.localStoreURL = oldLocalStoreURL;
return; return;
}
[[NSUserDefaults standardUserDefaults] setInteger:MPMigrationLevelLocalStoreCurrent forKey:MPMigrationLevelLocalStoreKey]; inf(@"Successfully migrated to new local store.");
inf(@"Successfully migrated old to new local store.");
} }
- (void)migrateCloudStoreForManager:(UbiquityStoreManager *)manager { - (void)migrateFromCloudStore:(NSURL *)oldCloudStoreURL cloudContent:(NSURL *)oldCloudContentURL contentName:(NSString *)contentName {
MPMigrationLevelCloudStore migrationLevel = (unsigned)[[NSUserDefaults standardUserDefaults] integerForKey:@"MPMigrationLevelCloudStore"]; if (![self.storeManager cloudSafeForSeeding]) {
if (migrationLevel >= MPMigrationLevelCloudStoreCurrent) inf(@"Can't migrate cloud store: A new cloud store already exists.");
// Cloud store up-to-date.
return;
// 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.
[[NSUserDefaults standardUserDefaults] setInteger:MPMigrationLevelCloudStoreCurrent forKey:MPMigrationLevelCloudStoreKey];
return; return;
} }
if (![manager cloudSafeForSeeding]) { NSURL *newCloudStoreURL = [self.storeManager URLForCloudStore];
wrn(@"Can't migrate old cloud store: A new cloud store already exists."); NSURL *newCloudContentURL = [self.storeManager URLForCloudContent];
[[NSUserDefaults standardUserDefaults] setInteger:MPMigrationLevelCloudStoreCurrent forKey:MPMigrationLevelCloudStoreKey];
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"]);
NSError *error = nil; NSError *error = nil;
NSDictionary *oldCloudStoreOptions = @{ NSDictionary *oldCloudStoreOptions = @{
STORE_OPTIONS STORE_OPTIONS
// This is here in an attempt to have iCloud recreate the old store file from NSPersistentStoreUbiquitousContentNameKey : contentName,
// 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,
NSPersistentStoreUbiquitousContentURLKey : oldCloudContentURL, NSPersistentStoreUbiquitousContentURLKey : oldCloudContentURL,
// So instead, we'll just open up the old store as read-only, if it exists.
NSReadOnlyPersistentStoreOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES NSInferMappingModelAutomaticallyOption : @YES
}; };
NSDictionary *newCloudStoreOptions = @{ NSDictionary *newCloudStoreOptions = @{
STORE_OPTIONS STORE_OPTIONS
NSPersistentStoreUbiquitousContentNameKey : [manager valueForKey:@"contentName"], NSPersistentStoreUbiquitousContentNameKey : [self.storeManager valueForKey:@"contentName"],
NSPersistentStoreUbiquitousContentURLKey : newCloudContentURL, NSPersistentStoreUbiquitousContentURLKey : newCloudContentURL,
NSMigratePersistentStoresAutomaticallyOption : @YES, NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES NSInferMappingModelAutomaticallyOption : @YES
@ -258,24 +295,25 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
// Create the directory to hold the new cloud store. // 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. // 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 if (![[NSFileManager defaultManager] createDirectoryAtPath:[oldCloudStoreURL URLByDeletingLastPathComponent].path
withIntermediateDirectories:YES attributes:nil error:&error]) { withIntermediateDirectories:YES attributes:nil error:&error])
err(@"While creating directory for old cloud store: %@", error); err(@"While creating directory for old cloud store: %@", error);
return; if (![[NSFileManager defaultManager] createDirectoryAtPath:oldCloudContentURL.path
} withIntermediateDirectories:YES attributes:nil error:&error])
if (![[NSFileManager defaultManager] createDirectoryAtPath:[manager URLForCloudStoreDirectory].path err(@"While creating directory for old cloud content: %@", error);
withIntermediateDirectories:YES attributes:nil error:&error]) { if (![[NSFileManager defaultManager] createDirectoryAtPath:[self.storeManager URLForCloudStoreDirectory].path
err(@"While creating directory for new cloud store: %@", error); withIntermediateDirectories:YES attributes:nil error:&error])
return; 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 if (![self.storeManager copyMigrateStore:oldCloudStoreURL withOptions:oldCloudStoreOptions
toStore:newCloudStoreURL withOptions:newCloudStoreOptions toStore:newCloudStoreURL withOptions:newCloudStoreOptions
error:nil cause:nil context:nil]) error:nil cause:nil context:nil])
return; return;
[[NSUserDefaults standardUserDefaults] setInteger:MPMigrationLevelCloudStoreCurrent forKey:MPMigrationLevelCloudStoreKey]; inf(@"Successfully migrated to new cloud store.");
inf(@"Successfully migrated old to new cloud store.");
} }
#pragma mark - UbiquityStoreManagerDelegate #pragma mark - UbiquityStoreManagerDelegate
@ -314,10 +352,25 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
} ); } );
// Create our contexts. // Create our contexts.
NSManagedObjectContext *privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; NSManagedObjectContext
*privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[privateManagedObjectContext performBlockAndWait:^{ [privateManagedObjectContext performBlockAndWait:^{
privateManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; privateManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
privateManagedObjectContext.persistentStoreCoordinator = coordinator; 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]; NSManagedObjectContext *mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

View File

@ -25,9 +25,11 @@
@property(nonatomic, weak) IBOutlet NSMenuItem *dialogStyleRegular; @property(nonatomic, weak) IBOutlet NSMenuItem *dialogStyleRegular;
@property(nonatomic, weak) IBOutlet NSMenuItem *dialogStyleHUD; @property(nonatomic, weak) IBOutlet NSMenuItem *dialogStyleHUD;
- (IBAction)showPasswordWindow;
- (IBAction)activate:(id)sender; - (IBAction)activate:(id)sender;
- (IBAction)togglePreference:(NSMenuItem *)sender; - (IBAction)togglePreference:(NSMenuItem *)sender;
- (IBAction)newUser:(NSMenuItem *)sender; - (IBAction)newUser:(NSMenuItem *)sender;
- (IBAction)lock:(id)sender; - (IBAction)lock:(id)sender;
- (IBAction)rebuildCloud:(id)sender;
@end @end

View File

@ -11,12 +11,6 @@
#import "MPAppDelegate_Store.h" #import "MPAppDelegate_Store.h"
#import <Carbon/Carbon.h> #import <Carbon/Carbon.h>
@interface MPMacAppDelegate()
@property(nonatomic) BOOL wasRunning;
@end
@implementation MPMacAppDelegate @implementation MPMacAppDelegate
#pragma clang diagnostic push #pragma clang diagnostic push
@ -46,7 +40,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
// Check which hotkey this was. // Check which hotkey this was.
if (hotKeyID.signature == MPShowHotKey.signature && hotKeyID.id == MPShowHotKey.id) { if (hotKeyID.signature == MPShowHotKey.signature && hotKeyID.id == MPShowHotKey.id) {
[((__bridge MPMacAppDelegate *)userData) activate:nil]; [((__bridge MPMacAppDelegate *)userData) showPasswordWindow];
return noErr; return noErr;
} }
if (hotKeyID.signature == MPLockHotKey.signature && hotKeyID.id == MPLockHotKey.id) { if (hotKeyID.signature == MPLockHotKey.signature && hotKeyID.id == MPLockHotKey.id) {
@ -92,15 +86,18 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
@"Then give iCloud some time to sync the new user to your Mac."; @"Then give iCloud some time to sync the new user to your Mac.";
} }
MPUserEntity *activeUser = self.activeUserForThread;
for (MPUserEntity *user in users) { for (MPUserEntity *user in users) {
NSMenuItem *userItem = [[NSMenuItem alloc] initWithTitle:user.name action:@selector(selectUser:) keyEquivalent:@""]; NSMenuItem *userItem = [[NSMenuItem alloc] initWithTitle:user.name action:@selector(selectUser:) keyEquivalent:@""];
[userItem setTarget:self]; [userItem setTarget:self];
[userItem setRepresentedObject:[user objectID]]; [userItem setRepresentedObject:[user objectID]];
[[self.usersItem submenu] addItem:userItem]; [[self.usersItem submenu] addItem:userItem];
if ([user.name isEqualToString:[MPMacConfig get].usedUserName]) if (!activeUser && [user.name isEqualToString:[MPMacConfig get].usedUserName])
[self selectUser:userItem]; [self selectUser:userItem];
} }
[self updateMenuItems];
} }
- (void)selectUser:(NSMenuItem *)item { - (void)selectUser:(NSMenuItem *)item {
@ -192,6 +189,16 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
self.key = nil; 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 { - (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)oldValue {
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
@ -347,20 +354,16 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
- (void)applicationDidBecomeActive:(NSNotification *)notification { - (void)applicationDidBecomeActive:(NSNotification *)notification {
[self showPasswordWindow]; // [self showPasswordWindow];
} }
- (void)showPasswordWindow { - (IBAction)showPasswordWindow {
// Don't show window if we weren't already running (ie. if we haven't been activated before). // Don't show window if we weren't already running (ie. if we haven't been activated before).
if (!self.wasRunning) if (!self.passwordWindow)
self.wasRunning = YES; self.passwordWindow = [[MPPasswordWindowController alloc] initWithWindowNibName:@"MPPasswordWindowController"];
else {
if (!self.passwordWindow)
self.passwordWindow = [[MPPasswordWindowController alloc] initWithWindowNibName:@"MPPasswordWindowController"];
[self.passwordWindow showWindow:self]; [self.passwordWindow showWindow:self];
}
} }
- (void)applicationWillResignActive:(NSNotification *)notification { - (void)applicationWillResignActive:(NSNotification *)notification {

View File

@ -53,6 +53,8 @@
// } forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil]; // } forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserverForName:NSWindowDidBecomeKeyNotification object:self.window queue:nil usingBlock:^(NSNotification *note) { addObserverForName:NSWindowDidBecomeKeyNotification object:self.window queue:nil usingBlock:^(NSNotification *note) {
if (![MPMacAppDelegate managedObjectContextForThreadIfReady])
[self waitUntilStoreLoaded];
if (!self.inProgress) if (!self.inProgress)
[self unlock]; [self unlock];
[self.siteField selectText:self]; [self.siteField selectText:self];
@ -66,10 +68,17 @@
_activeElementOID = nil; _activeElementOID = nil;
[self.window close]; [self.window close];
}]; }];
[[NSNotificationCenter defaultCenter]
addObserverForName:UbiquityManagedStoreDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
[self waitUntilStoreLoaded];
}];
[super windowDidLoad]; [super windowDidLoad];
} }
- (void)waitUntilStoreLoaded {
}
- (void)unlock { - (void)unlock {
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady]; NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
@ -323,12 +332,12 @@
- (void)trySiteWithAction:(BOOL)doAction { - (void)trySiteWithAction:(BOOL)doAction {
NSString *siteName = [self.siteField stringValue];
[self.backgroundQueue addOperationWithBlock:^{ [self.backgroundQueue addOperationWithBlock:^{
NSString *content = [[self activeElementForThread].content description]; NSString *content = [[self activeElementForThread].content description];
if (!content) if (!content)
content = @""; content = @"";
NSString *siteName = [self.siteField stringValue];
dbg(@"name: %@, action: %d", siteName, doAction); dbg(@"name: %@, action: %d", siteName, doAction);
if (doAction) { if (doAction) {
if ([content length]) { if ([content length]) {

View File

@ -27,6 +27,8 @@
DA3EF17B15A47744003ABF4E /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3EF17A15A47744003ABF4E /* SenTestingKit.framework */; }; DA3EF17B15A47744003ABF4E /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3EF17A15A47744003ABF4E /* SenTestingKit.framework */; };
DA3EF17D15A47744003ABF4E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; }; DA3EF17D15A47744003ABF4E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
DA4425CC1557BED40052177D /* 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 */; }; DA4DA1D91564471A00F6F596 /* libjrswizzle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC6326C148680650075AEA5 /* libjrswizzle.a */; };
DA5E5C8817248AA1003798D8 /* crypto_aesctr.h in Headers */ = {isa = PBXBuildFile; fileRef = DA5E5C7B17248AA1003798D8 /* crypto_aesctr.h */; }; 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 */; }; DA5E5C8917248AA1003798D8 /* crypto_scrypt.h in Headers */ = {isa = PBXBuildFile; fileRef = DA5E5C7C17248AA1003798D8 /* crypto_scrypt.h */; };
@ -201,6 +203,8 @@
DA3EF17915A47744003ABF4E /* Tests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; 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; }; 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; }; DA4425CB1557BED40052177D /* libUbiquityStoreManager.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libUbiquityStoreManager.a; 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; }; 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; }; 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; }; DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
@ -577,6 +581,8 @@
DACA22B61705DE7D002C6C22 /* UbiquityStoreManager */ = { DACA22B61705DE7D002C6C22 /* UbiquityStoreManager */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
DA4C45F2173B57B700745CC5 /* NSURL+UbiquityStoreManager.h */,
DA4C45F3173B57B700745CC5 /* NSURL+UbiquityStoreManager.m */,
DACA22BA1705DE7D002C6C22 /* UbiquityStoreManager.h */, DACA22BA1705DE7D002C6C22 /* UbiquityStoreManager.h */,
DACA22B71705DE7D002C6C22 /* UbiquityStoreManager.m */, DACA22B71705DE7D002C6C22 /* UbiquityStoreManager.m */,
DACA22B81705DE7D002C6C22 /* NSError+UbiquityStoreManager.h */, DACA22B81705DE7D002C6C22 /* NSError+UbiquityStoreManager.h */,
@ -800,6 +806,7 @@
files = ( files = (
DACA22BC1705DE7D002C6C22 /* NSError+UbiquityStoreManager.h in Headers */, DACA22BC1705DE7D002C6C22 /* NSError+UbiquityStoreManager.h in Headers */,
DACA22BE1705DE7D002C6C22 /* UbiquityStoreManager.h in Headers */, DACA22BE1705DE7D002C6C22 /* UbiquityStoreManager.h in Headers */,
DA4C45F4173B57B700745CC5 /* NSURL+UbiquityStoreManager.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -1116,6 +1123,7 @@
files = ( files = (
DACA22BB1705DE7D002C6C22 /* UbiquityStoreManager.m in Sources */, DACA22BB1705DE7D002C6C22 /* UbiquityStoreManager.m in Sources */,
DACA22BD1705DE7D002C6C22 /* NSError+UbiquityStoreManager.m in Sources */, DACA22BD1705DE7D002C6C22 /* NSError+UbiquityStoreManager.m in Sources */,
DA4C45F5173B57B700745CC5 /* NSURL+UbiquityStoreManager.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -48,6 +48,13 @@
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj"> ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "CA_DEBUG_TRANSACTIONS"
value = "1"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
<AdditionalOptions> <AdditionalOptions>
</AdditionalOptions> </AdditionalOptions>
</LaunchAction> </LaunchAction>

View File

@ -201,6 +201,41 @@
</array> </array>
</object> </object>
</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> </array>
<bool key="NSNoAutoenable">YES</bool> <bool key="NSNoAutoenable">YES</bool>
</object> </object>
@ -288,14 +323,6 @@
</object> </object>
<int key="connectionID">731</int> <int key="connectionID">731</int>
</object> </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="IBConnectionRecord">
<object class="IBOutletConnection" key="connection"> <object class="IBOutletConnection" key="connection">
<string key="label">useICloudItem</string> <string key="label">useICloudItem</string>
@ -408,6 +435,22 @@
</object> </object>
<int key="connectionID">774</int> <int key="connectionID">774</int>
</object> </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> </array>
<object class="IBMutableOrderedSet" key="objectRecords"> <object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects"> <array key="orderedObjects">
@ -503,6 +546,7 @@
<reference ref="110488020"/> <reference ref="110488020"/>
<reference ref="123831322"/> <reference ref="123831322"/>
<reference ref="123543264"/> <reference ref="123543264"/>
<reference ref="939693094"/>
</array> </array>
<reference key="parent" ref="851296005"/> <reference key="parent" ref="851296005"/>
</object> </object>
@ -590,6 +634,33 @@
<reference key="object" ref="117792016"/> <reference key="object" ref="117792016"/>
<reference key="parent" ref="293904698"/> <reference key="parent" ref="293904698"/>
</object> </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> </array>
</object> </object>
<dictionary class="NSMutableDictionary" key="flattenedProperties"> <dictionary class="NSMutableDictionary" key="flattenedProperties">
@ -628,14 +699,158 @@
<string key="766.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> <string key="766.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="767.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="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>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/> <dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/> <nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/> <dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/> <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>
<object class="IBClassDescriber" key="IBDocument.Classes"/>
<int key="IBDocument.localizationMode">0</int> <int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string> <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies"> <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">

View File

@ -849,16 +849,16 @@
} ); } );
} }
}]; }];
MPCheckpoint( MPCheckpointUseType, @{
@"type" : element.typeName,
@"version" : @(element.version)
} );
} }
[self.searchDisplayController setActive:NO animated:YES]; [self.searchDisplayController setActive:NO animated:YES];
self.searchDisplayController.searchBar.text = element.name; self.searchDisplayController.searchBar.text = element.name;
MPCheckpoint( MPCheckpointUseType, @{
@"type" : element.typeName,
@"version" : @(element.version)
} );
[self updateAnimated:YES]; [self updateAnimated:YES];
} }

View File

@ -1356,7 +1356,7 @@ L4m3P4sSw0rD</string>
<rect key="frame" x="0.0" y="16" width="320" height="340"/> <rect key="frame" x="0.0" y="16" width="320" height="340"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<subviews> <subviews>
<button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" showsTouchWhenHighlighted="YES" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="Ten-ig-gog"> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" showsTouchWhenHighlighted="YES" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="Ten-ig-gog">
<rect key="frame" x="105" y="30" width="110" height="110"/> <rect key="frame" x="105" y="30" width="110" height="110"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="calibratedRGB"/> <color key="backgroundColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>

View File

@ -16,9 +16,11 @@
93D396BA1C74C4A06FD86437 /* PearlOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D3942A356B639724157982 /* PearlOverlay.h */; }; 93D396BA1C74C4A06FD86437 /* PearlOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D3942A356B639724157982 /* PearlOverlay.h */; };
93D3992FA1546E01F498F665 /* PearlNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */; }; 93D3992FA1546E01F498F665 /* PearlNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */; };
93D399433EA75E50656040CB /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D394077F8FAB8167647187 /* Twitter.framework */; }; 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 */; }; 93D399BBC0A7EC746CB1B19B /* MPLogsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D391943675426839501BB8 /* MPLogsViewController.h */; };
93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.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 */; }; 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 */; }; 93D39F8A9254177891F38705 /* MPSetupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A28369954D147E239BA /* MPSetupViewController.m */; };
DA04E33E14B1E70400ECA4F3 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA04E33D14B1E70400ECA4F3 /* MobileCoreServices.framework */; }; DA04E33E14B1E70400ECA4F3 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA04E33D14B1E70400ECA4F3 /* MobileCoreServices.framework */; };
DA095E75172F4CD8001C948B /* MPLogsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3979190DACEBD1F6AE9F4 /* MPLogsViewController.m */; }; DA095E75172F4CD8001C948B /* MPLogsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3979190DACEBD1F6AE9F4 /* MPLogsViewController.m */; };
@ -976,7 +978,9 @@
93D394077F8FAB8167647187 /* Twitter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Twitter.framework; path = System/Library/Frameworks/Twitter.framework; sourceTree = SDKROOT; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlNavigationController.h; sourceTree = "<group>"; };
@ -3072,6 +3076,8 @@
DACA22B71705DE7D002C6C22 /* UbiquityStoreManager.m */, DACA22B71705DE7D002C6C22 /* UbiquityStoreManager.m */,
DACA22B81705DE7D002C6C22 /* NSError+UbiquityStoreManager.h */, DACA22B81705DE7D002C6C22 /* NSError+UbiquityStoreManager.h */,
DACA22B91705DE7D002C6C22 /* NSError+UbiquityStoreManager.m */, DACA22B91705DE7D002C6C22 /* NSError+UbiquityStoreManager.m */,
93D3970B24FC0B53D989F7E3 /* NSURL+UbiquityStoreManager.m */,
93D3957F61D8AFE3B6580C32 /* NSURL+UbiquityStoreManager.h */,
); );
name = UbiquityStoreManager; name = UbiquityStoreManager;
path = UbiquityStoreManager/UbiquityStoreManager; path = UbiquityStoreManager/UbiquityStoreManager;
@ -3530,6 +3536,7 @@
DACA22BC1705DE7D002C6C22 /* NSError+UbiquityStoreManager.h in Headers */, DACA22BC1705DE7D002C6C22 /* NSError+UbiquityStoreManager.h in Headers */,
DACA22BE1705DE7D002C6C22 /* UbiquityStoreManager.h in Headers */, DACA22BE1705DE7D002C6C22 /* UbiquityStoreManager.h in Headers */,
93D399BBC0A7EC746CB1B19B /* MPLogsViewController.h in Headers */, 93D399BBC0A7EC746CB1B19B /* MPLogsViewController.h in Headers */,
93D39EC9C559D2922B048CFE /* NSURL+UbiquityStoreManager.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -4696,6 +4703,7 @@
files = ( files = (
DACA22BB1705DE7D002C6C22 /* UbiquityStoreManager.m in Sources */, DACA22BB1705DE7D002C6C22 /* UbiquityStoreManager.m in Sources */,
DACA22BD1705DE7D002C6C22 /* NSError+UbiquityStoreManager.m in Sources */, DACA22BD1705DE7D002C6C22 /* NSError+UbiquityStoreManager.m in Sources */,
93D399A3008C590EE104F856 /* NSURL+UbiquityStoreManager.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -5092,7 +5100,7 @@
GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 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_INVALID_OFFSETOF_MACRO = YES;
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
@ -5162,7 +5170,7 @@
GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 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_INVALID_OFFSETOF_MACRO = YES;
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
@ -5287,7 +5295,7 @@
GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 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_INVALID_OFFSETOF_MACRO = YES;
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES;