mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-14 15:12:21 +00:00
MPDocument now does the searching and notifies anyone that want to be informed
This commit is contained in:
@@ -8,16 +8,21 @@
|
||||
|
||||
#import "MPDocument.h"
|
||||
|
||||
FOUNDATION_EXPORT NSString *const MPDocumentDidEnterSearchNotification;
|
||||
FOUNDATION_EXTERN NSString *const MPDocumentDidChangeSearchNotification;
|
||||
FOUNDATION_EXPORT NSString *const MPDocumentDidChangeSearchFlags;
|
||||
FOUNDATION_EXTERN NSString *const MPDocumentDidEnterSearchNotification;
|
||||
FOUNDATION_EXTERN NSString *const MPDocumentDidChangeSearchFlags;
|
||||
FOUNDATION_EXTERN NSString *const MPDocumentDidExitSearchNotification;
|
||||
FOUNDATION_EXPORT NSString *const MPDocumentDidChangeSearchResults;
|
||||
/**
|
||||
* Posted by the document, when the search results have been updated. This is only called when searching.
|
||||
* If the search is exited, it will be notified by MPDocumentDidExitSearchNotification
|
||||
* The userInfo dictionary has one key kMPDocumentSearchResultsKey with an NSArray of KPKEntries mathching the search.
|
||||
*/
|
||||
FOUNDATION_EXTERN NSString *const MPDocumentDidChangeSearchResults;
|
||||
|
||||
/* keys used in userInfo dictionaries on notifications */
|
||||
FOUNDATION_EXTERN NSString *const kMPDocumentSearchResultsKey;
|
||||
|
||||
@interface MPDocument (Search)
|
||||
|
||||
- (NSArray *)entriesInDocument:(MPDocument *)document matching:(NSString *)string;
|
||||
|
||||
/* Should be called by the NSSearchTextField to update the search string */
|
||||
- (IBAction)updateSearch:(id)sender;
|
||||
/* exits searching mode */
|
||||
|
||||
@@ -8,32 +8,47 @@
|
||||
|
||||
#import "MPDocument+Search.h"
|
||||
#import "MPDocument.h"
|
||||
#import "MPDocumentWindowController.h"
|
||||
|
||||
#import "KPKGroup.h"
|
||||
#import "KPKEntry.h"
|
||||
|
||||
#import "MPFlagsHelper.h"
|
||||
|
||||
NSString *const MPDocumentDidEnterSearchNotification = @"com.hicknhack.macpass.MPDocumentDidEnterSearchNotification";
|
||||
NSString *const MPDocumentDidChangeSearchNotification = @"com.hicknhack.macpass.MPDocumentDidChangeSearchNotification";
|
||||
NSString *const MPDocumentDidChangeSearchFlags = @"com.hicknhack.macpass.MPDocumentDidChangeSearchFlagsNotification";
|
||||
NSString *const MPDocumentDidExitSearchNotification = @"com.hicknhack.macpass.MPDocumentDidExitSearchNotification";
|
||||
|
||||
NSString *const MPDocumentDidChangeSearchResults = @"com.hicknhack.macpass.MPDocumentDidChangeSearchResults";
|
||||
|
||||
NSString *const kMPDocumentSearchResultsKey = @"kMPDocumentSearchResultsKey";
|
||||
|
||||
|
||||
@implementation MPDocument (Search)
|
||||
|
||||
#pragma mark Actions
|
||||
|
||||
- (void)performFindPanelAction:(id)sender {
|
||||
self.hasSearch = YES;
|
||||
NSWindow *window = [[self windowControllers][0] window];
|
||||
NSToolbar *toolbar = [window toolbar];
|
||||
if(![toolbar isVisible]) {
|
||||
[toolbar setVisible:YES];
|
||||
}
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidEnterSearchNotification object:self];
|
||||
}
|
||||
|
||||
- (void)updateSearch:(id)sender {
|
||||
MPDocumentWindowController *windowController = [self windowControllers][0];
|
||||
self.searchString = [windowController.searchField stringValue];
|
||||
if(NO == self.hasSearch) {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidEnterSearchNotification object:self];
|
||||
}
|
||||
self.hasSearch = YES;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidChangeSearchNotification object:self];
|
||||
MPDocument __weak *weakSelf = self;
|
||||
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
dispatch_async(backgroundQueue, ^{
|
||||
NSArray *results = [weakSelf _findEntriesMatchingCurrentSearch];
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
weakSelf.selectedEntry = nil;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidChangeSearchResults object:weakSelf userInfo:@{ kMPDocumentSearchResultsKey: results }];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
- (void)exitSearch:(id)sender {
|
||||
@@ -65,16 +80,18 @@ NSString *const MPDocumentDidExitSearchNotification = @"com.hicknhack.macpass.
|
||||
if(newFlags == self.activeFlags) {
|
||||
self.activeFlags = (newFlags == MPEntrySearchNone) ? MPEntrySearchTitles : newFlags;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidChangeSearchFlags object:self];
|
||||
[self updateSearch:self];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Search
|
||||
- (NSArray *)entriesInDocument:(MPDocument *)document matching:(NSString *)string {
|
||||
- (NSArray *)_findEntriesMatchingCurrentSearch {
|
||||
/* Filter double passwords */
|
||||
MPDocument __weak *weakSelf = self;
|
||||
if(MPTestFlagInOptions(MPEntrySearchDoublePasswords, self.activeFlags)) {
|
||||
__block NSMutableDictionary *passwordToEntryMap;
|
||||
/* Build up a usage map */
|
||||
[[document.root childEntries] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
[[weakSelf.root childEntries] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
KPKEntry *entry = obj;
|
||||
NSMutableSet *entrySet = passwordToEntryMap[entry.password];
|
||||
if(entrySet) {
|
||||
@@ -96,13 +113,13 @@ NSString *const MPDocumentDidExitSearchNotification = @"com.hicknhack.macpass.
|
||||
return doublePasswords;
|
||||
}
|
||||
/* Filter using predicates */
|
||||
NSArray *predicates = [self _filterPredicatesWithString:string];
|
||||
NSArray *predicates = [self _filterPredicatesWithString:self.searchString];
|
||||
if(predicates) {
|
||||
NSPredicate *fullFilter = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];
|
||||
return [[document.root childEntries] filteredArrayUsingPredicate:fullFilter];
|
||||
return [[self.root childEntries] filteredArrayUsingPredicate:fullFilter];
|
||||
}
|
||||
/* No filter, just return everything */
|
||||
return [document.root childEntries];
|
||||
return [self.root childEntries];
|
||||
}
|
||||
|
||||
- (NSArray *)optionsEnabledInMode:(MPEntrySearchFlags)mode {
|
||||
@@ -117,10 +134,6 @@ NSString *const MPDocumentDidExitSearchNotification = @"com.hicknhack.macpass.
|
||||
return [allOptions objectsAtIndexes:indexes];
|
||||
}
|
||||
|
||||
- (void)_updateSearch {
|
||||
self.searchResult = [self entriesInDocument:self matching:self.searchString];
|
||||
}
|
||||
|
||||
- (NSArray *)_filterPredicatesWithString:(NSString *)string{
|
||||
NSMutableArray *prediactes = [[NSMutableArray alloc] initWithCapacity:4];
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ typedef NS_ENUM(NSUInteger, MPAlertContext) {
|
||||
@private
|
||||
id _firstResponder;
|
||||
BOOL _saveAfterPasswordChange;
|
||||
BOOL _didShowToolbarForSearch;
|
||||
}
|
||||
|
||||
@property (strong) IBOutlet NSSplitView *splitView;
|
||||
@@ -57,6 +58,7 @@ typedef NS_ENUM(NSUInteger, MPAlertContext) {
|
||||
if( self ) {
|
||||
_firstResponder = nil;
|
||||
_saveAfterPasswordChange = NO;
|
||||
_didShowToolbarForSearch = NO;
|
||||
_toolbarDelegate = [[MPToolbarDelegate alloc] init];
|
||||
_outlineViewController = [[MPOutlineViewController alloc] init];
|
||||
_entryViewController = [[MPEntryViewController alloc] init];
|
||||
@@ -77,12 +79,13 @@ typedef NS_ENUM(NSUInteger, MPAlertContext) {
|
||||
[[self window] setDelegate:self.documentWindowDelegate];
|
||||
[[self window] registerForDraggedTypes:@[NSURLPboardType]];
|
||||
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didRevertDocument:) name:MPDocumentDidRevertNotifiation object:[self document]];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showEntries) name:MPDocumentDidUnlockDatabaseNotification object:[self document]];
|
||||
|
||||
MPDocument *document = [self document];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didRevertDocument:) name:MPDocumentDidRevertNotifiation object:document];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showEntries) name:MPDocumentDidUnlockDatabaseNotification object:document];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didEnterSearch:) name:MPDocumentDidEnterSearchNotification object:document];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didExitSearch:) name:MPDocumentDidExitSearchNotification object:document];
|
||||
|
||||
[_entryViewController regsiterNotificationsForDocument:document];
|
||||
[_inspectorViewController regsiterNotificationsForDocument:document];
|
||||
[_outlineViewController regsiterNotificationsForDocument:document];
|
||||
@@ -159,11 +162,32 @@ typedef NS_ENUM(NSUInteger, MPAlertContext) {
|
||||
[self.window makeFirstResponder:[viewController reconmendedFirstResponder]];
|
||||
}
|
||||
|
||||
#pragma mark MPDocument notifications
|
||||
- (void)_didRevertDocument:(NSNotification *)notification {
|
||||
[self.outlineViewController clearSelection];
|
||||
[self showPasswordInput];
|
||||
}
|
||||
|
||||
- (void)_didEnterSearch:(NSNotificationCenter *)notification {
|
||||
/* Hide again after search ? */
|
||||
NSWindow *window = [self window];
|
||||
NSToolbar *toolbar = [window toolbar];
|
||||
if(![toolbar isVisible]) {
|
||||
_didShowToolbarForSearch = YES;
|
||||
[toolbar setVisible:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_didExitSearch:(NSNotification *)notification {
|
||||
/* Hide again after search ? */
|
||||
NSWindow *window = [self window];
|
||||
NSToolbar *toolbar = [window toolbar];
|
||||
if(_didShowToolbarForSearch && [toolbar isVisible]) {
|
||||
_didShowToolbarForSearch = NO;
|
||||
[toolbar setVisible:NO];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Actions
|
||||
- (void)saveDocument:(id)sender {
|
||||
_saveAfterPasswordChange = NO;
|
||||
|
||||
@@ -195,21 +195,21 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell";
|
||||
name:MPDocumentCurrentItemChangedNotification
|
||||
object:document];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(_updateSearchResults:)
|
||||
name:MPDocumentDidChangeSearchNotification
|
||||
object:document];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(_didEnterSearch:)
|
||||
name:MPDocumentDidEnterSearchNotification
|
||||
object:document];
|
||||
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(_didExitSearch:)
|
||||
name:MPDocumentDidExitSearchNotification
|
||||
object:document];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(_didUpdateSearchResults:)
|
||||
name:MPDocumentDidChangeSearchResults
|
||||
object:document];
|
||||
|
||||
|
||||
[self.contextBarViewController registerNotificationsForDocument:document];
|
||||
}
|
||||
@@ -337,22 +337,15 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell";
|
||||
}
|
||||
}
|
||||
#pragma mark MPDocumentSearchServiceNotifications
|
||||
- (void)_updateSearchResults:(NSNotification *)notification {
|
||||
- (void)_didUpdateSearchResults:(NSNotification *)notification {
|
||||
BOOL main = [NSThread isMainThread];
|
||||
[self _showContextBar];
|
||||
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
dispatch_async(backgroundQueue, ^{
|
||||
MPDocument *document = [[self windowController] document];
|
||||
NSString *searchString = [[[self windowController] searchField] stringValue];
|
||||
self.filteredEntries = [document entriesInDocument:document
|
||||
matching:searchString];
|
||||
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
document.selectedEntry = nil;
|
||||
NSArray *result = [notification userInfo][kMPDocumentSearchResultsKey];
|
||||
NSAssert(result != nil, @"Resutls should never be nil");
|
||||
self.filteredEntries = result;
|
||||
[self.entryArrayController unbind:NSContentArrayBinding];
|
||||
[self.entryArrayController setContent:self.filteredEntries];
|
||||
[[self.entryTable tableColumnWithIdentifier:MPEntryTableParentColumnIdentifier] setHidden:NO];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark NSDocument+Search Notifications
|
||||
|
||||
Reference in New Issue
Block a user