More progress on import plugin support

This commit is contained in:
Michael Starke
2018-10-25 16:34:35 +02:00
parent 5912f613cb
commit 38e7a5f0b9
10 changed files with 109 additions and 25 deletions

View File

@@ -162,6 +162,9 @@
</connections>
</menuItem>
</items>
<connections>
<outlet property="delegate" destination="494" id="gzA-SE-HKO"/>
</connections>
</menu>
</menuItem>
<menuItem title="Export" id="tz9-yK-pOf">
@@ -350,6 +353,7 @@ CA
<connections>
<outlet property="fileNewMenuItem" destination="82" id="BUX-dy-HS2"/>
<outlet property="fixAutotypeMenuItem" destination="nx7-Vf-LiD" id="5n1-bG-JxJ"/>
<outlet property="importMenu" destination="4q9-u1-pcm" id="0XM-fS-Vyy"/>
<outlet property="itemMenu" destination="Ttt-tR-emo" id="cdF-dt-2h9"/>
<outlet property="saveMenuItem" destination="75" id="dsN-Im-4eZ"/>
</connections>

View File

@@ -26,10 +26,11 @@ APPKIT_EXTERN NSString *const MPDidChangeStoredKeyFilesSettings;
@interface MPAppDelegate : NSObject <NSApplicationDelegate, NSMenuDelegate>
@property (weak) IBOutlet NSMenuItem *saveMenuItem;
@property (weak) IBOutlet NSMenuItem *fixAutotypeMenuItem;
@property (weak) IBOutlet NSMenuItem *fileNewMenuItem;
@property (weak) IBOutlet NSMenu *itemMenu;
@property (strong) IBOutlet NSMenuItem *saveMenuItem;
@property (strong) IBOutlet NSMenuItem *fixAutotypeMenuItem;
@property (strong) IBOutlet NSMenuItem *fileNewMenuItem;
@property (strong) IBOutlet NSMenu *itemMenu;
@property (strong) IBOutlet NSMenu *importMenu;
@property (nonatomic, assign) BOOL isAllowedToStoreKeyFile;

View File

@@ -40,6 +40,7 @@
#import "MPValueTransformerHelper.h"
#import "MPUserNotificationCenterDelegate.h"
#import "MPWelcomeViewController.h"
#import "MPPlugin.h"
#import "NSApplication+MPAdditions.h"
@@ -208,6 +209,17 @@ NSString *const MPDidChangeStoredKeyFilesSettings = @"com.hicknhack.macpass.MPDi
[menu addItem:item];
}
}
if(menu == self.importMenu) {
NSMenuItem *exportXML = menu.itemArray.firstObject;
[menu removeAllItems];
for(MPPlugin<MPImportPlugin> * plugin in MPPluginHost.sharedHost.importPlugins) {
NSMenuItem *importItem = [[NSMenuItem alloc] init];
[plugin prepareImportMenuItem:importItem];
importItem.target = nil;
importItem.action = @selector(importFromPlugin:);
}
[menu insertItem:exportXML atIndex:0];
}
}
#pragma mark -

View File

@@ -149,6 +149,7 @@ FOUNDATION_EXPORT NSString *const MPDocumentGroupKey;
- (BOOL)shouldEnforcePasswordChange;
- (BOOL)shouldRecommendPasswordChange;
- (void)importTree:(KPKTree *)tree;
- (void)writeXMLToURL:(NSURL *)url;
- (void)readXMLfromURL:(NSURL *)url;
- (void)mergeWithContentsFromURL:(NSURL *)url key:(KPKCompositeKey *)key;

View File

