2
0

Show all when empty and fix UI updates.

[FIXED]     Updating UI when changing entity model.
[UPDATED]   Show all recent sites when query is empty.
This commit is contained in:
Maarten Billemont 2014-05-19 14:37:05 -04:00
parent a1ca633aaf
commit 8805a411ba
6 changed files with 114 additions and 67 deletions

2
External/Pearl vendored

@ -1 +1 @@
Subproject commit e0be1305f742b225818f4f7bf37b489c0b0b703e
Subproject commit a7233e2a01f95ae87b9586df883e8177a3e5c299

View File

@ -20,16 +20,16 @@
@class MPElementEntity;
@interface MPElementModel : NSObject
@property (nonatomic, readonly) NSString *site;
@property (nonatomic, readonly) MPElementType type;
@property (nonatomic, readonly) NSString *typeName;
@property (nonatomic, readonly) NSString *content;
@property (nonatomic, readonly) NSString *loginName;
@property (nonatomic, readonly) NSNumber *uses;
@property (nonatomic) NSString *site;
@property (nonatomic) MPElementType type;
@property (nonatomic) NSString *typeName;
@property (nonatomic) NSString *content;
@property (nonatomic) NSString *loginName;
@property (nonatomic) NSNumber *uses;
@property (nonatomic) NSUInteger counter;
@property (nonatomic, readonly) NSDate *lastUsed;
@property (nonatomic, readonly) id<MPAlgorithm> algorithm;
@property (nonatomic, readonly) NSArray *types;
@property (nonatomic) NSDate *lastUsed;
@property (nonatomic) id<MPAlgorithm> algorithm;
@property (nonatomic) NSArray *typeNames;
@property (nonatomic) NSUInteger typeIndex;
- (id)initWithEntity:(MPElementEntity *)entity;

View File

@ -23,16 +23,10 @@
#import "MPAppDelegate_Store.h"
#import "MPMacAppDelegate.h"
@interface MPElementModel()
@property(nonatomic, strong) NSManagedObjectID *entityOID;
@property(nonatomic, readwrite) NSString *content;
@property(nonatomic, readwrite) MPElementType type;
@property(nonatomic, readwrite) NSString *typeName;
@end
@implementation MPElementModel {
NSManagedObjectID *_entityOID;
NSMutableDictionary *_typesByName;
BOOL _initialized;
}
- (id)initWithEntity:(MPElementEntity *)entity {
@ -40,27 +34,40 @@
if (!(self = [super init]))
return nil;
_site = entity.name;
_lastUsed = entity.lastUsed;
_loginName = entity.loginName;
_type = entity.type;
_typeName = entity.typeName;
_uses = entity.uses_;
_counter = [entity isKindOfClass:[MPElementGeneratedEntity class]]? [(MPElementGeneratedEntity *)entity counter]: 0;
_content = [entity.algorithm resolveContentForElement:entity usingKey:[MPAppDelegate_Shared get].key];
_algorithm = entity.algorithm;
[self setEntity:entity];
_initialized = YES;
return self;
}
- (void)setEntity:(MPElementEntity *)entity {
if ([_entityOID isEqual:entity.objectID])
return;
_entityOID = entity.objectID;
self.algorithm = entity.algorithm;
self.site = entity.name;
self.lastUsed = entity.lastUsed;
self.loginName = entity.loginName;
self.type = entity.type;
self.typeName = entity.typeName;
self.uses = entity.uses_;
self.counter = [entity isKindOfClass:[MPElementGeneratedEntity class]]? [(MPElementGeneratedEntity *)entity counter]: 0;
// Find all password types and the index of the current type amongst them.
_typesByName = [NSMutableDictionary dictionary];
MPElementType type = _type;
MPElementType type = self.type;
do {
[_typesByName setObject:@(type) forKey:[_algorithm shortNameOfType:type]];
} while (_type != (type = [_algorithm nextType:type]));
_types = [_typesByName keysSortedByValueUsingSelector:@selector(compare:)];
_typeIndex = [[[_typesByName allValues] sortedArrayUsingSelector:@selector(compare:)] indexOfObject:@(_type)];
[_typesByName setObject:@(type) forKey:[self.algorithm shortNameOfType:type]];
} while (self.type != (type = [self.algorithm nextType:type]));
self.typeNames = [_typesByName keysSortedByValueUsingSelector:@selector( compare: )];
self.typeIndex = [[[_typesByName allValues] sortedArrayUsingSelector:@selector( compare: )] indexOfObject:@(self.type)];
return self;
[entity.algorithm resolveContentForElement:entity usingKey:[MPAppDelegate_Shared get].key
result:^(NSString *result) {
PearlMainQueue( ^{ self.content = result; } );
}];
}
- (MPElementEntity *)entityInContext:(NSManagedObjectContext *)moc {
@ -82,13 +89,20 @@
return;
_counter = counter;
if (!_initialized)
// This wasn't a change to the entity.
return;
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPElementEntity *entity = [self entityInContext:context];
if ([entity isKindOfClass:[MPElementGeneratedEntity class]]) {
((MPElementGeneratedEntity *)entity).counter = counter;
[context saveToStore];
self.content = [entity.algorithm resolveContentForElement:entity usingKey:[MPAppDelegate_Shared get].key];
[entity.algorithm resolveContentForElement:entity usingKey:[MPAppDelegate_Shared get].key
result:^(NSString *result) {
PearlMainQueue( ^{ self.content = result; } );
}];
}
}];
}
@ -99,14 +113,13 @@
return;
_typeIndex = typeIndex;
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPElementEntity *entity = [self entityInContext:context];
entity.type_ = _typesByName[_types[typeIndex]];
[context saveToStore];
if (!_initialized)
// This wasn't a change to the entity.
return;
self.type = entity.type;
self.typeName = entity.typeName;
self.content = [entity.algorithm resolveContentForElement:entity usingKey:[MPAppDelegate_Shared get].key];
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
[self setEntity:[[MPAppDelegate_Shared get] changeElement:[self entityInContext:context] saveInContext:context
toType:[_typesByName[self.typeNames[typeIndex]] unsignedIntegerValue]]];
}];
}

