diff --git a/MacPass/MPEntryAttributeViewController.h b/MacPass/MPEntryAttributeViewController.h index bb342305..27d8fe5f 100644 --- a/MacPass/MPEntryAttributeViewController.h +++ b/MacPass/MPEntryAttributeViewController.h @@ -24,6 +24,7 @@ NS_ASSUME_NONNULL_BEGIN @property (strong) IBOutlet NSButton *toggleProtectedButton; @property (strong) IBOutlet NSButton *removeButton; @property (strong) IBOutlet NSButton *actionButton; +@property SEL attributeSelector; // set this if the editor is bound to a default attributes - (void)updateValuesAndEditing; - (void)performCopyForText:(NSString *)text; diff --git a/MacPass/MPEntryAttributeViewController.m b/MacPass/MPEntryAttributeViewController.m index 90a734ba..ce963fef 100644 --- a/MacPass/MPEntryAttributeViewController.m +++ b/MacPass/MPEntryAttributeViewController.m @@ -25,9 +25,8 @@ NSString *nameForDefaultKey(NSString *key) { } -@interface MPEntryAttributeViewController () { - BOOL _isDefaultAttribute; -} +@interface MPEntryAttributeViewController () +@property (nonatomic, readonly, getter=isDefaultAttributeEditor) BOOL defaultAttributeEditor; @end @@ -39,17 +38,28 @@ NSString *nameForDefaultKey(NSString *key) { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if(self) { _isEditor = NO; - _isDefaultAttribute = NO; } return self; } - (instancetype)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; - _isEditor = NO; + if(self) { + _isEditor = NO; + NSString *selectorString = [coder decodeObjectOfClass:NSString.class forKey:NSStringFromSelector(@selector(attributeSelector))]; + if(selectorString) { + self.attributeSelector = NSSelectorFromString(selectorString); + } + } return self; } +- (void)encodeWithCoder:(NSCoder *)coder { + [super encodeWithCoder:coder]; + // editor state will be set to NO after decoding + [coder encodeObject:NSStringFromSelector(self.attributeSelector) forKey:NSStringFromSelector(@selector(attributeSelector))]; +} + - (void)viewDidLoad { [super viewDidLoad]; @@ -64,6 +74,27 @@ NSString *nameForDefaultKey(NSString *key) { self.actionButton.hidden = YES; self.actionButton.title = NSLocalizedString(@"COPY", "Button title for copying an attribute value"); + NSDictionary *bindingOptions = @{ NSNullPlaceholderBindingOption : NSLocalizedString(@"NONE", "Placeholder text for input fields if no entry or group is selected"), + NSConditionallySetsHiddenBindingOption : @(NO), + NSConditionallySetsEnabledBindingOption : @(NO), + NSConditionallySetsEditableBindingOption : @(NO) }; + NSString *valueKeyPath = [NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(representedObject)), NSStringFromSelector(@selector(value))]; + if(self.isDefaultAttributeEditor) { + valueKeyPath = [NSString stringWithFormat:@"%@.%@.%@", NSStringFromSelector(@selector(representedObject)),NSStringFromSelector(@selector(entry)), NSStringFromSelector(self.attributeSelector)]; + } + [self.valueTextField bind:NSValueBinding + toObject:self + withKeyPath:valueKeyPath + options:bindingOptions]; + + if(!self.isDefaultAttributeEditor) { + NSString *keyKeyPath = [NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(representedObject)), NSStringFromSelector(@selector(key))]; + [self.keyTextField bind:NSValueBinding + toObject:self + withKeyPath:keyKeyPath + options:bindingOptions]; + } + [self updateValuesAndEditing]; } @@ -74,17 +105,20 @@ NSString *nameForDefaultKey(NSString *key) { return nil; } +- (BOOL)isDefaultAttributeEditor { + return (self.attributeSelector != NULL); +} + - (void)setIsEditor:(BOOL)isEditor { _isEditor = isEditor; [self updateValuesAndEditing]; } - (void)setRepresentedObject:(id)representedObject { - [self.valueTextField unbind:NSValueBinding]; - [self.keyTextField unbind:NSValueBinding]; - if(self.representedAttribute) { - [NSNotificationCenter.defaultCenter removeObserver:self name:KPKDidChangeAttributeNotification object:self.representedObject]; + [NSNotificationCenter.defaultCenter removeObserver:self + name:KPKDidChangeAttributeNotification + object:self.representedObject]; } super.representedObject = representedObject; if(self.representedAttribute) { @@ -93,18 +127,10 @@ NSString *nameForDefaultKey(NSString *key) { name:KPKDidChangeAttributeNotification object:self.representedAttribute]; - } - _isDefaultAttribute = self.representedAttribute.isDefault; - - NSDictionary *bindingOptions = @{ NSNullPlaceholderBindingOption : NSLocalizedString(@"NONE", "Placeholder text for input fields if no entry or group is selected") }; - NSString *valueKeyPath = [NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(representedObject)), NSStringFromSelector(@selector(value))]; - [self.valueTextField bind:NSValueBinding toObject:self withKeyPath:valueKeyPath options:bindingOptions]; - - if(!_isDefaultAttribute) { - NSString *keyKeyPath = [NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(representedObject)), NSStringFromSelector(@selector(key))]; - [self.keyTextField bind:NSValueBinding toObject:self withKeyPath:keyKeyPath options:bindingOptions]; - } - else { + } + // bind with read-only setup and value transformer for names? + if(self.isDefaultAttributeEditor) { + [self.keyTextField unbind:NSValueBinding]; NSString *localizedKey = nameForDefaultKey(self.representedAttribute.key); if(localizedKey) { self.keyTextField.stringValue = localizedKey; @@ -167,19 +193,19 @@ NSString *nameForDefaultKey(NSString *key) { } - (void)updateValuesAndEditing { - /* values */ + // values self.view.hidden = self.isEditor ? NO : self.representedAttribute.value.length == 0; self.valueTextField.showPassword = !self.representedAttribute.protect; - /* editor */ - self.keyTextField.editable = !_isDefaultAttribute && self.isEditor; + // editor + self.keyTextField.editable = !self.isDefaultAttributeEditor && self.isEditor; self.valueTextField.editable = self.isEditor; self.keyTextField.selectable = YES; self.valueTextField.selectable = YES; - self.toggleProtectedButton.hidden = _isDefaultAttribute; + self.toggleProtectedButton.hidden = self.isDefaultAttributeEditor; - self.removeButton.hidden = !self.isEditor ? YES : _isDefaultAttribute; + self.removeButton.hidden = !self.isEditor ? YES : self.isDefaultAttributeEditor; // set draws background first, since bezeld might have side effects self.valueTextField.drawsBackground = self.isEditor; diff --git a/MacPass/MPEntryInspectorViewController.m b/MacPass/MPEntryInspectorViewController.m index 8399d1c0..8b544022 100644 --- a/MacPass/MPEntryInspectorViewController.m +++ b/MacPass/MPEntryInspectorViewController.m @@ -608,27 +608,26 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { - (void)_setupAttributeEditors { self.iconViewController = [[MPNodeIconViewController alloc] init]; [self addChildViewController:self.iconViewController]; - self.iconViewController.isEditor = NO; [self.fieldsStackView addArrangedSubview:self.iconViewController.view]; self.titleEditorViewController = [[MPEntryAttributeViewController alloc] init]; [self addChildViewController:self.titleEditorViewController]; - self.titleEditorViewController.isEditor = NO; + self.titleEditorViewController.attributeSelector = @selector(title); [self.fieldsStackView addArrangedSubview:self.titleEditorViewController.view]; self.usernameEditorViewController = [[MPEntryAttributeViewController alloc] init]; [self addChildViewController:self.usernameEditorViewController]; - self.usernameEditorViewController.isEditor = NO; + self.usernameEditorViewController.attributeSelector = @selector(username); [self.fieldsStackView addArrangedSubview:self.usernameEditorViewController.view]; self.passwordEditorViewController = [[MPEntryPasswordAttributeViewController alloc] init]; [self addChildViewController:self.passwordEditorViewController]; - self.passwordEditorViewController.isEditor = NO; + self.passwordEditorViewController.attributeSelector = @selector(password); [self.fieldsStackView addArrangedSubview:self.passwordEditorViewController.view]; self.urlEditorViewController = [[MPEntryAttributeViewController alloc] init]; [self addChildViewController:self.urlEditorViewController]; - self.urlEditorViewController.isEditor = NO; + self.urlEditorViewController.attributeSelector = @selector(url); [self.fieldsStackView addArrangedSubview:self.urlEditorViewController.view]; self.totpViewController = [[MPTOTPViewController alloc] init]; diff --git a/MacPass/NSImage+MPQRCode.m b/MacPass/NSImage+MPQRCode.m index 6a56382e..e9475ea5 100644 --- a/MacPass/NSImage+MPQRCode.m +++ b/MacPass/NSImage+MPQRCode.m @@ -34,7 +34,7 @@ + (instancetype)QRCodeImageWithString:(NSString *)string { NSData *asciiData = [string dataUsingEncoding:NSISOLatin1StringEncoding]; if(!asciiData) { - return nil; + return [[NSImage alloc] init]; } CIFilter *qrCodeFilter = [CIFilter filterWithName:@"CIQRCodeGenerator" withInputParameters:@{@"inputMessage": asciiData}]; NSAffineTransform *scale = [[NSAffineTransform alloc] init];