Fuzzy site name search and highlight fuzzy results.
This commit is contained in:
parent
d642cb1aee
commit
8615f6af5d
2
External/KCOrderedAccessorFix
vendored
2
External/KCOrderedAccessorFix
vendored
@ -1 +1 @@
|
|||||||
Subproject commit e1955221bf52d53736e7d3e7d38465c509e02562
|
Subproject commit 1b8f8b79ad12b70976c7a417ff1a9d29e8c0ed73
|
2
External/Pearl
vendored
2
External/Pearl
vendored
@ -1 +1 @@
|
|||||||
Subproject commit ef628f388e70459725de21e3528831c705f88795
|
Subproject commit 2237aaf4295f74627b63040c4c246cddff339958
|
@ -29,7 +29,6 @@
|
|||||||
@property(nonatomic) BOOL alternatePressed;
|
@property(nonatomic) BOOL alternatePressed;
|
||||||
@property(nonatomic) BOOL locked;
|
@property(nonatomic) BOOL locked;
|
||||||
@property(nonatomic) BOOL newUser;
|
@property(nonatomic) BOOL newUser;
|
||||||
@property(nonatomic) BOOL alwaysYes;
|
|
||||||
|
|
||||||
@property(nonatomic, weak) IBOutlet NSArrayController *sitesController;
|
@property(nonatomic, weak) IBOutlet NSArrayController *sitesController;
|
||||||
@property(nonatomic, weak) IBOutlet NSImageView *blurView;
|
@property(nonatomic, weak) IBOutlet NSImageView *blurView;
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation MPPasswordWindowController { BOOL _skipTextChange; }
|
@implementation MPPasswordWindowController
|
||||||
|
|
||||||
#pragma mark - Life
|
#pragma mark - Life
|
||||||
|
|
||||||
@ -54,31 +54,33 @@
|
|||||||
// }];
|
// }];
|
||||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification object:self.window
|
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification object:self.window
|
||||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||||
[self fadeIn];
|
[self fadeIn];
|
||||||
[self updateUser];
|
[self updateUser];
|
||||||
}];
|
}];
|
||||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:self.window
|
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:self.window
|
||||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||||
NSWindow *sheet = [self.window attachedSheet];
|
NSWindow *sheet = [self.window attachedSheet];
|
||||||
if (sheet)
|
if (sheet)
|
||||||
[NSApp endSheet:sheet];
|
[NSApp endSheet:sheet];
|
||||||
}];
|
}];
|
||||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillResignActiveNotification object:nil
|
[[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillResignActiveNotification object:nil
|
||||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||||
|
#ifndef DEBUG
|
||||||
[self fadeOut];
|
[self fadeOut];
|
||||||
}];
|
#endif
|
||||||
|
}];
|
||||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedInNotification object:nil
|
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedInNotification object:nil
|
||||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||||
[self updateUser];
|
[self updateUser];
|
||||||
}];
|
}];
|
||||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedOutNotification object:nil
|
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedOutNotification object:nil
|
||||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||||
[self updateUser];
|
[self updateUser];
|
||||||
}];
|
}];
|
||||||
[self observeKeyPath:@"sitesController.selection"
|
[self observeKeyPath:@"sitesController.selection"
|
||||||
withBlock:^(id from, id to, NSKeyValueChange cause, id _self) {
|
withBlock:^(id from, id to, NSKeyValueChange cause, id _self) {
|
||||||
[_self updateSelection];
|
[_self updateSelection];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
NSSearchFieldCell *siteFieldCell = self.siteField.cell;
|
NSSearchFieldCell *siteFieldCell = self.siteField.cell;
|
||||||
siteFieldCell.searchButtonCell = nil;
|
siteFieldCell.searchButtonCell = nil;
|
||||||
@ -124,17 +126,15 @@
|
|||||||
- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector {
|
- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector {
|
||||||
|
|
||||||
if (control == self.siteField) {
|
if (control == self.siteField) {
|
||||||
if ([NSStringFromSelector( commandSelector ) rangeOfString:@"delete"].location == 0) {
|
if ([NSStringFromSelector( commandSelector ) rangeOfString:@"delete"].location == 0)
|
||||||
_skipTextChange = YES;
|
return NO;
|
||||||
dbg_return_tr( NO, @, control, NSStringFromSelector( commandSelector ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (control == self.securePasswordField || control == self.revealPasswordField) {
|
if (control == self.securePasswordField || control == self.revealPasswordField) {
|
||||||
if (commandSelector == @selector( insertNewline: ))
|
if (commandSelector == @selector( insertNewline: ))
|
||||||
dbg_return_tr( NO, @, control, NSStringFromSelector( commandSelector ) );
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg_return_tr( [self handleCommand:commandSelector], @, control, NSStringFromSelector( commandSelector ) );
|
return [self handleCommand:commandSelector];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor {
|
- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor {
|
||||||
@ -174,7 +174,6 @@
|
|||||||
|
|
||||||
- (BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector {
|
- (BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector {
|
||||||
|
|
||||||
dbg( @"textView:%@doCommandBySelector:%@", textView, NSStringFromSelector( commandSelector ) );
|
|
||||||
return [self handleCommand:commandSelector];
|
return [self handleCommand:commandSelector];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,9 +226,9 @@
|
|||||||
// "Create" button.
|
// "Create" button.
|
||||||
[[MPMacAppDelegate get] addSiteNamed:[self.siteField stringValue] completion:
|
[[MPMacAppDelegate get] addSiteNamed:[self.siteField stringValue] completion:
|
||||||
^(MPSiteEntity *site, NSManagedObjectContext *context) {
|
^(MPSiteEntity *site, NSManagedObjectContext *context) {
|
||||||
if (site)
|
if (site)
|
||||||
PearlMainQueue( ^{ [self updateSites]; } );
|
PearlMainQueue( ^{ [self updateSites]; } );
|
||||||
}];
|
}];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -305,19 +304,6 @@
|
|||||||
|
|
||||||
#pragma mark - State
|
#pragma mark - State
|
||||||
|
|
||||||
- (NSString *)query {
|
|
||||||
|
|
||||||
return [self.siteField.stringValue stringByReplacingCharactersInRange:self.siteField.currentEditor.selectedRange withString:@""]?: @"";
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)alwaysYes {
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setAlwaysYes:(BOOL)alwaysYes {
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)insertObject:(MPSiteModel *)model inSitesAtIndex:(NSUInteger)index {
|
- (void)insertObject:(MPSiteModel *)model inSitesAtIndex:(NSUInteger)index {
|
||||||
|
|
||||||
[self.sites insertObject:model atIndex:index];
|
[self.sites insertObject:model atIndex:index];
|
||||||
@ -347,7 +333,7 @@
|
|||||||
[alert addButtonWithTitle:@"Delete"];
|
[alert addButtonWithTitle:@"Delete"];
|
||||||
[alert addButtonWithTitle:@"Cancel"];
|
[alert addButtonWithTitle:@"Cancel"];
|
||||||
[alert setMessageText:@"Delete Site?"];
|
[alert setMessageText:@"Delete Site?"];
|
||||||
[alert setInformativeText:strf( @"Do you want to delete the site named:\n\n%@", self.selectedSite.siteName )];
|
[alert setInformativeText:strf( @"Do you want to delete the site named:\n\n%@", self.selectedSite.name )];
|
||||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||||
didEndSelector:@selector( alertDidEnd:returnCode:contextInfo: ) contextInfo:MPAlertDeleteSite];
|
didEndSelector:@selector( alertDidEnd:returnCode:contextInfo: ) contextInfo:MPAlertDeleteSite];
|
||||||
}
|
}
|
||||||
@ -358,7 +344,7 @@
|
|||||||
[alert addButtonWithTitle:@"Save"];
|
[alert addButtonWithTitle:@"Save"];
|
||||||
[alert addButtonWithTitle:@"Cancel"];
|
[alert addButtonWithTitle:@"Cancel"];
|
||||||
[alert setMessageText:@"Change Login Name"];
|
[alert setMessageText:@"Change Login Name"];
|
||||||
[alert setInformativeText:strf( @"Enter the login name for: %@", self.selectedSite.siteName )];
|
[alert setInformativeText:strf( @"Enter the login name for: %@", self.selectedSite.name )];
|
||||||
NSTextField *loginField = [[NSTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
NSTextField *loginField = [[NSTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||||
loginField.stringValue = self.selectedSite.loginName?: @"";
|
loginField.stringValue = self.selectedSite.loginName?: @"";
|
||||||
[loginField selectText:self];
|
[loginField selectText:self];
|
||||||
@ -392,7 +378,7 @@
|
|||||||
[alert addButtonWithTitle:@"Save"];
|
[alert addButtonWithTitle:@"Save"];
|
||||||
[alert addButtonWithTitle:@"Cancel"];
|
[alert addButtonWithTitle:@"Cancel"];
|
||||||
[alert setMessageText:@"Change Password"];
|
[alert setMessageText:@"Change Password"];
|
||||||
[alert setInformativeText:strf( @"Enter the new password for: %@", self.selectedSite.siteName )];
|
[alert setInformativeText:strf( @"Enter the new password for: %@", self.selectedSite.name )];
|
||||||
[alert setAccessoryView:[[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )]];
|
[alert setAccessoryView:[[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )]];
|
||||||
[alert layout];
|
[alert layout];
|
||||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||||
@ -408,8 +394,9 @@
|
|||||||
MPSiteType type = [types[t] unsignedIntegerValue];
|
MPSiteType type = [types[t] unsignedIntegerValue];
|
||||||
NSString *title = [site.algorithm nameOfType:type];
|
NSString *title = [site.algorithm nameOfType:type];
|
||||||
if (type & MPSiteTypeClassGenerated)
|
if (type & MPSiteTypeClassGenerated)
|
||||||
title = [site.algorithm generatePasswordForSiteNamed:site.siteName ofType:type
|
title = [site.algorithm generatePasswordForSiteNamed:site.name ofType:type
|
||||||
withCounter:site.counter usingKey:[MPMacAppDelegate get].key];
|
withCounter:site.counter
|
||||||
|
usingKey:[MPMacAppDelegate get].key];
|
||||||
|
|
||||||
NSButtonCell *cell = [self.passwordTypesMatrix cellAtRow:(NSInteger)t column:0];
|
NSButtonCell *cell = [self.passwordTypesMatrix cellAtRow:(NSInteger)t column:0];
|
||||||
cell.tag = type;
|
cell.tag = type;
|
||||||
@ -421,7 +408,7 @@
|
|||||||
[alert addButtonWithTitle:@"Save"];
|
[alert addButtonWithTitle:@"Save"];
|
||||||
[alert addButtonWithTitle:@"Cancel"];
|
[alert addButtonWithTitle:@"Cancel"];
|
||||||
[alert setMessageText:@"Change Password Type"];
|
[alert setMessageText:@"Change Password Type"];
|
||||||
[alert setInformativeText:strf( @"Choose a new password type for: %@", site.siteName )];
|
[alert setInformativeText:strf( @"Choose a new password type for: %@", site.name )];
|
||||||
[alert setAccessoryView:self.passwordTypesBox];
|
[alert setAccessoryView:self.passwordTypesBox];
|
||||||
[alert layout];
|
[alert layout];
|
||||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||||
@ -464,9 +451,9 @@
|
|||||||
NSUserNotification *notification = [NSUserNotification new];
|
NSUserNotification *notification = [NSUserNotification new];
|
||||||
notification.title = @"Password Copied";
|
notification.title = @"Password Copied";
|
||||||
if (selectedSite.loginName.length)
|
if (selectedSite.loginName.length)
|
||||||
notification.subtitle = strf( @"%@ at %@", selectedSite.loginName, selectedSite.siteName );
|
notification.subtitle = strf( @"%@ at %@", selectedSite.loginName, selectedSite.name );
|
||||||
else
|
else
|
||||||
notification.subtitle = selectedSite.siteName;
|
notification.subtitle = selectedSite.name;
|
||||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -515,12 +502,24 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *query = [self query];
|
static NSRegularExpression *fuzzyRE;
|
||||||
|
static dispatch_once_t once = 0;
|
||||||
|
dispatch_once( &once, ^{
|
||||||
|
fuzzyRE = [NSRegularExpression regularExpressionWithPattern:@"(.)" options:0 error:nil];
|
||||||
|
} );
|
||||||
|
|
||||||
|
NSString *queryString = self.siteField.stringValue;
|
||||||
|
NSString *queryPattern = [queryString stringByReplacingMatchesOfExpression:fuzzyRE withTemplate:@"*$1*"];
|
||||||
|
NSMutableArray *fuzzyGroups = [NSMutableArray new];
|
||||||
|
[fuzzyRE enumerateMatchesInString:queryString options:0 range:NSMakeRange( 0, queryString.length )
|
||||||
|
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
|
||||||
|
[fuzzyGroups addObject:[queryString substringWithRange:result.range] ];
|
||||||
|
}];
|
||||||
[MPMacAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) {
|
[MPMacAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) {
|
||||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )];
|
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )];
|
||||||
fetchRequest.sortDescriptors = @[ [[NSSortDescriptor alloc] initWithKey:@"lastUsed" ascending:NO] ];
|
fetchRequest.sortDescriptors = @[ [[NSSortDescriptor alloc] initWithKey:@"lastUsed" ascending:NO] ];
|
||||||
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(%@ == '' OR name BEGINSWITH[cd] %@) AND user == %@",
|
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(%@ == '' OR name LIKE[cd] %@) AND user == %@",
|
||||||
query, query, [[MPMacAppDelegate get] activeUserInContext:context]];
|
queryPattern, queryPattern, [[MPMacAppDelegate get] activeUserInContext:context]];
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
NSArray *siteResults = [context executeFetchRequest:fetchRequest error:&error];
|
NSArray *siteResults = [context executeFetchRequest:fetchRequest error:&error];
|
||||||
@ -531,36 +530,14 @@
|
|||||||
|
|
||||||
NSMutableArray *newSites = [NSMutableArray arrayWithCapacity:[siteResults count]];
|
NSMutableArray *newSites = [NSMutableArray arrayWithCapacity:[siteResults count]];
|
||||||
for (MPSiteEntity *site in siteResults)
|
for (MPSiteEntity *site in siteResults)
|
||||||
[newSites addObject:[[MPSiteModel alloc] initWithEntity:site]];
|
[newSites addObject:[[MPSiteModel alloc] initWithEntity:site fuzzyGroups:fuzzyGroups]];
|
||||||
self.sites = newSites;
|
self.sites = newSites;
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateSelection {
|
- (void)updateSelection {
|
||||||
|
|
||||||
if (_skipTextChange) {
|
|
||||||
_skipTextChange = NO;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSString *siteName = self.selectedSite.siteName;
|
|
||||||
if (!siteName)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ([self.window isKeyWindow] && [self.siteField isEqual:[self.window firstResponder]]) {
|
|
||||||
NSRange siteNameQueryRange = [siteName rangeOfString:[self query]];
|
|
||||||
self.siteField.stringValue = siteName;
|
|
||||||
|
|
||||||
if (siteNameQueryRange.location == 0)
|
|
||||||
self.siteField.currentEditor.selectedRange =
|
|
||||||
NSMakeRange( siteNameQueryRange.length, siteName.length - siteNameQueryRange.length );
|
|
||||||
}
|
|
||||||
|
|
||||||
[self.siteTable scrollRowToVisible:(NSInteger)self.sitesController.selectionIndex];
|
[self.siteTable scrollRowToVisible:(NSInteger)self.sitesController.selectionIndex];
|
||||||
[self updateGradient];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)updateGradient {
|
|
||||||
|
|
||||||
NSView *siteScrollView = self.siteTable.superview.superview;
|
NSView *siteScrollView = self.siteTable.superview.superview;
|
||||||
NSRect selectedCellFrame = [self.siteTable frameOfCellAtColumn:0 row:((NSInteger)self.sitesController.selectionIndex)];
|
NSRect selectedCellFrame = [self.siteTable frameOfCellAtColumn:0 row:((NSInteger)self.sitesController.selectionIndex)];
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
</ciFilter>
|
</ciFilter>
|
||||||
<ciFilter name="CIExposureAdjust">
|
<ciFilter name="CIExposureAdjust">
|
||||||
<configuration>
|
<configuration>
|
||||||
<real key="inputEV" value="-1"/>
|
<real key="inputEV" value="0.0"/>
|
||||||
<null key="inputImage"/>
|
<null key="inputImage"/>
|
||||||
</configuration>
|
</configuration>
|
||||||
</ciFilter>
|
</ciFilter>
|
||||||
@ -181,11 +181,11 @@
|
|||||||
</shadow>
|
</shadow>
|
||||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" alignment="center" title="apple.com" id="o0g-Zv-pH4">
|
<textFieldCell key="cell" lineBreakMode="truncatingTail" alignment="center" title="apple.com" id="o0g-Zv-pH4">
|
||||||
<font key="font" size="24" name="HelveticaNeue-Thin"/>
|
<font key="font" size="24" name="HelveticaNeue-Thin"/>
|
||||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="textColor" name="alternateSelectedControlTextColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
<connections>
|
<connections>
|
||||||
<binding destination="xQb-o5-M5U" name="value" keyPath="objectValue.siteName" id="CZi-gD-5Ec">
|
<binding destination="xQb-o5-M5U" name="value" keyPath="objectValue.displayedName" id="CZi-gD-5Ec">
|
||||||
<dictionary key="options">
|
<dictionary key="options">
|
||||||
<bool key="NSContinuouslyUpdatesValue" value="YES"/>
|
<bool key="NSContinuouslyUpdatesValue" value="YES"/>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
@ -438,7 +438,7 @@
|
|||||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
</binding>
|
</binding>
|
||||||
<binding destination="mcS-ik-b0n" name="value" keyPath="selection.contentDisplay" id="djg-i5-pwt"/>
|
<binding destination="mcS-ik-b0n" name="value" keyPath="selection.displayedContent" id="djg-i5-pwt"/>
|
||||||
</connections>
|
</connections>
|
||||||
</textField>
|
</textField>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Ia6-7b-dFr">
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Ia6-7b-dFr">
|
||||||
|
@ -17,15 +17,17 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "MPSiteEntity.h"
|
||||||
@class MPSiteEntity;
|
@class MPSiteEntity;
|
||||||
|
|
||||||
@interface MPSiteModel : NSObject
|
@interface MPSiteModel : NSObject
|
||||||
|
|
||||||
@property (nonatomic) NSString *siteName;
|
@property (nonatomic) NSString *name;
|
||||||
|
@property (nonatomic) NSAttributedString *displayedName;
|
||||||
@property (nonatomic) MPSiteType type;
|
@property (nonatomic) MPSiteType type;
|
||||||
@property (nonatomic) NSString *typeName;
|
@property (nonatomic) NSString *typeName;
|
||||||
@property (nonatomic) NSString *content;
|
@property (nonatomic) NSString *content;
|
||||||
@property (nonatomic) NSString *contentDisplay;
|
@property (nonatomic) NSString *displayedContent;
|
||||||
@property (nonatomic) NSString *loginName;
|
@property (nonatomic) NSString *loginName;
|
||||||
@property (nonatomic) NSNumber *uses;
|
@property (nonatomic) NSNumber *uses;
|
||||||
@property (nonatomic) NSUInteger counter;
|
@property (nonatomic) NSUInteger counter;
|
||||||
@ -34,7 +36,7 @@
|
|||||||
@property (nonatomic) BOOL generated;
|
@property (nonatomic) BOOL generated;
|
||||||
@property (nonatomic) BOOL stored;
|
@property (nonatomic) BOOL stored;
|
||||||
|
|
||||||
- (id)initWithEntity:(MPSiteEntity *)entity;
|
- (instancetype)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups;
|
||||||
- (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc;
|
- (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc;
|
||||||
|
|
||||||
- (void)updateContent;
|
- (void)updateContent;
|
||||||
|
@ -28,25 +28,41 @@
|
|||||||
BOOL _initialized;
|
BOOL _initialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithEntity:(MPSiteEntity *)entity {
|
- (id)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups {
|
||||||
|
|
||||||
if (!(self = [super init]))
|
if (!(self = [super init]))
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
[self setEntity:entity];
|
[self setEntity:entity fuzzyGroups:fuzzyGroups];
|
||||||
_initialized = YES;
|
_initialized = YES;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setEntity:(MPSiteEntity *)entity {
|
- (void)setEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups {
|
||||||
|
|
||||||
if ([_entityOID isEqual:entity.objectID])
|
if ([_entityOID isEqual:entity.objectID])
|
||||||
return;
|
return;
|
||||||
_entityOID = entity.objectID;
|
_entityOID = entity.objectID;
|
||||||
|
|
||||||
|
NSString *siteName = entity.name;
|
||||||
|
NSMutableAttributedString *attributedSiteName = [[NSMutableAttributedString alloc] initWithString:siteName];
|
||||||
|
for (NSUInteger f = 0, s = (NSUInteger)-1; f < [fuzzyGroups count]; ++f) {
|
||||||
|
s = [siteName rangeOfString:fuzzyGroups[f] options:NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch
|
||||||
|
range:NSMakeRange( s + 1, [siteName length] - (s + 1) )].location;
|
||||||
|
if (s == NSNotFound)
|
||||||
|
break;
|
||||||
|
|
||||||
|
[attributedSiteName addAttribute:NSBackgroundColorAttributeName value:[NSColor alternateSelectedControlColor]
|
||||||
|
range:NSMakeRange( s, [fuzzyGroups[f] length] )];
|
||||||
|
}
|
||||||
|
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
|
||||||
|
paragraphStyle.alignment = NSCenterTextAlignment;
|
||||||
|
[attributedSiteName addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange( 0, [siteName length] )];
|
||||||
|
|
||||||
|
self.displayedName = attributedSiteName;
|
||||||
|
self.name = siteName;
|
||||||
self.algorithm = entity.algorithm;
|
self.algorithm = entity.algorithm;
|
||||||
self.siteName = entity.name;
|
|
||||||
self.lastUsed = entity.lastUsed;
|
self.lastUsed = entity.lastUsed;
|
||||||
self.type = entity.type;
|
self.type = entity.type;
|
||||||
self.typeName = entity.typeName;
|
self.typeName = entity.typeName;
|
||||||
@ -123,7 +139,7 @@
|
|||||||
|
|
||||||
PearlMainQueue( ^{
|
PearlMainQueue( ^{
|
||||||
self.content = result;
|
self.content = result;
|
||||||
self.contentDisplay = displayResult;
|
self.displayedContent = displayResult;
|
||||||
} );
|
} );
|
||||||
}];
|
}];
|
||||||
[entity resolveLoginUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) {
|
[entity resolveLoginUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) {
|
||||||
|
Loading…
Reference in New Issue
Block a user