View File

@ -55,6 +55,7 @@
// }];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:YES];
[self updateElements];
}];
} forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil];
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification object:self.window
@ -62,6 +63,7 @@
^(NSNotification *note) {
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:NO];
[self.siteField selectText:nil];
[self updateElements];
}];
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:self.window
queue:[NSOperationQueue mainQueue] usingBlock:
@ -334,17 +336,17 @@
- (void)updateElements {
NSString *query = [self.siteField.currentEditor string];
if (![query length] || ![MPMacAppDelegate get].key) {
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:@"(name BEGINSWITH[cd] %@) AND user == %@",
query, [[MPMacAppDelegate get] activeUserInContext:context]];
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];

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13B3116" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<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="4514"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="MPPasswordWindowController">
@ -19,7 +19,7 @@
<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="878"/>
<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">
@ -168,7 +168,11 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.loginName" id="kuR-ui-n33"/>
<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">
@ -184,7 +188,11 @@
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.content" id="19u-Zx-3vP"/>
<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">
@ -200,7 +208,11 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.uses" id="7gd-qw-W5L"/>
<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">
@ -241,8 +253,8 @@
</menu>
</popUpButtonCell>
<connections>
<binding destination="QBZ-sO-HQn" name="contentValues" keyPath="representedObject.types" id="bT1-aF-gww"/>
<binding destination="QBZ-sO-HQn" name="selectedIndex" keyPath="representedObject.typeIndex" previousBinding="bT1-aF-gww" id="U2t-Oc-k46"/>
<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">

View File

