diff --git a/platform-darwin/Source/Mac/MPSiteModel.h b/platform-darwin/Source/Mac/MPSiteModel.h index 429cc090..d69e0868 100644 --- a/platform-darwin/Source/Mac/MPSiteModel.h +++ b/platform-darwin/Source/Mac/MPSiteModel.h @@ -45,7 +45,7 @@ @property(nonatomic, readonly) BOOL stored; @property(nonatomic, readonly) BOOL transient; -- (instancetype)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups; +- (instancetype)initWithEntity:(MPSiteEntity *)entity queryGroups:(NSArray *)queryGroups; - (instancetype)initWithName:(NSString *)siteName forUser:(MPUserEntity *)user; - (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc; diff --git a/platform-darwin/Source/Mac/MPSiteModel.m b/platform-darwin/Source/Mac/MPSiteModel.m index 79a4ce46..0970674a 100644 --- a/platform-darwin/Source/Mac/MPSiteModel.m +++ b/platform-darwin/Source/Mac/MPSiteModel.m @@ -31,12 +31,12 @@ @implementation MPSiteModel -- (instancetype)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups { +- (instancetype)initWithEntity:(MPSiteEntity *)entity queryGroups:(NSArray *)queryGroups { if (!(self = [super init])) return nil; - [self setEntity:entity fuzzyGroups:fuzzyGroups]; + [self setEntity:entity queryGroups:queryGroups]; self.initialized = YES; return self; @@ -53,23 +53,25 @@ return self; } -- (void)setEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups { +- (void)setEntity:(MPSiteEntity *)entity queryGroups:(NSArray *)queryGroups { if ([self.entityOID isEqual:entity.permanentObjectID]) return; self.entityOID = entity.permanentObjectID; 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; + NSMutableAttributedString *attributedSiteName = [[NSMutableAttributedString alloc] initWithString:siteName?: @""]; + if ([attributedSiteName length]) + for (NSUInteger f = 0, s = 0; f < [queryGroups count]; ++f, ++s) { + s = [siteName rangeOfString:queryGroups[f] options:NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch + range:NSMakeRange( s, [siteName length] - s )].location; + if (s == NSNotFound) + break; + + [attributedSiteName addAttribute:NSBackgroundColorAttributeName value:[NSColor alternateSelectedControlColor] + range:NSMakeRange( s, [queryGroups[f] length] )]; + } - [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] )]; diff --git a/platform-darwin/Source/Mac/MPSitesWindowController.m b/platform-darwin/Source/Mac/MPSitesWindowController.m index f7a1a347..7da7f82d 100644 --- a/platform-darwin/Source/Mac/MPSitesWindowController.m +++ b/platform-darwin/Source/Mac/MPSitesWindowController.m @@ -611,22 +611,20 @@ return; } - static NSRegularExpression *fuzzyRE; - static dispatch_once_t once = 0; - dispatch_once( &once, ^{ - fuzzyRE = [NSRegularExpression regularExpressionWithPattern:@"(.)" options:0 error:nil]; - } ); - prof_new( @"updateSites" ); NSString *queryString = self.siteField.stringValue; - NSString *queryPattern = [[queryString stringByReplacingMatchesOfExpression:fuzzyRE withTemplate:@"*$1"] stringByAppendingString:@"*"]; + NSMutableArray *queryGroups = [NSMutableArray new]; + NSMutableString *queryPattern = [NSMutableString new]; + [queryString enumerateSubstringsInRange: NSMakeRange(0, [queryString length]) options: NSStringEnumerationByComposedCharacterSequences + usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { + if (substringRange.location < 10) { + [queryGroups addObject:substring]; + [queryPattern appendString:@"*"]; + } + [queryPattern appendString:substring]; + }]; + [queryPattern appendString:@"*"]; prof_rewind( @"queryPattern" ); - 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]]; - }]; - prof_rewind( @"fuzzyRE" ); [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { prof_rewind( @"moc" ); @@ -648,7 +646,7 @@ BOOL exact = NO; NSMutableArray *newSites = [NSMutableArray arrayWithCapacity:[siteResults count]]; for (MPSiteEntity *site in siteResults) { - [newSites addObject:[[MPSiteModel alloc] initWithEntity:site fuzzyGroups:fuzzyGroups]]; + [newSites addObject:[[MPSiteModel alloc] initWithEntity:site queryGroups:queryGroups]]; exact |= [site.name isEqualToString:queryString]; } prof_rewind( @"newSites: %u, exact: %d", (uint)[siteResults count], exact ); diff --git a/platform-darwin/Source/iOS/MPSiteCell.h b/platform-darwin/Source/iOS/MPSiteCell.h index 4b78adc7..dc7c4b2e 100644 --- a/platform-darwin/Source/iOS/MPSiteCell.h +++ b/platform-darwin/Source/iOS/MPSiteCell.h @@ -27,7 +27,7 @@ typedef NS_ENUM ( NSUInteger, MPSiteCellMode ) { @interface MPSiteCell : MPCell -@property(nonatomic) NSArray *fuzzyGroups; +@property(nonatomic) NSArray *queryGroups; - (void)setSite:(MPSiteEntity *)site animated:(BOOL)animated; - (void)setTransientSite:(NSString *)siteName animated:(BOOL)animated; diff --git a/platform-darwin/Source/iOS/MPSiteCell.m b/platform-darwin/Source/iOS/MPSiteCell.m index 7b086666..c912b8c0 100644 --- a/platform-darwin/Source/iOS/MPSiteCell.m +++ b/platform-darwin/Source/iOS/MPSiteCell.m @@ -135,7 +135,7 @@ [super prepareForReuse]; self.siteOID = nil; - self.fuzzyGroups = nil; + self.queryGroups = nil; self.transientSite = nil; self.mode = MPPasswordCellModePassword; [self updateAnimated:NO]; @@ -150,11 +150,11 @@ #pragma mark - State -- (void)setFuzzyGroups:(NSArray *)fuzzyGroups { +- (void)setQueryGroups:(NSArray *)queryGroups { - if (self.fuzzyGroups == fuzzyGroups) + if (self.queryGroups == queryGroups) return; - _fuzzyGroups = fuzzyGroups; + _queryGroups = queryGroups; [self updateSiteName:[self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]]]; } @@ -656,14 +656,14 @@ NSString *siteName = self.transientSite?: site.name; NSMutableAttributedString *attributedSiteName = [[NSMutableAttributedString alloc] initWithString:siteName?: @""]; if ([attributedSiteName length]) - for (NSUInteger f = 0, s = (NSUInteger)-1; f < [self.fuzzyGroups count]; ++f) { - s = [siteName rangeOfString:self.fuzzyGroups[f] options:NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch - range:NSMakeRange( s + 1, [siteName length] - (s + 1) )].location; + for (NSUInteger f = 0, s = 0; f < [self.queryGroups count]; ++f, ++s) { + s = [siteName rangeOfString:self.queryGroups[f] options:NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch + range:NSMakeRange( s, [siteName length] - s )].location; if (s == NSNotFound) break; [attributedSiteName addAttribute:NSBackgroundColorAttributeName value:[UIColor redColor] - range:NSMakeRange( s, [self.fuzzyGroups[f] length] )]; + range:NSMakeRange( s, [self.queryGroups[f] length] )]; } if (self.transientSite) diff --git a/platform-darwin/Source/iOS/MPSitesViewController.m b/platform-darwin/Source/iOS/MPSitesViewController.m index 523890f1..e94b7154 100644 --- a/platform-darwin/Source/iOS/MPSitesViewController.m +++ b/platform-darwin/Source/iOS/MPSitesViewController.m @@ -36,7 +36,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) { @interface MPSitesViewController() @property(nonatomic, strong) NSFetchedResultsController *fetchedResultsController; -@property(nonatomic, strong) NSArray *fuzzyGroups; +@property(nonatomic, strong) NSArray *queryGroups; @property(nonatomic, strong) NSCharacterSet *siteNameAcceptableCharactersSet; @property(nonatomic, strong) NSMutableArray *dataSource; @property(nonatomic, weak) UIViewController *popdownVC; @@ -162,7 +162,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) { - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { MPSiteCell *cell = [MPSiteCell dequeueFromCollectionView:collectionView indexPath:indexPath]; - [cell setFuzzyGroups:self.fuzzyGroups]; + [cell setQueryGroups:self.queryGroups]; id item = self.dataSource[(NSUInteger)indexPath.section][(NSUInteger)indexPath.item]; if ([item isKindOfClass:[MPSiteEntity class]]) [cell setSite:item animated:NO]; @@ -355,21 +355,19 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) { - (void)reloadSites { [self.fetchedResultsController.managedObjectContext performBlock:^{ - static NSRegularExpression *fuzzyRE; - static dispatch_once_t once = 0; - dispatch_once( &once, ^{ - fuzzyRE = [NSRegularExpression regularExpressionWithPattern:@"(.)" options:0 error:nil]; - } ); - NSString *queryString = self.query; - NSString *queryPattern = [[queryString stringByReplacingMatchesOfExpression:fuzzyRE withTemplate:@"*$1"] - stringByAppendingString:@"*"]; - 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]]; - }]; - self.fuzzyGroups = fuzzyGroups; + NSMutableArray *queryGroups = [NSMutableArray new]; + NSMutableString *queryPattern = [NSMutableString new]; + [queryString enumerateSubstringsInRange: NSMakeRange(0, [queryString length]) options: NSStringEnumerationByComposedCharacterSequences + usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { + if (substringRange.location < 10) { + [queryGroups addObject:substring]; + [queryPattern appendString:@"*"]; + } + [queryPattern appendString:substring]; + }]; + [queryPattern appendString:@"*"]; + self.queryGroups = queryGroups; NSError *error = nil; self.fetchedResultsController.fetchRequest.predicate = @@ -382,7 +380,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) { toSections:[self createDataSource] reloadItems:@[ MPTransientPasswordItem ] completion:^(BOOL finished) { for (MPSiteCell *cell in self.collectionView.visibleCells) - [cell setFuzzyGroups:self.fuzzyGroups]; + [cell setQueryGroups:self.queryGroups]; }]; } ); }];