diff --git a/MacPass.xcodeproj/project.pbxproj b/MacPass.xcodeproj/project.pbxproj index f119444b..587b1073 100644 --- a/MacPass.xcodeproj/project.pbxproj +++ b/MacPass.xcodeproj/project.pbxproj @@ -12,6 +12,8 @@ 4C01C2421764D8980016D5D0 /* MPContextMenuHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C01C2411764D8980016D5D0 /* MPContextMenuHelper.m */; }; 4C0728BD17B5B7F7005A7DD9 /* MPPasswordEditWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0728BC17B5B7F7005A7DD9 /* MPPasswordEditWindowController.m */; }; 4C0728BF17B68ED0005A7DD9 /* SavePanelAccessoryView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C0728BE17B68ED0005A7DD9 /* SavePanelAccessoryView.xib */; }; + 4C0949591FD6B89B004F2971 /* NSUserNotification+MPAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0949581FD6B89B004F2971 /* NSUserNotification+MPAdditions.m */; }; + 4C09495C1FD6E510004F2971 /* MPAddCustomFieldContextMenuDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C09495B1FD6E510004F2971 /* MPAddCustomFieldContextMenuDelegate.m */; }; 4C0AF62F195C1F2B009E658D /* MPEntrySearchContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0AF62E195C1F2B009E658D /* MPEntrySearchContext.m */; }; 4C0B038C18E36DA400B9F9C9 /* MPFixAutotypeWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0B038A18E36DA400B9F9C9 /* MPFixAutotypeWindowController.m */; }; 4C0B038D18E36DA400B9F9C9 /* FixAutotypeWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C0B038B18E36DA400B9F9C9 /* FixAutotypeWindow.xib */; }; @@ -129,7 +131,7 @@ 4C5FE9AE17843CE20001D5A8 /* MPSelectedAttachmentTableCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C5FE9AD17843CE20001D5A8 /* MPSelectedAttachmentTableCellView.m */; }; 4C61EA0316D2FD0800AC519E /* MPOutlineViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C61EA0216D2FD0800AC519E /* MPOutlineViewController.m */; }; 4C61EA0516D2FFE200AC519E /* OutlineView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C61EA0416D2FFE200AC519E /* OutlineView.xib */; }; - 4C63B8FB17A3154D0091BD72 /* MPContextToolbarButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C63B8FA17A3154D0091BD72 /* MPContextToolbarButton.m */; }; + 4C63B8FB17A3154D0091BD72 /* MPContextButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C63B8FA17A3154D0091BD72 /* MPContextButton.m */; }; 4C65C79C16DD283900E32CFF /* MPToolbarButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C65C79B16DD283900E32CFF /* MPToolbarButton.m */; }; 4C65FAE916D16DDB006E0577 /* MPPasswordInputController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C65FAE716D16DDB006E0577 /* MPPasswordInputController.m */; }; 4C663D411D6D91A900CB6237 /* MPNumberFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C663D401D6D91A900CB6237 /* MPNumberFormatter.m */; }; @@ -324,6 +326,10 @@ 4C0728BB17B5B7F7005A7DD9 /* MPPasswordEditWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordEditWindowController.h; sourceTree = ""; }; 4C0728BC17B5B7F7005A7DD9 /* MPPasswordEditWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordEditWindowController.m; sourceTree = ""; }; 4C0728BE17B68ED0005A7DD9 /* SavePanelAccessoryView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SavePanelAccessoryView.xib; sourceTree = ""; }; + 4C0949571FD6B89B004F2971 /* NSUserNotification+MPAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSUserNotification+MPAdditions.h"; sourceTree = ""; }; + 4C0949581FD6B89B004F2971 /* NSUserNotification+MPAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSUserNotification+MPAdditions.m"; sourceTree = ""; }; + 4C09495A1FD6E510004F2971 /* MPAddCustomFieldContextMenuDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPAddCustomFieldContextMenuDelegate.h; sourceTree = ""; }; + 4C09495B1FD6E510004F2971 /* MPAddCustomFieldContextMenuDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPAddCustomFieldContextMenuDelegate.m; sourceTree = ""; }; 4C0AF62D195C1F2B009E658D /* MPEntrySearchContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEntrySearchContext.h; sourceTree = ""; }; 4C0AF62E195C1F2B009E658D /* MPEntrySearchContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPEntrySearchContext.m; sourceTree = ""; }; 4C0B038918E36DA400B9F9C9 /* MPFixAutotypeWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPFixAutotypeWindowController.h; sourceTree = ""; }; @@ -517,8 +523,8 @@ 4C61EA0116D2FD0800AC519E /* MPOutlineViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPOutlineViewController.h; sourceTree = ""; }; 4C61EA0216D2FD0800AC519E /* MPOutlineViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPOutlineViewController.m; sourceTree = ""; }; 4C61EA0416D2FFE200AC519E /* OutlineView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = OutlineView.xib; sourceTree = ""; }; - 4C63B8F917A3154D0091BD72 /* MPContextToolbarButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPContextToolbarButton.h; sourceTree = ""; }; - 4C63B8FA17A3154D0091BD72 /* MPContextToolbarButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPContextToolbarButton.m; sourceTree = ""; }; + 4C63B8F917A3154D0091BD72 /* MPContextButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPContextButton.h; sourceTree = ""; }; + 4C63B8FA17A3154D0091BD72 /* MPContextButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPContextButton.m; sourceTree = ""; }; 4C65C79A16DD283900E32CFF /* MPToolbarButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPToolbarButton.h; sourceTree = ""; }; 4C65C79B16DD283900E32CFF /* MPToolbarButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPToolbarButton.m; sourceTree = ""; }; 4C65FAE616D16DDB006E0577 /* MPPasswordInputController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordInputController.h; sourceTree = ""; }; @@ -1005,6 +1011,8 @@ 4CDA35741EBA0CF2003CD59F /* NSString+MPComposedCharacterAdditions.m */, 4C8F0C771FD05A6A00BE157F /* NSString+MPPrettyPasswordDisplay.h */, 4C8F0C781FD05A6A00BE157F /* NSString+MPPrettyPasswordDisplay.m */, + 4C0949571FD6B89B004F2971 /* NSUserNotification+MPAdditions.h */, + 4C0949581FD6B89B004F2971 /* NSUserNotification+MPAdditions.m */, ); name = Categories; sourceTree = ""; @@ -1094,6 +1102,8 @@ 4CE501331BBC47F500FB819D /* MPTagsTokenFieldDelegate.m */, 4C2F17A01FD69BCA0097418D /* MPUserNotificationCenterDelegate.h */, 4C2F17A11FD69BCA0097418D /* MPUserNotificationCenterDelegate.m */, + 4C09495A1FD6E510004F2971 /* MPAddCustomFieldContextMenuDelegate.h */, + 4C09495B1FD6E510004F2971 /* MPAddCustomFieldContextMenuDelegate.m */, ); name = Delegates; sourceTree = ""; @@ -1515,8 +1525,8 @@ 4C65C79B16DD283900E32CFF /* MPToolbarButton.m */, 4C888C9116EB6F5E003D34A1 /* MPToolbarItem.h */, 4C888C9216EB6F5E003D34A1 /* MPToolbarItem.m */, - 4C63B8F917A3154D0091BD72 /* MPContextToolbarButton.h */, - 4C63B8FA17A3154D0091BD72 /* MPContextToolbarButton.m */, + 4C63B8F917A3154D0091BD72 /* MPContextButton.h */, + 4C63B8FA17A3154D0091BD72 /* MPContextButton.m */, 4C57AE1217BA422B00CA4F34 /* MPSegmentedContextCell.h */, 4C57AE1317BA422B00CA4F34 /* MPSegmentedContextCell.m */, 8345D7271F39023E002B7B0F /* MPPathControl.h */, @@ -1961,7 +1971,7 @@ 4CB33F861EAF54A000C9341E /* KPKNode+MPIsHistory.m in Sources */, 4CCEDE2E179F213B008402BE /* MPNotifications.m in Sources */, 4C17D8E517A1C780006C8C1E /* MPDocumentWindowDelegate.m in Sources */, - 4C63B8FB17A3154D0091BD72 /* MPContextToolbarButton.m in Sources */, + 4C63B8FB17A3154D0091BD72 /* MPContextButton.m in Sources */, 4C1E9885185F71A800943563 /* MPContextBarViewController.m in Sources */, 4C1FA07B18231900003A3F8C /* MPDocument+Autotype.m in Sources */, 4C4B7EE917A45EC6000234C7 /* MPDatePickingViewController.m in Sources */, @@ -1974,9 +1984,11 @@ 8345D7291F39023E002B7B0F /* MPPathControl.m in Sources */, 4CD7223B17A7CB0700F5A1E1 /* MPWorkflowSettingsController.m in Sources */, 4CA08DA017A831B200A6544B /* MPAddEntryContextMenuDelegate.m in Sources */, + 4C09495C1FD6E510004F2971 /* MPAddCustomFieldContextMenuDelegate.m in Sources */, 4CE3E62617AB0D2D00D9E4B4 /* MPAttachmentTableDataSource.m in Sources */, 4C0728BD17B5B7F7005A7DD9 /* MPPasswordEditWindowController.m in Sources */, 4C0F647B17B6BC9C00D9522A /* MPSavePanelAccessoryViewController.m in Sources */, + 4C0949591FD6B89B004F2971 /* NSUserNotification+MPAdditions.m in Sources */, 4C3B42871F935316007B04FD /* MPDayCountFormatter.m in Sources */, 4C57AE1417BA422B00CA4F34 /* MPSegmentedContextCell.m in Sources */, 4CE2961518429AA5005F01CE /* MPAutotypeKeyPress.m in Sources */, diff --git a/MacPass/Base.lproj/EntryInspectorView.xib b/MacPass/Base.lproj/EntryInspectorView.xib index f2048e0b..a3251099 100644 --- a/MacPass/Base.lproj/EntryInspectorView.xib +++ b/MacPass/Base.lproj/EntryInspectorView.xib @@ -1,8 +1,8 @@ - + - + @@ -10,7 +10,7 @@ - + @@ -455,17 +455,6 @@ - + + + + + + + + + + + + + + @@ -513,24 +516,24 @@ - - - + + + @@ -898,7 +901,7 @@ - + diff --git a/MacPass/MPAddCustomFieldContextMenuDelegate.h b/MacPass/MPAddCustomFieldContextMenuDelegate.h new file mode 100644 index 00000000..ce608fe7 --- /dev/null +++ b/MacPass/MPAddCustomFieldContextMenuDelegate.h @@ -0,0 +1,15 @@ +// +// MPAddCustomFieldContextMenuDelegate.h +// MacPass +// +// Created by Michael Starke on 05.12.17. +// Copyright © 2017 HicknHack Software GmbH. All rights reserved. +// + +#import + +@interface MPAddCustomFieldContextMenuDelegate : NSObject + +@property (weak) NSViewController *viewController; + +@end diff --git a/MacPass/MPAddCustomFieldContextMenuDelegate.m b/MacPass/MPAddCustomFieldContextMenuDelegate.m new file mode 100644 index 00000000..48bda314 --- /dev/null +++ b/MacPass/MPAddCustomFieldContextMenuDelegate.m @@ -0,0 +1,58 @@ +// +// MPAddCustomFieldContextMenuDelegate.m +// MacPass +// +// Created by Michael Starke on 05.12.17. +// Copyright © 2017 HicknHack Software GmbH. All rights reserved. +// + +#import "MPAddCustomFieldContextMenuDelegate.h" +#import "KeePassKit/KeePassKit.h" + +NSString *const MPHMACOTPSeedAttributeKey = @"HMACOTP-Seed"; +NSString *const MPHMACOTPConfigAttributeKey = @"HMACOTP-Config"; + +@interface MPAddCustomFieldContextMenuDelegate () +@property (readonly, nonatomic) KPKEntry *entry; +@end + +@implementation MPAddCustomFieldContextMenuDelegate + +- (KPKEntry *)entry { + KPKEntry *entry = self.viewController.representedObject; + if([entry isKindOfClass:KPKEntry.class]) { + return entry; + } + return nil; +} + +- (void)menuNeedsUpdate:(NSMenu *)menu { + [menu removeAllItems]; + [self _setupHOTPMenuItemsToMenu:menu]; +} + +- (void)_setupHOTPMenuItemsToMenu:(NSMenu *)menu { + + BOOL hasConfigAttribute = nil != [self.entry customAttributeWithKey:MPHMACOTPConfigAttributeKey]; + if(!hasConfigAttribute) { + NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Add config" action:@selector(_addHMACConfig:) keyEquivalent:@""]; + item.target = self; + [menu addItem:item]; + } + BOOL hasSeedAttribute = nil != [self.entry customAttributeWithKey:MPHMACOTPSeedAttributeKey]; + if(!hasSeedAttribute) { + NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Add seed" action:@selector(_addHMACSeed:) keyEquivalent:@""]; + item.target = self; + [menu addItem:item]; + } +} + +- (IBAction)_addHMACConfig:(id)sender { + [self.entry addCustomAttribute:[[KPKAttribute alloc] initWithKey:MPHMACOTPConfigAttributeKey value:@""]]; +} + +- (IBAction)_addHMACSeed:(id)sender { + [self.entry addCustomAttribute:[[KPKAttribute alloc] initWithKey:MPHMACOTPSeedAttributeKey value:@""]]; +} + +@end diff --git a/MacPass/MPAppDelegate.m b/MacPass/MPAppDelegate.m index 3837b831..f04b2643 100644 --- a/MacPass/MPAppDelegate.m +++ b/MacPass/MPAppDelegate.m @@ -38,6 +38,7 @@ #import "MPPrettyPasswordTransformer.h" #import "MPTemporaryFileStorageCenter.h" #import "MPValueTransformerHelper.h" +#import "MPUserNotificationCenterDelegate.h" #import "NSApplication+MPAdditions.h" @@ -50,6 +51,7 @@ NSString *const MPDidChangeStoredKeyFilesSettings = @"com.hicknhack.macpass.MPDi @interface MPAppDelegate () { @private MPDockTileHelper *_dockTileHelper; + MPUserNotificationCenterDelegate *_userNotificationCenterDelegate; BOOL _shouldOpenFile; // YES if app was started to open a } @@ -71,6 +73,7 @@ NSString *const MPDidChangeStoredKeyFilesSettings = @"com.hicknhack.macpass.MPDi - (instancetype)init { self = [super init]; if(self) { + _userNotificationCenterDelegate = [[MPUserNotificationCenterDelegate alloc] init]; /* We know that we do not use the variable after instantiation */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-variable" diff --git a/MacPass/MPAutotypeDaemon.m b/MacPass/MPAutotypeDaemon.m index 663c315d..2c63ade4 100644 --- a/MacPass/MPAutotypeDaemon.m +++ b/MacPass/MPAutotypeDaemon.m @@ -22,23 +22,20 @@ #import "MPAutotypeDaemon.h" #import "MPDocument.h" - #import "MPAutotypeCommand.h" #import "MPAutotypeContext.h" #import "MPAutotypePaste.h" - #import "MPPasteBoardController.h" #import "MPSettingsHelper.h" - -#import "NSApplication+MPAdditions.h" - #import "MPAutotypeCandidateSelectionViewController.h" -#import "KeePassKit/KeePassKit.h" +#import "NSApplication+MPAdditions.h" +#import "NSUserNotification+MPAdditions.h" #import "DDHotKeyCenter.h" #import "DDHotKey+MacPassAdditions.h" +#import "KeePassKit/KeePassKit.h" #import NSString *const kMPWindowTitleKey = @"kMPWindowTitleKey"; @@ -170,7 +167,8 @@ static MPAutotypeDaemon *_sharedInstance; NSUserNotification *notification = [[NSUserNotification alloc] init]; notification.title = NSApp.applicationName; notification.informativeText = NSLocalizedString(@"AUTOTYPE_OVERLAY_NO_DOCUMENTS", "Notification: Autotype failed, no documents are open"); - + notification.actionButtonTitle = NSLocalizedString(@"OPEN_DOCUMENT", "Action button in Notification to open a document"); + //notification.showsButtons = YES; [NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:notification]; return; } diff --git a/MacPass/MPContextToolbarButton.h b/MacPass/MPContextButton.h similarity index 83% rename from MacPass/MPContextToolbarButton.h rename to MacPass/MPContextButton.h index 45873e49..521e897e 100644 --- a/MacPass/MPContextToolbarButton.h +++ b/MacPass/MPContextButton.h @@ -22,12 +22,10 @@ #import -@interface MPContextToolbarButton : NSSegmentedControl +@interface MPContextButton : NSSegmentedControl + +@property (nonatomic, strong) NSMenu *contextMenu; - (void)setImage:(NSImage *)image; -- (void)setContextMenu:(NSMenu *)menu; - -- (NSControlSize)controlSize; -- (void)setControlSize:(NSControlSize)controlSize; @end diff --git a/MacPass/MPContextToolbarButton.m b/MacPass/MPContextButton.m similarity index 60% rename from MacPass/MPContextToolbarButton.m rename to MacPass/MPContextButton.m index 3441a80b..0d092156 100644 --- a/MacPass/MPContextToolbarButton.m +++ b/MacPass/MPContextButton.m @@ -20,42 +20,52 @@ // along with this program. If not, see . // -#import "MPContextToolbarButton.h" +#import "MPContextButton.h" #import "MPSegmentedContextCell.h" -@interface MPContextToolbarButton () { - @private - NSMenu *_contextMenu; -} +@interface MPContextButton () @end -@implementation MPContextToolbarButton +@implementation MPContextButton -- (id)initWithFrame:(NSRect)frame { - self = [super initWithFrame:frame]; - if (self) { - NSData *data = [NSKeyedArchiver archivedDataWithRootObject:[self cell]]; - NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; - MPSegmentedContextCell *cell = [[MPSegmentedContextCell alloc] initWithCoder:unarchiver]; - self.cell = cell; - - self.focusRingType = NSFocusRingTypeNone; - self.segmentCount = 2; - cell.trackingMode = NSSegmentSwitchTrackingMomentary; - self.segmentStyle = NSSegmentStyleTexturedSquare; - [cell setWidth:31 forSegment:0]; - [cell setWidth:17 forSegment:1]; - - NSImage *contextTriangle = [[NSBundle mainBundle] imageForResource:@"contextTriangleTemplate"]; - [self setImage:contextTriangle forSegment:1]; - - cell.contextMenuAction = @selector(showContextMenu:); - cell.contextMenuTarget = self; +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if(self) { + [self _setup]; } return self; } +- (instancetype)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self _setup]; + } + return self; +} + +- (void)_setup { + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:[self cell]]; + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; + MPSegmentedContextCell *cell = [[MPSegmentedContextCell alloc] initWithCoder:unarchiver]; + self.cell = cell; + + self.focusRingType = NSFocusRingTypeNone; + self.segmentStyle = NSSegmentStyleTexturedSquare; + self.segmentCount = 2; + cell.trackingMode = NSSegmentSwitchTrackingMomentary; + [cell setWidth:31 forSegment:0]; + [cell setWidth:17 forSegment:1]; + cell.trackingMode = NSSegmentSwitchTrackingMomentary; + + NSImage *contextTriangle = [NSBundle.mainBundle imageForResource:@"contextTriangleTemplate"]; + [self setImage:contextTriangle forSegment:1]; + + cell.contextMenuAction = @selector(showContextMenu:); + cell.contextMenuTarget = self; +} + - (void)setContextMenu:(NSMenu *)menu { if(_contextMenu != menu) { _contextMenu = menu; @@ -106,25 +116,11 @@ default: break; } - if([self.superclass instancesRespondToSelector:@selector(setControlSize:)]) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" - super.controlSize = controlSize; -#pragma clang diagnostic pop - } - else { - self.cell.controlSize = controlSize; - } + super.controlSize = controlSize; } - (NSControlSize)controlSize { - if([self.superclass instancesRespondToSelector:@selector(controlSize)]) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" - return super.controlSize; -#pragma clang diagnostic pop - } - return self.cell.controlSize; + return super.controlSize; } @end diff --git a/MacPass/MPDocumentWindowController.m b/MacPass/MPDocumentWindowController.m index 96685d73..a54e1a38 100644 --- a/MacPass/MPDocumentWindowController.m +++ b/MacPass/MPDocumentWindowController.m @@ -25,7 +25,7 @@ #import "MPAppDelegate.h" #import "MPAutotypeDaemon.h" #import "MPConstants.h" -#import "MPContextToolbarButton.h" +#import "MPContextButton.h" #import "MPDatabaseSettingsWindowController.h" #import "MPDocument.h" #import "MPDocumentWindowDelegate.h" diff --git a/MacPass/MPEntryInspectorViewController.h b/MacPass/MPEntryInspectorViewController.h index 7a1e7e26..395be4a8 100644 --- a/MacPass/MPEntryInspectorViewController.h +++ b/MacPass/MPEntryInspectorViewController.h @@ -25,6 +25,7 @@ #import @class HNHUIRoundedSecureTextField; +@class MPContextButton; @class MPDocument; @interface MPEntryInspectorViewController : MPViewController @@ -48,7 +49,7 @@ @property (weak) IBOutlet NSTextField *createdTextField; @property (weak) IBOutlet NSTextField *modifiedTextField; -@property (weak) IBOutlet NSButton *addCustomFieldButton; +@property (weak) IBOutlet MPContextButton *addCustomFieldButton; /* Attachments */ @property (weak) IBOutlet NSButtonCell *addAttachmentButton; diff --git a/MacPass/MPEntryInspectorViewController.m b/MacPass/MPEntryInspectorViewController.m index 5bd85619..e395835d 100644 --- a/MacPass/MPEntryInspectorViewController.m +++ b/MacPass/MPEntryInspectorViewController.m @@ -43,6 +43,8 @@ #import "MPActionHelper.h" #import "MPSettingsHelper.h" #import "MPPasteBoardController.h" +#import "MPContextButton.h" +#import "MPAddCustomFieldContextMenuDelegate.h" #import "MPArrayController.h" @@ -67,6 +69,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { MPWindowAssociationsTableViewDelegate *_windowAssociationsTableDelegate; MPWindowTitleComboBoxDelegate *_windowTitleMenuDelegate; MPTagsTokenFieldDelegate *_tagTokenFieldDelegate; + MPAddCustomFieldContextMenuDelegate *_addCustomFieldContextMenuDelegate; } @property (nonatomic, assign) BOOL showPassword; @@ -97,9 +100,12 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { _windowAssociationsTableDelegate = [[MPWindowAssociationsTableViewDelegate alloc] init]; _windowTitleMenuDelegate = [[MPWindowTitleComboBoxDelegate alloc] init]; _tagTokenFieldDelegate = [[MPTagsTokenFieldDelegate alloc] init]; + _addCustomFieldContextMenuDelegate = [[MPAddCustomFieldContextMenuDelegate alloc] init]; _tagTokenFieldDelegate.viewController = self; _attachmentTableDelegate.viewController = self; _customFieldTableDelegate.viewController = self; + _addCustomFieldContextMenuDelegate.viewController = self; + _activeTab = MPEntryTabGeneral; } return self; @@ -166,6 +172,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { self.tagsTokenField.delegate = _tagTokenFieldDelegate; + [self _setupCustomFieldsButton]; [self _setupViewBindings]; } @@ -542,6 +549,14 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { } +- (void)_setupCustomFieldsButton { + /* FIXME: this is a bug in MPContextButton preventing the image set in IB to be used */ + [self.addCustomFieldButton setImage:[NSImage imageNamed:NSImageNameAddTemplate]]; + NSMenu *customFieldMenu = [[NSMenu alloc] initWithTitle:NSLocalizedString(@"ADD_CUSTOM_FIELD_CONTEXT_MENU", @"Menu displayed for adding special custom keys")]; + customFieldMenu.delegate = _addCustomFieldContextMenuDelegate; + self.addCustomFieldButton.contextMenu = customFieldMenu; +} + #pragma mark - #pragma mark HNHUITextFieldDelegate - (NSMenu *)textField:(NSTextField *)textField textView:(NSTextView *)view menu:(NSMenu *)menu { diff --git a/MacPass/MPPickcharsParser.m b/MacPass/MPPickcharsParser.m index 9d8bf5d0..497e5631 100644 --- a/MacPass/MPPickcharsParser.m +++ b/MacPass/MPPickcharsParser.m @@ -46,7 +46,7 @@ for(NSString *character in string.composedCharacters) { } - + return nil; } /* diff --git a/MacPass/MPPlugin.h b/MacPass/MPPlugin.h index 4c2a5081..3b290234 100644 --- a/MacPass/MPPlugin.h +++ b/MacPass/MPPlugin.h @@ -27,6 +27,7 @@ NS_ASSUME_NONNULL_BEGIN @class MPPluginHost; @class MPAutotypeCommand; @class KPKEntry; +@class KPKAttribute; @interface MPPlugin : NSObject @@ -35,8 +36,6 @@ NS_ASSUME_NONNULL_BEGIN @property (copy, readonly) NSString *version; @property (nonatomic, strong, readonly) NSBundle *bundle; -@property (readonly) NSString *requiredHostVersion; // the host version required for running the plugin in mayor.minor.path format - /** If your plugin needs initalization override this method but you have to call [super initWithPluginHost:] @@ -59,41 +58,29 @@ NS_ASSUME_NONNULL_BEGIN @end -/* Adopt this protocoll if you plugin supplied additinal autotype commands */ -@protocol MPAutotypePlugin -@required -/** - Returns an array of string of commands supported by this pluing. Leave out enclosing curly brackets! - E.g. if you support {FOO} and {BAR} you will return @[ @"FOO", @"BAR" ]. The autotype system is case insenstivie. - */ -@property (nonatomic,copy) NSArray *commandStrings; -/** - Will be called by the plugin host to generate autotype commands for the corresponding string. - Command strings are considered case insensitive but mostly will be used in upper case. - You should therefore compare case insensitive. - - @param commandString The command string without any enclosing curly brackets. The string is normalized to upper cased. - @param entry The entry for which the command will be used - @return a command for the supplied string, return nil if parsing fails or an unsupported command is supplied - */ -- (MPAutotypeCommand * _Nullable)commandForString:(NSString *)commandString entry:(KPKEntry *)entry; -@end - /* Adopt this protocoll if your plugin supports actions on entries. - Actions will get listed in various places in menues. You should shoudl supply a valid menu item - that is wired up with the correct target and action. Since there's responder chain resolving involved - as well as a + Actions will get listed in various places in menues. + You should not set target nor actions since they will get stripped. + MacPass will call you back via -[MPPlugin performActionFroMenuItem:withEntries:] */ @protocol MPEntryActionPlugin @optional - (NSMenuItem * _Nullable)menuItemForEntry; +- (void)performActionForMenuItem:(NSMenuItem *)item withEntries:(NSArray *)entries; @end @protocol MPCustomAttributePlugin @optional /* Supply a list of attribute keys that will get suggested for autocompletion as well as added to the extend add for custom fields */ @property (nonatomic,copy) NSArray* attributeKeys; +/* + For any attribute created with the special key the plugin will get called to offer a custom generation for the attributes value. + You can e.g. show UI to help the user create a special format. + + If nil is returned, an empty value will be used. + */ +- (NSString *)valueForAttributeWithKey:(NSString *)key; @end @interface MPPlugin (Deprecated) diff --git a/MacPass/MPToolbarDelegate.m b/MacPass/MPToolbarDelegate.m index b548c39f..b7e9355d 100644 --- a/MacPass/MPToolbarDelegate.m +++ b/MacPass/MPToolbarDelegate.m @@ -24,7 +24,7 @@ #import "MPToolbarButton.h" #import "MPToolbarItem.h" -#import "MPContextToolbarButton.h" +#import "MPContextButton.h" #import "MPAddEntryContextMenuDelegate.h" #import "MPActionHelper.h" @@ -103,7 +103,7 @@ NSString *const MPToolbarItemHistory = @"TOOLBAR_HISTORY"; if(!item) { item = [[MPToolbarItem alloc] initWithItemIdentifier:itemIdentifier]; NSString *itemLabel = [self _localizedLabelForToolbarItemIdentifier:itemIdentifier]; - [item setLabel:itemLabel]; + item.label = itemLabel; if([itemIdentifier isEqualToString:MPToolbarItemAction]) { NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 50, 32) pullsDown:YES]; @@ -135,8 +135,8 @@ NSString *const MPToolbarItemHistory = @"TOOLBAR_HISTORY"; item.view = popupButton; } else if( [itemIdentifier isEqualToString:MPToolbarItemAddEntry]) { - MPContextToolbarButton *button = [[MPContextToolbarButton alloc] initWithFrame:NSMakeRect(0, 0, 32, 32)]; - [button setAction:[self _actionForToolbarItemIdentifier:itemIdentifier]]; + MPContextButton *button = [[MPContextButton alloc] initWithFrame:NSMakeRect(0, 0, 32, 32)]; + button.action = [self _actionForToolbarItemIdentifier:itemIdentifier]; NSImage *image = self.toolbarImages[itemIdentifier]; image.size = NSMakeSize(16, 16); [button setImage:image]; @@ -145,7 +145,7 @@ NSString *const MPToolbarItemHistory = @"TOOLBAR_HISTORY"; NSMenu *menu = [NSMenu allocWithZone:[NSMenu menuZone]]; [menu addItemWithTitle:NSLocalizedString(@"UNKNOWN_TOOLBAR_ITEM", @"") action:NULL keyEquivalent:@""]; menu.delegate = _entryMenuDelegate; - [button setContextMenu:menu]; + button.contextMenu = menu; NSRect fittingRect = button.frame; diff --git a/MacPass/MPTreeDelegate.m b/MacPass/MPTreeDelegate.m index 08fe6b6b..2fd92275 100644 --- a/MacPass/MPTreeDelegate.m +++ b/MacPass/MPTreeDelegate.m @@ -95,7 +95,7 @@ panel.title = NSLocalizedString(@"PICKFIELD_WINDOW_TITLE", @"Window displayed to the user to pick an amout of characters"); [panel center]; if(NSModalResponseOK == [NSApp runModalForWindow:panel]) { - /* add appropriate key press comamnds? or let the pick-char view-controller handel this? */ + /* add appropriate key press commands? or let the pick-char view-controller handel this? */ return pickFieldViewController.pickedValue; } return @""; diff --git a/MacPass/MPUserNotificationCenterDelegate.m b/MacPass/MPUserNotificationCenterDelegate.m index a08f4d43..754d590e 100644 --- a/MacPass/MPUserNotificationCenterDelegate.m +++ b/MacPass/MPUserNotificationCenterDelegate.m @@ -18,4 +18,8 @@ return self; } +- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification { + NSLog(@"%@", notification); +} + @end diff --git a/MacPass/MacPass-Info.plist b/MacPass/MacPass-Info.plist index 12a3e035..5443b699 100644 --- a/MacPass/MacPass-Info.plist +++ b/MacPass/MacPass-Info.plist @@ -2,6 +2,8 @@ + NSUserNotificationAlertStyle + alert CFBundleDevelopmentRegion en CFBundleDocumentTypes diff --git a/MacPass/NSUserNotification+MPAdditions.h b/MacPass/NSUserNotification+MPAdditions.h new file mode 100644 index 00000000..20b9b814 --- /dev/null +++ b/MacPass/NSUserNotification+MPAdditions.h @@ -0,0 +1,15 @@ +// +// NSUserNotification+MPAdditions.h +// MacPass +// +// Created by Michael Starke on 05.12.17. +// Copyright © 2017 HicknHack Software GmbH. All rights reserved. +// + +#import + +@interface NSUserNotification (MPAdditions) + +@property (nonatomic) BOOL showsButtons; + +@end diff --git a/MacPass/NSUserNotification+MPAdditions.m b/MacPass/NSUserNotification+MPAdditions.m new file mode 100644 index 00000000..08b1b44f --- /dev/null +++ b/MacPass/NSUserNotification+MPAdditions.m @@ -0,0 +1,21 @@ +// +// NSUserNotification+MPAdditions.m +// MacPass +// +// Created by Michael Starke on 05.12.17. +// Copyright © 2017 HicknHack Software GmbH. All rights reserved. +// + +#import "NSUserNotification+MPAdditions.h" + +@implementation NSUserNotification (MPAdditions) + +- (BOOL)showsButtons { + return [[self valueForKey:@"_showsButtons"] boolValue]; +} + +- (void)setShowsButtons:(BOOL)showsButtons { + [self setValue:@(showsButtons) forKey:@"_showsButtons"]; +} + +@end diff --git a/MacPass/en.lproj/Localizable.strings b/MacPass/en.lproj/Localizable.strings index 5a61e04f..dc93999d 100644 --- a/MacPass/en.lproj/Localizable.strings +++ b/MacPass/en.lproj/Localizable.strings @@ -372,6 +372,9 @@ /* Open button in the open panel to import an XML file */ "OPEN_BUTTON_IMPORT_XML_OPEN_PANEL" = "Import"; +/* Notification Button */ +"OPEN_DOCUMENT" = "Open Document"; + /* Menu item to open the URL with the default application */ "OPEN_URL" = "Open URL";