@ -68,6 +68,9 @@
DA5E5D0C1724A667003798D8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CC61724A667003798D8 /* main.m */; };
DA5E5D0D1724A667003798D8 /* MasterPassword.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CC71724A667003798D8 /* MasterPassword.xcdatamodeld */; };
DA5E5D551724F9C8003798D8 /* MasterPassword.iconset in Resources */ = {isa = PBXBuildFile; fileRef = DA5E5D541724F9C8003798D8 /* MasterPassword.iconset */; };
DA8ED895192906920099B726 /* PearlTween.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8ED891192906920099B726 /* PearlTween.m */; };
DA8ED896192906920099B726 /* PearlTween.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8ED892192906920099B726 /* PearlTween.h */; };
DA8ED897192906920099B726 /* map-macro.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8ED894192906920099B726 /* map-macro.h */; };
DABC6C02175D8C85000C15D4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
DABC6C15175D8CE1000C15D4 /* RHStatusItemView.m in Sources */ = {isa = PBXBuildFile; fileRef = DABC6C14175D8CE1000C15D4 /* RHStatusItemView.m */; };
DABC6C16175D8E3A000C15D4 /* libRHStatusItemView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DABC6C01175D8C85000C15D4 /* libRHStatusItemView.a */; };
@ -395,6 +398,9 @@
DA6701B716406A4100B61001 /* Accounts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accounts.framework; path = System/Library/Frameworks/Accounts.framework; sourceTree = SDKROOT; };
DA6701DD16406B7300B61001 /* Social.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Social.framework; path = System/Library/Frameworks/Social.framework; sourceTree = SDKROOT; };
DA672D2E14F92C6B004A189C /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
DA8ED891192906920099B726 /* PearlTween.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlTween.m; sourceTree = "<group>"; };
DA8ED892192906920099B726 /* PearlTween.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlTween.h; sourceTree = "<group>"; };
DA8ED894192906920099B726 /* map-macro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "map-macro.h"; sourceTree = "<group>"; };
DABB981515100B4000B05417 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
DABC6C01175D8C85000C15D4 /* libRHStatusItemView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRHStatusItemView.a; sourceTree = BUILT_PRODUCTS_DIR; };
DABC6C13175D8CE1000C15D4 /* RHStatusItemView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RHStatusItemView.h; sourceTree = "<group>"; };
@ -790,6 +796,14 @@
path = Mac;
sourceTree = "<group>";
};
DA8ED893192906920099B726 /* include */ = {
isa = PBXGroup;
children = (
DA8ED894192906920099B726 /* map-macro.h */,
);
path = include;
sourceTree = "<group>";
};
DABC6C0E175D8CE1000C15D4 /* RHStatusItemView */ = {
isa = PBXGroup;
children = (
@ -1071,6 +1085,9 @@
DAFE45D715039823003ABA7C /* Pearl */ = {
isa = PBXGroup;
children = (
DA8ED891192906920099B726 /* PearlTween.m */,
DA8ED892192906920099B726 /* PearlTween.h */,
DA8ED893192906920099B726 /* include */,
DA3B8450190FC86F00246EEA /* NSManagedObject+Pearl.m */,
DA3B8451190FC86F00246EEA /* NSManagedObject+Pearl.h */,
DA2CA4E718D323D3007798F8 /* NSError+PearlFullDescription.m */,
@ -1199,6 +1216,7 @@
DA3B8453190FC86F00246EEA /* NSManagedObject+Pearl.h in Headers */,
DAEB93F518AB0FFD000490CC /* evp.h in Headers */,
DAEB941918AB0FFD000490CC /* ts.h in Headers */,
DA8ED897192906920099B726 /* map-macro.h in Headers */,
DAEB93F818AB0FFD000490CC /* krb5_asn.h in Headers */,
DAFE4A1915039824003ABA7C /* Pearl.h in Headers */,
DAEB93F318AB0FFD000490CC /* engine.h in Headers */,
@ -1211,6 +1229,7 @@
DAEB940418AB0FFD000490CC /* ossl_typ.h in Headers */,
DAEB93DC18AB0FFD000490CC /* asn1t.h in Headers */,
DAFE4A2215039824003ABA7C /* PearlDeviceUtils.h in Headers */,
DA8ED896192906920099B726 /* PearlTween.h in Headers */,
DAEB93E518AB0FFD000490CC /* conf.h in Headers */,
DAFE4A2415039824003ABA7C /* PearlInfoPlist.h in Headers */,
DAEB940618AB0FFD000490CC /* pem2.h in Headers */,
@ -1668,6 +1687,7 @@
DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */,
DAFE4A3915039824003ABA7C /* PearlRSAKey.m in Sources */,
DAFE4A3B15039824003ABA7C /* PearlSCrypt.m in Sources */,
DA8ED895192906920099B726 /* PearlTween.m in Sources */,
DA30E9CF15722ECA00A68B4C /* NSBundle+PearlMutableInfo.m in Sources */,
DA2CA4F118D323D3007798F8 /* NSTimer+PearlBlock.m in Sources */,
DA3B8452190FC86F00246EEA /* NSManagedObject+Pearl.m in Sources */,
@ -2006,7 +2026,6 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_OBJC_ARC = YES;
CODE_SIGN_ENTITLEMENTS = MasterPassword.entitlements;
CODE_SIGN_IDENTITY = "Mac Developer: Maarten Billemont (DWGU95U4ZD)";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@ -2014,6 +2033,7 @@
);
GCC_PREFIX_HEADER = "MasterPassword-Prefix.pch";
INFOPLIST_FILE = "MasterPassword-Info.plist";
PROVISIONING_PROFILE = "77750158-06A9-41B0-B992-532E2033463E";
SKIP_INSTALL = NO;
WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}";
};
@ -2025,7 +2045,6 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_OBJC_ARC = YES;
CODE_SIGN_ENTITLEMENTS = MasterPassword.entitlements;
CODE_SIGN_IDENTITY = "Developer ID Application: Maarten Billemont (HL3Q45LX9N)";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@ -2033,6 +2052,7 @@
);
GCC_PREFIX_HEADER = "MasterPassword-Prefix.pch";
INFOPLIST_FILE = "MasterPassword-Info.plist";
PROVISIONING_PROFILE = "51A082ED-2873-4B5E-9C73-A74A85EC0CBA";
SKIP_INSTALL = NO;
WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}";
};
@ -2123,7 +2143,6 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_OBJC_ARC = YES;
CODE_SIGN_ENTITLEMENTS = MasterPassword.entitlements;
CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application: Maarten Billemont (HL3Q45LX9N)";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@ -2131,6 +2150,7 @@
);
GCC_PREFIX_HEADER = "MasterPassword-Prefix.pch";
INFOPLIST_FILE = "MasterPassword-Info.plist";
PROVISIONING_PROFILE = "170D83FD-18FE-4A05-B13C-8D16876480C6";
SKIP_INSTALL = NO;
WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}";
};