Mac support for preferences: rememberKey, saveKey, useICloud.
[ADDED] OS X: Lots of warning checks when compiling. [ADDED] OS X: Ability to enable and disable iCloud. [ADDED] OS X: Support for rememberKey & saveKey. [UPDATED] storeKey -> saveKey: makes more sense to people. [IMPROVED] OS X: Password display window fancier.
This commit is contained in:
parent
1b90c9bfa3
commit
7c5cea9c8d
2
External/Pearl
vendored
2
External/Pearl
vendored
@ -1 +1 @@
|
||||
Subproject commit a78cd7daf1fae0fc9e86702de9b9f6d5782ae352
|
||||
Subproject commit a8346d6715eb258d11d41a4775e8f1abee620312
|
@ -6093,7 +6093,12 @@
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_CXX0X_EXTENSIONS = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
|
||||
CLANG_WARN_OBJCPP_ARC_ABI = YES;
|
||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
@ -6104,10 +6109,32 @@
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
|
||||
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_INVALID_OFFSETOF_MACRO = YES;
|
||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = YES;
|
||||
GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
|
||||
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
|
||||
GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
|
||||
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
|
||||
GCC_WARN_MISSING_PARENTHESES = YES;
|
||||
GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
|
||||
GCC_WARN_SIGN_COMPARE = YES;
|
||||
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = NO;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = YES;
|
||||
GCC_WARN_UNUSED_LABEL = YES;
|
||||
GCC_WARN_UNUSED_VALUE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
LD_DYLIB_INSTALL_NAME = "@rpath/$(EXECUTABLE_PATH)";
|
||||
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
|
||||
@ -6125,15 +6152,42 @@
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_CXX0X_EXTENSIONS = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
|
||||
CLANG_WARN_OBJCPP_ARC_ABI = YES;
|
||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
|
||||
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_INVALID_OFFSETOF_MACRO = YES;
|
||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = YES;
|
||||
GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
|
||||
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
|
||||
GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
|
||||
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
|
||||
GCC_WARN_MISSING_PARENTHESES = YES;
|
||||
GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
|
||||
GCC_WARN_SIGN_COMPARE = YES;
|
||||
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = YES;
|
||||
GCC_WARN_UNUSED_LABEL = YES;
|
||||
GCC_WARN_UNUSED_VALUE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
LD_DYLIB_INSTALL_NAME = "@rpath/$(EXECUTABLE_PATH)";
|
||||
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
|
||||
@ -6209,6 +6263,7 @@
|
||||
DA79A9F5155821E500BAA07A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
DAB8D982150374AC00CED3BC /* Build configuration list for PBXProject "MasterPassword-Mac" */ = {
|
||||
isa = XCConfigurationList;
|
||||
|
@ -17,7 +17,7 @@ static NSDictionary *keyQuery() {
|
||||
static NSDictionary *MPKeyQuery = nil;
|
||||
if (!MPKeyQuery)
|
||||
MPKeyQuery = [PearlKeyChain createQueryForClass:kSecClassGenericPassword
|
||||
attributes:[NSDictionary dictionaryWithObject:@"Stored Master Password"
|
||||
attributes:[NSDictionary dictionaryWithObject:@"Saved Master Password"
|
||||
forKey:(__bridge id)kSecAttrService]
|
||||
matches:nil];
|
||||
|
||||
@ -38,7 +38,7 @@ static NSDictionary *keyHashQuery() {
|
||||
|
||||
- (void)forgetKey {
|
||||
|
||||
dbg(@"Deleting master key and hash from key chain.");
|
||||
dbg(@"Deleting key and hash from key chain.");
|
||||
[PearlKeyChain deleteItemForQuery:keyQuery()];
|
||||
[PearlKeyChain deleteItemForQuery:keyHashQuery()];
|
||||
|
||||
@ -55,15 +55,15 @@ static NSDictionary *keyHashQuery() {
|
||||
|
||||
- (void)loadStoredKey {
|
||||
|
||||
if ([[MPConfig get].storeKey boolValue]) {
|
||||
if ([[MPConfig get].saveKey boolValue]) {
|
||||
// Key is stored in keychain. Load it.
|
||||
dbg(@"Loading key from key chain.");
|
||||
[self updateKey:[PearlKeyChain dataOfItemForQuery:keyQuery()]];
|
||||
dbg(@" -> Key %@.", self.key? @"found": @"NOT found");
|
||||
} else {
|
||||
// Key should not be stored in keychain. Delete it.
|
||||
dbg(@"Deleting key from key chain.");
|
||||
[PearlKeyChain deleteItemForQuery:keyQuery()];
|
||||
if ([PearlKeyChain deleteItemForQuery:keyQuery()] != errSecItemNotFound)
|
||||
dbg(@"Deleted key from key chain.");
|
||||
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||
[TestFlight passCheckpoint:MPTestFlightCheckpointMPUnstored];
|
||||
#endif
|
||||
@ -121,7 +121,7 @@ static NSDictionary *keyHashQuery() {
|
||||
kSecAttrAccessibleWhenUnlocked, (__bridge id)kSecAttrAccessible,
|
||||
#endif
|
||||
nil]];
|
||||
if ([[MPConfig get].storeKey boolValue]) {
|
||||
if ([[MPConfig get].saveKey boolValue]) {
|
||||
dbg(@"Storing key in key chain.");
|
||||
[PearlKeyChain addOrUpdateItemForQuery:keyQuery()
|
||||
withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
|
@ -109,12 +109,6 @@
|
||||
return self.managedObjectContext;
|
||||
}
|
||||
|
||||
- (void)ubiquityStoreManager:(UbiquityStoreManager *)manager didSwitchToiCloud:(BOOL)didSwitch {
|
||||
|
||||
dbg(@"didSwitchToiCloud:%@", [NSNumber numberWithBool:didSwitch]);
|
||||
//[masterViewController.iCloudSwitch setOn:didSwitch animated:YES];
|
||||
}
|
||||
|
||||
- (void)saveContext {
|
||||
|
||||
[self.managedObjectContext performBlock:^{
|
||||
|
@ -8,8 +8,7 @@
|
||||
|
||||
@interface MPConfig : PearlConfig
|
||||
|
||||
@property (nonatomic, retain) NSNumber *dataStoreError;
|
||||
@property (nonatomic, retain) NSNumber *storeKey;
|
||||
@property (nonatomic, retain) NSNumber *saveKey;
|
||||
@property (nonatomic, retain) NSNumber *rememberKey;
|
||||
|
||||
+ (MPConfig *)get;
|
||||
|
@ -7,21 +7,23 @@
|
||||
//
|
||||
|
||||
#import "MPConfig.h"
|
||||
#import "MPAppDelegate_Shared.h"
|
||||
|
||||
@implementation MPConfig
|
||||
@dynamic dataStoreError, storeKey, rememberKey;
|
||||
@dynamic saveKey, rememberKey;
|
||||
|
||||
- (id)init {
|
||||
|
||||
if(!(self = [super init]))
|
||||
return self;
|
||||
return nil;
|
||||
|
||||
[self.defaults registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(dataStoreError)),
|
||||
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(storeKey)),
|
||||
[NSNumber numberWithBool:YES], NSStringFromSelector(@selector(rememberKey)),
|
||||
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(saveKey)),
|
||||
[NSNumber numberWithBool:YES], NSStringFromSelector(@selector(rememberKey)),
|
||||
nil]];
|
||||
|
||||
self.delegate = [MPAppDelegate get];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -9,15 +9,17 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "MPPasswordWindowController.h"
|
||||
|
||||
@interface MPAppDelegate : NSObject <NSApplicationDelegate>
|
||||
@interface MPAppDelegate : NSObject <NSApplicationDelegate, PearlConfigDelegate>
|
||||
|
||||
@property (strong) NSStatusItem *statusItem;
|
||||
@property (weak) IBOutlet NSMenuItem *unlockItem;
|
||||
@property (weak) IBOutlet NSMenuItem *lockItem;
|
||||
@property (weak) IBOutlet NSMenuItem *showItem;
|
||||
@property (strong) IBOutlet NSMenu *statusMenu;
|
||||
@property (weak) IBOutlet NSMenuItem *useICloudItem;
|
||||
@property (weak) IBOutlet NSMenuItem *rememberPasswordItem;
|
||||
@property (weak) IBOutlet NSMenuItem *savePasswordItem;
|
||||
|
||||
- (IBAction)activate:(id)sender;
|
||||
- (IBAction)unlock:(id)sender;
|
||||
- (IBAction)togglePreference:(NSMenuItem *)sender;
|
||||
|
||||
@end
|
||||
|
@ -20,16 +20,19 @@
|
||||
|
||||
@implementation MPAppDelegate
|
||||
@synthesize statusItem;
|
||||
@synthesize unlockItem;
|
||||
@synthesize lockItem;
|
||||
@synthesize showItem;
|
||||
@synthesize statusMenu;
|
||||
@synthesize useICloudItem;
|
||||
@synthesize rememberPasswordItem;
|
||||
@synthesize savePasswordItem;
|
||||
@synthesize passwordWindow;
|
||||
|
||||
@synthesize key;
|
||||
@synthesize keyHash;
|
||||
@synthesize keyHashHex;
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wfour-char-constants"
|
||||
static EventHotKeyID MPShowHotKey = { .signature = 'show', .id = 1 };
|
||||
|
||||
+ (void)initialize {
|
||||
@ -59,19 +62,41 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
- (void)showMenu {
|
||||
|
||||
[self.showItem setEnabled:![self.passwordWindow.window isVisible]];
|
||||
self.rememberPasswordItem.state = [[MPConfig get].rememberKey boolValue]? NSOnState: NSOffState;
|
||||
self.savePasswordItem.state = [[MPConfig get].saveKey boolValue]? NSOnState: NSOffState;
|
||||
self.showItem.enabled = ![self.passwordWindow.window isVisible];
|
||||
|
||||
[self.statusItem popUpStatusItemMenu:self.statusMenu];
|
||||
}
|
||||
|
||||
- (IBAction)activate:(id)sender {
|
||||
|
||||
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
|
||||
if ([[NSApplication sharedApplication] isActive])
|
||||
[self applicationDidBecomeActive:nil];
|
||||
else
|
||||
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
|
||||
}
|
||||
|
||||
- (IBAction)togglePreference:(NSMenuItem *)sender {
|
||||
|
||||
if (sender == useICloudItem)
|
||||
[self.storeManager useiCloudStore:sender.state == NSOffState];
|
||||
if (sender == rememberPasswordItem)
|
||||
[MPConfig get].rememberKey = [NSNumber numberWithBool:![[MPConfig get].rememberKey boolValue]];
|
||||
if (sender == savePasswordItem)
|
||||
[MPConfig get].saveKey = [NSNumber numberWithBool:![[MPConfig get].saveKey boolValue]];
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||
|
||||
// Setup delegates and listeners.
|
||||
[MPConfig get].delegate = self;
|
||||
[self addObserver:self forKeyPath:@"key" options:0 context:nil];
|
||||
|
||||
// Initially, use iCloud.
|
||||
if ([[MPConfig get].firstRun boolValue])
|
||||
[[self storeManager] useiCloudStore:YES];
|
||||
|
||||
// Status item.
|
||||
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
|
||||
self.statusItem.title = @"•••";
|
||||
@ -89,17 +114,40 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
status = RegisterEventHotKey(35 /* p */, controlKey + cmdKey, MPShowHotKey, GetApplicationEventTarget(), 0, &hotKeyRef);
|
||||
if(status != noErr)
|
||||
err(@"Error registering hotkey: %d", status);
|
||||
}
|
||||
|
||||
[[self storeManager] useiCloudStore:YES];
|
||||
- (void)applicationWillBecomeActive:(NSNotification *)notification {
|
||||
|
||||
if (!self.passwordWindow)
|
||||
self.passwordWindow = [[MPPasswordWindowController alloc] initWithWindowNibName:@"MPPasswordWindowController"];
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(NSNotification *)notification {
|
||||
|
||||
if (!self.passwordWindow)
|
||||
self.passwordWindow = [[MPPasswordWindowController alloc] initWithWindowNibName:@"MPPasswordWindowController"];
|
||||
[self.passwordWindow showWindow:self];
|
||||
static BOOL firstTime = YES;
|
||||
if (firstTime)
|
||||
firstTime = NO;
|
||||
else
|
||||
[self.passwordWindow showWindow:self];
|
||||
}
|
||||
|
||||
[self unlock:self];
|
||||
- (void)applicationWillResignActive:(NSNotification *)notification {
|
||||
|
||||
if (![[MPConfig get].rememberKey boolValue])
|
||||
self.key = nil;
|
||||
}
|
||||
|
||||
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)oldValue {
|
||||
|
||||
if (configKey == @selector(rememberKey))
|
||||
self.rememberPasswordItem.state = [[MPConfig get].rememberKey boolValue]? NSOnState: NSOffState;
|
||||
if (configKey == @selector(saveKey))
|
||||
self.savePasswordItem.state = [[MPConfig get].saveKey boolValue]? NSOnState: NSOffState;
|
||||
}
|
||||
|
||||
- (void)ubiquityStoreManager:(UbiquityStoreManager *)manager didSwitchToiCloud:(BOOL)didSwitch {
|
||||
|
||||
self.useICloudItem.state = didSwitch? NSOnState: NSOffState;
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
||||
@ -114,54 +162,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)unlock:(id)sender {
|
||||
|
||||
if (!self.key)
|
||||
// Try and load the key from the keychain.
|
||||
[self loadStoredKey];
|
||||
|
||||
if (!self.key)
|
||||
// Ask the user to set the key through his master password.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.key)
|
||||
return;
|
||||
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"Master Password is locked."
|
||||
defaultButton:@"Unlock" alternateButton:@"Change" otherButton:@"Quit"
|
||||
informativeTextWithFormat:@"Your master password is required to unlock the application."];
|
||||
NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 22)];
|
||||
[alert setAccessoryView:passwordField];
|
||||
[alert layout];
|
||||
[passwordField becomeFirstResponder];
|
||||
[alert beginSheetModalForWindow:self.passwordWindow.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:NULL];
|
||||
|
||||
[self printStore];
|
||||
});
|
||||
}
|
||||
|
||||
- (void) alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
||||
|
||||
if (returnCode == NSAlertAlternateReturn)
|
||||
// "Change" button.
|
||||
if ([[NSAlert alertWithMessageText:@"Changing Master Password"
|
||||
defaultButton:nil alternateButton:[PearlStrings get].commonButtonCancel otherButton:nil
|
||||
informativeTextWithFormat:
|
||||
@"This will allow you to log in with a different master password.\n\n"
|
||||
@"Note that you will only see the sites and passwords for the master password you log in with.\n"
|
||||
@"If you log in with a different master password, your current sites will be unavailable.\n\n"
|
||||
@"You can always change back to your current master password later.\n"
|
||||
@"Your current sites and passwords will then become available again."] runModal] == 1)
|
||||
[self forgetKey];
|
||||
|
||||
if (returnCode == NSAlertOtherReturn)
|
||||
// "Quit" button.
|
||||
[[NSApplication sharedApplication] terminate:self];
|
||||
|
||||
if (![self tryMasterPassword:[(NSSecureTextField *)alert.accessoryView stringValue]])
|
||||
[self unlock:self];
|
||||
}
|
||||
|
||||
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window {
|
||||
|
||||
return [[self managedObjectContext] undoManager];
|
||||
|
@ -8,10 +8,17 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface MPPasswordWindowController : NSWindowController <NSTextFieldDelegate>
|
||||
@interface MPPasswordWindowController : NSWindowController <NSTextFieldDelegate> {
|
||||
|
||||
NSString *_content;
|
||||
}
|
||||
|
||||
@property (strong) NSString *content;
|
||||
|
||||
@property (weak) IBOutlet NSTextField *siteField;
|
||||
@property (weak) IBOutlet NSTextField *contentField;
|
||||
@property (weak) IBOutlet NSTextField *tipField;
|
||||
|
||||
- (void)unlock;
|
||||
|
||||
@end
|
||||
|
@ -26,11 +26,12 @@
|
||||
|
||||
- (void)windowDidLoad {
|
||||
|
||||
[self.contentField setStringValue:@""];
|
||||
[self setContent:@""];
|
||||
[self.tipField setStringValue:@""];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification object:self.window queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[self unlock];
|
||||
[self.siteField selectText:self];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:self.window queue:nil
|
||||
@ -53,6 +54,59 @@
|
||||
[super windowDidLoad];
|
||||
}
|
||||
|
||||
- (void)unlock {
|
||||
|
||||
if (![MPAppDelegate get].key)
|
||||
// Try and load the key from the keychain.
|
||||
[[MPAppDelegate get] loadStoredKey];
|
||||
|
||||
if (![MPAppDelegate get].key)
|
||||
// Ask the user to set the key through his master password.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if ([MPAppDelegate get].key)
|
||||
return;
|
||||
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"Master Password is locked."
|
||||
defaultButton:@"Unlock" alternateButton:@"Change" otherButton:@"Quit"
|
||||
informativeTextWithFormat:@"Your master password is required to unlock the application."];
|
||||
NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 22)];
|
||||
[alert setAccessoryView:passwordField];
|
||||
[alert layout];
|
||||
[passwordField becomeFirstResponder];
|
||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:NULL];
|
||||
});
|
||||
}
|
||||
|
||||
- (void) alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
||||
|
||||
switch (returnCode) {
|
||||
case NSAlertAlternateReturn:
|
||||
// "Change" button.
|
||||
if ([[NSAlert alertWithMessageText:@"Changing Master Password"
|
||||
defaultButton:nil alternateButton:[PearlStrings get].commonButtonCancel otherButton:nil
|
||||
informativeTextWithFormat:
|
||||
@"This will allow you to log in with a different master password.\n\n"
|
||||
@"Note that you will only see the sites and passwords for the master password you log in with.\n"
|
||||
@"If you log in with a different master password, your current sites will be unavailable.\n\n"
|
||||
@"You can always change back to your current master password later.\n"
|
||||
@"Your current sites and passwords will then become available again."] runModal] == 1)
|
||||
[[MPAppDelegate get] forgetKey];
|
||||
break;
|
||||
|
||||
case NSAlertOtherReturn:
|
||||
// "Quit" button.
|
||||
[[NSApplication sharedApplication] terminate:self];
|
||||
return;
|
||||
|
||||
case NSAlertDefaultReturn:
|
||||
// "Unlock" button.
|
||||
[[MPAppDelegate get] tryMasterPassword:[(NSSecureTextField *)alert.accessoryView stringValue]];
|
||||
}
|
||||
|
||||
[self unlock];
|
||||
}
|
||||
|
||||
- (NSArray *)control:(NSControl *)control textView:(NSTextView *)textView completions:(NSArray *)words forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(NSInteger *)index {
|
||||
|
||||
NSString *query = [[control stringValue] substringWithRange:charRange];
|
||||
@ -83,20 +137,24 @@
|
||||
|
||||
- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector {
|
||||
|
||||
if (commandSelector == @selector(cancel:))
|
||||
if (commandSelector == @selector(cancel:)) {
|
||||
[self.window close];
|
||||
if (commandSelector == @selector(insertNewline:) && [[self.contentField stringValue] length]) {
|
||||
return YES;
|
||||
}
|
||||
if (commandSelector == @selector(insertNewline:) && [self.content length]) {
|
||||
[[NSPasteboard generalPasteboard] declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
|
||||
if ([[NSPasteboard generalPasteboard] setString:[self.contentField stringValue] forType:NSPasteboardTypeString]) {
|
||||
if ([[NSPasteboard generalPasteboard] setString:self.content forType:NSPasteboardTypeString]) {
|
||||
self.tipField.alphaValue = 1;
|
||||
[self.tipField setStringValue:@"Copied!"];
|
||||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 3.0f * NSEC_PER_SEC);
|
||||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0f * NSEC_PER_SEC));
|
||||
dispatch_after(popTime, dispatch_get_main_queue(), ^{
|
||||
[NSAnimationContext beginGrouping];
|
||||
[[NSAnimationContext currentContext] setDuration:0.2f];
|
||||
[self.tipField.animator setAlphaValue:0];
|
||||
[NSAnimationContext endGrouping];
|
||||
});
|
||||
|
||||
[[self findElement] use];
|
||||
return YES;
|
||||
} else
|
||||
wrn(@"Couldn't copy password to pasteboard.");
|
||||
@ -111,21 +169,47 @@
|
||||
[self trySite];
|
||||
}
|
||||
|
||||
- (NSString *)content {
|
||||
|
||||
return _content;
|
||||
}
|
||||
|
||||
- (void)setContent:(NSString *)content {
|
||||
|
||||
_content = content;
|
||||
|
||||
NSShadow *shadow = [NSShadow new];
|
||||
shadow.shadowColor = [NSColor colorWithDeviceWhite:0.0f alpha:0.6f];
|
||||
shadow.shadowOffset = NSMakeSize(1.0f, -1.0f);
|
||||
shadow.shadowBlurRadius = 1.2f;
|
||||
|
||||
NSMutableParagraphStyle *paragraph = [NSMutableParagraphStyle new];
|
||||
paragraph.alignment = NSCenterTextAlignment;
|
||||
|
||||
[self.contentField setAttributedStringValue:
|
||||
[[NSAttributedString alloc] initWithString:_content
|
||||
attributes:[[NSMutableDictionary alloc] initWithObjectsAndKeys:
|
||||
shadow, NSShadowAttributeName,
|
||||
paragraph, NSParagraphStyleAttributeName,
|
||||
nil]]];
|
||||
}
|
||||
|
||||
- (BOOL)trySite {
|
||||
|
||||
MPElementEntity *result = [self findElement];
|
||||
if (!result) {
|
||||
[self.contentField setStringValue:@""];
|
||||
[self setContent:@""];
|
||||
[self.tipField setStringValue:@""];
|
||||
return NO;
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
||||
NSString *description = [result.content description];
|
||||
[result use];
|
||||
if (!description)
|
||||
description = @"";
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.contentField setStringValue:description];
|
||||
[self setContent:description];
|
||||
[self.tipField setStringValue:@"Hit enter to copy the password."];
|
||||
self.tipField.alphaValue = 1;
|
||||
});
|
||||
@ -147,7 +231,7 @@
|
||||
[element use];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.contentField setStringValue:description? description: @""];
|
||||
[self setContent:description];
|
||||
});
|
||||
}];
|
||||
*/
|
||||
|
@ -36,7 +36,7 @@
|
||||
<string key="NSClassName">NSApplication</string>
|
||||
</object>
|
||||
<object class="NSWindowTemplate" id="45434518">
|
||||
<int key="NSWindowStyleMask">8209</int>
|
||||
<int key="NSWindowStyleMask">277</int>
|
||||
<int key="NSWindowBacking">2</int>
|
||||
<string key="NSWindowRect">{{600, 530}, {480, 159}}</string>
|
||||
<int key="NSWTFlags">611845120</int>
|
||||
@ -69,7 +69,7 @@
|
||||
<double key="NSSize">13</double>
|
||||
<int key="NSfFlags">1044</int>
|
||||
</object>
|
||||
<string key="NSPlaceholderString">Site</string>
|
||||
<string key="NSPlaceholderString">Site name</string>
|
||||
<string key="NSCellIdentifier">_NS:9</string>
|
||||
<reference key="NSControlView" ref="291791585"/>
|
||||
<int key="NSTextBezelStyle">1</int>
|
||||
@ -115,6 +115,7 @@
|
||||
</object>
|
||||
<string key="NSCellIdentifier">_NS:9</string>
|
||||
<reference key="NSControlView" ref="226215720"/>
|
||||
<bool key="NSDrawsBackground">YES</bool>
|
||||
<object class="NSColor" key="NSBackgroundColor" id="245864165">
|
||||
<int key="NSColorSpace">6</int>
|
||||
<string key="NSCatalogName">System</string>
|
||||
@ -165,8 +166,8 @@
|
||||
<string key="NSReuseIdentifierKey">_NS:21</string>
|
||||
</object>
|
||||
<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
|
||||
<string key="NSMinSize">{480, 153}</string>
|
||||
<string key="NSMaxSize">{480, 339}</string>
|
||||
<string key="NSMinSize">{480, 150}</string>
|
||||
<string key="NSMaxSize">{480, 336}</string>
|
||||
<bool key="NSWindowIsRestorable">YES</bool>
|
||||
</object>
|
||||
</array>
|
||||
@ -594,7 +595,7 @@
|
||||
<boolean value="YES" key="22.IBNSWindowAutoPositionCentersHorizontal"/>
|
||||
<boolean value="YES" key="22.IBNSWindowAutoPositionCentersVertical"/>
|
||||
<string key="22.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<boolean value="YES" key="22.NSWindowTemplate.visibleAtLaunch"/>
|
||||
<boolean value="NO" key="22.NSWindowTemplate.visibleAtLaunch"/>
|
||||
<array class="NSMutableArray" key="23.IBNSViewMetadataConstraints">
|
||||
<reference ref="137127436"/>
|
||||
<reference ref="582018795"/>
|
||||
|
@ -61,6 +61,94 @@
|
||||
<string key="NSResourceName">NSMenuMixedState</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMenuItem" id="851296005">
|
||||
<reference key="NSMenu" ref="764588027"/>
|
||||
<string key="NSTitle">Preferences</string>
|
||||
<string key="NSKeyEquiv"/>
|
||||
<int key="NSMnemonicLoc">2147483647</int>
|
||||
<reference key="NSOnImage" ref="552246001"/>
|
||||
<reference key="NSMixedImage" ref="752047669"/>
|
||||
<string key="NSAction">submenuAction:</string>
|
||||
<object class="NSMenu" key="NSSubmenu" id="800575174">
|
||||
<string key="NSTitle">Preferences</string>
|
||||
<array class="NSMutableArray" key="NSMenuItems">
|
||||
<object class="NSMenuItem" id="14397049">
|
||||
<reference key="NSMenu" ref="800575174"/>
|
||||
<string key="NSTitle">Use iCloud</string>
|
||||
<string key="NSKeyEquiv"/>
|
||||
<int key="NSMnemonicLoc">2147483647</int>
|
||||
<reference key="NSOnImage" ref="552246001"/>
|
||||
<reference key="NSMixedImage" ref="752047669"/>
|
||||
</object>
|
||||
<object class="NSMenuItem" id="461686112">
|
||||
<reference key="NSMenu" ref="800575174"/>
|
||||
<bool key="NSIsDisabled">YES</bool>
|
||||
<string key="NSTitle">Synchronize available sites from your iCloud account.</string>
|
||||
<string key="NSKeyEquiv"/>
|
||||
<int key="NSMnemonicLoc">2147483647</int>
|
||||
<reference key="NSOnImage" ref="552246001"/>
|
||||
<reference key="NSMixedImage" ref="752047669"/>
|
||||
<object class="NSAttributedString" key="NSAttributedTitle">
|
||||
<string key="NSString">Synchronize available sites from your iCloud account.</string>
|
||||
<dictionary key="NSAttributes" id="583461090">
|
||||
<object class="NSFont" key="NSFont">
|
||||
<string key="NSName">Helvetica</string>
|
||||
<double key="NSSize">12</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
<object class="NSParagraphStyle" key="NSParagraphStyle">
|
||||
<int key="NSAlignment">4</int>
|
||||
<nil key="NSTabStops"/>
|
||||
</object>
|
||||
</dictionary>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMenuItem" id="290760748">
|
||||
<reference key="NSMenu" ref="800575174"/>
|
||||
<string key="NSTitle">Remember Password</string>
|
||||
<string key="NSKeyEquiv"/>
|
||||
<int key="NSMnemonicLoc">2147483647</int>
|
||||
<reference key="NSOnImage" ref="552246001"/>
|
||||
<reference key="NSMixedImage" ref="752047669"/>
|
||||
</object>
|
||||
<object class="NSMenuItem" id="907921953">
|
||||
<reference key="NSMenu" ref="800575174"/>
|
||||
<bool key="NSIsDisabled">YES</bool>
|
||||
<string key="NSTitle">Remember the password while the application is running.</string>
|
||||
<string key="NSKeyEquiv"/>
|
||||
<int key="NSMnemonicLoc">2147483647</int>
|
||||
<reference key="NSOnImage" ref="552246001"/>
|
||||
<reference key="NSMixedImage" ref="752047669"/>
|
||||
<object class="NSAttributedString" key="NSAttributedTitle">
|
||||
<string key="NSString">Remember the password while the application is running.</string>
|
||||
<reference key="NSAttributes" ref="583461090"/>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMenuItem" id="110488020">
|
||||
<reference key="NSMenu" ref="800575174"/>
|
||||
<string key="NSTitle">Save Password</string>
|
||||
<string key="NSKeyEquiv"/>
|
||||
<int key="NSMnemonicLoc">2147483647</int>
|
||||
<reference key="NSOnImage" ref="552246001"/>
|
||||
<reference key="NSMixedImage" ref="752047669"/>
|
||||
</object>
|
||||
<object class="NSMenuItem" id="123831322">
|
||||
<reference key="NSMenu" ref="800575174"/>
|
||||
<bool key="NSIsDisabled">YES</bool>
|
||||
<string key="NSTitle">Save the password in your keychain so you don't need to enter it again.</string>
|
||||
<string key="NSKeyEquiv"/>
|
||||
<int key="NSMnemonicLoc">2147483647</int>
|
||||
<reference key="NSOnImage" ref="552246001"/>
|
||||
<reference key="NSMixedImage" ref="752047669"/>
|
||||
<object class="NSAttributedString" key="NSAttributedTitle">
|
||||
<string key="NSString">Save the password in your keychain so you don't need to enter it again.</string>
|
||||
<reference key="NSAttributes" ref="583461090"/>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
<bool key="NSNoAutoenable">YES</bool>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMenuItem" id="466252869">
|
||||
<reference key="NSMenu" ref="764588027"/>
|
||||
<bool key="NSIsDisabled">YES</bool>
|
||||
@ -150,6 +238,54 @@
|
||||
</object>
|
||||
<int key="connectionID">736</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBOutletConnection" key="connection">
|
||||
<string key="label">useICloudItem</string>
|
||||
<reference key="source" ref="976324537"/>
|
||||
<reference key="destination" ref="14397049"/>
|
||||
</object>
|
||||
<int key="connectionID">749</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBOutletConnection" key="connection">
|
||||
<string key="label">rememberPasswordItem</string>
|
||||
<reference key="source" ref="976324537"/>
|
||||
<reference key="destination" ref="290760748"/>
|
||||
</object>
|
||||
<int key="connectionID">750</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBOutletConnection" key="connection">
|
||||
<string key="label">savePasswordItem</string>
|
||||
<reference key="source" ref="976324537"/>
|
||||
<reference key="destination" ref="110488020"/>
|
||||
</object>
|
||||
<int key="connectionID">751</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBActionConnection" key="connection">
|
||||
<string key="label">togglePreference:</string>
|
||||
<reference key="source" ref="976324537"/>
|
||||
<reference key="destination" ref="14397049"/>
|
||||
</object>
|
||||
<int key="connectionID">752</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBActionConnection" key="connection">
|
||||
<string key="label">togglePreference:</string>
|
||||
<reference key="source" ref="976324537"/>
|
||||
<reference key="destination" ref="290760748"/>
|
||||
</object>
|
||||
<int key="connectionID">753</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBActionConnection" key="connection">
|
||||
<string key="label">togglePreference:</string>
|
||||
<reference key="source" ref="976324537"/>
|
||||
<reference key="destination" ref="110488020"/>
|
||||
</object>
|
||||
<int key="connectionID">754</int>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
<array key="orderedObjects">
|
||||
@ -201,6 +337,7 @@
|
||||
<reference ref="466252869"/>
|
||||
<reference ref="846612332"/>
|
||||
<reference ref="229948989"/>
|
||||
<reference ref="851296005"/>
|
||||
</array>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
@ -224,6 +361,57 @@
|
||||
<reference key="object" ref="229948989"/>
|
||||
<reference key="parent" ref="764588027"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">739</int>
|
||||
<reference key="object" ref="851296005"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<reference ref="800575174"/>
|
||||
</array>
|
||||
<reference key="parent" ref="764588027"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">742</int>
|
||||
<reference key="object" ref="800575174"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<reference ref="14397049"/>
|
||||
<reference ref="290760748"/>
|
||||
<reference ref="907921953"/>
|
||||
<reference ref="461686112"/>
|
||||
<reference ref="110488020"/>
|
||||
<reference ref="123831322"/>
|
||||
</array>
|
||||
<reference key="parent" ref="851296005"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">743</int>
|
||||
<reference key="object" ref="14397049"/>
|
||||
<reference key="parent" ref="800575174"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">745</int>
|
||||
<reference key="object" ref="907921953"/>
|
||||
<reference key="parent" ref="800575174"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">744</int>
|
||||
<reference key="object" ref="290760748"/>
|
||||
<reference key="parent" ref="800575174"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">746</int>
|
||||
<reference key="object" ref="461686112"/>
|
||||
<reference key="parent" ref="800575174"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">747</int>
|
||||
<reference key="object" ref="110488020"/>
|
||||
<reference key="parent" ref="800575174"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">748</int>
|
||||
<reference key="object" ref="123831322"/>
|
||||
<reference key="parent" ref="800575174"/>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
||||
@ -238,14 +426,86 @@
|
||||
<string key="718.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="719.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="720.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="739.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="742.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="743.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="744.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="745.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="746.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="747.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="748.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">736</int>
|
||||
<int key="maxID">754</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">MPAppDelegate</string>
|
||||
<string key="superclassName">NSObject</string>
|
||||
<dictionary class="NSMutableDictionary" key="actions">
|
||||
<string key="activate:">id</string>
|
||||
<string key="signOut:">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="signOut:">
|
||||
<string key="name">signOut:</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="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>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<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>
|
||||
</dictionary>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/MPAppDelegate.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">
|
||||
|
@ -160,7 +160,7 @@
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:kIASKAppSettingChanged object:nil queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
if ([NSStringFromSelector(@selector(storeKey))
|
||||
if ([NSStringFromSelector(@selector(saveKey))
|
||||
isEqualToString:[note.object description]]) {
|
||||
[self updateKey:self.key];
|
||||
[self loadKey:YES];
|
||||
|
Loading…
Reference in New Issue
Block a user