An experimental new mac ui that blurs the whole screen.
This commit is contained in:
parent
1433c0851e
commit
c5fc87b7b5
@ -21,6 +21,7 @@
|
||||
#import "MPElementModel.h"
|
||||
#import "MPMacAppDelegate.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPPasswordDialogController.h"
|
||||
|
||||
#define MPAlertChangeType @"MPAlertChangeType"
|
||||
#define MPAlertChangeLogin @"MPAlertChangeLogin"
|
||||
@ -204,7 +205,7 @@
|
||||
[context deleteObject:element];
|
||||
[context saveToStore];
|
||||
|
||||
[((MPPasswordWindowController *)self.collectionView.window.windowController) updateElements];
|
||||
[((MPPasswordDialogController *)self.collectionView.window.windowController) updateElements];
|
||||
}];
|
||||
break;
|
||||
}
|
||||
|
@ -8,8 +8,8 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "MPAppDelegate_Shared.h"
|
||||
#import "MPPasswordWindowController.h"
|
||||
#import "RHStatusItemView.h"
|
||||
#import "MPPasswordWindowController.h"
|
||||
|
||||
@interface MPMacAppDelegate : MPAppDelegate_Shared<NSApplicationDelegate>
|
||||
|
||||
|
@ -9,12 +9,13 @@
|
||||
#import "MPMacAppDelegate.h"
|
||||
#import "MPAppDelegate_Key.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPPasswordWindowController.h"
|
||||
#import <Carbon/Carbon.h>
|
||||
#import <ServiceManagement/ServiceManagement.h>
|
||||
|
||||
#define LOGIN_HELPER_BUNDLE_ID @"com.lyndir.lhunath.MasterPassword.Mac.LoginHelper"
|
||||
|
||||
@interface UbiquityStoreManager (Private)
|
||||
@interface UbiquityStoreManager(Private)
|
||||
|
||||
- (void)markCloudStoreCorrupted;
|
||||
|
||||
@ -25,7 +26,7 @@
|
||||
@property(nonatomic, strong) NSWindowController *initialWindow;
|
||||
@end
|
||||
|
||||
@implementation MPMacAppDelegate
|
||||
@implementation MPMacAppDelegate { NSWindow *_window; }
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wfour-char-constants"
|
||||
@ -50,7 +51,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
// Extract the hotkey ID.
|
||||
EventHotKeyID hotKeyID;
|
||||
GetEventParameter( theEvent, kEventParamDirectObject, typeEventHotKeyID,
|
||||
NULL, sizeof(hotKeyID), NULL, &hotKeyID );
|
||||
NULL, sizeof( hotKeyID ), NULL, &hotKeyID );
|
||||
|
||||
// Check which hotkey this was.
|
||||
if (hotKeyID.signature == MPShowHotKey.signature && hotKeyID.id == MPShowHotKey.id) {
|
||||
@ -100,7 +101,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
fetchRequest.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO] ];
|
||||
NSArray *users = [context executeFetchRequest:fetchRequest error:&error];
|
||||
if (!users)
|
||||
err(@"Failed to load users: %@", error);
|
||||
err( @"Failed to load users: %@", error );
|
||||
|
||||
if (![users count]) {
|
||||
NSMenuItem *noUsersItem = [self.usersItem.submenu addItemWithTitle:@"No users" action:NULL keyEquivalent:@""];
|
||||
@ -111,7 +112,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
self.usersItem.state = NSMixedState;
|
||||
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 setRepresentedObject:[user objectID]];
|
||||
[[self.usersItem submenu] addItem:userItem];
|
||||
@ -139,7 +140,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
self.activeUser = (MPUserEntity *)[context existingObjectWithID:[item representedObject] error:&error];
|
||||
|
||||
if (error)
|
||||
err(@"While looking up selected user: %@", error);
|
||||
err( @"While looking up selected user: %@", error );
|
||||
}
|
||||
|
||||
- (void)showMenu {
|
||||
@ -206,7 +207,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
[moc saveToStore];
|
||||
NSError *error = nil;
|
||||
if (![moc obtainPermanentIDsForObjects:@[ newUser ] error:&error])
|
||||
err(@"Failed to obtain permanent object ID for new user: %@", error);
|
||||
err( @"Failed to obtain permanent object ID for new user: %@", error );
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
[self updateUsers];
|
||||
@ -290,19 +291,19 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
[MPConfig get].delegate = self;
|
||||
__weak id weakSelf = self;
|
||||
[self addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[weakSelf updateMenuItems];
|
||||
});
|
||||
} );
|
||||
} forKeyPath:@"key" options:0 context:nil];
|
||||
[self addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[weakSelf updateMenuItems];
|
||||
});
|
||||
} );
|
||||
} forKeyPath:@"activeUser" options:0 context:nil];
|
||||
[self addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[weakSelf updateMenuItems];
|
||||
});
|
||||
} );
|
||||
} forKeyPath:@"storeManager.cloudAvailable" options:0 context:nil];
|
||||
|
||||
// Status item.
|
||||
@ -311,18 +312,18 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
self.statusView.image = [NSImage imageNamed:@"menu-icon"];
|
||||
self.statusView.menu = self.statusMenu;
|
||||
self.statusView.target = self;
|
||||
self.statusView.action = @selector(showMenu);
|
||||
self.statusView.action = @selector( showMenu );
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidChangeNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
[self updateUsers];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidImportChangesNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
[self updateUsers];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPCheckConfigNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
@ -346,16 +347,16 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
// Global hotkey.
|
||||
EventHotKeyRef hotKeyRef;
|
||||
EventTypeSpec hotKeyEvents[1] = { { .eventClass = kEventClassKeyboard, .eventKind = kEventHotKeyPressed } };
|
||||
OSStatus status = InstallApplicationEventHandler(NewEventHandlerUPP( MPHotKeyHander ), GetEventTypeCount( hotKeyEvents ),
|
||||
hotKeyEvents, (__bridge void *)self, NULL);
|
||||
OSStatus status = InstallApplicationEventHandler( NewEventHandlerUPP( MPHotKeyHander ), GetEventTypeCount( hotKeyEvents ),
|
||||
hotKeyEvents, (__bridge void *)self, NULL );
|
||||
if (status != noErr)
|
||||
err(@"Error installing application event handler: %i", (int)status);
|
||||
err( @"Error installing application event handler: %i", (int)status );
|
||||
status = RegisterEventHotKey( 35 /* p */, controlKey + cmdKey, MPShowHotKey, GetApplicationEventTarget(), 0, &hotKeyRef );
|
||||
if (status != noErr)
|
||||
err(@"Error registering 'show' hotkey: %i", (int)status);
|
||||
err( @"Error registering 'show' hotkey: %i", (int)status );
|
||||
status = RegisterEventHotKey( 35 /* p */, controlKey + optionKey + cmdKey, MPLockHotKey, GetApplicationEventTarget(), 0, &hotKeyRef );
|
||||
if (status != noErr)
|
||||
err(@"Error registering 'lock' hotkey: %i", (int)status);
|
||||
err( @"Error registering 'lock' hotkey: %i", (int)status );
|
||||
|
||||
// Initial display.
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
@ -372,9 +373,9 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
[MPMacConfig get].usedUserName = activeUser.name;
|
||||
|
||||
PearlMainQueue(^{
|
||||
PearlMainQueue( ^{
|
||||
[self updateUsers];
|
||||
});
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)updateMenuItems {
|
||||
@ -467,7 +468,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
if (SMLoginItemSetEnabled( (__bridge CFStringRef)LOGIN_HELPER_BUNDLE_ID, (Boolean)enabled ) == true)
|
||||
loginItemEnabled = enabled;
|
||||
else
|
||||
wrn(@"Failed to set login item.");
|
||||
wrn( @"Failed to set login item." );
|
||||
}
|
||||
|
||||
self.openAtLoginItem.state = loginItemEnabled? NSOnState: NSOffState;
|
||||
@ -481,11 +482,11 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
for (NSDictionary *job in jobs)
|
||||
if ([LOGIN_HELPER_BUNDLE_ID isEqualToString:[job objectForKey:@"Label"]]) {
|
||||
dbg(@"loginItemEnabled: %@", @([[job objectForKey:@"OnDemand"] boolValue]));
|
||||
dbg( @"loginItemEnabled: %@", @([[job objectForKey:@"OnDemand"] boolValue]) );
|
||||
return [[job objectForKey:@"OnDemand"] boolValue];
|
||||
}
|
||||
|
||||
dbg(@"loginItemEnabled: not found");
|
||||
dbg( @"loginItemEnabled: not found" );
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
23
MasterPassword/ObjC/Mac/MPPasswordDialogController.h
Normal file
23
MasterPassword/ObjC/Mac/MPPasswordDialogController.h
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// MPPasswordDialogController.h
|
||||
// MasterPassword-Mac
|
||||
//
|
||||
// Created by Maarten Billemont on 04/03/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
@class MPElementModel;
|
||||
|
||||
@interface MPPasswordDialogController : NSWindowController<NSTextFieldDelegate, NSCollectionViewDelegate>
|
||||
|
||||
@property(nonatomic, strong) NSMutableArray *elements;
|
||||
@property(nonatomic, strong) NSIndexSet *elementSelectionIndexes;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *siteField;
|
||||
@property(nonatomic, weak) IBOutlet NSView *contentContainer;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *userLabel;
|
||||
@property(nonatomic, weak) IBOutlet NSCollectionView *siteCollectionView;
|
||||
|
||||
- (void)updateElements;
|
||||
|
||||
@end
|
477
MasterPassword/ObjC/Mac/MPPasswordDialogController.m
Normal file
477
MasterPassword/ObjC/Mac/MPPasswordDialogController.m
Normal file
@ -0,0 +1,477 @@
|
||||
//
|
||||
// MPPasswordDialogController.m
|
||||
// MasterPassword-Mac
|
||||
//
|
||||
// Created by Maarten Billemont on 04/03/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPPasswordDialogController.h"
|
||||
#import "MPMacAppDelegate.h"
|
||||
#import "MPAppDelegate_Key.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPElementModel.h"
|
||||
|
||||
#define MPAlertUnlockMP @"MPAlertUnlockMP"
|
||||
#define MPAlertIncorrectMP @"MPAlertIncorrectMP"
|
||||
#define MPAlertCreateSite @"MPAlertCreateSite"
|
||||
|
||||
@interface MPPasswordDialogController()
|
||||
|
||||
@property(nonatomic) BOOL inProgress;
|
||||
|
||||
@property(nonatomic, strong) NSOperationQueue *backgroundQueue;
|
||||
@property(nonatomic, strong) NSAlert *loadingDataAlert;
|
||||
@property(nonatomic) BOOL closing;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPPasswordDialogController
|
||||
|
||||
#pragma mark - Life
|
||||
|
||||
- (void)windowDidLoad {
|
||||
|
||||
if ([[MPMacConfig get].dialogStyleHUD boolValue]) {
|
||||
self.window.styleMask = NSHUDWindowMask | NSTitledWindowMask | NSUtilityWindowMask | NSClosableWindowMask;
|
||||
self.userLabel.textColor = [NSColor whiteColor];
|
||||
}
|
||||
else {
|
||||
self.window.styleMask = NSTexturedBackgroundWindowMask | NSResizableWindowMask | NSTitledWindowMask | NSClosableWindowMask;
|
||||
self.userLabel.textColor = [NSColor controlTextColor];
|
||||
}
|
||||
|
||||
self.backgroundQueue = [NSOperationQueue new];
|
||||
self.backgroundQueue.maxConcurrentOperationCount = 1;
|
||||
|
||||
[[MPMacAppDelegate get] addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
// [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
// if (![MPAlgorithmDefault migrateUser:[[MPMacAppDelegate get] activeUserInContext:moc]])
|
||||
// [NSAlert alertWithMessageText:@"Migration Needed" defaultButton:@"OK" alternateButton:nil otherButton:nil
|
||||
// informativeTextWithFormat:@"Certain sites require explicit migration to get updated to the latest version of the "
|
||||
// @"Master Password algorithm. For these sites, a migration button will appear. Migrating these sites will cause "
|
||||
// @"their passwords to change. You'll need to update your profile for that site with the new password."];
|
||||
// [moc saveToStore];
|
||||
// }];
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:YES];
|
||||
[self updateElements];
|
||||
}];
|
||||
} forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification object:self.window
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:NO];
|
||||
[self.siteField selectText:nil];
|
||||
[self updateElements];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:self.window
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
NSWindow *sheet = [self.window attachedSheet];
|
||||
if (sheet)
|
||||
[NSApp endSheet:sheet];
|
||||
|
||||
[NSApp hide:nil];
|
||||
self.closing = NO;
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedOutNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
self.userLabel.stringValue = @"";
|
||||
self.siteField.stringValue = @"";
|
||||
self.elements = nil;
|
||||
|
||||
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:YES];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedInNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
self.userLabel.stringValue = PearlString( @"%@'s password for:",
|
||||
[[MPMacAppDelegate get] activeUserForMainThread].name );
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidChangeNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:NO];
|
||||
}];
|
||||
|
||||
[super windowDidLoad];
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
|
||||
self.closing = YES;
|
||||
[super close];
|
||||
}
|
||||
|
||||
#pragma mark - NSAlert
|
||||
|
||||
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
||||
|
||||
if (contextInfo == MPAlertIncorrectMP) {
|
||||
[self close];
|
||||
return;
|
||||
}
|
||||
if (contextInfo == MPAlertUnlockMP) {
|
||||
switch (returnCode) {
|
||||
case NSAlertFirstButtonReturn: {
|
||||
// "Unlock" button.
|
||||
self.contentContainer.alphaValue = 0;
|
||||
self.inProgress = YES;
|
||||
|
||||
NSString *password = [(NSSecureTextField *)alert.accessoryView stringValue];
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc];
|
||||
NSString *userName = activeUser.name;
|
||||
BOOL success = [[MPMacAppDelegate get] signInAsUser:activeUser saveInContext:moc
|
||||
usingMasterPassword:password];
|
||||
self.inProgress = NO;
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
if (success)
|
||||
self.contentContainer.alphaValue = 1;
|
||||
else {
|
||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey : PearlString( @"Incorrect master password for user %@", userName )
|
||||
}]] beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertIncorrectMP];
|
||||
}
|
||||
}];
|
||||
}];
|
||||
break;
|
||||
}
|
||||
|
||||
case NSAlertSecondButtonReturn: {
|
||||
// "Change" button.
|
||||
NSAlert *alert_ = [NSAlert new];
|
||||
[alert_ addButtonWithTitle:@"Update"];
|
||||
[alert_ addButtonWithTitle:@"Cancel"];
|
||||
[alert_ setMessageText:@"Changing Master Password"];
|
||||
[alert_ setInformativeText:@"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."];
|
||||
|
||||
if ([alert_ runModal] == NSAlertFirstButtonReturn) {
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:context];
|
||||
activeUser.keyID = nil;
|
||||
[[MPMacAppDelegate get] forgetSavedKeyFor:activeUser];
|
||||
[[MPMacAppDelegate get] signOutAnimated:YES];
|
||||
[context saveToStore];
|
||||
}];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NSAlertThirdButtonReturn: {
|
||||
// "Cancel" button.
|
||||
[self close];
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (contextInfo == MPAlertCreateSite) {
|
||||
switch (returnCode) {
|
||||
case NSAlertFirstButtonReturn: {
|
||||
// "Create" button.
|
||||
[[MPMacAppDelegate get] addElementNamed:[self.siteField stringValue] completion:^(MPElementEntity *element) {
|
||||
if (element)
|
||||
PearlMainQueue( ^{ [self updateElements]; } );
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case NSAlertThirdButtonReturn:
|
||||
// "Cancel" button.
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - NSCollectionViewDelegate
|
||||
|
||||
#pragma mark - NSTextFieldDelegate
|
||||
- (void)doCommandBySelector:(SEL)commandSelector {
|
||||
|
||||
if (commandSelector == @selector(insertNewline:))
|
||||
[self useSite];
|
||||
}
|
||||
|
||||
- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector {
|
||||
|
||||
if (commandSelector == @selector(cancel:))
|
||||
[self close];
|
||||
if (commandSelector == @selector(moveUp:))
|
||||
self.elementSelectionIndexes =
|
||||
[NSIndexSet indexSetWithIndex:MAX(self.elementSelectionIndexes.firstIndex, (NSUInteger)1) - 1];
|
||||
if (commandSelector == @selector(moveDown:))
|
||||
self.elementSelectionIndexes =
|
||||
[NSIndexSet indexSetWithIndex:MIN(self.elementSelectionIndexes.firstIndex + 1, self.elements.count - 1)];
|
||||
if (commandSelector == @selector(moveLeft:))
|
||||
[[self selectedView].animator setBoundsOrigin:NSZeroPoint];
|
||||
if (commandSelector == @selector(moveRight:))
|
||||
[[self selectedView].animator setBoundsOrigin:NSMakePoint( self.siteCollectionView.frame.size.width / 2, 0 )];
|
||||
if (commandSelector == @selector(insertNewline:))
|
||||
[self useSite];
|
||||
else
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)controlTextDidChange:(NSNotification *)note {
|
||||
|
||||
if (note.object != self.siteField)
|
||||
return;
|
||||
|
||||
// Update the site content as the site name changes.
|
||||
if ([[NSApp currentEvent] type] == NSKeyDown &&
|
||||
[[[NSApp currentEvent] charactersIgnoringModifiers] isEqualToString:@"\r"]) { // Return while completing.
|
||||
[self useSite];
|
||||
return;
|
||||
}
|
||||
|
||||
// if ([[NSApp currentEvent] type] == NSKeyDown &&
|
||||
// [[[NSApp currentEvent] charactersIgnoringModifiers] characterAtIndex:0] == 0x1b) { // Escape while completing.
|
||||
// [self trySiteWithAction:NO];
|
||||
// return;
|
||||
// }
|
||||
|
||||
[self updateElements];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (BOOL)ensureLoadedAndUnlockedOrCloseIfLoggedOut:(BOOL)closeIfLoggedOut {
|
||||
|
||||
if (![self ensureStoreLoaded])
|
||||
return NO;
|
||||
|
||||
if (self.closing || self.inProgress || !self.window.isKeyWindow)
|
||||
return NO;
|
||||
|
||||
return [self ensureUnlocked:closeIfLoggedOut];
|
||||
}
|
||||
|
||||
- (BOOL)ensureStoreLoaded {
|
||||
|
||||
if ([MPMacAppDelegate managedObjectContextForMainThreadIfReady]) {
|
||||
// Store loaded.
|
||||
if (self.loadingDataAlert.window)
|
||||
[NSApp endSheet:self.loadingDataAlert.window];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
[self.loadingDataAlert = [NSAlert alertWithMessageText:@"Opening Your Data" defaultButton:@"..." alternateButton:nil otherButton:nil
|
||||
informativeTextWithFormat:@""]
|
||||
beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:nil];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)ensureUnlocked:(BOOL)closeIfLoggedOut {
|
||||
|
||||
__block BOOL unlocked = NO;
|
||||
[MPMacAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc];
|
||||
NSString *userName = activeUser.name;
|
||||
if (!activeUser) {
|
||||
// No user to sign in with.
|
||||
if (closeIfLoggedOut)
|
||||
[self close];
|
||||
return;
|
||||
}
|
||||
if ([MPMacAppDelegate get].key) {
|
||||
// Already logged in.
|
||||
unlocked = YES;
|
||||
return;
|
||||
}
|
||||
if (activeUser.saveKey && closeIfLoggedOut) {
|
||||
// App was locked, don't instantly unlock again.
|
||||
[self close];
|
||||
return;
|
||||
}
|
||||
if ([[MPMacAppDelegate get] signInAsUser:activeUser saveInContext:moc usingMasterPassword:nil]) {
|
||||
// Loaded the key from the keychain.
|
||||
unlocked = YES;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ask the user to set the key through his master password.
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
if ([MPMacAppDelegate get].key)
|
||||
return;
|
||||
|
||||
[self.siteField setStringValue:@""];
|
||||
|
||||
NSAlert *alert = [NSAlert new];
|
||||
[alert addButtonWithTitle:@"Unlock"];
|
||||
[alert addButtonWithTitle:@"Change"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
[alert setMessageText:@"Master Password is locked."];
|
||||
[alert setInformativeText:PearlString( @"The master password is required to unlock the application for:\n\n%@", userName )];
|
||||
|
||||
NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||
[alert setAccessoryView:passwordField];
|
||||
[alert layout];
|
||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertUnlockMP];
|
||||
[passwordField becomeFirstResponder];
|
||||
}];
|
||||
}];
|
||||
|
||||
return unlocked;
|
||||
}
|
||||
|
||||
- (void)updateElements {
|
||||
|
||||
if (![MPMacAppDelegate get].key) {
|
||||
self.elements = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *query = [self.siteField.currentEditor string];
|
||||
[MPMacAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) {
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
||||
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"lastUsed" ascending:NO]];
|
||||
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(%@ == '' OR name BEGINSWITH[cd] %@) AND user == %@",
|
||||
query, query, [[MPMacAppDelegate get] activeUserInContext:context]];
|
||||
|
||||
NSError *error = nil;
|
||||
NSArray *siteResults = [context executeFetchRequest:fetchRequest error:&error];
|
||||
if (!siteResults) {
|
||||
err(@"While fetching elements for completion: %@", error);
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableArray *newElements = [NSMutableArray arrayWithCapacity:[siteResults count]];
|
||||
for (MPElementEntity *element in siteResults)
|
||||
[newElements addObject:[[MPElementModel alloc] initWithEntity:element]];
|
||||
self.elements = newElements;
|
||||
if (!self.selectedElement)
|
||||
self.elementSelectionIndexes = [newElements count]? [NSIndexSet indexSetWithIndex:0]: nil;
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSUInteger)selectedIndex {
|
||||
|
||||
if (!self.elementSelectionIndexes)
|
||||
return NSNotFound;
|
||||
NSUInteger selectedIndex = self.elementSelectionIndexes.firstIndex;
|
||||
if (selectedIndex >= self.elements.count)
|
||||
return NSNotFound;
|
||||
|
||||
return selectedIndex;
|
||||
}
|
||||
|
||||
- (NSBox *)selectedView {
|
||||
|
||||
NSUInteger selectedIndex = [self selectedIndex];
|
||||
if (selectedIndex == NSNotFound)
|
||||
return nil;
|
||||
|
||||
return (NSBox *)[self.siteCollectionView itemAtIndex:selectedIndex].view;
|
||||
}
|
||||
|
||||
- (MPElementModel *)selectedElement {
|
||||
|
||||
NSUInteger selectedIndex = [self selectedIndex];
|
||||
if (selectedIndex == NSNotFound)
|
||||
return nil;
|
||||
|
||||
return (MPElementModel *)self.elements[selectedIndex];
|
||||
}
|
||||
|
||||
- (void)setSelectedElement:(MPElementModel *)element {
|
||||
|
||||
self.elementSelectionIndexes = [NSIndexSet indexSetWithIndex:[self.elements indexOfObject:element]];
|
||||
}
|
||||
|
||||
- (void)useSite {
|
||||
|
||||
MPElementModel *selectedElement = [self selectedElement];
|
||||
if (selectedElement) {
|
||||
// Performing action while content is available. Copy it.
|
||||
[self copyContent:selectedElement.content];
|
||||
|
||||
[self close];
|
||||
|
||||
NSUserNotification *notification = [NSUserNotification new];
|
||||
notification.title = @"Password Copied";
|
||||
if (selectedElement.loginName.length)
|
||||
notification.subtitle = PearlString( @"%@ at %@", selectedElement.loginName, selectedElement.site );
|
||||
else
|
||||
notification.subtitle = selectedElement.site;
|
||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
||||
}
|
||||
else {
|
||||
NSString *siteName = [self.siteField stringValue];
|
||||
if ([siteName length])
|
||||
// Performing action without content but a site name is written.
|
||||
[self createNewSite:siteName];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)copyContent:(NSString *)content {
|
||||
|
||||
[[NSPasteboard generalPasteboard] declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
|
||||
if (![[NSPasteboard generalPasteboard] setString:content forType:NSPasteboardTypeString]) {
|
||||
wrn(@"Couldn't copy password to pasteboard.");
|
||||
return;
|
||||
}
|
||||
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
[[self.selectedElement entityInContext:moc] use];
|
||||
[moc saveToStore];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)createNewSite:(NSString *)siteName {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
NSAlert *alert = [NSAlert new];
|
||||
[alert addButtonWithTitle:@"Create"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
[alert setMessageText:@"Create site?"];
|
||||
[alert setInformativeText:PearlString( @"Do you want to create a new site named:\n\n%@", siteName )];
|
||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertCreateSite];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - KVO
|
||||
|
||||
- (void)setElementSelectionIndexes:(NSIndexSet *)elementSelectionIndexes {
|
||||
|
||||
// First reset bounds.
|
||||
PearlMainQueue(^{
|
||||
NSUInteger selectedIndex = self.elementSelectionIndexes.firstIndex;
|
||||
if (selectedIndex != NSNotFound && selectedIndex < self.elements.count)
|
||||
[[self selectedView].animator setBoundsOrigin:NSZeroPoint];
|
||||
} );
|
||||
|
||||
_elementSelectionIndexes = elementSelectionIndexes;
|
||||
}
|
||||
|
||||
- (void)insertObject:(MPElementModel *)model inElementsAtIndex:(NSUInteger)index {
|
||||
|
||||
[self.elements insertObject:model atIndex:index];
|
||||
}
|
||||
|
||||
- (void)removeObjectFromElementsAtIndex:(NSUInteger)index {
|
||||
|
||||
[self.elements removeObjectAtIndex:index];
|
||||
}
|
||||
|
||||
@end
|
380
MasterPassword/ObjC/Mac/MPPasswordDialogController.xib
Normal file
380
MasterPassword/ObjC/Mac/MPPasswordDialogController.xib
Normal file
@ -0,0 +1,380 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13D65" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment defaultVersion="1080" identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="MPPasswordDialogController">
|
||||
<connections>
|
||||
<outlet property="contentContainer" destination="143" id="214"/>
|
||||
<outlet property="siteCollectionView" destination="pr9-BO-vQV" id="Bnh-WQ-RaO"/>
|
||||
<outlet property="siteField" destination="182" id="224"/>
|
||||
<outlet property="userLabel" destination="216" id="223"/>
|
||||
<outlet property="window" destination="22" id="40"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application"/>
|
||||
<window title="Master Password" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="22" customClass="NSPanel">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES" texturedBackground="YES"/>
|
||||
<rect key="contentRect" x="600" y="530" width="480" height="320"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<value key="minSize" type="size" width="480" height="320"/>
|
||||
<value key="maxSize" type="size" width="480" height="320"/>
|
||||
<view key="contentView" wantsLayer="YES" id="23">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="320"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="143">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="320"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="182">
|
||||
<rect key="frame" x="140" y="256" width="200" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="200" id="258"/>
|
||||
</constraints>
|
||||
<shadow key="shadow" blurRadius="2">
|
||||
<color key="color" name="controlShadowColor" catalog="System" colorSpace="catalog"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="center" placeholderString="Site name" usesSingleLineMode="YES" bezelStyle="round" id="185">
|
||||
<font key="font" metaFont="cellTitle"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="188"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="216">
|
||||
<rect key="frame" x="146" y="286" width="188" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" alignment="center" title="Maarten Billemont's password for:" usesSingleLineMode="YES" id="217">
|
||||
<font key="font" metaFont="palette"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<scrollView autohidesScrollers="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tjI-mV-s8H">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="248"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<clipView key="contentView" id="mfh-QT-ClZ">
|
||||
<rect key="frame" x="1" y="1" width="478" height="246"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<collectionView selectable="YES" maxNumberOfColumns="1" id="pr9-BO-vQV">
|
||||
<rect key="frame" x="0.0" y="0.0" width="478" height="246"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="primaryBackgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="secondaryBackgroundColor" name="controlAlternatingRowColor" catalog="System" colorSpace="catalog"/>
|
||||
<connections>
|
||||
<binding destination="jTN-Q9-Ajn" name="content" keyPath="arrangedObjects" id="dtF-fs-Fpe"/>
|
||||
<binding destination="-2" name="selectionIndexes" keyPath="elementSelectionIndexes" previousBinding="dtF-fs-Fpe" id="UFy-9F-18H"/>
|
||||
<outlet property="delegate" destination="-2" id="4cD-GP-imR"/>
|
||||
<outlet property="itemPrototype" destination="QBZ-sO-HQn" id="QAi-HN-YUc"/>
|
||||
</connections>
|
||||
</collectionView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="6vP-Im-BRg">
|
||||
<rect key="frame" x="-100" y="-100" width="233" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="vs6-1G-hvM">
|
||||
<rect key="frame" x="-100" y="-100" width="15" height="143"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<button horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="tLu-3k-QiL">
|
||||
<rect key="frame" x="449" y="288" width="25" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="help" bezelStyle="helpButton" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="51o-8V-9eq">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="216" firstAttribute="top" secondItem="143" secondAttribute="top" constant="20" symbolic="YES" id="218"/>
|
||||
<constraint firstItem="182" firstAttribute="top" secondItem="216" secondAttribute="bottom" constant="8" symbolic="YES" id="221"/>
|
||||
<constraint firstAttribute="bottom" secondItem="tjI-mV-s8H" secondAttribute="bottom" id="6y8-tJ-1sX"/>
|
||||
<constraint firstItem="tLu-3k-QiL" firstAttribute="top" secondItem="143" secondAttribute="top" constant="8" id="9h7-dN-MqZ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tLu-3k-QiL" secondAttribute="trailing" constant="8" id="UQN-Ab-fIg"/>
|
||||
<constraint firstAttribute="centerX" secondItem="182" secondAttribute="centerX" id="W6t-BO-Njn"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tjI-mV-s8H" secondAttribute="trailing" id="aKe-a9-Br8"/>
|
||||
<constraint firstItem="tjI-mV-s8H" firstAttribute="leading" secondItem="143" secondAttribute="leading" id="d8F-JD-EhR"/>
|
||||
<constraint firstItem="tjI-mV-s8H" firstAttribute="top" secondItem="182" secondAttribute="bottom" constant="8" symbolic="YES" id="izG-uH-9BF"/>
|
||||
<constraint firstAttribute="centerX" secondItem="216" secondAttribute="centerX" id="mkv-5E-dy5"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="143" firstAttribute="leading" secondItem="23" secondAttribute="leading" id="145"/>
|
||||
<constraint firstItem="143" firstAttribute="bottom" secondItem="23" secondAttribute="bottom" id="147"/>
|
||||
<constraint firstItem="143" firstAttribute="trailing" secondItem="23" secondAttribute="trailing" id="148"/>
|
||||
<constraint firstItem="143" firstAttribute="top" secondItem="23" secondAttribute="top" id="150"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="39"/>
|
||||
</connections>
|
||||
</window>
|
||||
<collectionViewItem id="QBZ-sO-HQn" customClass="MPElementCollectionView">
|
||||
<connections>
|
||||
<outlet property="view" destination="bhu-Ky-PQq" id="jZh-jC-6bL"/>
|
||||
</connections>
|
||||
</collectionViewItem>
|
||||
<arrayController objectClassName="MPElementModel" id="jTN-Q9-Ajn">
|
||||
<connections>
|
||||
<binding destination="-2" name="contentArray" keyPath="self.elements" id="8Uz-14-YG0"/>
|
||||
</connections>
|
||||
</arrayController>
|
||||
<box autoresizesSubviews="NO" wantsLayer="YES" boxType="custom" borderType="none" titlePosition="noTitle" id="bhu-Ky-PQq">
|
||||
<rect key="frame" x="0.0" y="0.0" width="960" height="61"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<view key="contentView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="960" height="61"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xwJ-Pu-glP">
|
||||
<rect key="frame" x="6" y="35" width="60" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.59999999999999998" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="apple.com" usesSingleLineMode="YES" id="ymH-M0-M5d">
|
||||
<font key="font" size="12" name="Exo2.0-Light"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.site" id="4as-ow-WbD"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Cn5-nt-e6X">
|
||||
<rect key="frame" x="362" y="35" width="111" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.59999999999999998" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="lhunath@lyndir.com" usesSingleLineMode="YES" id="Px4-pS-kwG">
|
||||
<font key="font" size="12" name="Exo2.0-Light"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.loginName" id="C2s-1d-p2H">
|
||||
<dictionary key="options">
|
||||
<bool key="NSContinuouslyUpdatesValue" value="YES"/>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="a1n-Sf-Mw6">
|
||||
<rect key="frame" x="6" y="8" width="206" height="38"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.59999999999999998" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="RutuTutnTeni4," id="7jb-Fa-xX3">
|
||||
<font key="font" size="24" name="SourceCodePro-Light"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.content" id="41c-PF-OeH">
|
||||
<dictionary key="options">
|
||||
<bool key="NSContinuouslyUpdatesValue" value="YES"/>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="mp4-r1-7Xg">
|
||||
<rect key="frame" x="440" y="8" width="33" height="38"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.59999999999999998" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="12" id="Vb9-nO-cWY">
|
||||
<font key="font" size="24" name="SourceCodePro-Light"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.uses" id="gSt-Nd-lVa">
|
||||
<dictionary key="options">
|
||||
<bool key="NSContinuouslyUpdatesValue" value="YES"/>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<box autoresizesSubviews="NO" horizontalHuggingPriority="750" title="Box" boxType="separator" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="tsT-Xh-Nxb">
|
||||
<rect key="frame" x="477" y="0.0" width="5" height="61"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
|
||||
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<font key="titleFont" metaFont="system"/>
|
||||
</box>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vEl-aL-Qd4">
|
||||
<rect key="frame" x="791" y="27" width="167" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="lhunath@lyndir.com" bezelStyle="rounded" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sl3-bH-Hh2">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="updateLoginName:" target="QBZ-sO-HQn" id="pJI-k8-LRl"/>
|
||||
<binding destination="QBZ-sO-HQn" name="title" keyPath="representedObject.loginName" id="uaP-Y1-bz6">
|
||||
<dictionary key="options">
|
||||
<string key="NSNullPlaceholder">Click to set login name</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</button>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="d2a-pG-7CW">
|
||||
<rect key="frame" x="528" y="31" width="127" height="26"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Long Password" bezelStyle="rounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" selectedItem="7Bj-S7-WSd" id="RZo-c7-kqA">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" title="OtherViews" id="mQN-XZ-YKz">
|
||||
<items>
|
||||
<menuItem title="Long Password" state="on" id="7Bj-S7-WSd"/>
|
||||
<menuItem title="Item 2" id="WUd-69-IBV"/>
|
||||
<menuItem title="Item 3" id="pgH-yZ-G0J"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="contentValues" keyPath="representedObject.typeNames" id="eyo-f9-MwY"/>
|
||||
<binding destination="QBZ-sO-HQn" name="selectedIndex" keyPath="representedObject.typeIndex" previousBinding="eyo-f9-MwY" id="dpI-HX-GpX"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="npg-mh-AfY">
|
||||
<rect key="frame" x="486" y="36" width="38" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Type:" id="U2E-DE-2j4">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hqw-ZP-4c1">
|
||||
<rect key="frame" x="486" y="11" width="59" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Number:" id="CDU-Ah-QDj">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="counterHidden" id="xlz-gk-Gwc"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<stepper horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JPX-xQ-VKZ">
|
||||
<rect key="frame" x="565" y="6" width="19" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<stepperCell key="cell" alignment="left" minValue="1" maxValue="100" doubleValue="1" autorepeat="NO" id="ELG-fy-nVF"/>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="counterHidden" id="3FO-ks-R7U"/>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.counter" id="awJ-Vg-RUn"/>
|
||||
</connections>
|
||||
</stepper>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="kZI-sG-dEn">
|
||||
<rect key="frame" x="549" y="11" width="13" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="1" id="EUB-gJ-7Db">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="counterHidden" id="ZFX-79-eAY"/>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.counter" id="20y-tn-B5k"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="qOt-Rp-G9T">
|
||||
<rect key="frame" x="877" y="2" width="81" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Delete" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="QCU-VC-W0u">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="delete:" target="QBZ-sO-HQn" id="mLJ-JY-5fz"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5YU-4W-4gz">
|
||||
<rect key="frame" x="727" y="2" width="150" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Change Password" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="NQY-Oo-Eid">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="updateContent:" target="QBZ-sO-HQn" id="J8f-vx-10A"/>
|
||||
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="updateContentHidden" id="UwG-p5-kH4"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bzg-90-kmh">
|
||||
<rect key="frame" x="748" y="36" width="43" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Login:" id="uxE-6c-RjC">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstItem="hqw-ZP-4c1" firstAttribute="centerY" secondItem="qOt-Rp-G9T" secondAttribute="centerY" id="6xp-tI-BkX"/>
|
||||
<constraint firstItem="npg-mh-AfY" firstAttribute="leading" secondItem="tsT-Xh-Nxb" secondAttribute="trailing" constant="8" id="7kp-OB-3BI"/>
|
||||
<constraint firstItem="kZI-sG-dEn" firstAttribute="leading" secondItem="hqw-ZP-4c1" secondAttribute="trailing" constant="8" symbolic="YES" id="8qK-Et-c1F"/>
|
||||
<constraint firstItem="d2a-pG-7CW" firstAttribute="leading" secondItem="npg-mh-AfY" secondAttribute="trailing" constant="8" symbolic="YES" id="F6X-FD-kEX"/>
|
||||
<constraint firstItem="Cn5-nt-e6X" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" constant="8" id="FWS-tY-KkM"/>
|
||||
<constraint firstItem="hqw-ZP-4c1" firstAttribute="top" secondItem="npg-mh-AfY" secondAttribute="bottom" constant="8" symbolic="YES" id="GuG-5I-quA"/>
|
||||
<constraint firstItem="hqw-ZP-4c1" firstAttribute="leading" secondItem="tsT-Xh-Nxb" secondAttribute="trailing" constant="8" id="Hzf-XZ-auZ"/>
|
||||
<constraint firstItem="tsT-Xh-Nxb" firstAttribute="leading" secondItem="Cn5-nt-e6X" secondAttribute="trailing" constant="8" id="LjD-10-tVU"/>
|
||||
<constraint firstItem="tsT-Xh-Nxb" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" id="ODH-Nx-QdY"/>
|
||||
<constraint firstItem="qOt-Rp-G9T" firstAttribute="centerY" secondItem="5YU-4W-4gz" secondAttribute="centerY" id="PdB-X5-eqF"/>
|
||||
<constraint firstItem="xwJ-Pu-glP" firstAttribute="leading" secondItem="bhu-Ky-PQq" secondAttribute="leading" constant="8" id="QAM-jm-t0y"/>
|
||||
<constraint firstAttribute="centerY" secondItem="tsT-Xh-Nxb" secondAttribute="centerY" id="Rpi-lc-dZ1"/>
|
||||
<constraint firstItem="tsT-Xh-Nxb" firstAttribute="leading" secondItem="mp4-r1-7Xg" secondAttribute="trailing" constant="8" id="Xfc-Jq-2Rb"/>
|
||||
<constraint firstAttribute="trailing" secondItem="vEl-aL-Qd4" secondAttribute="trailing" constant="8" id="ZZu-AS-C07"/>
|
||||
<constraint firstAttribute="bottom" secondItem="tsT-Xh-Nxb" secondAttribute="bottom" id="ds1-7i-B7I"/>
|
||||
<constraint firstItem="a1n-Sf-Mw6" firstAttribute="leading" secondItem="bhu-Ky-PQq" secondAttribute="leading" constant="8" id="e3g-2s-yee"/>
|
||||
<constraint firstItem="npg-mh-AfY" firstAttribute="centerY" secondItem="vEl-aL-Qd4" secondAttribute="centerY" id="ftr-2Z-9J0"/>
|
||||
<constraint firstItem="npg-mh-AfY" firstAttribute="centerY" secondItem="d2a-pG-7CW" secondAttribute="centerY" id="g9a-r0-EOo"/>
|
||||
<constraint firstAttribute="bottom" secondItem="mp4-r1-7Xg" secondAttribute="bottom" constant="8" id="jCW-5H-6pT"/>
|
||||
<constraint firstAttribute="centerX" secondItem="tsT-Xh-Nxb" secondAttribute="centerX" id="kx6-g0-jUW"/>
|
||||
<constraint firstAttribute="bottom" secondItem="a1n-Sf-Mw6" secondAttribute="bottom" constant="8" id="mWW-rt-kl2"/>
|
||||
<constraint firstItem="npg-mh-AfY" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" constant="8" id="n7Z-EF-Dcm"/>
|
||||
<constraint firstItem="qOt-Rp-G9T" firstAttribute="leading" secondItem="5YU-4W-4gz" secondAttribute="trailing" constant="12" symbolic="YES" id="uWm-hE-itO"/>
|
||||
<constraint firstAttribute="trailing" secondItem="qOt-Rp-G9T" secondAttribute="trailing" constant="8" id="x6J-1l-rU4"/>
|
||||
<constraint firstItem="hqw-ZP-4c1" firstAttribute="centerY" secondItem="kZI-sG-dEn" secondAttribute="centerY" id="xZ7-Mc-9dq"/>
|
||||
<constraint firstItem="vEl-aL-Qd4" firstAttribute="leading" secondItem="bzg-90-kmh" secondAttribute="trailing" constant="8" symbolic="YES" id="z7h-om-WAV"/>
|
||||
<constraint firstItem="xwJ-Pu-glP" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" constant="8" id="z8k-ot-NjU"/>
|
||||
<constraint firstItem="bzg-90-kmh" firstAttribute="centerY" secondItem="vEl-aL-Qd4" secondAttribute="centerY" id="zbz-Qg-uHO"/>
|
||||
<constraint firstItem="JPX-xQ-VKZ" firstAttribute="centerY" secondItem="kZI-sG-dEn" secondAttribute="centerY" id="zcO-M3-gyr"/>
|
||||
<constraint firstItem="JPX-xQ-VKZ" firstAttribute="leading" secondItem="kZI-sG-dEn" secondAttribute="trailing" constant="8" symbolic="YES" id="zvB-Vk-IL2"/>
|
||||
</constraints>
|
||||
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
|
||||
<color key="fillColor" name="selectedControlColor" catalog="System" colorSpace="catalog"/>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="transparent" keyPath="selected" id="Tpz-Rp-lA7">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</box>
|
||||
</objects>
|
||||
</document>
|
23
MasterPassword/ObjC/Mac/MPPasswordWindow.h
Normal file
23
MasterPassword/ObjC/Mac/MPPasswordWindow.h
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPPasswordWindow.h
|
||||
// MPPasswordWindow
|
||||
//
|
||||
// Created by lhunath on 2014-06-19.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
|
||||
@interface MPPasswordWindow : NSWindow
|
||||
@end
|
43
MasterPassword/ObjC/Mac/MPPasswordWindow.m
Normal file
43
MasterPassword/ObjC/Mac/MPPasswordWindow.m
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPPasswordWindow.h
|
||||
// MPPasswordWindow
|
||||
//
|
||||
// Created by lhunath on 2014-06-19.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPPasswordWindow.h"
|
||||
|
||||
|
||||
@implementation MPPasswordWindow
|
||||
|
||||
#pragma mark - Life
|
||||
|
||||
- (void)awakeFromNib {
|
||||
|
||||
[super awakeFromNib];
|
||||
|
||||
self.level = NSScreenSaverWindowLevel;
|
||||
self.alphaValue = 0;
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeKeyWindow {
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - State
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
@end
|
@ -1,23 +1,27 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPPasswordWindowController.h
|
||||
// MasterPassword-Mac
|
||||
// MPPasswordWindowController
|
||||
//
|
||||
// Created by Maarten Billemont on 04/03/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
// Created by lhunath on 2014-06-18.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
@class MPElementModel;
|
||||
|
||||
@interface MPPasswordWindowController : NSWindowController<NSTextFieldDelegate, NSCollectionViewDelegate>
|
||||
|
||||
@property(nonatomic, strong) NSMutableArray *elements;
|
||||
@property(nonatomic, strong) NSIndexSet *elementSelectionIndexes;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *siteField;
|
||||
@property(nonatomic, weak) IBOutlet NSView *contentContainer;
|
||||
@property(nonatomic, weak) IBOutlet NSImageView *blurView;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *userLabel;
|
||||
@property(nonatomic, weak) IBOutlet NSCollectionView *siteCollectionView;
|
||||
|
||||
- (void)updateElements;
|
||||
@property(nonatomic, weak) IBOutlet NSSearchField *siteField;
|
||||
|
||||
@end
|
||||
|
@ -1,30 +1,24 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPPasswordWindowController.m
|
||||
// MasterPassword-Mac
|
||||
// MPPasswordWindowController.h
|
||||
// MPPasswordWindowController
|
||||
//
|
||||
// Created by Maarten Billemont on 04/03/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
// Created by lhunath on 2014-06-18.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPPasswordWindowController.h"
|
||||
#import "MPMacAppDelegate.h"
|
||||
#import "MPAppDelegate_Key.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPElementModel.h"
|
||||
|
||||
#define MPAlertUnlockMP @"MPAlertUnlockMP"
|
||||
#define MPAlertIncorrectMP @"MPAlertIncorrectMP"
|
||||
#define MPAlertCreateSite @"MPAlertCreateSite"
|
||||
|
||||
@interface MPPasswordWindowController()
|
||||
|
||||
@property(nonatomic) BOOL inProgress;
|
||||
|
||||
@property(nonatomic, strong) NSOperationQueue *backgroundQueue;
|
||||
@property(nonatomic, strong) NSAlert *loadingDataAlert;
|
||||
@property(nonatomic) BOOL closing;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPPasswordWindowController
|
||||
|
||||
@ -32,446 +26,78 @@
|
||||
|
||||
- (void)windowDidLoad {
|
||||
|
||||
if ([[MPMacConfig get].dialogStyleHUD boolValue]) {
|
||||
self.window.styleMask = NSHUDWindowMask | NSTitledWindowMask | NSUtilityWindowMask | NSClosableWindowMask;
|
||||
self.userLabel.textColor = [NSColor whiteColor];
|
||||
}
|
||||
else {
|
||||
self.window.styleMask = NSTexturedBackgroundWindowMask | NSResizableWindowMask | NSTitledWindowMask | NSClosableWindowMask;
|
||||
self.userLabel.textColor = [NSColor controlTextColor];
|
||||
}
|
||||
|
||||
self.backgroundQueue = [NSOperationQueue new];
|
||||
self.backgroundQueue.maxConcurrentOperationCount = 1;
|
||||
|
||||
[[MPMacAppDelegate get] addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
// [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
// if (![MPAlgorithmDefault migrateUser:[[MPMacAppDelegate get] activeUserInContext:moc]])
|
||||
// [NSAlert alertWithMessageText:@"Migration Needed" defaultButton:@"OK" alternateButton:nil otherButton:nil
|
||||
// informativeTextWithFormat:@"Certain sites require explicit migration to get updated to the latest version of the "
|
||||
// @"Master Password algorithm. For these sites, a migration button will appear. Migrating these sites will cause "
|
||||
// @"their passwords to change. You'll need to update your profile for that site with the new password."];
|
||||
// [moc saveToStore];
|
||||
// }];
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:YES];
|
||||
[self updateElements];
|
||||
}];
|
||||
} forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification object:self.window
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:NO];
|
||||
[self.siteField selectText:nil];
|
||||
[self updateElements];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:self.window
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
NSWindow *sheet = [self.window attachedSheet];
|
||||
if (sheet)
|
||||
[NSApp endSheet:sheet];
|
||||
|
||||
[NSApp hide:nil];
|
||||
self.closing = NO;
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedOutNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
self.userLabel.stringValue = @"";
|
||||
self.siteField.stringValue = @"";
|
||||
self.elements = nil;
|
||||
|
||||
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:YES];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedInNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
self.userLabel.stringValue = PearlString( @"%@'s password for:",
|
||||
[[MPMacAppDelegate get] activeUserForMainThread].name );
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidChangeNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:NO];
|
||||
}];
|
||||
|
||||
[super windowDidLoad];
|
||||
|
||||
// [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillBecomeActiveNotification object:nil
|
||||
// queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
// [self fadeIn];
|
||||
// }];
|
||||
// [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillResignActiveNotification object:nil
|
||||
// queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
// [self fadeOut];
|
||||
// }];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification object:self.window
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
[self fadeIn];
|
||||
[self.siteField becomeFirstResponder];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidResignKeyNotification object:self.window
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
[self fadeOut];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedInNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
[self updateUser];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedOutNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
[self updateUser];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
- (void)updateUser {
|
||||
|
||||
self.closing = YES;
|
||||
[super close];
|
||||
[MPMacAppDelegate managedObjectContextForMainThreadPerformBlock:^(NSManagedObjectContext *mainContext) {
|
||||
MPUserEntity *mainActiveUser = [[MPMacAppDelegate get] activeUserInContext:mainContext];
|
||||
if (mainActiveUser)
|
||||
self.userLabel.stringValue = strf( @"%@'s password for:", mainActiveUser.name );
|
||||
else
|
||||
self.userLabel.stringValue = @"";
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - NSAlert
|
||||
|
||||
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
||||
|
||||
if (contextInfo == MPAlertIncorrectMP) {
|
||||
[self close];
|
||||
return;
|
||||
}
|
||||
if (contextInfo == MPAlertUnlockMP) {
|
||||
switch (returnCode) {
|
||||
case NSAlertFirstButtonReturn: {
|
||||
// "Unlock" button.
|
||||
self.contentContainer.alphaValue = 0;
|
||||
self.inProgress = YES;
|
||||
|
||||
NSString *password = [(NSSecureTextField *)alert.accessoryView stringValue];
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc];
|
||||
NSString *userName = activeUser.name;
|
||||
BOOL success = [[MPMacAppDelegate get] signInAsUser:activeUser saveInContext:moc
|
||||
usingMasterPassword:password];
|
||||
self.inProgress = NO;
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
if (success)
|
||||
self.contentContainer.alphaValue = 1;
|
||||
else {
|
||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey : PearlString( @"Incorrect master password for user %@", userName )
|
||||
}]] beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertIncorrectMP];
|
||||
}
|
||||
}];
|
||||
}];
|
||||
break;
|
||||
}
|
||||
|
||||
case NSAlertSecondButtonReturn: {
|
||||
// "Change" button.
|
||||
NSAlert *alert_ = [NSAlert new];
|
||||
[alert_ addButtonWithTitle:@"Update"];
|
||||
[alert_ addButtonWithTitle:@"Cancel"];
|
||||
[alert_ setMessageText:@"Changing Master Password"];
|
||||
[alert_ setInformativeText:@"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."];
|
||||
|
||||
if ([alert_ runModal] == NSAlertFirstButtonReturn) {
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:context];
|
||||
activeUser.keyID = nil;
|
||||
[[MPMacAppDelegate get] forgetSavedKeyFor:activeUser];
|
||||
[[MPMacAppDelegate get] signOutAnimated:YES];
|
||||
[context saveToStore];
|
||||
}];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NSAlertThirdButtonReturn: {
|
||||
// "Cancel" button.
|
||||
[self close];
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (contextInfo == MPAlertCreateSite) {
|
||||
switch (returnCode) {
|
||||
case NSAlertFirstButtonReturn: {
|
||||
// "Create" button.
|
||||
[[MPMacAppDelegate get] addElementNamed:[self.siteField stringValue] completion:^(MPElementEntity *element) {
|
||||
if (element)
|
||||
PearlMainQueue( ^{ [self updateElements]; } );
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case NSAlertThirdButtonReturn:
|
||||
// "Cancel" button.
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - NSCollectionViewDelegate
|
||||
|
||||
#pragma mark - NSTextFieldDelegate
|
||||
- (void)doCommandBySelector:(SEL)commandSelector {
|
||||
|
||||
if (commandSelector == @selector(insertNewline:))
|
||||
[self useSite];
|
||||
}
|
||||
|
||||
- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector {
|
||||
|
||||
if (commandSelector == @selector(cancel:))
|
||||
[self close];
|
||||
if (commandSelector == @selector(moveUp:))
|
||||
self.elementSelectionIndexes =
|
||||
[NSIndexSet indexSetWithIndex:MAX(self.elementSelectionIndexes.firstIndex, (NSUInteger)1) - 1];
|
||||
if (commandSelector == @selector(moveDown:))
|
||||
self.elementSelectionIndexes =
|
||||
[NSIndexSet indexSetWithIndex:MIN(self.elementSelectionIndexes.firstIndex + 1, self.elements.count - 1)];
|
||||
if (commandSelector == @selector(moveLeft:))
|
||||
[[self selectedView].animator setBoundsOrigin:NSZeroPoint];
|
||||
if (commandSelector == @selector(moveRight:))
|
||||
[[self selectedView].animator setBoundsOrigin:NSMakePoint( self.siteCollectionView.frame.size.width / 2, 0 )];
|
||||
if (commandSelector == @selector(insertNewline:))
|
||||
[self useSite];
|
||||
else
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)controlTextDidChange:(NSNotification *)note {
|
||||
|
||||
if (note.object != self.siteField)
|
||||
return;
|
||||
|
||||
// Update the site content as the site name changes.
|
||||
if ([[NSApp currentEvent] type] == NSKeyDown &&
|
||||
[[[NSApp currentEvent] charactersIgnoringModifiers] isEqualToString:@"\r"]) { // Return while completing.
|
||||
[self useSite];
|
||||
return;
|
||||
}
|
||||
|
||||
// if ([[NSApp currentEvent] type] == NSKeyDown &&
|
||||
// [[[NSApp currentEvent] charactersIgnoringModifiers] characterAtIndex:0] == 0x1b) { // Escape while completing.
|
||||
// [self trySiteWithAction:NO];
|
||||
// return;
|
||||
// }
|
||||
|
||||
[self updateElements];
|
||||
}
|
||||
#pragma mark - State
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (BOOL)ensureLoadedAndUnlockedOrCloseIfLoggedOut:(BOOL)closeIfLoggedOut {
|
||||
- (void)fadeIn {
|
||||
|
||||
if (![self ensureStoreLoaded])
|
||||
return NO;
|
||||
CGWindowID windowID = (CGWindowID)[self.window windowNumber];
|
||||
CGImageRef capturedImage = CGWindowListCreateImage( CGRectInfinite, kCGWindowListOptionOnScreenBelowWindow, windowID,
|
||||
kCGWindowImageBoundsIgnoreFraming );
|
||||
NSImage *screenImage = [[NSImage alloc] initWithCGImage:capturedImage size:NSMakeSize(
|
||||
CGImageGetWidth( capturedImage ) / self.window.backingScaleFactor,
|
||||
CGImageGetHeight( capturedImage ) / self.window.backingScaleFactor )];
|
||||
|
||||
if (self.closing || self.inProgress || !self.window.isKeyWindow)
|
||||
return NO;
|
||||
NSImage *smallImage = [[NSImage alloc] initWithSize:NSMakeSize(
|
||||
CGImageGetWidth( capturedImage ) / 20,
|
||||
CGImageGetHeight( capturedImage ) / 20 )];
|
||||
[smallImage lockFocus];
|
||||
[screenImage drawInRect:(NSRect){ .origin = CGPointZero, .size = smallImage.size, }
|
||||
fromRect:NSZeroRect
|
||||
operation:NSCompositeSourceOver
|
||||
fraction:1.0];
|
||||
[smallImage unlockFocus];
|
||||
|
||||
return [self ensureUnlocked:closeIfLoggedOut];
|
||||
self.blurView.image = smallImage;
|
||||
|
||||
[self.window setFrame:self.window.screen.frame display:YES];
|
||||
[[self.window animator] setAlphaValue:1.0];
|
||||
}
|
||||
|
||||
- (BOOL)ensureStoreLoaded {
|
||||
- (void)fadeOut {
|
||||
|
||||
if ([MPMacAppDelegate managedObjectContextForMainThreadIfReady]) {
|
||||
// Store loaded.
|
||||
if (self.loadingDataAlert.window)
|
||||
[NSApp endSheet:self.loadingDataAlert.window];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
[self.loadingDataAlert = [NSAlert alertWithMessageText:@"Opening Your Data" defaultButton:@"..." alternateButton:nil otherButton:nil
|
||||
informativeTextWithFormat:@""]
|
||||
beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:nil];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)ensureUnlocked:(BOOL)closeIfLoggedOut {
|
||||
|
||||
__block BOOL unlocked = NO;
|
||||
[MPMacAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc];
|
||||
NSString *userName = activeUser.name;
|
||||
if (!activeUser) {
|
||||
// No user to sign in with.
|
||||
if (closeIfLoggedOut)
|
||||
[self close];
|
||||
return;
|
||||
}
|
||||
if ([MPMacAppDelegate get].key) {
|
||||
// Already logged in.
|
||||
unlocked = YES;
|
||||
return;
|
||||
}
|
||||
if (activeUser.saveKey && closeIfLoggedOut) {
|
||||
// App was locked, don't instantly unlock again.
|
||||
[self close];
|
||||
return;
|
||||
}
|
||||
if ([[MPMacAppDelegate get] signInAsUser:activeUser saveInContext:moc usingMasterPassword:nil]) {
|
||||
// Loaded the key from the keychain.
|
||||
unlocked = YES;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ask the user to set the key through his master password.
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
if ([MPMacAppDelegate get].key)
|
||||
return;
|
||||
|
||||
[self.siteField setStringValue:@""];
|
||||
|
||||
NSAlert *alert = [NSAlert new];
|
||||
[alert addButtonWithTitle:@"Unlock"];
|
||||
[alert addButtonWithTitle:@"Change"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
[alert setMessageText:@"Master Password is locked."];
|
||||
[alert setInformativeText:PearlString( @"The master password is required to unlock the application for:\n\n%@", userName )];
|
||||
|
||||
NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||
[alert setAccessoryView:passwordField];
|
||||
[alert layout];
|
||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertUnlockMP];
|
||||
[passwordField becomeFirstResponder];
|
||||
}];
|
||||
}];
|
||||
|
||||
return unlocked;
|
||||
}
|
||||
|
||||
- (void)updateElements {
|
||||
|
||||
if (![MPMacAppDelegate get].key) {
|
||||
self.elements = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *query = [self.siteField.currentEditor string];
|
||||
[MPMacAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) {
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
||||
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"lastUsed" ascending:NO]];
|
||||
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(%@ == '' OR name BEGINSWITH[cd] %@) AND user == %@",
|
||||
query, query, [[MPMacAppDelegate get] activeUserInContext:context]];
|
||||
|
||||
NSError *error = nil;
|
||||
NSArray *siteResults = [context executeFetchRequest:fetchRequest error:&error];
|
||||
if (!siteResults) {
|
||||
err(@"While fetching elements for completion: %@", error);
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableArray *newElements = [NSMutableArray arrayWithCapacity:[siteResults count]];
|
||||
for (MPElementEntity *element in siteResults)
|
||||
[newElements addObject:[[MPElementModel alloc] initWithEntity:element]];
|
||||
self.elements = newElements;
|
||||
if (!self.selectedElement)
|
||||
self.elementSelectionIndexes = [newElements count]? [NSIndexSet indexSetWithIndex:0]: nil;
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSUInteger)selectedIndex {
|
||||
|
||||
if (!self.elementSelectionIndexes)
|
||||
return NSNotFound;
|
||||
NSUInteger selectedIndex = self.elementSelectionIndexes.firstIndex;
|
||||
if (selectedIndex >= self.elements.count)
|
||||
return NSNotFound;
|
||||
|
||||
return selectedIndex;
|
||||
}
|
||||
|
||||
- (NSBox *)selectedView {
|
||||
|
||||
NSUInteger selectedIndex = [self selectedIndex];
|
||||
if (selectedIndex == NSNotFound)
|
||||
return nil;
|
||||
|
||||
return (NSBox *)[self.siteCollectionView itemAtIndex:selectedIndex].view;
|
||||
}
|
||||
|
||||
- (MPElementModel *)selectedElement {
|
||||
|
||||
NSUInteger selectedIndex = [self selectedIndex];
|
||||
if (selectedIndex == NSNotFound)
|
||||
return nil;
|
||||
|
||||
return (MPElementModel *)self.elements[selectedIndex];
|
||||
}
|
||||
|
||||
- (void)setSelectedElement:(MPElementModel *)element {
|
||||
|
||||
self.elementSelectionIndexes = [NSIndexSet indexSetWithIndex:[self.elements indexOfObject:element]];
|
||||
}
|
||||
|
||||
- (void)useSite {
|
||||
|
||||
MPElementModel *selectedElement = [self selectedElement];
|
||||
if (selectedElement) {
|
||||
// Performing action while content is available. Copy it.
|
||||
[self copyContent:selectedElement.content];
|
||||
|
||||
[self close];
|
||||
|
||||
NSUserNotification *notification = [NSUserNotification new];
|
||||
notification.title = @"Password Copied";
|
||||
if (selectedElement.loginName.length)
|
||||
notification.subtitle = PearlString( @"%@ at %@", selectedElement.loginName, selectedElement.site );
|
||||
else
|
||||
notification.subtitle = selectedElement.site;
|
||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
||||
}
|
||||
else {
|
||||
NSString *siteName = [self.siteField stringValue];
|
||||
if ([siteName length])
|
||||
// Performing action without content but a site name is written.
|
||||
[self createNewSite:siteName];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)copyContent:(NSString *)content {
|
||||
|
||||
[[NSPasteboard generalPasteboard] declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
|
||||
if (![[NSPasteboard generalPasteboard] setString:content forType:NSPasteboardTypeString]) {
|
||||
wrn(@"Couldn't copy password to pasteboard.");
|
||||
return;
|
||||
}
|
||||
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
[[self.selectedElement entityInContext:moc] use];
|
||||
[moc saveToStore];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)createNewSite:(NSString *)siteName {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
NSAlert *alert = [NSAlert new];
|
||||
[alert addButtonWithTitle:@"Create"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
[alert setMessageText:@"Create site?"];
|
||||
[alert setInformativeText:PearlString( @"Do you want to create a new site named:\n\n%@", siteName )];
|
||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertCreateSite];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - KVO
|
||||
|
||||
- (void)setElementSelectionIndexes:(NSIndexSet *)elementSelectionIndexes {
|
||||
|
||||
// First reset bounds.
|
||||
PearlMainQueue(^{
|
||||
NSUInteger selectedIndex = self.elementSelectionIndexes.firstIndex;
|
||||
if (selectedIndex != NSNotFound && selectedIndex < self.elements.count)
|
||||
[[self selectedView].animator setBoundsOrigin:NSZeroPoint];
|
||||
} );
|
||||
|
||||
_elementSelectionIndexes = elementSelectionIndexes;
|
||||
}
|
||||
|
||||
- (void)insertObject:(MPElementModel *)model inElementsAtIndex:(NSUInteger)index {
|
||||
|
||||
[self.elements insertObject:model atIndex:index];
|
||||
}
|
||||
|
||||
- (void)removeObjectFromElementsAtIndex:(NSUInteger)index {
|
||||
|
||||
[self.elements removeObjectAtIndex:index];
|
||||
[[self.window animator] setAlphaValue:0.0];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -7,374 +7,203 @@
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="MPPasswordWindowController">
|
||||
<connections>
|
||||
<outlet property="contentContainer" destination="143" id="214"/>
|
||||
<outlet property="siteCollectionView" destination="pr9-BO-vQV" id="Bnh-WQ-RaO"/>
|
||||
<outlet property="siteField" destination="182" id="224"/>
|
||||
<outlet property="userLabel" destination="216" id="223"/>
|
||||
<outlet property="window" destination="22" id="40"/>
|
||||
<outlet property="blurView" destination="Bwc-sd-6gm" id="wNV-0x-LJn"/>
|
||||
<outlet property="siteField" destination="CnS-iI-dhr" id="nPo-Kb-YM2"/>
|
||||
<outlet property="window" destination="QvC-M9-y7g" id="dPy-F3-9rn"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application"/>
|
||||
<window title="Master Password" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="22" customClass="NSPanel">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES" texturedBackground="YES"/>
|
||||
<rect key="contentRect" x="600" y="530" width="480" height="320"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<value key="minSize" type="size" width="480" height="320"/>
|
||||
<value key="maxSize" type="size" width="480" height="320"/>
|
||||
<view key="contentView" wantsLayer="YES" id="23">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="320"/>
|
||||
<window title="Master Password" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hasShadow="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="QvC-M9-y7g" customClass="MPPasswordWindow">
|
||||
<windowCollectionBehavior key="collectionBehavior" transient="YES" ignoresCycle="YES" fullScreenAuxiliary="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="0.0" y="0.0" width="640" height="480"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
|
||||
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="640" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="143">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="320"/>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Bwc-sd-6gm">
|
||||
<rect key="frame" x="0.0" y="0.0" width="640" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<contentFilters>
|
||||
<ciFilter name="CIGaussianBlur">
|
||||
<configuration>
|
||||
<null key="inputImage"/>
|
||||
<real key="inputRadius" value="40"/>
|
||||
</configuration>
|
||||
</ciFilter>
|
||||
<ciFilter name="CIColorControls">
|
||||
<configuration>
|
||||
<real key="inputBrightness" value="0.0"/>
|
||||
<real key="inputContrast" value="1.1000000000000001"/>
|
||||
<null key="inputImage"/>
|
||||
<real key="inputSaturation" value="2"/>
|
||||
</configuration>
|
||||
</ciFilter>
|
||||
</contentFilters>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyUpOrDown" image="small-screen" id="ArA-2w-I56"/>
|
||||
</imageView>
|
||||
<scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="37" horizontalPageScroll="10" verticalLineScroll="37" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Bme-XK-MMc">
|
||||
<rect key="frame" x="120" y="0.0" width="400" height="207"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="e11-59-xSS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="400" height="207"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="none" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" rowHeight="35" rowSizeStyle="automatic" viewBased="YES" id="xvJ-5c-vDp">
|
||||
<rect key="frame" x="0.0" y="0.0" width="403" height="207"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.0" colorSpace="calibratedRGB"/>
|
||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||
<tableColumns>
|
||||
<tableColumn editable="NO" width="400" minWidth="40" maxWidth="1000" id="S71-gk-yF7">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="dRO-6J-4JL">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView id="Rv8-uU-ieA">
|
||||
<rect key="frame" x="1" y="1" width="400" height="35"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="pTl-fc-MSY">
|
||||
<rect key="frame" x="-2" y="0.0" width="404" height="35"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" alignment="center" title="Table View Cell" id="5Ug-eU-C9Y">
|
||||
<font key="font" size="24" name="Baskerville"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="pTl-fc-MSY" firstAttribute="leading" secondItem="Rv8-uU-ieA" secondAttribute="leading" id="73u-nD-WxM"/>
|
||||
<constraint firstItem="pTl-fc-MSY" firstAttribute="top" secondItem="Rv8-uU-ieA" secondAttribute="top" id="ER6-pU-Swl"/>
|
||||
<constraint firstAttribute="trailing" secondItem="pTl-fc-MSY" secondAttribute="trailing" id="Fv4-ob-IQm"/>
|
||||
<constraint firstAttribute="bottom" secondItem="pTl-fc-MSY" secondAttribute="bottom" id="rde-CC-bsL"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="textField" destination="pTl-fc-MSY" id="Bh8-R0-bFt"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
</tableView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.0" colorSpace="calibratedRGB"/>
|
||||
</clipView>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="400" id="qfu-pO-SvM"/>
|
||||
</constraints>
|
||||
<scroller key="horizontalScroller" verticalHuggingPriority="750" horizontal="YES" id="8wr-pu-1lc">
|
||||
<rect key="frame" x="0.0" y="191" width="400" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="mcf-ST-XXI">
|
||||
<rect key="frame" x="-16" y="17" width="16" height="0.0"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<button hidden="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vES-W5-m4x">
|
||||
<rect key="frame" x="266" y="272" width="109" height="19"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="recessed" title="Long Password" bezelStyle="recessed" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Fom-sN-EtZ">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="systemBold" size="12"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<searchField focusRingType="none" verticalHuggingPriority="750" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CnS-iI-dhr">
|
||||
<rect key="frame" x="170" y="215" width="300" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="300" id="rW7-Vq-4Xy"/>
|
||||
</constraints>
|
||||
<searchFieldCell key="cell" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" focusRingType="none" alignment="center" placeholderString="Site Name" drawsBackground="YES" id="ppl-2c-1E9">
|
||||
<font key="font" size="36" name="Baskerville-Italic"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.0" colorSpace="calibratedRGB"/>
|
||||
</searchFieldCell>
|
||||
</searchField>
|
||||
<customView hidden="YES" translatesAutoresizingMaskIntoConstraints="NO" id="d3u-Ze-9uf">
|
||||
<rect key="frame" x="383" y="271" width="29" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="182">
|
||||
<rect key="frame" x="140" y="256" width="200" height="22"/>
|
||||
<stepper horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="XgA-Vl-CKh">
|
||||
<rect key="frame" x="-3" y="-3" width="19" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="200" id="258"/>
|
||||
</constraints>
|
||||
<shadow key="shadow" blurRadius="2">
|
||||
<color key="color" name="controlShadowColor" catalog="System" colorSpace="catalog"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="center" placeholderString="Site name" usesSingleLineMode="YES" bezelStyle="round" id="185">
|
||||
<font key="font" metaFont="cellTitle"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="188"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="216">
|
||||
<rect key="frame" x="146" y="286" width="188" height="14"/>
|
||||
<stepperCell key="cell" continuous="YES" alignment="left" maxValue="100" id="ikF-n4-xiI"/>
|
||||
</stepper>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="NvO-kt-eZ2">
|
||||
<rect key="frame" x="19" y="3" width="12" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" alignment="center" title="Maarten Billemont's password for:" usesSingleLineMode="YES" id="217">
|
||||
<font key="font" metaFont="palette"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="1" id="dhQ-bJ-rn3">
|
||||
<font key="font" metaFont="systemBold" size="12"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<scrollView autohidesScrollers="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tjI-mV-s8H">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="248"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<clipView key="contentView" id="mfh-QT-ClZ">
|
||||
<rect key="frame" x="1" y="1" width="478" height="246"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<collectionView selectable="YES" maxNumberOfColumns="1" id="pr9-BO-vQV">
|
||||
<rect key="frame" x="0.0" y="0.0" width="478" height="246"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="primaryBackgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="secondaryBackgroundColor" name="controlAlternatingRowColor" catalog="System" colorSpace="catalog"/>
|
||||
<connections>
|
||||
<binding destination="jTN-Q9-Ajn" name="content" keyPath="arrangedObjects" id="dtF-fs-Fpe"/>
|
||||
<binding destination="-2" name="selectionIndexes" keyPath="elementSelectionIndexes" previousBinding="dtF-fs-Fpe" id="UFy-9F-18H"/>
|
||||
<outlet property="delegate" destination="-2" id="4cD-GP-imR"/>
|
||||
<outlet property="itemPrototype" destination="QBZ-sO-HQn" id="QAi-HN-YUc"/>
|
||||
</connections>
|
||||
</collectionView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="6vP-Im-BRg">
|
||||
<rect key="frame" x="-100" y="-100" width="233" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="vs6-1G-hvM">
|
||||
<rect key="frame" x="-100" y="-100" width="15" height="143"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<button horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="tLu-3k-QiL">
|
||||
<rect key="frame" x="449" y="288" width="25" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="help" bezelStyle="helpButton" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="51o-8V-9eq">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="216" firstAttribute="top" secondItem="143" secondAttribute="top" constant="20" symbolic="YES" id="218"/>
|
||||
<constraint firstItem="182" firstAttribute="top" secondItem="216" secondAttribute="bottom" constant="8" symbolic="YES" id="221"/>
|
||||
<constraint firstAttribute="bottom" secondItem="tjI-mV-s8H" secondAttribute="bottom" id="6y8-tJ-1sX"/>
|
||||
<constraint firstItem="tLu-3k-QiL" firstAttribute="top" secondItem="143" secondAttribute="top" constant="8" id="9h7-dN-MqZ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tLu-3k-QiL" secondAttribute="trailing" constant="8" id="UQN-Ab-fIg"/>
|
||||
<constraint firstAttribute="centerX" secondItem="182" secondAttribute="centerX" id="W6t-BO-Njn"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tjI-mV-s8H" secondAttribute="trailing" id="aKe-a9-Br8"/>
|
||||
<constraint firstItem="tjI-mV-s8H" firstAttribute="leading" secondItem="143" secondAttribute="leading" id="d8F-JD-EhR"/>
|
||||
<constraint firstItem="tjI-mV-s8H" firstAttribute="top" secondItem="182" secondAttribute="bottom" constant="8" symbolic="YES" id="izG-uH-9BF"/>
|
||||
<constraint firstAttribute="centerX" secondItem="216" secondAttribute="centerX" id="mkv-5E-dy5"/>
|
||||
<constraint firstAttribute="trailing" secondItem="NvO-kt-eZ2" secondAttribute="trailing" id="4Jx-wu-xIx"/>
|
||||
<constraint firstAttribute="centerY" secondItem="NvO-kt-eZ2" secondAttribute="centerY" id="7XR-0G-Ptd"/>
|
||||
<constraint firstAttribute="height" priority="250" id="S2c-OE-l9l"/>
|
||||
<constraint firstItem="NvO-kt-eZ2" firstAttribute="leading" secondItem="XgA-Vl-CKh" secondAttribute="trailing" constant="8" symbolic="YES" id="V9l-un-zYj"/>
|
||||
<constraint firstAttribute="centerY" secondItem="XgA-Vl-CKh" secondAttribute="centerY" id="Ye6-AA-god"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="XgA-Vl-CKh" secondAttribute="bottom" id="f3p-gK-Pzg"/>
|
||||
<constraint firstItem="NvO-kt-eZ2" firstAttribute="top" relation="greaterThanOrEqual" secondItem="d3u-Ze-9uf" secondAttribute="top" id="pdR-fg-9FI"/>
|
||||
<constraint firstItem="XgA-Vl-CKh" firstAttribute="top" relation="greaterThanOrEqual" secondItem="d3u-Ze-9uf" secondAttribute="top" id="sLs-IG-OES"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="NvO-kt-eZ2" secondAttribute="bottom" id="upD-lF-5lW"/>
|
||||
<constraint firstItem="XgA-Vl-CKh" firstAttribute="leading" secondItem="d3u-Ze-9uf" secondAttribute="leading" id="vKj-dp-A0D"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
<button hidden="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="1Qo-iG-CQt">
|
||||
<rect key="frame" x="251" y="300" width="139" height="19"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="recessed" title="lhunath@lyndir.com" alternateTitle="Login Name" bezelStyle="recessed" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="QFo-9y-aVe">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="systemBold" size="12"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="143" firstAttribute="leading" secondItem="23" secondAttribute="leading" id="145"/>
|
||||
<constraint firstItem="143" firstAttribute="bottom" secondItem="23" secondAttribute="bottom" id="147"/>
|
||||
<constraint firstItem="143" firstAttribute="trailing" secondItem="23" secondAttribute="trailing" id="148"/>
|
||||
<constraint firstItem="143" firstAttribute="top" secondItem="23" secondAttribute="top" id="150"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Bme-XK-MMc" secondAttribute="bottom" id="1kJ-cV-fhc"/>
|
||||
<constraint firstItem="Bme-XK-MMc" firstAttribute="top" secondItem="CnS-iI-dhr" secondAttribute="bottom" constant="8" symbolic="YES" id="1ta-BC-BdQ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Bwc-sd-6gm" secondAttribute="bottom" id="3fF-7g-c6C"/>
|
||||
<constraint firstItem="vES-W5-m4x" firstAttribute="centerX" secondItem="CnS-iI-dhr" secondAttribute="centerX" id="92S-HP-Vk7"/>
|
||||
<constraint firstAttribute="centerY" secondItem="CnS-iI-dhr" secondAttribute="centerY" id="HjG-vb-3Qg"/>
|
||||
<constraint firstItem="d3u-Ze-9uf" firstAttribute="leading" secondItem="vES-W5-m4x" secondAttribute="trailing" constant="8" symbolic="YES" id="Juf-Q3-pkt"/>
|
||||
<constraint firstItem="CnS-iI-dhr" firstAttribute="top" secondItem="vES-W5-m4x" secondAttribute="bottom" constant="8" symbolic="YES" id="KV1-8O-msX"/>
|
||||
<constraint firstItem="Bwc-sd-6gm" firstAttribute="top" secondItem="EiT-Mj-1SZ" secondAttribute="top" id="Kqb-ig-5cP"/>
|
||||
<constraint firstAttribute="centerX" secondItem="CnS-iI-dhr" secondAttribute="centerX" id="Qqi-bu-q65"/>
|
||||
<constraint firstItem="1Qo-iG-CQt" firstAttribute="centerX" secondItem="vES-W5-m4x" secondAttribute="centerX" id="YEW-63-DI1"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Bwc-sd-6gm" secondAttribute="trailing" id="gKu-JH-NDR"/>
|
||||
<constraint firstItem="Bme-XK-MMc" firstAttribute="centerX" secondItem="CnS-iI-dhr" secondAttribute="centerX" id="i7B-jz-xgm"/>
|
||||
<constraint firstItem="d3u-Ze-9uf" firstAttribute="centerY" secondItem="vES-W5-m4x" secondAttribute="centerY" id="oyK-p1-dQM"/>
|
||||
<constraint firstItem="Bwc-sd-6gm" firstAttribute="leading" secondItem="EiT-Mj-1SZ" secondAttribute="leading" id="tea-fv-b1S"/>
|
||||
<constraint firstItem="d3u-Ze-9uf" firstAttribute="top" secondItem="1Qo-iG-CQt" secondAttribute="bottom" constant="8" symbolic="YES" id="vYh-fH-UME"/>
|
||||
</constraints>
|
||||
<backgroundFilters>
|
||||
<ciFilter name="CIGaussianBlur">
|
||||
<configuration>
|
||||
<null key="inputImage"/>
|
||||
<real key="inputRadius" value="10"/>
|
||||
</configuration>
|
||||
</ciFilter>
|
||||
</backgroundFilters>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="39"/>
|
||||
</connections>
|
||||
</window>
|
||||
<collectionViewItem id="QBZ-sO-HQn" customClass="MPElementCollectionView">
|
||||
<connections>
|
||||
<outlet property="view" destination="bhu-Ky-PQq" id="jZh-jC-6bL"/>
|
||||
</connections>
|
||||
</collectionViewItem>
|
||||
<arrayController objectClassName="MPElementModel" id="jTN-Q9-Ajn">
|
||||
<connections>
|
||||
<binding destination="-2" name="contentArray" keyPath="self.elements" id="8Uz-14-YG0"/>
|
||||
</connections>
|
||||
</arrayController>
|
||||
<box autoresizesSubviews="NO" wantsLayer="YES" boxType="custom" borderType="none" titlePosition="noTitle" id="bhu-Ky-PQq">
|
||||
<rect key="frame" x="0.0" y="0.0" width="960" height="61"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<view key="contentView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="960" height="61"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xwJ-Pu-glP">
|
||||
<rect key="frame" x="6" y="35" width="60" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.59999999999999998" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="apple.com" usesSingleLineMode="YES" id="ymH-M0-M5d">
|
||||
<font key="font" size="12" name="Exo2.0-Light"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.site" id="4as-ow-WbD"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Cn5-nt-e6X">
|
||||
<rect key="frame" x="362" y="35" width="111" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.59999999999999998" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="lhunath@lyndir.com" usesSingleLineMode="YES" id="Px4-pS-kwG">
|
||||
<font key="font" size="12" name="Exo2.0-Light"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.loginName" id="C2s-1d-p2H">
|
||||
<dictionary key="options">
|
||||
<bool key="NSContinuouslyUpdatesValue" value="YES"/>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="a1n-Sf-Mw6">
|
||||
<rect key="frame" x="6" y="8" width="206" height="38"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.59999999999999998" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="RutuTutnTeni4," id="7jb-Fa-xX3">
|
||||
<font key="font" size="24" name="SourceCodePro-Light"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.content" id="41c-PF-OeH">
|
||||
<dictionary key="options">
|
||||
<bool key="NSContinuouslyUpdatesValue" value="YES"/>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="mp4-r1-7Xg">
|
||||
<rect key="frame" x="440" y="8" width="33" height="38"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.59999999999999998" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="12" id="Vb9-nO-cWY">
|
||||
<font key="font" size="24" name="SourceCodePro-Light"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.uses" id="gSt-Nd-lVa">
|
||||
<dictionary key="options">
|
||||
<bool key="NSContinuouslyUpdatesValue" value="YES"/>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<box autoresizesSubviews="NO" horizontalHuggingPriority="750" title="Box" boxType="separator" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="tsT-Xh-Nxb">
|
||||
<rect key="frame" x="477" y="0.0" width="5" height="61"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
|
||||
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<font key="titleFont" metaFont="system"/>
|
||||
</box>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vEl-aL-Qd4">
|
||||
<rect key="frame" x="791" y="27" width="167" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="lhunath@lyndir.com" bezelStyle="rounded" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sl3-bH-Hh2">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="updateLoginName:" target="QBZ-sO-HQn" id="pJI-k8-LRl"/>
|
||||
<binding destination="QBZ-sO-HQn" name="title" keyPath="representedObject.loginName" id="uaP-Y1-bz6">
|
||||
<dictionary key="options">
|
||||
<string key="NSNullPlaceholder">Click to set login name</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</button>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="d2a-pG-7CW">
|
||||
<rect key="frame" x="528" y="31" width="127" height="26"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Long Password" bezelStyle="rounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" selectedItem="7Bj-S7-WSd" id="RZo-c7-kqA">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" title="OtherViews" id="mQN-XZ-YKz">
|
||||
<items>
|
||||
<menuItem title="Long Password" state="on" id="7Bj-S7-WSd"/>
|
||||
<menuItem title="Item 2" id="WUd-69-IBV"/>
|
||||
<menuItem title="Item 3" id="pgH-yZ-G0J"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="contentValues" keyPath="representedObject.typeNames" id="eyo-f9-MwY"/>
|
||||
<binding destination="QBZ-sO-HQn" name="selectedIndex" keyPath="representedObject.typeIndex" previousBinding="eyo-f9-MwY" id="dpI-HX-GpX"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="npg-mh-AfY">
|
||||
<rect key="frame" x="486" y="36" width="38" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Type:" id="U2E-DE-2j4">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hqw-ZP-4c1">
|
||||
<rect key="frame" x="486" y="11" width="59" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Number:" id="CDU-Ah-QDj">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="counterHidden" id="xlz-gk-Gwc"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<stepper horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JPX-xQ-VKZ">
|
||||
<rect key="frame" x="565" y="6" width="19" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<stepperCell key="cell" alignment="left" minValue="1" maxValue="100" doubleValue="1" autorepeat="NO" id="ELG-fy-nVF"/>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="counterHidden" id="3FO-ks-R7U"/>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.counter" id="awJ-Vg-RUn"/>
|
||||
</connections>
|
||||
</stepper>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="kZI-sG-dEn">
|
||||
<rect key="frame" x="549" y="11" width="13" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="1" id="EUB-gJ-7Db">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="counterHidden" id="ZFX-79-eAY"/>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.counter" id="20y-tn-B5k"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="qOt-Rp-G9T">
|
||||
<rect key="frame" x="877" y="2" width="81" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Delete" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="QCU-VC-W0u">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="delete:" target="QBZ-sO-HQn" id="mLJ-JY-5fz"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5YU-4W-4gz">
|
||||
<rect key="frame" x="727" y="2" width="150" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Change Password" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="NQY-Oo-Eid">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="updateContent:" target="QBZ-sO-HQn" id="J8f-vx-10A"/>
|
||||
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="updateContentHidden" id="UwG-p5-kH4"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bzg-90-kmh">
|
||||
<rect key="frame" x="748" y="36" width="43" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Login:" id="uxE-6c-RjC">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstItem="hqw-ZP-4c1" firstAttribute="centerY" secondItem="qOt-Rp-G9T" secondAttribute="centerY" id="6xp-tI-BkX"/>
|
||||
<constraint firstItem="npg-mh-AfY" firstAttribute="leading" secondItem="tsT-Xh-Nxb" secondAttribute="trailing" constant="8" id="7kp-OB-3BI"/>
|
||||
<constraint firstItem="kZI-sG-dEn" firstAttribute="leading" secondItem="hqw-ZP-4c1" secondAttribute="trailing" constant="8" symbolic="YES" id="8qK-Et-c1F"/>
|
||||
<constraint firstItem="d2a-pG-7CW" firstAttribute="leading" secondItem="npg-mh-AfY" secondAttribute="trailing" constant="8" symbolic="YES" id="F6X-FD-kEX"/>
|
||||
<constraint firstItem="Cn5-nt-e6X" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" constant="8" id="FWS-tY-KkM"/>
|
||||
<constraint firstItem="hqw-ZP-4c1" firstAttribute="top" secondItem="npg-mh-AfY" secondAttribute="bottom" constant="8" symbolic="YES" id="GuG-5I-quA"/>
|
||||
<constraint firstItem="hqw-ZP-4c1" firstAttribute="leading" secondItem="tsT-Xh-Nxb" secondAttribute="trailing" constant="8" id="Hzf-XZ-auZ"/>
|
||||
<constraint firstItem="tsT-Xh-Nxb" firstAttribute="leading" secondItem="Cn5-nt-e6X" secondAttribute="trailing" constant="8" id="LjD-10-tVU"/>
|
||||
<constraint firstItem="tsT-Xh-Nxb" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" id="ODH-Nx-QdY"/>
|
||||
<constraint firstItem="qOt-Rp-G9T" firstAttribute="centerY" secondItem="5YU-4W-4gz" secondAttribute="centerY" id="PdB-X5-eqF"/>
|
||||
<constraint firstItem="xwJ-Pu-glP" firstAttribute="leading" secondItem="bhu-Ky-PQq" secondAttribute="leading" constant="8" id="QAM-jm-t0y"/>
|
||||
<constraint firstAttribute="centerY" secondItem="tsT-Xh-Nxb" secondAttribute="centerY" id="Rpi-lc-dZ1"/>
|
||||
<constraint firstItem="tsT-Xh-Nxb" firstAttribute="leading" secondItem="mp4-r1-7Xg" secondAttribute="trailing" constant="8" id="Xfc-Jq-2Rb"/>
|
||||
<constraint firstAttribute="trailing" secondItem="vEl-aL-Qd4" secondAttribute="trailing" constant="8" id="ZZu-AS-C07"/>
|
||||
<constraint firstAttribute="bottom" secondItem="tsT-Xh-Nxb" secondAttribute="bottom" id="ds1-7i-B7I"/>
|
||||
<constraint firstItem="a1n-Sf-Mw6" firstAttribute="leading" secondItem="bhu-Ky-PQq" secondAttribute="leading" constant="8" id="e3g-2s-yee"/>
|
||||
<constraint firstItem="npg-mh-AfY" firstAttribute="centerY" secondItem="vEl-aL-Qd4" secondAttribute="centerY" id="ftr-2Z-9J0"/>
|
||||
<constraint firstItem="npg-mh-AfY" firstAttribute="centerY" secondItem="d2a-pG-7CW" secondAttribute="centerY" id="g9a-r0-EOo"/>
|
||||
<constraint firstAttribute="bottom" secondItem="mp4-r1-7Xg" secondAttribute="bottom" constant="8" id="jCW-5H-6pT"/>
|
||||
<constraint firstAttribute="centerX" secondItem="tsT-Xh-Nxb" secondAttribute="centerX" id="kx6-g0-jUW"/>
|
||||
<constraint firstAttribute="bottom" secondItem="a1n-Sf-Mw6" secondAttribute="bottom" constant="8" id="mWW-rt-kl2"/>
|
||||
<constraint firstItem="npg-mh-AfY" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" constant="8" id="n7Z-EF-Dcm"/>
|
||||
<constraint firstItem="qOt-Rp-G9T" firstAttribute="leading" secondItem="5YU-4W-4gz" secondAttribute="trailing" constant="12" symbolic="YES" id="uWm-hE-itO"/>
|
||||
<constraint firstAttribute="trailing" secondItem="qOt-Rp-G9T" secondAttribute="trailing" constant="8" id="x6J-1l-rU4"/>
|
||||
<constraint firstItem="hqw-ZP-4c1" firstAttribute="centerY" secondItem="kZI-sG-dEn" secondAttribute="centerY" id="xZ7-Mc-9dq"/>
|
||||
<constraint firstItem="vEl-aL-Qd4" firstAttribute="leading" secondItem="bzg-90-kmh" secondAttribute="trailing" constant="8" symbolic="YES" id="z7h-om-WAV"/>
|
||||
<constraint firstItem="xwJ-Pu-glP" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" constant="8" id="z8k-ot-NjU"/>
|
||||
<constraint firstItem="bzg-90-kmh" firstAttribute="centerY" secondItem="vEl-aL-Qd4" secondAttribute="centerY" id="zbz-Qg-uHO"/>
|
||||
<constraint firstItem="JPX-xQ-VKZ" firstAttribute="centerY" secondItem="kZI-sG-dEn" secondAttribute="centerY" id="zcO-M3-gyr"/>
|
||||
<constraint firstItem="JPX-xQ-VKZ" firstAttribute="leading" secondItem="kZI-sG-dEn" secondAttribute="trailing" constant="8" symbolic="YES" id="zvB-Vk-IL2"/>
|
||||
</constraints>
|
||||
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
|
||||
<color key="fillColor" name="selectedControlColor" catalog="System" colorSpace="catalog"/>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="transparent" keyPath="selected" id="Tpz-Rp-lA7">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</box>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="small-screen" width="25" height="15.5"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
@ -7,12 +7,14 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
93D390C676DF52DA7E459F19 /* MPPasswordWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D9D0061FF1159998F06 /* MPPasswordWindow.m */; };
|
||||
93D392EC39DA43C46C692C12 /* NSDictionary+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */; };
|
||||
93D395F08A087F8A24689347 /* NSArray+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */; };
|
||||
93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; };
|
||||
93D39C5789EFA607CF788082 /* MPElementModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39E73BF5CBF8E5B005CD3 /* MPElementModel.m */; };
|
||||
93D39C7C2BE7C0E0763B0177 /* MPElementCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D394495528B10D1B61A2C3 /* MPElementCollectionView.m */; };
|
||||
93D39E281E3658B30550CB55 /* NSDictionary+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */; };
|
||||
93D39F833DEC1C89B2F795AC /* MPPasswordWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A57A7823DE98A0FF83C /* MPPasswordWindowController.m */; };
|
||||
DA0933CC1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0933CB1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png */; };
|
||||
DA0933D01747B91B00DE1CEF /* appstore.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0933CF1747B91B00DE1CEF /* appstore.png */; };
|
||||
DA16B33F170661D4000A0EAB /* libUbiquityStoreManager.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA4425CB1557BED40052177D /* libUbiquityStoreManager.a */; };
|
||||
@ -21,6 +23,10 @@
|
||||
DA16B344170661EE000A0EAB /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA16B343170661EE000A0EAB /* Cocoa.framework */; };
|
||||
DA16B345170661F2000A0EAB /* libPearl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC77CAD148291A600BCF976 /* libPearl.a */; };
|
||||
DA1E4D50176E0E280065E0EF /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA1E4D4F176E0E280065E0EF /* Media.xcassets */; };
|
||||
DA2508F119511D3600AC23F1 /* MPPasswordWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA2508F019511D3600AC23F1 /* MPPasswordWindowController.xib */; };
|
||||
DA2508F719513C1400AC23F1 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA16B343170661EE000A0EAB /* Cocoa.framework */; };
|
||||
DA250924195148B300AC23F1 /* libRMBlurredView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2508F619513C1400AC23F1 /* libRMBlurredView.a */; };
|
||||
DA250925195148E200AC23F1 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEBC45214F6364500987BF6 /* QuartzCore.framework */; };
|
||||
DA2CA4ED18D323D3007798F8 /* NSError+PearlFullDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2CA4E718D323D3007798F8 /* NSError+PearlFullDescription.m */; };
|
||||
DA2CA4EE18D323D3007798F8 /* NSError+PearlFullDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = DA2CA4E818D323D3007798F8 /* NSError+PearlFullDescription.h */; };
|
||||
DA2CA4EF18D323D3007798F8 /* NSArray+Pearl.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2CA4E918D323D3007798F8 /* NSArray+Pearl.m */; };
|
||||
@ -57,8 +63,8 @@
|
||||
DA5E5D021724A667003798D8 /* MPUserEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CB11724A667003798D8 /* MPUserEntity.m */; };
|
||||
DA5E5D031724A667003798D8 /* MPMacAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CB41724A667003798D8 /* MPMacAppDelegate.m */; };
|
||||
DA5E5D041724A667003798D8 /* MPMacConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CB61724A667003798D8 /* MPMacConfig.m */; };
|
||||
DA5E5D051724A667003798D8 /* MPPasswordWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CB81724A667003798D8 /* MPPasswordWindowController.m */; };
|
||||
DA5E5D061724A667003798D8 /* MPPasswordWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA5E5CB91724A667003798D8 /* MPPasswordWindowController.xib */; };
|
||||
DA5E5D051724A667003798D8 /* MPPasswordDialogController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CB81724A667003798D8 /* MPPasswordDialogController.m */; };
|
||||
DA5E5D061724A667003798D8 /* MPPasswordDialogController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA5E5CB91724A667003798D8 /* MPPasswordDialogController.xib */; };
|
||||
DA5E5D081724A667003798D8 /* MasterPassword.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = DA5E5CBF1724A667003798D8 /* MasterPassword.entitlements */; };
|
||||
DA5E5D091724A667003798D8 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = DA5E5CC01724A667003798D8 /* Credits.rtf */; };
|
||||
DA5E5D0A1724A667003798D8 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA5E5CC21724A667003798D8 /* InfoPlist.strings */; };
|
||||
@ -300,11 +306,15 @@
|
||||
/* Begin PBXFileReference section */
|
||||
93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Indexing.m"; sourceTree = "<group>"; };
|
||||
93D39240B5143E01F0B75E96 /* MPElementModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementModel.h; sourceTree = "<group>"; };
|
||||
93D392C3918763B3B72CF366 /* MPPasswordWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordWindowController.h; sourceTree = "<group>"; };
|
||||
93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = "<group>"; };
|
||||
93D394495528B10D1B61A2C3 /* MPElementCollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementCollectionView.m; sourceTree = "<group>"; };
|
||||
93D3960D320FF8A072B092E3 /* MPElementCollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementCollectionView.h; sourceTree = "<group>"; };
|
||||
93D396D04E57792A54D437AC /* NSArray+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Indexing.h"; sourceTree = "<group>"; };
|
||||
93D3977484534E99F9BA579D /* MPPasswordWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordWindow.h; sourceTree = "<group>"; };
|
||||
93D39A57A7823DE98A0FF83C /* MPPasswordWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordWindowController.m; sourceTree = "<group>"; };
|
||||
93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+Indexing.m"; sourceTree = "<group>"; };
|
||||
93D39D9D0061FF1159998F06 /* MPPasswordWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordWindow.m; sourceTree = "<group>"; };
|
||||
93D39E73BF5CBF8E5B005CD3 /* MPElementModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementModel.m; sourceTree = "<group>"; };
|
||||
DA0933C91747A56A00DE1CEF /* MPInitialWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPInitialWindow.xib; sourceTree = "<group>"; };
|
||||
DA0933CB1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "shot-laptop-leaning-iphone.png"; sourceTree = "<group>"; };
|
||||
@ -312,6 +322,14 @@
|
||||
DA16B340170661DB000A0EAB /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
|
||||
DA16B343170661EE000A0EAB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
DA1E4D4F176E0E280065E0EF /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Media.xcassets; path = MasterPassword/Media.xcassets; sourceTree = "<group>"; };
|
||||
DA2508F019511D3600AC23F1 /* MPPasswordWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPPasswordWindowController.xib; sourceTree = "<group>"; };
|
||||
DA2508F619513C1400AC23F1 /* libRMBlurredView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRMBlurredView.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA2508F919513C1400AC23F1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
DA2508FA19513C1400AC23F1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
|
||||
DA2508FB19513C1400AC23F1 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||
DA25090719513C1400AC23F1 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
|
||||
DA2509261951B86C00AC23F1 /* small-screen.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "small-screen.png"; sourceTree = "<group>"; };
|
||||
DA2509271951B86C00AC23F1 /* screen.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = screen.png; sourceTree = "<group>"; };
|
||||
DA2CA4E718D323D3007798F8 /* NSError+PearlFullDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+PearlFullDescription.m"; sourceTree = "<group>"; };
|
||||
DA2CA4E818D323D3007798F8 /* NSError+PearlFullDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+PearlFullDescription.h"; sourceTree = "<group>"; };
|
||||
DA2CA4E918D323D3007798F8 /* NSArray+Pearl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Pearl.m"; sourceTree = "<group>"; };
|
||||
@ -369,9 +387,9 @@
|
||||
DA5E5CB41724A667003798D8 /* MPMacAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMacAppDelegate.m; sourceTree = "<group>"; };
|
||||
DA5E5CB51724A667003798D8 /* MPMacConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMacConfig.h; sourceTree = "<group>"; };
|
||||
DA5E5CB61724A667003798D8 /* MPMacConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMacConfig.m; sourceTree = "<group>"; };
|
||||
DA5E5CB71724A667003798D8 /* MPPasswordWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordWindowController.h; sourceTree = "<group>"; };
|
||||
DA5E5CB81724A667003798D8 /* MPPasswordWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordWindowController.m; sourceTree = "<group>"; };
|
||||
DA5E5CB91724A667003798D8 /* MPPasswordWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPPasswordWindowController.xib; sourceTree = "<group>"; };
|
||||
DA5E5CB71724A667003798D8 /* MPPasswordDialogController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordDialogController.h; sourceTree = "<group>"; };
|
||||
DA5E5CB81724A667003798D8 /* MPPasswordDialogController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordDialogController.m; sourceTree = "<group>"; };
|
||||
DA5E5CB91724A667003798D8 /* MPPasswordDialogController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPPasswordDialogController.xib; sourceTree = "<group>"; };
|
||||
DA5E5CBA1724A667003798D8 /* MasterPassword-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "MasterPassword-Info.plist"; sourceTree = "<group>"; };
|
||||
DA5E5CBE1724A667003798D8 /* MasterPassword-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MasterPassword-Prefix.pch"; sourceTree = "<group>"; };
|
||||
DA5E5CBF1724A667003798D8 /* MasterPassword.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = MasterPassword.entitlements; sourceTree = "<group>"; };
|
||||
@ -587,6 +605,14 @@
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
DA2508F319513C1400AC23F1 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DA2508F719513C1400AC23F1 /* Cocoa.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DA4425C81557BED40052177D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -599,6 +625,8 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DA250925195148E200AC23F1 /* QuartzCore.framework in Frameworks */,
|
||||
DA250924195148B300AC23F1 /* libRMBlurredView.a in Frameworks */,
|
||||
DAD9B5F01762CAA4001835F9 /* ServiceManagement.framework in Frameworks */,
|
||||
DABC6C16175D8E3A000C15D4 /* libRHStatusItemView.a in Frameworks */,
|
||||
DA16B33F170661D4000A0EAB /* libUbiquityStoreManager.a in Frameworks */,
|
||||
@ -639,6 +667,16 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
DA2508F819513C1400AC23F1 /* Other Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA2508F919513C1400AC23F1 /* Foundation.framework */,
|
||||
DA2508FA19513C1400AC23F1 /* CoreData.framework */,
|
||||
DA2508FB19513C1400AC23F1 /* AppKit.framework */,
|
||||
);
|
||||
name = "Other Frameworks";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA3B8447190FC5A900246EEA /* iOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -675,6 +713,7 @@
|
||||
DAC6326C148680650075AEA5 /* libjrswizzle.a */,
|
||||
DA4425CB1557BED40052177D /* libUbiquityStoreManager.a */,
|
||||
DABC6C01175D8C85000C15D4 /* libRHStatusItemView.a */,
|
||||
DA2508F619513C1400AC23F1 /* libRMBlurredView.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@ -695,6 +734,8 @@
|
||||
DA5BFA4A147E415C00F98B1E /* Foundation.framework */,
|
||||
DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */,
|
||||
DA5BFA4E147E415C00F98B1E /* CoreData.framework */,
|
||||
DA25090719513C1400AC23F1 /* XCTest.framework */,
|
||||
DA2508F819513C1400AC23F1 /* Other Frameworks */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@ -755,9 +796,9 @@
|
||||
DA5E5CB41724A667003798D8 /* MPMacAppDelegate.m */,
|
||||
DA5E5CB51724A667003798D8 /* MPMacConfig.h */,
|
||||
DA5E5CB61724A667003798D8 /* MPMacConfig.m */,
|
||||
DA5E5CB71724A667003798D8 /* MPPasswordWindowController.h */,
|
||||
DA5E5CB81724A667003798D8 /* MPPasswordWindowController.m */,
|
||||
DA5E5CB91724A667003798D8 /* MPPasswordWindowController.xib */,
|
||||
DA5E5CB71724A667003798D8 /* MPPasswordDialogController.h */,
|
||||
DA5E5CB81724A667003798D8 /* MPPasswordDialogController.m */,
|
||||
DA5E5CB91724A667003798D8 /* MPPasswordDialogController.xib */,
|
||||
DA5E5CBA1724A667003798D8 /* MasterPassword-Info.plist */,
|
||||
DA5E5CBE1724A667003798D8 /* MasterPassword-Prefix.pch */,
|
||||
DA5E5CBF1724A667003798D8 /* MasterPassword.entitlements */,
|
||||
@ -770,6 +811,11 @@
|
||||
93D3960D320FF8A072B092E3 /* MPElementCollectionView.h */,
|
||||
93D39E73BF5CBF8E5B005CD3 /* MPElementModel.m */,
|
||||
93D39240B5143E01F0B75E96 /* MPElementModel.h */,
|
||||
DA2508F019511D3600AC23F1 /* MPPasswordWindowController.xib */,
|
||||
93D39A57A7823DE98A0FF83C /* MPPasswordWindowController.m */,
|
||||
93D392C3918763B3B72CF366 /* MPPasswordWindowController.h */,
|
||||
93D39D9D0061FF1159998F06 /* MPPasswordWindow.m */,
|
||||
93D3977484534E99F9BA579D /* MPPasswordWindow.h */,
|
||||
);
|
||||
path = Mac;
|
||||
sourceTree = "<group>";
|
||||
@ -842,6 +888,8 @@
|
||||
DACA23B51705DF7D002C6C22 /* Media */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA2509261951B86C00AC23F1 /* small-screen.png */,
|
||||
DA2509271951B86C00AC23F1 /* screen.png */,
|
||||
DA0933CF1747B91B00DE1CEF /* appstore.png */,
|
||||
DA0933CB1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png */,
|
||||
DA5E5D541724F9C8003798D8 /* MasterPassword.iconset */,
|
||||
@ -1153,6 +1201,13 @@
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
DA2508F419513C1400AC23F1 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DA4425C91557BED40052177D /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -1294,6 +1349,23 @@
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
DA2508F519513C1400AC23F1 /* RMBlurredView */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DA25091519513C1500AC23F1 /* Build configuration list for PBXNativeTarget "RMBlurredView" */;
|
||||
buildPhases = (
|
||||
DA2508F219513C1400AC23F1 /* Sources */,
|
||||
DA2508F319513C1400AC23F1 /* Frameworks */,
|
||||
DA2508F419513C1400AC23F1 /* Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = RMBlurredView;
|
||||
productName = RMBlurredView;
|
||||
productReference = DA2508F619513C1400AC23F1 /* libRMBlurredView.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
DA4425CA1557BED40052177D /* UbiquityStoreManager */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DA4425D31557BED40052177D /* Build configuration list for PBXNativeTarget "UbiquityStoreManager" */;
|
||||
@ -1424,6 +1496,7 @@
|
||||
DAC6326B148680650075AEA5 /* jrswizzle */,
|
||||
DA4425CA1557BED40052177D /* UbiquityStoreManager */,
|
||||
DABC6C00175D8C85000C15D4 /* RHStatusItemView */,
|
||||
DA2508F519513C1400AC23F1 /* RMBlurredView */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@ -1457,6 +1530,7 @@
|
||||
DAF4EF59190A828100023C90 /* Exo2.0-Bold.otf in Resources */,
|
||||
DACA27181705DF81002C6C22 /* avatar-9.png in Resources */,
|
||||
DACA27191705DF81002C6C22 /* avatar-1@2x.png in Resources */,
|
||||
DA2508F119511D3600AC23F1 /* MPPasswordWindowController.xib in Resources */,
|
||||
DACA271A1705DF81002C6C22 /* avatar-11@2x.png in Resources */,
|
||||
DACA271B1705DF81002C6C22 /* avatar-7@2x.png in Resources */,
|
||||
DACA271C1705DF81002C6C22 /* avatar-17@2x.png in Resources */,
|
||||
@ -1497,7 +1571,7 @@
|
||||
DACA296F1705DF81002C6C22 /* Crashlytics.plist in Resources */,
|
||||
DACA29731705E1A8002C6C22 /* ciphers.plist in Resources */,
|
||||
DACA29741705E1A8002C6C22 /* dictionary.lst in Resources */,
|
||||
DA5E5D061724A667003798D8 /* MPPasswordWindowController.xib in Resources */,
|
||||
DA5E5D061724A667003798D8 /* MPPasswordDialogController.xib in Resources */,
|
||||
DA5E5D081724A667003798D8 /* MasterPassword.entitlements in Resources */,
|
||||
DA5E5D091724A667003798D8 /* Credits.rtf in Resources */,
|
||||
DA5E5D0A1724A667003798D8 /* InfoPlist.strings in Resources */,
|
||||
@ -1544,6 +1618,13 @@
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
DA2508F219513C1400AC23F1 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DA4425C71557BED40052177D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -1573,11 +1654,13 @@
|
||||
DA5E5D021724A667003798D8 /* MPUserEntity.m in Sources */,
|
||||
DA5E5D031724A667003798D8 /* MPMacAppDelegate.m in Sources */,
|
||||
DA5E5D041724A667003798D8 /* MPMacConfig.m in Sources */,
|
||||
DA5E5D051724A667003798D8 /* MPPasswordWindowController.m in Sources */,
|
||||
DA5E5D051724A667003798D8 /* MPPasswordDialogController.m in Sources */,
|
||||
DA5E5D0C1724A667003798D8 /* main.m in Sources */,
|
||||
DA5E5D0D1724A667003798D8 /* MasterPassword.xcdatamodeld in Sources */,
|
||||
93D39C7C2BE7C0E0763B0177 /* MPElementCollectionView.m in Sources */,
|
||||
93D39C5789EFA607CF788082 /* MPElementModel.m in Sources */,
|
||||
93D39F833DEC1C89B2F795AC /* MPPasswordWindowController.m in Sources */,
|
||||
93D390C676DF52DA7E459F19 /* MPPasswordWindow.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1686,6 +1769,27 @@
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
DA25091619513C1500AC23F1 /* Debug-Mac */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
};
|
||||
name = "Debug-Mac";
|
||||
};
|
||||
DA25091719513C1500AC23F1 /* AdHoc-Mac */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
};
|
||||
name = "AdHoc-Mac";
|
||||
};
|
||||
DA25091819513C1500AC23F1 /* AppStore-Mac */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
};
|
||||
name = "AppStore-Mac";
|
||||
};
|
||||
DA4425D41557BED40052177D /* Debug-Mac */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@ -2108,6 +2212,16 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
DA25091519513C1500AC23F1 /* Build configuration list for PBXNativeTarget "RMBlurredView" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DA25091619513C1500AC23F1 /* Debug-Mac */,
|
||||
DA25091719513C1500AC23F1 /* AdHoc-Mac */,
|
||||
DA25091819513C1500AC23F1 /* AppStore-Mac */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = "AdHoc-Mac";
|
||||
};
|
||||
DA4425D31557BED40052177D /* Build configuration list for PBXNativeTarget "UbiquityStoreManager" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
Loading…
Reference in New Issue
Block a user