@@ -329,6 +329,12 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou
// else do nothing!
}
- (void)importTree:(KPKTree *)tree {
self.tree = tree;
self.compositeKey = nil;
self.encryptedData = nil;
}
- (void)writeXMLToURL:(NSURL *)url {
NSData *xmlData = [self.tree xmlData];
NSError *error;
@@ -339,9 +345,8 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou
- (void)readXMLfromURL:(NSURL *)url {
NSError *error;
self.tree = [[KPKTree alloc] initWithXmlContentsOfURL:url error:&error];
self.compositeKey = nil;
self.encryptedData = nil;
KPKTree *tree = [[KPKTree alloc] initWithXmlContentsOfURL:url error:&error];
[self importTree:tree];
}
- (void)mergeWithContentsFromURL:(NSURL *)url key:(KPKCompositeKey *)key {

View File

@@ -58,6 +58,7 @@
- (IBAction)exportAsXML:(id)sender;
- (IBAction)mergeWithOther:(id)sender;
- (IBAction)importFromXML:(id)sender;
- (IBAction)importFromPlugin:(id)sender;
- (IBAction)lock:(id)sender;
- (IBAction)createGroup:(id)sender;

View File

@@ -40,6 +40,9 @@
#import "MPToolbarDelegate.h"
#import "MPTitlebarColorAccessoryViewController.h"
#import "MPPluginHost.h"
#import "MPPlugin.h"
#import "KeePassKit/KeePassKit.h"
typedef NS_ENUM(NSUInteger, MPAlertContext) {
@@ -274,6 +277,28 @@ typedef void (^MPPasswordChangedBlock)(BOOL didChangePassword);
}];
}
- (void)importFromPlugin:(id)sender {
if(![sender isKindOfClass:NSMenuItem.class]) {
return;
}
NSMenuItem *menuItem = sender;
if(![menuItem.representedObject isKindOfClass:NSDictionary.class]) {
return;
}
NSWindow *sheetWindow = ((MPDocument *)self.document).windowForSheet;
if(!sheetWindow) {
return;
}
MPPlugin<MPImportPlugin> *importPlugin;
NSOpenPanel *openPanel = NSOpenPanel.openPanel;
[importPlugin prepareOpenPanel:openPanel];
[openPanel beginSheetModalForWindow:sheetWindow completionHandler:^(NSModalResponse result) {
KPKTree *importedTree = [importPlugin treeForRunningOpenPanel:openPanel withResponse:result];
[self.document importTree:importedTree];
}];
}
- (void)mergeWithOther:(id)sender {
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
MPDocument *document = self.document;

View File

@@ -89,8 +89,33 @@ FOUNDATION_EXPORT NSString *const MPPluginUnkownVersion;
@protocol MPImportPlugin <NSObject>
@required
@property (readonly, copy) NSArray<NSString *> *supportedUTIs;
- (KPKTree *)importTreeWithContentsOfURL:(NSURL *)url;
/**
Called by the Host to upate a menu item for importing.
You are supposed to update the title to something meaningfull.
target and action will get set by host, so do not rely on them
@param item MenuItem that will be used to import via the plugin
*/
- (void)prepareImportMenuItem:(NSMenuItem *)item;
/**
Called by the host when an import is about to happen.
Update the panel to allow work for all the files and formats you can open.
Host will simply run the panel with - beginSheetModalForWindow:completionHandler:
and will call treeForRunningOpenPanel:withResponse: afterwards to handle the result.
@param panel The open panel that will be displayed to the user for importing files
*/
- (void)prepareOpenPanel:(NSOpenPanel *)panel;
/**
This will get called when the open panel is closed by the user.
You should retrieve any results from the panel and act accordingly.
@param panel The open panel used for selecting what file(s) to import
@param response The response for of the user for running the panel
@return The tree constructed from the selected input file(s)
*/
- (KPKTree *)treeForRunningOpenPanel:(NSOpenPanel *)panel withResponse:(NSModalResponse)response;
@end
@interface MPPlugin (Deprecated)

View File

@@ -23,8 +23,8 @@
#import <Foundation/Foundation.h>
/* Notifications for loading plugins */
FOUNDATION_EXPORT NSString *const MPPluginHostWillLoadPlugin;
FOUNDATION_EXPORT NSString *const MPPluginHostDidLoadPlugin;
FOUNDATION_EXPORT NSString *const MPPluginHostWillLoadPluginNotification;
FOUNDATION_EXPORT NSString *const MPPluginHostDidLoadPluginNotification;
/* Keys used in info dictionary on notifications */
FOUNDATION_EXPORT NSString *const MPPluginHostPluginBundleIdentifiyerKey;
@@ -37,7 +37,6 @@ FOUNDATION_EXPORT NSString *const MPPluginHostPluginBundleIdentifiyerKey;
/* List of all plugins known to the plugin manager. Disabled plugins are also present! */
@property (readonly, copy) NSArray <MPPlugin __kindof*> *plugins;
@property (readonly, copy) NSArray <MPPlugin __kindof*> *importPlugins;
@property (nonatomic, readonly, copy) NSString *version;
+ (instancetype)sharedHost;
@@ -54,3 +53,9 @@ FOUNDATION_EXPORT NSString *const MPPluginHostPluginBundleIdentifiyerKey;
- (MPPlugin *)pluginWithBundleIdentifier:(NSString *)identifer;
- (NSArray *)avilableMenuItemsForEntries:(NSArray <KPKEntry *>*)entries;
@end
@interface MPPluginHost (MPImportPluginSupport)
@property (readonly, copy) NSArray <MPPlugin<MPImportPlugin> __kindof*> *importPlugins;
@end

View File

@@ -38,8 +38,8 @@
#import "KeePassKit/KeePassKit.h"
NSString *const MPPluginHostWillLoadPlugin = @"com.hicknhack.macpass.MPPluginHostWillLoadPlugin";
NSString *const MPPluginHostDidLoadPlugin = @"comt.hicknhack.macpass.MPPluginHostDidLoadPlugin";
NSString *const MPPluginHostWillLoadPluginNotification = @"com.hicknhack.macpass.MPPluginHostWillLoadPlugin";
NSString *const MPPluginHostDidLoadPluginNotification = @"comt.hicknhack.macpass.MPPluginHostDidLoadPlugin";
NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBundleIdentifiyerKey";
@@ -87,13 +87,6 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
return [self.mutablePlugins copy];
}
- (NSArray<MPPlugin *> *)importPlugins {
NSPredicate *filterPredicate = [NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return ([evaluatedObject conformsToProtocol:@protocol(MPImportPlugin)]);
}];
return [self.mutablePlugins filteredArrayUsingPredicate:filterPredicate];
}
- (BOOL)installPluginAtURL:(NSURL *)url error:(NSError *__autoreleasing *)error {
if(![self _isValidPluginURL:url]) {
if(error) {
@@ -267,11 +260,11 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
if(plugin) {
NSLog(@"Loaded plugin instance %@", pluginBundle.principalClass);
[[NSNotificationCenter defaultCenter] postNotificationName:MPPluginHostWillLoadPlugin
[[NSNotificationCenter defaultCenter] postNotificationName:MPPluginHostWillLoadPluginNotification
object:self
userInfo:@{ MPPluginHostPluginBundleIdentifiyerKey : plugin.identifier }];
[self _addPlugin:plugin];
[[NSNotificationCenter defaultCenter] postNotificationName:MPPluginHostDidLoadPlugin
[[NSNotificationCenter defaultCenter] postNotificationName:MPPluginHostDidLoadPluginNotification
object:self
userInfo:@{ MPPluginHostPluginBundleIdentifiyerKey : plugin.identifier }];
}
@@ -414,6 +407,18 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
[context.plugin performActionForMenuItem:item withEntries:context.entries];
}
@end
NSString *const MPPluginBundleIdentifierKey = @"MPPluginBundleIdentifierKey";
NSString *const MPImportPluginUTIKey = @"MPImportPluginUTIKey";
@implementation MPPluginHost (MPImportPluginSupport)
- (NSArray<MPPlugin *> *)importPlugins {
NSPredicate *filterPredicate = [NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return ([evaluatedObject conformsToProtocol:@protocol(MPImportPlugin)]);
}];
return [self.mutablePlugins filteredArrayUsingPredicate:filterPredicate];
}
@end